RAG(Retrieval-Augmented Generation)是当前 AI 应用开发中最实用的范式之一。它的核心思想简单而强大:在 LLM 回答之前,先从外部知识库检索相关文档,将检索结果作为上下文注入 Prompt。这样既解决了 LLM 的知识截止问题,也大幅减少了幻觉。
文档切分的艺术
chunk_size 是 RAG 系统最重要的超参数之一:
- 太小(128 tokens):信息碎片化,检索到的片段缺乏上下文。比如"它是1989年发布的"——没有上文根本不知道"它"指什么。
- 太大(2048 tokens):检索精度下降,无关内容稀释了 Prompt。而且大 chunk 在向量空间中容易被"平均化"。
- 推荐 512~1024 tokens:配合 overlap=50~100 tokens 做滑动窗口。实测在这个区间内召回率和精度的 tradeoff 最优。
另一个常被忽略的点:文档结构保留。Markdown 标题层级、代码块边界、表格结构——在切分时应该保留这些语义边界,而不是在 512 token 处硬切。
Embedding 模型选型
对比了几个主流方案:text-embedding-3-small 性价比最高($0.02/1M tokens),适合大多数场景;bge-large-zh 在中文语义理解上略胜一筹,但需要本地 GPU 部署;all-MiniLM-L6-v2 轻量到可以在 CPU 上跑,但长文本表现一般。
如果知识库主要是中文,bge 系列是最优选择。如果混合中英文,text-embedding-3-small 的多语言能力更稳定。
向量存储的选择
ChromaDB 上手最快——pip install 即可,适合原型验证。FAISS 在百万级向量规模下查询速度碾压 ChromaDB,但需要手动管理索引文件。Milvus 功能最全但部署最重。我的建议:原型用 ChromaDB,生产环境根据数据量在 FAISS 和 Milvus 之间选。
多轮对话中的上下文压缩
一个容易被忽略的痛点:多轮对话中,每轮都把完整检索结果塞进 Prompt,token 消耗线性增长。解决方案是用 ConversationSummaryBufferMemory 或手动维护一个滑动窗口,只保留最近 N 轮的关键信息。LangChain 的 stuff / map_reduce / refine 三种 chain 类型对应不同的压缩策略,选 refine 最适合需要保留细节的场景。
--- 约 720 字