阶段 2:LLM 应用基础学习日志
阶段 2:LLM 应用基础学习日志
主题:模型 API、消息结构、流式输出、Prompt、Structured Outputs、Function Calling、参数校验与错误兜底
适用阶段:RAG / Tool Calling / Agent 之前的关键基础阶段
学习目标:从“会写提示词”升级到“能稳定构建 LLM 应用”
一、这一阶段到底在学什么
阶段 2 的核心,不是“会聊天”,而是“会把模型接入程序系统”。
二、这一阶段的总认知框架
把一次 LLM 请求理解成下面这个结构:
用户任务
↓
指令(instructions / system behavior)
↓
输入(input / messages / items)
↓
模型生成
↓
输出约束(文本 / JSON / schema / tool call)
↓
程序解析
↓
工具执行 / 数据查询 / 结果展示
↓
错误处理 / 重试 / fallback
所以,真正的工程化 LLM 应用,不只有一个 prompt,至少包含:
- 指令设计
- 上下文管理
- 输出格式约束
- 工具协议
- 参数校验
- 异常处理
- 状态管理
三、第一部分:模型 API、消息结构、流式输出
3.1 Responses API 是当前主线
当前学习 OpenAI API 时,建议把 Responses API 当成主线来学。
它可以统一处理:
- 普通文本生成
- 多轮上下文
- structured outputs
- function calling
- 内置工具
- conversation state
你不要再把“LLM 调用”只理解成旧式的 messages=[...] 聊天接口。
在新的接口思路里,更应该理解为:
instructions:本轮高层行为约束input:当前输入内容tools:模型可调用的能力stream:是否流式返回output:模型真正的输出项集合output_text:方便读取最终文本的快捷字段
3.2 最小可运行调用
Python 示例
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.4",
instructions="你是一个简洁的技术助教。",
input="请用一句话解释什么是 HTTP。"
)
print(response.output_text)
你要理解的点
1)instructions
它是高层指令,决定模型这次“以什么身份、什么原则、什么风格”回答。
适合放:
- 角色
- 行为边界
- 风格要求
- 输出原则
例如:
- 你是一个严谨的技术助教
- 回答要分点但不能过度啰嗦
- 如果信息不足要明确说明不确定
2)input
它是当前轮实际处理的内容。
适合放:
- 用户问题
- 当前任务描述
- 当前轮上下文
- 需要分析的数据
3)response.output_text
这是最方便的读取方式,适合“只关心最终文本”的场景。
但你必须知道:
底层真正的返回不是一段字符串,而是 output items。
因为模型的输出未来可能不只是文本,还可能是:
- 消息内容
- function call
- tool output
- reasoning item
这点是你进入 Agent 学习前必须先建立的思维。
3.3 不要把“模型输出”只当成一段文字
初学者常见误区:
模型输入是一段 prompt,模型输出是一段文本。
这在最简单 demo 里没问题,但一旦进入工程就不够用了。
你要逐渐建立下面这个理解:
模型输出 ≠ 单纯文本
模型输出 = 一组可被程序消费的结果项
例如在一个工具调用场景里,模型输出可能是:
- “我需要调用天气工具”
- 工具名:
get_weather - 参数:
{"city": "Hangzhou"} - 工具执行完后,模型再基于结果生成最终回答
也就是说,模型输出要能驱动程序动作,而不是只让人阅读。
3.4 消息结构:为什么要分层
初学时最容易犯的错误是把下面这些东西全糊在一个 prompt 里:
- 系统指令
- 用户输入
- 历史对话
- 工具结果
- 输出格式要求
- 边界规则
这会造成两个问题:
问题 1:可维护性差
你后续修改任何一个部分,都容易破坏整体行为。
问题 2:职责不清
程序分不清:
- 哪部分是规则
- 哪部分是任务
- 哪部分是历史
- 哪部分是工具结果
因此,工程化思路一定是分层:
推荐的输入分层
第 1 层:行为指令
例如:
- 你是一个代码审查助手
- 优先指出严重 bug
- 输出先给结论,再给理由
第 2 层:当前任务输入
例如:
- 下面是用户的代码
- 请检查可能的空指针问题
第 3 层:历史上下文
例如:
- 用户之前说系统运行在 FastAPI 中
- 用户更关注性能,不太关注代码风格
第 4 层:工具结果
例如:
- 数据库查询结果
- 搜索结果
- 文件内容
第 5 层:输出要求
例如:
- 必须输出 JSON
- 字段包括
risk_level,issues,suggestions
3.5 多轮上下文的本质
多轮对话不是“聊天记录滚动显示”这么简单。
它的本质是:
当前这一轮,要不要把前面的内容继续带入模型上下文。
你要解决的核心问题
- 带哪些历史?
- 带多少历史?
- 历史里哪些信息才真正重要?
- 如何降低 token 成本?
- 如何避免旧上下文污染当前任务?
3.6 多轮上下文的两种基本思路
方式 1:手动拼接上下文
最传统的方法是自己保存聊天记录,然后下一轮再拼回去。
示意:
history = [
{"role": "user", "content": "什么是 HTTP?"},
{"role": "assistant", "content": "HTTP 是一种应用层协议。"},
{"role": "user", "content": "那 404 是什么?"}
]
这种方式的优点:
- 可控性强
- 兼容性高
- 好理解
缺点:
- 容易越拼越长
- token 成本越来越高
- 程序端要自己管理摘要、裁剪、截断
方式 2:使用 previous_response_id
Responses API 支持把上一轮 response 作为下一轮上下文链起来。
示意:
from openai import OpenAI
client = OpenAI()
r1 = client.responses.create(
model="gpt-5.4",
instructions="你是一个耐心的助教。",
input="什么是 HTTP?"
)
r2 = client.responses.create(
model="gpt-5.4",
previous_response_id=r1.id,
instructions="你是一个耐心的助教。",
input="那 404 状态码又是什么意思?"
)
print(r2.output_text)
这里有一个非常容易忽略的点
使用 previous_response_id 时,上一轮的 instructions 不会自动继承。
所以你不能误以为“上一轮设过系统行为,这一轮就自动还在”。
如果你希望行为持续稳定,通常要在新一轮里继续提供对应指令。
3.7 会话状态管理:为什么不能无脑带全量历史
上下文不是越多越好。
无脑带全量历史的问题
1)成本上升
输入 token 变多,请求更贵。
2)延迟变高
模型读更长上下文,首字节响应通常会更慢。
3)噪声变多
旧历史可能和当前问题无关,反而干扰当前回答。
4)注意力污染
模型可能抓住旧约束,忽略当前更重要的任务。
正确做法
上下文管理要做选择:
- 保留当前任务强相关历史
- 对长对话做摘要
- 只保留关键事实、用户偏好、未完成事项
- 工具输出尽量结构化保存,而不是原样塞回全部文本
你后面做 Agent 时,所谓“记忆”,本质上就是这个问题的升级版。
3.8 流式输出是什么
默认响应模式:
- 模型生成完整回答
- 服务端一次性返回
- 前端再统一显示
流式输出模式:
- 模型边生成
- 服务端边返回增量事件
- 前端边展示内容
用户体验上的差异非常大。
适合流式输出的场景
- 聊天产品
- 回答较长
- 用户希望尽快看到首字
- 你想提升“系统正在工作”的感知
- 你需要边生成边渲染
不一定非流式的场景
- 结果很短
- 结果必须严格校验后才能展示
- 后端流程里还要先调用多个工具
- 更关注稳定入库而不是交互体验
3.9 流式输出不是“print 一下就行”
这是一个很常见误解。
流式输出真正会遇到的问题包括:
- 增量内容如何拼接
- 如何识别结束事件
- 中途断流如何处理
- 前端取消请求怎么办
- 工具调用过程中如何切换展示状态
- 结构化输出场景里是否适合边展示边解析
所以流式输出属于:
交互体验能力 + 工程处理能力
不是简单的语法问题。
3.10 流式输出的学习重点
你不需要一开始就死扣事件名细节,但要搞懂下面几个点:
1)为什么要流式
为了降低用户等待焦虑,提升首字节体验。
2)流式的本质
返回的是事件流,不是一次性完整文本。
3)程序端要做什么
- 接收事件
- 增量拼接
- 判断结束
- 处理异常
- 将结果推送到前端
4)什么情况下不适合流式
- 结果必须先整体校验
- 工具链很长,中间不适合直接向用户暴露过程
- 输出非常短,流式收益小
3.11 什么时候直接 prompt,什么时候接 tool
这个是 LLM 应用开发最重要的判断之一。
适合直接 prompt 的情况
模型自己就能完成任务,并且不需要访问外部世界。
例如:
- 翻译
- 改写
- 总结
- 提取关键词
- 对一段文本分类
- 解释一个稳定概念
适合接 tool 的情况
任务依赖外部数据、外部动作或确定性系统能力。
例如:
- 查最新天气
- 查数据库订单
- 查用户账户余额
- 搜索知识库
- 调用公司内部接口
- 发邮件
- 创建日历事件
一句话判断原则
只靠模型记忆能完成的,优先直接 prompt。
凡是需要访问外部世界的,就应该考虑 tool。
3.12 为什么“能不用 tool 就别用”也是错的
有些初学者会想:
tool 太麻烦了,我都让模型自己回答算了。
这会导致两个大问题:
问题 1:时效性错误
比如你问:
- 今天杭州天气怎么样
- 我最近一笔订单状态如何
模型如果不调工具,只能“猜”。
问题 2:确定性不足
比如:
- 做复杂数学计算
- 查具体数据库记录
- 执行某个业务动作
这些事情应该由程序系统完成,而不是由模型凭概率生成。
结论
LLM 负责理解与决策。
工具负责连接真实世界与确定性系统。
四、第二部分:Prompt、结构化输出、函数调用基础
4.1 为什么只会写 prompt 远远不够
很多初学者学大模型时,只关注“怎么把 prompt 写得更像咒语”。
这在 demo 阶段还凑合,但到了实际系统里不够。
因为真正要解决的问题是:
- 输出能不能稳定解析
- 字段能不能固定
- 参数能不能可信
- 工具调用能不能被程序安全执行
- 错误时能不能自动兜底
所以你必须从“prompt 工程”升级成:
Prompt + Schema + Validation + Fallback
这才是 LLM 应用工程的基础组合拳。
4.2 什么是 Structured Outputs
Structured Outputs 的核心目标是:
让模型输出严格符合你定义的结构,而不是只“看起来像 JSON”。
这是非常关键的差别。
普通“请输出 JSON”
模型可能:
- 漏字段
- 多字段
- 类型错误
- 枚举值写错
- 在 JSON 外面再加一段解释
Structured Outputs
你提供 schema 后,模型输出要满足这个结构要求。
这样程序才能稳定消费结果。
4.3 JSON mode 和 Structured Outputs 的区别
这是面试高频题。
JSON mode
只能尽量保证输出是合法 JSON。
它不保证:
- 字段齐全
- 字段名正确
- 字段类型正确
- 枚举范围正确
- 嵌套结构符合预期
Structured Outputs
不仅要求是 JSON,还要求符合你定义的 JSON Schema。
结论
- 只想让输出长得像 JSON:JSON mode
- 真正需要程序稳定解析:Structured Outputs
在工程里,优先级明显是后者更重要。
4.4 为什么 Agent 强依赖结构化输出
Agent 不是为了“说得像人”,而是为了“驱动程序继续行动”。
例如一个 Agent 系统可能要做下面这些事:
- 判断当前任务属于哪种类型
- 决定是否调用工具
- 决定调用哪个工具
- 生成工具参数
- 接收工具结果
- 更新状态
- 决定是否结束循环
如果模型输出不稳定,比如:
- 有时返回字符串
- 有时返回半结构化文本
- 有时字段名不一致
- 有时漏必要字段
那整个系统的控制流就会变得非常脆弱。
所以你可以记住一句话:
对聊天产品来说,结构化输出是加分项;对 Agent 来说,结构化输出是基础设施。
4.5 JSON Schema 是什么
JSON Schema 可以理解为:
你给模型和程序共同约定的一份“数据合同”。
它定义了:
- 允许有哪些字段
- 每个字段是什么类型
- 哪些字段必填
- 枚举值有哪些
- 是否允许多余字段
- 嵌套对象长什么样
例如:
{
"type": "object",
"properties": {
"intent": {"type": "string", "enum": ["qa", "search", "action"]},
"confidence": {"type": "number"},
"need_tool": {"type": "boolean"}
},
"required": ["intent", "confidence", "need_tool"],
"additionalProperties": false
}
这个 schema 表达的意思
模型必须返回一个对象,并且:
intent只能是qa/search/actionconfidence必须是数字need_tool必须是布尔值- 不能偷偷返回别的字段
这就是“结构化”的真正含义。
4.6 结构化输出的典型使用场景
场景 1:信息抽取
比如从自然语言里提取:
- 时间
- 地点
- 人物
- 事件
场景 2:任务分类
比如把用户请求分类为:
- 问答
- 检索
- 执行操作
- 投诉
场景 3:前端渲染
让模型直接返回卡片渲染需要的字段。
场景 4:Agent 状态流转
让模型输出:
- 当前状态
- 下一步动作
- 是否结束
- 需要调用的工具类别
场景 5:报告结构化摘要
把总结结果固定成:
- 核心结论
- 风险点
- 建议项
- 优先级
4.7 Structured Outputs 示例思路
你不必死记所有 SDK 细节,但一定要懂下面这个模式:
目标
让模型把一句话中的事件信息抽取成结构化对象。
示例结构
from pydantic import BaseModel
from openai import OpenAI
client = OpenAI()
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
response = client.responses.parse(
model="gpt-4o-2024-08-06",
input=[
{"role": "system", "content": "Extract the event information."},
{"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}
],
text_format=CalendarEvent,
)
print(response.output_parsed)
你真正要学到的东西
不是这几行代码,而是这套工程思路:
- 先定义 schema / Pydantic 模型
- 再让模型按这个结构输出
- 再由程序直接解析成对象
- 然后安全地进入后续业务逻辑
4.8 Function Calling / Tool Calling 的本质
Function calling 的本质不是“让模型会写函数”,而是:
让模型告诉你的程序:现在该调用哪个工具,以及调用参数是什么。
这个流程一般分为几步:
第 1 步:你把工具定义告诉模型
包括:
- 工具名
- 工具描述
- 参数 schema
第 2 步:模型决定是否调用工具
如果当前任务需要外部能力,模型会产出一个工具调用请求。
第 3 步:你的程序执行工具
比如:
- 查数据库
- 调用天气 API
- 搜索内部知识库
第 4 步:把工具结果回传给模型
模型基于工具结果继续生成。
第 5 步:模型输出最终结果
或者继续进入下一轮工具调用。
所以本质上:
模型负责决策
程序负责执行
4.9 Function Calling 和 Structured Outputs 的区别
这个一定要分清。
Structured Outputs 关注的是
最终给程序消费的回答结构。
例如:
{
"summary": "...",
"risk_level": "high",
"suggestions": ["...", "..."]
}
Function Calling 关注的是
要调用哪个工具,以及参数是什么。
例如:
{
"name": "get_weather",
"arguments": {
"city": "Hangzhou",
"date": "today"
}
}
一句话记忆
- Structured Outputs:约束“回答长什么样”
- Function Calling:约束“动作怎么执行”
4.10 工具 schema 为什么是核心能力
很多人学习 tool calling,只停留在“哦,模型能调函数”。
真正难的不是“会不会调”,而是:
你能不能把工具定义得清晰、稳定、可控。
一个好的工具 schema 至少应该包含:
- 工具名清晰
- 描述明确
- 参数字段语义清楚
- 枚举范围明确
- 必填项明确
- 禁止额外字段
差的工具定义会导致什么
- 模型不知道什么时候该调用
- 模型参数经常写错
- 工具职责重叠,模型选错工具
- 工具输出无法被下游稳定消费
例子:一个更合理的工具定义
{
"type": "function",
"name": "get_weather",
"description": "查询指定城市某天的天气信息",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,例如 Hangzhou"
},
"date": {
"type": "string",
"enum": ["today", "tomorrow"]
}
},
"required": ["city", "date"],
"additionalProperties": false
}
}
这个工具定义表达得很清楚:
- 查询什么:天气
- 需要什么参数:城市、日期
- 日期允许哪些值:today/tomorrow
- 不允许额外字段
4.11 strict: true 为什么重要
在工具调用和结构化输出中,strict 都是非常重要的设计点。
它的核心目的就是:
尽量让模型输出严格遵守你定义的 schema。
开启 strict 的意义
- 参数更稳定
- 字段更规范
- 减少解析失败
- 减少模型乱补字段
- 降低工具误调用风险
但你也要注意
严格模式不是“万能保险”。
你程序端仍然要做:
- 参数校验
- 类型检查
- 安全边界控制
- 异常处理
因为:
模型再强,也不能取代业务代码的防线。
4.12 Prompting best practices:现阶段最实用的原则
这一阶段你不需要追求“写出多华丽的提示词”,而是要追求:
- 任务清晰
- 约束清晰
- 输出清晰
- 边界清晰
建议记住的几条原则
1)先说任务,再说要求
错误写法:
- 说了一大堆背景,最后才告诉模型要干什么
更好的写法:
任务:请把下面这段文本总结为 3 条要点。
要求:
1. 每条不超过 20 字
2. 不要输出额外解释
3. 输出 JSON 数组
2)重要约束写明确,不要含糊
不要写:
- 尽量简洁
- 稍微正式一点
- 最好是 JSON
而要写:
- 必须输出合法 JSON
- 只允许包含
title、summary两个字段 - 不要输出 Markdown
3)把上下文和任务分开
推荐格式:
任务:...
输出要求:...
上下文:
"""
...
"""
4)负向约束不要太多
与其写一堆:
- 不要这样
- 不要那样
- 不要废话
- 不要解释
不如直接写:
- 输出格式固定为 …
- 仅输出字段 …
- 缺失信息时返回 null
5)给例子往往比抽象要求更有效
特别是以下任务:
- 分类
- 抽取
- 改写
- 固定格式输出
给 1~2 个正例,通常比写很多抽象描述更稳。
4.13 一个好 prompt 的推荐模板
你是一个____助手。
任务:
请完成以下工作:____
输出要求:
1. 输出格式必须为 ____
2. 字段包括 ____
3. 不要输出 ____
4. 如果信息不足,返回 ____
上下文:
"""
____
"""
这个模板为什么有用
因为它天然把内容拆成了:
- 角色
- 任务
- 输出要求
- 上下文
这比把所有东西挤成一大段自然语言稳定得多。
五、参数校验与错误兜底
5.1 为什么这部分极其重要
很多人做 LLM demo 时,最容易忽略的就是:
- 解析失败怎么办
- 参数不合法怎么办
- 工具报错怎么办
- 超时怎么办
- 模型拒绝怎么办
- 结果字段不全怎么办
但到了工程里,这些才是系统能不能稳定运行的关键。
真正的 LLM 应用,不是“成功时多厉害”,而是“失败时能不能体面地活下来”。
5.2 你至少要做的三层防线
第一层:模型侧约束
用:
- 明确 prompt
- Structured Outputs
- strict schema
目的:减少错误发生概率。
第二层:程序侧校验
用:
- Pydantic
- JSON Schema 校验
- 类型检查
- 业务规则检查
目的:不要盲信模型输出。
第三层:失败兜底
用:
- 重试
- 默认值
- fallback 提示
- 降级逻辑
- 记录日志
目的:错误发生时系统不要直接崩。
5.3 常见错误类型与处理思路
1)JSON 解析失败
可能原因
- 模型混入解释性文本
- 括号不闭合
- 引号格式不对
- 输出被截断
处理思路
- 先记录原始输出
- 做一次轻量重试
- 再次失败则 fallback
- 不要 silently ignore
2)字段缺失 / 类型错误
可能原因
- prompt 约束不够清晰
- schema 不完整
- 模型理解偏差
处理思路
- Pydantic 二次校验
- 缺必要字段则判失败
- 非关键字段可给默认值
3)工具参数不合法
可能原因
- 模型字段名写错
- 枚举值不在范围内
- 参数逻辑冲突
处理思路
- 先校验,不通过不执行
- 返回明确错误结果
- 让模型或程序重新决策
4)工具执行失败
可能原因
- 外部 API 超时
- 网络错误
- 数据库异常
- 权限不足
处理思路
- 捕获异常
- 返回结构化错误信息
- 允许模型基于错误决定降级回复
5)模型拒答或结果不可信
处理思路
- 明确识别 refusal
- 必要时改为安全提示
- 不要强行用不可信输出继续驱动高风险动作
5.4 一个最小兜底流程模板
try:
response = call_model(...)
parsed = parse_output(response)
validate(parsed)
except ParseError:
# 解析失败,考虑重试一次
...
except ValidationError:
# 参数或结构不合法,不执行敏感动作
...
except ToolError:
# 工具执行失败,记录日志并降级
...
else:
# 成功才进入后续业务逻辑
...
学习重点
你不用一开始就把兜底写得很复杂,但你要先建立思维:
模型输出必须先被“怀疑”,再被“验证”,最后才能“执行”。
六、第二阶段最核心的知识点清单
下面这份可以直接拿去复习。
6.1 模型 API
- 知道 Responses API 是当前主线
- 知道
instructions和input的职责区别 - 知道
output_text是快捷字段 - 知道底层返回的是
output items
6.2 消息结构
- 知道输入要分层
- 知道系统指令、任务输入、历史上下文、工具结果不能乱糊
- 知道多轮上下文本质是“带哪些历史”
6.3 上下文管理
- 知道
previous_response_id的基本作用 - 知道
instructions不会自动继承 - 知道上下文不是越多越好
- 知道长对话需要摘要、裁剪、筛选
6.4 流式输出
- 知道流式是增量事件流
- 知道它主要改善交互体验
- 知道流式需要处理拼接、结束、异常
- 知道并非所有场景都适合流式
6.5 Tool Calling
- 知道什么时候该接工具
- 知道工具调用的本质是“模型决策,程序执行”
- 知道工具定义依赖 JSON Schema
- 知道参数设计质量决定工具调用质量
6.6 Structured Outputs
- 知道 JSON mode 和 Structured Outputs 的区别
- 知道结构化输出是 Agent 的重要基础
- 知道 schema 是数据合同
- 知道程序端仍然要继续校验
6.7 错误处理
- 知道模型输出不能直接信
- 知道至少要做解析、校验、兜底
- 知道工具失败后要能降级
- 知道敏感动作不能因一次错误输出就直接执行
七、第二阶段的难点总结
难点 1:从“聊天思维”切到“系统思维”
初学者最难的一步,是从:
- 我怎么问模型
切换到:
- 我的程序怎么和模型协作
难点 2:理解“文本输出”和“结构化输出”不是一回事
模型说得通顺,不代表程序能消费。
难点 3:理解 Function Calling 和 Structured Outputs 是两种不同问题
- 一个管“动作参数”
- 一个管“最终结果结构”
难点 4:理解上下文管理不是简单地拼聊天记录
而是:
- 记什么
- 忘什么
- 压缩什么
- 保留什么约束
难点 5:真正重视校验和兜底
很多 demo 成功,是因为测试样例太理想。
一旦输入变脏、接口变慢、工具失败,没有兜底的系统会非常脆弱。
八、常见误区
误区 1:会写 prompt 就算会做 LLM 应用
错。提示词只是入口,不是完整系统能力。
误区 2:只要让模型输出 JSON 就稳了
错。合法 JSON 不等于符合业务 schema。
误区 3:模型输出严格了,就不需要程序校验
错。程序校验永远不能省。
误区 4:上下文越长越好
错。上下文越长,成本越高,噪声越大,污染风险越高。
误区 5:工具调用就是“模型自己执行函数”
错。模型只是生成调用请求,真正执行的是你的程序。
误区 6:流式输出只是为了酷炫
错。它主要服务于用户体验,但也会带来更复杂的工程处理。
九、面试高频问题与回答思路
9.1 什么是 Responses API?为什么它重要?
回答思路
Responses API 可以理解为当前更统一的模型调用接口。它不仅能做文本生成,还能处理多轮上下文、结构化输出和工具调用。相比只把模型当聊天接口来看,Responses API 更适合构建完整的 LLM 应用和 Agent 系统。
9.2 instructions 和 input 有什么区别?
回答思路
instructions 负责高层行为约束,比如角色、风格、规则;input 负责当前轮实际任务内容。前者更像行为配置,后者更像本次请求的数据输入。
9.3 多轮上下文管理要注意什么?
回答思路
重点不是简单保存历史,而是选择性保留高价值上下文。要考虑 token 成本、噪声污染、长期记忆压缩和历史约束是否仍然有效。使用 previous_response_id 可以方便串联多轮,但也要注意上一轮的 instructions 不会自动继承。
9.4 什么时候应该用 Tool Calling?
回答思路
当任务需要访问外部实时数据、私有数据或执行外部动作时,就应该考虑 Tool Calling,比如查数据库、查天气、搜索知识库、调用内部系统。纯文本改写、总结、翻译这类任务通常直接 prompt 就够了。
9.5 Structured Outputs 和 Function Calling 有什么区别?
回答思路
Structured Outputs 用来约束模型最终输出结果的结构,方便程序解析和下游消费;Function Calling 用来约束模型调用工具时的参数结构,方便程序执行具体动作。一个偏“结果结构”,一个偏“动作协议”。
9.6 为什么不能只要求“输出 JSON”?
回答思路
因为“输出 JSON”只能保证形式上更像 JSON,不保证字段完整、类型正确、枚举合法、嵌套结构符合预期。真正要做稳定系统,需要 schema 级约束和程序端二次校验。
9.7 为什么程序端还要做校验?
回答思路
因为模型输出本质上仍然是概率生成,不能直接视为可信输入。尤其是涉及敏感动作、工具执行、状态流转时,程序必须进行类型、字段、业务规则和安全边界校验。
9.8 流式输出的价值是什么?
回答思路
流式输出的主要价值是提升交互体验,缩短用户感知等待时间,让用户尽快看到生成结果。但它也会引入增量处理、断流恢复、前后端协同等工程复杂度。
官方资料速记(便于后续复习)
建议后续复习时优先看这些官方文档:
- Responses API Overview
- Text generation guide
- Conversation state guide
- Streaming responses guide
- Structured outputs guide
- Function calling guide
- Using tools guide
- Migrate to the Responses API
- Prompt engineering best practices
学习建议:以后每学完一个知识点,都补一条“我自己理解的关键结论”和“一段最小可运行代码”,这样学习日志才会真正变成你的面试资产。
参考链接(官方)
- Responses Overview: https://developers.openai.com/api/reference/responses/overview/
- Text generation guide: https://developers.openai.com/api/docs/guides/text
- Conversation state guide: https://developers.openai.com/api/docs/guides/conversation-state
- Function calling guide: https://developers.openai.com/api/docs/guides/function-calling
- Using tools guide: https://developers.openai.com/api/docs/guides/tools
- Migrate to the Responses API: https://developers.openai.com/api/docs/guides/migrate-to-responses
- OpenAI API docs home: https://developers.openai.com/api/docs
- Prompt engineering best practices: https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-the-openai-api
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)