在 ARM VPS 上用 llama.cpp 部署 Gemma 4 E2B 本地模型

在 ARM VPS 上,使用 llama.cpp 的 Docker 镜像部署本地 LLM,记录从 Gemma 3 到 Gemma 4 的部署过程、性能测试和资源监控。 背景:Gemma 4 发布 2026 年 3 月,Google DeepMind 发布了 Gemma 4 系列开源模型。Gemma 4 带来了多项重大升级: 推理能力:全系模型支持可配置的思维链(Chain of Thought)推理模式 多模态:支持文本、图像输入,小模型(E2B/E4B)额外支持音频 MoE + Dense 双架构:提供 Dense 和混合专家(Mixture-of-Experts)两种架构 超长上下文:小模型 128K tokens,大模型 256K tokens 原生函数调用:支持 function calling,适用于 Agent 场景 原生系统提示:首次原生支持 system role Gemma 4 共 4 个规格: 模型 架构 有效参数 上下文长度 特点 E2B Dense 2.3B 128K 轻量高效,支持音频,适合手机/边缘设备 E4B Dense 4.5B 128K 平衡性能,支持音频 26B A4B MoE 3.……

阅读全文

Claude Code 完整使用手册

引言 Claude Code 是由 Anthropic 公司开发的 AI 驱动的代码编辑器和开发助手。它将强大的 Claude AI 模型深度集成到开发环境中,为开发者提供前所未有的智能编程体验。 与传统 IDE 的区别 传统 IDE(如 VS Code、IntelliJ IDEA)主要提供代码编辑、语法高亮、调试等基础功能,而 Claude Code 通过以下方式重新定义了开发体验: 自然语言交互:可以用中文或英文直接描述任务,无需记忆复杂的命令 智能理解:能够理解整个代码库的上下文,跨文件进行推理 自动化执行:从任务规划到代码实现,全自动完成 多工具集成:集成文件操作、命令执行、浏览器测试等全套开发工具 学习适应:随着使用,AI 会逐渐理解你的编码风格和项目需求 核心优势 效率提升:减少 70% 以上的重复编码工作 质量保证:AI 帮助发现潜在 bug 和优化机会 学习加速:实时解释代码逻辑,快速掌握新技术 跨领域能力:前端、后端、DevOps 全栈支持 安全可靠:本地化执行,代码不离开你的机器 适用场景 新项目快速原型开发 代码重构和优化 调试和问题排查 学习新技术栈 自动化脚本编写 文档生成和维护 测试用例编写 安装和配置 系统要求 操作系统:macOS、Linux、Windows(WSL2) Node.js:v16 或更高版本(如使用 CLI 版本) IDE:Visual Studio Code(推荐)或支持的编辑器 网络:稳定的互联网连接(访问 Anthropic API) 安装方式 方式一:VS Code 扩展(推荐) 打开 VS Code 在扩展商店搜索 “Claude Code” 点击安装 安装完成后,会在侧边栏看到 Claude Code 图标 方式二:CLI 版本 # 使用 npm 安装 npm install -g @anthropic-ai/claude-code # 或使用 yarn yarn global add @anthropic-ai/claude-code # 验证安装 claude-code --version 初始化配置 首次使用需要配置 API 密钥:……

阅读全文

wg 使用

wg-go 使用说明 项目地址: https://github.com/marlin2024/wg-go 介绍 wg-go 提供了一套工具,可以在 非 root 用户 下运行 WireGuard,并且支持通过 Cloudflare Warp 落地到指定国家或地区。 它的核心思路是把 WireGuard 封装成 SOCKS5 代理,避免直接使用 tun,这样既安全又方便,也非常适合容器环境。 特性 非 root 用户即可运行 WireGuard 提供 SOCKS5 代理接口 支持 Warp 与其他代理叠加 容器环境友好 可以搭建 wg-over-wg 这样的实验场景 使用方法 1. socks-wg 直接将 WireGuard 转换成本地 SOCKS5 代理。 go run ./socks_over_wg \ -config socks_over_wg/wg.conf \ -listen 127.0.0.1:9999 效果对比: # 直连(本机 IP) curl https://ipinfo.io/json # 通过 socks-wg 代理(Warp IP) curl -x socks5://127.0.0.1:9999 https://ipinfo.io/json 2. socks-wg-upstream_socks 在 socks-wg 的基础上,可以指定上游 SOCKS 代理。……

