LangChain 1.2.0 完全精通指南

237 阅读25分钟

目录

  1. 第一部分:基础入门
  2. 第二部分:核心概念详解
  3. 第三部分:提示工程
  4. 第四部分:记忆管理
  5. 第五部分:Runnable与链
  6. 第六部分:工具与函数调用
  7. 第七部分:代理Agent
  8. 第八部分:RAG检索增强
  9. 第九部分:详细应用案例
  10. 第十部分:高级特性

第一部分:基础入门

1.1 什么是LangChain?

LangChain是由LangChain AI公司开发的开源框架,专门用于构建基于大语言模型(LLM)的AI应用。它提供了一套标准化、模块化的工具和框架,使开发者能够快速构建从简单的聊天应用到复杂的多代理系统。

LangChain的核心价值

功能描述
统一API无论使用OpenAI、Claude、Gemini,API接口保持一致
模块化设计灵活组装各功能模块(提示、链、记忆、工具、代理)
生产就绪包含日志、监控、持久化、错误处理等企业级特性
丰富集成集成200+外部服务(数据库、搜索引擎、API等)
流式处理支持实时流式输出,提升用户体验
中间件系统通过中间件实现PII保护、人工审核、请求限流等

1.2 环境安装与配置

# 基础安装
pip install -U langchain langchain-core

# 安装特定LLM集成(选择需要的)
pip install langchain-openai              # OpenAI
pip install langchain-anthropic           # Claude
pip install langchain-google-genai         # Gemini
pip install langchain-ollama               # 本地模型

# 安装社区集成(包含许多工具和集成)
pip install langchain-community

# 安装LangSmith用于监控(可选但推荐)
pip install langsmith

# 安装其他常用工具
pip install python-dotenv                 # 环境变量管理

1.3 配置API密钥

import os
from dotenv import load_dotenv

# 从.env文件加载环境变量
load_dotenv()

# 或直接设置
os.environ["OPENAI_API_KEY"] = "your-api-key"
os.environ["ANTHROPIC_API_KEY"] = "your-api-key"

# LangSmith配置(用于追踪和调试)
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = "your-langsmith-key"
os.environ["LANGSMITH_PROJECT"] = "my-project"

1.4 快速开始示例

from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage, SystemMessage

# 初始化模型
model = init_chat_model("gpt-4o-mini")

# 方式1:简单调用
response = model.invoke("你好,请自我介绍")
print(response.content)

# 方式2:结构化消息
messages = [
    SystemMessage(content="你是一个专业的技术顾问"),
    HumanMessage(content="什么是LangChain?")
]
response = model.invoke(messages)
print(response.content)

# 方式3:流式处理
for chunk in model.stream("讲述AI发展历史"):
    print(chunk.content, end="", flush=True)

第二部分:核心概念详解

2.1 消息系统

LangChain使用标准化的消息格式来处理对话,这是与LLM交互的基础。

2.1.1 消息类型

from langchain.messages import (
    HumanMessage,      # 用户消息
    AIMessage,         # AI回复消息
    SystemMessage,     # 系统指令
    ToolMessage,       # 工具执行结果
    FunctionMessage    # 函数执行结果
)

# 构建对话历史
messages = [
    # 系统消息:定义AI角色和行为
    SystemMessage(content="你是一个精通Python的编程导师,用简洁的方式解释复杂概念"),
    
    # 用户消息:第一轮提问
    HumanMessage(content="什么是装饰器?"),
    
    # AI消息:AI的回复
    AIMessage(content="装饰器是一个函数,它接受另一个函数作为参数,并返回一个修改后的函数..."),
    
    # 用户消息:跟进提问
    HumanMessage(content="能给个实际例子吗?"),
    
    # 工具消息:来自工具的结果
    ToolMessage(
        content="示例代码已执行,输出为:[1, 2, 3]",
        tool_call_id="tool_123"
    )
]

# 传递给模型
response = model.invoke(messages)

2.1.2 消息内容块

LangChain 1.2引入的内容块统一了不同LLM提供商的功能:

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(model="claude-sonnet-4-5-20250929")

# Claude支持多种内容块类型
response = model.invoke("分析这个复杂问题并给出推理过程")

# 访问响应中的各种内容块
if hasattr(response, 'content'):
    for block in response.content:
        if isinstance(block, dict):
            if block.get("type") == "thinking":
                print(f"推理过程: {block.get('thinking')}")
            elif block.get("type") == "text":
                print(f"最终答案: {block.get('text')}")

2.2 LLM与Chat Model

两种基本的模型接口:

from langchain_openai import ChatOpenAI, OpenAI

# Chat Model:推荐使用
# 专为对话优化,基于消息的接口
chat_model = ChatOpenAI(
    model="gpt-4o",
    temperature=0.7,           # 创意度(0-1,0最保守)
    max_tokens=2000,           # 最大输出长度
    timeout=30,                # 超时时间
    max_retries=2              # 失败重试次数
)

# LLM Model:遗留模式
# 基于文本的接口,已逐步被ChatModel替代
llm = OpenAI(
    model="gpt-3.5-turbo-instruct",
    temperature=0.5
)

# 调用方式相同
response = chat_model.invoke("你的问题")
print(response.content)

2.3 输出解析器

将模型输出转换为结构化格式:

from langchain.output_parsers import (
    StrOutputParser,           # 提取字符串
    JSONOutputParser,          # JSON解析
    PydanticOutputParser,      # Pydantic模型
    CommaSeparatedListOutputParser  # 逗号分隔列表
)
from pydantic import BaseModel, Field

# 方法1:简单字符串解析
from langchain.chat_models import init_chat_model
parser = StrOutputParser()
model = init_chat_model("gpt-4o-mini")
chain = model | parser
result = chain.invoke("生成5个创意产品名称")
print(result)  # 直接获得字符串

