mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-10-19 05:48:15 +00:00
feat(app): add provider methods
This commit is contained in:
94
src/app/api/providers/[id]/models/route.ts
Normal file
94
src/app/api/providers/[id]/models/route.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import ModelRegistry from '@/lib/models/registry';
|
||||||
|
import { Model } from '@/lib/models/types';
|
||||||
|
import { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
export const POST = async (
|
||||||
|
req: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> },
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { id } = await params;
|
||||||
|
|
||||||
|
const body: Partial<Model> & { type: 'embedding' | 'chat' } =
|
||||||
|
await req.json();
|
||||||
|
|
||||||
|
if (!body.key || !body.name) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Key and name must be provided',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 400,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registry = new ModelRegistry();
|
||||||
|
|
||||||
|
await registry.addProviderModel(id, body.type, body);
|
||||||
|
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Model added successfully',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('An error occurred while adding provider model', err);
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'An error has occurred.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DELETE = async (
|
||||||
|
req: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> },
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { id } = await params;
|
||||||
|
|
||||||
|
const body: { key: string; type: 'embedding' | 'chat' } = await req.json();
|
||||||
|
|
||||||
|
if (!body.key) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Key and name must be provided',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 400,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registry = new ModelRegistry();
|
||||||
|
|
||||||
|
await registry.removeProviderModel(id, body.type, body.key);
|
||||||
|
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Model added successfully',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('An error occurred while deleting provider model', err);
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'An error has occurred.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
89
src/app/api/providers/[id]/route.ts
Normal file
89
src/app/api/providers/[id]/route.ts
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import ModelRegistry from '@/lib/models/registry';
|
||||||
|
import { NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
export const DELETE = async (
|
||||||
|
req: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> },
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { id } = await params;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Provider ID is required.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 400,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registry = new ModelRegistry();
|
||||||
|
await registry.removeProvider(id);
|
||||||
|
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Provider deleted successfully.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('An error occurred while deleting provider', err.message);
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'An error has occurred.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PATCH = async (
|
||||||
|
req: NextRequest,
|
||||||
|
{ params }: { params: Promise<{ id: string }> },
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const body = await req.json();
|
||||||
|
const { name, config } = body;
|
||||||
|
const { id } = await params;
|
||||||
|
|
||||||
|
if (!id || !name || !config) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Missing required fields.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 400,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registry = new ModelRegistry();
|
||||||
|
|
||||||
|
const updatedProvider = await registry.updateProvider(id, name, config);
|
||||||
|
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
provider: updatedProvider,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('An error occurred while updating provider', err.message);
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'An error has occurred.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
@@ -1,4 +1,5 @@
|
|||||||
import ModelRegistry from '@/lib/models/registry';
|
import ModelRegistry from '@/lib/models/registry';
|
||||||
|
import { NextRequest } from 'next/server';
|
||||||
|
|
||||||
export const GET = async (req: Request) => {
|
export const GET = async (req: Request) => {
|
||||||
try {
|
try {
|
||||||
@@ -6,9 +7,13 @@ export const GET = async (req: Request) => {
|
|||||||
|
|
||||||
const activeProviders = await registry.getActiveProviders();
|
const activeProviders = await registry.getActiveProviders();
|
||||||
|
|
||||||
|
const filteredProviders = activeProviders.filter((p) => {
|
||||||
|
return !p.chatModels.some((m) => m.key === 'error');
|
||||||
|
});
|
||||||
|
|
||||||
return Response.json(
|
return Response.json(
|
||||||
{
|
{
|
||||||
providers: activeProviders,
|
providers: filteredProviders,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: 200,
|
status: 200,
|
||||||
@@ -26,3 +31,44 @@ export const GET = async (req: Request) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const POST = async (req: NextRequest) => {
|
||||||
|
try {
|
||||||
|
const body = await req.json();
|
||||||
|
const { type, name, config } = body;
|
||||||
|
|
||||||
|
if (!type || !name || !config) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'Missing required fields.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 400,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registry = new ModelRegistry();
|
||||||
|
|
||||||
|
const newProvider = await registry.addProvider(type, name, config);
|
||||||
|
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
provider: newProvider,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('An error occurred while creating provider', err);
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
message: 'An error has occurred.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@@ -225,6 +225,8 @@ class ConfigManager {
|
|||||||
|
|
||||||
this.currentConfig.modelProviders.push(newModelProvider);
|
this.currentConfig.modelProviders.push(newModelProvider);
|
||||||
this.saveConfig();
|
this.saveConfig();
|
||||||
|
|
||||||
|
return newModelProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeModelProvider(id: string) {
|
public removeModelProvider(id: string) {
|
||||||
@@ -240,6 +242,69 @@ class ConfigManager {
|
|||||||
this.saveConfig();
|
this.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateModelProvider(id: string, name: string, config: any) {
|
||||||
|
const provider = this.currentConfig.modelProviders.find((p) => {
|
||||||
|
return p.id === id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!provider) throw new Error('Provider not found');
|
||||||
|
|
||||||
|
provider.name = name;
|
||||||
|
provider.config = config;
|
||||||
|
|
||||||
|
this.saveConfig();
|
||||||
|
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addProviderModel(
|
||||||
|
providerId: string,
|
||||||
|
type: 'embedding' | 'chat',
|
||||||
|
model: any,
|
||||||
|
) {
|
||||||
|
const provider = this.currentConfig.modelProviders.find(
|
||||||
|
(p) => p.id === providerId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!provider) throw new Error('Invalid provider id');
|
||||||
|
|
||||||
|
delete model.type;
|
||||||
|
|
||||||
|
if (type === 'chat') {
|
||||||
|
provider.chatModels.push(model);
|
||||||
|
} else {
|
||||||
|
provider.embeddingModels.push(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveConfig();
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeProviderModel(
|
||||||
|
providerId: string,
|
||||||
|
type: 'embedding' | 'chat',
|
||||||
|
modelKey: string,
|
||||||
|
) {
|
||||||
|
const provider = this.currentConfig.modelProviders.find(
|
||||||
|
(p) => p.id === providerId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!provider) throw new Error('Invalid provider id');
|
||||||
|
|
||||||
|
if (type === 'chat') {
|
||||||
|
provider.chatModels = provider.chatModels.filter(
|
||||||
|
(m) => m.key !== modelKey,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
provider.embeddingModels = provider.embeddingModels.filter(
|
||||||
|
(m) => m.key != modelKey,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
public isSetupComplete() {
|
public isSetupComplete() {
|
||||||
return this.currentConfig.setupComplete;
|
return this.currentConfig.setupComplete;
|
||||||
}
|
}
|
||||||
@@ -255,6 +320,10 @@ class ConfigManager {
|
|||||||
public getUIConfigSections(): UIConfigSections {
|
public getUIConfigSections(): UIConfigSections {
|
||||||
return this.uiConfigSections;
|
return this.uiConfigSections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getCurrentConfig(): Config {
|
||||||
|
return JSON.parse(JSON.stringify(this.currentConfig));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const configManager = new ConfigManager();
|
const configManager = new ConfigManager();
|
||||||
|
@@ -4,7 +4,8 @@ import BaseModelProvider, {
|
|||||||
} from './providers/baseProvider';
|
} from './providers/baseProvider';
|
||||||
import { getConfiguredModelProviders } from '../config/serverRegistry';
|
import { getConfiguredModelProviders } from '../config/serverRegistry';
|
||||||
import { providers } from './providers';
|
import { providers } from './providers';
|
||||||
import { MinimalProvider, Model } from './types';
|
import { MinimalProvider, ModelList } from './types';
|
||||||
|
import configManager from '../config';
|
||||||
|
|
||||||
class ModelRegistry {
|
class ModelRegistry {
|
||||||
activeProviders: (ConfigModelProvider & {
|
activeProviders: (ConfigModelProvider & {
|
||||||
@@ -40,7 +41,25 @@ class ModelRegistry {
|
|||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
this.activeProviders.map(async (p) => {
|
this.activeProviders.map(async (p) => {
|
||||||
const m = await p.provider.getModelList();
|
let m: ModelList = { chat: [], embedding: [] };
|
||||||
|
|
||||||
|
try {
|
||||||
|
m = await p.provider.getModelList();
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error(
|
||||||
|
`Failed to get model list. Type: ${p.type}, ID: ${p.id}, Error: ${err.message}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
m = {
|
||||||
|
chat: [
|
||||||
|
{
|
||||||
|
key: 'error',
|
||||||
|
name: err.message,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
embedding: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
providers.push({
|
providers.push({
|
||||||
id: p.id,
|
id: p.id,
|
||||||
@@ -48,6 +67,7 @@ class ModelRegistry {
|
|||||||
chatModels: m.chat,
|
chatModels: m.chat,
|
||||||
embeddingModels: m.embedding,
|
embeddingModels: m.embedding,
|
||||||
});
|
});
|
||||||
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -73,6 +93,132 @@ class ModelRegistry {
|
|||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addProvider(
|
||||||
|
type: string,
|
||||||
|
name: string,
|
||||||
|
config: Record<string, any>,
|
||||||
|
): Promise<ConfigModelProvider> {
|
||||||
|
const provider = providers[type];
|
||||||
|
if (!provider) throw new Error('Invalid provider type');
|
||||||
|
|
||||||
|
const newProvider = configManager.addModelProvider(type, name, config);
|
||||||
|
|
||||||
|
const instance = createProviderInstance(
|
||||||
|
provider,
|
||||||
|
newProvider.id,
|
||||||
|
newProvider.name,
|
||||||
|
newProvider.config,
|
||||||
|
);
|
||||||
|
|
||||||
|
let m: ModelList = { chat: [], embedding: [] };
|
||||||
|
|
||||||
|
try {
|
||||||
|
m = await instance.getModelList();
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error(
|
||||||
|
`Failed to get model list for newly added provider. Type: ${type}, ID: ${newProvider.id}, Error: ${err.message}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
m = {
|
||||||
|
chat: [
|
||||||
|
{
|
||||||
|
key: 'error',
|
||||||
|
name: err.message,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
embedding: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.activeProviders.push({
|
||||||
|
...newProvider,
|
||||||
|
provider: instance,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...newProvider,
|
||||||
|
chatModels: m.chat || [],
|
||||||
|
embeddingModels: m.embedding || [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeProvider(providerId: string): Promise<void> {
|
||||||
|
configManager.removeModelProvider(providerId);
|
||||||
|
this.activeProviders = this.activeProviders.filter(
|
||||||
|
(p) => p.id !== providerId,
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateProvider(
|
||||||
|
providerId: string,
|
||||||
|
name: string,
|
||||||
|
config: any,
|
||||||
|
): Promise<ConfigModelProvider> {
|
||||||
|
const updated = await configManager.updateModelProvider(
|
||||||
|
providerId,
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
const instance = createProviderInstance(
|
||||||
|
providers[updated.type],
|
||||||
|
providerId,
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
);
|
||||||
|
|
||||||
|
let m: ModelList = { chat: [], embedding: [] };
|
||||||
|
|
||||||
|
try {
|
||||||
|
m = await instance.getModelList();
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error(
|
||||||
|
`Failed to get model list for updated provider. Type: ${updated.type}, ID: ${updated.id}, Error: ${err.message}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
m = {
|
||||||
|
chat: [
|
||||||
|
{
|
||||||
|
key: 'error',
|
||||||
|
name: err.message,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
embedding: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.activeProviders.push({
|
||||||
|
...updated,
|
||||||
|
provider: instance,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...updated,
|
||||||
|
chatModels: m.chat || [],
|
||||||
|
embeddingModels: m.embedding || [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Using async here because maybe in the future we might want to add some validation?? */
|
||||||
|
async addProviderModel(
|
||||||
|
providerId: string,
|
||||||
|
type: 'embedding' | 'chat',
|
||||||
|
model: any,
|
||||||
|
): Promise<any> {
|
||||||
|
const addedModel = configManager.addProviderModel(providerId, type, model);
|
||||||
|
return addedModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeProviderModel(
|
||||||
|
providerId: string,
|
||||||
|
type: 'embedding' | 'chat',
|
||||||
|
modelKey: string,
|
||||||
|
): Promise<void> {
|
||||||
|
configManager.removeProviderModel(providerId, type, modelKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ModelRegistry;
|
export default ModelRegistry;
|
||||||
|
Reference in New Issue
Block a user