首页 / 文章 / 应根据工作负载选择RAG框架,而非跟随LangChain的流行趋势。

应根据工作负载选择RAG框架,而非跟随LangChain的流行趋势。

当搜索和PDF质量检测功能并非由专用代理处理时,Haystack与LlamaIndex在延迟、依赖关系以及调试便捷性方面均能优于LangChain的单一架构。

1200 词

具体背景中的问题

在凌晨2点发现某个依赖项引入了破坏性变更、固定版本号出现偏移,而值班人员还要花一小时通过逐步排查来恢复一个本质上仅负责检索内容片段并基于其生成答案的功能,这种状况实在糟糕。

更根本的问题并非单次故障。团队已无法理清自身的数据检索路径。LangChain从项目一开始就是默认选择,所有人都依赖它,但各种抽象层不断叠加,最终使得系统变得难以理解。难以理解的系统会在夜间出故障,而且故障发展缓慢,因为没人能指出具体的问题所在。

这并非恶意抨击。当产品确实需要工具调用、内存管理、提示词处理以及多步骤协调功能时,LangChain才能发挥价值。问题在于将本不应使用代理式架构的工作负载用通用的协调工具来处理。

原则

应根据工作负载来选择RAG框架,而非跟风潮流。抽象层会增加延迟、依赖关系复杂度以及调试难度。只有当问题与框架所抽象的内容匹配时,才会产生这些额外成本;否则它就只是累赘。

一个产品可以用同一品牌覆盖两种不同的工作负载。例如:针对内部文档的企业级语义搜索,以及针对上传PDF的快速文档问答功能。这两种功能都不是智能代理。为两项独立任务重复支付完整的编排成本,实在是不合理之举。

一旦去掉营销层面的标签,工具与任务之间的实际对应关系就会显现不同面貌。Deepset的Haystack更适合需要可解释性的生产级检索流程;LlamaIndex则更适用于快速处理私有文档的问答任务,能够实现从文件到答案的简短路径。像Rasa这样的对话平台则适合以意图识别为主的支持流程;Botpress或Dialogflow则适用于低代码客户机器人。Hugging Face Transformers则适合那些需要直接控制模型或对其进行微调的团队。CrewAI、AutoGen和DSPy则适合多智能体协同实验。

这些以智能体为核心的技术方案都经过了客观评估,当产品确实需要多个智能体协同工作时,它们依然具有很大的应用价值。不过,由于存在两种不同的检索工作负载,Haystack和LlamaIndex在本次迁移中唯一重要的评估维度上占据了优势。

权衡取舍

企业级语义搜索——需要可解释、可测试、可扩展且能自托管的架构 → Haystack(组件更多;需运行向量数据库)。

上传的PDF文档质量检测——需要快速部署、低延迟及低计算成本 → LlamaIndex(刻意设计为功能有限;并非任务调度工具)。

真正的多工具智能体——需要各种工具、内存及模板功能 → LangChain / CrewAI(在高频使用路径上存在延迟与依赖问题)。

Haystack旨在实现具有明确检索、路由和生成功能的模块化流程,可与Elasticsearch、OpenSearch、Weaviate等真实后端配合使用,并能自托管以保障隐私。其流程各阶段结构清晰易读:

from haystack.document_stores import InMemoryDocumentStore
from haystack.nodes import DensePassageRetriever, FARMReader
from haystack.pipelines import ExtractiveQAPipeline
document_store = InMemoryDocumentStore()
retriever = DensePassageRetriever(document_store=document_store)
reader = FARMReader(model_name_or_path="deepset/roberta-base-squad2")pipeline = ExtractiveQAPipeline(reader=reader, retriever=retriever)
response = pipeline.run(query="What is Haystack used for?")

Retriever负责评分文档,读取器则从候选项中选出最佳结果。若出现速度缓慢或错误情况,需检查相关节点。无需重写其他部分,只需将InMemoryDocumentStore替换为OpenSearch即可。

LlamaIndex可将大语言模型与本地数据相连——实现数据的导入、索引构建和查询操作——而且其设计初衷就比LangChain更为精简:

from llama_index import SimpleDirectoryReader, GPTTreeIndex
documents = SimpleDirectoryReader("<directory_path>").load_data()
index = GPTTreeIndex(documents)
response = index.query("What is the purpose of this document?")

