☰
Agent Harness在供应链预测中的落地实践:从模型精度到协作流程
2026/10/18 18:33:38 网站建设 项目流程

1. 为什么供应链预测卡在了"最后一公里",而不是模型精度

做供应链预测的朋友应该都有过类似经历:手上模型的效果明明已经跑到了不错的MAPE,但业务部门拿着预测结果问你的问题永远是——"你这个数怎么来的?为什么这周突然涨了30%?下周的大促叠加缺货你能看到吗?"

我在某制造供应链的数据团队里接手需求预测模块时,最初的直觉也是"模型不够强,换个更强的"。当时我们在用的是一套以统计方法为主的基线模型,配合几个时序模型做候选池,按验证集表现选最优。整体效果不算差,但有两个问题始终绕不开。

第一个是外部信息进不来。模型看到的是历史销量、库存、价格这类数值,但业务里真正驱动需求变化的往往是促销安排、竞对动作、节假日迁移、甚至某天的舆情事件。这些信息不是没有,而是散落在业务系统的各个角落,传统时序建模很难把它们的信号及时吃进去。

第二个是结果没法对话。预测出来一个数,业务想理解"为什么",模型给不出解释。他们只能再去翻活动日历、看库存记录、问运营同事,相当于预测系统只管发数字,说服工作全由人来扛。

后来我们试过直接把历史序列和外部事件描述灌给语言模型,让它"看着办"。结果更不靠谱,幻觉、数字不稳定、跨批次复现性差,连最基本的"过去12周的销量呈上升趋势"这种话,不同轮次跑出来措辞都不一样,更别提让它输出可信的预测值了。

真正改变思路的是我们开始把问题从"预测得更准"转向"如何组织好一堆预测工具和业务信息,让它们协同工作"。这个中间编排层,业界叫 Agent Harness Engineering——不追求某一个模型无所不能,而是让一个具备推理能力的 Agent 去调度时序模型、规则引擎、业务知识库和外部数据源,共同产出预测结果并解释逻辑。

这套思路落地之后,团队内部的价值感完全不一样了:预测模型负责给"数字基准",Agent 负责补"业务上下文"和"推理过程",最终输出的不只是一个值,而是一份有依据、可追问的预测结论。这篇文章就围绕这个方案展开,重点讲清楚我们在落地过程中踩过的坑、想明白的取舍,以及一套可以直接参考复现的最小架构。

2. 先拆解多变量时序与LLM各自的边界,再谈"结合"

2.1 传统模型擅长"从历史推未来",但擅长不了"理解世界"

时序模型不管多复杂,本质上做的是同一件事:从历史序列中提模式,然后外推。这在相对稳定的需求场景里屡试不爽。比如某类标准工业件的备件需求,季节性稳定、生命周期长、外部扰动少,ARIMA、ETS甚至移动平均都能给出不错的预测。

但供应链里大量场景并不满足"稳定"假设。举个我们实际遇到的情况:某品类在电商渠道有一波大规模直播推广,单日销量冲到平日的8倍,之后回落。时序模型看到这个点后,会把它学进季节性或者趋势成分里,导致接下来几周的预测都被抬高。模型不理解"这是偶发推广事件,不是新常态",因为它没有渠道去知道"直播推广那天发生了什么"。

这类问题的本质是信息的模态鸿沟:数值序列能表达结果,但表达不了原因。而原因恰恰藏在非结构化的信息里——活动排期表、运营周报、竞品动态、天气预警。

2.2 直接用LLM裸测预测,会栽在四个地方

一开始我们认为,既然LLM能理解自然语言,那就把历史数据转成文字喂给它,让它直接输出预测值。实验下来,失败得非常稳定,基本有四种典型问题:

数值敏感度低。语言模型是按token说话的,它并不是真正在做数值运算。让它判断"序列整体上行还是下行"它做得不错,但让它输出具体到个位的预测数字,经常出现对细微变化的无感。比如过去三周销量分别是980、1020、1010,它可能直接给你预测个1250,完全没有意识到序列已经进入平台期。

输出不稳定。同一个Prompt、同样的数据,跑两次结果不一样。这在工程上非常致命,预测系统需要可复现性。业务追问"昨天你预测980,今天怎么变成1050了,数据没变啊",你没法解释。

