☰
Jev不写文本?从“生成式提示词”到“类型化决策”的Agent落地实践
2026/11/3 20:58:11 网站建设 项目流程

刚开始接触 Jev 的时候,我也被“不写文本”这个描述搞得有点懵。做了几年提示词工程,大家默认的共识都是 prompt 越长越详细越好,怎么到了 Jev 这里,反而不让写文本了?后来在 Codex 这类 Agent 环境里跑了几轮,我才回过味来:Jev 并不是不让你表达需求,而是换了一种表达方式——把“告诉模型怎么做”变成了“让模型在给定的选项中做决策”。这个转变,本质上就是从“生成式提示词”转向“类型化决策”。

这篇文章我想把这个思路彻底拆开聊。不管你是刚接触 Jev 的小白,还是已经在 Agent 开发里摸爬滚打的老手,只要能理解“类型化决策”这四个字背后的设计逻辑,你就能少走很多弯路。我会从原理讲到实操,最后把踩过的坑也一并列出来,照着做基本就能在自己的项目里落地。

1. 先搞懂“不写文本”到底在说什么

1.1 传统提示词工程的瓶颈在哪里

传统提示词工程的核心是“写”。写角色设定、写任务描述、写步骤清单、写约束条件,恨不得把所有可能性都塞进那几段文字里。这种方式在单轮对话、简单任务上确实有效,可一旦进入 Agent 场景,问题就暴露出来了。

首先是输出不稳定。同样一段 prompt,模型每次给的结果措辞不同、结构不同,甚至执行路径都可能跑偏。你写“如果测试失败,请尝试修复”,模型可能真的去改代码,也可能只是把错误信息复述一遍,还可能直接给出一个完全不相关的建议。文本描述得再详细,模型理解时仍然存在歧义空间。

其次是上下文浪费。Agent 场景里每一轮工具调用都要消耗 token,长文本 prompt 会占用大量上下文窗口。更糟糕的是,这些文本往往只是“指令”,并不是“信息”。模型需要的是当前仓库状态、函数签名、错误日志这类硬数据,而不是一大段“你是一个优秀的软件工程师”式的角色扮演。

还有一点很难受:不可编程。文本 prompt 没法被程序解析、校验、分支。你想根据模型输出做自动化处理,就得靠正则或字符串匹配去猜它的意图,这在工程上是极其脆弱的。我见过太多团队在解析 LLM 输出时写出一堆 hack 代码,最后维护成本比写 prompt 本身还高。

1.2 Jev 的“不写文本”本质是决策优先

Jev 的思路完全反过来。它不要求用户写“怎么做”,而是要求用户定义“有哪些选择”。模型要做的事情不再是生成一段自由文本,而是在一个预先定义好的决策空间里做出选择。

举个例子,传统 prompt 会让你写:

如果测试失败了,分析失败原因,然后决定是修改代码、补充日志还是上报人工。

Jev 式的做法则是定义一个决策结构:

{ "decision_point": "test_failure_handler", "available_actions": ["modify_implementation", "add_logging", "escalate_to_human"], "context_required": ["test_output", "failure_bucket", "recent_changes"] }

模型收到的是这个结构化定义和必要上下文,输出的是一个决策枚举值,附带少量结构化参数。没有大段解释,没有多余修辞,只有干净利落的“我选择做什么”。

这个转变的本质是:把模型从“答题者”变成“选择题作答者”。问答题可以自由发挥,全凭模型心情;选择题则框架清晰,答错了你知道它错在哪一步,答对了你知道它为什么对。这种确定性,在 Agent 里就是生命线。

用生活化的类比来说,传统 prompt 是让实习生“根据你的理解去处理这件事”,类型化决策是给实习生一张工单选择表:问题属于 A 类,就走 A 流程;属于 B 类,就走 B 流程。看起来少了些“智能感”,但实际跑起来,稳定性完全不在一个量级。

2. 类型化决策的核心方法论

