外卖履约时间预估:从规则到机器学习,如何算准送达时间

发布时间:2026/10/13 10:57:24
外卖履约时间预估:从规则到机器学习,如何算准送达时间 1. 履约时间预估到底在解决什么问题做了几年即时配送业务我对“履约时间预估”这几个字的感情很复杂。用户看到的是“预计28分钟送达”运营看到的是超时率和客诉骑手看到的是“系统又给了一个不可能完成的时间”而做系统的我们看到的是一个目标函数、一堆特征、一套模型以及无数次被线上真实数据打脸的瞬间。先说结论履约时间预估的核心目标从来不是“把时间写短”而是“把时间算准”。用户要的不是一个虚假的“20分钟”而是一个“说了能做到、做到能信”的承诺。平台要的是在承诺和实际之间取得平衡——太保守下单转化率下降太激进超时率飙升骑手和用户一起骂。整个外卖履约体系的效率很大程度上取决于我们能不能把时间预估这件事做好。这条链路里所有人都在依赖同一个数字。用户下单时看到预计送达时间决定要不要等骑手接到订单时看到系统给的配送时长决定能不能接、怎么跑调度系统根据每个订单的预估时长做派单决策是压给近处的骑手还是顺路带一单商家也要根据出餐时间决定是否接单、是否提前备餐。换句话说履约时间预估不是一个简单的“倒计时显示”它是整个运力调度系统里最底层的决策输入。那么问题来了这个数字到底应该怎么算一单外卖从用户下单到骑手送达中间经历多少个环节、哪些环节可以预测、哪些环节根本预测不了这是我们做预估系统之前必须先想清楚的问题。1.1 先搞清楚“更快”不等于“显示更短”我刚接手这块业务时最先被业务方问的一句话是“能不能把预估时间再调短一点用户老嫌我们慢。”我当时没有直接回答而是先把过去一个月的订单数据拉出来看了一遍。结果发现实际履约时长中位数是32分钟而页面显示的预计送达时长是35分钟按说显示时间已经比实际时间长了为什么用户还是觉得慢后来拆完数据才明白用户感知的“慢”不是页面数字长而是“承诺和体验之间的落差”。有相当一部分订单实际送达时间超过了显示时间一旦超过用户就会觉得“你骗我”这种负面体验远比“显示40分钟但32分钟就送到了”来得严重。所以在履约预估这件事上最重要的原则是宁可把时间往宽里估也不能为了好看而刻意压短。预估的准确度比预估的美观度重要一个量级。我们内部定过一个规矩任何新模型上线首要指标是预估误差下降而不是页面显示时长下降。显示时长只是结果误差才是根因。1.2 履约时间的四个组成部分一单外卖从用户下单到骑手送达看起来是一个连续过程但真正做预估时必须把它拆成四个独立环节因为每个环节的变化规律完全不同。第一段是商家出餐时间。从用户下单到骑手取到餐这段时间主要取决于商家菜品的复杂程度、当前订单排队情况、商家是否提前备餐。第二段是骑手到店时间。骑手从当前位置到商家门店的骑行时间取决于距离、路况、天气。第三段是取餐等待时间。骑手到店后如果餐还没好需要等待这部分和第一段高度耦合。第四段是交付时间。骑手从商家到用户手中的骑行时间加上上楼、等电梯、打电话的时间。这四个环节不是简单相加的关系。骑手到店时间和商家出餐时间如果首尾相接取餐等待可能很短如果骑手到店太早而商家出餐又慢取餐等待就会很长。许多早期方案用“固定出餐时间路程时间”直接算误差特别大原因就是没有处理环节之间的耦合关系。一个相对合理的估算方式是出门时间 max(骑手到店时间, 商家预计出餐完成时间)。也就是说骑手到店时间和商家出餐时间取最大值再加上交付时间而不是简单地把所有环节都累加一遍。这个逻辑很简单却是我见过最容易被新手忽略的地方。2. 做好预估的地基数据和指标模型也好规则也好都建立在一个前提之上数据足够细、足够准、足够稳定。做履约时间预估最怕的不是算法不够强而是数据链路有洞模型在“半盲”状态下做预测。我先带队把埋点全面梳理了一遍。订单从创建到完成每一步都要有事件、有时间戳、有位置信息。这里不是“差不多就行”而是必须做到订单ID关联上商家出餐状态变化、关联上骑手轨迹点关联上用户收货地址的楼层和门牌。否则后面做特征工程连“这个商家这单是出餐快还是骑手到店快”都分不清。2.1 先定义清楚北极星指标如果没有统一的衡量口径预估系统优化起来就是各说各话。运营说“超时率降了没”算法说“MAE降了多少”产品说“用户投诉少了没”——三个指标有时候方向还是反的。我们当时的做法是建立一套分层的指标体系顶层看超时率也就是实际送达时间超过承诺时间或者超过一个容忍阈值比如承诺5分钟的订单占比。超时率是用户可感知的最终结果也是我们最在意的业务指标。中间层看预估误差常用的是绝对误差率定义是abs(实际时长-预估时长) / 实际时长。这个指标能反映预估系统本身的准头。底层看每个环节的单独误差出餐误差、到店误差、交付误差分别拆开看。只有把误差下探到环节级别才知道问题出在商家侧、骑手侧还是模型侧。对这三层指标我有一条经验顶层超时率不能只看平均值必须分时段、分天气、分商圈看。暴雨天和平时混在一起平均数会掩盖一切问题。我们当时建立了一张小时级的监控报表把一天的订单按照时段、区域、天气切成格子每天早晨扫一眼哪个格子异常一眼就能看出来。2.2 哪些数据决定了预估的准头要预测一个订单的履约时间最核心的数据至少有这么几类。订单本身的属性是基础下单时间、商家ID、商品类目、用户地址的楼层和楼栋类型。我们后来发现商品类目特别重要一碗面和一份炸鸡的出餐差异非常大面食相对快炸鸡涉及现炸环节出餐时间长且不稳定。商家侧的实时状态是金矿最近15分钟商家产出的订单量、当前在途订单数、商家平均出餐时长、商家出餐时长的波动性。我们接入了一批商家的接单系统和出餐状态上报由商家在菜品完成后点击“出餐”这个动作带来的信号比任何模型都准。当然不是所有商家都会及时点所以还需要用历史数据兜底。骑手侧的状态是变量骑手当前位置、当前手上在派订单数量、当前订单的剩余配送距离。如果骑手手上已经有三单第四单的预估时间就不能按空载来算。环境侧的信息是调节项天气、温度、时段、商圈单量。雨天配送速度平均下降10%到20%这个规律稳定得很。这里面最难拿的是商家出餐状态。许多平台早期没有能力让商家上报出餐状态就只能靠历史分布来猜。我们做过一个对比接入出餐上报信号之后整体预估误差改善了约7个百分点效果非常明显。2.3 建立小时级与分钟级的数据管道有了数据源还得有靠谱的数据管道。我踩过一个大坑早期用的是小时级统计任务把历史订单按小时聚合算平均时长。结果一到午高峰聚合数据还没跑完外卖都送完了模型还在用半小时前的数据做预估。后来我们把整个链路改成了分钟级实时计算。订单状态事件通过消息队列实时上报特征计算用流式计算引擎按订单维度做窗口聚合模型服务直接读取最新的特征值。这条链路的改动不大但预估的时效性提升了一个量级。简单说商家当前排队多少单、骑手当前距离多远这些特征必须是“此刻”的值而不是“上一个小时”的统计值。注意做实时特征的时候一定要关注事件乱序。骑手轨迹点的上报频率不一样有的骑手网络不好事件晚到几十秒如果不做事件时间戳对齐特征值会来回跳动模型输出也会跟着抖动。我们曾经遇到过某个区域预估时间在几分钟内反复横跳最后定位下来就是事件乱序导致的。3. 预估模型怎么从规则一步步升级到机器学习履约时间预估这个任务业界已经有比较成熟的路径从规则估计到统计分位数再到机器学习回归最后到深度学习模型。我带的这个项目基本把这条路径完整走了一遍每一步都有必要因为每一步都在解决前一步解决不了的问题。3.1 第一版分位数规则估计最朴素的方案是查表法。把订单特征离散化比如按城市、区域、时段、天气组合成一个个桶每个桶里取历史订单实际履约时长的P50或P80作为预估时间。这个方案的优点是简单、稳健、容易解释。取P80意味着80%的历史订单在这个时间内完成超时率天然压得比较低。缺点也很明显它是“平均人”的画像没有办法区分同一时间段、同一区域内一个骑手手上挂一单和挂四单的情况。但我们仍然建议第一版用分位数规则来打底。因为它的可解释性极强线上出问题很容易排查哦这个桶的数据没更新所以预估时间偏了。后面上线模型时分位数结果也适合作为基线。3.2 第二版梯度提升树模型业务稳定运行一段时间后我们开始用梯度提升树来做回归预估。特征输入是前面提到的那几大类的几十个特征标签是订单实际履约时长损失函数用MAE或者Huber Loss。为什么优先选树模型而不是深度学习因为外卖履约数据里有大量离散特征和高阶交叉特征树模型对这类数据的拟合能力很强而且训练成本低、推理快、线上容易部署。我们用LightGBM训练了一个回归模型离线验证下来MAE比规则方案下降了约15%。有一件事必须提醒不要让模型直接预测“总时长”。我们在开发中试过直接回归总时长效果不够好因为总时长的分布太宽长尾订单严重拖累模型训练。更好的做法是分段预测先预测出餐时长、骑行时长再预测取餐等待和交付时长最后组装。分段模型的好处是各段的特征更聚焦出餐时长主要看商家状态骑行时长主要看距离和天气互不干扰。缺点是工程上要维护多个模型链路更长。3.3 特征工程里最容易被忽略的三个特征做特征工程那段时间我们踩了不少坑也积累了一些普通文档里不会写的经验。有三个特征看着不起眼实际对模型提升特别大。第一个是“商家当前在途单量”。刚开始我们只用了商家历史平均出餐时长模型对高峰期的预估明显偏低。后来把商家当前未完成的订单数作为特征加进去模型的出餐误差立刻下来了。道理很简单商家出餐是排队系统前面排着10单和排着1单出餐时间完全不同。第二个是“骑手当前被执行中的订单剩余距离之和”。这个特征本质上描述的是骑手的忙碌程度。同样都在商圈里一个骑手手上三单还剩5公里要跑另一个骑手手上三单但都顺路两个人的可接单能力完全不同。第三个是“历史同时段的区域单量”。外卖有非常强的潮汐效应午高峰的11:45和11:15看起来只差半小时配送难度却差很多。这个特征对高峰期的订单预估特别有用。3.4 输出区间还是输出单点很多刚入行的同学问预估时间到底应该输出一个单点值还是一个区间我的答案是区间更实用但对外展示可以只展示单点。模型可以同时输出P50和P80两个预估P50代表期望值P80代表保守承诺。调度系统内部用P50做决策因为派单时更关注大概率事件用户端展示用P80因为承诺要更稳妥一些。两个模型共用一套特征只是损失函数不同P50用MAEP80用分位数损失工程实现上并不复杂。提示输出区间的另一个好处是可以方便地做“动态承诺”。在运力充足时P50和P80之间的距离比较小页面可以展示一个较短的时间在运力紧张时两者距离拉大系统自然会把承诺时间调长。这种做法比硬编码一个固定缓冲时间要优雅得多。4. 预估结果如何反哺调度与运力履约时间预估不是孤立存在的。它既是一个面向用户展示的结果也是整个调度系统做决策的输入。预估准不准、稳不稳定直接决定了调度策略能不能跑起来。4.1 派单与路径规划对预估的强依赖我们平台的派单策略里有一个核心目标函数在满足骑手工作时间和订单时效要求的前提下最小化整体配送成本。在这个函数里每个订单的预估完成时间是一个关键约束。如果预估偏短系统会把订单派给一个时间上根本来不及的骑手导致连锁超时如果预估偏长系统又会把订单派给一个原本可以更快完成的骑手浪费运力。还有一个容易被忽视的问题路径规划对预估的反向影响。同一个骑手同时拿三单系统怎么规划取送顺序决定了每个订单的实际送达时间。我们最初把路径规划结果作为静态输入给了预估模型后来发现路径本身也是动态的骑手可能因为路况临时改变顺序。一个相对成熟的做法是在路径规划模块里做“时间窗校验”用预估模型的时间窗反过来约束路径顺序的选择形成闭环。4.2 动态ETA重算与用户端展示订单创建时算出的是一版预估时间但它绝不应该是静态的。我们上线了动态重算机制每隔一段时间或者关键节点发生变化时比如骑手到店、商家出餐完成、骑手取餐重新计算剩余时长更新用户端展示的ETA。动态重算的触发条件需要仔细设计。触发太频繁用户端时间跳来跳去体验很差触发太少又失去了动态调整的意义。我们的做法是只在这几种情况下重算骑手到店、骑手取餐、骑手距离用户地址还有约1公里、订单实际用时已经超过原预计时间。超过原预计时间这在体验上特别重要——宁可主动告知“可能延迟”也好过让用户干等不知道要等到什么时候。4.3 履约节点闭环从“算了准”到“改了准”我在项目里反复强调一个理念预估系统不只是一个预测系统更是一个控制系统。预测做得再准如果实际履约过程中出了问题还是要有人为干预的通道。我们建立了一个节点监控和干预的机制当系统发现某些订单的实际进度明显落后于预期进度时自动触发调度干预策略。具体来说如果骑手到店时间比预计晚了超过5分钟系统会给订单加急标记优先重派给附近更合适的骑手如果商家的出餐时间明显超过预估系统可以把骑手的取餐时间顺延避免骑手白等。这套机制上线后超时率又下降了一个点。原因很简单预估模型解决的是“大多数情况下预测得准”而干预机制解决的是“少数情况下能纠偏”。两者配合才是完整的履约保障体系。5. 让配送真正变快的几个非模型手段模型再强也只是在给定条件下做预测。要让外卖真的变快还得靠几个模型之外的抓手。5.1 出餐环节的协同履约链条里商家出餐是最不可控的一环。我们后来做了一件事把“预估出餐时长”透明化给商家。商家端可以看到系统预期自己需要多长时间出餐如果实际出餐时间经常超时系统会提醒商家、给出优化建议比如提前备菜、优化菜单结构、在高峰期加人手。这个方案的效果比我们预想的好。原因在于很多商家其实不知道自己出餐慢直到平台把数据和同行对比摆在他面前。有家做简餐的商家原本出餐经常掉到15分钟开外看到数据和对比后主动调整了备餐流程一个月后平均出餐时长缩短到8分钟连带它的订单量都涨了。所以说预估系统不是只用来“算”的还可以用来“驱动改进”。5.2 取餐交付阶段的动作标准化交付环节的隐形损耗我估计至少占到总时长的5%到8%。骑手到店找不到餐、商家找不到骑手、用户不接电话、小区不让进这些看起来都是小事叠加起来就是大延误。我们的做法是尽量把动作标准化。骑手到店前系统推送商家桌号和取餐码到店后如果餐未完成系统预估还需多久并展示给骑手让骑手决定先去跑其他订单还是原地等交付时如果用户地址是高层住宅系统会提示骑手提前电话联系。这些细节单独看都不起眼但合在一起能让骑手少浪费很多时间。5.3 极端天气与爆单场景下的履约策略下雨天外卖量暴涨骑手配送速度却下降这会带来一个矛盾平台想承接更多订单但越接单整体履约质量越差。我们做过一次极端测试雨天订单全部接进来之后超时率飙升到平时的三倍用户投诉也暴涨。后来我们调整了策略雨天来临前根据天气预报提前调整预估时间的“保守系数”比如把P80的缓冲上调10%同时控制高峰期的接单量优先保证已有订单能按时送达。这样做虽然少接了一部分单但整体体验和用户满意度反而更高了。这个案例告诉我们履约效率不是“接单越多越好”而是在现有运力条件下做正确的取舍。6. 实战中踩过的坑和排查经验这部分我想把项目推进过程中踩过的坑和排查经验尽量完整地分享出来。说句实话做履约预估真正让你成长的不是算法而是一个个线上事故和一遍遍排查。6.1 雨天模型失效问题出在天气特征太粗第一年雨季我们的模型在雨天的误差突然翻倍。排查下来发现天气特征是用“城市级”数据整个城市一个天气码。可实际情况是同一场雨在不同商圈的强度完全不同东边大雨倾盆西边只是毛毛雨用一个城市级特征去预测误差自然大。后来我们把天气数据源切换成网格级预报每个商圈匹配最近网格的降水强度和风力模型误差明显回落。这件事给我一个教训特征精度至少要和业务粒度匹配城市级特征配商圈级业务精度天然不够。6.2 新商家冷启动历史数据根本没有新商家的预测是最难的。没有历史出餐数据没有历史订单模型只能用同类目、同区域的平均水平来估。结果往往是新商家出餐慢我们按平均水平预估骑手到店后干等超时率极高。我们的解法是做“同品类冷启动模板”。新商家的预估出餐时长取同商圈同品类商家的中位数等这家商家积累了20单真实数据后再切换成个性化预测。这个“模板过渡”的方案不复杂但非常实用。6.3 AB实验的坑预算时间变了行为也跟着变做实验时最容易犯的错误是只关注预估误差本身忽略了行为变化。我们曾经上线了一个更准确的预估模型离线指标很漂亮在线实验超时率却没怎么降。拆解后发现新模型给部分订单的预估时间变短了用户看到更短的送达时间更愿意下单结果订单量上升运力被摊薄超时率又涨回去了。这个案例告诉我们预估系统优化会改变用户行为进而改变运力压力最终反过来影响履约指标。所以做AB实验不能只看单一指标要用一组指标综合判断超时率、预估误差、完单量、用户满意度全部放在一起看。6.4 监控报表怎么搭才有效预警和监控不是万能的但没有监控是万万不能的。我们最终搭建的监控体系分成三层第一层是小时级核心指标监控超时率、预估中位误差、页面显示时长第二层是城市级异常识别某个城市的预估误差连续两小时偏离基线超过一定比例就自动报警第三层是归因分析报表把异常自动拆解到环节和特征维度比如是出餐误差偏大还是交付误差偏大。这套监控体系的价值在于它把“问题出现后的排查时间”从小时级压缩到分钟级。一个区域预估突然不准打开归因报表如果是某个校园门口在办活动导致交付时间暴涨马上就能定位到然后针对性调整该区域的预估系数。7. 落地推进的几条心得项目做到最后技术上的东西反而聊得少了更多是组织和管理上的体会。履约时间预估这个项目横跨算法、产品、运营、调度、骑手端、商家端任何一个环节掉链子项目都推不动。我们当时推动商家出餐状态上报算法和产品花了很多精力去做商家后台的改造和宣导如果不是运营团队一家一家去说服商家启用模型的效果至少要打折一半。所以提醒想复制这套方案的同学提前把跨团队协调的资源和机制想清楚不要等技术方案定了才发现没人推进。另一个心得是线上问题永远会比离线实验先暴露。我们几乎每天都在处理线上反馈某个区域预估时间偏短、骑手集体爆单、某个商家的出餐时间特殊。建立一条快速响应线上问题的小作战机制比追求模型精度更重要。预估系统不是一次上线就完事它是需要长期运营、持续优化的系统。还记得项目上线半年后我拉出前后数据对比超时率下降了不少预估中位误差也明显缩小更关键的是用户对送达时间的负向反馈占比大幅下降。相比之下页面显示的预计送达时长并没有明显变短但用户觉得“平台靠谱了”。那一刻我意识到履约时间预估所做的所有事最终都指向一个朴素的目标让用户对“等多久”这件事心里有数让骑手干活时不至于总被时间追着跑。如果你也在做类似的东西我的建议很简单先把数据链路打通把指标口径定清楚再用简单方案上线跑到稳定然后再上模型。不要一上来就追新潮算法履约预估这个场景里稳定、可解释、可干预永远比炫技重要。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询