☰
法律智能问答系统实践:混合式架构与神经网络语义匹配
2026/10/8 2:43:48 网站建设 项目流程

简介:基于神经网络的法律智能问答系统是一份面向初学者的完整工程项目,适合用作毕业设计、课程设计或工程实训。项目围绕法律条文问答场景,整理了劳动合同、员工权益、工伤事故、辞退解雇等中文文本数据,并配套Python源码、交互界面与预训练模型,可帮助读者理解从数据清洗、关键词匹配到模型推理的完整流程。压缩包共30个文件,其中11个CSV数据表用于训练与检索,6个Python脚本覆盖GUI交互、文本预处理、相似度匹配和模型训练,5个TXT文本提供问答语料与停用词表,2个model文件保存已训练好的模型,整体大小37.48MB,目录结构清晰便于按模块学习。目前已有126人学习下载。借助这份资源包,可快速搭建一个可运行的法律问答Demo,同时参考其中律师问答、关键词分类、相似度匹配等代码逻辑,迁移到其他垂直领域智能问答项目。

1. 法律智能问答系统到底是什么:检索词条背后的语义缺口

当事人写“我把钱借给朋友他没还”,系统必须知道这是民间借贷纠纷而不是诈骗;律师问“预抵押登记是否具有物权效力”,系统要把物权编和担保制度解释同时翻出来。这是“基于神经网络的法律智能问答系统”要解决的核心问题:用神经网络把用户口语表达和结构化法律知识映射到同一个语义空间,再通过检索、匹配和生成组织成可读答案。它不是什么新奇实验室项目,而是把法条库、裁判文书、对话生成串起来的一套中台能力。适合律师助理、法律科技团队、政企法务和做知识服务的工程师:要么用于内部咨询助手,要么用于对外智能客服,核心产出是“能把当事人说不清楚的话翻译成法律问题,并给出可溯源答案”的系统。

2. 架构选型与语料:为什么法律问答不能只靠关键词检索

2.1 三种主流架构:检索式、生成式、混合式怎么选

做法律问答,第一直觉是关键词检索:把法条库灌进 Elasticsearch,用户输入“借钱不还”,ES 分词命中“借款”“不还”,返回民间借贷相关条目。这套方案在早几年的法律产品里很常见,实际效果是短而规范的问题能答,当事人真实提问的召回率掉得厉害。法条语言和日常语言是两套系统:法条写“借款人未按照约定返还借款的”,当事人只会说“他借我的钱拖了半年”。关键词重叠度低,倒排索引的 BM25 分数给得很低,甚至完全召回不了。这不是 ES 的缺陷,而是语义鸿沟需要另一层能力来填补。

行业里普遍把方案收敛成三类:检索式问答靠 ES 加向量检索把相关法条和判例捞回来;生成式问答直接用大模型读语料生成回答,不依赖外部检索;混合式问答先检索约束范围,再交给生成模型“带稿回答”。我经历过的落地项目里,混合式胜出得多,原因看这张对比就清楚:

架构可解释性口语表达适配幻觉风险落地成本
检索式高,直接给出条文来源低,对模糊问题无解低低
生成式低,黑匣子不可溯源高,能用口语解释高,容易编造高
混合式中高,来源在前端可见高,靠召回补齐表达中,由检索约束中

选混合式还有一个现实理由:法律场景要求输出可溯源。当事人可以接受模型说得不够流畅,但不能接受答案没有依据。混合式把溯源前置到检索环节,后面生成的自由度被检索结果约束住,幻觉空间就小了很多。

2.2 判决书法条清洗:一份可复用的预处理流水线

无论走哪条路,语料都要先处理。法律语料有几个特殊性:判决书是半结构化长文本,“本院认为”之后才是判决理由,前面是当事人、案号、诉讼请求;法条按章条编码,条款之间有引用依赖;裁判文书带地域、法院层级、审级信息,这些都会成为后续过滤的字段。最容易踩的坑是把整篇判决书直接喂进模型,又慢又乱。

我一般会把原始语料统一清洗成这种 JSONL 格式:

{"case_id":"(2023)某市民初188号","case_type":"民间借贷纠纷","court_level":"基层","valid_law":"民法典 第六百七十九条","facts":"2019年12月,原告通过银行转账向被告出借10万元,未签订书面借款合同。","reasoning":"本院认为,自然人之间的借款合同自贷款人提供借款时成立……","asking":"原告诉请被告返还借款本金及利息是否成立"}

