133 lines
3.6 KiB
Rust
133 lines
3.6 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),
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|