缺乏约束力。LLM没有内置的"合理区间"概念,它可能预测出一个负数,或者一个比历史峰值高十倍的数字,并且一本正经地给出理由。供应链预测一旦出现这种离群输出,下游计划系统直接乱套。

无法确保使用正确的数据。你给它12周的历史数据,它可能只"看到"了最近4周,或者把周同比当成环比来理解,而且你很难知道它到底用了哪些数字。这种不可控性让它在生产环境里完全没有安全感。

但这些失败反而帮我们明确了一点:LLM真正的价值不在于数值外推,而在于语境理解和多步推理。它可以解释为什么某个信号重要,可以判断当前场景该调用哪个模型,可以把外部事件的因果逻辑串成一条可验证的链。关键是不要让LLM硬算,而是让它编排调度——这就是Agent Harness的核心思想。

2.3 Agent Harness到底管什么

如果用一句话概括:Agent Harness 是给LLM装上一套"工具+约束+记忆"的外骨骼,让它在供应链预测场景里能稳定地完成多步任务。

具体到我们这个项目,它主要管四件事:

  1. 工具注册与路由:系统里挂了多个预测引擎——Prophet、XGBoost、ETS、简单基线,以及一个规则计算器。Agent根据数据特征和业务场景,决定调用哪个工具、调用几个工具、以什么顺序调用。
  2. 上下文装配:把历史销量、库存状态、促销日历、外部事件浓缩成结构化的上下文块,按相关性和时间窗口排列,控制token开销,不让Agent一次性接触过多噪声信息。
  3. 推理轨迹管理:要求Agent按步骤输出——先判断状态,再选择工具,再解释理由,最后给出预测建议。每一步都留痕,业务可以回溯整个预测是怎么来的。
  4. 输出约束与校验:Agent的输出必须是预定义的JSON结构或选项集合,还要经过规则校验器检查,比如是否在合理范围内、是否与长期趋势矛盾。不合规直接打回重做。

这套设计本质上是个质量护栏:允许LLM有灵活性,但决定性步骤必须落在程序可控的轨道上。

3. 多变量时序特征工程:决定Agent"看到什么"的翻译层

这里想重点聊聊这个方案里最容易被低估的环节——怎么把多变量时序数据翻译成LLM能高效消费的形式。

前面说过,LLM对数字的敏感度远低于对模式和关系的敏感度。所以特征工程的目标不是"尽可能多地把数字喂给它",而是"让它以最小代价捕捉到关键模式"。我们从几个层面做了处理。

3.1 特征选择:别把整个历史序列都扔给Agent

供应链预测相关的变量很多,但Agent的上下文窗口是有限资源。我们最终保留了以下几类高价值信息:

特征维度具体内容为什么重要
需求历史最近8-12周周销量、4周移动平均判断短期趋势和波动基线
同比基准去年同期的销量、增长率捕捉季节性迁移和年同比变化
业务事件未来4周内的促销日、上新日、库存限制外部驱动因素的核心来源
库存状态当前库存水位、在途量、可售天数直接限制可达成销量
价格变化近期调价幅度、折扣力度价格弹性对需求的即时影响
外部宏观节假日前后的班次调整、出行结构变化特殊时段需求的规律性偏移

值得注意的是:不是变量越多越好。我们把所有可选特征喂给Agent做过实验,发现它在信息过载时反而容易忽略关键事件。后来改成"按品类预配置特征模板",每个品类只暴露与之最相关的一组变量,效果明显提升。比如生鲜品类重视保供天数和气温,耐用消费品品类重视促销周期和库存深度。

3.2 把序列转成"模式语言",而不是数字流

早期我们尝试过直接把12周的销量数据用逗号分隔拼成一段文字喂给Agent,比如"1200, 1250, 1180, 1340,..."。效果很差,它根本抓不住序列的形态特征。

后来我们换了一种方式:先程序化提取模式描述,再让Agent在这个基础上推理。比如:

