☰
多人多AI协同系统架构设计与国产化落地实践
2026/10/1 12:11:37 网站建设 项目流程

1. 这不是“AI开会”,而是让AI真正成为团队里的“人”

“基于AI代理代为交互的多人多AI协同系统架构研究”——光看标题,很多人第一反应是:又一个高大上的学术名词堆砌?其实不然。我从去年开始在工业质检场景里落地这类系统,真实跑通了三类角色共存的协作流:一线工人用语音指令触发任务,产线边缘设备(带STM32模组)实时回传图像帧,后台部署的本地化多模态模型(Qwen-VL+Phi-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个代理协作完成:

  1. 感知代理(OCR+CV)→ 输出结构化缺陷列表;
  2. 推理代理(本地Phi-3-mini)→ 匹配缺陷类型到维修知识库,生成建议文本;
  3. 执行代理(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 1MB,RAM 192KB)。让它直连大模型显然不现实。我们的方案是:STM32只做“传感器网关”,不碰AI逻辑。

具体实现:

  • STM32固件升级,增加轻量级MQTT客户端(使用paho-mqtt嵌入式版),连接内网MQTT Broker(Mosquitto);
  • 摄像头采集图像后,STM32不做任何处理,直接以JPEG二进制流+Base64编码发布到主题/camera/line1/frame;
  • 边缘服务器(Ubuntu ARM64)订阅该主题,收到帧后:
    1. 解码JPEG → 裁剪ROI区域(只保留PCB板)→ 缩放至512×512;
    2. 送入TensorRT加速的CV模型(YOLOv8n-cls)做初步分类;
    3. 若判定为“疑似缺陷”,才将全图送入主推理代理(Phi-3-mini);
    4. 结果生成后,通过另一MQTT主题/ai/result/line1发布JSON,STM32订阅此主题,驱动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代理进程(Python+FastAPI)LangGraph(非LangChain!)+ Redis Streams做状态机每个代理启动时向Redis注册agent:{id}:state,状态机引擎通过XREADGROUP监听事件流,避免轮询开销
能力层模型服务(vLLM/Triton)、知识库(ChromaDB)、工具调用(自研ToolKit)vLLM(ARM64编译版)、ChromaDB(SQLite后端)ChromaDB不走网络,直接挂载本地SSD,避免网络IO成为瓶颈;工具调用统一用OpenAPI 3.1规范描述,代理自动解析生成调用代码
基础设施层麒麟V10 ARM64服务器、Jetson Orin边缘节点、Consul集群Kernel 5.10.0-21-amd64(麒麟定制版)、Docker 24.0.7必须关闭SELinux(麒麟默认开启),否则vLLM容器无法绑定GPU;Docker daemon.json配置{"default-runtime": "nvidia", "runtimes": {"nvidia": {...}}}

三平面详解:

  • 数据平面:所有业务数据流(图像、文本、指令)走Pulsar,保证有序、可靠、可追溯;
  • 控制平面:Consul + 自研Operator(Go编写)管理代理生命周期,如检测到某代理CPU持续>90%超2分钟,自动扩容副本并隔离故障实例;
  • 管理平面:基于Grafana+Prometheus构建监控看板,关键指标包括:代理平均响应时间、消息积压量、模型GPU显存占用率、STM32 MQTT连接成功率。

这套架构在产线已稳定运行7个月,期间经历3次麒麟系统内核升级、2次vLLM大版本迭代、1次STM32固件重写,各层独立演进,无一次全局停机。

4. 实操全流程:从零搭建可验证的最小协同系统

4.1 环境准备:麒麟ARM64环境的“避坑清单”

别跳过这步!麒麟系统(尤其是V10 SP1)的ARM64环境有大量隐藏陷阱:

  1. CUDA驱动兼容性:麒麟官方源提供的NVIDIA驱动(515.65.01)不支持JetPack 5.1.2,必须手动安装JetPack配套驱动。我们用nvidia-jetpack_5.1.2_arm64.deb包,安装后执行sudo nvidia-smi确认GPU识别。

  2. Python环境隔离:系统自带Python3.9,但vLLM要求≥3.10。我们不用pyenv(ARM64编译太慢),而是下载预编译的python3.11-arm64.tar.xz,解压到/opt/python3.11,创建软链接/usr/local/bin/python3.11。

  3. pip源替换:麒麟默认pip源访问极慢。编辑~/.pip/pip.conf:

    [global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn
  4. 关键依赖预装:

    • 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(host='10.0.1.10', port=6379, db=0, decode_responses=True) 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(title="Defect Classifier Agent") # 加载模型(TensorRT优化版) model = AutoModelForImageClassification.from_pretrained( "/models/defect-vit-trt", local_files_only=True, device_map="auto" ) processor = AutoProcessor.from_pretrained("/models/defect-vit-trt") @app.post("/classify", response_model=ClassificationResult) 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(images=roi, return_tensors="pt").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_type=defect_type, confidence=confidence.item(), bbox=[w*0.2, h*0.2, w*0.8, h*0.8] ) except Exception as e: raise HTTPException(status_code=500, detail=f"Classification failed: {str(e)}")

部署命令(Dockerfile):

FROM 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 \ torch==2.1.0+cpu \ torchvision==0.16.0+cpu \ transformers==4.35.0 \ fastapi==0.104.1 \ uvicorn==0.23.2 \ redis==4.6.0 \ Pillow==10.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端口(1883)sudo 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 128
Pulsar消息重复消费Consumer Group未正确配置pulsar-admin topics stats persistent://public/default/camera-frame查看msgBacklog创建Consumer时指定subscriptionType=Shared,并设置receiverQueueSize=1000
Consul服务发现失败麒麟DNS解析异常dig @127.0.0.1 service.consul测试;cat /etc/resolv.conf检查nameserver修改/etc/systemd/resolved.conf,添加DNS=10.0.1.10(Consul DNS IP);重启systemd-resolved
LangGraph工作流卡在某节点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%。

技巧2:STM32固件的“哑终端”设计
最初STM32固件尝试解析JSON响应,结果因RAM不足频繁崩溃。后来我们改成“哑终端”:STM32只收发Base64字符串,JSON解析全部交给边缘服务器。固件代码精简到2.1KB,CPU占用率从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"。这种血泪教训,比任何架构图都管用。

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

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

立即咨询