OpenAI Responses API 工具调用怎么接入 AI 写作流程
准备
先把写作流程拆成三个角色:模型负责判断是否需要工具并组织正文,应用负责执行真实函数,工具负责返回可核对的数据。Responses API 的创建方法支持 tools、tool_choice、parallel_tool_calls、previous_response_id 等参数;自定义函数工具应只开放必要能力。
- 准备 OpenAI Python SDK 和 API 密钥,密钥只放在服务端环境变量中。
- 确定一个小工具,例如按关键词读取内部资料摘要。
- 规定工具返回字段,例如
found、summary、source_id,避免返回一段无法解析的杂文。 - 确定失败处理:资料不存在时返回明确状态,不能让模型把空结果当成事实。
如果你的写作任务还需要固定输入字段,可以先参考OpenAI Responses API 写作结果怎么做结构化检查,把工具结果检查和最终文章检查分开。
分步操作
定义工具协议。工具名称、用途、参数和参数类型要写清楚。下面的定义只允许模型传入关键词和资料范围:
tools = [ { "type": "function", "name": "search_material", "description": "从内部资料库检索与写作主题相关的已确认信息", "parameters": { "type": "object", "properties": { "query": {"type": "string"}, "scope": {"type": "string", "enum": ["product", "policy", "case"]} }, "required": ["query", "scope"], "additionalProperties": False }, "strict": True } ]发送首次写作请求。将稳定规则放在
instructions,把本次主题放在input。首次接入时建议先使用非流式响应,便于完整记录工具调用和调试。from openai import OpenAI import json client = OpenAI() response = client.responses.create( model="你的模型标识", instructions="你是内容编辑。资料不足时先调用工具;不得补写工具未返回的事实。", input="请围绕‘产品上手’写一篇给新手看的文章,先核对资料再成文。", tools=tools, tool_choice="auto", parallel_tool_calls=False, store=False, )tool_choice用于控制模型如何选择工具;auto适合让模型按任务判断是否调用。若某一步必须查资料,可改为指定工具,但具体可用取值要以当前 SDK 类型定义和接口文档为准。识别工具调用并执行本地函数。不要直接执行模型传来的任意函数名。先用白名单匹配工具,再解析参数、校验长度和枚举值。
def search_material(query, scope): # 替换为你的数据库或检索服务 rows = material_db.search(query=query, scope=scope, limit=5) return { "found": bool(rows), "items": rows, "source_id": "internal-search" } for item in response.output: if getattr(item, "type", None) != "function_call": continue if item.name != "search_material": raise ValueError("未授权的工具") args = json.loads(item.arguments) if not args.get("query") or args.get("scope") not in {"product", "policy", "case"}: raise ValueError("工具参数不符合协议") result = search_material(args["query"], args["scope"])不同 SDK 版本对响应对象的访问方式可能不同。调试时先记录响应项的类型、工具名、调用标识和参数,再按当前版本的对象属性组装回传数据。
把工具结果交回模型。工具执行完后,使用模型返回的调用标识,把 JSON 结果作为工具输出发送回下一次 Responses 请求。调用标识必须和原请求对应,不能只把结果拼进普通文本。
tool_outputs = [ { "type": "function_call_output", "call_id": item.call_id, "output": json.dumps(result, ensure_ascii=False) } ] final_response = client.responses.create( model="你的模型标识", instructions="只使用工具返回的已确认资料;缺失信息请标注待核实。", input=tool_outputs, tools=tools, tool_choice="auto", previous_response_id=response.id, store=False, ) print(final_response.output_text)上面是可复制的流程骨架。实际项目中应保存首次响应、工具参数、工具原始结果和最终响应,方便定位是检索、参数校验还是生成环节出了问题。
接入字段校验和发布状态。最终文本生成后,不要直接发布。先解析标题、正文、资料引用和审核状态;字段缺失、工具未命中或内容超出资料范围时,回到草稿状态。
可复制模板
可以将下面的规则放入 instructions,再把主题和目标读者放入 input:
你负责生成可审核的中文文章。
1. 先判断是否需要调用 search_material。
2. 需要资料时,只能使用工具返回的内容。
3. 工具未命中时,不得自行补充具体事实、数字、日期或承诺。
4. 正文输出包含:标题、摘要、正文、待核实项。
5. 文章完成前检查标题、正文、引用标识和审核状态。
6. 工具失败时返回明确错误,不要伪装成正常资料。工具返回模板:
{
"found": true,
"items": [
{
"fact": "已确认的资料内容",
"source_id": "资料记录编号"
}
],
"source_id": "internal-search"
}翻车怎么改
模型直接写正文,没有调用工具
原因:工具只是放进 tools,但任务没有明确资料核对条件,模型判断可以直接回答。
修正动作:在 instructions 中写明哪些主题必须先检索,并在应用侧检查是否出现工具调用;没有调用时可以拒绝进入发布环节,要求重新请求或由程序先执行检索。
工具执行成功,但模型仍编造资料
原因:工具输出格式不稳定,或者提示词没有要求区分已确认信息和未知信息。
修正动作:固定返回 found、items 和 source_id,空结果明确返回 found: false,并在最终验收中检查正文中的关键事实是否能对应资料标识。
工具调用报参数错误
原因:参数名、枚举值或 JSON 类型与工具协议不一致。
修正动作:使用严格参数定义,应用侧再次校验参数;记录原始参数但不要把未校验参数直接传给数据库或内部接口。
完成前检查
- 确认首次请求确实传入了
tools,并按需求设置了tool_choice。 - 确认只执行白名单工具,并校验了工具参数。
- 确认工具结果通过对应调用标识回传,而不是拼接成普通提示词。
- 确认资料未命中、工具超时和工具异常都有独立状态。
- 确认最终文章的标题、正文、引用标识和审核字段均已通过发布前验收。
- 确认日志中没有保存 API 密钥、敏感原文或不必要的用户信息。
下一步
把这篇的方法练一遍
提示词和步骤可以带到创作里直接试做一版。