yoi/crates/llm-worker/docs/spec/basis.md
2026-04-04 04:27:46 +09:00

8.6 KiB

llm-worker

LLMを用いた自律的なワーカーを構築するためのライブラリ。

ツールの定義・呼び出し、コンテキスト管理、ストリーミングイベント処理、フック制御などを責務にもつ。

ワークスペース insomnia に属し、以下の3クレートで構成される:

クレート 概要
insomnia アプリケーション本体
llm-worker LLMワーカーライブラリ (本クレート)
llm-worker-macros #[tool_registry] / #[tool] 手続きマクロ

用語定義

  • Item: 会話の基本単位。Open Responses仕様に準じた列挙型で、MessageFunctionCallFunctionCallOutputReasoningの4バリアントを持つ。従来のメッセージベースAPIと異なり、ツール呼び出しや思考をファーストクラスのItemとして扱う。
  • ContentPart: Message Item内のコンテンツ要素。InputText(ユーザー入力)・OutputText(アシスタント出力)・Refusal(拒否)を区別する。
  • ブロック (Block): モデルが「開始→デルタ→終了」で囲む一塊の出力。OpenAIのresponse.output_itemやAnthropicのcontent_block、Geminiのcandidates[].content.partsなどが該当する。BlockTypeとしてTextThinkingToolUseToolResultが定義されている。
  • メタイベント (Meta Event): PingUsageStatusErrorなど、ブロックに属さない補助イベント群。ステータス更新やハートビートとして処理される。
  • Event: LLMからのストリーミングレスポンスを表現する統一型。メタイベントとブロックイベント(BlockStartBlockDeltaBlockStopBlockAbort)から成る。llm_client層とeventモジュールの双方に定義が存在する。
  • Worker: LLMとのインタラクションを管理する中心コンポーネント。ツール実行ループ、フック呼び出し、ストリーミングイベントのディスパッチを統括する。

以降の仕様では「ブロック」を上記の生成・ツール単位の総称として扱う。

アーキテクチャ

モジュール構成概念図:

llm-worker
├── worker          # Workerコア (実行ループ、状態管理)
├── state           # Type-stateパターン (Mutable / CacheLocked)
├── tool            # Tool trait, ToolMeta, ToolDefinition
├── tool_server     # ToolServer (ツールのレジストリと実行)
├── hook            # Hook trait, HookRegistry (10種のフックポイント)
├── handler         # Kind/Handler trait (イベントディスパッチ)
├── subscriber      # WorkerSubscriber trait (UI向けイベント購読)
├── event           # Worker層の公開Event型
├── message         # Item/ContentPart/Roleのre-export
├── timeline        # イベントストリームの状態管理とHandlerディスパッチ
│   ├── event       # Timeline内部イベント型
│   ├── timeline    # Timelineコア
│   ├── text_block_collector   # テキスト収集Handler
│   └── tool_call_collector    # ツール呼び出し収集Handler
└── llm_client      # LLMクライアント層
    ├── client      # LlmClient trait
    ├── event       # llm_client層のEvent型
    ├── error       # ClientError
    ├── types       # Item, ContentPart, Role, Request, RequestConfig, ToolDefinition
    ├── scheme      # APIスキーマ変換
    │   ├── openai       # OpenAI Chat Completions API
    │   ├── anthropic    # Anthropic Messages API
    │   └── gemini       # Google Gemini API
    └── providers   # プロバイダ固有クライアント
        ├── openai       # OpenAI
        ├── anthropic    # Anthropic
        ├── gemini       # Google Gemini
        └── ollama       # Ollama (ローカルLLM)

OpenAI互換のプロバイダでスキーマを使い回せるよう、schemeprovidersモジュールは分離されている。

scheme層

単純な変換を責務とするスキーマを定義する。

  • リクエスト変換: Request(SystemPrompt + Items + Tools + RequestConfig) → プロバイダ固有のリクエストJSON
  • レスポンス変換: SSEイベント → 型付きEvent構造体のストリーム

各APIスキーマ(OpenAI / Anthropic / Gemini)ごとに実装を持ち、APIスキーマに準じたパース・バリデーションを行う。

llm_client (providers) 層

LlmClient traitを実装する各プロバイダクライアントがリクエストを送信し、差異が吸収され統一されたEventストリームを出力する。

ストリーミング中のバッファリング(ToolArguments の累積等)もこの層で行う。

ConfigWarningにより、プロバイダがサポートしない設定オプションを警告として通知する仕組みを持つ。

timeline層

llm_clientからのイベントストリームを受信し、登録されたHandlerにディスパッチする。

Kind traitがイベント型を定義し、Handler<K: Kind> traitがScope(ブロックのライフサイクルに対応する状態)を持つイベント処理を行う。組み込みHandlerとしてTextBlockCollectorToolCallCollectorが提供される。

worker層

WorkerはType-stateパターンによりMutable状態とCacheLocked状態を持つ。

  • Mutable: システムプロンプトの設定変更、メッセージ履歴の編集、ツール・フックの登録が可能
  • CacheLocked: Worker::lock()で遷移。LLM APIのKVキャッシュヒット率を最大化するため、既存履歴の変更を制限する

WorkerSubscriber traitにより、テキスト生成やツール呼び出しのストリーミングイベントをUI等に配信できる。

Tools

各種プロバイダのLLMのAPI仕様として存在するTool CallやFunction CallingをTool traitとして統一的に扱う。

  • ToolMeta: ツール名・説明・入力スキーマ(JSON Schema)を保持する不変のメタ情報。Worker登録後は変更されない。
  • ToolDefinition: Fn() -> (ToolMeta, Arc<dyn Tool>)型のファクトリ。Worker登録時に一度呼び出され、メタ情報とインスタンスがセッションスコープでキャッシュされる。
  • Tool trait: async fn call(&self, arguments: Value) -> Result<String, ToolError>を持つ非同期trait。セッション中に状態を保持できる。
  • ToolServer: 登録済みツールのレジストリと実行を管理するインメモリサーバー。

llm-worker-macrosクレートが提供する#[tool_registry] / #[tool]手続きマクロにより、implブロック上のメソッドからTool trait実装を自動生成する。

Hooks

Claude Codeに存在するようなHooksと同様のターン制御・介入機構を搭載する。

以下の10種のフックポイントが定義されている:

フックポイント タイミング 戻り値による制御
OnPromptSubmit プロンプト送信時 Continue / Cancel
PreLlmRequest LLMリクエスト直前 Continue / Cancel
PreToolCall ツール実行直前 Continue / Skip / Abort / Pause
PostToolCall ツール実行直後 Continue / Abort
OnTurnEnd ターン終了時 Finish / ContinueWithMessages / Paused
OnAbort 中断時 (通知のみ)
OnTextDelta テキストデルタ受信時 (ストリーミング)
OnToolCallDelta ツール引数デルタ受信時 (ストリーミング)
OnStreamChunk ストリームチャンク受信時 (ストリーミング)
OnStreamComplete ストリーム完了時 (ストリーミング)

フックはHook traitとして表現され、HookRegistryで管理される。

ストリーミングイベント処理

イベントストリームを扱う設計目標として、Text / InputJSON / Thinkingのデルタと、細粒度ツールストリーミングを含む、デルタの低遅延・リアルタイム処理がある。

ブロックのライフサイクル: BlockStartBlockDelta(複数回) → BlockStop / BlockAbort

DeltaContentの種別:

  • Text(String) - テキスト生成のデルタ
  • Thinking(String) - 思考(Extended Thinking等)のデルタ
  • InputJson(String) - ツール引数JSONの部分文字列デルタ