林大夫在小镇上开了三十多年医馆,柜子里整整齐齐码着几万本病历:谁得过什么病、吃过什么方、几副药见效,都记得清清楚楚。今天来了一位新病人,症状有点像三年前的赵大爷,又有点像去年的王婶。林大夫不慌不忙,抽出那几本最像的旧病历,一页页对照着斟酌开方。AI 与法律结合的“相似案例推荐”,干的就是这件活儿:给法官配一位翻遍千万份判例的 AI 助手,把案情库里最像的老案子找出来、排好队递上去。要做好这件事,得回答四个问题:案情怎么变成机器能算的“病历”?两本“病历”怎么比像不像?上千万本案卷怎么翻得快?推荐得准不准又怎么衡量?接下来,我们就跟着林大夫的医馆,把这套逻辑一处处看明白。

岗位关联

学会相似案例推荐,等于掌握了 AI 落地法律行业的“入口级技能”——类案推送、文书检索、裁判辅助都从这里起步。

目录
  1. 可视化演示
  2. 案例检索基础
  3. 案情文本表示
  4. 相似度计算
  5. 检索与排序
  6. 索引与性能
  7. 评估指标
  8. 实践挑战
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

演示混合推荐算法融合、律师画像驱动的个性化推荐,以及多指标评估与持续优化流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

混合推荐算法 协同过滤+内容 融合排序 CF+内容→融合 互补缓解稀疏

案例检索基础

林大夫的医馆有个老规矩:新病人进门,先翻旧病历。三十年的病历按病症分柜、按年份编号,她常说看病不是凭空想,而是“以旧证新”。法律界的法官面对新案子,同样要“以旧证新”——查一查过去类似的案件是怎么判的。这套“查旧案、证新案”的思路,在 AI+法律中就叫相似案例推荐。

相相似案例推荐依托的“病历柜”叫案例库,里面存着海量生效裁判文书、案情摘要和判决结果。这里要区分两个近义词:检索是法官主动输入关键词去查,像自己去翻病历;推荐是系统分析完新案后主动把相似旧案递上来,像助手把一摞病历送到桌上。实际系统常常两者结合,先检索后推荐。

一套完整的推荐流程通常分五步:收集新案情、抽取关键要素、把文本转成向量、计算与历史案例的相似度、选相似度最高的前 K 个结果再精排推送。这五步就像林大夫问诊、记特征、翻病历、比症状、定方案。

所以说,相似案例推荐本质上是一次“以旧证新”的搜索加排序。就像林大夫从几万本病历里挑出最像的几本,系统从案例库里挑出最像的几份判决——这一步想明白了,后面的细节就都有了挂靠的地方。

R(q,K)=arg⁡max⁡d∈D  sim⁡(q,d)取前 K 个结果\displaystyle \mathcal{R}(q, K) = \arg\max_{d \in \mathcal{D}} \; \operatorname{sim}(q, d) \quad \text{取前 } K \text{ 个结果}
公式说的是:在所有历史案例组成的集合里,找到与新案情相似度最高的前 K 份案例,把它们作为推荐结果。
  1. 查询案件 \(q\)指新来的案情,经过文本向量化后变成一个机器能计算的表示。
    qq
  2. 案例库 \(\mathcal{D}\)全部历史案例的集合,相当于医馆里所有旧病历。
    D={d1,d2,…,dN}\mathcal{D} = \{d_1, d_2, \ldots, d_N\}
  3. 相似度函数 \(\operatorname{sim}(q, d)\)计算新案与某份历史案例的相似程度,取值通常在 0 到 1 之间。
    sim⁡(q,d)∈[0,1]\operatorname{sim}(q, d) \in [0, 1]
  4. 取前 K 个对所有历史案例按相似度从高到低排序,只保留前 K 名。
    R(q,K)\mathcal{R}(q, K)

案情文本表示

林大夫的每本病历都有一页“特征页”:高热、咳嗽、脉浮,几笔写清病症关键。机器读案情也一样,它看不懂自然语言,必须把一段案情转成一张“特征卡”,也就是数字向量。这个转换过程叫文本表示,是整个推荐系统的地基。

