知识图谱+RAG双通道法务问答系统实战:20万语料构建与部署 📅 发布时间:2026/8/28 2:10:31 👁 浏览次数: 简介在自然语言处理与智能问答领域知识图谱通过结构化实体关系建模为复杂问题提供精确的推理路径检索增强生成RAG则利用向量检索补充语义覆盖。两者融合能有效解决法律咨询中“检索不到、答案不准、依据不明”的痛点。基于20万条法务问答语料从数据清洗、实体关系抽取到Neo4j图存储与向量数据库双引擎构建再到双通道问答、时效校验、幻觉抑制等工程实践一套开源可复用的法务知识库问答系统方案由此完整呈现。 先说结论这个项目我前后花了四个月从数据清洗到图谱落地再到双通道问答跑通中间踩了不少坑。今天这篇就把整个思路、架构、代码资源、调优经验一次性写清楚想做法务知识库问答的朋友可以直接拿来当底稿。开头先交代一下背景。我做的这个系统核心是两件事一是构建了一个法务领域的智能知识图谱二是基于图谱加上RAG流水线实现了20万条法务问答和法律资讯问答。所谓“含码源”是我把整个项目的代码、数据集处理脚本、图谱构建流程、问答接口全部整理成了一套可复用的工程资源不是那种只给个Demo的玩具项目。这套系统能解决的问题非常明确传统法律咨询里用户问“公司拖欠工资三个月我怎么主张赔偿”普通关键词搜索返回的是一堆法条和文书用户还得自己读自己找。而基于知识图谱的问答系统能直接把“拖欠工资”“三个月”“赔偿”这几个实体和关系抽出来定位到《劳动合同法》第八十五条、经济补偿金计算规则、劳动仲裁时效等关联节点给出结构化的结论和依据链。这才是法务问答该有的体验。适合看这篇文章的人有两类一类是想把RAG落地的技术同学另一类是法律科技产品经理。前者能拿到一套可复现的图谱构建RAG问答方案后者能理解法务知识场景和通用知识场景在产品设计上的本质差异。1. 项目整体设计与架构拆解1.1 法务问答为什么卡在“检索不到”而不是“模型不够强”很多人一上来就想到微调大模型让模型背法律知识这个思路我直接劝退。法律知识的特点是结构复杂、关系密集、更新频繁而且答案必须落到具体法条和解释上。大模型微调后可能“说得像那么回事”但引用的法条版本、司法解释名称、时效节点一旦对不上就是严重事故。我实测下来最稳的方案是把法务问答拆成“精确查询”和“语义查询”两条路。精确查询走知识图谱把“实体到实体”“实体到属性”这类结构化问题转成Cypher查询语义查询走向量召回处理“法条原文怎么说”“类似案例怎么判”这类非结构化内容。两条路的结果再做融合排序最后交给语言模型组织话术。标题里的“20W法务问答”是底层的问答语料库规模。这20万条问答对覆盖了劳动纠纷、合同审查、公司治理、知识产权、交通事故、婚姻家事六个领域每条问答对都做了实体链接和法条标注。这步数据工程做完之后知识图谱的构建才有的放矢RAG的召回质量也才有保障。1.2 为什么最终选了“知识图谱 向量数据库”双引擎纯向量数据库做RAG问题在于召回结果是“语义相似但不一定准确”。比如“试用期被辞退有赔偿吗”向量召回可能返回“试用期管理规定”“辞退程序”“经济补偿金”这些高相似度的片段但无法精确回答“试用期辞退是否需要支付赔偿金”这个具有严格法律前提的问题。它缺少的是关系的推理。知识图谱恰恰补上了这个短板。它把“试用期”“辞退”“赔偿金”这些实体建模成节点把“是否支付”“适用条件”“法律依据”建模成关系问答系统可以通过图遍历走出一条完整的推理链。我用Neo4j做图存储用向量数据库做语义检索两者通过实体链接模块衔接。查询的时候先做实体识别和关系判断命中图谱就走图查询没有明确实体关系就走RAG两路结果同时输出再做交叉验证。这个架构的核心价值在于图谱保证准确性向量保证覆盖面。20万问答语料里大约35%的问题能被完全结构化直接走图谱通道精确回答剩下65%的开放型问题靠图谱做基础约束、向量做扩展召回。2. 数据工程20万语料的清洗与知识抽取2.1 原始语料长什么样脏在哪数据来源我整理了三块公开的法律咨询问答对、裁判文书中的“本院认为”段落、法条与司法解释的结构化文本。其中问答对是最主要的底料但也是最难处理的。原始数据有几个典型的坑口语化严重大量短句省略主语比如“公司不给交社保怎么办”省略了“我是员工”这个前提同一实体的表述多样比如“劳动仲裁”“仲裁委员会”“劳动争议仲裁”指向同一个概念时间敏感型的法条引用经常过期比如旧《劳动法》和相关司法解释的沿革关系如果没做版本管理答案就会引用失效条款。我的处理流程分四步清洗去重、句子切分与对齐、依存句法分析、实体与关系标注。清洗去重先干掉空数据和高重复率样本然后做句子级切分把一条长问答拆成“问题-证据句-结论句-法条引用”四元组这步是后面知识抽取的基础。2.2 实体识别和关系抽取的落地路径命名实体识别这块一开始我尝试用通用中文NER模型效果稀烂。因为法律领域的实体边界和通用领域差异很大比如“无固定期限劳动合同”在通用NER里会被切成“无固定期限”“劳动合同”两段丢了整体语义。后来我换成“法律词典规则BIO标注微调”三层策略。第一层用自建的法律实体词典做最大匹配先覆盖高频实体第二层用正则规则处理日期、金额、法条编号这些强模式实体第三层拿前两层结果做训练数据在通用NER模型上微调一轮。这个组合下来实体识别F1值从0.61提到了0.83。关系抽取是更硬的骨头。法律文本的关系往往不是显式的“主谓宾”而是条件式的判断比如“如果连续工作满一年则享有带薪年假”。这里我把关系分成了三类处理上下位关系is-a比如“劳动合同”包含“固定期限合同”“无固定期限合同”因果/条件关系leads-to / if-then比如“未缴纳社保”导致“员工可解除合同”法条-场景关系applies-to比如“《劳动法》第九十八条”适用于“用人单位违法解除合同”。我用远程监督的方式把已有的结构化法条和问答对做远距离对齐自动生成一部分训练样本再人工抽检修正。最终构建了12类实体、18类关系规模在10万实体、30万关系三元组。码源里的数据构建脚本可以完整复现这一流程。3. 知识图谱的本体设计与存储实现3.1 本体设计怎么建模法务关系网络知识图谱的本体设计我参考了法律知识工程的一些常见做法但做了不少调整。核心实体类型包括法条、法规、案例、情境、主体自然人/法人、行为、后果、程序、时效节点。关系类型上除了常见的引用、修订、生效、废止之外还设计了“构成要件”“法律后果”“举证责任”“管辖归属”这类法律专用关系。举个例子“用人单位未支付劳动报酬”这个情境连接到的关系有导致→ “劳动者可以解除劳动合同”适用法条→ 《劳动合同法》第八十五条需要举证→ “工资支付记录”“考勤记录”时效→ “劳动仲裁时效一年”这样的图模型让问答系统不再只是“找一段相似文本”而是真正沿着法律关系做推理。实体消歧我用了“上下文属性约束”的方式比如“补偿金”这个实体在“解除合同”语境下指向经济补偿金在“工伤”语境下指向伤残补助金靠图谱上下文做属性匹配来实现歧义消除。3.2 Neo4j落地与向量存储的分工图存储我选了Neo4j理由很直接Cypher查询语言对路径遍历的支持非常强社区版完全够用而且可视化调试方便能直接看到实体之间的关系链。实体去重和关系合并是在导入阶段完成的靠实体的归一化ID做Merge。向量库我用的Milvus主要存两类内容一是问答对的Embedding向量用于开放型问题召回二是法条原文的段落向量用于答案生成前的引用参考。Embedding模型用的BGE-large-zh效果对比过好几款在法务语料上的语义相似度检索表现最稳。图谱和向量库的分工策略是图谱管“关系准确的答案”向量库管“语义相似的参考”。系统查询时先接图谱通道如果实体命中得分超过阈值优先用图查询结果如果图谱没命中再走向量召回。注意这里不是简单的二选一而是两路结果同时出最后做一个答案融合保证图谱结果里有向量相关的补充引用向量结果里也有图谱约束。4. 双通道问答链路的核心实现4.1 图谱查询通道意图识别到Cypher生成图谱查询通道的流程是问题输入 → 实体识别 → 实体链接到图节点 → 意图分类 → 生成Cypher → 图查询 → 结果包装。意图分类这里我做了一个比较轻量的分类器把问题分成“查定义”“查法条”“查条件”“查后果”“查流程”“查时效”六类。为什么不用大模型直接生成Cypher因为大模型生成的Cypher经常语法正确但逻辑跑偏比如该用最短路径的时候用了全表扫描或者关系方向搞反。轻量分类器加模板化的Cypher生成虽然看起来土但准确率实测能到91%而且响应时间基本在200ms以内。模板示例比如“查条件”类型的问题MATCH (s:Situation {name: $situation})-[r:SUCH_AS]-(c:Condition) RETURN c.name AS condition, r.description AS relation这里的$situation由实体链接模块填充用户问“试用期被辞退可以拿赔偿金吗”实体链接会把“试用期”“辞退”“赔偿金”三个实体映射到图里的三个节点意图分类判定为“查条件”然后模板自动补齐关系路径。这个返回的结果不是一段文本而是一组结构化的条件列表再交给语言模型组织成答案。4.2 向量检索通道召回、重排与答案生成向量通道处理的是图谱覆盖不到的问题比如“公司周末培训算不算加班”。这类问题实体关系不明确但语义上和很多法条、问答对相关。流程是问题向量化 → 向量召回Top-K → 重排 → 生成。召回阶段我用的是Milvus的IVF索引召回Top100候选。重排我用的Cross-Encoder模型把100条压缩到Top5。这里有个细节纯向量相似度召回的“相关”和“有用”是两回事Cross-Encoder做交叉编码后能把“语义相近但无关紧要”的结果压下去。我自己测过重排后答案的命中率从47%提升到了68%。生成端用的本地部署的Qwen2-7B-Instruct通过llama.cpp量化到Q5_K_M单张显卡上就能跑。为什么不调API因为法务数据的隐私性要求本地化而且延迟要可控。系统会在Prompt里拼入图谱查询的结果片段和向量召回的Top3段落明确告诉模型“优先引用给定材料不要臆造法条”。4.3 法律资讯问答的时效性处理标题里说的“法律资讯问答”是一个容易被忽略的难点也是很多通用RAG系统翻车的地方。法律资讯的时效性极强一条新司法解释出来可能直接改变旧法条的适用结论。比如《民法典》实施后原《合同法》的相关条文就自动废止了。如果知识库里还存着旧法条问答系统就会用过期的依据来回答。我的做法是给图谱里的每条法规节点加了“生效日期”“废止日期”“替代法条”属性并在问答链路里加了一个“时效校验”步骤。查询时先检查当前日期是否在法条生效区间内如果命中已废止法条就自动跳转到替代法条节点。资讯问答场景则额外接了一个法律资讯更新通道新发布的法规和解读会通过NLP流水线自动抽取事实三元组增量合并到图谱中。这个增量更新的机制让系统不至于越用越旧。5. 码源目录结构与本地部署实操5.1 码源包含哪些模块整个项目的码源已经整理成公开仓库目录结构大概是这样legal-knowledge-graph/ ├── data/ │ ├── raw/ # 原始语料 │ ├── cleaned/ # 清洗后的问答对 │ └── graph/ # 图谱导入文件 ├── scripts/ │ ├── clean_data.py # 数据清洗 │ ├── extract_entities.py # 实体识别 │ ├── build_graph.py # 图谱构建 │ └── import_to_neo4j.py # 图数据导入 ├── nlp/ │ ├── entity_linker.py # 实体链接 │ ├── intent_classifier.py # 意图分类 │ └── relation_extractor.py # 关系抽取 ├── engine/ │ ├── graph_query.py # 图谱查询引擎 │ ├── vector_retriever.py # 向量检索模块 │ └── answer_fusion.py # 答案融合 ├── api/ │ ├── main.py # FastAPI入口 │ └── schemas.py # 请求响应定义 └── deploy/ ├── docker-compose.yml └── requirements.txt5.2 本地部署的完整步骤部署这套系统最简路径是三步起Neo4j和Milvus容器、导入图谱数据、启动FastAPI服务。先看Neo4j和Milvus的容器编排我用的docker-compose主要服务配置如下services: neo4j: image: neo4j:5.19-community ports: - 7474:7474 - 7687:7687 environment: NEO4J_AUTH: neo4j/yourpassword NEO4J_PLUGINS: [graph-data-science] volumes: - ./data/neo4j:/data milvus: image: milvusdb/milvus:v2.4.0 ports: - 19530:19530 - 9091:9091 volumes: - ./data/milvus:/var/lib/milvus我特别加上Neo4j官方Graph Data Science插件这个在后面的图谱分析、中心性计算时很有用。部署完这两个基础服务后先执行数据导入脚本导入图谱三元组再执行向量化脚本把问答对写入Milvus。模型推理服务用llama.cpp拉起参数大概长这样./llama-server \ -m models/qwen2-7b-instruct-q5_k_m.gguf \ --host 127.0.0.1 \ --port 8088 \ --n-gpu-layers 99 \ --ctx-size 8192 \ --temp 0.3注意温度设到0.3以下法务问答要求确定性温度高了会“自由发挥”。全部起来后FastAPI默认跑在8000端口可以通过Swagger文档直接调试。5.3 问答接口的调用与返回示例FastAPI的接口设计很简单一个POST接口搞定。from fastapi import FastAPI from pydantic import BaseModel from engine.answer_fusion import generate_answer app FastAPI() class QueryRequest(BaseModel): question: str class QueryResponse(BaseModel): answer: str graph_evidence: list vector_evidence: list app.post(/api/qa, response_modelQueryResponse) def qa_endpoint(req: QueryRequest): return generate_answer(req.question)实际调用效果我用一个比较典型的劳动纠纷问题来演示{ question: 公司拖欠工资三个月员工可以解除合同并要求赔偿吗 }返回结果包含三部分answer是最终回答graph_evidence是图谱命中路径vector_evidence是向量召回的参考文本。图谱证据会明确写出“未及时足额支付劳动报酬 → 劳动者可解除 → 依据《劳动合同法》第三十八条、第四十六条”。向量证据则补充了“拖欠工资三个月”对应的具体司法实践解释。这样用户看到的不只是结论还有完整的依据链。6. 常见问题与排查技巧实录6.1 我踩过的坑和排查速查表整个开发过程中我遇到的问题不算少挑几个最典型的列成速查表。问题现象原因分析解决方案实体识别把“试用期”识别成“试用”和“期”通用NER模型词典缺少法律领域词自建法律词典做最大匹配前置再走模型图谱查询返回空结果但实体都命中了实体虽在图中但关系类型不匹配检查意图分类结果确认用的Cypher关系方向是否正确向量召回结果相似度很高但答非所问单纯相似度匹配缺少关系约束加入实体链接限制先限定实体集合再向量检索Qwen2生成的答案引用了已废止法条模型训练语料里法条时效滞后在Prompt里强制约束“只依据提供的证据片段”并做时效校验增量更新后图谱出现重复节点Merge逻辑没做属性一致性检查用实体的归一化唯一键做合并冲突时保留新版本属性结果里混入低质量答案单路召回没做质量门槛增加阈值开关命中分低于阈值时明确回复“无法确定”第二条是特别容易被忽视的。实体节点都存在但关系不对图查询就会“找不到路”。我在排查时会把意图分类结果直接打印出来看它到底把问题分成了哪一类然后用对应的Cypher模板去手动测试。6.2 模型生成的幻觉问题怎么压制大模型幻觉是法务问答里必须正视的问题。我实测下来Qwen2-7B在不加约束时回答法务问题能编出看起来合理但根本不存在的规定。我的做法其实有三层第一层是Prompt约束。系统级指令明确写“必须基于给定的图谱证据和参考文段作答如果材料中未提及请回复依据不足”。这能挡住一部分幻觉。第二层是结构化拆分。先让模型做判断题“材料中是否包含该情境”再做选择题“该情境对应的法条和后果是哪个”最后才生成自然语言。分步走比直接生成整段答案要稳得多这个和代码里把任务拆成小函数是一个道理。第三层是事后校验。生成完后会用规则匹配去检查回答里的法条编号和图谱里实际引用的法条编号是否一致不一致就拦截掉强制走“依据不足”通道。这一层虽然笨但特别有效关键场景下宁可说不知道也不能说错。6.3 性能调优的几个实测数据20W问答对加图谱最担心的是检索延迟。我优化前后做了几轮压测直接说结论初始版本图谱查询平均延迟820ms原因是实体链接阶段调了好几个NLP服务串行跑。后来优化成并行调用实体识别和意图分类同时进行延迟降到410ms。向量召回初始450ms主要瓶颈在Embedding模型推理速度换用ONNX Runtime加速后降到210ms。整体问答延迟从最初的1.5秒左右优化到800毫秒以内。另外一个很关键的性能点Cypher查询一定要用参数化查询千万不要把参数拼接成字符串往里塞。我刚开始图方便直接拼接结果同一条查询模板在数据量大时执行计划完全不走索引后来全部改成参数化查询时间直接降了一个量级。这个细节码源里已经全部改好可以直接跑。7. 一点真实的使用心得最后说点真心话。知识图谱在问答系统里其实是个“好用但不好做”的方案。好用在于一旦图谱质量和实体链接精度到位答案的准确性和可解释性是两个数量级的提升。不好做在于数据工程投入很大从20万条语料到高质量知识图谱中间有大量脏活累活远不是装个Neo4j导点数据就完事的。如果要复刻这个项目我建议从一个小领域先做透比如只做“劳动纠纷”这一个子域把实体、关系、问答对做到极致再横向扩展到其他领域。不要一上来就想覆盖全法律领域那样图谱会很稀查询命中率反而难看。码源我全部开源了包含数据清洗脚本、图谱构建管线、双通道问答引擎和FastAPI服务。动手能力强的朋友可以按目录直接部署想深入了解某个模块逻辑的GitHub上的代码注释和README都有说明。有任何跑不通的地方多半是环境版本问题检查一下Neo4j插件和Milvus镜像版本就好。这个项目后续我还在扩展的方向是把图谱的推理能力再往前推一步。目前做的还是条件查询和关系路径展示下一步准备接入规则推理引擎让系统能自动判断“构成要件是否满足”而不是只把条件列出来让用户自己判断。到时候再写文章同步进展。本文还有配套的精品资源点击获取