Bump llm-worker to 0.2.1
This commit is contained in:
parent
1fd7a4c698
commit
6d87da90d1
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -708,7 +708,7 @@ checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "llm-worker"
|
name = "llm-worker"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"clap",
|
"clap",
|
||||||
|
|
|
||||||
|
|
@ -31,41 +31,48 @@ graph TD
|
||||||
|
|
||||||
Workerは以下のループ(ターン)を実行します。
|
Workerは以下のループ(ターン)を実行します。
|
||||||
|
|
||||||
1. **Start Turn**: `Worker::run(messages)` 呼び出し
|
1. **Start Turn**: `Worker::run(messages)` 呼び出し
|
||||||
2. **Hook: OnMessageSend**:
|
2. **Hook: OnMessageSend**:
|
||||||
* ユーザーメッセージの改変、バリデーション、キャンセルが可能。
|
- ユーザーメッセージの改変、バリデーション、キャンセルが可能。
|
||||||
* コンテキストへのシステムプロンプト注入などもここで行う想定。
|
- コンテキストへのシステムプロンプト注入などもここで行う想定。
|
||||||
3. **Request & Stream**:
|
3. **Request & Stream**:
|
||||||
* LLMへリクエスト送信。イベントストリーム開始。
|
- LLMへリクエスト送信。イベントストリーム開始。
|
||||||
* `Timeline`によるイベント処理。
|
- `Timeline`によるイベント処理。
|
||||||
4. **Tool Handling (Parallel)**:
|
4. **Tool Handling (Parallel)**:
|
||||||
* レスポンス内に含まれる全てのTool Callを収集。
|
- レスポンス内に含まれる全てのTool Callを収集。
|
||||||
* 各Toolに対して **Hook: BeforeToolCall** を実行(実行可否、引数改変)。
|
- 各Toolに対して **Hook: BeforeToolCall** を実行(実行可否、引数改変)。
|
||||||
* 許可されたToolを**並列実行 (`join_all`)**。
|
- 許可されたToolを**並列実行 (`join_all`)**。
|
||||||
* 各Tool実行後に **Hook: AfterToolCall** を実行(結果の確認、加工)。
|
- 各Tool実行後に **Hook: AfterToolCall** を実行(結果の確認、加工)。
|
||||||
5. **Next Request Decision**:
|
5. **Next Request Decision**:
|
||||||
* Tool実行結果がある場合 -> 結果をMessageとしてContextに追加し、**Step 3へ戻る** (自動ループ)。
|
- Tool実行結果がある場合 -> 結果をMessageとしてContextに追加し、**Step
|
||||||
* Tool実行がない場合 -> Step 6へ。
|
3へ戻る** (自動ループ)。
|
||||||
6. **Hook: OnTurnEnd**:
|
- Tool実行がない場合 -> Step 6へ。
|
||||||
* 最終的な応答に対するチェック(Lint/Fmt)。
|
6. **Hook: OnTurnEnd**:
|
||||||
* エラーがある場合、エラーメッセージをContextに追加して **Step 3へ戻る** ことで自己修正を促せる。
|
- 最終的な応答に対するチェック(Lint/Fmt)。
|
||||||
* 問題なければターン終了。
|
- エラーがある場合、エラーメッセージをContextに追加して **Step 3へ戻る**
|
||||||
|
ことで自己修正を促せる。
|
||||||
|
- 問題なければターン終了。
|
||||||
|
|
||||||
## Tool 設計
|
## Tool 設計
|
||||||
|
|
||||||
### アーキテクチャ概要
|
### アーキテクチャ概要
|
||||||
|
|
||||||
Rustの静的型付けシステムとLLMの動的なツール呼び出し(文字列による指定)を、**Trait Object** と **動的ディスパッチ** を用いて接続します。
|
Rustの静的型付けシステムとLLMの動的なツール呼び出し(文字列による指定)を、**Trait
|
||||||
|
Object** と **動的ディスパッチ** を用いて接続します。
|
||||||
|
|
||||||
1. **共通インターフェース (`Tool` Trait)**: 全てのツールが実装すべき共通の振る舞い(メタデータ取得と実行)を定義します。
|
1. **共通インターフェース (`Tool` Trait)**:
|
||||||
2. **ラッパー生成 (`#[tool]` Macro)**: ユーザー定義のメソッドをラップし、`Tool` Traitを実装した構造体を自動生成します。
|
全てのツールが実装すべき共通の振る舞い(メタデータ取得と実行)を定義します。
|
||||||
3. **レジストリ (`HashMap`)**: Workerは動的ディスパッチ用に `HashMap<String, Box<dyn Tool>>` でツールを管理します。
|
2. **ラッパー生成 (`#[tool]` Macro)**: ユーザー定義のメソッドをラップし、`Tool`
|
||||||
|
Traitを実装した構造体を自動生成します。
|
||||||
|
3. **レジストリ (`HashMap`)**: Workerは動的ディスパッチ用に
|
||||||
|
`HashMap<String, Box<dyn Tool>>` でツールを管理します。
|
||||||
|
|
||||||
この仕組みにより、「名前からツールを探し、JSON引数を型変換して関数を実行する」フローを安全に実現します。
|
この仕組みにより、「名前からツールを探し、JSON引数を型変換して関数を実行する」フローを安全に実現します。
|
||||||
|
|
||||||
### 1. Tool Trait 定義
|
### 1. Tool Trait 定義
|
||||||
|
|
||||||
ツールが最低限持つべきインターフェースです。`Send + Sync` を必須とし、マルチスレッド(並列実行)に対応します。
|
ツールが最低限持つべきインターフェースです。`Send + Sync`
|
||||||
|
を必須とし、マルチスレッド(並列実行)に対応します。
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
|
@ -113,7 +120,8 @@ impl MyApp {
|
||||||
|
|
||||||
**マクロ展開後のイメージ (擬似コード):**
|
**マクロ展開後のイメージ (擬似コード):**
|
||||||
|
|
||||||
マクロは、元のメソッドに対応する**ラッパー構造体**を生成します。このラッパーが `Tool` Trait を実装します。
|
マクロは、元のメソッドに対応する**ラッパー構造体**を生成します。このラッパーが
|
||||||
|
`Tool` Trait を実装します。
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// 1. 引数をデシリアライズ用の中間構造体に変換
|
// 1. 引数をデシリアライズ用の中間構造体に変換
|
||||||
|
|
@ -155,15 +163,18 @@ impl Tool for GetUserTool {
|
||||||
|
|
||||||
### 3. Workerによる実行フロー
|
### 3. Workerによる実行フロー
|
||||||
|
|
||||||
Workerは生成されたラッパー構造体を `Box<dyn Tool>` として保持し、以下のフローで実行します。
|
Workerは生成されたラッパー構造体を `Box<dyn Tool>`
|
||||||
|
として保持し、以下のフローで実行します。
|
||||||
|
|
||||||
1. **登録**: アプリケーション開始時、コンテキスト(`MyApp`)から各ツールのラッパー(`GetUserTool`)を生成し、WorkerのMapに登録。
|
1. **登録**:
|
||||||
2. **解決**: LLMからのレスポンスに含まれる `ToolUse { name: "get_user", ... }` を受け取る。
|
アプリケーション開始時、コンテキスト(`MyApp`)から各ツールのラッパー(`GetUserTool`)を生成し、WorkerのMapに登録。
|
||||||
3. **検索**: `name` をキーに Map から `Box<dyn Tool>` を取得。
|
2. **解決**: LLMからのレスポンスに含まれる `ToolUse { name: "get_user", ... }`
|
||||||
4. **実行**:
|
を受け取る。
|
||||||
* `tool.execute(json)` を呼び出す。
|
3. **検索**: `name` をキーに Map から `Box<dyn Tool>` を取得。
|
||||||
* 内部で `serde_json` による型変換とメソッド実行が行われる。
|
4. **実行**:
|
||||||
* 結果が返る。
|
- `tool.execute(json)` を呼び出す。
|
||||||
|
- 内部で `serde_json` による型変換とメソッド実行が行われる。
|
||||||
|
- 結果が返る。
|
||||||
|
|
||||||
これにより、型安全性を保ちつつ、動的なツール実行が可能になります。
|
これにより、型安全性を保ちつつ、動的なツール実行が可能になります。
|
||||||
|
|
||||||
|
|
@ -171,8 +182,9 @@ Workerは生成されたラッパー構造体を `Box<dyn Tool>` として保持
|
||||||
|
|
||||||
### コンセプト
|
### コンセプト
|
||||||
|
|
||||||
* **制御の介入**: ターンの進行、メッセージの内容、ツールの実行に対して介入します。
|
- **制御の介入**:
|
||||||
* **Contextへのアクセス**: メッセージ履歴(Context)を読み書きできます。
|
ターンの進行、メッセージの内容、ツールの実行に対して介入します。
|
||||||
|
- **Contextへのアクセス**: メッセージ履歴(Context)を読み書きできます。
|
||||||
|
|
||||||
### Hook Trait
|
### Hook Trait
|
||||||
|
|
||||||
|
|
@ -219,7 +231,8 @@ pub enum OnTurnEndResult {
|
||||||
|
|
||||||
### Tool Call Context
|
### Tool Call Context
|
||||||
|
|
||||||
`before_tool_call` / `after_tool_call` は、ツール実行の文脈を含む入力を受け取る。
|
`before_tool_call` / `after_tool_call`
|
||||||
|
は、ツール実行の文脈を含む入力を受け取る。
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub struct ToolCallContext {
|
pub struct ToolCallContext {
|
||||||
|
|
@ -237,17 +250,20 @@ pub struct ToolResultContext {
|
||||||
|
|
||||||
## 実装方針
|
## 実装方針
|
||||||
|
|
||||||
1. **Worker Struct**:
|
1. **Worker Struct**:
|
||||||
* `Timeline`を所有。
|
- `Timeline`を所有。
|
||||||
* `Handler`として「ToolCallCollector」をTimelineに登録。
|
- `Handler`として「ToolCallCollector」をTimelineに登録。
|
||||||
* `stream`終了後に収集したToolCallを処理するロジックを持つ。
|
- `stream`終了後に収集したToolCallを処理するロジックを持つ。
|
||||||
|
- **履歴管理**: `set_history`, `with_messages`, `history_mut`
|
||||||
|
等を通じて、会話履歴の注入や編集を可能にする。
|
||||||
|
|
||||||
2. **Tool Executor Handler**:
|
2. **Tool Executor Handler**:
|
||||||
* Timeline上ではツール実行を行わず、あくまで「ToolCallブロックの収集」に徹する(Toolの実行は非同期かつ並列で、ストリーム終了後あるいはブロック確定後に行うため)。
|
- Timeline上ではツール実行を行わず、あくまで「ToolCallブロックの収集」に徹する(Toolの実行は非同期かつ並列で、ストリーム終了後あるいはブロック確定後に行うため)。
|
||||||
* ただし、リアルタイム性を重視する場合(ストリーミング中にToolを実行開始等)は将来的な拡張とするが、現状は「結果が揃うのを待って」という要件に従い、収集フェーズと実行フェーズを分ける。
|
- ただし、リアルタイム性を重視する場合(ストリーミング中にToolを実行開始等)は将来的な拡張とするが、現状は「結果が揃うのを待って」という要件に従い、収集フェーズと実行フェーズを分ける。
|
||||||
|
|
||||||
3. **worker-macros**:
|
3. **worker-macros**:
|
||||||
* `syn`, `quote` を用いて、関数定義から `Tool` トレイト実装と `InputSchema` (schemars利用) を生成。
|
- `syn`, `quote` を用いて、関数定義から `Tool` トレイト実装と `InputSchema`
|
||||||
|
(schemars利用) を生成。
|
||||||
|
|
||||||
## Worker Event API 設計
|
## Worker Event API 設計
|
||||||
|
|
||||||
|
|
@ -256,6 +272,7 @@ pub struct ToolResultContext {
|
||||||
Workerは内部でイベントを処理し結果を返しますが、UIへのストリーミング表示やリアルタイムフィードバックには、イベントを外部に公開する仕組みが必要です。
|
Workerは内部でイベントを処理し結果を返しますが、UIへのストリーミング表示やリアルタイムフィードバックには、イベントを外部に公開する仕組みが必要です。
|
||||||
|
|
||||||
**要件**:
|
**要件**:
|
||||||
|
|
||||||
1. テキストデルタをリアルタイムでUIに表示
|
1. テキストデルタをリアルタイムでUIに表示
|
||||||
2. ツール呼び出しの進行状況を表示
|
2. ツール呼び出しの進行状況を表示
|
||||||
3. ブロック完了時に累積結果を受け取る
|
3. ブロック完了時に累積結果を受け取る
|
||||||
|
|
@ -264,10 +281,10 @@ Workerは内部でイベントを処理し結果を返しますが、UIへのス
|
||||||
|
|
||||||
Worker APIは **Timeline層のHandler機構の薄いラッパー** として設計します。
|
Worker APIは **Timeline層のHandler機構の薄いラッパー** として設計します。
|
||||||
|
|
||||||
| 層 | 目的 | 提供するもの |
|
| 層 | 目的 | 提供するもの |
|
||||||
|---|------|-------------|
|
| ------------------------ | ------------------ | ---------------------------------- |
|
||||||
| **Handler (Timeline層)** | 内部実装、役割分離 | スコープ管理 + Deltaイベント |
|
| **Handler (Timeline層)** | 内部実装、役割分離 | スコープ管理 + Deltaイベント |
|
||||||
| **Worker Event API** | ユーザー向け利便性 | Handler露出 + Completeイベント追加 |
|
| **Worker Event API** | ユーザー向け利便性 | Handler露出 + Completeイベント追加 |
|
||||||
|
|
||||||
Handlerのスコープ管理パターン(Start→Delta→End)をそのまま活かしつつ、累積済みのCompleteイベントも追加提供します。
|
Handlerのスコープ管理パターン(Start→Delta→End)をそのまま活かしつつ、累積済みのCompleteイベントも追加提供します。
|
||||||
|
|
||||||
|
|
@ -448,7 +465,8 @@ impl<C: LlmClient> Worker<C> {
|
||||||
### 設計上のポイント
|
### 設計上のポイント
|
||||||
|
|
||||||
1. **Handlerの再利用**: 既存のHandler traitをそのまま活用
|
1. **Handlerの再利用**: 既存のHandler traitをそのまま活用
|
||||||
2. **スコープ管理の維持**: ブロックイベントはStart→Delta→Endのライフサイクルを保持
|
2. **スコープ管理の維持**:
|
||||||
|
ブロックイベントはStart→Delta→Endのライフサイクルを保持
|
||||||
3. **選択的購読**: on_*で必要なイベントだけ、またはSubscriberで一括
|
3. **選択的購読**: on_*で必要なイベントだけ、またはSubscriberで一括
|
||||||
4. **累積イベントの追加**: Worker層でComplete系イベントを追加提供
|
4. **累積イベントの追加**: Worker層でComplete系イベントを追加提供
|
||||||
5. **後方互換性**: 従来の`run()`も引き続き使用可能
|
5. **後方互換性**: 従来の`run()`も引き続き使用可能
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "llm-worker"
|
name = "llm-worker"
|
||||||
description = "A library for building autonomous LLM-powered systems"
|
description = "A library for building autonomous LLM-powered systems"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user