知识模块
🤖 Agent 知识模块
六、主流 Agent 框架
LangChain 框架

LangChain 框架

LangChain 是目前最流行的 Agent 开发框架,由 Harrison Chase 于 2022 年创立。它提供了构建 LLM 应用所需的全套组件,包括模型封装、提示词管理、链式调用、工具集成和记忆系统等。


一、核心原理

1.1 LangChain 设计哲学

LangChain 的设计理念是"组合优先"(Composition First):

┌─────────────────────────────────────────────────────────────┐
│                    LangChain 设计哲学                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   核心思想:像搭积木一样构建 LLM 应用                        │
│                                                             │
│   ┌─────────┐   ┌─────────┐   ┌─────────┐   ┌─────────┐   │
│   │   LLM   │ + │ Prompt  │ + │  Tool   │ + │ Memory  │   │
│   │  组件   │   │  模板   │   │  工具   │   │  记忆   │   │
│   └────┬────┘   └────┬────┘   └────┬────┘   └────┬────┘   │
│        │             │             │             │         │
│        └─────────────┼─────────────┼─────────────┘         │
│                      │             │                       │
│                      ↓             ↓                       │
│              ┌─────────────────────────────┐               │
│              │           Chain              │               │
│              │        (链式组合)            │               │
│              └─────────────────────────────┘               │
│                            │                               │
│                            ↓                               │
│              ┌─────────────────────────────┐               │
│              │           Agent              │               │
│              │       (智能决策层)           │               │
│              └─────────────────────────────┘               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 核心组件架构

┌─────────────────────────────────────────────────────────────────────┐
│                    LangChain 核心组件架构                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   ┌─────────────────────────────────────────────────────────────┐ │
│   │                      应用层 (Application)                    │ │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │ │
│   │  │  Agent   │  │  Chain   │  │  RAG App │  │ Chat App │    │ │
│   │  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘    │ │
│   └───────┼─────────────┼─────────────┼─────────────┼───────────┘ │
│           │             │             │             │             │
│   ┌───────┴─────────────┴─────────────┴─────────────┴───────────┐ │
│   │                      核心层 (Core)                           │ │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │ │
│   │  │  Prompt  │  │  Output  │  │  Memory  │  │Document  │    │ │
│   │  │  Template│  │  Parser  │  │          │  │  Loader  │    │ │
│   │  └──────────┘  └──────────┘  └──────────┘  └──────────┘    │ │
│   └──────────────────────────────────────────────────────────────┘ │
│           │             │             │             │             │
│   ┌───────┴─────────────┴─────────────┴─────────────┴───────────┐ │
│   │                      集成层 (Integration)                    │ │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐    │ │
│   │  │   LLM    │  │  Tools   │  │ Vector   │  │  Other   │    │ │
│   │  │ Providers│  │          │  │  Stores  │  │ Services │    │ │
│   │  └──────────┘  └──────────┘  └──────────┘  └──────────┘    │ │
│   └──────────────────────────────────────────────────────────────┘ │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

1.3 核心概念详解

概念英文作用示例
Chain将多个组件串联成工作流LLMChain, SequentialChain
Agent智能体动态决策和工具调用ReActAgent, OpenAIFunctionsAgent
Tool工具外部能力集成Search, Calculator, PythonREPL
Memory记忆对话历史管理ConversationBufferMemory
Prompt提示词输入模板管理PromptTemplate, ChatPromptTemplate
Output Parser输出解析结构化输出提取PydanticOutputParser, JsonOutputParser

二、核心组件详解

2.1 Model I/O(模型输入输出)

Model I/O 是 LangChain 与 LLM 交互的基础层:

┌─────────────────────────────────────────────────────────────┐
│                    Model I/O 架构                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   输入处理              模型调用              输出处理       │
│   ┌─────────┐        ┌─────────┐         ┌─────────┐       │
│   │ Prompt  │ ─────→ │   LLM   │ ──────→ │ Output  │       │
│   │Template │        │  Model  │         │ Parser  │       │
│   └─────────┘        └─────────┘         └─────────┘       │
│       │                  │                    │            │
│       ↓                  ↓                    ↓            │
│   ┌─────────┐        ┌─────────┐         ┌─────────┐       │
│   │ 格式化  │        │ API调用 │         │ 结构化  │       │
│   │ 变量注入│        │ 响应获取│         │ 数据提取│       │
│   └─────────┘        └─────────┘         └─────────┘       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

代码示例:

