ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

企业技术支持RAG与Agent实战:无Token可用,有Token更聪明

企业技术支持RAG与Agent实战:无Token可用,有Token更聪明 1. 企业技术支持 Agent 的 RAG 实战拆解1.1 这个项目到底在做什么企业技术支持这个场景做过的人都懂——每天面对的是海量重复问题、产品文档、历史工单、FAQ、内部 Wiki还有一堆散落在聊天记录里的“民间解决方案”。新人上手慢老人被问烦知识沉淀在个人脑子里人一走就断档。这个项目要解决的核心问题就是用 RAG 加 Agent 的方式把企业技术支持的知识库变成一个能对话、能推理、能给出可执行答案的智能助手。标题里那句“没 Token 能用有 Token 更聪明”说的其实是两件事。第一层意思是系统在没有外部大模型 Token 配额的情况下依然能靠本地模型和本地 Embedding 跑起来保证基础可用第二层意思是当你有 Token 配额、能调用更强的 LLM 时系统的回答质量、推理深度、多轮对话能力会明显上一个台阶。这不是一个“非黑即白”的方案而是一个可降级、可升级、按需付费的弹性架构。适合谁来参考三类人最值得看一是企业 IT 支持团队的负责人想降低支持成本、提升响应速度二是正在做 RAG 落地的开发者想看看真实企业场景里 RAG 到底怎么搭三是对 Agent 架构感兴趣但还没动手的人这个项目是一个很好的“从零到一”的参考样本。1.2 为什么选 RAG 加 Agent 而不是纯 LLM纯 LLM 做企业技术支持最大的问题是幻觉。你问它“我们公司内部系统的登录报错 403 怎么处理”它可能会编一个看起来很像但完全不对的答案。企业场景里错误答案比没有答案更可怕因为用户会照着做然后问题更大。RAG 的价值在于把答案锚定在真实文档上。用户问一个问题系统先去知识库里检索相关片段再把片段和问题一起交给 LLM 生成回答。这样 LLM 不是在“凭空想”而是在“阅读理解后总结”。检索增强生成核心就是让模型有据可依。Agent 的价值在于多步推理和工具调用。企业技术支持不是简单的“一问一答”很多时候需要先查工单系统看历史记录再查知识库找解决方案然后对比版本差异最后给出操作步骤。Agent 可以把这些步骤串起来像一个真正的技术支持工程师那样工作而不是一个只会背答案的机器人。两者结合RAG 保证答案的准确性和可追溯性Agent 保证流程的自动化和智能化。这就是为什么这个项目没有选纯 LLM也没有选纯检索而是走了 RAG 加 Agent 的路线。1.3 整体架构长什么样这个项目的架构可以拆成四层从下往上分别是数据层企业内部的文档、工单、FAQ、Wiki 页面、聊天记录导出。这些数据格式五花八门有 PDF、Word、Markdown、HTML、Excel还有数据库里的结构化记录。数据层要做的是统一采集、清洗、分块、向量化。检索层向量数据库加关键词检索的混合检索。向量检索负责语义匹配关键词检索负责精确匹配。两者结合既能找到“意思相近”的内容也能找到“字面匹配”的内容。检索层还要做重排序把最相关的片段排到前面。Agent 层负责意图识别、任务规划、工具调用、多轮对话管理。用户问一个问题Agent 先判断这是什么类型的问题然后决定要不要查知识库、要不要查工单系统、要不要调用外部 API最后把结果整合成回答。模型层LLM 和 Embedding 模型。LLM 负责生成回答Embedding 模型负责把文本转成向量。这一层是“有 Token 更聪明”的关键——本地小模型能跑但效果有限换成更强的云端 LLM效果会明显提升。这四层之间通过标准接口通信每一层都可以独立替换。比如你今天用本地 Embedding明天想换成更好的云端 Embedding只需要改配置不需要动上层代码。这种松耦合的设计是企业级系统能长期演进的基础。2. 核心细节解析与实操要点2.1 文档分块RAG 效果的第一道分水岭很多人做 RAG 效果不好第一反应是“模型不行”其实十有八九是分块没做好。文档分块是 RAG 的地基地基没打好后面怎么调都白搭。企业技术支持文档有个特点结构性强但格式不统一。有的文档是标准的产品手册章节清晰有的是工单记录一段话里混着问题描述、排查过程、解决方案还有的是聊天记录东一句西一句。如果统一按固定字数切很容易把一段完整的解决方案切成两半检索的时候只召回一半LLM 看到的就是残缺信息。我的做法是按语义分块辅以结构信息。具体来说对于有明确标题层级的文档按标题切分每个最小标题下的内容作为一个块。如果块太大再按段落切分。对于工单和聊天记录先按“问题-解决”对进行配对每一对作为一个块。如果一对太长按句子边界切分。每个块保留上下文元数据来源文档、所属章节、前后块的关系。这样检索到某个块时可以把相邻块也带出来给 LLM 更完整的上下文。块的大小控制在300 到 800 个 Token之间。太小了信息不完整太大了检索精度下降。这个范围是实测下来比较稳的当然具体还要看你的文档密度和问题复杂度。注意分块的时候一定要保留原始文档的标题和层级信息这些信息在检索和生成时非常有用。很多开源工具默认把标题丢掉只留正文这是很大的浪费。2.2 Embedding 模型选型不是越贵越好Embedding 模型负责把文本转成向量它的质量直接决定检索的准确率。市面上 Embedding 模型很多从开源的 BGE、M3E到商用的 OpenAI Embedding、Cohere Embed选择很多。选型的时候不要只看榜单排名要看你的场景。企业技术支持文档里有很多专业术语、产品名称、错误码这些词在通用语料里出现频率低通用 Embedding 模型可能区分度不够。这时候可以考虑用领域数据微调Embedding 模型让模型更懂你的业务语言。用混合检索弥补单一 Embedding 的不足关键词检索能抓住那些 Embedding 抓不住的精确匹配。如果预算有限本地 Embedding 模型完全够用。BGE 系列在中文场景下表现很稳而且可以本地部署不消耗 Token。“没 Token 能用”这个目标很大程度上就是靠本地 Embedding 加本地 LLM 实现的。本地 Embedding 模型跑起来对硬件要求不高一张消费级显卡甚至 CPU 都能跑只是速度慢一点。对于中小企业来说这是一个性价比很高的起点。2.3 检索策略向量加关键词的混合打法纯向量检索有个问题它对精确匹配不敏感。比如用户问“错误码 E5023 怎么解决”向量检索可能会召回一堆“错误码处理”相关的文档但不一定精准命中 E5023 那一条。这时候关键词检索就派上用场了。我的做法是双路召回加融合排序向量召回用 Embedding 模型把 query 转成向量在向量数据库里找最相似的 Top K 个块。关键词召回用 BM25 或类似算法在全文索引里找包含 query 关键词的 Top K 个块。融合排序把两路结果合并用重排序模型Reranker重新打分取 Top N 个最相关的块。重排序模型是提升 RAG 效果的一个“秘密武器”。它比 Embedding 模型更重但精度更高可以对少量候选块做精细打分。实测下来加了重排序之后检索准确率能提升 10 到 20 个百分点。提示重排序模型不需要和 Embedding 模型一样可以用更小的模型做粗排再用更大的模型做精排。这样兼顾速度和精度。2.4 Agent 的工具设计让模型知道“能做什么”Agent 的核心能力是调用工具。在企业技术支持场景里工具可以包括知识库检索工具输入 query返回相关文档片段。工单查询工具输入工单号或关键词返回历史工单记录。系统状态查询工具输入服务名返回当前系统状态和最近告警。操作执行工具输入操作指令执行重启、清理缓存等操作需要严格权限控制。工具设计的关键是描述清晰。LLM 决定调用哪个工具完全依赖工具的描述。如果描述模糊LLM 就会乱调。每个工具的描述要说明这个工具是干什么的、什么时候用、输入是什么、输出是什么。比如知识库检索工具的描述可以写成“当用户询问产品功能、操作步骤、错误解决方法时使用此工具检索内部知识库。输入为用户问题的关键词输出为相关文档片段。”这样 LLM 就知道什么时候该用它。2.5 多轮对话管理记住上下文但别记太多企业技术支持往往是多轮对话。用户第一句说“登录报错”第二句说“错误码是 403”第三句说“我试过重启了没用”。如果系统不记住上下文每一轮都当新问题处理体验会很差。但上下文也不是越多越好。LLM 的上下文窗口有限塞太多历史对话会挤占检索结果的空间。我的做法是滑动窗口加摘要保留最近几轮对话的原文更早的对话压缩成摘要。这样既保留了关键信息又不会撑爆上下文。另外Agent 要能识别话题切换。如果用户突然问了一个完全不相关的问题系统应该开启新的话题而不是把旧话题的上下文硬塞进去。这个可以通过意图识别来实现判断当前问题是否和上一轮属于同一主题。3. 实操过程与核心环节实现3.1 环境准备与依赖安装先说一下基础环境。这个项目对硬件的要求取决于你选本地模型还是云端模型。如果全本地跑建议至少 16GB 内存有一张 8GB 显存的显卡会更流畅。如果只用本地 Embedding 加云端 LLM那普通开发机就能跑。Python 环境建议用 3.10 或以上。核心依赖包括pip install langchain langchain-community chromadb sentence-transformers pip install fastapi uvicorn pip install pypdf python-docx markdown这里用 ChromaDB 作为向量数据库因为它轻量、易用、支持本地持久化适合中小规模知识库。如果数据量很大可以换成 Milvus 或 Weaviate。LangChain 用来串联整个流程Sentence-Transformers 用来加载本地 Embedding 模型。3.2 文档采集与清洗企业文档来源多格式杂第一步是统一采集。我的做法是写一个采集脚本遍历指定目录按文件类型分别处理PDF 用 pypdf 提取文本注意处理扫描件需要 OCR。Word 用 python-docx 提取段落和表格。Markdown 直接读取保留标题层级。HTML 用 BeautifulSoup 提取正文去掉导航和广告。Excel 用 pandas 读取每一行作为一个记录。清洗环节要做几件事去掉页眉页脚、去掉重复内容、统一编码、修正明显的 OCR 错误。这一步看起来琐碎但直接影响后续检索质量。我见过太多项目因为清洗没做好导致检索出来的片段里全是乱码和页眉。3.3 分块与向量化分块用 LangChain 的 RecursiveCharacterTextSplitter但不要用默认参数。我一般设置from langchain.text_splitter import RecursiveCharacterTextSplitter splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50, separators[\n## , \n### , \n\n, \n, 。, , , , ] )chunk_size设为 500 个字符左右chunk_overlap设为 50保证块与块之间有重叠避免信息被切断。separators的顺序很重要优先按标题切再按段落切最后按句子切。向量化用 Sentence-Transformers 加载 BGE 模型from sentence_transformers import SentenceTransformer model SentenceTransformer(BAAI/bge-base-zh-v1.5) embeddings model.encode(chunks, normalize_embeddingsTrue)normalize_embeddingsTrue很重要它把向量归一化这样余弦相似度计算更稳定。BGE 模型在中文场景下表现很好而且模型不大本地跑完全没问题。3.4 向量入库与索引构建用 ChromaDB 建库import chromadb client chromadb.PersistentClient(path./chroma_db) collection client.create_collection( nametech_support, metadata{hnsw:space: cosine} ) collection.add( documentschunks, embeddingsembeddings.tolist(), metadatas[{source: s, section: sec} for s, sec in metadata], ids[fid_{i} for i in range(len(chunks))] )hnsw:space设为 cosine因为我们的向量已经归一化了。metadata 里保留来源和章节信息方便后续过滤和展示。3.5 检索链路实现检索分三步向量召回、关键词召回、重排序。向量召回直接用 ChromaDB 的 queryresults collection.query( query_embeddings[query_embedding], n_results20 )关键词召回可以用 rank_bm25 库from rank_bm25 import BM25Okapi tokenized_corpus [doc.split() for doc in chunks] bm25 BM25Okapi(tokenized_corpus) scores bm25.get_scores(query.split())重排序用 Cross-Encoder 模型from sentence_transformers import CrossEncoder reranker CrossEncoder(BAAI/bge-reranker-base) pairs [[query, doc] for doc in candidate_docs] scores reranker.predict(pairs)把两路召回的结果合并去重然后用重排序模型打分取 Top 5 作为最终上下文。3.6 Agent 编排与工具调用Agent 用 LangChain 的 AgentExecutor 来编排。先定义工具from langchain.tools import Tool def search_knowledge(query: str) - str: # 调用检索链路 return retrieved_context tools [ Tool( nameknowledge_search, funcsearch_knowledge, description当用户询问产品功能、操作步骤、错误解决方法时使用。输入为问题关键词。 ) ]然后初始化 Agentfrom langchain.agents import initialize_agent, AgentType agent initialize_agent( toolstools, llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, verboseTrue )ZERO_SHOT_REACT_DESCRIPTION是最常用的 Agent 类型它让 LLM 根据工具描述决定调用哪个工具。verboseTrue方便调试可以看到 Agent 的思考过程。3.7 本地模型与云端模型的切换“没 Token 能用有 Token 更聪明”的切换逻辑可以通过配置来实现。定义一个 LLM 工厂函数def get_llm(use_cloud: bool False): if use_cloud: from langchain_openai import ChatOpenAI return ChatOpenAI(modelgpt-4, temperature0) else: from langchain_community.llms import Ollama return Ollama(modelqwen2:7b)本地用 Ollama 跑 Qwen2 7B云端用更强的模型。切换只需要改一个配置项。这样在 Token 配额用完或者网络不通的时候系统自动降级到本地模型保证基础可用。注意本地模型和云端模型的 prompt 格式可能不同切换的时候要确保 prompt 模板兼容。建议把 prompt 模板抽象成独立的配置不要硬编码在代码里。4. 常见问题与排查技巧实录4.1 检索不准先查分块再查模型检索不准是最常见的问题。排查顺序应该是先看分块再看 Embedding最后看检索策略。分块问题表现为检索出来的片段是半句话或者把不相关的内容拼在一起。解决方法是调整分块参数增加重叠优化分隔符。Embedding 问题表现为语义相近的内容检索不到或者检索出来的内容语义偏差大。解决方法是换模型或者用领域数据微调。检索策略问题表现为精确匹配的内容排不到前面。解决方法是加关键词召回和重排序。4.2 回答幻觉让 LLM 学会说“不知道”即使有 RAGLLM 还是可能编答案。解决办法是在 prompt 里明确要求如果检索结果里没有相关信息就回答“根据现有知识库无法回答建议联系人工支持”。同时可以在生成回答时附上引用来源让用户知道答案是从哪篇文档来的。这样即使答案有误用户也能追溯和判断。4.3 Token 消耗过快优化 prompt 和上下文Token 消耗快通常是两个原因prompt 太长或者检索结果太多。优化方法精简 system prompt去掉不必要的说明。控制检索结果数量Top 5 通常够用不要塞 Top 20。用摘要代替原文对于长文档先摘要再放入上下文。开启对话历史压缩把早期对话压缩成摘要。4.4 并发扛不住异步加缓存Agent 处理一个请求可能要几秒到十几秒并发一高就扛不住。解决办法用 FastAPI 的异步接口避免阻塞。对常见问题加缓存相同问题直接返回缓存结果。用队列削峰请求先入队后台 worker 慢慢处理。如果本地模型推理慢考虑用 vLLM 或 TGI 做推理加速。4.5 常见问题速查表问题现象可能原因排查方法解决方案检索结果不相关分块不合理检查检索片段是否完整调整分块参数增加重叠精确匹配失效纯向量检索测试关键词是否能召回加入 BM25 关键词召回回答编造内容prompt 约束不足检查 prompt 是否要求引用来源加强 prompt 约束要求引用Token 消耗快上下文太长统计每次请求的 Token 数精简 prompt控制检索数量并发上不去同步阻塞压测观察响应时间异步化加缓存用队列本地模型慢硬件不足监控 GPU/CPU 使用率换更小模型或用推理加速框架多轮对话混乱上下文管理不当检查历史对话是否超长滑动窗口加摘要识别话题切换4.6 几个踩过的坑第一个坑是元数据丢失。早期版本分块的时候没保留来源信息检索出来的片段不知道是哪篇文档的用户问“这个答案从哪来的”就答不上来。后来在 metadata 里加了 source 和 section问题解决。第二个坑是重排序模型太慢。一开始用大模型做重排序每次请求要好几秒。后来换成小模型做粗排、大模型做精排速度提升明显。第三个坑是本地模型和云端模型输出格式不一致。本地模型有时候不按格式输出导致解析失败。后来在 prompt 里加了严格的格式要求并且加了输出解析的容错逻辑。第四个坑是知识库更新不及时。文档更新了但向量库没更新检索出来的还是旧内容。后来加了一个定时任务每天凌晨重新索引变更的文档。5. 后续扩展与个人体会这个项目跑通之后后续可以扩展的方向不少。比如加入多模态检索让系统能处理图片和表格比如加入用户反馈闭环让用户对回答打分用反馈数据优化检索和生成比如加入权限控制不同角色的用户看到不同的知识库内容。我个人在实际操作中的体会是RAG 加 Agent 这套东西效果的上限取决于数据质量下限取决于工程实现。数据质量好即使模型一般效果也不会差工程实现稳即使模型强也不会翻车。很多团队一上来就追求最强模型结果数据一团糟工程一堆坑最后效果还不如一个简单的关键词搜索。另外不要一开始就追求大而全。先跑通一个最小闭环采集一批文档分块向量化检索生成。跑通之后再逐步优化分块、加混合检索、加重排序、加 Agent。每一步都验证效果不要一次性堆太多东西否则出了问题都不知道是哪一层的问题。最后分享一个小技巧用真实用户问题做测试集。不要自己编问题去工单系统里捞真实问题用它们来评估检索和生成效果。真实问题的表达方式、用词习惯、上下文依赖和你自己编的问题完全不一样。用真实问题测出来的效果才是真正靠谱的效果。
返回列表