一份说明写着“已付款”“已发码”“账号可用”,这三句话能直接合并成“订阅已经生效”吗?不能。它们描述的是不同阶段。让豆包或ChatGPT帮助整理文字时,也应保留这层区别:提取原文已有的信息,再用确定性的规则逐项核对。本文用离线构造样例演示,不对模型做排名测试。
本文含AI辅助起草,代码与构造样例已在本地测试复核。
先拆成三类字段。payment表示付款记录,delivery表示交付记录,account_check表示对目标账号的核对记录。某项原文没有提供,就保持缺失,不让模型自行补成“成功”。例如,已付款并收到卡密,但没有账号核对记录,合理结果仍是“待核对账号”,而非“已生效”。
下面全部使用SYNTHETIC合成数据:账号和方案都是sample-开头的别名,日期也是固定示例。它们不是实际客户、订单或平台截图。函数不读取浏览器、不调用API,不连接支付或订阅系统,只检查一份字典内部的记录是否一致。
from datetime import datetime
def verify_record(row):
if not isinstance(row, dict) or row.get("sample_kind") != "synthetic":
raise ValueError("Only synthetic dictionary examples are accepted")
payment, delivery = row.get("payment"), row.get("delivery")
if not isinstance(payment, str) or payment not in {"pending", "paid", "failed"}:
raise ValueError("Unknown payment state")
if not isinstance(delivery, str) or delivery not in {"waiting", "code_issued", "manual_processing", "completed"}:
raise ValueError("Unknown delivery state")
for field in ("expected_account", "expected_plan"):
if not isinstance(row.get(field), str) or not row[field].startswith("sample-"):
raise ValueError("Use sample-prefixed aliases, not real account data")
issues = []
delivered = delivery in {"code_issued", "completed"}
if payment != "paid" and delivered:
issues.append("payment_delivery_conflict")
check = row.get("account_check")
if check is not None:
if not isinstance(check, dict):
raise ValueError("account_check must be a dictionary or null")
for field, wanted, issue in (
("kind", "manual_official_page", "source_unverified"),
("account", row["expected_account"], "account_mismatch"),
("plan", row["expected_plan"], "plan_mismatch"),
("status", "active", "activation_not_recorded"),
):
if check.get(field) != wanted:
issues.append(issue)
try:
if datetime.fromisoformat(check.get("checked_at")).utcoffset() is None:
issues.append("invalid_check_time")
except (TypeError, ValueError):
issues.append("invalid_check_time")
if payment != "paid":
result = "payment_unconfirmed"
elif not delivered:
result = "delivery_pending"
elif check is None:
result = "account_check_missing"
else:
result = "needs_manual_review" if issues else "consistent_record"
return {"sample_kind": "synthetic", "scope": "record_consistency_only",
"result": result, "issues": issues}
可以先用json.loads解析下面的JSON,再把字典传给verify_record。即使payment为paid、delivery为code_issued,account_check仍为null,因此输出应为account_check_missing。
{
"sample_kind": "synthetic",
"payment": "paid",
"delivery": "code_issued",
"expected_account": "sample-user-a",
"expected_plan": "sample-plan-a",
"account_check": null
}
如果随后添加账号核对记录,需要包含kind、account、plan、status和带时区的checked_at。kind写为manual_official_page只表示输入者声明记录来自人工查看官方页面,并不是数字签名,也不会让这份JSON自动变真。函数没有验证网页真实性、图片内容或实际平台状态;即使得到consistent_record,也只表示这些合成字段彼此一致。
为什么需要同时比较账号和方案?因为“某个账号已生效”不能证明“预期账号的预期方案已生效”。样例把目标设为sample-user-a、sample-plan-a;若核对记录换成sample-user-b或sample-plan-b,就应留下不一致标记,而不是用一条“完成”覆盖细节。
校验顺序也有用。付款尚未确认时,结果先保留payment_unconfirmed;人工处理中则保留delivery_pending。收到卡密以后仍需要账号核对,不把交付事件当成订阅事件。这种做法适合检查AI提取结果是否发生了阶段跳跃,不负责判断付款凭证真假或执行任何售后动作。
测试不要只放一个顺利样例。配套unittest覆盖12类情形:一致记录、付款未确认、付款与交付冲突、等待交付、人工处理中、领码未核对、账号不一致、方案不一致、AI摘要来源、未记录激活、时间格式与时区异常,以及输入结构或合成标记错误。测试通过只证明这些预设分支按约定运行,不证明真实服务成功。
让AI整理时,可以先给出边界:“只提取提供材料中存在的字段,缺失保留null;不要根据付款推断交付,不要根据交付推断账号已生效。”随后再把输出交给确定性的检查函数。先保留缺项,再人工追问原始证据,通常比让模型直接下一个完整结论更便于复核。
本文由AIXiamo维护者整理。补充阅读可查看另一个离线SQLite订阅对账示例:查看完整SQLite订阅对账教程。该资料与本文的JSON校验代码不同,不表示本文代码已托管在该页面。全文无真实账号、订单或充值数据,也没有执行购买、激活或发货。