"""
LangChain Model I/O 示例
演示 Prompt Template、LLM 和 Output Parser 的使用
"""
 
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from typing import List
 
 
# 1. 定义输出结构
class MovieReview(BaseModel):
    """电影评论结构"""
    title: str = Field(description="电影名称")
    rating: int = 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. 创建提示词模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一位专业的影评人。请按照指定格式输出影评。"),
    ("human", "{query}"),
    ("system", "{format_instructions}")
])
 
# 4. 创建 LLM
llm = ChatOpenAI(model="gpt-4", temperature=0)
 
# 5. 构建链
chain = prompt | llm | parser
 
# 6. 执行
result = chain.invoke({
    "query": "请评价电影《盗梦空间》",
    "format_instructions": parser.get_format_instructions()
})
 
print(f"电影: {result.title}")
print(f"评分: {result.rating}/10")
print(f"总结: {result.summary}")
print(f"优点: {result.pros}")
print(f"缺点: {result.cons}")

2.2 Chain(链)

Chain 是 LangChain 的核心概念,用于将多个组件串联:

┌─────────────────────────────────────────────────────────────┐
│                    Chain 类型全景                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  LLMChain (基础链)                                   │  │
│   │  ┌─────────┐    ┌─────────┐    ┌─────────┐         │  │
│   │  │ Prompt  │ →  │   LLM   │ →  │  Output │         │  │
│   │  │         │    │         │    │         │         │  │
│   │  └─────────┘    └─────────┘    └─────────┘         │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  SequentialChain (顺序链)                            │  │
│   │  ┌─────────┐    ┌─────────┐    ┌─────────┐         │  │
│   │  │ Chain 1 │ →  │ Chain 2 │ →  │ Chain 3 │         │  │
│   │  │         │    │         │    │         │         │  │
│   │  └─────────┘    └─────────┘    └─────────┘         │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  RouterChain (路由链)                                │  │
│   │  ┌─────────────────────────────────────────────┐    │  │
│   │  │              Router (路由器)                 │    │  │
│   │  └─────────────────┬───────────────────────────┘    │  │
│   │            ┌────────┼────────┐                       │  │
│   │            ↓        ↓        ↓                       │  │
│   │      ┌─────────┐ ┌─────────┐ ┌─────────┐            │  │
│   │      │ Chain A │ │ Chain B │ │ Chain C │            │  │
│   │      └─────────┘ └─────────┘ └─────────┘            │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  TransformChain (转换链)                             │  │
│   │  ┌─────────┐    ┌─────────┐    ┌─────────┐         │  │
│   │  │  Input  │ →  │Transform│ →  │ Output  │         │  │
│   │  │         │    │ Function│    │         │         │  │
│   │  └─────────┘    └─────────┘    └─────────┘         │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

LCEL(LangChain Expression Language)示例:

"""
使用 LCEL 构建链
LCEL 是 LangChain 2.0 引入的声明式语法,使用 | 操作符连接组件
"""
 
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableParallel, RunnablePassthrough
 
 
# 1. 创建组件
model = ChatOpenAI(model="gpt-4")
prompt = ChatPromptTemplate.from_template(
    "请用简洁的语言回答:{question}"
)
output_parser = StrOutputParser()
 
# 2. 使用 LCEL 构建简单链
simple_chain = prompt | model | output_parser
 
# 3. 执行简单链
result = simple_chain.invoke({"question": "什么是量子计算?"})
print(result)
 
# 4. 使用 RunnableParallel 构建并行链
parallel_chain = RunnableParallel(
    summary=prompt | model | output_parser,
    original=RunnablePassthrough()
)
 
# 5. 执行并行链
result = parallel_chain.invoke({"question": "什么是区块链?"})
print(f"原始问题: {result['original']}")
print(f"回答: {result['summary']}")
 
# 6. 构建复杂链(带重试和回调)
from langchain.schema.runnable import RunnableRetry
 
robust_chain = (
    prompt 
    | model 
    | output_parser
).with_retry(
    stop_after_attempt=3,
    wait_exponential_multiplier=1000
).with_fallbacks([
    ChatOpenAI(model="gpt-3.5-turbo") | output_parser
])

2.3 Agent(智能体)

Agent 是 LangChain 中最强大的组件,能够动态决策和调用工具:

