151 lines
6.3 KiB
Markdown
151 lines
6.3 KiB
Markdown
# `worker` クレート
|
||
|
||
`worker` クレートは、大規模言語モデル (LLM) を利用したアプリケーションのバックエンド機能を提供するコアコンポーネントです。LLMプロバイダーの抽象化、ツール利用、柔軟なプロンプト管理、フックシステムなど、高度な機能をカプセル化し、アプリケーション開発を簡素化します。
|
||
|
||
## 主な機能
|
||
|
||
- **マルチプロバイダー対応**: Gemini, Claude, OpenAI, Ollama, XAIなど、複数のLLMプロバイダーを統一されたインターフェースで利用できます。
|
||
- **ツール利用 (Function Calling)**: LLMが外部ツールを呼び出す機能をサポートします。独自のツールを簡単に定義して `Worker` に登録できます。
|
||
- **ストリーミング処理**: LLMの応答やツール実行結果を `StreamEvent` として非同期に受け取ることができます。これにより、リアルタイムなUI更新が可能になります。
|
||
- **フックシステム**: `Worker` の処理フローの特定のタイミング(例: メッセージ送信前、ツール使用後)にカスタムロジックを介入させることができます。
|
||
- **セッション管理**: 会話履歴やワークスペースの状態を管理し、永続化する機能を提供します。
|
||
- **柔軟なプロンプト管理**: 設定ファイルを用いて、ロールやコンテキストに応じたシステムプロンプトを動的に構築します。
|
||
|
||
## 主な概念
|
||
|
||
### `Worker`
|
||
このクレートの中心的な構造体です。LLMとの対話、ツールの登録と実行、セッション管理など、すべての主要な機能を担当します。
|
||
|
||
### `LlmProvider`
|
||
サポートしているLLMプロバイダー(`Gemini`, `Claude`, `OpenAI` など)を表すenumです。
|
||
|
||
### `Tool` トレイト
|
||
`Worker` が利用できるツールを定義するためのインターフェースです。このトレイトを実装することで、任意の機能をツールとして `Worker` に追加できます。
|
||
|
||
```rust
|
||
pub trait Tool: Send + Sync {
|
||
fn name(&self) -> &str;
|
||
fn description(&self) -> &str;
|
||
fn parameters_schema(&self) -> serde_json::Value;
|
||
async fn execute(&self, args: serde_json::Value) -> Result<serde_json::Value, crate::WorkerError>;
|
||
}
|
||
```
|
||
|
||
### `WorkerHook` トレイト
|
||
`Worker` のライフサイクルイベントに介入するためのフックを定義するインターフェースです。特定のイベント(例: `OnMessageSend`, `PostToolUse`)に対して処理を追加できます。
|
||
|
||
### `StreamEvent`
|
||
`Worker` の処理結果を非同期ストリームで受け取るためのenumです。LLMの応答チャンク、ツール呼び出し、エラーなど、さまざまなイベントを表します。
|
||
|
||
## アプリケーションへの組み込み方法
|
||
|
||
### 1. Workerの初期化
|
||
|
||
まず、`Worker` のインスタンスを作成します。これには `LlmProvider`、モデル名、APIキーが必要です。
|
||
|
||
```rust
|
||
use worker::{Worker, LlmProvider};
|
||
use std::collections::HashMap;
|
||
|
||
// APIキーを準備
|
||
let mut api_keys = HashMap::new();
|
||
api_keys.insert("openai".to_string(), "your_openai_api_key".to_string());
|
||
api_keys.insert("claude".to_string(), "your_claude_api_key".to_string());
|
||
|
||
// Workerを作成
|
||
let mut worker = Worker::new(
|
||
LlmProvider::OpenAI,
|
||
"gpt-4o",
|
||
&api_keys,
|
||
None // RoleConfigはオプション
|
||
).expect("Workerの作成に失敗しました");
|
||
```
|
||
|
||
### 2. ツールの定義と登録
|
||
|
||
`Tool` トレイトを実装してカスタムツールを作成し、`Worker` に登録します。
|
||
|
||
```rust
|
||
use worker::{Tool, ToolResult};
|
||
use worker::schemars::{self, JsonSchema};
|
||
use worker::serde_json::{self, json, Value};
|
||
use async_trait::async_trait;
|
||
|
||
// ツールの引数を定義
|
||
#[derive(Debug, serde::Deserialize, JsonSchema)]
|
||
struct FileSystemToolArgs {
|
||
path: String,
|
||
}
|
||
|
||
// カスタムツールを定義
|
||
struct ListFilesTool;
|
||
|
||
#[async_trait]
|
||
impl Tool for ListFilesTool {
|
||
fn name(&self) -> &str { "list_files" }
|
||
fn description(&self) -> &str { "指定されたパスのファイル一覧を表示します" }
|
||
|
||
fn parameters_schema(&self) -> Value {
|
||
serde_json::to_value(schemars::schema_for!(FileSystemToolArgs)).unwrap()
|
||
}
|
||
|
||
async fn execute(&self, args: Value) -> ToolResult<Value> {
|
||
let tool_args: FileSystemToolArgs = serde_json::from_value(args)?;
|
||
// ここで実際のファイル一覧取得処理を実装
|
||
let files = vec!["file1.txt", "file2.txt"];
|
||
Ok(json!({ "files": files }))
|
||
}
|
||
}
|
||
|
||
// 作成したツールをWorkerに登録
|
||
worker.register_tool(Box::new(ListFilesTool)).unwrap();
|
||
```
|
||
|
||
### 3. 対話処理の実行
|
||
|
||
`process_task_with_history` メソッドを呼び出して、ユーザーメッセージを処理します。このメソッドはイベントのストリームを返します。
|
||
|
||
```rust
|
||
use futures_util::StreamExt;
|
||
|
||
let user_message = "カレントディレクトリのファイルを教えて".to_string();
|
||
|
||
let mut stream = worker.process_task_with_history(user_message, None).await;
|
||
|
||
while let Some(event_result) = stream.next().await {
|
||
match event_result {
|
||
Ok(event) => {
|
||
// StreamEventに応じた処理
|
||
match event {
|
||
worker::StreamEvent::Chunk(chunk) => {
|
||
print!("{}", chunk);
|
||
}
|
||
worker::StreamEvent::ToolCall(tool_call) => {
|
||
println!("\n[Tool Call: {} with args {}]", tool_call.name, tool_call.arguments);
|
||
}
|
||
worker::StreamEvent::ToolResult { tool_name, result } => {
|
||
println!("\n[Tool Result: {} -> {:?}]", tool_name, result);
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
Err(e) => {
|
||
eprintln!("\n[Error: {}]", e);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. (オプション) フックの登録
|
||
|
||
`WorkerHook` トレイトを実装してカスタムフックを作成し、`Worker` に登録することで、処理フローをカスタマイズできます。
|
||
|
||
```rust
|
||
// (WorkerHookの実装は省略)
|
||
// let my_hook = MyCustomHook::new();
|
||
// worker.register_hook(Box::new(my_hook));
|
||
```
|
||
|
||
これで、アプリケーションの要件に応じて `Worker` を中心とした強力なLLM連携機能を構築できます。
|