# 方法2:JSON解析
from langchain.output_parsers import JsonOutputParser

parser = JsonOutputParser()
model = init_chat_model("gpt-4o-mini")

prompt = """
生成3个产品的信息,返回JSON格式:
[
  {
    "name": "产品名称",
    "price": 价格,
    "features": ["特性1", "特性2"]
  }
]
"""

chain = model | parser
result = chain.invoke(prompt)
print(result)  # 自动解析为Python字典列表

# 方法3:Pydantic模型解析(最强大)
from pydantic import BaseModel

class Product(BaseModel):
    """产品信息模型"""
    name: str = Field(description="产品名称")
    price: float = Field(description="价格")
    features: list = Field(description="产品特性")

parser = PydanticOutputParser(pydantic_object=Product)

# 自动生成格式指导
format_instructions = parser.get_format_instructions()
print(format_instructions)  # 告诉模型如何输出

prompt_text = f"""
生成一个产品的信息。

{format_instructions}
"""

chain = model | parser
result = chain.invoke(prompt_text)
# result是Product对象,可以直接访问属性
print(result.name, result.price, result.features)

# 方法4:列表解析
list_parser = CommaSeparatedListOutputParser()
chain = model | list_parser
result = chain.invoke("列出5种水果")
print(result)  # ['苹果', '香蕉', '橙子', '葡萄', '西瓜']

第三部分:提示工程

3.1 Prompt Template基础

from langchain.prompts import PromptTemplate

# 方法1:简单模板
template = PromptTemplate(
    input_variables=["product", "tone"],
    template="为{product}生成一个{tone}的广告文案"
)

prompt = template.format(product="咖啡", tone="激情洋溢的")
print(prompt)
# 输出:为咖啡生成一个激情洋溢的广告文案

# 方法2:使用from_template(更简洁)
template = PromptTemplate.from_template(
    "为{product}生成一个{tone}的广告文案"
)

# 方法3:多行模板
template = PromptTemplate.from_template(
    """
    你是一个专业的营销专家。
    
    产品:{product}
    目标市场:{market}
    广告风格:{style}
    
    请生成一个能够吸引目标市场的广告文案。
    """
)

3.2 Chat Prompt Template

用于对话模型的高级提示:

from langchain.prompts import ChatPromptTemplate
from langchain.prompts import SystemMessagePromptTemplate, HumanMessagePromptTemplate

# 方法1:使用from_messages
chat_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的{profession}"),
    ("human", "请回答这个问题:{question}"),
])

messages = chat_template.format_messages(
    profession="数据科学家",
    question="什么是特征工程?"
)
print(messages)

# 方法2:使用专门的Template类
system_template = SystemMessagePromptTemplate.from_template(
    "你是一个专业的{profession}"
)
human_template = HumanMessagePromptTemplate.from_template(
    "请回答这个问题:{question}"
)

chat_template = ChatPromptTemplate.from_messages([
    system_template,
    human_template
])

# 方法3:多轮对话模板
chat_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个友好的AI助手"),
    ("human", "你好,你叫什么?"),
    ("ai", "你好,我是Claude,很高兴认识你"),
    ("human", "{user_input}"),
])

messages = chat_template.format_messages(
    user_input="你能做什么?"
)
response = model.invoke(messages)

3.3 高级提示模式

Few-Shot Learning(少样本学习)

from langchain.prompts import FewShotChatMessagePromptTemplate, ChatPromptTemplate

# 定义示例
examples = [
    {
        "input": "我想创业",
        "output": "创业需要:1. 有竞争力的想法 2. 足够的资金 3. 坚定的执行力"
    },
    {
        "input": "怎样改进生产效率",
        "output": "可以考虑:1. 自动化生产流程 2. 优化工作流程 3. 员工培训"
    }
]

# 创建示例提示
example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}")
])

# 创建少样本提示
few_shot_prompt = FewShotChatMessagePromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    suffix="现在请回答这个问题:{input}",
    input_variables=["input"]
)

# 使用
final_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个商业咨询专家"),
    few_shot_prompt
])

messages = final_prompt.format_messages(
    input="如何建立供应链?"
)
response = model.invoke(messages)

Dynamic Prompt Selection

from langchain.prompts import PromptTemplate
from langchain.chat_models import init_chat_model

# 根据用户输入选择不同的提示
def get_prompt(topic):
    prompts = {
        "编程": PromptTemplate.from_template(
            "作为Python专家,解释{topic}的最佳实践"
        ),
        "商业": PromptTemplate.from_template(
            "作为商业顾问,分析{topic}对企业的影响"
        ),
        "科学": PromptTemplate.from_template(
            "作为科学家,从科学角度解释{topic}"
        )
    }
    return prompts.get(topic, prompts["编程"])

# 使用
topic = "人工智能"
category = "科学"  # 用户选择的类别
prompt = get_prompt(category)
formatted_prompt = prompt.format(topic=topic)
response = model.invoke(formatted_prompt)

第四部分:记忆管理

4.1 Memory系统概述

记忆是使AI应用能够进行有意义对话的关键。LangChain提供了多种记忆类型:

类型保存方式适用场景Token消耗
BufferMemory保存全部对话短对话,需要完整上下文随对话增长
BufferWindowMemory仅保存最近N轮长对话,只需近期信息恒定
TokenBufferMemory按Token数限制需要精确控制成本恒定
SummaryMemory自动总结很长的对话中等

4.2 Buffer Memory(缓冲记忆)

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
from langchain.chat_models import init_chat_model

# 初始化
llm = init_chat_model("gpt-4o-mini")
memory = ConversationBufferMemory()

# 创建对话链
conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True  # 打印调试信息
)

# 多轮对话
conversation.invoke({"input": "我叫张三"})
conversation.invoke({"input": "我的职业是工程师"})
conversation.invoke({"input": "你记得我的名字吗?"})  # AI会回忆

