LangChain Prompts模块

LangChain Prompts模块学习

背景

在AI交互中,清晰的提示词设计与输出控制是提升任务成功率的关键,例如:

  • 当提示词为:"请列举3种最适合猫咪编程的语言"

    AI输出:

    yaml 复制代码
    AI: 为猫咪设计的"编程语言"需要极简、直观且符合猫咪的习性(比如喜欢拍打键盘或随机踩踏)。以下是三种最适合猫咪的趣味编程语言推荐:
    
    ---
    
    ### 1. **Catlang**  
    - **特点**:专为猫咪设计的极简语言,键盘上的任意按键组合都可能生成有效代码(比如 `Meow++` 表示循环,`Purr()` 表示输出)。  
    - **猫咪友好度**:键盘
  • 当提示词为:"请列举3种最适合猫咪编程的语言,并用逗号分隔。"

    AI 输出:

    makefile 复制代码
    AI: Scratch, Python, JavaScript

由此可以看出,一个"好"的提示词对模型输出结果影响较大,那么如何写好提示词?

本文将介绍LangChain框架提供了哪些Prompts方法

概念介绍

模型输入(Prompts)有助于将用户输入和参数转换为语言模型的指令。这可以用来指导模型的响应,帮助其理解上下文并生成相关且连贯的语言输出。提示模板输出一个 PromptValue。此 PromptValue 可以传递给 LLM 或 ChatModel,也可以转换为字符串或消息列表。此 PromptValue 存在的目的是为了方便在字符串和消息之间切换。LangChain框架主要提供了一下3个PromptTemplate

  • PromptTemplate 基础模板引擎,支持动态参数替换(如{price}、{flower_name}),实现指令与数据的解耦。通过占位符机制避免硬编码问题,提升代码复用性。
  • ChatPromptTemplate 适配多轮对话场景,支持角色化消息模板(如SystemMessage、HumanMessage、AIMessage),构建结构化聊天上下文
  • FewShotPromptTemplate 通过预置示例引导模型生成特定风格的输出(如广告文案模板),提升任务适配性

验证模型:Deepseek-chat

python 复制代码
from langchain.chat_models import ChatOpenAI
import os

llm = ChatOpenAI(
    model="deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1",
    temperature=0.7,
    max_tokens=100
)

基础模板类:PromptTemplates

提示模板由一个字符串模板组成。它接受来自用户的一组参数,这些参数可用于生成语言模型的提示。可以使用 f 字符串(默认)、jinja2 或 mustache 语法来格式化模板。

ini 复制代码
class PromptTemplate(StringPromptTemplate):
    template: str                                          # 必填	定义提示模板的字符串内容,包含占位符(如 {variable})用于动态替换
    template_format: PromptTemplateFormat = "f-string"     # 指定模板渲染格式,可选值:"f-string"、"mustache"、"jinja2"
    validate_template: bool = False                        # 是否验证模板合法性(如变量是否匹配、语法是否正确),默认关闭以避免性能损耗
python 复制代码
class BasePromptTemplate(
    RunnableSerializable[dict, PromptValue], Generic[FormatOutputType], ABC
):
    """Base class for all prompt templates, returning a prompt."""
    功能:定义模板中必须由用户提供的变量名称列表(如 {topic})。这些变量在调用 format() 时需显式传入
        示例:input_variables=["adjective", "content"] 对应模板中的 {adjective} 和 content 占位符
    input_variables: list[str]

    功能:声明模板中的可选变量,通常用于占位符或动态推断场景。这些变量无需用户显式传入,由系统自动处理
    optional_variables: list[str] = Field(default=[])

    功能:指定输入变量的类型约束(如 int、str)。若未声明,默认所有变量为字符串类型,增强类型安全性
    input_types: typing.Dict[str, Any] = Field(default_factory=dict, exclude=True)  # noqa: UP006

    功能:定义如何解析模型的输出(如转为 JSON 或结构化数据)
    output_parser: Optional[BaseOutputParser] = None

    功能:预填充模板中的部分变量(如固定指令、上下文信息),减少重复参数传递。例如,预填 date="2025-05-22" 后,调用时只需传入其他变量
    partial_variables: Mapping[str, Any] = Field(default_factory=dict)
    
    功能:用于追踪模板的元数据(如版本、作者)和标签(如分类标记),支持调试与监控
    metadata: Optional[typing.Dict[str, Any]] = None  # noqa: UP006
    tags: Optional[list[str]] = None

