☰
Koharu 运行时同步技能解析:用编码 Agent SKILL 维护 llama.cpp 与 stable-diffusion.cpp 绑定
2026/10/12 1:36:37 网站建设 项目流程

【免费下载链接】koharu

ML-powered manga translator, written in Rust.

项目地址:https://gitcode.com/gh_mirrors/ko/koharu
点击查看免费下载

本文围绕 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.hcrates/koharu-llama-sys/include/llama.h
ggml/include/gguf.hcrates/koharu-llama-sys/include/gguf.h
ggml/include/ggml.hcrates/koharu-llama-sys/include/ggml.h
ggml/include/ggml-alloc.hcrates/koharu-llama-sys/include/ggml-alloc.h
ggml/include/ggml-backend.hcrates/koharu-llama-sys/include/ggml-backend.h
ggml/include/ggml-cpu.hcrates/koharu-llama-sys/include/ggml-cpu.h
ggml/include/ggml-opt.hcrates/koharu-llama-sys/include/ggml-opt.h
tools/mtmd/mtmd.hcrates/koharu-llama-sys/include/mtmd.h
tools/mtmd/mtmd-helper.hcrates/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.h

stable-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 updatecrates/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 为例,生成过程是:

  1. 以 wrapper.h 为入口,它依次 include 了 llama.h、gguf.h、mtmd.h、mtmd-helper.h;
  2. 配置bindgen::Builder:追加-Iinclude 路径、关闭布局测试、开启derive_partialeq、设置三个 allowlist 正则、关闭枚举名前缀;
  3. 调用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 运行时升级,推荐按以下顺序执行:

  1. 在仓库根目录运行bash .agents/skills/runtime/scripts/sync.sh(需安装gh与curl),确认脚本打印的 llama.cpp 与 stable-diffusion.cpp 最新版本号;
  2. 用git diff审查 crates/koharu-llama-sys/include/ 与 crates/koharu-diffusion-sys/include/stable-diffusion.h 的头文件变更,关注 API 增删与结构体重排;
  3. 将打印的版本更新到 llama.rs 与 diffusion.rs 的RELEASE常量;
  4. 构建 sys crate 重新生成绑定,用--allowlist检查确认新旧符号面符合预期(可参照 build.rs 中的正则);
  5. 按需更新koharu-llama/koharu-diffusion安全包装,移除被上游删除的 API;
  6. 对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.

项目地址:https://gitcode.com/gh_mirrors/ko/koharu
点击查看免费下载

相关推荐

上一篇:Wing语言终极指南:如何用革命性云原生编程语言快速构建应用
下一篇:YOLO-World 的 DeepStream 部署实战:MMYOLO 模型自定义 BBox Parser 与 TensorRT 端到端推理

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询