feat: Add OpenRouter as LLM/embedding provider (#162)

* feat: Add OpenRouter as LLM/embedding provider

Add OpenRouter provider support for Graphiti memory integration,
enabling access to multiple LLM providers through a single API.

Changes:
Backend:
- Created openrouter_llm.py: OpenRouter LLM provider using OpenAI-compatible API
- Created openrouter_embedder.py: OpenRouter embedder provider
- Updated config.py: Added OpenRouter to provider enums and configuration
  - New fields: openrouter_api_key, openrouter_base_url, openrouter_llm_model, openrouter_embedding_model
  - Validation methods updated for OpenRouter
- Updated factory.py: Added OpenRouter to LLM and embedder factories
- Updated provider __init__.py files: Exported new OpenRouter functions

Frontend:
- Updated project.ts types: Added 'openrouter' to provider type unions
  - GraphitiProviderConfig extended with OpenRouter fields
- Updated GraphitiStep.tsx: Added OpenRouter to provider arrays
  - LLM_PROVIDERS: 'Multi-provider aggregator'
  - EMBEDDING_PROVIDERS: 'OpenAI-compatible embeddings'
  - Added OpenRouter API key input field with show/hide toggle
  - Link to https://openrouter.ai/keys
- Updated env-handlers.ts: OpenRouter .env generation and parsing
  - Template generation for OPENROUTER_* variables
  - Parsing from .env files with proper type casting

Documentation:
- Updated .env.example with OpenRouter section
  - Configuration examples
  - Popular model recommendations
  - Example configuration (#6)

Fixes #92

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* refactor: address CodeRabbit review comments for OpenRouter

- Add globalOpenRouterApiKey to settings types and store updates
- Initialize openrouterApiKey from global settings
- Update documentation to include OpenRouter in provider lists
- Add OpenRouter handling to get_embedding_dimension() method
- Add openrouter to provider cleanup list
- Add OpenRouter to get_available_providers() function
- Clarify Legacy comment for openrouterLlmModel

These changes complete the OpenRouter integration by ensuring proper
settings persistence and provider detection across the application.

* fix: apply ruff formatting to OpenRouter code

- Break long error message across multiple lines
- Format provider list with one item per line
- Fixes lint CI failure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Fernando Possebon
2025-12-23 13:58:55 -03:00
committed by GitHub
parent f168bdc3ac
commit 02bef954f3
10 changed files with 289 additions and 10 deletions
+32 -2
View File
@@ -153,10 +153,10 @@ GRAPHITI_ENABLED=true
# Choose which providers to use for LLM and embeddings.
# Default is "openai" for both.
# LLM provider: openai | anthropic | azure_openai | ollama | google
# LLM provider: openai | anthropic | azure_openai | ollama | google | openrouter
# GRAPHITI_LLM_PROVIDER=openai
# Embedder provider: openai | voyage | azure_openai | ollama | google
# Embedder provider: openai | voyage | azure_openai | ollama | google | openrouter
# GRAPHITI_EMBEDDER_PROVIDER=openai
# =============================================================================
@@ -221,6 +221,28 @@ GRAPHITI_ENABLED=true
# Google Embedding Model (default: text-embedding-004)
# GOOGLE_EMBEDDING_MODEL=text-embedding-004
# =============================================================================
# GRAPHITI: OpenRouter Provider (Multi-provider aggregator)
# =============================================================================
# Use OpenRouter to access multiple LLM providers through a single API.
# OpenRouter provides access to Anthropic, OpenAI, Google, and many other models.
# Get API key from: https://openrouter.ai/keys
#
# Required: OPENROUTER_API_KEY
# OpenRouter API Key
# OPENROUTER_API_KEY=sk-or-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# OpenRouter Base URL (default: https://openrouter.ai/api/v1)
# OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
# OpenRouter LLM Model (default: anthropic/claude-3.5-sonnet)
# Popular choices: anthropic/claude-3.5-sonnet, openai/gpt-4o, google/gemini-2.0-flash
# OPENROUTER_LLM_MODEL=anthropic/claude-3.5-sonnet
# OpenRouter Embedding Model (default: openai/text-embedding-3-small)
# OPENROUTER_EMBEDDING_MODEL=openai/text-embedding-3-small
# =============================================================================
# GRAPHITI: Azure OpenAI Provider
# =============================================================================
@@ -307,3 +329,11 @@ GRAPHITI_ENABLED=true
# GRAPHITI_LLM_PROVIDER=google
# GRAPHITI_EMBEDDER_PROVIDER=google
# GOOGLE_API_KEY=AIzaSyxxxxxxxx
#
# --- Example 6: OpenRouter (multi-provider aggregator) ---
# GRAPHITI_ENABLED=true
# GRAPHITI_LLM_PROVIDER=openrouter
# GRAPHITI_EMBEDDER_PROVIDER=openrouter
# OPENROUTER_API_KEY=sk-or-xxxxxxxx
# OPENROUTER_LLM_MODEL=anthropic/claude-3.5-sonnet
# OPENROUTER_EMBEDDING_MODEL=openai/text-embedding-3-small
+58 -3
View File
@@ -8,8 +8,8 @@ Follows the same patterns as linear_config.py for consistency.
Uses LadybugDB as the embedded graph database (no Docker required, requires Python 3.12+).
Multi-Provider Support (V2):
- LLM Providers: OpenAI, Anthropic, Azure OpenAI, Ollama, Google AI
- Embedder Providers: OpenAI, Voyage AI, Azure OpenAI, Ollama, Google AI
- LLM Providers: OpenAI, Anthropic, Azure OpenAI, Ollama, Google AI, OpenRouter
- Embedder Providers: OpenAI, Voyage AI, Azure OpenAI, Ollama, Google AI, OpenRouter
Environment Variables:
# Core
@@ -89,6 +89,7 @@ class LLMProvider(str, Enum):
AZURE_OPENAI = "azure_openai"
OLLAMA = "ollama"
GOOGLE = "google"
OPENROUTER = "openrouter"
class EmbedderProvider(str, Enum):
@@ -99,6 +100,7 @@ class EmbedderProvider(str, Enum):
AZURE_OPENAI = "azure_openai"
OLLAMA = "ollama"
GOOGLE = "google"
OPENROUTER = "openrouter"
@dataclass
@@ -141,6 +143,12 @@ class GraphitiConfig:
google_llm_model: str = "gemini-2.0-flash"
google_embedding_model: str = "text-embedding-004"
# OpenRouter settings (multi-provider aggregator)
openrouter_api_key: str = ""
openrouter_base_url: str = "https://openrouter.ai/api/v1"
openrouter_llm_model: str = "anthropic/claude-3.5-sonnet"
openrouter_embedding_model: str = "openai/text-embedding-3-small"
# Ollama settings (local)
ollama_base_url: str = DEFAULT_OLLAMA_BASE_URL
ollama_llm_model: str = ""
@@ -196,6 +204,18 @@ class GraphitiConfig:
"GOOGLE_EMBEDDING_MODEL", "text-embedding-004"
)
# OpenRouter settings
openrouter_api_key = os.environ.get("OPENROUTER_API_KEY", "")
openrouter_base_url = os.environ.get(
"OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1"
)
openrouter_llm_model = os.environ.get(
"OPENROUTER_LLM_MODEL", "anthropic/claude-3.5-sonnet"
)
openrouter_embedding_model = os.environ.get(
"OPENROUTER_EMBEDDING_MODEL", "openai/text-embedding-3-small"
)
# Ollama settings
ollama_base_url = os.environ.get("OLLAMA_BASE_URL", DEFAULT_OLLAMA_BASE_URL)
ollama_llm_model = os.environ.get("OLLAMA_LLM_MODEL", "")
@@ -227,6 +247,10 @@ class GraphitiConfig:
google_api_key=google_api_key,
google_llm_model=google_llm_model,
google_embedding_model=google_embedding_model,
openrouter_api_key=openrouter_api_key,
openrouter_base_url=openrouter_base_url,
openrouter_llm_model=openrouter_llm_model,
openrouter_embedding_model=openrouter_embedding_model,
ollama_base_url=ollama_base_url,
ollama_llm_model=ollama_llm_model,
ollama_embedding_model=ollama_embedding_model,
@@ -267,6 +291,8 @@ class GraphitiConfig:
return bool(self.ollama_embedding_model)
elif self.embedder_provider == "google":
return bool(self.google_api_key)
elif self.embedder_provider == "openrouter":
return bool(self.openrouter_api_key)
return False
def get_validation_errors(self) -> list[str]:
@@ -309,6 +335,11 @@ class GraphitiConfig:
elif self.embedder_provider == "google":
if not self.google_api_key:
errors.append("Google embedder provider requires GOOGLE_API_KEY")
elif self.embedder_provider == "openrouter":
if not self.openrouter_api_key:
errors.append(
"OpenRouter embedder provider requires OPENROUTER_API_KEY"
)
else:
errors.append(f"Unknown embedder provider: {self.embedder_provider}")
@@ -367,6 +398,18 @@ class GraphitiConfig:
elif self.embedder_provider == "azure_openai":
# Depends on the deployment, default to 1536
return 1536
elif self.embedder_provider == "openrouter":
# OpenRouter uses provider/model format
# Extract underlying provider to determine dimension
model = self.openrouter_embedding_model.lower()
if model.startswith("openai/"):
return 1536 # OpenAI text-embedding-3-small
elif model.startswith("voyage/"):
return 1024 # Voyage-3
elif model.startswith("google/"):
return 768 # Google text-embedding-004
# Add more providers as needed
return 1536 # Default for unknown OpenRouter models
return 768 # Safe default
def get_provider_signature(self) -> str:
@@ -403,7 +446,14 @@ class GraphitiConfig:
base_name = self.database
# Remove existing provider suffix if present
for provider in ["openai", "ollama", "voyage", "google", "azure_openai"]:
for provider in [
"openai",
"ollama",
"voyage",
"google",
"azure_openai",
"openrouter",
]:
if f"_{provider}_" in base_name:
base_name = base_name.split(f"_{provider}_")[0]
break
@@ -617,6 +667,11 @@ def get_available_providers() -> dict:
available_llm.append("google")
available_embedder.append("google")
# Check OpenRouter
if config.openrouter_api_key:
available_llm.append("openrouter")
available_embedder.append("openrouter")
# Check Ollama
if config.ollama_llm_model:
available_llm.append("ollama")
@@ -18,6 +18,7 @@ from .ollama_embedder import (
get_embedding_dim_for_model,
)
from .openai_embedder import create_openai_embedder
from .openrouter_embedder import create_openrouter_embedder
from .voyage_embedder import create_voyage_embedder
__all__ = [
@@ -26,6 +27,7 @@ __all__ = [
"create_azure_openai_embedder",
"create_ollama_embedder",
"create_google_embedder",
"create_openrouter_embedder",
"KNOWN_OLLAMA_EMBEDDING_MODELS",
"get_embedding_dim_for_model",
]
@@ -0,0 +1,60 @@
"""
OpenRouter Embedder Provider
=============================
OpenRouter embedder implementation for Graphiti.
Uses OpenAI-compatible embedding API.
"""
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from ...config import GraphitiConfig
from ..exceptions import ProviderError, ProviderNotInstalled
def create_openrouter_embedder(config: "GraphitiConfig") -> Any:
"""
Create OpenRouter embedder client.
OpenRouter uses OpenAI-compatible API, so we use the OpenAI embedder
with custom base URL.
Args:
config: GraphitiConfig with OpenRouter settings
Returns:
OpenAI-compatible embedder instance
Raises:
ProviderNotInstalled: If graphiti-core is not installed
ProviderError: If API key is missing
Example:
>>> from auto_claude.integrations.graphiti.config import GraphitiConfig
>>> config = GraphitiConfig(
... openrouter_api_key="sk-or-...",
... openrouter_embedding_model="openai/text-embedding-3-small"
... )
>>> embedder = create_openrouter_embedder(config)
"""
try:
from graphiti_core.embedder import EmbedderConfig, OpenAIEmbedder
except ImportError as e:
raise ProviderNotInstalled(
f"OpenRouter provider requires graphiti-core. "
f"Install with: pip install graphiti-core\n"
f"Error: {e}"
)
if not config.openrouter_api_key:
raise ProviderError("OpenRouter provider requires OPENROUTER_API_KEY")
embedder_config = EmbedderConfig(
api_key=config.openrouter_api_key,
model=config.openrouter_embedding_model,
base_url=config.openrouter_base_url,
)
return OpenAIEmbedder(config=embedder_config)
@@ -16,6 +16,7 @@ from .embedder_providers import (
create_google_embedder,
create_ollama_embedder,
create_openai_embedder,
create_openrouter_embedder,
create_voyage_embedder,
)
from .exceptions import ProviderError
@@ -25,6 +26,7 @@ from .llm_providers import (
create_google_llm_client,
create_ollama_llm_client,
create_openai_llm_client,
create_openrouter_llm_client,
)
logger = logging.getLogger(__name__)
@@ -58,6 +60,8 @@ def create_llm_client(config: "GraphitiConfig") -> Any:
return create_ollama_llm_client(config)
elif provider == "google":
return create_google_llm_client(config)
elif provider == "openrouter":
return create_openrouter_llm_client(config)
else:
raise ProviderError(f"Unknown LLM provider: {provider}")
@@ -90,5 +94,7 @@ def create_embedder(config: "GraphitiConfig") -> Any:
return create_ollama_embedder(config)
elif provider == "google":
return create_google_embedder(config)
elif provider == "openrouter":
return create_openrouter_embedder(config)
else:
raise ProviderError(f"Unknown embedder provider: {provider}")
@@ -15,6 +15,7 @@ from .azure_openai_llm import create_azure_openai_llm_client
from .google_llm import create_google_llm_client
from .ollama_llm import create_ollama_llm_client
from .openai_llm import create_openai_llm_client
from .openrouter_llm import create_openrouter_llm_client
__all__ = [
"create_openai_llm_client",
@@ -22,4 +23,5 @@ __all__ = [
"create_azure_openai_llm_client",
"create_ollama_llm_client",
"create_google_llm_client",
"create_openrouter_llm_client",
]
@@ -0,0 +1,63 @@
"""
OpenRouter LLM Provider
=======================
OpenRouter LLM client implementation for Graphiti.
Uses OpenAI-compatible API.
"""
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from ...config import GraphitiConfig
from ..exceptions import ProviderError, ProviderNotInstalled
def create_openrouter_llm_client(config: "GraphitiConfig") -> Any:
"""
Create OpenRouter LLM client.
OpenRouter uses OpenAI-compatible API, so we use the OpenAI client
with custom base URL.
Args:
config: GraphitiConfig with OpenRouter settings
Returns:
OpenAI-compatible LLM client instance
Raises:
ProviderNotInstalled: If graphiti-core is not installed
ProviderError: If API key is missing
Example:
>>> from auto_claude.integrations.graphiti.config import GraphitiConfig
>>> config = GraphitiConfig(
... openrouter_api_key="sk-or-...",
... openrouter_llm_model="anthropic/claude-3.5-sonnet"
... )
>>> client = create_openrouter_llm_client(config)
"""
try:
from graphiti_core.llm_client.config import LLMConfig
from graphiti_core.llm_client.openai_client import OpenAIClient
except ImportError as e:
raise ProviderNotInstalled(
f"OpenRouter provider requires graphiti-core. "
f"Install with: pip install graphiti-core\n"
f"Error: {e}"
)
if not config.openrouter_api_key:
raise ProviderError("OpenRouter provider requires OPENROUTER_API_KEY")
llm_config = LLMConfig(
api_key=config.openrouter_api_key,
model=config.openrouter_llm_model,
base_url=config.openrouter_base_url,
)
# OpenRouter uses OpenAI-compatible API
# Disable reasoning/verbosity for compatibility
return OpenAIClient(config=llm_config, reasoning=None, verbosity=None)
@@ -44,6 +44,7 @@ const LLM_PROVIDERS: Array<{
{ id: 'anthropic', name: 'Anthropic', description: 'Claude models', requiresApiKey: true },
{ id: 'google', name: 'Google AI', description: 'Gemini models', requiresApiKey: true },
{ id: 'groq', name: 'Groq', description: 'Llama models (fast inference)', requiresApiKey: true },
{ id: 'openrouter', name: 'OpenRouter', description: 'Multi-provider aggregator', requiresApiKey: true },
{ id: 'azure_openai', name: 'Azure OpenAI', description: 'Enterprise Azure deployment', requiresApiKey: true },
{ id: 'ollama', name: 'Ollama', description: 'Local models (free)', requiresApiKey: false }
];
@@ -58,6 +59,7 @@ const EMBEDDING_PROVIDERS: Array<{
{ id: 'openai', name: 'OpenAI', description: 'text-embedding-3-small (recommended)', requiresApiKey: true },
{ id: 'voyage', name: 'Voyage AI', description: 'voyage-3 (great with Anthropic)', requiresApiKey: true },
{ id: 'google', name: 'Google AI', description: 'Gemini text-embedding-004', requiresApiKey: true },
{ id: 'openrouter', name: 'OpenRouter', description: 'OpenAI-compatible embeddings', requiresApiKey: true },
{ id: 'azure_openai', name: 'Azure OpenAI', description: 'Enterprise Azure embeddings', requiresApiKey: true }
];
@@ -82,6 +84,11 @@ interface GraphitiConfig {
googleApiKey: string;
// Groq
groqApiKey: string;
// OpenRouter
openrouterApiKey: string;
openrouterBaseUrl: string;
openrouterLlmModel: string;
openrouterEmbeddingModel: string;
// HuggingFace
huggingfaceApiKey: string;
// Ollama
@@ -118,6 +125,10 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
voyageApiKey: '',
googleApiKey: settings.globalGoogleApiKey || '',
groqApiKey: settings.globalGroqApiKey || '',
openrouterApiKey: settings.globalOpenRouterApiKey || '',
openrouterBaseUrl: 'https://openrouter.ai/api/v1',
openrouterLlmModel: 'anthropic/claude-3.5-sonnet',
openrouterEmbeddingModel: 'openai/text-embedding-3-small',
huggingfaceApiKey: '',
ollamaBaseUrl: settings.ollamaBaseUrl || 'http://localhost:11434',
ollamaLlmModel: '',
@@ -194,6 +205,9 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
if (llmProvider === 'groq') {
if (!config.groqApiKey.trim()) return 'Groq API key';
}
if (llmProvider === 'openrouter' || embeddingProvider === 'openrouter') {
if (!config.openrouterApiKey.trim()) return 'OpenRouter API key';
}
if (llmProvider === 'ollama') {
if (!config.ollamaLlmModel.trim()) return 'Ollama LLM model name';
}
@@ -221,9 +235,11 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
config.llmProvider === 'anthropic' ? config.anthropicApiKey :
config.llmProvider === 'google' ? config.googleApiKey :
config.llmProvider === 'groq' ? config.groqApiKey :
config.llmProvider === 'openrouter' ? config.openrouterApiKey :
config.llmProvider === 'azure_openai' ? config.azureOpenaiApiKey :
config.llmProvider === 'ollama' ? '' : // Ollama doesn't need API key
config.embeddingProvider === 'openai' ? config.openaiApiKey : '';
config.embeddingProvider === 'openai' ? config.openaiApiKey :
config.embeddingProvider === 'openrouter' ? config.openrouterApiKey : '';
const result = await window.electronAPI.testGraphitiConnection({
dbPath: config.dbPath || undefined,
@@ -303,6 +319,9 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
if (config.groqApiKey.trim()) {
settingsToSave.globalGroqApiKey = config.groqApiKey.trim();
}
if (config.openrouterApiKey.trim()) {
settingsToSave.globalOpenRouterApiKey = config.openrouterApiKey.trim();
}
if (config.ollamaBaseUrl.trim()) {
settingsToSave.ollamaBaseUrl = config.ollamaBaseUrl.trim();
}
@@ -311,11 +330,12 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
if (result?.success) {
// Update local settings store with API key settings
const storeUpdate: Partial<Pick<AppSettings, 'globalOpenAIApiKey' | 'globalAnthropicApiKey' | 'globalGoogleApiKey' | 'globalGroqApiKey' | 'ollamaBaseUrl'>> = {};
const storeUpdate: Partial<Pick<AppSettings, 'globalOpenAIApiKey' | 'globalAnthropicApiKey' | 'globalGoogleApiKey' | 'globalGroqApiKey' | 'globalOpenRouterApiKey' | 'ollamaBaseUrl'>> = {};
if (config.openaiApiKey.trim()) storeUpdate.globalOpenAIApiKey = config.openaiApiKey.trim();
if (config.anthropicApiKey.trim()) storeUpdate.globalAnthropicApiKey = config.anthropicApiKey.trim();
if (config.googleApiKey.trim()) storeUpdate.globalGoogleApiKey = config.googleApiKey.trim();
if (config.groqApiKey.trim()) storeUpdate.globalGroqApiKey = config.groqApiKey.trim();
if (config.openrouterApiKey.trim()) storeUpdate.globalOpenRouterApiKey = config.openrouterApiKey.trim();
if (config.ollamaBaseUrl.trim()) storeUpdate.ollamaBaseUrl = config.ollamaBaseUrl.trim();
updateSettings(storeUpdate);
onNext();
@@ -355,6 +375,7 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
const needsVoyage = embeddingProvider === 'voyage';
const needsGoogle = llmProvider === 'google' || embeddingProvider === 'google';
const needsGroq = llmProvider === 'groq';
const needsOpenRouter = llmProvider === 'openrouter' || embeddingProvider === 'openrouter';
const needsOllama = llmProvider === 'ollama' || embeddingProvider === 'ollama';
return (
@@ -606,6 +627,39 @@ export function GraphitiStep({ onNext, onBack, onSkip }: GraphitiStepProps) {
</div>
)}
{/* OpenRouter API Key */}
{needsOpenRouter && (
<div className="space-y-2">
<Label htmlFor="openrouter-key" className="text-sm font-medium text-foreground">
OpenRouter API Key
</Label>
<div className="relative">
<Input
id="openrouter-key"
type={showApiKey['openrouter'] ? 'text' : 'password'}
value={config.openrouterApiKey}
onChange={(e) => setConfig(prev => ({ ...prev, openrouterApiKey: e.target.value }))}
placeholder="sk-or-..."
className="pr-10 font-mono text-sm"
disabled={isSaving || isValidating}
/>
<button
type="button"
onClick={() => toggleShowApiKey('openrouter')}
className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
>
{showApiKey['openrouter'] ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
</button>
</div>
<p className="text-xs text-muted-foreground">
Get your key from{' '}
<a href="https://openrouter.ai/keys" target="_blank" rel="noopener noreferrer" className="text-primary hover:text-primary/80">
OpenRouter Dashboard
</a>
</p>
</div>
)}
{/* Ollama Settings */}
{needsOllama && (
<div className="space-y-3 p-3 rounded-md bg-muted/50">
+9 -3
View File
@@ -176,12 +176,12 @@ export interface GraphitiConnectionTestResult {
}
// Memory Provider Types
// Embedding Providers: OpenAI, Voyage AI, Azure OpenAI, Ollama (local), Google
// Embedding Providers: OpenAI, Voyage AI, Azure OpenAI, Ollama (local), Google, OpenRouter
// Note: LLM provider removed - Claude SDK handles RAG queries
export type GraphitiEmbeddingProvider = 'openai' | 'voyage' | 'azure_openai' | 'ollama' | 'google';
export type GraphitiEmbeddingProvider = 'openai' | 'voyage' | 'azure_openai' | 'ollama' | 'google' | 'openrouter';
// Legacy type aliases for backward compatibility
export type GraphitiLLMProvider = 'openai' | 'anthropic' | 'azure_openai' | 'ollama' | 'google' | 'groq';
export type GraphitiLLMProvider = 'openai' | 'anthropic' | 'azure_openai' | 'ollama' | 'google' | 'groq' | 'openrouter';
export type GraphitiProviderType = GraphitiLLMProvider;
export interface GraphitiProviderConfig {
@@ -206,6 +206,12 @@ export interface GraphitiProviderConfig {
googleApiKey?: string;
googleEmbeddingModel?: string;
// OpenRouter (multi-provider aggregator)
openrouterApiKey?: string;
openrouterBaseUrl?: string; // Default: https://openrouter.ai/api/v1
openrouterLlmModel?: string; // LLM model selection (e.g., 'anthropic/claude-3.5-sonnet')
openrouterEmbeddingModel?: string;
// Ollama Embeddings (local, no API key required)
ollamaBaseUrl?: string; // Default: http://localhost:11434
ollamaEmbeddingModel?: string;
@@ -89,6 +89,7 @@ export interface AppSettings {
globalAnthropicApiKey?: string;
globalGoogleApiKey?: string;
globalGroqApiKey?: string;
globalOpenRouterApiKey?: string;
// Graphiti LLM provider settings
graphitiLlmProvider?: 'openai' | 'anthropic' | 'google' | 'groq' | 'ollama';
ollamaBaseUrl?: string;