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 发布!

相关推荐
青 春 记 忆9 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO39 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO12 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白12 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲13 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)15 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机15 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69215 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy16 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽17 小时前
真实即粗糙,光滑是伪造
人工智能·python