WMS AI Agent实战:用19个工具让大模型精准查询库存
2026/9/13 6:10:57 网站建设 项目流程

“A001这个SKU现在库存多少?”——一句话问出来,摆在WMS系统里的AI Agent面前,就变成了一个“准确性”问题,而不是“语义理解”问题。前几讲我们把Agent的骨架搭好、提示词模板也调顺了,团队已经开始把业务问题往Agent上堆。结果马上撞到一个让人头大的事实:大模型根本没有摸过我数据库里的任何一张表。你跟它聊业务流程,它能给你说出一套很完整的SOP;你问它某个SKU的实时库存,它只会回你“根据相关资料,目前库存约在几百件左右”。这个“约”字一出来,仓储负责人的脸色基本就变了。

WMS不是知识问答系统,库存数量、单据状态、货位占用这些都是强事实数据。事实数据不能靠“推测”,只能靠访问。这一讲的核心任务,就是给Agent装上一套真正能触达数据库的“手”,让大模型以工具调用的方式,安全、精准地读写那15张核心业务表。我按项目里的习惯做了一个很有仪式感的总结:15张表确定数据边界,19个AI工具确定能力边界,两者对齐,Agent才算真正开始“上岗”。

1. 为什么前几讲做完,Agent还是“够不着”库里数据

1.1 我在前三讲解决了什么,还剩下什么

这个系列走到第4讲,前面的铺垫不能再忽略。第1讲我们把Agent的工程骨架搭起来,选型、项目结构、模型接入,目的是让Agent能跑起来;第2讲我们把WMS领域的业务提示词、角色设定和常用术语灌进去,目的是让模型说话像个懂仓储的人;第3讲我们开始做任务拆解和流程编排,让Agent知道一个复杂的查询应该分几步去回答。

但你回头看看,这三步本质上都发生在“模型推理”这一侧。模型确实是变专业了,它会说“入库单”“波次”“上架”这些词了,但它的所有知识来源,仍然只是训练语料和我塞进去的那几段上下文。WMS里的数据是每秒钟都在变的:一个盘点单刚审核完,库存数字就变了;一个拣货任务完成,库存流水立刻要记账。这些东西不存在于任何一本训练资料里,只存在于数据库里。

所以必须承认一个边界:推理层的优化解决的是“表达得像不像”,存储层的打通解决的是“答得准不准”。第4讲要做的,就是把这个断层补上。这也是为什么我把这讲起名叫“让大模型真正摸到数据库”——它得先摸到,才能谈得上准不准。

1.2 RAG和向量检索为什么救不了库存查询

可能会有人问:那我不接数据库,我用RAG把库存数据灌到向量库里行不行?我在项目早期真的试过这个方案,把WMS的库存表定时同步成一个文本快照,切块、向量化、存进向量数据库,然后让Agent去检索。结论是:演示的时候挺好看,真用起来非常不靠谱。

原因说穿了也简单。库存数据的查询条件是精确过滤:SKU编码要完全匹配、仓库要按编码过滤、货位要按库区维度聚合。向量数据库擅长的是语义相似度匹配,它会把“SKU A001”和“SKU A002”看作相近的东西返回给你。但对于库存查询来说,相近的东西毫无意义,我要的就是那一个SKU,差一个字符都不行。而且库存是强时效数据,每分钟都在变,向量库同步的延迟哪怕只有几分钟,都可能在仓管员问“这批货能不能发”的时候给出一个过期的数字。

所以RAG在我这个场景里只适合做一件事:知识问答,比如“退货流程怎么走”“盘点差异怎么处理”这类SOP问题。一旦问题落到具体数字上,必须放弃向量检索,直接走数据库实时查询。这两条路线在WMS Agent里是并行的,不是替代关系。

1.3 正确姿势:工具函数包住SQL,而不是让模型裸写SQL

想让大模型摸数据库,最粗暴的思路是Text2SQL:让模型自己生成SQL,然后执行。我在项目初期也动过这个念头,但很快打消了,后面第5节我会专门展开原因。这里先给一个结论性的方向:我们采用的方法是把SQL封装进预设的工具函数里,大模型只负责传参数,不负责写SQL。

