在 Android/Termux 上使用 Adreno 840 + Vulkan 部署 llama.cpp 本地大模型

随着移动端 SoC 性能越来越强,现在已经可以直接在 Android 手机上运行 GGUF 格式的大语言模型。本文记录一次实际部署过程:使用 Termux + llama.cpp + Mesa Freedreno/Turnip + Vulkan,让高通 Adreno GPU 参与 LLM 推理。 本文以 Adreno 840 为例,并使用 LFM2.5-2.6B-Q8_0 进行测试。 一、环境 本次测试环境: 项目 配置 系统 Android SoC Qualcomm Snapdragon GPU Adreno 840 推理框架 llama.cpp llama.cpp b10516 GPU Backend Vulkan Mesa 26.0.6 Vulkan 驱动 Freedreno / Turnip 模型 LFM2.5-2.6B-Q8_0 模型大小 约 2.7 GB 手机使用的是统一内存架构,因此 vulkaninfo 显示的 GPU memory 并不是传统 PC 独立显卡意义上的 VRAM。 二、安装 Termux 建议使用官方 Termux 项目提供的版本,不建议使用来源不明的第三方修改版。 ...

2026-08-25 · 4 分钟

从零打造 Linux TUN 全局代理客户端:sscli 架构与踩坑记录

一个轻量、原生 Linux、无 GUI 的 Shadowsocks 分流工具的诞生过程。从需求分析到架构选型,从核心实现到踩过的每一个坑。 为什么要做这个 市面上的代理工具很多,但很少有同时满足以下条件的: 纯命令行、无 GUI——跑在服务器/WSL 上,没有桌面环境 全局接管——所有应用流量自动分流,不需要每个程序单独设置代理环境变量 规则分流——国内直连、被墙的走代理,而不是一刀切全代理或全直连 轻量可控——不依赖 Clash/mihomo 那套大而全的框架,只要核心功能 Clash 系太重,simple-tun2socks 没有分流,tun2socks 只做协议转换不做路由决策。于是决定自己造一个。 架构设计 核心思路: TUN 网卡 + 用户态 TCP/IP 栈 + 规则引擎 + Shadowsocks 子进程 Linux / WSL │ 所有应用流量(无需设置任何代理环境变量) ▼ TUN 网卡 (sscli0) │ ▼ sscli 路由引擎(gvisor 用户态 TCP/IP 栈 + 规则匹配) │ ├──── DIRECT ──→ 直接出网(fwmark 防回环) │ └──── PROXY ───→ 本地 SOCKS5 → sslocal → VPS 关键选型 组件 选型 理由 TUN 设备 wireguard/tun (MIT) WireGuard 同款,稳定可靠,MIT 许可 用户态 TCP/IP 栈 gvisor netstack (Apache-2.0) sing-box/mihomo/tun2socks 同款,200 行就能桥接 TUN SOCKS5 客户端 x/net/proxy Go 标准库扩展,支持 UDP ASSOCIATE Shadowsocks 加密 shadowsocks-rust 的 sslocal 不自己实现加密,复用官方预编译二进制,安全可靠 为什么用 gvisor netstack 而不是直接处理 IP 包?因为 gvisor 提供了完整的 TCP/IP 协议栈——你只需要处理"这个连接走代理还是直连",TCP 三次握手、拥塞控制、重传这些脏活累活全由 gvisor 在用户态搞定。 ...

2026-08-22 · 2 分钟

从零搭建一台低频冷备服务器:Debian + ZFS RAIDZ2

