最近终于抽时间继续折腾 Jetson Orin Nano。
一开始我的目标其实很简单:我想让它跑一个本地模型,然后慢慢变成一个可以长期运行的个人 AI 助手。
但实际做下来,这件事比"跑起来一个模型"复杂很多。因为一个真正可用的本地 AI 设备,不只是能回答一句话就结束了。它还需要:
- 本地模型
- 云端模型
- 网络出口
- 自动恢复
- 服务管理
- 模型切换
- 代理配置
- 断电恢复
- 后续语音和视觉扩展
这次折腾下来,Jetson 基本已经从"刚装好的开发板",变成了一个初步可长期运行的 AI 小主机。
一、先从清理系统开始
刚开始检查磁盘的时候,发现系统空间占用比预期高很多。
最后排查到里面有不少历史遗留内容,包括:
- 旧 Docker 镜像
- 旧 llama.cpp Docker 环境
- Docker overlay 数据
- CUDA local repo
- CUDNN local repo
- TensorRT local repo
这些东西并不是全部没用,但很多属于"安装时留下来的本地缓存"或者"旧实验环境"。真正危险的是,模型文件一开始其实藏在 Docker overlay 里面。
如果直接清理 Docker,很可能会把本地模型一起删掉。
所以第一步并不是直接 prune,而是先确认:
- 模型到底在哪里
- 模型是不是唯一副本
- CUDA / PyTorch / TensorRT 是否还依赖这些文件
- Docker 镜像里有没有还需要保留的内容
最后成功把 Gemma 模型从 Docker 环境里迁移出来,保存到用户目录。
清理前后大概变化是:
- 清理前:约 56GB used
- 清理后:约 32GB used
- 净释放:约 24GB
这一步的重点不是"删了多少",而是保住了真正重要的东西。
二、保住本地模型
这次保留下来的本地模型是 Gemma 4 E2B 的 GGUF 版本。
模型文件被保存到本机用户目录下,不再依赖 Docker overlay。这样以后 Docker、容器、旧镜像怎么删,都不会影响模型本体。
当前本地模型目录大致包含:
- Gemma 4 E2B GGUF 主模型
- mmproj 文件
总大小约 3.8GB。
这一步完成后,模型从"藏在 Docker 里面的不确定状态",变成了"明确、可管理、可备份的本地模型资产"。
三、修复 apt / dpkg
清理过程中还发现了一个隐藏问题:系统的 dpkg 状态数据库出过问题。
具体表现是:
apt操作异常dpkg -l结果异常/var/lib/dpkg/status缺失或损坏
这类问题短期可能不影响已经运行的 AI 服务,但以后只要安装软件、更新依赖、装浏览器、装工具,就会出问题。
最后通过系统备份恢复了 dpkg status 数据库,并确认:
dpkg -l正常apt-get check正常- 软件包数据库恢复
这一步算是本次项目里的隐藏大坑。如果不修,后面装 sing-box、浏览器、工具链都会很麻烦。
四、重新编译 llama.cpp
原来的 llama.cpp 是 Docker 里的旧环境。清理 Docker 后,本地只保留了模型,没有推理运行时。
所以接下来重新在 Jetson 上编译 llama.cpp,并启用 CUDA 支持。
最终生成了:
- llama-server
- llama-cli
并确认 CUDA / cuBLAS 能正常链接。
这个过程 CPU 一度满载,属于正常现象。因为它不是在"安装一个软件包",而是在 Jetson 上本地编译 C++ / CUDA 程序。
编译完成后,Jetson 拥有了原生运行 GGUF 模型的能力,不再依赖旧 Docker 镜像。
五、创建 local-gemma-agent
有了模型和 llama.cpp 后,下一步是把它包装成一个长期运行的本地服务。
本地 Gemma Agent 的目标是:
- 在 Jetson 本机运行
- 只监听 localhost
- 提供 OpenAI-compatible API
- 供 Hermes / Melody 或其他 Agent 调用
- 不暴露到公网
服务地址:
http://127.0.0.1:18080/v1
健康检查:
http://127.0.0.1:18080/health
测试结果正常返回:
{"status":"ok"}
这意味着本地模型已经不只是"能跑",而是变成了一个本地 API 服务。
六、修复 GPU Offload,速度提升 6 倍
刚开始测试 Gemma 的时候,速度非常慢。
第一次测试大概只有:
3 token/s 左右
后来发现虽然 llama.cpp 识别到了 CUDA,但启动参数里没有真正把模型层 offload 到 GPU。
也就是说:
看起来有 CUDA
实际上主要在 CPU 跑
后来加上 GPU offload 参数后,速度提升到了:
20~26 token/s
大概是 6 倍提升。
这一步非常关键。因为 Jetson Orin Nano 的价值就在于它有 GPU,如果模型主要跑 CPU,就浪费了硬件能力。
七、把 local-gemma-agent 交给 systemd 管理
手动启动模型有一个问题:
- 终端关了可能会停
- 重启后不会自动恢复
- 断电后需要手动 SSH 进去启动
所以后面给 local-gemma-agent 创建了 systemd service。
最终实现:
- systemd 管理
- 开机自动启动
- 异常退出自动重启
- 使用普通用户运行
- 绑定 127.0.0.1:18080
- 保留 GPU offload 参数
现在系统重启后,本地 Gemma 服务会自动恢复。
这是从"开发环境"进入"服务环境"的重要一步。
八、搭建 Codex Coding Agent
除了本地模型,我还希望有一个更强的云端 coding agent。
本地 Gemma 适合:
- 快速响应
- 离线使用
- 简单问答
- 本地控制
- Agent 路由
但复杂代码任务、本地项目分析、debug、架构修改,还是需要更强的模型。
所以我搭了一个 Codex Coding Agent。
过程里遇到了几个坑:
1. Codex 登录问题
Jetson 是 headless / 半 headless 环境,OAuth 登录会跳转 localhost。如果在另一台电脑浏览器打开登录链接,localhost 指向的是那台电脑,不是 Jetson。
后来尝试 device code,也因为网络原因失败。
最终解决方式是:
- 在 Mac 上完成 Codex 登录
- 找到本机 Codex 的 auth 文件
- 复制到 Jetson 的独立 Codex 目录
这样绕开了 Jetson 上 OAuth callback / token exchange 的问题。
2. 错误代理导致 Codex 超时
一开始 Codex 进程读到了一个错误的代理地址。这个代理地址来自另一个网段,Jetson 实际上访问不到。
结果就是:
- 认证看起来成功
- 进入 Codex 界面
- 但是模型请求一直 Working
- WebSocket / HTTPS 都超时
后来把错误 proxy 配置移除,Codex 正常访问 GPT-5.5。
现在 Codex 已经可以作为 coding agent 使用。
九、给主 Agent 取名 Melody
我不想每个模型都像不同的人。
所以设计了一个统一的人格层:Melody。
底层可以是:
- Hermes
- Gemma
- Codex
- MiniMax
- 未来的语音模型
- 未来的视觉模型
但用户面对的统一身份是 Melody。
也就是说:
人格 = Melody
能力 = 不同模型 / 不同 Agent
这比"每个模型一个人格"更自然。
Melody 的设定是:
- 温和
- 好说话
- 有耐心
- 技术能力强
- 不会让用户觉得自己问了蠢问题
- 会优先保护数据
- 做危险操作前先解释风险
- 喜欢把复杂项目拆成一步一步
这个人格已经写进 Hermes 的 SOUL 文件。主 Agent 之后会以 Melody 的身份运行。
不过 subagent 默认不会自动继承 SOUL 文件,这是 Hermes 的隔离设计。所以额外创建了一个 Melody subagent context snippet,未来需要子 Agent 保持同一语气时,可以显式传入。
十、配置 sing-box,让 Jetson 拥有自己的网络出口
之前 Jetson 依赖其他设备的代理,这不适合长期运行。
因为一个真正的 AI 小主机应该自己能处理网络访问,而不是依赖 Mac、Windows 或路由器临时配置。
所以这次安装并配置了 sing-box。
一开始尝试 TUN 模式,但 Jetson 当前内核 / netfilter 对相关规则支持不完整,导致 TUN 无法正常工作。
后来决定放弃 TUN,改用更稳定的显式代理架构:
- SOCKS5: 127.0.0.1:1080
- HTTP: 127.0.0.1:1081
这个选择反而更适合当前项目。
因为 Jetson 上真正需要代理的主要是:
- Codex
- 未来云端 API
- 未来联网 Agent
而本地 Gemma、localhost 服务、Tailscale 等并不需要代理。
所以最终架构是:
需要访问外部 AI API 的程序
↓
127.0.0.1:1080 / 1081
↓
sing-box
↓
加拿大 / 美国节点
↓
目标服务
这比全局透明代理更可控,也更容易排查问题。
十一、限制节点为加拿大 / 美国
订阅里节点很多,包括多个地区。
但对 AI 服务来说,我更希望使用加拿大 / 美国出口。
原因是部分 AI 服务、模型功能、账号风控和地区支持可能与地区有关。
所以最终配置为:
- 加拿大节点优先
- 美国节点备用
- 香港、台湾、日本、韩国、新加坡等节点不参与自动选择
这样可以减少因为出口地区导致的奇怪兼容问题。
十二、sing-box systemd 化
sing-box 配置完成后,也交给 systemd 管理。
现在 sing-box 已经实现:
- systemd 管理
- 开机自启
- 断电恢复
- SOCKS5 / HTTP 代理端口可用
- 加拿大 / 美国节点池
- 与 Tailscale 不冲突
- 与 local-gemma-agent 不冲突
这样 Jetson 重启后,不需要手动启动代理服务。
十三、模型切换
当前默认模型仍然是 MiniMax-M2.7。
因为它是订阅制,不是按 token 付费,所以没有必要为了省钱强行默认切本地模型。
但我希望 Gemma 能作为可切换模型存在。
现在已经把 local_gemma 注册到了 Hermes 配置里。
目标是实现:
- 默认继续用 MiniMax
- 需要离线 / 本地测试时切到 Gemma
- 复杂 coding 任务用 Codex
- 未来再接入更多模型
当前模型结构大概是:
Melody + MiniMax = 默认云端强脑
Melody + Gemma = 本地离线脑
Melody + Codex = 代码专家
十四、当前系统架构
目前 Jetson Orin Nano 上已经有:
Jetson Orin Nano
├── Tailscale
├── sing-box
│ ├── SOCKS5: 127.0.0.1:1080
│ └── HTTP: 127.0.0.1:1081
├── llama.cpp
├── Gemma 4 E2B
├── local-gemma-agent
│ └── http://127.0.0.1:18080/v1
├── Hermes / Melody
├── Codex Coding Agent
└── MiniMax-M2.7
已经 systemd 化并开机自启的服务:
- Tailscale
- sing-box
- local-gemma-agent
暂时没有 systemd 化的:
- Hermes / Melody
原因是 Melody 本身是控制者。如果现在让她修改自己的启动方式,风险比较高。所以 Hermes/Melody 服务化会放到后面单独处理,并且要有备份、dry-run 和回滚方案。
十五、为什么这次不急着让 Hermes 自启
这是一个很重要的决定。
sing-box、Gemma、Tailscale 都是"外部服务"。它们坏了,可以由 Melody 帮忙排查。
但 Hermes / Melody 是当前的控制者。如果让它自己修改自己的 systemd service,万一写错:
Melody 启动失败
↓
控制者消失
↓
只能人工 SSH 救火
所以更稳妥的顺序是:
- 先把网络、代理、本地模型服务化
- 确认断电恢复没问题
- 最后再单独设计 Hermes / Melody 自启
- 必须有备份和回滚方案
目前这个决定让系统更安全。
十六、目前完成度
已经完成:
- 系统清理
- 模型迁移
- apt / dpkg 修复
- llama.cpp CUDA 编译
- 本地 Gemma 服务
- GPU 加速
- local-gemma-agent systemd 化
- Codex 登录与验证
- Melody SOUL 文件
- sing-box 安装与配置
- 加拿大 / 美国节点筛选
- sing-box systemd 化
- Tailscale 保持自启
当前整体状态:
系统层:稳定
网络层:稳定
代理层:稳定
本地模型:稳定
Codex:可用
Melody:可用
Hermes 自启:暂缓
下一阶段计划
接下来会进入更有趣的阶段。
1. 摄像头接入
目标:
- 接 USB / CSI 摄像头
- 验证 Linux 能否识别
- 测试图像采集
- 后续接入视觉模型
2. Whisper 本地语音识别
目标:
- 接麦克风
- 本地语音转文字
- 中英文识别
- 低延迟输入
3. 语音唤醒
目标:
- 不需要一直打字
- 可以用唤醒词启动 Melody
- 后续配合 TTS 输出
4. Agent Router
目标:
让 Melody 自动判断:
- 简单问题 → Gemma
- 复杂分析 → MiniMax
- 编程任务 → Codex
- 视觉任务 → Vision Agent
5. Hermes / Melody 服务化
最后再做 Melody 自启。
这一步必须谨慎,因为它涉及主控制 Agent 本身。
总结
这次折腾下来,我最大的感觉是:
搭建本地 AI 助手不是"跑一个模型"这么简单。
真正麻烦的是:
- 模型在哪里
- 服务怎么启动
- 网络怎么走
- 断电后怎么恢复
- 哪些东西应该本地
- 哪些东西应该云端
- 哪些服务该自启
- 哪些服务不该急着自启
现在 Jetson 已经不再只是一个开发板,而是一个初步成型的本地 AI 小主机。
它已经具备:
- 本地模型
- 云端 coding agent
- 独立代理出口
- 开机自启服务
- 统一人格 Melody
- 后续语音 / 视觉扩展基础
接下来终于可以从"基础设施搭建"进入"真正好玩的 AI 交互"阶段了。