LLM プロバイダーモジュール概要
このドキュメントでは、Elftia における LLM プロバイダーサブシステムの全体アーキテクチャを説明します。このサブシステムは、マルチプロバイダー設定の管理、API キープール、モデルディスカバリー、リクエストルーティング、Completion 呼び出しパイプラインを担当します。
ファイルの場所
| モジュール | パス |
|---|---|
| CompletionService | packages/desktop/app/main/services/capabilities/llm/completion/CompletionService.ts |
| ApiKeyPoolService | packages/desktop/app/main/services/capabilities/llm/completion/ApiKeyPoolService.ts |
| LLMConfigService | packages/desktop/app/main/services/capabilities/llm/config-service/LLMConfigService.ts |
| ProviderManager | packages/desktop/app/main/services/capabilities/llm/config-service/ProviderManager.ts |
| ModelDiscoveryManager | packages/desktop/app/main/services/capabilities/llm/config-service/ModelDiscoveryManager.ts |
| ConfigIOManager | packages/desktop/app/main/services/capabilities/llm/config-service/ConfigIOManager.ts |
| AgentModelsManager | packages/desktop/app/main/services/capabilities/llm/config-service/AgentModelsManager.ts |
| ThinkingResolver | packages/desktop/app/main/services/capabilities/llm/completion/ThinkingResolver.ts |
| StreamHandler | packages/desktop/app/main/services/capabilities/llm/completion/StreamHandler.ts |
| DirectApiHandler | packages/desktop/app/main/services/capabilities/llm/completion/DirectApiHandler.ts |
| ToolHandler | packages/desktop/app/main/services/capabilities/llm/completion/ToolHandler.ts |
| TransformerHandler | packages/desktop/app/main/services/capabilities/llm/completion/TransformerHandler.ts |
| ProviderSearchInjector | packages/desktop/app/main/services/capabilities/llm/completion/ProviderSearchInjector.ts |
| NativeSearchInjector | packages/desktop/app/main/services/capabilities/llm/completion/NativeSearchInjector.ts |
| URL Builder | packages/desktop/app/main/services/capabilities/llm/completion/url-builder.ts |
| Header Builder | packages/desktop/app/main/services/capabilities/llm/completion/header-builder.ts |
| Message Converter | packages/desktop/app/main/services/capabilities/llm/completion/message-converter.ts |
| Provider Presets | packages/desktop/app/shared/provider-presets.ts |
| IPC Routers | packages/desktop/app/main/services/routers/llm/ |
アーキテクチャの全体像
graph TB
subgraph Frontend ["Frontend (Renderer)"]
UI[Provider Settings UI]
ChatUI[Chat Interface]
end
subgraph IPCLayer ["IPC Layer"]
PR[ProviderRouter]
AKR[ApiKeyRouter]
CR[CompletionRouter]
RCR[RouterConfigRouter]
TR[TransformerRouter]
MPR[ModelParametersRouter]
end
subgraph LLMConfigService ["LLMConfigService (Delegate Pattern)"]
PM[ProviderManager]
MDM[ModelDiscoveryManager]
CIOM[ConfigIOManager]
AMM[AgentModelsManager]
end
subgraph CompletionService ["CompletionService (Facade Pattern)"]
DAH[DirectApiHandler]
SH[StreamHandler]
TH[ToolHandler]
THR[TransformerHandler]
TR2[ThinkingResolver]
end
AKPS[ApiKeyPoolService]
subgraph ExternalAPIs ["External APIs"]
OpenAI[OpenAI API]
Anthropic[Anthropic API]
Gemini[Gemini API]
Azure[Azure OpenAI API]
Others[Other Providers...]
end
subgraph Storage ["Storage"]
SQLite[(SQLite)]
JSON[(llms-config.json)]
end
UI --> PR
UI --> AKR
ChatUI --> CR
PR --> PM
AKR --> AKPS
CR --> CompletionService
PM --> SQLite
PM --> JSON
MDM --> SQLite
MDM --> JSON
CompletionService --> AKPS
CompletionService --> LLMConfigService
DAH --> OpenAI
DAH --> Anthropic
DAH --> Gemini
DAH --> Azure
SH --> OpenAI
SH --> Anthropic
SH --> Gemini
SH --> Azure
データ構造
コアの型定義
// API format enum
type ApiFormat = 'openai' | 'anthropic' | 'google' | 'azure-openai' | 'openai-response';
// LLM provider
interface LLMProvider {
id: string; // Unique identifier
name: string; // Display name
apiFormat?: ApiFormat; // API format (preferred field)
chatApiFormat?: ApiFormat; // Legacy API format field
apiType?: string; // Legacy type field
api_base_url?: string; // API base URL
api_key: string; // Single key (legacy)
models: string[]; // Model ID list
modelConfigs?: ModelConfig[]; // Per-model detailed config
modelGroups?: ModelGroup[]; // Model groups
modelsEndpoint?: string; // Model discovery endpoint
enabled: boolean; // Whether enabled
transformer?: TransformerConfig; // Transformer chain config
icon?: string; // Icon
website?: string; // Official website
docsUrl?: string; // Documentation link
defaultSettings?: CompletionSettings; // Default completion parameters
codingPlan?: CodingPlanConfig; // Coding Plan config
isSystem?: boolean; // System built-in provider
presetId?: string; // Preset template ID
createdAt: string;
updatedAt: string;
}
// Completion request options
interface CompletionOptions {
providerId: string; // Provider ID
model: string; // Model ID
messages: SimpleChatMessage[]; // Message list
maxTokens?: number; // Max token count
temperature?: number; // Temperature
stream?: boolean; // Whether streaming
thinkLevel?: ThinkLevel; // Thinking level
nativeSearchAugmentation?: NativeSearchAugmentation; // Native search augmentation
sessionId?: string; // Session ID (for API Key Pool affinity)
}
// API key pool entry
interface ApiKeyEntry {
id: string; // Unique ID
providerId: string; // Owning provider
label?: string; // Display label
apiKey: string; // Key value
enabled: boolean; // Whether enabled
weight: number; // Weight (1-100)
}
データフロー概要
Completion リクエストパイプライン
sequenceDiagram
participant Frontend as フロントエンド
participant CS as CompletionService
participant LLC as LLMConfigService
participant AKP as ApiKeyPoolService
participant Handler as API Handler
participant API as Provider API
Frontend->>CS: complete() / completeStream()
CS->>LLC: resolveRoutedModel(providerId, model)
LLC-->>CS: actualProviderId + actualModel
CS->>LLC: getProvider(actualProviderId)
LLC-->>CS: provider config
CS->>CS: resolveApiKeyForRequest()
Note right of CS: Priority: codingPlan > pool > legacy
CS->>AKP: getKeyForSession(providerId, sessionId)
AKP-->>CS: resolved API key
CS->>CS: resolveApiFormat(provider)
CS->>Handler: callDirectHandler / callStreamHandler
Handler->>API: HTTP request
API-->>Handler: response / SSE stream
Handler-->>CS: CompletionResult
alt 429/529 error
CS->>AKP: reportError(providerId, sessionId, status)
AKP-->>CS: new key
CS->>Handler: retry with new key
end
CS->>AKP: reportSuccess(sessionId)
CS-->>Frontend: result
モジュール境界と責務
| モジュール | 責務 | 担当外 |
|---|---|---|
| CompletionService | リクエストパイプラインのオーケストレーション、フォーマットのディスパッチ、リトライ、Vision フォールバック | プロバイダー CRUD、キーの保存 |
| ApiKeyPoolService | マルチキーの負荷分散、セッションアフィニティ、クールダウンバックオフ | キーの永続化(DB に委譲) |
| LLMConfigService | プロバイダー設定管理、モデルディスカバリー、ルーティング、Transformer チェーン | API 呼び出し |
| ProviderManager | プロバイダー CRUD、テンプレート/プリセットシステム、SQLite 永続化 | モデルディスカバリー、ルーティング設定 |
| ModelDiscoveryManager | モデルリストのディスカバリー、キャッシュ(SQLite + ファイル) | プロバイダー CRUD |
| ConfigIOManager | 設定のインポート/エクスポート、JSON ファイル I/O | データベース操作 |
| AgentModelsManager | ルーティング設定、Transformer 管理、グローバルパラメータ | プロバイダー CRUD |
| ThinkingResolver | max_tokens の解決、思考バジェットの計算 | リクエストの送信 |
| StreamHandler | SSE ストリーム処理(OpenAI/Anthropic/Gemini) | 非ストリーミングリクエスト |
| DirectApiHandler | 非ストリーミング API 呼び出し | ストリーミングリクエスト |
| ToolHandler | Agent ツール呼び出しループ | 通常の Completion |
| TransformerHandler | Transformer チェーン Completion | 直接 API 呼び出し |
IPC 統合テーブル
| IPC チャンネル | 方向 | Router | 説明 |
|---|---|---|---|
llmConfig:getProviders | Renderer -> Main | ProviderRouter | すべてのプロバイダーを取得 |
llmConfig:getProvider | Renderer -> Main | ProviderRouter | 単一プロバイダーを取得 |
llmConfig:addProvider | Renderer -> Main | ProviderRouter | プロバイダーを追加 |
llmConfig:updateProvider | Renderer -> Main | ProviderRouter | プロバイダーを更新 |
llmConfig:deleteProvider | Renderer -> Main | ProviderRouter | プロバイダーを削除 |
llmConfig:toggleProvider | Renderer -> Main | ProviderRouter | プロバイダーを有効/無効化 |
llmConfig:discoverModels | Renderer -> Main | ProviderRouter | モデル一覧をディスカバリー |
llmConfig:getProviderPresets | Renderer -> Main | ProviderRouter | プリセットテンプレートを取得 |
llmConfig:addFromPreset | Renderer -> Main | ProviderRouter | プリセットからプロバイダーを追加 |
llmConfig:exportConfig | Renderer -> Main | ProviderRouter | 設定をエクスポート |
llmConfig:importConfig | Renderer -> Main | ProviderRouter | 設定をインポート |
llmConfig:getApiKeys | Renderer -> Main | ApiKeyRouter | キー一覧を取得 |
llmConfig:addApiKey | Renderer -> Main | ApiKeyRouter | キーを追加 |
llmConfig:updateApiKey | Renderer -> Main | ApiKeyRouter | キーを更新 |
llmConfig:deleteApiKey | Renderer -> Main | ApiKeyRouter | キーを削除 |
llmConfig:toggleApiKey | Renderer -> Main | ApiKeyRouter | キーを有効/無効化 |
拡張ポイント
- 新しい API フォーマットの追加:
url-builder.tsに URL ビルダー関数を追加し、DirectApiHandler.ts/StreamHandler.tsにハンドラー関数を追加して、CompletionServiceの switch に登録する - 新しいプロバイダープリセットの追加:
provider-presets.tsのPROVIDER_PRESETS配列にテンプレートを追加する - 新しい検索設定の追加:
provider-presets.tsのPROVIDER_SEARCH_CONFIGSにエントリを追加する - カスタム Transformer:
AgentModelsManager経由で新しい Transformer チェーンを登録する
関連ファイル
| ファイル | 目的 |
|---|---|
packages/desktop/app/shared/llm-config.ts | LLM 設定の共有型定義 |
packages/desktop/app/shared/completion-types.ts | Completion の型定義 |
packages/desktop/app/shared/thinking-config.ts | 思考設定とバジェット計算 |
packages/desktop/app/shared/provider-presets.ts | プロバイダープリセットテンプレートと検索設定 |
packages/desktop/app/main/services/routers/llm/schemas.ts | IPC リクエストの Zod バリデーションスキーマ |
packages/desktop/app/main/services/capabilities/llm/config-service/schemas.ts | 設定サービス内部の Zod スキーマ |
packages/desktop/app/main/services/infra/utils/sse-parser.ts | SSE ストリーム解析ユーティリティ |
packages/desktop/app/main/workers/db/apiKeys.ts | API キーのデータベース操作 |
packages/desktop/app/main/workers/DbClient.ts | データベースクライアント |
packages/desktop/app/preload/index.ts | Preload API の公開 |