最朴素的特征卡是词频卡:统计每个词出现几次。但“的”“了”“本案”这类词在每份判决里都高频出现,对区分案由毫无帮助。于是有了 TF-IDF(词频—逆文档频率),它给常见词降权、给罕见的关键词加权重,就像林大夫不会把“患者”“服用”记进特征页,而会重点记“胸痛三日”“舌苔黄腻”这类辨识度高的症状。

再进一步,用预训练语言模型(如 BERT 类模型)可以把整段案情编码成携带语义的向量,让“打伤”和“故意伤害”这类不同写法但含义相近的表达也能落在向量空间的相近位置。这相当于病历特征页从“手写关键词”升级成了“语义标签”。

病历特征页写得好不好,直接决定后面比对准不准。TF-IDF 负责把“有辨识度的词”挑出来,语义编码负责把“说得不一样但意思一样”的案情拉近——这两层配合,机器才算真正“读懂”了案情。

tf-idf⁡(t,d)=tf⁡(t,d)×log⁡Ndf⁡(t)\displaystyle \operatorname{tf\text{-}idf}(t, d) = \operatorname{tf}(t, d) \times \log \frac{N}{\operatorname{df}(t)}
公式含义:一个词在案例中的权重,等于它在文档里出现的频率乘以一个“稀有度”系数。越稀有的词系数越大,越常见的词系数越小。
  1. 词频 \(\operatorname{tf}(t, d)\)词 \(t\) 在文档 \(d\) 中出现的次数占比,反映词在本文档中的重要程度。
    tf⁡(t,d)=ct,d∑t′ct′,d\operatorname{tf}(t, d) = \frac{c_{t,d}}{\sum_{t'} c_{t',d}}
  2. 文档频率 \(\operatorname{df}(t)\)整个案例库中,有多少篇文档包含词 \(t\)。
    df⁡(t)=∣{d:t∈d}∣\operatorname{df}(t) = |\{d : t \in d\}|
  3. 逆文档频率用文档总数 \(N\) 除以文档频率再取对数,词越常见,这个值越小。
    log⁡Ndf⁡(t)\log \frac{N}{\operatorname{df}(t)}
  4. 相乘合成词频与逆文档频率相乘,得到这个词最终的特征权重。
    tf⁡(t,d)×log⁡Ndf⁡(t)\operatorname{tf}(t, d) \times \log \frac{N}{\operatorname{df}(t)}

相似度计算

特征卡写好了,怎么判断两张卡像不像?林大夫的办法很直白:把两张卡上的症状逐条对照重合。机器没有眼睛,它把每张“特征卡”看成一个向量,向量的每个维度就是一个特征词的权重,于是“比像不像”变成了“比两个向量有多接近”。

最常用的尺子是余弦相似度:把两个向量从原点画出去,比较它们方向上的夹角。夹角越小,方向越一致,案情就越相似。它的好处是只看方向不看长度,不会因为一份判决写得很长、另一份写得很短,就被“篇幅”带偏。

另一把尺子是欧氏距离:直接量两个向量终点之间的直线距离。它同时受方向和长度影响,适合向量已经归一化的场景。还有语义匹配:用模型判断“殴打他人”“故意伤害致人轻伤”这类表达在语义上是否对应,这是对词面匹配的重要补充。

林大夫的“逐条对照症状”落到数学上,就是向量之间的夹角计算:方向一致,余弦接近 1,病历高度相似;方向偏得越远,余弦越小,相似度越低。选哪把尺子,取决于案子本身的特点——这正是算法工程师要在实践中权衡的地方。

