第2章:模型调用与提示词

本章将深入学习LangChain最核心的功能:如何调用各种AI模型,以及如何编写高效的提示词(Prompt)。掌握这些技能是构建LLM应用的基础。

2.1 支持的模型类型

LangChain支持多种大语言模型,让你可以根据需求灵活选择:

2.1.1 OpenAI模型

最常用、文档最完善的选项:

  • GPT-4/GPT-4o:最强大的模型,适合复杂任务
  • GPT-3.5-turbo:性价比高,响应速度快
  • Text-Embedding:用于文本向量化的嵌入模型
# OpenAI模型使用示例
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI

# 文本补全模型(旧版接口)
llm = OpenAI(model_name="gpt-3.5-turbo-instruct")

# 对话模型(推荐使用)
chat_model = ChatOpenAI(model="gpt-3.5-turbo")

2.1.2 Anthropic Claude模型

以长文本处理和安全性著称:

# Anthropic Claude模型
from langchain.chat_models import ChatAnthropic

claude = ChatAnthropic(model="claude-3-sonnet-20240229")

2.1.3 本地模型(HuggingFace)

在本地运行开源模型,无需联网、数据隐私:

# HuggingFace本地模型
from langchain.llms import HuggingFacePipeline
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline

# 加载本地模型
model_id = "meta-llama/Llama-2-7b-chat-hf"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)

# 创建pipeline
pipe = pipeline(
    "text-generation",
    model=model,
    tokenizer=tokenizer,
    max_new_tokens=100
)

llm = HuggingFacePipeline(pipeline=pipe)

2.1.4 Azure OpenAI

企业级部署选择,符合合规要求:

# Azure OpenAI
from langchain.chat_models import AzureChatOpenAI

azure_llm = AzureChatOpenAI(
    azure_deployment="your-deployment-name",
    openai_api_version="2024-02-01",
    azure_endpoint="https://your-resource.openai.azure.com/",
    openai_api_key="your-azure-api-key"
)

2.1.5 其他模型

提供商 导入路径 特点
Google Gemini langchain.chat_models.ChatGoogleGenerativeAI Google最新模型
Cohere langchain.llms.Cohere 专注于企业应用
百度文心 langchain.llms.ErnieBot 国产中文模型
阿里通义 langchain.chat_models.ChatTongyi 国产大模型
安装提示:使用不同模型前,需要先安装对应的Python包。例如:pip install anthropicpip install google-generativeai

2.2 LLM vs Chat Model

LangChain提供了两种主要模型接口,理解它们的区别非常重要:

2.2.1 LLM(文本补全模型)

工作原理:接收一个文本字符串,预测后续文本。

  • 输入:单个字符串
  • 输出:单个字符串
  • 类似"自动补全"功能
# LLM使用示例
from langchain.llms import OpenAI

# 创建LLM实例
llm = OpenAI(temperature=0.7)

# 输入一个字符串
prompt = "中国的首都是"
response = llm.predict(prompt)

print(response)  # 输出: 北京

2.2.2 Chat Model(对话模型)

工作原理:接收一组消息(包含角色信息),生成回复消息。

  • 输入:消息列表(System、Human、AI)
  • 输出:AI消息对象
  • 更适合构建对话应用
# Chat Model使用示例
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage

# 创建Chat Model实例
chat = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)

# 构建消息列表
messages = [
    SystemMessage(content="你是一个 helpful 的助手"),  # 系统指令
    HumanMessage(content="你好,请介绍一下自己")       # 用户输入
]

# 调用模型
response = chat.predict_messages(messages)

print(response.content)  # 输出AI的回复

2.2.3 代码对比

特性 LLM Chat Model
输入类型 字符串 消息列表
支持系统指令 ❌ 不支持 ✅ 支持(SystemMessage)
对话历史 ❌ 手动拼接 ✅ 消息列表自然支持
价格 部分模型较便宜 GPT-3.5-turbo性价比高
推荐使用 简单文本任务 ⭐ 对话应用(强烈推荐)
最佳实践:新建项目建议直接使用 Chat Model(如 ChatOpenAI),它功能更强大、设计更合理,是LangChain推荐的主流用法。