┌─────────────────────────────────────────────────────────────┐
│                    Agent 工作流程                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────┐                                          │
│   │  用户输入   │                                          │
│   └──────┬──────┘                                          │
│          │                                                  │
│          ↓                                                  │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                 Agent Loop (循环)                    │  │
│   │  ┌───────────────────────────────────────────────┐  │  │
│   │  │              1. 思考 (Think)                   │  │  │
│   │  │  ┌─────────────────────────────────────────┐  │  │  │
│   │  │  │ 分析输入,决定下一步行动                 │  │  │  │
│   │  │  └─────────────────────────────────────────┘  │  │  │
│   │  └───────────────────────────────────────────────┘  │  │
│   │                       │                              │  │
│   │                       ↓                              │  │
│   │  ┌───────────────────────────────────────────────┐  │  │
│   │  │              2. 行动 (Act)                     │  │  │
│   │  │  ┌─────────────────────────────────────────┐  │  │  │
│   │  │  │ 选择工具,传入参数,执行调用             │  │  │  │
│   │  │  └─────────────────────────────────────────┘  │  │  │
│   │  └───────────────────────────────────────────────┘  │  │
│   │                       │                              │  │
│   │                       ↓                              │  │
│   │  ┌───────────────────────────────────────────────┐  │  │
│   │  │              3. 观察 (Observe)                 │  │  │
│   │  │  ┌─────────────────────────────────────────┐  │  │  │
│   │  │  │ 获取工具执行结果,更新上下文             │  │  │  │
│   │  │  └─────────────────────────────────────────┘  │  │  │
│   │  └───────────────────────────────────────────────┘  │  │
│   │                       │                              │  │
│   │              ┌────────┴────────┐                     │  │
│   │              ↓                 ↓                     │  │
│   │         [继续循环]        [生成答案]                  │  │
│   └─────────────────────────────────────────────────────┘  │
│          │                                                  │
│          ↓                                                  │
│   ┌─────────────┐                                          │
│   │  最终输出   │                                          │
│   └─────────────┘                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Agent 类型对比:

Agent 类型特点适用场景
ZeroShotAgent零样本推理,无示例通用场景
ReActAgent思考-行动-观察循环需要工具调用的场景
OpenAIFunctionsAgent使用 OpenAI Function CallingOpenAI 模型最佳实践
StructuredChatAgent支持多输入工具复杂工具调用场景
ConversationalAgent优化对话体验聊天机器人场景

代码示例:

"""
LangChain Agent 示例
创建一个具备搜索和计算能力的 Agent
"""
 
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain.tools import Tool
from langchain import hub
 
 
# 1. 定义工具
def search_tool(query: str) -> str:
    """搜索工具(模拟)"""
    # 实际应用中调用真实搜索 API
    mock_data = {
        "天气": "北京今天晴天,气温 15-25°C",
        "新闻": "今日科技新闻:AI 技术持续突破",
        "股票": "苹果股价今日收盘 $178.50"
    }
    for key, value in mock_data.items():
        if key in query:
            return value
    return f"未找到关于 '{query}' 的信息"
 
 
def calculator_tool(expression: str) -> str:
    """计算器工具"""
    try:
        result = eval(expression)
        return f"计算结果: {result}"
    except Exception as e:
        return f"计算错误: {str(e)}"
 
 
def weather_tool(city: str) -> str:
    """天气查询工具"""
    # 模拟天气 API
    weather_data = {
        "北京": "晴天,15-25°C,空气质量良好",
        "上海": "多云,18-28°C,有轻微雾霾",
        "广州": "小雨,22-30°C,湿度较高"
    }
    return weather_data.get(city, f"未找到 {city} 的天气信息")
 
 
# 2. 创建工具列表
tools = [
    Tool(
        name="search",
        func=search_tool,
        description="搜索互联网获取信息,输入搜索关键词"
    ),
    Tool(
        name="calculator",
        func=calculator_tool,
        description="执行数学计算,输入数学表达式,如 '2+2' 或 '10*5'"
    ),
    Tool(
        name="weather",
        func=weather_tool,
        description="查询城市天气,输入城市名称"
    )
]
 
# 3. 创建 LLM
llm = ChatOpenAI(model="gpt-4", temperature=0)
 
# 4. 获取提示词模板
prompt = hub.pull("hwchase17/openai-functions-agent")
 
# 5. 创建 Agent
agent = create_openai_functions_agent(
    llm=llm,
    tools=tools,
    prompt=prompt
)
 
# 6. 创建 Agent 执行器
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,              # 打印详细执行过程
    max_iterations=10,         # 最大迭代次数
    handle_parsing_errors=True, # 处理解析错误
    max_execution_time=60      # 最大执行时间(秒)
)
 
# 7. 执行 Agent
result = agent_executor.invoke({
    "input": "北京今天天气怎么样?如果温度适中,计算一下 15+10 的结果"
})
 
