尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

全栈AI修图Agent实战:从架构设计到部署上线

发布时间:2026/9/24 20:00:35

资讯中心
01
ARTICLE

全栈AI修图Agent实战:从架构设计到部署上线

全栈AI修图Agent实战:从架构设计到部署上线
最近手上的全栈 AI 修图 Agent 项目终于完结了。所谓完结不是代码提交完就算完事而是从需求梳理、技术选型、前后端开发到 AI 能力接入、多端适配再到部署上线整个闭环都跑通了。这几年陆陆续续做了不少全栈项目有 Vue Go 的传统前后端分离也有 uniapp 跨端应用但像这次这样把 AI 大模型的能力真正落进图片处理业务里、还做成 Agent 形态的确实是头一回。趁着项目刚收尾、踩过的坑还记得清楚我把这个项目的完整思路和落地过程整理出来给想搞全栈 AI 项目的朋友做个参考。这项目解决的痛点其实很直接传统修图软件功能强大但学习成本高普通用户想实现去掉背景里的路人老照片修复一键换背景这类需求往往要在多个工具之间来回切换。而 AI 修图 Agent 的思路是用户用自然语言描述需求Agent 自动理解意图、拆分任务、调用对应的图像处理模型最后把成品直接返回给用户。整个交互链路从人适应工具变成了工具理解人这也是我当初决定做这个项目的核心动机。这个项目适合谁参考如果你是刚接触 AI Agent 开发、想看看 Agent 真实落地长什么样或者你做全栈开发想在现有技术栈上接入 AI 图像处理能力又或者你是产品经理/独立开发者想找一个AI 垂直场景的产品化案例这篇文章应该都能给你一些启发。下面我按项目的实际推进顺序把从设计到落地的每个关键环节拆开讲。提示文中涉及具体技术实现的地方我会结合自己项目的真实做法展开但不同团队的技术栈和业务场景不一样代码和架构方案只是参考核心思路才是可以复用的部分。1. 需求拆解与整体架构设计为什么选全栈 AI Agent 形态1.1 核心需求梳理与功能定位动手写第一行代码之前我先花了大概三天时间把需求彻底理清楚。这个阶段很重要AI 项目最怕的就是一上来就堆模型选型结果做到一半发现业务根本跑不通。我梳理出的核心场景有五个背景移除与替换、老照片修复、图像去水印、智能调色美化、批量风格化处理。每个场景背后都对应不同的模型能力和不同的交互方式。比如背景替换需要先做主体分割老照片修复需要做超分和去划痕去水印需要检测修复区域。这些能力如果全做成固定按钮交互会非常死板恰好可以用自然语言统一入口——用户说什么Agent 翻译成对应操作组合。另外我明确了一个边界这个 Agent 的核心价值是理解意图 编排模型而不是自己训练图像模型。开源社区已经有足够好的基础模型我要做的重点是定义好 Agent 怎么选模型、怎么串联步骤、怎么处理模型输出的中间结果。1.2 技术选型Vue 3 Go uniapp 的组合逻辑技术选型上我最终确定的是 Vue 3 写 Web 管理端Go 写后端服务uniapp 打包 App 端和 H5 端这套组合看起来常规但背后是有明确考量的。Web 端选 Vue 3 TypeScript Vite看重的是组合式 API 对复杂交互状态的表达能力。修图场景里有大量中间状态——原图预览、处理进度、步骤撤销、模型参数调整用组合式函数能把每组状态封装得干净比 Options API 好维护得多。组件库选了 Naive UI它对 TypeScript 的支持在同级别里是数一数二的主题定制也灵活适合做工具类产品的后台界面。后端选 Go核心原因是性能和部署的平衡。图像处理是一个计算密集型的场景Go 的并发模型非常适合同时处理多路推理请求。标准库的 net/http 配合 Gin 框架撸 API 非常快编译产物是单文件部署进 Docker 也就一个镜像的事。更关键的是Go 生态里有非常成熟的图像编解码库比如 imaging、bild我做预处理缩放、裁剪、格式转换可以不入 Python 环境直接在后端完成省掉了不少跨语言通信开销。移动端选 uniapp说句实话最大的理由是效率。这个项目最终要覆盖 iOS、Android 和微信小程序三端用 uniapp 一套代码多端运行日常维护成本低很多。虽然重度图像处理不适合在端上做但作为上传原图 展示结果 支付的前端壳子uniapp 完全够用。真正繁重的推理计算全部放在服务端端上只是拿到了处理之后的图片。1.3 Agent 架构设计的核心思路接下来是最关键的部分Agent 架构怎么设计才不会让它变成一个带对话框的工具集合。我参考了业界主流 Agent 设计范式结合修图这个垂直场景做了简化。整体分成三层最底层是工具层Tool Layer每个图像处理模型封装成一个标准工具接口注册给 Agent中间层是规划层Planning Layer大模型在这里做意图识别和任务拆解把用户需求翻译成一组有序的工具调用最上层是交互层Interaction Layer负责管理多轮对话上下文把每一步工具的输入输出串起来。规划层是整个 Agent 的脑。我用的方式是给大模型一个结构化的工具描述列表每个工具包含名称、功能说明、输入参数 schema、输出格式。模型每轮要先输出一个计划告诉我它打算调用哪几个工具、按什么顺序调、每个工具的参数怎么填。我有意识地不让 Agent 一次性把所有工具调用完而是跑一步看一步比如模型先调分割工具拿到前景遮罩这个遮罩的置信度会作为下一步处理的输入参考如果分割结果不理想模型可以调整参数重新分割。这种计划 - 执行 - 观察 - 再计划的循环跟人类的修图习惯本质上是同构的先局部处理看效果觉得哪里不对再微调。Agent 不追求一次生成完美结果而是通过多轮推理逼近用户想要的成品。2. 核心功能拆解与 AI 能力接入模型封装与工具化2.1 图像基础处理管线的搭建任何 AI 图像处理都跑不脱一层基础管线读图、校验、预处理、推理、后处理、编码输出。Go 后端在这块承担了绝大部分工作。流程是这样的前端把图片以 multipart 形式上传到 Go 服务Go 先做格式和大小校验然后统一转成 RGB 三通道的标准格式再根据模型输入要求缩放到目标尺寸。这里有个细节值得讲很多开源图像模型对输入有固定尺寸要求比如 512 或 1024 的倍数但用户上传的原图五花八门直接硬缩放会严重失真。我的做法是做一个保持宽高比的居中裁剪缩放先把图缩放到短边刚好等于目标尺寸再从中心裁出目标尺寸区域。这样虽然丢了一点边缘信息但对主体内容的形变影响是最小的。边框填充的方案我也试过但填充区域会在分割类任务中产生假阳性后来就放弃了。编码输出环节我统一用 PNG 格式。因为 AI 处理后的图像可能有透明通道比如抠图转 JPEG 会导致透明区域变黑这是个非常容易踩的坑。PNG 虽然体积大一些但经过压缩配置优化后两兆以内的图上传下来体感不会有太大差别网上展示反而更稳定。2.2 模型选型与治理开源模型的应用封装图像处理能力这块我最终选用的基础模型集中在几个主流开源方案上。分割用基于 SAM 的轻量变体修复用生成式填充模型超分用 ESRGAN 系的训练权重。这里要说清楚一个概念模型跑在哪里决定整个服务的架构。我的方案是模型全部跑在独立的 GPU 推理服务里Go 后端通过 HTTP 或 gRPC 调用这个推理服务。刚开始我图省事想直接在 Go 进程里用纯 Go 跑模型结果发现完全行不通——图像模型的主流生态在 PythonONNX 运行时虽然能导出一部分但很多模型私有算子支持不到位有人还专门给算子支持不全建了个劝退帖。最后老老实实用 FastAPI PyTorch 起了一个推理服务Go 只做业务编排和中间数据中转。这套架构虽然多了一层网络调用但是解耦效果极好模型更新、A/B 测试都不会影响主服务。推理服务内部我用了一个简单的模型管理器模型懒加载到显存后保持常驻推理请求进来就排队执行。每个模型注册的时候要声明一个预估的推理耗时和最大并发数调度器根据这些参数决定是否接受请求。刚开始我图省事没有做并发控制结果几张图同时进来直接把显存打爆NVIDIA 驱动直接报错整个推理服务崩掉连带业务服务也挂了。这个教训后面细说。2.3 Agent 工具注册与调用机制工具注册表是连接 Agent 大脑和底层模型能力的桥梁。我在代码里定义了一个统一的工具接口每个图像能力都实现这个接口工具的核心字段包括工具名英文标识给模型识别用、展示名给用户看的中文名、描述自然语言描述工具能干什么、适合什么场景、输入参数 SchemaJSON Schema 格式定义参数名、类型、取值范围、执行函数真正的处理逻辑。描述这块我吃了不少亏。最开始我把工具描述写得很技术化比如执行图像语义分割返回二进制掩码大模型倒是能看懂但它根本不知道这个功能对用户有什么价值。后来我把描述改成了用户视角移除图片背景中的指定物体返回去除该物体后的新图片适合去除背景路人、杂物、电线等干扰元素模型的选用准确率立刻上了一个台阶。大模型做工具选择的依据就是工具的语义描述你描述的越贴近真实使用场景它选得越准。这个经验做 Agent 的同学可以直接抄。工具执行流程是我自己写的编排引擎核心逻辑是串行执行 手动确认。模型完成规划后引擎先渲染一个执行计划给前端展示用户确认后引擎再逐条调用工具。每调完一个工具结果会回填到上下文中模型可以基于中间结果调整后续步骤。最初我想的是全自动执行结果用户反馈完全不知道 AI 在干嘛体验很虚。加了手动确认之后虽然多了一步操作但用户对结果的信任感和掌控感明显增强了。3. 实操过程与核心环节实现从 0 到 1 的完整落地3.1 Go 后端 API 设计与图片上传链路后端服务我拆成了三个模块API 网关、Agent 编排引擎、任务队列。API 网关对外暴露 HTTP 接口走 Gin 路由编排引擎是核心业务逻辑负责对接 LLM 和工具层任务队列处理异步长耗时任务。图片上传这块前端传的原图直接走二进制流Go 后端用io.Copy写入临时文件然后生成一个 UUID 作为任务 ID。文件先落在本地磁盘后续所有处理都基于这个 ID 引用原图。为什么不用对象存储直接一步到位因为开发阶段没有现成的 OSS 可以连本地文件系统最简单后面如果接了 MinIO只需要把读写文件这层抽象换掉就行其他逻辑不用动。任务队列我用的是 Go channel worker pool 实现的内存队列。每个任务是一个结构体包含任务 ID、用户 ID、工具执行序列、当前步骤和状态。Worker 从队列取任务后按顺序执行编排引擎生成的操作序列每完成一步就把进度更新到内存状态和数据库里。客户端通过轮询接口拿进度前端显示一个实时进度条。为什么不用 RabbitMQ 这类消息队列这个项目的并发量远没有到需要消息队列撑场面的程度内存队列在单机部署下完全够用少一个中间件就少一个运维负担。等以后确实需要水平扩展了再把 channel 换成 RabbitMQ接口层封装好改动不会大。3.2 前端 Vue 3 的多状态管理与大图裁剪预览前端是用户直接接触的第一层体验做不好后端再强大也白搭。我在 Vue 3 里用 Pinia 做了三个核心 storeAuthStore 管理用户态、TaskStore 管理图片处理任务状态、AgentStore 管理 Agent 会话和步骤计划。TaskStore 是状态管理里最复杂的部分。一次修图任务会经历待上传 - 已上传 - 分析中 - 执行中 - 部分完成 - 全部完成 - 失败等多个状态为了不让每个组件都去关心任务状态机我在 TaskStore 里封装了一个状态机状态流转的合法性由 store 自己校验。组件只需要调用taskStore.updateStatus(taskId, executing)如果当前状态不允许跳转store 会直接抛错提示。这个小设计帮我拦住了不少异步回调顺序颠倒导致的 bug。图片预览这块前端有个绕不过去的问题是原图太大。有些用户手机拍的照片有十几兆如果直接塞进img标签或者 Canvas内存直接吃满移动端直接白屏。我的方案是上传前先用 Canvas 做一次压缩预览预览图的宽限定为 1600px质量压到 0.8用来做展示和交互。真正传给后端做处理的是原图处理完成后后端返回一张压缩适中的结果图给前端细节图和原图则通过 URL 提供下载。用户看到的结果图已经经过了一层压缩体感上很轻但放大看细节又不会糊。3.3 Agent 编排引擎的代码实现与工具调度编排引擎是整个项目的大脑中枢这里贴一段核心的调度伪代码帮大家理解整个流程// Agent 编排引擎核心循环 func (e *Engine) Run(ctx context.Context, req *TaskRequest) (*TaskResult, error) { // 1. 构建会话上下文 session : e.sessionManager.NewSession(req.UserID) // 2. 将用户需求发送给 LLM生成初始计划 plan : e.LLMClient.CreatePlan(ctx, session, req.UserPrompt, e.toolRegistry.GetSchema()) // 3. 展示计划给用户确认 stepConfirmed : e.ConfirmPlan(ctx, session, plan) if !stepConfirmed { return nil, ErrPlanRejected } // 4. 逐步执行计划 for i : 0; i len(plan.Steps); i { step : plan.Steps[i] // 4.1 找到步骤对应的工具 tool, ok : e.toolRegistry.Get(step.ToolName) if !ok { // 工具不存在时让 LLM 调整计划 plan e.LLMClient.AdjustPlan(ctx, session, plan, fmt.Sprintf(tool %s not found, step.ToolName)) i -1 // 重新执行完整个计划 continue } // 4.2 执行工具调用 result, err : tool.Execute(ctx, session.Images[step.SourceID], step.Args) if err ! nil { // 执行失败询问 LLM 如何处理 adjusted : e.LLMClient.RecoverPlan(ctx, session, plan, step, err.Error()) plan adjusted i -1 continue } // 4.3 把中间结果写回会话作为下一步的输入 session.Images[step.OutputID] result session.History append(session.History, result.Summary()) } // 5. 汇总最终结果 return session.Finalize(), nil }这个设计里有几个值得留意的点。首先是对工具不存在的兜底处理大模型偶尔会生成一个不存在的工具名尤其是刚改完工具描述的时候这时候不能直接报错结束而是要把错误信息反馈给 LLM让它重新调整计划我见过的大多数 Agent 框架都是这个思路。其次是错误恢复机制。工具执行失败后附带错误信息询问 LLM 怎么补救——是重试一次换参数还是换个工具。这种知错能改的能力让整个 Agent 的稳定性和智能感都上了一个档次实际使用中差不多 20% 的任务会触发一次自我修正修完之后大多数能顺利完成。最后是中间结果的回填。每个步骤的输出都会写入 session 的 Images 表里后续步骤通过 ID 引用这些中间产物整体形成一个有向的数据流。用户可以查看每张中间步骤图这在计划确认 - 分步执行的产品逻辑里非常自然。3.4 uniapp 多端适配的封装策略uniapp 做多端适配最痛苦的是平台差异。我的处理方式是把所有平台差异集中到一个小模块里业务代码不直接碰平台 API。图片上传这块Web 端可以直接用input typefile拿文件App 端需要调用 uni.chooseImage 拿临时路径小程序端的逻辑又略有不同。我封装了一个uploadImage的统一函数内部按平台分发业务层只调这个函数。预览和下载同理App 里保存图片到相册用的是 uni.saveImageToPhotosAlbumH5 端则是直接触发浏览器的下载行为。这些平台差异如果散落在业务代码里维护起来就是一场灾难我建议所有做 uniapp 项目的朋友都建立一层 OneKey 式的平台适配封装哪怕前期多花两个晚上后面省下的调试时间绝对物超所值。小程序的包体大小也是个现实问题。我们原生的图像预览组件很小但图表库和 UI 组件很容易把包撑到 2MB 上限。我的手段是按需引入组件、图片资源全部转 CDN、外部插件能不用就不用。最终小程序包控制在 1.4MB 左右虽然不算特别优秀但至少没有在包体积上卡壳。4. 模型服务、并发调度与多轮对话的工程化4.1 推理服务的模型加载与显存管理模型推理服务是性能瓶颈所在我这里单独拎出来讲。服务用 FastAPI 起PyTorch 做推理核心难点在显存管理和并发控制。模型加载我采用懒加载策略服务启动时不加载任何模型第一个推理请求进来后启动一个后台协程加载模型加载期间后续请求排队。模型加载完放入一个字典key 是模型名value 是模型实例和文件句柄。这样多个模型可以按需加载避免了全部模型常驻显存导致的开销。显存管理上我踩过一次大坑。第一次上线的时候我没有做并发限制三个分割任务同时打到同一个模型上每张图 2048x2048 分辨率一下把 8GB 显存吃满了驱动直接崩掉。后面我加了一个信号量每个模型限定最多两个并发推理超出的请求在队列里等待。做法其实很简单# 每个模型的并发信号量 semaphores { segmentation: asyncio.Semaphore(2), inpainting: asyncio.Semaphore(1), sr: asyncio.Semaphore(2), } async def run_inference(model_name, image): async with semaphores[model_name]: # 真正的推理调用 return await do_infer(model_name, image)显存占用还有一个隐形杀手是推理构图时的临时张量。给超分模型输入一张 2048x1536 的图中间过程可能产生好几个同样尺寸的中间张量每个几十 MB。为了降低峰值我做了分块推理把大图切成 512x512 的块每块独立过模型再拼接。分块会导致边缘出现接缝我处理的方式是块与块之间重叠 32 像素重叠区做一个线性的 alpha 融合拼出来的效果肉眼看不出接缝。这个技巧在处理大分辨率图像时非常实用。4.2 多轮对话上下文管理与用户意图修正Agent 的对话能力不是简单的记住聊天记录而是要维护一个被工程化的上下文结构。我的实现里每一次用户输入都会变成一条消息但消息分为三种类型用户指令、工具执行记录、系统提示。用户指令就是用户说的自然语言工具执行记录是引擎在跑完一个工具后自动追加的内容包含工具名、参数、返回结果摘要系统提示是系统生成的、用于引导模型的指令比如用户正在执行第 3 步当前图片的中间结果很满意请继续。这三类消息混合在一起在每轮调用 LLM 时拼成 prompt 发送过去。有一个上下文长度的问题工具执行记录往往很长尤其是包含 base64 图片时很容易把 token 上下文打满。我的处理策略是给工具执行记录做摘要不把整张图的 base64 放进去只放分割完成前景占比 65%检测到 2 个主体这样的文本摘要。图片数据本身放在会话的 Images 表里LLM 需要时通过查看图工具去调取而不是直接把图像塞给模型。这个设计大大降低了 token 消耗处理时长也跟着降下来了。用户在多轮交互中常常会修正意图比如背景换成蓝色不不不还是换成都市场景。这种修正意图在对话里表现为模型需要先丢弃之前的工具执行结果重新规划后续步骤。我在引擎里加了一个replace语义当用户说重新、换一个、不要了等关键词时LLM 会触发 reset 操作清空会话中与其相关的图片引用然后重新走规划流程。这个功能做出来后用户反馈能听懂人话的比例明显高了。很多人把 Agent 理解成API 调用链的工具人但真正接近产品级体验的 Agent恰恰要处理好这类上下文变更的场景。4.3 任务状态的实时通知与结果追踪客户端需要实时感知任务状态。我第一版是用纯轮询每 500ms 调一次接口拿任务进度。后面发现轮询的写法简单是简单但流量消耗大、响应也不够及时尤其在移动端这种体验很难接受。后面改成了 WebSocket 推送。Go 后端用 gorilla/websocket 维护连接每个连接绑定一个用户 ID。任务状态每次变更编排引擎就通过 Hub 往对应用户的连接推送一条消息内容包括任务 ID、步骤名、进度百分比、当前中间结果图的缩略图链接。移动端 uniapp 也支持 WebSocket API所以我写了一套跨端复用的消息订阅模块Web 和 App 都走同一套接口。连接池的心跳维护也是一个值得注意的细节移动端的弱网环境容易导致 WebSocket 假死。我做了 30 秒一次的 ping/pong 心跳连续两次 pong 超时就断线重连重连后客户端会自动查一次当前所有进行中的任务状态把断线期间的状态差补回来。这个机制上线后移动端卡住了的工单少了很多之前大部分上报都是 WebSocket 假死导致的展示层问题。5. Agent 效果优化与多端验收实战5.1 Prompt 工程与工具描述的迭代方法很多人以为 Agent 做完了就完了实际上效果优化占了整个项目 30% 以上的时间。Prompt 和工具描述是迭代频率最高的两个点。工具描述我前面提到过要站在用户视角写这里展开讲一个具体例子。最早我写的分割工具描述是对输入图像执行语义分割输出前景对象的二进制遮罩LLM 经常不知道什么时候该调它。后来我改成这样从图像中识别并分离指定的主体对象人物、动物、车辆、商品等将其从背景中提取出来可用于去除背景、更换背景、分离前景等场景。可选参数包括目标区域提示框和文本提示。如果用户提到抠图去掉背景换背景等意图优先调用此工具。改完之后模型在对应意图下几乎总是能准确选中这个工具。我还发现一个规律描述里一定要包含该工具的触发场景和最后的 fallback 逻辑模型会根据这段描述做相似度匹配描述越具体匹配越准确。Prompt 工程不完全是玄学它是有一套工程方法论支撑的。另一个迭代点是给 LLM 加了很多系统级的约束提示。比如如果用户意图不明确先追问澄清不要擅自执行处理图片前先检查图像分辨率是否满足要求涉及隐私需求时必须提醒用户如果执行结果与预期不符主动向用户解释原因并提供备选方案。这些约束让 Agent 变得“有分寸”而不是一个傻乎乎的工具调用器这在真实用户场景里的体感差异巨大。5.2 Web 端视觉与交互设计的关键细节工具类的 Web 端视觉设计不需要花哨但交互细节必须到位。这次前端的 UI 设计稿是我自己画的核心原则是让每一步操作都有反馈。用户上传图片后的瞬间页面会立刻显示图片已上传成功、正在分析中同时一个区块提示正在为你规划处理步骤然后逐步展示 Agent 的计划。计划展示我做成文字流的形式每生成一个步骤就逐步渲染出来很像 ChatGPT 的打字机效果。配合上进度信息用户会觉得 Agent 在一边想一边做而不是等等等最后给个结果。预览交互上我做了分屏对比功能。原图放左边、结果图放右边支持同步缩放和拖动。处理多步任务时每一步生成的结果图也会以一个历史时间线的形式竖排在右侧用户可以点击任意一步跳回当时的中间状态。这个 回看中间结果 的功能是产品同学提的一开始我觉得没必要做了之后发现是好评度最高的功能之一好多人就喜欢看 AI 是怎么一步一步把图像改出来的很有成就感。5.3 移动端真机调试与兼容性测试uniapp 虽说是一套代码多端运行但真机上跑起来还是有不小的兼容性差异。这次项目的移动端测试覆盖了iOS、安卓主流机型总结下来有几个高频坑。第一个坑是图片处理的内存问题。iOS 的 Safari 和部分安卓 WebView 对 Canvas 的尺寸和内存限制非常严格传一张 7000px 以上的原图做预览压缩页面直接崩溃。我的解决办法是做压缩预览前先读取图片的原始尺寸如果超过 4096px 宽先用createImageBitmap做一次降采样把尺寸降到 4096 以内再进 Canvas。createImageBitmap的兼容性虽然不是 100% 完美但主流浏览器都支持是一个见效很快的优化手段。第二个坑是移动端的键盘弹出和页面滚动问题。uniapp 里如果使用自定义导航栏键盘弹出时经常会把页面顶飞。我专门写了一个键盘高度监听模块用uni.onKeyboardHeightChange动态调整聊天输入框的 bottom 值保证输入时不会被键盘遮挡也不会引起页面跳动。这个小问题在 Web 端非常简单但移动端真机上花了整整一天才处理好。第三个坑是苹果的 APS 网络定位权限弹窗这个和业务本身无关但如果在 App Store 审核前没有处理好会被直接拒审。审核的时候如果 App 调用了定位权限而没有提供“不使用时禁用”的选择就会被判违规。我做的处理是不在首屏触发定位请求而是在用户主动选择图片分类需要地理位置时才询问这样既满足了业务需求也符合审核要求。5.4 性能压测与上线部署的最终冲刺上线前我做了一轮压测目标很朴素单台 4 核 8G 一张 8G 显存显卡的机器上能稳定支撑 20 个并发用户同时使用。压测结果比预期的好API 网关层 QPS 能到 400瓶颈出在推理服务上。并发 10 个以上的推理请求时GPU 利用率已经接近 100%带动了接口平均耗时从 2 秒增长到 5 秒。解决方案是加了一个“推理排队提示”的逻辑当推理队列积压超过 5 个请求时前端会显示当前处理量大预计等待 XX 秒并允许用户取消任务。这个提示逻辑虽然是妥协方案但把用户体验的保护线画住了好过让用户干等。部署这块我用了 Docker Compose 编排了四个服务Go 后端、Python 推理服务、MySQL、Redis。前端构建产物用 Nginx 容器托管静态资源全走 CDN。整条部署链路用 GitHub Actions 自动化代码 push 到 main 分支后自动构建镜像、推送到私有仓库、登录服务器执行docker compose pull docker compose up -d。上线到这一步项目才算真正意义上结束了。6. 常见问题与排查技巧实录这些坑你大概率也会遇到6.1 显存溢出与模型推理超时的解决路径问题一显存溢出CUDA out of memory这是我最开始遇到频率最高的错误。排查思路分四步第一检查是否有其他进程占用了显存用nvidia-smi看第二看是不是输入图片太大临时张量撑爆显存做一个输入尺寸限制第三检查并发的推理请求数增加信号量限制第四如果模型本身确实太大考虑模型剪枝或者换成蒸馏版本。我最终是尺寸限制 信号量双管齐下彻底解决了这个隐患。问题二推理超时即使模型可以在正常情况下一两秒出结果但并发高的时候排队时间也会很长造成客户端超时。我刚上线的时候Go 后端设置的 HTTP 超时是 30 秒但推理队列一长就很容易打满 30 秒。后面我做了两个调整一是把推理接口从同步调用改成异步提交先接收任务返回 task ID前端轮询任务状态二是给每个任务设置了细分超时比如分割 15 秒、修复 30 秒、超分 20 秒超过时限直接标记失败并提供重试按钮。这么改完以后超时不再表现为转圈圈卡死而是有明确的状态提示用户感知到的稳定性好了非常多。6.2 Base64 传图导致 token 爆炸的规避技巧这个坑比较隐蔽但遇到一次你就长记性了。我在调试 Agent 对话的时候发现每次工具执行后如果引擎把工具的完整输出包含图像数据重新发回给 LLMtoken 消耗会以肉眼可见的速度暴涨。一张 512x512 的图 base64 化之后光这一步就相当于消耗上万 token几轮对话下来预算直接爆炸。我的解决办法是给工具执行结果加一个摘要器。每个工具执行完先提取一个 JSON 格式的文本摘要包含处理类型、输出尺寸、关键属性如分割区域的占比、检测到的目标数量、缩略图 URL。只有在用户明确要求让我看看中间结果或者系统需要调用一个依赖详细视觉信息的工具时才把图片数据发回给 LLM。这么一改token 消耗降了 90%响应速度也显著提升。对做 Agent 开发的开发者来说能不传图就不传图能传缩略图就不传原图 这条原则应该刻进脑子里。6.3 前端状态不同步与多端样式不一致的处理前端状态不同步的典型场景是用户在 Web 端处理图片然后在手机 App 上打开发现任务列表状态还是处理中或者完全看不到。这是因为我第一版把任务状态放在后端内存里多端查不到。后来我把任务状态同步写入了数据库并且给任务表加了 user_id 索引多端从库里拉任务列表问题就解决了。状态机的实现要放到 store 层统一维护任何组件不能直接改任务状态必须通过 store 的方法这样能杜绝很多匪夷所思的状态跳转 bug。多端样式不一致这个问题传统方案是写条件编译比如template里写#ifdef MP-WEIXIN或者样式文件里用/* #ifdef H5 */。我在这个项目里尽量减少条件编译的使用能用统一组件的就用统一组件实在不行的才用条件编译。我的原则是优先保证功能一致样式能统一就统一统一不了的分别在平台分支里单独处理切不可写一个看似能用、但每个平台都有小问题的通用代码。6.4 上线后的日志监控与用户反馈跟踪项目上线不是终点数据验证和反馈迭代才是。我在后端集成了一个极简的日志系统每个任务从开始到结束都会记一条结构化日志包含用户 ID、用户意图、工具调用序列、每步耗时、最终状态。这些日志用来分析 Agent 的任务成功率平均步数最常见失败原因非常有用。刚开始运行时我发现失败原因集中在两类一类是工具选择错误占 40%另一类是参数生成错误占 30%。工具选择错误主要是描述不够精细导致的我又回去迭代了一轮工具描述参数生成错误则需要给每个参数加上更严格的 enum 限制和范围检查让模型在生成参数时不容易跑出边界。用户反馈的渠道我挂在 Web 端的右下角用一个小气泡的形式提供意见反馈入口用户在任意页面都可以提交问题和截图。这个入口上线第一个月就收到了 80 多条有效反馈其中有 30% 直接撞在已知 bug 上另外 70% 是新场景和优化建议产品迭代的方向基本靠这些反馈驱动。提示Agent 类项目的日志比功能日志值钱得多因为每一条日志都在记录模型是怎么思考的。如果你的 Agent 上线后没有日志系统我强烈建议你补一个这是你做效果优化的根基数据。7. 多端产品化的关键决策与商业化思考7.1 免费版与付费版的边界划分产品要做商业化功能的免费/付费边界必须提前想清楚。我当时的划分逻辑是把验证价值的功能做成免费效率提升的功能做成付费。免费版包含基础的背景移除、一键修复、智能调色满足用户尝鲜和基本需求付费版提供高分辨率输出、批量处理、更多风格模板、历史任务云端存储。这个划分逻辑背后的思考是用户第一次用工具时需要的是快速看到效果所以免费的基础功能体验必须完整而一旦用户真的需要批量处理 100 张商品图或者需要高清原图下载用于印刷这时候花钱的意愿就很高了。付费转化率的数据出来之后验证了这个思路基本走通。7.2 私有化部署与 API 开放的可能性技术架构上已经做好了两种扩展路径。私有化部署方面因为整个服务都是 Docker Compose 编排的加上模型权重也都在镜像里完全可以交付给客户做内网部署只需要把 GPU 驱动和 Docker 环境准备好就行。这个能力对 ToB 客户尤其有吸引力数据安全是很多企业客户的第一诉求。API 开放方面我预留了一套 API Key 认证体系和接口限频逻辑。外部开发者接入后可以直接调用图像处理能力而不需要理解底层的 Agent 编排。Agent 的修图能力可以变成一个 Image Processing as a Service 产品按次或按量计费。这类 API 开放模式的好处是能复用的能力不再局限于自家 App 的用户而是可以服务整个开发者生态。7.3 Agent 能力横向扩展的想象空间这个项目做下来我最大的感受是Agent 并不是一个固定的产品形态而是一种可以不断横向扩展的能力底座。修图场景只是这个底座上的一个垂直应用。比如同样的意图理解 - 任务拆解 - 工具调用 - 结果展示框架可以很自然地复用到视频处理、文档处理、数据分析等场景。现在底层的 Agent 编排引擎和工具注册机制是通用的换一套工具集、换一套 Prompt就可以快速落地一个新的垂直 Agent。这个可复用性是我觉得这次技术投入最值得的部分。不过我也得泼一盆冷水垂直领域的 Agent 最难的不是 Agent 技术本身而是对业务的深度理解。修图 Agent 能做得好前提是我懂图像处理的基础逻辑、熟悉用户修图的习惯、知道什么样的话会被理解成什么样的意图。把这些领域知识沉淀成工具描述和约束规则Agent 才真正“懂行”。如果没有这个基础再牛的模型也发挥不出来。写在最后我当时要是懂这些能少走一个月的弯路这个项目从立项到完结前后花了差不多三个月。如果现在让我重新做一遍有几件事我会放在最高优先级去做。第一件事是最开始就把Agent 编排和推理服务解耦这个架构想清楚而不是边做边发现 Go 直接调模型不可行才拆开。有一个原则在 AI 项目里几乎是铁律模型迭代速度远快于业务代码业务层千万不要和模型层绑死。第二件事是工具描述一定要先站在用户的表达习惯去写不要站在技术人的视角写。技术人写工具描述总会不自觉带上术语而大模型和真实用户一样更懂“自然语言描述的功能”而不懂“接口定义”。这个认知我是在踩了好几次坑之后才真正刻进脑子里的。第三件事是 Agent 任务一定要异步化前端不要等同步响应。图像处理本身是重计算再加上 LLM 的规划时间一个完整任务动辄几十秒同步等待只会让用户把页面关掉。异步任务 WebSocket 推送 进度提示是整个项目体验的生命线这一点优先级高于任何花哨的功能。最后是日志。Agent 项目没有日志就是盲人摸象你根本不知道模型在哪一步胡言乱语、在哪一步卡了壳。拿到高质量的日志之后很多优化方向都是不言自明的。这次项目完结对我来说很有收获。全栈 AI 不是把 AI 能力堆到传统项目里就完事它需要重新思考交互流程、重新设计系统边界、重新定义性能瓶颈。这个项目结束后的经验我会沉淀成一套可复用的模板下一个 Agent 项目起步的速度希望能快上不少。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。