打个比方,这就好比一个访客进你的仓库,你可以给他一张全局门禁卡让他自己去开所有的门,也可以安排一个库管员跟着他,他只需要告诉库管员“我要到A区拿一份货单”,具体开哪扇门、走哪条通道由库管员判断。我选的一定是后者。预设工具相当于库管员,模型只管表达意图、传递参数,具体落在哪张表上、拼什么SQL,完全由工具的逻辑决定。

这个架构有几个非常实际的好处:一是权限可控,工具只读的读、该写的走审批;二是输出稳定,每个工具返回什么样的结构在代码里写死了,不会因为模型换参数名而乱掉;三是便于审计,每次工具调用都会留下日志,谁在什么时间查了什么数据一目了然。

2. WMS里的15张核心表:Agent的认知地图

2.1 主数据四张表:仓库、库区、货位、商品

设计工具之前,先把WMS的数据地图铺开。一个中大型WMS的库表可能有上百张,但真正和Agent日常问答高度相关的,我认为可以收敛到15张表。第一组是四张主数据表,它们是所有业务单据的基础维度。

  • wms_warehouse(仓库表):记录仓库编码、仓库名称、地址、状态。多仓场景下,几乎所有库存查询都要关联这张表确认仓库维度。
  • wms_storage_area(库区表):一条仓库下分成多个库区,按业务类型分为收货区、存储区、拣货区、退货区等。库区表的关键字段是area_type,它决定了这个区域是做什么用的。
  • wms_storage_location(货位表):货位是物理库存的最小位置维度,字段包含库区ID、巷道、排、层、货位类型,以及是否冻结。货位编码一般遵循“区-库-排-层-位”的统一规则,比如A010201代表A区1库2排0层1位。
  • wms_sku(商品主数据表):包含SKU编码、SKU名称、条码、单位、规格、品牌、安全库存、默认货位。这张表是库存和单据关联商品维度时绕不开的核心。

这四张表本身不产生业务变动,但它们是Agent回答“哪个仓”“哪个区”“哪个货位”“哪个商品”这类基础定位问题的底表。我在给Agent写工具说明时,会把这张表直接作为“空间坐标系”来描述,让模型知道货位和库区是从属关系,SKU是商品维度,不要搞混。

2.2 库存事实层:批次、余额、流水

第二组是库存事实的三张表,它们是我认为整个WMS数据模型里最值得花时间理解的部分。

  • wms_batch(批次表):记录SKU所属的批次号、生产日期、效期、入库日期、质检状态。加了批次维度之后,库存才能精确到“哪一批货还有多少”。
  • wms_inventory(库存余额表):按SKU、仓库、货位、批次维护当前库存余额。字段里最关键的一组是四个数量:总在库数、冻结数、占用数、可用数。后面写工具定义时,这四个字段的含义我会原封不动地写进描述里,因为模型对“可用”和“在库”的区分经常出问题。
  • wms_inventory_flow(库存流水表):每次库存变动都会记一条流水,包括变动类型、变动前数量、变动后数量、关联单号、操作人、时间。有这张表在,Agent才能回答“这个SKU最近7天出库了多少”“这批货是什么时候入库的”这类历史追溯问题。

这三张表的基本关系是:wms_batch提供批次标签,wms_inventory是某个时间点的余额快照,wms_inventory_flow是变动轨迹。余额是结果,流水是原因。Agent分析库存异常时,我通常引导它先用余额表定位现状,再用流水表回溯原因,这是一个很高效的排查路径。

2.3 入库链路三张表:入库单、入库明细、上架任务

从这一组开始,就进入业务流程表了。入库链路的三张表是物流从“收货”到“可售”之间的核心凭证。

  • wms_inbound_order(入库单表):单据头,记录入库单号、供应商、仓库、预期到货时间、收货完成时间、整体状态。
  • wms_inbound_order_detail(入库单明细表):明细行,记录每个SKU的预期收货数量、实际收货数量、已上架数量、目标货位等。一张入库单包含多个明细行。
  • wms_putaway_task(上架任务表):记录从收货暂存区到存储货位的上架执行任务,包含来源货位、目标货位、SKU、数量、任务状态和执行人。

