关于 transaction-categorizer
Transaction Categorizer 根据原始描述和带正负号的金额分类财务交易,适用于家庭财务流程。它先应用匹配规则,再由 LLM 处理剩余交易;保留原始描述,并可根据高置信度的重复模式提出新规则。
主要功能
- 01规范化描述以供匹配
- 02按优先级应用商户规则
- 03依据给定分类体系归类
- 04标记可能的定期交易
- 05评估置信度并标记不确定项
- 06根据重复匹配提出规则
适用场景
- 01批量分类账户交易
- 02识别可能的定期支出
- 03检查低置信度分类
- 04根据重复商户模式扩展规则
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lyndonkl/ claude --skill transaction-categorizer安装后在 Claude Code 中输入/transaction-categorizer确认已加载。
详细介绍
交易分类器
目录
概览
一笔交易只有一个 description_raw 字符串和一个带符号的 amount_cents。此技能会将其转换为规范的 merchant、category + subcategory、一个 is_recurring 布尔候选值,以及一个置信度。它会先应用规则(成本低且确定),仅在处理剩余交易时才回退到 LLM 推断。
它还会生成学习到的规则——当高置信度分类符合清晰的商户模式时,会为规则表提出一条新规则,以便今后相同的交易可以免费匹配。
输入约定
调用方提供:
transactions—{id, description_raw, amount_cents, account_id, date, account_type}数组。taxonomy—categories.json中的分类体系区块(顶层类别 → 子类别列表)。rules— 现有规则数组(参见规则格式)。account_type_hints(可选)— 如果已知,可帮助消除歧义(例如,经纪账户中的存款更可能是dividends,而不是salary)。
工作流
Categorization Progress:
- [ ] Step 1: Normalize description_raw
- [ ] Step 2: Apply rules in priority order
- [ ] Step 3: Classify residual via LLM with taxonomy guard
- [ ] Step 4: Detect recurring candidates
- [ ] Step 5: Score confidence
- [ ] Step 6: Propose new rules from high-confidence matches
步骤 1 — 规范化
构建一个仅用于匹配的 description_normalized — 绝不覆盖 description_raw。
- 转为大写。
- 去除开头的供应商代码(
SQ *、TST*、PAYPAL *、CKCD、POS DEBIT、ACH DEBIT)。 - 去除结尾的地理信息(
PORTLAND OR、800-555-1234 CA、#1234)。 - 将多个空格合并为一个。
- 删除描述中的日期数字。
SQ *TRADER JOES #123 PORTLAND OR → TRADER JOES。
步骤 2 — 应用规则
对每笔交易,按优先级顺序遍历 rules。第一个 match 子串(不区分大小写)出现在 description_normalized 中的规则胜出。应用其 merchant、category、subcategory,以及(如果已设置)is_recurring。
如果有多条规则匹配,则最具体的规则(match 最长)胜出。
如果规则匹配,则设置 source: "rule" 和 confidence: 1.0。
步骤 3 — 分类剩余交易
对未匹配的交易,通过 LLM 进行分类:
- 将输出限制在所提供的
taxonomy范围内 — 绝不编造类别。 - 选择
category.subcategory(例如,food.groceries)。 - 提出一个规范的
merchant名称。 - 如果符号和 account_type 表明这是收入,则优先选择
income.*分支。 - 如果 account_type 为
brokerage或401k且金额为正,则优先选择income.dividends、income.interest_earned或savings_investment.*。 - 如果
description_raw看起来像用户两个账户之间的内部转账,则分类为financial.transfers_internal。
根据线索强度设置 source: "llm" 和 confidence: 0.6–0.9。
步骤 4 — 检测定期交易候选项
符合以下条件时,将 is_recurring 候选值设为 true:
- 过去 90 天内,同一账户中该商户出现 ≥ 3 次,金额相差在 ±10% 以内,且具有固定周期(每周、每两周、每月、每季度)。
- 或者,匹配的规则明确将
is_recurring设为true。
这只是一个候选项 — 将其提升至 recurring.json 是定期扣费检测技能的工作。
步骤 5 — 置信度
| 来源 | 默认置信度 |
|---|---|
| 规则匹配(子串长度 ≥ 8) | 1.00 |
| 规则匹配(子串长度 4–7) | 0.92 |
| LLM 具有强分类信号(例如,“NETFLIX” → entertainment.streaming) | 0.85 |
| LLM 信号较弱 | 0.65 |
无法分类到 uncategorized 以上 | 0.30 |
如果置信度 < 0.5,则将 category: "uncategorized.unknown" 标记为待审核。
步骤 6 — 提出新规则
分类后,扫描高置信度的 LLM 匹配项(confidence ≥ 0.85),其中相同的 description_normalized 子串覆盖输入集合中的 ≥ 3 笔交易。对每个匹配项提出一条新规则,并将其追加到输出中的 rules.proposed[]。记账 Agent 会在这些规则合并到 categories.json 之前进行确认。
分类体系
该技能遵循调用方提供的分类体系。家庭财务团队使用的默认分类体系如下:
housing → mortgage, rent, property_tax, hoa, home_insurance, home_maintenance,
utilities_electric, utilities_gas, utilities_water, utilities_internet
food → groceries, restaurants, coffee, alcohol
transportation → gas, auto_insurance, auto_maintenance, public_transit, rideshare,
parking, tolls
health → medical_copay, prescriptions, dental, vision, mental_health, gym
personal → clothing, haircare, subscriptions_personal
kids → childcare, school, activities, kids_clothing
entertainment → streaming, events, hobbies, books
travel → flights, lodging, travel_food, travel_other
financial → fees, interest_paid, transfers_internal
income → salary, bonus, interest_earned, dividends, capital_gains, refund, other_income
savings_investment → 401k_contribution, ira_contribution, hsa_contribution,
brokerage_deposit, savings_deposit
uncategorized → unknown
切勿臆造类别。如果一笔交易不符合任何类别,请使用 uncategorized.unknown,并发出 taxonomy_gap 警告。
规则格式
{
"match": "TRADER JOE",
"merchant": "Trader Joe's",
"category": "food",
"subcategory": "groceries",
"is_recurring": false,
"priority": 100,
"added_on": "2026-01-20",
"source": "user_confirmed | learned"
}
priority 值越大,优先级越高。人工添加的规则默认优先级为 200;由该技能学习到的规则默认优先级为 100。
置信度与审计
每笔输出交易都包含:
category和subcategory— 必须属于分类体系。merchant— 规范的显示名称。confidence—[0.0, 1.0]。source—rule | llm | uncategorized。matched_rule_id(如果source: rule)。
切勿覆盖 description_raw;始终保留该字段,以便重新分类。
输出约定
{
"categorized": [
{
"id": "tx_20260115_001",
"merchant": "Trader Joe's",
"category": "food",
"subcategory": "groceries",
"is_recurring_candidate": false,
"confidence": 1.0,
"source": "rule",
"matched_rule_id": "rule_trader_joes"
}
],
"rules_proposed": [
{
"match": "BLUE BOTTLE",
"merchant": "Blue Bottle Coffee",
"category": "food",
"subcategory": "coffee",
"evidence_count": 4,
"evidence_tx_ids": ["tx_20260103_004", "tx_20260110_002", "tx_20260117_007", "tx_20260124_001"]
}
],
"warnings": [
{ "tx_id": "tx_20260118_009", "type": "taxonomy_gap", "description_raw": "ZELLE TO M COPPENS" }
],
"summary": {
"total": 142,
"rule_matched": 118,
"llm_classified": 22,
"uncategorized": 2,
"uncategorized_pct": 1.4
}
}
防护措施
- 逐字节保留
description_raw。 规范化仅用于匹配。 - 切勿臆造类别。 只能使用提供的分类体系中的类别。
- 考虑账户类型。 券商账户中的“存款”不是工资;储蓄账户中的“取款”很可能是转账,而非消费。
- 内部转账在各账户间必须相互抵消。 如果一侧被归类为
financial.transfers_internal,另一账户中金额符号相反的对应交易也应归类为transfers_internal;如不一致,请标记。 - 未分类比例超过批次中新交易的 5% 时,属于质量信号;请在摘要中指出。
- 拟议规则中不得包含个人身份信息(PII)。 诸如
match: "ZELLE TO JOHN SMITH"的规则会暴露姓名;请对其脱敏或跳过此类提议。