提示(Prompts) #

提示是与大语言模型交互的核心方式。LangChain 提供了强大的提示管理工具,帮助你构建高效、可复用的提示。

提示系统概览 #

text
┌─────────────────────────────────────────────────────────────┐
│                    LangChain 提示系统                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Prompt Templates(提示模板)             │   │
│  │                                                      │   │
│  │  - 动态生成提示                                      │   │
│  │  - 变量插值                                          │   │
│  │  - 多种格式支持                                      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Few-shot Examples(少样本示例)          │   │
│  │                                                      │   │
│  │  - 示例学习                                          │   │
│  │  - 提高输出质量                                      │   │
│  │  - 格式引导                                          │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Output Parsers(输出解析器)             │   │
│  │                                                      │   │
│  │  - 结构化输出                                        │   │
│  │  - 格式验证                                          │   │
│  │  - 自动修复                                          │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

提示模板 #

提示模板让你可以动态生成提示,支持变量插值和条件逻辑。

基础模板 #

python
from langchain_core.prompts import PromptTemplate

# 创建模板
template = PromptTemplate.from_template("告诉我关于{topic}的{count}个事实")

# 格式化
prompt = template.format(topic="Python", count="3")
print(prompt)
# 告诉我关于Python的3个事实

# 使用 invoke
result = template.invoke({"topic": "Python", "count": "3"})
print(result.text)

聊天提示模板 #

python
from langchain_core.prompts import ChatPromptTemplate

# 方式一:from_messages
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个{role},请用{style}的风格回答"),
    ("human", "{question}")
])

# 方式二:from_template(简化版)
prompt = ChatPromptTemplate.from_template(
    "你是一个{role},请回答:{question}"
)

# 格式化
messages = prompt.format_messages(
    role="Python 专家",
    style="幽默",
    question="什么是装饰器?"
)

for msg in messages:
    print(f"{msg.type}: {msg.content}")

消息占位符 #

python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 包含历史消息的模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个有帮助的助手"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{input}")
])

# 使用
from langchain_core.messages import HumanMessage, AIMessage

chat_history = [
    HumanMessage(content="你好"),
    AIMessage(content="你好!有什么可以帮助你的?"),
]

messages = prompt.format_messages(
    chat_history=chat_history,
    input="我刚才说了什么?"
)
text
┌─────────────────────────────────────────────────────────────┐
│                    消息占位符作用                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  模板定义:                                                  │
│  [                                                          │
│    ("system", "你是助手"),                                  │
│    MessagesPlaceholder("history"),  ← 占位符               │
│    ("human", "{input}")                                     │
│  ]                                                          │
│                                                             │
│  格式化后:                                                  │
│  [                                                          │
│    SystemMessage("你是助手"),                               │
│    HumanMessage("你好"),        ← history 内容             │
│    AIMessage("你好!"),         ← history 内容             │
│    HumanMessage("问题...")       ← 当前输入                │
│  ]                                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

部分格式化 #

python
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个{role}"),
    ("human", "{question}")
])

# 部分填充变量
partial_prompt = prompt.partial(role="Python 专家")

# 后续填充剩余变量
messages = partial_prompt.format_messages(question="什么是列表推导式?")

Few-shot 学习 #

Few-shot 学习通过提供示例来引导模型输出。

基础示例 #

python
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate

# 定义示例
examples = [
    {"input": "快乐", "output": "悲伤"},
    {"input": "高大", "output": "矮小"},
    {"input": "炎热", "output": "寒冷"},
]

# 示例模板
example_template = PromptTemplate(
    input_variables=["input", "output"],
    template="输入: {input}\n输出: {output}"
)

# 创建 Few-shot 模板
few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_template=example_template,
    prefix="给出每个词的反义词:",
    suffix="输入: {input}\n输出:",
    input_variables=["input"],
    example_separator="\n\n"
)

# 使用
prompt = few_shot_prompt.format(input="聪明")
print(prompt)

输出:

text
给出每个词的反义词:

输入: 快乐
输出: 悲伤

输入: 高大
输出: 矮小

输入: 炎热
输出: 寒冷

输入: 聪明
输出:

动态示例选择 #

python
from langchain_core.prompts import FewShotPromptTemplate
from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma

# 示例库
examples = [
    {"input": "快乐", "output": "悲伤"},
    {"input": "高大", "output": "矮小"},
    {"input": "炎热", "output": "寒冷"},
    {"input": "聪明", "output": "愚蠢"},
    {"input": "美丽", "output": "丑陋"},
]

# 创建语义相似度选择器
example_selector = SemanticSimilarityExampleSelector.from_examples(
    examples,
    OpenAIEmbeddings(),
    Chroma,
    k=2  # 选择最相似的 2 个示例
)