sim⁡(q,d)=q⃗⋅d⃗∥q⃗∥×∥d⃗∥=cos⁡θ\displaystyle \operatorname{sim}(q, d) = \frac{\vec{q} \cdot \vec{d}}{\|\vec{q}\| \times \|\vec{d}\|} = \cos \theta
公式含义:两个案情向量的相似度,等于它们的点积除以各自模长的乘积,本质上就是两个向量夹角的余弦值。
  1. 点积 \(\vec{q} \cdot \vec{d}\)把两个向量对应维度相乘后求和,衡量它们在同一方向上的分量有多大。
    q⃗⋅d⃗=∑iqidi\vec{q} \cdot \vec{d} = \sum_{i} q_i d_i
  2. 向量模长 \(\|\vec{q}\|\)对向量每个分量平方求和再开根号,衡量这个向量的“长度”。
    ∥q⃗∥=∑iqi2\|\vec{q}\| = \sqrt{\sum_{i} q_i^2}
  3. 余弦比值点积除以两个模长的乘积,把长度因素消掉,只剩下方向信息。
    q⃗⋅d⃗∥q⃗∥×∥d⃗∥\frac{\vec{q} \cdot \vec{d}}{\|\vec{q}\| \times \|\vec{d}\|}
  4. 夹角的余弦结果正好等于两个向量夹角的余弦值,越接近 1 表示方向越一致。
    cos⁡θ\cos \theta

检索与排序

医馆的病历越堆越多,林大夫从不会从头翻到尾。她的办法是两段式:先按“主症索引”粗粗筛出一小摞疑似病历,再坐下来把这一小摞逐本细读。案例检索也是同样的套路——第一段叫粗排召回,第二段叫精排重排。

粗排召回(Top-K 召回)追求“快而全”:用向量相似度这种轻量计算,从全量库里快速捞回 K 份候选案例。K 通常取几十到几百,宁可多捞一些,也不放跑真正的相似案例。这一步就像先按“咳嗽”这个主症筛出五十本再说。

精排重排追求“准而细”:对候选集逐个做更精细的打分,把法律要素(案由、争议焦点、标的额、地域、审级)的匹配度、判决时间的新旧等因素都融合进来,重新排序后只保留前几名推送给法官。这一步就像林大夫在五十本里再挑出最对症的三本,结合病人体质反复斟酌。

粗排负责“不漏”,精排负责“不乱”。林大夫先靠索引缩小范围,再凭经验细读定夺;推荐系统先靠轻量召回圈定候选,再靠要素融合精排定序——两级配合,既保速度又保质量,这是相似案例推荐在工程上的标准打法。

Score⁡(q,d)=λ×sim⁡vec(q,d)+(1−λ)×sim⁡law(q,d)\displaystyle \operatorname{Score}(q, d) = \lambda \times \operatorname{sim}_\text{vec}(q, d) + (1-\lambda) \times \operatorname{sim}_\text{law}(q, d)
公式含义:最终推荐分由两部分加权合成——语义层面的向量相似度,加上法律要素层面的匹配度,权重由参数 \(\lambda\) 控制。
  1. 向量相似度 \(\operatorname{sim}_\text{vec}\)粗排阶段已经算好的文本语义相似度,快但比较粗。
    sim⁡vec(q,d)\operatorname{sim}_\text{vec}(q, d)
  2. 法律要素相似度 \(\operatorname{sim}_\text{law}\)案由、争议焦点等结构化要素的匹配分数,准但计算更重。
    sim⁡law(q,d)\operatorname{sim}_\text{law}(q, d)
  3. 权重参数 \(\lambda\)取值在 0 到 1 之间,控制语义分和法律分各占多大比重。
    λ∈(0,1)\lambda \in (0, 1)
  4. 加权求和两项分数按权重合成最终排序分数,分数最高的案例排在最前。
    λ×a+(1−λ)×b\lambda \times a + (1-\lambda) \times b

索引与性能

病历多到一定程度,翻柜子就成了体力活。林大夫在柜前挂了一排“症状索引卡”:每张卡写一个症状,下面是一串病历编号。想看“头痛”,直接抽头痛卡,按编号取病历就行,不必整柜翻找。案例检索里对应的工具叫倒排索引。

