jarviszoo/recurring-payment-detector
GitHub: jarviszoo/recurring-payment-detector
这是一个AI驱动的定期付款检测器,用于识别银行交易中的订阅收费异常并提供取消指导。
Stars: 0 | Forks: 0
# 定期付款检测器
定期付款检测器可导入银行导出文件、JSON 记录、粘贴的邮件收据以及 `.eml` 文件,将嘈杂的商户名称解析为规范的服务名称,检测异常的定期收费,并为订阅显示取消指导。
该检测器不依赖于固定的订阅价格表。它从用户的交易历史中学习,对诸如 `NETFLIX.COM`、`NFLX DIGITAL` 和 `NETFLX` 等变体进行分组,然后标记出该商户和类别中不寻常的金额变化。
## 功能亮点
- 支持 CSV、JSON、手动输入行、粘贴邮件及 `.eml` 文件导入。
- 具备收据感知的邮件解析能力,可提取商户、金额、收费日期和操作链接。
- 实体解析支持精确别名、模糊匹配和 TF-IDF 嵌入匹配。
- 结合类别感知阈值的定期收费检测。
- 基于机器学习金额预测,在历史记录不足时采用中位数回退。
- Streamlit 用户界面,支持数据导入、检测审查、反馈保存及报告导出。
- 来自 Excel 数据库的取消指导。
- 通过 API 支持的网络搜索查询未知取消流程,并以相同数据库格式保存回工作簿。
## 快速开始
```
pip install -r requirements.txt
python tests.py
python tests_ingest.py
streamlit run app.py
```
打开终端中显示的 Streamlit URL,通常是:
```
http://localhost:8501
```
## 配置
运行时状态存储在本地并被 Git 忽略:
- `services.json`: 学习到的规范商户注册表
- `feedback.json`: 保存的用户反馈
可选环境变量:
```
# 使用特定的 cancellation workbook 而非默认的 search paths。
SUBSCRIPTION_CANCELLATION_XLSX=/path/to/subscription_cancellation_process.xlsx
# 启用 API-backed web search 以查询未知的 cancellation policies。
OPENAI_API_KEY=your_api_key
# 可选;默认为 gpt-4.1-mini。
OPENAI_WEBSEARCH_MODEL=gpt-4.1-mini
```
在 Windows PowerShell 中:
```
$env:OPENAI_API_KEY="your_api_key"
$env:SUBSCRIPTION_CANCELLATION_XLSX="C:\Users\user\Downloads\subscription_cancellation_process.xlsx"
```
## Streamlit 工作流
应用支持以下导入路径:
| 选项卡 | 输入内容 |
| --- | --- |
| CSV 上传 | 包含 `merchant_raw`、`amount` 和 `date` 的银行导出文件 |
| JSON 上传 | 交易数组或 `{"transactions": [...]}` 格式 |
| 邮件 | 粘贴的收据文本或上传的 `.eml` 文件 |
| 手动输入 | 可编辑的交易表格 |
| 示例数据 | 内置的示例交易历史记录 |
数据加载完成后,点击侧边栏的**运行检测**。应用将显示:
- 已加载的交易预览
- 识别订阅的取消指导
- 包含严重性、预期金额、实际金额和原因的警报表
- 商户解析详情
- 每个警报的反馈控制
- JSON 和 CSV 导出按钮
## 邮件与 `.eml` 解析
邮件解析器处理纯文本和 HTML 收据。它会对收据字段进行排序,以避免常见错误,例如选择小计、税费、退款或促销金额而非实际收费总额。
对于 Apple 订阅确认及类似邮件,它能从邮件正文结构中识别真正的订阅,例如:
- `App -> iCloud`
- `Plan -> iCloud+ with 200 GB storage`
- `Renewal Price -> $3.99/month`
- `Date of Upgrade -> Sep 9, 2025`
解析器还会从 `.eml` HTML 中提取有用的操作链接,例如账户、购买历史、账单、管理和订阅链接。
## 取消指导
取消指导按以下顺序加载:
1. Excel 工作簿数据库
2. 常见服务的内置回退指南
3. 结构化网络搜索回退
默认情况下,应用会查找:
```
./subscription_cancellation_process.xlsx
~/Downloads/subscription_cancellation_process.xlsx
```
您可以通过 `SUBSCRIPTION_CANCELLATION_XLSX` 覆盖此设置。
该工作簿预计使用现有的数据库格式列:
| 列名 | 用途 |
| --- | --- |
| Provider | 服务或公司名称 |
| Market Position | 市场覆盖范围或背景说明 |
| Price Range | 典型套餐定价 |
| Billing Cycle | 月度、年度、季度等 |
| Website | 供应商网站 |
| Cancellation Process | 详细的取消流程 |
| additional resources | 官方 URL、支持链接或来源说明 |
## API 网络搜索查询未知供应商
对于未知供应商,应用会显示**使用 API 研究并更新数据库**。点击后,它会:
1. 使用 `OPENAI_API_KEY` 和 OpenAI Responses API 的网络搜索工具。
2. 搜索当前的官方取消说明。
3. 将结果格式化为相同的工作簿模式。
4. 在 `LLM Web Search` 工作表中保存或更新一行。
5. 从工作簿重新加载指南。
生成的取消流程故意采用工作簿风格,例如:
```
Type 1 - Direct subscription
Direct link: https://example.com/account
Workflow:
1. Sign in.
2. Open Billing or Subscriptions.
3. Select Cancel or turn off auto-renewal.
4. Confirm and keep the confirmation email.
Watch-out:
If billed through Apple, Google Play, Amazon, PayPal, a mobile carrier, or
another partner, cancel through that billing provider.
```
应用不会在每次页面刷新时静默运行 API 网络研究。用户必须点击研究按钮,以明确 API 使用。
## 编程用法
```
from ingest import parse_csv, analyze
with open("charges.csv", encoding="utf-8") as f:
parsed = parse_csv(f.read())
report = analyze(parsed.transactions, use_ml=True)
for alert in report.alerts:
print(alert.merchant, alert.severity, alert.actual_amount)
```
解析 `.eml` 文件:
```
from pathlib import Path
from ingest.email_parser import parse_eml
extraction, parsed = parse_eml(Path("receipt.eml").read_bytes())
print(extraction.merchant_raw, extraction.amount, extraction.date)
print(parsed.transactions)
```
研究并保存取消流程:
```
from cancellation import research_and_update_cancellation_guide
guide = research_and_update_cancellation_guide("Example Vendor")
print(guide.service_name)
print(guide.cancellation_process)
```
## 流程
```
raw transaction
-> entity_resolver
-> merchant registry and category
-> recurring_detector
-> category_rules
-> ml_predictor or median fallback
-> outlier_detector
-> feedback_adjuster
-> alert report
```
## 文件映射
| 文件 | 用途 |
| --- | --- |
| `app.py` | 用于导入、检测、反馈、取消指导和导出的 Streamlit UI |
| `cancellation.py` | 基于 Excel 的取消数据库查找及 API 网络搜索更新流程 |
| `ingest/email_parser.py` | 收据和 `.eml` 解析 |
| `ingest/parsers.py` | 将 CSV、JSON 和记录解析为 `Transaction` 对象 |
| `ingest/runner.py` | 结构化分析报告构建器 |
| `ingest/serializers.py` | JSON 和 CSV 导出助手 |
| `models.py` | 核心数据类 |
| `entity_resolver.py` | 商户身份解析协调器 |
| `merchant_normalizer.py` | 商户清理和种子服务别名 |
| `service_registry.py` | 基于 JSON 的规范商户注册表 |
| `pipeline.py` | 端到端检测流程 |
| `recurring_detector.py` | 计费周期和金额层级检测 |
| `ml_predictor.py` | 预期金额预测 |
| `outlier_detector.py` | 警报评分和严重性 |
| `feedback_store.py` | 反馈持久化 |
| `feedback_adjuster.py` | 基于反馈的警报重新评分 |
| `sample_data.py` | 示例交易数据 |
| `templates/sample_transactions.csv` | 上传模板 |
| `tests.py` | 实体解析冒烟测试 |
| `tests_ingest.py` | 导入、`.eml`、取消和分析测试 |
## 测试
```
python tests.py
python tests_ingest.py
```
当前覆盖范围包括:
- 商户文本清理
- 精确别名、模糊和嵌入解析
- 别名自动学习
- 跨变体分组
- CSV 和 JSON 导入
- 收据和 `.eml` 解析
- Apple/iCloud 订阅解析
- 取消数据库查找
- API 研究行的保存/加载行为
- 分析冒烟测试
## 安全与隐私
- 不要提交 `services.json`、`feedback.json`、`.env` 或 API 密钥。
- 应用仅在用户点击研究按钮时调用 OpenAI API。
- 未知供应商的 API 研究结果在执行取消指导(特别是退款、截止日期和计费合作伙伴相关)前应进行审查。
- 取消工作簿可以包含来源 URL 和支持链接;在输入凭据前请验证官方域名。
## 限制
- 机器学习训练使用合成示例;使用标记的生产数据重新训练可获得更精确的预测。
- 首年用户在历史记录不足时可能会看到季节性误报。
- API 网络搜索输出会保存到工作簿,但仍应审查供应商特定术语和当前退款政策。
标签:Apex, Excel数据库, Homebrew安装, JSON数据处理, Kubernetes, ML预测模型, OpenAI集成, Petitpotam, Python编程, Streamlit应用, TF-IDF匹配, 个人财务管理, 代码示例, 取消指导信息, 商家名称解析, 数据分析, 数据导入导出, 机器学习, 欺诈检测, 正则表达式解析, 流式用户界面, 用户反馈循环, 置信区间计算, 订阅收费检测, 订阅管理, 费用异常检测, 费用追踪器, 逆向工具, 金融科技, 银行记录分析