生成这个 JSONL 的逻辑是:先用正则按段落拆判决书,识别“原告”“被告”“本院认为”等区域标记;再从“本院认为”里抽条文引用,比如“依照《中华人民共和国民法典》第六百七十九条”会落到 valid_law 字段。清洗阶段的抽取算法不必一开始就上模型,正则加规则就能覆盖多数判决书,例外情况用少量兜底规则补。清洗的性价比远高于模型内置能力。

对应的 Python 清洗脚本通常长这样:

import json import re from pathlib import Path RAW_DIR = "data/judgments_raw/" OUT_FILE = "data/judgments_clean.jsonl" REGION_PATTERNS = { "facts": r"(经审理查明|审理查明)(?P<content>.*?)(本院认为|本院经审查认为|依据)", "reasoning": r"本院认为(?P<content>.*?)(依照|判决如下|裁判如下)", } def extract_case_id(text): m = re.search(r"((\d{4})).*?民(初|终)字第?(\d+)号", text) return f"{m.group(1)}-民{m.group(2)}-{m.group(3)}" if m else "unknown" def normalize_whitespace(s): return re.sub(r"\s+", " ", s).strip() def raw_doc_to_record(fp): raw_text = fp.read_text(encoding="utf-8") record = {"case_id": extract_case_id(raw_text)} for field, pat in REGION_PATTERNS.items(): m = re.search(pat, raw_text, re.S) record[field] = normalize_whitespace(m.group("content")) if m else "" return record with open(OUT_FILE, "w", encoding="utf-8") as fout: for fp in Path(RAW_DIR).glob("*.txt"): rec = raw_doc_to_record(fp) fout.write(json.dumps(rec, ensure_ascii=False) + "\n")

逻辑说明:脚本按四个语义区域粗切,核心是用“经审理查明”“本院认为”这类固定边界做锚点。extract_case_id 匹配“(2023)某市民初188号”这种常见案号,匹配不到写 unknown,留到后面人工补。REGION_PATTERNS 里的 content 是命名分组,re.S 让点号跨行匹配,保证“本院认为”之后到“依照”之前的整段判理被完整捕获。

参数说明:三个地方需要按自己的语料调。一是 REGION_PATTERNS 的边界词,刑事判决书常用“本院认为”前面是“公诉机关指控”,民事判决书是“经审理查明”,都换成实际表述。二是 extract_case_id 的正则,不同法院在案号写法上有差异,有些直接写“民初第188号”没有年份,建议先跑一遍统计未命中比例,超过 5% 就补正则。三是 normalize_whitespace 会把半角全角连续空白都压成单个空格,千万别省,判决书排版噪声会干扰后面所有分词和向量化步骤。

提示:清洗后的 JSONL 一定要保留原始文本路径和切分版本号,后续调模型时才能回溯是哪一批语料导致效果变化。

2.3 混合式问答的最小链路:召回 → 精排 → 生成

混合式系统把问题拆成三段,每段各自可替换可回退。第一段召回:用户 query 同时走 BM25 和向量检索,分别从法条库和判例库取 top 50。第二段精排:用交叉编码器把召回结果逐条与 query 算分,取 top 5。第三段生成:把 top 5 的条文和判例摘要按模板拼进 prompt,让生成模型输出答案,并强制它只能在检索片段里摘录细节。这个三段链路成立的关键是每段失败都能降级:召回返回空,就退回关键词检索结果而不是直接报错;精排分数全部低于阈值,就反问用户补充案情,而不是硬答。

链路参数有经验值。BM25 的 k1 和 b 保持默认附近即可,法律文本长,b 可调到 0.7 左右避免长度惩罚过度;向量召回用 768 维中文向量模型够用;精排模型输入长度限制在 512 token 内,因为它只看“问题—条文片段”匹配度。生成侧 max_new_tokens 控制在 512 以内,temperature 在 0.2 到 0.5 之间,温度太高模型爱自由发挥。这条链路最大的好处是每一段都可独立上线,哪天向量召回效果不好,只换向量模型,不动精排和生成模块。

