从 AtomCode 7 天续杯到昇腾容器:一次对“昇腾模型生态“选项卡的意外探索,我把免费 NPU 接进了 Mac
2026/7/21 17:02:13 网站建设 项目流程

摘要

作者:一名在 M3 MacBook Air 上"斤斤计较"的开发者

摘要:本来只是在 ai.atomgit.com 盯着 AtomCode 的免费模型续杯倒计时,随手点开旁边的"昇腾模型生态"选项卡,没想到挖到了宝。本文将记录如何把网页里的"昇腾模型助手"变成 Mac 本地 Agent 的后端,过程中充满容器权限的博弈、pip 的依赖坑和网络隔离挑战,最终在远端昇腾 NPU 上跑通 Qwen2.5-7B,并通过 SSH 反向隧道将 OpenAI 兼容的 API 服务穿透到本地 Mac,实现免本地内存压力的远端推理。

前言:AtomCode 的"续杯"日常与功耗焦虑

作为一名重度依赖 AI 辅助编程的开发者,我早已习惯了 AtomCode 官方客户端的节奏。平时盯着官方构建版,心里都有一本账:

  • Lite 版:30 天一登录一续,不用抢,到点/login一下就能续杯,主打一个佛系。
  • Pro 版:想用 GLM-5.2 就得抢。但要注意——Pro 没过期的时候点/login是续不了的,系统不让续,必须等当前 Pro 过期那一天、第二天早上 10 点准点去抢才能抢到 GLM-5.2 额度。所以 Pro 用户的节奏是:过期 → 次日 10 点/login→ 抢到 → 再撑一阵。

💡 这里先澄清一个常见误解:AtomCode 里能调到的 DeepSeek-V4-Flash、GLM-5.2 这类模型,并不是在你 Mac 上跑的。它们更可能是 AtomGit 平台提供的中转 API,或者是模型方(智谱 / 深度求索)在 AtomGit / 华为云之上部署过的云端实例,atomcode 客户端只是走 HTTP 调远端。所以平时用 atomcode 写代码,Mac 本身并不会因为使用 AtomCode 或昇腾模型服务而发烫——M3 Air 本来也无风扇,C 面靠被动散热,但即便如此,如果你真在本地用 ollama 硬跑个 7B 模型,内存压力一黄,功耗还是会悄悄上来,摸 C 面能感觉到温。

直到那天,我盯着网页中的选项卡,目光从 AtomCode 移到了旁边的"昇腾模型生态"。出于好奇点进去,发现这不仅仅是静态页面,而是一个活生生的昇腾模型助手 Agent 页面——带 Web 终端的那种。我决定试试,能不能把这个网页里的算力"抠"出来,给本地 Agent 当后端。

踩坑实录一:容器环境的"镣铐"

申请容器、进终端,第一刻就意识到这不会一帆风顺——这是个典型的受限环境:

  1. 家目录只读(Read-Only):.ssh/config 写不了,known_hosts 也落不下来,pip install 往用户目录写包也会炸。所有"临时物"只能往 /tmp 或 /opt/atomgit 塞。
  2. pip 的 PEP 668 坑:直接 pip install fastapi 会报 error: externally-managed-environment。必须用 pip install --break-system-packages ...,现代容器(Debian 12 系)基本都踩这个。
  3. CANN / torch-npu 的环境变量:ASCEND_HOME、LD_LIBRARY_PATH 没全默认加载时,Torch-NPU 会找不到底层 .so;另外 ASCEND_LOG_DIR 如果指到家目录会报 can not create directory, directory: /home/xxx/ascend/log,得手动 export ASCEND_LOG_DIR=/opt/atomgit/ascend/log。
  4. torch_dtype 弃用:新版 transformers 里 torch_dtype=torch.float16 已经 deprecate,启动日志会甩 torch_dtype is deprecated! Use dtype instead!,得改成 dtype=torch.float16,不然一堆警告。
  5. 进程保活:容器有闲置回收或会话断掉就清场的机制,单纯 python xxx.py & 很容易在关网页后悄无声息死掉。
  6. 端口绑定权限:后面建 SSH 反向隧道时,-R 18000:... 第一次被跳板机拒了(bind: Address already in use / permission denied),估计是低位端口或 GatewayPorts 限制,换到 18002 这个高位口才过。

想法:昇腾 NPU 能跑啥,不能跑啥

先把预期压 realistic:

  • ❌ 跑不动的:DeepSeek-V3 / R1 全量、GLM-5.2 闭源重炮——这些是 AtomCode Pro 那边云端 API 的活,昇腾体验容器这点资源扛不动。
  • ✅ 能跑的:Qwen2.5-7B / DeepSeek-R1-Distill-Qwen-32B 这个量级,在昇腾 910 上 FP16 推理是稳的,当"副驾驶"够用。而且这台容器是 2×64GB HBM,32B 双卡 device_map="auto" 刚好能塞。

关于 Qwen2.5-7B 的定位:这个 7B 模型在代码生成、复杂逻辑推理上确实有限,更多是对话、文本理解、简单脚本辅助。它当不了全栈 Agent,但作为"对话副驾驶"、文本处理助手是合格的。真要写复杂代码,还是得靠 GLM-5.2 或 DeepSeek-V4-Flash 这类大模型。

