AI Agent 入门(二):理解 LLM —— Chat Completion、参数调优与结构化输出
·
本文是 AI Agent 入门系列的第 2 篇。学完第 1 篇的基础调用后,我们来深入理解 LLM 的工作机制。
掌握这些知识,下一课就能实现 Tool Use(函数调用),这是 Agent 最核心的能力。
本课目标
- 理解 LLM 对话补全的本质(消息结构、多轮对话)
- 掌握关键参数的含义与调优(temperature、max_tokens)
- 学会结构化输出 —— 让 LLM 返回 JSON
本课产出
- 新建文件:
lesson02_structured_output.py,粘贴下文完整代码 - 运行:
python lesson02_structured_output.py - 效果:让 LLM 稳定输出 JSON 格式数据,掌握 temperature 和 max_tokens 的影响
一、Chat Completion 的本质
消息结构
LLM 的输入是一个消息列表,每条消息有 role 和 content:
messages = [
{"role": "system", "content": "你是 AI 助手"}, # 系统指令
{"role": "user", "content": "你好"}, # 用户输入
{"role": "assistant","content": "你好!"}, # LLM 回复
{"role": "user", "content": "什么是 Agent?"}, # 继续发问
]
| role | 含义 | 说明 |
|---|---|---|
system |
系统指令 | 设定 LLM 身份和行为规则 |
user |
用户消息 | 用户的输入 |
assistant |
LLM 回复 | 模型生成的回复,多轮时保留历史 |
关键理解:LLM 本质上是"下一个词预测器"。给定前面的所有文本,它预测最可能的下一个词。对话补全只是包装成了聊天的形式。
多轮对话
每次调用 API 时,你需要把完整的对话历史传回去:
# 第一轮
messages = [{"role": "user", "content": "1+1 等于几?"}]
response = llm(messages)
# 第二轮 —— 带上第一轮的历史
messages = [
{"role": "user", "content": "1+1 等于几?"},
{"role": "assistant", "content": "等于2"},
{"role": "user", "content": "再加上3呢?"},
]
response = llm(messages) # LLM 才能理解上下文
这就是 LLM 没有记忆的体现——每次调用独立,"记忆"靠你把历史传回去。
二、关键参数详解
temperature —— 创造力的旋钮
| temperature | 行为 | 适用场景 |
|---|---|---|
| 0 ~ 0.2 | 确定性输出,相同输入几乎总是相同输出 | 代码生成、分类 |
| 0.3 ~ 0.7 | 平衡创造力和准确性 | 日常对话 |
| 0.8 ~ 1.5 | 高随机性 | 创意写作、头脑风暴 |
核心:temperature 控制概率分布的采样策略。越低越倾向选概率最高的词,越高低概率词也有机会被选中。
max_tokens —— 输出长度上限
- LLM 生成到
max_tokens个 token 后停止 - 一个汉字约 1~2 个 token
- 设置太小会导致回答被截断
其他参数
| 参数 | 作用 | 说明 |
|---|---|---|
| top_p | 核采样 | 和 temperature 二选一 |
| stream | 流式输出 | 逐 token 返回,体验更流畅 |
| stop | 停止序列 | 遇到指定字符串时停止生成 |
三、结构化输出 —— JSON mode
这是 Agent 开发中最重要的技能之一。
Agent 需要 LLM 返回机器可解析的数据,而非自然语言:
- Tool Use 的参数(下节课核心)
- 信息抽取的结果
- 分类/判定的结果
方式一:在 prompt 中要求
response = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": "你只输出 JSON 格式。"},
{"role": "user", "content": "从"张三,25岁,北京"中提取信息,返回 {"name": "", "age": 0}"}
]
)
方式二:使用 response_format(推荐)
response = client.chat.completions.create(
model=MODEL,
messages=[...],
response_format={"type": "json_object"}, # 原生 JSON mode
)
不是所有模型都支持
response_format。不支持时,方式一的 prompt 方式同样有效。
四、完整代码
💡 环境准备:本课使用与第 1 课相同的环境。如尚未配置,请先完成:
pip install openai python-dotenv- 进入
code/目录,复制.env.example为.env,填入你的 API Key(详见第 1 课)
新建 lesson02_structured_output.py,粘贴以下代码:
"""
第 2 课:理解 LLM —— 参数调优与结构化输出
"""
import json, os
from dotenv import load_dotenv
load_dotenv()
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com",
)
MODEL = "deepseek-chat"
# 切换 OpenAI 或通义千问请参考第 1 课
if not client.api_key:
print("❌ 未检测到 API Key!")
exit(1)
# === 示例 1:多轮对话 ===
print("=" * 50, "多轮对话", "=" * 50, sep="\n")
messages = [
{"role": "system", "content": "你是 AI 助手,回答要简洁。"},
{"role": "user", "content": "什么是 AI Agent?"},
]
resp = client.chat.completions.create(model=MODEL, messages=messages)
print("第一轮回答:", resp.choices[0].message.content[:100], "...")
messages.append({"role": "assistant", "content": resp.choices[0].message.content})
messages.append({"role": "user", "content": "它和普通 LLM 有什么区别?"})
resp = client.chat.completions.create(model=MODEL, messages=messages)
print("第二轮回答:", resp.choices[0].message.content[:100], "...")
# === 示例 2:temperature 对比 ===
print("\n", "=" * 50, "temperature 对比", "=" * 50, sep="\n")
for temp in [0.0, 0.7, 1.2]:
print(f"\n--- temperature = {temp} ---")
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": "给出一个 Python 斐波那契函数。"}],
temperature=temp,
)
print(resp.choices[0].message.content[:120] + "...")
# === 示例 3:JSON 结构化输出(prompt 方式)===
print("\n", "=" * 50, "JSON 结构化输出", "=" * 50, sep="\n")
resp = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": "你只输出 JSON 格式。"},
{"role": "user", "content": "从'王小明今年28岁,住在深圳'中提取信息。"
"格式: {\"name\": \"...\", \"age\": 0, \"city\": \"...\"}"}
],
)
try:
data = json.loads(resp.choices[0].message.content)
print("解析成功:", json.dumps(data, indent=2, ensure_ascii=False))
except json.JSONDecodeError:
print("解析失败,原始输出:", resp.choices[0].message.content)
# === 示例 4:response_format JSON mode ===
print("\n", "=" * 50, "response_format JSON mode", "=" * 50, sep="\n")
print("(部分模型不支持此功能,不支持时会自动降级)\n")
try:
resp = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": "你是一个 JSON 信息提取助手。"},
{"role": "user", "content": "提取:李四,30岁,上海,设计师。"}
],
response_format={"type": "json_object"},
)
data = json.loads(resp.choices[0].message.content)
print("解析成功:", json.dumps(data, indent=2, ensure_ascii=False))
except Exception as e:
print(f"response_format 方式失败(此模型可能不支持): {e}")
# === 示例 5:max_tokens 截断 ===
print("\n", "=" * 50, "max_tokens 截断效果", "=" * 50, sep="\n")
for limit in [20, 100, 500]:
print(f"\n--- max_tokens = {limit} ---")
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": "用 200 字介绍 AI Agent。"}],
max_tokens=limit,
)
print(f"实际输出 {len(resp.choices[0].message.content)} 字",
"→ 被截断" if resp.choices[0].finish_reason == "length" else "→ 完整")
运行结果示例
==================================================
多轮对话
==================================================
第一轮回答:AI Agent 是一个能自主感知环境、做出决策并采取行动...
第二轮回答:主要区别在于:LLM 只生成文本回复,而 Agent...
==================================================
temperature 对比
==================================================
--- temperature = 0.0 ---
def fibonacci(n): ...
--- temperature = 1.2 ---
Oh, 斐波那契!这玩意有趣,我想想...
==================================================
JSON 结构化输出
==================================================
解析成功:{
"name": "王小明",
"age": 28,
"city": "深圳"
}
常见报错
| 问题 | 原因 | 解决 |
|---|---|---|
json.JSONDecodeError |
LLM 返回的不是有效 JSON | 优化 prompt,或使用 response_format |
response_format 方式失败 |
模型不支持原生 JSON mode | 切回 prompt 方式 |
finish_reason: length |
输出被 max_tokens 截断 | 增大 max_tokens 值 |
动手练习
- 写一个 prompt 让 LLM 稳定输出包含姓名、年龄、城市的 JSON
- 把 temperature 设为 0,连续调用 5 次,观察输出是否完全一致
- 把 max_tokens 设为 5,观察被截断的效果
思考题
- temperature = 0 时输出是"完全确定"的吗?为什么?
- 在 Agent 场景中,结构化输出为什么比自然语言输出更适合?
- 如果你的 Agent 需要从一段文本中提取关键信息,你会怎么设计 prompt?
📦 完整代码
本课程所有代码已托管在 GitCode:
git clone git@gitcode.com:gcw_A202cbBm/ai-agent.git
cd ai-agent/code
也可直接访问:https://gitcode.com/gcw_A202cbBm/ai-agent
下一篇预告:AI Agent 入门(三):Tool Use 入门 —— Function Calling 原理与实战
你将学会给 LLM 绑定工具(计算器、天气查询),让它从"只能说话"变成"能做事"。这是 Agent 最核心的一课。
如果您觉得有用,欢迎 点赞、转发、评论、关注。
更多推荐


所有评论(0)