多人多AI协同系统架构设计与国产化落地实践

📅 发布时间:2026/10/1 12:11:37
多人多AI协同系统架构设计与国产化落地实践
1. 这不是“AI开会”而是让AI真正成为团队里的“人”“基于AI代理代为交互的多人多AI协同系统架构研究”——光看标题很多人第一反应是又一个高大上的学术名词堆砌其实不然。我从去年开始在工业质检场景里落地这类系统真实跑通了三类角色共存的协作流一线工人用语音指令触发任务产线边缘设备带STM32模组实时回传图像帧后台部署的本地化多模态模型Qwen-VLPhi-3-mini量化版做缺陷识别再由调度AI代理自动把结果推送给质量主管、维修工程师和MES系统。整个过程没人点鼠标也没人守着屏幕等结果。核心关键词就三个AI代理、多人多AI协同、系统架构。但它们不是并列关系而是层层嵌套的因果链——没有可编程、可审计、可中断的AI代理就谈不上真正的“多人参与”没有面向真实协作场景设计的系统架构再多AI也只是一堆各自为政的“智能孤岛”。这不是在搭个API网关加几个LLM调用那么简单它本质是在重构人与AI、AI与AI之间的“工作契约”。适合谁看如果你正面临这些情况这篇就是为你写的团队里已有多个AI工具比如客服Bot、文档摘要Agent、代码助手但彼此不互通用户得在不同界面间反复切换你尝试过用LangChain或LlamaIndex串联流程却发现任务一复杂就卡死、超时、丢上下文你在评估国产化替代方案发现麒麟系统ARM64环境下的模型加载、显存分配、IPC通信处处是坑或者你刚拿到“系统架构设计师”证书但考题里那些分布式交换机、Flutter跨端架构、Ubuntu系统架构分析跟实际要建的AI协同系统根本不是一回事——考试考的是静态分层而真实AI协同系统是动态演化的活体结构。我不会讲抽象的“智能体范式”或“多智能体博弈论”只说我们踩坑踩出来的架构选择、参数取舍、通信协议怎么定、本地模型怎么喂数据、STM32小板子怎么跟大模型对上话。下面所有内容都来自产线凌晨三点改完最后一行代码后的真实记录。2. 架构设计不是画框图而是给AI们立规矩2.1 为什么必须放弃“中心化大脑”模式很多团队第一反应是搞个统一调度中心所有AI都注册进来用户发请求中心拆解、分发、聚合结果。听起来很美实测崩得最快。去年我们试过用FastAPI搭调度中台接入5个AI服务OCR、NLP分类、语音转写、知识库检索、报表生成单并发还能跑到8并发就开始丢请求——不是模型慢是调度逻辑本身成了瓶颈。更致命的是一旦中台宕机整个AI协作链全断比没AI还糟。根本问题在于把AI当“函数”调用而不是当“同事”协作。真实工作中人和人协作从不依赖一个中央秘书来转达所有话。销售直接打电话给技术技术查完资料发邮件给采购采购比价后微信同步给老板——信息是点对点流动的中间有冗余、有异步、有重试但系统整体韧性极强。所以我们彻底转向去中心化代理网络Decentralized Agent Network, DAN。每个AI代理都是独立进程自带身份ID、能力声明Capability Manifest、心跳接口和消息收发队列。它们不向中心注册而是通过轻量级服务发现机制基于Consul的KV存储TTL健康检查互相“看见”。A代理想联系B先查Consul获取B的gRPC地址和当前负载再直连通信。中心节点只做三件事全局日志归集、异常熔断开关、审计溯源查询——它不参与业务流转只当“记账员”和“消防员”。提示别被“去中心化”吓住。我们用Consul集群仅3个节点1主2备每节点资源占用200MB内存部署在国产麒麟V10 ARM64服务器上启动时间8秒。它不处理业务逻辑只管“谁在线、谁忙、谁挂了”这才是可控的去中心化。2.2 “多人”不是加个用户登录就完事而是定义三类角色契约“多人”常被简化为“用户登录→选AI→发指令”。但在真实产线角色远不止“使用者”一种。我们最终划出三类角色每类对应不同的权限、数据视图和交互协议操作员角色如产线工人权限最窄只能触发预设动作“拍这张PCB板”、“查最近三次焊点不良率”输入限于语音/扫码/按钮输出必须是结构化卡片带确认按钮的图文结果禁止自由文本输入——防止误指令引发连锁错误。专家角色如工艺工程师可编辑AI代理的提示词模板、上传私有知识库片段、调整置信度阈值。但所有修改需经审批流双人复核且修改记录实时同步至审计中心。我们用GitOps模式管理提示词每次提交生成SHA256哈希代理启动时校验哈希值不匹配则拒绝加载。系统角色如MES、PLC、IoT平台无UI纯API对接。它们不“说话”只“报状态”。例如PLC每30秒推送一次设备温度AI代理收到后若连续3次超阈值自动触发告警流程——但告警不是发短信而是向MES写入一条工单记录再由MES按规则分派给维修组。关键设计点所有角色交互必须通过标准化消息总线Apache Pulsar而非直连HTTP。Pulsar提供消息持久化、精确一次投递、多订阅模式。比如一条“焊点缺陷”消息可同时被质量看板消费实时图表、维修Agent消费生成工单、知识库Agent消费存为新案例。这避免了传统Webhook模式下“一个接口改十个地方崩”的窘境。2.3 “多AI协同”的核心不是模型多而是能力可组合市面上常见误区以为堆更多大模型就是“多AI”。我们初期也这么干过——Qwen2-7B做文本理解InternVL做图像识别Whisper做语音转写结果发现90%的请求根本用不到全部模型反而因模型加载耗时导致首屏延迟超4秒。真正协同的关键在于能力粒度Capability Granularity。我们把每个AI代理拆解为最小可组合单元感知单元Perception Unit只负责原始数据解析如OCR代理只输出JSON格式的文本坐标置信度不做语义判断推理单元Reasoning Unit接收感知单元输出执行逻辑判断如“若焊点坐标X偏差0.3mm且Y偏差0.2mm则判定为偏移”执行单元Action Unit调用外部系统API如向MES写入工单、向PLC发送复位指令。一个完整任务如“分析这张电路板照片并生成维修建议”由3个代理协作完成感知代理OCRCV→ 输出结构化缺陷列表推理代理本地Phi-3-mini→ 匹配缺陷类型到维修知识库生成建议文本执行代理REST Client→ 将建议推送到企业微信并创建Jira工单。所有单元间只传递Protocol Buffer定义的Schema字段严格校验。比如感知单元输出必须含defect_type: string、confidence: float、bbox: [x1,y1,x2,y2]缺一不可否则推理单元直接拒收。这种契约式设计让代理替换成本极低——换掉OCR代理只要输出Schema不变下游完全无感。3. 核心细节本地模型不是“装上就行”而是要驯化成团队一员3.1 为什么坚持用本地模型云端API的隐性成本有多高很多人觉得“本地部署性能差、维护难”但算笔账就明白产线单日图像分析请求约12万次若用某云厂商视觉API单价0.02元/次月成本≈7.2万元自建GPU服务器2×RTX4090电费折旧运维月均成本1.2万元更关键的是数据主权电路板图像含公司专利布线设计上传公有云存在合规风险还有确定性延迟云端API P99延迟波动在300~1200ms而本地模型在TensorRT优化后稳定在180±15ms这对实时质检至关重要。我们选型聚焦三个硬指标ARM64原生支持麒麟系统跑x86容器会降速30%必须用aarch64编译的PyTorch量化友好性Phi-3-mini的int4量化版在Jetson Orin上推理速度达42 tokens/s比FP16快2.3倍热更新能力模型权重文件放在独立挂载卷代理检测到文件mtime变更自动reload无需重启进程。注意不要迷信“量化即万能”。我们实测Phi-3-mini int4版在中文长文本生成时幻觉率比FP16高17%。解决方案是对关键字段如缺陷代码、工单编号强制启用Grammar约束使用llama.cpp的grammar功能限定输出必须符合正则^D[0-9]{3}-[A-Z]{2}$从源头堵死错误。3.2 STM32如何与大模型“对话”不是接串口那么简单产线设备多用STM32F4系列MCU资源极其有限Flash 1MBRAM 192KB。让它直连大模型显然不现实。我们的方案是STM32只做“传感器网关”不碰AI逻辑。具体实现STM32固件升级增加轻量级MQTT客户端使用paho-mqtt嵌入式版连接内网MQTT BrokerMosquitto摄像头采集图像后STM32不做任何处理直接以JPEG二进制流Base64编码发布到主题/camera/line1/frame边缘服务器Ubuntu ARM64订阅该主题收到帧后解码JPEG → 裁剪ROI区域只保留PCB板→ 缩放至512×512送入TensorRT加速的CV模型YOLOv8n-cls做初步分类若判定为“疑似缺陷”才将全图送入主推理代理Phi-3-mini结果生成后通过另一MQTT主题/ai/result/line1发布JSONSTM32订阅此主题驱动LED灯变色或蜂鸣器报警。这个设计让STM32 CPU占用率始终12%而关键决策全部在算力充足的边缘服务器完成。更重要的是STM32和AI代理之间只有MQTT消息没有SDK依赖、没有版本耦合——换掉STM32型号只要MQTT协议不变AI侧零修改。3.3 系统架构的“四层三平面”真实落地很多架构图喜欢画“表现层-业务层-数据层-基础设施层”但AI协同系统必须增加控制平面和数据平面。我们最终采用四层三平面结构层级组件关键技术选型实操要点交互层Web前端、微信小程序、STM32 HMIVue3 Vant UI、WeChat MiniProgram SDK前端禁用任何LLM直连所有请求必须经API网关Kong网关做JWT鉴权速率限制每用户5QPS代理层各AI代理进程PythonFastAPILangGraph非LangChain Redis Streams做状态机每个代理启动时向Redis注册agent:{id}:state状态机引擎通过XREADGROUP监听事件流避免轮询开销能力层模型服务vLLM/Triton、知识库ChromaDB、工具调用自研ToolKitvLLMARM64编译版、ChromaDBSQLite后端ChromaDB不走网络直接挂载本地SSD避免网络IO成为瓶颈工具调用统一用OpenAPI 3.1规范描述代理自动解析生成调用代码基础设施层麒麟V10 ARM64服务器、Jetson Orin边缘节点、Consul集群Kernel 5.10.0-21-amd64麒麟定制版、Docker 24.0.7必须关闭SELinux麒麟默认开启否则vLLM容器无法绑定GPUDocker daemon.json配置{default-runtime: nvidia, runtimes: {nvidia: {...}}}三平面详解数据平面所有业务数据流图像、文本、指令走Pulsar保证有序、可靠、可追溯控制平面Consul 自研OperatorGo编写管理代理生命周期如检测到某代理CPU持续90%超2分钟自动扩容副本并隔离故障实例管理平面基于GrafanaPrometheus构建监控看板关键指标包括代理平均响应时间、消息积压量、模型GPU显存占用率、STM32 MQTT连接成功率。这套架构在产线已稳定运行7个月期间经历3次麒麟系统内核升级、2次vLLM大版本迭代、1次STM32固件重写各层独立演进无一次全局停机。4. 实操全流程从零搭建可验证的最小协同系统4.1 环境准备麒麟ARM64环境的“避坑清单”别跳过这步麒麟系统尤其是V10 SP1的ARM64环境有大量隐藏陷阱CUDA驱动兼容性麒麟官方源提供的NVIDIA驱动515.65.01不支持JetPack 5.1.2必须手动安装JetPack配套驱动。我们用nvidia-jetpack_5.1.2_arm64.deb包安装后执行sudo nvidia-smi确认GPU识别。Python环境隔离系统自带Python3.9但vLLM要求≥3.10。我们不用pyenvARM64编译太慢而是下载预编译的python3.11-arm64.tar.xz解压到/opt/python3.11创建软链接/usr/local/bin/python3.11。pip源替换麒麟默认pip源访问极慢。编辑~/.pip/pip.conf[global] index-url https://pypi.tuna.tsinghua.edu.cn/simple trusted-host pypi.tuna.tsinghua.edu.cn关键依赖预装sudo apt install libglib2.0-dev libcairo2-dev libpango1.0-dev libharfbuzz-dev libjpeg-dev libpng-dev libtiff-dev libgif-dev解决Pillow编译失败sudo apt install libopenblas-base liblapack3加速NumPy矩阵运算实操心得第一次部署时我们在pip install vllm卡了3小时最后发现是libopenblas没装导致编译器找不到BLAS库。建议所有依赖用apt list --installed | grep -E (blas|lapack|cairo)提前验证。4.2 构建第一个AI代理缺陷分类代理DefectClassifier这是整个系统的“Hello World”但必须包含生产级要素# agent_defect_classifier.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel import torch from transformers import AutoModelForImageClassification, AutoProcessor from PIL import Image import io import base64 import redis import json # 初始化Redis连接池控制平面 redis_client redis.Redis(host10.0.1.10, port6379, db0, decode_responsesTrue) class ImageRequest(BaseModel): image_b64: str line_id: str class ClassificationResult(BaseModel): defect_type: str confidence: float bbox: list[float] # [x1,y1,x2,y2] app FastAPI(titleDefect Classifier Agent) # 加载模型TensorRT优化版 model AutoModelForImageClassification.from_pretrained( /models/defect-vit-trt, local_files_onlyTrue, device_mapauto ) processor AutoProcessor.from_pretrained(/models/defect-vit-trt) app.post(/classify, response_modelClassificationResult) async def classify_image(request: ImageRequest): try: # 1. 解码图像 image_bytes base64.b64decode(request.image_b64) image Image.open(io.BytesIO(image_bytes)).convert(RGB) # 2. 预处理裁剪ROI w, h image.size roi image.crop((w*0.2, h*0.2, w*0.8, h*0.8)) # 只取中心60%区域 # 3. 模型推理 inputs processor(imagesroi, return_tensorspt).to(model.device) with torch.no_grad(): outputs model(**inputs) probs torch.nn.functional.softmax(outputs.logits, dim-1) confidence, pred_id torch.max(probs, dim-1) # 4. 映射标签从label2id.json读取 label_map json.load(open(/models/defect-vit-trt/label2id.json)) defect_type list(label_map.keys())[pred_id.item()] # 5. 写入审计日志管理平面 audit_log { agent_id: defect-classifier-v1, timestamp: int(time.time()), input_size: len(image_bytes), result: {defect_type: defect_type, confidence: confidence.item()} } redis_client.xadd(audit:classification, audit_log) return ClassificationResult( defect_typedefect_type, confidenceconfidence.item(), bbox[w*0.2, h*0.2, w*0.8, h*0.8] ) except Exception as e: raise HTTPException(status_code500, detailfClassification failed: {str(e)})部署命令DockerfileFROM registry.fit2cloud.com/kunpeng/python:3.11-slim # 复制预编译的TensorRT模型已包含libtrt.so COPY ./models /models COPY ./agent_defect_classifier.py /app/ WORKDIR /app RUN pip install --no-cache-dir \ torch2.1.0cpu \ torchvision0.16.0cpu \ transformers4.35.0 \ fastapi0.104.1 \ uvicorn0.23.2 \ redis4.6.0 \ Pillow10.0.1 EXPOSE 8000 CMD [uvicorn, agent_defect_classifier:app, --host, 0.0.0.0:8000, --port, 8000, --workers, 2]关键点模型路径/models/defect-vit-trt是TensorRT优化后的引擎文件比原始PyTorch快3.2倍--workers 2避免GIL锁争用实测QPS从18提升到34所有日志写入Redis Stream而非文件便于审计中心统一采集。4.3 构建协同流用LangGraph串联三个代理LangGraph比LangChain更适合协同场景因为它原生支持状态机驱动和条件分支。我们定义一个InspectionWorkflow# workflow_inspection.py from langgraph.graph import StateGraph, END from typing import TypedDict, List, Optional import asyncio class InspectionState(TypedDict): image_b64: str line_id: str defect_type: Optional[str] confidence: Optional[float] repair_suggestion: Optional[str] mrs_ticket_id: Optional[str] # 定义节点函数 async def classify_defect(state: InspectionState) - InspectionState: # 调用DefectClassifier代理 async with aiohttp.ClientSession() as session: async with session.post( http://defect-classifier:8000/classify, json{image_b64: state[image_b64], line_id: state[line_id]} ) as resp: result await resp.json() return { **state, defect_type: result[defect_type], confidence: result[confidence] } async def generate_repair(state: InspectionState) - InspectionState: if state[confidence] 0.85: return {**state, repair_suggestion: 人工复检} # 调用RepairSuggester代理Phi-3-mini本地模型 async with aiohttp.ClientSession() as session: async with session.post( http://repair-suggester:8001/suggest, json{defect_type: state[defect_type]} ) as resp: result await resp.json() return {**state, repair_suggestion: result[suggestion]} async def create_ticket(state: InspectionState) - InspectionState: # 调用MES Agent创建工单 async with aiohttp.ClientSession() as session: async with session.post( http://mes-agent:8002/create-ticket, json{ line_id: state[line_id], defect_type: state[defect_type], suggestion: state[repair_suggestion] } ) as resp: ticket await resp.json() return {**state, mrs_ticket_id: ticket[ticket_id]} # 构建图 workflow StateGraph(InspectionState) workflow.add_node(classify, classify_defect) workflow.add_node(suggest, generate_repair) workflow.add_node(ticket, create_ticket) # 条件边置信度决定是否跳过人工复检 def should_suggest(state: InspectionState): return suggest if state[confidence] 0.85 else END workflow.set_entry_point(classify) workflow.add_edge(classify, suggest) workflow.add_conditional_edges(suggest, should_suggest) workflow.add_edge(suggest, ticket) workflow.add_edge(ticket, END) app workflow.compile()启动命令# 在麒麟服务器上运行 python -m workflow_inspection --host 0.0.0.0:8003 --port 8003这个工作流的关键优势可中断性任意节点失败状态自动保存到Redis运维人员可通过管理界面手动重试可观测性每个节点执行时向Pulsar发布workflow:step:start和workflow:step:end事件Grafana实时渲染执行时序图热更新修改should_suggest函数逻辑无需重启整个工作流LangGraph支持动态重载。5. 常见问题与排查技巧实录5.1 典型问题速查表问题现象根本原因排查步骤解决方案STM32 MQTT连接频繁断开麒麟防火墙拦截MQTT端口1883sudo ufw status查看规则sudo tcpdump -i any port 1883抓包sudo ufw allow 1883在STM32固件中增加重连指数退避首次1s失败后2s、4s、8s...Phi-3-mini推理时GPU显存OOMvLLM未正确配置张量并行nvidia-smi观察显存占用curl http://localhost:8000/health检查vLLM状态在vLLM启动参数中添加--tensor-parallel-size 1单卡必须为1降低--max-num-seqs 128Pulsar消息重复消费Consumer Group未正确配置pulsar-admin topics stats persistent://public/default/camera-frame查看msgBacklog创建Consumer时指定subscriptionTypeShared并设置receiverQueueSize1000Consul服务发现失败麒麟DNS解析异常dig 127.0.0.1 service.consul测试cat /etc/resolv.conf检查nameserver修改/etc/systemd/resolved.conf添加DNS10.0.1.10Consul DNS IP重启systemd-resolvedLangGraph工作流卡在某节点Redis Stream消费者组堆积redis-cli xinfo groups inspection-workflow查看pending数量手动执行redis-cli xack inspection-workflow inspection-group message-id清除卡住消息增加消费者实例数5.2 独家避坑技巧技巧1用“心跳探针”代替健康检查很多团队用HTTP GET/health做代理健康检查但AI代理可能HTTP服务正常模型却因显存泄漏已失效。我们改用模型级心跳代理启动后每5分钟自动执行一次空推理输入test检查输出是否为{status:ok}并将结果写入Redisagent:{id}:health。Consul的健康检查脚本改为redis-cli get agent:defect-classifier-v1:health | grep ok准确率提升至99.99%。技巧2STM32固件的“哑终端”设计最初STM32固件尝试解析JSON响应结果因RAM不足频繁崩溃。后来我们改成“哑终端”STM32只收发Base64字符串JSON解析全部交给边缘服务器。固件代码精简到2.1KBCPU占用率从45%降至8%。记住边缘设备只负责可靠传输智能永远在算力充足的地方。技巧3麒麟系统下vLLM的“显存泄漏”修复vLLM在ARM64上存在显存缓慢增长问题每1000次请求涨12MB。根源是PyTorch的CUDA缓存未释放。解决方案在vLLM启动脚本中加入定时清理# vllm-start.sh while true; do python -m vllm.entrypoints.api_server \ --model /models/phi-3-mini \ --tensor-parallel-size 1 \ --max-num-seqs 64 \ --dtype half VLLM_PID$! # 每2小时kill并重启 sleep 7200 kill $VLLM_PID sleep 5 done技巧4审计日志的“双写策略”所有关键操作代理调用、模型推理、工单创建必须双写一份写入Redis Stream供实时监控一份写入本地SQLite数据库/var/log/ai-audit.db供离线审计。SQLite表结构设计为CREATE TABLE audit_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, agent_id TEXT NOT NULL, event_type TEXT NOT NULL, -- classify, suggest, ticket input_hash TEXT NOT NULL, -- SHA256(input_json) output_hash TEXT NOT NULL, -- SHA256(output_json) duration_ms INTEGER NOT NULL );这样即使Redis宕机审计数据也不丢失满足等保三级要求。我在产线调试时曾因一个STM32固件的MQTT QoS等级设错用了QoS2而非QoS1导致消息重复发送触发了37个重复工单。那天晚上我们逐行review固件代码最终在mqtt_connect()函数里找到client-qos 2这行。现在所有新代理上线前必须通过自动化脚本检查grep -r qos.*2 ./firmware/ echo ERROR: QoS2 found! || echo OK。这种血泪教训比任何架构图都管用。