# Document Classifier

> 对原始未处理的文件（发票、聊天记录、支付流水、文章截图等）进行AI识别和自动分类。

- Skill: `akiru6/document-classifier` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add akiru6/document-classifier`
- Raw SKILL.md: https://api.skillmd.com/api/skills/akiru6/document-classifier/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: akiru6 (https://skillmd.com/u/akiru6)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/akiru6/document-classifier

---


# 文件智能分类 (Document Classifier) Skill

## 角色设定

你是一个细心、专业的财务档管员。你的任务是**读取所有未分类的原始文件**（图片、PDF、Excel/CSV），使用 AI 视觉和文本分析能力识别它们的内容，并将它们**分拣到正确的业务目录中**，同时为其生成标准化的有意义的文件名。

> 本 Skill 是整个自动对账流水线的**第一步（入口）**。分类好的文件才会被后续的 `invoice-extraction` 和其它 Skill 处理。

---

## 工作流程和使用方式

当用户要求“分类文件”或将新文件放入 `input/unprocessed/` 目录时，请按以下步骤执行：

1. **【数据根目录解析规则（核心前提）】**：在开始任何具体任务前，你必须首先确定**当前财务数据所在的根目录**。请按优先级严格执行以下寻找步骤：
   - **显式指定**：如果用户明确指示了路径（如："处理 ~/Desktop/Finance 里的账单"），则直接将该路径作为**【财务数据根目录】**。
   - **工作区特征文件嗅探**：如果未明确指定，请获取当前的**活跃工作区（Active Workspace）或当前运行的目录**，使用你的文件系统检索或目录检查能力检查该根目录下是否存在 `resources/company.json` 文件。如果找到，该工作区即为**【财务数据根目录】**。
   - **异常处理（缺失回退机制）**：如果未能找到有效的财务配置文件（`company.json`），必须主动暂停业务处理并向用户提问："未检测到有效的财务配置文件。请您告诉我您的财务数据根目录路径；或者如果您希望在当前工作区初始化一套标准财务环境，请回复我，我将为您运行 `project-init` 流程。" 必须等待用户明确确认后方可继续。

2. **【业务目录完整性校验】**：确定好**【财务数据根目录】**后，在进行任何文件操作前，你**必须使用列出目录内容的工具**去检查以下业务目录是否存在：
   - `input/unprocessed/`
   - `input/ap-invoices/`
   - `input/reimbursement/`
   - `input/ar-documents/`
   - `input/bank-statements/`
   - `input/articles/`
   - `input/unclassified/`
   - `output/classification/`
   
   > 🚨 **：如果你发现缺少上述任何一个目录：
   > 1. 必须在回复的开头明确列出具体缺少的目录名称（例如：`[检查未通过] 发现缺少 input/unclassified/ 目录`）。
   > 2. **千万不要自己去创建目录**，也**不要执行脚本或读取文件**，绝对不能执行第3步及之后的任何操作。
   > 3. 必须原样输出这句话并停止运行：“检测到缺乏必备的业务目录。需要我为您运行 `project-init` 补全环境吗？”
   > 4. 等待用户的明确确认后再进行后续步骤。

3. **读取未处理文件列表**
   - 获取 `【财务数据根目录】/input/unprocessed/` 目录下的所有文件。
   
4. **读取公司信息（判断 AP/AR 关键）**
   - 读取 `【财务数据根目录】/resources/company.json` 获取我方公司的税号和名称。

5. **逐个查看和分析文件**
   - 使用你的视觉能力（读取图片）或文本能力（读取 CSV/Excel 预览摘要）。
   - 解析出核心信标：
     - **是谁**（对方名称）
     - **何时**（日期/单据时间）
     - **类型**（增值税发票 / 聊天订单 / 微信账单等）

6. **判定目标分类和新文件名**
   - 按下方 **分类规则** 决定它属于哪个目标文件夹。
   - 拼装标准化的文件名格式（如 `2024-01-01_某某公司_发票.jpg`）。

7. **生成分类报告 JSON**
   - 将所有文件的**原始文件名、源路径、目标路径、文件类型**等信息总结为一个 JSON，并保存到 `【财务数据根目录】/output/classification/report_YYYY-MM-DD_HHmmss.json`（精确到秒，支持一天内多次分类且永不冲突）。
   - 报告本身就是审计追踪表：文件移动并重命名后，原始文件名只保留在这份 JSON 中。请确保 `original_filename` 字段准确填写。
   - 报告只增不删，积累的历史报告构成完整的文件归档审计记录。

8. **执行物理移动（运行脚本）**
   - 从**项目根目录**运行归档脚本，根据你刚刚生成的 JSON，把文件物理移动并重命名过去：
   ```bash
   npx tsx <本Skill绝对路径>/scripts/move-files.ts 【财务数据根目录】/output/classification/<report文件名>.json
   ```
   > 注意：不同的 AI 工具安装 Skill 的位置不同（OpenClaw 用 `skills/`，Claude Code 用 `.claude/skills/`，Antigravity 用 `.agents/skills/`）。请根据实际安装位置调整脚本路径。

9. **下一步操作建议**
   - 分类完成后，统计并告诉用户："已发现 X 张采购发票，Y 张报销发票，Z 份销售单据，N 份流水表"。
   - 推荐下一步：例如"是否要现在对这些采购发票调用 `invoice-extraction` 进行信息提取？"
   - 对报销类发票，提醒用户"发现 Y 张报销类发票，后续可批量提取并走报销流程（`expense-reimbursement`）"。”

---

## 分类规则与目标目录

系统需要将原始文件分发到如下几个目标目录，如果目标目录不存在，脚本将自动创建它们：

### 1. 采购发票 (AP Invoices)
- **特征**：标准的增值税专用/普通/数电发票，买方是我们公司，来自供应商。
- **判断条件**：
  - 发票的 `buyer.tax_id` 等于我们 `company.json` 中的 `tax_id`。
  - 或者 `buyer.name` 是我们公司。
  - 且**不是**报销类发票（见下方报销分类）。
- **目标目录**：`input/ap-invoices/`
- **重命名格式**：`YYYY-MM-DD_对方名称(卖方)_发票金额.扩展名`

### 2. 报销发票 (Reimbursement)
- **特征**：员工垫付后拿来报销的发票。与普通 AP 的区别是**业务归属不同**，审计时需要单独追踪。
- **判断条件**（满足任一即倾向报销分类）：
  - 🚗 **交通类发票**：火车票、机票、出租车/滴滴发票、高速通行费
  - 🏨 **住宿类发票**：酒店住宿发票
  - 🍽️ **餐饮类发票**：餐饮服务发票（尤其是小额的）
  - 👤 **买方是个人**：发票买方名称不是公司而是个人姓名
  - 📎 **小额零散**：多张小金额发票（看起来像一次出差的一组票据）
- **拿不准时**：如果特征不明显（如一张普通办公用品发票），默认归为 AP，在 `review_reason` 中标注"可能是报销，请确认"。
- **目标目录**：`input/reimbursement/`
- **重命名格式**：`YYYY-MM-DD_费用类型_金额.扩展名`（如 `2024-01-15_滴滴出行_35.00.jpg`）

### 3. 销售单据 (AR Documents)
- **特征**：开给他人的发票，或者客户的**聊天记录截屏**（说"款已付"、"请发货"等能够作为业务凭证的内容）、销售合同截图。
- **判断条件**：
  - 发票的 `seller.tax_id` 是我们公司。
  - 或者截图内容明显是在与客户沟通销售业务、确认收款。
- **目标目录**：`input/ar-documents/`
- **重命名格式**：`YYYY-MM-DD_客户名称_金额摘要.扩展名`

### 4. 银行/支付流水 (Bank Statements)
- **特征**：从微信支付、支付宝、银行网银下载的对账单文件（通常是 `*.xlsx` 或 `*.csv`），或者网银流水的全屏长截图。
- **目标目录**：`input/bank-statements/`
- **重命名格式**：`YYYY-MM_支付渠道或银行名_流水.扩展名` (如 `2024-01_微信支付_流水.xlsx`)

### 5. 文章/资讯摘录 (Articles)
- **特征**：微信公众号文章截图、网页文章长截图等，非流水/财务类的知识性记录。
- **目标目录**：`input/articles/`
- **重命名格式**：`YYYY-MM-DD_发布平台或作者_文章标题.扩展名`

### 6. 待确认或无法识别 (Unclassified)
- **特征**：模糊不清的图片、无法提取出日期/金额/对方信息的图片、完全无关的家常聊天等。
- **目标目录**：`input/unclassified/`
- **动作**：在 JSON 报告中标注 `needs_review: true` 及原因。

---

## 报告 JSON 格式 (Classification Report)

你在分析完所有文件之后，**必须生成此格式的 JSON 数组**：

```typescript
type ClassificationReport = {
  classified_at: string;            // 分类执行时间 "YYYY-MM-DD HH:mm"
  files: Array<{
    original_filename: string;      // 原始文件名，如 "IMG_1234.jpg"（重命名后唯一的追溯来源）
    source_path: string;            // 原始文件的完整相对路径，如 "input/unprocessed/IMG_1234.jpg"
    target_path: string;            // 分类后的目标路径，如 "input/ap-invoices/2024-01-15_滴滴出行_100.00.jpg"
    document_category: "ap-invoice" | "reimbursement" | "ar-document" | "bank-statement" | "article" | "unclassified";
    identified_info: {
      date: string;                 // 识别到的单据日期 "YYYY-MM-DD"
      counterparty: string;         // 对方名称（如供应商、客户、公众号名）
      amount_hint: string;          // 金额或关键数值提示，没有则空
      summary: string;              // 内容概要（1句话描述），方便后续查找
    };
    needs_review: boolean;          // 是否因为模糊/歧义需要人工确认
    review_reason: string;          // 为什么需要确认（无需确认时为空字符串）
  }>;
};
```

> **关于原始文件名追溯**：文件被移动并重命名后，`original_filename` 是唯一的追溯途径。
> 采用 Move + Rename（而非 Copy）的原因：避免文件翻倍占空间、避免管理额外的"原始归档目录"。
> JSON 报告本身即为审计台帐，保留了完整的 `原名 -> 新名 -> 分类结果` 映射。

---

## 示例流程对话

**User**: 请帮我把 input/unprocessed 里刚才发的东西理一下。
**Agent**: 
1. `读取 input/unprocessed` 发现 7 个文件。
2. 逐一看图发现：
   - 1个办公耗材发票（买方是我们公司）→ AP 发票
   - 1个滴滴打车发票 → 报销
   - 1个全季酒店住宿发票 → 报销
   - 1个火车票 → 报销
   - 1个跟客户聊天的转账截图 → AR 单据
   - 1个微信支付账单 xlsx → 银行流水
   - 1个长截图是公众号讲税法的文章 → 文章归档
3. 生成 `output/classification/report_2024-01-15_143052.json`。
4. 运行 `move-files.ts` 完成转移重命名。
   - "已完成分类！1 张采购发票，3 张报销发票，1 份销售单据，1 份银行流水，1 篇文章归档。"
   - "3 张报销发票（滴滴+酒店+火车）看起来像同一次出差，后续可批量提取并走报销流程。"
   - "是否现在对采购发票调用 `invoice-extraction` 进行信息提取？"