一、为什么要单独做一台冷备机 对于一些重要数据,单纯依赖主服务器上的 RAID、快照或者定期备份并不够。 我准备搭建一台专门用于冷备的机器: 4 块 4TB 硬盘 实际冷备数据量不会超过 8TB 一个月甚至更久才开机一次 完成备份、检查后直接关机 平时整机断电 主要目标是防止硬盘故障,同时保证数据长期完整性 这台机器并不是传统意义上的 NAS。 它大部分时间都是: 关机 ↓ 开机 ↓ 备份 ↓ 检查 ↓ 关机 ↓ 断电 因此设计目标不是高性能,也不是提供 7×24 小时文件共享,而是尽可能简单、可靠。 二、为什么选择 RAIDZ2 4 块 4TB 硬盘一共有约 16TB 原始容量。 由于实际需要的冷备容量不到 8TB,因此没有必要为了容量去选择 RAID5。 最终选择: 4 × 4TB → ZFS RAIDZ2 RAIDZ2 相当于双校验,可以容忍同时损坏两块硬盘。 大致结构: 4 × 4TB HDD │ ▼ RAIDZ2 │ ▼ ≈ 8TB 可用容量 对于冷备场景来说,容量利用率并不是第一目标。 相比 RAID5,RAIDZ2 可以在一块硬盘已经损坏、正在更换和恢复的情况下,再承受一块硬盘故障,因此更适合这种低频使用、长期存放数据的场景。 三、为什么选择 ZFS,而不是 mdadm RAID6 RAIDZ2 和传统 RAID6 在容错能力和可用容量上非常接近。 ...

2026-08-09 · 3 分钟

Hermes Agent Docker 部署踩坑实录:从「能跑」到「为什么我最终放弃容器化」

最近折腾了一段时间 Hermes Agent。 最开始我的想法非常简单: «Hermes 不就是一个 AI Agent 吗?Docker 隔离一下环境,岂不是既干净又方便升级?» 于是我选择了 Docker 部署。 结果一路从"这东西跑起来真简单",折腾到了"我已经把 Docker 部署所有坑都踩完了"。 最后得出的结论反而是: Hermes 可以很好地运行在 Docker 里,但如果你的目标是让它长期作为一台机器上的自动化 Agent 使用,原生部署反而更加合理。 这篇文章记录一下整个过程。 一、为什么一开始选择 Docker 我平时本身就大量使用 Docker。 数据库、Home Assistant、各种 Web 服务基本都是容器化部署,因此看到 Hermes 官方提供 Docker 镜像之后,第一反应就是: services: hermes: image: nousresearch/hermes-agent:latest container_name: hermes restart: unless-stopped command: gateway run ports: - "9119:9119" # Dashboard(默认 127.0.0.1,按需暴露) volumes: - ./data:/opt/data environment: HERMES_DASHBOARD: "1" 然后: ...

2026-08-07 · 4 分钟

Hermes Dashboard 修改密码:配置热更新技巧

修改 Hermes Dashboard 的登录密码,不需要重启整个容器——改配置 + kill 进程即可,QQ 会话不断线。 背景 Hermes Agent 的 Dashboard(Web 管理界面)默认带 basic auth 登录。Dashboard 页面本身没有"改密码"功能,需要改配置文件。但很多人以为要重启容器才能生效——其实有更轻的方式。 方法 1. 改配置文件 编辑 Hermes 配置(config.yaml),找到 dashboard 的 basic_auth 配置: dashboard: basic_auth: username: admin password_hash: "<scrypt 哈希>" # 或明文 password: "xxx" 两种密码写法: password_hash:scrypt 哈希(推荐,不存明文) password:明文密码(简单但安全性低) 生成 password_hash(交互式输入,避免密码出现在命令行历史里): # 容器部署的,先进入容器内再执行: docker exec -it <容器名> bash # 然后在容器内: python3 -c " from plugins.dashboard_auth.basic import hash_password import getpass pw = getpass.getpass('输入新密码: ') print(hash_password(pw)) " 用 getpass 交互输入——密码不会显示在终端、不会进 shell history。 (如果容器里找不到 plugins 模块,说明需要在 Hermes 的虚拟环境里执行:/opt/hermes/.venv/bin/python3) ...

2026-08-07 · 1 分钟

Hugo + PaperMod 博客搭建记录(含踩坑)