倒排索引的逻辑正好和正排相反:正排是“这份文档有哪些词”,倒排是“这个词出现在哪些文档”。建立倒排索引后,包含“合同”的判决书编号被集中在一张表里,关键词查询只需查表,速度从全库扫描降到“只查相关编号”。

但向量相似度没法直接建倒排索引,因为向量是稠密的连续数值,没有天然的关键词。于是工程上引入 ANN(近似最近邻)检索,常见的有局部敏感哈希(LSH)和分层可导航小世界图(HNSW)。它们的思想是:把“长相接近”的向量提前聚到临近区域,查询时只搜邻居区域,用一点点精度损失换来巨大的速度提升。

有了“症状索引卡”,林大夫的手速快了几十倍;有了倒排索引和 ANN,检索系统才能在千万级案例库里毫秒级响应。性能优化的本质,就是用巧劲替代笨功夫——先把搜索范围缩到最小,再做精细比较。

Tbrute=O(N×D),Tann≈O(log⁡N)\displaystyle T_\text{brute} = O(N \times D), \qquad T_\text{ann} \approx O(\log N)
公式含义:暴力搜索的耗时随案例总数和向量维度线性增长;而 ANN 检索借助索引结构,把耗时压到接近对数级别。
  1. 案例总数 \(N\)案例库里全部案例的数量,规模可达百万甚至千万级。
    NN
  2. 向量维度 \(D\)每个案情向量的维度数,通常有几百维。
    DD
  3. 暴力复杂度 \(O(N \times D)\)逐一计算每个案例与查询向量的相似度,总计算量正比于两者的乘积。
    O(N×D)O(N \times D)
  4. 近似检索复杂度 \(O(\log N)\)借助索引树或哈希分桶,查找范围随规模增长只按对数增加。
    O(log⁡N)O(\log N)

评估指标

推荐给法官三份相似案例,到底灵不灵?林大夫有个小本子,专门记录每次推荐后被采纳了几次、有几份真管用。推荐系统也需要这样的小本子,这就是评估指标——用数字回答“推荐质量高不高”。

最核心的两个指标是精确率(Precision)和召回率(Recall)。精确率回答“推上来的案例里,有多少是真相关的”——好比递给法官的几本病历里,几本是真正对症的;召回率回答“所有相关案例里,有多少被找出来了”——好比库里本来有十本对症病历,林大夫翻出了几本。一个管“推得准”,一个管“找得全”。

这两个指标常常此消彼长:候选范围放大,找得更全但掺进更多不相关结果;候选范围缩小,推得更准但可能漏掉相关案例。为了综合衡量,工程上常用 F1 分数,它是精确率和召回率的调和平均,对两者取平衡。

小本子记得越细,林大夫的推荐就越稳。对系统而言,除了精确率、召回率和 F1,还会看法官的采纳率、点击率等用户反馈指标——毕竟推荐出来没人看,分数再高也是白搭。评估不是终点,而是让系统持续变聪明的标尺。

F1=2×P×RP+R,P=TPTP+FP,R=TPTP+FN\displaystyle F_1 = \frac{2 \times P \times R}{P + R}, \qquad P = \frac{TP}{TP + FP}, \qquad R = \frac{TP}{TP + FN}
公式含义:\(P\) 是推荐结果中相关案例的占比,\(R\) 是相关案例被推荐出来的比例,\(F_1\) 把两者调和成一个综合分数。
  1. 命中与误报\(TP\) 表示推荐且确实相关的案例,\(FP\) 表示推荐了但不相关的案例,\(FN\) 表示相关但没被推荐出来的案例。
    TP,FP,FNTP, FP, FN
  2. 精确率 \(P\)推荐出的所有案例中,真正相关案例所占的比例。
    P=TPTP+FPP = \frac{TP}{TP + FP}
  3. 召回率 \(R\)所有真正相关的案例中,被成功推荐出来的比例。
    R=TPTP+FNR = \frac{TP}{TP + FN}
  4. F1 调和平均当 \(P\) 和 \(R\) 都高时 \(F_1\) 才高,避免只顾一头。
    F1=2×P×RP+RF_1 = \frac{2 \times P \times R}{P + R}

