Перейти к основному содержимому

Обзор модуля LLM Providers

Этот документ описывает общую архитектуру подсистемы LLM provider в Elftia. Подсистема отвечает за управление конфигурациями нескольких provider, пулами API-ключей, обнаружением моделей, маршрутизацией запросов и конвейером вызовов Completion.


Расположение файлов

МодульПуть
CompletionServicepackages/desktop/app/main/services/capabilities/llm/completion/CompletionService.ts
ApiKeyPoolServicepackages/desktop/app/main/services/capabilities/llm/completion/ApiKeyPoolService.ts
LLMConfigServicepackages/desktop/app/main/services/capabilities/llm/config-service/LLMConfigService.ts
ProviderManagerpackages/desktop/app/main/services/capabilities/llm/config-service/ProviderManager.ts
ModelDiscoveryManagerpackages/desktop/app/main/services/capabilities/llm/config-service/ModelDiscoveryManager.ts
ConfigIOManagerpackages/desktop/app/main/services/capabilities/llm/config-service/ConfigIOManager.ts
AgentModelsManagerpackages/desktop/app/main/services/capabilities/llm/config-service/AgentModelsManager.ts
ThinkingResolverpackages/desktop/app/main/services/capabilities/llm/completion/ThinkingResolver.ts
StreamHandlerpackages/desktop/app/main/services/capabilities/llm/completion/StreamHandler.ts
DirectApiHandlerpackages/desktop/app/main/services/capabilities/llm/completion/DirectApiHandler.ts
ToolHandlerpackages/desktop/app/main/services/capabilities/llm/completion/ToolHandler.ts
TransformerHandlerpackages/desktop/app/main/services/capabilities/llm/completion/TransformerHandler.ts
ProviderSearchInjectorpackages/desktop/app/main/services/capabilities/llm/completion/ProviderSearchInjector.ts
NativeSearchInjectorpackages/desktop/app/main/services/capabilities/llm/completion/NativeSearchInjector.ts
URL Builderpackages/desktop/app/main/services/capabilities/llm/completion/url-builder.ts
Header Builderpackages/desktop/app/main/services/capabilities/llm/completion/header-builder.ts
Message Converterpackages/desktop/app/main/services/capabilities/llm/completion/message-converter.ts
Provider Presetspackages/desktop/app/shared/provider-presets.ts
IPC Routerspackages/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 Frontend
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Оркестрация конвейера запросов, диспетчеризация форматов, повторные попытки, fallback для visionProvider CRUD, хранение ключей
ApiKeyPoolServiceБалансировка нагрузки между несколькими ключами, привязка к сессии, cooldown backoffСохранение ключей (делегировано DB)
LLMConfigServiceУправление конфигурацией provider, обнаружение моделей, маршрутизация, цепочка TransformerAPI-вызовы
ProviderManagerProvider CRUD, система шаблонов/пресетов, сохранение в SQLiteОбнаружение моделей, конфигурация маршрутизации
ModelDiscoveryManagerОбнаружение списка моделей, кэширование (SQLite + файл)Provider CRUD
ConfigIOManagerИмпорт/экспорт конфигурации, ввод-вывод JSON-файловОперации с базой данных
AgentModelsManagerКонфигурация маршрутизации, управление Transformer, глобальные параметрыProvider CRUD
ThinkingResolverРазрешение max_tokens, расчет thinking budgetОтправка запросов
StreamHandlerОбработка SSE-потоков (OpenAI/Anthropic/Gemini)Непотоковые запросы
DirectApiHandlerНепотоковые API-вызовыПотоковые запросы
ToolHandlerЦикл вызовов инструментов AgentОбычный Completion
TransformerHandlerCompletion через цепочку TransformerПрямые API-вызовы

Таблица интеграции IPC

IPC-каналНаправлениеRouterОписание
llmConfig:getProvidersRenderer -> MainProviderRouterПолучить всех provider
llmConfig:getProviderRenderer -> MainProviderRouterПолучить одного provider
llmConfig:addProviderRenderer -> MainProviderRouterДобавить provider
llmConfig:updateProviderRenderer -> MainProviderRouterОбновить provider
llmConfig:deleteProviderRenderer -> MainProviderRouterУдалить provider
llmConfig:toggleProviderRenderer -> MainProviderRouterВключить/отключить provider
llmConfig:discoverModelsRenderer -> MainProviderRouterОбнаружить список моделей
llmConfig:getProviderPresetsRenderer -> MainProviderRouterПолучить шаблоны пресетов
llmConfig:addFromPresetRenderer -> MainProviderRouterДобавить provider из пресета
llmConfig:exportConfigRenderer -> MainProviderRouterЭкспортировать конфигурацию
llmConfig:importConfigRenderer -> MainProviderRouterИмпортировать конфигурацию
llmConfig:getApiKeysRenderer -> MainApiKeyRouterПолучить список ключей
llmConfig:addApiKeyRenderer -> MainApiKeyRouterДобавить ключ
llmConfig:updateApiKeyRenderer -> MainApiKeyRouterОбновить ключ
llmConfig:deleteApiKeyRenderer -> MainApiKeyRouterУдалить ключ
llmConfig:toggleApiKeyRenderer -> MainApiKeyRouterВключить/отключить ключ

Точки расширения

  • Добавление нового API-формата: добавьте функцию построения URL в url-builder.ts, добавьте функции-обработчики в DirectApiHandler.ts / StreamHandler.ts и зарегистрируйте их в switch в CompletionService
  • Добавление нового пресета provider: добавьте шаблон в массив PROVIDER_PRESETS в provider-presets.ts
  • Добавление новой поисковой конфигурации: добавьте запись в PROVIDER_SEARCH_CONFIGS в provider-presets.ts
  • Пользовательский Transformer: зарегистрируйте новую цепочку Transformer через AgentModelsManager

Связанные файлы

ФайлНазначение
packages/desktop/app/shared/llm-config.tsОбщие определения типов конфигурации LLM
packages/desktop/app/shared/completion-types.tsОпределения типов Completion
packages/desktop/app/shared/thinking-config.tsКонфигурация thinking и расчет budget
packages/desktop/app/shared/provider-presets.tsШаблоны пресетов provider и поисковые конфигурации
packages/desktop/app/main/services/routers/llm/schemas.tsZod schemas для валидации IPC-запросов
packages/desktop/app/main/services/capabilities/llm/config-service/schemas.tsВнутренние Zod schemas сервиса конфигурации
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