LangChain LangGraph
Module 1 Module 2 Module 3
Module 1 · 基础能力
1 1.1a 基础模型
2 1.1b Prompting
3 1.2a Tools
4 1.2b Web Search
5 1.3 Memory
6 1.4 Multimodal
7 1.5 Personal Chef
SUM Module Summary
HomeLangChainModule 1 · 基础能力1.1b Prompting
📓 Notebook 📖 Explained
LANGCHAIN MODULE 1 · LESSON 1.1b

提示工程四大技巧
Basic · Few-shot · Structured · 结构化输出

通过 System Prompt 控制模型行为,用 Few-shot 示例引导风格,用 Pydantic 强制模型输出结构化 JSON——这是构建可靠 AI 应用的核心技能。

1 提示工程概览:四种递进技巧

提示工程(Prompt Engineering)是影响 LLM 输出质量的最直接手段。本节从最基础到最严格,介绍四种递进的提示技巧:

① 基础提示(Basic Prompting)

通过 system_prompt 参数定义 Agent 的角色和行为准则。最简单但效果显著。

② Few-shot 提示

在 system prompt 里加入 2-5 个输入/输出示例,引导模型模仿特定风格或格式。

③ 结构化提示

在 prompt 里用模板明确定义输出的字段名称和格式,让自然语言输出更规整。

④ 结构化输出

用 Pydantic 定义数据模型,通过 response_format 强制 LLM 输出严格的 JSON,可直接作为 Python 对象使用。

技巧升级路径

可靠性和可解析性依次提升:基础 → Few-shot → 结构化提示 → 结构化输出。生产环境中,凡是需要程序解析 LLM 输出的场景,都应优先考虑结构化输出(Pydantic),它是最可靠的方式。

2 基础提示:用 system_prompt 定义 Agent 角色

最简单的提示方式:在 create_agent 时传入 system_prompt 参数,告诉模型它是谁、应该怎么做。

不加 system_prompt 的默认行为

没有 system prompt 时,模型会给出"诚实"的回答——月亮没有首都:

agent = create_agent(model=deepseek_model())

question = HumanMessage(content="What's the capital of the moon?")
response = agent.invoke({"messages": [question]})
print(response['messages'][1].content)
输出(无 system prompt)
The Moon does not have a capital city. It is a natural satellite with no permanent human settlements or political structures...

加上 system_prompt:切换为科幻作家角色

system_prompt = "You are a science fiction writer, create a capital city at the users request."

scifi_agent = create_agent(
    model=deepseek_model(temperature=1),  # temperature=1 增加创意性
    system_prompt=system_prompt
)

response = scifi_agent.invoke({"messages": [question]})
print(response['messages'][1].content)
输出(有 system prompt)
**Luna Prime** — the gleaming capital of the Moon, nestled in the Tycho Crater. Founded in 2157, it houses the Lunar Confederation's parliament beneath its great geodesic domes...
temperature 参数的作用

temperature=1 让模型输出更具创意性和多样性(每次运行结果不同);temperature=0 使输出更确定、可重复(每次运行结果相同)。创意型任务用高 temperature,需要一致性的任务(如代码生成、数据提取)用低 temperature。

3 Few-shot 提示:在 System Prompt 里嵌入示例

Few-shot(少样本)提示是一种强大的技巧:在 system prompt 里直接给出几个"输入 → 输出"的示例,LLM 会模仿这些示例的风格和格式来生成新的响应。

加入 Few-shot 示例

system_prompt = """

You are a science fiction writer, create a space capital city at the users request.

User: What is the capital of mars?
Scifi Writer: Marsialis

User: What is the capital of Venus?
Scifi Writer: Venusovia

"""

scifi_agent = create_agent(
    model=deepseek_model(),
    system_prompt=system_prompt
)

question = HumanMessage(content="What is the capital of The Moon?")
response = scifi_agent.invoke({"messages": [question]})
print(response['messages'][1].content)
输出(Few-shot 风格)
Scifi Writer: Lunaris

注意输出风格的变化:模型学习了示例里"Scifi Writer: [单词]"的格式,给出了一个简洁的单词答案,而不是长篇描述。

Few-shot 的核心原理

LLM 通过训练学会了"续写"文本。Few-shot 示例相当于给模型展示了一段"对话脚本",模型会按照这个脚本的风格续写。示例的质量和一致性直接决定了 Few-shot 效果——示例要有代表性,格式要统一。

4 结构化提示:用格式模板约束输出结构

结构化提示(Structured Prompting)是在 system prompt 里定义明确的字段名称和输出格式,让模型的自然语言输出更规整、更易解析。

定义输出格式模板

system_prompt = """

You are a science fiction writer, create a space capital city at the users request.

Please keep to the below structure.

Name: The name of the capital city

Location: Where it is based

Vibe: 2-3 words to describe its vibe

Economy: Main industries

"""

scifi_agent = create_agent(
    model=deepseek_model(),
    system_prompt=system_prompt
)

