AI超级智能开发系列从入门到上天第十一篇:RAG最佳实践和调优

发布时间:2026/5/19 7:50:50

AI超级智能开发系列从入门到上天第十一篇:RAG最佳实践和调优 一文档收集和切割知识完备性是文档质量的首要条件。知识库缺失相关内容大模型将无法准确回答问题。需通过收集用户反馈或统计知识库检索命中率不断完善和优化知识库内容。在知识完整的前提下需注意 3 个方面1原始文档优化1内容结构化原始文档应保持排版清晰、结构合理如案例编号、项目概述、设计要点等。文档的各级标题层次分明各标题下的内容表达清晰。列表中间的某一条之下尽量不要再分级减少层级嵌套。2内容规范化语言统一确保文档语言与用户提示词一致如英语场景采用英文文档专业术语可进行多语言标注。表述统一同一概念应使用统一表达方式如 ML、Machine Learning 规范为 “机器学习”可通过大模型分段处理长文档辅助完成。减少噪音尽量避免水印、表格和图片等可能影响解析的元素。3格式标准化优先使用 Markdown、DOC/DOCX 等文本格式PDF 解析效果可能不佳可通过百炼 DashScopeParse 工具将 PDF 转为 Markdown再借助大模型整理格式。若文档包含图片需链接化处理确保回答中能正常展示文档中的插图可通过在文档中插入可公网访问的 URL 链接实现。标题最多两层子标题最多400字。只允许有文字文档采用MarkDown最容易被AI理解的格式。。标注好计算公式。拿着标准拿着文档去问大模型让大模型给优化给打分。2文档切片最佳的切片策略是智能分块算法和人工二次校验。最佳文档切片策略是结合智能分块算法和人工二次校验。智能分块算法基于分句标识符先划分为段落再根据语义相关性动态选择切片点避免固定长度切分导致的语义断裂。在实际应用中应尽量让文本切片包含完整信息同时避免包含过多干扰信息。公有云咱们就用阿里云百联就够了一站式服务非常之开心。至于专属化直接文库上传、接口回调知识库切分存库人工干预Embdding存向量库。3元数据标注可以为文档添加丰富的结构化信息俗称元信息形成多维索引便于后续向量化处理和精准检索。在编程实现中可以通过多种方式为文档添加元数据。第一种方式documents.add(new Document( 案例编号LR-2023-001\n 项目概述180平米大平层现代简约风格客厅改造\n 设计要点\n 1. 采用5.2米挑高的落地窗最大化自然采光\n 2. 主色调云雾白(哑光NCS S0500-N)配合莫兰迪灰\n 3. 家具选择意大利BB品牌真皮沙发北欧白橡木茶几\n 空间效果通透大气适合商务接待和家庭日常起居, Map.of( type, interior, // 文档类型 year, 2025, // 年份 month, 05, // 月份 style, modern, // 装修风格 )));第二种方式// 提取文档倒数第 3 和第 2 个字作为标签 String status fileName.substring(fileName.length() - 6, fileName.length() - 4); MarkdownDocumentReaderConfig config MarkdownDocumentReaderConfig.builder() .withHorizontalRuleCreateDocument(true) .withIncludeCodeBlock(false) .withIncludeBlockquote(false) .withAdditionalMetadata(filename, fileName) .withAdditionalMetadata(status, status) .build();第三种方式我们从MySQL数据库读取出来之后构建成Spring的Document对象然后手动进行干预即可。Document document new Document(内容); // 动态添加元数据 document.getMetadata().put(filename, xxx.md); document.getMetadata().put(status, 02);第四中方式使用SpringAI的元数据标注增强器。import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.document.Document; import org.springframework.ai.model.transformer.KeywordMetadataEnricher; Component public class MyKeywordEnricher { Resource private ChatModel dashscopeChatModel;//注意使用阿里的。 public ListDocument enrichDocuments(ListDocument documents) { KeywordMetadataEnricher keywordMetadataEnricher new KeywordMetadataEnricher(dashscopeChatModel, 5); return keywordMetadataEnricher.apply(documents); } }效果如下线上的阿里云百联构建知识库的时候有自己的metadata抽取。这个时候。如果使用知识库云服务这个建议还是开一下。4补充SpringAI提供的原生AI切片读取文档和初步拆分之后保存到数据库然后用户进行手动干预完毕之后我们在进行处理import org.springframework.ai.document.Document; import org.springframework.ai.reader.markdown.MarkdownDocumentReader; import org.springframework.ai.reader.markdown.config.MarkdownDocumentReaderConfig; import org.springframework.core.io.Resource; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.stereotype.Component; Component Slf4j public class LoveAppDocumentLoader { private final ResourcePatternResolver resourcePatternResolver; public LoveAppDocumentLoader(ResourcePatternResolver resourcePatternResolver) { this.resourcePatternResolver resourcePatternResolver; } /** * 加载多篇 Markdown 文档 * return */ public ListDocument loadMarkdowns() { ListDocument allDocuments new ArrayList(); try { Resource[] resources resourcePatternResolver.getResources(classpath:document/*.md); for (Resource resource : resources) { String filename resource.getFilename(); // 提取文档倒数第 3 和第 2 个字作为标签 String status filename.substring(filename.length() - 6, filename.length() - 4); MarkdownDocumentReaderConfig config MarkdownDocumentReaderConfig.builder() .withHorizontalRuleCreateDocument(true) .withIncludeCodeBlock(false) .withIncludeBlockquote(false) .withAdditionalMetadata(filename, filename) .withAdditionalMetadata(status, status) .build(); MarkdownDocumentReader markdownDocumentReader new MarkdownDocumentReader(resource, config); allDocuments.addAll(markdownDocumentReader.get()); } } catch (IOException e) { log.error(Markdown 文档加载失败, e); } return allDocuments; } }自定义切词器import org.springframework.ai.document.Document; import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.stereotype.Component; import java.util.List; /** * 自定义基于 Token 的切词器 */ Component class MyTokenTextSplitter { public ListDocument splitDocuments(ListDocument documents) { TokenTextSplitter splitter new TokenTextSplitter(); return splitter.apply(documents); } public ListDocument splitCustomized(ListDocument documents) { TokenTextSplitter splitter new TokenTextSplitter(200, 100, 10, 5000, true); return splitter.apply(documents); } }自定义元数据补充器import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.document.Document; import org.springframework.ai.model.transformer.KeywordMetadataEnricher; Component public class MyKeywordEnricher { Resource private ChatModel dashscopeChatModel; public ListDocument enrichDocuments(ListDocument documents) { KeywordMetadataEnricher keywordMetadataEnricher new KeywordMetadataEnricher(dashscopeChatModel, 5); return keywordMetadataEnricher.apply(documents); } }二次切分元数据补充Resource private LoveAppDocumentLoader loveAppDocumentLoader; Resource private MyTokenTextSplitter myTokenTextSplitter; Resource private MyKeywordEnricher myKeywordEnricher; Bean VectorStore loveAppVectorStore(EmbeddingModel dashscopeEmbeddingModel) { // 这里指定EmbaddingModel模型是什么 SimpleVectorStore simpleVectorStore SimpleVectorStore.builder(dashscopeEmbeddingModel).build(); // 加载文档 ListDocument documentList loveAppDocumentLoader.loadMarkdowns(); // 自主切分文档 // ListDocument splitDocuments myTokenTextSplitter.splitCustomized(documentList); // 自动补充关键词元信息 ListDocument enrichedDocuments myKeywordEnricher.enrichDocuments(documentList); // 进行Embadding和Store到Java对象当中。 simpleVectorStore.add(enrichedDocuments); return simpleVectorStore; } }二向量转换和存储向量转换和存储是 RAG 系统的核心环节直接影响检索的效率和准确性。这块主要是一个技术选型。1云平台阿里提供了内置数据库和ADB-PG两种一般选内置就行了。Embedding模型DashScope textembedding-v2到v4商业化模型。排序配置基于Rank模型设置一下相似度阈值即可。三文档过滤和检索这个环节是我们开发者最能大显身手的地方在技术已经确定的情况下优化这个环节可以显著提升系统整体效果。1多查询拓展在多轮会话场景中用户输入的提示词有时可能不够完整或者存在歧义。多查询扩展技术可以扩大检索范围提高相关文档的召回率。使用多查询扩展时要注意设置合适的查询数量建议 3-5 个过多会影响性能、增大成本保留原始查询的核心语义import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.rag.Query; import org.springframework.ai.rag.preretrieval.query.expansion.MultiQueryExpander; import org.springframework.stereotype.Component; import java.util.List; /** * 查询扩展器 Demo */ Component public class MultiQueryExpanderDemo { private final ChatClient.Builder chatClientBuilder; public MultiQueryExpanderDemo(ChatModel dashscopeChatModel) { this.chatClientBuilder ChatClient.builder(dashscopeChatModel); } public ListQuery expand(String query) { MultiQueryExpander queryExpander MultiQueryExpander.builder() .chatClientBuilder(chatClientBuilder) .numberOfQueries(3) .build(); ListQuery queries queryExpander.expand(new Query(谁是国服第一李白)); return queries; } }2查询重写和翻译Component public class QueryRewriter { // 通过构造函数注入。 private final QueryTransformer queryTransformer; public QueryRewriter(ChatModel dashscopeChatModel/**使用阿里云百联的chatmodel*/) { ChatClient.Builder builder ChatClient.builder(dashscopeChatModel); // 创建查询重写转换器 //CompressionQueryTransformer //RewriteQueryTransformer //TranslationQueryTransformer queryTransformer RewriteQueryTransformer.builder() .chatClientBuilder(builder) .build(); } /** * 执行查询重写 * * param prompt * return */ public String doQueryRewrite(String prompt) { Query query new Query(prompt); // 执行查询重写 Query transformedQuery queryTransformer.transform(query); // 输出重写后的查询 return transformedQuery.text(); }阿里云百练上也有这个功能叫做多轮对话改写。会基于用户输入和历史上下文信息来做一个优化。3检索器配置检索器配置是影响检索质量的关键因素主要包括三个方面相似度阈值、返回文档数量和过滤规则。1设置合理的相似度阈值相似度阈值控制文档被召回的标准需根据具体问题调整问题解决方案知识库的召回结果不完整没有包含全部相关的文本切片建议降低相似度阈值提高召回片段数以召回一些原本应被检索的信息知识库的召回结果中包含大量无关的文本切片建议提高相似度阈值以排除与用户提示词相似度低的信息在编程实现中可以通过文档检索器配置// 1. 构建检索器 VectorStoreDocumentRetriever retriever VectorStoreDocumentRetriever.builder() .vectorStore(我的向量库) .similarityThreshold(0.5) .maxResults(5) .build(); // 2. 构建过滤条件重点 MapString, Object filter new HashMap(); filter.put(filename, 恋爱常见问题_01.md); // 只检索这个文件 filter.put(status, 01); // 只检索状态为01 // 3. 带过滤条件检索 ListDocument documents retriever.retrieve(如何提升魅力, filter);云平台提供了更便捷的配置界面参考文档2控制返回文档数量VectorStoreDocumentRetriever retriever VectorStoreDocumentRetriever.builder() .vectorStore(我的向量库) .similarityThreshold(0.5) .maxResults(5) .build();3配置文档过滤规则Slf4j public class LoveAppRagCustomAdvisorFactory { public static Advisor createLoveAppRagCustomAdvisor(VectorStore vectorStore, String status) { Filter.Expression expression new FilterExpressionBuilder() .eq(status, status) .build(); DocumentRetriever documentRetriever VectorStoreDocumentRetriever.builder() .vectorStore(vectorStore) .filterExpression(expression) // 过滤条件 .similarityThreshold(0.5) // 相似度阈值 .topK(3) // 返回文档数量 .build(); return RetrievalAugmentationAdvisor.builder() .documentRetriever(documentRetriever) .build(); } }晕百联也是支持基于元数据进行过滤。开启后知识库会在限量检索前添加一层结构化搜索。通过API调用晕白丽娜是可以在请求参数中tags指定标签。4检索命中测试编写测试用例调整测试相似度阈值命中测试。对召回结果满意。修正知识库相似度阈值。四查询增强关联经过前面的文档检索系统已经获取了与用户查询相关的文档。此时大模型需要根据用户提示词和前面的文档生成最终回答。然而返回结果可能仍未达到预期效果需要进一步优化。1错误处理机制在实际应用中可能出现多种异常情况如找不到相关文档、相似度过低、查询超时等。良好的错误处理机制可以提升用户体验。异常处理主要包括允许空上下文查询即处理边界情况提供友好的错误提示引导用户提供必要信息RetrievalAugmentationAdvisor.builder() .queryAugmenter( ContextualQueryAugmenter.builder() .allowEmptyContext(false) .build() )Configuration Slf4j public class LoveAppRagCloudAdvisorConfig { Value(${spring.ai.dashscope.api-key}) private String dashScopeApiKey; Bean public Advisor loveAppRagCloudAdvisor() { DashScopeApi dashScopeApi DashScopeApi.builder() .apiKey(dashScopeApiKey) .build(); final String KNOWLEDGE_INDEX 恋爱大师; DocumentRetriever dashScopeDocumentRetriever new DashScopeDocumentRetriever(dashScopeApi, DashScopeDocumentRetrieverOptions.builder() .withIndexName(KNOWLEDGE_INDEX) .build()); return RetrievalAugmentationAdvisor.builder() .documentRetriever(dashScopeDocumentRetriever) .build(); }public String doChatWithRag(String message, String chatId) { // 查询重写 String rewrittenMessage queryRewriter.doQueryRewrite(message); ChatResponse chatResponse chatClient .prompt() // 使用改写后的查询 .user(rewrittenMessage) .advisors(spec - spec.param(ChatMemory.CONVERSATION_ID, chatId)) // 开启日志便于观察效果 .advisors(new MyLoggerAdvisor()) // 应用 RAG 知识库问答 .advisors(new QuestionAnswerAdvisor(loveAppVectorStore)) // 应用 RAG 检索增强服务基于云知识库服务 // .advisors(loveAppRagCloudAdvisor) // 应用 RAG 检索增强服务基于 PgVector 向量存储 // .advisors(new QuestionAnswerAdvisor(pgVectorVectorStore)) // 应用自定义的 RAG 检索增强服务文档查询器 上下文增强器 // .advisors( // LoveAppRagCustomAdvisorFactory.createLoveAppRagCustomAdvisor( // loveAppVectorStore, 单身 // ) // ) .call() .chatResponse(); String content chatResponse.getResult().getOutput().getText(); log.info(content: {}, content); return content; }通过单元测试调用即可验证。2其他建议除了上述优化策略外还可以考虑以下方面的改进表格问题类型改进策略大模型并未理解知识和用户提示词之间的关系答案生硬拼凑建议 选择合适的大模型提升语义理解能力返回的结果没有按照要求或者不够全面建议 优化提示词模板引导模型生成更符合要求的回答返回结果不够准确混入了模型自身的通用知识建议 开启拒识功能限制模型只基于知识库回答相似提示词希望控制回答的一致性或多样性建议 调整大模型参数如温度值等如果有必要的话还可以考虑更高级的优化方向比如分离检索阶段和生成阶段的知识块针对不同阶段使用不同粒度的文档进一步提升系统性能和回答质量针对查询重写、关键词元信息增强等用到 AI 大模型的场景可以选择相对轻量的大模型不一定整个项目只引入一种大模型

相关新闻