关于 rag
rag 是用于设计检索增强生成(RAG)系统的技能,面向构建文档问答、语义搜索和领域知识应用的开发者。内容涵盖文档处理、向量存储、检索配置、管线实现与评估。
主要功能
- 01文档清理、切分与嵌入
- 02向量数据库选择指导
- 03密集、混合及元数据检索
- 04重排序与上下文注入
- 05检索和回答质量评估
适用场景
- 01构建专有文档问答系统
- 02为知识库聊天机器人提供事实依据
- 03实现自然语言语义搜索
- 04减少缺少依据的回答
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill rag安装后在 Claude Code 中输入/rag确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/retriever-pipeline.javavector-store-config.yamlreferences/document-chunking.mdembedding-models.mdlangchain4j-rag-guide.mdretrieval-strategies.mdvector-databases.md详细介绍
RAG 实现
构建检索增强生成系统,通过外部知识源扩展 AI 能力。
概述
此技能涵盖:文档处理、嵌入生成、向量存储、检索配置和 RAG 工作流实现。
适用场景
- 基于专有文档构建问答系统
- 创建可从知识库获取事实信息的聊天机器人
- 使用自然语言查询实现语义搜索
- 通过提供依据和来源的回答减少幻觉
- 构建文档助手和研究工具
- 让 AI 系统能够访问特定领域的知识
说明
步骤 1:选择向量数据库
根据需求进行选择:
| 需求 | 推荐方案 |
|---|---|
| 生产环境可扩展性 | Pinecone、Milvus |
| 开源 | Weaviate、Qdrant |
| 本地开发 | Chroma、FAISS |
| 混合搜索 | 使用 BM25 的 Weaviate |
步骤 2:选择嵌入模型
| 用例 | 模型 |
|---|---|
| 通用 | text-embedding-ada-002 |
| 快速轻量 | all-MiniLM-L6-v2 |
| 多语言 | e5-large-v2 |
| 最佳性能 | bge-large-en-v1.5 |
步骤 3:实现文档处理工作流
- 从来源(文件系统、数据库、API)加载文档
- 清理并预处理(移除格式、规范化文本)
- 使用适当的策略将文档拆分为文本块
- 为每个文本块生成嵌入
- 将嵌入及元数据存储在向量数据库中
验证:确认嵌入已成功生成:
List<Embedding> embeddings = embeddingModel.embedAll(segments);
if (embeddings.isEmpty() || embeddings.get(0).dimension() != expectedDim) {
throw new IllegalStateException("Embedding generation failed");
}
步骤 4:配置检索策略
选择合适的策略:
- 稠密检索:通过嵌入进行语义相似度检索(大多数情况下的默认选项)
- 混合搜索:结合稠密检索和稀疏检索,以获得更好的覆盖率
- 元数据过滤:按文档属性进行筛选
- 重排序:对精度要求较高时,使用交叉编码器进行重排序
步骤 5:构建 RAG 工作流
- 使用嵌入存储创建内容检索器
- 配置 AI 服务,添加检索器和聊天记忆
- 实现带有上下文注入的提示词模板
- 添加回答验证和依据检查
验证:使用已知查询进行测试,确认上下文注入正常工作。
错误处理:对于批量导入,请使用重试逻辑进行封装:
for (Document doc : documents) {
int attempts = 0;
while (attempts < 3) {
try {
store.add(embeddingModel.embed(doc).content(), doc.toTextSegment());
break;
} catch (EmbeddingException e) {
attempts++;
if (attempts == 3) throw new RuntimeException("Failed after 3 retries", e);
}
}
}
步骤 6:评估和优化
- 衡量检索指标:precision@k、recall@k、MRR
- 评估回答质量:忠实度、相关性
- 监控性能和用户反馈
- 迭代调整文本块、检索和提示词参数
示例
示例 1:基础文档问答
List<Document> documents = FileSystemDocumentLoader.loadDocuments("/docs");
InMemoryEmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>();
EmbeddingStoreIngestor.ingest(documents, store);
DocumentAssistant assistant = AiServices.builder(DocumentAssistant.class)
.chatModel(chatModel)
.contentRetriever(EmbeddingStoreContentRetriever.from(store))
.build();
String answer = assistant.answer("What is the company policy on remote work?");
示例 2:按元数据筛选检索
EmbeddingStoreContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store)
.embeddingModel(embeddingModel)
.maxResults(5)
.minScore(0.7)
.filter(metadataKey("category").isEqualTo("technical"))
.build();
示例 3:多来源 RAG 工作流
ContentRetriever webRetriever = EmbeddingStoreContentRetriever.from(webStore);
ContentRetriever docRetriever = EmbeddingStoreContentRetriever.from(docStore);
List<Content> results = new ArrayList<>();
results.addAll(webRetriever.retrieve(query));
results.addAll(docRetriever.retrieve(query));
List<Content> topResults = reranker.reorder(query, results).subList(0, 5);
示例 4:带聊天记忆的 RAG
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(chatModel)
.chatMemory(MessageWindowChatMemory.withMaxMessages(10))
.contentRetriever(retriever)
.build();
assistant.chat("Tell me about the product features");
assistant.chat("What about pricing for those features?"); // Maintains context
最佳实践
文档准备
- 导入前清理文档;移除无关内容和格式
- 添加相关元数据,以便筛选并补充上下文
文本块拆分策略
- 每个文本块使用 500-1000 个 token,以取得最佳平衡
- 设置 10-20% 的重叠,以保留边界处的上下文
- 针对具体用例测试不同的文本块大小
检索优化
- 从较高的 k 值(10-20)开始,然后进行筛选或重排序
- 使用元数据筛选来提高相关性
- 监控检索质量,并根据用户反馈迭代改进
性能
- 缓存频繁访问内容的嵌入
- 使用批处理导入文档
- 根据规模优化向量存储索引
限制和警告
系统限制
- 嵌入模型对每份文档都有最大 token 限制
- 向量数据库需要正确建立索引,才能保证性能
- 复杂文档的文本块边界可能会丢失上下文
- 混合搜索需要额外的基础设施
质量警告
- 检索质量很大程度上取决于分块策略
- 嵌入模型可能无法捕捉特定领域的语义
- 元数据筛选需要正确标注文档
- 重排会增加查询响应延迟
安全警告
- 切勿将凭据硬编码:使用环境变量存储 API 密钥和密码
- 验证外部内容:来自文件系统、API 或 Web 来源的文档可能包含恶意内容(提示词注入)
- 将检索到的文档传递给 LLM 前,先进行内容筛选
- 使用允许列表限制允许的数据源 URL 和文件路径
资源
参考文档
评论
支持 Markdown