2.3 Prompt Templates(提示词模板)

提示词模板是LangChain最强大的功能之一,让你可以创建可复用、可配置的提示词。

2.3.1 什么是提示词模板?

提示词模板 = 提示词 + 变量占位符

类比理解:

  • 普通提示词:"用一句话介绍Python编程语言"
  • 提示词模板:"用一句话介绍{language}编程语言" → 可替换为任意语言

2.3.2 PromptTemplate基础用法

用于LLM(文本补全模型)的模板:

# PromptTemplate基础用法
from langchain.prompts import PromptTemplate

# 方式1:使用from_template工厂方法(推荐)
template = PromptTemplate.from_template(
    "请用{style}风格,介绍一下{topic}"
)

# 方式2:直接实例化
template = PromptTemplate(
    input_variables=["style", "topic"],
    template="请用{style}风格,介绍一下{topic}"
)

# 格式化模板(填入变量值)
formatted_prompt = template.format(
    style="幽默",
    topic="人工智能"
)

print(formatted_prompt)
# 输出: 请用幽默风格,介绍一下人工智能

2.3.3 ChatPromptTemplate对话模板

用于Chat Model的模板,支持多角色消息:

# ChatPromptTemplate使用示例
from langchain.prompts import ChatPromptTemplate
from langchain.schema import SystemMessage, HumanMessage

# 方式1:使用from_messages创建多角色模板
chat_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的{role}"),
    ("human", "{question}")
])

# 方式2:使用消息对象
chat_template = ChatPromptTemplate.from_messages([
    SystemMessage(content="你是一个专业的{role}"),
    HumanMessage(content="{question}")
])

# 格式化模板
messages = chat_template.format_messages(
    role="厨师",
    question="如何做红烧肉?"
)

# messages现在是:[SystemMessage, HumanMessage]
print(messages)

2.3.4 带变量的模板实战

更复杂的模板示例,包含多个变量和不同类型的消息:

# 复杂模板示例
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI

# 创建一个翻译助手的提示词模板
translation_template = ChatPromptTemplate.from_messages([
    # 系统指令:定义AI的角色和行为
    ("system", """你是一个专业的翻译助手。
请将用户输入的{text_language}文本翻译成{target_language}。
要求:
1. 保持原文的语气和风格
2. 专业术语翻译准确
3. 只输出翻译结果,不要解释"""),
    
    #  few-shot示例:给AI举例子
    ("human", "Hello, how are you?"),
    ("ai", "你好,你好吗?"),
    
    # 真正的用户输入
    ("human", "{input_text}")
])

# 使用模板
messages = translation_template.format_messages(
    text_language="英文",
    target_language="中文",
    input_text="The quick brown fox jumps over the lazy dog."
)

# 调用模型
chat = ChatOpenAI()
response = chat.predict_messages(messages)
print(response.content)
提示词工程技巧:在模板中加入few-shot示例(给AI看几个例子),能显著提升输出质量。人类学习需要例子,AI也一样!

2.3.5 模板的高级特性

# 模板组合
from langchain.prompts import PromptTemplate, ChatPromptTemplate

# 创建基础模板
base_template = PromptTemplate.from_template("请用{tone}的语气")
instruction_template = PromptTemplate.from_template("解释{topic}")

# 组合模板
full_template = PromptTemplate.from_template(
    "{base},{instruction}",
    partial_variables={
        "base": base_template,
        "instruction": instruction_template
    }
)

# 部分格式化(先填部分变量)
template = PromptTemplate.from_template("你好{name},{message}")
partial_template = template.partial(name="小明")  # 先填入name
final = partial_template.format(message="欢迎光临!")  # 再填入message

2.4 输出解析器 Output Parsers

