hklii_samples/案件信息提取思路.md

10 KiB
Raw Blame History

我需要从一个案件的content里面提取我想要的信息案件案件内容比较长可长达几万个字不等。但用的是本地ollama的小模型如何在这些有限条件下提高信息提取的准确度

Extraction Rules (字段提取规则)

一、 主体与管辖信息

  1. plaintiff (原告/申索人/上诉人/覆核申请人) [数组]
    • 提取所有当事人的完整姓名或机构名(含中英文)。若无则输出空数组 []
  2. defendant (被告/答辩人/被上诉人) [数组]
    • 提取所有被告的完整姓名或机构名。若无则输出空数组 []
  3. jurisdiction_code (司法区域代码) [字符串]
    • 提取官方代码HKSCT, HKCFA, HKCA, HKCFI 等。
  4. jurisdiction_name (司法区域名称) [字符串]
    • 完整的法院或审裁处名称(如:香港特別行政區終審法院)。
  5. case_location (案件地点) [数组]
    • 提取与案件直接相关的地理位置
    • 必须包含:司法管辖区(如 "香港特別行政區")。
    • 可包含:行政区域、城市、国家(如 "九龍", "Luxor City, Egypt")。
    • 严禁提取:法院名称(如"小額錢債審裁處")、具体建筑物或场所名称(如"通州街公園"、"某某大厦")。若原文无明确地点,仅输出司法管辖区。

二、 核心案件要素

  1. case_reason (事由) [字符串]
    • 字数强制限制:绝对不可超过 100 字,必须浓缩为单句。
    • 内容公式[原告身份] + [针对什么事件/行为] + [向谁] + [提出什么请求/诉讼]
    • ⚠️ 覆核/上诉案件特例:需指明对哪个裁决(含日期/案号)提出覆核、核心理由及法律依据。
    • 严禁包含:判决结果、法庭分析、详细案发经过。
  2. case_object (案件标的物) [数组]
    • 提取诉讼请求指向的实体权利或利益(如:私人財物損失賠償、精神困擾賠償、合同履行、房产所有权)。合并本质相同的标的物。
    • 严禁提取:证据材料(如单据、证人证词)、程序性诉求(如"要求法庭裁决"、"追究责任")。

三、 裁判与实体分析

  1. judgment_result (判决结果) [对象数组]
    • 拆分原则:若案件涉及多项请求,或包含“责任判定”与“损失/金额计算”两个层面,必须分条列出
    • 子字段 charge [字符串]:具体的诉讼请求或覆核理由(请在括号内标注是“责任问题”还是“损失范围”)。
    • 子字段 result [字符串]:明确的裁决结果(胜诉/败诉/部分胜诉/维持/撤销等),并简述 2-3 个关键法庭理由及具体金额/命令。
  2. judgment_summary (判决总结) [字符串]
    • 字数强制限制:不得超过 300 字。
    • 结构四要素 (1) 案件背景1-2句话交代起因与当事人关系 (2) 核心争议焦点; (3) 法庭法律分析与推理(核心重点):法庭如何评估证据?接受/拒绝主张的逻辑是什么?引用了哪些关键法律或判例? (4) 最终裁决结果及命令。
    • ⚠️ 必须使用 YAML 多行字符串语法(>)。
  3. involved_entities (涉及实体) [对象数组]
    • 仅提取与案件相关的自然人、法人、组织、机构
    • 子字段 entity_name [字符串]:实体全称(如 "林希維審裁官", "康樂文化事務署")。
    • 子字段 reason [字符串]:说明其在案件中的角色与作用。
    • ⚠️ 法官提取特例:除主审法官外,必须提取法庭引用的先例中所提及的法官reason 需写明在XX案[案号]中担任XX职位阐述XX法律原则及引用的段落
    • 严禁提取:法案名、条例名、法律条文、纯案例名称、文献期刊名。

Strict YAML Format Constraints (严格格式约束)

  • 遇到包含冒号 :、井号 #、连字符 - 的字符串时,必须使用双引号 "" 将其包裹,防止 YAML 解析错误。
  • 对于长文本(case_reason, judgment_summary),请使用 > 折叠换行符。

Output Template

请严格按照以下格式输出结果,不要输出任何多余的解释:

plaintiff:
  - ""
defendant:
  - ""
jurisdiction_code: ""
jurisdiction_name: ""
case_location:
  - ""
case_reason: >
  [此处填入符合公式、限 100 字内的事由]  
case_object:
  - ""
judgment_result:
  - charge: "[请求描述] (责任问题/损失范围)"
    result: "[裁定结果及理由简述]"
judgment_summary: >
  [此处填入包含四要素的判决总结,限 300 字内]  
involved_entities:
  - entity_name: ""
    reason: ""


----------案件信息提取思路--------------

针对你的场景(本地小模型 + 数万字长文本 + 严格结构化抽取),单次喂入全文 + 一次性输出所有字段几乎注定失败。提升准确度的关键不在"换更好的提示词",而在**重构整个抽取管线**。以下是按优先级排列的策略:

## 一、核心思路:放弃"一次抽取所有字段"

