news 2026/11/4 4:57:33

AI Agent知识获取管道:TypeScript实现RAG检索增强生成全链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent知识获取管道:TypeScript实现RAG检索增强生成全链路

1. 为什么知识获取管道是 AI Agent 落地的第一道坎

做 AI Agent 开发的人,绕不开一个现实问题:模型本身很聪明,但它不知道你公司内部的业务规则、不知道你昨天刚更新的产品文档、更不知道你私有的那套数据表结构。你问它一个关于内部流程的问题,它要么一本正经地胡说八道,要么直接告诉你“我无法回答”。这不是模型不行,而是它的知识边界就停在那里。

知识获取管道要解决的就是这件事——把外部知识在合适的时机、以合适的形式喂给模型,让它基于真实资料来回答。而RAG(检索增强生成)就是目前工程上最成熟、性价比最高的一条路径。它的核心思路用一句话说清楚:先把知识切片存起来,用户提问时先检索出最相关的片段,再把这些片段塞进提示词里让模型生成答案。

我见过太多团队一上来就想着微调模型,结果数据准备了两周、训练跑了三天,上线后发现业务文档一天改三版,微调根本追不上变化。RAG 的好处在于知识库和模型解耦——文档更新了,重新灌一次向量库就行,模型完全不用动。这也是为什么从 2024 年到现在,几乎所有企业级 AI Agent 项目的第一期,都是先搭一条 RAG 管道。

这篇文章是“走进 AI Agent”系列的第四篇,前面几篇聊了 Agent 的整体架构、工具调用和记忆机制,这一篇专门把知识获取管道拆开讲透。我会用TypeScript作为主要实现语言,因为它在前后端通吃、类型系统能帮你在管道各环节少踩很多坑。内容会覆盖从文档加载、切片、向量化、存储、检索到重排的完整链路,也会聊到实际项目里那些文档不会告诉你的坑。不管你是刚接触 RAG 的新手,还是已经搭过一版想优化的老手,应该都能从里面找到能直接用的东西。

2. RAG 管道的五个核心环节与数据流转

2.1 从原始文档到可检索片段的完整链路

一条标准的 RAG 管道,数据要经过五个环节才能变成模型能用的知识。我用一个实际的企业知识库场景来串一遍:假设你有一批产品手册 PDF、一批 Markdown 格式的 FAQ、还有一堆 Confluence 导出的 HTML 页面。

第一个环节是加载(Loading)。不同格式的文档需要不同的解析器。PDF 要用 pdf-parse 或 pdfjs 提取文本,HTML 要用 cheerio 或 jsdom 清洗标签,Markdown 相对简单直接读就行。这一步的坑在于 PDF 里的表格和分栏排版,直接提取出来的文本顺序经常是乱的,后面切片就会切出莫名其妙的片段。

第二个环节是切片(Chunking)。把长文档切成一段段适合检索的小块。切片的粒度直接决定检索质量——切太大,一个片段里混了好几个主题,检索出来噪音多;切太小,一个完整的逻辑被切断,模型拿到手里拼不出完整意思。常见的做法是按字符数切,比如 500 到 1000 字符一块,块之间留 10% 到 20% 的重叠,防止关键信息正好卡在边界上被切掉。

第三个环节是向量化(Embedding)。把每个文本块通过嵌入模型转成一串浮点数向量。语义相近的文本,向量在空间里的距离也近。这一步决定了你的检索是“按关键词匹配”还是“按语义匹配”。比如用户问“怎么退款”,文档里写的是“申请退货流程”,关键词对不上但语义很近,向量检索就能命中。

第四个环节是存储(Storage)。向量要存进向量数据库,同时把原始文本和元数据(来源文件、页码、章节标题)一起存进去。检索出来向量后,你得能拿回对应的原文片段。常见的选型有 pgvector、Qdrant、Milvus、Chroma 等,小项目用 pgvector 就够了,不用额外维护一套数据库。