3. 神经网络语义层:用双塔模型解决“法条和当白话对不上”

3.1 短文本匹配的难点与双塔/交叉编码器的取舍

这种语义鸿沟落到模型层,本质是文本匹配问题:给定 query 和候选法条,判断它们是否指向同一法律意图。神经网络在这一层的主流形态是句子表征模型,常见的是双塔(Dual Encoder)和交叉编码器(Cross Encoder)。双塔把 query 和候选各自编码成向量,再用余弦相似度打分,优点是候选可以离线预计算,在线只算 query 向量,适合召回。交叉编码器把 query 和候选拼成一句话过模型直接输出匹配分,精度更高,但候选必须在线逐个算,只适合对 top 50 做精排。法律问答里两者的分工很固定:双塔做召回,交叉编码器做精排。只上双塔不做精排,top 5 里经常混入语义相近但法律上无关的对;只上精排不做召回,就得把全量法条逐条过模型,在线延迟不可接受。

顺带说明为什么法律文本不首选一维卷积或 LSTM 做句子编码。这类模型在短文本分类上仍有价值,但法律问答的输入是长句和带指代的案情描述,卷积的感受野和 LSTM 的长期依赖表达都不如预训练 Transformer。LSTM 的主场是时间序列预测,这里是问答系统,直接用预训练语言模型当主干更省事。图神经网络等结构化方法适合在后文的关系抽取阶段用,做语义匹配不是它的主场。

3.2 用中文向量模型跑通语义召回:最小可运行实验

先不做复杂训练。我一般在任何法律问答项目里,第一周先用现成中文向量模型跑基线,看召回质量够不够,再决定要不要在垂直语料上微调。最小实验只需要一个脚本:

from sentence_transformers import SentenceTransformer, util model = SentenceTransformer("BAAI/bge-large-zh-v1.5") query = "我把钱借给朋友他没有还怎么办" law_chunks = [ "民法典第六百七十九条 自然人之间的借款合同,自贷款人提供借款时成立。", "刑法第二百六十六条 诈骗公私财物,数额较大的,处三年以下有期徒刑……", "民法典第六百六十七条 借款合同是借款人向借款人借款,到期返还借款并支付利息的合同。", ] q_vec = model.encode(query, normalize_embeddings=True) chunk_vecs = model.encode(law_chunks, normalize_embeddings=True) scores = util.cos_sim(q_vec, chunk_vecs)[0] for c, s in sorted(zip(law_chunks, scores), key=lambda x: x[1], reverse=True): print(round(s.item(), 4), c)

逻辑说明:encode 把 query 与三条候选法条分别向量化,normalize_embeddings 让余弦相似度等价于内积,结果才可比较。输出会看到“借款合同成立”这条分数明显高于诈骗条文,这正是要的语义召回效果。注意 bge 系列对短查询有加指令前缀的惯例,不加的话相似度会整体偏低,新手很容易拿到全面低分然后怀疑模型坏了。

参数说明:normalize_embeddings 必须开,不开的话直接比较原始向量,bge 在原始向量空间里不保序。util.cos_sim 返回二维张量,取 [0] 再排序。候选条数少时看不出问题,实际落地时候选库几十万条,双塔的代价在第一次全量向量化,千万级文本在一张 A100 上也要数小时,但只跑一次,之后存向量数据库即可。检索时的主要参数是 top_k,常见做法是先取 50,交给精排再砍到 5,不要在召回阶段就把 top_k 缩到 5,否则精排失去意义。

3.3 相似度阈值怎么定:三类参考值与按案由校准

向量相似度不是“大于 0.8 就相关”这种绝对说法。我在多个法律项目里验证过的经验是:同一个模型、同一个向量库,不同案由下阈值要分开调。民间借贷类表述高度集中,0.72 以上基本靠谱;知识产权类长句多、术语杂,0.68 以下就已经开始出现误召回;劳动争议里当事人常把加班费和经济补偿混在一起说,相似度高但法律意图可能完全相反。所以阈值必须分桶校准:把测试集按案由分组,对每组画 Precision-Recall 曲线,取 F1 最大的点做该组阈值。只维护一个全局阈值,是法律问答最容易翻车的点之一。