print(f"\n最终答案: {result['output']}")

2.4 Memory(记忆系统)

Memory 用于管理对话历史和上下文:

┌─────────────────────────────────────────────────────────────┐
│                    Memory 类型架构                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  ConversationBufferMemory (缓冲区记忆)               │  │
│   │  ┌─────────────────────────────────────────────┐    │  │
│   │  │ 存储完整对话历史                             │    │  │
│   │  │ User: 你好 → AI: 你好!有什么可以帮助你的?  │    │  │
│   │  │ User: 天气 → AI: 请问您想查询哪个城市?      │    │  │
│   │  └─────────────────────────────────────────────┘    │  │
│   │  特点:完整保留,Token 消耗大                       │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  ConversationBufferWindowMemory (窗口记忆)           │  │
│   │  ┌─────────────────────────────────────────────┐    │  │
│   │  │ 只保留最近 k 轮对话                          │    │  │
│   │  │ [最近3轮]                                    │    │  │
│   │  │ User: x → AI: y (最近)                       │    │  │
│   │  │ User: x → AI: y (第2近)                      │    │  │
│   │  │ User: x → AI: y (第3近)                      │    │  │
│   │  └─────────────────────────────────────────────┘    │  │
│   │  特点:控制长度,可能丢失早期上下文                 │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  ConversationSummaryMemory (摘要记忆)                │  │
│   │  ┌─────────────────────────────────────────────┐    │  │
│   │  │ 压缩历史对话为摘要                           │    │  │
│   │  │ 摘要:用户询问了北京天气,AI推荐了户外活动   │    │  │
│   │  │ 当前:用户询问明天天气...                    │    │  │
│   │  └─────────────────────────────────────────────┘    │  │
│   │  特点:节省 Token,但摘要可能丢失细节               │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  VectorStoreMemory (向量记忆)                        │  │
│   │  ┌─────────────────────────────────────────────┐    │  │
│   │  │ 向量数据库存储 + 相似性检索                  │    │  │
│   │  │ [向量存储] → [相关性检索] → [检索结果]       │    │  │
│   │  └─────────────────────────────────────────────┘    │  │
│   │  特点:支持大规模历史,检索相关记忆                 │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

代码示例:

"""
LangChain Memory 示例
演示不同类型记忆系统的使用
"""
 
from langchain_openai import ChatOpenAI
from langchain.memory import (
    ConversationBufferMemory,
    ConversationBufferWindowMemory,
    ConversationSummaryMemory
)
from langchain.chains import ConversationChain
 
 
# 1. ConversationBufferMemory(完整缓冲)
buffer_memory = ConversationBufferMemory(
    memory_key="history",
    return_messages=True
)
 
# 2. ConversationBufferWindowMemory(滑动窗口)
window_memory = ConversationBufferWindowMemory(
    k=3,  # 保留最近 3 轮对话
    memory_key="history",
    return_messages=True
)
 
# 3. ConversationSummaryMemory(摘要压缩)
llm = ChatOpenAI(model="gpt-4")
summary_memory = ConversationSummaryMemory(
    llm=llm,
    memory_key="history",
    return_messages=True
)
 
# 4. 创建对话链
conversation = ConversationChain(
    llm=llm,
    memory=buffer_memory,
    verbose=True
)
 
# 5. 进行对话
response1 = conversation.predict(input="你好,我是小明")
print(f"AI: {response1}")
 
response2 = conversation.predict(input="我喜欢打篮球")
print(f"AI: {response2}")
 
response3 = conversation.predict(input="你记得我叫什么名字吗?")
print(f"AI: {response3}")
 
# 6. 查看记忆内容
print(f"\n对话历史:\n{buffer_memory.load_memory_variables({})}")

2.5 Tools(工具系统)

Tools 是 Agent 与外部世界交互的桥梁:

