【手搓 AI Agent 从 0 到 1】第三课:让 AI 的输出变得可靠
📌 前置知识:已完成第一课、第二课
🎯 本课目标:让 AI 输出可以被程序直接读取和处理
💡 核心概念:结构化输出 / JSON 约束 / 验证重试
前言
上节课我们给模型赋予了角色,让它扮演不同的助手。
但你有没有遇到这种情况——
你问 AI:“这句话是正面还是负面情感?”
AI 回答:“这句话表达的是比较积极正面的情绪,带有一定的喜悦感……”
你想从回答里提取一个简单的"正面"或"负面",结果发现:根本没法用程序处理这段话。
这就是本课要解决的核心问题。
一、自由文本的困境
当我们用 Agent 处理真实业务时,AI 的输出往往需要被程序继续使用,比如:
- 判断情感,存入数据库
- 提取关键词,写入文件
- 分类用户问题,路由到不同处理逻辑
这时候,AI 的自由文本回答就成了障碍。
原因有三:
① 格式不固定
同样的问题,每次回答的格式可能不一样。有时加"好的!",有时直接答,有时还带个小结。程序没有办法稳定地解析它。
② 内容不可预测
模型可能在回答里加入多余的解释、注意事项、补充说明,你想提取的那个值被淹没在大段文字里。
③ 字段无法保证
你需要"情感"和"置信度"两个字段,但模型只给了你一个,或者用了不同的叫法。
二、解决思路:让 AI 按格式输出
解决方案其实很直接:在提示词里明确告诉模型,必须按照某个格式回答。
这里说的"提示词",指的是系统级提示词(System Prompt)——还记得第二课讲的内容吗?System Prompt 是在对话开始前写给模型的"角色设定",模型在整个对话中都会遵守它。
把格式要求写进 System Prompt,而不是每次用户问问题时才临时附上,有两个好处:
- 全局生效:整个对话过程中,模型始终知道要输出 JSON
- 权重更高:System Prompt 的优先级高于 User 消息,更难被模型"忽略"
最常用的格式是 JSON,因为:
- 几乎所有编程语言都能直接解析
- 字段名明确,结构清晰
- 支持嵌套,表达能力强
我们把这个要求叫做输出契约——模型必须遵守的输出规范。
比如,在 System Prompt 中这样写:
你是一个情感分析助手。
你必须只返回 JSON,格式如下:
{"sentiment": "正面" | "负面" | "中性", "confidence": "high" | "medium" | "low"}
不要任何解释,不要 Markdown,直接从 { 开始。
然后用户发来任意一句话,模型就会按这个格式回答。
三、但光靠提示词还不够
你可能会问:直接在提示词里要求 JSON,模型就会老老实实输出吗?
不一定。
大模型是概率模型,它不是确定性程序。同样的提示词,有时候输出标准 JSON,有时候会在前面加一句"好的,以下是结果:" ,有时候会用 Markdown 的代码块包起来。
所以,只靠提示词还不够,我们还需要两个额外的手段:
3.1 JSON 提取
不直接信任模型的原始输出,而是从输出文本中主动提取 JSON 部分。
即使模型在 JSON 前后加了废话,我们也能把真正的 JSON 找出来。
示意逻辑如下:
原始输出:"好的!以下是结果:{"sentiment": "正面", "confidence": "high"} 希望对你有帮助。"
提取后:{"sentiment": "正面", "confidence": "high"}
3.2 重试机制
如果提取失败(模型输出了完全无法解析的内容),不要直接报错,而是重试。
一般重试 3 次就足够了。大模型的输出具有随机性,第一次失败不代表第二次也失败。
重试逻辑:
第1次请求 → 提取 JSON → 失败
第2次请求 → 提取 JSON → 成功 ✓
三次都失败,再返回错误。这样把"概率性行为"变成了"可靠行为"。
四、验证:不能只管格式,还要管内容
拿到 JSON 之后,还不能直接用,需要验证字段是否符合预期。
三个检查点:
| 检查项 | 说明 | 例子 |
|---|---|---|
| 是否是合法 JSON | 基本格式检查 | { 开头,} 结尾,引号成对 |
| 是否有必要字段 | 不能缺字段 | sentiment 字段必须存在 |
| 字段值是否合法 | 枚举值检查 | confidence 只能是 high/medium/low |
验证不通过,进入重试流程。
这就是工程化思维的体现——把 LLM 当作一个可能出错的组件来处理,而不是无条件信任它。
五、完整流程总结
用户输入
↓
构造提示词(含 JSON schema 要求)
↓
调用模型(temperature=0,降低随机性)
↓
提取 JSON
↓
验证字段
↓
通过? → 返回结果
失败? → 重试(最多3次)→ 全部失败则返回错误
整个流程做下来,你的程序就可以稳定地处理 AI 输出了。
六、为什么 temperature 要设为 0?
temperature 控制模型输出的随机程度:
temperature=1.0:创意写作,输出多样temperature=0.0:结构化输出,结果更稳定、更确定
做情感分析、信息提取这类任务,我们不需要"创意",需要的是每次都给我一样格式的答案。所以设为 0。
七、常见问题
Q:提示词写得很清楚,模型还是不按 JSON 输出?
A:加上更强的限制语气,比如 “CRITICAL: Respond with ONLY valid JSON”,同时配合 JSON 提取函数兜底。
Q:重试 3 次还是失败怎么办?
A:说明这个任务对模型来说比较难,可以尝试:① 简化 schema;② 换更强的模型;③ 在提示词里加一个 JSON 示例。
Q:验证逻辑要写多复杂?
A:够用就好。一般检查"字段存在"和"枚举值合法"这两条就够了,不用搞成完整的 JSON Schema 验证器。
八、下期预告
第四课:让 AI 做决策(工具调用)
单纯问答已经不够用了。下一课,我们让 Agent 根据用户输入,自主选择要执行什么动作——这才是 Agent 区别于普通聊天机器人的核心能力。
完整代码获取
本课涉及的完整代码包括:
extract_json_from_text()提取函数- 带重试的
generate_structured()方法 - 完整的情感分析项目
代码获取方法,请参照 【手搓 AI Agent 从 0 到 1】第一课:Ollama + Qwen 跑起你的第一个 AI 程序
本文为《手搓 AI Agent 从 0 到 1》系列教程第 3 课
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)