LangChain 开发:构建基于大型语言模型(LLM)的应用

本文将全面解析 LangChain 框架,从核心概念、环境搭建到高级应用开发,通过 7 个精心设计的实战案例,一步步教你如何利用 LangChain 释放大型语言模型(LLM)的全部潜能,构建强大的、数据感知的、具备代理能力的 AI 应用。


在这里插入图片描述

导语

大型语言模型(LLM),如 GPT-4、Claude 等,展现了惊人的自然语言处理能力。然而,将这些强大的模型真正落地到具体的应用场景中,却面临诸多挑战:如何让 LLM 连接外部数据?如何让它拥有记忆?如何让它调用 API 或工具?如何编排复杂的任务流?

LangChain 正是为解决这些问题而生的开源框架。它提供了一套完整的工具、组件和接口,使开发者能够轻松地将 LLM 与外部世界连接起来,构建端到端的、功能丰富的 AI 应用。本文将通过一系列实战案例,带你进入 LangChain 的世界。


一、环境准备与核心概念

在开始之前,需要安装 LangChain 及其相关的包。LangChain 已经模块化,核心功能、社区组件和特定模型(如 OpenAI)需要分开安装。

# LangChain 核心包
pip install langchain-core

# LangChain 社区包,包含大量第三方集成
pip install langchain-community

# OpenAI 模型接口
pip install langchain-openai

# 用于 RAG 案例的包
pip install faiss-cpu beautifulsoup4

# 用于 Agent 案例的包
pip install duckduckgo-search

⚠️ 设置 API Key:在使用 OpenAI 等商业模型时,需要设置环境变量。

export OPENAI_API_KEY="your-api-key"

LangChain 核心概念

  • Models: 语言模型,LangChain 的核心,如 ChatOpenAI
  • Prompts: 提示词模板,用于动态生成输入给模型的指令。
  • Chains: 链,将多个组件(甚至其他链)按顺序组合起来,实现复杂逻辑。LangChain 表达式语言(LCEL)是构建链的标准方式。
  • RAG (Retrieval-Augmented Generation): 检索增强生成,通过从外部数据源检索信息来增强 LLM 的回答,解决知识陈旧和幻觉问题。
  • Agents: 代理,让 LLM 具备思考和决策能力,动态选择并使用工具(如搜索、计算)来完成任务。

二、案例一:与 LLM 的第一次对话

这是 LangChain 的 “Hello, World!”。我们将使用提示词模板 PromptTemplate 来格式化输入,并调用 ChatOpenAI 模型。

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 1. 初始化模型
# model_name 可以替换为 "gpt-4", "gpt-3.5-turbo" 等
llm = ChatOpenAI(model_name="gpt-4o")

# 2. 创建提示词模板
# 模板中的 {input} 是一个占位符,后续将被实际输入替换
prompt = ChatPromptTemplate.from_template("请给我讲一个关于 {topic} 的笑话。")

# 3. 使用 LangChain 表达式语言 (LCEL) 构建链
# 这里的 "|" 符号是 LCEL 的语法,表示将前一个组件的输出作为后一个组件的输入
chain = prompt | llm

# 4. 调用链
# invoke 方法用于执行链,并传入输入变量
response = chain.invoke({"topic": "程序员"})

print(response.content)

结果分析:这个简单的链条清晰地展示了 LangChain 的工作流:Prompt -> Model -> Output。LCEL 的 | 管道操作符让链的定义直观而优雅。


三、案例二:使用输出解析器规范输出

LLM 的输出通常是字符串,但在应用中我们常常需要结构化的数据(如 JSON、CSV)。输出解析器(Output Parsers)就是用来解决这个问题的。

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

# 1. 创建提示词模板
prompt = ChatPromptTemplate.from_template("你是一位专业的翻译家,请将以下句子翻译成 {language}:\n\n{sentence}")

# 2. 创建模型
model = ChatOpenAI(model="gpt-4o", temperature=0)

# 3. 创建输出解析器
# StrOutputParser 是最简单的解析器,它将模型的输出(ChatMessage)解析为字符串
output_parser = StrOutputParser()

# 4. 使用 LCEL 组合链
chain = prompt | model | output_parser

# 5. 调用链
result = chain.invoke({
    "language": "法语",
    "sentence": "Programming is a superpower."
})

print(result)

