# engine
**Repository Path**: ariacompute/engine
## Basic Information
- **Project Name**: engine
- **Description**: aria engine
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-27
- **Last Updated**: 2026-11-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Aria Engine
**面向 AFM-D 类型化决策的纯 Rust 推理运行时**
**Encoder**(`afm_de`,Laya 布局 ModernBERT DecisionModel)与 **Decoder**
(`afm_dd`,MiniCPM5-2B ± PEFT LoRA)各自在同一份契约下发布类型化决策——
**System One**。产品面:**`aria-engine` CLI** · **`POST /v1/systemone`** ·
**`libaria_ffi` C ABI** · `bindings/` 下各语言 SDK。
[English](./README.md) · **简体中文** · [Agent 上下文](./AGENTS.md) · [需求](./requirements.md) · [任务](./task.md)
[![][release-shield]][release-link] [![][rust-shield]][rust-link] [![][license-shield]][license-link] [![][lastcommit-shield]][lastcommit-link]
[![][httpapi-shield]][httpapi-link] [![][tests-shield]][tests-link] [![][sdks-shield]][sdks-link] [![][trust-shield]][trust-link]
Table of contents
#### TOC
**上手**
- [✨ 功能](#-功能)
- [🧱 工作区](#-工作区)
- [🚀 快速开始](#-快速开始)
- [🧰 命令行](#-命令行)
- [🔧 配置](#-配置)
**部署与服务**
- [🛳 部署](#-部署)
- [`A` 源码运行](#a-源码运行)
- [`B` Docker Compose](#b-docker-compose)
- [🔌 HTTP API](#-http-api)
**内部机制**
- [🧭 Decide(类型化决策)](#-decide类型化决策)
- [🧩 FFI 与语言 SDK](#-ffi-与语言-sdk)
- [🔏 信任库安全](#-信任库安全)
- [🔨 开发](#-开发)
- [📚 文档](#-文档)
- [📝 许可证](#-许可证)
- [🤝 工程约定](#-工程约定)
## ✨ 功能
Aria Engine 把「一个问题」变成「一个类型化答案」——*对这个状态,哪个选项是(或哪个等级、是否)正确决策?*——没有聊天循环。Encoder 与 Decoder 共用同一份 System One 契约,调用方无需关心是哪个模型作答。
- 🧮 **AFM-D 类型化决策** —— `choice` / `score` / `noul` 答案共用同一 System One 形态,不做开放式生成。
- ⚡ **两条轨** —— Encoder(ModernBERT)快速输出选项 logits;Decoder(MiniCPM5-2B)走 SemIf 风格直接打分。
- 🖥 **四种接入面** —— `aria-engine` CLI、`POST /v1/systemone` HTTP、`libaria_ffi` C ABI,以及八语言 SDK。
- 📦 **离线优先** —— 真实权重前向需要已下载的 checkpoint;黄金路径打分(`--logits` / `--semif-out`)无需权重也可运行。
- 🌍 **区域 hub** —— `.com` 解析 Hugging Face,`.cn` 解析 ModelScope,由 `aria-engine setup` 选定。
- 🔏 **钉死的信任库** —— 二进制内嵌 `webpki-roots >=1.0.10`,剔除被泄露的 emSign 根(见 [信任库安全](#-信任库安全))。
[![][back-to-top]](#readme-top)
## 🧱 工作区
Rust 工作区,无运行时数据库、无持久化。只复用产品外壳模式(CLI、FFI 打包、`release.yml`);已废弃的 chat graph 不再保留。
| Crate | 职责 |
|---|---|
| `ariacompute-core` | System One 类型、打包、`~/.ariacompute` 配置、gateway |
| `ariacompute-de` | Encoder checkpoint + 打包 + score/logits |
| `ariacompute-dd` | SemIf 行 + decoder map + scorer shell |
| `aria-cli` | bin `aria-engine`(`setup` / `download` / `upgrade` / `serve` / `decide`) |
| `ariacompute-ffi` | cdylib `aria_ffi` → 发布名 `libaria-engine_ffi` |
| `bindings/rust` | crates.io `ariacompute-engine` |
[![][back-to-top]](#readme-top)
## 🚀 快速开始
```bash
cargo build --workspace
cargo test --workspace
cargo build --release -p aria-cli -p ariacompute-ffi
```
可选 CUDA:`cargo build -p aria-cli --features cuda`(会传到 de/dd)。
```bash
# 1. 配置区域与 hub token(写入 ~/.ariacompute/engine.yml)
aria-engine setup --site-url https://ariacompute.cn --compute cuda
# 2. 下载 checkpoint(HF / ModelScope HTTP API,不依赖 hub CLI)
aria-engine download afm-de
aria-engine download afm-dd
# 3. 以本地 System One 服务启动 Encoder(→ http://127.0.0.1:8010)
aria-engine serve --model-name afm-de
# 4. 提一个类型化问题
curl -s http://127.0.0.1:8010/v1/systemone \
-H 'content-type: application/json' \
-d '{
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {
"refund": "issue a full refund",
"deny": "deny the request"
}
}
}
}'
```
真实权重前向需要完整本地 checkpoint(见 [`task.md`](task.md) 阶段 B)。此前可用 `decide` 的 `--logits` / `--semif-out` 做黄金路径打分。
[![][back-to-top]](#readme-top)
## 🧰 命令行
```bash
aria-engine download afm-de # HF/ModelScope HTTP API(site_url + setup token);不依赖 hub CLI
# .cn → ModelScope /api/v1/.../repo?FilePath=… ;.com → HF resolve
aria-engine list | check | clean # list = 本地 ∪ Hub 组织(ariacompute / AriaCompute);标记 downloaded|not downloaded
# check/clean:仅完整 checkpoint;失败下载会清理
aria-engine upgrade [version] # 需要 upgrade_url
aria-engine serve … # 见下方 HTTP API
aria-engine decide … # 见下方 Decide
aria-engine -v
```
| 命令 | 用途 |
|---|---|
| `setup` | 写入 `~/.ariacompute/engine.yml`(区域、hub token、compute) |
| `download` | 经 HF/ModelScope HTTP API 拉取 AFM checkpoint |
| `list` / `check` / `clean` | 列举 / 校验 / 清理本地与 hub checkpoint |
| `upgrade` | 从 `upgrade_url` 升级二进制(需有 release) |
| `serve` | 启动本地 System One HTTP 服务 |
| `decide` | 对一份 JSON 做一次性类型化决策 |
| `-v` | 打印版本 |
[![][back-to-top]](#readme-top)
## 🔧 配置
`aria-engine setup` 写入 `~/.ariacompute/engine.yml`(**无** router 字段):
| 字段 | 含义 | 默认 |
| --- | --- | --- |
| `site_url` | 站点(`.com` / `.cn`)→ hub 分区 | 语言环境(`LANG=zh*` → `.cn`) |
| `upgrade_url` | Releases 组织根(GitHub / Gitee) | 随 `site_url` |
| `compute` | `auto` \| `cpu` \| `cuda` | `auto` |
| `hf_token` | Hugging Face token(`.com`) | _(空)_ |
| `modelscope_api_token` | ModelScope token(`.cn`) | _(空)_ |
```bash
aria-engine setup # 交互
aria-engine setup --status # 密钥脱敏
aria-engine setup --clear
aria-engine setup --site-url https://ariacompute.cn --compute cuda
```
区域 hub token:`.cn` 只问 ModelScope;否则只问 Hugging Face。交互输入时回显为 `*`,不明码显示。
[![][back-to-top]](#readme-top)
## 🛳 部署
支持两条路径:直接运行二进制(连已下载 checkpoint),或以容器方式跑整套栈。
### `A` 源码运行
```bash
cargo build --release -p aria-cli
aria-engine setup # 写入 ~/.ariacompute/engine.yml
aria-engine download afm-de # 拉取 encoder checkpoint
aria-engine serve --model-name afm-de --bind 127.0.0.1:8010
```
encoder 服务默认监听 `127.0.0.1:8010`,decoder 监听 `127.0.0.1:8011`。可用 `--compute cpu|cuda` 覆盖 `engine.yml` 中的取值。跨主机暴露前,请在其前方放置一个终结 TLS 的反向代理(如 Nginx、Caddy)。
### `B` Docker Compose
将 System One HTTP 服务以容器方式运行。仓库附带一个参数化 `Dockerfile`、编排脚本
`docker/entrypoint.sh`、CPU 版 `docker-compose.yml`(两个服务:`engine-encoder`
在 **8010**、`engine-decoder` 在 **8011**),以及 GPU 覆盖文件
`docker-compose.cuda.yml`。
1. 基于模板生成 `.env`:
```bash
cp .env.example .env # 将 ARIA_DATA_DIR 设为宿主的 ~/.ariacompute(绝对路径)
```
两个服务将宿主的 `ARIA_DATA_DIR`(默认 `~/.ariacompute`)绑定挂载到 `/data/aria`,
因此**宿主已下载的** `engine.yml`(配置)与 `models/`(checkpoint)会被直接使用——
**离线、无需下载**。entrypoint 仅在 `engine.yml` 缺失时依据环境变量生成它,
**已挂载的配置会被尊重**(例如宿主的 `~/.ariacompute/engine.yml`)。
2. 构建并启动(CPU):
```bash
docker compose build
docker compose up -d
```
3. 验证:
```bash
curl -s http://localhost:8010/health # {"ok":true,"service":"afm-engine","model":"afm-de"}
curl -s http://localhost:8011/health # decoder
docker compose ps # 两个服务均 healthy
```
**模型**
- **离线(默认,`AUTO_DOWNLOAD=0`)**:权重取自宿主
`ARIA_DATA_DIR/models/{afm-de,afm-dd}`。请确保两个 checkpoint 都已存在于宿主
(在宿主执行一次 `aria-engine download afm-de && aria-engine download afm-dd`,
或把它们拷入 `~/.ariacompute/models/`)。
- **自动下载**:在 `.env` 中设置 `AUTO_DOWNLOAD=1`,entrypoint 会在首次运行时
执行 `aria-engine download `(需联网与对应 hub token)。**下载失败不会
导致容器崩溃**——只会打印告警;仅当 checkpoint 仍然缺失时才拒绝启动。默认关闭。
> **注意 — hub 选择与网络**:当 `SITE_URL` 被设置时,容器会据此重新生成
> `engine.yml`,从而**覆盖**挂载进来的宿主配置。设置
> `SITE_URL=https://ariacompute.cn` 可让下载走 **ModelScope**(`afm-de` 发布于此),
> 而不是宿主里写死的 HuggingFace。若宿主只能通过本机代理访问外网,请在 `.env` 中设置
> `HTTPS_PROXY=http://host.docker.internal:<端口>`(compose 已将
> `host.docker.internal` 映射到宿主网关);容器内的 `127.0.0.1` 指的是容器自身,
> 而非宿主。
**GPU(CUDA)** —— 需要宿主机已装 NVIDIA 驱动 + `nvidia-container-toolkit`:
```bash
docker compose -f docker-compose.yml -f docker-compose.cuda.yml build
docker compose -f docker-compose.yml -f docker-compose.cuda.yml up -d
```
覆盖文件会将构建基础切换为 CUDA 镜像、以 `--features cuda` 编译,并为每个服务申请一块 GPU,
同时设置 `COMPUTE=cuda`,让 candle 选择 CUDA 后端。
**配置(`.env`)**
| 变量 | 默认 | 含义 |
| --- | --- | --- |
| `ENGINE_IMAGE` | `aria-engine:latest` | 构建镜像的标签 |
| `BUILD_IMAGE` / `RUNTIME_IMAGE` | `rust:1-slim` / *(默认等于 `BUILD_IMAGE`)* | CPU 构建基础镜像;运行时复用它以保证 glibc 始终一致。仅 CUDA 覆盖文件会设置 `RUNTIME_IMAGE` |
| `FEATURES` | _(空)_ | 构建特性;CUDA 覆盖文件设为 `cuda` |
| `SITE_URL` / `UPGRADE_URL` | _(空)_ | 区域 hub(`.com`→HF,`.cn`→ModelScope);设置后会覆盖挂载进来的配置 |
| `HF_TOKEN` / `MODELSCOPE_API_TOKEN` | _(空)_ | 当前区域的 hub token |
| `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` | _(空)_ | 下载用的出口代理(本机代理用 `host.docker.internal`) |
| `COMPUTE` | `auto` | `auto` \| `cpu` \| `cuda` |
| `ENCODER_MODEL` / `ENCODER_PORT` | `afm-de` / `8010` | encoder 模型(为空则禁用该服务)+ 端口 |
| `DECODER_MODEL` / `DECODER_PORT` | `afm-dd` / `8011` | decoder 模型(为空则禁用该服务)+ 端口 |
| `ARIA_DATA_DIR` | `${HOME}/.ariacompute` | 宿主目录,绑定挂载到 `/data/aria`(配置 + 模型) |
| `AUTO_DOWNLOAD` | `0` | 设为 `1` 可在首次运行时拉取权重(失败不致命) |
| `RUST_LOG` | `info` | Rust tracing 过滤级别 |
容器内部绑定 `0.0.0.0`;在容器之外 `serve` 仍保留其 `127.0.0.1` 默认绑定。
**请勿提交 `.env`** —— 它可能包含 hub token。
[![][back-to-top]](#readme-top)
## 🔌 HTTP API
`aria-engine serve` 基于已下载的 AFM checkpoint 启动本地 System One HTTP 服务。**不做** aria-router 注册。
| 旗标 | 默认 | 含义 |
| --- | --- | --- |
| `--track` | `encoder` | `encoder` \| `decoder` |
| `--model-name` | `afm-de` / `afm-dd`(随 `--track`) | 响应中的 model id;省略 `--checkpoint` 时兼作 checkpoint |
| `--checkpoint` | `~/.ariacompute/models/` | checkpoint 目录,或 `~/.ariacompute/models/` 下的缓存名 |
| `--bind` | `127.0.0.1:8010`(encoder)/ `127.0.0.1:8011`(decoder) | 监听地址 |
| `--compute` | 来自 `engine.yml`(`auto`) | `auto` \| `cpu` \| `cuda`(覆盖 setup;用于设备选择日志) |
`--model-name` 与 `--checkpoint` 二选一或同时提供。软布局检查:encoder 轨指向 decoder 形态目录(或相反)会直接报错。
| 方法 | 路径 | 响应 |
| --- | --- | --- |
| `GET` | `/health` 或 `/` | `{ "ok": true, "service": "afm-engine", "model": "" }` |
| `GET` | `/v1/models` | OpenAI 风格列表,含一条 `--model-name` |
| `POST` | `/v1/systemone` | `{ "answers": { … }, "model": "" }` |
`POST /v1/systemone` 请求体与 Decide 的 System One 形态相同:`{ "state": …, "questions": { "": { "type", "instructions", "criteria" } } }`(`type` = `choice` \| `score` \| `noul`)。题目非法 → HTTP **422**;打分失败 → **500**。
```bash
# Encoder(默认轨)用缓存名
aria-engine download afm-de
aria-engine serve --model-name afm-de
# → http://127.0.0.1:8010
# 显式 track + checkpoint 路径
aria-engine download afm-dd
aria-engine serve --track decoder --checkpoint ~/.ariacompute/models/afm-dd
# 自定义 bind + compute 覆盖
aria-engine serve --model-name afm-de --bind 0.0.0.0:8010 --compute cpu
# Health / models
curl -s http://127.0.0.1:8010/health
curl -s http://127.0.0.1:8010/v1/models
# System One — choice
curl -s http://127.0.0.1:8010/v1/systemone \
-H 'content-type: application/json' \
-d '{
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {
"refund": "issue a full refund",
"deny": "deny the request"
}
}
}
}'
# System One — score(criteria:2–10 个有序等级)
curl -s http://127.0.0.1:8010/v1/systemone \
-H 'content-type: application/json' \
-d '{
"state": "ticket sat in queue for three days with no reply",
"questions": {
"q1": {
"type": "score",
"instructions": "Rate urgency from 0 (low) to 3 (critical)",
"criteria": [
"can wait until next week",
"should be handled this week",
"needs attention today",
"page on-call now"
]
}
}
}'
# System One — noul(true / false)
curl -s http://127.0.0.1:8010/v1/systemone \
-H 'content-type: application/json' \
-d '{
"state": "customer wrote: this is unacceptable, I want a manager",
"questions": {
"q1": {
"type": "noul",
"instructions": "Is the user angry?",
"criteria": {
"false": "calm or neutral tone",
"true": "angry or escalating"
}
}
}
}'
```
[![][back-to-top]](#readme-top)
## 🧭 Decide(类型化决策)
对一份 JSON(stdin 或 `--file`)做一次性 typed decision;每个题/记录打印一份 pretty JSON 答案。打包与 typed-answer 契约与 `POST /v1/systemone` 相同。
| 旗标 | 默认 | 含义 |
| --- | --- | --- |
| `--track` | `encoder` | `encoder` \| `decoder` |
| `--model-name` | `afm-de` / `afm-dd`(随 `--track`) | 缓存名;省略 `--checkpoint` 时作为 checkpoint |
| `--checkpoint` | `~/.ariacompute/models/` | checkpoint 目录,或 `~/.ariacompute/models/` 下的缓存名 |
| `--file` | _(stdin)_ | 输入 JSON 路径 |
| `--logits` | — | Encoder **黄金路径**:选项原始 logits 的 JSON 数组(跳过权重前向) |
| `--semif-out` | — | Decoder **黄金路径**:SemIf 风格 JSON(跳过权重前向) |
未传 `--logits` / `--semif-out` 时,会对 checkpoint 做真实前向(需完整本地模型;见 [`task.md`](task.md) 阶段 B)。
**1. AFM-D record**(单题)— `task` + `options` + `state`:
```json
{
"id": "choice-1",
"task": "choice",
"instructions": "Select the fruit",
"options": [
{"name": "apple", "description": "a red fruit"},
{"name": "carrot", "description": "an orange vegetable"}
],
"state": "The user wants something sweet and red."
}
```
```json
{
"id": "score-1",
"task": "score",
"instructions": "Rate urgency from 0 (low) to 3 (critical)",
"options": [
{"name": "level-0", "description": "can wait until next week"},
{"name": "level-1", "description": "should be handled this week"},
{"name": "level-2", "description": "needs attention today"},
{"name": "level-3", "description": "page on-call now"}
],
"state": "ticket sat in queue for three days with no reply"
}
```
```json
{
"id": "noul-1",
"task": "noul",
"instructions": "Is the user angry?",
"options": [
{"name": "false", "description": "calm or neutral tone"},
{"name": "true", "description": "angry or escalating"}
],
"state": "customer wrote: this is unacceptable, I want a manager"
}
```
`task` 为 `choice` \| `score` \| `noul`。`noul` 选项名规范化为 `true` / `false`(接受 `yes` / `no` 别名)。仓库夹具:[`tests/fixtures/encoder_choice.json`](tests/fixtures/encoder_choice.json)、[`encoder_noul.json`](tests/fixtures/encoder_noul.json)、[`decoder_choice.json`](tests/fixtures/decoder_choice.json)。
**2. System One body**(可多题)— 与 HTTP serve 同形:
```json
{
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {
"refund": "issue a full refund",
"deny": "deny the request"
}
},
"q2": {
"type": "score",
"instructions": "Rate urgency from 0 (low) to 3 (critical)",
"criteria": [
"can wait until next week",
"should be handled this week",
"needs attention today",
"page on-call now"
]
},
"q3": {
"type": "noul",
"instructions": "Is the user angry?",
"criteria": {
"false": "calm",
"true": "angry"
}
}
}
}
```
| `type` | `criteria` |
| --- | --- |
| `choice` | 对象:选项名 → 描述 |
| `score` | 数组:2–10 个有序等级文案 |
| `noul` | 对象含 `true` / `false`(可省略,有默认文案) |
```bash
# Encoder 黄金路径(无权重前向)— logits 长度 = 选项数
aria-engine decide \
--track encoder \
--model-name afm-de \
--logits '[2.5, 0.1]' \
--file tests/fixtures/encoder_choice.json
# 从 stdin;--checkpoint 可覆盖 model-name 路径
aria-engine decide --track encoder --checkpoint afm-de --logits '[2.5,0.1]' \
< tests/fixtures/encoder_choice.json
# Decoder 黄金路径 — SemIf out JSON
aria-engine decide \
--track decoder \
--model-name afm-dd \
--semif-out '{"option_ids":["a","b"],"probabilities":[0.1,0.9]}' \
--file tests/fixtures/decoder_choice.json
# System One — choice(encoder 黄金路径;两选项 → 两 logits)
cat <<'EOF' | aria-engine decide --track encoder --model-name afm-de --logits '[1.0, 0.2]'
{
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {"refund": "issue a full refund", "deny": "deny the request"}
}
}
}
EOF
# System One — score(四个等级 → 四个 logits)
cat <<'EOF' | aria-engine decide --track encoder --model-name afm-de --logits '[0.1, 0.4, 2.0, 0.3]'
{
"state": "ticket sat in queue for three days with no reply",
"questions": {
"q1": {
"type": "score",
"instructions": "Rate urgency from 0 (low) to 3 (critical)",
"criteria": [
"can wait until next week",
"should be handled this week",
"needs attention today",
"page on-call now"
]
}
}
}
EOF
# System One — noul(false/true → 两 logits;也可用夹具)
aria-engine decide \
--track encoder \
--model-name afm-de \
--logits '[0.2, 1.8]' \
--file tests/fixtures/encoder_noul.json
cat <<'EOF' | aria-engine decide --track encoder --model-name afm-de --logits '[0.2, 1.8]'
{
"state": "customer wrote: this is unacceptable, I want a manager",
"questions": {
"q1": {
"type": "noul",
"instructions": "Is the user angry?",
"criteria": {"false": "calm or neutral tone", "true": "angry or escalating"}
}
}
}
EOF
# 真实前向(需已下载完整 checkpoint)
aria-engine decide --track encoder --model-name afm-de --file record.json
```
`--model-name afm-de`(或 `--checkpoint afm-de`)在路径存在时解析为 `~/.ariacompute/models/afm-de`(与 `serve` 相同)。
每个 record 打印一份 typed answer(如 `type`、`choice` / `score` / `noul`、`probabilities`、`confidence`)。System One 多题时按题顺序依次输出多个 JSON 文档。
[![][back-to-top]](#readme-top)
## 🧩 FFI 与语言 SDK
头文件:[`ffi/include/aria.h`](ffi/include/aria.h) — `aria_model_init`、`aria_systemone`、`aria_model_destroy`、`aria_last_error`。
发布资产:`aria-engine_${VERSION}_${OS}.tar.gz|zip`、`libaria-engine_ffi_${VERSION}_${OS}.tar.gz`。
原生 C ABI(`ariacompute-ffi` / `libaria-engine_ffi`)以及 `bindings/` 下的薄封装。API 面是 **System One**(`systemone`),不是 chat/complete。
| Binding | 路径 | Registry |
| --- | --- | --- |
| Rust | `bindings/rust`(`ariacompute-engine`) | crates.io |
| Python | `bindings/python` | PyPI `aria-engine` |
| Go | `bindings/go` | Go module |
| TypeScript | `bindings/typescript` | npm `@ariacompute/engine-ts` |
| React Native | `bindings/react-native` | npm `@ariacompute/engine-rn` |
| Flutter | `bindings/flutter` | pub.dev `aria_engine` |
| Swift | `bindings/swift` | CocoaPods `AriaEngine` |
| Kotlin | `bindings/kotlin` | Maven Central `com.ariacompute:engine` |
走 FFI 的 SDK 需要 `libaria-engine_ffi`(`aria-engine upgrade`、包内捆绑,或 `ARIA_FFI_LIB`)。`checkpoint` 指向已下载的 AFM 目录(例如 `aria-engine download afm-de` 后的 `~/.ariacompute/models/afm-de`)。Rust crate 原生链接 workspace crates,一般无需解压动态库。
```bash
cargo test -p ariacompute-ffi -p ariacompute-engine
./scripts/run-binding-tests.sh # 主机矩阵(Rust / Python / Go / TS)
```
**Python**(`aria-engine`;`ARIA_FFI_LIB` 可覆盖):
```bash
pip install aria-engine
# 可选:export ARIA_FFI_LIB=/path/to/libaria-engine_ffi.so
```
```python
from aria_engine import AriaEngine
eng = AriaEngine("/path/to/afm-de", "encoder") # 或 ~/.ariacompute/models/afm-de
out = eng.systemone({
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {
"refund": "issue a full refund",
"deny": "deny the request",
},
}
},
})
print(out["answers"]["q1"])
eng.destroy()
```
**TypeScript / Node**(`@ariacompute/engine-ts`):
```bash
npm install @ariacompute/engine-ts
# 可选:export ARIA_FFI_LIB=/path/to/libaria-engine_ffi.so
```
```ts
import { AriaEngine } from "@ariacompute/engine-ts";
const eng = new AriaEngine("/path/to/afm-de", "encoder");
const out = eng.systemone({
state: "user wants a refund",
questions: {
q1: {
type: "choice",
instructions: "Pick the best action",
criteria: {
refund: "issue a full refund",
deny: "deny the request",
},
},
},
}) as { answers: Record };
console.log(out.answers.q1);
eng.destroy();
```
**React Native**(`@ariacompute/engine-rn`):
```bash
npm install @ariacompute/engine-rn
```
```js
const { AriaEngine } = require("@ariacompute/engine-rn");
const eng = new AriaEngine("/path/to/afm-de", "encoder");
const out = await eng.systemone({
state: "user wants a refund",
questions: {
q1: {
type: "choice",
instructions: "Pick the best action",
"criteria": {
refund: "issue a full refund",
deny: "deny the request",
},
},
},
});
console.log(out.answers.q1);
eng.destroy();
```
**Go**(cgo;链接 `libaria_ffi` / `libaria-engine_ffi`):
```bash
export CGO_ENABLED=1
# 可选:export ARIA_FFI_LIB=/path/to/libaria-engine_ffi.so
go get github.com/ariacompute/engine/bindings/go@latest
```
```go
package main
import (
"fmt"
aria "github.com/ariacompute/engine/bindings/go"
)
func main() {
eng, err := aria.Open("/path/to/afm-de", "encoder")
if err != nil {
panic(err)
}
defer eng.Destroy()
out, err := eng.SystemOne(map[string]any{
"state": "user wants a refund",
"questions": map[string]any{
"q1": map[string]any{
"type": "choice",
"instructions": "Pick the best action",
"criteria": map[string]any{
"refund": "issue a full refund",
"deny": "deny the request",
},
},
},
})
if err != nil {
panic(err)
}
fmt.Println(out["answers"])
}
```
**Rust**(`ariacompute-engine` — 原生 API;一般无需解压 `libaria-engine_ffi`):
```bash
cargo add ariacompute-engine
```
```rust
use aria_engine::{Engine, EngineTrack, SystemOneRequest};
use serde_json::json;
fn main() -> Result<(), Box> {
let eng = Engine::open("/path/to/afm-de", EngineTrack::Encoder)?;
let req: SystemOneRequest = serde_json::from_value(json!({
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {
"refund": "issue a full refund",
"deny": "deny the request"
}
}
}
}))?;
let out = eng.systemone(&req)?;
println!("{out}");
Ok(())
}
```
**Flutter**(`package:aria_engine`):
```yaml
# pubspec.yaml
dependencies:
aria_engine: ^0.1.0
```
```dart
import 'package:aria_engine/aria_engine.dart';
final eng = AriaEngine('/path/to/afm-de', track: 'encoder');
final out = eng.systemone({
'state': 'user wants a refund',
'questions': {
'q1': {
'type': 'choice',
'instructions': 'Pick the best action',
'criteria': {
'refund': 'issue a full refund',
'deny': 'deny the request',
},
},
},
});
print(out['answers']);
eng.destroy();
```
**Swift**(CocoaPods `AriaEngine`):
```ruby
# Podfile
pod 'AriaEngine'
```
```swift
import AriaEngine
let eng = AriaEngine(checkpoint: "/path/to/afm-de", track: "encoder")
let req = """
{
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {
"refund": "issue a full refund",
"deny": "deny the request"
}
}
}
}
"""
let out = try eng.systemone(requestJson: req)
print(out)
eng.destroy()
```
**Kotlin**(`com.ariacompute:engine`):
```kotlin
// build.gradle.kts
implementation("com.ariacompute:engine:0.1.0")
```
```kotlin
import com.ariacompute.engine.AriaEngine
import org.json.JSONObject
val eng = AriaEngine("/path/to/afm-de", "encoder")
val out = eng.systemone(
JSONObject(
"""
{
"state": "user wants a refund",
"questions": {
"q1": {
"type": "choice",
"instructions": "Pick the best action",
"criteria": {
"refund": "issue a full refund",
"deny": "deny the request"
}
}
}
}
""".trimIndent()
)
)
println(out.getJSONObject("answers"))
eng.destroy()
```
各语言更多说明见 `bindings/*/README.md`。
GitHub Release 触发:`release.yml`(CLI + FFI 资产),以及 `publish-cargo.yml`、`publish-npm.yml`、`publish-pub.yml`、`publish-pypi.yml`、`publish-maven.yml`、`publish-cocoapods.yml`。
[![][back-to-top]](#readme-top)
## 🔏 信任库安全
2026-10 的 eMudhra(emSign)中间 CA 私钥泄露事件,由 Rust 侧兜底:`aria-engine` / `aria-cli` 二进制做 hub 下载等出向 TLS 时,经 `reqwest` 与 `hf-hub`(均为 `rustls-tls`)使用内嵌的 **`webpki-roots`**,并在 `cli/Cargo.toml` 中钉死 `>=1.0.10`(剔除被泄露的 emSign 根)。Docker 构建已安装 `ca-certificates`(系统 store),但二进制内嵌 `webpki-roots`,因此锁升级才是决定性修复。各语言绑定(Go / Python / TS / RN)均为 FFI-only,自身不做任何出向 TLS,故其运行时信任库不在范围内;真实的网络路径就是上文的 Rust 侧。
[![][back-to-top]](#readme-top)
## 🔨 开发
| 目标 | 作用 |
| --- | --- |
| `cargo build --workspace` | 构建全部 crate |
| `cargo test --workspace` | 跑完整 workspace 测试套件 |
| `cargo build --release -p aria-cli -p ariacompute-ffi` | Release 二进制 + FFI cdylib |
| `cargo build -p aria-cli --features cuda` | 以 CUDA 后端构建(传到 de/dd) |
| `cargo test -p ariacompute-ffi -p ariacompute-engine` | FFI + 原生 Rust SDK 测试 |
| `./scripts/run-binding-tests.sh` | 主机矩阵(Rust / Python / Go / TS) |
| `./scripts/prepare-binding-fixture.sh` | 构建本地 SDK 测试用的 binding fixture |
```bash
cargo test --workspace
./scripts/prepare-binding-fixture.sh
./scripts/run-binding-tests.sh
```
[![][back-to-top]](#readme-top)
## 📝 许可证
MIT,详见 [LICENSE](./LICENSE)。
[![][back-to-top]](#readme-top)
## 🤝 工程约定
- [`AGENTS.md`](./AGENTS.md):Agent 工程上下文入口与目录索引
- [`requirements.md`](./requirements.md):需求规格(功能边界 / 异常 / 验收标准,经人工审核门控)
- [`task.md`](./task.md):实施任务勾选清单
[![][back-to-top]](#readme-top)
---
Copyright © 2026 [ariacompute][org].
This project is [MIT](./LICENSE) licensed.
[org]: https://github.com/ariacompute
[release-shield]: https://img.shields.io/github/v/release/ariacompute/engine?style=flat-square&labelColor=black&color=555
[release-link]: https://github.com/ariacompute/engine/releases
[rust-shield]: https://img.shields.io/badge/rust-edition_2021-555?style=flat-square&labelColor=black
[rust-link]: ./Cargo.toml
[license-shield]: https://img.shields.io/github/license/ariacompute/engine?style=flat-square&labelColor=black&color=555
[license-link]: ./LICENSE
[lastcommit-shield]: https://img.shields.io/github/last-commit/ariacompute/engine?style=flat-square&labelColor=black&color=555
[lastcommit-link]: https://github.com/ariacompute/engine/commits
[httpapi-shield]: https://img.shields.io/badge/HTTP_API-3_routes-555?style=flat-square&labelColor=black
[httpapi-link]: #-http-api
[tests-shield]: https://img.shields.io/badge/tests-cargo_test-555?style=flat-square&labelColor=black
[tests-link]: ./Cargo.toml
[sdks-shield]: https://img.shields.io/badge/SDKs-8_languages-555?style=flat-square&labelColor=black
[sdks-link]: #-ffi-与语言-sdk
[trust-shield]: https://img.shields.io/badge/trust-webpki_roots_1.0.10-555?style=flat-square&labelColor=black
[trust-link]: #-信任库安全
[back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square