refactor: --id 改为真实 ID 列,新增 --sn 对应总排号

此前接口 --id 实际按总排号列查询,与数据库真实 ID 字段语义混淆。
现明确区分两种键类型:
- --id  -> 数据库真实 ID 列(config id_field)
- --sn  -> 总排号列(config id_column,即原先 --id 的语义)
- --ids-file 视为总排号(键类型 sn)

db.py: fetch_params_by_ids 改为接受 (标识符, 键类型) 列表,返回
  {标识符: {param, sn}};id 键回取对应总排号;新增 id_field 配置读取
classifier.py: classify_batch/classify_single 透传键类型,输出 zong_pai_hao
  一律为回查到的总排号,not_found 时回退输入标识符便于追溯
main.py / write_attachments.py: 新增 --sn,--id 改指真实 ID,二者可混用;
  全表扫描回退仍按总排号(sn)查询
README.md: 对齐 --id/--sn 语义并补充 id_field 配置说明

注:config.yaml 含密钥被 .gitignore 忽略,id_field 仅存于本地配置;
db.py 在未配置 id_field 时优雅降级为按总排号查询并告警。

Co-Authored-By: WorkBuddy <workbuddy@tencent.com>
This commit is contained in:
Misaka_Company
2026-07-24 16:00:21 +08:00
parent 622f348cf1
commit ee566e3fbd
5 changed files with 236 additions and 121 deletions

63
main.py
View File

@@ -3,15 +3,23 @@
"""布莱迪压力表 - 订单附件识别 命令行入口。
用法:
python main.py --id 26B742 # 单个总排号(粗分类,默认)
python main.py --id 26B742,26B743,26B744 # 批量,逗号分隔
python main.py --ids-file ids.txt # 批量,文件每行一个总排号
python main.py --id 26B742 --mode fine # 精分类(输出"大类:细分"格式)
python main.py --id 26B742 --config other.yaml # 指定其他配置文件
python main.py --id 26B742 --pretty # 格式化输出JSON(默认单行紧凑)
python main.py --id 26B742 --log-dir /tmp/logs # 覆盖配置文件里的日志目录
python main.py --id 26B742 --enable-other # 允许模型使用"其他"兜底类目
python main.py --id 26B742 --summary # 额外在 stderr 打印本批运行汇总统计
python main.py --sn 26B742 # 单个总排号(粗分类,默认)
python main.py --sn 26B742,26B743,26B744 # 批量,逗号分隔
python main.py --id 802 # 单个数据库真实 ID
python main.py --id 802,803,804 # 批量真实 ID逗号分隔
python main.py --ids-file ids.txt # 批量,文件每行一个总排号(键类型 sn)
python main.py --sn 26B742 --mode fine # 精分类(输出"大类:细分"格式)
python main.py --id 802 --config other.yaml # 指定其他配置文件
python main.py --sn 26B742 --pretty # 格式化输出JSON(默认单行紧凑)
python main.py --sn 26B742 --log-dir /tmp/logs # 覆盖配置文件里的日志目录
python main.py --sn 26B742 --enable-other # 允许模型使用"其他"兜底类目
python main.py --sn 26B742 --summary # 额外在 stderr 打印本批运行汇总统计
指定方式(两种键类型可混用):
--id 数据库真实 ID 列(id_field),如 802
--sn 总排号列(id_column),如 26B742即原先 --id 的语义)
--ids-file 每行一个总排号(键类型 sn)
无论用哪种方式指定,输出 JSON 中的 zong_pai_hao 一律为回查到的总排号。
分类模式(--mode):
coarse (默认) - 只判断大类: 资料/配件/耗材(启用 --enable-other 时还有"其他")
@@ -62,19 +70,27 @@ from classifier import classify_batch, summarize_results # noqa: E402
from config_loader import ConfigError, load_config # noqa: E402
def _parse_ids(args: argparse.Namespace) -> list[str]:
"""从 --id --ids-file 解析出总排号列表,去除空白项。"""
ids: list[str] = []
def _parse_ids(args: argparse.Namespace) -> list[tuple[str, str]]:
"""从 --id / --sn / --ids-file 解析出 (标识符, 键类型) 列表。
--id -> 键类型 "id"(数据库真实 ID 列)
--sn -> 键类型 "sn"(总排号列,即原先 --id 的语义)
--ids-file -> 每行一个总排号,键类型 "sn"
三者可同时提供、合并后返回(顺序:--id, --sn, --ids-file
"""
items: list[tuple[str, str]] = []
if args.id:
ids.extend(s.strip() for s in args.id.split(",") if s.strip())
items.extend((s.strip(), "id") for s in args.id.split(",") if s.strip())
if args.sn:
items.extend((s.strip(), "sn") for s in args.sn.split(",") if s.strip())
if args.ids_file:
p = Path(args.ids_file)
if not p.exists():
print(f"[错误] 总排号文件不存在: {p.resolve()}", file=sys.stderr)
sys.exit(1)
with p.open("r", encoding="utf-8") as f:
ids.extend(line.strip() for line in f if line.strip())
return ids
items.extend((line.strip(), "sn") for line in f if line.strip())
return items
def main() -> None:
@@ -85,11 +101,16 @@ def main() -> None:
)
parser.add_argument(
"--id", type=str, default=None,
help="总排号,单个或逗号分隔的多个,例如: 26B742 或 26B742,26B743",
help="数据库真实 ID如 802,单个或逗号分隔的多个,例如: 802 或 802,803",
)
parser.add_argument(
"--sn", type=str, default=None,
help="总排号(如 26B742单个或逗号分隔的多个例如: 26B742 或 26B742,26B743"
"与 --id 同义但键类型不同(--sn 查总排号列,--id 查真实 ID 列)",
)
parser.add_argument(
"--ids-file", type=str, default=None,
help="包含总排号的文本文件路径,每行一个总排号",
help="包含总排号的文本文件路径,每行一个总排号(键类型 sn",
)
parser.add_argument(
"--config", type=str, default="config.yaml",
@@ -119,12 +140,12 @@ def main() -> None:
)
args = parser.parse_args()
if not args.id and not args.ids_file:
parser.error("必须提供 --id --ids-file 其中之一")
if not args.id and not args.sn and not args.ids_file:
parser.error("必须提供 --id / --sn / --ids-file 其中之一")
ids = _parse_ids(args)
if not ids:
print("[错误] 未解析到任何有效的总排号", file=sys.stderr)
print("[错误] 未解析到任何有效的标识符(--id / --sn / --ids-file 均为空)", file=sys.stderr)
sys.exit(1)
try:
@@ -148,7 +169,7 @@ def main() -> None:
results = classify_batch(
db_cfg=cfg["database"],
llm_cfg=cfg["llm"],
zong_pai_hao_list=ids,
id_list=ids,
max_workers=cfg["business"]["max_workers"],
mode=mode,
log_dir=log_dir,