Local AI Stack Planner:本地大模型应用的技术栈规划
Local AI Stack Planner 不是一个只能跑通一次的安装脚本而是你在本地搭建大模型应用之前先把组件组合、硬件边界、数据流和验证路径想清楚的一套规划流程。很多人下载好了模型、装好了 Ollama却卡在后面的 RAG 接入、向量库选型、并发预估和显存分配上也有人一开始就搭了一套很重的 Kubernetes 平台结果一台机器连 7B 模型都跑不流畅。这里会从本地 AI 技术栈分层讲起给出硬件基线检查方法再用一个最小 Planner 示例把需求翻译成候选技术栈最后补充验证、排错和生产落地建议。“Stack”在软件领域有多个含义应用技术栈、处理协议栈、程序运行时的调用栈。Local AI Stack Planner 里的 stack 主要指的是技术栈但实际排错时你会经常遇到调用栈溢出、前端 Maximum call stack size exceeded、模型加载栈分配失败等问题。因此这篇文章把技术栈规划、运行期排错和性能验证放在一起讲才更贴近真实项目。1. 本地 AI 技术栈为什么需要“先规划后实现”1.1 Local AI Stack Planner 解决的是选择问题不是安装问题本地 AI 并不是一件单一产品。它至少包含模型文件、推理引擎、应用框架、向量数据库、部署方式和监控工具。每一层都有多个候选而这些候选之间互相约束。例如Ollama 使用方便但对高并发推理 API 的支持不如 vLLMLangChain 灵活性强但小场景里直接调用 Ollama API 可能更简单Chroma 适合单机向量检索但数据量到几十万条后Qdrant 或 Milvus 的优势会更明显。Local AI Stack Planner 的核心作用是把“我想在本地跑一个大模型”这种模糊想法拆成“模型多大、用什么引擎、要不要 RAG、需要多少显存、怎么部署、怎么验证”这些具体问题。规划完成后再动手安装过程的返工成本会低很多。1.2 与云端 API 方案相比本地 AI 栈的约束变化云端 API 方案通常只需要关注接口协议、Token 成本和限流。本地 AI 方案多了一层硬件约束规划方式完全不同。维度云端 API 方案本地 AI 方案算力来源服务端集群负责自己控制 GPU、CPU、内存数据边界数据需要通过网络发送到服务方数据可以留在本机或内网延迟构成受网络和限流影响受本地推理速度和队列影响成本模型按 Token 或调用量计费硬件采购、电费和维护成本扩容方式提升账号配额即可需要重新规划模型、显存和服务架构这些差异决定了本地 AI 技术栈无法照搬云端部署方案。显存不足时第一反应不应该是买新显卡而是看量化等级、上下文长度和并发数能不能先降下来。判断顺序应该是“先规划再调参最后决定要不要升级硬件”。1.3 本地 AI 技术栈的最小分层模型本地 AI 技术栈可以按五层来拆。每层独立演进替换某一层时不需要重写整条链路。模型层包括模型权重、量化格式、上下文长度和词表。推理层负责加载模型、分配显存、执行生成例如 Ollama、llama.cpp、vLLM。应用层负责对话、文档问答、Agent 流程例如 LangChain、LlamaIndex、Open WebUI。数据层负责文档解析、切片、向量化和检索例如 Chroma、FAISS、Qdrant、Milvus。部署与运维层负责容器编排、配置管理、日志、监控和版本回滚。规划时按这五层逐项填写最终形成一份可评审的 stack 清单而不是只下载一个大模型文件。2. 先盘点硬件、系统和运行前置条件2.1 硬件预算显存、内存、磁盘和处理单元本地 AI 最关键的硬件指标是显存。显存决定了能加载多大模型以及上下文和并发能开到什么程度。下面给出的是常见量化模型在短上下文、低并发场景下的参考值实际以模型文件大小和运行参数为准。模型档位量化文件大小约值推荐显存1B-3B Q4_K_M0.7GB-2GB4GB 以上7B Q4_K_M4GB-5GB8GB 以上14B Q5_K_M9GB-11GB16GB 以上32B Q4_K_M19GB-21GB24GB 以上70B Q4_K_M40GB-45GB48GB 以上显存计算可以先用近似公式估算模型权重显存大约等于“参数量乘以 0.6 字节”。例如 7B 参数按 Q4_K_M 量化后大约是 7 × 0.6 4.2GB再叠加 KV cache、临时缓冲和推理框架开销。KV cache 与上下文长度、并发请求数量直接相关长上下文或多并发时至少再预留几 GB。内存方面CPU 推理时需要足够内存加载模型即使 GPU 推理也会因为模型加载、tokenizer、应用框架产生内存占用。磁盘方面要特别检查模型目录和向量库目录的空间一个 7B 模型 5GB 左右14B 模型 10GB 左右多个版本叠加后占用很快增加。2.2 操作系统与驱动确认本地 AI 开发最顺畅的环境通常是 Linux。NVIDIA 显卡用户需要确认驱动和 CUDA 环境Apple Silicon 用户可以优先选择支持 Metal 的推理框架纯 CPU 环境则只能选择 3B 以下的小模型或者接受 7B 模型的较低生成速度。Windows 用户如果使用 NVIDIA 显卡常见做法是使用 WSL2 配合 Docker Desktop或者直接在 Windows 上运行 Ollama 等工具。这里要明确一个原则生产环境优先使用 Linux 服务器避免桌面系统自动更新导致驱动和容器 GPU 能力发生变化。2.3 用命令完成环境基线检查在下载模型之前先用一组命令确认基线。这些命令可以在 Linux 服务器或 WSL2 环境中执行。nvidia-smi lscpu free -h df -h /models python3 --version docker version docker compose version每一条命令都要有明确检查目标nvidia-smi确认显卡型号、驱动版本、当前显存占用。如果提示命令不存在说明当前没有 NVIDIA 用户态驱动。lscpu确认 CPU 核数和架构判断是否适合 CPU 推理。free -h确认可用内存。模型加载时会把权重加载到内存或显存内存不足会导致进程被 kill。df -h /models确认模型存储目录的磁盘空间。python3 --version确认脚本运行环境。docker version和docker compose version确认容器化部署前置条件。注意不要只验证命令能执行。还要把输出记录到文档里作为技术栈规划的输入否则换一台机器又会遇到驱动、显存、磁盘不匹配的问题。3. 用一个最小 Planner 把需求翻译成技术栈3.1 Planner 的输入场景、数据规模、并发和隐私要求Local AI Stack Planner 可以做成一份需求文件加一个决策脚本。需求文件使用 YAML 描述方便 Git 跟踪变更。下面是一个最小示例。scenario: rag-chat # chat、rag-chat、code-assistant model: language: zh max_context_tokens: 8192 data: total_docs: 5000 doc_type: pdf,md weekly_growth: 200 performance: concurrent_requests: 2 max_first_token_latency_ms: 3000 budget_gpu_vram_gb: 16这些字段分别对应规划时需要回答的问题。scenario决定要不要引入 RAGtotal_docs决定向量库规模concurrent_requests决定推理引擎的选型budget_gpu_vram_gb决定模型档位和量化等级。字段作用常见值scenario业务类型chat、rag-chat、code-assistantmodel.language生成语言zh、en、multilingualmodel.max_context_tokens上下文长度4096、8192、16384data.total_docs文档总量0、5000、50000performance.concurrent_requests预期并发1、2、8、30performance.budget_gpu_vram_gb显存预算8、16、24、483.2 一个最小 Planner 示例requirements.yaml planner.pyPlanner 脚本读取需求文件根据规则输出候选技术栈。下面代码用于说明思路实际项目需要结合自己的组件清单、版本和许可要求调整。import yaml # key: (data_size, load, scenario) PROFILE_TABLE { (small, low, chat): { model: qwen2.5:7b-instruct-q4_K_M, engine: ollama, framework: open-webui, vector_db: none, deploy: docker-compose, }, (small, low, rag): { model: qwen2.5:7b-instruct-q4_K_M, engine: ollama, framework: langchain, vector_db: chroma, deploy: docker-compose, }, (medium, medium, rag): { model: qwen2.5:14b-instruct-q5_K_M, engine: llama.cpp, framework: langchain, vector_db: qdrant, deploy: docker-compose, }, (high, high, rag): { model: qwen2.5:32b-instruct-q4_K_M, engine: vllm, framework: langchain, vector_db: milvus, deploy: kubernetes, }, } def pick_profile(requirements): docs requirements[data][total_docs] vram requirements[performance][budget_gpu_vram_gb] concurrent requirements[performance][concurrent_requests] scenario requirements[scenario] if docs 10000 and vram 16: data_size, load small, low elif docs 50000 and vram 32 and concurrent 8: data_size, load medium, medium else: data_size, load high, high if scenario rag-chat or docs 0: scenario rag return PROFILE_TABLE.get( (data_size, load, scenario), { model: qwen2.5:7b-instruct-q4_K_M, engine: ollama, framework: langchain, vector_db: chroma, deploy: docker-compose, }, ) def main(): with open(requirements.yaml, r, encodingutf-8) as f: requirements yaml.safe_load(f) profile pick_profile(requirements) print(yaml.safe_dump( {recommended_stack: profile}, allow_unicodeTrue, sort_keysFalse, )) if __name__ __main__: main()这个脚本没有做复杂的权重计算而是使用一张决策表把需求映射到候选组件。它解决的是“不同规模项目应该从哪条技术路线起步”的问题而不是“最终必须用这些组件”。3.3 运行 Planner 并理解输出在项目目录下执行以下命令。python3 -m venv .venv source .venv/bin/activate pip install pyyaml python planner.pyWindows PowerShell 下激活命令是.venv\Scripts\activate。正常输出如下。recommended_stack: model: qwen2.5:7b-instruct-q4_K_M engine: ollama framework: open-webui vector_db: none deploy: docker-compose如果需求文件里scenario是rag-chat或者total_docs大于 0输出会改为带vector_db: chroma的方案。这说明 Planner 的决策链路是文档量决定要不要向量库显存决定模型大小并发决定推理引擎。注意Planner 输出的是候选技术栈不是最终架构。落地前还要确认模型许可、容器镜像版本、模型目录权限和数据备份方案缺少这些检查不能直接进入生产环境。3.4 用决策表解释选型逻辑输入条件模型档位推理引擎向量库部署方式单机 16GB 以下纯聊天7B Q4_K_MOllama无Docker Compose单机 16GB文档问答7B-14B Q4/Q5Ollama 或 llama.cppChroma 或 QdrantDocker Compose单机 32GB中等并发32B Q4_K_MvLLM 或 llama.cppMilvus 或 QdrantKubernetes纯 CPU低延迟要求不高1B-3B Q4_K_Mllama.cppFAISS 或 Chroma单进程或 Docker4. 模型、推理引擎、应用框架与数据层怎么选4.1 模型层先定“参数、量化、上下文”模型层的选择顺序应该是先看显存预算再定参数量级然后选择量化格式最后确认上下文长度。参数越大生成质量通常越好但显存和延迟成本也越高。量化是一种压缩权重的方法常见格式如下。量化级别模型文件大小参考优缺点Q4_K_M小速度和质量比较均衡日常开发建议首选Q5_K_M中质量更稳显存需求略高Q8_0大接近半精度效果但显存占用明显上下文长度影响 KV cache 显存。把上下文从 2048 提升到 8192 时KV cache 占用会成倍增加。实际项目里不要盲目使用长上下文如果文档问答场景较多优先考虑 RAG 而不是把整份文档塞进上下文。4.2 推理引擎按部署方式选推理引擎是把模型权重变成可用 API 或命令行工具的关键层。选型依据主要是并发量、控制粒度和运维成本。引擎适合场景注意点Ollama个人开发、快速验证、单机部署API 简单便于和 Open WebUI 配合llama.cpp单机精细控制、CPU/GPU 混合推理需要手动准备 GGUF 模型vLLM多并发 API 服务、生产环境对 GPU 显存和 Linux 环境要求较高LM Studio桌面端试用、图形化操作更适合开发调试不擅长大规模服务Ollama 的优势是模型管理和 API 简单适合作为学习环境的第一步。vLLM 的优势是高并发吞吐但配置更复杂显存规划要更精细。生产环境不要仅凭“哪个下载量多”选型而是用真实压测数据判断。4.3 应用框架不是所有场景都需要如果只是做一个聊天界面直接使用 Open WebUI 加 Ollama 即可不一定要引入 LangChain。RAG 场景可以先用 LlamaIndex 或 LangChain 跑通检索链路再逐步增加 Agent、多轮对话和工具调用。框架主要优势适合场景LangChain组件丰富、生态大需要编排多个工具和模型能力LlamaIndex文档索引和检索设计较好文档问答、RAG 原型Open WebUI开箱即用的 Web 界面对话演示、本地知识库入口Dify低代码编排业务人员参与配置的场景框架的选择会影响后续扩展路径。如果业务核心是文档问答LlamaIndex 的检索抽象会更容易理解如果业务核心是多 Agent 编排LangChain 更合适。不要因为“大家都在用”就一次性引入全部生态。4.4 向量数据库从轻到重推进RAG 场景里向量数据库负责存储文档切片后的向量并在提问时检索相似片段。选型时先明确数据量和并发量。向量库部署成本适合场景Chroma低单机原型、几千到几万条向量FAISS低离线检索、内嵌到应用Qdrant中中大规模向量、过滤查询、生产服务Milvus高大规模向量、多节点、运维团队支持pgvector中已有 PostgreSQL希望减少组件数量如果文档量只有几百份直接用 Chroma 或 FAISS 即可。当文档增长到十万条以上或者需要复杂 metadata 过滤时再迁移到 Qdrant 或 Milvus。迁移时要注意 embedding 模型是否一致向量维度不一致会导致旧向量无法复用。5. 把最小闭环跑通并记录性能数据5.1 最小可运行闭环Ollama Open WebUI学习环境里先用 Docker Compose 启动 Ollama 和 Open WebUI 是成本最低的方案。下面的 compose 文件是示例实际使用时要锁定镜像版本避免latest或main在后续更新中引入不兼容变化。services: ollama: image: ollama/ollama:latest restart: unless-stopped volumes: - ./models:/root/.ollama deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] open-webui: image: ghcr.io/open-webui/open-webui:main restart: unless-stopped ports: - 3000:8080 environment: OLLAMA_BASE_URL: http://ollama:11434 volumes: - ./webui-data:/app/backend/data启动后访问http://localhost:3000完成初始化再进入模型管理界面拉取本地模型。注意模型下载和 Docker 镜像拉取都需要网络但模型下载完成后推理数据不会离开本机。5.2 用脚本记录 tokens/s、显存占用和首 token 延迟启动 Ollama 后可以用 API 做一次最小推理验证。curl http://localhost:11434/api/generate \ -d {model:qwen2.5:7b-instruct-q4_K_M,prompt:用一句话说明本地 AI 技术栈,stream:false}同时观察nvidia-smi确认 GPU 是否被进程占用。更规范的性能记录可以用 Python 脚本完成。import time import requests payload { model: qwen2.5:7b-instruct-q4_K_M, prompt: 介绍一下 RAG, stream: False, } start time.time() resp requests.post(http://localhost:11434/api/generate, jsonpayload) elapsed time.time() - start data resp.json() text data.get(response, ) eval_count data.get(eval_count, 0) eval_duration_ns data.get(eval_duration, 0) or 1 tokens_per_second eval_count / (eval_duration_ns / 1e9) print(generated_chars:, len(text)) print(elapsed_seconds:, round(elapsed, 3)) print(tokens_per_second:, round(tokens_per_second, 2))执行后记录三个指标生成字符数、端到端耗时、每秒生成 Token 数。后续修改量化等级、上下文长度或并发参数时再跑同一脚本形成对比基线。5.3 从结果反推硬件瓶颈性能数据可以快速定位瓶颈。现象判断处理建议首次请求很慢之后变快模型冷启动权重从内存加载到显存预热模型或调整常驻模型数量tokens/s 很低但显存占用高可能只用了部分 GPU 层或模型过大检查nvidia-smi中的进程调整 GPU layers请求一多就 OOMKV cache 或并发开销超出显存降低并发、缩短上下文、换小量化模型GPU 利用率很低CPU 很高推理没有充分使用 GPU确认引擎和容器配置正确传递 GPU注意不要只看服务能启动还要看显存占用、首 token 延迟和输出质量。一个能启动但回答质量差、响应极慢的本地 AI 服务不具备生产价值。6. 常见“栈”坑与排查路径6.1Maximum call stack size exceeded不是模型问题本地 AI 前端界面使用 Vue 等框架时浏览器控制台可能出现类似[Vue warn]: Error in beforeCreate hook: RangeError: Maximum call stack size exceeded的报错。这个错误是 JavaScript 调用栈溢出不是后端模型推理失败。常见原因是递归组件没有终止条件或者beforeCreate钩子里执行了会再次触发 hook 的代码。例如下面的写法就会无限递归。beforeCreate() { const loop () { loop(); }; loop(); }排查顺序是打开 DevTools 的 Console查看报错堆栈进入beforeCreate钩子确认是否有递归调用检查 Vue 组件树是否存在无终点的递归渲染。修复方式是增加递归终止条件或者把无限层级树的数据改成扁平结构并用 path 字段控制渲染。6.2 模型加载时显存不足本地推理常见的错误是failed to allocate或加载后进程被杀。原因通常是模型文件太大或者显存已经被其他进程占用。先执行nvidia-smi查看显存占用确认没有残留进程。然后看模型量化大小是多少再检查推理参数里的ctx-size和 GPU layers。如果显存不足优先降低上下文长度再考虑减少 GPU layers 或换更小的量化模型。生产环境里还要给其他服务预留显存不要把显卡全部占满。6.3 RAG 检索结果质量差RAG 问答效果差时问题往往不在大模型而在文档切片和 embedding。如果切片过大一个问题会检索到大段无关文本如果切片过小语义会被截断。实践中建议每片 512 到 1024 token切片之间保留 10% 到 20% 的重叠。embedding 模型需要和文档语言匹配中文场景可以优先测试支持中文的 embedding 模型再通过检索命中率验证。排查顺序是先打印检索出的 top-k 片段确认这些片段是否真的与问题相关如果不相关调整 chunk 大小、top_k 和 embedding 模型如果相关但回答仍不对再优化 prompt 和生成参数。6.4 技术栈规划中的组件冲突多个组件同时运行时端口、模型目录和数据目录容易互相干扰。例如 Ollama 默认端口 11434Open WebUI 默认端口 8080如果其他服务占用了这些端口启动会失败。检查命令如下。ss -lntp docker ps du -sh models/* webui-data/*生产环境建议为每个组件分配独立目录固定端口并通过.env文件统一管理配置。模型目录不要放在临时目录避免机器重启后模型丢失。7. 从开发验证到生产落地还需要补齐什么7.1 学习环境与生产环境的差异开发环境跑通只是第一步。生产环境要额外考虑配置外置、日志采集、权限控制、监控、备份和回滚。项目学习环境生产环境配置写在脚本或当前目录环境变量、配置文件模板模型版本手动下载随时替换固定模型 digest记录版本数据存储本地目录、SQLitePostgreSQL、内网对象存储日志终端输出集中日志系统监控手动 nvidia-smiPrometheus Grafana权限默认不鉴权API Key、SSO、最小权限回滚重装即可模型目录备份、镜像版本回退7.2 用环境变量管理关键参数生产环境不要把显存、模型名、上下文长度写死在代码里。下面是一个.env.example示例真实文件不要提交到 Git。OLLAMA_MODELqwen2.5:7b-instruct-q4_K_M OLLAMA_NUM_CTX8192 OLLAMA_MAX_LOADED_MODELS1 DATA_DIR/data/local-ai WEBUI_AUTHtrueDocker Compose 启动时读取这个文件可以把配置与代码分离。修改OLLAMA_NUM_CTX或模型名时不需要改源码只需要更新环境变量并重启容器。7.3 安全与回滚本地 AI 并不意味着可以完全忽略安全。需要确认三点模型文件来源是否可信、模型加载目录是否只允许指定用户写入、Web 服务是否暴露在公网。模型下载后要记录文件大小和校验值。镜像不能一直使用latest否则后续版本变化可能导致不可用。模型目录建议做软链接或符号链接管理方便切换模型版本向量库数据要定期备份备份与模型文件分开存放。8. 可复用清单与下一步路线8.1 技术栈规划检查清单每次搭建 Local AI Stack 之前按下面清单逐项确认。确认场景类型聊天、RAG、Agent、批量处理。确认硬件显存、内存、磁盘、GPU 驱动。确认模型参数量、量化格式、上下文长度、许可要求。确认推理引擎Ollama、llama.cpp、vLLM是否满足并发预期。确认是否引入向量库以及文档量和查询量级。确认部署方式单机 Docker Compose 还是 Kubernetes。固定模型、镜像和依赖版本。记录性能基线tokens/s、首 token 延迟、显存占用。配置日志、监控、备份和回滚。验证隐私边界哪些数据不会离开本地。8.2 从最小案例到生产力应用建议先跑通一个不超过三个组件的最小链路Ollama 提供推理Open WebUI 提供界面本机目录保存模型。确认稳定运行后再叠加 RAG加入文档解析、切片和向量库。此时不要直接上多节点先在一台机器上完成检索命中率和问答质量的验证。当并发请求超过单机能力时再把推理层替换为 vLLM并增加负载均衡和监控。每一步都要用上一阶段的基线数据来判断而不是凭感觉升级硬件。8.3 建议学习路径学习本地 AI 技术栈可以从四个方向推进先理解模型量化和显存关系再掌握 Ollama 或 llama.cpp 的部署参数然后实现一个 RAG 问答案例最后补充监控和权限控制。Local AI Stack Planner 真正要做的事是让每次选型变更都能被记录、被验证、被回滚。建议从一台单机和一个 7B 模型开始把性能指标和配置参数记在一个文件里再逐步替换组件。环境变化时这份记录就是你判断技术栈是否合理的依据。