┌─────────────────────────────────────────────────────────────┐
│                    Tools 系统架构                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │              Built-in Tools (内置工具)               │  │
│   │  ┌──────────┐ ┌──────────┐ ┌──────────┐            │  │
│   │  │  Search  │ │ Wikipedia│ │ Python   │            │  │
│   │  │          │ │          │ │   REPL   │            │  │
│   │  └──────────┘ └──────────┘ └──────────┘            │  │
│   │  ┌──────────┐ ┌──────────┐ ┌──────────┐            │  │
│   │  │ Requests │ │ Terminal │ │  Shell   │            │  │
│   │  │          │ │          │ │          │            │  │
│   │  └──────────┘ └──────────┘ └──────────┘            │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │              Custom Tools (自定义工具)               │  │
│   │                                                      │  │
│   │  class MyTool(BaseTool):                            │  │
│   │      name = "my_tool"                               │  │
│   │      description = "工具描述"                        │  │
│   │                                                      │  │
│   │      def _run(self, query: str) -> str:             │  │
│   │          # 工具逻辑                                  │  │
│   │          return result                              │  │
│   │                                                      │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │              Tool Integration (工具集成)             │  │
│   │  ┌──────────┐ ┌──────────┐ ┌──────────┐            │  │
│   │  │  Zapier  │ │ OpenAPI  │ │  SQL     │            │  │
│   │  │  NLA     │ │  Spec    │ │ Database │            │  │
│   │  └──────────┘ └──────────┘ └──────────┘            │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

自定义工具示例:

"""
自定义工具示例
展示如何创建符合 LangChain 规范的工具
"""
 
from typing import Optional, Type
from langchain.tools import BaseTool
from pydantic import BaseModel, Field
 
 
# 1. 定义输入参数模型
class StockPriceInput(BaseModel):
    """股票价格查询输入"""
    symbol: str = Field(description="股票代码,如 AAPL, GOOGL")
    date: Optional[str] = Field(
        default=None,
        description="查询日期,格式 YYYY-MM-DD,默认今天"
    )
 
 
# 2. 定义工具类
class StockPriceTool(BaseTool):
    """股票价格查询工具"""
    
    name = "stock_price"
    description = "查询股票价格信息"
    args_schema: Type[BaseModel] = StockPriceInput
    
    def _run(
        self,
        symbol: str,
        date: Optional[str] = None
    ) -> str:
        """执行工具逻辑"""
        # 模拟股票数据
        stock_data = {
            "AAPL": {"price": 178.50, "change": "+2.30"},
            "GOOGL": {"price": 141.80, "change": "-1.20"},
            "MSFT": {"price": 378.90, "change": "+5.60"}
        }
        
        symbol = symbol.upper()
        if symbol not in stock_data:
            return f"未找到股票代码 '{symbol}'"
        
        data = stock_data[symbol]
        return (
            f"股票 {symbol}:\n"
            f"  当前价格: ${data['price']}\n"
            f"  涨跌幅: {data['change']}"
        )
    
    async def _arun(
        self,
        symbol: str,
        date: Optional[str] = None
    ) -> str:
        """异步执行(可选)"""
        return self._run(symbol, date)
 
 
# 3. 使用装饰器创建工具(简化方式)
from langchain.tools import tool
 
 
@tool
def calculate_mortgage(
    principal: float,
    rate: float,
    years: int
) -> str:
    """
    计算房贷月供
    
    Args:
        principal: 贷款本金(元)
        rate: 年利率(如 0.05 表示 5%)
        years: 贷款年限
    
    Returns:
        月供金额和总利息信息
    """
    monthly_rate = rate / 12
    months = years * 12
    
    # 等额本息公式
    monthly_payment = principal * (
        monthly_rate * (1 + monthly_rate) ** months
    ) / ((1 + monthly_rate) ** months - 1)
    
    total_payment = monthly_payment * months
    total_interest = total_payment - principal
    
    return (
        f"贷款信息:\n"
        f"  月供: ¥{monthly_payment:,.2f}\n"
        f"  总还款: ¥{total_payment:,.2f}\n"
        f"  总利息: ¥{total_interest:,.2f}"
    )
 
 
# 4. 使用工具
tools = [StockPriceTool(), calculate_mortgage]
 
# 创建 Agent 使用这些工具
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain import hub
 
llm = ChatOpenAI(model="gpt-4")
prompt = hub.pull("hwchase17/openai-functions-agent")
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
 
# 执行
result = agent_executor.invoke({
    "input": "查询苹果公司(AAPL)的股价,然后计算贷款100万、利率4.9%、30年的月供"
})
print(result["output"])

三、RAG 应用实现

3.1 RAG 架构概述