目标就定了:在容器里用 transformers + FastAPI 起一个 OpenAI 兼容的 /v1/chat/completions,然后通过 SSH 反向隧道打到 Mac 本地,让 atomcode / 任意 OpenAI-sdk 客户端直接调。

踩坑实录二:SSH 反向隧道穿透

容器能连公网,但外面进不来——典型单向隔离。解法是用 SSH 反向隧道(Reverse Tunnel),让容器主动"打洞"连回 Mac 侧的跳板节点(平台给每个用户分配的 frp-xxx.com:5xxxx 那种入口)。

# 容器侧执行(脱敏版) ssh -i /tmp/tunnel_key \ -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null \ # 绕过家目录只读 -o ServerAliveInterval=30 \ -o ExitOnForwardFailure=yes \ -N -R 18002:127.0.0.1:8000 \ user@jump-node -p JUMP_PORT

⚠️ 第一次试的是 -R 18000:...,跳板机报 bind: Address already in use / permission denied——远端端口绑不上时先换高位号,这是通用套路。

Mac 侧(WezTerm / nushell)验证:

nc -z -w 2 localhost 18002; if ($env.LAST_EXIT_CODE == 0) { "✅ 隧道已通" }

看到 succeeded 那一秒,链路就通了:容器 8000 → 跳板 18002 → Mac localhost:18002。

踩坑实录三:API 服务在容器里起起来

容器里自带 torch-npu + CANN 环境,但 fastapi / uvicorn 不一定齐。踩的点:

  1. pip install --break-system-packages fastapi uvicorn—— 没这个 flag 直接 PEP 668 劝退。
  2. 模型 from_pretrained 时 torch-npu 会甩一堆 Warning: The /usr/local/Ascend/cann-xxx owner does not match the current owner 和 can not create directory /home/xxx/ascend/log —— 家目录只读的老毛病。提前:
    mkdir -p /opt/atomgit/ascend/log export ASCEND_LOG_DIR=/opt/atomgit/ascend/log
    能压掉大半。
  3. torch_dtype → dtype 替换,前面说过。
  4. 双 NPU 场景:.to("npu:0") 只塞一张卡,改成 device_map="auto"(需 accelerate)能让两张 910 自动拆权重,后面切 32B 时很关键。
  5. 加个简易 API Key 鉴权(Authorization: Bearer xxx / X-API-Key),否则端口万一漏出去被人白嫖算力就尴尬了。

服务起好后,Mac 侧直接 curl:

curl http://127.0.0.1:18002/v1/chat/completions \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"qwen2.5-7b","messages":[{"role":"user","content":"你好,我是Mac,我连上昇腾NPU了"}]}'

JSON 回来那一刻,M3 Air 的 C 面依旧凉凉——活全在远端 NPU 干了。

隧道保活(防容器断联)

容器侧写个简易 watchdog,防 SSH 悄悄断:

# 容器里跑 while true; do if ! pgrep -f "ssh.*18002:127.0.0.1:8000" >/dev/null; then echo "$(date): tunnel died, restarting..." nohup ssh -i /tmp/tunnel_key \ -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null \ -o ServerAliveInterval=30 \ -N -R 18002:127.0.0.1:8000 \ user@jump-node -p JUMP_PORT >/dev/null 2>&1 & fi sleep 30 done

现在的开发流场景走哪条路

  • 重逻辑 / 复杂推理 / 代码生成
    AtomCode Pro,等当前 Pro 过期那天 → 次日早 10 点/login抢 GLM-5.2;或用 Lite 的 DeepSeek-V4-Flash —— 都是平台 / 模型方云端部署,Mac 零负担
  • 长文本 / 对话 / 简单脚本辅助
    本地 Agent 配 base_url:http://127.0.0.1:18002/v1,背后是昇腾容器里的 Qwen2.5-7B(对话能力不错,但写复杂代码有限)
  • 想升杯
    容器里下完 DeepSeek-R1-Distill-Qwen-32B,改 openai_api.py 的 MODEL_PATH 重启即可,Mac 侧 Agent 配置一行不用动

M3 Air 16GB 的"内存压力"黄灯基本消失了,C 面谈凉不谈热。

总结:白嫖有边界,但真香

  • AtomCode 免费 API(GLM-5.2 / DeepSeek-V4-Flash):模型方或平台在云端部署,atomcode 客户端当中转调,Lite 30 天一续不用抢,Pro 抢 GLM 必须等过期次日早 10 点准点/login,这是规则。
  • 昇腾容器自建 Qwen 7B / 32B:跑在华为 NPU 上,SSH 反向隧道穿透回 Mac,当 OpenAI 兼容 endpoint 用,彻底不占本地内存。

踩坑收获清单:

  1. 容器只读家目录 → 东西往 /tmp /opt/atomgit 放
  2. PEP 668 → pip install --break-system-packages
  3. ASCEND_LOG_DIR 必须指向可写目录
  4. torch_dtype 已弃用,改用 dtype
  5. SSH 反向隧道高位端口(18002)才能绑
  6. 双 NPU 用 device_map="auto" 自动拆权重
  7. 简易 API Key 鉴权防白嫖
  8. 隧道保活脚本防断联

如果你也在寻找免费的 AI 算力,手里正好有一台内存吃紧的 Mac,不妨去 ai.atomgit.com 的昇腾生态页面看看。虽然路上有坑,但风景独好!

Happy Coding, Happy Saving!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询