十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

闲鱼自动发货系统:大模型+意图识别实现无人值守订单处理

闲鱼自动发货系统:大模型+意图识别实现无人值守订单处理 做闲鱼的朋友应该都有过这种体验同一个问题回答了几百遍还是有人问半夜一两点弹出订单人不在电脑前客户等不了转身就退款卡密发出去之后要手动查回收状态一单两单还行单量一上来真的分身乏术。我一直觉得闲鱼卖货最耗人的不是“卖”而是“守”——守着消息、守着订单、守着发货一天24小时根本不够用。XianYuAutoDeliveryX 就是冲着这个痛点去的。它是一个基于闲鱼消息接口与大语言模型LLM的智能自动发货系统能自动监听买家消息、识别买家意图、生成个性化回复并在确认订单后自动完成发货全程不需要人工守着电脑。这篇文章我会从整体设计思路、关键模块拆解、实操落地过程、常见问题排查四个维度展开把我开发这套系统时踩过的坑和沉淀下来的方法完整写出来。如果你正在做闲鱼自动发货、想用大模型处理客服消息、或者只是对“大模型平台自动化”的组合感兴趣这篇文章应该能给你一份可以直接参考的实战方案。1. 内容整体设计与思路拆解1.1 卖家真正的痛点是什么先说业务侧。我把闲鱼卖家的日常重复劳动拆开来看其实就那么几块回复重复咨询、确认拍下状态、发送卡密或网盘链接、处理简单的售后问题比如补发、换货、使用教程询问。这些操作的共同特点是流程固定、判断简单、但频率高且时间不固定。尤其是虚拟商品卖家卡密、会员、资料包、素材等发货动作本身完全不依赖物流是最适合自动化的品类但恰恰又是咨询量最密集的品类。传统做法有两条路一是纯人工费时费力还容易漏单二是用按键精灵之类的半自动脚本但只能“死板地点按钮”一旦买家换个问法脚本立刻抓瞎。再就是市面上有一些第三方工具但又存在账号安全风险、功能不够贴合自身业务的问题。所以自己做一套针对闲鱼场景的自动化系统本质上不是炫技而是把三个高频需求合并解决消息不漏回、订单不漏发、售后能兜底。1.2 为什么选择“消息接口 大模型”这套组合解决自动回复的问题绕不开一个关键点买家的话术千变万化。“在吗”“还有吗”“怎么买”“能便宜点吗”“发下链接”……这些说法看着简单但靠关键词匹配来做很容易翻车。比如买家问“你这个支持苹果手机用吗”关键词配置成“苹果”的话带货广告也能被误触发。所以这里需要大模型来做意图识别和语义理解而不是简单做规则引擎。大模型在系统里的角色不是“聊天机器人”而是“业务判断引擎”。它的输入是买家消息和上下文输出是结构化指令——比如“这个买家在询问价格请按话术模板回复”“这个买家已经拍下请从库存池取一个卡密并发送”。我把模型从“生成话术”这件事里解放出来让它只做分类、判断和参数提取回复话术由我们预设的模板来保证准确性和风格统一。这样既利用了模型的理解能力又避免了模型“自由发挥”导致乱承诺、乱报价的问题。方案选型上我没有一上来就追求“全自动无人值守”而是采用了半监督架构常规消息自动处理、异常情况自动转人工标记管理员每天只需花十几分钟过一遍异常列表。这么做的好处是系统上线初期不失控模型出错了也有兜底。1.3 系统整体架构整套系统的架构可以用简单的一句话概括消息驱动、模型判断、异步执行、人工兜底。消息接入层负责从闲鱼侧拉取会话消息和订单状态变更做增量同步避免重复处理。智能决策层大模型对消息进行意图分类提取订单号、商品ID、用户备注等关键参数输出结构化结果。指令执行层根据决策结果执行自动回复、发货、补发等操作所有指令都有幂等保护和操作日志。管理展示层一个简单的Web面板展示消息流、处理记录、库存余量、异常告警支持人工一键介入。数据流是这样的轮询模块每N秒拉取新消息 → 消息进入去重队列 → 调用大模型API进行意图识别 → 模型返回JSON结果 → 执行模块根据意图调用发货/回复指令 → 结果写回数据库并推送到管理端。整个过程所有请求都有trace_id串联方便出了问题按链路排查。这套架构的核心价值在于把大模型的不确定性控制在一个非常小的范围内模型只做“理解”这件事所有“执行”动作都是确定性代码并且任何一步失败都会有补偿机制。这是我认为做自动化系统最稳妥的设计方式。2. 核心细节解析与实操要点2.1 闲鱼消息接入登录态与消息轮询闲鱼目前并没有面向个人开发者开放的官方API所以系统底层实际采用的方式是模拟客户端请求。开发时需要先完成登录态的获取这一点是整套系统是否稳定的命门。我在项目里用的是扫码登录 Cookie持久化的方案首次启动生成二维码用户扫码后系统保存登录凭证到本地数据库后续请求自动携带。但闲鱼的登录态是会过期的尤其是在频繁请求或网络环境变化的情况下因此必须做好两件事一是定期检测登录态有效性比如每隔几分钟调一次轻量接口确认未失效二是失效时的告警和重新登录流程至少要能推送通知到手机上避免系统“静默死亡”。消息轮询的频率也很有讲究。太频繁容易触发平台风控太慢又影响回复时效。我最终选择的是每8~15秒随机间隔轮询一次的方案同时对拉取到的消息做增量去重每条消息根据会话ID和时间戳生成唯一指纹重复消息直接丢弃避免重复处理后把同一张卡密发给买家两次——这个问题在实际开发中一旦出现是相当尴尬的。另外要提一下订单状态同步。自动发货的前提是“已付款”所以系统不能只盯着消息还要定期拉取进行中订单的状态变更。我的做法是维护一个订单状态表每次轮询对比状态字段只有发生“待发货 → 已付款”这种跳变时才触发发货指令。通过状态机来做而不是简单判断消息内容能大大降低误发风险。2.2 大模型选型与部署方式大模型的选择上我一开始考虑的是两个方向云端API还是本地部署。云端API的优势是省心、速度快不需要自己维护推理环境缺点是成本和数据隐私的顾虑。本地部署的好处是消息数据不出机器、调用费用低、可定制性高但需要一台配置过得去的电脑。结合热搜词里大家经常讨论的“16G显存32G内存能本地部署什么模型”这类问题我实测下来的结论是16G显存跑 7B~14B 参数量的量化模型是可行的做意图识别和短文本分类完全够用。我最终采用的是“本地优先、API兜底”的混合方案。日常消息量不大本地部署一个Qwen系列的中小尺寸量化模型比如Qwen2.5-7B-Instruct的4bit量化版用Ollama或vLLM来做推理服务单条消息处理耗时控制在2秒以内。如果本地模型短时间内出现异常比如模型服务崩溃或推理超时自动切换到一个云端API备用通道保证系统不中断。这种双通道设计我在实际生产中验证了大半年稳定性非常有保障。部署时有几个参数值得留意。推理时的temperature建议调低我习惯设置到0.1~0.3减少随机性让输出更稳定。上下文长度不需要太长因为单个意图判断的输入通常只有几百个字所以max_tokens给到256就足够。还有一个容易被忽视的点是并发处理如果消息量大建议在模型服务前面加一层请求队列避免瞬时并发把推理服务压垮。用vLLM部署时可以通过--max-num-seqs参数限制并发序列数配合队列消费整体吞吐会更平滑。2.3 提示词模板的设计与踩坑提示词是这个系统里最值得花时间打磨的部分。我第一次写提示词时只是简单地让模型“判断买家意图并回复”结果模型经常输出一些营销味十足的客套话甚至回复中出现“尊敬的顾客”“祝您购物愉快”这种和闲鱼风格完全不符的表达一眼就能看出是机器人。后来我把提示词改成了完全不同的思路不再让模型“扮演客服”而是让它做“意图分类器”。我定义了一套固定的JSON输出协议模型只输出意图类型和关键参数不直接输出回复内容。比如{ intent: ask_price, params: {}, confidence: 0.95 }意图类型覆盖了询价、订单确认、发货催促、售后补发、闲聊、广告拦截、待人工处理等近20个分类。每个分类对应到预置的回复模板模板里可以带动态参数比如当前库存量、商品名称、发货说明由代码在生成回复时填充。这样既保证了回复的专业性和一致性也让系统行为完全可预期。提示词本身我写成了一个独立文本文件方便随时调整。结构上分三块角色设定你是谁、任务描述你要做什么、输出协议输出格式和示例。另外非常重要的一点是要在提示词里明确告诉模型“不确定时返回unknown意图宁可不处理也不要瞎判断”。这个约束能大幅降低误回复的概率。模型判断的置信度低于阈值时系统会自动把消息标记为“需人工介入”而不是强行回复。2.4 自动发货逻辑实现自动发货看似简单但其实有很多细节要注意。首先是库存管理卡密不是无限的所以系统必须维护一个库存池发货时按序取用取走后立刻标记为“已分配待发送”。为了保证不超卖取用操作必须加锁我用的方案是把取卡密和更新状态放在同一个数据库事务里状态更新失败就回滚。第二个是发送失败的处理如果发送消息时网络超时卡密已经出池了这时候如果没有补偿机制就会造成卡密丢失。我的方案是增加一个“待发送任务表”只有收到发送成功的确认后才把任务状态置为完成否则定时重试。还有一个非常容易忽略的问题是重复发货。买家的消息和订单状态是不同步的有可能消息模块和订单模块同时触发了发货逻辑。所以我在发货指令上加了业务幂等键——订单ID 商品SKU。执行前先查询是否已有同幂等键的成功记录有就直接返回已发货的信息不再生成新的卡密分配。自动回复的内容上也有讲究。闲鱼买家普遍不喜欢“太正式”的客服腔我预置的模板都是偏口语化的表达。比如发货后回复“亲已自动发货卡密在下方复制后使用。如果是苹果设备充值请先关闭自动续费再操作。有问题随时呼我。”这样的文案既提供了必要信息又降低了买家对“机器人”的警惕感。3. 实操过程与核心环节实现3.1 环境准备与依赖清单开发语言我选了Python理由很直接生态丰富无论是处理协议请求、数据库操作还是调用大模型SDK都非常顺手。基础环境是Python 3.10数据库用的SQLite起步——因为单店场景数据量完全够用零运维成本如果后续要做多店铺或大数据量分析切换PostgreSQL也是平滑的。消息队列我没有单独引入Redis而是用Python的asyncio队列在进程内解决对当前场景来说更简洁。大模型推理服务用Ollama本地配合OpenAI兼容客户端库调用云端API这样一个接口风格就能同时适配两个通道代码不用写两套。依赖清单大致如下pip install aiohttp httpx openai pydantic sqlalchemy apscheduleraiohttp异步HTTP客户端用于轮询闲鱼消息接口和发送回复。httpx同步/异步都支持大多用于和大模型API通信。openai虽然用的是本地或第三方API但大多兼容OpenAI消息格式所以我统一用这个SDK来接。pydantic定义并校验所有结构化数据尤其用于校验大模型返回的JSON。sqlalchemyORM管理订单、消息、库存、日志等数据表。apscheduler调度器管理轮询任务、定时检查任务、重试任务。做后端开发时间长了自然知道依赖的版本锁定也很重要。我现在所有项目里都会用一个requirements.txt把版本号固定下来避免隔几个月重新部署时因为依赖升级出现莫名其妙的行为变化。3.2 消息监听与意图识别核心代码先看消息轮询这部分。核心逻辑就是复用登录态、拉取增量消息、生成指纹去重、进入待处理队列。核心代码层面我抽象了一个Client类来处理消息会话async def poll_new_messages(self): params {session_id: self.session_id, last_msg_id: self.last_msg_id} resp await self.http_client.get(/api/chat/msg/list, paramsparams) messages resp.json().get(data, []) new_msgs [] for msg in messages: fingerprint f{msg[session_id]}:{msg[msg_id]}:{msg[timestamp]} if fingerprint not in self.seen_pool: self.seen_pool.add(fingerprint) new_msgs.append(msg) return new_msgs去重池这里要注意内存占用问题运行久了seen_pool会越来越大。我的处理是结合Redis或者数据库做持久化去重只保留最近7天的消息指纹定期清理这样既保证了去重效果又不至于消耗太多存储。接下来说意图识别环节。大模型返回的JSON必须做严格校验我直接用pydantic定义了响应模型class IntentResult(BaseModel): intent: str confidence: float Field(ge0.0, le1.0) params: dict Field(default_factorydict) property def is_reliable(self) - bool: return self.confidence 0.75 and self.intent ! unknown这里有个细节模型偶尔会输出格式不合法的JSON截断、多余逗号等都是常见问题。我在模型请求里开启了JSON模式在解析失败时还会有一个轻量的“自修复”逻辑——把错误的JSON片段重新组装提示模型再次解析两次都失败才走人工兜底。这样能把大模型的不稳定因素在代码层面最大程度消化掉。调用模型的时候我的Prompt构造方法是这样的先加载系统提示词文件system_prompt.txt再把当前消息内容、前文上下文、商品基本信息从数据库中查询拼接到用户消息里。这样做的好处是同样的模型能力下模型能结合商品上下文做出更准确的判断而不是完全依赖它自己的“世界知识”。3.3 自动回复与发货编排拿到意图结果后系统会进入一个类似状态机的处理流程。每一种意图都对应一个处理节点比如ask_price → 读取商品价格用模板回复order_created → 查询订单状态提示买家拍下并付款paid_pending → 执行发货流程after_sale → 读取商品售后政策转人工或自动补发spam_ad → 忽略并标记unknown → 标记人工介入每个处理节点都是独立函数接收上下文对象返回处理结果。这样职责划分清晰后续新增场景只需要加一个处理函数和一条配置映射不用改动核心逻辑。发货编排的核心流程我放在一个Transaction里实现async def auto_delivery(order_id: str, sku_id: str): async with db.transaction(): exists await delivery_record.find_by_order_sku(order_id, sku_id) if exists: return {status: repeat, record: exists} code await card_pool.acquire(sku_id) if not code: await alert_manager.notify(f库存不足: {sku_id}) return {status: out_of_stock} record await delivery_record.create( order_idorder_id, sku_idsku_id, card_codecode ) # 事务外发送消息避免网络耗时锁住数据库 result await chat_client.send_message( session_idctx.session_id, contentf亲已自动发货卡密{code}…… ) if not result.success: await delivery_task.retry_later(record.id) return {status: delivered, record: record}这里的事务边界是重点分配卡密和创建发货记录必须在一个事务里保证不会出现卡密出了池但记录没写上的情况。发送消息放到事务外是性能考虑——如果发送接口比较慢锁着数据库事务会让其他操作排队。如果发送失败依靠重试任务在后台补偿。3.4 管理端与日志设计这套系统的日志设计可能是我觉得最重要的工程决策之一。所有关键节点都打结构化日志格式统一为JSON行至少包含timestamp、trace_id、session_id、intent、action、result、latency_ms。trace_id从消息进入系统时生成贯穿整个处理链路排查问题的时候直接拿trace_id把所有日志串起来看效率翻倍。管理端我做了个轻量的Web界面用的是FastAPI 简单的HTML模板。界面上有三个核心页面消息监控实时滚动展示进入系统的消息和处理状态、库存管理卡密池余量、导入导出、分配记录、异常队列标记为人工介入的消息支持一键复制上下文跳转到闲鱼App处理。这个管理端不求功能多但求清晰、够用毕竟系统绝大多数时间在自动运行管理端只是兜底工具。3.5 本地部署大模型的落地配置很多朋友关心本地部署的具体配置我这边目前跑模型的机器是单张16G显存的GPU加32G内存。选择的是Qwen2.5-7B-Instruct用Ollama做推理服务量化级别是用GGUF的Q4_K_M实测效果在意图分类任务是够用的。如果消息量再大一些可以换成vLLM部署吞吐更高但显存占用也会上去。启动命令参考ollama run qwen2.5:7b-instruct-q4_K_M然后用openai库去调用本地接口from openai import OpenAI client OpenAI(base_urlhttp://localhost:11434/v1, api_keyollama) resp client.chat.completions.create( modelqwen2.5:7b-instruct-q4_K_M, messages[ {role: system, content: system_prompt}, {role: user, content: user_prompt} ], temperature0.1, max_tokens256, )如果只跑CPU推理7B模型会慢不少单条消息可能要5~10秒这时候建议缩小尺寸到更小的模型比如3B甚至1.5B或者干脆用云端API。这里没有绝对正确的答案关键看你的业务量和对延迟的容忍程度。4. 常见问题与排查技巧实录4.1 登录态失效与风控处理这是我运维这个系统遇到最多的一个问题。典型表现是系统运行一段时间后突然没有新消息进来管理端日志显示请求返回401或类似的未授权状态。排查思路是先确认是单次失败还是整体失效单次失败可能是网络抖动或接口临时调整重试即可整体失效基本就是登录态过期。我后来做了一个“心跳检测 多渠道告警”的机制心跳检测每5分钟请求一次轻量级接口连续3次失败就判定失效立刻通过钉钉/微信机器人推送到手机提醒管理员重新扫码。关于风控我的原则是“克制”。轮询频率不要过激、每次请求携带的header完整模拟真实客户端、不要在同一秒内发起多笔操作。实测下来只要行为模式接近真人很少触发额外的验证。如果真的遇到滑块验证我目前的策略是先暂停自动操作告警人工处理不硬碰硬破解验证码——毕竟自动化的目的是减轻负担不是挑战平台安全策略。4.2 大模型“胡说八道”怎么治大模型幻觉的问题在聊天场景中很常见但在业务系统里是致命的。我处理这个问题有三层防线第一层是在提示词里做约束明确输出协议要求“不确定返回unknown”第二层是结构校验解析失败或置信度低于阈值的直接走人工处理不出自动回复第三层是审核兜底对所有自动生成的回复内容做敏感词和格式校验包含价格、发货、承诺等关键词的语句要有明确的规则约束不会让模型自己“创造”优惠条件。另外我还加了一个简单的“语义黑名单”比如买家消息里如果含有“投诉”“举报”“退款原因”等词自动升级为人工优先处理因为这类场景情绪因素重稍有不慎就会激化矛盾。4.3 订单状态不同步导致漏发漏发是自动发货系统最怕的故障比多发严重得多。多发顶多损失一个卡密漏发轻则买家催单重则被平台判违规。我遇到过一次比较隐蔽的情况买家付款和系统拉取订单状态之间存在时间差恰好这个时间段内系统从消息流中读到了“已付款请发货”的内容但订单查询接口返回的状态还是“待付款”于是系统没有触发发货。买家等了几小时没收到来催了才发现。这个问题最终的解决方案是加了一个状态收敛器每隔10分钟把“等待发货中”的订单全量对一遍如果在旧状态停留超过30分钟就会被标记为异常转入重查。同时消息触发的发货请求如果发现订单状态尚未就绪会记录到一个待确认队列里等订单状态更新后再执行发货而不是直接丢弃。4.4 任务堆积与并发竞态问题当消息量短时间激增时如果处理速度跟不上队列就会越来越长。我遇到过连续几条消息同时触发发货逻辑的情况如果发货模块没有做幂等控制极端情况下可能出现一张卡密发两次虽然概率极低但一旦发生就很麻烦。前面提到的业务幂等键和事务处理在这里起到了决定性作用。为了提升吞吐我用了asyncio来并发处理消息但同时也控制了最大并发数。我用一个信号量把并发数限制在8以内避免瞬时请求过多导致模型服务超载或平台风控。实践下来单个账号的场景下这个数字足够用处理延迟可以从几十秒级降到秒级。4.5 避坑清单整理我把这段时间运维过程中最有价值的一些经验整理成一份速查表方便你直接参考问题类型症状排查思路解决方案登录态失效无新消息接入日志出现401检查心跳检测告警告警推送 扫码重登大模型返回格式错误JSON解析失败查看原始返回内容开启JSON模式 二次修复重复发货买家收到多个相同卡密查发货记录表的幂等键订单IDSKU唯一约束漏发订单已付款但未发货查待确认队列和状态收敛器状态机兜底重查队列堆积消息处理延迟飙升查队列长度和模型耗时限流 拆分并发粒度库存不足发货时报无码可发查库存池余量告警 自动下架商品这套表我打印出来贴在工位上每次系统异常都会先对着过一遍能省很多排查时间。最后分享几点个人经验整个系统从最初只是一个简单的“消息转发脚本”到现在演变成一个包含消息接入、意图理解、自动发货、异常兜底的完整工具技术上最大的心得是不要把大模型当成万能的要把它嵌进一个严格受控的工程体系里。模型负责它擅长的语义理解代码负责它不擅长的精确执行两边各司其职系统才谈得上稳定。如果你接下来打算做类似的事情我的建议是先从自己最痛的那个环节入手别一上来就追求全自动化。比如你最早可以只做“消息监听 人工在面板上点发货”让轮询和消息聚合帮你省掉反复刷新手机的精力再逐步加入大模型意图识别最后才把发货动作交给自动执行。小步快跑每一层都跑稳了再继续往上盖改造成本和试错成本都会低很多。这套系统后续还能扩展的方向也有不少。比如把库存管理做成自动对账定期核对已发卡密与订单金额是否匹配再比如接入RAG用你自己的商品文档和售后政策作为知识库让模型的回复更贴合实际业务还可以做多账号并发管理不过那样的话风控和隔离策略需要再上一个台阶就不是单机脚本能cover住的了。总之思路已经趟通剩下的就看你自己的业务需
返回列表