# 创建动态 Few-shot 模板
dynamic_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_template=example_template,
    prefix="给出每个词的反义词:",
    suffix="输入: {input}\n输出:",
    input_variables=["input"],
)

# 使用 - 会自动选择最相似的示例
prompt = dynamic_prompt.format(input="漂亮")
text
┌─────────────────────────────────────────────────────────────┐
│                    动态示例选择流程                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  输入: "漂亮"                                               │
│        │                                                    │
│        ▼                                                    │
│  ┌─────────────┐                                            │
│  │  向量化     │                                            │
│  └──────┬──────┘                                            │
│         │                                                   │
│         ▼                                                   │
│  ┌─────────────┐                                            │
│  │ 相似度计算  │                                            │
│  └──────┬──────┘                                            │
│         │                                                   │
│         ▼                                                   │
│  选择最相似的示例:                                          │
│  - "美丽" → "丑陋" (最相似)                                 │
│  - "聪明" → "愚蠢" (次相似)                                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

聊天模型的 Few-shot #

python
from langchain_core.prompts import (
    ChatPromptTemplate,
    FewShotChatMessagePromptTemplate,
)

# 定义示例
examples = [
    {"input": "2+2", "output": "4"},
    {"input": "3+3", "output": "6"},
]

# 示例模板
example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}")
])

# Few-shot 模板
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

# 完整提示
final_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个计算器,直接给出答案"),
    few_shot_prompt,
    ("human", "{input}"),
])

输出解析器 #

输出解析器将模型的文本输出转换为结构化数据。

字符串解析器 #

python
from langchain_core.output_parsers import StrOutputParser

parser = StrOutputParser()

# 解析 AIMessage
from langchain_core.messages import AIMessage
message = AIMessage(content="Hello, world!")
result = parser.invoke(message)
print(result)  # "Hello, world!"

JSON 解析器 #

python
from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field

# 定义数据模型
class Person(BaseModel):
    name: str = Field(description="姓名")
    age: int = Field(description="年龄")
    city: str = Field(description="城市")

# 创建解析器
parser = JsonOutputParser(pydantic_object=Person)

# 获取格式说明
format_instructions = parser.get_format_instructions()
print(format_instructions)

与模型结合使用:

python
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

model = ChatOpenAI(model="gpt-4o-mini")

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个有帮助的助手。{format_instructions}"),
    ("human", "{query}")
])

chain = prompt | model | parser

result = chain.invoke({
    "query": "介绍一个虚构的人物",
    "format_instructions": parser.get_format_instructions()
})

print(result)
# {'name': '张三', 'age': 28, 'city': '北京'}

列表解析器 #

python
from langchain_core.output_parsers import CommaSeparatedListOutputParser

parser = CommaSeparatedListOutputParser()

# 获取格式说明
format_instructions = parser.get_format_instructions()
# "Your response should be a list of comma separated values..."

# 解析
result = parser.invoke("苹果, 香蕉, 橙子")
print(result)  # ['苹果', '香蕉', '橙子']

日期解析器 #

python
from langchain.output_parsers import DatetimeOutputParser

parser = DatetimeOutputParser()

format_instructions = parser.get_format_instructions()

prompt = ChatPromptTemplate.from_messages([
    ("system", "{format_instructions}"),
    ("human", "{query}")
])

chain = prompt | model | parser

result = chain.invoke({
    "query": "美国独立日是哪一天?",
    "format_instructions": format_instructions
})

print(result)  # 1776-07-04 00:00:00

枚举解析器 #

python
from langchain.output_parsers import EnumOutputParser
from enum import Enum

class Sentiment(str, Enum):
    POSITIVE = "积极"
    NEGATIVE = "消极"
    NEUTRAL = "中性"

parser = EnumOutputParser(enum=Sentiment)

prompt = ChatPromptTemplate.from_messages([
    ("system", "分析文本的情感。{format_instructions}"),
    ("human", "{text}")
])

chain = prompt | model | parser

result = chain.invoke({
    "text": "这个产品太棒了,我非常喜欢!",
    "format_instructions": parser.get_format_instructions()
})

print(result)  # Sentiment.POSITIVE

Pydantic 模型解析器 #

python
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from typing import List

class Book(BaseModel):
    title: str = Field(description="书名")
    author: str = Field(description="作者")
    year: int = Field(description="出版年份")
    genres: List[str] = Field(description="类型列表")

parser = PydanticOutputParser(pydantic_object=Book)

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个图书管理员。{format_instructions}"),
    ("human", "介绍一本关于{topic}的书")
])

chain = prompt | model | parser

result = chain.invoke({
    "topic": "人工智能",
    "format_instructions": parser.get_format_instructions()
})