┌─────────────────────────────────────────────────────────────┐
│                    RAG 完整架构                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │              离线索引构建阶段                         │  │
│   │                                                      │  │
│   │  ┌──────────┐   ┌──────────┐   ┌──────────┐        │  │
│   │  │ Document │ → │  Split   │ → │ Embedding│        │  │
│   │  │  Loader  │   │   分块   │   │   向量化 │        │  │
│   │  └──────────┘   └──────────┘   └──────────┘        │  │
│   │                                      │              │  │
│   │                                      ↓              │  │
│   │                              ┌──────────┐          │  │
│   │                              │  Vector  │          │  │
│   │                              │  Store   │          │  │
│   │                              └──────────┘          │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │              在线查询阶段                            │  │
│   │                                                      │  │
│   │  ┌──────────┐   ┌──────────┐   ┌──────────┐        │  │
│   │  │  Query   │ → │ Embedding│ → │Retrieve  │        │  │
│   │  │  问题    │   │   向量化 │   │  检索    │        │  │
│   │  └──────────┘   └──────────┘   └──────────┘        │  │
│   │                                      │              │  │
│   │                                      ↓              │  │
│   │  ┌──────────┐   ┌──────────┐   ┌──────────┐        │  │
│   │  │  LLM     │ ← │  Prompt  │ ← │ Context  │        │  │
│   │  │  生成    │   │  构建    │   │  组装    │        │  │
│   │  └──────────┘   └──────────┘   └──────────┘        │  │
│   │                                      │              │  │
│   │                                      ↓              │  │
│   │                              ┌──────────┐          │  │
│   │                              │  Answer  │          │  │
│   │                              │  回答    │          │  │
│   │                              └──────────┘          │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.2 RAG 完整实现

"""
LangChain RAG 完整实现示例
构建一个基于文档的问答系统
"""
 
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import (
    PyPDFLoader,
    TextLoader,
    DirectoryLoader
)
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
 
 
# ========== 1. 文档加载 ==========
 
def load_documents(data_path: str):
    """加载文档"""
    # 加载 PDF 文件
    pdf_loader = DirectoryLoader(
        data_path,
        glob="**/*.pdf",
        loader_cls=PyPDFLoader
    )
    
    # 加载文本文件
    txt_loader = DirectoryLoader(
        data_path,
        glob="**/*.txt",
        loader_cls=TextLoader
    )
    
    documents = pdf_loader.load() + txt_loader.load()
    return documents
 
 
# ========== 2. 文档分割 ==========
 
def split_documents(documents, chunk_size=1000, chunk_overlap=200):
    """分割文档为小块"""
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=chunk_size,
        chunk_overlap=chunk_overlap,
        length_function=len,
        separators=["\n\n", "\n", " ", ""]
    )
    
    chunks = text_splitter.split_documents(documents)
    return chunks
 
 
# ========== 3. 向量存储 ==========
 
def create_vector_store(chunks, persist_directory="./chroma_db"):
    """创建向量存储"""
    embeddings = OpenAIEmbeddings()
    
    vector_store = Chroma.from_documents(
        documents=chunks,
        embedding=embeddings,
        persist_directory=persist_directory
    )
    
    return vector_store
 
 
# ========== 4. 检索器配置 ==========
 
def create_retriever(vector_store, search_type="mmr", k=4):
    """创建检索器"""
    # 基础检索器
    base_retriever = vector_store.as_retriever(
        search_type=search_type,
        search_kwargs={"k": k}
    )
    
    # 使用 LLM 进行上下文压缩
    llm = ChatOpenAI(model="gpt-4", temperature=0)
    compressor = LLMChainExtractor.from_llm(llm)
    
    compression_retriever = ContextualCompressionRetriever(
        base_compressor=compressor,
        base_retriever=base_retriever
    )
    
    return compression_retriever
 
 
# ========== 5. RAG 链构建 ==========
 
def create_rag_chain(retriever):
    """创建 RAG 问答链"""
    
    # 自定义提示词模板
    prompt_template = """
你是一个专业的问答助手。请根据以下上下文回答问题。
如果上下文中没有相关信息,请说"根据已有资料无法回答该问题"。
 
上下文:
{context}
 
问题:{question}
 
请提供详细、准确的回答:
"""
    
    PROMPT = PromptTemplate(
        template=prompt_template,
        input_variables=["context", "question"]
    )
    
    # 创建 LLM
    llm = ChatOpenAI(model="gpt-4", temperature=0)
    
    # 创建问答链
    qa_chain = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=retriever,
        return_source_documents=True,
        chain_type_kwargs={"prompt": PROMPT}
    )
    
    return qa_chain
 
 
# ========== 6. 完整 RAG 应用 ==========
 
