Metadata-Version: 2.4
Name: routed-confidence
Version: 0.1.2
Summary: Field-level confidence evaluator SDK for routed extraction results
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: pyyaml>=6.0.2
Requires-Dist: requests>=2.31.0

# routed-confidence

字段级置信度评估 SDK。

`routed-confidence` 输入一条抽取结果，输出每个字段的置信度分数。它默认不写文件、不启动服务、不计算检出率/误伤率/日报统计。只有显式传入 `collection_dir` 时，才会把评估输入和输出收集到本地 JSON 文件。

Python 包名：

```bash
pip install routed-confidence
```

Python 导入名：

```python
from routed_confidence import ConfidenceEvaluator
```

## 核心能力

SDK 有三种使用模式：

| 模式 | 入口 | 适用场景 |
| --- | --- | --- |
| 内置固定评估器 | `ConfidenceEvaluator()` | 使用包内置的股东大会召开情况字段规则 |
| 直接 LLM 评估 | `ConfidenceEvaluator(model=..., api_key=..., base_url=...)` 或 `use_llm=True` | 没有 schema、关系规则、历史数据时，直接让模型判断任意字段置信度 |
| 构建后的命名评估器 | `EvaluatorBuilder(...).build(...)` 后用 `ConfidenceEvaluator.from_name(...)` | 针对某类数据构建专用 schema、字段关系和 historical/Wilson 维度后长期复用 |

### 模式选择

- 只配置模型，且不传 `rules_file`、`weights`、`historical_data_file`、`wilson_scores` 时，会自动进入直接 LLM 评估模式。
- 传 `use_llm=True` 时，会强制进入直接 LLM 评估模式。
- 想构建某类数据专用 evaluator 时，使用 `EvaluatorBuilder.build(...)`，构建完成后再通过 `ConfidenceEvaluator.from_name(...)` 或 `ConfidenceEvaluator.from_config(...)` 加载。
- 使用 `ConfidenceEvaluator.from_name(...)` 或 `ConfidenceEvaluator.from_config(...)` 时，会加载构建后的配置化评估器。
- 不传模型也不加载配置时，使用内置固定评估器。

也就是说：

```text
只想马上评估任意字段       -> 直接 LLM 模式
想针对某类数据沉淀规则     -> 先 build，再按 evaluator_name 加载
想使用当前内置股东大会规则 -> ConfidenceEvaluator()
```

## 安装

本地开发安装：

```bash
pip install -e .
```

从本地 wheel 安装：

```bash
python3 -m pip wheel . --no-deps --no-build-isolation -w dist
pip install dist/routed_confidence-*.whl
```

从 PyPI 或私有 PyPI 安装：

```bash
pip install routed-confidence
```

## 快速开始

### 内置固定评估器

```python
from routed_confidence import ConfidenceEvaluator

record = {
    "extraction_result": {
        "会议召开时间": {
            "value": "2026-05-20 14:00:00",
            "content": "会议召开时间为2026年5月20日14:00",
            "type": "text",
            "title_path": ["一、会议基本情况"],
        }
    },
    "input_text": "会议召开时间为2026年5月20日14:00。",
}

evaluator = ConfidenceEvaluator()
result = evaluator.evaluate(record)
print(result)
```

一次性评估：

```python
from routed_confidence import evaluate_confidence

result = evaluate_confidence(record)
```

### 直接 LLM 评估

只配置模型时，SDK 会进入通用 LLM 评估模式。这个模式不限制字段名，适合开放式字段。

```python
from routed_confidence import ConfidenceEvaluator

record = {
    "input_text": "公司计划在上海建设新项目，总投资10亿元。",
    "extraction_result": {
        "项目地点": "上海",
        "总投资金额": "10亿元",
    },
}

evaluator = ConfidenceEvaluator(
    model="qwen3-14b",
    api_key="your-api-key",
    base_url="http://your-openai-compatible-endpoint/v1",
)

result = evaluator.evaluate(record)
print(result)
```

环境变量：

```bash
export ROUTED_CONFIDENCE_LLM_MODEL="qwen3-14b"
export ROUTED_CONFIDENCE_LLM_API_KEY="your-api-key"
export ROUTED_CONFIDENCE_LLM_BASE_URL="http://your-openai-compatible-endpoint/v1"
```

