ARTICLE DETAIL

资讯详情

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

隔离内网AI Agent工程实战:MCP与Skills离线部署及并发优化

隔离内网AI Agent工程实战:MCP与Skills离线部署及并发优化 1. 项目缘起为什么要在隔离内网里折腾 AI Agent第一次接到“在隔离内网里跑 AI Agent”这个需求时我脑子里蹦出来的第一个念头是这不是自己给自己找麻烦吗。外网环境里模型 API 随手就能调MCP 服务想连就连Skills 生态一抓一大把各种开源框架装起来就能跑。可一旦把场景搬到物理隔离的内网——没有外网出口、没有公网 DNS、连 pip 和 npm 都得走内部镜像源——整套玩法就完全变了。所谓隔离内网通常指与互联网物理断开、或者仅通过严格受控的单向通道交换数据的网络环境。金融、能源、制造、科研院所里的核心生产网很多都是这个形态。这类环境里做 AI Agent 工程最大的矛盾在于Agent 的能力上限高度依赖外部工具和模型服务而内网恰恰把这些外部依赖全部切断了。你不能指望在内网里直接pip install openai然后调云端接口也不能让 Agent 随手去访问某个公网的 MCP Server。那为什么还要做因为需求是真实存在的。内网里沉淀着大量高价值数据——工艺参数、设备日志、内部知识库、业务系统数据——这些数据出于合规和安全要求不能出网但业务方又确实希望用 AI 能力把它们盘活。于是“内网 AI Agent”就成了一个必须啃下来的硬骨头模型要本地化部署工具要内网自建协议要能离线跑通整个工程链路要能在断网环境下自洽。这篇文章面向的是已经有一定 AI Agent 开发基础、但第一次接触隔离内网部署的工程师。我会把从架构选型、模型落地、MCP 与 Skills 的内网适配到并发扛压、问题排查的完整链路拆开讲。里面很多坑是我自己踩出来的文档里不会写但实际部署时一定会遇到。读完你至少能拿到一套可以直接抄作业的内网 Agent 工程方案少走几周弯路。2. 整体架构设计内网 Agent 的骨架怎么搭2.1 核心矛盾拆解与设计原则内网 Agent 工程和公网版本的本质区别可以用一句话概括所有“伸手就能够到”的外部依赖都必须变成“自己家里有”的内部能力。这句话展开来就是三条设计原则。第一条是全链路离线自洽。模型推理、向量检索、工具调用、协议通信每一个环节都不能假设有外网。这意味着你不能用任何需要联网鉴权的 SaaS 服务不能依赖公网 CDN 加载前端资源甚至连字体和图标都要本地化。我见过有团队在内网部署时忘了把前端的一个 Google Fonts 引用去掉结果页面加载卡死三十秒排查了半天才发现是字体请求超时。第二条是能力分层解耦。Agent 的核心能力可以拆成四层模型层推理、记忆层向量库与知识库、工具层MCP 与 Skills、编排层Agent 主循环。每一层都要能独立替换和独立测试。为什么要这样因为内网环境里任何一层的组件出问题你都得能快速定位并单独替换而不是牵一发动全身。比如模型换了工具层不应该受影响向量库换了编排逻辑不应该改。第三条是资源预算前置。内网机器通常是“有什么用什么”不像云上可以随时扩容。所以在架构设计阶段就要把显存、内存、磁盘、并发数算清楚。一个 7B 的模型量化后大概占 4-6GB 显存13B 量化后 8-10GB如果还要同时跑向量库和 MCP 服务一台 16GB 显存的机器基本就是极限了。这个账必须提前算否则上线就崩。2.2 分层架构与组件选型我把内网 Agent 的架构分成五层从下往上依次是层级职责内网选型建议关键约束基础设施层计算、存储、网络本地 GPU 服务器 内网对象存储无外网出口DNS 需内网解析模型服务层推理与嵌入Ollama / vLLM / Xinference模型文件需离线导入能力层工具与技能自建 MCP Server Skills 仓库协议需离线可跑编排层Agent 主循环自研或开源框架本地化不依赖云端编排接入层前端与 API内网 Web 内网 API 网关静态资源全本地模型服务层我优先推荐Ollama做快速验证vLLM做生产部署。Ollama 的好处是模型管理简单ollama pull之后直接就能跑适合内网初期验证但它的并发能力偏弱生产环境还是得上 vLLM配合 PagedAttention 能把吞吐拉起来。嵌入模型单独用一个小的比如 bge-m3 或者 bge-large-zh跑在 CPU 上都行没必要占 GPU。能力层是内网工程的重头戏。MCPModel Context Protocol在这里的价值是提供了一套标准化的工具调用协议让 Agent 和工具之间解耦。内网里你需要自己实现 MCP Server把内部系统的能力数据库查询、文件检索、工单创建等包装成 MCP 工具。Skills则是更高层的封装把一组相关的工具调用和提示词打包成一个可复用的技能单元。内网里 Skills 的管理要自建仓库不能依赖公网市场。编排层我建议自研一个轻量的主循环而不是直接套用重型框架。原因很简单内网环境里框架的很多默认行为比如自动联网、自动上报都是负担改起来比重写还麻烦。一个几百行的主循环把“思考-调用工具-观察结果-再思考”这个循环写清楚反而更可控。2.3 网络拓扑与数据流向内网 Agent 的网络拓扑要特别注意单向数据流的设计。典型场景是用户在内网终端发起请求请求经过内网 API 网关到达编排层编排层调用模型服务和工具服务结果原路返回。整个过程不能有任何出网的尝试。这里有个容易被忽略的点很多开源组件默认会做版本检查或遥测上报。比如某些 Python 库启动时会去 PyPI 查最新版本某些前端框架会加载远程配置。这些行为在内网里会导致请求超时拖慢启动速度甚至让整个服务卡住。解决办法是在部署前做一次“断网测试”——把机器网线拔了跑一遍看哪些地方报错然后逐个关掉。数据流向还要考虑审计与留痕。内网环境通常有合规要求Agent 的每一次工具调用、每一次模型推理最好都记录到本地日志里。这不是为了监控而是为了出问题时能回溯。我一般会在编排层加一个统一的日志中间件把请求 ID、时间戳、调用的工具、返回结果摘要都记下来存到内网数据库。3. 模型与推理服务的内网落地3.1 模型文件的离线导入方案内网部署模型第一个拦路虎就是模型文件怎么进去。公网环境huggingface-cli download一行命令搞定内网里你得走离线导入。常见做法有三种我分别说说适用场景。第一种是移动介质摆渡。把模型文件在外网机器上下载好通过合规的移动介质拷贝到内网。这种方式适合模型体积不大比如 7B 量化后 4GB 左右的情况。操作上要注意下载时用huggingface-cli download --local-dir把文件完整拉到本地目录包括 config、tokenizer、权重文件一个都不能少。拷贝前做一次校验用sha256sum生成校验和内网侧再校验一遍避免传输损坏。第二种是内网镜像仓库。如果内网有自建的 Docker Registry 或者对象存储可以把模型打包成镜像或者上传到对象存储内网机器直接拉取。这种方式适合模型体积大、需要频繁更新的场景。打包成镜像的好处是环境依赖一起带进去坏处是镜像体积会很大拉取慢。第三种是内网模型市场。有些规模较大的内网环境会自建模型仓库类似内部的 HuggingFace。这种方式最规范但需要前期投入建设。如果你们单位有直接用没有的话前两种方式组合使用就够了。注意模型文件导入后一定要在内网侧做一次完整性验证。我遇到过权重文件少了一个分片模型加载时报错信息很隐晦排查了大半天。验证方法很简单加载模型跑一次推理看输出是否正常。3.2 推理引擎选型与参数调优内网推理引擎的选择核心看两个指标吞吐和显存占用。我实测下来Ollama 和 vLLM 是两个最实用的选择各有适用场景。Ollama 适合单用户或低并发场景。它的优势是部署极简模型管理方便Modelfile可以自定义系统提示词和参数。内网里用 Ollama关键是把OLLAMA_HOST设成内网地址OLLAMA_MODELS指向本地模型目录然后关掉它的自动更新检查。并发方面Ollama 默认是串行处理请求的可以通过OLLAMA_NUM_PARALLEL调高并发数但受限于显存一般调到 2-4 就差不多了。vLLM 适合生产级高并发场景。它的 PagedAttention 机制能显著提升显存利用率和吞吐。内网部署 vLLM关键参数有这么几个--tensor-parallel-size张量并行数等于 GPU 数量。单卡就设 1。--gpu-memory-utilization显存利用率默认 0.9内网如果还要跑其他服务调到 0.7-0.8 留余量。--max-model-len最大上下文长度根据模型能力和显存定。7B 模型在 16GB 显存上一般能跑到 8K 上下文。--max-num-seqs最大并发序列数这个直接决定并发能力。16GB 显存跑 7B 模型设 16-32 比较稳妥。参数调优有个经验公式显存占用 ≈ 模型权重 KV Cache 激活值。KV Cache 的大小和max-model-len × max-num-seqs成正比。如果显存不够优先降max-num-seqs因为并发数降下来单请求的响应质量不受影响而降max-model-len会导致长文本处理能力下降。3.3 嵌入模型与向量库的内网配置Agent 的记忆能力靠嵌入模型和向量库撑着。内网里这两个组件的配置有几个坑。嵌入模型我推荐bge-m3它对中文支持好而且能同时输出稠密向量和稀疏向量检索效果比单一向量好。部署上bge-m3 跑在 CPU 上就行用sentence-transformers加载内网里把模型路径指向本地目录。批量嵌入的时候注意 batch sizeCPU 上一般设 8-16太大反而慢。向量库的选择上Milvus和Qdrant是两个主流选项。Milvus 功能全但部署重需要 etcd、MinIO 等一堆依赖Qdrant 轻量单二进制就能跑内网里我更倾向 Qdrant。部署 Qdrant 时把storage路径指向内网大盘关掉遥测QDRANT__TELEMETRY_DISABLEDtrue然后配置内网访问地址。向量库的索引参数直接影响检索速度和召回率。以 Qdrant 为例HNSW 索引的关键参数是m和ef_construct。m控制图的连接数越大召回越高但内存占用越大一般设 16-32ef_construct控制构建时的搜索范围设 100-200 比较平衡。查询时的ef参数可以动态调设大一点召回高但慢设小一点快但可能漏。实操心得内网向量库初始化时一定要做一次全量数据的索引构建测试。我遇到过数据量到百万级时索引构建时间从几分钟涨到几小时的情况原因是ef_construct设太高了。后来降到 128构建时间降了一个数量级召回率只掉了不到 1%。4. MCP 与 Skills 的内网适配实战4.1 MCP 协议在内网的自建与部署MCP 这套协议的核心价值是把“工具调用”这件事标准化了。公网里你可以直接连别人搭好的 MCP Server内网里你得自己实现。好消息是 MCP 协议本身不复杂基于 JSON-RPC实现一个 Server 大概几百行代码。内网 MCP Server 的实现要点有这么几个。首先是传输层选择。MCP 支持 stdio 和 SSE 两种传输方式。内网里如果 Agent 和 MCP Server 在同一台机器用 stdio 最简单进程间通信没有网络开销如果跨机器用 SSE走内网 HTTP。我一般推荐 stdio因为内网跨机器通信还要考虑防火墙和端口管理麻烦。其次是工具定义。每个 MCP 工具需要定义名称、描述、输入参数 schema。这里的关键是描述要写清楚因为 Agent 是靠描述来决定调不调这个工具的。描述写得太模糊Agent 就会乱调或者不调。比如一个“查询设备状态”的工具描述里要写清楚查什么设备、返回什么字段、参数格式是什么。第三是错误处理。内网环境里工具调用失败是常态——数据库连不上、文件不存在、权限不够。MCP Server 要把这些错误包装成结构化的返回而不是直接抛异常。Agent 拿到错误信息后可以决定重试还是换工具。我一般会把错误分成三类可重试错误网络抖动、不可重试错误参数错误、需要人工介入的错误权限问题分别用不同的错误码标识。4.2 Skills 仓库的内网化管理Skills 是比 MCP 工具更高一层的封装。一个 Skill 通常包含一段系统提示词、一组可调用的 MCP 工具、以及一些示例。内网里管理 Skills核心是建一个本地 Skills 仓库。仓库的结构我一般这样设计skills-repo/ ├── registry.json # 技能注册表 ├── skills/ │ ├── device-query/ # 设备查询技能 │ │ ├── manifest.json # 技能元信息 │ │ ├── prompt.md # 系统提示词 │ │ └── examples/ # 示例对话 │ ├── log-analysis/ # 日志分析技能 │ └── report-gen/ # 报告生成技能registry.json记录所有可用技能的索引Agent 启动时加载这个文件就知道有哪些技能可用。manifest.json定义技能的元信息名称、描述、依赖的 MCP 工具、版本号。prompt.md是这个技能专属的系统提示词告诉 Agent 在什么场景下用这个技能、怎么用。Skills 的加载策略有两种全量加载和按需加载。全量加载是把所有技能的提示词都塞进上下文简单但占 token按需加载是先让 Agent 根据用户意图选择技能再加载对应提示词。内网里模型上下文通常有限我推荐按需加载用一个轻量的意图识别可以用小模型或者关键词匹配先做技能路由。注意Skills 的版本管理在内网里容易被忽略。公网可以随时拉最新版内网里技能更新要走发布流程。我建议给每个 Skill 加版本号Agent 调用时记录版本出问题时能定位到具体版本。4.3 工具调用的安全边界与权限控制内网 Agent 能调用的工具直接关系到内部系统的安全。权限控制必须做在 MCP Server 层而不是靠 Agent 自觉。我的做法是给每个 MCP 工具定义访问级别Agent 的身份信息从请求头或者配置里来决定它能调哪些工具。具体实现上MCP Server 维护一张权限表工具名最低权限级别是否可写审计要求query_device_statusread否记录调用日志create_ticketwrite是记录完整参数delete_recordadmin是双人复核query_logsread否记录调用日志Agent 发起工具调用时MCP Server 先查权限表权限不够直接拒绝返回明确的错误信息。这样即使 Agent 被诱导去调高危工具也会被拦住。另外写操作要加确认机制。内网里 Agent 自动创建工单、修改配置这类操作最好加一道人工确认。实现方式可以是 MCP 工具返回一个“待确认”状态Agent 把确认请求推给用户用户确认后再执行。这道机制看起来麻烦但能避免很多误操作。5. 并发扛压与性能优化5.1 并发瓶颈定位方法“AI Agent 怎么扛并发”是内网部署绕不开的问题。很多人第一反应是加机器但加机器之前得先搞清楚瓶颈在哪。Agent 的请求链路长从接入层到编排层到模型层到工具层任何一环都可能成为瓶颈。我的定位方法是分段压测。用压测工具比如 locust 或者 wrk分别压每一层看哪一层的 QPS 先到顶。压模型层直接调推理接口看单卡能扛多少并发。7B 模型在 16GB 显存上vLLM 大概能扛 20-30 并发。压工具层直接调 MCP Server看工具调用的响应时间和吞吐。数据库查询类工具通常是瓶颈。压编排层模拟完整 Agent 循环看端到端延迟。这一层往往是 CPU 瓶颈因为要处理大量 JSON 序列化和状态管理。定位到瓶颈后优化方向就明确了。模型层瓶颈就上量化、上多卡、上更高效的推理引擎工具层瓶颈就加缓存、优化 SQL、异步化编排层瓶颈就上多进程、优化数据结构。5.2 请求队列与限流策略内网 Agent 的并发控制核心是队列 限流。不能让它无限制地接收请求否则模型层会被打爆所有请求都变慢。我的做法是在编排层前面加一个请求队列用 Redis 或者内存队列实现。队列的长度根据模型层的处理能力定一般是并发数 × 平均处理时间 × 2。比如模型层能扛 20 并发平均处理 5 秒那队列长度设 200 左右。限流策略用令牌桶比较合适。给每个用户或者每个会话分配令牌令牌耗尽就排队。这样能防止单个用户把资源占满。令牌桶的参数桶容量设 10补充速率设 1/秒意味着每个用户最多突发 10 个请求之后每秒补充 1 个。实操心得队列满的时候不要直接拒绝请求而是返回一个“排队中”的状态让前端轮询。用户体验上等待比直接失败好得多。我一般会在返回里带上预估等待时间前端显示进度条。5.3 缓存与批处理优化缓存是提升并发能力最有效的手段之一。Agent 场景里可缓存的内容有三类模型推理结果、工具调用结果、嵌入向量。模型推理结果的缓存要谨慎因为同样的输入在不同上下文下可能要有不同输出。我的做法是只缓存“确定性”的推理比如意图分类、实体抽取这类任务缓存 key 用输入文本的哈希。生成类任务不缓存或者只缓存完全相同的输入。工具调用结果的缓存相对安全。数据库查询、文件读取这类操作结果在一定时间内是稳定的。缓存 key 用工具名 参数哈希TTL 设短一点比如 60 秒。这样能挡住大量重复查询。嵌入向量的缓存最直接。同样的文本嵌入结果不变可以长期缓存。用文本哈希做 key存到 Redis 或者本地 LRU 缓存里。批处理是另一个优化点。多个请求如果都要调模型可以攒一批一起送进去vLLM 本身支持 continuous batching你只要把请求并发发过去就行。工具调用也可以批处理比如多个数据库查询合并成一个批量查询。6. 常见问题与排查技巧实录6.1 内网部署典型故障速查内网环境的问题排查和外网最大的区别是没有搜索引擎可以查。出了问题只能靠自己。我把踩过的坑整理成一张速查表现象可能原因排查方法解决服务启动卡住组件尝试联网检查更新断网启动看日志卡在哪关掉遥测和自动更新模型加载失败模型文件不完整校验文件哈希重新导入完整文件工具调用超时内网 DNS 解析慢nslookup测试解析时间配置本地 hosts 或内网 DNS并发上不去显存不足导致排队看 GPU 利用率和显存占用降 max-num-seqs 或上量化前端加载慢静态资源引用外网浏览器开发者工具看网络请求全部改本地资源向量检索不准嵌入模型不匹配检查嵌入模型和索引是否一致统一嵌入模型版本这张表里的每一条都是我实际遇到过并且花时间解决的。特别是第一条“服务启动卡住”在内网里极其常见因为太多开源组件默认会做联网检查。6.2 断网环境下的依赖管理内网部署的依赖管理核心是把所有依赖提前准备好。Python 项目用pip download把 wheel 包全部下下来放到内网 PyPI 镜像或者本地目录Node 项目用npm pack或者直接拷贝node_modules系统依赖用离线包管理。我一般会做一个依赖清单记录每个组件的版本和来源。这样内网部署时照着清单装不会漏。清单格式大概这样python: 3.10.12 torch: 2.1.0cu118 vllm: 0.4.0 qdrant: 1.7.0 redis: 7.2.0版本号要精确到小版本因为大版本之间可能有 API 不兼容。内网里升级依赖成本很高所以初始版本选稳定版别追新。6.3 日志与可观测性建设内网 Agent 的可观测性靠的是结构化日志 本地监控。日志用 JSON 格式每条日志包含时间戳、请求 ID、层级、事件类型、耗时、结果状态。这样出问题时可以用jq或者脚本快速过滤。监控方面内网里 Prometheus Grafana 是标配。关键指标要埋请求 QPS、端到端延迟、模型推理延迟、工具调用延迟、队列长度、显存占用、错误率。这些指标能帮你快速定位问题。注意内网监控数据不要往外传所有 dashboard 都在内网访问。Grafana 的匿名访问要关掉配置内网认证。7. 工程化落地的一些个人体会内网 AI Agent 工程做下来我最大的体会是难点不在 AI在工程。模型选型、提示词调优这些 AI 相关的工作其实占不到三成时间剩下七成都在处理内网环境的特殊性——依赖怎么进去、网络怎么通、权限怎么控、并发怎么扛、问题怎么查。另一个体会是简单优先。内网环境里组件越少越好依赖越少越好配置越少越好。每多一个组件就多一个出问题的点而且内网里排查问题的成本远高于外网。我见过有团队在内网里堆了七八个中间件结果一个组件的配置问题排查了三天。后来砍到三个反而更稳。最后分享一个实用技巧在内网里建一个“沙箱环境”和正式环境隔离但配置尽量一致。所有新组件、新配置先在沙箱里跑通再上正式环境。沙箱环境可以随便折腾坏了就重装不影响生产。这个习惯帮我避免了好几次生产事故。内网 Agent 这个方向工具和协议还在快速演进MCP 和 Skills 的生态也在变化。但底层的工程原则是不变的离线自洽、分层解耦、资源前置、简单优先。把这几点守住不管上层技术怎么变你都能快速适配。
返回列表