说实话我第一次接触 Jev 时是有点懵的。我让它帮我做一次代码评审结果它不给我输出一段“分析意见”也不说“我觉得这里可能有风险”——它直接甩给我一个 JSONaction 是 request_changesconfidence 是 0.84reason 里一句话带过问题最后跟两个修改建议的字段。没有客套话没有上下文铺垫像一个冷冰冰的自动化工单系统。但用了一周之后我反而觉得这才是面向“真实任务”的模型应该有的样子。我们以前习惯的“提示词工程”本质上是教模型写自然语言回复而 Jev 这种“不写文本”的模型真正需要的是一套完全不同的提示词设计思路——不是让它说话而是让它做决策。这篇就把这套思路掰开揉碎讲清楚什么是类型化决策怎么用提示词约束模型输出结构化决策以及在 Jev 接 Codex、配置密钥、跑通自动化的过程中你会踩到哪些坑。1. 类型化决策提示词工程的新主线1.1 “写文本”和“做决策”是两种完全不同的任务我们平时写 prompt默认场景是“模型给我讲一段话”。你问它“这段代码有什么问题”它给你回一段包含分析、建议、示例代码的段落。人类读起来很舒服因为信息密度低、有过渡、有解释。但当你需要把模型接入到自动化流程里这套就废了。你的下游是一个程序它不关心模型写得通顺不通顺它只关心能不能从输出里稳定地抽取出“动作”和“参数”。如果模型每次回复的格式都不一样你后面的解析逻辑就要用正则去捞、用字符串去切捞出来的字段还可能对不上。这种脆弱链路线上跑两天就会让人崩溃。Jev 的策略很直接不生成自然语言文本直接生成“决策对象”。给它一个任务它给你一个结构化结果类似{action: approve, confidence: 0.92, ...}。这不是它能力不行而是它被刻意训练成“决策引擎”而不是“聊天助手”。这里就引出核心概念——类型化决策。所谓类型化就是给模型的输出定义一个明确的、可校验的数据结构哪些字段必须出现、每个字段的取值范围是什么、彼此之间有什么约束。传统 prompt 是“请你分析一下”决策型 prompt 是“请从这几个动作里选一个并附上指定字段”。两类任务的差异非常明显维度传统提示词类型化决策提示词输出形式自然语言段落结构化对象 / JSON / 枚举消费方人类阅读程序执行质量标准语义准确、措辞自然字段完整、取值合法、可解析失败模式回答偏题、胡编格式不合法、枚举越界、缺字段调优手段改说话风格、加背景改 schema、加约束、补示例所以“Jev 不写文本”并不是缺陷反而提醒我们提示词工程的重心正在从“措辞”转移到“决策空间设计”。你不需要教它怎么说漂亮话你需要告诉它你有哪些可选动作、每个动作的触发条件是什么、输出结构长什么样。1.2 类型化决策的三种常见形态我归纳了一下大部分“决策型模型输出”都可以归成三类第一类枚举决策。模型只负责从一组固定选项里选一个比如 approve / reject / request_changes再配一个置信度。这类最简单适合任务路由、内容审核、动作分发。你需要的约束很轻一个 enum 字段就够。第二类结构化对象。输出一个包含多个字段的对象可能嵌套数组。比如自然语言转 API 参数意图是 create_issue参数里有 title、description、assignee。这类最关键的是字段级约束哪些必填、哪些可选、字段间依赖关系怎么表达。第三类动作序列。模型输出一组有序动作每个动作有自己的参数。相当于把“决策”拆成多步。例如调试流程第一步读日志第二步查配置第三步改代码每一步都是一个带参数的对象。这类最接近 Agent 的行为但提示词设计难度也最高因为你要约束步骤之间的顺序和依赖。我自己用下来第一类最容易上手第二类最容易出价值第三类要谨慎。大多数场景先用枚举 结构化对象就够了不要一上来就设计一堆动作序列否则模型很容易在中间步骤“自由发挥”。1.3 给决策做类型定义从“人懂”到“机器也懂”传统提示词里我们靠自然语言描述来约束模型“你是一个严谨的工程师回复要简洁”。这种约束是软性的模型经常违反。类型化决策要求你把约束升级成“硬性定义”。最简单的形式是 JSON Schema或者直接给一段 TypeScript 类型定义。你可以把它放在 system prompt 里明明白白告诉模型“你的输出必须满足这个结构任何额外字段和文本都不允许”。我常用的是 JSON Schema因为它既能喂给模型看也能直接用于程序校验。先用它约束模型再用它校验输出一套定义两头用。举个例子。一个代码评审决策的 schema 长这样{ $schema: http://json-schema.org/draft-07/schema#, type: object, properties: { action: { type: string, enum: [approve, reject, request_changes] }, confidence: { type: number, minimum: 0, maximum: 1 }, reason: { type: string, maxLength: 200 }, changes: { type: array, items: { type: string } } }, required: [action, confidence] }这玩意儿的价值在于它把“模型应该输出什么”从模糊变成了精确。模型的自由被限制住了但稳定性大幅提升。你可以理解成传统 prompt 是面试聊天面试官看感觉决策型 prompt 是笔试答题卡选项、空位、评分标准全给你列清楚。有人会担心这样约束会不会让模型变蠢我的体验是恰恰相反。真正的推理发生在一个受限的选项集里时模型更容易聚焦少了很多“为了凑字数的废话”反而把有限的上下文预算花在了刀刃上。2. 面向类型化决策的提示词设计方法2.1 把“角色设定”换成“决策空间定义”很多人的 prompt 习惯是“你是一个资深后端工程师有十年分布式系统经验请帮我看看这段代码。”这套在决策型场景里不能说没用但优先级很低。模型不关心“你是谁”它关心“你有哪些动作可选、每个动作的触发规则是什么”。所以我建议把 system prompt 的大头从角色描述换成决策空间定义。角色设定留一句话带过即可核心部分写清楚三件事可用动作列表、每个动作的触发规则、输出格式要求。我给你一个可以直接抄的模板你是一个代码评审决策引擎。你不输出任何自然语言分析只输出一个符合给定 JSON Schema 的决策对象。 可用动作及规则 - approve: 改动安全、逻辑清晰、符合项目约定时使用。 - reject: 存在阻塞性 bug、安全漏洞或严重设计问题时使用。 - request_changes: 存在非阻塞改进点、但不影响主流程合并时使用。 输出要求 1. 必须包含 action 和 confidence 字段。 2. confidence 范围是 0.0 到 1.0表示你对本次决策的把握程度。 3. 除 JSON 外禁止输出任何额外内容。看到区别了吗角色设定只有半句话决策规则占了绝大部分。因为对决策型模型来说“边界”比“身份”重要得多。你给它设定一个角色它只会模仿那个角色的语气你给它定义决策空间它才能真正做出符合预期的选择。2.2 用 JSON Schema 管住模型的输出格式光在 system prompt 里写“输出 JSON 格式”是不够的。你还需要把 schema 直接贴进去。实践下来模型对 schema 的遵循度明显高于对自然语言要求“请输出 JSON”的遵循度。贴 schema 的时候注意一点字段不要贪多。一个常见的错误是你想一次性拿到所有信息结果定义了一个十几个字段的对象模型输出时要么漏字段要么字段之间逻辑矛盾。我建议每个决策对象控制在 3 到 6 个核心字段。如果不得已要有多个可选字段就用required明确哪些必须有。模型对 required 的遵循度比 optional 高很多。你只要允许“可选”它就敢给你缺着。另一个经验schema 里尽量给 enum 字段加一个默认动作比如代码评审里的 request_changes意图识别里的 other。模型遇到看不清的情况时会倾向输出一个“安全但不激进”的值。如果你不给默认值它可能随便编一个不在枚举里的词或者干脆输出一堆文本。注意enum 里不要加“不确定”这种抽象值。模型会过度使用它。你可以在规则里说明“当无法判断时输出 request_changes”然后让它落到一个具体动作上而不是给一个“maybe”字段。2.3 用少量示例锚定决策边界schema 能管住格式但管不住语义。模型知道 action 只能是 approve / reject / request_changes但它不一定知道什么情况算 reject什么情况算 request_changes。这时就需要 few-shot 示例来锚定边界。我每次搭建决策 prompt 时最少都会给两个正例和一个反例。正例展示“典型情况应选什么动作”反例展示“看似危险但其实应该选另一个动作”。这会显著改善模型在边界条件下的表现。举个例子在代码评审场景里我通常会放这两条输入修复了登录接口的空指针异常补充了对应单测改动 40 行。 输出{action: approve, confidence: 0.95, reason: 修复明确且带测试保护。} 输入新增了一个导出功能但文档没有更新且缺少对该功能的分页测试。 输出{action: request_changes, confidence: 0.8, reason: 功能主体逻辑正确但文档和测试覆盖需补全。}这两个示例一放进去模型对 action 边界的理解立刻清晰很多。对比一下如果只给定义模型面对“有小问题但不严重”的改动时可能一会儿 approve 一会儿 request_changes飘忽不定。示例还有个额外好处它们本身就是一种“上下文压缩”。模型不需要去推理“什么样的修改算阻塞性 bug”它可以直接类比示例。尤其在你接入 Jev 这种输出偏简短的模型时示例比抽象规则管用得多。2.4 让模型先推理再决策结构化思维链有些决策不能拍脑袋。代码评审里遇到一个涉及并发安全的问题模型直接给出 reject 很容易误判。这时候你需要让它把推理过程也结构化输出。我的做法是在 schema 里增加一个或两个“中间思考字段”。比如一个问题判断类的任务可以设计成{ type: object, properties: { evidence: { type: string, description: 本次决策依据的关键事实 }, risks: { type: array, items: { type: string } }, action: { type: string, enum: [approve, reject, request_changes] }, confidence: { type: number } }, required: [evidence, action, confidence] }让模型先输出它看到了什么证据再列风险最后给动作。这一步很像传统思维链CoT但关键是中间结果也是结构化的。这让下游不仅能看到最终决策还能看到决策依据出了问题容易复核。使用上有一个技巧并不是每步都要 thinking。简单路由任务强制模型先思考反而会增加延迟和偶发错误。我自己一般遵循这个原则——决策代价高、不可逆的加 evidence 和 risks决策代价低、可纠正的只输出 action 和 confidence。3. 实操在 Jev 场景里落地一套决策提示词3.1 场景代码评审自动通过/打回我先把完整代码评审决策流程走一遍。需求是接到一个 PR 的 diffJev 返回决策结果脚本根据 action 调用下游接口自动 approve 或打回。system prompt 就是前面那个“决策引擎”模板再加上 few-shot 示例。user prompt 里放 diff 和项目约定请评审以下 diff diff - def parse_config(raw): - return json.loads(raw) def parse_config(raw: str) - dict: data json.loads(raw) if not isinstance(data, dict): raise ValueError(config must be an object) return data /diff 项目约定 - 所有对外函数必须带类型注解。 - 新增逻辑必须有单元测试。 - 禁止使用 eval。Jev 返回的是{ action: approve, confidence: 0.9, reason: 新增了类型注解和输入校验改动符合项目约定未发现阻塞性问题。 }我拿到后直接用 jq 解析再根据 action 调 GitHub API。整个过程从“看代码”变成了“看决策对象”。一开始不太习惯后来发现反而省心——你不需要再读模型的“分析长文”去猜它到底支不支持合并。这里有个很关键的点评审规则必须写进 system prompt而不是藏在 user prompt 里。你每轮传入的 user 内容会变如果把规则写在 user 里规则权重会被 diff 内容稀释。system prompt 是常驻的模型始终能看到优先级最高。3.2 场景自然语言指令到 API 调用参数另一个高频场景是把用户的一句话转成结构化 API 参数。比如你有一个工单系统想让模型把“帮我给张三建一个高优先级 bug 单标题是关于登录报错”转成调用参数。这个场景的核心是意图识别加参数抽取。我定义了这样的期望输出{ intent: create_issue, params: { title: 修复登录接口报错问题, assignee: 张三, priority: high } }如果把字段再展开intent 的枚举是 create_issue / assign_issue / list_issues / close_issue。params 里的字段随 intent 变化。这里有个容易踩的坑参数类型不一致。模型可能把 priority 填成 HIGH 或 高优先级而你的系统只认 high。解决办法是两道防线第一在 prompt 里明确告诉你“priority 只接受 high / medium / low其他值一律归一化为 low”第二在代码里做个二次映射把 HIGH、高 这种值折叠到标准枚举里。只靠 prompt 不靠谱只有 prompt 加代码双层兜底才稳。3.3 把 Jev 接入 Codex 并跑通一次决策调用Jev 在 Codex 里的集成方式和多数兼容 OpenAI 接口的模型差不多。先配置密钥和相关环境变量export JEV_API_KEYsk-你的密钥 export JEV_BASE_URLhttps://api.jev.example.com/v1这里的地址是示例占位你申请密钥后从服务商控制台复制真实地址即可。然后在 Codex 配置里指定模型供应商model jev-1 model_provider jev [model_providers.jev] name JEV base_url ${JEV_BASE_URL} env_key JEV_API_KEY配置完成后先用一个最简单的请求验证连通性再上决策任务。我用 curl 直接测curl $JEV_BASE_URL/chat/completions \ -H Authorization: Bearer $JEV_API_KEY \ -H Content-Type: application/json \ -d { model: jev-1, messages: [ {role: system, content: 你是一个决策引擎只输出JSON。}, {role: user, content: 判断这个改动是否安全修改了密码校验逻辑但没有新增测试。} ], temperature: 0 }注意我这里 temperature 设成了 0。决策型任务尽量别给模型留随机性。你要的是稳定输出一个动作不是让它每次换个说法。拿到响应后用 jq 校验是否是我们期望的 JSON 结构curl ... | jq .choices[0].message.content | fromjson如果这一步能稳定输出合法 JSON再开始接后续自动化和解析逻辑。如果你是第一次跑大概率会遇到输出前面带文字、JSON 没闭合、字段缺失这些问题。别慌这在下一部分展开讲。3.4 上下文工程别把整本手册塞进 Prompt模型能参考的上下文是有限的。尤其是决策型模型上下文里噪音越多决策越飘。我见过有人把整个项目的 README、架构文档、代码规范全拼进 system prompt结果模型动不动就被无关信息带偏。“上下文工程”的核心不是“塞更多信息”而是“只保留和当前决策相关的信息”。以代码评审为例你不需要给整个仓库只需要给本次 diff、涉及文件的最近变更、以及项目里跟本次改动相关的几条约定。我通常的做法是三步检索、过滤、拼装。先用脚本找出 diff 涉及的文件再抽取这几条关键规则最后跟 diff 一起拼进 user prompt。这样既控制了上下文长度又保证了决策依据充分。4. 常见问题与排查技巧实录4.1 模型就是不按格式输出怎么办这是最普遍的问题。模型明明被告知“只输出 JSON”结果前面还是加了“好的根据您的描述我的判断是”这种废话。我有三层解法。第一层把 schema 放在 system prompt 靠前位置并增加一句“输出必须直接以 { 开头以 } 结尾否则将被系统拒绝”。很多小模型吃软不吃硬你把“否则”的后果说清楚它就不敢乱来了。第二层在代码里做容错解析。不要假设模型输出一定是合法 JSON。写一个提取器找到第一个{和最后一个}之间的内容再做解析这样能滤掉大部分前缀文本。第三层失败重试。解析失败后不需要重新问一遍完整问题而是把失败原因作为新消息发回去“你的上次输出不是合法 JSON请只输出一个 JSON 对象。”这一招非常管用因为模型知道自己刚才错了。4.2 枚举值漂移模型总爱“自由发挥”有时模型会输出一个不在枚举里的值比如action: check你的枚举里只有 approve / reject / request_changes。这通常是因为模型对任务的理解出现了偏差把动作名写成了动词。排查思路是先看是否是同义词问题。比如“check”可能想表达“request_changes”但被你拦截了。如果是同义词就在 prompt 里写明“check、review、needs_work 等词一律视为 request_changes”。如果完全是不合规输出就按 4.1 的重试逻辑处理。另一个技巧是给枚举加“别名映射表”。我在 schema 说明里直接写一段映射让模型知道哪些词是等价动作从源头减少漂移。4.3 system prompt 工程和 skill agent 有什么区别这个话题最近讨论很多我用一句话概括system prompt 是“宪法”skill agent 是“专家”。宪法定义了所有决策的底线和总原则专家负责在具体场景里执行具体动作。对 Jev 来说决策 schema、输出格式、全局安全规则应该写进 system prompt让它在任何时候都遵守。skill agent 则适合做成可插拔的专家工具比如“单测生成专家”、“SQL 优化专家”按需加载。如果你发现模型经常不按类型输出决策先检查 system prompt 里是不是忘了放 schema。如果模型输出格式对但决策质量差再考虑是不是 skill agent 的调用策略有问题例如没有在合适时机触发对应工具。4.4 误判与安全没有决策也是一种决策自动化决策的风险在于误判。代码评审模型把有严重 bug 的改动判成 approve后果很严重。所以必须设计兜底机制。我常用的策略是给 confidence 设阈值。当 confidence 低于 0.6 时不让模型直接决策而是进入人工队列。这相当于给系统加了一道保险。更进一步可以对高风险动作比如 reject涉及直接打回单独提高阈值要求必须同时满足证据充分。另一个思路是“默认动作”。当模型因为各种原因无法输出合法决策时不让流程沉默而是默认走最保守的路径。代码评审里最保守的路径是 request_changes工单系统里最保守的路径是“转人工”。记住一句话没有决策也是一种决策而且往往是成本最高的那一种。4.5 版本与生态问题开源、密钥、申请很多人问我 Jev 开源吗。从我目前了解到的情况看它不是全量开源那种更像是一个面向 Agent 场景的托管模型服务。但这不影响你在代码里集成它因为它提供了通用的 API 兼容层接 Codex 或者是自己写脚本都行。申请和使用流程一般分几步注册账号、申请 API 权限、拿密钥、配置环境变量。密钥建议放到环境变量里不要硬编码进代码仓库。在 Codex 里接入时务必确认 base_url 和模型名是否填对这两个字段错了会直接连不上。注意不同时期、不同版本的工具链差异很大。如果你照着教程配完发现连不上先别急着怀疑模型检查一下 base_url、模型名、API 版本八成是配置路径变了。我自己这阵子用下来最深的体会是Jev 这类“不写文本”的模型逼着我重新思考了提示词的本质。以前优化 prompt我总在想怎么把话说得更清楚现在优化 prompt我变成了一个“决策空间设计师”——考虑枚举值够不够用、字段结构稳不稳、兜底动作安不安全。这种思维转换并不容易但一旦转过来你会发现自己做的不是“聊天”而是一套可以测试、可以审计、可以回滚的工程系统。最后分享一个小技巧每一次迭代只改一个约束然后记录模型响应的分布变化。比如你加了一条“输出必须直接以 { 开头”跑二十次看看格式错误率从多少降到多少。把提示词当代码一样做 diff、做回归、做版本管理这才是类型化决策时代的提示词工程该有的样子。