兼容常见项目环境变量：

```bash
export MODEL_NAME="qwen3-14b"
export API_KEY="your-api-key"
export BASE_URL="http://your-openai-compatible-endpoint/v1"
```

如果同时传入 `rules_file`、`weights`、`historical_data_file` 或 `wilson_scores`，SDK 会认为用户要使用多维评估器，不会自动切到 LLM-only 模式。需要强制使用 LLM-only 时，可以传：

```python
evaluator = ConfidenceEvaluator(
    model="qwen3-14b",
    api_key="your-api-key",
    base_url="http://your-openai-compatible-endpoint/v1",
    use_llm=True,
)
```

## 构建命名评估器

命名评估器适合某类固定业务数据。构建后，目录里保存的是配置包，不是 Python 代码；通用执行逻辑在 SDK 内部，具体业务差异由 `schema.json`、`relation_rules.json`、`wilson_scores.json` 决定。

因此 build 后看到目录里都是 JSON/YAML 是正常的。SDK 不是为每个数据类型生成一份新的 Python 文件，而是用同一套通用评估执行器读取不同配置：

```text
人员留置 evaluator -> 人员留置 schema / 关系 / Wilson
股东大会 evaluator -> 股东大会 schema / 关系 / Wilson
其他数据类型       -> 对应类型自己的 schema / 关系 / Wilson
```

运行时通过 evaluator 名字选择配置包：

```python
evaluator = ConfidenceEvaluator.from_name(
    "personnel_retention_v1",
    evaluators_dir="./confidence_evaluators",
)
```

### 构建

```python
from routed_confidence import EvaluatorBuilder

builder = EvaluatorBuilder(
    model="qwen3-14b",
    api_key="your-api-key",
    base_url="http://your-openai-compatible-endpoint/v1",
)

builder.build(
    evaluator_name="personnel_retention_v1",
    infotype="O_临时公告_人员留置",
    historical_data_file="./data/O_临时公告_人员留置_preprocessed.json",
    output_dir="./confidence_evaluators",
    schema_file=None,
    schema_edit_mode="suggest",
    relation_mode="llm",
    wilson_adjustment="suggest",
    overwrite=False,
)
```

`evaluator_name` 必须以英文字母开头，只能包含英文字母、数字和下划线：

```text
^[A-Za-z][A-Za-z0-9_]{0,63}$
```

如果 `output_dir/evaluator_name` 已存在且 `overwrite=False`，构建会直接报错。传 `overwrite=True` 才会重建。

### 输出目录

```text
confidence_evaluators/
  registry.json
  personnel_retention_v1/
    evaluator.yaml
    schema.json
    relation_rules.json
    wilson_scores.json
    field_statistics.json
    build_report.json
    prompts/
      relation_prompt.md
```

这些文件共同定义一个可复用 evaluator：

- `evaluator.yaml`：评估器元信息、权重、文件路径、fallback 策略。
- `schema.json`：字段类型、必填、枚举、格式、长度等规则。
- `relation_rules.json`：字段间关系规则。
- `wilson_scores.json`：historical/Wilson 字段先验。
- `field_statistics.json`：历史数据字段统计。
- `build_report.json`：构建报告、warning、来源说明。

### 加载

按名字加载：

```python
from routed_confidence import ConfidenceEvaluator

evaluator = ConfidenceEvaluator.from_name(
    "personnel_retention_v1",
    evaluators_dir="./confidence_evaluators",
)

result = evaluator.evaluate(record)
```

按目录加载：

```python
evaluator = ConfidenceEvaluator.from_config(
    "./confidence_evaluators/personnel_retention_v1"
)
```

### Schema

如果不传 `schema_file`，构建器会根据历史数据生成 schema。

如果传入 `schema_file`，必须符合 SDK schema v1.0 格式：

```json
{
  "format_version": "1.0",
  "fields": {
    "原文_姓名": {
      "type": "string",
      "required": true,
      "description": "被留置或解除留置的人员姓名"
    }
  }
}
```

支持的字段类型：

```text
string, number, integer, datetime, date, enum, boolean
```

`schema_edit_mode` 控制构建器是否处理用户 schema：