小模型在长上下文里会严重"注意力稀释",必须把任务拆小。建议改成 **预处理 → 定位 → 分组抽取 → 校验** 四阶段管线。

## 二、预处理:先用规则把文本"压缩"和"切片"

在送入模型前,用纯代码做这些事,能让有效输入缩短 70% 以上:

- **去噪**删除页眉页脚、页码、空行、重复的法院抬头、英文与中文重复段落HK 判决书常见双语,可只保留中文版本,整段省一半)。
- **结构化切段**:判决书有强格式特征,用正则切分出:`【案件编号】`、`【当事人】`、`【判决理由】`、`【判决结果】`、`【命令】` 等区块,做成 `dict[section_name, text]`。
- **元数据用规则直接抽**:以下字段根本不需要 LLM
  - `jurisdiction_code` / `jurisdiction_name`:正则匹配 `HKSCT|HKCFA|...` 或法院全称。
  - `case_location`从法院名映射HKSCT → 香港特別行政區)。
  - 案件编号、日期、案号引用:正则。
- 规则能覆盖的字段准确率 ≈ 100%,不要浪费在模型上。

## 三、定位-再抽取Locate-then-Extract

每个字段都有"高信号区域",先定位再喂局部:

| 字段 | 高信号区域 |
|---|---|
| `plaintiff` / `defendant` | 文档前 5001000 字(标头部分) |
| `case_reason` | 首段 + "申索"/"訴因"/"本案涉及" 关键词附近段落 |
| `case_object` | "申索金额"、"索償"、"诉讼请求" 附近 |
| `judgment_result` | 文末 10002000 字("本席命令"、"判決"、"裁定" |
| `involved_entities`(先例法官) | 含"案[" / "v." / "[20XX]" 引用案例的句子 |
| `judgment_summary` | 全文,但可用提取出的其他字段拼接 |

实现:用关键词或 BM25/embedding 检索筛出每个字段的 Top-K 段落(一般 3-5 段2000 字以内),只把这部分喂给模型。

## 四、分组分次调用,而不是一次性全部输出

小模型一次吐 10 个字段一定有崩。把抽取分成 4-5 次独立调用:

1. **Call 1主体**plaintiff, defendant, jurisdiction用文档前部
2. **Call 2事由+标的)**case_reason, case_object用首段 + 申索段)
3. **Call 3判决结果**judgment_result用文末判决段
4. **Call 4涉及实体**involved_entities用先例引用段
5. **Call 5总结**judgment_summary把前 4 步结果拼回去喂模型生成,而不是从原文重新生成)

第 5 步特别关键——总结的输入是已抽取的结构化数据,而不是几万字原文,质量会跳一档。

## 五、用 Ollama 的强制结构化输出

Ollama 原生支持 `format: "json"`(或 `format` 传 JSON Schema强制模型只输出合法 JSON。**先输出 JSON再用代码转 YAML**,比让小模型直接写 YAML 稳定得多——小模型在 YAML 缩进、`>` 折叠、`""` 转义上极易出错。

每个 Call 用对应的子 schema 约束,例如 Call 1 的 schema 只包含 4 个字段,模型几乎无法跑偏。

## 六、Few-shot 示例(每个 Call 1-2 个就够)

给一个完整正例 + 一个反例("❌ 不要这样做"),效果远胜纯规则描述。例如对 `case_location`

正确:["香港特別行政區", "九龍"] 错误:["小額錢債審裁處", "通州街公園"] ← 这是法院名和场所名,不是地点


小模型不擅长抽象规则,但能很好地模仿示例。

## 七、后处理校验 + 失败重试

每个 Call 出来后用代码校验:

- **格式校验**JSON 解析、字段类型、数组非空规则。
- **业务校验**`case_reason` 字数 ≤ 100`judgment_summary` ≤ 300`case_location` 不含法院关键词(用黑名单 `["法院", "法庭", "審裁處"]``involved_entities` 不含法案名(黑名单 `["條例", "法案", "Cap."]`)。
- **失败时**:把校验错误信息回灌给模型重试一次("上次输出超过 100 字,请精简到 80 字以内"),通常一次重试就能修正。

## 八、可选增强

- **温度调到 0**`temperature: 0`),抽取任务不要随机性。
- **量化精度**:如果用的是 Q4 量化,换 Q5_K_M 或 Q6_K结构化抽取对量化精度敏感提升明显。
- **模型选型**同尺寸下Qwen2.5、GLM4 系列在中文抽取任务上明显强于 Llama 系7B 量级的 Qwen2.5-7B-Instruct 在你这类任务上是甜点。
- **自一致性**:对关键字段跑 2-3 次取众数,能压一部分波动(代价是延迟翻倍)。

## 九、推荐的最小可行落地顺序

如果只让你做三件事,按这个顺序做收益最大:

1. **正则抽元数据 + 文档分段**(一天工作量,准确率拉满)。
2. **改成分 4-5 次调用 + JSON 强制输出**(半天,崩溃率断崖式下降)。
3. **每字段加 Few-shot + 校验重试**(一天,长尾错误大幅减少)。

做完这三步,小模型也能在长判决书上跑出可用准确率。剩下的 prompt 微调和模型选型是锦上添花。