第五个环节是检索与重排(Retrieval & Rerank)。用户提问时,先把问题也向量化,然后在向量库里找最相似的 Top-K 个片段。但纯向量检索有个问题:它偏向语义相似,有时候会漏掉关键词精确匹配的结果。所以工程上通常会做混合检索——向量检索和关键词检索(BM25)各出一批结果,再用 RRF(倒数排名融合)合并。合并之后还可以加一层重排模型(Reranker),用交叉编码器对候选片段重新打分,把真正最相关的排到前面。

2.2 为什么每个环节都不能偷懒

很多人搭第一版 RAG 的时候,喜欢用现成的框架一把梭,LangChain 或者 LlamaIndex 几行代码就跑通了。跑通没问题,但上线之后效果不好,你根本不知道是哪个环节出了问题。是切片切坏了?是嵌入模型选错了?还是检索策略太单一?

我的经验是,每个环节都要能单独观测和调试。切片结果要能导出来人工看,嵌入向量要能算相似度验证,检索结果要能打印出分数和来源。这样出问题的时候,你能快速定位到具体环节,而不是对着一个黑盒干瞪眼。

还有一个容易被忽略的点:元数据的设计。很多人只存文本和向量,检索出来一个片段,不知道它来自哪个文件、哪一页。这在调试和展示引用来源时非常致命。我的做法是每个片段都带上source(文件路径)、chunkIndex(块序号)、heading(所属章节标题)这几个字段,检索结果直接能拼出“根据《产品手册》第 3 章……”这样的引用。

3. 用 TypeScript 搭一条最小可用的 RAG 管道

3.1 项目结构与依赖选型

先说一下技术选型。嵌入模型我推荐用 OpenAI 的text-embedding-3-small,1536 维,价格便宜,效果对大多数场景够用。如果你要完全本地化,可以用bge-m3或者nomic-embed-text,通过 Ollama 跑。向量库小项目直接用 pgvector,Postgres 你本来就要用,不用多维护一个组件。

TypeScript 项目结构大概长这样:

rag-pipeline/ src/ loaders/ # 各种格式的文档加载器 chunker.ts # 切片逻辑 embedder.ts # 向量化封装 store.ts # 向量库读写 retriever.ts # 检索与重排 pipeline.ts # 串联全流程 data/ # 原始文档 scripts/ ingest.ts # 灌数据脚本 query.ts # 查询测试脚本

依赖方面,核心就几个:openai做嵌入,pg连 Postgres,pdf-parse解析 PDF,cheerio清洗 HTML。不需要一上来就上 LangChain,自己写反而更可控。

3.2 文档加载与清洗的实操细节

加载这一步,我踩过最大的坑是 PDF。很多 PDF 是扫描件,pdf-parse提取出来是空的,这种情况必须上 OCR,但 OCR 成本高、速度慢,能避免就避免。还有一种情况是 PDF 里有多栏排版,提取出来的文本是左右栏交错混在一起的,读起来完全不通。我的处理方式是:如果发现提取文本的换行特别频繁且句子不连贯,就标记这个文件需要人工检查。

HTML 清洗相对简单,用 cheerio 把script、style、nav、footer这些标签去掉,只留正文。但要注意有些文档站点的正文在article标签里,有些在main里,得针对性地写选择器。

Markdown 最省心,直接读文本就行,但要注意代码块和表格不要被切片逻辑破坏。我的做法是在切片前先把代码块和表格用占位符替换掉,切完再还原,这样能保证它们作为整体不被切断。

3.3 切片策略:固定长度还是语义切分

切片策略我试过三种,说说各自的适用场景。

固定长度切片最简单,按字符数切,每 800 字符一块,重叠 100 字符。优点是实现快、结果可预测。缺点是经常把一个完整段落从中间切断,检索出来的片段读起来没头没尾。

按分隔符切片是固定长度的改进版,优先在段落边界(\n\n)、句子边界(。、!、?)切,切不到再按字符数硬切。这个策略在大多数场景下效果比纯固定长度好,实现也不复杂。

语义切片最理想,用嵌入模型判断相邻句子是否属于同一主题,主题变了就切一刀。效果最好,但成本高——每个句子都要算一次嵌入。我一般只在知识库质量要求特别高的场景才用。

实际项目里,我推荐按分隔符切片 + 固定长度兜底的组合。代码大概这样:

function chunkText(text: string, maxLen = 800, overlap = 100): string[] { const paragraphs = text.split(/\n\n+/); const chunks: string[] = []; let current = ""; for (const para of paragraphs) { if ((current + para).length > maxLen && current.length > 0) { chunks.push(current.trim()); // 保留尾部重叠,防止边界信息丢失 current = current.slice(-overlap) + para; } else { current += (current ? "\n\n" : "") + para; } } if (current.trim()) chunks.push(current.trim()); return chunks; }

注意:重叠部分不要设太大,否则向量库里会有大量重复内容,检索时同一段信息反复出现,反而稀释了其他相关内容的权重。10% 到 15% 的重叠比例比较合适。

3.4 向量化与入库:批量处理与错误重试

向量化这一步,核心是批量处理和错误重试。嵌入 API 一般支持一次传多个文本,比如 OpenAI 的接口一次最多传 2048 个输入。批量传能大幅减少网络往返,但要注意单批不要太大,否则一个失败整批重来。我的做法是每批 100 个片段,失败后指数退避重试三次。

入库的时候,pgvector 的表结构大概这样:

CREATE TABLE chunks ( id SERIAL PRIMARY KEY, source TEXT NOT NULL, chunk_index INT NOT NULL, heading TEXT, content TEXT NOT NULL, embedding vector(1536) ); CREATE INDEX ON chunks USING ivfflat (embedding vector_cosine_ops);

ivfflat索引适合数据量中等(几万到几十万条)的场景,建索引时要注意lists参数,一般设为sqrt(行数)左右。数据量再大就得上 HNSW 索引,查询更快但建索引更慢、占内存更多。

4. 检索质量上不去的四个真实原因

4.1 嵌入模型和业务语料不匹配

这是最隐蔽也最常见的问题。通用嵌入模型是在海量互联网文本上训练的,对日常语言理解很好,但你的业务领域可能有大量专有名词、缩写、内部代号。比如你问“XX 项目的验收标准是什么”,模型不知道“XX 项目”是什么,向量化出来的结果和文档里的“XX 项目”对不上。

解决办法有两个:一是换一个在你的领域数据上微调过的嵌入模型,二是做查询改写——用户提问后,先用 LLM 把问题改写成更完整、更明确的表述,再拿去检索。比如把“XX 项目验收”改写成“XX 项目的验收标准和验收流程是什么”,检索命中率会明显提升。

4.2 切片粒度与查询粒度不匹配

用户的问题通常很短,比如“退款要多久”。但文档里的相关段落可能是一大段关于退款政策的描述,有前提条件、有例外情况、有处理时效。如果切片切得太细,检索出来的片段只有“处理时效为 3 到 5 个工作日”,缺少前提条件,模型可能给出错误答案。

我的经验是:切片粒度要略大于典型查询的粒度。用户问一句话,你检索出来的片段应该能覆盖这句话涉及的完整上下文。800 到 1200 字符是比较稳妥的范围,具体要看你的文档密度。

4.3 纯向量检索漏掉关键词精确匹配

向量检索擅长语义相似,但对精确的关键词匹配反而不敏感。比如用户问“错误码 E5021 怎么解决”,向量检索可能返回一堆关于“错误处理”的通用文档,但真正包含“E5021”的那篇反而排在后面。因为“E5021”这个 token 在嵌入模型眼里可能没什么特殊含义。

这就是为什么必须做混合检索。BM25 这类关键词检索算法对精确匹配非常敏感,把向量检索和 BM25 的结果用 RRF 融合,能同时兼顾语义和关键词。RRF 的公式很简单:每个文档的得分是1 / (k + rank)的累加,k 一般取 60。实现起来也就几十行代码。

4.4 缺少重排导致 Top-K 里混入噪音

检索出 Top-10 个片段,不代表这 10 个都相关。向量相似度高不等于真正回答了问题。这时候需要重排模型做二次筛选。重排模型(比如bge-reranker系列)会把查询和每个候选片段拼在一起,输出一个相关性分数,比单纯的向量相似度准确得多。

重排的代价是速度——交叉编码器要对每个候选片段单独推理,10 个片段就要推理 10 次。所以工程上的做法是:向量检索先召回 Top-50,重排后取 Top-5 送给模型。这样既保证了召回率,又控制了延迟。

5. 从 Demo 到生产:管道工程化的几个关键决策

5.1 增量更新与全量重建的取舍

知识库不是一次灌完就不管了。文档会更新、会新增、会删除。全量重建简单粗暴,但数据量大时耗时很长,而且重建期间检索服务不可用。增量更新复杂,但能做到近实时。

我的做法是给每个文档算一个内容哈希,灌数据时对比哈希,变了才重新切片和向量化。删除文档时,根据source字段把对应的所有片段删掉。这样每次更新只处理变化的文档,速度很快。但要注意,如果切片策略变了,所有文档的哈希都会变,相当于全量重建,这个要提前规划好。

5.2 检索结果的缓存与降级

生产环境里,同样的查询可能被反复问到。加一层查询缓存能显著降低延迟和成本。缓存的 key 是查询文本的哈希,value 是检索结果。但要注意缓存失效——知识库更新后,旧缓存要清掉。

降级策略也很重要。如果嵌入 API 挂了,检索服务不能整个挂掉。我的做法是:嵌入失败时降级到纯关键词检索(BM25),虽然效果差一些,但至少服务可用。向量库连接失败时,返回一个友好的错误提示,而不是让整个 Agent 卡死。

5.3 观测指标:命中率、延迟与成本

RAG 管道上线后,必须有一套观测指标。我最关注的三个:

命中率(Hit Rate):检索结果里是否包含真正能回答问题的片段。这个需要人工标注一批测试问题,定期跑评估。命中率低于 80% 就说明检索环节有问题,得回去查切片和嵌入。

延迟(Latency):从用户提问到返回检索结果的时间。嵌入 API 调用、向量检索、重排各占多少,要能拆开看。一般来说,嵌入 100ms 以内、向量检索 50ms 以内、重排 200ms 以内是比较理想的。

成本(Cost):每次查询消耗的嵌入 token 数和重排调用次数。嵌入成本很低,但重排如果每次都跑 Top-50,成本会上去。可以通过缓存和动态调整 Top-K 来控制。

6. 那些文档不会告诉你的踩坑记录

6.1 中文分词的隐藏陷阱

做中文 RAG 的时候,BM25 检索需要分词。很多人直接用jieba或者nodejieba,但中文分词的粒度对检索效果影响很大。比如“人工智能”如果被切成“人工”和“智能”,用户搜“人工智能”时 BM25 可能匹配不上。我的做法是维护一个领域词典,把业务专有名词加进去,保证它们不被切碎。

还有一个坑是中英文混合。文档里经常有“使用 TypeScript 开发”这样的句子,分词器可能把“TypeScript”切成“Type”和“Script”,导致搜“TypeScript”时匹配不到。解决办法是在分词前先用正则把英文单词和数字提取出来作为整体 token。

6.2 向量维度和索引参数的调优

pgvector 的ivfflat索引有个probes参数,控制查询时扫描多少个聚类。probes越大,召回率越高但速度越慢。默认值是 1,实际用的时候至少要设到sqrt(lists)左右。我一般设lists = 100、probes = 10,在召回和速度之间取平衡。

还有一个容易忽略的点:向量归一化。如果你用余弦相似度,向量必须归一化,否则内积和余弦相似度不等价。OpenAI 的嵌入接口返回的向量默认是归一化的,但如果你自己跑本地模型,一定要检查这一点。

6.3 重排模型的延迟与成本平衡

重排模型效果好,但延迟是实打实的。我实测下来,bge-reranker-base在 CPU 上跑 50 个候选片段大概要 1 到 2 秒,GPU 上能压到 200ms 以内。如果你的场景对延迟敏感,要么上 GPU,要么减少候选数量。

还有一个取巧的办法:只对 Top-20 做重排。向量检索召回 Top-50,先用一个轻量级的规则过滤掉明显不相关的(比如完全不包含查询关键词的),剩下的 20 个再送重排。这样能在几乎不损失效果的前提下把重排成本降一半。

6.4 知识库更新后的缓存一致性

前面提到查询缓存,这里展开说一个具体的坑。知识库更新后,如果缓存没清,用户会拿到旧结果。但全量清缓存又会导致缓存命中率骤降。我的做法是给缓存加一个版本号,知识库每次更新版本号加一,查询时带上版本号作为 key 的一部分。这样旧版本的缓存自然失效,新版本缓存逐步建立,平滑过渡。

7. 下一步可以往哪里走

RAG 基础管道跑通之后,有几个方向可以继续深入。一个是Agentic RAG,让 Agent 自己决定什么时候检索、检索什么、检索几次,而不是每次查询都固定走一遍管道。另一个是GraphRAG,把知识图谱和向量检索结合起来,处理多跳推理类的问题。还有就是多模态 RAG,把图片、表格也纳入检索范围。

但我的建议是,先把基础管道做扎实。切片策略调好、混合检索跑通、重排加上、观测指标建起来。这些基础工作做到位,效果已经能覆盖 80% 的场景。后面那些高级玩法,等基础管道稳定了再逐步叠加,不然出了问题你根本分不清是基础环节的锅还是高级特性的锅。

我个人在实际项目里的体会是,RAG 的效果提升往往不来自某个炫酷的新技术,而是来自把每个环节的细节抠到位。切片多调几版、嵌入模型多试几个、检索参数多跑几组对比,这些笨功夫才是真正拉开差距的地方。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/4 4:57:31

多微网共享储能优化调度与NSGA-II博弈实现

1. 项目背景与核心价值去年参与某工业园区综合能源系统设计时,我第一次接触到多微网协同调度问题。传统独立微网运行模式下,各主体自建储能导致设备利用率不足40%,而共享储能模式理论上可将利用率提升至75%以上。这正是《含多微网租赁共享储能…

作者头像 李华
网站建设 2026/11/4 4:57:18

PHPCMS V9:轻量级PHP内容管理系统的原理与工程价值

简介:PHPCMS V9 UTF8是一款面向Web开发初学者与中小型网站运维人员的开源内容管理系统,专为构建多语言、高兼容性的企业官网、资讯门户或社区型站点提供开箱即用的解决方案。资源包为官方UTF8编码版本,完整包含系统核心程序、默认模板、常用模…

作者头像 李华
网站建设 2026/11/4 4:57:14

研究生必备AI论文工具:9款高效科研利器评测

1. 为什么研究生需要AI论文工具?读研期间最痛苦的时刻莫过于凌晨三点对着空白文档发呆,文献综述写了删删了写,实验数据像天书一样看不懂。去年帮导师审硕士论文时发现,90%的延期毕业都卡在文献调研和论文写作环节。现在不同了&…

作者头像 李华
网站建设 2026/11/4 4:56:55

RocketMQ支持MQTT协议的技术实现与架构优势

1. RocketMQ支持MQTT协议的核心意义在分布式系统架构演进过程中,消息中间件扮演着越来越重要的角色。作为Apache顶级开源项目,RocketMQ从5.0版本开始原生支持MQTT协议,这一特性改变了许多企业的技术架构选型。我曾在多个物联网平台建设项目中…

作者头像 李华
网站建设 2026/11/4 4:56:31

AI Agent Harness 七大子系统:从零搭建生产级智能体工程骨架

1. 从"Agent 到底在跑什么"说起很多人第一次接触 AI Agent,脑子里浮现的画面是:一个模型坐在那里,你给它一句话,它自己思考、自己调工具、自己写代码、自己交付结果。但真上手搭过一个能跑起来的 Agent 之后&#xff0c…

作者头像 李华
网站建设 2026/11/4 4:55:56

AI Agent知识获取管道设计:RAG检索增强生成实战与优化

1. 为什么知识获取管道是 AI Agent 的分水岭做 AI Agent 开发的人,绕不开一个尴尬的现实:模型本身很聪明,但它对你私有的业务数据一无所知。你问它公司内部的报销流程,它要么胡编一个看起来很像样的答案,要么礼貌地告诉…

作者头像 李华