阅读全文

如何优雅地重复读取HTTP响应体

背景介绍 在Go语言中处理HTTP请求时,我们经常需要多次读取响应体(Response Body)的内容。然而,默认情况下Response Body只能被读取一次,这是因为它实现了io.ReadCloser接口,读取完毕后数据就会被消费掉。本文将介绍一个优雅的解决方案。 问题描述 假设我们有以下场景: 需要在日志中记录API的响应内容 需要对响应内容进行多次处理 需要在中间件中查看响应内容,同时不影响后续处理 解决方案 我们可以使用io.TeeReader来实现响应体的复制,这样就能多次读取相同的内容。以下是具体实现: package main import ( "bytes" "fmt" "io" "net/http" ) func DupReadCloser(reader io.ReadCloser) (io.ReadCloser, io.ReadCloser) { var buf bytes.Buffer tee := io.TeeReader(reader, &buf) return io.NopCloser(tee), io.NopCloser(&buf) } func DupResponseBody(resp *http.Response) ([]byte, error) { var buf io.ReadCloser resp.Body, buf = DupReadCloser(resp.Body) data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } resp.Body = buf return data, nil } 代码解析 DupReadCloser函数:接收一个io.……

阅读全文

Jetbrains 非预期 format 代码过滤

在升级到 2025.1 系列版本后,我们项目中的 .proto 文件出现了一个令人头疼的问题:仅仅修改几行内容,却引发了整个文件的大面积 format 变化。 由于我们使用的是公共 repo,我们一直非常注重 diff 的最小化,避免格式化带来的冗余变更。但这次 .proto 文件却被“悄悄”改了样子。 ❓ 发生了什么? 我们原本以为是 protobuf 插件导致的自动格式化,于是尝试关闭 .proto 文件的相关插件支持,退回纯文本模式。然而,问题依旧存在。 在多次对比 format 前后的差异后,我们终于发现—— 原来是 所有注释行最后的空格被自动移除了。 也就是说,哪怕我们只改了一行逻辑代码,整个文件中尾部有空格的注释行也被一并“清理”,导致 Git diff 看起来像是大动干戈,实际只是视觉污染。 ✅ 解决方案:添加 .editorconfig 为了彻底杜绝这类问题,我们最终采用了 .editorconfig 文件配置来控制编辑器行为。 在项目根目录下创建 .editorconfig 文件,内容如下: [*] trim_trailing_whitespace = false 这条配置的意思是:对所有文件类型,不自动清除行尾空格。 配置完成后,记得重启编辑器,确保设置生效。……

阅读全文

解决 SELinux 拦截导致 systemctl 启动服务失败的问题

SELinux 与 systemctl 执行问题的解决方案 在系统管理中,SELinux(Security-Enhanced Linux)是一种强制访问控制(MAC)安全机制。尽管它提供了更高的安全性,但有时也会引发一些问题。本文将介绍一个常见的问题,并详细说明如何通过日志确认问题并修正它。 问题描述 我们遇到了一个问题,即可以直接使用命令执行某个服务,但当尝试使用 systemctl start caddy 命令启动时,却会出现以下错误: (code=exited, status=203/EXEC) 日志确认问题 要确认是否是SELinux导致的问题,可以通过查看系统的审计日志。在终端中使用以下命令: grep 'avc: ' /var/log/audit/audit.log 你会看到类似下面的日志条目: type=AVC msg=******: avc: denied { execute } for pid=**** comm="(caddy)" name="caddy" dev="dm-0" ino=**** scontext=********* tclass=file permissive=0 这条日志中的信息显示,SELinux 拒绝了 caddy 服务执行的请求。 解决方案 为了解决这个问题,我们可以采取临时方案,即将需要执行的文件放置在 /usr/bin 目录下。以下是具体步骤: 将 caddy 文件移动到 /usr/bin 目录下: sudo mv /path/to/caddy /usr/bin/ 执行 restorecon 命令,恢复文件的SELinux安全上下文: sudo restorecon -Rv /usr/bin restorecon 命令会根据SELinux策略恢复指定目录下文件的默认安全上下文。在执行完这个命令之后,你放在 /usr/bin 下的 caddy 文件就可以正常使用了。 为什么放在 /usr/bin 下才能用? SELinux 对系统中的每个文件和进程都施加了安全上下文。当你将文件放置在 /usr/bin 目录下时,系统会自动为这些文件分配合适的安全上下文,使得它们可以被系统服务执行。而自定义目录中的文件可能没有正确的安全上下文,因此被SELinux拒绝执行。……