2.1 把任务拆成决策树,而不是步骤清单

类型化决策的第一步,是重新理解任务结构。大部分人写 prompt 时习惯列步骤:先做 A,再做 B,然后 C。这在确定性流程里没问题,但 Agent 的任务往往存在大量分支,预设步骤根本覆盖不全。

决策树的思路是用来拆的:每个节点代表一个“需要判断的情况”,每个分支代表一种“可执行的动作”。根节点是任务的入口,子节点是不同情境下的决策点,叶子节点是具体动作。

以“修复测试失败”为例:

  • 根决策:测试失败了,失败类型是什么?(编译错误 / 断言失败 / 超时 / 环境问题)
  • 编译错误分支:是引入的 API 变了,还是语法错误?
  • 断言失败分支:是期望值不对,还是实现逻辑有 bug?
  • 超时分支:是算法复杂度问题,还是外部依赖阻塞?
  • 每个叶子节点对应一个具体动作:修改调用代码、改实现、加超时处理、上报人工。

这个拆法跟传统步骤清单的最大区别在于:决策树是“分支导向”的,每个分支点都要求模型做一次类型化判断;步骤清单是“顺序导向”的,模型经常在第一步卡住之后就不知道怎么办了。

实操建议:拆决策树时,最多拆到三层深度,超过三层的分支要么合并,要么拆成独立的子决策流程。决策树太深,模型判断的准确率会下降,调试起来也费劲。我见过好的实践是把树控制在“根决策 + 一级分支 + 叶子动作”的结构,清晰又好维护。

2.2 用类型定义约束输出空间

这是“类型化”三个字的核心。所谓类型,就是给模型的输出加上一道硬约束,让它只能在限定范围内选择,而不是自由发挥。

常用的类型约束手段有三种:

第一种是枚举类型。适用于“情况已经被前人总结过”的场景。比如代码变更类型,可以定义为["feature", "bugfix", "refactor", "docs", "test"]。模型只能输出其中一个值,不允许发明新的。枚举最大的价值是让输出变成可解析的固定值,程序拿到之后可以直接走 switch 分支。

第二种是结构体类型。适用于“决策需要附带参数”的场景。比如模型选择“修改实现”,那它需要同时给出修改的目标文件、修改的思路、风险评估等字段。结构体定义了完整的数据契约,比让模型自由写一段说明更可靠。

第三种是条件依赖类型。适用于“不同决策对应不同参数”的场景。比如模型选择“上报人工”,那不需要修改文件字段,但需要上报原因;模型选择“修改代码”,那不需要上报原因,但需要文件路径。条件依赖可以通过 JSON Schema 的oneOf或if-then-else来表达,让模型只在当前决策对应的分支里填参数。

这里有个很容易忽略的点:所谓“不写文本”,不是指模型输出里完全没有文本,而是指“决策本身不依赖文本表达”。模型仍然可以用结构化字段里的reason字段写一句简短理由,但程序逻辑只依赖枚举值和结构字段,不依赖那段理由。把理由当作文档留给人看,而不是当作文本留给程序解析。这个区分很重要。

2.3 上下文工程配合类型化决策

类型化决策再完美,也需要信息支撑。模型做判断的依据不是 schema 本身,而是当时拿到的上下文。这里要区分两类上下文:指令型上下文和信息型上下文。

指令型上下文描述的是“怎么做”,比如角色设定、禁止事项。这类内容在 Jev 体系里要尽量少,因为决策空间已经定义清楚了,重复强调“你要做一个谨慎的工程师”没有意义,反而稀释注意力。

信息型上下文描述的是“现状是什么”,比如当前仓库文件结构、最近一次提交的 diff、测试失败的具体日志、相关函数的签名。这些才是模型做决策真正需要的输入。

实际操作中,我建议把信息型上下文按“决策相关性”做筛选。一个常见的错误是:为了保险,把整个仓库的文件内容全塞进上下文,结果模型被海量无关信息淹没,决策质量反而下降。正确做法是:先确定当前决策需要哪些信息,再把相关信息组装成固定格式的上下文块,最后连同决策 schema 一起交给模型。

