尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

隔离内网AI Agent部署实践:依赖离线化、模型量化与本地推理

隔离内网AI Agent部署实践:依赖离线化、模型量化与本地推理 隔离内网下跑AI Agent感受最深的一点就是你在公网上用得顺手的那套东西到内网里几乎全部要重来。依赖拉不下来、模型权重传不过去、API域名解析不了连一个Python包都要靠人肉搬运。但正因为这样这件事做成了之后的价值也特别大——数据不出域、模型可控、链路自主整套系统真正长在了自己的土地上。这篇内容适合谁适合做政企、金融、能源、医疗等有数据合规硬性要求的项目团队也适合所有准备把AI Agent从“玩票”推向“生产”的人。我会把整个项目从方案选型、环境搭建、核心功能实现到踩坑记录完整讲一遍尽量说实操、给参数、讲原因不灌水。1. 项目概述为什么要在隔离内网里跑AI Agent1.1 核心需求解析先说我这次项目的背景。需要在一套与公网完全物理隔离的网络环境里部署一套AI Agent系统给内部运营团队做数据分析与工单处理。所谓隔离内网简单说就是不能上公网外网设备不能直连进来数据只能单向导入有时候连单向导入都要走审批和审计流程。这种环境的核心诉求有三条数据不出物理边界。所有数据、模型权重、推理日志、审计记录都必须留在内网任何一环都不允许走到公网上。服务自主可控。依赖外部厂商的云端API根本不现实模型必须私有化部署推理链路全部本地闭环。可运维、可审计。Agent的每一次决策、每一次工具调用都要有日志业务上出了问题要能回放、能定位、能问责。有人可能会问现在云上大模型API这么方便为什么非要自己折腾答案很简单客户要求数据不出域这一条就决定了所有云端方案直接出局。你可以在PPT里把私有化部署写得天花乱坠但真正落地时要面对的现实是没有外网、没有现成的依赖源、没有搜索可用。1.2 隔离内网的独特挑战相比公网环境隔离内网有五个很典型的麻烦依赖获取难。pip install、cargo build拉包全部失效需要提前把依赖仓库搬进去。模型权重搬运难。哪怕是一个7B模型的量化文件也有4~5GB跨网传输只能走光闸或者审批后的移动介质效率低得惊人。推理资源受限。内网机器往往是用了很多年的GPU服务器显存、算力参差不齐选模型必须精打细算。外部API全部不可用。连个翻译接口都调用不了所有能力都得在本地实现。排查问题难。没有外网搜索解决方案一切靠日志、经验和预判。这五个问题每一个单独拎出来都够喝一壶的。我这里把它们串起来讲重点是怎么在保证安全合规的前提下把Agent从零搭起来并且让它真正能干活。2. 技术选型Agent架构与运行环境的取舍2.1 AI Agent主流架构对比先聊架构。Agent说白了就是让大模型“想”和“做”。当前主流架构有三种各有各的适用场景ReAct模式Reasoning Acting模型在每一轮先生成思考过程再决定调用哪个工具执行完把结果拼回上下文继续推理。这个模式的优点是实现简单、效果直观很多开源框架都是这么干的缺点是上下文会越来越长token消耗大长时间跑下来成本不可控。Plan-and-Execute模式先让模型生成一个多步计划然后逐步执行执行完再修正计划。这个模式对长任务更稳能减少上下文冗余不会每走一步都把历史全倒一遍缺点是计划本身容易出错需要较强的修正机制模型能力不够的话计划直接跑偏。Reflexion模式执行失败后把错误信息反馈给模型让模型自我反思并重新尝试。这个模式能显著提升任务成功率但逻辑复杂调试成本高而且反复重试同样会推高token消耗。我这次的任务是工单处理典型的多步骤场景先解析工单内容再查知识库匹配历史方案然后生成回复草稿最后推送审核流。试下来发现纯用Plan-and-Execute会遇到计划明显不合理但模型坚持不改的情况所以最终采用的是以ReAct为底座、辅以计划校验和错误重试的混合架构单轮决策走ReAct多步骤任务先让模型给出执行计划计划通过校验后才进入执行队列执行失败时把错误信息回灌给模型做一轮Reflexion修正。2.2 为什么选择Rust作为运行时基础再讲运行时选型。市面上的Agent框架一大堆Python系的LangChain、LlamaIndex最热门圈内讨论也多但我们最后选了Rust自研核心、Python做外围脚本的组合。这个决定不是说Python不行而是结合隔离内网的实际情况做的取舍。原因有这么几条没有Python环境灾难。内网里装Python环境是最痛苦的事之一pip依赖一个接一个传到内网版本冲突、编译依赖、系统库缺失光是装环境就能耗掉两三天。Rust编译出来是单个静态二进制cargo build --release之后往内网一拷就能跑没有运行时依赖这是最大的优势。内存安全特性。Agent是要执行工具的工具调用链路上的安全本来就敏感。Rust的所有权系统和编译期检查能挡掉一大类内存相关的漏洞在处理用户输入、解析外部数据时省很多心。并发性能。多个Agent实例并发处理工单是常态Rust的tokio异步运行时是原生的并发利器比Python的GIL舒服太多。当然用Rust也是有代价的开发速度比Python慢生态规模也小。所以我的分工是核心的Agent调度、工具调度、安全校验用Rust写数据分析脚本、报表生成用Python写两边通过内网HTTP通信谁也不拖累谁。2.3 模型选型与离线化方案模型选型上我最终选择了Qwen2.5-7B-Instruct的GGUF量化版部署在llama.cpp上。为什么是7B而不是更大的因为内网的GPU是两片RTX 309024GB显存跑7B量化版单卡就能跑13B或者更大的模型效果固然好但单卡跑起来吃力多卡并行又要引入额外的调度复杂度性价比不划算。依赖离线化分两条线crates.io依赖在能联网的机器上用cargo vendor把所有依赖vendoring到一个目录再一起拷进内网。Cargo.toml里配置vendored-sources编译时加--offline参数。Python依赖用pip download把whl包全部拉下来内网里用pip install --no-index --find-links./packages离线安装。模型文件方面GGUF格式量化后大约4.7GB用移动介质搬进去不算太费劲。但搬完之后务必做SHA256校验传输介质反复使用后文件静默出错的情况我非常确定存在后面会详细说。3. 内网环境搭建与依赖准备3.1 离线依赖仓库的构建内网里真正第一件事不是写代码是把“干粮”备齐。我的做法是搭一个内网软件源同时在跳板机上把依赖全部拉好。Python侧在能联网的跳板机上执行mkdir -p offline_packages pip download -r requirements.txt -d offline_packages \ --platform manylinux2014_x86_64 \ --only-binary:all: \ --python-version 3.11注意这里一定要锁平台和Python版本否则whl包可能不兼容。我因为漏了这个参数踩过坑内网装到一半报“not a supported wheel on this platform”只能回头重新打包白等半天。crates.io这侧更简单直接在项目目录执行cargo vendor vendor会在vendor目录生成所有依赖源码同时需要在Cargo.toml里加一段配置[source.crates-io] replace-with vendored-sources [source.vendored-sources] directory vendor然后把整个目录挪进内网cargo build --release --offline就能编译全程不需要外网。这个方案比预先编译好二进制再拷进去更稳因为不同内网机器的CPU指令集和系统库版本可能有差异源码编译一次反而省心。3.2 本地模型的准备与量化模型这块说一下“下载-量化-搬运”三步。第一步在联网机器上从ModelScope或Hugging Face下载Qwen2.5-7B-Instruct的原始权重。国内访问Hugging Face有时候很慢ModelScope通常更快二者下载下来的模型文件是一致的只是目录结构略有区别。第二步用llama.cpp的转换和量化工具做GGUF转换python convert_hf_to_gguf.py /path/to/qwen2.5-7b-instruct \ --outfile model-f16.gguf \ --outtype f16 ./llama-quantize model-f16.gguf model-q4_k_m.gguf q4_k_mq4_k_m是我实测的甜点档位显存占用低、推理速度可以接受、质量损失相对可控。q8_0更好但显存压力大q3_k_m速度快但输出会明显变笨。这个选择没有标准答案要结合显卡显存来定我的原则是“能上q8就上q8实在不行再降”。第三步用移动介质搬进隔离网。搬完务必执行一次本地哈希校验sha256sum model-q4_k_m.gguf把结果和源机器上的哈希对比一致才继续。我再次强调一遍USB介质在拷贝大文件时偶尔会静默出错轻则模型加载报错重则推理结果全乱别贪省事跳过这步。3.3 内网推理服务搭建模型到位之后我在内网用llama.cpp的server模式起推理服务./llama-server -m model-q4_k_m.gguf \ -c 8192 \ --host 0.0.0.0 \ --port 8080 \ --n-gpu-layers 999这个服务提供的是OpenAI兼容的HTTP接口Agent这边直接用HTTP请求就能接入不用引入额外的SDK对内网环境来说简单可靠。启动参数里有几个点专门说下。-c 8192是上下文窗口长度这个值决定模型能“记住”多少信息。Agent场景下窗口太短会导致多轮工具调用时忘记前面说过的话太长又会增加显存占用和推理时延。8K是我试下来的平衡点如果你做的是长文档分析类任务建议调大一些但相应的KV Cache显存占用也要算清楚。--n-gpu-layers 999表示把尽可能多的层放到GPU上。7B模型用24GB显存可以全部放进去推理速度能跑到20~40 token/s对内部工单处理来说完全够用。4. 核心功能实现Agent的规划-执行-反思闭环4.1 工具注册与调用链路Agent的骨架搭好之后工作量最大的部分是工具系统。我的设计分四层工具定义层每个工具用Rust struct定义包含名称、描述、参数JSON Schema以及实际执行的函数。意图解析层模型输出后解析出“是否需要调用工具”以及“调用哪个工具、传什么参数”的意图。执行层意图校验通过后执行真实函数把结果格式化后回填到上下文。安全层对工具参数做类型校验和范围校验防止模型生成危险参数。拿工单系统里的“查用户历史工单”工具举例大概长这样struct QueryTicketsTool { db: SqlitePool, } #[async_trait] impl Tool for QueryTicketsTool { fn name(self) - str { query_user_tickets } fn description(self) - str { 查询指定用户的近期工单列表返回工单编号、状态、创建时间通常在需要了解用户历史问题背景时使用 } fn parameters(self) - Value { json!({ type: object, properties: { user_id: {type: string, description: 用户ID}, limit: {type: integer, description: 最多返回条数, default: 5} }, required: [user_id] }) } }模型输出的是JSON格式的参数解析后强类型转换参数错了直接返回结构化错误信息给模型重试而不是抛异常中断流程。这个“错误即消息”的设计非常关键能让Agent自己从错误里学习并修正。4.2 Prompt设计与Token预算Token管理是Agent工程里最容易被低估的环节。我建议用一张“预算表”来管理每轮请求的token消耗简单实用环节预估token说明系统提示词800~1200Agent角色设定、工具清单、输出格式约束对话历史可变多轮工具调用的过程记录设上限单轮输出256~1024模型回复与工具调用指令工具执行结果200~800塞回上下文的工具返回内容关键点是工具执行结果不要一股脑全塞回上下文。数据库查询返回几十行数据全塞进去几轮下来上下文窗口就爆了。我的做法是结果先截断到300~500字只保留核心摘要模型需要完整信息时再去调“查询详情”的另一个工具。这个“摘要优先按需取全”的机制同时解决了token溢出和信息过载两个问题。系统提示词里我还会明确约束输出格式例如要求工具调用指令必须用JSON包裹且只能出现在最后一行减少解析失败的几率。写提示词这件事没有银弹但一个清晰的“你能做什么、你在什么环境里、你遵循什么规则”的结构化开头实测效果远好于自由发挥的提示词。4.3 安全沙箱与权限控制隔离内网不等于内部绝对安全Agent能访问内部系统反而扩大了攻击面。所以在Agent和内部系统之间我加了三道闸参数白名单每个工具的参数都定义严格的JSON Schema未知字段直接拒绝防止模型幻觉出某个不存在的字段。命令执行白名单凡是涉及shell命令的工具命令必须走预定义列表参数再做正则过滤禁止拼接、禁止特殊字符。操作审计日志每一次工具调用都记录调用链、参数、返回码、耗时存入独立的审计库定期归档。这三道闸看着简单但能挡住绝大多数“模型幻觉导致误操作”的情况。我举一个真实例子有次模型在更新工单时把状态字段直接传成了“已完成”但参数校验发现该状态下还需要审批通过字段于是直接拒绝调用并返回提示信息模型根据提示重新生成了合法参数。如果没有这层校验这条工单就会带着错误状态流入审批流后面处理起来非常麻烦。5. 实操过程与踩坑记录5.1 从零到可用的部署流程整个部署流程梳理成八步照着做基本不会乱跳板机准备依赖包pip downloadcargo vendor拷入内网。内网配置离线源编译项目二进制确保cargo build --release --offline通过。拷贝模型GGUF文件入内网做SHA256校验。启动llama-server推理服务用curl发一个测试请求验证推理结果正确。启动Agent核心服务检查它能否正常连接推理服务和内部数据库。跑一轮端到端测试投一条模拟工单看Agent能否完成解析、查询、生成、推送全流程。接入审计日志验证每一步操作都有记录。压测并发5个Agent实例同时处理工单观察推理服务的响应延迟和显存占用。第6步一定要多准备几条不同难度的模拟数据。我当时准备了三种一条一句话能答的、一条需要连查三次工具的、一条参数明显有问题的。三种都能过才算基本可用。5.2 常见问题与排查技巧实录把这次项目里踩过的坑整理成一张表基本覆盖了多数隔离内网Agent项目会遇到的通病问题现象根本原因解决办法内网pip install报平台不兼容whl包在联网机器上用当前平台下载目标机器glibc版本不同下载时用--platform manylinux2014_x86_64固定平台模型加载后推理结果乱码GGUF文件拷贝损坏拷贝后SHA256校验重新搬运Agent几轮工具调用后上下文溢出工具结果全量回填摘要截断按需取全高并发时推理服务延迟陡增KV Cache内存分配不足或并发处理未开启调大-c值调并行处理参数模型频繁“乱调用”工具工具描述不清晰参数约束不严格重写工具description明确触发条件日志时间不准内网机器未配置NTP服务内网搭NTP时间源统一所有节点时钟这些坑里我特别想再说一下工具描述这件事。很多人把工具描述写得含糊不清模型自然就“自由发挥”。比如“获取用户信息”这种描述太泛了模型在只需要查工单历史的时候也可能去调用它。改成“根据用户ID查询用户基础信息通常在需要姓名、部门、联系方式时使用”模型对该工具的调用准确率会有肉眼可见的提升。写工具描述和写Prompt一样本质是在引导模型的注意力。5.3 性能调优与资源规划压测阶段发现推理服务是Agent整体吞吐的瓶颈。我的调优手段有三板斧增大并发处理能力。llama-server支持多个并发请求进来时自动调度GPU但默认参数偏保守我手动调了并行参数吞吐提升了30%~40%。分离推理与业务。Agent核心服务和推理服务分别跑在不同的机器上避免CPU繁忙导致推理请求排队这个分离也让故障影响面变小推理服务挂了不至于拖垮整个业务系统。缓存高频结果。同一批用户的工单查询结果两分钟内的重复查询直接走缓存绕过推理和数据库响应延迟从秒级降到毫秒级。资源规划方面按我这套配置1台GPU服务器跑推理1台CPU服务器跑Agent调度和数据库大概能支撑10个并发会话、每个会话3~5轮工具调用。想支撑更大规模要么上更快的GPU要么做多路推理服务的负载均衡或者拆分多个模型实例分别服务不同场景。6. 项目总结与扩展思考6.1 还能往哪里扩展这个项目的架构天然是可扩展的。我梳理了几个已经想清楚的方向多Agent协作把“工单处理”和“知识库问答”分别做成独立的Agent中间加一个调度Agent来路由任务避免单个Agent携带过多工具导致上下文膨胀。向量检索增强内网文档越来越多纯靠工具查数据库不够可以加一个基于Rust的本地向量库做知识库的相似度检索再把检索结果交给Agent综合比让模型死记硬背知识靠谱得多。更细粒度的审计把每个Agent的思考过程以结构化方式持久化配合Web UI可视化展示业务方就能直观理解Agent为什么做了这个决定出现纠纷时也有据可查。这些方向都不是另起炉灶而是顺着现有架构长出来的每一条都有明确的业务价值。6.2 几个值得记住的经验最后说点实际体会。隔离内网做Agent最大的敌人不是模型能力不够而是你对外网的依赖惯性。习惯了pip install一下就走习惯报错就去搜索这些习惯在内网全都得改。提前把依赖、模型、文档、常见问题排查手册准备好整个项目的交付速度会完全不一样。另一个体谅是关于验证顺序的。网络隔离环境下环境的构建顺序比逻辑代码的顺序更影响交付速度。先配环境、再跑通最小链路、最后叠业务功能是我这次项目里最稳妥的推进方式。一上来就写复杂业务流程结果环境有问题排查起来又慢又痛苦。再补一条实用建议隔离内网项目的交接文档一定要写“从哪里来、到哪里去”。把依赖包的来源、模型的下载地址、哈希值、内网各服务的端口映射全部记录下来。别觉得这些小事不值一提等你三个月后回头维护这套系统的时候会感谢当初认真记了这些信息。这个项目做完之后我对“Agent工程”这件事的看法有了不小的变化。以前觉得Agent是模型能力的延伸现在更觉得Agent是一套完整的软件工程系统——环境、架构、可观测性、安全边界每一项都比模型本身的“聪明程度”更影响最终交付效果。隔离内网不过是把这些本来就重要的事情逼到了台面上而已。
返回列表