实践挑战

新病种来了,旧病历里找不到像的;罕见病全县只有两三本记录,翻来翻去就那几页。这是林大夫的难题,也是案例检索的难题:数据稀疏和长尾案例。新类型案件(比如涉数据犯罪)历史判例稀少,相似度计算缺少参照物,推荐效果自然打折扣。

应对思路有三:一是借助预训练语言模型和迁移学习,用小样本也能学出较稳定的语义表示;二是引入裁判文书之外的法律知识(法条、司法解释)作为辅助特征,弥补案例不足;三是主动向法官征求反馈,把新案的“采纳结果”回填进案例库,让系统越用越熟——就像林大夫从每一次新病例里总结新经验,补充进自己的病历本。

案例库还有时效性问题:法律修订后,旧判例可能不再适用。系统需要持续更新,让新案例的向量逐步融入案例库,同时给过期案例降权或下线。这个更新过程可以写成在线增量更新的形式,让旧知识平滑过渡到新知识。

最后也是最关键的一条:AI 递上病历,开方还得靠大夫。相似案例推荐的价值是辅助决策而不是替代决策——系统把相似判例排在法官桌上,但每个案子独有的情节差异、价值权衡,必须由法律人来把关。林大夫的 AI 助手再聪明,最终落笔的方子里,始终有大夫三十年的功力。

c⃗new=(1−γ)×c⃗old+γ×c⃗case\displaystyle \vec{c}_\text{new} = (1-\gamma) \times \vec{c}_\text{old} + \gamma \times \vec{c}_\text{case}
公式含义:入库新案例时,把旧案例的向量表示按遗忘系数 \(\gamma\) 与新增案例的向量信息融合,生成更新后的案例向量。
  1. 旧案例向量 \(\vec{c}_\text{old}\)案例库中原来存储的案例表示,反映历史知识。
    c⃗old\vec{c}_\text{old}
  2. 新增案例向量 \(\vec{c}_\text{case}\)刚入库案例的语义向量,携带新信息。
    c⃗case\vec{c}_\text{case}
  3. 遗忘系数 \(\gamma\)取值在 0 到 1 之间,\(\gamma\) 越大,新信息的影响权重越高。
    γ∈(0,1)\gamma \in (0, 1)
  4. 加权融合新旧信息按比例合成新的案例向量,实现平滑更新。
    (1−γ)×c⃗old+γ×c⃗case(1-\gamma) \times \vec{c}_\text{old} + \gamma \times \vec{c}_\text{case}

AI 应用场景

智慧法院的类案强制检索推送

阶段:案例检索召回 + 排序推荐

解决的问题:传统方式下,法官遇到新案件主要靠个人记忆和人工翻阅裁判文书网检索类案,耗时数小时甚至数天,且容易遗漏关键判例。AI 助手在立案后自动解析新案案情,从千万份裁判文书中召回 Top-K 相似案例并精排,几分钟内把参考判例推送到合议庭桌面。

具体案例:某法院接入类案推送系统后,法官输入“房屋买卖合同纠纷 逾期过户 违约金”,系统先做分词与向量化,再结合案由、标的额等法律要素精排,返回五份最相似的生效判决,并标注每份判决中关于违约金的裁判理由。法官据此快速把握裁判尺度,同时结合案情差异自主判断。

律所的诉讼策略辅助

阶段:相似度计算 + 结果解释

解决的问题:律师撰写诉讼策略时,需要预判法官对类似案情的态度。过去靠资深合伙人口传心授,年轻律师难以系统掌握类案规律。AI 检索工具让律师输入案情摘要,即可获得胜诉率较高的相似判例群,辅助制定诉讼策略。

具体案例:某律所代理一起劳动争议案件,律师将“未签劳动合同 二倍工资 仲裁时效”输入检索系统,系统推荐了本市近三年同类判例,并给出支持二倍工资的判例比例与理由分布。律师据此调整举证重点,最终在仲裁中获得有利裁决。

