5.2 LangChain 与 Coze 平台实践:从链到智能体

14 阅读10分钟

基于《大规模语言模型:从理论到实践(第2版)》第8章 大模型智能体

爆款小标题:原书 LangChain/Coze 实践:链式调用与平台化 Agent 开发


为什么这一节重要

要把大模型「接上」工具、记忆与业务流程,要么写代码把 LLM、检索、工具调用和状态管理串起来,要么用低代码/可视化平台快速搭 Bot。LangChain 是当前最常用的「代码优先」框架:用 Chain、Agent、Memory 等组件把 LLM 与工具、向量库、提示模板组合成可复用的流水线。Coze 等平台则通过工作流编排与 Bot 配置,让产品与运营也能参与对话设计、插件与知识库配置。原书第 8 章对二者都有实践介绍。本节把 LangChain 的链与 Agent 的区别、工具与记忆的用法、以及 Coze 类平台的定位讲清,并给出「何时用代码、何时用平台」的选型建议,便于你在实际项目中做出合适选择并避开常见坑。


学习目标

  • 理解 LangChain 的核心抽象:能说明 Chain、Agent、工具封装与记忆(Memory)在 LangChain 中的角色,以及「谁决定下一步」在 Chain 与 Agent 中的本质区别(原书第 8 章实践部分)。
  • 了解 Coze 等平台的用法:知道如何通过工作流与 Bot 配置完成对话、插件与知识库的搭建,以及这类平台适合什么团队与场景。
  • 能做选型决策:根据「纯代码 vs 低代码」「深度定制 vs 快速上线」「数据与权限要求」等因素,在 LangChain 与 Coze 类平台之间做出合理选择,并明确与自建后端、数据边界的配合方式。

一、LangChain 中的 Chain:固定流水线(原书第 8 章)

什么是 Chain:Chain 把多个步骤按固定顺序串联起来,每一步的输入来自上一步的输出。例如:用户输入 → 提示模板填充 → 调用 LLM → 解析输出。谁决定下一步:由开发者预先定义的流程决定,模型只负责「当前这一步」的输入输出,不决定「接下来调用哪个工具、走哪条分支」。

典型用法:适合流程确定、无需根据中间结果动态选择路径的场景。例如「检索→拼 prompt→生成」的 RAG 链、「多步固定顺序的摘要/改写」等。在 LangChain 中,可用 LCEL(LangChain Expression Language)或 SequentialChain 等把 PromptTemplate、LLM、OutputParser 串起来。

RAG Chain 与 Agent 完整可运行代码(依赖:pip install langchain langchain-openai langchain-community sentence-transformers faiss-cpu;设置 OPENAI_API_KEY 可调用真实模型):

import os