这三张表之间的关系是:入库单头 + 明细描述“我要收什么”,上架任务描述“收到之后放到哪里”。Agent在回答“采购订单PO-1001的货现在收到哪一步了”时,需要一次性关联这三张表才能给出完整答案:入库单是不是已收货、明细里实际收了多少、上架任务还剩余多少没执行。

2.4 出库链路三张表:出库单、出库明细、拣货任务

出库侧的逻辑和入库侧对称,但我个人觉得实际使用中出库的查询频率比入库高得多。

  • wms_outbound_order(出库单表):记录出库单号、客户、优先级、计划发货时间、拣货完成时间、发货时间、整体状态。
  • wms_outbound_order_detail(出库单明细表):明细行,记录每个SKU的需求数量、已分配数量、已拣货数量、波次号、状态。
  • wms_picking_task(拣货任务表):记录拣货的执行维度,包括来源货位、目标集货位、SKU、拣货数量、任务状态。

出库侧有一个独特的维度:波次。波次是把多个出库单按一定策略打包到一起集中拣货的编排单位。所以Agent回答“今天上午生成的波次执行到哪了”时,实际是在查wms_outbound_order_detail.wave_no关联到wms_picking_task的状态。这是出库链路查询里最重要的一个关联模式。

2.5 异常与调整两张表:盘点单、库内调拨单

最后补上两张“保底表”,这类表平时不问,但一旦仓库里出了账实不符或者库内调整,它们就是排查的入口。

  • wms_stocktake_order(盘点单表):记录盘点任务的账存数量、实盘数量、差异数量、盘点状态、复核人。Agent在查“这个月盘亏最厉害的SKU是哪些”时,主要就是聚合这张表。
  • wms_stock_transfer(库内调拨/移动表):记录库内从源货位到目标货位的移动,包含SKU、批次、移动数量、状态、原因。货位调整、补货移动、库内整理都会产生这类记录。

我个人在项目里的习惯是,把这两张表规划成异常响应的“终结者”:盘点和调拨处理的本质是对账和纠偏,Agent在回答差异类问题时不光要给出差异数量,还要引导用户定位差异来源。这时候wms_inventory_flow就会派上用场,形成一条完整的排查链路。

2.6 表关系速查:给后面写工具用的关联地图

为了不让后面写SQL时去现翻表结构,我把15张表之间的主要关联键整理成一个速查表,Agent工具的参数校验和SQL绑定都基于这张表设计。

起点表关联表关联键说明
wms_inventorywms_skusku_id库存指向商品主数据
wms_inventorywms_storage_locationlocation_id库存落在货位维度
wms_inventorywms_batchbatch_id库存可选关联批次
wms_storage_locationwms_storage_areaarea_id货位归属库区
wms_inbound_order_detailwms_inbound_orderinbound_order_id明细归属单据头
wms_putaway_taskwms_inbound_order_detailinbound_detail_id上架任务关联入库明细
wms_outbound_order_detailwms_outbound_orderoutbound_order_id明细归属单据头
wms_picking_taskwms_outbound_order_detailoutbound_detail_id拣货任务关联出库明细
wms_inventory_flow各种单号order_no流水通过单号回溯业务来源

这张表的价值在于:Agent工具里大部分都是多表关联查询,提前把关联键在工具层固定成参数,可以避免模型在提示词里瞎猜字段名。

3. 19个AI工具分组设计:能力边界怎么划

3.1 为什么不能一张表对应一个工具

设计工具时最容易踩的灰区是:既然有15张表,是不是做15个查询工具就够了?我的答案是远远不够。原因在于Agent接到的问题很少是单表查询,比如“A001在华东仓还有多少可用库存”这个问题,至少需要同时关联wms_sku、wms_inventory、wms_storage_location、wms_warehouse四张表。如果一张表一个工具,模型就得连续调用四个工具自己做关联,既慢又容易把语义搞错。

