首页洞察 › 类案检索:语义向量 vs 关键词

类案检索 API:语义向量 vs 关键词,到底哪种更准?

2026-06-22 · 文书查 · 面向法律 AI 工程师与法律科技团队

做类案检索的团队,几乎都在同一个路口纠结过:到底是用关键词(BM25)还是语义向量(embedding)?有人发现纯关键词漏掉了换个说法的类案,转头全押向量;又发现向量把"看起来很像、其实判得完全相反"的案子也召回了,信心崩塌。两边都踩过坑之后才明白:这道题的正确答案不是二选一,而是理解法律文本到底"特殊"在哪里——一旦想清楚这点,该用混合检索、该在哪一步加重排、为什么必须回链原文,全都顺理成章。本文就从法律文本特性讲到生产级类案检索 API 的完整架构。

一、先说结论:这不是二选一

关键词和向量不是竞争关系,是互补关系。它们各自擅长一类召回,也各自有一类必然翻车的场景。生产里真正能用的类案检索,是把两路召回融合、再加一层重排把结果排对——而最后,无论用什么算法,每条结果都得能点回原文核对。下面拆开讲为什么。

二、法律文本特殊在哪:三条决定一切的特性

不理解这三点,选型就是在拍脑袋:

1. 关键差异常常藏在"数字和法条号"里

两份判决,正文九成相似,差别只在"判二倍赔偿"还是"判经济补偿"、是否适用了某一条司法解释。对人来说这是天壤之别,对通用向量模型来说,这点差异在几百维空间里可能几乎被抹平。语义相似 ≠ 裁判后果相似,这是法律检索最容易翻车的地方。

2. 术语高度专属,且差之毫厘谬以千里

"违法解除"和"经济性裁员"、"表见代理"和"无权代理"、"定金"和"订金"——这些词在通用语料里可能被压得很近,但裁判结果完全不同。法律检索需要的是领域适配的表示,而不是开放域 embedding 的"差不多就行"。

3. 案由是结构,不是一句话

"民间借贷纠纷""劳动合同纠纷""建设工程施工合同纠纷"是一套有层级的案由(案由 taxonomy)体系,本质是结构化标签而非自然语言。最强的过滤信号往往来自结构字段(案由 + 审级 + 法院层级 + 时间),而不是把整段文本丢进向量里硬算相似度。

三、关键词检索(BM25):什么时候是它最强

关键词检索基于词项精确匹配与统计权重(BM25/TF-IDF),它的强项恰恰是向量的弱项:

场景关键词检索表现
按案号 / 法条号查✅ 精确命中,不可替代
专有术语、当事人名、机构名✅ 准,且可解释(命中哪个词一目了然)
必须包含某个法定要素✅ 可强约束(must 包含)
换了说法的同义类案❌ 漏召(没出现该词就搜不到)
只描述了情节、没用法言法语❌ 召回差(用户口语 ≠ 判决用词)

一句话:关键词在"精确"和"可解释"上无可替代,但它召不回换了说法的类案。律师常用法言法语检索时它很好用;但当输入是当事人对情节的口语描述时,它会大量漏召。

四、语义向量检索(embedding):它补什么、又会怎么翻车

向量检索把文本编码成稠密向量,用相似度召回语义接近的判决。它补的正是关键词的盲区:

但纯向量会在三个地方翻车,且都很隐蔽:

翻车场景为什么
精确点失准案号、法条号、金额这类需要精确匹配的,向量会"近似"而非命中
伪类案正文九成像、关键裁判后果相反的判决被排到前面(最危险)
通用模型术语压缩违法解除 vs 经济性裁员被通用 embedding 拉近,召回不分

工程提醒:别直接拿通用 embedding 模型上法律类案检索。要么用法律领域语料适配过的表示,要么至少叠加结构化字段过滤(先用案由/审级/时间把候选集圈对)再算语义相似度,否则"伪类案"会大量混进前排,而且它们看起来特别像,最难被发现。

五、生产级答案:混合检索 + 重排 + 回链

把上面两节合起来,成熟的类案检索 API 通常是这样一条流水线:

  1. 结构化预过滤:先用案由、审级、法院层级、时间范围把搜索空间圈到对的子集——这一步砍掉大量噪声,也是法律检索独有的强信号。
  2. 两路并行召回:关键词(BM25)一路保精确与可解释,向量一路保同义与情节相似,各取 top-N。
  3. 融合 + 重排(rerank):把两路候选合并,用重排模型(cross-encoder)对"查询—判决"对逐一打分,把真正相关的排上去、把伪类案压下去。重排是纠正纯向量"看起来像"的关键一环。
  4. 回链原文:每条结果带案号 + 可点开的原文链接,供律师核对裁判要旨、审级与是否生效。