大语言模型输出的是文本,但我们通常需要结构化数据(如JSON)。输出解析器可以自动完成这个转换。

2.4.1 PydanticOutputParser结构化输出

使用Pydantic定义数据模型,让AI按指定格式输出:

# PydanticOutputParser示例
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from pydantic import BaseModel, Field
from typing import List

# 第1步:定义输出数据结构
class MovieReview(BaseModel):
    """电影评论的结构化输出格式"""
    movie_name: str = Field(description="电影名称")
    rating: float = Field(description="评分(1-10分)")
    summary: str = Field(description="一句话总结")
    pros: List[str] = Field(description="优点列表")
    cons: List[str] = Field(description="缺点列表")

# 第2步:创建解析器
parser = PydanticOutputParser(pydantic_object=MovieReview)

# 第3步:查看格式说明(会自动生成)
format_instructions = parser.get_format_instructions()
print(format_instructions)
# 输出包含JSON格式的说明和要求

# 第4步:创建带格式说明的提示词模板
prompt = PromptTemplate(
    template="""请对以下电影进行评论:
{movie_title}

{format_instructions}
""",
    input_variables=["movie_title"],
    partial_variables={"format_instructions": format_instructions}
)

# 第5步:调用模型
chat = ChatOpenAI(temperature=0)
formatted_prompt = prompt.format(movie_title="肖申克的救赎")
response = chat.predict(formatted_prompt)

# 第6步:解析输出
movie_review = parser.parse(response)
print(f"电影: {movie_review.movie_name}")
print(f"评分: {movie_review.rating}")
print(f"优点: {movie_review.pros}")

2.4.2 JsonOutputParser

如果只需要JSON格式,可以使用更简单的JsonOutputParser:

# JsonOutputParser示例
from langchain.output_parsers import JsonOutputParser
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI

# 创建JSON解析器
parser = JsonOutputParser()

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

# 创建提示词
template = """请提取以下文本中的关键信息,并以JSON格式输出:

文本: {text}

{format_instructions}
"""

prompt = PromptTemplate(
    template=template,
    input_variables=["text"],
    partial_variables={"format_instructions": format_instructions}
)

# 调用
chat = ChatOpenAI()
response = chat.predict(prompt.format(text="张三,25岁,软件工程师,毕业于清华大学"))

# 解析JSON
data = parser.parse(response)
print(data)
# 输出: {'name': '张三', 'age': 25, ...}

2.4.3 完整示例:让AI输出JSON格式

# 完整的结构化输出示例
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from pydantic import BaseModel, Field

# 定义产品信息的数据结构
class ProductInfo(BaseModel):
    product_name: str = Field(description="产品名称")
    category: str = Field(description="产品类别")
    price_range: str = Field(description="价格区间")
    key_features: list = Field(description="主要特点列表")
    target_audience: str = Field(description="目标用户群体")

# 创建解析器
parser = PydanticOutputParser(pydantic_object=ProductInfo)

# 创建提示词模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个产品分析专家。请分析用户输入的产品描述,提取关键信息。"),
    ("human", """请分析以下产品:
{product_description}

{format_instructions}
""")
])

# 填入变量
messages = prompt.format_messages(
    product_description="iPhone 15 Pro Max,售价9999元起,搭载A17 Pro芯片,配备钛金属边框,支持USB-C接口,拥有4800万像素主摄,适合追求极致体验的高端用户。",
    format_instructions=parser.get_format_instructions()
)

# 调用模型
chat = ChatOpenAI(temperature=0)
response = chat.predict_messages(messages)

# 解析结果
product = parser.parse(response.content)
print(product.json(indent=2, ensure_ascii=False))
注意事项:即使使用了输出解析器,AI有时仍可能输出不符合格式的内容(特别是弱一点的模型)。生产环境建议加上错误处理:try/except 包裹 parser.parse()

2.5 Runnable接口与管道操作符

LangChain Expression Language (LCEL) 提供了更简洁的链式调用方式。

2.5.1 pipe操作符 | 的使用