还有个边界问题值得单独说:系统提示词和 Skill Agent 在 Jev 体系里扮演什么角色。我的理解是这样:系统提示词负责“全局不变原则”,比如安全规范、输出格式底线;Skill Agent 负责“某一类任务的领域知识”,比如“如何分析内存泄漏”这类专业流程;而 Jev 负责“当前这一步做什么选择”。三者是分层关系,Jev 是最靠近具体动作的一层。如果全局规则频繁变化,那是系统提示词没设计好;如果决策点反复出现相同分支,那是应该把它抽象成 Skill;如果单个决策动作本身很复杂,那是 Jev 的决策粒度需要调整。这三个层次不要混在一起写。

3. 实操落地:Jev 式决策在 Agent 里怎么跑

3.1 一个可复用的决策框架模板

理论说完了,来看点能直接用的东西。我把自己在项目里沉淀的决策框架模板分享出来,它分成三层:决策定义、执行循环、记录回放。

决策定义层负责维护所有决策点及其类型约束。推荐用 JSON Schema 统一描述,这样既能喂给模型,又能做程序校验。下面是一个我常用的模板结构:

{ "schema_version": "1.0", "decision_points": [ { "id": "error_triage", "description": "对报错信息进行分流", "input_context": ["error_log", "code_snapshot"], "output_schema": { "type": "object", "properties": { "bucket": { "type": "string", "enum": ["syntax", "runtime", "logic", "infra", "unknown"] }, "confidence": { "type": "number", "minimum": 0, "maximum": 1 }, "suggested_action": { "type": "string", "enum": ["fix_now", "add_diagnostics", "escalate"] }, "reason": { "type": "string", "maxLength": 200 } }, "required": ["bucket", "confidence", "suggested_action"] } } ] }

这个 Schema 的精髓在于suggested_action和bucket都是枚举,程序可以拿到结果后直接做映射处理;reason字段虽然是个字符串,但只是给人看的,不参与程序逻辑。

执行循环层是 Agent 主循环的改造。传统 Agent 循环是“拿任务 -> 生成文本 -> 提取意图 -> 调工具”,Jev 式循环变成“拿决策定义 -> 收集上下文 -> 模型选决策 -> 程序分发动作”。区别在于,意图提取这一步被类型化决策替代了,模型输出直接就是一个可执行的动作标识。

记录回放层是很多人忽视但特别重要的部分。每次决策都应该记录:当前上下文摘要、模型选择的动作、置信度、最终执行结果。这套数据积累下来,你就能分析出哪些决策点模型经常选错、哪些上下文字段对决策帮助最大、哪些枚举值从来没人选中。这些都是后续优化决策定义的重要依据。

3.2 示例:从测试失败到修复方案的完整决策流

说个具体的例子。假设我在一个 Python 项目里跑测试,测试挂了,我想让 Jev 帮我分流这个失败。

传统提示词我可能会写:

测试失败了,请分析下面的错误日志,告诉我问题出在哪里,并给出修复建议: [粘贴日志]

Jev 式做法完全不同。先生成一个决策点定义,把失败场景的选项都列出来:

{ "decision": "test_failure_triage", "context": { "test_name": "test_user_creation", "error_message": "TypeError: create_user() missing 1 required positional argument: 'email'", "recent_diff": "- user = create_user(name, password)\n+ user = create_user(name, password, email)", "file_path": "tests/test_auth.py" }, "choices": [ { "id": "missing_arg", "action": "repair_call_site", "params": { "target_files": ["tests/test_auth.py"] } }, { "id": "wrong_signature", "action": "update_function_def", "params": { "target_files": ["auth/service.py"] } }, { "id": "test_bug", "action": "fix_test_setup", "params": { "target_files": ["tests/test_auth.py"] } }, { "id": "schema_drift", "action": "escalate", "params": { "reason": "接口签名与实际调用不一致,需要人工确认" } } ] }

