mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-07-07 00:58:38 +00:00
feat: add AIML API provider
Introduces support for the AI/ML API provider, including configuration options, chat and embedding model loading, and UI integration. Updates documentation and sample config to reflect the new provider.
This commit is contained in:
@ -90,7 +90,9 @@ There are mainly 2 ways of installing Perplexica - With Docker, Without Docker.
|
||||
- `OLLAMA`: Your Ollama API URL. You should enter it as `http://host.docker.internal:PORT_NUMBER`. If you installed Ollama on port 11434, use `http://host.docker.internal:11434`. For other ports, adjust accordingly. **You need to fill this if you wish to use Ollama's models instead of OpenAI's**.
|
||||
- `GROQ`: Your Groq API key. **You only need to fill this if you wish to use Groq's hosted models**.
|
||||
- `ANTHROPIC`: Your Anthropic API key. **You only need to fill this if you wish to use Anthropic models**.
|
||||
- `Gemini`: Your Gemini API key. **You only need to fill this if you wish to use Google's models**.
|
||||
- `Gemini`: Your Gemini API key. **You only need to fill this if you wish to use Google's models**.
|
||||
- `DEEPSEEK`: Your Deepseek API key. **Only needed if you want Deepseek models.**
|
||||
- `AIMLAPI`: Your AI/ML API key. **Only needed if you want to use AI/ML API models and embeddings.**
|
||||
|
||||
**Note**: You can change these after starting Perplexica from the settings dialog.
|
||||
|
||||
|
@ -25,6 +25,9 @@ API_URL = "" # Ollama API URL - http://host.docker.internal:11434
|
||||
[MODELS.DEEPSEEK]
|
||||
API_KEY = ""
|
||||
|
||||
[MODELS.AIMLAPI]
|
||||
API_KEY = "" # Required to use AI/ML API chat and embedding models
|
||||
|
||||
[MODELS.LM_STUDIO]
|
||||
API_URL = "" # LM Studio API URL - http://host.docker.internal:1234
|
||||
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
getOllamaApiEndpoint,
|
||||
getOpenaiApiKey,
|
||||
getDeepseekApiKey,
|
||||
getAimlApiKey,
|
||||
getLMStudioApiEndpoint,
|
||||
updateConfig,
|
||||
} from '@/lib/config';
|
||||
@ -57,6 +58,7 @@ export const GET = async (req: Request) => {
|
||||
config['groqApiKey'] = getGroqApiKey();
|
||||
config['geminiApiKey'] = getGeminiApiKey();
|
||||
config['deepseekApiKey'] = getDeepseekApiKey();
|
||||
config['aimlApiKey'] = getAimlApiKey();
|
||||
config['customOpenaiApiUrl'] = getCustomOpenaiApiUrl();
|
||||
config['customOpenaiApiKey'] = getCustomOpenaiApiKey();
|
||||
config['customOpenaiModelName'] = getCustomOpenaiModelName();
|
||||
@ -95,6 +97,9 @@ export const POST = async (req: Request) => {
|
||||
DEEPSEEK: {
|
||||
API_KEY: config.deepseekApiKey,
|
||||
},
|
||||
AIMLAPI: {
|
||||
API_KEY: config.aimlApiKey,
|
||||
},
|
||||
LM_STUDIO: {
|
||||
API_URL: config.lmStudioApiUrl,
|
||||
},
|
||||
|
@ -23,6 +23,7 @@ interface SettingsType {
|
||||
ollamaApiUrl: string;
|
||||
lmStudioApiUrl: string;
|
||||
deepseekApiKey: string;
|
||||
aimlApiKey: string;
|
||||
customOpenaiApiKey: string;
|
||||
customOpenaiApiUrl: string;
|
||||
customOpenaiModelName: string;
|
||||
@ -862,6 +863,25 @@ const Page = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col space-y-1">
|
||||
<p className="text-black/70 dark:text-white/70 text-sm">
|
||||
AI/ML API Key
|
||||
</p>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="AI/ML API Key"
|
||||
value={config.aimlApiKey}
|
||||
isSaving={savingStates['aimlApiKey']}
|
||||
onChange={(e) => {
|
||||
setConfig((prev) => ({
|
||||
...prev!,
|
||||
aimlApiKey: e.target.value,
|
||||
}));
|
||||
}}
|
||||
onSave={(value) => saveConfig('aimlApiKey', value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col space-y-1">
|
||||
<p className="text-black/70 dark:text-white/70 text-sm">
|
||||
LM Studio API URL
|
||||
|
@ -35,6 +35,9 @@ interface Config {
|
||||
DEEPSEEK: {
|
||||
API_KEY: string;
|
||||
};
|
||||
AIMLAPI: {
|
||||
API_KEY: string;
|
||||
};
|
||||
LM_STUDIO: {
|
||||
API_URL: string;
|
||||
};
|
||||
@ -85,6 +88,8 @@ export const getOllamaApiEndpoint = () => loadConfig().MODELS.OLLAMA.API_URL;
|
||||
|
||||
export const getDeepseekApiKey = () => loadConfig().MODELS.DEEPSEEK.API_KEY;
|
||||
|
||||
export const getAimlApiKey = () => loadConfig().MODELS.AIMLAPI.API_KEY;
|
||||
|
||||
export const getCustomOpenaiApiKey = () =>
|
||||
loadConfig().MODELS.CUSTOM_OPENAI.API_KEY;
|
||||
|
||||
|
94
src/lib/providers/aimlapi.ts
Normal file
94
src/lib/providers/aimlapi.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { ChatOpenAI, OpenAIEmbeddings } from '@langchain/openai';
|
||||
import { getAimlApiKey } from '../config';
|
||||
import { ChatModel, EmbeddingModel } from '.';
|
||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
||||
import { Embeddings } from '@langchain/core/embeddings';
|
||||
import axios from 'axios';
|
||||
|
||||
export const PROVIDER_INFO = {
|
||||
key: 'aimlapi',
|
||||
displayName: 'AI/ML API',
|
||||
};
|
||||
|
||||
interface AimlApiModel {
|
||||
id: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
const API_URL = 'https://api.aimlapi.com';
|
||||
|
||||
export const loadAimlApiChatModels = async () => {
|
||||
const apiKey = getAimlApiKey();
|
||||
|
||||
if (!apiKey) return {};
|
||||
|
||||
try {
|
||||
const response = await axios.get(`${API_URL}/models`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
});
|
||||
|
||||
const chatModels: Record<string, ChatModel> = {};
|
||||
|
||||
response.data.data.forEach((model: AimlApiModel) => {
|
||||
if (model.type === 'chat-completion') {
|
||||
chatModels[model.id] = {
|
||||
displayName: model.name || model.id,
|
||||
model: new ChatOpenAI({
|
||||
openAIApiKey: apiKey,
|
||||
modelName: model.id,
|
||||
temperature: 0.7,
|
||||
configuration: {
|
||||
baseURL: API_URL,
|
||||
},
|
||||
}) as unknown as BaseChatModel,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return chatModels;
|
||||
} catch (err) {
|
||||
console.error(`Error loading AI/ML API models: ${err}`);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
export const loadAimlApiEmbeddingModels = async () => {
|
||||
const apiKey = getAimlApiKey();
|
||||
|
||||
if (!apiKey) return {};
|
||||
|
||||
try {
|
||||
const response = await axios.get(`${API_URL}/models`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
});
|
||||
|
||||
const embeddingModels: Record<string, EmbeddingModel> = {};
|
||||
|
||||
response.data.data.forEach((model: AimlApiModel) => {
|
||||
if (model.type === 'embedding') {
|
||||
embeddingModels[model.id] = {
|
||||
displayName: model.name || model.id,
|
||||
model: new OpenAIEmbeddings({
|
||||
openAIApiKey: apiKey,
|
||||
modelName: model.id,
|
||||
configuration: {
|
||||
baseURL: API_URL,
|
||||
},
|
||||
}) as unknown as Embeddings,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return embeddingModels;
|
||||
} catch (err) {
|
||||
console.error(`Error loading AI/ML API embeddings models: ${err}`);
|
||||
return {};
|
||||
}
|
||||
};
|
@ -35,6 +35,11 @@ import {
|
||||
loadDeepseekChatModels,
|
||||
PROVIDER_INFO as DeepseekInfo,
|
||||
} from './deepseek';
|
||||
import {
|
||||
loadAimlApiChatModels,
|
||||
loadAimlApiEmbeddingModels,
|
||||
PROVIDER_INFO as AimlApiInfo,
|
||||
} from './aimlapi';
|
||||
import {
|
||||
loadLMStudioChatModels,
|
||||
loadLMStudioEmbeddingsModels,
|
||||
@ -49,6 +54,7 @@ export const PROVIDER_METADATA = {
|
||||
gemini: GeminiInfo,
|
||||
transformers: TransformersInfo,
|
||||
deepseek: DeepseekInfo,
|
||||
aimlapi: AimlApiInfo,
|
||||
lmstudio: LMStudioInfo,
|
||||
custom_openai: {
|
||||
key: 'custom_openai',
|
||||
@ -76,6 +82,7 @@ export const chatModelProviders: Record<
|
||||
anthropic: loadAnthropicChatModels,
|
||||
gemini: loadGeminiChatModels,
|
||||
deepseek: loadDeepseekChatModels,
|
||||
aimlapi: loadAimlApiChatModels,
|
||||
lmstudio: loadLMStudioChatModels,
|
||||
};
|
||||
|
||||
@ -87,6 +94,7 @@ export const embeddingModelProviders: Record<
|
||||
ollama: loadOllamaEmbeddingModels,
|
||||
gemini: loadGeminiEmbeddingModels,
|
||||
transformers: loadTransformersEmbeddingsModels,
|
||||
aimlapi: loadAimlApiEmbeddingModels,
|
||||
lmstudio: loadLMStudioEmbeddingsModels,
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user