企业合规风险研判

阶段:案例库构建 + 相似推荐

解决的问题:企业合规部门想评估某项业务的法律风险,但缺乏把海量处罚案例与自身业务场景关联的能力。AI 系统将企业业务描述与历史处罚案例做相似匹配,提示可能踩中的监管红线。

具体案例:某互联网公司上线新功能前,合规人员把功能说明输入系统,系统检索出多起涉及“用户信息收集”的行政处罚案例,并给出处罚金额区间和违规点描述。合规团队据此在功能上线前完成了整改,规避了潜在处罚。

Python 演示

python79 行
# -*- coding: utf-8 -*-"""用 TF-IDF + 余弦相似度实现相似案例推荐"""import mathfrom collections import Counter  class CaseRetriever:    def __init__(self, corpus):        self.corpus = corpus        self.docs = [self._tokenize(text) for text in corpus]        self.vocab = self._build_vocab()        self.df = self._doc_freq()     def _tokenize(self, text):        # 简易分词: 按空格切分 (实际项目中用 jieba)        return text.split()     def _build_vocab(self):        vocab = {}        for tokens in self.docs:            for w in tokens:                if w not in vocab:                    vocab[w] = len(vocab)        return vocab     def _doc_freq(self):        df = Counter()        for tokens in self.docs:            for w in set(tokens):                df[w] += 1        return df     def _tfidf(self, tokens):        vec = {}        n = len(self.docs)        count = Counter(tokens)        for w, c in count.items():            tf = c / len(tokens)            idf = math.log((n + 1) / (self.df[w] + 1)) + 1            vec[self.vocab[w]] = tf * idf        return vec     def _cosine(self, v1, v2):        dot = 0.0        norm1 = 0.0        norm2 = 0.0        for idx in set(v1.keys()) | set(v2.keys()):            a = v1.get(idx, 0.0)            b = v2.get(idx, 0.0)            dot += a * b            norm1 += a * a            norm2 += b * b        if norm1 == 0 or norm2 == 0:            return 0.0        return dot / (math.sqrt(norm1) * math.sqrt(norm2))     def recommend(self, query, top_k=3):        q_vec = self._tfidf(self._tokenize(query))        scores = []        for i, doc in enumerate(self.docs):            d_vec = self._tfidf(doc)            scores.append((i, self._cosine(q_vec, d_vec)))        scores.sort(key=lambda x: x[1], reverse=True)        return scores[:top_k]  if __name__ == "__main__":    cases = [        "合同纠纷 拖欠货款 违约金",        "合同纠纷 逾期交货 赔偿损失",        "离婚纠纷 财产分割 抚养权",        "交通事故 人身损害赔偿 医疗费",        "劳动纠纷 拖欠工资 经济补偿",        "合同纠纷 质量不合格 解除合同",    ]    retriever = CaseRetriever(cases)    query = "合同纠纷 货款 违约金 赔偿"    for idx, score in retriever.recommend(query, top_k=3):        print("相似度 %.3f -> %s" % (score, cases[idx]))
目的:用一个小型案例库演示相似案例推荐的完整链路——分词、构建词表、计算 TF-IDF、余弦相似度比较、Top-K 排序输出。
  1. self.docs = [self._tokenize(text) for text in corpus]对每份案例文本做分词,得到词序列列表,相当于给每本病历写词清单。
  2. self.df[w] += 1统计每个词出现在多少篇文档中,供后面计算逆文档频率使用。
  3. idf = math.log((n + 1) / (self.df[w] + 1)) + 1平滑版逆文档频率,避免因单词未出现而除零,常见词权重被压低。
  4. vec[self.vocab[w]] = tf * idf把词频与逆文档频率相乘,写入稀疏向量的对应维度。
  5. dot / (math.sqrt(norm1) * math.sqrt(norm2))两个向量点积除以模长乘积,即余弦相似度。
  6. scores.sort(key=lambda x: x[1], reverse=True)按相似度从高到低排序,完成 Top-K 候选排序。
  7. for idx, score in retriever.recommend(query, top_k=3)对查询案情返回前三个最相似的案例并打印。

