mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-15 02:42:45 +08:00
- Updated embedding_manager.py to include backend parameter in model configuration. - Modified model_manager.py to utilize cache_name for ONNX models. - Refactored hybrid_search.py to improve embedder initialization based on backend type. - Added backend column to vector_store.py for better model configuration management. - Implemented migration for existing database to include backend information. - Enhanced API settings implementation with comprehensive provider and endpoint management. - Introduced LiteLLM integration guide detailing configuration and usage. - Added examples for LiteLLM usage in TypeScript.
442 lines
9.9 KiB
Plaintext
442 lines
9.9 KiB
Plaintext
/**
|
|
* LiteLLM API Config Manager
|
|
* Manages provider credentials, endpoint configurations, and model discovery
|
|
*/
|
|
|
|
import { join } from 'path';
|
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
import { homedir } from 'os';
|
|
|
|
// ===========================
|
|
// Type Definitions
|
|
// ===========================
|
|
|
|
export type ProviderType =
|
|
| 'openai'
|
|
| 'anthropic'
|
|
| 'google'
|
|
| 'cohere'
|
|
| 'azure'
|
|
| 'bedrock'
|
|
| 'vertexai'
|
|
| 'huggingface'
|
|
| 'ollama'
|
|
| 'custom';
|
|
|
|
export interface ProviderCredential {
|
|
id: string;
|
|
name: string;
|
|
type: ProviderType;
|
|
apiKey?: string;
|
|
baseUrl?: string;
|
|
apiVersion?: string;
|
|
region?: string;
|
|
projectId?: string;
|
|
organizationId?: string;
|
|
enabled: boolean;
|
|
metadata?: Record<string, any>;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface EndpointConfig {
|
|
id: string;
|
|
name: string;
|
|
providerId: string;
|
|
model: string;
|
|
alias?: string;
|
|
temperature?: number;
|
|
maxTokens?: number;
|
|
topP?: number;
|
|
enabled: boolean;
|
|
metadata?: Record<string, any>;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface ModelInfo {
|
|
id: string;
|
|
name: string;
|
|
provider: ProviderType;
|
|
contextWindow: number;
|
|
supportsFunctions: boolean;
|
|
supportsStreaming: boolean;
|
|
inputCostPer1k?: number;
|
|
outputCostPer1k?: number;
|
|
}
|
|
|
|
export interface LiteLLMApiConfig {
|
|
version: string;
|
|
providers: ProviderCredential[];
|
|
endpoints: EndpointConfig[];
|
|
}
|
|
|
|
// ===========================
|
|
// Model Definitions
|
|
// ===========================
|
|
|
|
export const PROVIDER_MODELS: Record<ProviderType, ModelInfo[]> = {
|
|
openai: [
|
|
{
|
|
id: 'gpt-4-turbo',
|
|
name: 'GPT-4 Turbo',
|
|
provider: 'openai',
|
|
contextWindow: 128000,
|
|
supportsFunctions: true,
|
|
supportsStreaming: true,
|
|
inputCostPer1k: 0.01,
|
|
outputCostPer1k: 0.03,
|
|
},
|
|
{
|
|
id: 'gpt-4',
|
|
name: 'GPT-4',
|
|
provider: 'openai',
|
|
contextWindow: 8192,
|
|
supportsFunctions: true,
|
|
supportsStreaming: true,
|
|
inputCostPer1k: 0.03,
|
|
outputCostPer1k: 0.06,
|
|
},
|
|
{
|
|
id: 'gpt-3.5-turbo',
|
|
name: 'GPT-3.5 Turbo',
|
|
provider: 'openai',
|
|
contextWindow: 16385,
|
|
supportsFunctions: true,
|
|
supportsStreaming: true,
|
|
inputCostPer1k: 0.0005,
|
|
outputCostPer1k: 0.0015,
|
|
},
|
|
],
|
|
anthropic: [
|
|
{
|
|
id: 'claude-3-opus-20240229',
|
|
name: 'Claude 3 Opus',
|
|
provider: 'anthropic',
|
|
contextWindow: 200000,
|
|
supportsFunctions: true,
|
|
supportsStreaming: true,
|
|
inputCostPer1k: 0.015,
|
|
outputCostPer1k: 0.075,
|
|
},
|
|
{
|
|
id: 'claude-3-sonnet-20240229',
|
|
name: 'Claude 3 Sonnet',
|
|
provider: 'anthropic',
|
|
contextWindow: 200000,
|
|
supportsFunctions: true,
|
|
supportsStreaming: true,
|
|
inputCostPer1k: 0.003,
|
|
outputCostPer1k: 0.015,
|
|
},
|
|
{
|
|
id: 'claude-3-haiku-20240307',
|
|
name: 'Claude 3 Haiku',
|
|
provider: 'anthropic',
|
|
contextWindow: 200000,
|
|
supportsFunctions: true,
|
|
supportsStreaming: true,
|
|
inputCostPer1k: 0.00025,
|
|
outputCostPer1k: 0.00125,
|
|
},
|
|
],
|
|
google: [
|
|
{
|
|
id: 'gemini-pro',
|
|
name: 'Gemini Pro',
|
|
provider: 'google',
|
|
contextWindow: 32768,
|
|
supportsFunctions: true,
|
|
supportsStreaming: true,
|
|
},
|
|
{
|
|
id: 'gemini-pro-vision',
|
|
name: 'Gemini Pro Vision',
|
|
provider: 'google',
|
|
contextWindow: 16384,
|
|
supportsFunctions: false,
|
|
supportsStreaming: true,
|
|
},
|
|
],
|
|
cohere: [
|
|
{
|
|
id: 'command',
|
|
name: 'Command',
|
|
provider: 'cohere',
|
|
contextWindow: 4096,
|
|
supportsFunctions: false,
|
|
supportsStreaming: true,
|
|
},
|
|
{
|
|
id: 'command-light',
|
|
name: 'Command Light',
|
|
provider: 'cohere',
|
|
contextWindow: 4096,
|
|
supportsFunctions: false,
|
|
supportsStreaming: true,
|
|
},
|
|
],
|
|
azure: [],
|
|
bedrock: [],
|
|
vertexai: [],
|
|
huggingface: [],
|
|
ollama: [],
|
|
custom: [],
|
|
};
|
|
|
|
// ===========================
|
|
// Config File Management
|
|
// ===========================
|
|
|
|
const CONFIG_DIR = join(homedir(), '.claude', 'litellm');
|
|
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
|
|
function ensureConfigDir(): void {
|
|
if (!existsSync(CONFIG_DIR)) {
|
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
}
|
|
}
|
|
|
|
function loadConfig(): LiteLLMApiConfig {
|
|
ensureConfigDir();
|
|
|
|
if (!existsSync(CONFIG_FILE)) {
|
|
const defaultConfig: LiteLLMApiConfig = {
|
|
version: '1.0.0',
|
|
providers: [],
|
|
endpoints: [],
|
|
};
|
|
saveConfig(defaultConfig);
|
|
return defaultConfig;
|
|
}
|
|
|
|
try {
|
|
const content = readFileSync(CONFIG_FILE, 'utf-8');
|
|
return JSON.parse(content);
|
|
} catch (err) {
|
|
throw new Error(`Failed to load config: ${(err as Error).message}`);
|
|
}
|
|
}
|
|
|
|
function saveConfig(config: LiteLLMApiConfig): void {
|
|
ensureConfigDir();
|
|
|
|
try {
|
|
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
} catch (err) {
|
|
throw new Error(`Failed to save config: ${(err as Error).message}`);
|
|
}
|
|
}
|
|
|
|
// ===========================
|
|
// Provider Management
|
|
// ===========================
|
|
|
|
export function getAllProviders(): ProviderCredential[] {
|
|
const config = loadConfig();
|
|
return config.providers;
|
|
}
|
|
|
|
export function getProvider(id: string): ProviderCredential | null {
|
|
const config = loadConfig();
|
|
return config.providers.find((p) => p.id === id) || null;
|
|
}
|
|
|
|
export function createProvider(
|
|
data: Omit<ProviderCredential, 'id' | 'createdAt' | 'updatedAt'>
|
|
): ProviderCredential {
|
|
const config = loadConfig();
|
|
|
|
const now = new Date().toISOString();
|
|
const provider: ProviderCredential = {
|
|
...data,
|
|
id: `provider-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
};
|
|
|
|
config.providers.push(provider);
|
|
saveConfig(config);
|
|
|
|
return provider;
|
|
}
|
|
|
|
export function updateProvider(
|
|
id: string,
|
|
updates: Partial<ProviderCredential>
|
|
): ProviderCredential | null {
|
|
const config = loadConfig();
|
|
|
|
const index = config.providers.findIndex((p) => p.id === id);
|
|
if (index === -1) {
|
|
return null;
|
|
}
|
|
|
|
const updated: ProviderCredential = {
|
|
...config.providers[index],
|
|
...updates,
|
|
id,
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
|
|
config.providers[index] = updated;
|
|
saveConfig(config);
|
|
|
|
return updated;
|
|
}
|
|
|
|
export function deleteProvider(id: string): { success: boolean } {
|
|
const config = loadConfig();
|
|
|
|
const index = config.providers.findIndex((p) => p.id === id);
|
|
if (index === -1) {
|
|
return { success: false };
|
|
}
|
|
|
|
config.providers.splice(index, 1);
|
|
|
|
// Also delete endpoints using this provider
|
|
config.endpoints = config.endpoints.filter((e) => e.providerId !== id);
|
|
|
|
saveConfig(config);
|
|
|
|
return { success: true };
|
|
}
|
|
|
|
export async function testProviderConnection(
|
|
providerId: string
|
|
): Promise<{ success: boolean; error?: string }> {
|
|
const provider = getProvider(providerId);
|
|
|
|
if (!provider) {
|
|
return { success: false, error: 'Provider not found' };
|
|
}
|
|
|
|
if (!provider.enabled) {
|
|
return { success: false, error: 'Provider is disabled' };
|
|
}
|
|
|
|
// Basic validation
|
|
if (!provider.apiKey && provider.type !== 'ollama' && provider.type !== 'custom') {
|
|
return { success: false, error: 'API key is required for this provider type' };
|
|
}
|
|
|
|
// TODO: Implement actual provider connection testing using litellm-client
|
|
// For now, just validate the configuration
|
|
return { success: true };
|
|
}
|
|
|
|
// ===========================
|
|
// Endpoint Management
|
|
// ===========================
|
|
|
|
export function getAllEndpoints(): EndpointConfig[] {
|
|
const config = loadConfig();
|
|
return config.endpoints;
|
|
}
|
|
|
|
export function getEndpoint(id: string): EndpointConfig | null {
|
|
const config = loadConfig();
|
|
return config.endpoints.find((e) => e.id === id) || null;
|
|
}
|
|
|
|
export function createEndpoint(
|
|
data: Omit<EndpointConfig, 'id' | 'createdAt' | 'updatedAt'>
|
|
): EndpointConfig {
|
|
const config = loadConfig();
|
|
|
|
// Validate provider exists
|
|
const provider = config.providers.find((p) => p.id === data.providerId);
|
|
if (!provider) {
|
|
throw new Error('Provider not found');
|
|
}
|
|
|
|
const now = new Date().toISOString();
|
|
const endpoint: EndpointConfig = {
|
|
...data,
|
|
id: `endpoint-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
};
|
|
|
|
config.endpoints.push(endpoint);
|
|
saveConfig(config);
|
|
|
|
return endpoint;
|
|
}
|
|
|
|
export function updateEndpoint(
|
|
id: string,
|
|
updates: Partial<EndpointConfig>
|
|
): EndpointConfig | null {
|
|
const config = loadConfig();
|
|
|
|
const index = config.endpoints.findIndex((e) => e.id === id);
|
|
if (index === -1) {
|
|
return null;
|
|
}
|
|
|
|
// Validate provider if being updated
|
|
if (updates.providerId) {
|
|
const provider = config.providers.find((p) => p.id === updates.providerId);
|
|
if (!provider) {
|
|
throw new Error('Provider not found');
|
|
}
|
|
}
|
|
|
|
const updated: EndpointConfig = {
|
|
...config.endpoints[index],
|
|
...updates,
|
|
id,
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
|
|
config.endpoints[index] = updated;
|
|
saveConfig(config);
|
|
|
|
return updated;
|
|
}
|
|
|
|
export function deleteEndpoint(id: string): { success: boolean } {
|
|
const config = loadConfig();
|
|
|
|
const index = config.endpoints.findIndex((e) => e.id === id);
|
|
if (index === -1) {
|
|
return { success: false };
|
|
}
|
|
|
|
config.endpoints.splice(index, 1);
|
|
saveConfig(config);
|
|
|
|
return { success: true };
|
|
}
|
|
|
|
// ===========================
|
|
// Model Discovery
|
|
// ===========================
|
|
|
|
export function getModelsForProviderType(providerType: ProviderType): ModelInfo[] | null {
|
|
return PROVIDER_MODELS[providerType] || null;
|
|
}
|
|
|
|
export function getAllModels(): Record<ProviderType, ModelInfo[]> {
|
|
return PROVIDER_MODELS;
|
|
}
|
|
|
|
// ===========================
|
|
// Config Access
|
|
// ===========================
|
|
|
|
export function getFullConfig(): LiteLLMApiConfig {
|
|
return loadConfig();
|
|
}
|
|
|
|
export function resetConfig(): void {
|
|
const defaultConfig: LiteLLMApiConfig = {
|
|
version: '1.0.0',
|
|
providers: [],
|
|
endpoints: [],
|
|
};
|
|
saveConfig(defaultConfig);
|
|
}
|