ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于结构感知RAG的对话智能体:从嘈杂数据到精准问答的工程实践

基于结构感知RAG的对话智能体:从嘈杂数据到精准问答的工程实践 1. 项目概述从嘈杂数据到结构化对话的跨越最近在折腾对话智能体项目时遇到了一个经典难题我们手头积累了大量非结构化的、质量参差不齐的文档、聊天记录和报告也就是所谓的“嘈杂数据”。直接把这些数据扔给大语言模型效果时好时坏回答经常跑偏或者“一本正经地胡说八道”。为了解决这个问题我深入实践了“Structure-Aware RAG”这个方向。简单来说它不是一个全新的框架而是一种增强传统检索增强生成RAG的思路核心在于让系统在检索和生成时能够“理解”并利用数据中潜在的结构信息即使这些结构在原始数据中是模糊、不完整甚至被噪声淹没的。这对于构建稳定、可靠的对话智能体至关重要因为现实世界的数据从来都不是干净规整的。传统的RAG流程可以概括为“切块-向量化-检索-生成”。但在处理客服日志、技术论坛讨论、会议纪要这类数据时简单按字数或段落切分会把本应属于同一逻辑单元比如一个完整的问答对、一个故障排查步骤的内容割裂也会把无关的广告、重复发言、无意义符号噪声一并索引。这直接导致检索回来的“参考片段”质量低下要么信息不全要么掺杂无关内容最终拖累生成答案的准确性和连贯性。Structure-Aware RAG要做的就是在数据处理的早期甚至在检索和重排阶段引入对数据内在结构的感知从而提升整个管道的信噪比。这个项目适合所有正在或计划将RAG技术应用于企业知识库、智能客服、内部助手等场景的开发者。特别是当你面对的数据源五花八门、格式混乱时单纯优化向量模型或加大检索数量可能收效甚微这时就需要从“结构感知”这个维度入手了。接下来我会拆解整个实现思路、关键技术选型、实操步骤以及一路踩坑填坑的经验。2. 核心思路与架构设计为何以及如何感知结构2.1 从“盲检索”到“结构感知”的范式转变传统RAG的检索本质上是“语义相似度匹配”。它假设被检索的文本块chunk是语义自洽的独立单元。但在嘈杂数据中这个假设常常不成立。例如一份产品故障报告可能包含“用户描述”、“工程师诊断”、“解决步骤”、“后续建议”等不同部分它们语义关联但角色不同。如果简单切块可能“解决步骤”被单独检索出来却丢失了关键的“故障现象”上下文导致生成的回答缺乏针对性。Structure-Aware RAG的核心思想是进行两次映射首先将非结构化数据映射到某种结构化的表示或元数据然后利用这种结构化信息来指导检索和生成。这里的“结构”是广义的可以包括逻辑文档结构如标题、章节、列表、代码块、表格。内容类型结构如段落是“问题”、“答案”、“证据”、“总结”还是“引用”。领域本体结构利用领域知识图谱或本体识别文本中的实体如产品名、错误代码、人名及其关系。对话结构在聊天数据中识别发言者、对话轮次、问答配对关系。这种感知带来的优势是显而易见的。在检索阶段我们可以进行更精细的过滤例如只检索被标记为“解决方案”的文本块或者进行结构化的聚合检索将同一个案例的所有相关部分作为一个整体返回。在生成阶段模型可以将结构信息作为提示的一部分例如“根据以下‘故障现象’描述和对应的‘修复步骤’生成给用户的答复。”这极大地约束了生成过程使其更专注、更准确。2.2 系统架构设计分层处理与信息流基于上述思路我设计了一个分层处理架构整个流程分为离线处理和在线服务两大部分。离线处理管道知识库构建原始数据接入与解析支持多种格式PDF、Word、HTML、Markdown、纯文本、JSON日志。使用Apache Tika或Unstructured库进行初步解析提取原始文本和基础格式标记。噪声过滤与清洗针对特定数据源定制规则。例如去除HTML标签残留、标准化日期格式、过滤短于一定字符的无意义段落、使用正则表达式移除特定广告模板文本。结构识别与增强对于格式良好的文档利用解析器得到的标题层级H1, H2, H3自动构建文档大纲并将章节标题作为后续文本块的元数据。对于嘈杂文本/对话这是关键。我采用了基于提示词Prompt的轻量级大语言模型如GPT-3.5-Turbo或本地部署的Qwen2-7B进行“文本片段分类”。例如将客服对话片段分类为[用户查询]、[客服回复-解决方案]、[客服回复-询问信息]、[闲聊]等。同时使用NER命名实体识别工具如spaCy提取产品名、版本号、错误码等实体。智能分块Chunking这是与传统RAG差异最大的地方。我放弃了简单的固定长度重叠分块采用了基于结构的递归分块。策略优先按识别出的结构边界如章节标题、对话轮次进行分割。如果某个结构块过长再按语义使用句子分割器或固定长度进行二次分割。关键是为每个块保留丰富的元数据所属文档、父级标题、内容类型、包含的实体列表、在原文中的位置等。向量化与索引构建向量模型选用text-embedding-3-small或BGE-M3这类支持长文本且在多语言和领域表现良好的模型。关键点我们不仅为文本内容生成向量还可以选择为“文本内容关键元数据”如“标题安装故障类型解决方案实体产品A, 错误码500”生成一个增强向量用于特定场景的检索。向量数据库选用Milvus或PgVector如果与现有PostgreSQL生态结合紧密。除了存储向量必须利用其标量过滤能力。我们将所有结构元数据类型、实体、文档ID作为标量字段存入以便在检索时进行高效过滤。混合索引同时建立全文索引如Elasticsearch用于关键词召回与向量检索形成互补。在线服务管道问答查询理解与增强接收用户问题后首先进行查询分类和实体提取。例如识别出用户问题属于“故障排查”类并提取出“产品B”、“无法启动”等实体。结构化检索第一步候选召回。使用增强后的查询向量进行向量相似度搜索召回Top K个候选块例如K50。第二步结构过滤与重排。利用查询中识别出的类型和实体对候选集进行标量过滤。例如优先过滤内容类型为“解决方案”且实体包含“产品B”的块。然后可以结合BM25分数、元数据权重如赋予“标题”匹配更高权重、以及块之间的结构连贯性例如优先选择属于同一章节的连续块进行重新排序。上下文构建与提示工程将重排后的Top N个文本块连同它们的结构元数据按照一定的模板组织成提示上下文。模板会明确告诉大模型每个块的“角色”是什么。生成与后处理大模型基于富含结构信息的上下文生成答案。后处理可能包括引用溯源根据元数据标注答案来源、格式美化等。实操心得一结构信息的粒度权衡结构信息不是越多越好。最初我尝试为每个块标记十几种元数据导致索引膨胀和检索逻辑复杂。后来发现针对当前对话场景抓住内容类型、核心实体和父级标题这三类元数据就能解决80%的问题。关键在于分析你的问答场景中最常见的失败模式然后针对性地设计结构标签。3. 关键技术点实现与选型解析3.1 嘈杂数据下的结构识别规则、模型与混合策略处理噪声数据纯规则方法脆弱纯模型方法成本高且需要标注数据。我采用了一种“规则打底模型精修主动学习迭代”的混合策略。1. 基于规则与启发式的快速过滤正则表达式与关键词列表用于清除明显的噪声如版权声明、页眉页脚、特定联系方式模板。例如r^\\s*版权所有.*$。统计特征过滤剔除过短如15字符或过长如5000字符未经分段的文本块剔除符号占比过高的行。格式线索对于残留的Markdown或HTML标签如##, 将其转换为结构标记。2. 基于轻量级模型的分类与标注任务文本片段分类、命名实体识别NER、关系抽取可选。选型分类/NER优先考虑在特定领域数据上微调过的小模型如RoBERTa-base。如果领域通用spaCy的预训练管道是一个快速起步的选择。对于对话数据我使用了Conversational语料微调的BERT变体来区分用户和客服语句。零样本/少样本分类当标签体系不确定或数据未标注时使用大语言模型的function calling或structured output能力。例如让GPT-4根据定义好的JSON Schema输出片段的type和entities。虽然单次调用成本高但可用于生成初始训练数据。实施将清洗后的文本片段通常是一个段落或一个对话回合送入模型获得类型标签和实体列表。这里的一个技巧是对于长文档先进行初步分块再分类比直接分类整个文档准确率高。3. 主动学习循环将模型分类置信度低的样本自动放入一个待审核队列。开发一个简单的标注工具让领域专家定期审核队列中的样本并纠正。用新标注的数据定期微调模型形成闭环。这个过程能显著提升模型在特定数据分布下的表现。3.2 向量模型与数据库选型为结构化检索铺路向量模型选型考量上下文长度由于我们采用结构感知分块块的大小可能不固定需要模型支持足够长的上下文如8192 tokens。text-embedding-3-large和BGE-M3都支持长文本。领域适应性如果在专业领域如医疗、金融需要考虑在领域语料上继续训练Post-training或微调Fine-tuning嵌入模型。BGE系列提供了方便的微调脚本。多向量检索BGE-M3模型支持稠密向量、稀疏向量和多向量三种检索方式。对于结构化检索我们可以利用稀疏向量类似于关键词权重来强化元数据匹配。这是一个值得尝试的高级特性。实践选择在项目中我主要使用text-embedding-3-small因为其在通用任务上的性价比极高。在对特定行业术语召回要求高的场景我会用一批领域查询-相关文档对对BGE-M3进行轻量级Lora微调提升效果。向量数据库选型与索引设计为什么是MilvusMilvus专为向量搜索设计性能强劲尤其擅长处理十亿级向量。它强大的标量过滤功能与我们存储大量结构元数据的需求完美契合。其IVF_FLAT或HNSW索引能高效处理向量相似度搜索。表结构设计示例-- 概念上的表结构Milvus通过Collection和Field实现 Collection: knowledge_chunks Fields: id: String (主键) content: String (文本内容) content_vector: Float32[1536] (内容向量) doc_id: String (来源文档ID) chunk_type: String (e.g., problem, solution, reference) -- 内容类型 parent_headings: List[String] (父级标题路径如 [用户手册, 安装, 常见问题]) entities: List[String] (命名实体列表如 [ProductX, Error404]) metadata_json: String (其他原始元数据)检索时的过滤与混合搜索 Milvus允许在搜索时添加布尔表达式进行过滤。例如expr chunk_type solution and ProductX in entities先过滤再在过滤后的结果中做向量搜索或者先做向量搜索再对结果进行过滤排序。通常对于过滤后数据量仍然很大的情况“先搜后滤”更快对于过滤条件能极大缩小范围的情况“先滤后搜”更优。需要根据数据分布进行测试。3.3 检索策略与重排序融合语义与结构信号单纯的向量检索在嘈杂数据中容易“失焦”。我们需要融合多种信号。1. 混合检索Hybrid Search向量检索捕捉语义相似性。关键词检索BM25捕捉精确术语匹配对于产品型号、错误代码等关键词至关重要。使用Elasticsearch或Milvus2.3版本支持BM25实现。融合方法采用加权分数融合如score 0.7 * vector_score 0.3 * bm25_score或倒数融合排名RRF。RRF更鲁棒因为它不依赖于分数本身的绝对尺度。# 简化的RRF示例 def reciprocal_rank_fusion(results_list, k60): fused_scores {} for results in results_list: for rank, doc_id in enumerate(results): fused_scores[doc_id] fused_scores.get(doc_id, 0) 1 / (rank k) return sorted(fused_scores.items(), keylambda x: x[1], reverseTrue)2. 基于结构元数据的重排序 这是Structure-Aware的精髓。在混合检索得到初步排名后引入结构规则进行调序。规则重排类型优先级解决方案问题描述参考理论。实体匹配度完全匹配查询实体的块排名提升。结构完整性优先返回属于同一逻辑单元如相同parent_headings的连续块组而不是分散的块。学习式重排Learned Reranker 对于更复杂的场景可以训练一个轻量级的交叉编码器Cross-Encoder如bge-reranker-base来对查询-候选文档对进行精细打分。我们可以将结构特征如类型是否匹配、实体重叠度作为特征与文本对一起输入重排模型进行微调让模型学习结构重要性的权重。实操心得二检索效果的“黄金标准”不要盲目追求复杂的重排策略。建立一个由领域专家标注的小规模测试集约100-200个典型查询及其相关文档列表至关重要。任何检索策略的调整都以在这个测试集上的MRR平均倒数排名、RecallK或NDCG指标的提升为最终依据。否则很容易陷入主观感觉的误区。4. 基于Spring Boot与LangChain4j的实战实现4.1 项目环境搭建与核心依赖我们选择Spring Boot 3.x作为后端框架LangChain4j用于编排RAG流程Milvus作为向量数据库Elasticsearch用于关键词检索。Maven核心依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- LangChain4j 核心 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version0.31.0/version /dependency !-- LangChain4j Spring Boot 集成 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-spring-boot-starter/artifactId version0.31.0/version /dependency !-- Milvus Java SDK -- dependency groupIdio.milvus/groupId artifactIdmilvus-sdk-java/artifactId version2.3.6/version /dependency !-- Elasticsearch Java Client -- dependency groupIdorg.elasticsearch.client/groupId artifactIdelasticsearch-rest-high-level-client/artifactId version7.17.19/version !-- 注意版本与ES服务匹配 -- /dependency !-- 用于文本解析和NLP处理 -- dependency groupIdorg.apache.tika/groupId artifactIdtika-core/artifactId version2.9.1/version /dependency /dependencies配置文件application.ymlspring: application: name: structure-aware-rag-service langchain4j: open-ai: chat-model: api-key: ${OPENAI_API_KEY} model-name: gpt-4-turbo-preview # 或 gpt-3.5-turbo embedding-model: api-key: ${OPENAI_API_KEY} model-name: text-embedding-3-small dimensions: 1536 milvus: host: localhost port: 19530 collection-name: knowledge_chunks elasticsearch: host: localhost port: 92004.2 结构化知识库构建管道实现我们实现一个KnowledgeIngestionPipeline服务它封装了从原始文档到入库的完整流程。1. 文档解析与清洗组件Service public class DocumentProcessor { Autowired private TikaParser tikaParser; // 封装Apache Tika public ProcessedDocument parseAndClean(File file) { // 1. 原始解析 String rawText tikaParser.parseToString(file); // 2. 自定义清洗链 String cleanedText cleanText(rawText); // 3. 提取基础元数据如文件名、格式、作者等 Metadata metadata extractBasicMetadata(file); return new ProcessedDocument(cleanedText, metadata); } private String cleanText(String text) { // 应用一系列清洗规则 text removeHeaderFooter(text); // 基于正则的页眉页脚移除 text normalizeWhitespace(text); text filterShortLines(text, 10); // 过滤短行 // ... 更多领域特定规则 return text; } }2. 结构识别与智能分块组件 这是核心。我们实现一个StructureAwareChunker。Component public class StructureAwareChunker { Autowired private TextClassifier textClassifier; // 封装微调的文本分类模型 Autowired private NERService nerService; // 封装spaCy或BERT NER public ListTextChunk chunk(ProcessedDocument doc) { ListTextChunk chunks new ArrayList(); String fullText doc.getContent(); // 策略1: 优先按显式标题分割 (假设已通过解析器提取出标题列表) ListHeadingSegment headingSegments splitByHeadings(fullText); for (HeadingSegment segment : headingSegments) { // 策略2: 对每个标题下的内容如果过长再按语义句子分割 ListString subSegments splitBySemantic(segment.getContent(), 500); // 目标500字符 for (String subContent : subSegments) { // 对每个子块进行分类和实体识别 String chunkType textClassifier.classify(subContent); ListString entities nerService.extractEntities(subContent); // 构建富元数据的块对象 TextChunk chunk TextChunk.builder() .id(UUID.randomUUID().toString()) .content(subContent) .docId(doc.getId()) .chunkType(chunkType) .parentHeadings(segment.getHeadingPath()) // 如 [Chapter 3, Installation] .entities(entities) .metadata(/*...*/) .build(); chunks.add(chunk); } } // 如果没有标题结构则回退到递归字符分割 if (chunks.isEmpty()) { chunks recursiveSplitByCharacters(fullText, 500, 50); } return chunks; } }3. 向量化与索引入库组件Service public class VectorIndexingService { Autowired private EmbeddingModel embeddingModel; // LangChain4j注入 Autowired private MilvusService milvusService; // 封装的Milvus客户端 Autowired private ElasticsearchService esService; public void indexChunks(ListTextChunk chunks) { for (TextChunk chunk : chunks) { // 1. 生成向量 Embedding embedding embeddingModel.embed(chunk.getContent()).content(); chunk.setEmbedding(embedding.vector()); // 2. 准备Milvus插入数据 MapString, Object milvusData Map.of( id, chunk.getId(), content, chunk.getContent(), vector, chunk.getEmbedding(), doc_id, chunk.getDocId(), chunk_type, chunk.getChunkType(), parent_headings, chunk.getParentHeadings(), entities, chunk.getEntities() ); milvusService.insert(milvusData); // 3. 同时索引到Elasticsearch用于关键词检索 esService.index(chunk); } } }4.3 在线问答服务实现实现一个RAGQueryService处理用户查询。1. 查询理解Component public class QueryAnalyzer { public AnalyzedQuery analyze(String userQuery) { // 使用LLM或规则进行查询分类和实体提取 // 例如调用OpenAI的function calling String prompt 分析以下用户查询提取查询类型和关键实体。查询 userQuery; // ... 调用LLM获得结构化输出 // 假设返回{“type”: “troubleshooting, entities: [ProductZ, slow]} return new AnalyzedQuery(userQuery, “troubleshooting”, List.of(ProductZ, slow)); } }2. 结构化检索Service public class StructuredRetriever { Autowired private MilvusService milvusService; Autowired private ElasticsearchService esService; Autowired private RerankerService rerankerService; public ListRetrievedChunk retrieve(AnalyzedQuery query) { // 1. 混合召回 ListRetrievedChunk vectorResults milvusService.vectorSearch(query.getOriginalQuery(), 50); ListRetrievedChunk keywordResults esService.keywordSearch(query.getOriginalQuery(), 50); // 2. 融合 (例如使用RRF) ListRetrievedChunk fusedResults reciprocalRankFusion(vectorResults, keywordResults); // 3. 结构过滤 (可选也可在向量搜索时通过表达式完成) ListRetrievedChunk filteredResults fusedResults.stream() .filter(chunk - isRelevantByStructure(chunk, query)) // 例如类型匹配或实体包含 .collect(Collectors.toList()); // 4. 学习式重排 (如果有训练好的重排器) ListRetrievedChunk finalResults rerankerService.rerank(query.getOriginalQuery(), filteredResults); return finalResults.subList(0, Math.min(8, finalResults.size())); // 返回Top N } private boolean isRelevantByStructure(RetrievedChunk chunk, AnalyzedQuery query) { // 简单规则如果查询类型是“troubleshooting”则优先“solution”类型的块 if (troubleshooting.equals(query.getType())) { return solution.equals(chunk.getChunkType()) || chunk.getEntities().containsAll(query.getEntities()); } return true; } }3. 提示构建与答案生成Component public class AnswerGenerator { Autowired private ChatLanguageModel chatModel; public String generateAnswer(String query, ListRetrievedChunk contexts) { // 构建富含结构信息的提示词 StringBuilder contextBuilder new StringBuilder(请根据以下参考信息回答问题。参考信息已按类型组织\n\n); for (RetrievedChunk ctx : contexts) { contextBuilder.append(String.format([类型%s | 标题%s]\n%s\n---\n, ctx.getChunkType(), String.join( - , ctx.getParentHeadings()), ctx.getContent())); } String systemPrompt 你是一个专业的助手请严格依据提供的参考信息回答问题。参考信息中的[类型]和[标题]有助于你理解内容的结构和重点。如果信息不足请明确说明。; String userPrompt String.format(问题%s\n\n参考信息\n%s, query, contextBuilder.toString()); // 调用LLM String answer chatModel.generate(userPrompt); return answer; } }4. REST API端点RestController RequestMapping(/api/rag) public class RagController { Autowired private RAGQueryService ragService; PostMapping(/query) public ResponseEntityAnswerResponse query(RequestBody QueryRequest request) { String answer ragService.answerQuestion(request.getQuestion()); // 可以在这里附加检索到的来源chunk ID等信息 return ResponseEntity.ok(new AnswerResponse(answer)); } }5. 效果评估、问题排查与优化经验5.1 如何评估Structure-Aware RAG的效果评估不能只靠“感觉”需要建立多维度的评估体系。1. 检索阶段评估召回率RecallK对于一组测试问题标准答案相关的文档出现在Top K个检索结果中的比例。这是衡量检索系统是否“找得全”的核心指标。Structure-Aware的目标是在相同K下提升召回率尤其是召回高质量、结构完整的文档块。平均倒数排名MRR衡量相关文档排名的指标。提升MRR意味着系统能把更相关的文档排到更前面。人工评估检索结果相关性随机抽样一批查询让评估人员对Top 5检索结果的相关性打分如1-5分。重点关注结构感知是否减少了噪声片段的混入。2. 生成阶段评估事实准确性Factual Accuracy将生成的答案与标准答案对比检查关键事实如日期、数字、步骤是否一致。可以借助LLM本身进行评估如使用GPT-4作为裁判但需设计严谨的提示词。答案相关性Answer Relevance生成的答案是否直接、完整地回应了问题。引用质量Citation Quality如果系统支持引用溯源检查引用的来源块是否真正支持生成的陈述。3. 端到端评估人工整体评分模拟真实用户对问答结果从“准确性、有用性、流畅性”等方面进行综合打分1-5分。这是最可靠的终极指标。A/B测试在线上环境将一部分流量导向新Structure-Aware系统一部分导向旧系统对比关键业务指标如“问题解决率”、“用户满意度评分”、“转人工率”等。5.2 常见问题、排查与优化技巧在开发过程中我遇到了不少典型问题以下是排查思路和解决方案。问题1检索结果似乎没有利用到结构信息噪声依然很多。排查检查结构识别环节查看chunk_type和entities字段的赋值是否正确。抽样一些数据人工验证分类和NER的结果。检查向量数据库过滤表达式确保在Milvus搜索时过滤表达式语法正确且字段名匹配。例如expr chunk_type solution。检查混合检索权重如果关键词检索权重过高可能会拉回大量包含关键词但无关的噪声。尝试调整向量检索和关键词检索的权重比例或改用RRF。优化细化结构标签如果“solution”标签下仍然混杂了不同内容考虑进一步细分如“solution_step_by_step”, “solution_cause_analysis”。增强查询理解提升查询分类和实体提取的准确率。考虑使用少量标注数据微调一个小模型专门用于查询意图分类。问题2生成答案有时会“无视”结构提示依然胡编乱造。排查检查提示词模板确保提示词中明确指令模型关注[类型]和[标题]。可以尝试更强烈的指令如“你必须主要依据[类型解决方案]下的内容来生成回答步骤”。检查检索上下文质量即使有结构标签如果Top 3的检索块本身信息不足或矛盾模型也难以生成好答案。需要回溯检查检索阶段。检查模型本身尝试换用更强大的模型如从gpt-3.5-turbo切换到gpt-4看是否改善。如果必须使用小模型可能需要更严格的上下文过滤。优化实现“引用溯源”要求模型在生成答案时为每个主要陈述注明来源块的ID。这不仅能增加可信度也能反向验证模型是否真的参考了指定内容。可以通过system prompt强制要求并在后处理中解析输出。上下文压缩与摘要如果检索回的上下文过长可以在喂给LLM前先让另一个LLM对每个块或相关块组进行摘要保留核心信息去除冗余。问题3系统延迟较高响应慢。排查性能剖析使用APM工具如SkyWalking, OpenTelemetry定位耗时环节。通常是向量检索/混合检索、LLM API调用、或复杂的重排模型。检查索引Milvus的向量索引类型如HNSW参数是否优化efConstruction和M参数影响构建和搜索的权衡。检查缓存频繁出现的相似查询是否做了缓存优化异步与批处理对于文档入库的向量化过程采用批处理异步进行。对于查询中的LLM调用考虑是否可以使用流式响应先返回部分结果。精简重排模型如果使用学习式重排器确保模型足够轻量如bge-reranker-base而非large。可以考虑将重排模型部署在GPU上或使用量化版本。设置超时与降级为检索、LLM调用设置合理的超时时间。当某个环节失败时有降级方案如跳过重排直接使用向量检索结果。问题4处理特定领域术语或新词时效果差。排查检查嵌入模型和NER模型是否在这些术语上表现不佳。可以查看这些术语的向量是否与相关概念距离过远。优化领域微调嵌入模型收集领域内的查询正例文档对对BGE等可微调模型进行继续预训练或对比学习微调。扩展实体词典将领域内的专有名词、产品型号等加入NER模型的词典或作为外部词典进行匹配补充。同义词扩展在查询时自动将专业术语扩展为常见的同义表述增加召回机会。实操心得三持续迭代的飞轮Structure-Aware RAG不是一个一劳永逸的项目。必须建立一个数据飞轮日志收集记录所有用户查询、检索到的上下文、生成的答案以及用户的反馈显式的评分或隐式的后续行为。失败案例挖掘定期分析回答不佳或收到负面反馈的案例。是检索错了还是结构识别错了还是生成错了数据标注与模型更新针对性的失败案例进行数据标注用于优化结构识别模型、查询分类模型或重排模型。评估与上线将优化后的模型重新评估通过A/B测试验证效果后全量上线。 这个循环是系统持续进化的核心动力。
返回列表