刑事司法场景对文本生成的要求与通用写作截然不同。通用对话可以接受模糊表达,但量刑建议和裁判文书必须建立在可核验的事实、规范条文和计算过程之上。司法辅助Agent要解决的核心问题,不是让大模型自由发挥,而是把法律推理拆成可控制、可复核的步骤。一个可落地的系统通常会围绕案件事实抽取、量刑情节识别、类案检索、刑期计算、文书生成和结果校验来组织,每个环节都可以独立调试,也能在出现错误时快速定位。

司法辅助Agent的整体架构:从案件事实到文书草稿的链路
司法辅助Agent通常不是单一的大模型应用,而是由多个组件协同构成的智能体。大模型负责理解非结构化的案件描述,把起诉书、侦查笔录、庭审记录等文本转换成结构化的案件要素;规则引擎负责根据量刑规范计算刑期区间;检索引擎负责从历史案例库和法条库中找到相似判例和适用条文;文书生成模块则把上述结果组装成符合格式要求的法律文书。
这种模块化拆分的一个重要原因是可解释性。法律场景中的每一次输出都可能影响当事人的权利义务,如果系统只是一个黑盒,法官和检察官很难判断某段结论是否可信。把过程拆开后,量刑情节的识别可以单独校对,刑期计算可以逐项复核,法条引用可以追溯到具体版本。即使某个环节出错,也能在不推翻整个系统的前提下修正模型或规则。
下面是一个简化版的Agent主流程,展示各模块如何被串联起来。
class JudicialAgent:
def __init__(self, llm, retriever, rule_engine):
self.llm = llm
self.retriever = retriever
self.rule_engine = rule_engine
def process(self, case_text):
facts = self.llm.extract_facts(case_text)
circumstances = self.llm.classify_circumstances(facts)
similar_cases = self.retriever.search(facts, top_k=5)
sentence_range = self.rule_engine.calculate(circumstances)
draft = self.llm.generate_document(
facts=facts,
circumstances=circumstances,
similar_cases=similar_cases,
sentence_range=sentence_range
)
return self.validate(draft)
在这个流程中,extract_facts负责把案件文本中的时间、地点、行为、数额、后果等要素抽取出来;classify_circumstances负责判断是否存在自首、立功、累犯、退赃退赔等法定或酌定情节;retriever.search通过向量检索和关键词过滤找出相似案例;rule_engine.calculate则依据结构化情节完成刑期计算。最后生成文书草稿并进入校验环节。
这里需要特别强调,大模型和规则引擎的分工不是固定不变的。对于规范明确、边界清晰的计算,例如盗窃数额对应的基准刑,应当交给规则引擎;对于语义模糊、需要综合判断的内容,例如认罪态度是否真诚,则可以让模型给出初判,再由人工确认。这样既能利用大模型的语义理解能力,又能避免它在数字计算和法条引用上随意发挥。
量刑建议中的规则融合与模型推理
量刑建议的生成不能直接用大模型预测一个刑期。刑事量刑有严格的规范约束,通常按照确定基准刑、提取量刑情节、计算调节比例、确定宣告刑的步骤进行。不同罪名有不同的基准刑规则,不同情节又有从重、从轻或减轻的幅度。把这一套逻辑数字化,是司法辅助Agent能够实际使用的前提。
例如,在盗窃案件中,犯罪数额是确定基准刑的重要依据,自首、累犯、退赃退赔等情节会在基准刑基础上进行调节。规则引擎可以维护一张情节映射表,每个情节包含类型、调节比例区间和适用条件。模型负责从案件文本中识别出这些情节,规则引擎负责按照既定公式计算。这样计算过程完全可复现,法官在审查量刑建议时也能看到每一步的数值来源。
下面是一个简化版的刑期计算函数,展示规则引擎如何根据基准刑和情节列表计算建议刑期。
def calc_sentence(base_months, adjustments):
total_ratio = 0.0
for item in adjustments:
if item["type"] == "从重":
total_ratio += item["ratio"]
elif item["type"] == "从轻":
total_ratio -= item["ratio"]
suggested = base_months * (1 + total_ratio)
suggested = max(6, min(suggested, 240))
return round(suggested, 2)
上述代码中的adjustments是结构化情节列表,每个情节都带类型和调节比例。比如累犯可以设为从重情节,比例为正;自首可以设为从轻情节,比例为负。通过max和min限制最终刑期范围,可以初步避免极端计算结果。实际系统中还需要考虑减轻处罚的幅度、数罪并罚规则以及缓刑适用条件,这些都需要进一步细化规则。
模型推理和规则计算之间还需要冲突处理机制。比如模型识别出案件中有自首情节,但规则库中缺少对应的版本或适用条件,此时不能直接忽略,也不能让模型自行决定减轻多少。更合理的做法是把冲突标记出来,交给人工复核。复核结果可以回写到规则库或标注集,用于后续更新模型和规则。
法律文书生成的结构化约束与防幻觉策略
法律文书对格式和内容有严格要求,裁判文书通常包含当事人信息、案件由来、审理经过、指控事实、证据清单、裁判理由、法律依据和判决结果等部分。直接让大模型从零生成全文,容易出现事实漂移、法条引用错误、数额前后不一致等问题。因此,工程上更稳妥的做法是先做结构化要素抽取,再用模板和生成式改写结合的方式输出文书。
模板负责固定文书的骨架和规范表述,槽位填充负责注入案件专属信息。比如模板中写明“本院认为”,随后留出说理段落。生成模型只负责在给定事实、证据、法条和量刑建议的基础上组织语言,而不是自由创造新的案件事实。法条引用应从知识库中检索得到,并要求模型在输出时附带条文编号和具体内容,不允许凭记忆编造。
下面是一个简化版的文书生成函数,展示如何用槽位替换和法条注入来降低幻觉风险。
def generate_document(template, facts, laws, sentence):
document = template
for key, value in facts.items():
document = document.replace("{{" + key + "}}", value)
document = document.replace("{{LAWS}}", "\n".join(laws))
document = document.replace("{{SENTENCE}}", sentence)
return document
生成之后还需要做一致性校验。比如检查是否还有未替换的槽位、法条编号是否在知识库中真实存在、文书中的刑期是否与量刑建议一致、当事人姓名是否与原始材料完全一致。校验环节可以由规则和模型共同完成,规则负责精确匹配,模型负责识别语义层面的矛盾。这样可以把大多数低级错误拦截在提交人工审核之前。
防幻觉策略的核心是切断模型自由生成高风险内容的路径。对于数字、日期、身份信息、法条编号、刑期等关键内容,尽量使用检索和规则结果;对于需要语言组织的说理部分,可以允许模型表达,但必须限定在已抽取事实和已引用法条的范围内。必要时还可以给模型设置输出白名单,例如只允许引用知识库中存在的法条,否则要求返回未找到而不是继续生成。
数据治理、人工复核与安全合规
司法数据高度敏感,案件材料中通常包含姓名、身份证号、住址、银行卡号等个人信息。构建司法辅助Agent时,数据脱敏和权限隔离是必须优先考虑的问题。面向法院或检察院内部使用的系统,通常需要私有化部署,模型推理和数据存储都不能离开内网。训练数据如果来自真实案件,必须经过严格的匿名化处理,并且获得合法授权。
法律知识和司法解释会不断更新,历史案例也可能因为法律变化而失去参考价值。因此,知识库不能建成静态文件,而应当具备版本管理能力。每次法律法规修订后,需要同步更新规则引擎和检索库,并记录生效时间。对于历史案例,还要标注适用的法律版本,避免把旧法背景下的判例直接套用到新案中。
人工复核闭环是司法辅助Agent落地的最后一道防线。系统输出的量刑建议和文书草稿只能作为办案辅助,不能直接作为生效法律文书。法官或法官助理需要对情节识别、刑期计算、法条引用和最终表述逐项确认。每一次确认或修改都应当留痕,形成审计日志。日志中记录输入来源、模型版本、规则版本、输出结果和人工操作,方便事后追溯。
可解释性也不能只停留在展示最终结果。系统应当能够回答为什么给出这个刑期区间、引用了哪条法条、参考了哪些同类案例。量刑计算过程可以展开为逐步明细,证据引用可以关联到原始材料位置,生成理由可以追溯到具体事实。只有这样,司法辅助Agent才能从演示系统走向真正可用的办案工具。
总体来看,司法辅助Agent的价值不在于替代法律职业判断,而在于把重复性高、规则性强的工作自动化,把需要人工权衡的部分提示得更清晰。量刑建议和文书生成的每一个环节都应当可审计、可干预、可回溯,这是技术进入司法场景的基本前提。