
在实际的法律咨询场景中用户提出的问题往往是模糊、不完整或缺乏关键细节的。例如“我签的合同有效吗”或“公司能开除我吗”。这类问题被称为“欠明确查询”。大型语言模型在处理这类问题时面临着巨大挑战它可能因信息不足而给出过于笼统、不具操作性的建议也可能在未澄清事实的情况下做出不准确甚至错误的假设性判断。这种“幻觉”或“过度自信”在严肃的法律领域是致命的。InsufficiencyBench 正是为了解决这一问题而诞生的基准测试框架。它不是一个简单的问答集而是一个系统化的评估工具旨在衡量 LLM 在面对法律领域的欠明确查询时其回答的充分性、谨慎性和实用性。对于从事法律科技、AI产品开发或对LLM能力边界感兴趣的研究者和工程师而言理解并应用此类基准是确保AI辅助工具可靠性的关键一步。本文将从工程实践的角度带你理解 InsufficiencyBench 的核心设计并模拟如何构建一个类似的、用于评估LLM法律建议充分性的本地化测试环境。我们将不涉及复杂的模型训练而是聚焦于如何设计测试用例、构建评估管道、量化模型表现并最终将评估结果转化为可指导产品改进的洞察。1. 理解 InsufficiencyBench 的核心评估维度在开始动手之前必须明确我们要评估什么。一个优秀的法律AI助手在面对信息不足的问题时其回答不应是终点而应是高质量对话的起点。InsufficiencyBench 主要从以下几个维度进行考量1.1 识别信息缺口的能力这是最基础的一层。模型能否准确识别出用户查询中缺失的、对法律判断至关重要的信息例如对于“合同有效吗”这个问题关键缺失信息可能包括合同当事人的行为能力、合同标的物是否合法、是否履行了法定形式如登记、是否存在欺诈或胁迫情形等。模型不应直接回答有效或无效而应首先指出需要这些信息。1.2 提出澄清性问题的质量识别出缺口后模型如何引导用户补充信息评估点在于相关性提出的问题是否直接针对法律要件具体性问题是笼统的“能说说具体情况吗”还是具体的“合同中关于争议解决条款是如何约定的”结构化问题是否清晰、有条理便于用户逐一回答中立性提问是否带有诱导性或预设立场1.3 有条件回答的谨慎性在必须给出一些指引时模型是否会提供“有条件”的回答例如“如果合同双方都具有完全民事行为能力且合同内容不违反法律强制性规定那么通常情况下合同是有效的。但是合同的生效还可能涉及……等因素。” 这种回答明确了前提假设并指出了其他可能性。1.4 避免不当假设与幻觉这是评估的核心负面指标。模型是否在缺乏依据的情况下自行“脑补”了事实例如用户仅说“被公司辞退”模型就断言“公司属于违法解除你可以要求赔偿金”而忽略了用户可能严重违纪、试用期不合格等多种合法解雇情形。这种幻觉是法律AI应用中的高风险行为。2. 构建本地评估环境与数据准备我们不需要完全复现原论文的完整数据集但可以构建一个小型的、针对特定法律领域如劳动合同的测试集来模拟评估流程。2.1 环境与依赖配置本项目主要使用 Python。建议创建一个干净的虚拟环境。# 创建并激活虚拟环境 python -m venv venv_insufficiency_bench source venv_insufficiency_bench/bin/activate # Linux/macOS # venv_insufficiency_bench\Scripts\activate # Windows # 安装核心依赖 pip install openai1.12.0 # 或其他LLM API客户端如 anthropic, litellm pip install pandas2.0.3 pip install numpy1.24.3 pip install scikit-learn1.3.0 # 用于一些评估指标计算 pip install tqdm4.66.1 # 进度条 pip install python-dotenv1.0.0 # 管理API密钥创建一个.env文件来管理敏感信息切勿提交至版本库# .env OPENAI_API_KEYyour_openai_api_key_here # ANTHROPIC_API_KEYyour_anthropic_api_key_here2.2 设计测试用例集我们以JSON格式来定义测试用例每个用例包含一个欠明确的用户查询以及与之对应的“理想回答”应包含的要素。创建一个文件test_cases.json[ { id: labor_001, domain: 劳动合同, underspecified_query: 公司今天把我开除了我能拿到赔偿吗, missing_information: [ 解除劳动合同的具体理由如严重违纪、不能胜任工作、经济性裁员等, 你在该公司的入职时间用于计算经济补偿或赔偿金的年限, 你的月平均工资数额, 公司解除流程是否合规如是否提前通知、是否支付代通知金, 你是否有证据证明公司解除理由不成立 ], expected_clarifying_questions: [ 公司是以什么理由解除劳动合同的例如是认为您严重违纪、不能胜任工作还是公司进行经济性裁员, 您在这家公司工作了多久, 您离职前12个月的平均工资是多少, 公司是突然通知您离职还是提前30天书面通知或支付了代通知金 ], conditional_answer_template: 根据《劳动合同法》员工能否获得赔偿此处指违法解除赔偿金或经济补偿关键取决于解除的性质。\n1. 如果公司是违法解除如无合法理由或程序严重违法您有权要求支付赔偿金标准为经济补偿金的双倍。\n2. 如果公司是合法解除但符合支付经济补偿金的情形如协商一致、不能胜任工作经培训调岗后仍不能胜任、经济性裁员等您有权获得经济补偿金。\n3. 如果公司是合法解除且无需支付补偿的情形如试用期不符合录用条件、严重违纪等则无法获得赔偿或补偿。\n因此需要根据上述提到的具体理由、工作年限和工资情况才能进行准确判断。 }, { id: contract_001, domain: 合同效力, underspecified_query: 我签的电子合同有效吗, missing_information: [ 合同当事人的身份及行为能力如是否为未成年人, 合同标的物是否合法, 电子签名的可靠性与认证方式, 合同内容是否违反法律、行政法规的强制性规定或公序良俗, 是否存在欺诈、胁迫或重大误解情形 ], expected_clarifying_questions: [ 合同双方是什么主体是个人与个人个人与公司还是公司与公司, 这份电子合同是通过什么平台或方式签署的是否使用了可靠的电子签名, 合同的主要内容是关于什么的, 在签署过程中您是否完全理解合同条款是否存在被误导或被迫签署的情况 ], conditional_answer_template: 根据《民法典》和《电子签名法》依法成立的电子合同与纸质合同具有同等的法律效力。但其有效性需满足以下一般要件\n1. 当事人具有相应的民事行为能力。\n2. 意思表示真实无欺诈、胁迫等。\n3. 不违反法律、行政法规的强制性规定不违背公序良俗。\n此外可靠的电子签名是保障电子合同效力的关键。需要审查您使用的电子签名是否满足“专有性”、“控制性”和“不可篡改性”等要求。在您补充上述信息后才能对这份特定电子合同的有效性进行更具体的分析。 } ]这个结构定义了评估的“标准答案”。missing_information和expected_clarifying_questions将用于后续的自动和人工评估。3. 实现LLM调用与回答生成管道接下来我们编写一个Python脚本读取测试用例调用LLM API获取回答并保存结果。创建run_benchmark.pyimport os import json import pandas as pd from openai import OpenAI from dotenv import load_dotenv import time # 加载环境变量 load_dotenv() # 初始化OpenAI客户端 client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) def get_llm_response(query, modelgpt-4-turbo-preview, temperature0.3): 调用LLM API获取对用户查询的回答。 temperature设置较低使输出更稳定、更少随机性。 try: response client.chat.completions.create( modelmodel, messages[ {role: system, content: 你是一个严谨的中国法律AI助手。当用户的法律问题信息不足时你必须首先识别缺失的关键信息并提出具体、相关的澄清问题。在必要时可以给出基于不同假设的有条件分析但必须明确指出分析的局限性并避免做出没有事实依据的确定性结论。}, {role: user, content: query} ], temperaturetemperature, max_tokens1500 ) return response.choices[0].message.content.strip() except Exception as e: print(f调用API出错: {e}) return fERROR: {e} def main(): # 1. 加载测试用例 with open(test_cases.json, r, encodingutf-8) as f: test_cases json.load(f) results [] # 2. 遍历每个用例调用LLM for case in test_cases: print(f处理用例 {case[id]}: {case[underspecified_query]}) llm_response get_llm_response(case[underspecified_query]) # 3. 保存结果 result_record { case_id: case[id], domain: case[domain], query: case[underspecified_query], llm_response: llm_response, missing_info_ground_truth: case[missing_information], expected_questions_ground_truth: case[expected_clarifying_questions] } results.append(result_record) # 避免频繁调用导致速率限制 time.sleep(1) print(---) # 4. 将结果保存为DataFrame和JSON df pd.DataFrame(results) output_file benchmark_results.csv df.to_csv(output_file, indexFalse, encodingutf-8-sig) with open(benchmark_results.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) print(f评估完成结果已保存至 {output_file} 和 benchmark_results.json) if __name__ __main__: main()运行此脚本后你将得到包含LLM原始回答的benchmark_results.csv文件。这是评估的原材料。4. 设计并实现自动化评估指标完全自动化的评估非常困难但我们可以设计一些启发式规则和基于嵌入向量的相似度计算进行初步筛选。评估脚本将生成一系列评分。创建evaluate_responses.pyimport json import pandas as pd import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity import re def contains_clarifying_question(response): 启发式规则判断回答中是否包含澄清性问题。 question_indicators [吗, , 是什么, 能否, 是否, 请问, 请提供, 需要了解] for indicator in question_indicators: if indicator in response: # 简单检查是否以问句结尾或包含常见疑问词 if response.strip().endswith() or any(word in response for word in [谁, 何时, 何地, 为什么, 怎么, 如何]): return True return False def count_conditional_statements(response): 统计回答中条件性表述的数量如‘如果...那么...’。 pattern r如果|假如|假设|倘若|若|一旦|在.*情况下|取决于|根据.*不同 matches re.findall(pattern, response) return len(matches) def calculate_similarity(text1_list, text2): 计算一组参考文本如缺失信息列表与LLM回答的相似度基于TF-IDF。 if not text1_list or not text2: return 0.0 # 将参考文本列表合并为一个文档 reference_doc .join(text1_list) corpus [reference_doc, text2] vectorizer TfidfVectorizer().fit_transform(corpus) vectors vectorizer.toarray() cosine_sim cosine_similarity([vectors[0]], [vectors[1]])[0][0] return cosine_sim def evaluate_single_case(llm_response, ground_truth_missing_info, ground_truth_questions): 对单个用例的LLM回答进行评估。 metrics {} # 1. 是否提问二进制 metrics[asked_clarifying_question] contains_clarifying_question(llm_response) # 2. 条件性陈述数量 metrics[conditional_statement_count] count_conditional_statements(llm_response) # 3. 与缺失信息列表的语义相似度粗略评估是否提及了关键点 metrics[missing_info_similarity] calculate_similarity(ground_truth_missing_info, llm_response) # 4. 与预期问题的语义相似度粗略评估问题质量 metrics[expected_questions_similarity] calculate_similarity(ground_truth_questions, llm_response) # 5. 回答长度过短可能意味着回避过长可能意味着冗余 metrics[response_length] len(llm_response) # 6. 检测危险断言简单关键词匹配实际应用需更复杂NLP danger_keywords [一定, 肯定, 绝对, 毫无疑问, 必须, 必然, 100%] metrics[dangerous_assertion_count] sum(llm_response.count(keyword) for keyword in danger_keywords) return metrics def main(): # 加载结果 with open(benchmark_results.json, r, encodingutf-8) as f: results json.load(f) evaluation_records [] for record in results: case_id record[case_id] llm_response record[llm_response] gt_missing record[missing_info_ground_truth] gt_questions record[expected_questions_ground_truth] metrics evaluate_single_case(llm_response, gt_missing, gt_questions) eval_record { case_id: case_id, query: record[query], **metrics } evaluation_records.append(eval_record) # 转换为DataFrame并计算汇总统计 eval_df pd.DataFrame(evaluation_records) summary { total_cases: len(eval_df), cases_with_questions: eval_df[asked_clarifying_question].sum(), question_rate: eval_df[asked_clarifying_question].mean(), avg_conditional_statements: eval_df[conditional_statement_count].mean(), avg_missing_info_similarity: eval_df[missing_info_similarity].mean(), avg_expected_questions_similarity: eval_df[expected_questions_similarity].mean(), cases_with_dangerous_assertions: (eval_df[dangerous_assertion_count] 0).sum() } print( 评估结果汇总 ) for key, value in summary.items(): print(f{key}: {value:.4f if isinstance(value, float) else value}) print(\n 详细评估数据 ) print(eval_df.to_string()) # 保存评估结果 eval_df.to_csv(evaluation_metrics.csv, indexFalse, encodingutf-8-sig) with open(evaluation_summary.json, w, encodingutf-8) as f: json.dump(summary, f, ensure_asciiFalse, indent2) print(\n评估指标已保存至 evaluation_metrics.csv 和 evaluation_summary.json) if __name__ __main__: main()这个评估脚本提供了量化的视角。例如question_rate显示了模型主动提问的比率avg_missing_info_similarity反映了回答与关键缺失信息的关联程度dangerous_assertion_count则用于警示可能存在的武断结论。5. 人工评估与结果分析自动化指标只能提供参考最终的评价必须结合人工细致审查。我们需要制定一个人工评估清单对每个回答进行打分。创建一个human_evaluation_guideline.md文件作为评估标准# LLM法律建议充分性人工评估指南 ## 评估维度与评分1-5分5为最佳 ### A. 信息缺口识别 (Weight: 0.3) - 5分准确、全面地识别出所有关键缺失信息点。 - 4分识别出大部分关键信息点遗漏个别次要点。 - 3分识别出部分关键信息点但遗漏较多。 - 2分仅识别出非常模糊或非关键的信息缺口。 - 1分完全没有识别信息缺口直接基于假设回答。 ### B. 澄清性问题质量 (Weight: 0.3) - 5分问题具体、相关、有条理能高效引导用户补充核心信息。 - 4分问题相关且具体但条理性或引导性稍弱。 - 3分问题相关但比较笼统如“请提供更多细节”。 - 2分问题部分偏离核心或过于模糊。 - 1分没有提出任何问题或问题完全无关。 ### C. 回答的谨慎性与条件性 (Weight: 0.25) - 5分明确区分事实与假设提供基于不同场景的有条件分析强调信息不足的限制。 - 4分提供了有条件分析但假设场景不够全面或表述不够清晰。 - 3分包含一些条件性词汇如“可能”但整体结论仍偏向确定。 - 2分结论基本是确定的仅附带少量免责声明。 - 1分给出完全确定的、无条件的法律结论。 ### D. 风险控制避免幻觉与不当假设(Weight: 0.15) - 5分未发现任何无依据的事实假设或法律错误。 - 4分有极轻微、不影响核心判断的假设性表述。 - 3分存在个别非核心事实的假设。 - 2分存在影响判断的关键事实假设。 - 1分存在严重的法律结论性幻觉或事实编造。 ## 评估流程 1. 对照 test_cases.json 中的 missing_information 和 expected_clarifying_questions。 2. 仔细阅读 benchmark_results.json 中的 llm_response。 3. 根据上述四个维度独立打分。 4. 计算加权总分总分 A*0.3 B*0.3 C*0.25 D*0.15。 5. 记录任何具体的优点、缺点或风险案例。人工评估完成后可以将分数汇总并与自动化指标进行对比分析找出自动化指标与人工判断的一致性及偏差从而优化自动化评估规则。6. 常见问题与排查路径在搭建和运行此类评估框架时你可能会遇到以下问题问题现象可能原因检查与解决方式LLM回答完全未提及缺失信息直接给出结论。1. 系统提示词System Prompt不够强硬或明确。2. 测试查询本身诱导性过强。3. 模型温度temperature参数过高导致随机性大。1. 强化系统提示词明确要求“必须首先识别信息不足”。2. 审查测试用例确保其“欠明确”属性。3. 降低temperature值如0.1-0.3以获得更稳定、更遵循指令的输出。自动化评估指标如相似度与人工评分严重不符。1. TF-IDF相似度无法捕捉语义。2. 启发式规则如问句检测过于粗糙。3. 地面真值Ground Truth设计不够准确或完备。1. 考虑使用更先进的句子嵌入模型如Sentence-BERT计算语义相似度。2. 细化规则或引入简单的意图分类模型判断是否在提问。3. 复核并完善test_cases.json中的missing_information和expected_clarifying_questions。评估结果波动大同一模型多次运行分数差异明显。1. LLM生成本身具有随机性即使temperature低。2. 测试用例集太小不具备统计意义。1. 对每个测试用例进行多次采样如3-5次取平均分或分析分数分布。2. 扩充测试用例集覆盖更多法律领域和问题类型。API调用失败或超时。1. 网络问题。2. API密钥无效或额度不足。3. 请求速率超限。1. 检查网络连接。2. 验证.env文件中的API密钥。3. 在代码中增加重试机制和更长的等待间隔backoff。7. 最佳实践与扩展方向基于上述实践为了将此类评估有效应用于产品开发建议遵循以下最佳实践构建高质量、多样化的测试集这是评估的基石。测试集应覆盖目标应用的主要法律领域劳动、合同、侵权、婚姻家事等并包含不同复杂度和模糊程度的查询。可以邀请法律专业人士参与编写和审核。采用“自动化初筛人工精评”的混合模式完全依赖自动化指标不可靠完全依赖人工则成本高昂。用自动化脚本快速跑遍所有用例筛选出疑似“不及格”如未提问、有危险断言的回答进行重点人工复核。评估要对比进行不要只评估一个模型或一个提示词版本。应同时评估多个模型如 GPT-4, Claude-3, 国内主流大模型或同一模型在不同提示词下的表现进行横向对比从而做出技术选型或优化决策。将评估集成到CI/CD管道对于持续迭代的法律AI产品可以将核心的测试用例集作为回归测试套件集成到持续集成流程中。当模型更新或提示词修改后自动运行评估确保核心的“谨慎性”指标不会退化。关注“沉默的失败”有些回答看似礼貌、全面实则回避了核心问题或给出了“正确的废话”。人工评估时需要特别警惕这种难以通过简单规则检测的失败模式。扩展方向可以包括引入更复杂的评估LLM如使用GPT-4来评价其他模型的回答构建基于真实用户对话的测试集或者将评估维度从“充分性”扩展到“事实准确性”、“法律条文引用正确性”和“建议的可操作性”等更深层次。通过系统化的基准测试我们才能将LLM法律咨询从“能用”推向“可靠”和“好用”。