mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-10-14 11:38:14 +00:00
feat(models): add id
& name
fields, move getUIConfigSection
to seperate file
This commit is contained in:
@@ -4,7 +4,11 @@ import { Model, ModelList, ProviderMetadata } from '../types';
|
||||
import { UIConfigField } from '@/lib/config/types';
|
||||
|
||||
abstract class BaseModelProvider<CONFIG> {
|
||||
constructor(protected config: CONFIG) {}
|
||||
constructor(
|
||||
protected id: string,
|
||||
protected name: string,
|
||||
protected config: CONFIG,
|
||||
) {}
|
||||
abstract getDefaultModels(): Promise<ModelList>;
|
||||
abstract getModelList(): Promise<ModelList>;
|
||||
abstract loadChatModel(modelName: string): Promise<BaseChatModel>;
|
||||
@@ -15,6 +19,27 @@ abstract class BaseModelProvider<CONFIG> {
|
||||
static getProviderMetadata(): ProviderMetadata {
|
||||
throw new Error('Method not Implemented.');
|
||||
}
|
||||
static parseAndValidate(raw: any): any {
|
||||
/* Static methods can't access class type parameters */
|
||||
throw new Error('Method not Implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
export type ProviderConstructor<CONFIG> = {
|
||||
new (id: string, name: string, config: CONFIG): BaseModelProvider<CONFIG>;
|
||||
parseAndValidate(raw: any): CONFIG;
|
||||
getProviderConfigFields: () => UIConfigField[];
|
||||
getProviderMetadata: () => ProviderMetadata;
|
||||
};
|
||||
|
||||
export const createProviderInstance = <P extends ProviderConstructor<any>>(
|
||||
Provider: P,
|
||||
id: string,
|
||||
name: string,
|
||||
rawConfig: unknown,
|
||||
): InstanceType<P> => {
|
||||
const cfg = Provider.parseAndValidate(rawConfig);
|
||||
return new Provider(id, name, cfg) as InstanceType<P>;
|
||||
};
|
||||
|
||||
export default BaseModelProvider;
|
||||
|
21
src/lib/models/providers/index.ts
Normal file
21
src/lib/models/providers/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { ModelProviderUISection } from '@/lib/config/types';
|
||||
import { ProviderConstructor } from './baseProvider';
|
||||
import OpenAIProvider from './openai';
|
||||
|
||||
export const providers: Record<string, ProviderConstructor<any>> = {
|
||||
openai: OpenAIProvider,
|
||||
};
|
||||
|
||||
export const getModelProvidersUIConfigSection =
|
||||
(): ModelProviderUISection[] => {
|
||||
return Object.entries(providers).map(([k, p]) => {
|
||||
const configFields = p.getProviderConfigFields();
|
||||
const metadata = p.getProviderMetadata();
|
||||
|
||||
return {
|
||||
fields: configFields,
|
||||
key: k,
|
||||
name: metadata.name,
|
||||
};
|
||||
});
|
||||
};
|
@@ -6,7 +6,6 @@ import { Embeddings } from '@langchain/core/embeddings';
|
||||
import { UIConfigField } from '@/lib/config/types';
|
||||
|
||||
interface OpenAIConfig {
|
||||
name: string;
|
||||
apiKey: string;
|
||||
baseURL: string;
|
||||
}
|
||||
@@ -90,15 +89,6 @@ const defaultEmbeddingModels: Model[] = [
|
||||
];
|
||||
|
||||
const providerConfigFields: UIConfigField[] = [
|
||||
/* {
|
||||
type: 'string',
|
||||
name: 'Name (Optional)',
|
||||
key: 'name',
|
||||
description: 'An optional name for this provider configuration',
|
||||
required: false,
|
||||
placeholder: 'Provider Name',
|
||||
scope: 'server',
|
||||
}, */ /* FOR NAME DIRECTLY CREATE INPUT IN FRONTEND */
|
||||
{
|
||||
type: 'password',
|
||||
name: 'API Key',
|
||||
@@ -123,8 +113,8 @@ const providerConfigFields: UIConfigField[] = [
|
||||
];
|
||||
|
||||
class OpenAIProvider extends BaseModelProvider<OpenAIConfig> {
|
||||
constructor(config: OpenAIConfig) {
|
||||
super(config);
|
||||
constructor(id: string, name: string, config: OpenAIConfig) {
|
||||
super(id, name, config);
|
||||
}
|
||||
|
||||
async getDefaultModels(): Promise<ModelList> {
|
||||
@@ -192,6 +182,20 @@ class OpenAIProvider extends BaseModelProvider<OpenAIConfig> {
|
||||
});
|
||||
}
|
||||
|
||||
static parseAndValidate(raw: any): OpenAIConfig {
|
||||
if (!raw || typeof raw !== 'object')
|
||||
throw new Error('Invalid config provided. Expected object');
|
||||
if (!raw.apiKey || !raw.baseURL)
|
||||
throw new Error(
|
||||
'Invalid config provided. API key and base URL must be provided',
|
||||
);
|
||||
|
||||
return {
|
||||
apiKey: String(raw.apiKey),
|
||||
baseURL: String(raw.baseURL),
|
||||
};
|
||||
}
|
||||
|
||||
static getProviderConfigFields(): UIConfigField[] {
|
||||
return providerConfigFields;
|
||||
}
|
||||
|
@@ -1,32 +1,52 @@
|
||||
import { ModelProviderUISection, UIConfigField } from '../config/types';
|
||||
import { ProviderMetadata } from './types';
|
||||
import BaseModelProvider from './providers/baseProvider';
|
||||
import OpenAIProvider from './providers/openai';
|
||||
|
||||
interface ProviderClass<T> {
|
||||
new (config: T): BaseModelProvider<T>;
|
||||
getProviderConfigFields(): UIConfigField[];
|
||||
getProviderMetadata(): ProviderMetadata;
|
||||
}
|
||||
|
||||
const providers: Record<string, ProviderClass<any>> = {
|
||||
openai: OpenAIProvider,
|
||||
};
|
||||
import { ConfigModelProvider } from '../config/types';
|
||||
import BaseModelProvider, {
|
||||
createProviderInstance,
|
||||
} from './providers/baseProvider';
|
||||
import { getConfiguredModelProviders } from '../config/serverRegistry';
|
||||
import { providers } from './providers';
|
||||
import { ModelList } from './types';
|
||||
|
||||
class ModelRegistry {
|
||||
constructor() {}
|
||||
activeProviders: (ConfigModelProvider & {
|
||||
provider: BaseModelProvider<any>;
|
||||
})[] = [];
|
||||
|
||||
getUIConfigSection(): ModelProviderUISection[] {
|
||||
return Object.entries(providers).map(([k, p]) => {
|
||||
const configFields = p.getProviderConfigFields();
|
||||
const metadata = p.getProviderMetadata();
|
||||
constructor() {
|
||||
this.initializeActiveProviders();
|
||||
}
|
||||
|
||||
return {
|
||||
fields: configFields,
|
||||
key: k,
|
||||
name: metadata.name,
|
||||
};
|
||||
private initializeActiveProviders() {
|
||||
const configuredProviders = getConfiguredModelProviders();
|
||||
|
||||
configuredProviders.forEach((p) => {
|
||||
try {
|
||||
const provider = providers[p.type];
|
||||
if (!provider) throw new Error('Invalid provider type');
|
||||
|
||||
this.activeProviders.push({
|
||||
...p,
|
||||
provider: createProviderInstance(provider, p.id, p.name, p.config),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Failed to initialize provider. Type: ${p.type}, ID: ${p.id}, Config: ${JSON.stringify(p.config)}, Error: ${err}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async getActiveModels() {
|
||||
const models: ModelList[] = [];
|
||||
|
||||
await Promise.all(
|
||||
this.activeProviders.map(async (p) => {
|
||||
const m = await p.provider.getModelList();
|
||||
|
||||
models.push(m);
|
||||
}),
|
||||
);
|
||||
|
||||
return models;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user