- 最近4周平均销量:1280,前4周平均:1150,环比上升约11.3% - 最近8周趋势:整体上行,但第6周有明显回落,对应促销空档期 - 去年同期同4周:1040,同比上升约23% - 未来2周事件:B类促销活动,预计折扣幅度15% - 库存状态:当前可售7天,低于安全水位

这样Agent看到的是一份高度凝练的"状况简报",而不是一堆需要它自己解析的原始数字。它能够在此基础上做推理:趋势上行 + 即将促销 + 库存偏低 = 需要警惕供不应求,建议预测值考虑供应上限约束。

这个设计背后有个原则:计算模式的活交给程序,解读含义的活交给LLM。不要强迫LLM去做数值计算,那是Python的强项;要让LLM做它擅长的部分——基于模式理解做出判断。

3.3 窗口设计与事件对齐的细节

特征窗口的长短直接决定Agent的"时间视野"。我们试验下来,推荐这样的窗口组合:

  • 短期窗口:最近8周,密度按周计,用来判断即时趋势
  • 季节性窗口:去年同4-6周,用来捕捉年同比模式
  • 事件窗口:未来2-4周的活动与限制,用来前视判断

窗口太长,噪声和无用信息会稀释关键信号;太短,季节性模式看不到。8周是我们对不同品类做敏感性测试后的折中值。

事件对齐需要特别注意一点:促销日期、上新日期在落地时经常延期或调整,所以事件窗口的数据必须是动态拉取的,不能靠离线快照。我们做过一次事故,某次大促因为物流原因推迟了一周,Agent的预测还按原日期外推,结果高估了那一周的销量。后来把所有外部事件改为API实时拉取,并让Agent每一步推理前先确认当期事件列表,问题才解决。

4. Agent工作流设计:从"一个模型预测"到"一次预测推理"

4.1 整体流程骨架

我们落地的工作流不只是"调用LLM一次出结果",而是设计成了多步流水线,每一步都有明确的输入、输出和校验点:

  1. 状态识别:Agent先读取压缩后的状况简报,输出对当前需求状态的判断——快速增长期、平台期、下行期、波动异常期。
  2. 模型选择:基于状态判断,Agent从候选模型池里选择主模型和辅助模型,并说明理由。比如"数据上有明显趋势和季节性,建议以Prophet的预测为基础;最近4周波动较大,XGBoost可能更敏感,作为交叉参考"。
  3. 基础预测获取:程序调用选定模型生成预测值,这一步不经过LLM,保证数值的可靠性和可复现性。
  4. 事件叠加修正:把基础预测交给Agent,结合业务事件判断是否需要修正。比如"基础预测为1250,但下周有15%折扣的促销,根据历史同类活动平均提升25%-35%,建议修正区间为1560-1690"。
  5. 合理性校验:Agent输出修正结果后,经过规则引擎校验。如果预测值超过历史合理区间、或者出现了方向性冲突(比如库存严重不足却预测高增长),则标记为异常并交给人工复核。
  6. 解释生成:最终输出预测值、区间、依据和风险提示。

这个流程很有意思的一点是:LLM在其中的角色更像是一个项目负责人,而不是计算员。它负责理解目标、分派任务、汇总判断、解释结果;实际数值计算由专业的时序工具完成。

下面是一个极度简化但能表达核心思想的伪代码:

def run_forecast_agent(context, available_models): # 步骤1:状态识别 state = agent.identify_state(context.status_brief) # 步骤2:模型选择 selection = agent.select_models(state=state, candidates=available_models) if not validate_selection(selection): raise ForecastError("模型选择不合理") # 步骤3:基础预测(程序执行,不经过LLM) base_forecast = run_forecast_model(selection.primary_model) if selection.secondary_model: ref_forecast = run_forecast_model(selection.secondary_model) # 步骤4:事件修正(LLM推理) adjustment = agent.adjust_with_events( base=base_forecast, events=context.upcoming_events, event_history=context.similar_event_records ) # 步骤5:规则校验 final_prediction = rule_validator(adjustment, bounds=context.reasonable_bounds) # 步骤6:解释生成 explanation = agent.explain( final_prediction=final_prediction, base_forecast=base_forecast, reasoning_steps=adjustment.reasoning ) return final_prediction, explanation

这段代码不是可以直接上生产的级别,但可以看出分工边界:Agent负责判断和解释,程序负责数值计算和规则校验,两者各司其职。