只需三步即可将PDF文件夹中的内容转换为可查询的索引。对于那些需要几秒内就能给出答案的功能,减少调度开销可直接降低延迟。

与LangChain的单一架构相比,采用Haystack + LlamaIndex的组合方案的优势在于:p95延迟更低,RAG相关依赖项大约减少一半,节点故障更易于定位,框架更换问题更少,更适合自托管环境,而且部署时间从几天缩短至几小时。

如何采用

避免大规模重写,应分阶段进行并持续监测:

  1. 影子模式——对旧路径和新路径使用相同的查询;通过对比答案和响应时间来发现差异,且不会对用户造成影响。
  2. 功能标志切换——一旦新系统的评估质量达到或超越现有系统,便按百分比逐步将流量转移过去。
  3. 分离独立工作负载——如果PDF质量检测与搜索功能之间没有状态共享,可单独迁移该功能。
  4. 最后删除——只有在两个路径在多次发布中均表现良好后,才移除旧的依赖关系。

评估工具(包含已知正确答案的固定问题)可将“新路径是否合格?”这一问题转化为具体数值。影子模式往往会产生混合结果——某些查询的答案更好,而其他查询的答案则被截断——因此应将长文本路由到生成式阅读器,而将精确查询保留为提取式处理。如果没有相关测量数据,框架的变更就只是盲目尝试而已。

原则上的约束:不要过度执着于这种固定的分工方式(支持型机器人可能需要 Rasa,而原始模型工作则可能更适合 Transformers)。也不要永远禁止使用 LangChain——等到真正具备多功能能力的智能体出现时再决定是否继续使用它。

未来的发展方向

短期的工作仍将保持适度推进:在 Haystack 中实现重新排序功能,为长篇答案开发生成式阅读器,或许还会进行 Rasa 意图实验——每次都根据具体工作负载选择合适的工具。框架生态将会再次发生变化(CrewAI、AutoGen、DSPy、RAGFlow、Flowise 等)。那些仅凭热度做出选择的团队每个季度都会重新评估整个技术栈;而那些先明确工作负载再针对性选型的团队则只会关注发生变动的部分。如果觉得 LangChain 阻碍了实际工作,解决办法往往是选用更适合当前任务的框架——而非继续增加 LangChain 的使用。

“以工作负载优先”会给组织流程带来哪些变化

架构评审不再询问“我们是否采用了LangChain标准?”,而是开始关注“存在哪些命名的工作负载,以及哪种工具适合处理每项工作负载?”。这听起来很官僚化,但实际上这是团队避免再次出现不透明整体架构的方式。把各项工作负载列出来:在企业维基上搜索,对上传的文件进行PDF质量检查,未来还可以考虑多工具智能体,或许还需要一个用于处理支持请求的机器人。为每项工作负载指定负责人和服务等级目标。框架选择则成为每行内容下的实现细节。

采购与安全评审也会变得更简单。自托管的Haystack搭配OpenSearch,其数据边界的问题与SaaS型机器人构建工具有所不同;而基于临时上传存储的LlamaIndex又另当别论。如果把这三者都归到同一个“AI平台”议题下,就会掩盖这些差异。

待命操作手册应明确列出节点名称,而非框架名称。“数据检索延迟过高”这类描述具有可操作性,而“LangChain运行缓慢”则没有。分工之后,相关页面会指向OpenSearch的查询时间或读取器的GPU负载情况,而非那些难以理解的依赖问题。

新员工的培训方式也发生了变化。不再需要花一周时间讲解LangChain的相关知识,入职引导可以直接展示Haystack的流程图、LlamaIndex的三步脚本、评估数据集以及如何启用影子模式。由于关键流程更短,员工能够更快地提交有实际价值的代码修改。

这些措施并非要禁止使用LangChain。它们只是反对在产品中有一半组件其实并非智能代理时,还假装某种协调工具是唯一可行的选择。当真正具备多种功能的多工具助手最终被纳入开发计划时,LangChain或CrewAI都可以带着明确的职责描述出现——同时还有预先准备好的评估工具等待使用。

持续进行测量,持续为工作负载命名。确保关键路径足够短,这样即便是在凌晨2点的疲惫值班工程师也能解释清楚。