llm_worker_rs/worker/examples/timeline_basic.rs

135 lines
3.7 KiB
Rust

//! Timeline使用例
//!
//! 設計ドキュメントに基づいたTimelineの使用パターンを示すサンプル
use worker::{
Event, Handler, TextBlockEvent, TextBlockKind, Timeline, ToolUseBlockEvent, ToolUseBlockKind,
UsageEvent, UsageKind,
};
fn main() {
// シミュレートされたイベントストリーム
let events = simulate_llm_response();
// Timelineを作成し、ハンドラーを登録
let mut timeline = Timeline::new();
// Usage収集ハンドラー
timeline.on_usage(UsageAccumulator::new());
// テキスト収集ハンドラー
timeline.on_text_block(TextCollector::new());
// ツール呼び出し収集ハンドラー
timeline.on_tool_use_block(ToolCallCollector::new());
// イベントをディスパッチ
for event in &events {
timeline.dispatch(event);
}
println!("Timeline example completed!");
println!("Events processed: {}", events.len());
}
/// LLMレスポンスをシミュレート
fn simulate_llm_response() -> Vec<Event> {
vec![
// テキストブロック
Event::text_block_start(0),
Event::text_delta(0, "Hello, "),
Event::text_delta(0, "I can help you with that."),
Event::text_block_stop(0, None),
// 使用量
Event::usage(100, 50),
// ツール呼び出し
Event::tool_use_start(1, "call_abc123", "get_weather"),
Event::tool_input_delta(1, r#"{"city":"#),
Event::tool_input_delta(1, r#""Tokyo"}"#),
Event::tool_use_stop(1),
// 最終的な使用量
Event::usage(100, 75),
]
}
// =============================================================================
// Example Handlers (defined in example, not in library)
// =============================================================================
/// 使用量を累積するハンドラー
struct UsageAccumulator {
total_tokens: u64,
}
impl UsageAccumulator {
fn new() -> Self {
Self { total_tokens: 0 }
}
}
impl Handler<UsageKind> for UsageAccumulator {
type Scope = ();
fn on_event(&mut self, _scope: &mut (), usage: &UsageEvent) {
self.total_tokens += usage.total_tokens.unwrap_or(0);
}
}
/// テキストを収集するハンドラー
struct TextCollector {
results: Vec<String>,
}
impl TextCollector {
fn new() -> Self {
Self {
results: Vec::new(),
}
}
}
impl Handler<TextBlockKind> for TextCollector {
type Scope = String;
fn on_event(&mut self, buffer: &mut String, event: &TextBlockEvent) {
match event {
TextBlockEvent::Start(_) => {}
TextBlockEvent::Delta(s) => buffer.push_str(s),
TextBlockEvent::Stop(_) => {
self.results.push(std::mem::take(buffer));
}
}
}
}
/// ツール呼び出しを収集するハンドラー
struct ToolCallCollector {
calls: Vec<(String, String)>, // (name, args)
}
impl ToolCallCollector {
fn new() -> Self {
Self { calls: Vec::new() }
}
}
#[derive(Default)]
struct ToolCallScope {
name: String,
args: String,
}
impl Handler<ToolUseBlockKind> for ToolCallCollector {
type Scope = ToolCallScope;
fn on_event(&mut self, scope: &mut ToolCallScope, event: &ToolUseBlockEvent) {
match event {
ToolUseBlockEvent::Start(s) => scope.name = s.name.clone(),
ToolUseBlockEvent::InputJsonDelta(json) => scope.args.push_str(json),
ToolUseBlockEvent::Stop(_) => {
self.calls.push((
std::mem::take(&mut scope.name),
std::mem::take(&mut scope.args),
));
}
}
}
}