LangChain Model I/O 详解
LangChain Model I/O 是 LangChain 框架的核心组成部分之一,它提供了一套标准化的接口和工具,用于与各种大型语言模型 (LLMs) 和聊天模型 (Chat Models) 进行交互,并对其输入和输出进行有效的管理和结构化。这是构建任何基于 LLM 的应用程序的基础。
核心思想:将与 LLM 的“对话”分解为可管理、可组合的组件:输入 (Prompt Templates)、模型调用 (LLM/Chat Models) 和输出处理 (Output Parsers)。
一、为什么 Model I/O 至关重要?
在没有 LangChain Model I/O 的情况下,直接与 LLM 交互通常意味着:
- 手动拼接 Prompt: 需要手动构建复杂的字符串,其中包含指令、上下文、示例和用户输入。这既繁琐又容易出错。
- 硬编码模型调用: 每次更换模型或供应商时,都需要修改底层代码。
- 非结构化的输出: LLM 的原始输出通常是自由文本,需要编写复杂的字符串解析逻辑来提取所需信息。
- 缺乏可复用性: 不同应用场景下的 Prompt 和解析逻辑难以复用。
LangChain Model I/O 旨在解决这些问题,提供一个抽象层,使开发者能够:
- 标准化 Prompt: 通过
Prompt Templates精确控制输入结构和内容。 - 抽象模型接口: 轻松切换不同的
LLMs或Chat Models,实现供应商无关性。 - 结构化输出: 通过
Output Parsers将 LLM 的自由文本输出转换为 JSON、Pydantic 对象或其他结构化格式。 - 模块化与可组合性: Model I/O 组件可以与其他 LangChain 组件 (如 Chains, Agents) 无缝组合,构建更复杂的应用。
二、Model I/O 的核心组件
LangChain Model I/O 主要由以下三大核心组件构成:
- LLMs / Chat Models (模型):与大型语言模型本身交互的接口。
- Prompt Templates (提示词模板):生成发送给语言模型的指令。
- Output Parsers (输出解析器):从语言模型的响应中提取和结构化信息。
2.1 LLMs (Large Language Models)
LLMs 类是 LangChain 中用于表示像 GPT-3.5-turbo-instruct、Bison、Llama 等文本输入、文本输出的大型语言模型的抽象。它们接收一个字符串作为输入,并返回一个字符串作为输出。
特点:
- 文本到文本:最直接的交互方式。
- 无记忆:通常是无状态的,每个调用都是独立的。
常见的 LLM 提供商:
OpenAI(例如text-davinci-003,gpt-3.5-turbo-instruct)HuggingFaceHub(各种 Hugging Face 模型)GooglePalm(Google PaLM API)Anthropic(Claude)
示例 (Python):
1 | from langchain_openai import OpenAI |
2.2 Chat Models (聊天模型)
Chat Models 类用于表示设计为接收和返回消息列表的语言模型,通常用于多轮对话。例如 OpenAI 的 gpt-3.5-turbo 和 gpt-4,Anthropic 的 Claude 系列。
特点:
- 消息列表输入/输出:接收
HumanMessage,AIMessage,SystemMessage等对象。 - 更适合对话场景:模型内部通常有针对对话优化的结构。
消息类型:
SystemMessage: 提供模型关于其角色、行为和通用指令。HumanMessage: 用户发出的消息。AIMessage: AI 助理的回复。FunctionMessage(ToolMessage): 工具调用结果(高级Agent功能)。
常见的 Chat Model 提供商:
ChatOpenAI(例如gpt-3.5-turbo,gpt-4)ChatAnthropic(Claude 系列)ChatGoogleGenerativeAI(Gemini 系列)
示例 (Python):
1 | from langchain_openai import ChatOpenAI |
2.3 Prompt Templates (提示词模板)
Prompt Templates 使得构建动态、可重用的提示词变得简单。它们可以接收用户输入或其他变量,并将其格式化为模型能够理解的结构化字符串或消息列表。
主要类型:
StringPromptTemplate: 最基本的模板,用于LLMs。通过 Python 的格式化字符串语法 ({variable_name}) 来定义变量占位符。1
2
3
4
5
6from langchain_core.prompts import PromptTemplate
string_template = PromptTemplate.from_template("告诉我一个关于 {subject} 的 {adjective} 故事。")
prompt = string_template.format(subject="龙", adjective="有趣")
print(prompt)
# 预期输出: 告诉我一个关于 龙 的 有趣 故事。ChatPromptTemplate: 专为Chat Models设计,它通过定义不同角色的消息 (System, Human, AI) 来构建消息列表。1
2
3
4
5
6
7
8
9
10
11
12from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage
chat_template = ChatPromptTemplate.from_messages(
[
SystemMessage(content="你是一个专业的 {role}。"),
HumanMessage(content="为我起一个关于 {product_name} 的产品slogan。")
]
)
messages = chat_template.format_messages(role="市场营销专家", product_name="智能音箱")
print(messages)
# 预期输出: [SystemMessage(content='你是一个专业的 市场营销专家。'), HumanMessage(content='为我起一个关于 智能音箱 的产品slogan。')]FewShotPromptTemplate: 用于实现 Few-Shot Learning,它结合了一组输入/输出示例来指导模型生成更好的响应。它内部嵌套了另一个PromptTemplate来格式化每个示例。
2.4 Output Parsers (输出解析器)
Output Parsers 将 LLM / Chat Model 生成的原始文本输出转换为更易于程序处理的结构化格式,例如 JSON、列表或自定义 Pydantic 对象。
主要类型:
StrOutputParser: 最简单的解析器,它只是将模型输出转换为字符串并删除任何额外的空白。在大多数链的末端,如果没有指定其他解析器,这通常是默认的。1
2
3
4
5
6
7from langchain_core.output_parsers import StrOutputParser
parser = StrOutputParser()
# 假设模型输出是 " Hello World!\n"
parsed_output = parser.invoke(" Hello World!\n")
print(parsed_output)
# 预期输出: Hello World!PydanticOutputParser: 强大的解析器,能够将模型输出解析为预定义的 Pydantic 模型对象。这对于需要严格结构化数据的场景非常有用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
# 定义 Pydantic 模型
class Joke(BaseModel):
setup: str = Field(description="笑话的起始部分")
punchline: str = Field(description="笑话的结尾部分")
parser = PydanticOutputParser(pydantic_object=Joke)
prompt = PromptTemplate(
template="请按照以下格式给出关于程序员的一个笑话。\n{format_instructions}\n",
input_variables=[],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.7)
chain = prompt | chat_model | parser
output: Joke = chain.invoke({})
print(f"笑话铺垫: {output.setup}")
print(f"笑话包袱: {output.punchline}")
# 预期输出(动态生成,结构固定):
# 笑话铺垫: 为什么程序员总是喜欢呆在黑暗里?
# 笑话包袱: 因为他们喜欢 '暗' 示 (command prompt)!JsonOutputParser: 用于将模型输出解析为 JSON 格式。如果 LLM 生成的 JSON 结构明确,可以直接使用。CommaSeparatedListOutputParser: 将逗号分隔的字符串解析为 Python 列表。
三、构建 Model I/O Chain 的实践
在 LangChain 表达式语言 (LCEL) 中,| 操作符是构建 Model I/O 链的核心,它将 Prompt Template、LLM/Chat Model 和 Output Parser 有机地连接起来。
graph TD
A[Prompt Template] -->|格式化输入| B(LLM / Chat Model)
B -->|生成原始文本输出| C[Output Parser]
C -->|结构化输出| D(应用程序逻辑)
示例:使用 LCEL 构建一个问答链
1 | import os |
四、高级概念 (简述)
- Streaming Output (流式输出): 允许 LLM 逐字或逐词地返回响应,而不是等待整个响应生成完毕。LangChain 的 Model I/O 组件可以方便地与流式调用集成。
- Custom Prompt Templates / Output Parsers: 对于非常特定的需求,可以通过继承基类来创建自定义的 Prompt Templates 或 Output Parsers,以实现灵活的输入输出处理逻辑。
- Runnable Interface: LangChain 中所有可执行的组件 (
PromptTemplate,LLM,ChatModel,OutputParser,Chain等) 都实现了Runnable接口,这使得它们可以通过统一的invoke(),batch(),stream()等方法进行调用,并可以方便地使用 LCEL (|) 进行组合。
五、总结
LangChain Model I/O 是 LLM 应用开发中不可或缺的基石。它通过提供 LLMs/Chat Models、Prompt Templates 和 Output Parsers 这三大核心组件,极大地简化了与语言模型的交互过程。通过这种模块化、可组合的方式,开发者可以更高效地构建健壮、灵活且易于维护的 LLM 应用程序,无论是简单的问答系统还是复杂的 Agent 逻辑,Model I/O 都提供了坚实的基础。掌握 Model I/O 将使您能够充分发挥 LangChain 的强大能力。