class RAGApplication:
    """RAG 应用类"""
    
    def __init__(self, data_path: str, persist_directory: str = "./chroma_db"):
        """初始化 RAG 应用"""
        self.data_path = data_path
        self.persist_directory = persist_directory
        
        # 初始化组件
        self.vector_store = None
        self.retriever = None
        self.qa_chain = None
    
    def build_index(self):
        """构建索引"""
        print("1. 加载文档...")
        documents = load_documents(self.data_path)
        print(f"   加载了 {len(documents)} 个文档")
        
        print("2. 分割文档...")
        chunks = split_documents(documents)
        print(f"   分割为 {len(chunks)} 个文本块")
        
        print("3. 创建向量存储...")
        self.vector_store = create_vector_store(
            chunks,
            self.persist_directory
        )
        print("   向量存储创建完成")
    
    def load_index(self):
        """加载已有索引"""
        embeddings = OpenAIEmbeddings()
        self.vector_store = Chroma(
            persist_directory=self.persist_directory,
            embedding_function=embeddings
        )
    
    def setup(self, rebuild=False):
        """设置应用"""
        if rebuild:
            self.build_index()
        else:
            self.load_index()
        
        print("4. 创建检索器...")
        self.retriever = create_retriever(self.vector_store)
        
        print("5. 创建问答链...")
        self.qa_chain = create_rag_chain(self.retriever)
        
        print("RAG 应用准备就绪!")
    
    def query(self, question: str) -> dict:
        """查询问题"""
        result = self.qa_chain.invoke({"query": question})
        
        return {
            "answer": result["result"],
            "sources": [
                doc.metadata.get("source", "未知来源")
                for doc in result["source_documents"]
            ]
        }
 
 
# ========== 使用示例 ==========
 
if __name__ == "__main__":
    # 创建应用
    app = RAGApplication(
        data_path="./documents",
        persist_directory="./chroma_db"
    )
    
    # 设置(首次运行需要 rebuild=True)
    app.setup(rebuild=False)
    
    # 查询
    result = app.query("什么是机器学习?")
    print(f"\n回答:{result['answer']}")
    print(f"\n来源:{result['sources']}")

四、生产最佳实践

4.1 架构设计原则

┌─────────────────────────────────────────────────────────────┐
│                    生产级架构设计                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                    API 层                            │  │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐          │  │
│   │  │ FastAPI  │  │ Rate     │  │  Auth    │          │  │
│   │  │ Endpoint │  │ Limiter  │  │  Guard   │          │  │
│   │  └──────────┘  └──────────┘  └──────────┘          │  │
│   └─────────────────────────────────────────────────────┘  │
│                          │                                  │
│                          ↓                                  │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                   服务层                             │  │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐          │  │
│   │  │  Agent   │  │  Chain   │  │  Memory  │          │  │
│   │  │ Service  │  │ Service  │  │ Service  │          │  │
│   │  └──────────┘  └──────────┘  └──────────┘          │  │
│   └─────────────────────────────────────────────────────┘  │
│                          │                                  │
│                          ↓                                  │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                   数据层                             │  │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐          │  │
│   │  │ Vector   │  │  Cache   │  │   DB     │          │  │
│   │  │ Store    │  │ (Redis)  │  │ (Postgres)│          │  │
│   │  └──────────┘  └──────────┘  └──────────┘          │  │
│   └─────────────────────────────────────────────────────┘  │
│                          │                                  │
│                          ↓                                  │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                 可观测层                             │  │
│   │  ┌──────────┐  ┌──────────┐  ┌──────────┐          │  │
│   │  │ Logging  │  │ Metrics  │  │ Tracing  │          │  │
│   │  │          │  │ (Prom)   │  │ (Jaeger) │          │  │
│   │  └──────────┘  └──────────┘  └──────────┘          │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 错误处理与重试

"""
生产级错误处理和重试策略
"""
 
from tenacity import (
    retry,
    stop_after_attempt,
    wait_exponential,
    retry_if_exception_type
)
from langchain.schema import OutputParserException
import logging
 
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
 
 
class RobustChain:
    """具有错误处理能力的链"""
    
    def __init__(self, chain, max_retries=3):
        self.chain = chain
        self.max_retries = max_retries
    
    @retry(
        stop=stop_after_attempt(3),
        wait=wait_exponential(multiplier=1, min=2, max=10),
        retry=retry_if_exception_type(Exception),
        before_sleep=lambda retry_state: logger.warning(
            f"重试 {retry_state.attempt_number}..."
        )
    )
    def invoke(self, input_data):
        """执行链,带重试"""
        try:
            return self.chain.invoke(input_data)
        except OutputParserException as e:
            logger.error(f"输出解析错误: {e}")
            # 尝试修复输出
            return self._handle_parse_error(e, input_data)
        except Exception as e:
            logger.error(f"执行错误: {e}")
            raise
    
    def _handle_parse_error(self, error, input_data):
        """处理解析错误"""
        # 实现修复逻辑
        logger.info("尝试修复输出格式...")
        # 可以添加格式修复提示词重新调用
        raise error
 
 