模板渲染格式

f-string
python 复制代码
from langchain_core.prompts import PromptTemplate

prompt_template = PromptTemplate.from_template("Does {x} like {y} and why? ")
prompt = prompt_template.format(x="foo", y="bar")
print(prompt)  # Output: Does foo like bar and why? 
python 复制代码
from langchain_core.prompts import PromptTemplate

template = "Does {x} like {y} and why? "

prompt_template = PromptTemplate(
    template=template,
    template_format="f-string",
    validate_template=True,
    input_variables=["x", "y"],
    optional_variables=[],
    input_types={
        "x": str,
        "y": str,
    },
    partial_variables={
        "brand": "Generic"
    },
    metadata={
        "version": "1.0",
        "author": "AI Engineer"
    },
    tags=["marketing", "product"]
)

# 填充变量并生成提示
prompt = prompt_template.format(x="foo", y="bar")

print("生成的提示:", prompt) # Output: Does foo like bar and why?

# 疑问 prompt_template.format(x="foo", y=99) pormpt输出?
sql 复制代码
生成的提示: Does foo like 99 and why? 
jinja2
python 复制代码
from langchain_core.prompts import PromptTemplate
from typing import Dict, Any
from pydantic import Field
from langchain_core.output_parsers import BaseOutputParser
from langchain.chat_models import ChatOpenAI
import os
from langchain_core.messages import AIMessage

# 定义一个模板字符串,使用 Jinja2 格式
template = """
{% if product_category == 'electronics' %}
请为{{ product_name }}(电子产品)设计宣传语,强调其技术创新。
{% else %}
请为{{ product_name }}(普通商品)设计宣传语,突出性价比。
{% endif %}
"""

# 创建 PromptTemplate 实例,配置所有参数
prompt_template = PromptTemplate(
    template=template,
    template_format="jinja2",
    validate_template=True,
    input_variables=["product_category", "product_name"],
    optional_variables=["brand"],
    input_types={
        "product_category": str,
        "product_name": str,
        "brand": str
    },
    partial_variables={
        "brand": "Generic"
    },
    metadata={
        "version": "1.0",
        "author": "AI Engineer"
    },
    tags=["marketing", "product"]
)

# 填充变量并生成提示
prompt = prompt_template.format(
    product_category="electronics",
    product_name="智能耳机",
    brand="TechBrand"
)
print("生成的提示:", prompt) # Output: 请为智能耳机(电子产品)设计宣传语,强调其技术创新。

# 填充变量并生成提示
prompt = prompt_template.format(
    product_category="merchandise",
    product_name="智能耳机",
    brand="TechBrand"
)
print("生成的提示:", prompt) # Output: 请为智能耳机(普通商品)设计宣传语,突出性价比。
复制代码
生成的提示: 

请为智能耳机(电子产品)设计宣传语,强调其技术创新。

生成的提示: 

请为智能耳机(普通商品)设计宣传语,突出性价比。
mustache
python 复制代码
from langchain_core.prompts import PromptTemplate

# 定义 mustache 风格模板
template = """
{{#is_electronics}}
请为{{product_name}}(电子产品)设计宣传语,强调其技术创新。
{{/is_electronics}}
{{^is_electronics}}
请为{{product_name}}(普通商品)设计宣传语,突出性价比。
{{/is_electronics}}
"""