结果分析:通过在链的末尾添加 StrOutputParser,我们得到的 result 直接就是一个字符串,而不是一个包含 contentresponse_metadata 等信息的 AIMessage 对象,这让后续处理更加方便。LangChain 还提供了更强大的 PydanticOutputParserJsonOutputParser 等,可以自动将输出解析为 Python 对象或 JSON。


四、案例三:构建知识库问答 (RAG)

RAG 是 LangChain 最核心的应用场景。它通过“检索”和“生成”两个步骤,让 LLM 能够回答关于特定知识库的问题。

流程

  1. Load: 使用 DocumentLoader 加载文档。
  2. Split: 使用 TextSplitter 将长文档切分为小块。
  3. Embed: 使用 Embeddings 模型将文本块转换为向量。
  4. Store: 将向量化的文本存储在 VectorStore (如 FAISS) 中。
  5. Retrieve: 当用户提问时,从 VectorStore 中检索最相关的文本块。
  6. Generate: 将原始问题和检索到的文本块一起作为上下文,交给 LLM 生成最终答案。
import os
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_core.output_parsers import StrOutputParser
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 确保已设置 OPENAI_API_KEY
# os.environ["OPENAI_API_KEY"] = "your-api-key"

# 1. 加载文档
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
docs = loader.load()

# 2. 分割文本
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)

# 3. 创建向量存储
# OpenAIEmbeddings 用于将文本转换为向量
# FAISS 是一个高效的向量相似性搜索库
vectorstore = FAISS.from_documents(documents=splits, embedding=OpenAIEmbeddings())

# 4. 创建检索器
retriever = vectorstore.as_retriever()

# 5. 定义 RAG 提示词模板
template = """
Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

# 6. 定义 RAG 链
model = ChatOpenAI(model="gpt-4o")

# RunnableParallel 允许并行执行,这里并行获取 context 和 question
# RunnablePassthrough() 表示直接传递输入
chain = (
    RunnableParallel({"context": retriever, "question": RunnablePassthrough()})
    | prompt
    | model
    | StrOutputParser()
)

# 7. 提问
question = "What are the essential modules for a LLM-powered autonomous agent system?"
result = chain.invoke(question)

print(result)

结果分析:RAG 链成功地从指定的网页内容中找到了答案,而不是依赖 LLM 的内部知识。这极大地提高了答案的准确性和时效性,并有效降低了“幻觉”现象。


五、案例四:为对话添加记忆

为了让 LLM 能够理解对话的上下文,我们需要为其添加记忆(Memory)功能。ConversationBufferMemory 是最常用的记忆类型之一。

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

# 初始化模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)

# 初始化带有记忆的对话链
# verbose=True 可以打印出链的详细思考过程
conversation = ConversationChain(
    llm=llm,
    memory=ConversationBufferMemory(),
    verbose=True
)

# 第一轮对话
response1 = conversation.predict(input="你好,我叫马可。")
print(response1)

# 第二轮对话
response2 = conversation.predict(input="我叫什么名字?")
print(response2)

结果分析:在 verbose 输出中,可以看到第二轮对话的 Prompt 中包含了第一轮的对话历史。这使得 LLM 能够轻松回答“我叫什么名字?”这类依赖上下文的问题。


六、案例五:构建使用工具的 Agent

Agent(代理)是 LangChain 中最令人兴奋的概念。它让 LLM 拥有了“思考-行动”循环的能力,可以根据用户的请求,自主选择并使用工具来完成任务。

from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_community.tools.ddg_search import DuckDuckGoSearchRun
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# 1. 定义工具
# 这里使用 DuckDuckGo 搜索引擎作为工具
tools = [DuckDuckGoSearchRun()]

# 2. 定义提示词模板
# prompt 需要包含 {agent_scratchpad} 占位符,用于记录 agent 的思考过程
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

# 3. 初始化模型并绑定工具
llm = ChatOpenAI(model="gpt-4o", temperature=0)
llm_with_tools = llm.bind_tools(tools)

# 4. 创建 Agent
# create_tool_calling_agent 负责将 LLM 的输出解析为工具调用
# AgentExecutor 负责执行工具调用并将结果返回给 LLM
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 5. 运行 Agent
# LLM 无法直接回答 2024 年世界杯冠军,因为它没有实时信息
# Agent 会决定使用搜索工具来查找答案
response = agent_executor.invoke({
    "input": "2024年欧洲杯的冠军是哪个国家?"
})

print(response["output"])

结果分析verbose 输出展示了 Agent 的完整思考链:它首先意识到自己不知道答案,然后决定调用 duckduckgo_search 工具,并将问题作为参数。得到搜索结果后,它再次调用 LLM,基于搜索结果生成最终答案。


七、案例六:为 Agent 创建自定义工具

除了 LangChain 提供的内置工具,我们还可以轻松创建自定义工具,扩展 Agent 的能力。

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

# 1. 定义自定义工具
@tool
def get_word_length(word: str) -> int:
    """Returns the length of a word."""
    return len(word)

# 2. 将自定义工具放入工具列表
tools = [get_word_length]

# 3. 创建 Agent (与案例五类似)
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 4. 调用 Agent
# Agent 会识别出需要计算单词长度,并调用我们定义的 get_word_length 工具
response = agent_executor.invoke({"input": "单词 'supercalifragilisticexpialidocious' 有多长?"})
print(response["output"])

结果分析:Agent 成功调用了我们用 @tool 装饰器定义的 get_word_length 函数。这展示了将任意 Python 函数封装为 Agent 工具的强大能力,使得 Agent 几乎可以执行任何程序化任务。


八、案例七:构建多路路由链

在复杂应用中,我们可能需要根据用户的输入,将其路由到不同的处理链。RunnableBranchMultiPromptChain 可以实现这个功能。

from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableBranch
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI

# 1. 定义不同的处理链
llm = ChatOpenAI(model="gpt-4o")

# 物理问题链
physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise and easy to understand manner. \
When you don't know the answer to a question you admit that you don't know.
Here is a question:
{input}"""
physics_prompt = PromptTemplate.from_template(physics_template)
physics_chain = LLMChain(llm=llm, prompt=physics_prompt)