# 查看内存中的历史
print("对话历史:")
print(memory.buffer)

# 手动管理内存
memory.save_context(
    {"input": "什么是机器学习"},
    {"output": "机器学习是..."}
)

# 提取内存变量
variables = memory.load_memory_variables({})
print("内存变量:", variables)

# 返回消息列表格式(用于ChatModel)
memory_with_messages = ConversationBufferMemory(
    return_messages=True
)
variables = memory_with_messages.load_memory_variables({})
# variables['history']是消息对象列表,而非字符串

4.3 Window Memory(窗口记忆)

from langchain.memory import ConversationBufferWindowMemory

# 只保存最近k轮对话
memory = ConversationBufferWindowMemory(
    k=3,  # 保留最近3轮对话
    return_messages=True
)

conversation = ConversationChain(
    llm=llm,
    memory=memory
)

# 进行多轮对话
for i in range(10):
    response = conversation.invoke({"input": f"这是第{i+1}轮对话"})
    print(f"轮次{i+1}: 内存中保存{len(memory.buffer)}条消息")
    # 你会看到内存中最多保存3轮对话

4.4 Token Buffer Memory

from langchain.memory import ConversationTokenBufferMemory

# 根据Token数量而不是对话数量来保留历史
memory = ConversationTokenBufferMemory(
    llm=llm,
    max_token_limit=1000,  # 最多保留1000个Token
    return_messages=True
)

conversation = ConversationChain(
    llm=llm,
    memory=memory
)

# 对话会自动控制在Token数量内
conversation.invoke({"input": "讲述一个长故事..."})

4.5 Summary Memory(总结记忆)

from langchain.memory import ConversationSummaryMemory

# 自动总结对话内容
memory = ConversationSummaryMemory(
    llm=llm,
    return_messages=True
)

conversation = ConversationChain(
    llm=llm,
    memory=memory
)

# 进行多轮长对话
conversation.invoke({"input": "早上我去咖啡馆喝了咖啡"})
conversation.invoke({"input": "然后去公园散步"})
conversation.invoke({"input": "下午参加了会议"})
conversation.invoke({"input": "晚上看了电影"})

# 查看自动生成的总结
print("对话总结:")
print(memory.buffer)

# 内存会逐步总结,减少Token消耗

4.6 自定义Memory类

from langchain.memory.chat_memory import BaseChatMemory
from langchain.schema import get_buffer_string

class CustomMemory(BaseChatMemory):
    """自定义记忆类"""
    
    def load_memory_variables(self, inputs: dict) -> dict:
        """加载内存变量"""
        buffer_string = get_buffer_string(
            self.chat_memory.messages,
            human_prefix="用户",
            ai_prefix="助手"
        )
        return {"history": buffer_string}
    
    def save_context(self, inputs: dict, outputs: dict) -> None:
        """保存对话上下文"""
        self.chat_memory.add_user_message(inputs["input"])
        self.chat_memory.add_ai_message(outputs["output"])

# 使用自定义记忆
memory = CustomMemory()
memory.save_context(
    {"input": "你好"},
    {"output": "你好!很高兴认识你"}
)
print(memory.load_memory_variables({}))

第五部分:Runnable与链

5.1 Runnable概念

Runnable是LangChain 1.2的核心抽象,代表可以被链式调用的任何操作。

from langchain_core.runnables import Runnable, RunnableLambda
from langchain_core.output_parsers import StrOutputParser

# 所有这些都是Runnable:
# - LLM模型
# - 提示模板
# - 输出解析器
# - 自定义函数
# - 工具调用

model = init_chat_model("gpt-4o-mini")
parser = StrOutputParser()

# Runnable可以链式组合(使用|操作符)
chain = model | parser
result = chain.invoke("你好")
print(result)  # 直接获得字符串,不需要.content

5.2 构建链(Chain)

方法1:使用|操作符(推荐)

from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import init_chat_model
from langchain_core.output_parsers import StrOutputParser

# 定义组件
prompt = ChatPromptTemplate.from_template(
    "为{topic}生成一个创意想法"
)
model = init_chat_model("gpt-4o-mini")
parser = StrOutputParser()

# 链式组合
chain = prompt | model | parser

# 调用
result = chain.invoke({"topic": "未来的智能城市"})
print(result)

# 支持流式处理
for chunk in chain.stream({"topic": "AI应用"}):
    print(chunk, end="", flush=True)

# 批量处理
results = chain.batch([
    {"topic": "机器学习"},
    {"topic": "深度学习"},
    {"topic": "强化学习"}
])

方法2:RunnableLambda

from langchain_core.runnables import RunnableLambda

# 将普通函数转换为Runnable
def uppercase(text):
    return text.upper()

def count_words(text):
    return len(text.split())

# 创建Runnable
upper_runnable = RunnableLambda(uppercase)
count_runnable = RunnableLambda(count_words)

# 组合使用
chain = upper_runnable | count_runnable
result = chain.invoke("hello world")
print(result)  # 2

# 链式包含模型
model = init_chat_model("gpt-4o-mini")
chain = model | RunnableLambda(lambda x: x.content.upper())
result = chain.invoke("say hello")

方法3:RunnableParallel(并行执行)

from langchain_core.runnables import RunnableParallel

prompt = ChatPromptTemplate.from_template("讨论{topic}")
model = init_chat_model("gpt-4o-mini")

# 并行运行多个链
parallel_chain = RunnableParallel(
    original=model | StrOutputParser(),
    uppercase=model | RunnableLambda(lambda x: x.content.upper()),
    word_count=model | RunnableLambda(lambda x: len(x.content.split()))
)

result = parallel_chain.invoke({"topic": "AI发展"})
print(result)
# 输出:{
#     'original': '...',
#     'uppercase': '...',
#     'word_count': 123
# }