- `none`：只校验，不补充、不修改。
- `suggest`：不修改 schema，只在构建报告里写建议。
- `augment`：允许补充缺失字段、examples、description 等。
- `modify`：允许根据历史数据调整字段类型和 required。

如果用户传入 schema，建议先用 `schema_edit_mode="suggest"`。这样不会改 schema，只会在 `build_report.json` 里记录模型和统计分析给出的建议。

### 字段关系

字段关系由模型根据 `infotype`、schema、字段统计和样例梳理生成。输出文件是 `relation_rules.json`。

第一版支持的关系类型：

```text
date_lte, date_gte, number_lte, number_gte, same_value, required_together, mutually_exclusive
```

如果模型不可用或输出不合法，会使用启发式规则兜底，并在 `build_report.json` 里记录 warning。

### Historical / Wilson

`wilson_scores.json` 根据历史数据自动判断来源：

- 有 `is_correct` / `is_match`：使用 Wilson 下界，标记为 `wilson_from_ground_truth`。
- 没有正确性但有 `confidence` / `total_score`：使用历史置信度估计，标记为 `estimated_from_confidence`。
- 只有字段值：使用字段分布生成弱先验，标记为 `weak_prior_from_distribution`。

`wilson_adjustment` 可选值：

- `none`：完全使用统计结果。
- `suggest`：只在 metadata/build report 中给出建议。
- `bounded`：允许按字段分布做有限幅调整。

## 输入格式

评估输入可以是直接字段字典：

```python
record = {
    "input_text": "原文内容",
    "extraction_result": {
        "字段A": "抽取值A",
        "字段B": {
            "value": "抽取值B",
            "content": "字段附近上下文",
            "type": "text",
            "title_path": ["章节标题"],
        },
    },
}
```

Builder 的 `historical_data_file` 支持常见结构：

- SDK collector 输出的 `{ "records": {...} }`
- `{ "code": "...", "message": "...", "data": [...] }`
- 普通 `list[record]`
- 以 uuid 为 key 的对象

## 返回格式

多维评估器返回：

```json
{
  "field_scores": {
    "会议召开时间": {
      "source_value": "2026-05-20 14:00:00",
      "total_score": 0.75,
      "dimension_scores": {
        "schema": 1.0,
        "similarity": 0.82,
        "historical": 0.5,
        "relation": 1.0
      },
      "reason": "字段符合 schema",
      "violations": [],
      "suggestions": []
    }
  },
  "summary": {
    "total_fields": 1,
    "average_score": 0.75
  }
}
```

直接 LLM 评估器返回的维度是：

```json
{
  "dimension_scores": {
    "llm": 0.91
  }
}
```

注意：SDK 不返回 `is_correct`。`is_correct` 属于“标注数据 vs 提取数据”的评测逻辑，不属于置信度 SDK。

## 可选数据收集

如果想保存评估过的数据，初始化时传入 `collection_dir`：

```python
from routed_confidence import ConfidenceEvaluator

evaluator = ConfidenceEvaluator(
    collection_dir="./collected_data",
)

result = evaluator.evaluate(
    record,
    uuid="doc-001",
    infotype="股东大会-股东大会召开情况",
)
```

生成文件：

```text
./collected_data/evaluated_records_collected.json
```

收集文件格式：

```json
{
  "collection_info": {
    "description": "routed_confidence SDK collected evaluations",
    "format_version": "1.0"
  },
  "summary": {
    "total_records": 1,
    "updated_at": "2026-05-13T12:00:00"
  },
  "records": {
    "doc-001": {
      "uuid": "doc-001",
      "timestamp": "2026-05-13T12:00:00",
      "infotype": "股东大会-股东大会召开情况",
      "input": {
        "extraction_result": {}
      },
      "output": {
        "field_scores": {},
        "summary": {}
      }
    }
  }
}
```

说明：

- 只有传入 `collection_dir` 才会开启收集。
- `uuid` 用于去重；同一个 `uuid` 重复评估时只保留第一次收集的数据。
- 如果不传 `uuid`，SDK 会尝试从 `record["uuid"]`、`record["met_uuid"]`、`record["id"]` 或 `record["metadata"]` / `record["met_meta"]` 中读取；都没有时会自动生成一个 UUID。
- `infotype` 只作为记录元数据保存，不影响输出文件名。
- 收集失败不会影响评估结果返回。