print(result)
# Book(title='人工智能:现代方法', author='Stuart Russell', year=2020, genres=['计算机科学', '人工智能'])
text
┌─────────────────────────────────────────────────────────────┐
│                    输出解析器类型                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  StrOutputParser                                            │
│  └── 提取字符串内容                                         │
│                                                             │
│  JsonOutputParser                                           │
│  └── 解析 JSON 格式输出                                     │
│                                                             │
│  PydanticOutputParser                                       │
│  └── 解析为 Pydantic 模型                                   │
│                                                             │
│  CommaSeparatedListOutputParser                             │
│  └── 解析逗号分隔的列表                                     │
│                                                             │
│  DatetimeOutputParser                                       │
│  └── 解析日期时间                                           │
│                                                             │
│  EnumOutputParser                                           │
│  └── 解析枚举值                                             │
│                                                             │
│  StructuredOutputParser                                     │
│  └── 解析结构化数据(字典)                                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

自动修复解析器 #

当模型输出格式不正确时,自动修复解析器可以尝试修复:

python
from langchain.output_parsers import OutputFixingParser

# 原始解析器
original_parser = PydanticOutputParser(pydantic_object=Person)

# 带自动修复的解析器
fixing_parser = OutputFixingParser.from_llm(
    parser=original_parser,
    llm=model
)

# 如果原始输出格式有误,会自动尝试修复
result = fixing_parser.invoke(model_response)

重试解析器 #

python
from langchain.output_parsers import RetryWithErrorOutputParser

retry_parser = RetryWithErrorOutputParser.from_llm(
    parser=original_parser,
    llm=model
)

# 如果解析失败,会将错误信息反馈给模型重新生成
result = retry_parser.parse_with_prompt(
    completion=model_response,
    prompt_value=prompt_value
)

提示组合技巧 #

链式提示 #

python
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

model = ChatOpenAI(model="gpt-4o-mini")

# 第一步:生成主题
topic_prompt = ChatPromptTemplate.from_template(
    "生成一个关于{domain}的有趣话题"
)
topic_chain = topic_prompt | model | StrOutputParser()

# 第二步:生成内容
content_prompt = ChatPromptTemplate.from_template(
    "写一段关于{topic}的简短介绍"
)

# 组合
from langchain_core.runnables import RunnablePassthrough

chain = (
    {"topic": topic_chain, "domain": RunnablePassthrough()}
    | content_prompt
    | model
    | StrOutputParser()
)

result = chain.invoke("人工智能")

条件提示 #

python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableBranch

# 不同类型的提示
technical_prompt = ChatPromptTemplate.from_template(
    "用专业术语解释:{concept}"
)

simple_prompt = ChatPromptTemplate.from_template(
    "用简单的语言解释:{concept}"
)

# 条件分支
branch = RunnableBranch(
    (lambda x: x["level"] == "expert", technical_prompt),
    (lambda x: x["level"] == "beginner", simple_prompt),
    simple_prompt,  # 默认
)

chain = branch | model | StrOutputParser()

# 使用
result = chain.invoke({"concept": "机器学习", "level": "beginner"})

最佳实践 #

1. 清晰的指令 #

python
# 好的提示
prompt = ChatPromptTemplate.from_messages([
    ("system", """你是一个专业的技术文档撰写者。
    
请遵循以下规则:
1. 使用清晰简洁的语言
2. 提供具体的代码示例
3. 解释关键概念
4. 避免使用行话"""),
    ("human", "{question}")
])

2. 结构化输出 #

python
# 使用 Pydantic 定义清晰的输出结构
class Article(BaseModel):
    title: str = Field(description="文章标题")
    summary: str = Field(description="摘要,不超过100字")
    sections: List[str] = Field(description="章节标题列表")
    keywords: List[str] = Field(description="关键词列表")

parser = PydanticOutputParser(pydantic_object=Article)

3. 示例引导 #

python
# 使用 Few-shot 提高输出质量
examples = [
    {
        "input": "Python",
        "output": "Python 是一种高级编程语言,以简洁易读著称。"
    },
    {
        "input": "JavaScript",
        "output": "JavaScript 是一种脚本语言,主要用于网页开发。"
    }
]

4. 模板复用 #

python
# 创建可复用的模板库
class PromptTemplates:
    SUMMARIZE = ChatPromptTemplate.from_template(
        "请用{length}字总结以下内容:\n\n{content}"
    )
    
    TRANSLATE = ChatPromptTemplate.from_template(
        "将以下{source_lang}文本翻译成{target_lang}:\n\n{text}"
    )
    
    EXPLAIN = ChatPromptTemplate.from_messages([
        ("system", "你是一个{domain}专家"),
        ("human", "请解释{concept},使用{level}的语言")
    ])

下一步 #

最后更新:2026-03-30