mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-06-22 09:48:36 +00:00
feat(app): add groq, gemini & anthropic provider
This commit is contained in:
63
ui/lib/providers/anthropic.ts
Normal file
63
ui/lib/providers/anthropic.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { ChatOpenAI } from '@langchain/openai';
|
||||||
|
import { ChatModel } from '.';
|
||||||
|
import { getAnthropicApiKey } from '../config';
|
||||||
|
|
||||||
|
const anthropicChatModels: Record<string, string>[] = [
|
||||||
|
{
|
||||||
|
displayName: 'Claude 3.7 Sonnet',
|
||||||
|
key: 'claude-3-7-sonnet-20250219',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Claude 3.5 Haiku',
|
||||||
|
key: 'claude-3-5-haiku-20241022',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Claude 3.5 Sonnet v2',
|
||||||
|
key: 'claude-3-5-sonnet-20241022',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Claude 3.5 Sonnet',
|
||||||
|
key: 'claude-3-5-sonnet-20240620',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Claude 3 Opus',
|
||||||
|
key: 'claude-3-opus-20240229',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Claude 3 Sonnet',
|
||||||
|
key: 'claude-3-sonnet-20240229',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Claude 3 Haiku',
|
||||||
|
key: 'claude-3-haiku-20240307',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const loadAnthropicChatModels = async () => {
|
||||||
|
const anthropicApiKey = getAnthropicApiKey();
|
||||||
|
|
||||||
|
if (!anthropicApiKey) return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chatModels: Record<string, ChatModel> = {};
|
||||||
|
|
||||||
|
anthropicChatModels.forEach((model) => {
|
||||||
|
chatModels[model.key] = {
|
||||||
|
displayName: model.displayName,
|
||||||
|
model: new ChatOpenAI({
|
||||||
|
openAIApiKey: anthropicApiKey,
|
||||||
|
modelName: model.key,
|
||||||
|
temperature: 0.7,
|
||||||
|
configuration: {
|
||||||
|
baseURL: 'https://api.anthropic.com/v1/',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return chatModels;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error loading Anthropic models: ${err}`);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
94
ui/lib/providers/gemini.ts
Normal file
94
ui/lib/providers/gemini.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai';
|
||||||
|
import { getGeminiApiKey } from '../config';
|
||||||
|
import { ChatModel, EmbeddingModel } from '.';
|
||||||
|
|
||||||
|
const geminiChatModels: Record<string, string>[] = [
|
||||||
|
{
|
||||||
|
displayName: 'Gemini 2.0 Flash',
|
||||||
|
key: 'gemini-2.0-flash',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Gemini 2.0 Flash-Lite',
|
||||||
|
key: 'gemini-2.0-flash-lite',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Gemini 2.0 Pro Experimental',
|
||||||
|
key: 'gemini-2.0-pro-exp-02-05',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Gemini 1.5 Flash',
|
||||||
|
key: 'gemini-1.5-flash',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Gemini 1.5 Flash-8B',
|
||||||
|
key: 'gemini-1.5-flash-8b',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Gemini 1.5 Pro',
|
||||||
|
key: 'gemini-1.5-pro',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const geminiEmbeddingModels: Record<string, string>[] = [
|
||||||
|
{
|
||||||
|
displayName: 'Gemini Embedding',
|
||||||
|
key: 'gemini-embedding-exp',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const loadGeminiChatModels = async () => {
|
||||||
|
const geminiApiKey = getGeminiApiKey();
|
||||||
|
|
||||||
|
if (!geminiApiKey) return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chatModels: Record<string, ChatModel> = {};
|
||||||
|
|
||||||
|
geminiChatModels.forEach((model) => {
|
||||||
|
chatModels[model.key] = {
|
||||||
|
displayName: model.displayName,
|
||||||
|
model: new ChatOpenAI({
|
||||||
|
openAIApiKey: geminiApiKey,
|
||||||
|
modelName: model.key,
|
||||||
|
temperature: 0.7,
|
||||||
|
configuration: {
|
||||||
|
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return chatModels;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error loading Gemini models: ${err}`);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const loadGeminiEmbeddingModels = async () => {
|
||||||
|
const geminiApiKey = getGeminiApiKey();
|
||||||
|
|
||||||
|
if (!geminiApiKey) return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const embeddingModels: Record<string, EmbeddingModel> = {};
|
||||||
|
|
||||||
|
geminiEmbeddingModels.forEach((model) => {
|
||||||
|
embeddingModels[model.key] = {
|
||||||
|
displayName: model.displayName,
|
||||||
|
model: new OpenAIEmbeddings({
|
||||||
|
openAIApiKey: geminiApiKey,
|
||||||
|
modelName: model.key,
|
||||||
|
configuration: {
|
||||||
|
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai/',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return embeddingModels;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error loading OpenAI embeddings models: ${err}`);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
107
ui/lib/providers/groq.ts
Normal file
107
ui/lib/providers/groq.ts
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { ChatOpenAI } from '@langchain/openai';
|
||||||
|
import { getGroqApiKey } from '../config';
|
||||||
|
import { ChatModel } from '.';
|
||||||
|
|
||||||
|
const groqChatModels: Record<string, string>[] = [
|
||||||
|
{
|
||||||
|
displayName: 'Gemma2 9B IT',
|
||||||
|
key: 'gemma2-9b-it',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama 3.3 70B Versatile',
|
||||||
|
key: 'llama-3.3-70b-versatile',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama 3.1 8B Instant',
|
||||||
|
key: 'llama-3.1-8b-instant',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama3 70B 8192',
|
||||||
|
key: 'llama3-70b-8192',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama3 8B 8192',
|
||||||
|
key: 'llama3-8b-8192',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Mixtral 8x7B 32768',
|
||||||
|
key: 'mixtral-8x7b-32768',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Qwen QWQ 32B (Preview)',
|
||||||
|
key: 'qwen-qwq-32b',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Mistral Saba 24B (Preview)',
|
||||||
|
key: 'mistral-saba-24b',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Qwen 2.5 Coder 32B (Preview)',
|
||||||
|
key: 'qwen-2.5-coder-32b',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Qwen 2.5 32B (Preview)',
|
||||||
|
key: 'qwen-2.5-32b',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'DeepSeek R1 Distill Qwen 32B (Preview)',
|
||||||
|
key: 'deepseek-r1-distill-qwen-32b',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'DeepSeek R1 Distill Llama 70B SpecDec (Preview)',
|
||||||
|
key: 'deepseek-r1-distill-llama-70b-specdec',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'DeepSeek R1 Distill Llama 70B (Preview)',
|
||||||
|
key: 'deepseek-r1-distill-llama-70b',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama 3.3 70B SpecDec (Preview)',
|
||||||
|
key: 'llama-3.3-70b-specdec',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama 3.2 1B Preview (Preview)',
|
||||||
|
key: 'llama-3.2-1b-preview',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama 3.2 3B Preview (Preview)',
|
||||||
|
key: 'llama-3.2-3b-preview',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama 3.2 11B Vision Preview (Preview)',
|
||||||
|
key: 'llama-3.2-11b-vision-preview',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Llama 3.2 90B Vision Preview (Preview)',
|
||||||
|
key: 'llama-3.2-90b-vision-preview',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const loadGroqChatModels = async () => {
|
||||||
|
const groqApiKey = getGroqApiKey();
|
||||||
|
|
||||||
|
if (!groqApiKey) return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chatModels: Record<string, ChatModel> = {};
|
||||||
|
|
||||||
|
groqChatModels.forEach((model) => {
|
||||||
|
chatModels[model.key] = {
|
||||||
|
displayName: model.displayName,
|
||||||
|
model: new ChatOpenAI({
|
||||||
|
openAIApiKey: groqApiKey,
|
||||||
|
modelName: model.key,
|
||||||
|
temperature: 0.7,
|
||||||
|
configuration: {
|
||||||
|
baseURL: 'https://api.groq.com/openai/v1',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return chatModels;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error loading Groq models: ${err}`);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
@ -1,72 +1,91 @@
|
|||||||
import { Embeddings } from '@langchain/core/embeddings';
|
import { Embeddings } from '@langchain/core/embeddings';
|
||||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
||||||
import { loadOpenAIChatModels, loadOpenAIEmbeddingModels } from './openai';
|
import { loadOpenAIChatModels, loadOpenAIEmbeddingModels } from './openai';
|
||||||
import { getCustomOpenaiApiKey, getCustomOpenaiApiUrl, getCustomOpenaiModelName } from '../config';
|
import {
|
||||||
|
getCustomOpenaiApiKey,
|
||||||
|
getCustomOpenaiApiUrl,
|
||||||
|
getCustomOpenaiModelName,
|
||||||
|
} from '../config';
|
||||||
import { ChatOpenAI } from '@langchain/openai';
|
import { ChatOpenAI } from '@langchain/openai';
|
||||||
|
import { loadOllamaChatModels, loadOllamaEmbeddingModels } from './ollama';
|
||||||
|
import { loadGroqChatModels } from './groq';
|
||||||
|
import { loadAnthropicChatModels } from './anthropic';
|
||||||
|
import { loadGeminiChatModels, loadGeminiEmbeddingModels } from './gemini';
|
||||||
|
|
||||||
export interface ChatModelProvider {
|
export interface ChatModel {
|
||||||
displayName: string
|
displayName: string;
|
||||||
model: BaseChatModel
|
model: BaseChatModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EmbeddingModelProvider {
|
export interface EmbeddingModel {
|
||||||
displayName: string
|
displayName: string;
|
||||||
model: Embeddings
|
model: Embeddings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatModelProviders: Record<string, () => Promise<Record<string, ChatModelProvider>>> = {
|
const chatModelProviders: Record<
|
||||||
openai: loadOpenAIChatModels
|
string,
|
||||||
}
|
() => Promise<Record<string, ChatModel>>
|
||||||
|
> = {
|
||||||
|
openai: loadOpenAIChatModels,
|
||||||
|
ollama: loadOllamaChatModels,
|
||||||
|
groq: loadGroqChatModels,
|
||||||
|
anthropic: loadAnthropicChatModels,
|
||||||
|
gemini: loadGeminiChatModels
|
||||||
|
};
|
||||||
|
|
||||||
const embeddingModelProviders: Record<string, () => Promise<Record<string, EmbeddingModelProvider>>> = {
|
const embeddingModelProviders: Record<
|
||||||
openai: loadOpenAIEmbeddingModels
|
string,
|
||||||
}
|
() => Promise<Record<string, EmbeddingModel>>
|
||||||
|
> = {
|
||||||
|
openai: loadOpenAIEmbeddingModels,
|
||||||
|
ollama: loadOllamaEmbeddingModels,
|
||||||
|
gemini: loadGeminiEmbeddingModels
|
||||||
|
};
|
||||||
|
|
||||||
export const getAvailableChatModelProviders = async () => {
|
export const getAvailableChatModelProviders = async () => {
|
||||||
const models: Record<string, Record<string, ChatModelProvider>> = {};
|
const models: Record<string, Record<string, ChatModel>> = {};
|
||||||
|
|
||||||
for (const provider in chatModelProviders) {
|
for (const provider in chatModelProviders) {
|
||||||
const providerModels = await chatModelProviders[provider]();
|
const providerModels = await chatModelProviders[provider]();
|
||||||
if (Object.keys(providerModels).length > 0) {
|
if (Object.keys(providerModels).length > 0) {
|
||||||
models[provider] = providerModels;
|
models[provider] = providerModels;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const customOpenAiApiKey = getCustomOpenaiApiKey();
|
const customOpenAiApiKey = getCustomOpenaiApiKey();
|
||||||
const customOpenAiApiUrl = getCustomOpenaiApiUrl();
|
const customOpenAiApiUrl = getCustomOpenaiApiUrl();
|
||||||
const customOpenAiModelName = getCustomOpenaiModelName();
|
const customOpenAiModelName = getCustomOpenaiModelName();
|
||||||
|
|
||||||
models['custom_openai'] = {
|
models['custom_openai'] = {
|
||||||
...(customOpenAiApiKey && customOpenAiApiUrl && customOpenAiModelName
|
...(customOpenAiApiKey && customOpenAiApiUrl && customOpenAiModelName
|
||||||
? {
|
? {
|
||||||
[customOpenAiModelName]: {
|
[customOpenAiModelName]: {
|
||||||
displayName: customOpenAiModelName,
|
displayName: customOpenAiModelName,
|
||||||
model: new ChatOpenAI({
|
model: new ChatOpenAI({
|
||||||
openAIApiKey: customOpenAiApiKey,
|
openAIApiKey: customOpenAiApiKey,
|
||||||
modelName: customOpenAiModelName,
|
modelName: customOpenAiModelName,
|
||||||
temperature: 0.7,
|
temperature: 0.7,
|
||||||
configuration: {
|
configuration: {
|
||||||
baseURL: customOpenAiApiUrl,
|
baseURL: customOpenAiApiUrl,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
return models;
|
return models;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAvailableEmbeddingModelProviders = async () => {
|
export const getAvailableEmbeddingModelProviders = async () => {
|
||||||
const models: Record<string, Record<string, EmbeddingModelProvider>> = {};
|
const models: Record<string, Record<string, EmbeddingModel>> = {};
|
||||||
|
|
||||||
for (const provider in embeddingModelProviders) {
|
for (const provider in embeddingModelProviders) {
|
||||||
const providerModels = await embeddingModelProviders[provider]();
|
const providerModels = await embeddingModelProviders[provider]();
|
||||||
if (Object.keys(providerModels).length > 0) {
|
if (Object.keys(providerModels).length > 0) {
|
||||||
models[provider] = providerModels;
|
models[provider] = providerModels;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return models;
|
return models;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
73
ui/lib/providers/ollama.ts
Normal file
73
ui/lib/providers/ollama.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import { getKeepAlive, getOllamaApiEndpoint } from '../config';
|
||||||
|
import { ChatModel, EmbeddingModel } from '.';
|
||||||
|
import { ChatOllama } from '@langchain/community/chat_models/ollama';
|
||||||
|
import { OllamaEmbeddings } from '@langchain/community/embeddings/ollama';
|
||||||
|
|
||||||
|
export const loadOllamaChatModels = async () => {
|
||||||
|
const ollamaApiEndpoint = getOllamaApiEndpoint();
|
||||||
|
|
||||||
|
if (!ollamaApiEndpoint) return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.get(`${ollamaApiEndpoint}/api/tags`, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { models } = res.data;
|
||||||
|
|
||||||
|
const chatModels: Record<string, ChatModel> = {};
|
||||||
|
|
||||||
|
models.forEach((model: any) => {
|
||||||
|
chatModels[model.model] = {
|
||||||
|
displayName: model.name,
|
||||||
|
model: new ChatOllama({
|
||||||
|
baseUrl: ollamaApiEndpoint,
|
||||||
|
model: model.model,
|
||||||
|
temperature: 0.7,
|
||||||
|
keepAlive: getKeepAlive(),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return chatModels;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error loading Ollama models: ${err}`);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const loadOllamaEmbeddingModels = async () => {
|
||||||
|
const ollamaApiEndpoint = getOllamaApiEndpoint();
|
||||||
|
|
||||||
|
if (!ollamaApiEndpoint) return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.get(`${ollamaApiEndpoint}/api/tags`, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { models } = res.data;
|
||||||
|
|
||||||
|
const embeddingModels: Record<string, EmbeddingModel> = {};
|
||||||
|
|
||||||
|
models.forEach((model: any) => {
|
||||||
|
embeddingModels[model.model] = {
|
||||||
|
displayName: model.name,
|
||||||
|
model: new OllamaEmbeddings({
|
||||||
|
baseUrl: ollamaApiEndpoint,
|
||||||
|
model: model.model,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return embeddingModels;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error loading Ollama embeddings models: ${err}`);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
Reference in New Issue
Block a user