ai-lib-rust 0.6.0

Protocol Runtime for AI-Protocol - A high-performance Rust reference implementation
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
# ai-lib-rust


**AI-Protocol 协议运行时** - 高性能 Rust 参考实现

`ai-lib-rust` 是 [AI-Protocol](https://github.com/hiddenpath/ai-protocol) 规范的 Rust 运行时实现。它体现了核心设计原则:**一切逻辑皆算子,一切配置皆协议** (All logic is operators, all configuration is protocol)。

## 🎯 设计哲学


与硬编码 provider 特定逻辑的传统适配器库不同,`ai-lib-rust` 是一个**协议驱动的运行时**,执行 AI-Protocol 规范。这意味着:

- **零硬编码 provider 逻辑**:所有行为都由协议 manifest 驱动(source YAML 或 dist JSON)
- **基于算子的架构**:通过可组合的算子处理(Decoder → Selector → Accumulator → FanOut → EventMapper)
- **热重载**:协议配置可以在不重启应用的情况下更新
- **统一接口**:开发者使用单一、一致的 API,无论底层 provider 是什么

## 🏗️ 架构


库分为三层:

### 1. 协议规范层 (`protocol/`)

- **Loader**: 从本地文件系统、嵌入式资源或远程 URL 加载协议文件
- **Validator**: 根据 JSON Schema 验证协议
- **Schema**: 协议结构定义

### 2. 流水线解释器层 (`pipeline/`)

- **Decoder**: 将原始字节解析为协议帧(SSE、JSON Lines 等)
- **Selector**: 使用 JSONPath 表达式过滤帧
- **Accumulator**: 累积有状态数据(例如,工具调用参数)
- **FanOut**: 处理多候选场景
- **EventMapper**: 将协议帧转换为统一事件

### 3. 用户接口层 (`client/`, `types/`)

- **Client**: 统一客户端接口
- **Types**: 基于 AI-Protocol `standard_schema` 的标准类型系统

## 🧩 Feature 与 re-export(对外便利入口)


`ai-lib-rust` 的 runtime 核心保持精简;一些“更上层、更偏应用”的工具通过 feature opt-in 暴露,并在 crate root 做 re-export 以提升易用性。

更深入的架构说明见:[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)。

- **默认可用的 crate root re-export**  - `AiClient`, `AiClientBuilder`, `CancelHandle`, `CallStats`, `ChatBatchRequest`, `EndpointExt`
  - `Message`, `MessageRole`, `StreamingEvent`, `ToolCall`
  - `Result<T>`, `Error`, `ErrorContext`
- **feature-gated re-export**  - **`routing_mvp`**:纯逻辑的模型管理/路由工具(`CustomModelManager`, `ModelArray` 等)
  - **`interceptors`**:应用层调用钩子(`InterceptorPipeline`, `Interceptor`, `RequestContext`
启用方式:

```toml
[dependencies]
ai-lib-rust = { version = "0.6.0", features = ["routing_mvp", "interceptors"] }
```

## 🗺️ 能力结构清单(按层次划分)


下面是面向开发者的“能力地图”,按 runtime 的分层来组织:

### 1)协议层(`src/protocol/`
- **`ProtocolLoader`**:从本地路径 / 环境变量路径 / GitHub raw URL 加载 provider manifest
- **`ProtocolValidator`**:JSON Schema 验证(发布后也支持离线:内置 v1 schema 兜底)
- **`ProtocolManifest`**:provider manifest 的强类型结构
- **`UnifiedRequest`**:运行时内部的统一请求结构(provider 无关)

### 2)传输层(`src/transport/`
- **`HttpTransport`**:基于 reqwest 的传输实现(支持 `AI_PROXY_URL`、timeout 等生产 knobs)
- **API key 解析**:keyring → 环境变量 `<PROVIDER_ID>_API_KEY`

### 3)流水线解释器层(`src/pipeline/`
- **算子流水线**:decoder → selector → accumulator → fanout → event mapper
- **流式归一化**:把 provider 的 frame 映射为统一的 `StreamingEvent`

### 4)客户端层(`src/client/`
- **`AiClient`**:runtime 入口(`"provider/model"`- **Chat builder**`client.chat().messages(...).stream().execute_stream()`
- **Batch**`chat_batch`, `chat_batch_smart`
- **可观测性**`call_model_with_stats``CallStats`
- **取消流**`execute_stream_with_cancel()``CancelHandle`
- **服务发现/服务调用**`EndpointExt` 调用 protocol `services` 声明的管理接口

### 5)弹性/策略层(`src/resilience/` + `client/policy`
- **策略引擎**:capability 校验 + retry/fallback 决策
- **Rate limiter**:token bucket +(可选)基于 headers 的自适应模式
- **Circuit breaker**:最小熔断器(env 或 builder 默认值)
- **Backpressure**:max in-flight 并发许可

### 6)类型系统层(`src/types/`
- **消息**`Message`, `MessageRole`, `MessageContent`, `ContentBlock`
- **工具**`ToolDefinition`, `FunctionDefinition`, `ToolCall`
- **事件**`StreamingEvent`

### 7)Telemetry 层(`src/telemetry/`
- **`FeedbackSink` / `FeedbackEvent`**:可选的反馈上报能力(opt-in)

### 8)工具层(`src/utils/`
- JSONPath/路径映射、tool-call assembler 等运行时小工具

### 9)可选上层工具(feature-gated)

- **`routing_mvp`**`src/routing/`):模型选择 + endpoint array 负载均衡(纯逻辑)
- **`interceptors`**`src/interceptors/`):调用前后钩子(日志/指标/审计)

## 🚀 快速开始


### 基本用法(非流式)


```rust
use ai_lib_rust::{AiClient, Message};

#[tokio::main]

async fn main() -> ai_lib_rust::Result<()> {
    // 直接使用 provider/model 字符串创建客户端
    // 这完全由协议驱动,支持 ai-protocol manifest 中定义的任何 provider
    let client = AiClient::new("deepseek/deepseek-chat").await?;

    let messages = vec![
        Message::system("You are a helpful assistant."),
        Message::user("Hello! Explain the runtime briefly."),
    ];

    // 非流式:返回完整响应
    let resp = client
        .chat()
        .messages(messages)
        .temperature(0.7)
        .max_tokens(500)
        .execute()
        .await?;

    println!("Response:\n{}", resp.content);
    if let Some(usage) = resp.usage {
        println!("\nUsage: {usage:?}");
    }

    Ok(())
}
```

### 流式用法


```rust
use ai_lib_rust::{AiClient, Message};
use ai_lib_rust::types::events::StreamingEvent;
use futures::StreamExt;

#[tokio::main]

async fn main() -> ai_lib_rust::Result<()> {
    let client = AiClient::new("deepseek/deepseek-chat").await?;

    let messages = vec![Message::user("你好!")];

    // 流式:返回事件流
    let mut stream = client
        .chat()
        .messages(messages)
        .temperature(0.7)
        .stream()
        .execute_stream()
        .await?;

    while let Some(event) = stream.next().await {
        match event? {
            StreamingEvent::PartialContentDelta { content, .. } => print!("{content}"),
            StreamingEvent::StreamEnd { .. } => break,
            _ => {}
        }
    }

    Ok(())
}
```

### 多模态(图像 / 音频)


多模态输入表示为 `MessageContent::Blocks(Vec<ContentBlock>)`。

```rust
use ai_lib_rust::{Message, MessageRole};
use ai_lib_rust::types::message::{MessageContent, ContentBlock};

fn multimodal_message(image_path: &str) -> ai_lib_rust::Result<Message> {
    let blocks = vec![
        ContentBlock::text("简要描述这张图片。"),
        ContentBlock::image_from_file(image_path)?,
    ];
    Ok(Message::with_content(
        MessageRole::User,
        MessageContent::blocks(blocks),
    ))
}
```

### 有用的环境变量


- `AI_PROTOCOL_DIR` / `AI_PROTOCOL_PATH`: 本地 `ai-protocol` 仓库根目录路径(包含 `v1/`- `AI_LIB_ATTEMPT_TIMEOUT_MS`: 统一策略引擎使用的每次尝试超时保护
- `AI_LIB_BATCH_CONCURRENCY`: 批量操作的并发限制覆盖

### 自定义协议


```rust
use ai_lib_rust::protocol::ProtocolLoader;

let loader = ProtocolLoader::new()
    .with_base_path("./ai-protocol")
    .with_hot_reload(true);

let manifest = loader.load_provider("openai").await?;
```

## 📦 安装


添加到 `Cargo.toml`:

```toml
[dependencies]
ai-lib-rust = "0.6.0"
tokio = { version = "1.0", features = ["full"] }
futures = "0.3"
```

## 🔧 配置


库自动在以下位置查找协议 manifest(按顺序):

1. 通过 `ProtocolLoader::with_base_path()` 设置的自定义路径
2. `AI_PROTOCOL_DIR` / `AI_PROTOCOL_PATH`(本地路径或 GitHub raw URL)
3. 常见开发路径:`ai-protocol/``../ai-protocol/``../../ai-protocol/`
4. 最终兜底:GitHub raw `hiddenpath/ai-protocol`(main)

对每个 base path,provider manifest 的解析顺序为(向后兼容):
`dist/v1/providers/<id>.json` → `v1/providers/<id>.yaml`。

协议 manifest 应遵循 AI-Protocol v1.5 规范结构。运行时根据 AI-Protocol 仓库中的官方 JSON Schema 验证 manifest。

## 🔐 Provider 要求(API 密钥)


大多数 provider 需要 API 密钥。运行时按以下顺序读取密钥:

1. **操作系统密钥环**(可选,便利功能)
   - **Windows**: 使用 Windows 凭据管理器
   - **macOS**: 使用 Keychain
   - **Linux**: 使用 Secret Service API
   - 服务:`ai-protocol`,用户名:provider id
   - **注意**:密钥环是可选的,在容器/WSL 中可能无法工作。会自动回退到环境变量。

2. **环境变量**(生产环境推荐)
   - 格式:`<PROVIDER_ID>_API_KEY`(例如 `DEEPSEEK_API_KEY``ANTHROPIC_API_KEY``OPENAI_API_KEY`   - **推荐用于**:CI/CD、容器、WSL、生产部署

**示例**:
```bash
# 通过环境变量设置 API 密钥(推荐)

export DEEPSEEK_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."

# 或使用密钥环(可选,用于本地开发)

# Windows: 存储在凭据管理器中

# macOS: 存储在 Keychain 中

```

Provider 特定细节各不相同,但 `ai-lib-rust` 在统一客户端 API 后面将它们标准化。

## 🌐 代理 / 超时 / 背压(生产环境配置)


- **代理**:设置 `AI_PROXY_URL`(例如 `http://user:pass@host:port`- **HTTP 超时**:设置 `AI_HTTP_TIMEOUT_SECS`(后备:`AI_TIMEOUT_SECS`- **并发限制**:设置 `AI_LIB_MAX_INFLIGHT` 或使用 `AiClientBuilder::max_inflight(n)`
- **速率限制**(可选):设置以下之一
  - `AI_LIB_RPS`(每秒请求数),或
  - `AI_LIB_RPM`(每分钟请求数)
- **熔断器**(可选):通过 `AiClientBuilder::circuit_breaker_default()` 或环境变量启用
  - `AI_LIB_BREAKER_FAILURE_THRESHOLD`(默认 5)
  - `AI_LIB_BREAKER_COOLDOWN_SECS`(默认 30)

## 📊 可观测性:CallStats


如果需要每次调用的统计信息(延迟、重试、请求 ID、端点),请使用:

```rust
let (resp, stats) = client.call_model_with_stats(unified_req).await?;
println!("client_request_id={}", stats.client_request_id);
```

## 🛑 可取消的流式响应


```rust
let (mut stream, cancel) = client.chat().messages(messages).stream().execute_stream_with_cancel().await?;
// cancel.cancel(); // 发出 StreamEnd{finish_reason:"cancelled"},丢弃底层网络流,并释放并发许可
```

## 🧾 可选反馈(Choice Selection)


遥测是**选择加入**的。您可以注入 `FeedbackSink` 并显式报告反馈:

```rust
use ai_lib_rust::telemetry::{FeedbackEvent, ChoiceSelectionFeedback};

client.report_feedback(FeedbackEvent::ChoiceSelection(ChoiceSelectionFeedback {
    request_id: stats.client_request_id.clone(),
    chosen_index: 0,
    rejected_indices: None,
    latency_to_select_ms: None,
    ui_context: None,
    candidate_hashes: None,
})).await?;
```

## 🎨 核心特性


### 协议驱动架构


没有 `match provider` 语句。所有逻辑都来自协议配置:

```rust
// 流水线从协议 manifest 动态构建
let pipeline = Pipeline::from_manifest(&manifest)?;

// 算子通过 manifest(YAML/JSON)配置,而不是硬编码
// 添加新 provider 需要零代码更改
```

### 多候选支持


通过 `FanOut` 算子自动处理多候选场景:

```yaml
streaming:
  candidate:
    candidate_id_path: "$.choices[*].index"
    fan_out: true
```

### 工具累积


工具调用参数的有状态累积:

```yaml
streaming:
  accumulator:
    stateful_tool_parsing: true
    key_path: "$.delta.partial_json"
    flush_on: "$.type == 'content_block_stop'"
```

### 热重载


协议配置可以在运行时更新:

```rust
let loader = ProtocolLoader::new().with_hot_reload(true);
// 协议更改会自动拾取
```

## 📚 示例


查看 `examples/` 目录:

- `basic_usage.rs`: 简单的非流式聊天完成
- `deepseek_chat_stream.rs`: 流式聊天示例
- `deepseek_tool_call_stream.rs`: 流式工具调用
- `custom_protocol.rs`: 加载自定义协议配置
- `list_models.rs`: 列出 provider 的可用模型
- `service_discovery.rs`: 服务发现和自定义服务调用
- `test_protocol_loading.rs`: 协议加载自检

## 🧪 测试


```bash
cargo test
```

## 📦 批量(聊天)


对于批量执行(保持顺序),请使用:

```rust
use ai_lib_rust::{AiClient, ChatBatchRequest, Message};

let client = AiClient::new("deepseek/deepseek-chat").await?;

let reqs = vec![
    ChatBatchRequest::new(vec![Message::user("你好")]),
    ChatBatchRequest::new(vec![Message::user("用一句话解释 SSE")])
        .temperature(0.2),
];

let results = client.chat_batch(reqs, Some(5)).await;
```

### 智能批量调优


如果您更喜欢保守的默认启发式,请使用:

```rust
let results = client.chat_batch_smart(reqs).await;
```

通过以下方式覆盖并发:
- `AI_LIB_BATCH_CONCURRENCY`

## 🤝 贡献


欢迎贡献!请确保:

1. 所有协议配置遵循 AI-Protocol v1.5 规范
2. 新算子有适当文档
3. 新功能包含测试
4. 代码遵循 Rust 最佳实践并通过 `cargo clippy`

## 📄 许可证


本项目采用以下许可证之一:

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE)
- MIT License ([LICENSE-MIT]LICENSE-MIT)

您可以选择其中一种。

## 🔗 相关项目


- [AI-Protocol]https://github.com/hiddenpath/ai-protocol: 协议规范(v1.5)

---

**ai-lib-rust** - 协议与性能的完美结合。🚀