# 简化写法(字典自动转换为RunnableParallel)
parallel_chain = {
    "analysis": model | StrOutputParser(),
    "length": model | RunnableLambda(lambda x: len(x.content))
}

方法4:RunnablePassthrough

from langchain_core.runnables import RunnablePassthrough

prompt = ChatPromptTemplate.from_template(
    "根据上下文和问题生成答案\n"
    "上下文: {context}\n"
    "问题: {question}"
)

# 保留原始输入
chain = {
    "context": RunnablePassthrough(),
    "question": lambda x: x
} | prompt | model | StrOutputParser()

# 简化:直接使用RunnablePassthrough
chain = RunnablePassthrough() | prompt | model | StrOutputParser()

result = chain.invoke({"context": "背景信息", "question": "问题"})

5.3 条件路由

from langchain_core.runnables import RunnableBranch

# 定义不同的处理链
technical_chain = init_chat_model("gpt-4o-mini") | StrOutputParser()
business_chain = init_chat_model("gpt-4o-mini") | StrOutputParser()
default_chain = init_chat_model("gpt-4o-mini") | StrOutputParser()

# 创建条件路由
def route_by_topic(x):
    if "技术" in x.lower():
        return technical_chain
    elif "商业" in x.lower():
        return business_chain
    return default_chain

# 使用
router = RunnableBranch(
    (lambda x: "技术" in x, technical_chain),
    (lambda x: "商业" in x, business_chain),
    default_chain
)

result = router.invoke("解释什么是技术")

5.4 重试与异常处理

from langchain_core.runnables import Runnable
import time

class ResilientChain(Runnable):
    def __init__(self, chain, max_retries=3, backoff_factor=2):
        self.chain = chain
        self.max_retries = max_retries
        self.backoff_factor = backoff_factor
    
    def invoke(self, input):
        for attempt in range(self.max_retries):
            try:
                return self.chain.invoke(input)
            except Exception as e:
                if attempt == self.max_retries - 1:
                    raise
                wait_time = self.backoff_factor ** attempt
                print(f"尝试{attempt + 1}失败,等待{wait_time}秒后重试...")
                time.sleep(wait_time)

# 使用
chain = prompt | model | parser
resilient_chain = ResilientChain(chain, max_retries=3)
result = resilient_chain.invoke({"topic": "AI"})

第六部分:工具与函数调用

6.1 定义工具

from langchain.tools import tool, Tool
from typing import Optional
import math
import requests

# 方法1:使用@tool装饰器(推荐)
@tool
def calculate_area(radius: float) -> float:
    """计算圆的面积
    
    Args:
        radius: 圆的半径
    """
    return math.pi * radius ** 2

@tool
def search_wikipedia(query: str, max_results: int = 3) -> str:
    """在Wikipedia搜索信息
    
    Args:
        query: 搜索关键词
        max_results: 最多返回结果数
    """
    # 实现搜索逻辑
    return f"搜索 '{query}' 的结果..."

@tool
def get_current_weather(location: str, unit: str = "celsius") -> str:
    """获取指定位置的天气
    
    Args:
        location: 城市名称
        unit: 温度单位(celsius或fahrenheit)
    """
    return f"{location}的天气:晴天,25°C"

# 方法2:使用Tool类直接定义
def multiply(x: float, y: float) -> float:
    """两数相乘"""
    return x * y

multiply_tool = Tool(
    name="Multiply",
    func=multiply,
    description="将两个数字相乘",
    # 可选:为参数提供更详细的描述
)

# 工具列表
tools = [calculate_area, search_wikipedia, get_current_weather]

6.2 工具执行

from langchain_core.tools import ToolException

# 工具执行和错误处理
@tool
def division(x: float, y: float) -> float:
    """两数相除
    
    Args:
        x: 被除数
        y: 除数
    """
    if y == 0:
        raise ToolException("除数不能为0")
    return x / y

# 执行工具
result = division.invoke({"x": 10, "y": 2})
print(result)  # 5.0

# 获取工具信息
print(division.name)           # "division"
print(division.description)    # "两数相除..."
print(division.get_input_schema())  # 输入schema

6.3 动态工具注册

from langchain.agents import tool
import inspect

class ToolRegistry:
    def __init__(self):
        self.tools = {}
    
    def register(self, name: str, description: str):
        """动态注册工具的装饰器"""
        def decorator(func):
            self.tools[name] = tool(func)
            return func
        return decorator
    
    def get_tools(self):
        return list(self.tools.values())

registry = ToolRegistry()

@registry.register("compute_factorial", "计算阶乘")
def factorial(n: int) -> int:
    """计算n的阶乘"""
    if n <= 1:
        return 1
    return n * factorial(n - 1)

@registry.register("reverse_string", "反转字符串")
def reverse(text: str) -> str:
    """将字符串反转"""
    return text[::-1]

# 获取所有注册的工具
tools = registry.get_tools()

6.4 工具组合与管理

from langchain.tools import StructuredTool
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    """搜索工具的输入"""
    query: str = Field(description="搜索关键词")
    max_results: int = Field(default=5, description="返回结果数")

# 使用Pydantic定义结构化输入
def web_search(query: str, max_results: int = 5) -> str:
    """从网络搜索信息"""
    return f"找到关于'{query}'的{max_results}个结果"

search_tool = StructuredTool.from_function(
    func=web_search,
    name="WebSearch",
    description="搜索网络获取信息",
    args_schema=SearchInput
)

# 工具集合类
class ToolKit:
    """工具集合管理"""
    def __init__(self):
        self.tools = []
    
    def add_tool(self, tool):
        self.tools.append(tool)
    
    def get_tools(self):
        return self.tools
    
    def get_tool_by_name(self, name: str):
        for tool in self.tools:
            if tool.name == name:
                return tool
        return None

