
最近帮客户把一个 AI Agent 从开发机搬到隔离内网前后折腾了将近一个月。网上大部分 Agent 教程都默认你能随时访问云端模型服务、能在线拉最新依赖、能随便调各种在线 API——可在隔离内网里这些前提会挨个崩掉模型文件动辄几十个 G 拿不进来、Python 依赖没法装、Agent 想用搜索工具连个外网都出不去。如果你也要做这件事会很快发现真正难的从来不是 Agent 框架怎么写而是怎么让它在没有互联网的环境里活下来。这篇文章就是我踩完坑之后整理的实战笔记内容包括离线模型部署、RAG 组件自建、工具调用改造、并发与观测适合要部署生产内网 Agent 的团队参考。1. 隔离内网里的 Agent先搞清楚“缺什么”再动手很多人一听到“隔离内网部署 Agent”第一反应是“把外网那套搬进来不就完了”。实际做起来会发现完全不是一回事因为隔离内网不是简单的“没网”而是整套技术供应链和环境假设都变了。1.1 “隔离”的是网络不是问题三个直接影响 Agent 的硬约束先说清楚隔离内网和普通办公网的区别。普通办公网虽然出口受限但还允许访问一些白名单站点能勉强下载东西真正的隔离内网则是按照安全管理要求把生产、研发环境严格限制在可控的网络区域里里面的机器通常无法直连云端模型服务也无法访问公共依赖源。这个环境对 Agent 的影响不是“少了个搜索功能”那么简单而是三大硬约束模型与依赖进不来大模型权重文件动辄十几到几十个 GPython 依赖有几十上百个包如果没有提前准备好进到内网就是两眼一抹黑。外部服务全部失效Agent 里常用的网页搜索、天气查询、地图服务、OCR 云接口、在线向量库、云端监控面板在内网环境一个都用不了必须找内网替代品或自己搭。算力与权限是固定的你在开发机上可以随便申请一张高配 GPU到了内网显卡数量、显存、CPU 内存、磁盘配额基本是固定的申请新资源可能要等审批。Agent 的设计必须反过来适配这些约束而不是让环境迁就你的模型规模。这三点叠加起来决定了内网 Agent 项目的首要任务不是“写智能体逻辑”而是“先把运行环境给它铺平”。我见过太多团队一上来就调 Agent 编排框架结果模型还没跑起来就卡在依赖安装上。1.2 动手前先做“要带进来的资产”和“能调用的内网资源”两份清单进入内网前我强烈建议先画两张表一张是“要带进来的资产清单”一张是“内网可用资源清单”。这两张表能帮你把所有隐含依赖一次性暴露出来而不是边写代码边发现缺东西。要带进来的资产通常包括类别具体内容备注模型权重LLM 主模型、Embedding 模型、Rerank 模型、OCR 模型注意确认量化格式和目录完整性推理框架vLLM、SGLang、Triton 等版本必须与 CUDA、驱动匹配Python 依赖Agent 框架、向量库客户端、文档解析库、HTTP 框架用 pip download 打成离线包工具资源内部 API 文档、数据库连接信息、业务系统说明给 Agent 写工具描述时要用内网可用资源清单则完全不同它问的是“我的 Agent 能调用哪些东西”内部业务系统的 API 网关地址和鉴权方式数据库、数据仓库的只读账号文件服务、内部文档站、知识库系统消息队列、任务调度平台内部监控和日志系统。这两份清单画完后你在设计 Agent 时就能明确知道哪些能力是现成的哪些能力必须本地搭哪些工具需要找业务方开接口。没有这个前置步骤后面一定会遇到“Agent 都写好了发现数据源连不上”的尴尬。1.3 核心策略把 Agent 的大脑、记忆、工具全部“内网化”依赖清单理清楚之后整个 Agent 的架构思路就很清晰了。本质上一个 Agent 系统由三部分组成大脑大模型、记忆向量库、知识库、会话历史、工具各种可调用的能力。在隔离内网里这三部分都要换成内网方案。大脑用私有化部署的 LLM通过 OpenAI 兼容接口或推理框架自带接口对外服务不再调用云端模型。记忆用本地向量数据库 内部数据库保存知识、历史、状态不依赖任何托管服务。工具把能做的操作封装成内部 API、数据库查询、命令行脚本通过函数调用机制暴露给 Agent。用一个简单的文字架构描述我实际搭建的系统内部用户 → 内部门户/API网关 → Agent编排层LangGraph/自研状态机 → LLM推理网关vLLM提供openai兼容接口 → 工具层内部业务API、参数化SQL查询、文档检索服务 → 日志与审计trace_id贯穿全链路组件之间全部走内网域名或 Service 地址不依赖任何外部出口。这个架构看起来平淡无奇但恰恰是它能上生产的关键——每一层都是内网里已有的组件或者能顺利部署的组件。对大多数团队来说把复杂留在编排和工具设计里而不是留在网络访问上才是正路。2. 模型与推理底座把“大脑”搬进门的完整流程模型是整个 Agent 系统里最重的依赖也是内网部署时最容易出问题的地方。这一节我把从选型、下载校验到启动调优的完整流程展开讲每一步都标注了值得注意的细节。2.1 选模型的判断标准不是在选“最强”是在选“能跑且好维护”开发阶段你可能习惯用云端最强模型跑效果但在隔离内网模型选型的逻辑必须完全反过来先看算力再选模型。否则就算你把 70B 的模型文件辛苦搬进内网发现单卡显存放不下推理速度慢到 Agent 无法用那时候再换就非常痛苦了。我整理了一个适用于内网 Agent 的模型选型参考表参数量级精度/量化显存需求参考适合场景7BFP16 约 14GBINT4 约 5GB单卡即可工具调用、简单问答、低延迟场景14BFP16 约 28GBAWQ/INT4 约 9GB单卡 24G 可跑量化版中文理解、中等复杂任务内网首选32BFP16 约 65GBINT8 约 35GB多卡复杂推理、长流程规划70BINT8 约 70GB多卡且资源充足非必要不上维护成本高我给客户的首选一般是 14B 量化版能力足够做工具调用和中等复杂度的 Agent 任务显存压力小推理速度快出了问题也好排查。如果你所在团队有大量中文文档处理需求14B 级别的模型在语言理解上通常已经够用。另外要提醒一点不要迷信模型宣传的“超长上下文”。Agent 场景下上下文越长显存占用越大推理越慢。内网环境资源固定很多时候把 max-model-len 设置在 8192 或 16384 就够了强行上几十万上下文只会拖垮整个系统。2.2 离线模型文件导入前的校验与“预跑”验证模型选好之后接下来就是最容易被忽视、也最坑的一步把模型文件安全、完整地带进隔离内网。关于如何获取模型文件我只能说一种合规且通用的做法在你获准访问外网资源的环境中提前下载好所需模型经过完整性校验后再按单位的数据导入审批流程导入内网。整个过程必须走正规程序不要在安全边界上动脑筋。操作上有几个关键细节优先下载 safetensors 格式相比老式的 .bin 权重safetensors 加载更安全、更稳定很多框架默认优先读取它。下载完整目录不只是权重文件还要包含 config.json、tokenizer 相关的几个文件。缺 tokenizer 文件是内网启动失败的头号原因。校验 sha256不要只信文件大小。推荐下完后在本地算一遍哈希值和官方公布的哈希比对确认没有文件损坏。先“预跑”再进内网这一步强烈建议做。在还有外网或本地有同等 GPU 环境时用官方推理脚本把模型跑一次确认能正常加载、能正常生成回复再导入内网。否则文件进内网后才发现启动失败排查成本会高很多。别小看预跑这一步。我有一次在内网部署时启动报错查了半天发现是某个依赖版本不匹配而这是完全可以在预跑阶段发现的。内网环境里很多问题不是因为环境特殊而是因为少了一次“事前验证”。2.3 推理服务的启动参数与并发容量预估模型文件就位后就轮到推理服务上线。我习惯用 vLLM 这类高效推理框架因为它支持连续批处理能让 GPU 在并发请求下保持高吞吐这对 Agent 场景尤其重要——Agent 一次任务要多次调用 LLM单请求如果慢整个任务的体验就会非常差。一个典型的 vLLM 启动命令长这样vllm serve ./models/Qwen2.5-14B-Instruct \ --quantization awq \ --max-model-len 8192 \ --gpu-memory-utilization 0.90 \ --tensor-parallel-size 2 \ --served-model-name local-llm \ --port 8001几个关键参数解释一下--quantization awq指定量化方式必须和模型文件的量化格式一致否则会报错--max-model-len 8192限制最大序列长度直接影响显存占用超长文本需求不强烈时别调太大--gpu-memory-utilization 0.90控制预留给模型 KV Cache 的显存比例不是越高越好建议给系统留一点余量--tensor-parallel-size 2跨两张卡做张量并行如果只有单卡就不加这个参数--served-model-name local-llm给模型起一个内部服务名之后 Agent 调用时用这个名称。推理服务启动后我建议第一时间做一个简单的并发压测确认它能扛住多少并发。用 requests 写一个小脚本就很够用import requests import time import concurrent.futures def call_llm(prompt): t0 time.time() resp requests.post( http://model-gateway:8001/v1/chat/completions, json{model: local-llm, messages: [{role: user, content: prompt}], max_tokens: 512}, timeout120, ) return {code: resp.status_code, elapsed: time.time() - t0} with concurrent.futures.ThreadPoolExecutor(max_workers10) as pool: results list(pool.map(call_llm, [内网部署需要注意什么] * 10)) print(results)压测时重点看两个指标TTFT首 Token 耗时和TPOT每个 Token 的平均生成耗时。Agent 场景下TTFT 过长会让用户觉得“卡住了”TPOT 过长则会让长回复难以等待。一般来说TTFT 控制在 2 秒内、TPOT 控制在每 Token 30-50 毫秒左右体验才勉强可用。并发容量的估算有一个很朴素的口诀先测单请求耗时再看 GPU 能同时跑多少个请求。比如单请求生成 1000 个 Token 需要 40 秒如果你想做到 10 个并发同时跑就要保证 vLLM 的 Continuous Batching 在同样的 40 秒窗口内吃掉 10000 个 Token这取决于显存和模型优化程度。这也是外界老问“AI Agent 怎么扛并发”的答案起点——先扛住 LLM 网关的并发再谈 Agent 编排层的并发。3. 记忆与知识库向量检索和文档解析要做到“自给自足”隔离内网里的 Agent知识来源不能靠云端搜索只能依赖本地知识库和内部数据。这一节讲我把 RAG 链路完整搬到内网的过程中沉淀下来的选型逻辑和实操经验。3.1 Embedding模型与向量库选型别让记忆组件拖垮AgentRAG 链路的第一步是把文本向量化。在隔离内网里Embedding 模型同样要本地部署。选型时我只看三个指标中文效果、向量维度、上下文长度。中文效果不解释向量维度直接决定向量库占用内存的大小上下文长度则决定了单条文本能编码多长的语义。以常见的开源 Embedding 模型为例有的默认维度 1024有的支持长文档有的轻量到 CPU 也能跑。我的建议很直接如果知识库以中文短文本为主选轻量中文模型即可加载快、占用少如果知识库里混着大量长文档再考虑支持长上下文的模型同时接受更高的显存或内存开销。向量库的选型和 Embedding 一样不要一上来就上重武器。我按实际规模做了一个对比向量库部署模式适合场景注意点FAISS库文件形式嵌入你的服务百万级以下、单机为主写入和检索在同一进程多服务共享麻烦LanceDB嵌入式向量库本地轻量服务、快速原型支持多进程数据落在本地目录Milvus独立分布式服务生产级、千万级向量、多团队共享组件多部署和运维成本较高Elasticsearch已有 ES 则复用需要全文检索和向量混合查询必须提前设计向量字段 mapping我当时选择的是 FAISS 起步、后续切 Milvus 的路线。原因很简单初期知识库只有几十万条FAISS 单机完全够用部署成本几乎为零等数据量涨上来或者需要多团队共享时再平滑迁移到独立向量库服务。这里有两个容易踩的坑。第一别把 Embedding 模型直接加载在 Agent 进程里。如果 Agent 进程又要跑 LangGraph、又要加载 LLM、又要加载 Embedding内存妥妥爆掉。正确做法是把 Embedding 服务单独封装成一个小服务Agent 通过 API 调用它做向量化。第二向量维度要提前固定。如果你之后换一个维度不同的 Embedding 模型历史向量全部作废得重新索引。所以先定好模型再建库不要中途换。3.2 文档解析与清洗知识库质量比模型参数数量更关键RAG 效果好不好七分在文档解析和分块三分在检索。内网知识库常见的文件是 PDF、Word、扫描件每类都有对应的处理方案文本型 PDF用 PyMuPDF 这类库直接提取文字速度快适合电子版文档扫描件 PDF需要 OCR我用 PaddleOCR 或 RapidOCR 做本地识别精度够用且完全离线Word 文档用 python-docx 提取段落和表格注意表格要单独结构化处理Excel 报表最好转成结构化记录或 Markdown 表格再决定是入库还是走数据库查询。解析之后不能直接切片丢进向量库必须先做清洗。我一般按这套流程处理提取正文去掉页眉页脚、水印、干扰符号按标题层级切分成块每块控制在 300~500 字块与块之间留 50 字左右重叠表格单独提炼成结构化文本保留表头和关键数值每块打上元数据包括来源文档、章节路径、页码方便之后引用溯源最后才做向量化入库。这个流程看起来平淡但很多人省略了第二步和第四步。如果不保留章节路径和页码Agent 回答时就算检索到了内容也说不清它来自哪份文档这样的回答在生产环境是不敢直接展示给用户的。引用溯源能力在封闭环境里尤其重要因为它决定你对 Agent 的回答有没有信心。3.3 RAG检索链路的本地化实现从检索到引用的关键细节向量库和文档处理就位后RAG 的检索链路我建议做成一个独立服务而不是把检索逻辑散落在 Agent 代码里。服务化的好处是可以复用团队其他人也能直接调用这个检索能力。一个本地化 RAG 检索链路通常包含这几步Query 改写用户口语化提问先让 LLM 转成更适合检索的关键词或子问题能明显提升召回质量混合检索向量检索 关键词检索并行关键词检索可以借用 ES 或数据库的全文索引能兜住向量检索在专有名词上的短板Rerank 重排用 Rerank 模型对召回结果重新排序把最相关的几段顶到前面组装 Prompt把检索结果按“引用编号”塞进上下文明确要求 LLM 只依据这些内容回答并在答案中标出引用编号输出带溯源的答案后端再把引用编号映射回具体文档和章节。你可能会问在内网部署一套包含向量化、检索、重排的链路是不是太重了我的体会是前期可以砍掉 Rerank先靠向量 关键词跑起来但 Query 改写和引用溯源最好一开始就做因为它们直接影响回答质量和可信度。而且这些组件全部是内网开源自建不会产生外部依赖完全符合隔离要求。4. Agent 编排与工具调用把每个“在线能力”换成“内网能力”模型和知识库解决了“大脑”和“记忆”接下来最核心的是“工具”。Agent 和普通问答最大的区别就是它能调用工具去完成真实任务。在互联网环境里工具到处都能接在隔离内网里每个工具都要重新设计。4.1 LangChain/LangGraph本身没问题问题出在工具层先给一个结论LangChain、LangGraph 这类编排框架本身不依赖外网它们只是 Python 代码打包好依赖之后在内网完全可以运行。真正需要改造的是框架里默认接的那些在线工具以及你为 Agent 注册的每个工具调用逻辑。我见过一个蛮常见的情况团队在外网 Demo 阶段用了大量现成的在线组件比如网页搜索、在线文档加载器、云端向量库Demo 跑得很爽。结果一到内网所有组件全部失效代码层层报错最后只能推倒重来。在隔离内网里工具层的基本替代原则是在线工具/能力内网等价方案网页搜索内部文档站检索、知识库检索、数据库查询天气、日历等公共 API内部业务系统接口或直接不做云端 OCR本地 PaddleOCR 服务云端向量库本地 FAISS / Milvus第三方消息推送内部消息中间件或办公系统接口在做工具规划时建议先盘点内网已有的数据和系统把“能通过 API 查询的信息”和“能通过脚本操作的能力”分别列出来再决定给 Agent 暴露哪些工具。工具不是越多越好而是越精准越好——每个工具都要让 Agent 容易理解、容易调用。4.2 工具注册与Schema设计让LLM准确选工具的关键Agent 选工具靠的是大模型的 Function Calling 能力。LLM 会根据工具的“名称、描述、参数说明”判断该调用哪个工具、传入什么参数。所以工具描述写得清不清楚直接决定 Agent 能不能正确使用工具。以内网订单查询为例一个工具注册的代码片段大概是这样的tool def query_order_status(order_id: str) - str: 查询内部订单状态仅支持公司内部订单编号。参数说明 order_id: 内部订单号字符串例如 SO-2025-001 # 内部实现调用内部订单系统的 API 或数据库 result internal_order_client.query(order_id) return result但光有这个函数还不够真正喂给 LLM 的是 JSON Schema。我在实践中会显式声明参数类型、格式和必填项{ name: query_order_status, description: 根据内部订单号查询订单当前状态。仅支持公司内部订单编号格式为 SO-YYYY-NNN。, parameters: { type: object, properties: { order_id: { type: string, description: 内部订单号例如 SO-2025-001 } }, required: [order_id] } }关键词都在描述里包括编号格式和示例值LLM 照着填参数的成功率会明显上升。反过来如果工具描述写得很笼统比如“查询订单信息”LLM 可能不知道 order_id 该传什么甚至会自己编一个编号出来。这类问题在封闭环境调试时特别明显因为查不到真实数据时模型更容易“自由发挥”。我还有一个习惯对高风险工具加上参数校验和白名单校验。比如数据库查询工具绝不允许 Agent 传任意 SQL只能走封装好的参数化查询涉及内部人员信息查询时还要限制只能查特定范围。这不是保守是生产环境的基本要求。4.3 并发控制Agent扛不住并发往往先扛不住LLM网关回到“AI Agent 怎么扛并发”这个话题。很多团队问这个问题时都以为是要调 Agent 框架的并发参数其实真正的瓶颈几乎总是在底层。Agent 一次任务要多次访问 LLM还要串行调用工具如果 LLM 网关先崩了Agent 层再怎么优化都没用。我在内网环境用的策略很简单控制 Agent 层的在途并发给 LLM 网关留出稳定空间。用 Python 的话加一个信号量就能做最基本的限制import asyncio sem asyncio.Semaphore(8) async def run_agent(query: str): async with sem: # 内部会多次调用 LLM 和工具 result await agent_executor.run(query) return result这里的 8 就是允许同时运行的 Agent 任务数要根据压测数据来定不能拍脑袋。如果 LLM 网关测出来最多能同时处理 20 个请求而每个 Agent 任务平均要调用 LLM 3 次那 Agent 层并发设置在 6-8 比较稳妥。留点余量比把 GPU 打满然后全网超时要好得多。除了并发上限还有两个必须做的设置超时LLM 调用和工具调用都要设超时Agent 整体执行也要设超时。内网服务偶尔会慢没有超时一个卡住的任务会占住一个并发额度不放。重试内部服务抖动时重试能救回很多请求。我一般用指数退避第一次 1 秒、第二次 2 秒、第三次 4 秒超过 3 次就放弃并记录错误。另外如果 Agent 任务本身耗时长别用 HTTP 同步请求硬扛。正确做法是接入内部消息队列把 Agent 任务异步化用户提交请求后立刻返回“任务受理”后台 Worker 消费任务执行 Agent 流程执行完再通过内部消息或查询接口反馈结果。这在大并发场景几乎是必须的。4.4 长耗时任务别用HTTP硬扛异步化与重试策略承接上面说的Agent 任务一旦涉及多轮工具调用耗时很容易超过 30 秒甚至几分钟。此时如果前端页面一直等待 HTTP 响应体验会很差而且网关层也可能断连。我的做法是分两类处理短任务预期 10 秒内完成同步执行前端转圈等待超时设 30 秒长任务涉及数据库批量操作或多轮流程提交到内部任务队列后台执行前端轮询任务状态。任务队列可以用团队已有的 RabbitMQ、RocketMQ 或 Kafka如果没有先用 Redis 列表也能撑一阵子。重点是设计好任务状态表待执行、执行中、成功、失败、超时并在每个状态变更时记录 trace_id、入参、出参。这样后面排查问题才有据可循。5. 可观测性与效果调优内网没有“云端监控”就自己造一个在线环境里各种监控面板、日志平台、链路追踪服务都是现成的。隔离内网里这些也未必齐全所以必须用最小成本把“可观测性”做出来。否则 Agent 一旦出问题你会发现自己对着黑盒完全无从下手。5.1 用trace_id把一次Agent请求从头串到尾Agent 应用比普通接口复杂得多一次用户请求可能会触发多次 LLM 调用、多次工具调用中间还可能经过异步队列。如果日志里没有统一的追踪标识出了问题根本没法把链路串起来。我在所有 Agent 项目里都会在入口生成一个 trace_id然后在每个关键节点输出结构化日志格式类似{ ts: 2025-01-15T10:30:00.123Z, trace_id: 0a1b2c3d4e5f6a7b, event: tool_call, tool: query_order_status, args: {order_id: SO-2025-001}, latency_ms: 234, status: success }建议在以下节点都打日志请求入口、Agent 编排开始、每次 LLM 调用含 prompt 摘要和耗时、每次工具调用含参数和返回摘要、Agent 最终输出、异常和超时。日志统一走内部的日志采集通道如果内网有 ELK 或 Loki 就用没有就先落本地文件按天滚动后期再接入采集。有了统一的 trace_id再配合每个步骤的耗时记录你就能回答三个核心问题用户这个请求经历了哪些步骤每一步花了多久哪一步是瓶颈5.2 BadCase库离线Agent效果迭代的燃料模型和 RAG 的效果不是一锤子买卖需要持续迭代。迭代的第一步是收集失败案例。我建议做一个简单的 BadCase 库把每次 Agent 表现不佳的情况存下来字段包括用户原始问题Agent 最终回答中间工具调用记录用户反馈或人工标注满意/不满意/错误原因关联的 trace_id这些数据存在内部数据库里每周做一次聚类分析看看失败主要来自哪几类检索没召回、工具参数填错、模型不遵循指令、知识库内容缺失、还是上下文超长被截断。没有这个 BadCase 库你对 Agent 的优化基本靠猜。有了它你可以针对性地调 Query 改写逻辑、调检索分块大小、调工具描述、甚至换模型。内网环境没有在线评测集可以依赖自己维护 BadCase 和评测集就是最靠谱的迭代方式。5.3 关键性能指标用数据和日志判断“要不要调”除了效果问题性能问题也要用数据说话。我通常维护一张简单的指标表指标含义健康参考TTFT首 Token 耗时2 秒以内TPOT每 Token 生成耗时30-50 毫秒总耗时单任务从开始到结束的时长看任务复杂度工具调用失败率工具执行失败次数 / 总调用次数低于 5%Agent 任务成功率成功完成任务数 / 总任务数目标 95%超时率触发超时的任务占比低于 1%这些指标完全可以从日志里统计出来不需要额外引入监控平台。我一般每天跑一个定时脚本统计前一天的数据超过阈值就拉出来分析。千万别等到用户投诉了才想起来查日志那会非常被动。6. 隔离内网实战中反复出现的坑与排查经验最后一节我把这次实战中反复踩到的坑集中整理出来。这些坑看起来都不起眼但每一个都让我在机房、会议和深夜排查里浪费过不少时间。希望你能直接跳过。6.1 模型文件和依赖的“最后一公里”问题内网部署最常见的启动失败原因往往不是框架问题而是模型文件或依赖包不完整。几个我见过的高频问题模型目录里缺少 tokenizer 配置文件启动时报错“tokenizer config not found”下载的是量化模型但没有把量化配置文件一起放入目录vLLM 启动时识别不了模型的 safetensors 文件在传输过程中损坏加载时直接报错Python 依赖包版本和推理框架不兼容比如 vLLM 依赖的 CUDA 版本和机器驱动不匹配。解决方法分两条腿走一是导入前严格执行 sha256 校验和预跑验证二是在内网准备一个私有的依赖包仓库或离线 wheel 包目录。依赖版本最好锁定不要用“最新版”隔离环境升级一次代价很大锁定版本更稳妥。6.2 显存、磁盘、权限环境问题比代码问题更容易卡住代码层面的问题往往好查环境层面的问题反而能卡几天。举几个真实的例子模型文件导入后发现所在磁盘分区快满了向量库索引根本建不完服务用非 root 用户启动但模型目录权限没放开启动即 Permission Denied多机部署时把模型文件同步到另外几台机器其中一台软链接断了一半运行到中途才报错GPU 驱动版本太旧vLLM 启动时提示 CUDA 版本不支持。这些问题的共同特点是在开发机上根本不会出现只有到了真实环境才爆出来。我建议在内网部署前就做一次“环境体检”逐项确认磁盘空间、目录权限、GPU 驱动、CUDA 版本、可用的端口省得部署到一半被环境问题打断。6.3 封闭环境里Agent“幻觉”会被放大怎么压制在互联网环境里Agent 偶尔胡说八道一下用户可能当个乐子。但在内网业务场景里如果 Agent 把一个订单状态说错了、把一个审批结论编出来了后果很严重。我总结了三个压制幻觉的实用手段工具先行凡是能通过工具查到的信息一律先调用工具不要让模型凭记忆回答。比如用户问“这个订单到哪一步了”必须触发订单查询工具而不是让模型猜。严格限定回答来源在系统提示词里明确写“只能基于检索内容和工具返回结果作答如果信息不足直接告知用户不知道不要编造”。关键回答加引用溯源涉及业务数据时强制要求模型在答案中标注信息来源编号后端再把编号映射到具体文档或查询记录。另外从设计角度讲高风险操作比如审批、删除、转账不应该由 Agent 直接执行。Agent 可以帮你把操作准备好但最终执行要有人工确认环节。这不是技术保守而是生产环境的基本安全意识。6.4 从Demo到生产最小闭环和回滚意识内网 Agent 项目很容易陷入两种极端要么一直在技术 Demo 阶段打转要么一上来就想做一个“超级智能体”然后被复杂度拖垮。我的建议是先从最小闭环开始。最小的生产级闭环是一个本地 LLM 一个知识库检索工具 一个业务数据查询工具完成一个具体场景比如“查询订单进度并说明当前卡点”。把这个闭环跑稳、指标跑好、BadCase 库跑起来再逐步加工具、加编排节点。每次新增能力都要有对应的评测数据和回滚方案。模型文件也一样保留上一版模型文件的备份新模型上线后如果效果回退能快速切回旧版本。Agent 系统的配置最好能集中管理这样切换模型、调整 prompt、开关工具都只要改配置不需要重新发版。最后说点个人体会。项目结束后我最大的感受是隔离内网不是 Agent 工程的限制反而是一种倒逼你把架构做干净的约束。没有外部服务可用你只能把每一层都搞清楚、把每个依赖都固化下来这会让系统变得可控、可维护。如果你正准备做类似的事情别贪大先让一个最小 Agent 稳定跑通再一点一点往上加复杂度。内网里的每一次试错成本都比在开发机高得多所以前期的规划、资产清单和环境体检比写代码本身更重要。