家里电脑能跑哪个大模型?本地硬件检测出模型清单后,用 cpolar 远程验收模型 Demo
很多人装本地大模型,第一步就走歪了:还没看清楚自己电脑的 CPU、内存、显存,就直接照着别人教程拉模型。结果不是下载半天跑不动,就是 Demo 刚打开,风扇先起飞。
我更优先做一件朴素但有效的事:把本机硬件扫一遍,按规则生成一份“这台机器可运行哪些模型”的清单,再只开一个最小 Demo 或健康页给同事验收。验收重点也别贪多,就看响应速度、上下文长度和失败边界。
这篇不写 Open WebUI,也不写某个模型管理后台的泛安装。我们只搭一条稳妥链路:本地硬件检测 → 模型模型清单 → 最小 API 健康页 → cpolar 临时公网验收。
1 先说清楚:这篇到底验收什么
本地大模型的“能跑”,不是一句“支持 7B”就够了。真到自己电脑上,至少要回答三个问题:
- 当前机器有没有独立 GPU,显存是多少;
- 内存够不够给模型、运行时和系统一起用;
- Demo 在指定上下文长度下,响应速度和失败提示是否稳定。
所以这里的目标不是把管理后台暴露出去,也不是把 API Key 放到公网。我们只开放一个最小验收入口,让同事看到机器能力报告、模型档位,以及一个受控的/health或/demo返回。
提醒一句:如果你只是自己在局域网里测试,cpolar 这一步可以先跳过。它匹配“同事不在同一个网络,但需要临时看一眼效果”的场景。
2 环境准备:准备 Python 和一个干净目录
这套示例只依赖 Python,本地硬件检测和健康页都放在同一个目录里,方便后面关停和清理。
新建一个目录,不要混在已有模型项目里:
mkdir -p local-model-check-demo cd local-model-check-demo python3 -m venv .venv source .venv/bin/activate pip install fastapi uvicorn psutil pyyaml pynvml这里安装pynvml是为了读取 NVIDIA 显卡信息;没有 NVIDIA 显卡也不影响脚本运行。psutil负责读取 CPU 和内存,FastAPI用来提供最小健康页。
如果python3 -m venv报错,先确认本机 Python 版本:
python3 --versionPython 3.9 及以上就够用。这里别一上来就装完整模型服务,先把检测和清单跑通,后面排错轻很多。
3 本地硬件检测:把 CPU、内存、显存扫出来
先写一个硬件检测脚本。它会输出 JSON,里面包含 CPU 核心数、总内存、可用内存、操作系统和显卡显存。
新建hardware_probe.py:
import json import platform import subprocess import psutil def bytes_to_gb(value: int) -> float: return round(value / 1024 / 1024 / 1024, 2) def detect_nvidia_by_pynvml(): try: import pynvml pynvml.nvmlInit() count = pynvml.nvmlDeviceGetCount() gpus = [] for index in range(count): handle = pynvml.nvmlDeviceGetHandleByIndex(index) name = pynvml.nvmlDeviceGetName(handle) memory = pynvml.nvmlDeviceGetMemoryInfo(handle) if isinstance(name, bytes): name = name.decode("utf-8") gpus.append( { "index": index, "name": name, "vram_total_gb": bytes_to_gb(memory.total), "vram_free_gb": bytes_to_gb(memory.free), } ) pynvml.nvmlShutdown() return gpus except Exception: return [] def detect_nvidia_by_smi(): try: output = subprocess.check_output( [ "nvidia-smi", "--query-gpu=index,name,memory.total,memory.free", "--format=csv,noheader,nounits", ], text=True, stderr=subprocess.DEVNULL, ) gpus = [] for line in output.strip().splitlines(): index, name, total, free = [item.strip() for item in line.split(",")] gpus.append( { "index": int(index), "name": name, "vram_total_gb": round(int(total) / 1024, 2), "vram_free_gb": round(int(free) / 1024, 2), } ) return gpus except Exception: return [] def main(): memory = psutil.virtual_memory() gpus = detect_nvidia_by_pynvml() or detect_nvidia_by_smi() report = { "os": platform.platform(), "python": platform.python_version(), "cpu_physical_cores": psutil.cpu_count(logical=False), "cpu_logical_cores": psutil.cpu_count(logical=True), "memory_total_gb": bytes_to_gb(memory.total), "memory_available_gb": bytes_to_gb(memory.available), "gpus": gpus, } print(json.dumps(report, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()运行:
python hardware_probe.py | tee hardware-report.json你会得到一个hardware-report.json。没有独立显卡时,gpus会是空数组,这不是报错,而是说明脚本没有检测到 NVIDIA 显卡。
这一张图匹配放终端检测结果:左边是运行命令,右边是 JSON 报告。读者看到 CPU、内存、显存字段,就知道后面的清单不是拍脑袋。
如果输出里显卡为空,但你确认机器有 NVIDIA 显卡,先检查nvidia-smi是否能运行:
nvidia-smi这一步不是为了追求“检测得多漂亮”,而是确认本机驱动和命令行环境能正常给出硬件信息。显卡命令都读不到,后面直接跑模型只会更难排查。
4 生成模型模型清单:先按档位,不急着拉模型
硬件检测完成后,再用一套清晰规则生成模型清单。这里不绑定某个项目的官方命令,避免把读者带进版本差异里。规则很简单:看可用显存、总内存和 CPU 核心数,给出匹配本机测试的模型档位。
新建recommend_models.py:
import json import yaml from pathlib import Path def choose_tier(report): gpus = report.get("gpus", []) max_vram = max([gpu.get("vram_total_gb", 0) for gpu in gpus], default=0) memory_total = report.get("memory_total_gb", 0) cpu_cores = report.get("cpu_physical_cores") or 0 if max_vram >= 16 and memory_total >= 32: return { "tier": "gpu-16g-plus", "recommended": ["7B/8B 量化模型", "14B 低比特量化模型"], "context_tokens_for_demo": 8192, "notes": "优先用 GPU 跑推理,验收时重点看长上下文和并发请求下的响应。", } if max_vram >= 8 and memory_total >= 16: return { "tier": "gpu-8g", "recommended": ["3B/4B 模型", "7B/8B 量化模型"], "context_tokens_for_demo": 4096, "notes": "先测 1 个 7B/8B 量化模型,不要一次拉太多模型,节省磁盘和排错时间。", } if memory_total >= 16 and cpu_cores >= 4: return { "tier": "cpu-memory-16g", "recommended": ["1B/2B 小模型", "3B 低比特量化模型"], "context_tokens_for_demo": 2048, "notes": "以 CPU 测试为主,响应速度别和独立显卡机器对比。", } return { "tier": "lightweight-only", "recommended": ["1B 以内小模型", "Embedding 或分类类轻量模型"], "context_tokens_for_demo": 1024, "notes": "这类机器更匹配做轻量 Demo,不可以直接验收长文本生成。", } def main(): report = json.loads(Path("hardware-report.json").read_text(encoding="utf-8")) plan = choose_tier(report) result = { "hardware_summary": { "cpu_physical_cores": report.get("cpu_physical_cores"), "memory_total_gb": report.get("memory_total_gb"), "gpus": report.get("gpus", []), }, "model_recommendation": plan, "acceptance_checklist": [ "健康页能返回当前模型档位", "Demo 能在设定上下文长度内返回结果", "超过边界时返回清晰错误,不让服务卡死", "验收结束关闭公网隧道", ], } Path("model-plan.yaml").write_text( yaml.safe_dump(result, allow_unicode=True, sort_keys=False), encoding="utf-8", ) print(yaml.safe_dump(result, allow_unicode=True, sort_keys=False)) if __name__ == "__main__": main()执行:
python recommend_models.py这一步会生成model-plan.yaml。它不是“权威排行榜”,而是本机验收用的模型清单。划重点:清单要服务于测试边界,不要服务于炫配置。
这里可以只挑一个模型档位做验收。比如 8GB 显存机器,就先围绕 7B/8B 量化模型做 Demo;16GB 内存无独显机器,就把目标降到 1B/2B 或 3B 低比特量化模型。先把一个链路跑稳,比一次拉满五六个模型靠谱。
5 启动最小 Demo:只暴露健康页和受控接口
有了模型清单,再启动一个最小 API。这个 API 不放管理后台,不读取本机目录,不接收 API Key,只把验收需要的结果展示出来。
新建demo_api.py:
import time from pathlib import Path import yaml from fastapi import FastAPI, HTTPException from pydantic import BaseModel, Field PLAN_PATH = Path("model-plan.yaml") app = FastAPI(title="Local Model Acceptance Demo") class DemoRequest(BaseModel): prompt: str = Field(min_length=1, max_length=20000) def load_plan(): return yaml.safe_load(PLAN_PATH.read_text(encoding="utf-8")) @app.get("/health") def health(): plan = load_plan() return { "status": "ok", "tier": plan["model_recommendation"]["tier"], "recommended": plan["model_recommendation"]["recommended"], "context_tokens_for_demo": plan["model_recommendation"]["context_tokens_for_demo"], } @app.post("/demo") def demo(request: DemoRequest): plan = load_plan() limit = plan["model_recommendation"]["context_tokens_for_demo"] estimated_tokens = max(1, len(request.prompt) // 2) if estimated_tokens > limit: raise HTTPException( status_code=413, detail=f"输入长度超过验收边界:estimated_tokens={estimated_tokens}, limit={limit}", ) start = time.perf_counter() preview = request.prompt[:80] elapsed_ms = round((time.perf_counter() - start) * 1000, 2) return { "status": "accepted", "tier": plan["model_recommendation"]["tier"], "estimated_tokens": estimated_tokens, "elapsed_ms": elapsed_ms, "preview": preview, "message": "最小 Demo 已接收输入。接入真实模型时,把这里替换成本地推理调用。", }启动服务:
uvicorn demo_api:app --host 127.0.0.1 --port 7860这里故意监听127.0.0.1,不是0.0.0.0。本机服务先只对本机开放,再由 cpolar 转发到公网地址。这个边界很重要,别为了省事把模型服务、管理后台和文件目录一起暴露出去。
另开一个终端做本机测试:
curl http://127.0.0.1:7860/health curl -X POST http://127.0.0.1:7860/demo \ -H 'Content-Type: application/json' \ -d '{"prompt":"请用三句话说明这台机器匹配做哪类本地模型 Demo"}'再测一次失败边界。下面这条命令会构造一段长输入,接口应该返回413,而不是一直卡着:
python - <<'PY' import requests text = "本地模型验收边界测试" * 5000 r = requests.post("http://127.0.0.1:7860/demo", json={"prompt": text}) print(r.status_code) print(r.text[:300]) PY如果这里提示缺少requests,补装即可:
pip install requests这一步做完后,最小验收对象已经准备好了。同事需要看的不是完整管理台,而是:这台机器的档位是什么、Demo 能不能稳定返回、超出上下文边界时有没有明确失败提示。
这一张图匹配放浏览器里的/health返回,或者终端里/demo的成功和失败结果。截图里不要出现真实 API Key、内网目录和个人文件名。
6 用 cpolar 临时验收:只开放 7860 这个最小入口
本地7860已经跑通后,再用 cpolar 开一个 HTTP 隧道。cpolar 的价值在这里很明确:同事不需要远程登录你的电脑,也不需要进同一个局域网,只拿一个临时公网地址验收 Demo。
如果你的电脑还没安装 cpolar,官方入口如下:
- 官网:https://www.cpolar.com/
- 下载页:https://www.cpolar.com/download
- 文档首页:https://www.cpolar.com/docs/
- 用户后台:https://dashboard.cpolar.com/
macOS 可以用 Homebrew 安装:
brew tap probezy/core && brew install cpolarLinux 或树莓派可以使用官方一键安装脚本:
curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash安装后,打开本机管理界面:
curl -s http://127.0.0.1:9200 || echo "cpolar 服务未启动"有图形界面的机器,可以在浏览器访问:
http://127.0.0.1:9200账号绑定有两种常见方式:能打开 Web UI 时,登录流程会完成账号绑定;纯命令行环境或需要手动绑定时,再使用cpolar authtoken xxx。
确认本地 Demo 仍在运行后,启动临时 HTTP 隧道:
cpolar http 7860命令输出里会出现公网访问地址。把这个地址加上/health发给同事,例如:
https://你的临时地址/health验收时可以只给这三个测试点:
- 打开
/health,确认返回status: ok和清单档位; - 调用
/demo,用一段短文本观察响应时间; - 输入一段超长文本,确认服务返回清晰的边界错误。
如果公网地址打不开,按这个顺序查,不要一上来重装:
- 本机访问
http://127.0.0.1:7860/health是否正常; http://127.0.0.1:9200里隧道是否在线;- cpolar 输出的公网地址是否复制完整;
- Demo 是否只允许了奇怪的 Host 或 Origin。
这类验收用随机临时地址就够了。需要稳定地址时,再单独评估固定二级子域名;固定二级子域名需要对应版本支持。这个场景是临时验收,不可以为了短时间测试把公网入口长期挂着。
7 安全边界:别把验收做成裸奔
本地大模型经常会连着模型文件、日志目录、API Key、管理后台。远程验收时,最容易犯的错就是“为了方便”,直接把完整后台或真实业务接口开放出去。
这篇只可以开放最小 Demo,有几个边界别破:
- 不暴露模型管理后台,只暴露
/health和受控/demo; - 不在返回结果里输出 API Key、模型文件路径、用户目录;
- 不接入真实用户数据,用脱敏样例做验收;
- 不长期开放公网入口,验收结束立刻关闭 cpolar;
- 不把 SSH、数据库、文件管理端口一起映射出去。
关闭也很简单。临时命令行方式启动的 cpolar,回到运行cpolar http 7860的终端,按Ctrl + C结束隧道。再回到 uvicorn 的终端,同样按Ctrl + C停掉 Demo。
如果同事说“页面能打开但接口报错”,先看本机 Demo 终端日志。公网能命中服务,说明隧道链路已经通了,剩下多半是请求路径、请求方法或 JSON 格式没对上。
8 总结
现在这条链路已经跑完了:先用脚本读取本机 CPU、内存和显存,再按硬件档位生成模型模型清单,随后启动一个只包含健康页和受控接口的最小 Demo,并用 cpolar 给同事做短时间远程验收。
这套做法的重点不是“装得多”,而是把边界讲清楚:
- 硬件检测先行,避免盲目下载不匹配本机的模型;
- 模型清单按档位输出,验收时只测一个明确目标;
- cpolar 只用于临时开放最小入口,验收完成就关闭。
后面真要接入真实本地推理服务,也可以沿用这个结构:管理后台留在本机,公网只暴露一层经过限制的 Demo 或健康页。这样同事能验收效果,你也不用担心把整台电脑的模型环境一起交出去。