法律推理模拟的目标,是让计算机在给定案件事实的前提下,完成从事实认定、法条检索、判例比对到结论推导的全过程。这件事之所以难,是因为法律推理不是简单的文本分类:同一个事实,在不同法条语境下可能得出完全不同的结论,而判例之间的可比性又高度依赖案件要素的抽取质量。本文从法条建模与判例比对两个核心环节入手,拆解一套可运行的判决预测系统是怎么搭建起来的。

一、法条驱动的规则推理:把法条变成可计算的结构
规则推理的第一步是法条建模。法条在自然语言形态下无法直接参与计算,需要先做结构化处理。一条典型的刑法条文可以拆解为构成要件、法律后果和除外情形三个部分。以盗窃罪为例,条文规定的行为要件是秘密窃取,对象要件是公私财物,数额要件则直接影响量刑档位。把这些要件抽取出来之后,就形成了一棵要件树,系统可以沿着这棵树逐一核对案件事实是否满足每个要件。
要件抽取通常借助预训练语言模型完成。将法条文本输入模型,标注出其中的行为主体、行为方式、侵害对象、数额标准等槽位,再人工校验形成标准法条库。以下是一段简化的要件抽取示意代码:
# 法条要件结构示例(以盗窃罪为例)
article_264 = {
"article_id": "刑法第264条",
"constitutive_elements": [
{"slot": "行为方式", "value": "秘密窃取"},
{"slot": "侵害对象", "value": "公私财物"},
{"slot": "数额要件", "value": "数额较大", "threshold": 3000}
],
"legal_effects": {
"数额较大": "三年以下有期徒刑、拘役或管制",
"数额巨大": "三年以上十年以下有期徒刑",
"数额特别巨大": "十年以上有期徒刑或无期徒刑"
},
"exceptions": ["偷拿家庭成员或近亲属财物,一般可不按犯罪处理"]
}
def match_article(case_facts, article):
# 核对每个构成要件是否被案件事实满足
matched = []
for elem in article["constitutive_elements"]:
if elem["slot"] == "数额要件":
if case_facts.get("amount", 0) >= elem["threshold"]:
matched.append(elem["slot"])
elif elem["value"] in case_facts.get("behavior_desc", ""):
matched.append(elem["slot"])
return len(matched) == len(article["constitutive_elements"]), matched
规则推理的优点是可解释性极强,每一步结论都能追溯到具体条文和要件,输出判决书时可以直接引用法条编号。缺点也很明显:法条天然存在大量模糊表述,比如情节严重、情节特别恶劣这类措辞,规则引擎很难量化;而且法条之间还存在竞合关系,一个行为同时触犯多条法律时,纯粹靠规则匹配无法判断优先级。这正是需要引入判例推理来补足的原因。
二、判例驱动的类比推理:相似案件相似处理
类比推理的思想来源于司法实践中的同案同判原则:如果一个待判案件与历史上某个已决案件在关键要素上高度相似,那么裁判结果也大概率接近。技术实现上,核心是判例表示和相似度度量两件事。
判例表示目前主流做法是要素级向量。先从裁判文书中抽取结构化要素,包括罪名、数额、量刑区间、自首情节、退赔情况、是否累犯等,再把要素拼接成文本送入嵌入模型生成向量。相比直接对全文做嵌入,要素级表示能过滤掉文书中大量与判决无关的程序性描述,显著提升检索精度。相似案件召回可以交给向量数据库完成:
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer("BAAI/bge-large-zh-v1.5")
def encode_case(case):
# 将案件要素拼接成语义文本后编码
text = f"罪名:{case['charge']} 数额:{case['amount']} " \
f"自首:{case['surrender']} 退赔:{case['compensation']} 累犯:{case['recidivist']}"
return model.encode(text, normalize_embeddings=True)
def search_similar(query_vec, case_lib, top_k=10):
# 余弦相似度检索最相似的已决判例
sims = case_lib["vectors"] @ query_vec
top_idx = np.argsort(-sims)[:top_k]
return [case_lib["cases"][i] for i in top_idx], sims[top_idx]
拿到相似判例之后,判决预测有多种融合策略。最简单的是加权平均,用相似度作为权重,对相似判例的刑期做加权求和;更稳妥的做法是分层统计,即只在相同罪名、相同量刑档位的判例内部做聚合,避免把盗窃案和诈骗案的刑期混在一起平均。实践中还可以引入回归模型,把相似判例的要素差异作为特征,预测待判案件相对相似判例刑期的偏移量,这种相对预测方式往往比直接预测绝对刑期更稳定。
三、规则与判例的融合:以及如何评估系统好坏
单纯依赖任何一条路线都有短板,工程上通常把两者串联或并联。串联模式下,先用法条匹配确定罪名和量刑档位,再在档位内部用判例回归预测具体刑期;并联模式下,两条路线各自输出结论,再通过一个融合层权衡置信度。当规则推理与判例推理结论冲突时,一般以规则为准,因为罪刑法定原则决定了法条是裁判的根本依据,判例只承担细化量刑的作用。
评估判决预测系统不能只看整体准确率。常见的指标体系包括:罪名预测准确率、法条预测准确率、量刑档位准确率、刑期预测的平均绝对误差。刑期预测还要特别注意超过三年刑期的案件,因为量刑档位跨越带来的误差远大于档位内浮动,这类案件单列统计更有参考价值。此外,可解释性评估同样重要,系统给出的每个结论都应附上命中的法条编号和参考判例的案号,方便法律专业人士复核。
落地时还有一个绕不开的问题是数据合规。裁判文书数据的使用需要符合相关公开规范,涉及个人隐私的信息必须脱敏。同时要意识到,判决预测系统的定位是辅助办案而非替代法官,最终裁量权始终在人。理解这一点,才能在系统设计时把可解释性和人工复核通道放在优先级最高的位置,让技术真正服务于司法的公正与效率。