Files
violation-detector/README.md
3218485270 b413104587 feat: 结构化输出按官方规范 + 两段式重试 + DeepSeek 复检开关
- 豆包: response_format.json_schema(strict);DeepSeek: 切 Responses API text.format.json_schema
  (官方 chat/completions 通道不支持 json_schema),不支持时自动降级 json_object([output] schema)
- 重试两段式:传输错误 cfg.retries 次;解析失败/空正文有独立 3 次专用重试,仍失败落 parse_fail
- 移除三票复核(decide_final/_verify_clean/verify_clean),DeepSeek 单次判定即终稿
- 新增 [run] deepseek_recheck 开关(默认 no=仅豆包初筛;yes=追加 DeepSeek 复检)
- GUI 不再覆盖 config 提示词;prompt 相对/前导斜杠路径按 exe 目录解析
- 报表去「票型/复核」列并同步说明;README/config.example.ini 同步
- 测试新增输出格式、重试、开关与提示词路径用例(50 passed)
2026-09-03 11:44:10 +08:00

137 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 商品图合规检测工具
同一份 17 类违规检测提示词,两级级联调用视觉模型,在控制成本的同时从严检测:
```
全部图片 ──▶ 豆包(火山方舟 Ark)初筛 ──┬─ 判为违规 ──▶ 直接定稿(便宜,拦下大头)
└─ 无违规/违规不明/异常 ──▶ DeepSeek 复检(可开关)
(单次判定即终稿,已移除三票复核)
```
DeepSeek 复检默认关闭(`[run] deepseek_recheck=no`),即默认只跑豆包初筛;
需要第二级复检时把该开关设为 `yes`(或 `mode=deepseek` 全量走 DeepSeek)。
AI 输出启用官方结构化输出:豆包走 `response_format.json_schema`strict),DeepSeek 走
Responses API 的 `text.format.json_schema`(其 chat/completions 通道不支持 schema);
接口不支持时自动降级 `json_object`(见 `[output] schema`),保证单次判定稳定可靠。
## 输出结构
指定输出目录后,自动建立时间戳文件夹,按分类归档图片,Excel 放在一级目录:
```
<输出目录>/检测结果_20260902_151603/
├── 违规检测结果_20260902_151604.xlsx # 检测明细 + 统计汇总
├── 12. 侵权 - 除人物外的其他侵权/ *.jpg
├── 13. 侵权 - 人物相关(…)/
├── 无违规/ ……
```
## 使用方式
### exe 版(dist/ 目录)
- `商品图合规检测工具.exe`:双击打开图形界面(零配置:选图片文件夹和输出目录即可)。
- `商品图合规检测工具CLI.exe`:命令行版,用法同下方 CLI。
- 首次运行会在 exe 同目录生成 `config.ini` 模板;GUI 会弹窗引导填写
豆包 API Key / 接入点、DeepSeek API Key / 模型,四项填完保存即可。
- 内置提示词(打包进 exe);界面上也可另选 txt 覆盖。
### 源码运行(Python ≥3.10
```bash
uv run violation-detector-gui # GUI
uv run violation-detector tests -o output # CLI
# 或免安装:
PYTHONPATH=src python -m violation_detector.gui
PYTHONPATH=src python -m violation_detector tests -o output
```
### 重新打包
```bash
uv run --with pyinstaller --with aiohttp --with openpyxl \
pyinstaller --noconfirm --clean --onefile --windowed \
--name 商品图合规检测工具 --add-data "prompts.txt;." --paths src app_gui.py
uv run --with pyinstaller --with aiohttp --with openpyxl \
pyinstaller --noconfirm --clean --onefile \
--name 商品图合规检测工具CLI --add-data "prompts.txt;." --paths src app_cli.py
```
## CLI 用法
```
商品图合规检测工具CLI <图片文件夹> [选项]
-o, --output DIR 输出目录(默认为图片文件夹)
--mode cascade(默认)/ doubao / deepseek
--prompt FILE 自定义提示词(默认内置 prompts.txt
--workers-ark/--workers-ds/--max-tokens 调优项(默认即可)
```
## 配置(config.ini,自动生成)
缺失必填项时:GUI 弹窗引导填写;CLI 打印缺哪些项后退出。也可用环境变量
`ARK_API_KEY` / `ARK_MODEL_ID` / `DEEPSEEK_API_KEY` / `DEEPSEEK_MODEL` 覆盖。
```ini
[ark]
api_key = ...
model_id = ep-xxxx
[deepseek]
api_key = sk-...
model = deepseek-v4-flash-vision-exp
max_tokens = 5000
[run]
mode = cascade # cascade / doubao(仅豆包)/ deepseek(仅 DeepSeek
deepseek_recheck = no # 仅 cascade 生效:no=只豆包初筛(默认)/ yes=追加 DeepSeek 复检
[output]
schema = auto # auto(默认)/ on / off;auto=启用官方结构化输出,接口不支持自动降级 json_object
```
运行模式:config.ini `[run] mode` 全局生效(GUI 也跟随);CLI 的 `--mode` 参数可临时覆盖。
DeepSeek 复检开关:`[run] deepseek_recheck`(默认 `no`)。`no` 时 cascade 等效“仅豆包”,
DeepSeek 相关的 API Key 也不再是必填项;需要 DeepSeek 复检时设 `yes`(或直接 `mode=deepseek` 全量走 DeepSeek)。
## 项目结构
```
├── src/violation_detector/
│ ├── config.py # 配置(自动生成 ini、缺项检测、冻结环境路径)
│ ├── providers.py # 豆包/DeepSeek 异步客户端,统一结果结构
│ ├── pipeline.py # 级联调度、断点缓存(runs/)、成本汇总
│ ├── report.py # 时间戳输出目录、分类归档、Excel 报表
│ ├── cli.py / gui.py
├── app_gui.py / app_cli.py # 启动器 + PyInstaller 入口
├── prompts.txt # 内置提示词
├── runs/ # 分阶段缓存(断点续跑;删缓存即全量重跑)
├── dist/ # 打包产物 exe
└── legacy/ # 早期脚本与实验数据
```
## 日志与排错
所有运行过程写入日志文件(exe 同目录 / 源码项目根目录下的 `logs/violation_detector_日期.log`):
- 文件记录 DEBUG 级全量:运行配置、缓存命中、每次请求的重试与 HTTP 响应体、异常完整堆栈;
- 控制台/GUI 只显示 INFO 级简洁信息,异常时同样附带完整 traceback;
- GUI 右下角「打开日志」按钮直达日志文件;CLI 出错时会在结尾打印日志文件路径。
```bash
# 跑测试(33 个单元测试,无需网络与 API Key)
uv run --with pytest --with aiohttp --with openpyxl --no-project \
env PYTHONPATH=src pytest tests -q
```
## 检测规则与已知特性
- 分类按提示词 17 类标准输出唯一分类,自动归一化写法差异。
- AI 输出:按官方启用结构化输出——豆包=response_format.json_schema(strict)
DeepSeek=Responses API 的 text.format.json_schema(约束「文字/图形属性 · 侵权/违规逻辑 ·
违规分类」三字段);接口不支持时自动降级 json_object[output] schema)。
DeepSeek 走 chat/completions 兜底时 temperature=0、max_tokens=5000。
- 复检单次即终稿:DeepSeek 对豆包放行/存疑图各跑一遍即定稿,不再追加多票复核。
- 边界图仍可能存在运行间抖动(单模型单次判定所致),成本较低可整批重跑比对,存疑图建议人工终审。
- 级联成本:DeepSeek 只处理豆包放行的少数存疑图(单张约 1-1.6 分钱,
空闲时段半价;高峰=工作日 9-12、14-18 点)。