RAG 实战与踩坑:交通法规智能问答助手 RAG 实战与踩坑交通法规智能问答助手从四份官方 PDF 到一个带引用溯源、敢拒答、支持多轮追问的智能问答系统——本文记录这条 RAG 链路的完整实现、全部踩坑与对应优化。语料为四部交通法规《道路交通安全法》124 条、《实施条例》115 条、《事故处理程序规定》114 条、《记分管理办法》37 条最终知识库 453 个结构化 chunk基于 Spring AI 2.0.1 pgvector 自研混合检索管线构建。文中所有坑均为实际踩中并修复的问题标注了完整因果链与排查方法可直接作为同类项目的避坑清单。视频演示目录1. 全流程总览2. 知识库构建ETL 流水线2.1 结构探测2.2 文本抽取与清洗2.3 目录剥离2.4 章/节/条状态机解析2.5 分块策略本流水线的灵魂2.6 元数据与 embedText 组装2.7 校验贯穿流水线不是收尾一步2.8 合并与版本管理3. 向量库摄取3.1 幂等设计4. 查询理解层路由 多查询改写4.1 一次调用三合一4.2 核心 prompt4.3 踩坑实录静默降级掩盖了配置错误5. 检索层混合检索 → RRF → LLM 精排 → 剪枝 → 父子折叠5.1 为什么混合5.2 BM25 的实现选型5.3 RRF 融合与多查询稀释5.4 LLM 精排5.5 精排后剪枝5.6 父子折叠5.7 聚合问法直达6. 生成层法律场景的防幻觉铁律7. 多轮会话记忆8. 效果验证与分诊方法论9. 踩坑总表10. 方法论总结11. 已知局限与演进方向12. 附录文件清单与技术栈1. 全流程总览PDF ──► 结构探测 ──► 文本抽取与清洗 ──► 目录剥离 ──► 章/节/条状态机解析 ──► 分块普通条 列举条按项切分──► 元数据与 embedText 组装 ──► 校验 ──► 版本管理 ──► 向量库摄取幂等 │ 查询管线 ──► 会话历史 ──► 查询理解意图路由 多查询变体 ──► 短路链闲聊 / FAQ 缓存 / 聚合问法直达 ──► 混合检索向量 BM25 → RRF → LLM 精排 → 剪枝 → 父子折叠 ──► 受约束生成引用标注 拒答纪律 ──► 响应answer citations 溯源 会话记忆写回两条核心原则贯穿全程法条类文档按结构切不按 token 切——章/节/条/项就是天然的语义边界任何固定长度滑窗在这类语料上都是错的。检索质量决定上限生成只是守住下限——实践中的 RAG 效果问题八成出在检索侧而非模型侧。各场景的端到端成本实测场景LLM 调用检索耗时纯问候00100ms闲聊1 次小模型0~1sFAQ 命中1 次小模型路由0~1s聚合问法“记3分有哪些”1 小 1 大零向量~4s常规法规咨询1 小 2 大3 变体 × 2 路6~12s2. 知识库构建ETL 流水线2.1 结构探测写解析器之前先摸清排版对每份 PDF 先跑一遍探测脚本统计页数、条号样式行数、章/节样式行数、页码格式、目录有无、列举项标记分布。统计数要与该法规的公知条数对得上对不上就是解析有漏不带病进入下一步。这条纪律的必要性来自实战——同一个第X条在不同官方 PDF 里至少有三种排版变体实例后果条号独立成行道交法、实施条例、记分办法最友好条号与正文同行事故处理规定“第一条为了规范…”正则若只匹配整行一条都切不出同文档混排事故处理规定第一百一十二条又独立成行单一正则必漏章标题从词中间劈开“第六章调” “查”两行章名解析成调节标题混排“第一节一般规定”合并vs “第二节”独立解析逻辑需双形态兼容页码样式1全角vs- 1 -半角带空格清洗正则不全则残留噪音2.2 文本抽取与清洗PyMuPDF 逐页抽文本 → 去空行 → 去页脚页码。四个要点先判断文本型还是扫描型政府公文常见扫描件get_text()抽出空内容即是信号必须转 OCR 版面分析路线页码正则覆盖全角/半角/长破折号^[–—-]\s*\d\s*[–—-]$PDF 抽取会在数字与汉字间插空格抽出的是一次记12 分——所有涉及数值的正则都要写成记\s*(\d)\s*分。本项目记分值提取第一版就因这个空格全部失配保留原始行序不做任何智能合并——结构信息就藏在行与行的关系里。2.3 目录剥离目录会重复所有章/节标题甚至条号。不剥离的直接后果是检索时先召回目录而不是条文——“法律责任四个字在目录页和正文标题各出现一次目录页更靠前、更短、更像答案”。利用法条类文档的特性定位正文起点目录只列标题、不列条号正文因此首个行首第X条必在正文。从它向前回溯找到所属章标题行即为正文起点。2.4 章/节/条状态机解析单遍扫描维护(当前章, 当前节, 当前条)三个状态变量。四个关键防御每个都对应一次真实事故章切换时必须重置节——否则第九十一条会带着第四章高速公路的特别规定的残留节信息跨到法律责任章。状态机最常见的 bug 就是切换了父状态、忘了清子状态。条号严格连续性校验1…N 不缺不重——正文里有大量依照本法第X条式引用行首出现时会被误判成新条目。序列校验期望值 上一条 1是唯一可靠的兜底。章/节标题短行聚合——“第六章调”“查要拼回调查”停止条件是遇到下一个章/节/条样式行或标题超长。条号与正文同行时——条号取第X条前缀、其余为正文与独立成行形态用同一正则统一处理。一次真实事故复盘条号序列判断最初用了records[-1]已入列的最后一条而当前条还暂存在cur未入列——期望值恒差 1124 条全部被当成序列异常的引用吞进第一条。教训状态机的当前对象在哪个变量里写完立刻用真实数据跑序列校验失败会当场爆炸而不是静默出错——这正是校验的价值。2.5 分块策略本流水线的灵魂普通条一条 一个 chunk。固定 512 token 滑窗会把条文拦腰截断第九十一条的酒驾处罚切两半。按条切分后实测 chunk 长度 15~517 字符、平均约 120天然落在 embedding 舒适区。列举条按项切分 前导句继承 父子双索引。下列…一二…式列举条是检索黑洞记分管理办法实测通道被压制的原因实测数据向量第十一条 648 字符塞 15 个项多主题稀释——避让行人只占全文 0.9%与查询的相似度被均值拉平BM25648 ≈ 5×avgdlb0.75 的长度归一化把 tf 饱和项压掉约5 倍解法三要素缺一不可一项一 chunk三驾驶机动车不按规定使用灯光的独立成 chunk40~60 字符向量不再稀释BM25 反而因短于 avgdl 获得归一化加成前导句继承项文本本身不含记分值脱离前导句就是语义残片。item 的 embedText 必须拼上…有下列交通违法行为之一一次记1分——否则灯光扣几分召回了也答不出分值父条保留双索引记1分的情形有哪些这种聚合问法的正确答案单元是整条纯 items-only 的 small-to-big 只会召回单项。父条同时入索引各管一类问法。切分安全阀项序号必须从一开始严格连续不连续即判定为行内括号注释、整条保留不切——防止误切非列举结构。切分效果的量化记分管理办法 37 条 → 100 个 chunk7 条列举条切出 63 个 item全库 453 chunk。2.6 元数据与 embedText 组装metadata schema 决定知识库的检索上限{id:rtpoints2021-art-0011-it-07,kb:traffic-law,law:道路交通安全违法行为记分管理办法,lawCode:rtpoints2021,lawAbbr:记分管理办法,version:公安部令第163号 2021-12-27发布 2022-04-01施行,chapter:记分分值,section:null,article:第十一条,articleNo:11,chunkType:item,subItemNo:7,subItem:七,parentArticleId:rtpoints2021-art-0011,points:3}设计要点id 用稳定业务 idlawCode-art-XXXX[-it-YY]修法重刷时按 id 幂等 upsertembedText 带上下文前缀法名版本章节条号前导句跨法规检索时 embedding 模型能感知这是哪部法的哪一条条号跨法规不唯一道交法 82 条 ≠ 实施条例 82 条——精确查询必须带 lawCodepoints记分值入 metadata从前导句抽取扣1分有哪些变成零向量开销的精确过滤隐蔽关联坑item 与父条共享articleNo按条号过滤时必须限定chunkType article否则 top-1 随机取到 item返回半句残片。2.7 校验贯穿流水线不是收尾一步校验抓什么条号序列 1…N 连续引用误判、解析漏条章节归属抽查章切换节残留关键条目人工抽查酒驾/逃逸/记分值等已知答案的条元数据与原文比对id 全局唯一跨法规 lawCode 冲突长度分布min/max/avg 是否落在 embedding 舒适区内容级断言如带分值的 item 其 embedText 必含’一次记X分’原则校验失败要当场爆炸assert/异常。静默容错等于把错误灌进向量库事后无解。2.8 合并与版本管理法律场景特有per-law 文件 全量合并chunks_lawcode.jsonl各自独立修法后单法重刷秒级完成旧版本打 deprecated 标记、不物理删除——历史案件要查当时有效的版本合并排序键(lawCode, articleNo, subItemNo)父条在前、项紧随人工审查时上下文连贯。3. 向量库摄取3.1 幂等设计Document.builder().id(chunk.id)// ETL 稳定业务 id.text(chunk.embedText)// 上下文前缀版文本而非裸 content.metadata(metadata)// 全量元数据供过滤.build();幂等三层rebuildfalse默认启动时检测已有条数 0 即跳过避免每次重启全量重嵌入rebuildtrue按kbtraffic-law删旧重灌批写失败重试一次仍失败中止启动——宁可启动失败不留半库静默上线存储选型pgvector 为主库元数据过滤强、可事务、与业务库同实例法规与用户记忆分表vector_store_law/vector_store——HNSW 索引全表构建混表时一类数据挤占另一类的召回名额且 embedding 列维度建表即固定共表会锁死两类数据的模型选型null 元数据不写入pgvector 的 filter 表达式对 null 值行为不可预期。4. 查询理解层路由 多查询改写4.1 一次调用三合一用户查询的两大顽疾——问得烂口语化、关键词化和多轮指代“那第二个方案呢”——在这一层统一解决。设计上一个 LLM 调用同时完成三件事输入问题 最近 8 条历史小模型温度 0 输出{ intent: chat → 闲聊/寒暄不进检索管线顺带生成接待回复0 次主模型调用 intent: search → 1~3 个检索查询变体 ① 补全指代那酒驾呢 → 酒后驾驶机动车如何处罚 ② 术语归一直行道转弯 → 不按导向车道行驶 ③ 处罚聚焦…记分 罚款 }工程细节正则快速路径纯问候“你好/谢谢/再见”连小模型调用都省掉直接短路原问题始终兜底保留在变体列表首位变体去重 上限 3 个每变体 一次 embedding 调用per-request 指定小模型 温度 0路由是简单任务用生成级大模型是浪费温度 0 保证确定性。4.2 核心 prompt术语归一是召回质量的关键查询变体设计源于一个实测痛点用户口语在直行道转弯与法条术语不按导向车道行驶之间存在词形鸿沟——直接拿口语检索两路都打不中记分条款。术语归一变体让检索同时覆盖口语与法条两种表述空间。4.3 踩坑实录静默降级掩盖了配置错误多查询方案上线后效果毫无变化翻日志才发现[路由] 路由失败降级为 search原问题: 400: rejected by an internal MaaS component完整因果链全局 default options 含 thinking: disabled为降低生成延迟所设 → per-request optionsmodelflash 小模型合并时未指定字段继承 default → 该 flash 模型不接受 thinking 参数 → 400 → 路由降级为原问题直检 → 多查询从未运行修复双保险换用兼容该参数的轻量模型 路由调用显式.extraBody(Map.of())清空继承——参数集自包含不再依赖全局配置有什么。教训本文最重要的一条降级设计保证可用性的同时会掩盖配置错误——这次 400 静默降级了三轮对话才被发现。生产要求降级必须配告警至少 ERROR 级日志 失败率指标静默可用和静默错误只有一线之隔。附带一坑Spring AI 2.0 的.options(...)接收Builder 本身而非build()产物与直觉相反编译期才会暴露。5. 检索层混合检索 → RRF → LLM 精排 → 剪枝 → 父子折叠5.1 为什么混合两路各自的盲区查询向量路BM25 路“喝了杯啤酒开车怎么罚”口语✓ 语义泛化命中✗ 字面打不中“不按导向车道行驶 记3分”术语数值✗ 语义距离一般✓ 精确命中“礼让行人” vs 原文避让行人词形鸿沟✓ 近义可容✗ 完全打不中法条类语料专有名词、条号、金额密集纯向量区分度低纯关键词又容不了口语。混合是标配融合用 RRF。5.2 BM25 的实现选型PG 原生无 BM25中文还需 zhparser 扩展。453 条规模直接应用内存索引bigram 分词闯红灯→[闯红,红灯]无词典中文检索的经典方案查询与文档同分词器保证词表对齐构建 100ms、单查 1ms零环境依赖。两个实战调参b 参数 0.75 → 0.4法条多为长列举段强长度归一会系统性压低它们的排名——它们恰恰是高频查询的答案载体。子切分后此问题大幅缓解但保留调低的 b 作为防御规模化路径语料过万换 ES / ParadeDB接口语义不变。5.3 RRF 融合与多查询稀释// 跨查询、跨路累计score(d) Σ 1/(60 rank_i)for(inti0;ivectorHits.size();i)rrf.merge(vectorHits.get(i).id(),1.0/(RRF_Ki1),Double::sum);for(inti0;ibmAll.size();i)rrf.merge(bmAll.get(i).doc().id(),1.0/(RRF_Ki1),Double::sum);向量路多变体并行调用embedding HTTP 客户端线程安全延迟 ≈ 单查询。踩坑多查询的副作用3 变体 × 2 路 6 个排名列表RRF 名次被多路稳定中上位的噪声文档累积占据如某个变体与道交法某条原文逐字相似 → 多路霸榜真正相关的条款只被 1~2 个变体召回排不进融合前 10精排根本看不到它。修复精排候选 10 → 15让精排 LLM 有机会纠正 RRF 的名次偏差。教训多查询是用检索成本换召回覆盖融合层的名次稀释会抵消部分收益——扩候选 强精排是对冲手段。5.4 LLM 精排bi-encoder向量召回快但粗精排逐对评估该条文是否回答该问题——这是 LLM 的强项对话题相关但答非所问的片段混合检索最典型的假阳性区分度远高于字面/向量相似度。你是法规检索结果重排器。根据【查询】评估每条【候选法条】的相关度0-10 整数 10 条文直接回答该问题 7-9 高度相关 4-6 部分相关 0-3 无关 话题相近但答非所问也算无关三个关键设计以用户原始问题为基准不是变体——评估是否回答用户的真实意图打分覆盖校验LLM 漏给任何候选打分 → 整体判为不可信 → 降级 RRF 序不部分信任失败降级精排是增强不是依赖降级时 RRF 序照常返回。规模化路径换专用 cross-encoderbge-reranker / gte-rerank延迟从秒级降到百毫秒级——精排器是独立组件换实现不动管线。5.5 精排后剪枝topK 固定取满的隐患精排 0% 的条文也被硬凑进上下文——纯费 token 还稀释模型注意力。resultsorted.stream().filter(h-h.score()RERANK_MIN_SCORE)// 0.4精排 4 分以下视为无关.limit(topK).toList();实测某查询 6 条 → 3 条进生成上下文 token 省 40%。全部候选低于阈值时返回空 → 上层拒答——这是防幻觉期望的行为检索管线诚实地说没有可靠依据而不是拿低质条文硬凑。5.6 父子折叠ETL 侧按项切分2.5 节的检索侧收尾// 同条 ≥2 个 item 命中 → 整条语境问法 → 替换为父条文本超集、语境完整// 单 item 命中 → 保留 item引用粒度细到第十一条第七项MapString,LongitemCountByParenthits.stream().filter(h-item.equals(h.chunkType())h.parentArticleId()!null).collect(groupingBy(Hit::parentArticleId,counting()));已知小瑕疵折叠插入的父条与独立召回的父条可能并存citations 同条两次不影响回答去重边界待微调。5.7 聚合问法直达记3分的有哪些情形的正确答案单元是父条整条走混合检索既慢又可能召回零散 item。正则识别问法 →points元数据内存过滤 → 直达父条零向量开销privatestaticfinalPatternAGGREGATE_POINTSPattern.compile((?:一次)?记\\s*(\\d{1,2})\\s*分[^。?]{0,12}?(?:情形|行为|违法|有哪些|哪几));分值无命中时如记5分不存在回落混合检索由条文支撑拒答不硬编没有记5分这类答案。6. 生成层法律场景的防幻觉铁律你是道路交通安全领域的法规问答助手。知识库包含四部法规效力从高到低 1.《中华人民共和国道路交通安全法》(2021修正) 2.《中华人民共和国道路交通安全法实施条例》(2017修订) 3.《道路交通事故处理程序规定》(公安部令第146号) 4.《道路交通安全违法行为记分管理办法》(公安部令第163号) 回答规则 1. 只依据提供的条文原文回答禁止编造或推测法条内容 2. 涉及处罚/义务的表述必须逐字引用条文并在句末标注【法名简称 第X条】 3. 多部法规均有规定时优先引用效力层级高的程序性/细节性问题 如事故处理流程、记分值引用对应专门规定并说明各法分工 4. 若提供的条文中没有对应依据明确回答知识库内无对应条文不猜测、不外推四个关键设计拒答话术与指令一字不差“知识库内无对应条文”——两处一致模型行为才不漂移引用格式与 citations 数据对应answer 内【法名简称 第X条】 [n] 编号前端渲染溯源卡片思考模式全局关闭生成模型为思考型实测关思考后中等复杂问题 19.9s → 4.7s思考 token 877 → 0。对话场景不需要深度推理生成超时 降级90s 显式超时防线程占满曾实测上游故障时请求挂 243 秒超时返回友好提示而非裸 500。零命中拒答发生在检索侧源头防线检索为空直接返回知识库内无对应条文没有依据就不生成。7. 多轮会话记忆复用主对话链路的整套热层设施Redis、ChatMemory、20 条滑动窗口——零新增中间件会话命名空间域隔离convId 派生加law:前缀法规会话与闲聊会话即使用户传相同标识也互不污染手动管理读写时机而非挂官方 Advisor检索必须发生在生成之前而查询改写需要先读历史——Advisor 的固定时序满足不了读历史→改写→检索→生成的编排需求闲聊/拒答/缓存命中也写记忆上下文连续性对后续追问的改写质量有价值。8. 效果验证与分诊方法论8.1 正向用例全链路生效Q: 在高速上占用应急车道扣几分 A: 一次记6分。【记分管理办法 第十条】 item 级命中精排 1.0 满分前导句继承使回答自带记分值 并自动补充实施条例第八十二条的上位法禁止性规定8.2 知识边界用例正确的拒答Q: 在直行道转弯扣几分 A: 该行为违反实施条例第五十一条未按所需行进方向驶入导向车道 记分办法中无对应记分条款无法回答扣几分。这不是检索失败——全部 453 个 chunk 中导向车道仅出现于实施条例义务性规定记分办法确实没有普通道路不按导向车道的记分条款2022 新规已取消该记分仅保留高速公路/快速路场景。系统定位了违法行为、诚实说明记分无据——比编一个扣3分正确得多。8.3 分诊方法论判断效果差之前先分三类对策完全不同诊断看什么对策检索没召回citations 为空或不含目标条文查分块/embedding/查询变体召回了但排序差目标条文在候选里但被剪枝/排后调精排候选数、剪枝阈值知识边界外的正确拒答库里确实没有对应条文ETL 补数据不是检索问题深层认知否定性知识“某行为不记分”没有条款载体RAG 永远检索不到不存在的东西。此类知识只能在 ETL 侧显式补充通则性说明 chunk。8.4 评测集所有决策的裁判手写 30~50 条 golden QA问题 → 应命中的 lawCode条号/项号每次改分块策略、换 embedding 模型、调检索参数跑一遍 recall5。改动要可度量不能凭感觉全局铺开——这也是本项目当前最大的待补短板。9. 踩坑总表ETL 侧13 坑#坑症状修复1条号与正文同行条样式行只匹配到 1 个正则捕获行内条号前缀2章标题词中劈开“第六章调”“查”章名残缺短行聚合 停止条件3章切换节残留条带错误节信息状态机切章时重置节4依照本法第X条误判为新条条数暴增条号严格连续校验5状态机基准变量用错124 条全吞进第一条期望值基于当前暂存对象6目录未剥离检索先召回目录页首个行首条号定位正文起点7PDF 空格“记12 分”数值正则全失配记\s*(\d)\s*分8长列举条向量稀释具体行为查不到按项切分9长列举条 BM25 归一化重罚同上同上 b 参数调低10item 脱离前导句成语义残片召回了答不出分值embedText 继承前导句11item 与父条共享 articleNo按条号过滤取到残片过滤加 chunkTypearticle12词形鸿沟礼让/避让关键词通道打不中查询侧术语归一改写13切完不验证直接灌库错误静默入向量库全部校验 assert 化应用侧11 坑#坑症状修复14Boot 4 无 Jackson2 ObjectMapper bean启动即失败本地实例化或迁 Jackson 315PgVectorStore 默认 idTypeUUIDInvalid UUID string.idType(TEXT) DROP 表重建16embedding 批量上限 10batch size is invalidBATCH_SIZE817flash 模型不接受 thinking 参数路由 400 → 静默降级多轮未察觉换兼容模型 extraBody 显式清空18options API 接收 Builder 而非产物编译失败直接传 Builder19改代码/配置后未重启IDE 未同步“改了没生效”反复排查先确认 class 时间戳 源码时间20多查询 RRF 名次稀释相关条款进不了精排候选精排候选 10 → 1521精排 0% 条文硬凑进上下文token 浪费 注意力干扰阈值剪枝全剪空走拒答22上游网关故障请求挂 243s线程被无效等待占满90s 显式超时 降级23collapse 父条与独立召回并存citations 同条两次待微调10. 方法论总结全文压缩成可迁移的十条按结构切不按 token 切法条/合同/规章类文档的章节条款项是天然语义边界列举条三件套按项切分 前导句继承 父子双索引——缺一不可metadata 是检索上限稳定业务 id、上下文前缀 embedText、结构化字段如记分值入元数据校验 assert 化静默容错等于把错误灌进向量库事后无解混合检索是标配语义路与关键词路各有盲区RRF 融合查询理解决定召回意图路由 多查询变体补全指代/术语归一/处罚聚焦一次调用完成精排 剪枝守住上下文质量无关条文不进生成宁少勿滥降级必须配告警静默可用与静默错误只有一线之隔拒答是能力不是缺陷法律场景宁可知识库内无对应条文不可编造条号分值效果分诊三分法没召回 / 排序差 / 知识边界——先归类再开方。11. 已知局限与演进方向项现状方向评测集手工用例验证30~50 条 golden QA recall5 回归最高优先级精排延迟LLM 精排 ~4s/次cross-encoderbge-reranker / gte-rerank百 ms 级路由失败告警WARN 日志失败率指标 告警FAQ 缓存进程内存法规重灌不失效缓存键拼知识库版本号多副本外置 Redis流式输出无首字 6~12sSSE 流式生成引用后校验无answer 引用标注与 citations 比对错标告警列举切分推广仅记分办法7 条道交法 8 条、事故处理规定 20 条候选由评测集裁决后再推广collapse 去重同条可能重复出现折叠时跳过已存在的父条12. 附录文件清单与技术栈12.1 文件清单文件角色etl_law_chunks.pyETL多排版自适应 章/节/条状态机 列举条按项切分rag_out/chunks.jsonl全量知识库453 chunk4 法rag_out/chunks_lawcode.jsonlper-law 数据单法重刷用rag/LawRagIngest.java摄取幂等三层 父子元数据透传 BM25 索引刷新rag/LawBm25Index.java内存 BM25bigram 按条/按 id/按分值精确查询rag/LawQueryRouter.java查询理解意图路由 多查询变体小模型低温rag/LawReranker.javaLLM 精排降级协议Optional.empty → RRF 序rag/LawRetrievalService.java检索编排多查询混合 → RRF → 精排 → 剪枝 → 折叠controller/LawChatController.java问答入口短路链闲聊/FAQ/聚合 生成 记忆config/VectorStoreConfig.java双库分表vector_store记忆/ vector_store_law法规webapp/law.jsp前端聊天 UI 引用溯源卡片12.2 技术栈层选型说明语言/框架Java 21 / Spring Boot 4.0.8 / Spring AI 2.0.1Boot 4 的 Jackson 3 迁移、starter 更名等断点见踩坑表向量库PostgreSQL pgvectorHNSW / COSINE / 1536 维元数据过滤强、可事务法规与记忆分表关键词索引自研内存 BM25bigram 中文分词k11.2 / b0.4453 条规模零依赖规模化换 ES / ParadeDB融合与精排RRFk60 LLM 精排0~10 打分阈值 0.4 剪枝精排未来可换 bge-reranker / gte-rerank会话存储Redis StackRedisJSON RediSearch20 条滑动窗口law:前缀域隔离生成模型glm-5.2思考模式关闭受约束生成 引用标注 拒答纪律路由/改写模型deepseek-v4.1-flash温度 0意图识别 多查询变体一次调用三合一EmbeddingDashScope text-embedding-v41536 维与 pgvector 建表维度强绑定换模型须全量重嵌ETLPython PyMuPDF多排版自适应状态机解析扫描件需 OCR 路线前端JSP 原生 JS聊天式 UI 引用溯源卡片textContent 防 XSS构建/IDEMaven / IntelliJ IDEA注意 IDE 与 Maven 项目模型的同步踩坑 #19