校准方法是:准备 300 条问答对,每条标注与候选法条是否相关(1/0),分别计算每个候选阈值下的准确率召回率,再按案由分桶求最优值。法条库规模大时负样本不够是常态,此时可以参考“前 50 召回里至少存在一条真正相关”作为召回阈值,精排阈值则参考“top 5 中允许出现几条误召回”。这套做法把相似度阈值从玄学变成可度量的迭代依据,每换一次模型就重新采一次阈值。

4. 生成式回答:用 LoRA 微调法律对话模型并约束输出

4.1 为什么检索答案不能直接回复给用户

召回和精排给出了条文与判例,但把“第六百七十九条 自然人之间的借款合同……”直接甩给用户,产品上不成立:用户看到法条编号,还是不知道该怎么办。法律问答系统的最后一步必须把检索结果转译成对话式回答,既要解释法条含义,也要告诉用户下一步该收集什么证据、起诉还是调解。这段转译天然是生成模型的工作。

但生成式模型在法律领域有两个限制:一是通用对话大模型没读过足够多的法条原文和判决说理,直接提问会得到“我无法提供法律意见”的保守回答,或者一本正经编一个不存在的案号;二是模型参数越大,微调成本越高,很多法律团队没有从头训练的条件。常见解法是保留通用大模型的底座,在自建法律语料上用 LoRA 做参数高效微调,只更新一小部分低秩矩阵,就能获得可用的“法官+律师”混合说话风格。

4.2 用 PEFT 微调:最小可运行代码与关键参数

微调前要准备对话样本,把上一章的 JSONL 记录改写成问答对。例如 prompt 是“用户欠钱不还,出借人向法院提供了银行转账记录和聊天记录,是否会被认定为民间借贷?”;answer 是“根据民法典第六百七十九条,自然人之间借款合同自贷款人提供借款时成立。银行转账记录能证明款项交付,聊天记录中的‘借’字表述可证明借贷合意……”。一条样本就是一个 (prompt, answer) 对,数据量不需要上百万,几千条高质量对话对就能见效。

训练脚本在单卡场景下通常长这样:

from datasets import load_dataset from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training import torch dataset = load_dataset("json", data_files="data/legal_qa_train.jsonl")["train"] model_name = "Qwen/Qwen2.5-7B-Instruct" # 预算有限时换成 1.5B 版本 tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained( model_name, torch_dtype=torch.bfloat16, device_map="auto", load_in_4bit=True, ) model = prepare_model_for_kbit_training(model) lora_config = LoraConfig( r=16, lora_alpha=32, lora_dropout=0.05, target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], task_type="CAUSAL_LM", ) model = get_peft_model(model, lora_config) training_args = TrainingArguments( output_dir="checkpoints/legal_lora", per_device_train_batch_size=2, gradient_accumulation_steps=4, learning_rate=2e-4, num_train_epochs=3, logging_steps=50, save_steps=500, bf16=True, ) trainer = Trainer(model=model, args=training_args, train_dataset=dataset, tokenizer=tokenizer) trainer.train()

逻辑说明:load_in_4bit 开 4bit 量化,单张 24GB 显存就能训练 7B 模型;prepare_model_for_kbit_training 确保量化模式下可训练。LoraConfig 的 r=16 是低秩矩阵的秩,lora_alpha=32 是缩放系数,两者配合决定微调强度。target_modules 要按模型实际模块名写,不同底座不同,换模型前先打印 model.named_modules() 确认。训练目标是语言建模 loss,dataset 预处理要把 prompt 和 answer 拼成一个文本并截断到 max length,一般 2048 足够,避免把多轮对话拼成超长样本。

参数说明:learning_rate=2e-4 对多数开源对话模型够用,太小低于 5e-5 往往训不动,太大高于 5e-4 容易把底座知识压制掉,回答风格变生硬。per_device_train_batch_size 在量化后可以开到 2 或 4,显存不够就把 gradient_accumulation_steps 从 4 提到 8。num_train_epochs 控制在 2 到 3 轮,法律问答数据量小,多轮会过拟合,典型表现是回答里开始重复训练集的原句。

注意:target_modules 必须与基座模型真实模块名匹配,换底座前先打印模型结构确认,否则 LoRA 不会生效但也不报错。

4.3 让模型不编造:法条引用、免责声明与不确定性表达