toolkit = ToolKit()
toolkit.add_tool(calculate_area)
toolkit.add_tool(search_wikipedia)
toolkit.add_tool(search_tool)

# 获取工具
tools = toolkit.get_tools()

第七部分:代理Agent

7.1 创建基础代理

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model

# 初始化模型
model = init_chat_model("gpt-4o")

# 创建代理(最新方式)
agent = create_agent(
    model=model,
    tools=tools,  # 使用之前定义的工具
    system_prompt="你是一个有用的AI助手,能够使用提供的工具来完成任务"
)

# 调用代理
result = agent.invoke({
    "messages": [
        {"role": "user", "content": "请计算半径为5的圆的面积"}
    ]
})

print(result)

7.2 代理类型详解

类型1:ReAct Agent(推荐)

# ReAct = Reasoning + Acting
# 代理会交替进行推理和工具调用

agent = create_agent(
    model=model,
    tools=tools,
    system_prompt="""
    你是一个问题解决助手。
    
    对于每个问题,你应该:
    1. 思考问题的关键点
    2. 列出可以使用的工具
    3. 逐步调用工具获取信息
    4. 基于结果进行进一步分析
    5. 给出最终答案
    """
)

# 使用
result = agent.invoke({
    "messages": [
        {"role": "user", "content": "请计算三个数字的阶乘:3、5、7"}
    ]
})

类型2:Structured Agent(结构化输出)

from pydantic import BaseModel

class AgentResponse(BaseModel):
    """代理的结构化响应"""
    thought: str      # 思考过程
    action: str       # 采取的行动
    result: str       # 结果
    final_answer: str # 最终答案

# 代理可以配置返回结构化输出
agent = create_agent(
    model=model,
    tools=tools,
    system_prompt="使用提供的工具完成任务,并以结构化格式返回结果"
)

7.3 工具调用链

from langchain.agents import tool_calls_to_messages

# 当模型调用工具时的处理流程
def process_tool_call(tool_call):
    """处理工具调用"""
    tool_name = tool_call["name"]
    tool_args = tool_call["args"]
    
    # 查找并执行工具
    tool = next((t for t in tools if t.name == tool_name), None)
    if tool:
        result = tool.invoke(tool_args)
        return result
    else:
        return f"工具 '{tool_name}' 未找到"

# 示例流程
messages = [
    {"role": "user", "content": "今天杭州的天气怎么样?"}
]

# 1. 第一次调用:模型生成工具调用
response = model.invoke(messages)

# 2. 如果模型生成了工具调用
if response.tool_calls:
    for tool_call in response.tool_calls:
        tool_result = process_tool_call(tool_call)
        
        # 3. 将工具结果加入消息
        messages.extend([
            {"role": "assistant", "content": response.content},
            {"role": "tool", "content": tool_result}
        ])
    
    # 4. 再次调用模型生成最终回答
    final_response = model.invoke(messages)
    print(final_response.content)

7.4 代理状态管理

from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages

class AgentState(TypedDict):
    """代理状态"""
    messages: Annotated[list, add_messages]
    tool_calls: list
    current_tool: str

# 构建状态图
def should_continue(state):
    """判断是否继续执行"""
    return "CONTINUE" if state["tool_calls"] else "STOP"

graph = StateGraph(AgentState)

# 定义节点
def process_messages(state):
    """处理消息节点"""
    response = model.invoke(state["messages"])
    return {
        "messages": [response],
        "tool_calls": getattr(response, 'tool_calls', [])
    }

def execute_tools(state):
    """执行工具节点"""
    results = []
    for tool_call in state["tool_calls"]:
        result = process_tool_call(tool_call)
        results.append(result)
    return {"tool_calls": results}

# 添加节点
graph.add_node("process", process_messages)
graph.add_node("tools", execute_tools)

# 添加边
graph.add_edge(START, "process")
graph.add_conditional_edges(
    "process",
    should_continue,
    {"CONTINUE": "tools", "STOP": END}
)
graph.add_edge("tools", "process")

# 编译图
agent = graph.compile()

7.5 代理中间件

from langchain.agents.middleware import AgentMiddleware

class LoggingMiddleware(AgentMiddleware):
    """记录所有代理活动的中间件"""
    
    def before_agent(self, state):
        print(f"[开始] 消息数量: {len(state.get('messages', []))}")
    
    def after_agent(self, state):
        print(f"[结束] 生成了工具调用: {len(state.get('tool_calls', []))}")

class RateLimitMiddleware(AgentMiddleware):
    """限制工具调用频率"""
    
    def __init__(self, max_calls: int = 10):
        self.max_calls = max_calls
        self.call_count = 0
    
    def wrap_tool_call(self, tool_call, handler):
        if self.call_count >= self.max_calls:
            return {"error": f"已达到最大工具调用限制 ({self.max_calls})"}
        self.call_count += 1
        return handler(tool_call)

class SensitiveOperationMiddleware(AgentMiddleware):
    """需要人工批准的敏感操作"""
    
    def wrap_tool_call(self, tool_call, handler):
        sensitive_tools = ["delete_database", "send_email", "withdraw_funds"]
        if tool_call["name"] in sensitive_tools:
            # 在实际应用中这里应该发送批准请求
            print(f"[需要批准] 敏感操作: {tool_call['name']}")
            # 等待批准或返回错误
            return {"status": "pending_approval"}
        return handler(tool_call)

# 创建带中间件的代理
agent = create_agent(
    model=model,
    tools=tools,
    middleware=[
        LoggingMiddleware(),
        RateLimitMiddleware(max_calls=20),
        SensitiveOperationMiddleware()
    ]
)

第八部分:RAG检索增强

8.1 向量存储与嵌入

from langchain.embeddings import init_embeddings
from langchain.vectorstores import InMemoryVectorStore

# 初始化嵌入模型
embeddings = init_embeddings("openai")

