去年年底开始尝试用大模型做企业内部知识库问答,走的是 RAG(Retrieval-Augmented Generation)路线。不需要微调模型本身,而是让模型在回答之前先去"翻文档",把相关段落和问题一起喂给 LLM。
RAG 解决了什么问题
大模型的训练数据有截止时间,而且不知道公司内部的文档。直接问它"我们公司的支付接口怎么调",它只会给你一个八竿子打不着的通用回答。
RAG 的思路很直觉:先搜索,再回答。
用户: "支付接口超时时间怎么设?"
│
▼
┌──────────────┐
│ 1. 向量检索 │ 从知识库找相关的文档片段
│ Embedding │
└──────┬───────┘
│
▼
┌──────────────┐
│ 2. 拼 Prompt │ 把文档片段 + 用户问题一起
│ │ 组装成完整 prompt
└──────┬───────┘
│
▼
┌──────────────┐
│ 3. LLM 生成 │ 基于找到的文档回答问题
│ │ 并引用来源
└──────────────┘
系统架构
┌────────────────────────────────────────────┐
│ RAG 系统架构 │
│ │
│ ┌──────────────────────┐ │
│ │ 离线索引管线 │ │
│ │ │ │
│ │ PDF/Word/MD │ │
│ │ ↓ │ │
│ │ 文本切割 (Chunking) │ │
│ │ ↓ │ │
│ │ Embedding 向量化 │ ←→ Vector DB │
│ │ (text → [0.1, ...]) │ (Milvus/ │
│ │ │ Chroma) │
│ └──────────────────────┘ │
│ │
│ ┌──────────────────────┐ │
│ │ 在线查询管线 │ │
│ │ │ │
│ │ 用户问题 │ │
│ │ ↓ │ │
│ │ Embedding 向量化 │ │
│ │ ↓ │ │
│ │ 向量相似度搜索 │────→ Top-K 结果 │
│ │ ↓ │ │
│ │ 拼装 Prompt │ │
│ │ ↓ │ │
│ │ LLM 生成回答 │ │
│ └──────────────────────┘ │
└────────────────────────────────────────────┘
关键细节
文本切割
文档不能整篇塞进 Embedding——太长的文本向量表达会"模糊"。要切成小块(Chunk),大小一般在 300-800 tokens。但切得太碎会丢失上下文。
实践下来最好的方式是有重叠的滑动窗口切割:
原文: "Redis 是一个开源的内存数据库。它支持多种数据结构。
Redis 通常用作缓存、消息代理和数据库。"
Chunk1: "Redis 是一个开源的内存数据库。它支持多种数据结构。"
Chunk2: "它支持多种数据结构。Redis 通常用作缓存、消息代理和数据库。"
↑ 重叠部分
重叠 100-200 tokens 保证边界处的信息不会因为切分而丢失。
向量数据库选型
| 方案 | 适用场景 |
|---|---|
| Chroma | 原型开发、本地测试、小规模 |
| Milvus | 生产环境、百万级以上向量 |
| pgvector | 已有 PostgreSQL,不想引入新组件 |
| FAISS | 纯本地、不需要持久化 |
初期用 Chroma 快速验证,数据量上去后换 Milvus。
Prompt 模板
检索到的片段和用户问题要拼成一个结构化的 prompt:
你是一个技术支持助手。根据以下参考文档回答问题。
如果文档中没有相关信息,请诚实地说不知道,不要编造。
参考文档:
---[文档1]---
Redis 连接超时参数为 connectTimeout,默认值 2000ms。
---[文档2]---
建议 connectTimeout 不要低于 1000ms,网络抖动可能导致频繁断连。
问题:支付接口超时时间怎么设?
回答:
关键是明确指令:不知道就说不知道——这比任何技术细节都重要。大模型在没有信息时容易"张口就来"(幻觉)。
实际运行的效果与问题
检索质量是系统的天花板——检索不到相关文档,LLM 再强也没用。常见的检索失败原因:
- 用户问题和文档用词不一致(用户问"支付超时",文档写"连接超时参数")
- 问题太短,向量表示信息量不足
- 多跳问题(需要综合多个文档回答)
优化方向包括混合检索(向量 + 关键词)、HyDE(先让 LLM 扩展查询再检索)、以及 reranker 重排序。但每加一层,延迟就上来了。实际项目里建议先跑通最简单的方案,再根据真实用户的 bad case 迭代。
总结
RAG 是目前把私有知识和大模型能力结合起来最务实的方案。不需要训模型、不需要太多算力,一台机器加一个 Embedding 服务就能跑起来。真正的难点不在技术,而在文档质量和检索精度——垃圾进垃圾出,和搜索引擎一个道理。
评论