prompt_template = PromptTemplate(
    template=template,
    template_format="mustache",
    validate_template=False,   # mustache 模板不能自动校验,validate_template 必须设为 False。
    input_variables=["product_name", "is_electronics"],
    optional_variables=[],
    input_types={
        "product_name": str,
        "is_electronics": bool
    },
    metadata={
        "version": "1.0",
        "author": "AI Engineer"
    },
    tags=["marketing", "product"]
)

# 填充变量并生成提示(电子产品)
prompt1 = prompt_template.format(product_name="智能手表", is_electronics=True)
print("电子产品提示:", prompt1) # Output: 请为智能手表(电子产品)设计宣传语,强调其技术创新。

# 填充变量并生成提示(普通商品)
prompt2 = prompt_template.format(product_name="保温杯", is_electronics=False)
print("普通商品提示:", prompt2) # Output: 请为保温杯(普通商品)设计宣传语,突出性价比。
复制代码
电子产品提示: 
请为智能手表(电子产品)设计宣传语,强调其技术创新。

普通商品提示: 
请为保温杯(普通商品)设计宣传语,突出性价比。

对话模板:ChatPromptTemplate

SystemMessagePromptTemplate 和 HumanMessagePromptTemplate 是 ChatPromptTemplate 的组成部分,用于定义不同角色的消息内容

  1. ChatPromptTemplate 用于多轮对话场景,支持组合 system、human、ai 等多种消息模板,生成适合聊天模型的输入。

  2. HumanMessagePromptTemplate 用于定义"用户输入"消息模板,支持变量占位符,灵活插入用户输入内容。

  3. SystemMessagePromptTemplate 用于定义"系统消息"模板,通常用于设定 AI 的角色、行为准则等。

ChatPromptTemplate 类的实例,使用format_messages方法生成适用于聊天模型的提示。

python 复制代码
class ChatPromptTemplate(BaseChatPromptTemplate):
    """Prompt template for chat models."""
    messages: Annotated[list[MessageLike], SkipValidation()]
    """List of messages consisting of either message prompt templates or messages."""
    validate_template: bool = False
    """Whether or not to try validating the template."""
python 复制代码
from langchain_core.prompts import ChatPromptTemplate

template = ChatPromptTemplate([
    ("system", "You are a helpful AI bot. Your name is {name}."),
    ("human", "Hello, how are you doing?"),
    ("ai", "I'm doing well, thanks!"),
    ("human", "{user_input}"),
],validate_template = True
)

prompt_value = template.invoke(
    {
        "name": "Bob",
        "user_input": "What is your name?"
    }
)
for message in prompt_value.messages:
    print(message.content)

# Output:
#    SystemMessage: You are a helpful AI bot. Your name is Bob.
#    HumanMessage : Hello, how are you doing?
#    AIMessage    : I'm doing well, thanks!
#    HumanMessage : What is your name?
vbnet 复制代码
You are a helpful AI bot. Your name is Bob.
Hello, how are you doing?
I'm doing well, thanks!
What is your name?
python 复制代码
from langchain_core.prompts import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
    SystemMessagePromptTemplate,
)

# 定义一个多轮对话模板
prompt = ChatPromptTemplate([
    SystemMessagePromptTemplate.from_template("你是一个乐于助人的AI助手。"),
    HumanMessagePromptTemplate.from_template("请用{language}写一个冒泡排序。"),
])

# 填充变量并生成消息列表
prompt_value = prompt.invoke({"language": "Python"})
for message in prompt_value.messages:
    print(message.type, ":", message.content)
yaml 复制代码
system : 你是一个乐于助人的AI助手。
human : 请用Python写一个冒泡排序。

Messages Placeholder

MessagesPlaceholder 是 LangChain 框架中用于动态管理对话上下文的结构化占位符,主要解决多轮对话中历史消息注入、格式对齐与动态内容替换等问题。

python 复制代码
class MessagesPlaceholder(BaseMessagePromptTemplate):
    variable_name: str
    """Name of variable to use as messages."""

    optional: bool = False
    """If True format_messages can be called with no arguments and will return an empty
        list. If False then a named argument with name `variable_name` must be passed
        in, even if the value is an empty list."""

    n_messages: Optional[PositiveInt] = None
    """Maximum number of messages to include. If None, then will include all.
    Defaults to None."""