# 创建向量存储
vector_store = InMemoryVectorStore(
    embedding_function=embeddings.embed_query
)

# 添加文档
documents = [
    "LangChain是一个用于构建LLM应用的框架",
    "代理可以使用工具来完成复杂任务",
    "RAG结合了检索和生成的能力",
    "提示工程对LLM应用很重要"
]

# 添加文档到向量存储
from langchain_core.documents import Document

docs = [Document(page_content=doc) for doc in documents]
vector_store.add_documents(docs)

# 搜索相似文档
results = vector_store.similarity_search("什么是LangChain", k=2)
for doc in results:
    print(doc.page_content)

8.2 检索链

from langchain.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough

# 构建RAG链
template = """
基于以下上下文回答问题。

上下文:
{context}

问题:{question}

答案:
"""

prompt = ChatPromptTemplate.from_template(template)
model = init_chat_model("gpt-4o-mini")

# 创建检索链
retriever = vector_store.as_retriever(search_kwargs={"k": 2})

rag_chain = (
    RunnableParallel(
        context=retriever,
        question=RunnablePassthrough()
    )
    | {
        "context": lambda x: "\n".join([doc.page_content for doc in x["context"]]),
        "question": lambda x: x["question"]
    }
    | prompt
    | model
    | StrOutputParser()
)

# 使用
result = rag_chain.invoke("请解释RAG是什么")
print(result)

8.3 文档加载与处理

from langchain_community.document_loaders import WebBaseLoader, PDFPlumberLoader
from langchain.text_splitters import RecursiveCharacterTextSplitter

# 从网页加载
loader = WebBaseLoader("https://example.com")
documents = loader.load()

# 从PDF加载
pdf_loader = PDFPlumberLoader("document.pdf")
documents = pdf_loader.load()

# 文本分割
splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,      # 每个块的字符数
    chunk_overlap=50,    # 块之间的重叠
    separators=["\n\n", "\n", " ", ""]
)

chunks = splitter.split_documents(documents)

# 添加到向量存储
for chunk in chunks:
    vector_store.add_documents([chunk])

8.4 混合检索

from langchain.retrievers import BM25Retriever, EnsembleRetriever

# BM25检索器(关键词搜索)
bm25_retriever = BM25Retriever.from_documents(chunks)

# 向量检索器
vector_retriever = vector_store.as_retriever()

# 集合检索器(结合两种方法)
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.5, 0.5]  # 权重
)

# 使用
results = ensemble_retriever.get_relevant_documents("LangChain的核心特性")

第九部分:详细应用案例

案例1:智能个人助手

from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
from langchain.prompts import ChatPromptTemplate
from langchain.memory import ConversationBufferMemory
from langchain.tools import tool
from datetime import datetime

# 定义工具
@tool
def get_current_time() -> str:
    """获取当前时间"""
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")

@tool
def set_reminder(task: str, time: str) -> str:
    """设置提醒"""
    return f"已设置提醒:{time}提醒我'{task}'"

@tool
def search_knowledge_base(query: str) -> str:
    """搜索知识库"""
    kb = {
        "Python": "Python是一种高级编程语言",
        "AI": "人工智能是模拟人类智能的技术",
        "机器学习": "机器学习是AI的一个分支"
    }
    return kb.get(query, f"未找到关于'{query}'的信息")

# 创建助手
model = init_chat_model("gpt-4o-mini")
memory = ConversationBufferMemory(return_messages=True)

assistant = create_agent(
    model=model,
    tools=[get_current_time, set_reminder, search_knowledge_base],
    system_prompt="""
    你是一个有用的个人助手。你能够:
    1. 告诉用户当前时间
    2. 帮助设置提醒
    3. 回答关于各个主题的问题
    
    始终友好和专业,记住之前的对话内容。
    """
)

# 交互示例
messages = [
    {"role": "user", "content": "现在几点了?"}
]
response = assistant.invoke({"messages": messages})
print("助手:", response)

messages.append({"role": "assistant", "content": response})
messages.append({"role": "user", "content": "帮我设置一个明天10点的提醒,提醒我开会"})
response = assistant.invoke({"messages": messages})
print("助手:", response)

案例2:代码审查机器人

from langchain.chat_models import init_chat_model
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field

class CodeReview(BaseModel):
    """代码审查结果"""
    issues: list = Field(description="发现的问题列表")
    severity: str = Field(description="严重程度: critical, high, medium, low")
    improvements: list = Field(description="改进建议")
    score: int = Field(description="代码质量评分 0-100")

# 构建代码审查链
template = """
请审查以下代码,找出潜在问题并提供改进建议。

代码:
```python
{code}

语言:{language} 焦点:{focus}

请以JSON格式返回审查结果。 """

prompt = ChatPromptTemplate.from_template(template) model = init_chat_model("gpt-4o") parser = JsonOutputParser(pydantic_object=CodeReview)

code_reviewer = prompt | model | parser

使用

code = """ def calculate_total(items): total = 0 for item in items: total = total + item['price'] * item['quantity'] return total """

result = code_reviewer.invoke({ "code": code, "language": "Python", "focus": "性能和最佳实践" })

print("代码审查结果:") for issue in result["issues"]: print(f"- {issue}") print(f"评分: {result['score']}/100")


## 案例3:文档问答系统

