LLM Provider Abstraction Factory
Relevant source files
The following files were used as context for generating this wiki page:
The LLM Provider Abstraction Factory is a centralized system within the @repo/llm package designed to provide a vendor-agnostic interface for Large Language Model (LLM) interactions. By abstracting specific SDK implementations (such as OpenAI and Anthropic) behind a unified factory and interface, the project enables "Bring Your Own LLM" (BYO-LLM) capabilities and allows for provider swaps with zero changes to downstream service code.
Sources: packages/llm/README.md:3-10, packages/llm/src/index.ts:3-13
This architecture ensures that services like the AI Review Orchestrator depend solely on the LLMProvider interface rather than concrete classes, adhering to the Dependency Inversion principle. This allows the application to support multiple AI models for tasks such as automated code reviews, comment explanation, and knowledge extraction.
Sources: packages/llm/src/index.ts:13-15, packages/review/src/llm-client.ts:3-10
Architecture and Components
The system is structured into several layers, moving from high-level service requirements down to concrete API implementations.
This diagram illustrates the hierarchical flow from consumer services to specific provider implementations.
Sources: packages/llm/README.md:15-26, packages/llm/src/factory.ts:18-38
The LLMProvider Interface
The LLMProvider interface defines the mandatory contract for every concrete implementation. It ensures Liskov substitutability, meaning callers can interact with any provider without needing to branch logic based on the vendor.
| Method | Purpose |
|---|---|
chat(request) | Executes a single-shot completion returning full text and usage data. |
chatStream(request) | Yields content deltas as an async iterable for real-time responses. |
validate() | Performs a cheap 1-token call to verify API credentials. |
estimateTokens(text) | Provides a budget estimate of tokens for a given string before making a call. |
Sources: packages/llm/src/types.ts:63-88
LLMProviderFactory
The LLMProviderFactory serves as the single point of construction. It uses an exhaustive switch pattern on the LLMProviderKind to instantiate the appropriate class. If a new provider kind is added to the types but not handled in the factory, TypeScript will trigger a compilation error.
static create(config: LLMProviderConfig): LLMProvider {
switch (config.kind) {
case 'openai':
case 'openai_compatible':
case 'azure_openai':
return new OpenAIProvider(config);
case 'anthropic':
return new AnthropicProvider(config);
// ... logic for other kinds
}
}
Sources: packages/llm/src/factory.ts:18-40
Concrete Provider Implementations
Anthropic Provider
The AnthropicProvider wraps the @anthropic-ai/sdk. It handles specific requirements of the Anthropic Messages API, such as separating the system prompt from user turns and requiring a max_tokens value.
- Default Model:
claude-sonnet-4-6 - Token Estimation: Approximately 4 characters per token.
- Stop Reason Mapping: Maps Anthropic's
end_turnormax_tokensto standardizedChatResultfinish reasons.
Sources: packages/llm/src/providers/anthropic.ts:24-34, packages/llm/src/providers/anthropic.ts:114-124
OpenAI and Compatible Providers
The factory utilizes the OpenAIProvider to handle not only standard OpenAI API calls but also Azure OpenAI and "OpenAI-compatible" endpoints (e.g., Groq, Together, Ollama) via baseUrl overrides.
Sources: packages/llm/src/factory.ts:21-25, packages/llm/src/types.ts:101-103
Data Models and Configuration
The factory requires an LLMProviderConfig object to determine which provider to instantiate and how to authenticate it.
| Field | Type | Description |
|---|---|---|
kind | LLMProviderKind | The provider identifier (e.g., 'openai', 'anthropic'). |
apiKey | string | Plaintext API key (decrypted at runtime). |
model | string? | Optional override for the provider's default model. |
baseUrl | string? | Custom endpoint for Azure or self-hosted models. |
organizationId | string? | OpenAI-specific organizational identifier. |
Sources: packages/llm/src/types.ts:106-118
Interaction Flow: AI Review Example
When a review is processed, the ReviewLLMClient uses the factory-created provider to send structured prompts and validate JSON responses.
This diagram shows how the Review package consumes the abstracted LLM interface.
Sources: packages/review/src/llm-client.ts:85-115
Summary
The LLM Provider Abstraction Factory enables the AI Reviewer project to remain flexible and vendor-neutral. By centralizing construction in LLMProviderFactory and enforcing a strict interface via LLMProvider, the system supports a diverse range of models while maintaining high type safety and testability through dependency injection.
Sources: packages/llm/README.md:1-12, packages/llm/src/index.ts:3-15