模型拿到这个决策定义和上下文之后,输出:

{ "choice_id": "wrong_signature", "confidence": 0.87, "evidence": "调用处传了三个参数,但函数定义只包含两个参数" }

程序拿到choice_id之后直接分发到update_function_def这个工具,把它当成一个普通函数调用处理。整个过程没有正则匹配,没有文本意图猜测,完全结构化。

这个流程的关键价值在于可回滚、可审计。如果这次修复把别的测试搞挂了,回放记录时能明确看到“模型当时判断是 wrong_signature,置信度 0.87”,是判断错了还是执行错了,一眼就能定位。

3.3 在 Codex 这类 Agent 环境中怎么接入 Jev

既然热词里提到了 Jev 在 Codex 中使用,这里单独说一下接入思路。Codex 本身是一个编码 Agent,执行循环已经内置,我们需要做的是把类型化决策嵌入到它的工具调用链路里。

我的做法是写一个独立的 router 工具。Agent 在执行过程中遇到需要判断的情况时,不再自己拍脑袋,而是调用jev_router这个工具。jev_router接收当前上下文和决策定义,返回类型化决策结果,再由 Codex 根据决策结果调用后续工具。

伪代码大概是这样的:

def jev_router(context: dict, decision_schema: dict) -> dict: prompt = build_decision_prompt(context, decision_schema) response = jev_model.complete(prompt, response_format="json") validated = validate_decision(response, decision_schema) return validated

关键点在于:response_format="json"和后续的validate_decision。前者从模型端约束输出格式,后者在程序端做二次校验。哪怕模型偶尔抽风输出了 schema 之外的值,校验层也能拦截下来,不会让坏数据流到执行层。

网络热词里提到“jev密钥”,这个其实就是 API key,跟其他模型服务的用法一致。申请密钥、配置到环境变量,然后通过 SDK 或 HTTP 调用。需要注意的一点是:Jev 这种决策型模型的调用频次通常比传统生成型模型高得多,因为每个决策点都要单独调一次。如果你的 Agent 跑一个大任务,可能会产生几十甚至上百次决策调用,密钥的权限配置和额度监控要做好。

另外,热词里还反映了不少人在问“Jev 模型开源吗”。从我目前掌握的信息来看,Jev 是以闭源 API 服务方式提供的,但这不影响我们借鉴它的方法论。哪怕你完全不用 Jev 这个具体模型,只要理解了类型化决策的设计思路,用 GPT-4 或任何一个大模型都能复现同样的效果。方法论是通用的,模型只是载体。

4. 常见问题与排查技巧实录

4.1 决策项太少,模型总是硬凑选项

这是我会遇到的第一个坑。决策定义里选项给少了,模型面对一个不在预设分类里的情况,会硬塞一个相近选项,导致后续动作完全跑偏。

比如你定义了错误类型只有["syntax", "runtime"],模型遇到一个逻辑错误(Logic Error),大概率会往runtime上归类,因为它没有别的可选。后续处理逻辑就会按运行时异常去排查,方向全错。

解决办法是两点:一是增加unknown或other兜底选项,让模型有“不确定”的出口;二是在兜底选项的逻辑里,默认走“上报人工”或“收集更多信息后重试”,而不是自动选择一个危险动作。这个兜底设计不是偷懒,它是类型化决策体系里的安全气囊。

判断兜底选项设计得好不好,有个简单的检查方式:统计一段时间内unknown被选中的比例。如果经常高于 5%,说明你的决策分类没有覆盖真实场景,需要回去补充枚举值;如果几乎从来没被选中,可能分类粒度太粗,模型把所有情况都归到了具体选项里,兜底形同虚设。

4.2 决策类型过死,灵活场景跑不动

跟上面的问题相反,这个坑是分支定义太死板,模型明明可以处理复杂情况,却被 schema 限制住了。