# 使用示例
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.output_parsers import PydanticOutputParser
 
llm = ChatOpenAI(model="gpt-4")
prompt = ChatPromptTemplate.from_template("...")
chain = prompt | llm
 
robust_chain = RobustChain(chain)
result = robust_chain.invoke({"input": "测试输入"})

4.3 性能优化

"""
性能优化策略
"""
 
import asyncio
from langchain.cache import InMemoryCache, SQLiteCache
from langchain.globals import set_llm_cache
from langchain_openai import ChatOpenAI
 
 
# 1. 启用缓存
set_llm_cache(InMemoryCache())  # 或 SQLiteCache("cache.db")
 
# 2. 异步调用
async def batch_invoke(chain, inputs):
    """批量异步调用"""
    tasks = [chain.ainvoke(input_data) for input_data in inputs]
    return await asyncio.gather(*tasks)
 
# 3. 流式输出
async def stream_response(chain, input_data):
    """流式输出"""
    async for chunk in chain.astream(input_data):
        yield chunk
 
# 4. 连接池优化
from langchain_openai import ChatOpenAI
 
llm = ChatOpenAI(
    model="gpt-4",
    max_retries=3,
    timeout=30,
    request_timeout=60
)

五、面试问答

Q1: LangChain 的核心组件有哪些?它们之间的关系是什么?

回答要点:

组件作用关系
Prompt输入模板管理Chain 的输入层
LLM模型调用Chain 的处理层
Chain组件串联连接所有组件
Agent动态决策使用 Tools 和 Memory
Tool外部能力Agent 的扩展
Memory状态管理Agent 和 Chain 的上下文

关系图:

Prompt → LLM → Output Parser (基础链)

         + Tools + Memory (Agent)

            最终输出

Q2: LCEL(LangChain Expression Language)的优势是什么?

回答要点:

  1. 声明式语法:使用 | 操作符直观连接组件
  2. 自动异步支持:无需额外代码即可使用异步
  3. 流式输出:内置流式处理能力
  4. 易于调试:每个步骤都可追踪
  5. 类型安全:更好的类型提示和验证
# 传统方式
chain = LLMChain(llm=llm, prompt=prompt)
 
# LCEL 方式
chain = prompt | llm | parser  # 更简洁直观

Q3: 如何选择合适的 Memory 类型?

回答要点:

Memory 类型适用场景Token 消耗
BufferMemory短对话、需要完整历史
WindowMemory中等对话、只关注近期
SummaryMemory长对话、关注整体主题
VectorMemory大规模历史、按相关性检索

选择建议:

  • 对话轮数 < 10:BufferMemory
  • 对话轮数 10-50:WindowMemory
  • 对话轮数 > 50:SummaryMemory 或 VectorMemory

Q4: LangChain 如何实现工具调用?

回答要点:

  1. 工具定义:使用 @tool 装饰器或继承 BaseTool
  2. 工具绑定:通过 llm.bind_tools(tools) 或在 Agent 中配置
  3. 执行流程:LLM 生成工具调用 → 解析参数 → 执行工具 → 返回结果
  4. 错误处理handle_parsing_errors=True 自动处理格式错误

Q5: LangChain 的局限性和改进方向?

回答要点:

局限性:

  • 复杂工作流编排能力有限
  • 状态管理不够灵活
  • 调试和可观测性有待加强
  • 学习曲线较陡峭

改进方向:

  • LangGraph 提供更灵活的工作流
  • LangSmith 提供可观测性平台
  • 更多的内置工具和集成
  • 简化的 API 设计

六、小结

LangChain 作为最流行的 Agent 开发框架,提供了构建 LLM 应用的完整工具链:

核心优势

  • 生态丰富:支持多种 LLM、工具和向量存储
  • 模块化设计:组件可灵活组合
  • 生产就绪:缓存、重试、异步等企业级特性

关键要点

  1. Chain 是核心:理解 LCEL 语法是掌握 LangChain 的基础
  2. Agent 是目标:动态决策和工具调用是 Agent 的核心能力
  3. Memory 是关键:合适的记忆策略影响应用质量
  4. Tools 是扩展:丰富的工具生态扩展 Agent 能力

下一步学习

  • 深入学习 LlamaIndex 的 RAG 能力
  • 探索 LangGraph 的复杂工作流编排
  • 实践生产级 Agent 应用的开发和部署