LangChain 学习笔记 04:什么时候该用 Chain,什么时候该写普通代码

“Chain”这个名字很容易让人产生一个误会:只要把几个模型调用首尾相接,就算搭好了应用。

第 5 章从基础链、顺序链、路由链讲到 Stuff、Refine 和 MapReduce。读下来以后,我更关心的反而是另一个问题:一段流程什么时候值得封装成 Chain,又有哪些逻辑应该老老实实留在普通代码里?

从一个客服流程开始

假设用户提交一句反馈:“升级后无法导出 Excel,而且订单号是 A1024。”系统可能要做这些事:

识别问题类型 -> 查询对应知识库 -> 生成回复 -> 检查是否需要转人工

这是一条比较适合组合的流程,因为每一步都有清晰输入和输出:分类器返回问题类型,Retriever 返回文档,模型根据文档生成草稿,规则判断是否升级工单。

但“用户有没有查看订单的权限”“工单是否已经创建”不适合让模型凭语义判断。权限、事务、幂等和金额计算应继续由确定性代码负责。

顺序、路由和并行,差别在控制流

顺序流程适合前一步结果稳定地交给下一步。例如先抽取文章主题,再按主题生成摘要。它容易理解,但上游错误会一路传下去。

路由流程先判断输入属于哪个分支,例如售前咨询进入产品知识库,故障问题进入排障知识库。文件类型、用户角色等确定条件可以直接用代码判断;只有模糊的语义意图才值得交给模型分类。

并行流程适合互不依赖的任务。例如同时生成摘要、关键词和风险提示,最后再合并。并行可以降低整体延迟,但要提前定义合并时的数据结构。

无论使用哪种方式,我都会先写清楚每一步的契约:需要哪些字段,产生哪些字段,失败后是重试、跳过,还是终止流程。

长文档为什么有多种合并策略

书中介绍的 Stuff、Refine 和 MapReduce,可以用“怎样处理一摞材料”来理解。

策略 做法 更适合的情况 主要代价
Stuff 把材料一次交给模型 内容少、上下文放得下 噪声多,容易超长
Refine 先写初稿,再逐份材料修正 答案需要持续完善 调用次数多,受顺序影响
MapReduce 分别处理,再汇总中间结果 长文档、可并行任务 汇总时可能丢细节

例如总结 100 页会议记录时,Stuff 简单但可能塞不下;MapReduce 可以先分章节提炼行动项,再统一去重;Refine 则适合沿时间顺序不断更新一份项目结论。

策略没有固定排名。文档长度、预算、延迟、是否能拆分,以及答案是否需要全局一致性,都会影响选择。

Chain 变长以后,最先坏在哪里

长链最麻烦的不是代码多,而是错误位置和表现位置可能相隔很远。分类步骤输出了一个意外标签,直到后面的 Prompt 缺变量时才报错;摘要步骤遗漏了数字,最后汇总出来的报告仍然语句通顺。

我会给关键节点加三类保护:

  1. 中间结果尽量结构化,并对字段做校验;
  2. 记录步骤名、输入摘要、输出摘要、耗时和错误;
  3. 给重试、并发和总调用次数设置上限。

重要流程还可以保存中间状态。这样失败后不必从第一步重跑,也能还原哪一步开始偏离。

这章给我的启发

Chain 最有价值的地方,是把数据流和阶段边界表达清楚。它不是隐藏复杂度的盒子,更不是所有代码都要进入的容器。

如果一段流程连输入输出都说不清,先套框架只会把问题藏起来。先画出数据怎样流动,再决定哪些步骤组合、哪些分支显式书写,通常会更稳。

文章摘自:https://www.cnblogs.com/hazy-star/p/22080562