所以我设计工具的原则是:按业务问题聚合,不按单表拆分。一个工具对应一个高频业务场景,工具内部去处理复杂的表关联。项目最终收敛出19个工具,分成四组:库存查询类8个、单据任务类5个、经营分析类4个、运营动作类2个。下面分别展开。

3.2 库存查询类:8个只读工具撑起“实时看货”能力

库存查询是Agent最核心的看家本领,我把它拆成8个工具,每个工具解决一类明确的库存问题:

  1. query_sku_basic:按SKU编码查询商品主数据,返回品名、规格、单位、安全库存、状态。
  2. query_stock_onhand:按SKU汇总查询多仓库/多货位的实时在库数量,返回总在库、冻结数、占用数、可用数。
  3. query_stock_by_location:按货位编码查询该货位上的库存明细,适合“某个位置现在码了什么货”这类问题。
  4. query_stock_by_batch:按批次号查询某批次的库存分布,适合效期管理和批次追溯。
  5. query_available_stock:计算指定SKU在指定仓库的可用库存,内部逻辑是“在库-冻结-已分配”,供订单承诺使用。
  6. query_expiry_alert:按指定天数范围查询即将过期或已过期的批次列表。
  7. query_low_stock:按安全库存阈值扫描低于安全库存的SKU清单。
  8. query_inventory_flow:按SKU、时间范围、变动类型查询库存流水,用于变动追溯。

这8个工具覆盖了日常“库存还有多少”“货在哪”“什么时候过期”“哪些快断货”这几大高频问题。写工具描述时我会刻意强调字段口径,比如query_stock_onhand的输出中“可用数 = 在库数 - 冻结数 - 占用数”,避免Agent把数据传回给用户时把口径说错。

3.3 单据任务类:5个工具让Agent能“盯住业务流程”

库存是结果,单据是过程。仓储管理员很多时候问的不是“还剩多少”,而是“那一单现在卡在哪一步”。这组工具解决的就是跟踪问题。

  1. query_inbound_progress:输入入库单号,返回入库单头状态、各明细的实际收货数量和已上架数量,判断到底卡在收货还是上架。
  2. query_outbound_progress:输入出库单号,返回单据状态、波次号、拣货进度、是否已发货。
  3. query_putaway_task:按状态、库区查询待上架、上架中、已完成的上架任务列表。
  4. query_picking_task:按波次号或状态查询拣货任务进度,返回已完成数量与总数量。
  5. query_stocktake_diff:按盘点单号或时间范围查询盘点差异明细,按差异数量倒序排列。

这一组工具对状态字段的表达要求很高。我在工具描述里会明确给出WMS的状态枚举,比如入库单的状态码有“草稿/部分收货/已收货/已上架/关闭”,这样模型根据用户语气匹配状态词时才不容易错。

3.4 经营分析类:4个工具让Agent从“查数”走向“分析”

Agent如果只能查数,本质上就是个语音版的报表工具。要让它有“参谋”的样子,就得加一点分析型工具。这一组工具在SQL层面基本都走聚合查询,不是简单地把记录列出来。

  1. analyze_inventory_turnover:按SKU或分类计算指定时间范围的库存周转率,输出周转天数,用来判断哪些货卖得慢、资金压得重。
  2. analyze_slow_moving:按时间阈值扫描滞销/呆滞SKU,输出库存金额、最后出库时间、建议处理方式。
  3. analyze_location_utilization:按库区维度统计货位占用率,支持定位空置率高或者过载的库区。
  4. analyze_workload:统计指定日期的入库单量、出库单量、拣货任务量、完成率,输出库内作业负荷概览。

这四个工具在实现上有更强的SQL聚合能力。底层SQL基本都带GROUP BY、SUM、AVG这类操作。我曾经踩过一个坑:分析类工具的入参如果不固定“时间范围”,模型经常漏传时间导致全量扫描。所以这组工具的时间参数在工具层做了必填约束,缺了就直接报错提示,逼着模型向用户追问时间条件。

3.5 运营动作类:2个有限写入工具,权限必须“软写”