这是一种轻量、可选、默认关闭的收集能力。没有 `collection_dir` 参数时，SDK 不会写任何收集文件。

## 自定义规则和权重

内置固定评估器支持传入规则和权重：

```python
from routed_confidence import ConfidenceEvaluator

evaluator = ConfidenceEvaluator(
    rules_file="/path/to/meeting_ruler.json",
    weights={
        "schema": 0.1,
        "sim": 0.2,
        "wilson": 0.1,
        "relation": 0.6,
    },
)
```

如果不传 `rules_file`，SDK 会优先寻找当前项目里的 `schema/ruler/meeting_ruler.json`，找不到时使用包内置的默认规则。

## Embedding 相似度

`similarity` 维度默认会尝试调用 OpenAI-compatible embedding 接口。

开源包不会内置任何 embedding 服务地址、模型名或 API Key。不显式配置时，SDK 会提示并自动使用本地 fuzzy 相似度，评估流程不会中断。

如果显式配置了 embedding，但服务不可用，SDK 也会提示并自动回退到本地 fuzzy 相似度。

显式配置：

```python
from routed_confidence import ConfidenceEvaluator

evaluator = ConfidenceEvaluator(
    embedding_api_base_url="http://your-embedding-service:8191",
    embedding_model="qwen3-embedding-0.6b",
    embedding_api_key="your-api-key",
)
```

环境变量：

```bash
export ROUTED_CONFIDENCE_EMBEDDING_API_BASE_URL="http://your-embedding-service:8191"
export ROUTED_CONFIDENCE_EMBEDDING_MODEL="qwen3-embedding-0.6b"
export ROUTED_CONFIDENCE_EMBEDDING_API_KEY="your-api-key"
```

本地 fallback 使用 fuzzy 相似度：

```text
0.6 * jaccard_similarity + 0.4 * sequence_similarity
```

## 包结构

主要入口：

```text
routed_confidence/evaluator.py
routed_confidence/builder.py
routed_confidence/configured_evaluator.py
routed_confidence/llm_evaluator.py
routed_confidence/collection.py
```

构建器内部模块：

```text
routed_confidence/builder_parts/
```

内置规则和默认 historical/Wilson 数据：

```text
routed_confidence/rules/meeting_ruler.json
routed_confidence/data/default_wilson_scores.json
```

## 本地测试

在项目根目录执行：

```bash
cd /Users/apple/Documents/work/routeD/routed
python3 test_routed_confidence_collector.py
```

当前测试脚本覆盖：

- 默认不收集数据。
- 传入 `collection_dir` 后会收集评估输入/输出，并按 UUID 去重。
- 内置 Wilson 默认数据可以加载。
- 只配置模型时可以进入 LLM 通用评估模式。
- `EvaluatorBuilder.build(...)` 可以基于本地历史数据构建命名 evaluator。
- 构建后的 evaluator 可以通过 `ConfidenceEvaluator.from_name(...)` 加载并执行评估。

测试输出目录：

```text
/Users/apple/Documents/work/routeD/routed/tmp_routed_confidence_collector_test
```

测试脚本会读取项目根目录 `.env` 中的模型配置，例如：

```text
MODEL_NAME=qwen3-14b
BASE_URL=http://your-openai-compatible-endpoint/v1
API_KEY=your-api-key
```

如果只是做确定性冒烟测试，脚本会使用 fake client，避免依赖真实模型返回。

## 发布

安装构建工具：

```bash
pip install build twine
```

构建：

```bash
rm -rf dist build *.egg-info
python -m build
```

上传到 PyPI：

```bash
twine upload dist/*
```

上传到私有 PyPI：

```bash
twine upload --repository-url https://your-private-pypi/simple/ dist/*
```

## 当前边界

- 只做单条/字段级置信度评估。
- 可选收集评估过的数据，但默认关闭。
- 不计算检出率。
- 不计算误伤率。
- 不包含 Web/API 服务。
- 不自动生成 Python validator 代码。
- 不要求用户导入内部四维组件。