本博客即本文的产物。记录完整搭建过程和踩过的坑,供以后重建参考。 技术选型 Hugo v0.164.0(extended)— Go 单二进制,极快 PaperMod 主题 — 极简技术风,内置搜索/归档/标签 目标:按日期更新的技术日志流 搭建步骤 1. 安装 Hugo(容器内,免 root) # 下载官方 release 的 tar.gz 到用户目录(路径按实际环境替换) curl -L "https://github.com/gohugoio/hugo/releases/download/v0.164.0/hugo_extended_0.164.0_linux-amd64.tar.gz" -o /tmp/hugo.tar.gz mkdir -p ~/bin && tar -xzf /tmp/hugo.tar.gz -C ~/bin hugo # 验证 ~/bin/hugo version 2. 建站点 + 装主题 cd ~ && ~/bin/hugo new site techlog git clone --depth 1 https://github.com/adityatelange/hugo-PaperMod ~/techlog/themes/PaperMod 3. 配置 config.toml(中文) 关键配置点: theme = "PaperMod" 菜单:归档 / 搜索 / 标签 输出:HTML + RSS + JSON(搜索需要) 4. 创建归档/搜索页面 <!-- content/archives.md --> --- title: "归档" layout: "archives" url: "/archives/" --- <!-- content/search.md --> --- title: "搜索" layout: "search" url: "/search/" --- 5. 构建 hugo --minify # 输出到 public/ 踩坑记录 坑 1:hugo.toml vs config.toml 并存 Hugo 0.164 的 hugo new site 默认生成 hugo.toml,如果又写了 config.toml,两个文件并存时 hugo 优先读 hugo.toml(还是默认内容),你的配置全部不生效。 ...

2026-08-07 · 2 分钟

AI 用量成本真相:4 亿 token 里 98.6% 是便宜的缓存读

仪表盘显示 7 天消耗 4 亿 token,看似吓人——但拆开看,真实成本一个月才几十块。 现象 hermes insights 显示: 输入 477 万 + 输出 92 万 Total 4 亿(对不上?) 真相:Total = 输入 + 输出 + 缓存读 + 缓存写 + 推理 4 亿的真实构成: 项目 数量 占比 缓存读取(cache read) 3.99 亿 98.6% 输入 447 万 1.1% 输出 76 万 0.2% 推理 33 万 0.08% “4 亿"几乎全是缓存读取——不是真的消耗了 4 亿新 token。 为什么有这么多缓存读 长会话场景(如 QQ 单窗口聊天):每轮对话都要把整个会话历史重新发给模型。但历史大部分没变,被**上下文缓存(cache)**命中——服务端只收极低的缓存价,不重新计费。 单轮实测:发一条消息,输入 2,421 token,但缓存读 23 万(整个历史)。 成本换算 按 DeepSeek V4-Flash 价格(涨价前): ...

2026-08-06 · 1 分钟

Firecrawl 计费陷阱:PDF 提取按页计费

一次 82 页 PDF 提取烧掉 84 credits(月度免费额度的 8.4%),血的教训。 计费规则(官方确认) 操作 消耗 搜索 2 credits / 10 条结果(向上取整) HTML 提取 1 credit / 页 PDF 提取 按页计费(82 页 ≈ 84 credits) 搜索+自动抓正文 搜索 2 + 每结果 1 credit 免费额度:1000 credits/月。 教训 PDF 绝对不要直接扔给 Firecrawl 提取——按页计费,一个几十页的 PDF 就能烧掉月度额度的百分之几到十几。 正确做法 PDF → curl 下载到本地 → 本地解析(pymupdf/read_file) → 免费 HTML → Firecrawl(1 credit/页) 或 curl 搜索 → DeepSeek 服务端(不耗 Firecrawl 额度) 实测对比: 82 页 PDF 扔 Firecrawl:84 credits 同 PDF curl + 本地解析:0 credits 为什么 Firecrawl 搜索也烧额度 Firecrawl 的搜索默认会抓每个结果的正文(“search + extraction in one call”)——一次搜索 10 条结果 = 2(搜索)+ 10(抓取)= 12 credits。所以搜索密集场景要小心,最好用纯搜索服务(如 DeepSeek web_search)。 ...

2026-08-06 · 1 分钟

搜索体系重建:DeepSeek 服务端搜索 + Firecrawl 提取

