📌 前置知识:已完成第一课、第二课
🎯 本课目标:让 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 课

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