4.2 让Agent"知道该信谁",是模型选择的关键

在多模型环境里,Agent面临的核心挑战不是"哪个模型平均更准",而是"在当前数据特征下哪个模型更可信"。这两个问题完全不同。

我们构造了一个简单的模型画像表给Agent做参考:

模型擅长场景弱项适用的数据特征
ETS稳定的趋势+季节性对突变不敏感周度数据、低噪声
Prophet多季节周期、缺失值容忍度对非线性事件反应迟钝月度/周度混合周期
XGBoost特征丰富、非线性模式数据量小时容易过拟合有外部特征的场景
简单基线极度稳定的品类无法捕捉复杂变化低波动、长生命周期产品

Agent选择模型时,我们要求它不仅给出选择结果,还要给出一个"可信度打分",比如"此品类数据量偏少且波动大,XGBoost容易过拟合,我倾向选择Prophet,可信度0.72,建议辅助参考简单基线"。这个打分并不直接用于加权计算,但它会写入预测日志,帮助团队后期审计Agent的决策质量。

4.3 事件修正中的"记忆检索"与相似案例

大多数供应链事件不是第一次发生。每次大促、调价、上新,事后都会有实际销量数据回填。我们把这些历史事件和对应的"需求变化系数"沉淀成一个事件知识表,Agent做修正时先去检索最相似的3个历史事件,用它们的实际效果来支撑推理。

举个例子:某品类下周四有个满减活动,Agent检索到去年同品类类似力度的满减活动在当时创造了约28%的销量提升,并且活动结束后一周销量回落约15%。它据此给出的修正预测就比凭空猜一个涨幅要可靠得多。

这个机制本质上是给Agent装了一个经验记忆系统,而记忆的来源正是组织里长期积累但未被有效利用的运营记录。做这个表的时候要注意清洗数据:只收录有明确开始结束时间、有明确影响口径的事件,并且同类事件至少要有3次以上才纳入参考,避免用单次特殊情况误导Agent。

5. 最终验收环节:不只问"准不准",还要问"替谁省了什么"

5.1 拿什么指标考核这套体系

单纯对比MAPE或WAPE很容易陷入一种误区:Agent方案在某几个品类上表现突出,在另一些品类上跟传统模型打平甚至略差,那到底算成功还是失败?

我们后来把评估体系分成三层:

  • 第一层:数值精度。还是看MAPE、覆盖率、偏差方向,这是最基础的底线,不能比传统模型差太多。
  • 第二层:业务决策价值。采购和计划是否愿意采纳这套系统的预测?采纳后动销率/库存周转是否有改善?这个维度比纯误差数字更重要。团队里后来约定:预测可以说"偏了",但如果预测帮助业务多抓住了两个热销SKU的备货机会,那体系就是有价值的。
  • 第三层:解释与审计成本。业务问"为什么这么预测"时,团队需要花多久回答出来?传统模型往往需要半天甚至更久去翻数据、猜原因;Agent方案因为有推理留痕,几分钟就能给出解释链条。这个成本的下降,是以前没预料到的最大红利。

5.2 对比实验怎么设计才不骗自己

我们做对照实验时,把同一批历史数据切成三类来测:

  1. 纯时序模型:用最佳单项模型预测,不做事件修正。
  2. LLM裸预测:把序列和事件描述直接交给语言模型输出数值。
  3. Agent Harness方案:完整流程,含工具调用、事件检索、规则校验。

结果在意料之中:Agent方案在MAPE上没有碾压纯模型,但在业务事件密集的时间段内误差明显更低;LLM裸预测在数字稳定性上惨不忍睹,直接出局。这个结论很关键——Agent的收益集中在"有外部事件扰动的场景",而这类场景恰恰是传统模型最薄弱的地方。

5.3 方案框架评估:成本和时延不划算怎么办

必须诚实地说,Agent方案不是免费的。每次预测调用会涉及多次LLM推理,单SKU的预测耗时从毫秒级涨到秒级,成本也更高。如果你的场景是每天凌晨跑一次全量预测,完全可以接受;如果业务要求实时的自动补货决策,那可能需要先做一轮模型压缩和结果缓存。