讲到这里,很多人会问:有没有写操作?WMS的写操作风险极高,直接让模型执行update库存表这种事,我在生产环境是绝对不碰的。所有写操作都采用“软写”模式,也就是生成一张待审核的业务单,由仓管员在WMS管理端审批后才真正生效。

  1. create_stock_adjustment:按SKU、货位、调整数量、原因创建库存调整单。正数代表盘盈入库,负数代表盘亏出库。这个工具不直接改库存,只插入一条待审批的调整单记录。
  2. freeze_unfreeze_stock:按库存ID或SKU+仓库维度发起冻结/解冻申请。同样走审批流,审批通过后才真正修改冻结状态。

让模型发起写操作时,我在工具逻辑里加了三个防线:第一,数量绝对值不能超过设定阈值;第二,原因字段必填并且要做关键词合理性校验;第三,所有写操作都落入操作日志表,即使最终没有审批通过,整个过程也能追踪。写操作宁可慢,不可错,这是WMS Agent和普通聊天机器人最大的不同。

4. 工具注册与SQL绑定的实现细节

4.1 一份规范的Function Schema长什么样

工具设计是脑力活,落地写代码时最常用的就是Function Calling这套标准。我拿query_stock_onhand举个例子,看一下在代码里注册的时候,这个工具的定义应该怎么写。

{ "type": "function", "function": { "name": "query_stock_onhand", "description": "按SKU编码查询指定仓库中的实时库存汇总,返回总在库数、冻结数、占用数、可用数。可用数=在库数-冻结数-占用数。不传仓库编码时默认查询所有仓库。", "parameters": { "type": "object", "properties": { "sku_code": { "type": "string", "description": "商品SKU编码,精确匹配,如A001" }, "warehouse_code": { "type": "string", "description": "仓库编码,可选,如WH001" } }, "required": ["sku_code"] } } }

这里有两个我特别强调的点:description里把字段计算口径写清楚,是提升模型判断准确率的性价比最高的一步;必填参数只有sku_code,warehouse_code是可选,因为用户可能就想看全仓的库存,少一个参数模型也能完成任务。

4.2 Python工具函数:SQL绑定与参数校验

Schema是给模型看的,真正干活的还是背面的Python函数。我习惯把每个工具写成一个函数,函数内部做参数校验、SQL拼接、结果格式化三层逻辑。

def query_stock_onhand(sku_code: str, warehouse_code: str = None) -> str: """ 查询SKU实时库存汇总。 参数校验、SQL聚合、结果格式化。 """ # 第一层:参数校验 if not sku_code or len(sku_code) > 50: return json.dumps({"error": "sku_code不能为空且长度不能超过50"}, ensure_ascii=False) params = {"sku_code": sku_code} sql = """ SELECT w.warehouse_code, w.warehouse_name, SUM(inv.qty_onhand) AS qty_onhand, SUM(inv.qty_frozen) AS qty_frozen, SUM(inv.qty_locked) AS qty_locked, SUM(inv.qty_available) AS qty_available FROM wms_inventory inv JOIN wms_sku s ON inv.sku_id = s.id AND s.sku_code = %(sku_code)s JOIN wms_warehouse w ON inv.warehouse_id = w.id WHERE inv.qty_onhand != 0 """ if warehouse_code: sql += " AND w.warehouse_code = %(warehouse_code)s" params["warehouse_code"] = warehouse_code sql += " GROUP BY w.warehouse_code, w.warehouse_name ORDER BY qty_onhand DESC" rows = db_query(sql, params) if not rows: return json.dumps({"message": f"未查询到SKU {sku_code} 的库存记录"}, ensure_ascii=False) return json.dumps(rows, ensure_ascii=False, default=str)

这段代码展示的是最常用的聚合查询模式。要注意的地方是:SQL里全部用参数绑定,不拼字符串,这是在数据库层面防注入的关键;结果统一转成JSON字符串返回给模型,模型拿到结构化数据后再用自己的语言组织成回答;查询结果为空时也不要返回空列表,而是给一段明确的中文说明,这样模型不会顺着空列表编造出“该SKU已售罄”的结论。

4.3 多工具连续调用:Agent处理复合问题的完整链路