以下是两种不同的写法:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.prompts import MessagesPlaceholder

template = ChatPromptTemplate([
    ("system", "You are a helpful AI bot."),
    MessagesPlaceholder(variable_name="conversation", optional=True)
])

prompt_value = template.invoke(
    {
        "conversation": [
            ("human", "Hi!"),
            ("ai", "How can I assist you today?"),
            ("human", "Can you make me an ice cream sundae?"),
            ("ai", "No.")
        ]
    }
)
for message in prompt_value.messages:
    print(message.content)
css 复制代码
You are a helpful AI bot.
Hi!
How can I assist you today?
Can you make me an ice cream sundae?
No.
python 复制代码
template = ChatPromptTemplate([
    ("system", "You are a helpful AI bot."),
    ("placeholder", "{conversation}")
])

prompt_value = template.invoke(
    {
        "conversation": [
            ("human", "Hi!"),
            ("ai", "How can I assist you today?"),
            ("human", "Can you make me an ice cream sundae?"),
            ("ai", "No.")
        ]
    }
)

for message in prompt_value.messages:
    print(message.content)
css 复制代码
You are a helpful AI bot.
Hi!
How can I assist you today?
Can you make me an ice cream sundae?
No.

Single-variable template

python 复制代码
from langchain_core.prompts import ChatPromptTemplate

template = ChatPromptTemplate([
    ("system", "You are a helpful AI bot. Your name is Carl."),
    ("human", "{user_input}"),
])

prompt_value = template.invoke("Hello, there!")
for message in prompt_value.messages:
    print(message.content)
csharp 复制代码
You are a helpful AI bot. Your name is Carl.
Hello, there!

示例增强模板:FewShotPromptTemplate

FewShotPromptTemplate是向模型提供你希望它执行的操作的示例, 比如:在提示词中可以添加,按照以下格式生成

python 复制代码
class FewShotPromptTemplate(_FewShotPromptTemplateMixin, StringPromptTemplate):
    """Prompt template that contains few shot examples."""

    validate_template: bool = False
    """Whether or not to try validating the template."""

    example_prompt: PromptTemplate
    """PromptTemplate used to format an individual example."""

    suffix: str
    """A prompt template string to put after the examples."""

    example_separator: str = "\n\n"
    """String separator used to join the prefix, the examples, and suffix."""

    prefix: str = ""
    """A prompt template string to put before the examples."""

    template_format: Literal["f-string", "jinja2"] = "f-string"
    """The format of the prompt template. Options are: 'f-string', 'jinja2'."""
python 复制代码
import os
from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.chat_models import ChatOpenAI
examples = [
    {
        "question": "家庭成员的年龄和职业推理",
        "answer": """ 
        1. 母亲是教师,年龄为 40 岁。
        2. 父亲比母亲大 5 岁,所以父亲 45 岁。
        3. 儿子是程序员,年龄是母亲的一半,即 20 岁。
        4. 女儿是医生,年龄比父亲小 10 岁,即 35 岁。
        最终结论:
        - 父亲:45 岁,职业:未知
        - 母亲:40 岁,职业:教师
        - 儿子:20 岁,职业:程序员
        - 女儿:35 岁,职业:医生
        """
    },
    {
        "question": "公司员工的职位与年龄推理",
        "answer": """ 
        1. 员工 A 是项目经理,年龄 35 岁。
        2. 员工 B 是设计师,年龄比项目经理小 5 岁,即 30 岁。
        3. 员工 C 是工程师,年龄是设计师的两倍,即 60 岁。
        4. 员工 D 是实习生,年龄比设计师小 10 岁,即 20 岁。
        最终结论:
        - A:35 岁,职业:项目经理
        - B:30 岁,职业:设计师
        - C:60 岁,职业:工程师
        - D:20 岁,职业:实习生
        """
    },
    {
        "question": "学生兴趣小组的年龄与兴趣推理",
        "answer": """ 
        1. 学生甲是 15 岁,兴趣是编程。
        2. 学生乙比甲大 2 岁,兴趣是绘画。
        3. 学生丙比乙小 1 岁,兴趣是音乐。
        4. 学生丁比丙大 3 岁,兴趣是运动。
        最终结论:
        - 甲:15 岁,兴趣:编程
        - 乙:17 岁,兴趣:绘画
        - 丙:16 岁,兴趣:音乐
        - 丁:19 岁,兴趣:运动
        """
    }
]