LoRA 微调解决风格和领域知识,但模型依然可能编造。法律场景编造的风险极高:引用一条被废止的司法解释会让系统一夜之间失去信任。所以系统设计上要用“格式化输出约束 + 生成前检索约束”双保险。生成前检索约束在混合链路里做了:答案必须先基于检索片段;这里再做一层格式化约束,让模型只输出固定结构。

prompt 模板一般如下:

def build_answer_prompt(query, law_chunks, judge_reasons): chunks_text = "\n".join([f"[法条{i+1}] {c}" for i, c in enumerate(law_chunks)]) reasons_text = "\n".join([f"[判例{i+1}] {r}" for i, r in enumerate(judge_reasons)]) return f"""你是法律问答助手。请只引用下面给出的法条和判例回答,不得引用未提供的来源。 {chunks_text} {reasons_text} 用户问题:{query} 输出要求: 1. 若法条和判例不足以回答,明确说明“现有资料无法完整回答”,并列出还需要的信息。 2. 法条引用格式为“民法典第六百七十九条”。 3. 结尾附一句“以上信息仅供参考,不构成法律意见”。 回答:"""

逻辑说明:模板把检索片段按序号列在问题前,模型没接触过片段之外的法条,生成时的引用范围被卡在检索结果里。输出要求的三条都是可被代码检查的硬约束:回答里若出现“[法条”编号以外的数字引用,就判定不合规;结尾缺免责声明就重生成或退回检索答案。

参数说明:这个模板配合生成参数使用,temperature 建议 0.2 到 0.5,top_p 0.8 到 0.9。温度越高输出越多样,但对需要稳定引用的法律问答来说,多样性是敌人。max_new_tokens 不要给太长,512 足够容纳一段问答;超过 512 的答案意味着模板设计有问题,长度不是质量指标。调试时如果模型无视模板,先检查检索结果里是否真的包含对应法条编号,很多时候是检索侧把它裁掉了,模型根本没看见可引用的条文,于是被迫自行发挥。

5. 法律问答系统常见问题排查:五条从现象到修复的踩坑记录

出现问题时,我固定的排查顺序是:先看检索结果能不能找到正确答案,再看生成模型有没有被允许自由发挥,最后看数据分布是否在掩盖问题。这三步能区分八成的故障来源。下面五条是反复遇到的现象。

5.1 引用已废止法条:时效链断裂

现象:系统回答“根据《合同法》第八条……”而《合同法》已经废止。用户按该条文主张权利,被法院驳回。

原因:法条库导入了历史文本,但没有维护条文的效力状态。检索模型不会自动区分现行有效和已废止,它在语料里看到“合同法”与“借款”语义相关,就把它召回。

解决:预处理时给法条表加 valid_until 和 status 字段,status 取“现行有效/已废止/已修改”,检索前用过滤器只保留“现行有效”。涉及“已修改”的条文,额外维护一张指向替代条文的映射表。生成侧的引用格式也要携带效力字段,供前端展示时标注。这条排查起来不难,难的是建立机制:法条库要有每日同步和变更日志,每次同步都 diff 出新增、废止、修改的条目。

5.2 当事人用词不同导致结果漂移

现象:同一案情,用户写“借条”“欠条”“借钱不还”,系统给出的答案完全不同,甚至把欠条案导向买卖合同纠纷。

原因:三种表述语义相关但法律性质不同:借条对应借贷合同关系,欠条可能对应货款、工资或损害赔偿,指向完全不同。向量模型很容易把“欠条”和“借条”学得很近,无法自动区分这些法言法语里的精细差别。

解决:在召回前增加一个“争议焦点归一化”模块,用扩展词表加少量规则把当事人表述映射成标准法律案由:欠条、借条都归一为“债权凭证”,但追问它的形成原因;再把这层归一结果注入 query,重新编码进向量召回。词表要人工审,不能全量交给模型生成,法律场景的错误映射比不映射危害更大。

5.3 生成器编造判例案号

现象:回答中引用“最高人民法院(2019)最高法民终1234号”,检索列表里根本没有这个案号。

原因:生成模型在训练阶段见过大量案号范式,LoRA 微调后又有输出压力,于是在两个真实案号之间插接了一个不存在的组合。案号幻觉是法律问答生成侧最隐蔽的毛病,因为案号格式太规整,人眼都不一定能第一时间识破。

解决:用代码做案号白名单校验。回答中包含案号时,必须能在本次检索结果的“案例号”字段里找到完全匹配项;找不到就把该句标记为可疑,执行“删除该句并重生成”的降级逻辑。更保险的做法是让模型只在模板里填“参照上述第 2 个案例”,案号由前端从检索结果动态拼装,模型完全不产出案号,从根上断掉幻觉。

5.4 长文本被截断:关键事实丢了

现象:输入刑事判决书原文,模型把“二审改判有期徒刑缓期执行”这类关键结论完全忽略,回答基于了一审判决认定的事实。

原因:BERT 类模型输入上限普遍是 512 token,长判决书会被硬截断。而判决书的关键结论恰恰在文书后半段——“本院认为”和“判决如下”的位置,粗暴截断等于把答案区切没了。

解决:不要在模型侧做全文截断,要在预处理侧做要素抽取式分段:先用规则把判决书切分成“指控/查明/认为/判决”四段,只把“查明事实”和“本院认为”送入模型;若这两段仍超长,用滑动窗口 256 步长 128 切块,逐块过模型后按位置权重融合。这个方案牺牲整体阅读能力,换来关键结论不丢。

5.5 评估指标好看但分案由不均衡

现象:整体准确率 91%,上线后发现劳动纠纷答得不错,知识产权和破产案件一塌糊涂。

原因:测试集和训练集一样不均衡,劳动纠纷样本占七成,平均指标被少数类目拉高,掩盖了长尾案由的低质量。

解决:评估强制按案由分桶,报告每一桶的准确率、召回率、驳回率和法条命中率,设置最少桶数量门槛,如每个案由至少 50 条测试样本,少于 50 条的列为灰色地带,禁止进入量化统计。这一步不是技术指标问题,而是交付物边界问题:要让甲方知道系统在标注数据充足的案由上是稳定的,在样本不足的案由上处于探索状态,而不是假装全面可用。

6. 从回测到上线:一个用公开裁判文书做评估的小技巧

上线前最值得做的验证是端到端回测:从公开裁判文书里抽取 200 个真实问答对,跑一遍完整链路,计算“答案是否正确引用至少一条有效法条”和“答案是否覆盖裁判结论”两个指标。这个回测脚本要写得足够简单,能放进 CI 里每次发版自动跑:

import json with open("data/eval_200.jsonl", encoding="utf-8") as f: cases = [json.loads(line) for line in f] def evaluate(system_answer, expected_law, expected_conclusion): hit_law = expected_law in system_answer hit_conclusion = expected_conclusion in system_answer return hit_law, hit_conclusion law_hit, conclusion_hit = 0, 0 for case in cases: answer = legal_qa_system.answer(case["query"]) # 你的完整链路 lh, ch = evaluate(answer, case["expected_law"], case["expected_conclusion"]) law_hit += lh conclusion_hit += ch print(f"法条命中率: {law_hit/len(cases):.2%}") print(f"结论命中率: {conclusion_hit/len(cases):.2%}")

逻辑说明:expected_law 设计成“民法典第六百七十九条”这种精确表达,expected_conclusion 设计成“借款合同成立”这种判决核心词。两个指标分开统计,能看出是检索侧问题还是生成侧问题:法条命中率低,去查召回和精排;结论命中率低,去查生成模板和 LoRA 权重。

参数说明:200 条是下限,最好按案由均匀抽取,避免再犯上一章的分桶不均衡问题。这个脚本不要贪多,加额外指标会让它在 CI 里跑得既慢又不稳定。

进阶方向有三个。一是把多轮对话状态加进来,让系统在用户第一次没说清时主动追问“有没有转账记录”“对方写了借条还是欠条”,而不是一次答完。二是用图神经网络把当事人、法条、担保物、金额实体建成关系图,辅助召回和证据链梳理,这比在纯文本上堆模型更能体现法律结构。三是做增量更新,法条库变更后只重编受影响向量的索引,不用全量重跑。我自己最大的教训是上线前过度优化生成模型,忽略了检索侧一条已废止法条被召回,结果生成得越流利错得越完整。现在每次迭代都先跑回测,把法条命中率钉在第一位再谈流畅度。这套习惯救了我好几次,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询