```python
from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitters import RecursiveCharacterTextSplitter
from langchain.embeddings import init_embeddings
from langchain.vectorstores import InMemoryVectorStore
from langchain.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

# 加载文档
loader = DirectoryLoader(
    "./docs",
    glob="*.md",
    loader_cls=TextLoader
)
documents = loader.load()

# 分割文档
splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=100
)
chunks = splitter.split_documents(documents)

# 创建向量存储
embeddings = init_embeddings("openai")
vector_store = InMemoryVectorStore(
    embedding_function=embeddings.embed_query
)
vector_store.add_documents(chunks)

# 构建问答系统
retriever = vector_store.as_retriever(search_kwargs={"k": 3})

template = """
使用以下文档片段回答问题。如果无法从文档中找到答案,请说"我不知道"。

文档:
{context}

问题:{question}

答案:"""

prompt = ChatPromptTemplate.from_template(template)
model = init_chat_model("gpt-4o")

qa_system = (
    {
        "context": retriever | (lambda docs: "\n\n".join([d.page_content for d in docs])),
        "question": RunnablePassthrough()
    }
    | prompt
    | model
    | StrOutputParser()
)

# 使用
answer = qa_system.invoke("什么是LangChain?")
print(answer)

案例4:多步骤工作流自动化

from langchain.agents import create_agent
from langchain.tools import tool
from langchain.chat_models import init_chat_model
from langgraph.graph import StateGraph, START, END
from typing import Annotated, TypedDict
from langgraph.graph.message import add_messages

class WorkflowState(TypedDict):
    """工作流状态"""
    messages: Annotated[list, add_messages]
    workflow_step: int
    data: dict

# 定义工作流步骤对应的工具
@tool
def validate_input(data: str) -> str:
    """验证用户输入"""
    if len(data) < 10:
        return "输入太短,请至少输入10个字符"
    return "输入有效"

@tool
def process_data(data: str) -> str:
    """处理数据"""
    return f"已处理: {data.upper()}"

@tool
def generate_report(processed_data: str) -> str:
    """生成报告"""
    return f"报告:\n{processed_data}\n生成时间:{datetime.now()}"

@tool
def send_notification(report: str) -> str:
    """发送通知"""
    return "报告已发送给相关人员"

# 构建工作流
def validation_step(state):
    """第1步:验证"""
    response = model.invoke({
        "messages": state["messages"] + [
            {"role": "system", "content": "请验证提供的数据"}
        ]
    })
    return {"messages": [response], "workflow_step": 2, "data": {"raw": state["messages"][-1]["content"]}}

def processing_step(state):
    """第2步:处理"""
    response = model.invoke({
        "messages": state["messages"] + [
            {"role": "system", "content": "请处理验证后的数据"}
        ]
    })
    return {"messages": [response], "workflow_step": 3}

def reporting_step(state):
    """第3步:生成报告"""
    response = model.invoke({
        "messages": state["messages"] + [
            {"role": "system", "content": "请基于处理结果生成报告"}
        ]
    })
    return {"messages": [response], "workflow_step": 4}

def notification_step(state):
    """第4步:发送通知"""
    return {"messages": state["messages"], "workflow_step": 5}

# 构建图
model = init_chat_model("gpt-4o-mini")
graph = StateGraph(WorkflowState)

graph.add_node("validation", validation_step)
graph.add_node("processing", processing_step)
graph.add_node("reporting", reporting_step)
graph.add_node("notification", notification_step)

graph.add_edge(START, "validation")
graph.add_edge("validation", "processing")
graph.add_edge("processing", "reporting")
graph.add_edge("reporting", "notification")
graph.add_edge("notification", END)

workflow = graph.compile()

# 执行工作流
initial_state = {
    "messages": [{"role": "user", "content": "请处理这个数据:这是一个关于销售数据的重要文档"}],
    "workflow_step": 1,
    "data": {}
}

result = workflow.invoke(initial_state)

案例5:实时数据分析与报告

from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
from langchain.tools import tool
import json
from datetime import datetime, timedelta
import random

# 定义数据工具
@tool
def fetch_sales_data(date_range: str) -> str:
    """获取销售数据"""
    data = {
        "total_sales": random.randint(50000, 100000),
        "orders": random.randint(100, 500),
        "customers": random.randint(50, 200),
        "average_order_value": random.randint(200, 800)
    }
    return json.dumps(data)

@tool
def fetch_market_trends(category: str) -> str:
    """获取市场趋势"""
    trends = {
        "growth_rate": f"{random.randint(5, 20)}%",
        "market_share": f"{random.randint(10, 40)}%",
        "competitor_count": random.randint(5, 20)
    }
    return json.dumps(trends)

@tool
def generate_insights(data: str) -> str:
    """生成洞察"""
    return f"基于数据的分析洞察:\n- 销售趋势向上\n- 客户满意度较高\n- 竞争压力适中"

@tool
def create_chart_url(chart_type: str, data: str) -> str:
    """创建图表"""
    return f"chart.png?type={chart_type}&data={data[:20]}..."

# 创建数据分析代理
model = init_chat_model("gpt-4o")

analyst = create_agent(
    model=model,
    tools=[fetch_sales_data, fetch_market_trends, generate_insights, create_chart_url],
    system_prompt="""
    你是一个数据分析专家。你的任务是:
    1. 获取最新的销售和市场数据
    2. 分析数据中的趋势
    3. 生成可视化图表
    4. 提供可行性建议
    
    使用提供的工具完成分析,并生成详细的报告。
    """
)

# 执行分析
result = analyst.invoke({
    "messages": [
        {"role": "user", "content": "请生成一份本周销售分析报告,包括趋势分析和图表"}
    ]
})

print("分析报告:")
print(result)

第十部分:高级特性

10.1 流式处理与实时输出

from langchain.chat_models import init_chat_model
from langchain.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template(
    "以故事的形式讲述{topic}"
)
model = init_chat_model("gpt-4o")
chain = prompt | model

# 流式输出
print("开始讲述...")
for chunk in chain.stream({"topic": "AI的未来"}):
    print(chunk.content, end="", flush=True)
print("\n讲述完毕")

# 异步流式处理
import asyncio

async def async_stream():
    async for chunk in chain.astream({"topic": "区块链技术"}):
        print(chunk.content, end="", flush=True)

asyncio.run(async_stream())

# 批量处理
topics = ["人工智能", "机器学习", "深度学习"]
results = chain.batch([{"topic": t} for t in topics])

# 并行处理
import concurrent.futures

with concurrent.futures.ThreadPoolExecutor() as executor:
    futures = [
        executor.submit(chain.invoke, {"topic": t})
        for t in topics
    ]
    results = [f.result() for f in futures]

10.2 对话持久化

from langgraph.checkpoint.sqlite import SqliteSaver

# 使用SQLite保存对话历史
checkpointer = SqliteSaver.from_conn_string(":memory:")

# 创建支持持久化的代理
agent = create_agent(
    model=model,
    tools=tools,
    checkpointer=checkpointer
)

# 同一个用户的对话可以跨会话保持
user_id = "user_123"
session_1 = agent.invoke(
    {"messages": [{"role": "user", "content": "我叫张三"}]},
    config={"configurable": {"thread_id": user_id}}
)

# 后续对话会记住之前的信息
session_2 = agent.invoke(
    {"messages": [{"role": "user", "content": "你记得我是谁吗?"}]},
    config={"configurable": {"thread_id": user_id}}
)

# agent会回答"你是张三"

10.3 自定义中间件

from langchain.agents.middleware import AgentMiddleware
from langchain.tools import ToolException
import time

class PerformanceMonitorMiddleware(AgentMiddleware):
    """监控代理性能"""
    
    def __init__(self):
        self.metrics = []
    
    def before_agent(self, state):
        state["start_time"] = time.time()
    
    def after_agent(self, state):
        elapsed = time.time() - state.get("start_time", time.time())
        self.metrics.append({
            "execution_time": elapsed,
            "tool_calls": len(state.get("tool_calls", []))
        })
        print(f"执行时间: {elapsed:.2f}秒")
    
    def get_metrics(self):
        return self.metrics

class DataValidationMiddleware(AgentMiddleware):
    """验证工具输入和输出"""
    
    def wrap_tool_call(self, tool_call, handler):
        # 验证输入
        args = tool_call.get("args", {})
        if not args:
            raise ToolException("工具调用缺少参数")
        
        # 执行工具
        result = handler(tool_call)
        
        # 验证输出
        if result is None:
            raise ToolException("工具返回了None")
        
        return result

class ContextEnrichmentMiddleware(AgentMiddleware):
    """丰富执行上下文"""
    
    def before_agent(self, state):
        # 添加元数据
        state["execution_id"] = f"exec_{int(time.time() * 1000)}"
        state["metadata"] = {
            "timestamp": datetime.now().isoformat(),
            "version": "1.0"
        }

monitor = PerformanceMonitorMiddleware()
agent = create_agent(
    model=model,
    tools=tools,
    middleware=[
        monitor,
        DataValidationMiddleware(),
        ContextEnrichmentMiddleware()
    ]
)

10.4 成本优化

from langchain.chat_models import init_chat_model
from langchain.callbacks import get_openai_callback

# 方法1:使用回调追踪成本
def analyze_with_cost_tracking():
    with get_openai_callback() as cb:
        # 执行操作
        chain = prompt | model
        result = chain.invoke({"topic": "AI"})
        
        print(f"总Token数: {cb.total_tokens}")
        print(f"提示Token: {cb.prompt_tokens}")
        print(f"完成Token: {cb.completion_tokens}")
        print(f"成本: ${cb.total_cost}")

# 方法2:智能模型选择
def select_model_by_complexity(task_complexity: str):
    """根据任务复杂度选择不同的模型"""
    if task_complexity == "simple":
        return init_chat_model("gpt-4o-mini")  # 更便宜
    elif task_complexity == "medium":
        return init_chat_model("gpt-4")
    else:
        return init_chat_model("gpt-4-turbo")  # 最强大

# 方法3:批量处理以减少API调用
def batch_process(queries, batch_size=10):
    """批量处理减少往返次数"""
    results = []
    for i in range(0, len(queries), batch_size):
        batch = queries[i:i+batch_size]
        result = chain.batch([{"topic": q} for q in batch])
        results.extend(result)
    return results

# 方法4:缓存优化
from langchain.cache import InMemoryCache
from langchain.globals import set_llm_cache

# 启用缓存
set_llm_cache(InMemoryCache())

# 相同的请求会使用缓存结果
result1 = model.invoke("什么是AI?")
result2 = model.invoke("什么是AI?")  # 使用缓存,不消耗Token

10.5 监控与调试

import logging
from langsmith import Client

# 设置日志
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

# 启用LangSmith追踪
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_PROJECT"] = "my-project"

# 自定义回调用于监控
from langchain_core.callbacks import BaseCallbackHandler

class DebugCallback(BaseCallbackHandler):
    """调试回调"""
    
    def on_llm_start(self, serialized, prompts, **kwargs):
        logger.debug(f"LLM开始,提示: {prompts[0][:50]}...")
    
    def on_tool_start(self, serialized, input_str, **kwargs):
        logger.debug(f"工具启动: {serialized['name']}")
    
    def on_tool_end(self, output, **kwargs):
        logger.debug(f"工具完成,输出长度: {len(str(output))}")
    
    def on_chain_error(self, error, **kwargs):
        logger.error(f"链错误: {error}")

# 使用回调
chain = prompt | model
result = chain.invoke(
    {"topic": "AI"},
    config={"callbacks": [DebugCallback()]}
)

总结

LangChain 1.2.0是构建AI应用的强大框架,核心优势包括:

  1. 统一API - 无论使用哪个LLM,接口保持一致
  2. 模块化设计 - 灵活组装各种功能模块
  3. 生产就绪 - 包含监控、日志、错误处理等企业级特性
  4. 丰富集成 - 集成200+外部服务
  5. 中间件系统 - 实现细粒度的流程控制

掌握本教程中的所有概念和案例,您就能构建从简单的聊天应用到复杂的多代理系统的各种AI应用。