单个工具好写,真正体现Agent能力的地方在于多步调用。用户问“A001现在还有多少可用库存?最近7天出库了多少?”这个问题,就需要连续调用两个工具:query_stock_onhand和query_inventory_flow。

流程会是这样展开:

第一步,Agent拿到用户问题后,根据工具描述判断需要查库存和流水;第二步,先调用query_stock_onhand,获得当前库存汇总;第三步,再调用query_inventory_flow,传入SKU编码、变动类型为“出库”、时间范围是最近7天;第四步,把两个工具的结果拼在一起组织回答:

A001当前总在库1280件,其中冻结50件、已分配120件、可用1110件。最近7天累计出库320件。

整个链路的编排由Agent自己完成,但每一步都落在固定工具上,所以输出质量是可控的。对于复杂一点的场景,比如“把低于安全库存且最近两周没有补货的SKU列出来”,工具设计上其实可以专门做一个组合工具,把两个判断一次性做完,减少模型来回调用的次数。

4.4 让Agent的答案带上“数据出处”

这个细节是我在实际使用后补的一个功能,但我觉得价值被严重低估。默认情况下,Agent只会给用户一个数字答案,用户很难判断这个数字到底是查出来的还是模型编的。我在工具返回结果里额外附加了一个字段,记录SQL执行的数据库服务器时间、数据来源表名列表、查询耗时。

Agent在组织最终回答时,会自然带出一句:数据来源为库存汇总表和库存流水表,查询时间14:32:07。别小看这行字,它既是对用户的交代,也是对模型幻觉的一种隐性约束。当模型明确知道自己是在陈述一次真实查询结果时,它编造信息的概率会明显降低。这也是企业内部用户建立对AI Agent信任感的起点。

5. 上线前我踩过的坑和补救方案

5.1 让人心惊肉跳的Text2SQL诱惑

我不止一次在产品讨论会上听到“既然大模型这么强,直接让它写SQL多省事”的说法。从Demo演示的角度看,Text2SQL确实很惊艳,但放到生产环境会发现几个非常现实的问题。

模型会根据自己的训练知识去猜表名字段名,哪怕是给足了表结构,它也可能把wms_stock_transfer写成wms_transfer_order。对了还好,错了你根本不知道它下一次会猜出什么来。同时SQL执行超时没有兜底,一个没带时间过滤条件的聚合查询,直接在全表几百万条流水上跑一遍,能把数据库连接池打满,影响生产线上的正常业务。还有一个问题是审计困难:模型生成的SQL每次都不一样,出了数据问题几乎没办法回溯责任。

我把Text2SQL只保留在一个受限的私有场景里用:给数据分析师提供一个只读库的临时查询入口,并且强制开启查询超时和只读账号。面向业务用户的Agent,绝对采用预设工具方案。工具预设意味着SQL是Review过的、索引是提前看过的、执行计划是可控的,这是生产环境最稳妥的路。

5.2 SKU、单位和多仓库:三处最容易翻车的细节

工具都写好之后,测试阶段最先暴露出来的问题不是技术框架,而是一些业务上的“老资历才能踩到的坑”。

第一个坑是SKU主数据有重复编码的历史问题。系统早期导入数据不规范,同一个商品可能对应两个SKU编码,一个在用、一个废弃。工具在查询前不能只按sku_code精确匹配,我加了一层主数据状态过滤,默认只查状态为“启用”的SKU。

第二个坑是单位混乱。WMS里有些商品按件存,有些按箱存,查询结果如果只给一个数量,用户根本不知道是件还是箱。我在工具的输出格式里强制要求带上单位字段,同时描述里提示模型“如果用户没说明按什么单位查询,优先返回基础计量单位,并注明单位”。

第三个坑是多仓库维度。默认情况下模型非常容易忽略“哪个仓”这个条件,导致把所有仓的库存加在一起回复用户。我在query_stock_onhand的描述里写了“不传仓库编码时默认查询所有仓库”,但这还不够,实际更稳妥的做法是在大多数库存工具里把warehouse_code设为必填,宁可让模型多追问用户一句,也不能让它答一个不存在的“全仓总数”。

5.3 写操作必须软写,并且要有三层保险

