Field-level confidence evaluator SDK for routed extraction results
Project description
routed-confidence
字段级置信度评估 SDK。
routed-confidence 输入一条抽取结果,输出每个字段的置信度分数。它默认不写文件、不启动服务、不计算检出率/误伤率/日报统计。只有显式传入 collection_dir 时,才会把评估输入和输出收集到本地 JSON 文件。
Python 包名:
pip install routed-confidence
Python 导入名:
from routed_confidence import ConfidenceEvaluator
核心能力
SDK 有三类使用模式:
| 模式 | 入口 | 适用场景 |
|---|---|---|
| 内置评估器 | ConfidenceEvaluator.from_infotype(...)、from_builtin(...) 或 from_name(..., evaluators_dir=None) |
使用 SDK 包内置 evaluator,包括股东大会召开情况规则和上市公司公告类别配置包 |
| 直接 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 评估模式。 - 想使用 SDK 已内置的 evaluator 时,使用
ConfidenceEvaluator.from_infotype(...)、ConfidenceEvaluator.from_builtin(...)或ConfidenceEvaluator.from_name(..., evaluators_dir=None)。 - 想构建某类数据专用 evaluator 时,使用
EvaluatorBuilder.build(...),构建完成后再通过ConfidenceEvaluator.from_name(...)或ConfidenceEvaluator.from_config(...)加载。 - 使用
ConfidenceEvaluator.from_name(...)或ConfidenceEvaluator.from_config(...)时,会加载构建后的配置化评估器。 ConfidenceEvaluator()仍保留为兼容旧用法,等价于加载包内置的LegacyMeetingEvaluator股东大会召开情况规则。
也就是说:
只想马上评估任意字段 -> 直接 LLM 模式
想使用内置 evaluator -> from_infotype / from_builtin
想针对某类数据沉淀规则 -> 先 build,再按 evaluator_name 加载
想使用内置股东大会规则 -> from_infotype("股东大会-股东大会召开情况")
安装
本地开发安装:
pip install -e .
从本地 wheel 安装:
python3 -m pip wheel . --no-deps --no-build-isolation -w dist
pip install dist/routed_confidence-*.whl
从 PyPI 或私有 PyPI 安装:
pip install routed-confidence
快速开始
内置评估器
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.from_infotype("股东大会-股东大会召开情况")
result = evaluator.evaluate(record)
print(result)
也可以用 evaluator 名称加载同一个内置评估器:
evaluator = ConfidenceEvaluator.from_builtin("LegacyMeetingEvaluator")
ConfidenceEvaluator() 仍可使用,但它只是兼容旧写法;新代码建议统一使用 from_infotype(...) 或 from_builtin(...)。
一次性评估:
from routed_confidence import evaluate_confidence
result = evaluate_confidence(record)
SDK 也内置了从 methods/100_kinds/evaluator_generator/output 迁移来的上市公司公告类别配置包。调用时同样优先按 infotype 加载:
from routed_confidence import ConfidenceEvaluator
record = {
"input_text": "公司将于2025年9月19日15:00-17:00通过网络远程方式举行上市公司集体接待日活动。",
"extraction_result": {
"原文_举行方式": {
"value": "网络远程",
"content": "通过网络远程方式举行",
"type": "text",
"title_path": ["活动安排"],
},
"原文_活动时间": {
"value": "2025年9月19日15:00-17:00",
"content": "2025年9月19日15:00-17:00",
"type": "text",
"title_path": ["活动安排"],
},
},
}
evaluator = ConfidenceEvaluator.from_infotype("临时公告-上市公司集体接待日")
result = evaluator.evaluate(record)
也可以按 evaluator 名称加载:
evaluator = ConfidenceEvaluator.from_builtin("TN_LCRDEvaluator")
result = evaluator.evaluate(record)
或用 from_name(..., evaluators_dir=None) 表示从 SDK 内置目录加载:
evaluator = ConfidenceEvaluator.from_name("TN_LCRDEvaluator", evaluators_dir=None)
内置类别查询
内置 evaluator 的字段名以 SDK 内置配置为准。调用前不要手写或猜测字段名;请统一通过查询接口确认 infotype、evaluator_name 和该类别接收的字段名。
完整类别和字段清单见 docs/builtin_evaluators.md。
查看当前内置类别:
from routed_confidence import list_builtin_infotypes
for item in list_builtin_infotypes():
print(item)
当前内置 evaluator 数量为 109 个;其中 LegacyMeetingEvaluator 是包内置的股东大会召开情况规则,其余为上市公司公告类别配置包。infotype 支持完整名称和常见别名,例如 临时公告-上市公司集体接待日 与 上市公司集体接待日 都可以匹配。
list_builtin_infotypes() 返回示例:
[
{
"infotype": "股东大会-股东大会召开情况",
"evaluator_name": "LegacyMeetingEvaluator",
"aliases": ["股东大会-股东大会召开情况", "股东大会召开情况", "股东大会", "meeting"],
"field_count": 15,
"score_scaling": False,
},
{
"infotype": "临时公告-发生重大债务或重大债权到期未清偿",
"evaluator_name": "TN_MDOCDEvaluator",
"aliases": ["临时公告-发生重大债务或重大债权到期未清偿"],
"field_count": 8,
"score_scaling": True,
},
]
查询某个类别接收的字段名和输入格式:
from routed_confidence import get_builtin_evaluator_info
info = get_builtin_evaluator_info("临时公告-发生重大债务或重大债权到期未清偿")
print(info["evaluator_name"])
print(info["field_names"])
print(info["fields"]["原文_证券代码"])
print(info["input_shape"])
get_builtin_evaluator_info(...) 返回示例:
{
"evaluator_name": "TN_MDOCDEvaluator",
"infotype": "临时公告-发生重大债务或重大债权到期未清偿",
"field_count": 8,
"field_names": [
"原文_公司名称",
"原文_证券代码",
"原文_证券简称",
"原文_重要内容提示",
"原文_债务未清偿原因",
"原文_未清偿债务本息金额",
"原文_公告日期_不包括年份",
"原文_未清偿债务利息和违约金合计金额",
],
"score_scaling": {
"enabled": True,
"mode": "legacy_display_score",
"field_thresholds": {"原文_证券代码": 0.41533266205276875},
},
"input_shape": {
"record": {
"input_text": "公告全文或相关原文,可选但建议提供",
"extraction_result": {
"原文_证券代码": {
"value": "<抽取值>",
"content": "<字段证据文本,可选>",
"type": "string",
"title_path": "<标题路径,可选>",
}
},
},
"field_value_keys": ["value", "content", "type", "title_path"],
},
}
input_shape 描述 SDK 接收的记录结构。核心格式是:
record = {
"input_text": "公告全文或相关原文",
"extraction_result": {
"原文_证券代码": {
"value": "600466",
"content": "证券代码:600466",
"type": "string",
"title_path": ["公告标题"],
}
},
}
字段值也可以简写成原始值:
record = {
"input_text": "证券代码:600466",
"extraction_result": {
"原文_证券代码": "600466",
},
}
批量工作流与续写输出
如果希望一次跑直接 LLM、临时构建 evaluator、内置 evaluator,并把过程完整保存到本地目录,可以使用 ConfidenceWorkflowRunner。用户只需要提供模型配置、输入文件和输出目录;SDK 会负责:
- 每条成功后立即保存 partial/final 结果
- 再次运行时跳过已经成功的
index + uuid - 中断后续跑
- 跳过 live LLM 时保留已有 direct LLM 成功结果
- 构建 evaluator 包已存在时自动复用
from routed_confidence import ConfidenceWorkflowRunner, WorkflowRunConfig
config = WorkflowRunConfig(
output_dir="tmp_routed_confidence_prompt_test",
input_file="methods/100_kinds/collect_dataset_match_confidence_10/O_临时公告_发生重大债务或重大债权到期未清偿_corrected.json",
limit=10,
infotype="临时公告-发生重大债务或重大债权到期未清偿",
evaluator_name="sdk_mdocd_smoke",
model="qwen3-14b",
api_key="your-api-key",
base_url="http://your-openai-compatible-endpoint/v1",
llm_timeout=600,
evidence_mode="auto",
retrieval_top_k=5,
)
summary = ConfidenceWorkflowRunner(config, progress=print).run()
print(summary)
默认是续写模式。需要清空输出目录重新开始时设置:
config.reset_output = True
直接 LLM 评估
只配置模型时,SDK 会进入通用 LLM 评估模式。这个模式不限制字段名,适合开放式字段。
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)
环境变量:
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"
兼容常见项目环境变量:
export MODEL_NAME="qwen3-14b"
export API_KEY="your-api-key"
export BASE_URL="http://your-openai-compatible-endpoint/v1"
直接 LLM 模式会在 SDK 内部处理模型交互的稳定性:默认关闭思考输出,模型请求超时、连接错误、5xx/429、JSON 解析失败等可恢复错误会自动重试;多次失败后会为每个字段返回中性兜底分 0.5 和失败原因,调用方不需要自己写重试或跳过逻辑。
长文本会自动走字段级证据模式:field.content 只作为候选证据,SDK 会先校验它是否可追溯到 input_text,再从全文检索每个字段相关的 top-k 证据片段。模型收到的是证据包,不是整篇一两百页的长文。
证据模式参数:
evaluator = ConfidenceEvaluator(
model="qwen3-14b",
api_key="your-api-key",
base_url="http://your-openai-compatible-endpoint/v1",
evidence_mode="auto", # auto / verify_then_retrieve / raw
retrieval_top_k=5,
chunk_size=1200,
chunk_overlap=150,
max_evidence_chars=8000,
)
行为:
auto:有字段content或input_text超过约 20000 字符时启用证据解析。verify_then_retrieve:总是启用证据解析。raw:保留旧行为,直接传截断后的input_text和字段content。
默认输出仍只包含 total_score 和 reason。排查证据检索时使用 include_details=True,每个字段会额外包含 evidence,例如:
{
"candidate_content": {
"text": "证券代码:600466",
"found_in_input_text": true,
"match_score": 1.0
},
"retrieved_evidence": [
{
"text": "证券代码:600466 证券简称:*ST蓝光",
"match_score": 0.97,
"source": "input_text"
}
],
"evidence_summary": {
"has_verified_content": true,
"has_retrieved_evidence": true,
"value_found_in_retrieved_evidence": true
}
}
可选环境变量:
export ROUTED_CONFIDENCE_LLM_MAX_RETRIES=2
export ROUTED_CONFIDENCE_LLM_RETRY_DELAY=2
export ROUTED_CONFIDENCE_LLM_FAIL_ON_ERROR=false
需要严格失败而不是兜底时,可以传:
evaluator = ConfidenceEvaluator(
model="qwen3-14b",
api_key="your-api-key",
base_url="http://your-openai-compatible-endpoint/v1",
llm_fail_on_error=True,
)
如果同时传入 rules_file、weights、historical_data_file 或 wilson_scores,SDK 会认为用户要使用多维评估器,不会自动切到 LLM-only 模式。需要强制使用 LLM-only 时,可以传:
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 文件,而是用同一套通用评估执行器读取不同配置:
人员留置 evaluator -> 人员留置 schema / 关系 / Wilson
股东大会 evaluator -> 股东大会 schema / 关系 / Wilson
其他数据类型 -> 对应类型自己的 schema / 关系 / Wilson
运行时通过 evaluator 名字选择配置包:
evaluator = ConfidenceEvaluator.from_name(
"personnel_retention_v1",
evaluators_dir="./confidence_evaluators",
)
构建
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 必须以英文字母开头,只能包含英文字母、数字和下划线:
^[A-Za-z][A-Za-z0-9_]{0,63}$
如果 output_dir/evaluator_name 已存在且 overwrite=False,构建会直接报错。传 overwrite=True 才会重建。
输出目录
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、来源说明。
加载
按名字加载:
from routed_confidence import ConfidenceEvaluator
evaluator = ConfidenceEvaluator.from_name(
"personnel_retention_v1",
evaluators_dir="./confidence_evaluators",
)
result = evaluator.evaluate(record)
按目录加载:
evaluator = ConfidenceEvaluator.from_config(
"./confidence_evaluators/personnel_retention_v1"
)
Schema
如果不传 schema_file,构建器会根据历史数据生成 schema。
如果传入 schema_file,必须符合 SDK schema v1.0 格式:
{
"format_version": "1.0",
"fields": {
"原文_姓名": {
"type": "string",
"required": true,
"description": "被留置或解除留置的人员姓名"
}
}
}
支持的字段类型:
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。
第一版支持的关系类型:
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:允许按字段分布做有限幅调整。
输入格式
评估输入可以是直接字段字典:
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 的对象
返回格式
默认返回简洁格式,每个字段只包含 total_score 和 reason:
{
"field_scores": {
"会议召开时间": {
"total_score": 0.75,
"reason": "字段符合 schema"
}
}
}
本地测试或排查时可以打开详细输出:
evaluator = ConfidenceEvaluator.from_infotype(
"临时公告-发生重大债务或重大债权到期未清偿",
include_details=True,
)
result = evaluator.evaluate(record)
include_details=True 时返回完整调试信息:
{
"field_scores": {
"原文_证券代码": {
"source_value": "600000",
"total_score": 0.9297,
"raw_total_score": 0.8357,
"dimension_scores": {
"schema": 1.0,
"similarity": 0.82,
"historical": 0.5,
"relation": 1.0
},
"reason": "字段符合 schema",
"score_scaling": {
"threshold": 0.4153,
"direction": "low",
"triggered": false,
"is_match": true,
"calibrated_score": 0.7946
},
"violations": [],
"suggestions": []
}
},
"summary": {
"total_fields": 1,
"average_score": 0.75
}
}
直接 LLM 评估器在默认模式下同样只返回 total_score 和 reason。include_details=True 时会包含:
{
"dimension_scores": {
"llm": 0.91
}
}
注意:SDK 不返回 is_correct。is_correct 属于“标注数据 vs 提取数据”的评测逻辑,不属于置信度 SDK。
字段阈值缩放
内置公告配置包 evaluator 中,带旧版字段阈值配置的类别会启用字段级缩放。缩放发生在多维加权分之后:
schema / similarity / wilson / relation -> raw_total_score -> 字段阈值缩放 -> total_score
缩放规则沿用旧 evaluator 的展示分语义:
通过字段:映射到 [0.8, 1.0]
未通过字段:映射到 [0.0, 0.4]
默认输出只返回缩放后的 total_score。需要查看原始加权分、字段阈值和是否触发时,使用 include_details=True。
可选数据收集
如果想保存评估过的数据,初始化时传入 collection_dir:
from routed_confidence import ConfidenceEvaluator
evaluator = ConfidenceEvaluator(
collection_dir="./collected_data",
)
result = evaluator.evaluate(
record,
uuid="doc-001",
infotype="股东大会-股东大会召开情况",
)
生成文件:
./collected_data/evaluated_records_collected.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 不会写任何收集文件。
自定义规则和权重
使用 legacy 股东大会规则评估器时,也可以直接传入自定义规则和权重:
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 相似度。
显式配置:
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",
)
环境变量:
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 相似度:
0.6 * jaccard_similarity + 0.4 * sequence_similarity
包结构
主要入口:
routed_confidence/evaluator.py
routed_confidence/builder.py
routed_confidence/configured_evaluator.py
routed_confidence/llm_evaluator.py
routed_confidence/builtin.py
routed_confidence/builtin_importer.py
routed_confidence/collection.py
构建器内部模块:
routed_confidence/builder_parts/
内置规则和默认 historical/Wilson 数据:
routed_confidence/rules/meeting_ruler.json
routed_confidence/data/default_wilson_scores.json
routed_confidence/builtin_evaluators/
当前边界
- 只做单条/字段级置信度评估。
- 可选收集评估过的数据,但默认关闭。
- 不计算检出率。
- 不计算误伤率。
- 不包含 Web/API 服务。
- 不自动生成 Python validator 代码。
- 不要求用户导入内部四维组件。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file routed_confidence-0.1.7.tar.gz.
File metadata
- Download URL: routed_confidence-0.1.7.tar.gz
- Upload date:
- Size: 503.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4323f3f29dd5053e1c92ff396105fbdcad34bee459947996870e096e21d3ad18
|
|
| MD5 |
df9b01206fafb2a2c7736d9320057b07
|
|
| BLAKE2b-256 |
58ea7539e0f28d78a9f5ea7e164f194e000d94e58394d543b0523a94e1e9457b
|
File details
Details for the file routed_confidence-0.1.7-py3-none-any.whl.
File metadata
- Download URL: routed_confidence-0.1.7-py3-none-any.whl
- Upload date:
- Size: 732.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c7804256701f56a6fbd71b31f100992dce4f05e73a7f28711dc44368b872dbc
|
|
| MD5 |
4c187c60c37f227deb7c14e06d5411ef
|
|
| BLAKE2b-256 |
f514232732af446d0dc98770da2af09f19598b0628d87f843495a2c51d1f6bf4
|