2026-08-05 ~ 08-06 折腾两天,解决"搜索引擎全被反爬"的痛点的完整方案。 背景 之前用 curl/浏览器直接抓搜索引擎(Google/Bing/DDG/Startpage/Yandex 等),结果全被反爬挡住(CAPTCHA/403/验证页)。需要一个稳定、免反爬、低成本的搜索方案。 方案演进 阶段 1:发现 DeepSeek 支持服务端 web_search DeepSeek 官方 Responses API 支持 web_search 工具——搜索在 DeepSeek 服务器端执行,客户端拿到的就是结构化结果,完全绕开反爬。 关键验证: api.deepseek.com/v1/responses 支持 tools: [{type: web_search}] 事件流有 web_search_call.in_progress / searching / completed 返回结果含 title/url/description 阶段 2:发现 opencode-go 中转也支持 意外收获:opencode-go 的 /zen/go/v1/responses 端点同样支持 web_search 工具——意味着可以用已有的 OPENCODE_GO_API_KEY(和主模型同一账户),不用额外注册 DeepSeek 官方 key。 实测: {"tools": [{"type": "web_search"}]} → output 含 web_search_call(completed),返回真实搜索结果 阶段 3:Firecrawl 负责提取(分工) 社区共识:Firecrawl 擅长网页提取(extract),搜索是弱项(官方也承认"basic search endpoint, not true SERP")。于是分工: web.search_backend: deepseek ← 搜索(服务端,免反爬) web.extract_backend: firecrawl ← 提取(HTML 转 markdown) 最终架构 ┌─────────────────────────────────────────────┐ │ 搜索(web_search) → opencode-go /responses │ │ → DeepSeek 服务端执行 → 结构化结果 │ ├─────────────────────────────────────────────┤ │ 提取(web_extract) → Firecrawl API │ │ → 网页转 markdown(1 credit/页) │ ├─────────────────────────────────────────────┤ │ 兜底 → cn.bing / 搜狗 / curl 直抓 │ └─────────────────────────────────────────────┘ 关键点 搜索和提取解耦:搜索走模型服务商(不烧 Firecrawl 额度),提取走 Firecrawl(免费 1000 credits/月) 服务端搜索免反爬:反爬是客户端直抓的问题,服务端执行彻底绕开 成本极低:搜索按 token 计费(缓存命中 0.02 元/百万),提取 1 credit/页 附:Firecrawl 注册 2026 年 6 月起 Firecrawl 推出 Keyless 模式(免 key 每月 1000 credits),但 Hermes 插件仍需要 key——邮箱注册即可拿到 fc- 开头的 key,免费额度无需绑卡。 ...

2026-08-06 · 1 分钟

AI Agent 记忆分层架构:常驻内存 + 外部知识库

解决 AI Agent 记忆"不够用、存不下、查不到"三难问题的实践方案。 问题背景 AI Agent(如 Hermes)的持久记忆面临矛盾: 常驻记忆有容量上限(默认 2000 字符,可扩容)— 存不了多少事实 全部塞进上下文太贵——每轮对话都要重新发送,按 token 计费 低频信息不能丢——设备配置、排障细节、API 用法,几周后可能还要用 分层方案 ┌─────────────────────────────────────────────┐ │ 第一层:常驻记忆(memory) │ │ · 高频事实:IP/端口/凭据位置/用户偏好/关键配置 │ │ · 默认2000字符可扩容,每轮注入上下文 │ │ · 只放精简核心 │ ├─────────────────────────────────────────────┤ │ 第二层:外部知识库(fact_store) │ │ · 低频背景:设备配置/排障细节/软件特性/API用法 │ │ · 大容量、不衰减、不删除、不占 token │ │ · 结构化存储,支持实体关联/组合查询 │ ├─────────────────────────────────────────────┤ │ 第三层:会话历史(session db) │ │ · 完整对话记录,可全文检索 │ │ · 用于回溯"当时怎么做的" │ └─────────────────────────────────────────────┘ 核心机制 1. 自动分层存储 先扩容常驻记忆(默认 2000 → 8000 字符),容纳更多高频事实 扩容后仍放不下的低频信息 → 外部库 Agent 判断信息频度:高频 → 常驻 memory,低频 → 外部库 存储时自动打标签(tags),支持实体关联 2. 索引锚点(关键设计) 外部库内容不注入上下文(不占 token),但需要"知道有这回事"才能去查: ...

2026-08-05 · 1 分钟