response = scifi_agent.invoke({"messages": [question]})
print(response['messages'][1].content)
输出(结构化提示)
Name: Selenopolis
Location: Mare Tranquillitatis, near the historic Apollo 11 landing site
Vibe: Futuristic, serene, scientific
Economy: Helium-3 extraction, space tourism, lunar research stations
结构化提示 vs 结构化输出的区别

结构化提示的输出仍然是自然语言字符串,字段分隔只是约定,模型可能不严格遵守(偶尔会增减字段、改变顺序)。如果你需要用代码可靠地解析每个字段,必须用下一节的结构化输出(Pydantic)

5 结构化输出:用 Pydantic 强制输出 JSON 对象

结构化输出(Structured Output)是最可靠的方式:用 Pydantic 定义数据模型,通过 response_format 参数告诉 LLM 必须按这个 schema 输出。LangChain 会在底层把模型的 JSON 输出自动解析为 Pydantic 对象。

定义 Pydantic 数据模型

from pydantic import BaseModel

class CapitalInfo(BaseModel):
    name:     str  # 城市名称
    location: str  # 地理位置
    vibe:     str  # 氛围描述
    economy:  str  # 经济支柱

传入 response_format 参数

agent = create_agent(
    model=deepseek_model(),
    system_prompt="You are a science fiction writer, create a capital city at the users request.",
    response_format=CapitalInfo   # 关键:传入 Pydantic 类
)

question = HumanMessage(content="What is the capital of The Moon?")
response = agent.invoke({"messages": [question]})

# structured_response 是 Pydantic 对象,不是字符串
print(response["structured_response"])
输出(Pydantic 对象)
CapitalInfo(
  name='Lunar Prime',
  location='Mare Imbrium, near the lunar equator',
  vibe='futuristic, serene, industrious',
  economy='Helium-3 mining, space tourism, zero-gravity manufacturing'
)

底层工作机制

当你传入 response_format=CapitalInfo 时,LangChain 会:

  1. 把 Pydantic 模型转换为 JSON Schema,注入到工具定义里
  2. LLM 收到指令:必须调用名为 CapitalInfo 的工具,参数严格符合 schema
  3. 模型输出 tool_call(而非普通文本),参数就是结构化的 JSON
  4. LangChain 把 JSON 解析为 Pydantic 对象,存入 response["structured_response"]
为什么结构化输出用工具调用实现?

现代 LLM(GPT-4、DeepSeek、Claude)都支持工具调用(Function Calling / Tool Use),这要求模型输出严格符合 JSON Schema 的参数,可靠性远高于"在普通文本里嵌入 JSON"。response_format 参数正是利用了这一机制。

6 structured_response 的读取与使用

拿到 Pydantic 对象后,可以像访问普通 Python 对象属性一样读取每个字段:

capital_info = response["structured_response"]

# 访问具体字段
print(capital_info.name)      # → 'Lunar Prime'
print(capital_info.location)  # → 'Mare Imbrium, near the lunar equator'
print(capital_info.vibe)      # → 'futuristic, serene, industrious'
print(capital_info.economy)   # → 'Helium-3 mining...'

# 组合使用
print(f"{capital_info.name} is located at {capital_info.location}")
执行输出
Lunar Prime
Mare Imbrium, near the lunar equator
futuristic, serene, industrious
Helium-3 mining, space tourism, zero-gravity manufacturing

Lunar Prime is located at Mare Imbrium, near the lunar equator

messages 内部结构(进阶调试)

使用 response_format 时,messages 列表里除了 HumanMessageAIMessage,还会有一条 ToolMessage

for msg in response["messages"]:
    pprint(msg)
消息历史(3条)
1. HumanMessage: "What is the capital of The Moon?"
2. AIMessage: content='' tool_calls=[{'name': 'CapitalInfo', 'args': {...}}]
   # AI 消息的 content 为空,用工具调用承载结构化数据
3. ToolMessage: "Returning structured response: name='Lunar Prime'..."
   # 工具执行结果被记录到消息历史
注意:AIMessage.content 为空

用结构化输出时,response['messages'][-1].content 不再是你要的内容(它可能是空字符串或工具调用消息)。应该通过 response["structured_response"] 来获取 Pydantic 对象,而不是 messages[-1].content

7 四种技巧对比与选型指南

技巧输出格式可靠性适用场景
基础提示 自然语言(自由格式) 开放式对话、创意写作、简单问答
Few-shot 自然语言(模仿示例格式) 需要特定风格/格式,有样例可参考
结构化提示 自然语言(有字段约定) 需要大致结构,允许偶发偏差
结构化输出 Pydantic 对象(严格 JSON) 需要程序解析输出、数据管道、表单填写
选型决策树
  • 需要代码解析输出? → 用结构化输出(Pydantic + response_format)
  • 需要特定风格/短格式? → 用 Few-shot 提示(在 prompt 里加示例)
  • 需要结构清晰但格式灵活? → 用结构化提示(prompt 里定义字段模板)
  • 只是定义角色/行为? → 用基础提示(system_prompt 定义角色)