Skip to content

章节4:LangChain应用开发


学习目标

  • 掌握 LangChain 核心组件:Model / Prompt / Chain
  • 理解 LCEL 表达式语言(管道式链式调用)
  • 掌握 Memory 记忆系统(BufferMemory / SummaryMemory)
  • 学会 Tools 工具调用与 Function Calling
  • 熟悉 Retriever 检索器与文档加载器

核心知识点

4.1 核心组件:Model / Prompt / Chain

定义

LangChain 三大核心抽象:

组件作用常用类
Model封装 LLM 调用ChatOpenAI, OllamaLLM
Prompt管理提示词模板PromptTemplate, ChatPromptTemplate
Chain串联多个组件LLMChain, SequentialChain

代码示例:Model + Prompt + Chain 基础用法

python
# pip install langchain langchain-openai

from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain

# 1. Model —— 初始化模型
llm = ChatOpenAI(
    model="gpt-4o",
    temperature=0.7,
    api_key="your-api-key"
)

# 2. Prompt —— 定义模板
prompt = PromptTemplate(
    input_variables=["topic", "style"],
    template="请以{style}的风格写一段关于{topic}的简短介绍,不超过100字。"
)

# 3. Chain —— 串联
chain = LLMChain(llm=llm, prompt=prompt)

# 4. 执行
result = chain.invoke({"topic": "人工智能", "style": "幽默"})
print(result["text"])
python
# ChatPromptTemplate —— 支持多角色消息
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个{role},擅长{field}方面的咨询。"),
    ("user", "{question}"),
    MessagesPlaceholder(variable_name="history"),  # 对话历史占位
])

chain = chat_prompt | llm
result = chain.invoke({
    "role": "资深算法工程师",
    "field": "自然语言处理",
    "question": "为什么Transformer比RNN更适合处理长文本?",
    "history": []
})
print(result.content)

4.2 LCEL 表达式语言

定义

LCEL(LangChain Expression Language):使用 | 管道操作符将组件串联成执行链,类似 Unix 管道或函数式编程的组合风格。

输入 → PromptTemplate → LLM → OutputParser → 输出
       │         │        │        │
       └─────────┴────────┴────────┘
               用 | 连接

代码示例:LCEL 链式调用

python
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o")

# 基础 LCEL 链
prompt = PromptTemplate.from_template("用{language}写一首关于{subject}的诗,4行。")
chain = prompt | llm | StrOutputParser()

result = chain.invoke({"language": "中文", "subject": "程序员"})
print(result)
python
# 复杂 LCEL 链:分支 + 合并
from operator import itemgetter

# 两个并行的翻译链
en_prompt = PromptTemplate.from_template("将以下内容翻译为英文:{text}")
jp_prompt = PromptTemplate.from_template("将以下内容翻译为日文:{text}")

en_chain = en_prompt | llm | StrOutputParser()
jp_chain = jp_prompt | llm | StrOutputParser()

# 合并链
from langchain_core.runnables import RunnableParallel

parallel_chain = RunnableParallel(
    english=en_chain,
    japanese=jp_chain
)

# 最终格式化
format_prompt = PromptTemplate.from_template(
    "原文:{text}\n\n英文:{english}\n日文:{japanese}"
)
format_chain = format_prompt | llm | StrOutputParser()

# 完整 LCEL 管道
full_chain = {
    "text": itemgetter("text"),  # 透传原始输入
    "english": en_chain,
    "japanese": jp_chain
} | format_chain

result = full_chain.invoke({"text": "你好,今天天气真好!"})
print(result)

4.3 Memory 记忆系统

定义

Memory 让 Chain 具备"记忆"能力,在多轮对话中记住之前的交互内容。

记忆类型原理适用场景
ConversationBufferMemory完整保存所有对话历史短期对话
ConversationSummaryMemory定期总结压缩历史长对话
ConversationBufferWindowMemory只保留最近 K 轮控制 Token 消耗
VectorStoreRetrieverMemory按相关性检索历史超长会话

代码示例:对话记忆

python
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o")

# 缓冲区记忆
memory = ConversationBufferMemory(return_messages=True)

conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True  # 输出内部步骤
)

# 多轮对话
print(conversation.predict(input="你好!我叫张三。"))
print(conversation.predict(input="我是Python开发者。"))
print(conversation.predict(input="你还记得我叫什么名字吗?"))  # 应该记得
python
# 摘要记忆 —— 节省 Token
from langchain.memory import ConversationSummaryMemory