# 数学问题链
math_template = """You are a very good mathematician. You are great at answering math questions. \
You are so good because you are able to break down hard problems into their component parts, \
answer the component parts, and then put them together to answer the broader question.
Here is a question:
{input}"""
math_prompt = PromptTemplate.from_template(math_template)
math_chain = LLMChain(llm=llm, prompt=math_prompt)

# 通用对话链
general_chain = LLMChain(llm=llm, prompt=PromptTemplate.from_template("{input}"))

# 2. 定义路由逻辑
# 这是一个简单的路由链,它判断输入中是否包含 'physics' 或 'math'
def route(info):
    if "physics" in info["topic"].lower():
        return physics_chain
    elif "math" in info["topic"].lower():
        return math_chain
    else:
        return general_chain

# 3. 使用 RunnableBranch 构建路由链
full_chain = RunnableBranch(
  (lambda x: "physics" in x["topic"].lower(), physics_chain),
  (lambda x: "math" in x["topic"].lower(), math_chain),
  general_chain
)

# 4. 测试路由
# 提一个物理问题
physics_question = {"topic": "physics", "input": "What is quantum entanglement?"}
print("--- Physics Question ---")
print(full_chain.invoke(physics_question)['text'])

# 提一个数学问题
math_question = {"topic": "math", "input": "What is the Pythagorean theorem?"}
print("\n--- Math Question ---")
print(full_chain.invoke(math_question)['text'])

# 提一个通用问题
general_question = {"topic": "history", "input": "Who was Napoleon Bonaparte?"}
print("\n--- General Question ---")
print(full_chain.invoke(general_question)['text'])

结果分析RunnableBranch 像一个 if-elif-else 语句,它按顺序评估条件,并执行第一个匹配的分支。这使得我们可以根据输入内容,动态地选择最合适的专家提示词(Prompt)和处理逻辑,从而得到更专业、更准确的回答。


总结与展望

从简单的提示词工程到复杂的 Agent 系统,LangChain 为构建基于 LLM 的应用程序提供了坚实的基础设施。它通过标准化的接口和可组合的组件,将 LLM 的原始能力转化为可控、可扩展、可与外部世界交互的强大动力。

掌握 LangChain,就等于掌握了通往下一代 AI 应用开发的钥匙。当然,所有这些强大的功能都依赖于背后强大的大型语言模型。

拥抱强大的 LLM 算力

对于开发者而言,稳定、高效且经济的 LLM API 是将想法变为现实的基石。

  • 😳 0v0 AI 助手推荐:如果你想免费体验和测试各种前沿模型(包括 Llama、Qwen、gpt-4o,甚至每周免费的 gpt-5),https://0v0.pro 是一个不容错过的平台。它提供无限制的对话次数,是学习和探索 LLM 的绝佳工具。

LangChain 负责编排,而这些平台则提供了核心动力。二者结合,将为你的 AI 应用开发之旅插上翅膀。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