data fixes, partial custom indicator support
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
||||
import { ChatAnthropic } from '@langchain/anthropic';
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
import type { FastifyBaseLogger } from 'fastify';
|
||||
import { type ModelMiddleware, NoopMiddleware, AnthropicCachingMiddleware } from './middleware.js';
|
||||
|
||||
@@ -10,7 +10,7 @@ export { NoopMiddleware, AnthropicCachingMiddleware };
|
||||
* Supported LLM providers
|
||||
*/
|
||||
export enum LLMProvider {
|
||||
ANTHROPIC = 'anthropic',
|
||||
DEEP_INFRA = 'deepinfra',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,11 +47,13 @@ export interface LicenseModelsConfig {
|
||||
* Provider configuration with API keys
|
||||
*/
|
||||
export interface ProviderConfig {
|
||||
anthropicApiKey?: string;
|
||||
deepinfraApiKey?: string;
|
||||
defaultModel?: ModelConfig;
|
||||
licenseModels?: LicenseModelsConfig;
|
||||
}
|
||||
|
||||
const DEEP_INFRA_BASE_URL = 'https://api.deepinfra.com/v1/openai';
|
||||
|
||||
/**
|
||||
* LLM Provider factory
|
||||
* Creates model instances with unified interface across providers
|
||||
@@ -75,8 +77,8 @@ export class LLMProviderFactory {
|
||||
);
|
||||
|
||||
switch (modelConfig.provider) {
|
||||
case LLMProvider.ANTHROPIC:
|
||||
return this.createAnthropicModel(modelConfig);
|
||||
case LLMProvider.DEEP_INFRA:
|
||||
return this.createDeepInfraModel(modelConfig);
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported provider: ${modelConfig.provider}`);
|
||||
@@ -84,22 +86,24 @@ export class LLMProviderFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Anthropic Claude model
|
||||
* Create Deep Infra model via OpenAI-compatible API
|
||||
*/
|
||||
private createAnthropicModel(config: ModelConfig): { model: ChatAnthropic; middleware: AnthropicCachingMiddleware } {
|
||||
if (!this.config.anthropicApiKey) {
|
||||
throw new Error('Anthropic API key not configured');
|
||||
private createDeepInfraModel(config: ModelConfig): { model: ChatOpenAI; middleware: NoopMiddleware } {
|
||||
if (!this.config.deepinfraApiKey) {
|
||||
throw new Error('Deep Infra API key not configured');
|
||||
}
|
||||
|
||||
const model = new ChatAnthropic({
|
||||
const model = new ChatOpenAI({
|
||||
model: config.model,
|
||||
temperature: config.temperature ?? 0.7,
|
||||
maxTokens: config.maxTokens ?? 4096,
|
||||
anthropicApiKey: this.config.anthropicApiKey,
|
||||
clientOptions: { defaultHeaders: { 'anthropic-beta': 'prompt-caching-2024-07-31' } },
|
||||
apiKey: this.config.deepinfraApiKey,
|
||||
configuration: {
|
||||
baseURL: DEEP_INFRA_BASE_URL,
|
||||
},
|
||||
});
|
||||
|
||||
return { model, middleware: new AnthropicCachingMiddleware() };
|
||||
return { model, middleware: new NoopMiddleware() };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,13 +114,13 @@ export class LLMProviderFactory {
|
||||
return this.config.defaultModel;
|
||||
}
|
||||
|
||||
if (!this.config.anthropicApiKey) {
|
||||
throw new Error('Anthropic API key not configured');
|
||||
if (!this.config.deepinfraApiKey) {
|
||||
throw new Error('Deep Infra API key not configured');
|
||||
}
|
||||
|
||||
return {
|
||||
provider: LLMProvider.ANTHROPIC,
|
||||
model: 'claude-sonnet-4-6',
|
||||
provider: LLMProvider.DEEP_INFRA,
|
||||
model: 'zai-org/GLM-5',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -132,16 +136,12 @@ export class LLMProviderFactory {
|
||||
* Predefined model configurations
|
||||
*/
|
||||
export const MODELS = {
|
||||
CLAUDE_SONNET: {
|
||||
provider: LLMProvider.ANTHROPIC,
|
||||
model: 'claude-sonnet-4-6',
|
||||
GLM_5: {
|
||||
provider: LLMProvider.DEEP_INFRA,
|
||||
model: 'zai-org/GLM-5',
|
||||
},
|
||||
CLAUDE_HAIKU: {
|
||||
provider: LLMProvider.ANTHROPIC,
|
||||
model: 'claude-haiku-4-5-20251001',
|
||||
},
|
||||
CLAUDE_OPUS: {
|
||||
provider: LLMProvider.ANTHROPIC,
|
||||
model: 'claude-opus-4-6',
|
||||
QWEN_235B: {
|
||||
provider: LLMProvider.DEEP_INFRA,
|
||||
model: 'Qwen/Qwen3-235B-A22B-Instruct-2507',
|
||||
},
|
||||
} as const satisfies Record<string, ModelConfig>;
|
||||
|
||||
@@ -113,17 +113,17 @@ export class ModelRouter {
|
||||
// Fallback to hardcoded defaults
|
||||
if (license.licenseType === 'enterprise') {
|
||||
return isComplex
|
||||
? { provider: LLMProvider.ANTHROPIC, model: 'claude-opus-4-6' }
|
||||
: { provider: LLMProvider.ANTHROPIC, model: 'claude-sonnet-4-6' };
|
||||
? { provider: LLMProvider.DEEP_INFRA, model: 'Qwen/Qwen3-235B-A22B-Instruct-2507' }
|
||||
: { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' };
|
||||
}
|
||||
|
||||
if (license.licenseType === 'pro') {
|
||||
return isComplex
|
||||
? { provider: LLMProvider.ANTHROPIC, model: 'claude-sonnet-4-6' }
|
||||
: { provider: LLMProvider.ANTHROPIC, model: 'claude-haiku-4-5-20251001' };
|
||||
? { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' }
|
||||
: { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' };
|
||||
}
|
||||
|
||||
return { provider: LLMProvider.ANTHROPIC, model: 'claude-haiku-4-5-20251001' };
|
||||
return { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,13 +141,13 @@ export class ModelRouter {
|
||||
// Fallback to hardcoded defaults
|
||||
switch (license.licenseType) {
|
||||
case 'enterprise':
|
||||
return { provider: LLMProvider.ANTHROPIC, model: 'claude-sonnet-4-6' };
|
||||
return { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' };
|
||||
|
||||
case 'pro':
|
||||
return { provider: LLMProvider.ANTHROPIC, model: 'claude-sonnet-4-6' };
|
||||
return { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' };
|
||||
|
||||
case 'free':
|
||||
return { provider: LLMProvider.ANTHROPIC, model: 'claude-haiku-4-5-20251001' };
|
||||
return { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' };
|
||||
|
||||
default:
|
||||
return this.defaultModel;
|
||||
@@ -166,8 +166,8 @@ export class ModelRouter {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: use Haiku for cost efficiency
|
||||
return { provider: LLMProvider.ANTHROPIC, model: 'claude-haiku-4-5-20251001' };
|
||||
// Fallback: use GLM-5
|
||||
return { provider: LLMProvider.DEEP_INFRA, model: 'zai-org/GLM-5' };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,12 +195,12 @@ export class ModelRouter {
|
||||
|
||||
// Fallback to hardcoded defaults
|
||||
if (license.licenseType === 'free') {
|
||||
const allowedModels = ['claude-haiku-4-5-20251001'];
|
||||
const allowedModels = ['zai-org/GLM-5'];
|
||||
return allowedModels.includes(model.model);
|
||||
}
|
||||
|
||||
if (license.licenseType === 'pro') {
|
||||
const blockedModels = ['claude-opus-4-6'];
|
||||
const blockedModels = ['Qwen/Qwen3-235B-A22B-Instruct-2507'];
|
||||
return !blockedModels.includes(model.model);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user