做法律方向的智能体,最容易掉进去的坑是把系统当成"更会聊天的知识库"。真正的分水岭在于:模型给出的每个结论,能不能还原出依据、能不能被独立复核、错了能不能追责。这三件事决定了法律Agent能不能进生产环境。
为什么法律场景不能套普通问答架构
普通企业问答答错一句,代价通常是用户重新问一遍。法律场景不同——一个错误的时效判断、一条引用错了的条款,可能直接影响诉讼策略和当事人利益。美国律师协会 2024 年的 Formal Opinion 512 已经把生成式AI的使用划进职业伦理范畴:胜任义务、客户保密、向法院诚实,一条都跑不掉。
所以建设目标要换掉:不是"做一个懂法律的模型",而是搭一条受控的法律工作流。模型只是链条上的一环,负责语言理解和信息综合;确定性的部分必须交给确定性程序。
一个值得内化的设计原则:系统能力的高低,首先体现在它知道自己缺什么事实。用户问"解除一名工作8年的员工要赔多少",合格的系统第一步不是回答,而是反问——适用哪个法域、连续工龄怎么算、解除原因是什么、通知程序走了没有。缺事实就补事实,缺依据就拒答。
知识库先做版本化,再谈向量检索
法律知识有强结构:法律分编章节条款项,案例有案号、裁判日期、争议焦点、裁判结果。直接把法规文本灌进向量库,检索出来的东西可能早就废止了。
更稳的做法是把知识库当成一张版本化数据表:
CREATE TABLE legal_documents (
id BIGINT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
document_type VARCHAR(50),
jurisdiction VARCHAR(100),
effective_date DATE,
expiry_date DATE,
status VARCHAR(30),
version VARCHAR(50),
content TEXT,
updated_at TIMESTAMP
);
检索时先过确定性过滤,再做语义召回:
SELECT * FROM legal_documents
WHERE jurisdiction = ?
AND status = 'effective'
AND effective_date <= CURRENT_DATE
AND (expiry_date IS NULL OR expiry_date >= CURRENT_DATE);
一句话概括这个思路:法律知识库首先是一个版本管理系统,向量检索只是它的一个查询入口。 实操中推荐"结构化元数据 + 全文索引 + 向量召回 + 关系检索"四层混合,任何一次召回都携带法域、生效状态、时间三个硬过滤。
检索、规则、模型各管一段
把整个推理链拆开看:意图识别之后并行走三条检索线(法规、案例、内部知识),汇成证据包,先过规则引擎,再交给模型综合,最后做引用校验。每一段的职责边界要钉死。
模型擅长的:理解问题、整理事实、解释规则、生成自然语言结论。必须从模型手里拿走的:日期计算、金额计算、法律状态判断、权限判定、引用编号。赔偿金就是典型例子——模型只负责从对话里抽出"工作年限8年、月工资15000",乘法由规则引擎完成,模型再解释计算依据。让模型直接算数,等于把确定性任务交给概率过程。
工具层的设计同理。search_law(query, jurisdiction, effective_at)、calculate_compensation(salary, years) 这类接口的参数里显式带上法域和时间,等于把"引用是否有效"的判断下沉到了工具签名层面。
引用验证器是单独的模块,不是提示词
"根据相关法律规定……"这种没有出处的输出,在法律场景里等于没说。所以引用验证要做成独立组件,至少检查四件事:法律名称是否存在、条款是否真实、当前是否有效、条文内容是否真的支持结论。四项全过才允许引用进入最终答案。
可以给每个引用打分:来源可信度 × 条款存在性 × 有效性 × 语义支持度。分数低于阈值的结论自动转入人工审核。
增量点:把"置信度低"变成可执行的闸门条件,是一套可以直接抄的规则——
def need_human_review(r):
if r.risk_level == "HIGH": return True
if r.citation_score < 0.90: return True
if len(r.legal_sources) < 2: return True
if r.jurisdiction_uncertain: return True
return False
这四条是硬编码的确定性判断,不依赖模型自评。模型"觉得自己对"从来不是放行理由。
权限隔离在检索层做,而不是靠提示词
律所数据的隔离要求极高:律师B绝不能因为向量相似度高就检索到律师A的案件。正确姿势是在向量检索之前挂元数据过滤器,把身份、案件归属、访问级别做进查询条件:
filters = {
"tenant_id": user.tenant_id,
"matter_id": user.matter_id,
"access_level": {"$lte": user.level}
}
docs = vector_db.search(query_embedding, filters=filters, top_k=10)
常见反例是先取 TopK 再让模型判断"这个文件能不能看"——那等于把安全边界交给概率模型。同理,客户身份信息进模型前先走脱敏管道,模型只处理业务语义,身份证号这类字段统一替换成匿名编号、映射表留在内网。
审计与评测:让每个结论可复盘
一次法律结论是怎么产生的,事后要能完整还原:谁、什么时候、查了什么案件、调了什么工具、用了哪个版本的模型和知识库、律师改没改。审计表不必存全文,存哈希加关键路径即可,核心是可恢复。
评测也不能只看"答案像不像"。至少分五层:检索层看 Recall/Precision,引用层看准确率和语义支持,推理层核对"事实→规则→涵摄→结论"的逻辑一致性,安全层专测越权访问和提示注入,最后由律师做端到端评价。引用准确率这一层是法律Agent特有的,也是最容易出事的一层。
落地节奏与最终形态
从零起步别直接上完整平台。合理路径是四段:先做副驾驶(搜索、总结、文书初稿),验证律师愿不愿意用;再补法规库、案例库和版本控制,解决"答案可不可靠";第三步引入规划器、工具、审批流和审计,这时候才配叫Agent;多智能体拆分放在最后,而且只在单Agent复杂度明显失控时才做——为了"多"而拆,只会放大通信和状态同步的成本。
成熟的系统最终长什么样?不是"AI律师",而是一个会主动说明依据的数字助理:完成解析、列出风险、给出条款和案例引用,并对高风险项明确标注"建议人工确认后再形成最终意见"。法律的Agent工程,比拼的不是语言能力,而是准确、有据、可追溯、可接管这条链路的完整度。

评论0