使用 | 符号将多个组件串联起来:

# Runnable接口与管道操作符
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.output_parsers import StrOutputParser

# 定义提示词模板
prompt = ChatPromptTemplate.from_template(
    "请用中文解释{concept}的概念"
)

# 创建模型
model = ChatOpenAI(model="gpt-3.5-turbo")

# 创建输出解析器(将AIMessage转为字符串)
output_parser = StrOutputParser()

# 使用管道符连接组件 | 
# 数据流向: prompt -> model -> output_parser
chain = prompt | model | output_parser

# 调用链
result = chain.invoke({"concept": "区块链"})
print(result)

# 等价于传统写法:
# messages = prompt.format_messages(concept="区块链")
# response = model.predict_messages(messages)
# result = output_parser.parse(response)

2.5.2 管道的工作流程

# 复杂管道示例
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field

# 定义输出结构
class AnalysisResult(BaseModel):
    keywords: list = Field(description="关键词列表")
    sentiment: str = Field(description="情感倾向")
    summary: str = Field(description="内容摘要")

parser = PydanticOutputParser(pydantic_object=AnalysisResult)

# 创建提示词
prompt = ChatPromptTemplate.from_template("""
请分析以下文本:
{text}

{format_instructions}
""")

# 构建管道
# 第一步:将输入字典格式化为提示词
# 第二步:调用模型生成回复
# 第三步:解析为结构化数据
chain = (
    {"text": lambda x: x["text"], "format_instructions": lambda x: parser.get_format_instructions()}
    | prompt
    | ChatOpenAI(temperature=0)
    | parser
)

# 调用
result = chain.invoke({"text": "这家餐厅的食物太美味了!服务也很棒,下次一定再来!"})
print(result)
管道操作符的优势:
1. 代码更简洁、可读性更强
2. 自动支持流式输出(streaming)
3. 自动支持批处理(batch)
4. 内置重试和错误处理机制

2.6 完整实战:构建"翻译助手"链

综合运用本章知识,构建一个完整的翻译助手应用。

2.6.1 需求分析

我们要实现的功能:

  • 输入:中文文本
  • 处理:翻译成英文
  • 输出:JSON格式(包含原文、译文、单词数)

2.6.2 完整代码

# translator_app.py
# 完整实战:构建翻译助手链

from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.output_parsers import PydanticOutputParser
from langchain.schema import StrOutputParser
from pydantic import BaseModel, Field
from typing import Literal

# ==================== 第1步:定义输出数据结构 ====================
class TranslationResult(BaseModel):
    """翻译结果的数据结构"""
    original_text: str = Field(description="原文")
    translated_text: str = Field(description="译文")
    source_language: Literal["中文", "英文"] = Field(description="源语言")
    target_language: Literal["中文", "英文"] = Field(description="目标语言")
    word_count: int = Field(description="译文单词/字数")
    confidence: Literal["高", "中", "低"] = Field(description="翻译置信度")

# ==================== 第2步:创建组件 ====================

# 创建输出解析器
parser = PydanticOutputParser(pydantic_object=TranslationResult)

# 创建提示词模板
translation_prompt = ChatPromptTemplate.from_messages([
    ("system", """你是一位专业的翻译助手,精通中英文互译。
请将用户的输入翻译成目标语言,并提供结构化输出。

翻译要求:
1. 准确传达原文意思
2. 保持原文的语气和风格
3. 专业术语翻译准确
4. 如果原文有歧义,选择最可能的解释
"""),
    ("human", """请翻译以下内容:
源语言: {source_language}
目标语言: {target_language}
原文: {text}

{format_instructions}
""")
])

# 创建模型
model = ChatOpenAI(
    model="gpt-3.5-turbo",
    temperature=0.3  # 翻译任务需要较低的温度以保证准确性
)

# ==================== 第3步:构建链 ====================

# 使用管道操作符构建链
# 输入: {"text": "...", "source_language": "...", "target_language": "..."}
# 输出: TranslationResult对象

