本案例详细介绍了如何使用 LangChain 创建和利用提示词模板,以生成动态和灵活的提示词,满足各种应用场景,如对话历史、结构化输出和专门查询。

1. 案例目标

本案例旨在帮助开发者掌握 LangChain 中 PromptTemplate 的核心功能,包括:

  1. 创建提示词模板:学习两种不同的方法创建 PromptTemplate 对象
  2. 使用部分变量:了解如何使用 partial_variables 预填充部分变量
  3. 从 YAML 文件加载模板:掌握如何从外部 YAML 文件加载提示词模板
  4. 聊天提示词模板:学习使用 ChatPromptTemplate 处理对话历史
  5. 消息占位符:了解如何使用 MessagesPlaceholder 动态插入消息列表

2. 技术栈与核心依赖

  • LangChain:用于构建基于大语言模型的应用框架
  • LangChain Core:提供 LangChain 的核心功能
  • LangChain Community:社区贡献的组件和集成
  • LangChain OpenAI:与 OpenAI API 的集成
  • OpenAI API:用于访问 GPT 模型

安装所需依赖的代码:

# 安装必要的包
from langchain_opentutorial import package

package.install(
    [
        "langsmith",
        "langchain",
        "langchain_core",
        "langchain_community",
        "langchain_openai",
    ],
    verbose=False,
    upgrade=False,
)

3. 环境配置

在开始之前,需要设置环境变量:

# 设置环境变量
from langchain_opentutorial import set_env

set_env(
    {
        "OPENAI_API_KEY": "your-openai-api-key",
        "LANGCHAIN_API_KEY": "your-langchain-api-key",
        "LANGCHAIN_TRACING_V2": "true",
        "LANGCHAIN_ENDPOINT": "https://api.smith.langchain.com",
        "LANGCHAIN_PROJECT": "Prompt-Template",
    }
)

然后,设置 ChatOpenAI 模型:

from langchain_openai import ChatOpenAI

# 加载模型
llm = ChatOpenAI(model_name="gpt-4o")

4. 案例实现

4.1 创建 PromptTemplate 对象

方法1:使用 from_template() 方法
from langchain_core.prompts import PromptTemplate

# 定义模板,其中 {country} 是一个变量
template = "What is the capital of {country}?"

# 使用 from_template 方法创建 PromptTemplate 对象
prompt = PromptTemplate.from_template(template)
prompt
方法2:同时创建 PromptTemplate 对象和提示词
# 定义模板
template = "What is the capital of {country}?"

# 使用 PromptTemplate 对象创建提示词模板
prompt = PromptTemplate(
    template=template,
    input_variables=["country"],
)
prompt

4.2 使用 partial_variables

partial_variables 允许部分应用函数,这对于有共享的公共变量特别有用,例如日期或时间。

from datetime import datetime

# 定义返回当前日期的函数
def get_today():
    return datetime.now().strftime("%B %d")

# 创建带有部分变量的提示词模板
prompt = PromptTemplate(
    template="Today's date is {today}. Please list {n} celebrities whose birthday is today. Please specify their date of birth.",
    input_variables=["n"],
    partial_variables={
        "today": get_today  # 以字典形式传递 partial_variables
    },
)

4.3 从 YAML 文件加载提示词模板

可以将提示词模板管理在单独的 YAML 文件中,并使用 load_prompt 加载:

from langchain_core.prompts import load_prompt

# 从 YAML 文件加载提示词模板
prompt = load_prompt("prompts/fruit_color.yaml", encoding="utf-8")
prompt

4.4 ChatPromptTemplate

ChatPromptTemplate 可以用于包含对话历史的提示词。消息结构为 (role, message) 格式的元组,并创建为列表。

from langchain_core.prompts import ChatPromptTemplate

chat_template = ChatPromptTemplate.from_messages(
    [
        # role, message
        ("system", "You are a friendly AI assistant. Your name is {name}."),
        ("human", "Nice to meet you!"),
        ("ai", "Hello! How can I assist you?"),
        ("human", "{user_input}"),
    ]
)

# 创建聊天消息
messages = chat_template.format_messages(name="Teddy", user_input="What is your name?")
messages

4.5 MessagePlaceholder

MessagePlaceholder 提供了在格式化期间渲染消息的完全控制。这在不确定消息提示词模板中使用哪些角色,或者想在格式化期间插入消息列表时非常有用。

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

chat_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are a summarization specialist AI assistant. Your mission is to summarize conversations using key points.",
        ),
        MessagesPlaceholder(variable_name="conversation"),
        ("human", "Summarize the conversation so far in {word_count} words."),
    ]
)
chat_prompt

5. 案例效果

5.1 基本提示词模板效果

# 创建链
chain = prompt | llm

# 替换 country 变量为选择的值
chain.invoke("United States of America").content
# 输出: "The capital of the United States of America is Washington, D.C."

5.2 部分变量效果

# 创建链
chain = prompt | llm

# 调用链并检查结果
print(chain.invoke(3).content)
# 输出: 
# "Here are three celebrities born on January 14:
# 
# 1. **Dave Grohl** - Born on January 14, 1969.
# 2. **LL Cool J** - Born on January 14, 1968.
# 3. **Jason Bateman** - Born on January 14, 1969."

3. 聊天提示词模板效果

# 创建链
chain = chat_template | llm

# 调用链并检查结果
chain.invoke({"name": "Teddy", "user_input": "What is your name?"}).content
# 输出: "My name is Teddy. How can I help you today?"

4. 消息占位符效果

# 创建链
chain = chat_prompt | llm | StrOutputParser()

# 调用链并检查结果
chain.invoke(
    {
        "word_count": 5,
        "conversation": [
            (
                "human",
                "Hello! I'm Teddy. Nice to meet you.",
            ),
            ("ai", "Nice to meet you! I look forward to working with you."),
        ],
    }
)
# 输出: "Teddy introduces himself, exchanges greetings."

6. 案例实现思路

本案例的核心思路是"模板与数据分离"。我们将固定的提示词结构(模板)与动态变化的变量(如国家名称、日期、对话历史)分离开来。这种方法带来以下优势:

  • 可维护性高:修改提示词风格只需编辑模板或 YAML 文件,无需改动代码
  • 复用性强:同一个模板可以用于不同的数据填充场景
  • 功能强大:通过动态注入上下文,为构建复杂应用奠定了基础

7. 扩展建议

  • 多模板管理:设计一个更复杂的模板管理器,根据业务场景动态选择不同的模板
  • 模板缓存:对于频繁使用的模板,增加缓存层,避免每次请求都从磁盘加载,提升性能
  • A/B 测试:通过配置或请求头,动态切换不同版本的提示词模板,用于效果对比和优化
  • 集成向量数据库:将静态文档替换为从向量数据库中检索到的相关文本片段,构建真正的 RAG 系统
  • 多语言支持:扩展模板系统以支持多语言提示词,适应不同语言环境的应用

8. 总结

本案例详细介绍了 LangChain 中 PromptTemplate 的核心功能和使用方法。通过学习如何创建提示词模板、使用部分变量、从 YAML 文件加载模板、处理对话历史以及使用消息占位符,开发者可以构建更加灵活和强大的 AI 应用。

提示词模板是构建基于大语言模型应用的基础组件,掌握其使用方法对于开发高质量 AI 应用至关重要。通过模板与数据分离的设计思路,我们可以创建更加可维护、可复用和功能强大的应用系统。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