常见症状是:模型对同一个问题给出了合理但不在枚举里的动作,你为了适配它,只能不断往 schema 里加枚举值,越加越多,最后整个决策定义膨胀到几十个选项,模型反而更不知道选哪个了。

这个问题的本质是“决策粒度”和“灵活性”的平衡没有找好。我的经验是:决策点只负责“选方向”,不负责“定细节”。方向的枚举值控制在 5 到 7 个以内,细节交给工具执行时再展开。比如fix_now这个动作,它可以代表“修复未找到的问题”,但具体怎么修,是改实现还是改测试,由执行工具内部再去判断,不要让决策层背负所有分支。

还有一个保险做法是:给每个决策点设定一个“推荐拒识”逻辑。当模型输出的置信度低于某个阈值时,不直接执行,而是返回给上层人工确认或重新收集上下文后再次决策。这个逻辑用对了,比调什么 prompt 都管用。

4.3 决策结果和实际执行的偏差怎么排查

类型化决策的模型端准确率不一定比传统 prompt 高多少,它真正的优势是“可排查”。因为每一步决策都被记录成结构化数据,一旦执行结果与预期不符,我们可以直接回放:模型选了什么、上下文是什么、置信度多高、执行器做了什么。

排查顺序一般是三步:先看决策结果本身是否合理。如果模型选错了,那是决策定义或上下文的问题。再看执行器是否按决策结果执行。有时候模型选择“修改 A 文件”,但执行器因为路径解析问题改了 B 文件,这就是工程 bug,跟模型无关。最后看上下文数据是否可靠。如果塞给模型的 diff 是过期的、或日志被截断了一半,模型基于错误信息做的判断自然不能信。

这里要特别提醒一点:上下文采集的“新鲜度”是个隐蔽的坑。很多 Agent 框架里,上下文是异步预取的,如果某个文件在预取之后被修改了,模型拿到的就是旧信息。我遇到过排查了半天的“模型判断错误”,最后发现是 Agent 上下文缓冲失效。所以要在执行循环里给上下文块打上时间戳,执行前做一次校验。

4.4 上下文太长与决策信息不足的平衡

最后一个高频问题:类型化决策到底该给模型多少上下文?给太少,模型看不清全貌;给太多,关键信号被淹没,还会浪费大量 token。

我的经验做法是“三级裁剪”。第一级是原始信息全量保留,但不直接喂给模型。第二级是从原始信息里提取决策关键字段,比如错误行号、函数名、最近变更文件。第三级是把关键字段格式化成结构化的“决策简报”,再和决策 schema 一起送进模型。

用一个例子说明。原始错误日志可能有一百行,里面绝大多数是无关堆栈。裁剪之后只保留:错误类型、出错文件、出错函数、相邻上下文代码段。模型需要判断的是“这是语法问题还是逻辑问题”,给它堆栈全貌反而分散注意力。

如果预算允许,还可以给模型加一个“信息请求”动作,让它在自己觉得信息不足时主动申请额外上下文。这个动作天然适合 Jev 的类型化设计——它本身就是决策点之一。把这个动作加进枚举后,模型就不再蒙着头做决定,而是会把“我不知道”变成一次明确的工具调用。

我在实际使用中的体会是:Jev 这类“不写文本”的决策范式,最难的其实不是技术实现,而是思维转换。你得接受“模型不需要理解全局才能做好局部”这个观点。每个决策点只关注当前情况,选一个动作,执行,观察结果,再进入下一个决策点。这样组装出来的 Agent 行为,可能没有那种“一口气写出一个完整方案”的惊艳感,但可靠性和可维护性完全是另一个层次。

最后再分享一个小技巧:把你定义好的决策点和枚举值当作代码接口来维护,每次都做 schema 版本控制。模型输出的决策结构跟着 schema 版本走,程序解析时也要做版本兼容处理。这套体系跑久了之后你会发现,提示词工程的“工程”二字,在 Jev 这里终于落回到了真正的工程范式上。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询