
1. 为什么要在局域网里自建 AI Agent 平台1.1 从“调用云端 API”到“把模型搬进机房”的转变过去一年我身边不少做企业内部工具的朋友都遇到同一个尴尬业务部门想用大模型做知识问答、文档摘要、工单分类但数据不能出内网采购流程又走不动。于是“局域网里跑一个能对话、能调工具、能接内部系统的 AI Agent 平台”就成了刚需。DeepSeek 系列模型在中文理解、代码生成、长文本推理上的表现配合 Docker 的标准化交付恰好能拼出一套成本可控、维护简单的方案。这里说的“Harness”你可以理解成一套模型运行外壳 Agent 调度框架的组合它负责把模型权重加载起来暴露兼容 OpenAI 风格的接口同时提供工具调用、会话管理、流式输出这些 Agent 必备能力。把它 Docker 化之后整个平台就变成一个可复制、可迁移、可版本控制的“黑盒”换台机器照样跑。1.2 局域网部署到底解决了哪些真实痛点第一是数据边界清晰。所有推理请求、对话记录、上传的文档都留在内网不经过任何外部链路这对法务、财务、研发这类敏感部门尤其重要。第二是延迟稳定。局域网内千兆甚至万兆互联首 token 延迟通常能压到几百毫秒级别比公网调用体验好很多。第三是成本可预期。一次性投入显卡或租用内网算力后续没有按 token 计费的焦虑高频调用场景下摊薄成本非常明显。第四是可定制。你可以在 Harness 层挂载自己的工具函数比如查内部数据库、调工单系统、读共享盘文件让 Agent 真正“长”在业务里而不是一个只会聊天的玩具。第五是可离线。断外网也能跑适合生产车间、实验室、涉密办公区这类环境。1.3 这套方案适合谁不适合谁适合的人群很明确有基本 Linux 和 Docker 操作经验的后端或运维同学手里有一到两张消费级或专业级显卡、想先做原型验证的团队以及需要给内部多个部门提供统一 AI 入口的平台建设者。不太适合的情况也要说清楚如果你只是偶尔用几次、对数据边界没有硬要求直接调云端 API 更省事如果你完全没有显卡、也不打算采购纯 CPU 推理大模型的速度会让你怀疑人生。另外Harness 本身不是“一键傻瓜包”它需要你理解端口映射、卷挂载、显存分配这些基础概念否则排查问题会很痛苦。2. 部署前的整体设计与选型思路2.1 硬件与操作系统的底线要求先说显卡。以 7B 到 14B 参数级别的模型为例FP16 精度下大约需要 14GB 到 28GB 显存量化到 INT8 或 INT4 后可以压到 8GB 到 16GB。我实测下来单张 16GB 显存的卡跑 7B 量化模型做 Agent 调度是够用的但如果要并发处理多个会话建议 24GB 起步。CPU 方面现代 8 核以上基本不会成为瓶颈内存建议不低于 32GB因为 Docker 镜像、模型缓存、会话上下文都会吃内存。操作系统优先选 Ubuntu 22.04 或 24.04 LTS内核版本新、驱动兼容性好。如果你用的是其他发行版只要 Docker 和 NVIDIA Container Toolkit 能正常装问题也不大。磁盘方面模型文件动辄十几 GB加上镜像和日志建议预留至少 100GB 的 SSD 空间机械盘加载模型会慢到让你想砸键盘。2.2 Docker 与 GPU 运行时的准备逻辑Docker 本身不难装难的是让容器里的进程能看见宿主机的 GPU。核心是三步装好宿主机显卡驱动装好 NVIDIA Container Toolkit然后在docker run时加上--gpus all或者更精细的--gpus device0。很多人卡在“容器里nvidia-smi报错”九成是 Toolkit 没装或者 Docker 服务没重启。注意驱动版本和 CUDA 版本要匹配。容器镜像里自带的 CUDA 运行时版本不能高于宿主机驱动支持的上限否则会报 “CUDA driver version is insufficient” 这类错误。选镜像前先查一下宿主机驱动对应的 CUDA 最高版本。2.3 网络与端口规划局域网部署的核心是“让内网其他机器能访问”。你需要规划三样东西容器内部服务端口、宿主机映射端口、以及内网访问地址。通常 Harness 会暴露一个 HTTP 端口比如 8000 或 8080你把它映射到宿主机的某个端口内网用户通过http://宿主机内网IP:端口访问。如果要做多实例或者前后端分离建议用 Docker Compose 管理把模型服务、Web 前端、反向代理分成不同容器通过自定义 bridge 网络互通。这样后续扩容或替换组件时不用推倒重来。防火墙方面确认宿主机和内网交换机没有拦截目标端口很多“部署成功但别人访问不了”的问题都出在这里。3. 核心细节解析与实操要点3.1 镜像选择官方、社区还是自构建镜像来源一般有三种。第一种是模型官方或框架官方提供的镜像优点是可信度高、更新及时缺点是往往只包含最基础的服务Agent 相关的工具链要自己补。第二种是社区维护的“全家桶”镜像集成了 Web UI、工具调用、会话管理开箱即用但要注意版本滞后和安全审计。第三种是自己写 Dockerfile 构建灵活度最高适合有明确定制需求的团队。我的建议是原型阶段先用社区镜像快速跑通验证效果进入生产前基于官方基础镜像自己构建把依赖版本、启动脚本、健康检查都固化下来。这样既省了前期时间又避免了后期被社区镜像的“黑盒”坑到。3.2 模型文件的挂载与缓存策略模型文件不要打进镜像里否则镜像体积会膨胀到几十 GB推送和拉取都痛苦。正确做法是把模型放在宿主机的一个目录通过-v /data/models:/app/models这种方式挂载进容器。这样镜像保持轻量模型可以独立更新。缓存策略上Hugging Face 风格的模型加载会默认往~/.cache写东西容器里这个路径是临时的重启就没了。建议把缓存目录也挂载出来或者通过环境变量指定到挂载点。另外如果你有多张卡可以通过环境变量控制模型切分方式比如张量并行度让显存利用更均衡。3.3 环境变量与启动参数的关键项启动容器时环境变量决定了服务的行为。常见的几个关键项包括模型路径、监听地址、监听端口、最大并发数、上下文长度、量化精度、是否启用工具调用。这些参数不是拍脑袋定的要根据显存和业务场景算。举个例子上下文长度设成 8192 还是 32768直接影响到单次请求的显存占用。上下文越长KV Cache 越大并发能力就越弱。如果业务主要是短问答8192 足够如果是长文档分析就得权衡并发数和上下文长度。我一般会先设一个保守值压测后再逐步调大观察显存和延迟曲线。3.4 工具调用与 Agent 能力的接入方式Agent 和普通聊天机器人的区别在于“能动手”。Harness 通常提供工具注册机制你可以用 JSON 或 Python 函数描述工具的名称、参数、返回值模型在对话中判断是否需要调用。接入内部系统时建议把工具封装成独立的微服务Harness 只负责调度这样权限控制和审计都好做。注意工具调用的超时和异常处理必须做。模型可能会生成格式错误的参数或者调用一个暂时不可用的服务。如果没有兜底逻辑整个会话就会卡死。我的做法是给每个工具设 5 到 10 秒超时失败时返回结构化错误信息让模型自己决定是重试还是告知用户。4. 实操过程与核心环节实现4.1 宿主机环境准备与驱动安装第一步确认显卡被系统识别。执行lspci | grep -i nvidia能看到显卡型号说明硬件层面没问题。然后安装驱动Ubuntu 下可以用ubuntu-drivers devices查看推荐版本再用apt install安装。装完后nvidia-smi能输出显卡信息、驱动版本、CUDA 版本才算过关。第二步安装 Docker。官方脚本一行命令搞定但生产环境建议用 apt 仓库方式方便版本管理。装完后把当前用户加入 docker 组避免每次都要 sudo。第三步安装 NVIDIA Container Toolkit配置好 runtime 后重启 Docker 服务。验证方法是跑一个测试容器docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi能看到显卡信息就说明容器能访问 GPU 了。4.2 目录规划与模型下载我习惯在宿主机上建一个统一的工作目录比如/opt/ai-platform下面分models、data、logs、config四个子目录。models放模型权重data放会话记录和上传文件logs放服务日志config放配置文件和启动脚本。这样备份和迁移都很清晰。模型下载可以用命令行工具也可以用 Python 脚本。下载前确认磁盘空间和网络带宽十几 GB 的文件在慢速网络下可能要几个小时。下载完成后校验文件完整性避免因为传输中断导致加载失败。如果内网有多台机器需要同一模型可以搭一个内网文件服务避免重复下载。4.3 启动容器与参数配置实战下面是一个典型的启动命令结构我把它拆开讲每个参数的意义docker run -d \ --name deepseek-harness \ --gpus device0 \ -p 18080:8000 \ -v /opt/ai-platform/models:/app/models \ -v /opt/ai-platform/data:/app/data \ -v /opt/ai-platform/logs:/app/logs \ -e MODEL_PATH/app/models/deepseek-7b-int8 \ -e LISTEN_HOST0.0.0.0 \ -e LISTEN_PORT8000 \ -e MAX_CONCURRENCY4 \ -e CONTEXT_LENGTH8192 \ --restart unless-stopped \ your-harness-image:latest--gpus device0指定用第一张卡多卡时可以写device0,1。-p 18080:8000把容器内 8000 映射到宿主机 18080内网用户访问 18080。三个-v分别挂载模型、数据、日志。环境变量里MAX_CONCURRENCY4是我根据 16GB 显存和 8192 上下文估算的保守值实际可以压测调整。--restart unless-stopped保证宿主机重启后容器自动拉起。4.4 验证服务与内网访问测试容器起来后先看日志docker logs -f deepseek-harness确认模型加载完成、服务监听正常。然后在宿主机上curl http://127.0.0.1:18080/health返回健康状态说明服务本身没问题。接着从内网另一台机器访问http://宿主机内网IP:18080/health如果能通说明网络和防火墙配置正确。最后做一次真实对话测试发一个简单的请求观察响应时间和输出质量。如果首 token 延迟超过几秒可能是模型加载没完成或者显存不足在换页。如果输出乱码或截断检查上下文长度和编码配置。这一步不要跳过很多问题在真实请求下才会暴露。4.5 用 Docker Compose 管理多组件当平台组件变多时单个docker run命令会变得难以维护。这时候用 Docker Compose 把模型服务、Web 前端、反向代理编排起来。Compose 文件里定义服务、网络、卷、环境变量一条docker compose up -d全部拉起。更新时改镜像标签docker compose pull docker compose up -d即可滚动更新。Compose 的另一个好处是网络隔离。自定义 bridge 网络里容器之间用服务名互相访问不用暴露多余端口到宿主机。前端容器只需要暴露一个端口给内网模型服务端口完全内部化安全性更好。5. 常见问题与排查技巧实录5.1 容器启动失败与显存相关报错最常见的报错是 “CUDA out of memory”。原因通常是模型太大、上下文太长、并发太高三者叠加。排查顺序先看nvidia-smi确认显存占用再把MAX_CONCURRENCY降到 1把CONTEXT_LENGTH降到 4096看能否启动。如果能启动说明是资源不够需要量化模型或者换更大显存的卡。另一个常见报错是 “no CUDA-capable device is detected”。这基本是 NVIDIA Container Toolkit 没配好或者--gpus参数没加。检查docker info里有没有 nvidia runtime没有就重新配置 Toolkit 并重启 Docker。5.2 内网访问不通的排查路径访问不通分几种情况。第一种宿主机本地能访问内网其他机器不能。这通常是防火墙拦截检查ufw status或iptables -L放行对应端口。第二种端口映射写错比如-p 18080:8000写成了-p 8000:18080方向反了。第三种宿主机有多个网卡服务只监听了 127.0.0.1需要把LISTEN_HOST改成0.0.0.0。还有一种隐蔽情况内网有多个网段访问方和宿主机不在同一网段路由没通。这种要用traceroute或ping逐跳排查确认网络层可达。5.3 模型加载慢与推理延迟高的优化模型加载慢通常是磁盘 IO 瓶颈。把模型放在 SSD 上加载时间能从几分钟降到几十秒。如果模型文件是分散的小文件打包成单个大文件也能提速。推理延迟高则要看是首 token 慢还是后续 token 慢。首 token 慢一般是 prompt 处理阶段计算量大可以缩短系统提示词后续 token 慢可能是显存带宽不足或并发争抢降低并发数试试。量化是另一个有效手段。INT8 量化通常能减少一半显存占用速度损失在可接受范围内。INT4 更激进但精度下降明显适合对质量要求不高的场景。我一般先用 INT8 跑效果不够再考虑其他方案。5.4 常见问题速查表现象可能原因排查动作解决方向容器启动即退出模型路径错误或显存不足看docker logs最后 50 行修正挂载路径降低并发或上下文容器内看不到 GPUToolkit 未装或未重启 Dockerdocker info查 runtime重装 Toolkit重启 Docker内网访问超时防火墙拦截或监听地址错误本地 curl 对比内网 curl放行端口改监听 0.0.0.0首 token 延迟高prompt 过长或模型未预热发短请求对比精简系统提示加预热请求输出截断上下文长度不够检查请求 token 数调大 CONTEXT_LENGTH工具调用失败参数格式错误或服务不可用看工具服务日志加超时和兜底返回5.5 几个我踩过的坑和独家技巧第一个坑镜像里的默认用户权限和挂载目录权限不匹配导致容器写日志失败。解决方法是启动时加--user $(id -u):$(id -g)或者提前把挂载目录权限放开。第二个坑模型缓存目录没挂载每次重启都重新下载浪费大量时间。后来我把缓存目录也挂出来重启秒起。第三个技巧给服务加一个/health健康检查接口配合 Docker 的HEALTHCHECK指令容器异常时能自动重启。第四个技巧日志用 JSON 格式输出方便后续接入日志收集系统。第五个技巧把常用配置写成.env文件Compose 自动读取不用每次改命令行。6. 平台上线后的维护与扩展思路6.1 日常监控与日志管理平台跑起来只是开始后续要关注三件事显存占用、请求延迟、错误率。显存占用可以用nvidia-smi定时采集或者接入 Prometheus 的 GPU exporter。请求延迟和错误率从服务日志里统计建议用结构化日志方便聚合分析。日志量大了之后本地文件会迅速膨胀。可以配置日志轮转按大小或天数切割保留最近若干份。如果内网有日志收集系统把容器日志直接输出到标准输出由收集器统一拉取省去本地管理。6.2 多模型共存与灰度切换业务场景多了之后一个模型可能不够用。有的任务需要强推理有的需要快响应。可以在同一台机器上跑多个模型实例用不同端口区分前端根据任务类型路由。显存不够时用按需加载的方式不常用的模型先卸载请求来了再加载。灰度切换是另一个实用能力。新模型上线前先切一小部分流量过去对比输出质量和延迟确认没问题再全量。Docker 的镜像标签和 Compose 的服务定义让这个过程很顺滑改个标签重启即可。6.3 安全加固与权限控制局域网不等于绝对安全基本的加固还是要做。第一服务不要用 root 跑容器里建个普通用户。第二接口加认证哪怕是简单的 token 校验也能挡住误访问。第三工具调用的权限要细分不同用户能调用的工具不同避免越权操作。第四定期更新基础镜像和依赖修补已知漏洞。第五备份模型文件和配置文件万一磁盘故障能快速恢复。这些措施不复杂但能避免很多低级事故。6.4 后续可以扩展的方向这套平台搭好之后往上可以接的东西很多。比如接内部知识库做 RAG让 Agent 回答问题时引用内部文档接工作流引擎让 Agent 触发审批、通知、数据同步接多模态模型处理图片和表格。Harness 层保持稳定能力层按需扩展这是比较健康的架构。我在实际维护中的体会是不要一开始就追求大而全。先把单模型、单工具、单场景跑通验证价值再逐步加能力。每加一个组件都要问自己它解决了什么具体问题维护成本能不能接受想清楚再动手比事后返工省事得多。