summary_memory = ConversationSummaryMemory(
    llm=llm,
    max_token_limit=200  # 摘要最大 Token 数
)

# 长对话时,系统会自动将历史压缩为摘要
conv_with_summary = ConversationChain(
    llm=llm,
    memory=summary_memory,
    verbose=True
)

4.4 Tools 工具调用与 Function Calling

定义

Tool / Function Calling 让 LLM 能够调用外部工具(搜索、计算、数据库查询等),极大地扩展了模型的能力边界。

用户请求 "北京市今天的天气怎么样?"


LLM 判断需要调用天气 API


Tool: get_weather("北京") → "晴,22-28°C"


LLM 用工具结果生成最终回答

代码示例:自定义工具与 Function Calling

python
from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain.prompts import ChatPromptTemplate

# 1. 定义工具
@tool
def calculate(expression: str) -> str:
    """计算数学表达式的结果"""
    try:
        result = eval(expression, {"__builtins__": {}}, {})
        return f"计算结果: {result}"
    except Exception as e:
        return f"计算错误: {e}"

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

# 2. 创建 Agent
llm = ChatOpenAI(model="gpt-4o")
tools = [calculate, get_current_time]

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个智能助手,可以使用工具来回答问题。"),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 3. 执行
agent_executor.invoke({"input": "计算 123 × 456 + 789 等于多少,并告诉我现在几点了?"})

4.5 Retriever 检索器与文档加载

定义

Document Loader(文档加载器):从各种源加载文档(PDF、网页、CSV、数据库)。

Retriever(检索器):根据查询从文档集合中检索相关片段,是 RAG 与 LangChain 的桥梁。

代码示例:文档加载与检索

python
# pip install langchain-community pypdf chromadb

# 文档加载
from langchain_community.document_loaders import PyPDFLoader, TextLoader, WebBaseLoader

# 加载 PDF
# loader = PyPDFLoader("document.pdf")
# documents = loader.load()

# 加载网页
# web_loader = WebBaseLoader("https://example.com")
# web_docs = web_loader.load()

# 加载文本文件
text_loader = TextLoader("notes.txt", encoding="utf-8")
text_docs = text_loader.load()
python
# 向量检索器 —— ChromaDB + LangChain 集成
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 1. 分块
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
# chunks = splitter.split_documents(documents)

# 2. 创建向量存储
# vector_store = Chroma.from_documents(
#     documents=chunks,
#     embedding=OpenAIEmbeddings(),
#     persist_directory="./chroma_langchain"
# )

# 3. 创建检索器
# retriever = vector_store.as_retriever(
#     search_type="similarity",
#     search_kwargs={"k": 3}
# )

# 4. 使用检索器
# results = retriever.invoke("你的问题")
# for doc in results:
#     print(f"[{doc.metadata.get('source', 'unknown')}] {doc.page_content[:100]}")
python
# RetrievalQA Chain —— 开箱即用的 RAG 链
from langchain.chains import RetrievalQA

# qa_chain = RetrievalQA.from_chain_type(
#     llm=llm,
#     chain_type="stuff",  # stuff | map_reduce | refine | map_rerank
#     retriever=retriever,
#     return_source_documents=True
# )

# response = qa_chain.invoke({"query": "文档的核心内容是什么?"})
# print(response["result"])
# print("来源文档:", [doc.metadata["source"] for doc in response["source_documents"]])

小结与练习

小结

  • LangChain 的三大核心抽象 Model / Prompt / Chain 构成了应用开发的基础
  • LCEL 表达式语言用 | 管道符实现简洁的链式组合,是 LangChain 推荐的开发范式
  • Memory 系统让 LLM 应用具备多轮对话能力,BufferMemory 和 SummaryMemory 覆盖不同场景
  • Tool / Function Calling 让 LLM 可以调用外部工具,能力边界大幅扩展
  • Retriever + Document Loader + Vector Store 是构建 RAG 应用的开发基础

练习题

  1. 基础题:使用 ChatPromptTemplate + ChatOpenAI + StrOutputParser 构建一个 LCEL 链,实现"翻译+解释"功能。
  2. 实践题:构建一个带有 ConversationBufferMemory 的聊天机器人,让它能记住用户的名字和偏好,并在后续对话中调用。
  3. 实践题:实现一个自定义 Tool(如查询天气或计算器),并用 AgentExecutor 让 LLM 自动调用它。
  4. 综合题:结合 Document Loader + Text Splitter + ChromaDB + RetrievalQA,构建一个完整的本地文档问答系统。

Python 学习资料