# RAG Chain
def run_rag_chain():
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_core.runnables import RunnablePassthrough
    from langchain_community.vectorstores import FAISS
    from langchain_community.embeddings import HuggingFaceEmbeddings
    from langchain_core.documents import Document
    embeddings = HuggingFaceEmbeddings(model_name="paraphrase-multilingual-MiniLM-L12-v2", model_kwargs={"device": "cpu"})
    docs = [Document(page_content="退货政策:7天内可无理由退货。", metadata={"source": "1"}), Document(page_content="远程办公:每周可远程2天。", metadata={"source": "2"})]
    vectorstore = FAISS.from_documents(docs, embeddings)
    retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
    if os.getenv("OPENAI_API_KEY"):
        from langchain_openai import ChatOpenAI
        llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
    else:
        from langchain_community.chat_models.fake import FakeListChatModel
        llm = FakeListChatModel(responses=["根据参考内容,退货政策为:7天内可无理由退货。"])
    format_docs = lambda ds: "\n\n".join(d.page_content for d in ds)
    prompt = ChatPromptTemplate.from_messages([("system", "根据以下参考内容回答。参考:\n{context}"), ("human", "{question}")])
    chain = ({"context": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser())
    return chain.invoke("请问退货政策?")

# Agent(工具调用)
def run_agent():
    from langchain.agents import create_tool_calling_agent, AgentExecutor
    from langchain_core.tools import tool
    from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
    @tool
    def search(query: str) -> str:
        if "退货" in query: return "退货政策:7天内可无理由退货。"
        if "远程" in query: return "远程办公政策:每周可远程2天。"
        return "未找到相关文档。"
    @tool
    def get_weather(city: str) -> str:
        return f"{city}今天晴,25°C。"
    tools = [search, get_weather]
    prompt = ChatPromptTemplate.from_messages([("system", "你是一个助手。"), MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad")])
    if os.getenv("OPENAI_API_KEY"):
        from langchain_openai import ChatOpenAI
        llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
    else:
        from langchain_community.chat_models.fake import FakeListChatModel
        llm = FakeListChatModel(responses=["北京今天晴,25°C。公司远程办公政策:每周可远程2天。"])
    agent = create_tool_calling_agent(llm, tools, prompt)
    agent_executor = AgentExecutor(agent=agent, tools=tools, max_iterations=5, verbose=True)
    return agent_executor.invoke({"input": "北京今天天气怎样?公司允许远程办公吗?"})["output"]

if __name__ == "__main__":
    print("RAG Chain:", run_rag_chain())
    print("Agent:", run_agent())
  • retriever 返回 Top-K 文档;format_docs 将文档列表拼成字符串;RunnablePassthrough() 透传用户输入。
  • 流程固定:检索 → 拼 prompt → 调用 LLM → 解析输出,无模型决策分支。

优点:逻辑清晰、易调试、可单独测试每一步。局限:无法根据模型输出「临时决定」调用哪个工具或是否多轮检索,灵活性不如 Agent。


二、LangChain 中的 Agent:由模型决定下一步(原书第 8 章)

什么是 Agent:Agent 在每步都会把「当前状态(含历史、工具列表、当前输出)」交给 LLM,由 LLM 决定下一步是「调用某个工具(及参数)」还是「直接给出最终答案」。执行完工具后,工具返回会作为新的上下文再次交给 LLM,形成「规划→行动→观察」的循环,直到模型输出最终答案或达到步数上限。

谁决定下一步模型根据当前上下文与工具描述,输出结构化的「下一步动作」(如 {"tool": "search", "args": {...}}),由框架解析后执行工具,再把结果拼回上下文,继续交给模型。因此 Agent 适合「需要多步推理、试错或根据中间结果选工具」的任务;原书第 8 章对 Agent 与工具学习的结合有说明。

与 Chain 的对比:Chain 的下一步是代码里写死的;Agent 的下一步是模型生成的。所以「单步或固定流程」用 Chain 更简单;「多步、分支、工具选择」用 Agent 更合适。模型根据 input 决定先调 get_weather 还是 search;工具返回作为 Observation 再次交给模型。

  • max_iterations=5 限制最大步数,避免无限循环。

三、工具封装与记忆(原书第 8 章)

工具(Tools):在 LangChain 中,工具通常被封装成统一接口(如 namedescriptionargsrun),在构造 Agent 时传入。模型通过描述与 few-shot 示例学会「何时调哪个工具、传什么参数」。工具可以是本地函数、HTTP API、或对向量库的检索等。原书第 8 章强调,工具描述要清晰、参数类型与示例完整,以便模型正确选择与调用。

记忆(Memory):Agent 或 Chain 可能需要「记住」多轮对话或历史决策。LangChain 提供多种 Memory:如 ConversationBufferMemory(简单缓存在内存)、ConversationSummaryMemory(用 LLM 做摘要以省长度)、以及和向量库结合的长期记忆。根据业务选择「只保留最近 N 轮」或「重要信息写入向量库」等策略。


四、Coze 等平台的定位与用法(原书第 8 章)

Coze 等平台通过可视化工作流Bot 配置完成:对话流程设计、插件(相当于工具)配置、知识库(相当于 RAG)挂载、以及发布与运营。适合快速上线、多角色协作(产品/运营可直接改流程与话术),而不必写大量代码。典型能力包括:多轮对话管理、插件市场(天气、搜索、数据库等)、知识库上传与检索、发布到飞书/钉钉/网页等渠道。

工作流与 Bot 的区别:工作流通常指「固定步骤」的流程编排,类似 Chain;Bot 可配置为 Agent 模式,由模型决定下一步调用哪个插件。平台一般支持在 Bot 内挂载多个插件,模型根据用户意图选择调用;也支持在工作流中嵌入 LLM 节点,做条件分支、循环等。选型时需分清:你的场景更需要「固定流程」还是「模型决策」,对应选工作流或 Agent 模式。

与 LangChain 的对比:LangChain 适合复杂逻辑、深度定制、全代码控制的场景;Coze 适合快速验证、运营迭代、低代码协作。若后续需要与自建后端、私有数据或私有化部署深度整合,需在选型时明确:平台的数据存放位置、模型是否可更换、是否支持私有化与权限边界,便于后续迁移或混合架构(自建核心逻辑 + 平台做对话前端等)。


五、工程实战要点

1. 用 LangChain 时先理清「哪些步骤要 LLM、哪些是规则/工具」

避免「一切皆 Chain」导致难以调试。把「必须由模型决策」的部分放在 Agent 或关键节点,把「固定规则、查表、调用 API」放在工具或 Chain 的确定步骤里,便于定位问题与做单元测试。

2. 平台类产品要明确数据与权限边界

使用 Coze 等平台时,确认:用户数据与对话内容存放位置、是否支持私有化、模型是否可替换为自建或私有化模型、权限与审计是否满足合规要求。若业务强依赖自有数据与权限,可考虑「核心用自建(LangChain + 自建后端)、对话入口用平台」的混合方式。知识库上传到平台时,需确认数据是否会离开企业边界、是否符合数据安全与合规要求。

3. Chain 与 Agent 的混用

在实际项目中,可将 Chain 与 Agent 组合:例如用 Chain 做「检索→拼 prompt→生成」的 RAG 固定流程,再用 Agent 做「根据用户追问决定是否再检索、是否调用计算器」的灵活分支。LangChain 支持在 Agent 中调用子 Chain,或在 Chain 的某一步调用 Agent,按业务需要组合即可。

4. Agent 从简单到复杂迭代

不要一上来就写「多工具 + 多轮记忆 + 复杂规划」的 Agent。建议先跑通「单工具 + 单轮」或「两三个工具 + 固定 prompt」,再逐步加记忆、多步与异常处理(如超时、工具失败重试)。

5. Coze 平台搭建流程(步骤概要)

  1. 创建 Bot,选择「对话型」或「工作流型」;2. 在插件市场添加或自建插件(相当于 tools),填写名称、描述、参数 schema;3. 上传知识库文档,配置切块与检索参数;4. 在 prompt 中说明 Bot 角色与使用方式;5. 发布到飞书/钉钉/网页,配置权限与回调;6. 通过对话测试并迭代 prompt 与插件。

六、常见误区与避坑指南

误区一:一上来就写大而全的 Agent

容易陷入调试困难、行为不可控。避坑:从「单工具 + 单轮」跑通,再逐步加规划与记忆,每步都做人工测试与日志检查。

误区二:忽视平台的数据与模型绑定

平台默认可能把对话与知识库存在厂商侧、模型用厂商提供列表。避坑:确认数据存放位置、模型是否可更换、是否支持私有化,再决定是否把核心业务放在平台上。

误区三:Chain 和 Agent 混用不当

该用 Chain 的固定流程写成 Agent 会浪费 token 与延迟;该用 Agent 的决策流程硬写成 Chain 会难以扩展。避坑:按「下一步是否由模型决定」来选 Chain 还是 Agent。


七、小结与衔接

本节基于原书第 8 章梳理了 LangChain 的 Chain(固定流水线)与 Agent(模型决定下一步)的区别、工具与记忆的用法,以及 Coze 等平台的定位与选型注意点;并给出了「先理清 LLM 与规则分工」「明确平台数据与权限」「Agent 从简单到复杂」等工程要点。下一节将专门讲 ReAct 与规划框架:Thought–Action–Observation 循环、Plan-and-Execute 与 ReAct 的差异,以及实现时的解析与步数控制(原书第 8 章,5.3 节)。


课后思考题

  1. LangChain 的「Chain」和「Agent」在「谁决定下一步」上有什么本质区别?各适合什么类型的任务?
  2. 若你要做一个「内部知识库问答 + 查天气」的助手,在 LangChain 与 Coze 之间你会如何选择?列出至少两条理由。