常见误区

误区我以为相似案例推荐就是把法官输入的词拿去数据库里搜一遍,哪个判例里包含这些词就推哪个,跟百度搜索差不多。

正解关键词搜索只在字面层面匹配,而相似案例推荐的核心是语义匹配。案情描述往往表达多样,比如“打伤他人”和“故意伤害致人轻伤”几乎没有共同关键词,但语义上高度相关。推荐系统先做向量化再算相似度,就是为了抓住字面之下的含义。倒排索引可以加快关键词查询,但它只是性能工具,不是推荐的核心逻辑。

为何常见:因为“检索”这个词容易让人联想到搜索引擎,初学者很自然地把两者画等号,忽略了向量化和语义相似度这条主线。

误区我以为系统推荐了相似度 95% 的判例,法官直接照着判就行,相似案例推荐就是替法官做决定。

正解相似案例推荐只是“递病历”,不是“开方子”。两个案件即使整体相似,也可能在关键情节上存在重要差异,比如是否自首、金额大小、主观恶性不同,都会影响判决。系统的价值是帮助法官快速找到参考、把握裁判尺度,最终定案必须由法官结合法律和案情独立判断,这就是人机协同的意义。

为何常见:看到“相似度 95%”这样的高分数,容易产生“机器已经很懂”的错觉,忽略了法律推理中对具体情节差异的权衡。

误区我觉得上千万份判例的库,每查一次都要全库比较一遍,肯定慢得没法用,案例库规模大了系统就废了。

正解全库暴力搜索确实慢,但工程上有倒排索引和 ANN 近似检索这两大加速手段。倒排索引让关键词查询只访问相关编号,ANN 让向量查询只搜索邻近区域,两者都能把千万级规模的检索压到毫秒级。真正要警惕的是索引没建好、ANN 参数没调优,而不是案例库本身大。

为何常见:初学者往往先从最朴素的暴力算法理解问题,用“逐个比较”的直觉推断性能,不知道还有索引和近似检索这层优化。

误区我以为系统设了 Top-K 之后,返回的前 K 条就是最终结果,直接推给法官就行,精度好坏全看 K 取多少。

正解Top-K 只是粗排召回,召回的目的是“不漏”,其后通常还有精排重排阶段,融合案由、争议焦点、时效等法律要素重新打分。而且推荐质量要靠评估指标持续检验,精确率、召回率、F1 和用户反馈都用来衡量“推荐得准不准”,发现问题后还要调权重、换模型。

为何常见:因为 Top-K 概念简单直观,容易让人误以为它是推荐的终点,忽略了“召回—精排—评估—迭代”这套完整体系。

面试题

Q1. 在相似案例推荐中,第一步通常要做的是()

单选题 · easy

  • A.快速计算全部案例距离
  • B.把案情文本向量化表示← 正确答案
  • C.直接给法官推送案例
  • D.删除低相似度案例

答案:B。推荐的第一步是把自然语言案情转换成机器可计算的向量,就像林大夫先给新病人记特征页。没有向量化就没法算相似度。直接推送和删除相似度低案例都发生在计算之后,快速计算全部案例距离则是召回阶段的事。

Q2. 余弦相似度主要衡量两个文本向量的()

单选题 · easy

  • A.向量长度的倍率关系
  • B.向量方向的接近程度← 正确答案
  • C.向量维度的数量多少
  • D.向量坐标的具体位置

答案:B。余弦相似度是两向量夹角之余弦,只关心方向是否一致,与长度无关。好比两份病历文字详略不同,只要症状特征方向一致就算相似。它衡量的既不是长度、维度,也不是坐标位置本身。

Q3. TF-IDF 中逆文档频率(IDF)的主要作用是()

单选题 · mid

  • A.强调文档中的生僻词语
  • B.抑制常见且无区分度的词← 正确答案
  • C.提高所有词在句中的权重
  • D.统计词在文档中出现的次数

