第4讲:Prompt工程与结构化输出——给Agent装上“严谨的大脑“
欢迎来到《Python + AI Agent 实战开发完全指南》专栏!
在前面的课程中,我们成功让大模型跑通了ReAct循环。但在实际开发中,很多开发者会遇到一个令人抓狂的现象:明明代码逻辑没问题,但Agent就是会"发疯"——比如它忘记调用工具直接瞎编答案,或者输出的JSON格式缺胳膊少腿导致程序崩溃。
这其实是因为:大模型本质上是一个概率预测机器,而不是一个严格的执行引擎。
今天这一讲,我们就来聊聊如何给Agent装上"严谨的大脑",通过Prompt工程和结构化输出,让它乖乖按照我们的规矩办事。
一、为什么你的Agent总是"不听话"?
在编写Agent的提示词(System Prompt)时,新手最容易犯的错误是指令模糊。
错误示范:
“你是一个助手,请帮用户解决问题,如果需要查资料就用搜索工具。”
大模型的困惑:
“什么时候算’需要’?我是不是应该先自己猜一下再搜?搜完的结果要不要告诉用户?”
核心问题:
Agent的System Prompt不是用来"聊天"的,它是用来写代码逻辑的。你必须像写if-else一样,把边界条件和行为规范写得清清楚楚。
二、打造Agent专属的"黄金Prompt"模板
一个优秀的Agent系统提示词,通常需要包含以下四个核心模块:
- 角色定义(Role):明确它的身份和最终目标
- 工具说明(Tools):告诉它有哪些工具可用,以及什么情况下绝对不能用
- 思考路径(Reasoning Path):强制它遵循ReAct的思考步骤
- 防御性约束(Constraints):设定底线,防止幻觉
💡 实战:一份工业级的AgentPrompt示例
你是一个专业的数据分析Agent。你的任务是帮助用户分析数据并给出结论。
【可用工具】
- search_database: 用于查询历史销售数据。
- calculator: 用于复杂的数学运算。
【工作准则】
1. 永远不要凭空捏造数据。如果不知道答案,必须调用search_database。
2. 每次只能调用一个工具,等待Observation结果后再决定下一步。
3. 当且仅当你确信已经掌握了所有必要信息时,才能输出Final Answer。
4. 你的回复必须严格遵循Thought/Action/Observation/Final Answer的格式。
三、致命痛点:结构化输出(Structured Output)
在第3讲的代码中,我们用split("\n")来提取大模型输出的Action和参数。说实话,这种字符串解析方式非常脆弱。只要大模型稍微调皮一点(比如多加个换行符),整个Agent就会崩溃。
真正的企业级做法是:强制大模型返回标准的JSON格式。
目前主流的大模型(如智谱GLM、通义千问等)都支持在API层面开启response_format={"type": "json_object"},或者通过Function Calling机制直接返回结构化数据。
🧩 代码演示:告别脆弱的字符串解析
让我们用更优雅的方式重构上一讲的Agent核心逻辑:
import json
from openai import OpenAI
client = OpenAI(api_key="your-api-key", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1")
def get_agent_next_step(messages):
"""
强制大模型以标准JSON格式返回决策结果
"""
response = client.chat.completions.create(
model="qwen-turbo",
messages=messages,
# 【核心魔法】:强制要求输出合法的JSON对象
response_format={"type": "json_object"}
)
content = response.choices[0].message.content
try:
return json.loads(content)
except json.JSONDecodeError:
return {"error": "大模型未返回合法JSON", "raw_content": content}
# 模拟测试
system_prompt = """你是一个决策引擎。请以纯JSON格式返回你的下一步动作。
格式要求:{"thought": "你的思考过程", "action": "工具名称或null", "final_answer": "最终答案或null"}"""
test_messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": "帮我查一下北京的天气"}
]
result = get_agent_next_step(test_messages)
print(result)
运行这段代码,你会得到一个极其干净的字典:
{
"thought": "用户需要查询北京的天气,我需要使用天气查询工具来获取信息。",
"action": "weather_query",
"final_answer": None
}
有了这个标准的字典,你在Python里只需要简单地判断if result["action"]:就可以精准路由,再也不用去苦苦split字符串了!
四、本节小结与避坑指南
📌 核心要点总结
- Prompt即代码:写Agent的Prompt要像写伪代码一样严谨,多用列表和明确的约束条件
- 拒绝文本解析:在生产环境中,尽量使用
json_object模式或原生的Tool Calling,彻底杜绝正则表达式和字符串切割带来的隐患 - 容错机制:即使开启了JSON模式,大模型偶尔也会抽风。一定要在代码里加上
try-except捕获解析异常,并在报错时将错误信息反馈给大模型让它重新生成
⚠️ 生产环境避坑指南
- 永远不要信任大模型的输出格式,必须进行严格的类型检查和异常处理
- 为每个工具定义清晰的参数规范,避免大模型传入错误的参数类型
- 在System Prompt中明确错误处理流程,告诉大模型当遇到异常情况时该如何应对
- 考虑使用Pydantic等数据验证库,对大模型返回的结构化数据进行二次验证
五、课后思考与实践
🧠 思考题
- 如果大模型返回的JSON格式正确,但字段值不符合预期(如action字段为null),应该如何处理?
- 如何设计一个通用的Prompt模板,可以适配不同业务场景下的Agent需求?
💻 实践任务
- 尝试为你的Agent添加更多的工具,并更新对应的Prompt说明
- 实现一个完整的错误处理机制,当大模型输出异常时能够自动重试或降级处理
- 对比使用字符串解析和JSON格式两种方式的开发体验和稳定性差异
六、下一讲预告
下一讲,我们将正式进入Agent的"手脚"部分——工具调用(Tool Calling)底层机制。我们会带你手写一个真实的联网搜索工具,并接入到我们的Agent系统中。准备好让你的智能体真正"连接世界"了吗?
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)