调用形态大致如下(结构示意,字段以接口文档为准):

# Python 示例:类案检索(混合检索 + 结构化过滤)
import requests

resp = requests.post(
    "https://tob.wenshucha.com/api/v1/similar-cases",
    headers={"Authorization": "Bearer <你的 key>"},
    json={
        "query": "公司未协商一致单方调岗降薪,员工被迫离职主张违法解除",
        "filters": {"cause": "劳动合同纠纷", "trial_level": "二审"},
        "mode": "hybrid",      # keyword | vector | hybrid
        "rerank": True,
        "size": 10
    },
)
for hit in resp.json().get("data", []):
    print(hit["case_no"], hit["court"], hit["score"], hit["url"])

关键不是某个参数,而是这条链路的设计:结构过滤定边界、双路召回保全面、重排保精度、回链保可信。四者缺一,生产里都会出问题。

六、评测:别只看"召回了多少",要看"前几条对不对"

类案检索的好坏不是靠感觉,得用工程指标量:

建一个小而真实的评测集(让懂业务的人标几十个查询的"正确类案"),每次改算法都跑一遍。没有评测集的调优都是自我安慰。这套方法论和我们在 法律 AI 数据底座选型 里讲的"先验证再扩量"是一脉相承的。

七、自建还是接 API:看你卡在数据还是算法

混合检索 + 重排这套算法本身,有经验的团队两三周能搭起来。真正的瓶颈几乎总在数据底座:

自建(裸爬数据)接类案检索 API
数据覆盖不可表征(爬到哪算哪)全量 1.7 亿+,可表征
结构化字段要自己抽,质量难保案号/案由/审级/当事人脱敏/结果已结构化
去重 / 同案多版自己处理,易污染已做去重与版本归并
回链原文链接不稳定稳定标识 + 可点回链
上手速度数月起试用 key 当天接通

如果你已经有干净、去重、结构化、且授权可商用的全量底座,自建是合理的;多数团队没有,这时接一个把脏活累活做完的类案检索 API 更快——而且能先用试用 key 在你真实的几个查询上验证召回质量,再决定扩量。

数据不出域怎么办? 对律所、法院、检察院、政府,云端 API 适合验证与中小用量;涉密数据不能出内网时,正确路径是先用 API 验证检索质量,再上私有化离线部署——全量裁判文书 + 检索引擎 + 模型都跑在内网,混合检索这套链路同样适用。

八、常见问题

Q:只用向量检索行不行?省得维护两套。

A:不建议。你会在案号/法条号精确查询和"伪类案"上持续翻车,而这两类恰恰是法律场景的高频与高危。混合检索多维护的成本,远低于伪类案带来的信任崩塌。

Q:重排模型一定要吗?

A:强烈建议。双路召回保证了"该有的都在候选里",但排序往往不对;重排是把相关的排上来、伪类案压下去最有效的一步,对律师只看前几条的使用习惯尤其重要。

Q:用大模型直接做检索不就行了?

A:大模型负责理解查询和归纳结果,但它不该负责"记住判例"——那正是它会编案号的根源。正确分工是:检索系统找真实判决并回链,大模型在检索到的真实内容上作答。详见 用 MCP 把裁判文书接进 AI

Q:输入是当事人口语描述,检索效果会差吗?

A:这正是向量那一路的价值——把口语映射到法律表述。配合结构化过滤(先圈对案由)效果更稳。建议在评测集里专门放一批口语查询单独看指标。

申请试用 key,在你真实的查询上验证类案召回

提交团队与用途,1 个工作日内发放试用 key;先在自己的几个真实案子上跑混合检索,看召回与回链是否够用,再决定扩量或私有化离线部署。

📞 联系商务 Jack · 131 6872 7779

或邮件 chenjiaxin@wenshucha.com · 试用申请 paileme.wenshucha.com/tob/api-trial

相关阅读:5 分钟把文书查接入 Claude Desktop(MCP 实战) · 法律 AI 数据底座选型:文书查 vs 北大法宝 vs 无讼 vs Alpha · 法院类案推送系统:从数据到模型到法官界面 · 裁判文书 API / MCP 定价