阅读全文

adguard home 安装与配置

引言 AdGuard Home 是一款网络级广告和跟踪器拦截器。它可以帮助你在家中或办公室的网络上拦截广告,保护隐私,并且提升上网速度。选择 AdGuard Home 的原因包括它的开源性质、易于配置和强大的功能。 安装 部署我们选择 docker + caddy 的方式 使用 docker 部署 adguard adguard 提供了 docker 部署的方式: github地址 建议使用 docker run --name adguardhome --restart unless-stopped -v /root/adguardhome/work:/opt/adguardhome/work -v /root/adguardhome/confdir:/opt/adguardhome/conf -p 53:53/tcp -p 53:53/udp -p 8080:80/tcp -p 4443:443/tcp -p 4434:443/udp -p 3000:3000/tcp -d adguard/adguardhome 配置 caddy yourdomain.com { reverse_proxy 127.0.0.1:3000 配置 adguard 访问 http://yourdomain.com:3000 进行配置 访问 admin 配置页面 修改 CaddyFile 文件,修改为配置 yourdomain.com { reverse_proxy 127.0.0.1:8080 配置 adguard 配置 DOH 需要配置上, 证书和密钥, 证书可以使用 acme.……

阅读全文

golang json.Marshal(error) 返回 `{}`, 问题分析与解决方案

序列化 Go 语言中的 error 接口问题:问题发现、原因与解决方案 在开发 Go 语言项目时,我们常常需要将结构体序列化为 JSON 格式。然而,当结构体中包含 error 接口时,序列化结果往往会不如预期。在这篇博客中,我们将讨论这个问题的原因,并提供两种解决方案。 问题描述 我们有一个结构体 CustomError,其中包含一个 error 类型的字段。如下所示: package main import ( "encoding/json" "fmt" ) type CustomError struct { UserID int64 Err error } func (e *CustomError) Error() string { return fmt.Sprintf("user %d: %s", e.UserID, e.Err.Error()) } func main() { var errs []CustomError errs = append(errs, CustomError{UserID: 1, Err: fmt.Errorf("error 1")}) errs = append(errs, CustomError{UserID: 2, Err: fmt.Errorf("error 2")}) errs = append(errs, CustomError{UserID: 3, Err: fmt.……

阅读全文

使用 docker 搭建 filebrowser

filebrowser 是一个文件管理器,可以通过 web 界面管理文件,支持文件上传、下载、预览等功能。 详情可以参考github:github 使用 docker 搭建 filebrowser 先初始化配置文件和数据库文件 这个在 https://filebrowser.org/installation 上没有说明, 如果直接启动将直接失败 mkdir -p /root/filebrowser touch /root/filebrowser/filebrowser.db touch /root/filebrowser/config.json echo '{ "port": 80, "baseURL": "", "address": "", "log": "stdout", "database": "/database.db", "root": "/srv" }' > /root/filebrowser/config.json 使用 docker 启动 filebrowser docker run \ -d --name=filebrowser \ -v /root/filebrowser/file:/srv \ -v /root/filebrowser/filebrowser.db:/database.db \ -v /root/filebrowser/config.json:/.filebrowser.json \ -u $(id -u):$(id -g) \ -p 8081:80 \ --restart=always \ filebrowser/filebrowser 查看日志, 看到如下日志就证明已经启动成功了 2024/05/26 15:38:15 Warning: filebrowser.……

阅读全文

博客迁移到 cloudflare pages

最近把博客迁移到了cloudflare pages,感觉还不错,速度也挺快的。 顺便记录下这个过程。 需要先在 github 上创建好仓库, 可以参开这里。 在 cloudflare pages 上创建一个应用, 连接到 github 上的仓库。 选择使用 hugo 静态网站生成器。 ……

阅读全文