我们做了一个分级策略:对波动小、历史稳定的SKU,直接用传统模型跑,不进Agent链路;只有达到一定波动阈值、或者未来两周内存在事件的SKU才走完整流程。这让整体成本下降了约6成,而预测质量基本没受影响。这是我认为整个落地过程中最值得做的工程优化——让Agent去处理它最能增值的边界场景,而不是大包大揽。

6. 实际运行中的故障清单与调优手记

6.1 上下文窗口不够用,怎么压缩不丢信息

供应链场景的上下文可能包含12周周度数据、未来4周事件、库存水位、价格变化、相似案例记录,全部展开很容易超过上下文长度限制。

试过几轮以后,我们确定了压缩原则是"先算好,再简述,最后只留结论和关键数字"。程序先把所有数据预处理成上面说的状况简报,再把相似案例只保留Top3的摘要,事件描述控制在每条约20-30个字。最终每次预测的上下文控制在1-2K token以内,效果和全量信息几乎一致。

6.2 "模型看不到的盲区",Agent也看不见——除非你教它看

这是一个容易让人产生错觉的地方:你以为加了Agent,它就能自动发现所有影响因素。但实际上,如果某个信息源没有接进来,Agent根本不知道它的存在。

有一次某品类的销量突然飙升,Agent给的解释是"趋势上行动能增强",听起来合理但完全没说到点上。后来分析发现,真正原因是某大客户提前下了一个大单。这个信息存在CRM系统里,根本没有进入预测链路。你没法指望Agent主动去查一个自己不知道存在的系统——所以数据接入清单比Prompt调优更优先。每季度盘一遍"哪些业务动作会影响需求,它们的数据在哪,接进来了没有",是维持体系有效的日常工作。

6.3 数字描述方式的颗粒度影响推理质量

同一个信息有两种写法:

  • 写法A:"第6周销量为980"
  • 写法B:"第5周销量为1020,第6周为980,环比下降3.9%"

Agent在处理写法A时,容易把所有数字都当成独立点,看不出趋势;写法B直接把关系和变化量给出来了,它的判断就准确得多。我们最后的规则是:凡是涉及比较的信息,一律按"对比+差值+比例"描述,绝不只扔绝对数值。

这里涉及语言模型的词元切分机制:LLM数值感知能力弱,一个细微差异要花很多 token 才能"看到",而相对变化是现成的叙述,直接给它结果比让它自己算可靠得多。这条经验放到任何数据结合LLM的场景都适用:先把变化算出来,再让模型去解释变化。

6.4 输出结构化:让Agent说人话,但按代码格式说

最后一条是工程上的关键约束:Agent的输出一定要限定结构化格式。我们使用的Schema大概是这样:

{ "state": "growth", "selected_models": [{"name": "prophet", "confidence": 0.72}], "base_forecast": {"point": 1250, "interval": [1120, 1380]}, "adjustment": {"value": 350, "reason": "促销活动预计提升25%-30%"}, "final_forecast": {"point": 1600, "interval": [1440, 1760]}, "explanation": "趋势上行,叠加下周B类促销活动,预测区间上调", "risk_flags": ["库存可售天数低于8天,可能限制实际销量"] }

如果Agent返回的JSON缺字段、或者区间上下界写反了,直接被规则引擎拦下来重跑。强迫结构化的另一好处是可以做回归测试:每次更新模型或Prompt后,在历史数据上回放一遍,看有几条输出变了、变化方向是否合理。这套回归机制几乎是我们在生产环境里敢持续迭代API的底气。


把Agent Harness这套思路落地到供应链预测,我们走了一条从"追求更准的模型"到"设计更聪明的协作流程"的转折。如果你现在面对的问题也是模型够强但业务仍旧不买账,我的建议是别急着换算法,先画一张图:你的预测链路里,外部信息从哪里来?谁来解释结果的合理性和风险?如果这两个问题答不上来,那大概率缺的不是更强的模型,而是一个能把模型、数据和业务语境编织到一起的Agent编排层。可以先从最小闭环试起,把一个品类的预测流程跑通,再逐步扩品类、补工具,这条路会比你想象中走得稳得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询