RAG系统全流程与关键要素解析

发布时间:2026/7/22 5:56:48
RAG系统全流程与关键要素解析 一、离线阶段把文档变成能被查到的小块1. 文档采集就是把各处的原始材料收过来。常见来源本地 PDF / Word / Excel、Confluence、Notion、数据库表里的大字段、对象存储S3/OSS里的文件Python 栈requests 定时任务爬内部知识库oss2阿里云/boto3AWS拉文件增量同步一般靠last_modified时间戳或 MD5 去重 生产坑一定要给每个文档挂source_url update_time doc_id后面排错全靠它。2. 解析清洗把 PDF/Word 变成纯文本并且把页眉页脚、乱码、导航栏这些噪音干掉。Python 库PDFpymupdf快、pdfplumber表格友好、unstructured一站式但重Wordpython-docxHTMLbeautifulsoup4 自己写正则去 nav/footer清洗常见操作连续换行压成 1 个Unicode 乱码\ufffd替换或丢行表格转键值对文本比如| 日期 | 金额 | → “日期2024-03-01金额5000” 参数级经验pymupdf开sortTrue能让阅读顺序更接近人眼表格别硬拆留着给后面的分块当整体更稳3. 分块Chunking——真正影响效果的第一杠杆不分块 → 文本太长塞不进 embedding 模型 检索精度炸。三种主流切法① 固定长度切最常用Baselinefromlangchain.text_splitterimportRecursiveCharacterTextSplitter splitterRecursiveCharacterTextSplitter(chunk_size512,# token 数或字符数中文 512≈380 tokenchunk_overlap80,# 前后重叠防句子被腰斩separators[\n\n,\n,。,,, ])chunk_size中文场景384–768是甜区太小上下文不够太大召回 noise 多separators顺序很关键——优先在段落切再句子再逗号② 语义切用\n##标题、###这种 Markdown 结构先切大块再递归适合技术文档、API 文档③ 按引用单元切最强但最贵一段 紧跟的表格 下面的 2 条 example 绑一起需要规则或小规模标注 生产建议标题 递归字符组合先用80% 场景够剩下的用 Bad Case 复盘去修。每块要挂的元数据{chunk_id:docA_0032,doc_id:xxx,title:退款规则,section:第3章,chunk_index:32,text:...}4. 向量化Embedding把文字变成一串浮点数方便后面算相似度。模型选型Python 可调用的中文首选bge-large-zh-v1.5、bge-m3支持 8192 上下文开源推理sentence-transformersfromsentence_transformersimportSentenceTransformer modelSentenceTransformer(BAAI/bge-large-zh-v1.5)embmodel.encode([今天天气不错],normalize_embeddingsTrue)API 派openai.embeddings.create(modeltext-embedding-v3) 参数级normalize_embeddingsTrue→ 点积 余弦省算力batch_size32~64太长爆显存bge 系列要在 query 前面拼为这段文本生成检索向量官方 trick5. 写入向量库向量库本质是存向量 存原文 能按向量算近邻。选项小项目faissIndexHNSWFlat够用生产milvus、elasticsearch8.x 自带 dense_vector、pgvectorMilvus 建表示例frompymilvusimportCollectionSchema,FieldSchema,DataType fields[FieldSchema(chunk_id,DataType.VARCHAR,max_length128,is_primaryTrue),FieldSchema(emb,DataType.FLOAT_VECTOR,dim1024),FieldSchema(text,DataType.VARCHAR,max_length4096),] HNSW 参数影响召回率和延迟M16, efConstruction128→ 建索引慢但查得准efSearch64~256→ 查的时候越大越准越慢线上一般 64 起步二、在线阶段用户问一句系统跑这一圈1. Query 预处理用户打的字不能直接用。常见操作拼写纠错pycorrector长度截断200 字基本是用户在贴文档要提示意图识别闲聊 / 查知识 / 让 AI 写代码 → 分流query rewrite把它这个指代消掉拼上文变成独立问句2. 检索Retrieval拿 query 的 embedding 去向量库里找最像的几块。resultscollection.search(data[query_emb],limit8,# top-koutput_fields[text,title]) 检索策略升级纯向量→ 召回高但可能跑偏向量 关键词Hybrid用 BM25 再算一次加权融合RRF 算法metadata 过滤先where doc_type政策再查能砍一半噪声3. Rerank重排序——性价比最高的提升点向量库返回的 8 条是按向量距离排的但不等于对回答有用。Rerank 用交叉编码器把(query, chunk)一对一对塞进去打分。fromFlagEmbeddingimportFlagReranker rerankerFlagReranker(BAAI/bge-reranker-v2-m3,use_fp16True)pairs[(query,c[text])forcinchunks]scoresreranker.compute_score(pairs)# 越大越相关一般用bge-reranker-v2-m3中文强3B 以下向量库取 top-20 → rerank → 留 top-5 进 prompt延迟rerank 5 条 ≈ 20–50 ms / 条GPU4. 组装 Prompt把 rerank 后的 chunk 拼进上下文再包一层指令。promptf 以下是参考资料按相关度排序{ctx}用户问题{query}回答要求 1. 仅基于上述资料回答资料不够就说资料中未提及 2. 不要编数字、不要编条款 3. 每条事实后用 [1][2] 标注来自哪段资料 关键约束能挡掉 60% 幻觉“不知道就说不知道”“禁止编造”强制 citation 格式 → 后面引用展示才能做5. 调用大模型生成respclient.chat.completions.create(modelgpt-4o-mini,# 或 qwen-max / deepseekmessages[{role:user,content:prompt}],temperature0.1,# 知识问答压低0~0.3max_tokens1024)知识问答temp0~0.3创意才上 0.7max_tokens别省中文回答 800 很常见三、生成后容易被当边角料但其实很值钱的几步1. 引用展示生成时让模型吐[1][3]→ 前端把编号映射到chunk_id→ hover 显示原文片段。实现细节每 chunk 在 prompt 里写成[1] 文本...后端校验模型标的[x]有没有越界模型偶尔编编号2. 敏感词过滤两层规则层acora/flashtext做 Aho–Corasick 多模式匹配身份证、手机号、竞对公司名模型层过一次小分类器“这段会不会泄密”3. 日志记录至少记{trace_id:...,query:...,retrieved_chunk_ids:[...],rerank_scores:[...],llm_model:...,latency_ms:{...},answer:...,user_feedback:null}trace_id串起检索 → rerank → 生成排错唯一入口。4. 用户反馈收集 / 两个按钮踩的时候弹一句哪里不对可选输入框反馈直接进 Bad Case 池四、四个真正常量再点一下杠杆改了之后感受最明显的场景分块质量答案一半对一半断 → 看是不是块切在句子中间Embedding 模型同义词召回不上来 → 换 bge-m3 或加 query 前缀检索策略召回一堆不沾边的 → 上 hybrid metadata 过滤Prompt 约束 评估闭环幻觉、编条款 → 强化不知道就说 用 Bad Case 反哺五、评估闭环怎么搭很多人 RAG 上线即停半年后效果还是那样。评估闭环 让系统自己长记性。1. 评估分三层① 离线基准集Human Labeled攒 200–500 个真实 query每个配query期望答案人写必须召回的 chunk_id 列表可选每次改分块 / embedding / rerank 前跑一遍看指标动没动② RAGAS 自动指标不用人工看每一条RAGAS 四个核心指标Python 直接跑Faithfulness忠实度回答里每一句话能不能被上下文撑住 → 测编没编Answer Relevance回答相关性回答是不是在答这个问题 → 测飘没飘Context Precision上下文精度召回的 chunk 里相关的是不是排前面 → 测 rerankContext Recall上下文召回率该召回的 chunk 有没有在里 → 测检索fromragasimportevaluatefromragas.metricsimportfaithfulness,answer_relevancy,context_precision,context_recall evaluate(datasetyour_dataset,# 要含 query / answer / contextsmetrics[faithfulness,answer_relevancy,context_precision,context_recall],llmgpt-4o-mini# ragas 自己会再调一次 LLM 当 judge) 生产用法Faithfulness 0.85 → 重点看 prompt 约束 分块Context Precision 低 → rerank 没生效或 top-k 太大Context Recall 低 → embedding / 分块 / 索引参数问题③ 在线反馈User Signal 率、追问率、Session 内不对应该是…的出现频次每周把 样本捞 50 条人工标根因2. Bad Case 复盘模板字段说明trace_id日志主键query用户原问召回的 chunksID标题一眼能看漏没漏模型回答贴原文问题归类召回漏 / 召坏 / rerank 排低了 / 生成编 / 分块碎根因猜测比如chunk 把’退款条件’和’运费规则’切一块噪声盖过信号改哪一步分块规则 / embedding 换模型 / rerank 阈值 / prompt验证结果改完同一 query 再跑一次faithfulness 从 0.7 → 0.92六、全链路一张图

相关新闻

最新新闻

日新闻

周新闻

月新闻