docs: Tidying up comments
This commit is contained in:
+35
-6
@@ -1,10 +1,39 @@
|
||||
//! worker - LLMワーカーのメイン実装
|
||||
//! worker - LLMワーカーライブラリ
|
||||
//!
|
||||
//! このクレートは以下を提供します:
|
||||
//! - Worker: ターン制御を行う高レベルコンポーネント
|
||||
//! - Timeline: イベントストリームの状態管理とハンドラーへのディスパッチ
|
||||
//! - LlmClient: LLMプロバイダとの通信
|
||||
//! - 型消去されたHandler実装
|
||||
//! LLMとの対話を管理するコンポーネントを提供します。
|
||||
//!
|
||||
//! # 主要なコンポーネント
|
||||
//!
|
||||
//! - [`Worker`] - LLMとの対話を管理する中心コンポーネント
|
||||
//! - [`Tool`] - LLMから呼び出し可能なツール
|
||||
//! - [`WorkerHook`] - ターン進行への介入
|
||||
//! - [`WorkerSubscriber`] - ストリーミングイベントの購読
|
||||
//!
|
||||
//! # Quick Start
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use worker::{Worker, Message};
|
||||
//!
|
||||
//! // Workerを作成
|
||||
//! let mut worker = Worker::new(client)
|
||||
//! .system_prompt("You are a helpful assistant.");
|
||||
//!
|
||||
//! // ツールを登録(オプション)
|
||||
//! worker.register_tool(my_tool);
|
||||
//!
|
||||
//! // 対話を実行
|
||||
//! let history = worker.run("Hello!").await?;
|
||||
//! ```
|
||||
//!
|
||||
//! # キャッシュ保護
|
||||
//!
|
||||
//! KVキャッシュのヒット率を最大化するには、[`Worker::lock()`]で
|
||||
//! ロック状態に遷移してから実行してください。
|
||||
//!
|
||||
//! ```ignore
|
||||
//! let mut locked = worker.lock();
|
||||
//! locked.run("user input").await?;
|
||||
//! ```
|
||||
|
||||
pub mod llm_client;
|
||||
mod subscriber_adapter;
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
//! LLMクライアント層
|
||||
//!
|
||||
//! LLMプロバイダと通信し、統一された`Event`ストリームを出力する。
|
||||
//! 各LLMプロバイダと通信し、統一された[`Event`](crate::Event)ストリームを出力します。
|
||||
//!
|
||||
//! # サポートするプロバイダ
|
||||
//!
|
||||
//! - Anthropic (Claude)
|
||||
//! - OpenAI (GPT-4, etc.)
|
||||
//! - Google (Gemini)
|
||||
//! - Ollama (ローカルLLM)
|
||||
//!
|
||||
//! # アーキテクチャ
|
||||
//!
|
||||
//! - **client**: `LlmClient` trait定義
|
||||
//! - **scheme**: APIスキーマ(リクエスト/レスポンス変換)
|
||||
//! - **providers**: プロバイダ固有のHTTPクライアント実装
|
||||
//! - [`LlmClient`] - プロバイダ共通のtrait
|
||||
//! - `providers`: プロバイダ固有のクライアント実装
|
||||
//! - `scheme`: APIスキーマ(リクエスト/レスポンス変換)
|
||||
|
||||
pub mod client;
|
||||
pub mod error;
|
||||
|
||||
+35
-11
@@ -1,6 +1,7 @@
|
||||
//! Timeline層の実装
|
||||
//! Timeline層
|
||||
//!
|
||||
//! イベントストリームを受信し、登録されたHandlerへディスパッチする
|
||||
//! LLMからのイベントストリームを受信し、登録されたHandlerにディスパッチします。
|
||||
//! 通常はWorker経由で使用しますが、直接使用することも可能です。
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -10,9 +11,11 @@ use worker_types::*;
|
||||
// Type-erased Handler
|
||||
// =============================================================================
|
||||
|
||||
/// 型消去されたHandler trait
|
||||
/// 型消去された`Handler` trait
|
||||
///
|
||||
/// 各Handlerは独自のScope型を持つため、Timelineで保持するには型消去が必要
|
||||
/// 各Handlerは独自のScope型を持つため、Timelineで保持するには型消去が必要です。
|
||||
/// 通常は直接使用せず、`Timeline::on_text_block()`などのメソッド経由で
|
||||
/// 自動的にラップされます。
|
||||
pub trait ErasedHandler<K: Kind>: Send {
|
||||
/// イベントをディスパッチ
|
||||
fn dispatch(&mut self, event: &K::Event);
|
||||
@@ -22,7 +25,7 @@ pub trait ErasedHandler<K: Kind>: Send {
|
||||
fn end_scope(&mut self);
|
||||
}
|
||||
|
||||
/// Handler<K>からErasedHandler<K>へのラッパー
|
||||
/// `Handler<K>`を`ErasedHandler<K>`として扱うためのラッパー
|
||||
pub struct HandlerWrapper<H, K>
|
||||
where
|
||||
H: Handler<K>,
|
||||
@@ -316,13 +319,34 @@ where
|
||||
// Timeline
|
||||
// =============================================================================
|
||||
|
||||
/// Timeline - イベントストリームの状態管理とディスパッチ
|
||||
/// イベントストリームの管理とハンドラへのディスパッチ
|
||||
///
|
||||
/// # 責務
|
||||
/// 1. Eventストリームを受信
|
||||
/// 2. Block系イベントをBlockKindごとのライフサイクルイベントに変換
|
||||
/// 3. 各Handlerごとのスコープの生成・管理
|
||||
/// 4. 登録されたHandlerへの登録順ディスパッチ
|
||||
/// LLMからのイベントを受信し、登録されたハンドラに振り分けます。
|
||||
/// ブロック系イベントはスコープ管理付きで処理されます。
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Timeline, Handler, TextBlockKind, TextBlockEvent};
|
||||
///
|
||||
/// struct MyHandler;
|
||||
/// impl Handler<TextBlockKind> for MyHandler {
|
||||
/// type Scope = String;
|
||||
/// fn on_event(&mut self, buffer: &mut String, event: &TextBlockEvent) {
|
||||
/// if let TextBlockEvent::Delta(text) = event {
|
||||
/// buffer.push_str(text);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let mut timeline = Timeline::new();
|
||||
/// timeline.on_text_block(MyHandler);
|
||||
/// ```
|
||||
///
|
||||
/// # サポートするイベント種別
|
||||
///
|
||||
/// - **メタ系**: Usage, Ping, Status, Error
|
||||
/// - **ブロック系**: TextBlock, ThinkingBlock, ToolUseBlock
|
||||
pub struct Timeline {
|
||||
// Meta系ハンドラー
|
||||
usage_handlers: Vec<Box<dyn ErasedHandler<UsageKind>>>,
|
||||
|
||||
+96
-19
@@ -82,20 +82,40 @@ impl<S: WorkerSubscriber + 'static> TurnNotifier for SubscriberTurnNotifier<S> {
|
||||
// Worker
|
||||
// =============================================================================
|
||||
|
||||
/// Worker - ターン制御コンポーネント
|
||||
/// LLMとの対話を管理する中心コンポーネント
|
||||
///
|
||||
/// Type-stateパターンによりキャッシュ保護を実現する。
|
||||
/// ユーザーからの入力を受け取り、LLMにリクエストを送信し、
|
||||
/// ツール呼び出しがあれば自動的に実行してターンを進行させます。
|
||||
///
|
||||
/// # 状態
|
||||
/// - `Mutable`: 初期状態。システムプロンプトや履歴を自由に編集可能。
|
||||
/// - `Locked`: キャッシュ保護状態。前方コンテキストは不変となり、追記のみ可能。
|
||||
/// # 状態遷移(Type-state)
|
||||
///
|
||||
/// # 責務
|
||||
/// - LLMへのリクエスト送信とレスポンス処理
|
||||
/// - ツール呼び出しの収集と実行
|
||||
/// - Hookによる介入の提供
|
||||
/// - ターンループの制御
|
||||
/// - 履歴の所有と管理
|
||||
/// - [`Mutable`]: 初期状態。システムプロンプトや履歴を自由に編集可能。
|
||||
/// - [`Locked`]: キャッシュ保護状態。`lock()`で遷移。前方コンテキストは不変。
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Worker, Message};
|
||||
///
|
||||
/// // Workerを作成してツールを登録
|
||||
/// let mut worker = Worker::new(client)
|
||||
/// .system_prompt("You are a helpful assistant.");
|
||||
/// worker.register_tool(my_tool);
|
||||
///
|
||||
/// // 対話を実行
|
||||
/// let history = worker.run("Hello!").await?;
|
||||
/// ```
|
||||
///
|
||||
/// # キャッシュ保護が必要な場合
|
||||
///
|
||||
/// ```ignore
|
||||
/// let mut worker = Worker::new(client)
|
||||
/// .system_prompt("...");
|
||||
///
|
||||
/// // 履歴を設定後、ロックしてキャッシュを保護
|
||||
/// let mut locked = worker.lock();
|
||||
/// locked.run("user input").await?;
|
||||
/// ```
|
||||
pub struct Worker<C: LlmClient, S: WorkerState = Mutable> {
|
||||
/// LLMクライアント
|
||||
client: C,
|
||||
@@ -128,13 +148,37 @@ pub struct Worker<C: LlmClient, S: WorkerState = Mutable> {
|
||||
// =============================================================================
|
||||
|
||||
impl<C: LlmClient, S: WorkerState> Worker<C, S> {
|
||||
/// WorkerSubscriberを登録
|
||||
/// イベント購読者を登録する
|
||||
///
|
||||
/// Subscriberは以下のイベントを受け取ることができる:
|
||||
/// - ブロックイベント: on_text_block, on_tool_use_block
|
||||
/// - 単発イベント: on_usage, on_status, on_error
|
||||
/// - 累積イベント: on_text_complete, on_tool_call_complete
|
||||
/// - ターン制御: on_turn_start, on_turn_end
|
||||
/// 登録したSubscriberは、LLMからのストリーミングイベントを
|
||||
/// リアルタイムで受信できます。UIへのストリーム表示などに利用します。
|
||||
///
|
||||
/// # 受信できるイベント
|
||||
///
|
||||
/// - **ブロックイベント**: `on_text_block`, `on_tool_use_block`
|
||||
/// - **メタイベント**: `on_usage`, `on_status`, `on_error`
|
||||
/// - **完了イベント**: `on_text_complete`, `on_tool_call_complete`
|
||||
/// - **ターン制御**: `on_turn_start`, `on_turn_end`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Worker, WorkerSubscriber, TextBlockEvent};
|
||||
///
|
||||
/// struct MyPrinter;
|
||||
/// impl WorkerSubscriber for MyPrinter {
|
||||
/// type TextBlockScope = ();
|
||||
/// type ToolUseBlockScope = ();
|
||||
///
|
||||
/// fn on_text_block(&mut self, _: &mut (), event: &TextBlockEvent) {
|
||||
/// if let TextBlockEvent::Delta(text) = event {
|
||||
/// print!("{}", text);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// worker.subscribe(MyPrinter);
|
||||
/// ```
|
||||
pub fn subscribe<Sub: WorkerSubscriber + 'static>(&mut self, subscriber: Sub) {
|
||||
let subscriber = Arc::new(Mutex::new(subscriber));
|
||||
|
||||
@@ -159,7 +203,19 @@ impl<C: LlmClient, S: WorkerState> Worker<C, S> {
|
||||
.push(Box::new(SubscriberTurnNotifier { subscriber }));
|
||||
}
|
||||
|
||||
/// ツールを登録
|
||||
/// ツールを登録する
|
||||
///
|
||||
/// 登録されたツールはLLMからの呼び出しで自動的に実行されます。
|
||||
/// 同名のツールを登録した場合、後から登録したものが優先されます。
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::Worker;
|
||||
/// use my_tools::SearchTool;
|
||||
///
|
||||
/// worker.register_tool(SearchTool::new());
|
||||
/// ```
|
||||
pub fn register_tool(&mut self, tool: impl Tool + 'static) {
|
||||
let name = tool.name().to_string();
|
||||
self.tools.insert(name, Arc::new(tool));
|
||||
@@ -172,7 +228,28 @@ impl<C: LlmClient, S: WorkerState> Worker<C, S> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Hookを追加
|
||||
/// Hookを追加する
|
||||
///
|
||||
/// Hookはターンの進行・ツール実行に介入できます。
|
||||
/// 複数のHookを登録した場合、登録順に実行されます。
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// use worker::{Worker, WorkerHook, ControlFlow, ToolCall};
|
||||
///
|
||||
/// struct LoggingHook;
|
||||
///
|
||||
/// #[async_trait::async_trait]
|
||||
/// impl WorkerHook for LoggingHook {
|
||||
/// async fn before_tool_call(&self, call: &mut ToolCall) -> Result<ControlFlow, HookError> {
|
||||
/// println!("Calling tool: {}", call.name);
|
||||
/// Ok(ControlFlow::Continue)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// worker.add_hook(LoggingHook);
|
||||
/// ```
|
||||
pub fn add_hook(&mut self, hook: impl WorkerHook + 'static) {
|
||||
self.hooks.push(Box::new(hook));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user