translation_chain = (
    {
        "text": lambda x: x["text"],
        "source_language": lambda x: x["source_language"],
        "target_language": lambda x: x["target_language"],
        "format_instructions": lambda x: parser.get_format_instructions()
    }
    | translation_prompt
    | model
    | parser
)

# ==================== 第4步:使用链 ====================

def translate(text: str, source: str = "中文", target: str = "英文") -> TranslationResult:
    """
    翻译函数
    
    参数:
        text: 要翻译的文本
        source: 源语言("中文"或"英文")
        target: 目标语言("中文"或"英文")
    
    返回:
        TranslationResult对象,包含翻译结果和元信息
    """
    try:
        result = translation_chain.invoke({
            "text": text,
            "source_language": source,
            "target_language": target
        })
        return result
    except Exception as e:
        print(f"翻译出错: {e}")
        raise

# ==================== 第5步:测试运行 ====================

if __name__ == "__main__":
    # 测试1: 中译英
    print("=" * 50)
    print("测试1: 中译英")
    print("=" * 50)
    
    result1 = translate(
        text="人工智能正在改变我们的生活方式。",
        source="中文",
        target="英文"
    )
    
    print(f"原文: {result1.original_text}")
    print(f"译文: {result1.translated_text}")
    print(f"字数: {result1.word_count}")
    print(f"置信度: {result1.confidence}")
    
    # 测试2: 英译中
    print("\n" + "=" * 50)
    print("测试2: 英译中")
    print("=" * 50)
    
    result2 = translate(
        text="The future belongs to those who believe in the beauty of their dreams.",
        source="英文",
        target="中文"
    )
    
    print(f"原文: {result2.original_text}")
    print(f"译文: {result2.translated_text}")
    print(f"字数: {result2.word_count}")
    print(f"置信度: {result2.confidence}")
    
    # 以JSON格式输出
    print("\n" + "=" * 50)
    print("JSON格式输出:")
    print("=" * 50)
    print(result2.json(indent=2, ensure_ascii=False))

2.6.3 运行结果示例

==================================================
测试1: 中译英
==================================================
原文: 人工智能正在改变我们的生活方式。
译文: Artificial intelligence is transforming the way we live.
字数: 9
置信度: 高

==================================================
测试2: 英译中
==================================================
原文: The future belongs to those who believe in the beauty of their dreams.
译文: 未来属于那些相信梦想之美的人。
字数: 16
置信度: 高

==================================================
JSON格式输出:
==================================================
{
  "original_text": "The future belongs to those who believe in the beauty of their dreams.",
  "translated_text": "未来属于那些相信梦想之美的人。",
  "source_language": "英文",
  "target_language": "中文",
  "word_count": 16,
  "confidence": "高"
}
代码亮点:
1. 使用Pydantic严格定义输入输出结构
2. 提示词模板包含清晰的翻译要求
3. 管道操作符让代码简洁易读
4. 添加了完整的错误处理
5. 支持中/英双向翻译

本章小结

恭喜完成第2章的学习!你已经掌握了LangChain最核心的技能:

  • ✅ 了解各种模型类型和如何选择
  • ✅ 掌握LLM和Chat Model的区别(强烈推荐使用Chat Model)
  • ✅ 熟练使用PromptTemplate和ChatPromptTemplate
  • ✅ 使用Output Parser获取结构化输出
  • ✅ 使用Runnable接口和管道操作符简化代码
  • ✅ 完成一个完整的翻译助手实战项目

关键概念回顾

概念 用途 关键类/方法
Chat Model 对话式AI交互 ChatOpenAI, predict_messages()
提示词模板 复用和参数化提示词 ChatPromptTemplate.from_messages()
输出解析器 结构化模型输出 PydanticOutputParser
管道操作符 链式组合组件 | (如 prompt | model | parser)
下章预告:第3章我们将学习Chains(链)的更多用法,以及如何使用Memory让AI记住对话历史,构建真正的对话机器人!