最近接了个私有化部署的 AI Agent 项目环境一上来就把我整不会了服务器在内网外网被掐断装个 Python 依赖都要折腾半天更别提调云端大模型 API。头两周基本在踩坑后来把一条能跑通的 Agent 工程链路梳理清楚才意识到隔离内网做 AI Agent 工程实战核心不是模型选型也不是花哨的 Agent 架构而是把“依赖、模型、工具、并发、观测”这几件事全部内生化。这篇就把我的实操过程、踩过的坑、以及最终验证过可行的方案完整写出来给同样在隔离环境里做 Agent 落地的朋友一点参考。1. 先把“隔离内网”这四个字拆清楚1.1 三种常见的隔离强度很多人一听到“隔离内网”就默认是那种完全断网的机房但实际做项目会发现隔离的强度千差万别直接决定了你后面技术方案怎么定。我这次遇到的情况属于“白名单单向访问”即内网服务器可以访问一些经过审批的企业内部域名但普通互联网访问基本不可用。另外两种常见的形态一是完全物理隔离机器不能插外网网线文件只能通过介质或者企业内部的文件摆渡系统进入二是逻辑隔离有出网能力但需要经过网关审批速度极不稳定且随时可能被关停。建议拿到项目先花半天做一次环境盘点别上来就写代码。盘点项包括服务器能不能访问公网、有没有企业内部软件源或制品库、大模型推理要用 GPU 还是 CPU、容器环境是 Docker 还是 Kubernetes、网络策略是否允许跨机调用。这一步做得越细后面越少返工。1.2 隔离给 Agent 工程带来的五连击隔离内网会让常规的 Agent 开发流程直接失效我总结下来至少是五类问题模型依赖拿不到。默认想用云端大模型 API 或者 H ugging Face 上下载开源模型权重在隔离内网里全部走不通。你需要先解决“模型从哪来、怎么进内网”的问题。Python 依赖装不上。pip install 直接超时项目里几十个间接依赖每一个都要手动处理还得考虑依赖版本互相打架的问题。工具生态被卡死。Agent 要用的 Web 搜索、地图、天气、OCR、翻译这些第三方服务公网 API 全都连不上工具集必须重新设计。数据回流没有现成通道。Agent 产生的日志、轨迹、评估结果需要持久化而常用的云端监控、日志服务都在外网得自己搭建或另想办法。并发和性能的约束完全变了。云端大模型的并发能力不需要你操心隔离内网里跑本地模型显存、吞吐、排队全部变成你的工程问题。这五连击意味着你在隔离内网里做的不是“Agent 应用开发”而是“Agent 基础设施自建”。心态和节奏都要调整。2. AI Agent 主流架构与选型逻辑2.1 绕不开的技术栈盘点AI Agent 的热度起来之后市面上的架构方案五花八门但如果要工程落地真正主流的其实就那么几条路。开发框架层面Python 生态里 LangChain 和 LangGraph 用得最多LangChain 适合快速搭原型LangGraph 则胜在把 Agent 的流程定义成有状态的状态机节点、边、循环都能显式管理在复杂业务场景里可控性更强。Java 技术栈的团队往往会看 Spring AI它把 LLM 调用、提示词模板、结构化输出这些基础能力统一封装成 Spring Boot Starter对已有 Java 中后台体系非常友好。Rust 系最近也有不少项目冒出来比如基于 rig-core 的轻量 Agent 框架性能表现不错但生态还在快速演进适合有充足精力深入贡献的团队不适合急着交付的业务项目。平台层也有选择像扣子这类智能体应用平台能通过可视化编排迅速做出 Agent 原型POC 阶段效率非常高但隔离内网私有化场景下数据要出域、平台和模型要绑定对外服务往往绕不开“需要企业版私有部署”这道坎。2.2 为什么我推荐 FastAPI LangGraph 的组合这次实战我最终选了 FastAPI LangChain LangGraph 的组合。不单是因为 Python 在 AI 生态里最成熟更核心的原因是这套组合把三个问题处理得很干净。第一是开发交付能力。内网 Agent 本质是一个被反复调用的服务FastAPI 天然支持异步接口、参数校验、请求上下文管理和 OpenAPI 文档用来做 Agent 的统一入口非常顺手。第二是流程可控性。LangGraph 可以把“意图识别 - 工具调用 - 结果汇总”之类的流程显式建模业务方想插一个审批节点、加一个兜底逻辑直接在图里加一条边就行不用把逻辑堆在 prompt 里。第三是排查维护的友好度。LangGraph 的状态快照和中间步骤记录在隔离内网这种不能随便造数据结构的环境里排查问题能省一半时间。2.3 单 Agent 还是多 Agent另一个容易被带偏的决策是“要不要上多 Agent”。市面上很多教程一上来就展示多 Agent 辩论、多角色协作看起来很酷但工程上多 Agent 意味着多次模型调用、更长的链路时延、更大的状态管理复杂度以及成倍的排查难度。我现在的判断标准很简单能用单 Agent 解决的场景坚决不上多 Agent。比如检索问答、工单分类、字段抽取、报表生成这些用“一个 Agent 多个工具”就足够了LangGraph 里一个节点做规划一个节点执行工具一个节点生成答复。只有当任务确实可以并行拆解比如同时查库存、查物流、查价格并且单条链路对时延有明确要求时才拆出并行分支甚至多 Agent 协作。隔离内网里的模型推理资源本来就紧张这一步克制非常关键。3. 隔离内网的依赖与模型资产准备3.1 Python 依赖离线导入先解决环境依赖。我当时的做法是在一台具备外网访问权限的构建机上用 pip download 把需要的包连同依赖全部拉下来打成离线包目录再通过企业内部的摆渡系统传到内网机器。执行时重点注意三点。第一构建机 Python 版本要和内网目标机器保持一致最好连小版本都对齐否则很多二进制 wheel比如 pydantic-core、numpy、tokenizers会因为平台标签不匹配而装不上。第二不能用pip install 包名 --download这种简单逻辑要采用pip download -r requirements.txt -d wheelhouse --platform manylinux2014_x86_64 --python-version 3.11 --implementation cp --abi cp311进入内网后pip install --no-index --find-links./wheelhouse -r requirements.txt第三如果团队规模不小、项目数量多更推荐直接在内网搭一个 Nexus PyPI 私服把构建机下载的包全部上传进去后续所有机器统一从私服安装省掉每个项目单独拷贝轮子的麻烦。3.2 模型权重与 Embedding 本地化模型资产是隔离内网最容易卡住的一环。开源大模型权重动辄十几 GB 到上百 GB跨内网传输本身就是体力活。我的实践经验是先把模型下载到一台可联网的服务器用校验工具算好 SHA256然后通过内部文件服务器或离线硬盘拷入内网。模型文件原则上全部放到一个统一目录按“模型类型/模型名/版本号”的组织方式管理避免散落在各个项目的虚拟环境里后面想做版本回退会非常痛苦。对内网 Agent 来说Embedding 模型往往比主对话模型更常用。知识库检索需要它工具结果向量化需要它有些场景还会用它做路由和分类。建议优先本地化部署一个小而快的 BERT 类或 text-embedding 类模型口粮再紧张也要保证 Embedding 服务稳定否则 Agent 的召回能力会极大退化。模型服务化我用的是 vLLM OpenAI 兼容接口的方式内网服务可以暴露成一个本地地址Agent 代码里只需要把 base_url 指到它就行。对于没有 GPU 的环境Ollama 也支持纯 CPU 推理虽然速度一般但胜在部署极简适合验证和开发调试。3.3 Docker 镜像离线分发如果内网有 Kubernetes 环境容器镜像也必须离线化。在可联网的构建机上执行docker pull准备好所有镜像再用docker save导出为 tar 包传入内网最后用docker load导入到节点的本地镜像仓库或者推送到内网 Harbor。这里最容易踩坑的是基础镜像版本不一致。AI 项目的镜像里有 CUDA、cuDNN、Python 运行时、模型推理库任何一个组件版本不对容器跑起来就是各种诡异报错。建议项目一开始就把基础镜像锁死所有服务统一基于同一个方案构建不要在 Pod 级别各写各的。4. Tool 内生化与 Token 管理4.1 内网 Agent 的工具画像隔离内网里没有 Web 搜索、没有公网 APIAgent 的工具集全部得靠内网资产来定义。我整理下来常见的可内生化工具大致这几类内网业务接口封装比如查订单状态、查库存、提交审批、拉取报表本质是把 HTTP 接口封装成 Agent 可调用的函数输入输出都做结构化约束。数据库查询工具封装成只读的 SQL 执行接口让 Agent 能回答“上个月退货率是多少”这类数据问题。脚本执行工具运维和自动化场景很常见Agent 生成命令后通过受控的执行器去跑比如远程执行巡检脚本、批量处理文件。消息推送工具企业内部办公软件的机器人接口Agent 可以把结果主动推送到群组或者个人。内部知识库检索把文档、Wiki、FAQ 全部向量化之后做成检索工具这基本上是内网 Agent 的最强刚需。很多人问我“能不能让 Agent 去做期货交易或者挂个小红书账号自动发消息”本质上这些都是工具编排问题行情源、交易接口、发帖接口全是工具Agent 是决策调度层。技术上不是不能做但涉及自动交易、对外发布这类动作业务风险、合规边界和异常兜底必须前置设计我建议先想清楚容错和责任归属再谈自动化。4.2 权限、审计与工具安全工具内生化之后安全问题会被放大。Agent 一旦可以通过自然语言触发工具调用工具的边界就变成了模型可控范围的边界。我这边做了几层防护工具注册表白名单Agent 能看到的工具列表是硬编码维护的每个工具都有明确的入参 schema 和出参 schema不允许模型自由发明工具名。参数校验前置工具入口统一走 Pydantic 校验数据库工具强制 only-read脚本工具只允许执行白名单目录下的受控脚本。敏感操作二次确认涉及审批、转账、群发消息这类高影响操作Agent 不能直接执行必须生成一个待确认请求由用户点击确认后真正调用。全链路审计日志每轮对话、每次工具调用的参数和结果都要落库保留隔离内网环境里出了问题没法甩锅给外部日志就是唯一的现场证据。4.3 搞懂 Agent 里的 Token 到底指什么很多刚接触 Agent 的人看到网上讨论 Token 就懵。Token 在 Agent 里有双重含义一是 LLM 对文本切分的基本单元一个中文汉字往往对应一个到一个多 Token它是模型计费和上下文窗口容量衡量的基础二是在并发工程里Token 也是资源分配和限流的核心计量单位。我在做 Agent 服务时会把“Token 预算”拆成两层。第一层是单次请求预算一个请求最多允许消耗多少输入、输出 Token防止某次超长上下文把推理服务拖垮。第二层是全局速率预算单位时间内所有请求累计消耗的 Token 总数不能超过模型服务的承载上限。在代码里我维护了一个简单的令牌桶计数器按分钟统计已消耗 Token 量超过阈值就返回“系统繁忙请稍后重试”这比让请求无限排队要优雅得多。5. 并发与性能AI Agent 怎么扛住生产流量5.1 先从同步串行到异步并发内网 Agent 服务刚上线时很多人写的接口是同步的一个请求进来调用模型推理卡住等模型返回整个过程占用一个工作线程。模型推理动辄几秒并发一上来工作线程很快耗尽请求全部排队。这个阶段其实还没到模型能力瓶颈卡的是代码层的 IO 模型。必须把 HTTP 层改成异步。FastAPI 的 async 接口对于等待型操作HTTP 调用、数据库查询、消息队列能极大提升单位资源的请求承载量。举一个直观的例子同样的 4 核 8G 机器同步写法能同时处理 10 个请求已经在抖改成异步后可以轻松挂住几百个等待中的请求虽然推理本身没有变快但系统不再因为线程耗尽而拒绝服务。5.2 连接池、线程池与任务队列模型推理虽然最终是算力密集型但 Agent 链路里的外围依赖大多是 IO 型的这些依赖必须全部池化。对大模型推理服务的 HTTP 调用用连接池复用长连接避免每次请求都走 TCP 握手对数据库访问连接池大小按并发峰值调节太小会排队太大浪费内存对脚本执行器这种 CPU 密集型工具用独立线程池隔离开避免 Agent 链路里某个脚本把整个服务拖死。如果流量再上一个量级就要引入任务队列。把请求先放到 Redis/RabbitMQ 之类的队列再让消费端以固定速率从队列里取任务去请求推理服务。这本质上是一种背压机制模型服务扛不住的时候队列帮你缓冲而不是直接雪崩。生产环境里消息队列的弹性远比代码里塞各种超时重试要可靠。5.3 限流、超时与降级策略隔离内网的资源是封闭的一旦出问题没有外部资源可以借力所以限流和降级是保命手段。限流维度我参考如下表格实际值根据资源和业务容忍度调整维度限流手段推荐值/策略用户维度每个用户每分钟请求数5~10 次/分钟服务维度全局并发请求数推理服务并发上限的 60%Token 维度每分钟总 Token 消耗按模型 TPS 实测估算队列维度最大排队长度超过 50 直接拒绝超时策略也很重要模型调用超时、工具调用超时、整条 Agent 链路超时必须分别设置且链路超时要小于下游超时。我的经验是模型推理单次超时设 60 秒工具调用看具体接口一般 10~15 秒Agent 整链路 120 秒。超时后统一返回降级答案比如“内部服务暂时不可用请稍后再试”。5.4 推理侧吞吐调优实测隔离内网的 GPU 资源一般很稀缺推理服务的吞吐优化比代码并发更重要。我实测中几个有效手段首先vLLM 的连续批处理机制能显著提升吞吐。相同的 Qwen 系列模型开 vLLM 和原生 transformers 接口做同样并发压测吞吐能提升 4~5 倍。其次max_concurrency 和 max_num_batched_tokens 要按显存实测调不要照抄默认值。我这边一张 24G 显存的卡量化到 INT4 后并发调到 8~16 是一个比较稳的区间太高了显存溢出太低了浪费算力。另外一个很容易忽略的点是 Embedding 模型和主模型不要抢资源。把 Embedding 推理单独放在独立小容器里避免文档检索和对话推理互相干扰。实测下来隔离内网环境下这一条能让单次对话延迟稳定降低 15% 以上。6. 可复现的最小实战内网订单问答 Agent6.1 需求与架构为了让上面的方法落地我拆一个完整的小案例内网订单问答 Agent。场景是业务运营同学在群里问“A 客户今天出了多少单、有几单还没发货”Agent 先去查订单数据库再调内部物流接口核实发货状态最后返回一段自然语言结论。整体链路是这样的用户在客户端发起对话请求FastAPI 网关接收请求后进入 LangGraph 编排Agent 根据问题路由到订单查询工具和物流查询工具工具底层访问内网数据库和 HTTP 接口中间所有日志写入本地监控表。不需要 GPU 也能跑用小一点的 7B 量化模型就够了。6.2 FastAPI 服务代码先写一个简单的 FastAPI 入口把 Agent 的核心逻辑包进来from fastapi import FastAPI, HTTPException, Depends from pydantic import BaseModel from contextlib import asynccontextmanager from agent_core import run_agent app FastAPI(titleInnerNet Agent Gateway) class ChatRequest(BaseModel): user_id: str message: str class ChatResponse(BaseModel): answer: str trace_id: str app.post(/api/chat, response_modelChatResponse) async def chat(req: ChatRequest): try: trace_id, answer await run_agent(req.user_id, req.message) return ChatResponse(answeranswer, trace_idtrace_id) except TimeoutError: raise HTTPException(status_code504, detailagent chain timeout) except Exception as e: raise HTTPException(status_code500, detailstr(e))run_agent 内部负责构造请求 ID、调用 LangGraph 图、把整链路状态快照和最终回答都返回出去。注意这里全部是 async 函数后续工具调用才能享受异步红利。6.3 内网 Tool 封装每个工具就是一个带 schema 约束的函数我用 LangChain 的 tool 装饰器来做from langchain_core.tools import tool import aiohttp tool async def query_order_count(customer_id: str, date: str) - str: 查询指定客户在指定日期的下单数量 async with aiohttp.ClientSession() as session: async with session.get( fhttp://internal-order-api/orders/count, params{customer_id: customer_id, date: date}, timeoutaiohttp.ClientTimeout(total10) ) as resp: data await resp.json() return f订单数: {data[count]} tool async def query_delivery_status(order_id: str) - str: 查询指定订单的物流发货状态 async with aiohttp.ClientSession() as session: async with session.get( fhttp://internal-logistics-api/delivery/status, params{order_id: order_id}, timeoutaiohttp.ClientTimeout(total10) ) as resp: data await resp.json() return f发货状态: {data[status]}工具返回的字符串会被模型当作观察结果继续推理。所以工具的描述要写得让模型能看懂输出的内容要结构化最好能原文拼接成自然语言推断的依据这能显著降低模型“发挥”的空间。6.4 LangGraph 编排接下来用 LangGraph 把流程定义出来这里我只建四个节点入口节点 agent_route 负责判断问题需要哪些工具query_order 和 query_logistics 分别做数据查询answer 节点汇总结果生成最终回答。from langgraph.graph import StateGraph, END from typing import TypedDict, Annotated class AgentState(TypedDict): message: str order_count: str delivery_status: str answer: str def build_graph(): g StateGraph(AgentState) g.add_node(agent_route, agent_route) g.add_node(query_order, query_order) g.add_node(query_logistics, query_logistics) g.add_node(answer, answer) g.set_entry_point(agent_route) g.add_edge(agent_route, query_order) g.add_edge(agent_route, query_logistics) g.add_edge(query_order, answer) g.add_edge(query_logistics, answer) g.add_edge(answer, END) return g.compile()LangGraph 真正有价值的是它允许你在节点之间增加条件和循环比如当工具查询失败时可以让 Agent 重新规划而不是直接摆烂。这也是我选择它的核心原因。6.5 部署联调与实测部署时我把服务拆成两个部分推理服务单独启动Agent 网关单独启动。内网联调时最常遇到的问题是模型返回不稳定同一个问题在五轮测试里可能有一轮直接给了一个瞎编的数字。后来我在 answer 节点里强制加入“如果工具返回值为空必须如实说查询不到不许猜测”的约束情况才好转。实测下来单用户连续提问的响应时间大约在 8~15 秒其中 80% 的时间都花在模型推理上。并发 10 个请求时未做限流的版本直接导致推理服务 OOM加上令牌桶限流后系统稳定在“部分请求排队、无失败”的状态。这个数据说明隔离内网环境下资源天花板决定了体验天花板该排队就排队比反复重试导致雪崩要强。7. 常见问题与排查实录7.1 依赖与镜像问题现象内网机器 pip install 时报 “Could not find a version that satisfies the requirement”。原因多半是离线 wheel 包里根本没有匹配当前 Python 版本和系统架构的轮子。解决办法是在构建机上用更严格的 platform tag 重新下载。如果是二进制包的 glibc 版本不匹配直接换 manylinux 标签或者改用纯源码包重新构建。另一个高频问题是 Docker 镜像导入后发现容器内缺 CUDA 库。这种优先检查基础镜像和推理镜像的 CUDA 版本是否一致建议统一用同一个 PyTorch 官方镜像作为底座。7.2 推理服务问题现象请求偶尔报 502过一会儿又自己恢复。大多是显存碎片化或者并发超限导致的。建议在推理服务端开启持久化日志观察最大并发数和显存峰值同时对单实例设置保守的 max_concurrency多实例横向扩展比单实例硬扛更稳。如果模型推理速度越来越慢看看是否上下文越积越长。对话历史无限累加会造成每次重新预填充整个历史复杂度陡增。务必要做上下文滑动窗口只保留最近 N 轮对话加系统提示词。7.3 Agent 行为问题现象Agent 乱调用工具比如回答“你今天怎么样”这种寒暄却去调了订单查询。排查思路是先确认工具描述是否清晰工具名和描述中关键词是否与真实业务术语接近其次看 prompt 里是否明确给出路由规则比如“只有涉及订单、物流、客户信息时才能调用数据库工具”。如果问题依旧就退化为路由模型单独做意图识别不要让同一个模型既做路由又做对话。另一种常见情况是 Agent 把多个工具的返回结果搞混A 客户的数据被当成 B 客户。这类问题靠 prompt 修不太稳最好是让每个工具返回时带上明确的实体标识客户 ID、订单号并在回答节点要求模型必须引用工具返回中的真实 ID 字段。7.4 日志与追踪问题隔离内网没有现成的云监控链路Agent 的调试往往像盲人摸象。我自己搭了一套极简方案在 FastAPI 中间件里为每个请求生成 trace_idLangGraph 的每个节点执行前后都往日志表写一条记录包含节点名、输入状态、输出状态、耗时。这样用户报问题后只要提供 trace_id我就能把整条链路的执行记录拉出来定位到具体是路由错了、工具超时了还是模型输出乱来了。日志表的设计不需要很复杂字段就五六个trace_id、节点名、输入摘要、输出摘要、耗时、创建时间。实测下来这套方案运维排查效率提升了不止一个量级。最后说点个人体会。隔离内网里做 AI Agent最大的难点反而不是模型效果而是被环境倒逼着把工程基本功做扎实依赖要可复现、资源要可计量、工具要有边界、链路要可追踪。这些都是好事公网项目可能靠着容错糊弄过去的问题在这里全部必须硬碰硬解决。后面如果条件允许我还会把模型监控、Prompt 版本管理、Agent 自动评估这几块补上让整条链路更完善。如果你也正在隔离环境里做 Agent希望这篇能帮你少走几步弯路。
阅读完成 · 觉得有帮助?