# 创建示例提示模板
example_prompt = PromptTemplate(
    input_variables=["question", "answer"],
    template="问题: {question}\n推理过程:{answer}"
)

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="任务说明:回答以下问题\n",
    suffix="问题:{user_input}\n答案:",
    input_variables=["user_input"]
)

usr_input = """1. 员工 A 是项目经理,年龄 20 岁。
        2. 员工 B 是设计师,年龄比项目经理小 4 岁。
        3. 员工 C 是工程师,年龄是设计师的两倍。
        4. 员工 D 是实习生,年龄比设计师小 10 岁。"""
# 生成格式化后的字符串
formatted_prompt = few_shot_prompt.format(user_input=usr_input)

# 初始化模型
llm = ChatOpenAI(
    model="deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1",
    temperature=0.7,
    max_tokens=400
)

# 调用提示模板生成答案
response = llm.invoke(formatted_prompt)
print(response.content)
markdown 复制代码
/tmp/ipykernel_13815/1004832111.py:71: LangChainDeprecationWarning: The class `ChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-openai package and should be used instead. To use it run `pip install -U :class:`~langchain-openai` and import as `from :class:`~langchain_openai import ChatOpenAI``.
  llm = ChatOpenAI(


### 初始信息整理:
1. **员工A**  
   - 职位:项目经理  
   - 年龄:20岁  

2. **员工B**  
   - 职位:设计师  
   - 年龄比项目经理小4岁  

3. **员工C**  
   - 职位:工程师  
   - 年龄是设计师的两倍  

4. **员工D**  
   - 职位:实习生  
   - 年龄比设计师小10岁  

### 分步推理:
#### 第一步:计算员工B的年龄
- 员工B的年龄 = 项目经理的年龄 - 4  
- 项目经理(A)的年龄 = 20岁  
- 因此,员工B的年龄 = 20 - 4 = **16岁**  

#### 第二步:计算员工C的年龄
- 员工C的年龄 = 设计师的年龄 × 2  
- 设计师(B)的年龄 = 16岁  
- 因此,员工C的年龄 = 16 × 2 = **32岁**  

#### 第三步:计算员工D的年龄
- 员工D的年龄 = 设计师的年龄 - 10  
- 设计师(B)的年龄 = 16岁  
- 因此,员工D的年龄 = 16 - 10 = **6岁**  

#### 验证年龄合理性:
- 员工D的年龄为6岁,现实中不太可能成为实习生(通常实习生需成年)。可能是题目设定特殊,暂按逻辑计算。  

### 最终结论:
- **A**:20岁,职业:项目经理  
- **B**:16岁,职业:设计师  
- **C**:32岁,职业:工程师  
- **D**:6岁,职业:实习生  

### 完整答案:
```
- A:20 岁,职业:项目经理
- B:16 岁,职业:设计师

流水线模板:PipelinePromptTemplate

PipelinePromptTemplate 用于将多个提示模板(PromptTemplate)或链式组件(如 LLM、工具等)组合成一个"流水线",实现多阶段、分步处理复杂任务。它常用于需要多步推理、信息汇总、上下文动态注入等场景。

新版 LangChain 已不推荐单独的 PipelinePromptTemplate 类,推荐直接用"RunnablePassthrough链式写法"来实现流水线功能。

python 复制代码
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableSequence
from langchain.chat_models import ChatOpenAI

# 定义子模板
city_template = PromptTemplate.from_template("推荐一个适合{season}旅游的城市:")
attraction_template = PromptTemplate.from_template("列举{city}的3个热门景点:")
food_template = PromptTemplate.from_template("推荐{city}的{attraction}周边美食:")


llm = ChatOpenAI(
    model="deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1",
    temperature=0.7,
    max_tokens=100
)
# 构建多阶段链
travel_chain = (
    RunnablePassthrough.assign(
        city=lambda x: llm.invoke(city_template.format(season=x["season"])).content
    )
    | RunnablePassthrough.assign(
        attraction=lambda x: llm.invoke(attraction_template.format(city=x["city"])).content
    )
    | RunnablePassthrough.assign(
        food=lambda x: llm.invoke(food_template.format(
            city=x["city"], attraction=x["attraction"]
        )).content
    )
    | (lambda x: f"**{x['season']}旅行攻略**\n城市:{x['city']}\n景点:{x['attraction']}\n美食:{x['food']}")
)

# 调用链生成攻略
result = travel_chain.invoke({"season": "春季"})
print(result)
markdown 复制代码
    **春季旅行攻略**
    城市:春季是万物复苏、气候宜人的季节,适合去一些风景优美、气候温和的城市旅行。以下推荐几个适合春季旅游的国内外城市,各有特色,供你参考:

    ---

    ### **国内推荐:**
    1. **杭州(浙江)**  
        - **推荐理由**:西湖的春天桃红柳绿,苏堤、白堤樱花和桃花盛开,龙井茶园新绿盎然。  
        - **亮点**:漫步西湖、品龙井茶
    景点:以下是杭州春季旅游的3个热门景点推荐,结合自然风光与茶文化体验:

    ---

    ### **1. 西湖(苏堤 & 白堤)**  
    - **春日特色**:  
        - 苏堤"六桥烟柳"春色如画,两岸樱花、桃花交错盛开,形成粉色长廊。  
        - 白堤"一株柳树一株桃"的经典景观,3月底至4月初最佳,桃红柳绿
    美食:以下是杭州春季旅游的3个热门景点推荐,结合自然风光、茶文化体验及周边美食,助你规划一场春日味觉与视觉的双重盛宴:

    ---

    ### **1. 西湖(苏堤 & 白堤)**  
    - **春日特色**:  
        - 苏堤"六桥烟柳":两岸樱花、桃花交错盛开,形成粉色长廊,最佳观赏期为3月下旬至4月中旬。  
        - 白堤经典景观:

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
SSH_55231 小时前
【大模型】情绪对话模型项目研发
人工智能·python·语言模型
love530love1 小时前
【笔记】在 MSYS2(MINGW64)中安装 python-maturin 的记录
运维·开发语言·人工智能·windows·笔记·python
G皮T4 小时前
【Python Cookbook】文件与 IO(二)
python·i/o·io·文件·gzip·stringio·bytesio
封奚泽优4 小时前
使用Python绘制节日祝福——以端午节和儿童节为例
人工智能·python·深度学习
干啥都是小小白5 小时前
话题通信之python实现
python·机器人·ros
仟濹5 小时前
「数据采集与网络爬虫(使用Python工具)」【数据分析全栈攻略:爬虫+处理+可视化+报告】
大数据·爬虫·python·数据挖掘·数据分析
水银嘻嘻5 小时前
03 APP 自动化-定位元素工具&元素定位
python·appium·自动化
蹦蹦跳跳真可爱5896 小时前
Python----目标检测(《用于精确目标检测和语义分割的丰富特征层次结构》和R-CNN)
人工智能·python·深度学习·神经网络·目标检测·cnn
抽风的雨6106 小时前
【python深度学习】Day 42 Grad-CAM与Hook函数
开发语言·python·深度学习
Mikhail_G6 小时前
Python应用for循环临时变量作用域
大数据·运维·开发语言·python·数据分析