答案:B。IDF 用文档总数除以包含该词的文档数再取对数,“的”“本案”这类每篇都出现的词会得到接近零的权重,从而被抑制。它并不是在强调生僻词,而是让中等频率、有区分度的法律关键词凸显出来。

Q4. 倒排索引解决的核心问题是()

单选题 · mid

  • A.提高文本编码的精度
  • B.压缩向量存储的空间
  • C.加快案例检索的速度← 正确答案
  • D.提升语义理解的能力

答案:C。倒排索引维护“词 → 文档编号列表”的映射,查询时直接定位到包含该词的文档,避免全库扫描,解决的是速度问题。它不负责编码精度、语义理解,存储压缩也不是它的主要目标。

Q5. 召回阶段返回的候选集越大,通常会导致()

单选题 · mid

  • A.准确率上升而召回率下降
  • B.召回率上升而准确率下降← 正确答案
  • C.召回率和准确率同时上升
  • D.召回率和准确率同时下降

答案:B。候选集扩大,更多相关案例被捞进来,召回率上升;但同时也混入更多不相关案例,推得准的比例下降。就像林大夫把筛选范围从小摞扩大到整柜,找到的相关病历变多了,但递给病人的读物里无关内容也多了。

Q6. 案例推荐采用“粗排召回+精排重排”两级结构的根本原因是()

单选题 · hard

  • A.召回阶段速度慢但精度高
  • B.召回阶段速度快但精度低← 正确答案
  • C.精排阶段不需要计算相似度
  • D.粗排阶段不使用向量表示

答案:B。粗排用轻量向量相似度快速圈定候选,速度快但精度有限;精排再融合法律要素细算,精度高但耗时。两级结构正是用粗排的速度换范围,用精排的精度换质量。若粗排又慢又准就不需要两级,精排和粗排都需要相似度计算。

Q7. 针对新类型案件数量少、数据稀疏的问题,较有效的做法是()

单选题 · mid

  • A.直接删除所有稀疏的新案例
  • B.只保留热度高的历史案例
  • C.借助预训练模型增强语义表示← 正确答案
  • D.停止更新案例库中的内容

答案:C。预训练语言模型在小样本下也能学到稳定的语义表示,还能结合法条等外部知识弥补案例不足,是应对稀疏的主流思路。删除案例、只留热门、停止更新都会让长尾案件彻底失去推荐依据。

Q8. 下列属于相似案例推荐评估指标的有()

多选题 · mid

  • A.召回率和精确率← 正确答案
  • B.F1 综合分数← 正确答案
  • C.用户满意度指标← 正确答案
  • D.人脸识别准确率

答案:ABC。召回率、精确率、F1 是衡量推荐质量的核心指标,用户满意度(如法官采纳率)属于用户反馈指标。人脸识别准确率针对的是视觉任务,与文本案例推荐无关,是干扰项。

Q9. 关于 ANN(近似最近邻)检索,下列说法正确的有()

多选题 · extreme

  • A.检索速度比暴力搜索更快← 正确答案
  • B.结果与精确 Top-K 略有差异← 正确答案
  • C.一定能保证完全精确的结果
  • D.适合大规模案例库的场景← 正确答案

答案:ABD。ANN 通过哈希分桶或图索引只搜索邻近区域,速度远快于暴力全库扫描,因此适合大规模案例库。它属于“近似”检索,返回结果与精确 Top-K 会有少量差异,这是以精度换速度的代价,因此“一定能保证完全精确”是错误的。

Q10. 相似案例推荐可落地的法律场景包括()

多选题 · easy

  • A.法官裁判类案推送← 正确答案
  • B.律师检索相似判例← 正确答案
  • C.文书撰写辅助参考← 正确答案
  • D.自动驾驶车辆导航

答案:ABC。类案推送、判例检索、辅助撰写法律文书都是相似案例推荐在法律领域的典型落地场景。自动驾驶导航属于交通感知领域,与案例文本检索无关,属于干扰项。