关于写操作我在3.5节提过软写模式,这里再展开说一下实现层的保险设计。第一层是数量校验,create_stock_adjustment工具里,调整数量绝对值超过500直接拒绝执行;第二层是原因校验,调整原因必须是预设关键词,比如“盘点差异”“损坏报废”“补录差异”,如果模型传了一个“随便改一下”这种无意义原因,系统直接返回错误,让模型要求用户给出明确理由;第三层是权限校验,调用写操作工具前,会检查当前登录用户的角色,只有仓管员角色允许创建调整单,普通访客角色只能走只读工具。

这三层保险看着麻烦,但它们保证了Agent即使被诱导、被注入,也不会出现“一句话把库存改没了”的事故。WMS对写操作的容忍度极低,宁可让用户多做一步审批,也不能让一个模型请求直接动底层数据。

5.4 响应速度优化:数据库返回快不代表Agent快

上线初期,我们收到的第一条负面反馈是“太慢了”。查一次库存,用户在界面上转了七八秒才出结果。拆开耗时发现,数据库查询本身只要80毫秒,前后端网络耗时也不大,大头都耗在了模型推理上:模型要理解问题、分析该调哪个工具、生成参数JSON、等待工具返回后再生成回答。两步推理加在一起,四五秒很正常,七八秒也能遇到。

我做了两个方向的优化。一是把高频问题尽量设计成单工具查询,避免模型绕两三个来回;二是给工具开启流式输出,先把工具执行状态“正在查询库存数据”返回给前端,用户至少知道系统在工作,心理上会觉得快很多。另外我在数据库层为wms_inventory、wms_inventory_flow这些高频查询表加了组合索引(sku_id + warehouse_id + status),把底层SQL响应控制在100毫秒内,给模型推理留出足够的时间预算。

5.5 权限与审计:给数据库侧和工具侧各装一道闸

最后一遍安全收尾。数据库侧,我给Agent专用的数据库账号设置为只读,账号只能执行SELECT,所有写操作走应用层API,数据库账号层面断绝了update/delete的可能。工具侧,每次调用都记录完整的入参、出参、用户ID、时间戳,存进独立的agent_audit_log表。这些日志平时没有人看,但出现数据争议时,它就是排查的重要证据。

审计日志的字段我建议至少包含这八个:工具名、入参JSON、出参摘要、用户ID、会话ID、仓库编码、耗时、创建时间。有了这份日志,才能回答“刚才是哪个用户让Agent查了什么数据、Agent返回了什么结果”这个最基本的追溯问题。

6. 从“摸到”到“用好”:后续演进的经验与建议

15张表、19个工具全部上线后,Agent才算真正开始接触业务。我自己后续的使用体会是,工具数量不要急着膨胀,先把现有19个工具的命中率和准确率跑稳。每次用户问了一个现有工具答不了的问题,我会先判断这个问题是不是高频,高频才增加工具,低频就直接告诉用户不支持。

另外我建议每个工具都要有一个版本概念。工具改了SQL、改了输出字段,都会影响Agent在模型侧的判断,升级工具的时最好同步把工具描述也更新,并且跑一遍对应的回归测试。LLM应用的测试不像传统软件那么容易自动化,我的做法是维护了一份“50个高频问题+正确答案”的黄金回归集,每次工具升级后把这50个问题全部跑一遍,快速发现模型是否因为工具描述或参数结构的变化而答错。

接下来这个项目我已经在规划两个方向的延展:一是把经营分析类工具往预测方向走,比如基于历史出库流水的安全库存动态建议、补货预测;二是把多个工具组合成更上层的“技能”,比如“库位利用率分析”和“波次任务进度”组合成一个“仓内运营健康度”技能,让Agent从回答单个问题进化到主动汇报仓内整体运行状态。

这一讲的内容说到底,核心只有一句话:让大模型摸到数据库,靠的不是把SQL能力交给模型,而是把数据能力和业务规则提前封装成工具,让模型在安全边界内精准调用。做到这一步,Agent才会真正开始成为仓管团队里的一个“数字同事”,而不只是一个会聊天的机器人。

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

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

立即咨询