用AI+规则构建外卖订单分析工具:数据清洗与实体归一化实战 已经忘了具体是从哪一天开始我觉得“把一个月的订单讲明白”比研究任何宏大选题都有意思。当时的情况是支付App提示“本月在你常去的几家店花了XX”外卖平台也弹了“你的月结算超过了附近多少用户”可我真正想回答的问题——这个月到底哪类店吃得最多、哪家店回头率最离谱、还有没有低质重复消费——却答不上来。订单信息零散在四个地方外卖平台的导出文件、邮箱里的下单通知、支付账单里的商户流水以及我脑子里完全不可靠的“好像也没多点”。拼了半天数据格式对不上门店名称对不上优惠金额对不上。最后索性决定自己写一个“外卖分析工具”让AI参与整条处理链。这个项目从第一行想法到能稳定产出周报前后大概三周跑通之后回头反思真正要反省的不是AI不够聪明而是我一开始拿AI当会计用了。这篇文章不打算讲什么高大上的架构也不给完整代码我想把项目里极其朴素的几个决策过程梳理一遍需求边界怎么划、数据入口怎么定、实体归一化和指标计算为什么要人机分工、以及最终哪些环节真正省下了时间。希望给正准备做同类小工具的朋友一些可以抄作业的思路也给你兜个底——哪些坑你大可不必亲自踩。1. 需求边界我想让AI解决什么它不该解决什么1.1 原始需求听起来很“大”其实要拆成很“小”的事一开始我的脑内需求是做一个工具能够导入所有来源的订单自动清洗自动分品类自动分析花费规律然后还能像聊天一样回答我“本月我哪家店买得最多”。方向听起来很完整但真动手才发现这种“完整”恰恰是后面所有纠结的根源。拆解之后真正要解决的问题落到四个具体问题上每月实际外卖支出的口径是什么。这里包含实付金额、配送费、包装费、会员费还要剔除退款。不同店名和菜品名如何归并成可分析的档位。类似于“老王螺蛳粉(大学城店)”和“大学城老王螺蛳粉”其实是同一家。品类趋势怎么体现。例如川湘菜、日料、奶茶分别占多少周末和深夜有什么不同特征。哪些店值得继续复购、哪些属于惯性消费甚至盲目下单。同时我也划定了一个很重要的“不做清单”不收集任何外部商户评分和销量排行不做店铺级利润测算不追求百分之百解析所有历史订单。理由很简单个人项目的价值在于核心闭环跑通而不在于证明自己能把每条脏数据都变成干净数据。1.2 选AI而不是纯规则引擎到底图什么最初我也认真考虑过不碰AI全用脚本和SQL硬解。为什么最后坚持让AI参与因为这批数据里相当一部分是非结构化文本比如邮箱收到的HTML下单通知同一个菜品在不同邮件里描述差异极大用规则匹配会写出一堆脆弱难维护的if-else。但我也提前定了底线AI只做“翻译”和“摘要”不做“记账”。所有金额、数量、时间这类确定性字段必须走程序计算或人工核对。原因后面会细讲这里先给结论模型在文本归类上表现优秀在数值精确性上表现糟糕而你做账恰恰不能接受“大概准确”。1.3 先把样本攒够再决定架构动手写代码之前我花了两天时间做数据盘点。方式很笨登录外卖平台后台导出近一年订单CSV然后打开邮箱按“订单”“外卖”等关键词把历史通知邮件筛出来再把支付账单按月份导成Excel。这一步不涉及任何技术含量但直接影响后续所有设计的取舍。样本带来的一个关键信息是真正能当“主数据”用的只有平台导出CSV其他来源要么缺字段要么格式飘忽不定。这个发现直接决定了整个项目的数据架构——不是写一个万能解析器而是分主次、保核心、降期望。2. 数据进来之前AI再强也使不上劲2.1 一份真实订单数据长什么样先展示我当时遇到的数据形态大家感受一下来源类型常见承载格式缺失或容易出问题的字段我最终的处理方式外卖平台导出CSV表格门店名称在不同时期写法不一致当作主数据直接建立订单主表邮箱下单通知HTML邮件或PDF附件配送费、优惠金额经常不完整商品名有增删转存HTML后用脚本提取PDF仅作备份支付账单导出Excel或CSV只有“商户名金额”没有明细专门用于金额核对与退款校验这里最坑的问题是订单号对不上。三个来源各自有一套订单号平台导出是“PL20240321XXXX”邮件里是“20240321XXXX”支付账单里直接就是商户名称和金额。我只能用“商户名相似度金额相同时间接近”三重条件做匹配而不是依赖统一的ID。2.2 我干的第一件蠢事直接把PDF批量塞给AI现在想起来很讽刺我最早想省事把所有PDF订单通知交给一个大模型读让它输出结构化表格。翻车来得非常快。先是识别商家名称出错把“陶鲜生”读成“导先生”接着在金额上犯离谱错误一张订单的“支付100元”被识别成“10000元”。更隐蔽的问题是模型会“脑补”不存在的商品在某个模糊截图里硬生生补了一行“酸菜鱼”而原始订单里根本没有这道菜。这种错误最大的风险在于看起来很合理如果不逐单对照完全察觉不到。从那以后我立了两条规矩第一金额类字段必须由确定性代码从原始数字字符串提取禁止让模型做OCR或口算第二凡是模型给出的结构化信息必须保留原始文本字段作为证据任何结果都能追溯到源头。2.3 最终稳定下来的一条入库链路经历了上面的折腾最终入库流程反而回归简单手动从外卖平台导出近一年的CSV这个动作每月做一次当作订单主数据。写脚本自动抓邮箱里的HTML通知把“商品名数量金额”拆出来作为订单明细的补充。PDF附件只做备份存储不参与核心计算需要时再用规则加AI混合的方式提取。把所有来源统一转成三个本地表结构订单主表、订单明细表、支付流水表。给每条记录补充三个衍生字段品类、时段、星期属性随后进入分析层。我强调顺序是为了避免踩坑不要先处理格式最乱的邮件HTML而是先拿到最完整的平台CSV作为基准再拿其他数据去“对账”。如果我当时反着做可能会花几周时间在一个错误百出的入口上。3. 清洗和实体归一化才是AI真正替我跑腿的地方3.1 同一家店五种叫法正则表达式写到手软外卖数据最烦的地方之一就是实体词的同一个对象往往有一堆别名。例如我常点的那家粉店在平台记录里出现过这些写法“柳州螺蛳粉(大学城店)”“螺蛳粉·加辣(北区店)”“柳州螺狮粉(大学城店)”“招牌螺蛳粉”甚至出现过把“螺蛳粉”写成“螺狮粉”的错别字。如果完全靠人工维护映射表内容会越来越多而且新店一多就烦。如果靠正则表达式很难穷尽所有变体门店改名、加后缀、删空格都会让规则失效。3.2 别名合并方案相似度聚类加上AI最终裁决我的做法分三步。第一步做预清洗。把括号、特殊符号、店铺后缀之类先统一处理例如去掉“(外送)”“(到店自取)”等无关标识把全角符号转半角连续空格合并。这一步能解决一小部分简单差异。第二步做候选聚类。用“编辑距离相似度字符向量相似度”组合计算每个店名两两之间的相似度把相似度超过阈值的名字放到一个候选组。这个阶段不做精确判断只求把“可能相同”的放在一起减少人工查阅的量。第三步让AI做最终裁决。我把一组候选店名发给模型让它判断这些是否为同一家店并输出一个标记了“是/否/不确定”的JSON数组。为了减少偶然性同一组候选我会重复四次取多数结果。最终结果落到本地映射表下次遇到相同名字直接查表不再询问模型。这套方案的实际效果是高频店铺的归并准确率很高低频且不规范的店名仍偶尔出错但已经比手写正则强不少。我的经验是人工在映射提交前快速扫一眼保留“最终解释权”是性价比最高的办法。3.3 优惠分摊AI不合适规则才合适外卖订单里的优惠类型五花八门平台满减、商家优惠券、会员红包、配送费立减。第一版时我想当然地让AI自动拆分优惠到每个菜品结果它把“满35减8”按金额比例拆得特别均匀却解释不了“为什么这单的某两个菜优惠特别多”。后来我放弃了这个想法。优惠分摊只采用简单规则默认按商品金额比例分摊优惠遇到特殊整单优惠时在备注里写清楚退款则直接按整单处理。AI在这里唯一做的事情是根据历史数据生成一句“如果这家店优惠类目包含‘会员红包’你平均每个红包冲抵了3.6元”这样的解释性文案真正的计算跟我无关。4. 让AI做分析之前我先把业务指标定义得很死4.1 分析层的核心指标分析工具好不好用关键在于指标口径是否清晰。下面是我最终固定下来的几个指标指标名称计算口径分析层用途实付支出订单实付金额合计 配送费 - 退款看月度总支出和环比变化品类金额占比按订单明细归属品类后加总实付分摊金额发现偏食程度餐厅复购次数30天内同一商家命名实体出现订单数判断回头客集中度菜品重复率90天内同一商家同一菜品出现次数占比前20锁定“惯性点单”对象时段分布按早/午/晚/夜四个时段统计单量结合日历判断加班相关性定义清楚之后AI就没有太多发挥空间了。它唯一负责的是“品类分类”我给出一份固定选项例如“中式快餐、川湘菜、日料、烧烤、奶茶、甜品、小吃、轻食”再给它几十条已标注的历史样本让它按相同口径对全部明细做分类。这个任务它完成得意外地好尤其是把辣味小吃和家常菜分开比传统关键词规则灵活得多。4.2 自然语言问答只做“翻译”不做“写SQL”项目做到后半段我一度想加入一个自然语言问答框让用户直接问“上个月周末我花了多少钱”。一开始我试着让大模型把问题转成SQL去查库测试了几轮就放弃了因为模型偶尔会生成取数逻辑完全不同的SQL字段名一不对就报错。最终的产品形态是先把维度和指标做成预设好的切片模型只负责把用户的问题翻译成“筛选条件可视化类型”的参数比如“上个月”“周末”“按品类汇总”“柱状图”。翻译之后再调用固定的统计接口返回结果和图表。这样模型永远碰不到底层查询语句幻觉的风险从源头被掐掉。4.3 一个很反直觉的发现图表比“绝妙分析”有用第一版我还设计了一个“AI洞察”模块每天自动生成三条“聪明结论”。跑了几周后发现结论准确但几乎不解决问题比如“您本月奶茶支出增长20%”“您深夜点单比例较高”这种话看着有道理看完也就完了。反而是最朴素的“消费Top餐厅列表复购次数表”帮我改变了行为我发现有一家煲仔饭在那段时间里点了12次但其中6次发生在晚上加班后口味评价都一般。这个信息完全是从数据表里直接看到的AI没有赋予它神奇的“洞见”但它比任何文本摘要都要有行动价值。5. 全链路复盘AI哪些环节真实提效哪些环节帮了倒忙5.1 真实收益最高和最低的三个环节我把整个项目按环节拆开复盘了AI在里面的作用项目环节AI参与方式实际感受HTML订单提取把邮件HTML转文本后交给模型提取收益极高格式复杂也能照样处理品类分类基于少量样本的文本分类收益高省去大量手工打标门店名归一化聚类后让AI做最终判断收益中等仍需人工抽查OCR识别历史PDF图片文字提取加重建结构基本失败金额识别风险大优惠分摊计算不参与规则执行完全不适合AI自然语言问答只做条件翻译不直接取数有体验价值但非核心自动撰写洞察报告AI生成短句形式大于内容最终还是靠人看表这张表写出来我最大的感受是AI在“非结构化到结构化”这一段是人类的好帮手在“结构化数据到确定性结论”这一段完全帮不上忙甚至会添乱。5.2 为什么看起来“很智能”的生成式报表容易翻车有一类做法很诱人让AI每天自动生成一份分析报告然后用看似自然的语言描述数据。问题在于数据描述一旦被模型“润色”读者很难区分哪些数字是真实统计、哪些是模型推测出来的解释。举个例子某个模型生成“你的外卖支出主要集中在工作日晚间说明加班是外卖增长的主要驱动力”。这个结论从数据上看完全正确但模型没有能力告诉你它是不是基于完整月份判断、是否排除了节假日等特例。如果直接拿这种结论去做行为调整很容易被带偏。我的规则很简单AI负责“总结别人已经算好的数字”人不负责“让AI算出数字”。任何AI生成的结论都必须附上可以人工点开核验的明细表否则在发布前直接丢弃。5.3 人工复核的三个检查点我最终给项目设定了三道人工介入关口第一关在入库之后检查总量级是否异常比如某天突然刷出几十条重复订单可能是脚本重复运行。第二关在优惠分摊和退款合并之后抽查十单看分摊规则有没有明显不合理。第三关在报告生成之前对照趋势图看数字是否和原始表格一致。这套做法牺牲了一点点自动化但保住了结果的可用性。个人工具最忌讳“全自动但没人信”一道简单的人工确认反而让每次看报告都更踏实。5.4 隐私和安全只分析自己的数据也要划线最后简单说隐私。这个工具从头到尾只分析我自己的订单数据不涉及任何第三方采集。但我还是做了几个动作把包含详细地址的门店信息脱敏后再进入分析库图片和PDF扫描件只保留在本地目录不上传任何公共接口跟云服务交互时prompt里只传菜品名和金额不传订单号、电话、地址等标识字段。我的观点是个人小工具不用像企业系统那样上全套合规流程但基本的最小化原则一定要有——数据能留在本地就留在本地能脱敏就脱敏。6. 如果做第二版我会先改这三件事6.1 第一件事把数据血缘和计算口径记在代码里第一版我有很多临时计算散落在脚本里比如“实付订单金额配送费-退款”这个口径写在某个函数深处后来改过一次字段名整个历史报告对不上了。第二版我会在项目里增加一个结构化配置写明每个指标的计算公式、数据来源、版本号并让每张报告都输出口径说明。6.2 第二件事把异常单当成数据资产而不是垃圾以前我遇到退款、取消、少送这类记录会直接把它们从收入统计里剔除。问题在于丢掉了这些记录就丢掉了“哪家店最近经常出问题”的信号。第二版我要专门建一个异常事件表记录退款原因、取消时间、补送情况未来可以做“近30天异常率”指标用来说明哪些店需要减少复购频率。6.3 第三件事从月度报表改成连续周报月度报告最大的缺点是反馈太慢。第二版我想做的是每周日晚自动生成一张“饮食周报”本周点了几单、花费多少、奶茶几杯、哪家店连续两周出现。再配上AI生成的短句提示例如“本周三晚上又点了麻辣烫最近加班多可能需要注意”。这种设定期望的小提示比一次性大报告更适合改变行为。说实话做完这个项目我对AI辅助数据处理的心态变得务实了很多。它确实能处理很多我懒得写的文本规则但永远替代不了我对业务口径的定义和数据真实性的判断。下一次再有人说“用AI做一个完全自动的分析工具”我大概会回答让AI帮你读懂的就行账还是要自己心里有数。