【免费下载链接】koharu
ML-powered manga translator, written in Rust.
本文围绕 Koharu 仓库中面向编码 Agent 的runtime技能(.agents/skills/runtime/SKILL.md)展开,完整讲解如何通过一条命令同步 llama.cpp 与 stable-diffusion.cpp 的 vendored C/C++ 头文件、触发 Rust FFI 绑定重新生成,并联动更新koharu-runtime中的运行时版本常量。读完本文,你将掌握 Koharu 原生运行时的标准升级流程、绑定生成的底层机制,以及如何用聚焦的 Cargo 检查验证五个运行时 crate 的改动。
一、.agents目录:为编码 Agent 准备的资源库
Koharu 仓库根目录下存在一个面向编码 Agent 的专用资源目录 .agents/README.md,它只说明了两件事:
skills/目录存放面向特定维护任务的可复用工作流;- 仓库级的长期约束仍然保留在根目录的 AGENTS.md 中,由 Codex 等 Agent 自动发现。
这种分工与 AGENTS.md 开头的规定完全一致:仓库级文件只记录"持久、与仓库绑定的约束"(如变更策略、源码边界、ML 架构、上游对齐、性能与验证规则),而把"当前文件布局、临时路径、模型清单、辅助工具名"等实现细节排除在外——这些容易在重构中变化的内容,恰恰被放进了.agents/skills/的技能描述与脚本里,便于随实现演进而更新。
二、runtime技能:元数据与适用场景
技能本体是 SKILL.md,其 frontmatter 定义了 Agent 触发该技能的条件:
name: runtime description: Sync Koharu's llama.cpp and stable-diffusion.cpp headers and Rust bindings. Use when updating native runtime releases, vendored C/C++ headers, koharu-llama, or koharu-diffusion after upstream API changes.即:当需要更新原生运行时发布版本、vendored C/C++ 头文件、koharu-llama、koharu-diffusion(例如上游 llama.cpp / stable-diffusion.cpp API 发生变化)时,就应该进入这个技能的工作流。
配套的 Agent 界面描述位于 .agents/skills/runtime/agents/openai.yaml,它为配置了该技能的 Agent 提供默认提示词,把"同步 llama.cpp 与 stable-diffusion.cpp 运行时、头文件和绑定"这一任务与$runtime技能绑定,方便模型在工具选择阶段直接命中正确技能。
三、核心工作流:一条命令同步头文件
在仓库根目录运行 sync.sh 即可完成头文件同步:
.agents/skills/runtime/scripts/sync.sh脚本以set -euo pipefail开头,任何一步失败都会立即终止并返回非零退出码,避免留下半更新状态。它的工作分为四步:
1. 解析上游发布版本
source_tag() { local repository=$1 local release=$2 local source=${release%.*} if [[ "$source" == "$release" ]] || ! gh api "repos/$repository/releases/tags/$source" --silent 2>/dev/null; then source=$release fi printf '%s' "$source" } llama_release=$(gh api 'repos/koharu-rs/llama/releases/latest' --jq '.tag_name') diffusion_release=$(gh api 'repos/koharu-rs/diffusion/releases/latest' --jq '.tag_name')脚本依赖gh(GitHub CLI)查询 koharu-rs/llama 与 koharu-rs/diffusion 两个 fork 的最新 release tag。source_tag处理了"主 tag + 补丁号"的常见情况:例如 release 为b11317.1时,先尝试去掉最后一个点之后的内容得到b11317作为源码 tag;只有当剥离后的值与 release 相同(本就没有点号)或该 tag 在仓库中不存在时,才退回使用完整 release 名。
2. 同步 llama.cpp 系列头文件
脚本通过while read -r source target循环,逐行把上游源码文件下载到仓库内的 vendored 位置:
| 上游 llama.cpp 源路径 | 仓库内目标路径 |
|---|---|
include/llama.h | crates/koharu-llama-sys/include/llama.h |
ggml/include/gguf.h | crates/koharu-llama-sys/include/gguf.h |
ggml/include/ggml.h | crates/koharu-llama-sys/include/ggml.h |
ggml/include/ggml-alloc.h | crates/koharu-llama-sys/include/ggml-alloc.h |
ggml/include/ggml-backend.h | crates/koharu-llama-sys/include/ggml-backend.h |
ggml/include/ggml-cpu.h | crates/koharu-llama-sys/include/ggml-cpu.h |
ggml/include/ggml-opt.h | crates/koharu-llama-sys/include/ggml-opt.h |
tools/mtmd/mtmd.h | crates/koharu-llama-sys/include/mtmd.h |
tools/mtmd/mtmd-helper.h | crates/koharu-llama-sys/include/mtmd-helper.h |
注意mtmd.h与mtmd-helper.h来自 llama.cpp 仓库的tools/mtmd/目录——mtmd 是 llama.cpp 生态中的多模态标记(multimodal tokenizer)辅助库,它通过 wrapper.h 与 llama.h、gguf.h 一起被纳入 FFI 绑定范围,这也解释了为什么运行时包中同时需要libllama.so与libmtmd.so两个动态库(见下文第四节)。
3. 同步 stable-diffusion.cpp 头文件
curl -fsSL \ "https://raw.githubusercontent.com/leejet/stable-diffusion.cpp/$diffusion/include/stable-diffusion.h" \ -o crates/koharu-diffusion-sys/include/stable-diffusion.hstable-diffusion.cpp 侧只 vendored 一个 stable-diffusion.h,目标位于 crates/koharu-diffusion-sys/include/,与 wrapper.h 中的#include "stable-diffusion.h"一一对应。
4. 打印最新版本号
printf 'llama.cpp: %s\nstable-diffusion.cpp: %s\n' "$llama_release" "$diffusion_release"脚本结束时会把两个 fork 的最新 release tag(注意是 release 名而非剥离后的源码 tag)打印到终端,这些版本号将作为下一步手动更新的输入。
一个容易被忽略的事实是:sync.sh 只更新头文件,并不直接生成 Rust 绑定。绑定由各 sys crate 在cargo build时通过build.rs调用 koharu-bindgen 自动生成,因此"运行脚本 → 更新版本常量 → 触发一次构建"就是完整的同步闭环。
四、同步之后:更新运行时版本与安全包装
SKILL.md 明确给出了脚本运行后的后续步骤:
Use those versions to update
crates/koharu-runtime/src/runtime/packages/llama.rsandcrates/koharu-runtime/src/runtime/packages/diffusion.rs.
1. 更新版本常量
在 crates/koharu-runtime/src/runtime/packages/llama.rs 中,运行时包通过一个RELEASE常量固定下载资产的发布版本:
const RELEASE: &str = "b11317";而 crates/koharu-runtime/src/runtime/packages/diffusion.rs 对应为:
const RELEASE: &str = "master-929-3f8527a.3";这两个常量不仅用于拼接下载 URL,还决定包在本地 Store 中的缓存路径(Store::root()/llama/{RELEASE}/{variant}与Store::root()/diffusion/{RELEASE}/{variant},见 store.rs 的Store::directory逻辑)。因此升级上游后必须同步修改,否则会出现"头文件已更新但下载的二进制仍为旧版本"的不一致状态。
2. 审查生成的绑定
两个 sys crate 的 build.rs 会在编译期用koharu_bindgen::Generator从 wrapper 头文件生成绑定并写入OUT_DIR/bindings.rs,src/lib.rs 则通过include!(concat!(env!("OUT_DIR"), "/bindings.rs"))引入。升级头文件后,需要检查新生成的绑定是否包含预期的 API、类型与常量。为此,koharu-bindgen/src/main.rs 还提供了一组 CLI 参数,可在 CI 或本地独立复现生成过程:
| 参数 | 说明 |
|---|---|
--header/-o | 指定 C 头文件与输出路径 |
--library-name | 声明动态库名(决定__KOHARU_BINDGEN_LIBRARY_NAMES) |
--clang-arg | 透传 clang 参数(如-I头文件搜索路径) |
--allowlist-function/type/var | 仅保留指定前缀的符号 |
--blocklist-function/type/var | 排除指定符号 |
--no-layout-tests/--use-core | 关闭布局测试 / 使用core而非std |
两个 sys crate 的 build.rs 都通过正则 allowlist 收窄符号面:koharu-llama-sys 只保留^(ggml|gguf|llama|mtmd)_.*的函数、类型与变量;koharu-diffusion-sys 则精确列出sd_*、new_sd_ctx、generate_image、new_upscaler_ctx、adetail_image等一组合法符号,超出范围的符号不会被绑定。
3. 更新安全包装并做聚焦检查
审查绑定后,需要按需更新安全包装 crate(koharu-llama与koharu-diffusion),最后只对五个运行时 crate 运行聚焦的 Cargo 检查——即koharu-llama-sys、koharu-llama、koharu-diffusion-sys、koharu-diffusion、koharu-runtime这五个与 llama/diffusion 运行时直接相关的 crate。这与 AGENTS.md 的验证规则一致:"默认只运行最小相关检查或聚焦测试一次(debug profile),不跑全量测试套件",既保证改动被验证,又避免不必要的构建开销。
五、绑定生成链路:从 C 头文件到动态加载适配器
理解同步流程的价值,需要先看懂 koharu-bindgen 做了什么。以 koharu-llama-sys/build.rs 为例,生成过程是:
- 以 wrapper.h 为入口,它依次 include 了 llama.h、gguf.h、mtmd.h、mtmd-helper.h;
- 配置
bindgen::Builder:追加-Iinclude 路径、关闭布局测试、开启derive_partialeq、设置三个 allowlist 正则、关闭枚举名前缀; - 调用
Generator::from_header(..., "llama").with_libraries(["llama", "mtmd"])——两个库名意味着生成的绑定会尝试在llama与mtmd两个动态库中查找符号。
koharu-bindgen/src/lib.rs 的Generator::generate()先跑 bindgen,再把输出交给 rewrite.rs 的rewrite_bindings_for_libraries做一次语法树级重写,把原始的extern "C"函数声明改写成"顶层动态加载适配器"。改写后的绑定具备以下特性(见 rewrite.rs 中的loader_tokens与adapter_tokens):
- 用
OnceLock缓存符号指针,每个 C 函数只解析一次; - 按平台映射库文件名:Windows 为
llama.dll、macOS 为libllama.dylib、Linux 为libllama.so; - 先尝试复用进程内已加载的同名库(Windows 用
open_already_loaded,Linux 用RTLD_NOLOAD),再尝试可执行文件目录与 macOSFrameworks下的捆绑路径,最后回退到系统搜索路径; - 所有库加载失败时直接 panic,找不到符号时 panic 并列出缺失符号名;
- 生成的源文件头部写有 "Automatically generated by koharu-bindgen. Do not edit by hand."——与 AGENTS.md 中"不得手改生成或派生源码,应修改权威输入并重新运行生成器"的源码边界规则严格对应。
这套动态加载设计的直接受益者正是koharu-runtime:运行时在启动阶段决定加载哪个平台的二进制,绑定层则保持与具体库解耦。
六、运行时激活链路:下载、硬件发现与依赖排序
同步工作流的最终目的是让koharu-runtime能在目标机器上正确激活对应平台的 llama/diffusion 二进制。整条链路在 crates/koharu-runtime/src/runtime/mod.rs 中可见:
Feature::{Torch, Llama, Diffusion}表示消费方请求的运行时能力;Runtime::discover(features)先做硬件发现(Hardware::discover()),再对每个候选设备尝试生成安装计划;Runtime::initialize()按计划安装并激活所有包,最终返回进程级Device。
包层面的平台与后端选择位于 llama.rs 的DiscoverablePackage::discover:在 Windows/Linux x86_64 上依次探测 CUDA → ROCm → Vulkan,macOS 上选择 Metal,Linux aarch64 仅支持 CUDA;每个变体对应一个带strum属性的资产名(如x86_64-pc-windows-msvc-cuda.tar.gz)。dependencies()进一步声明:CUDA 变体依赖Cuda::Runtime13与Cuda::Blas13,ROCm 变体依赖Rocm目标,Vulkan/Metal 无额外依赖;diffusion 包的逻辑与 llama 完全对称(diffusion.rs)。
依赖关系在 graph.rs 中被组织成 petgraph 有向图,同一 CUDA 组件在图中共享唯一节点(避免重复安装),并通过toposort保证按依赖顺序激活;graph.rs内置的测试cuda_dependencies_are_shared_and_ordered验证了 CUDA Runtime13 → Blas13 → Llama 的先后顺序。激活本身由 loader.rs 完成:Windows 使用LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32标志加载,Unix 平台默认以RTLD_LOCAL加载(避免污染符号表),加载成功后forget句柄使库常驻进程。
七、与 AGENTS.md 仓库规则的呼应
runtime 同步工作流并非孤立脚本,它处处体现 AGENTS.md 的长期约束:
- Source Boundaries:头文件由 sync.sh 统一 vendored,绑定由 koharu-bindgen 自动生成,均"修改权威输入、运行生成器",禁止手改生成物;
- Upstream Alignment:sync.sh 从 fork 的固定 release tag拉取头文件(而非跟踪滚动分支),保证移植可追溯到某个具体版本;同步后还需审查绑定与包装,确认参数路径、布局、执行顺序未偏离上游;
- Change Policy:不添加向后兼容层——上游 API 变化时直接更新所有仓库内消费方并删除旧形式,这正是 SKILL 要求"更新 koharu-llama / koharu-diffusion 安全包装"的原因;
- Verification:默认只对五个运行时 crate 运行聚焦的 debug 检查,与"快速迭代"的验证基调一致。
八、给 Agent 的实操检查清单
完成一次 llama.cpp / stable-diffusion.cpp 运行时升级,推荐按以下顺序执行:
- 在仓库根目录运行
bash .agents/skills/runtime/scripts/sync.sh(需安装gh与curl),确认脚本打印的 llama.cpp 与 stable-diffusion.cpp 最新版本号; - 用
git diff审查 crates/koharu-llama-sys/include/ 与 crates/koharu-diffusion-sys/include/stable-diffusion.h 的头文件变更,关注 API 增删与结构体重排; - 将打印的版本更新到 llama.rs 与 diffusion.rs 的
RELEASE常量; - 构建 sys crate 重新生成绑定,用
--allowlist检查确认新旧符号面符合预期(可参照 build.rs 中的正则); - 按需更新
koharu-llama/koharu-diffusion安全包装,移除被上游删除的 API; - 对
koharu-llama-sys、koharu-llama、koharu-diffusion-sys、koharu-diffusion、koharu-runtime五个 crate 运行聚焦的cargo check(debug profile),确认无编译错误后提交。
这套流程把"上游发布 → 头文件 → 绑定 → 运行时包 → 验证"串成了一条可重复执行的维护链路,也让任何编码 Agent 都能在不需要人工干预的情况下,安全地把 Koharu 的原生推理与图像生成运行时升级到新的上游版本。
【免费下载链接】koharu
ML-powered manga translator, written in Rust.
相关推荐
stable-diffusion.cpp 运行 SeFi-Image:双时步 Transformer 图像生成全指南
stable diffusion.cpp 运行 SeFi Image:双时步 Transformer 图像生成全指南 本篇技术指南以 docs/sefi_ima
人工智能大模型本地部署推理引擎媒体生成LobeHub deep-review 的 Skill Freshness 维度:让 Agent 技能库与代码演进保持同步
LobeHub deep review 的 Skill Freshness 维度:让 Agent 技能库与代码演进保持同步 LobeHub(lobehub)仓库
人工智能AI 应用大模型AI Agent多智能体工具调用前端后端opendataloader-pdf 代码贡献实战指南:构建、CLI 选项同步与 Agent Skill 维护
opendataloader pdf 代码贡献实战指南:构建、CLI 选项同步与 Agent Skill 维护 本篇指南以仓库根目录的 CONTRIBUTING
AI 应用OCRMCP 服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考