完善差旅报销归档流程

将附件整理到本次处理目录,并在填表后按行程信息归档,避免过程文件和报销附件污染根目录。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
copper-xw 2026-05-29 11:50:12 +08:00
parent 4e869ba4b3
commit be21f0ab5a
3 changed files with 215 additions and 65 deletions

9
.gitignore vendored
View File

@ -1,3 +1,12 @@
*.pdf *.pdf
*.jpg *.jpg
*.jpeg
*.png
*.txt
*.json
*.xlsx
报销输出/ 报销输出/
__pycache__/
[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/
[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-*/
[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_*/

View File

@ -5,8 +5,8 @@
当用户把本 `README.md` 提供给大模型,或让大模型在本目录处理差旅报销时,大模型应直接按下面流程开始执行,不需要用户再复制额外提示词: 当用户把本 `README.md` 提供给大模型,或让大模型在本目录处理差旅报销时,大模型应直接按下面流程开始执行,不需要用户再复制额外提示词:
1. 先阅读本说明,确认当前目录是报销目录。 1. 先阅读本说明,确认当前目录是报销目录。
2. 检查当前目录是否存在基础文件:`差旅报销.py`、`差旅费明细表.xlsx`、本次报销 PDF。 2. 检查当前目录是否存在基础文件:`差旅报销.py`、`差旅费明细表.xlsx`,以及用户放在根目录的本次报销 PDF/图片附件。
3. 如果 `报销输出/pdf_raw_text.txt` 不存在,自动运行: 3. 自动运行 `extract`,脚本会先把根目录的 PDF/JPG/JPEG/PNG 移动到处理当天目录(如 `20260529/`),再提取 PDF 原文:
```bash ```bash
python3 差旅报销.py extract python3 差旅报销.py extract
@ -18,23 +18,23 @@
py 差旅报销.py extract py 差旅报销.py extract
``` ```
4. 读取 `报销输出/pdf_raw_text.txt`,按本文的 JSON Schema 分析出差人、日期、事由、费用分类、金额和证据。 4. 读取本次处理目录中的 `报销输出/pdf_raw_text.txt`,按本文的 JSON Schema 分析出差人、日期、事由、费用分类、金额和证据。
5. 如果同一笔滴滴/打车费用同时有行程单和电子发票,金额只按电子发票计入一次;行程单只作为附件和行程明细使用,不要与发票重复计入金额。 5. 如果同一笔滴滴/打车费用同时有行程单和电子发票,金额只按电子发票计入一次;行程单只作为附件和行程明细使用,不要与发票重复计入金额。
6. 如果出差人、出差事由、出发地、目的地、日期、金额等关键信息无法从原文可靠判断,必须先问用户;不要编造。 6. 如果出差人、出差事由、出发地、目的地、日期、金额等关键信息无法从原文可靠判断,必须先问用户;不要编造。
7. 将最终 JSON 保存为 `报销输出/analyzed_result.json`。 7. 将最终 JSON 保存为本次处理目录中的 `报销输出/analyzed_result.json`。
8. 确认 `questions` 为空、金额合计一致、附件张数一致后,自动运行: 8. 确认 `questions` 为空、金额合计一致、附件张数一致后,自动运行:
```bash ```bash
python3 差旅报销.py fill 报销输出/analyzed_result.json python3 差旅报销.py fill 20260529/报销输出/analyzed_result.json
``` ```
Windows 环境可改用: Windows 环境可改用:
```powershell ```powershell
py 差旅报销.py fill 报销输出/analyzed_result.json py 差旅报销.py fill 20260529/报销输出/analyzed_result.json
``` ```
9. 最后告诉用户生成的 Excel 文件路径,以及是否有任何需要人工复核的证据或假设;如果存在行程单和电子发票对应同一笔费用,必须明确提醒用户:行程单未重复计入金额,只作为附件和行程明细使用。 9. 最后告诉用户生成的 Excel 文件路径和本次归档目录,以及是否有任何需要人工复核的证据或假设;如果存在行程单和电子发票对应同一笔费用,必须明确提醒用户:行程单未重复计入金额,只作为附件和行程明细使用。
> 简单说:看到本 README 后,大模型应自动完成“提取 PDF 原文 → 分析生成 JSON → 填写 Excel”,只有在信息不确定时才暂停询问用户。 > 简单说:看到本 README 后,大模型应自动完成“提取 PDF 原文 → 分析生成 JSON → 填写 Excel”,只有在信息不确定时才暂停询问用户。
@ -99,7 +99,7 @@ py -m pip install pdfplumber openpyxl
```powershell ```powershell
py 差旅报销.py extract py 差旅报销.py extract
py 差旅报销.py fill 报销输出/analyzed_result.json py 差旅报销.py fill 20260529/报销输出/analyzed_result.json
``` ```
### Linux / macOS ### Linux / macOS
@ -112,39 +112,55 @@ python3 -m pip install pdfplumber openpyxl
```bash ```bash
python3 差旅报销.py extract python3 差旅报销.py extract
python3 差旅报销.py fill 报销输出/analyzed_result.json python3 差旅报销.py fill 20260529/报销输出/analyzed_result.json
``` ```
--- ---
## 标准目录结构 ## 标准目录结构
每次开始处理前,根目录只需要保留基础文件,并把本次报销附件直接放到根目录:
```text ```text
报销目录/ 报销目录/
├── 差旅费明细表.xlsx # 必需:模板 ├── 差旅费明细表.xlsx # 必需:模板
├── 差旅报销.py # 必需:脚本 ├── 差旅报销.py # 必需:脚本
├── README.md # 必需:说明 ├── README.md # 必需:说明
├── 住宿.pdf # 本次报销 PDF ├── 住宿.pdf # 本次报销 PDF,运行 extract 后会被移动
├── 机票*.pdf # 本次报销 PDF ├── 机票*.pdf # 本次报销 PDF,运行 extract 后会被移动
├── 滴滴出行行程报销单*.pdf # 本次报销 PDF ├── 滴滴出行行程报销单*.pdf # 本次报销 PDF,运行 extract 后会被移动
└── 滴滴电子发票*.pdf # 本次报销 PDF ├── 滴滴电子发票*.pdf # 本次报销 PDF,运行 extract 后会被移动
└── 打车截图.jpg # 本次报销图片附件,运行 extract 后会被移动
``` ```
脚本输出统一放到: 运行 `extract` 后会先形成处理当天目录,例如:
```text
报销输出/
```
运行后会形成:
```text ```text
报销目录/ 报销目录/
└── 报销输出/ └── 20260529/
├── pdf_raw_text.txt ├── 住宿.pdf
├── analyzed_result.json ├── 机票*.pdf
├── schema_example.json # 可选 ├── 滴滴出行行程报销单*.pdf
└── 差旅费明细表_xxxx_20260520_广州_售后维修.xlsx ├── 滴滴电子发票*.pdf
├── 打车截图.jpg
└── 报销输出/
└── pdf_raw_text.txt
```
运行 `fill` 成功后,会把当天目录重命名为本次归档目录,并保留 `报销输出/` 结构:
```text
报销目录/
└── 20260520-20260522_北京-广州_售后维修/
├── 住宿.pdf
├── 机票*.pdf
├── 滴滴出行行程报销单*.pdf
├── 滴滴电子发票*.pdf
├── 打车截图.jpg
└── 报销输出/
├── pdf_raw_text.txt
├── analyzed_result.json
└── 差旅费明细表_xxxx_20260520_广州_售后维修.xlsx
``` ```
--- ---
@ -163,23 +179,25 @@ Windows 可用:
py 差旅报销.py extract py 差旅报销.py extract
``` ```
输出: 运行时会把根目录的 PDF/JPG/JPEG/PNG 移动到处理当天目录,例如 `20260529/`。如果当天目录已存在且已有附件,脚本会询问是否合并;不合并会创建 `20260529-1/`、`20260529-2/` 这样的新目录。
输出位于本次处理目录中,例如:
```text ```text
报销输出/pdf_raw_text.txt 20260529/报销输出/pdf_raw_text.txt
``` ```
这个文件按 PDF 文件分块保存原始文本,例如: 这个文件按 PDF 文件分块保存原始文本,例如:
```text ```text
============================================================ ============================================================
文件: 住宿.pdf 文件: 20260529/住宿.pdf
============================================================ ============================================================
电子发票(增值税专用发票) 电子发票(增值税专用发票)
... ...
============================================================ ============================================================
文件: 滴滴出行行程报销单A.pdf 文件: 20260529/滴滴出行行程报销单A.pdf
============================================================ ============================================================
滴滴出行-行程单 滴滴出行-行程单
... ...
@ -191,10 +209,10 @@ py 差旅报销.py extract
### Step 2:让大模型分析 TXT 并输出 JSON ### Step 2:让大模型分析 TXT 并输出 JSON
把 `报销输出/pdf_raw_text.txt` 交给大模型,让大模型生成: 把本次处理目录中的 `报销输出/pdf_raw_text.txt` 交给大模型,让大模型生成同目录下的 JSON,例如:
```text ```text
报销输出/analyzed_result.json 20260529/报销输出/analyzed_result.json
``` ```
可以先查看 JSON 模板: 可以先查看 JSON 模板:
@ -221,17 +239,17 @@ python3 差旅报销.py schema --output
请根据本 README 自动处理当前目录的差旅报销。 请根据本 README 自动处理当前目录的差旅报销。
你的任务: 你的任务:
1. 如果 `报销输出/pdf_raw_text.txt` 不存在,先运行 `python3 差旅报销.py extract` 提取 PDF 原文。 1. 先运行 `python3 差旅报销.py extract`,脚本会把根目录 PDF/JPG/JPEG/PNG 移动到本次处理目录,并提取 PDF 原文。
2. 读取 `报销输出/pdf_raw_text.txt`,从 PDF 原文中识别出差人、出差事由、出发日期、结束日期、出发地、目的地、出行方式、出差天数。 2. 读取 extract 输出提示中的 `报销输出/pdf_raw_text.txt`,从 PDF 原文中识别出差人、出差事由、出发日期、结束日期、出发地、目的地、出行方式、出差天数。
3. 将费用分为:住宿、交通、饮食、其他。 3. 将费用分为:住宿、交通、饮食、其他。
4. 每个费用类别都要给出金额、单据张数、说明。 4. 每个费用类别都要给出金额、单据张数、说明。
5. 计算附件总张数、报销总额、预借差旅费、补领金额、退还金额。 5. 计算附件总张数、报销总额、预借差旅费、补领金额、退还金额。
6. 每个金额必须写入 evidence,说明来自哪个文件、依据是哪段文本。 6. 每个金额必须写入 evidence,说明来自哪个文件、依据是哪段文本。
7. 如果同一笔滴滴/打车费用同时有行程单和电子发票,金额只按电子发票计入一次;行程单只作为附件和行程明细使用,不要与发票重复计入金额。 7. 如果同一笔滴滴/打车费用同时有行程单和电子发票,金额只按电子发票计入一次;行程单只作为附件和行程明细使用,不要与发票重复计入金额。
8. 如果某个字段无法可靠判断,必须先问用户,不要编造;在未确认前不要填表。 8. 如果某个字段无法可靠判断,必须先问用户,不要编造;在未确认前不要填表。
9. 将最终 JSON 保存为 `报销输出/analyzed_result.json`,JSON 必须符合 README 中的 schema。 9. 将最终 JSON 保存到本次处理目录中的 `报销输出/analyzed_result.json`,JSON 必须符合 README 中的 schema。
10. 确认 `questions` 为空、金额合计一致、附件张数一致后,运行 `python3 差旅报销.py fill 报销输出/analyzed_result.json` 生成最终 Excel。 10. 确认 `questions` 为空、金额合计一致、附件张数一致后,运行 `python3 差旅报销.py fill 本次处理目录/报销输出/analyzed_result.json` 生成最终 Excel,并把本次目录重命名为 `出发日期-结束日期_出发地-目的地_事由简写` 格式。
11. 最后告诉用户生成的 Excel 文件路径,并列出需要人工复核的证据或假设;如果存在行程单和电子发票对应同一笔费用,必须明确提醒用户:行程单未重复计入金额,只作为附件和行程明细使用。 11. 最后告诉用户生成的 Excel 文件路径和本次归档目录,并列出需要人工复核的证据或假设;如果存在行程单和电子发票对应同一笔费用,必须明确提醒用户:行程单未重复计入金额,只作为附件和行程明细使用。
``` ```
--- ---
@ -322,13 +340,13 @@ python3 差旅报销.py schema --output
## Step 3:读取 JSON 并填表 ## Step 3:读取 JSON 并填表
```bash ```bash
python3 差旅报销.py fill 报销输出/analyzed_result.json python3 差旅报销.py fill 20260529/报销输出/analyzed_result.json
``` ```
Windows 可用: Windows 可用:
```powershell ```powershell
py 差旅报销.py fill 报销输出/analyzed_result.json py 差旅报销.py fill 20260529/报销输出/analyzed_result.json
``` ```
脚本会: 脚本会:
@ -338,7 +356,8 @@ py 差旅报销.py fill 报销输出/analyzed_result.json
3. 校验附件张数是否一致 3. 校验附件张数是否一致
4. 复制 `差旅费明细表.xlsx` 4. 复制 `差旅费明细表.xlsx`
5. 用 openpyxl 填入固定单元格 5. 用 openpyxl 填入固定单元格
6. 输出最终 XLSX 到 `报销输出/` 6. 输出最终 XLSX 到本次处理目录的 `报销输出/`
7. 将本次处理目录重命名为 `出发日期-结束日期_出发地-目的地_事由简写` 格式
输出文件命名规则: 输出文件命名规则:
@ -349,7 +368,7 @@ py 差旅报销.py fill 报销输出/analyzed_result.json
示例: 示例:
```text ```text
报销输出/差旅费明细表_xxxx_20260520_广州_售后维修.xlsx 20260520-20260522_北京-广州_售后维修/报销输出/差旅费明细表_xxxx_20260520_广州_售后维修.xlsx
``` ```
--- ---

View File

@ -3,8 +3,8 @@
差旅报销自动化脚本 差旅报销自动化脚本
Python 只做两类确定性工作: Python 只做两类确定性工作:
1. extract:提取 PDF 原文到 TXT 1. extract:整理输入附件,提取 PDF 原文到本次归档目录的 TXT
2. fill:读取大模型生成的 JSON,填入 Excel 模板 2. fill:读取大模型生成的 JSON,填入 Excel 模板,并完成本次归档目录命名
中间的发票理解、金额分类、日期/事由/人员判断全部由大模型完成。 中间的发票理解、金额分类、日期/事由/人员判断全部由大模型完成。
模板使用 .xlsx,完全依赖 Python 包实现跨平台,不依赖 LibreOffice。 模板使用 .xlsx,完全依赖 Python 包实现跨平台,不依赖 LibreOffice。
@ -14,14 +14,17 @@ import argparse
import json import json
import re import re
import shutil import shutil
from datetime import date
from pathlib import Path from pathlib import Path
import pdfplumber import pdfplumber
OUTPUT_DIR = Path("报销输出") OUTPUT_DIR_NAME = "报销输出"
RAW_TEXT_FILE = OUTPUT_DIR / "pdf_raw_text.txt" RAW_TEXT_FILENAME = "pdf_raw_text.txt"
ANALYZED_RESULT_FILENAME = "analyzed_result.json"
TEMPLATE_FILE = Path("差旅费明细表.xlsx") TEMPLATE_FILE = Path("差旅费明细表.xlsx")
ATTACHMENT_SUFFIXES = {".pdf", ".jpg", ".jpeg", ".png"}
SCHEMA_EXAMPLE = { SCHEMA_EXAMPLE = {
@ -83,24 +86,24 @@ SCHEMA_EXAMPLE = {
} }
def ensure_output_dir():
OUTPUT_DIR.mkdir(exist_ok=True)
def command_extract(_args): def command_extract(_args):
ensure_output_dir() archive_dir = prepare_archive_dir()
pdf_files = sorted(Path(".").glob("*.pdf")) output_dir = archive_dir / OUTPUT_DIR_NAME
if not pdf_files: output_dir.mkdir(exist_ok=True)
raise SystemExit("当前目录未找到 PDF 文件。") raw_text_file = output_dir / RAW_TEXT_FILENAME
with open(RAW_TEXT_FILE, "w", encoding="utf-8") as output: pdf_files = sorted(archive_dir.glob("*.pdf"))
if not pdf_files:
raise SystemExit(f"{archive_dir} 中未找到 PDF 文件。请把 PDF 放到根目录后重新运行 extract。")
with open(raw_text_file, "w", encoding="utf-8") as output:
output.write("=" * 60 + "\n") output.write("=" * 60 + "\n")
output.write("PDF 原始内容汇总\n") output.write("PDF 原始内容汇总\n")
output.write("=" * 60 + "\n\n") output.write("=" * 60 + "\n\n")
for pdf_path in pdf_files: for pdf_path in pdf_files:
output.write(f"\n{'=' * 60}\n") output.write(f"\n{'=' * 60}\n")
output.write(f"文件: {pdf_path.name}\n") output.write(f"文件: {pdf_path}\n")
output.write("=" * 60 + "\n") output.write("=" * 60 + "\n")
try: try:
@ -113,14 +116,93 @@ def command_extract(_args):
except Exception as exc: except Exception as exc:
output.write(f"\n[读取失败: {exc}]\n") output.write(f"\n[读取失败: {exc}]\n")
print(f"已提取 {len(pdf_files)} 个 PDF 文件到 {RAW_TEXT_FILE}") print(f"本次附件目录:{archive_dir}")
print(f"已提取 {len(pdf_files)} 个 PDF 文件到 {raw_text_file}")
print(f"请将分析结果保存为:{output_dir / ANALYZED_RESULT_FILENAME}")
def prepare_archive_dir():
root_attachments = find_root_attachments()
today_dir = Path(date.today().strftime("%Y%m%d"))
if root_attachments:
archive_dir = choose_archive_dir(today_dir)
archive_dir.mkdir(exist_ok=True)
for attachment in root_attachments:
target = unique_file_path(archive_dir / attachment.name)
shutil.move(str(attachment), target)
print(f"已移动 {len(root_attachments)} 个输入文件到 {archive_dir}")
return archive_dir
existing_today_dir = find_existing_today_dir(today_dir)
if existing_today_dir:
return existing_today_dir
raise SystemExit("当前根目录未找到 PDF/JPG/JPEG/PNG 文件。请把本次发票、行程单或截图放到根目录后再运行 extract。")
def find_root_attachments():
return sorted(
path for path in Path(".").iterdir()
if path.is_file() and path.suffix.lower() in ATTACHMENT_SUFFIXES
)
def choose_archive_dir(today_dir):
if not today_dir.exists():
return today_dir
if has_attachments(today_dir):
answer = input(f"{today_dir} 已存在且包含附件,是否合并本次根目录附件?[y/N] ").strip().lower()
if answer in {"y", "yes"}:
return today_dir
return next_numbered_dir(today_dir)
return today_dir
def find_existing_today_dir(today_dir):
candidates = [today_dir] + sorted(Path(".").glob(f"{today_dir.name}-*"))
candidates = [path for path in candidates if path.is_dir() and list(path.glob("*.pdf"))]
if not candidates:
return None
return candidates[-1]
def has_attachments(directory):
return any(
path.is_file() and path.suffix.lower() in ATTACHMENT_SUFFIXES
for path in directory.iterdir()
)
def next_numbered_dir(base_dir):
index = 1
while True:
candidate = Path(f"{base_dir.name}-{index}")
if not candidate.exists():
return candidate
index += 1
def unique_file_path(path):
if not path.exists():
return path
index = 1
while True:
candidate = path.with_name(f"{path.stem}-{index}{path.suffix}")
if not candidate.exists():
return candidate
index += 1
def command_schema(args): def command_schema(args):
ensure_output_dir() output_dir = Path(OUTPUT_DIR_NAME)
output_dir.mkdir(exist_ok=True)
text = json.dumps(SCHEMA_EXAMPLE, ensure_ascii=False, indent=2) text = json.dumps(SCHEMA_EXAMPLE, ensure_ascii=False, indent=2)
if args.output: if args.output:
schema_path = OUTPUT_DIR / "schema_example.json" schema_path = output_dir / "schema_example.json"
schema_path.write_text(text + "\n", encoding="utf-8") schema_path.write_text(text + "\n", encoding="utf-8")
print(f"已写入 {schema_path}") print(f"已写入 {schema_path}")
else: else:
@ -132,9 +214,17 @@ def command_fill(args):
validate_result(result) validate_result(result)
ensure_fill_dependencies() ensure_fill_dependencies()
output_file = fill_template(result) json_path = Path(args.json_path)
output_dir = json_path.parent
archive_dir = output_dir.parent if output_dir.name == OUTPUT_DIR_NAME else Path(".")
output_file = fill_template(result, output_dir)
verify_output(output_file, result) verify_output(output_file, result)
print(f"完成:{output_file}") final_archive_dir = finalize_archive_dir(archive_dir, result)
final_output_file = final_archive_dir / OUTPUT_DIR_NAME / output_file.name
print(f"完成:{final_output_file}")
print(f"本次归档目录:{final_archive_dir}")
def load_json(json_path): def load_json(json_path):
@ -213,13 +303,13 @@ def ensure_fill_dependencies():
raise SystemExit("缺少 openpyxl,请运行:python -m pip install openpyxl") raise SystemExit("缺少 openpyxl,请运行:python -m pip install openpyxl")
def fill_template(result): def fill_template(result, output_dir):
ensure_output_dir() output_dir.mkdir(exist_ok=True)
import openpyxl import openpyxl
meta = result["meta"] meta = result["meta"]
expenses = result["expenses"] expenses = result["expenses"]
output_file = OUTPUT_DIR / build_output_filename(meta) output_file = output_dir / build_output_filename(meta)
shutil.copy(TEMPLATE_FILE, output_file) shutil.copy(TEMPLATE_FILE, output_file)
wb = openpyxl.load_workbook(output_file) wb = openpyxl.load_workbook(output_file)
@ -244,6 +334,38 @@ def fill_template(result):
return output_file return output_file
def finalize_archive_dir(archive_dir, result):
if archive_dir == Path("."):
return archive_dir
target_dir = unique_archive_dir(archive_dir.parent / build_archive_dir_name(result["meta"]))
if archive_dir.resolve() == target_dir.resolve():
return archive_dir
archive_dir.rename(target_dir)
return target_dir
def unique_archive_dir(path):
if not path.exists():
return path
index = 1
while True:
candidate = path.with_name(f"{path.name}-{index}")
if not candidate.exists():
return candidate
index += 1
def build_archive_dir_name(meta):
start_date = normalize_date_for_filename(meta["出发日期"])
end_date = normalize_date_for_filename(meta["结束日期"])
route = sanitize_filename(f'{meta["出发地"]}-{meta["目的地"]}')
reason = sanitize_filename(meta["事由简写"])
return f"{start_date}-{end_date}_{route}_{reason}"
def build_output_filename(meta): def build_output_filename(meta):
date_str = normalize_date_for_filename(meta["出发日期"]) date_str = normalize_date_for_filename(meta["出发日期"])
safe_parts = [ safe_parts = [
@ -304,14 +426,14 @@ def build_parser():
parser = argparse.ArgumentParser(description="差旅报销自动化脚本") parser = argparse.ArgumentParser(description="差旅报销自动化脚本")
subparsers = parser.add_subparsers(dest="command", required=True) subparsers = parser.add_subparsers(dest="command", required=True)
extract_parser = subparsers.add_parser("extract", help="提取当前目录所有 PDF 原文到 报销输出/pdf_raw_text.txt") extract_parser = subparsers.add_parser("extract", help="整理根目录附件并提取 PDF 原文到本次归档目录")
extract_parser.set_defaults(func=command_extract) extract_parser.set_defaults(func=command_extract)
schema_parser = subparsers.add_parser("schema", help="输出大模型需要生成的 JSON schema 示例") schema_parser = subparsers.add_parser("schema", help="输出大模型需要生成的 JSON schema 示例")
schema_parser.add_argument("--output", action="store_true", help="写入 报销输出/schema_example.json,而不是打印到终端") schema_parser.add_argument("--output", action="store_true", help="写入 报销输出/schema_example.json,而不是打印到终端")
schema_parser.set_defaults(func=command_schema) schema_parser.set_defaults(func=command_schema)
fill_parser = subparsers.add_parser("fill", help="读取 JSON 并填入差旅费明细表模板") fill_parser = subparsers.add_parser("fill", help="读取 JSON 并填入差旅费明细表模板,再归档本次目录")
fill_parser.add_argument("json_path", help="大模型生成的 analyzed_result.json 路径") fill_parser.add_argument("json_path", help="大模型生成的 analyzed_result.json 路径")
fill_parser.set_defaults(func=command_fill) fill_parser.set_defaults(func=command_fill)