简介这是一份面向机器学习与人工智能方向开发者、运维人员的本地私有化智能问答助理示例项目基于 Gradio 搭建文件上传与知识库查询界面结合 FAISS 向量检索与 Sentence-Transformers 文本嵌入实现从大量文档中快速定位并生成回答适合想动手实践 RAG 问答系统、关注数据隐私与私有化部署的中级学习者。压缩包共 18 个文件约 336KB包含 5 个 py 主程序与脚本、5 个 txt 配置与说明、2 个 yaml 环境配置、1 个 whl 依赖包、1 个 sh 安装脚本以及 docx、xlsx、pdf 等示例知识库文档和 pem 证书文件覆盖从环境搭建到问答交互的完整链路。目前已有 140 人学习。通过该示例可掌握 FAISS 相似性检索与句向量匹配的落地方式、Gradio 界面与后端模型的对接思路以及私有化部署下的依赖管理与目录组织便于按自身业务定制知识库与问答流程。1. 本地部署 ChatGLM 智能问答助理从选版本到跑通第一条对话很多人第一次装 ChatGLM 都栽在同一个地方模型权重下完了Python 环境也配了结果transformers版本和torch版本对不上加载模型直接报KeyError: ChatGLMForConditionalGeneration。这不是模型坏了是版本组合没锁死。本地部署私有化智能问答助理这件事说难不难说简单也绝不简单——它吃显存、吃依赖版本、吃网络环境任何一个环节松了后面全是玄学报错。这套环境适合两类人一是想把问答能力放进内网、数据不出本地机房的后端或运维二是做机器学习 Demo、需要快速验证 ChatGLM 推理效果的开发者。下面按我实际装过几台机器的顺序把版本选择、依赖安装、模型加载、接口验证和翻车救援一次讲清。2. 装前定版本ChatGLM 权重、Python 与 CUDA 的对应关系2.1 先确认硬件底线再决定装哪一版ChatGLM 系列常见的有 ChatGLM-6B、ChatGLM2-6B、ChatGLM3-6B 几个代际。6B 参数在 FP16 下大约需要 13GB 显存INT8 量化后降到 8GB 左右INT4 量化后 6GB 上下能跑。我一般先让读者跑一条命令看显卡nvidia-smi输出里重点看三列CUDA Version驱动支持的最高 CUDA 版本、Memory-Usage当前占用、GPU Name。如果显存只有 8GB别硬上 FP16直接走 INT4 量化加载。如果机器没有 NVIDIA 显卡CPU 推理也能跑但 6B 模型在纯 CPU 上一条回复等十几秒是常态只适合功能验证不适合当问答服务用。Python 版本我固定在 3.10。3.8 太老部分新算子不支持3.11 和 3.12 在torch与transformers的某些组合下会出现编译轮子缺失。3.10 是当前兼容性最稳的中间点。2.2 版本对照表别让 torch 和 transformers 打架下面这张表是我在几台机器上验证过的组合直接抄组件推荐版本说明Python3.10.x3.8~3.10 均可3.10 最稳PyTorch2.0.1 或 2.1.2需与 CUDA 版本匹配CUDA11.7 / 11.8由驱动决定上限transformers4.33.3 ~ 4.36.2低于 4.33 不认 ChatGLM3accelerate0.21.0 以上量化加载依赖它sentencepiece0.1.99分词器依赖protobuf3.20.x太高会报 descriptor 错误提示如果你装的是 ChatGLM3transformers必须 ≥ 4.33.3否则AutoModel找不到模型类。ChatGLM2 用 4.30 左右也能跑但没必要省这一步。2.3 创建独立环境别污染系统 Python我习惯用 conda 建一个干净环境避免和系统里已有的torch冲突conda create -n chatglm python3.10 -y conda activate chatglm这两条命令做完后面所有pip install都只影响chatglm这个环境。如果你不用 conda用python -m venv chatglm-env也行逻辑一样隔离。装完环境后先升级 pippip install --upgrade pip setuptools wheel这一步很多人跳过结果装torch时因为wheel太旧编译到一半失败报一堆building wheel for xxx的错。先升级省后面十分钟排查。3. 装依赖与拉权重pip 源、CUDA 匹配和模型下载3.1 装 PyTorchCUDA 版本对不上是最常见的翻车点nvidia-smi右上角的CUDA Version是驱动支持的上限不是你实际装的 CUDA 版本。装torch时要选不超过这个上限的 CUDA 版本。比如驱动显示 12.2你可以装 cu11.8 的 torch也可以装 cu12.1 的但不能装 cu12.4 的。# 以 CUDA 11.8 为例 pip install torch2.1.2 torchvision0.16.2 torchaudio2.1.2 --index-url https://download.pytorch.org/whl/cu118--index-url指定 PyTorch 官方轮子源避免从默认源拉到 CPU 版本。装完后验证python -c import torch; print(torch.__version__, torch.cuda.is_available())输出应该是2.1.2cu118 True。如果cuda.is_available()返回False说明装成了 CPU 版重新用上面的--index-url装一遍。3.2 装 transformers 与量化依赖pip install transformers4.36.2 accelerate0.25.0 sentencepiece0.1.99 protobuf3.20.3accelerate是量化加载的调度器sentencepiece负责分词protobuf锁在 3.20.x 是因为 4.x 版本改了 descriptor 接口ChatGLM 的 tokenizer 会报TypeError: Descriptors cannot be created directly。这个坑我踩过两次每次都是装完一堆包才发现是 protobuf 太新。3.3 拉模型权重两种方式按网络情况选方式一用huggingface-cli直接拉pip install huggingface_hub huggingface-cli download THUDM/chatglm3-6b --local-dir ./chatglm3-6b --local-dir-use-symlinks False--local-dir指定本地目录--local-dir-use-symlinks False让文件实体落盘而不是软链方便后面迁移到内网机器。方式二如果目标机器完全离线先在能访问的机器上下载再把整个目录拷过去。模型目录结构应该是chatglm3-6b/ ├── config.json ├── tokenizer_config.json ├── tokenizer.model ├── pytorch_model-00001-of-00007.bin ├── ... └── pytorch_model.bin.index.json注意如果pytorch_model.bin.index.json缺失加载时会报Error no file named pytorch_model.bin。这个文件是分片索引必须和所有.bin分片一起在。3.4 写一个最小加载脚本先验证模型能起来from transformers import AutoTokenizer, AutoModel # 指向本地模型目录避免联网 model_path ./chatglm3-6b tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) model AutoModel.from_pretrained( model_path, trust_remote_codeTrue, device_mapauto, # 自动分配显卡 load_in_4bitTrue # 显存不足时开4bit量化 ).eval() response, history model.chat(tokenizer, 你好, history[]) print(response)trust_remote_codeTrue是必须的ChatGLM 的模型类不在transformers主库里需要执行模型目录下的自定义代码。device_mapauto让accelerate自动决定放哪张卡。load_in_4bitTrue在显存小于 10GB 时打开代价是推理速度略降。如果这一步能打印出回复说明模型加载链路通了。如果报CUDA out of memory把load_in_4bit改成load_in_8bit或去掉量化、换更小的模型代际。4. 配服务接口把本地模型变成可调用的问答助理4.1 用 FastAPI 包一层 HTTP 接口模型能加载只是第一步要当问答助理用得有个接口。我一般用 FastAPI 起一个最小服务from fastapi import FastAPI from pydantic import BaseModel from transformers import AutoTokenizer, AutoModel app FastAPI() model_path ./chatglm3-6b tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) model AutoModel.from_pretrained(model_path, trust_remote_codeTrue, device_mapauto).eval() class Query(BaseModel): prompt: str history: list [] app.post(/chat) def chat(q: Query): response, new_history model.chat(tokenizer, q.prompt, historyq.history) return {response: response, history: new_history}Query里带history是为了多轮对话。ChatGLM 的model.chat返回两个值本轮回复和更新后的历史列表把历史传回来就能续上上下文。启动命令pip install fastapi uvicorn uvicorn main:app --host 0.0.0.0 --port 8000--host 0.0.0.0让同网段其他机器也能访问--port 8000按需改。启动后访问http://本机IP:8000/docs能看到自动生成的接口文档直接在里面发请求测试。4.2 参数怎么调temperature、top_p 和 max_lengthChatGLM 的model.chat支持几个关键参数参数作用建议值temperature控制随机性0.1~0.7问答场景 0.1 更稳top_p核采样阈值0.7~0.9max_length最大生成长度512~2048按显存调repetition_penalty重复惩罚1.0~1.2问答助理场景我一般把temperature设 0.1减少胡言乱语max_length设 1024再长显存吃不住。这些参数在model.chat调用时传入response, history model.chat( tokenizer, 介绍一下机器学习, history[], temperature0.1, top_p0.8, max_length1024 )4.3 多轮对话的历史管理ChatGLM 的history是一个列表每轮对话追加两个元素用户输入和模型回复。如果历史太长会撑爆显存。常见做法是限制历史轮数MAX_TURNS 5 if len(history) MAX_TURNS * 2: history history[-MAX_TURNS * 2:]这段逻辑放在每次model.chat之前只保留最近 5 轮。超过就截断避免max_length被历史占满导致新回复被截断。5. 避坑与排查装 ChatGLM 最常见的 5 个翻车现场5.1 报错KeyError: ChatGLMForConditionalGeneration现象加载模型时提示找不到模型类。原因transformers版本太低不认识 ChatGLM3 的模型注册名。解决升级到 4.33.3 以上并确认trust_remote_codeTrue已传。5.2 报错RuntimeError: CUDA out of memory现象加载或推理时显存爆了。原因FP16 加载 6B 模型需要约 13GB 显存8GB 卡扛不住。解决加load_in_4bitTrue或load_in_8bitTrue或者换用device_mapauto让 accelerate 自动分片。5.3 报错TypeError: Descriptors cannot be created directly现象导入 tokenizer 时 protobuf 报错。原因protobuf 4.x 改了内部接口。解决pip install protobuf3.20.3锁死版本。5.4 模型下载到一半中断文件不完整现象加载时报Unable to load weights from pytorch checkpoint file。原因下载中断.bin分片缺失或大小不对。解决删掉整个模型目录重新下载或者用huggingface-cli download的断点续传功能重跑。下载完后核对文件数量和index.json里列出的分片是否一致。5.5 接口能通但回复乱码或空字符串现象HTTP 200 但response是空或乱码。原因tokenizer 和模型不匹配或者max_length设太小导致生成被截断。解决确认 tokenizer 和 model 从同一个目录加载把max_length调到 512 以上检查输入 prompt 是否为空。6. 装完怎么验证三条命令确认问答链路真的通了装完别急着接业务先跑这三步验证。第一步确认环境和显存python -c import torch; print(CUDA:, torch.cuda.is_available(), | GPU:, torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU)输出CUDA: True且显卡名正确说明 torch 和驱动匹配。如果显示False后面所有推理都会走 CPU速度差一个数量级。第二步确认模型能加载并回复python -c from transformers import AutoTokenizer, AutoModel t AutoTokenizer.from_pretrained(./chatglm3-6b, trust_remote_codeTrue) m AutoModel.from_pretrained(./chatglm3-6b, trust_remote_codeTrue, device_mapauto).eval() r, h m.chat(t, 11等于几, history[]) print(回复:, r) 能打印出类似「11等于2」的回复说明模型加载、分词、推理链路全通。这一步如果报错回到第 5 章对号入座。第三步确认 HTTP 接口可用curl -X POST http://127.0.0.1:8000/chat \ -H Content-Type: application/json \ -d {prompt: 你好, history: []}返回 JSON 里response字段有内容说明服务层也通了。这三步走完整套本地私有化问答助理就算落地了。我自己的习惯是每次换机器或重装环境这三条命令必须依次跑一遍不跳步。有一次偷懒跳过第二步直接起服务结果接口一直返回空排查了半小时才发现是模型分片少了一个文件。从那以后我每次部署完都强制走一遍「环境→模型→接口」的验证链确认每一环都独立可复现再交给业务方用。希望帮到你。本文还有配套的精品资源点击获取