mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-12-16 08:38:15 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f88f179920 | ||
|
|
4cb0aeeee3 | ||
|
|
e8fe74ae7c | ||
|
|
ed47191d9b | ||
|
|
b4d787d333 | ||
|
|
38b1995677 | ||
|
|
f28257b480 |
11
README.md
11
README.md
@@ -10,6 +10,7 @@
|
|||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Getting Started with Docker (Recommended)](#getting-started-with-docker-recommended)
|
- [Getting Started with Docker (Recommended)](#getting-started-with-docker-recommended)
|
||||||
- [Non-Docker Installation](#non-docker-installation)
|
- [Non-Docker Installation](#non-docker-installation)
|
||||||
|
- [Ollama connection errors](#ollama-connection-errors)
|
||||||
- [One-Click Deployment](#one-click-deployment)
|
- [One-Click Deployment](#one-click-deployment)
|
||||||
- [Upcoming Features](#upcoming-features)
|
- [Upcoming Features](#upcoming-features)
|
||||||
- [Support Us](#support-us)
|
- [Support Us](#support-us)
|
||||||
@@ -90,6 +91,16 @@ There are mainly 2 ways of installing Perplexica - With Docker, Without Docker.
|
|||||||
|
|
||||||
**Note**: Using Docker is recommended as it simplifies the setup process, especially for managing environment variables and dependencies.
|
**Note**: Using Docker is recommended as it simplifies the setup process, especially for managing environment variables and dependencies.
|
||||||
|
|
||||||
|
#### Ollama connection errors
|
||||||
|
|
||||||
|
If you're facing an Ollama connection error, it is often related to the backend not being able to connect to Ollama's API. How can you fix it? You can fix it by updating your Ollama API URL in the settings menu to the following:
|
||||||
|
|
||||||
|
On Windows: `http://host.docker.internal:11434`<br>
|
||||||
|
On Mac: `http://host.docker.internal:11434`<br>
|
||||||
|
On Linux: `http://private_ip_of_computer_hosting_ollama:11434`
|
||||||
|
|
||||||
|
You need to edit the ports accordingly.
|
||||||
|
|
||||||
## One-Click Deployment
|
## One-Click Deployment
|
||||||
|
|
||||||
[](https://repocloud.io/details/?app_id=267)
|
[](https://repocloud.io/details/?app_id=267)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "perplexica-backend",
|
"name": "perplexica-backend",
|
||||||
"version": "1.3.2",
|
"version": "1.3.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "ItzCrazyKns",
|
"author": "ItzCrazyKns",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -14,74 +14,87 @@ export const handleConnection = async (
|
|||||||
ws: WebSocket,
|
ws: WebSocket,
|
||||||
request: IncomingMessage,
|
request: IncomingMessage,
|
||||||
) => {
|
) => {
|
||||||
const searchParams = new URL(request.url, `http://${request.headers.host}`)
|
try {
|
||||||
.searchParams;
|
const searchParams = new URL(request.url, `http://${request.headers.host}`)
|
||||||
|
.searchParams;
|
||||||
|
|
||||||
const [chatModelProviders, embeddingModelProviders] = await Promise.all([
|
const [chatModelProviders, embeddingModelProviders] = await Promise.all([
|
||||||
getAvailableChatModelProviders(),
|
getAvailableChatModelProviders(),
|
||||||
getAvailableEmbeddingModelProviders(),
|
getAvailableEmbeddingModelProviders(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const chatModelProvider =
|
const chatModelProvider =
|
||||||
searchParams.get('chatModelProvider') || Object.keys(chatModelProviders)[0];
|
searchParams.get('chatModelProvider') ||
|
||||||
const chatModel =
|
Object.keys(chatModelProviders)[0];
|
||||||
searchParams.get('chatModel') ||
|
const chatModel =
|
||||||
Object.keys(chatModelProviders[chatModelProvider])[0];
|
searchParams.get('chatModel') ||
|
||||||
|
Object.keys(chatModelProviders[chatModelProvider])[0];
|
||||||
|
|
||||||
const embeddingModelProvider =
|
const embeddingModelProvider =
|
||||||
searchParams.get('embeddingModelProvider') ||
|
searchParams.get('embeddingModelProvider') ||
|
||||||
Object.keys(embeddingModelProviders)[0];
|
Object.keys(embeddingModelProviders)[0];
|
||||||
const embeddingModel =
|
const embeddingModel =
|
||||||
searchParams.get('embeddingModel') ||
|
searchParams.get('embeddingModel') ||
|
||||||
Object.keys(embeddingModelProviders[embeddingModelProvider])[0];
|
Object.keys(embeddingModelProviders[embeddingModelProvider])[0];
|
||||||
|
|
||||||
let llm: BaseChatModel | undefined;
|
let llm: BaseChatModel | undefined;
|
||||||
let embeddings: Embeddings | undefined;
|
let embeddings: Embeddings | undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
chatModelProviders[chatModelProvider] &&
|
chatModelProviders[chatModelProvider] &&
|
||||||
chatModelProviders[chatModelProvider][chatModel] &&
|
chatModelProviders[chatModelProvider][chatModel] &&
|
||||||
chatModelProvider != 'custom_openai'
|
chatModelProvider != 'custom_openai'
|
||||||
) {
|
) {
|
||||||
llm = chatModelProviders[chatModelProvider][chatModel] as
|
llm = chatModelProviders[chatModelProvider][chatModel] as
|
||||||
| BaseChatModel
|
| BaseChatModel
|
||||||
| undefined;
|
| undefined;
|
||||||
} else if (chatModelProvider == 'custom_openai') {
|
} else if (chatModelProvider == 'custom_openai') {
|
||||||
llm = new ChatOpenAI({
|
llm = new ChatOpenAI({
|
||||||
modelName: chatModel,
|
modelName: chatModel,
|
||||||
openAIApiKey: searchParams.get('openAIApiKey'),
|
openAIApiKey: searchParams.get('openAIApiKey'),
|
||||||
temperature: 0.7,
|
temperature: 0.7,
|
||||||
configuration: {
|
configuration: {
|
||||||
baseURL: searchParams.get('openAIBaseURL'),
|
baseURL: searchParams.get('openAIBaseURL'),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
embeddingModelProviders[embeddingModelProvider] &&
|
embeddingModelProviders[embeddingModelProvider] &&
|
||||||
embeddingModelProviders[embeddingModelProvider][embeddingModel]
|
embeddingModelProviders[embeddingModelProvider][embeddingModel]
|
||||||
) {
|
) {
|
||||||
embeddings = embeddingModelProviders[embeddingModelProvider][
|
embeddings = embeddingModelProviders[embeddingModelProvider][
|
||||||
embeddingModel
|
embeddingModel
|
||||||
] as Embeddings | undefined;
|
] as Embeddings | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!llm || !embeddings) {
|
if (!llm || !embeddings) {
|
||||||
|
ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'error',
|
||||||
|
data: 'Invalid LLM or embeddings model selected, please refresh the page and try again.',
|
||||||
|
key: 'INVALID_MODEL_SELECTED',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.on(
|
||||||
|
'message',
|
||||||
|
async (message) =>
|
||||||
|
await handleMessage(message.toString(), ws, llm, embeddings),
|
||||||
|
);
|
||||||
|
|
||||||
|
ws.on('close', () => logger.debug('Connection closed'));
|
||||||
|
} catch (err) {
|
||||||
ws.send(
|
ws.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
data: 'Invalid LLM or embeddings model selected, please refresh the page and try again.',
|
data: 'Internal server error.',
|
||||||
key: 'INVALID_MODEL_SELECTED',
|
key: 'INTERNAL_SERVER_ERROR',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
ws.close();
|
ws.close();
|
||||||
|
logger.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
ws.on(
|
|
||||||
'message',
|
|
||||||
async (message) =>
|
|
||||||
await handleMessage(message.toString(), ws, llm, embeddings),
|
|
||||||
);
|
|
||||||
|
|
||||||
ws.on('close', () => logger.debug('Connection closed'));
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,13 +50,13 @@ const useSocket = (url: string) => {
|
|||||||
!chatModelProviders ||
|
!chatModelProviders ||
|
||||||
Object.keys(chatModelProviders).length === 0
|
Object.keys(chatModelProviders).length === 0
|
||||||
)
|
)
|
||||||
return console.error('No chat models available');
|
return toast.error('No chat models available');
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!embeddingModelProviders ||
|
!embeddingModelProviders ||
|
||||||
Object.keys(embeddingModelProviders).length === 0
|
Object.keys(embeddingModelProviders).length === 0
|
||||||
)
|
)
|
||||||
return console.error('No embedding models available');
|
return toast.error('No embedding models available');
|
||||||
|
|
||||||
chatModelProvider = Object.keys(chatModelProviders)[0];
|
chatModelProvider = Object.keys(chatModelProviders)[0];
|
||||||
chatModel = Object.keys(chatModelProviders[chatModelProvider])[0];
|
chatModel = Object.keys(chatModelProviders[chatModelProvider])[0];
|
||||||
|
|||||||
@@ -33,12 +33,8 @@ const SettingsDialog = ({
|
|||||||
const [selectedEmbeddingModel, setSelectedEmbeddingModel] = useState<
|
const [selectedEmbeddingModel, setSelectedEmbeddingModel] = useState<
|
||||||
string | null
|
string | null
|
||||||
>(null);
|
>(null);
|
||||||
const [customOpenAIApiKey, setCustomOpenAIApiKey] = useState<string | null>(
|
const [customOpenAIApiKey, setCustomOpenAIApiKey] = useState<string>('');
|
||||||
null,
|
const [customOpenAIBaseURL, setCustomOpenAIBaseURL] = useState<string>('');
|
||||||
);
|
|
||||||
const [customOpenAIBaseURL, setCustomOpenAIBaseURL] = useState<string | null>(
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isUpdating, setIsUpdating] = useState(false);
|
const [isUpdating, setIsUpdating] = useState(false);
|
||||||
|
|
||||||
@@ -51,8 +47,49 @@ const SettingsDialog = ({
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
|
||||||
|
const data = (await res.json()) as SettingsType;
|
||||||
setConfig(data);
|
setConfig(data);
|
||||||
|
|
||||||
|
const chatModelProvidersKeys = Object.keys(
|
||||||
|
data.chatModelProviders || {},
|
||||||
|
);
|
||||||
|
const embeddingModelProvidersKeys = Object.keys(
|
||||||
|
data.embeddingModelProviders || {},
|
||||||
|
);
|
||||||
|
|
||||||
|
const defaultChatModelProvider =
|
||||||
|
chatModelProvidersKeys.length > 0 ? chatModelProvidersKeys[0] : '';
|
||||||
|
const defaultEmbeddingModelProvider =
|
||||||
|
embeddingModelProvidersKeys.length > 0
|
||||||
|
? embeddingModelProvidersKeys[0]
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const chatModelProvider =
|
||||||
|
localStorage.getItem('chatModelProvider') ||
|
||||||
|
defaultChatModelProvider ||
|
||||||
|
'';
|
||||||
|
const chatModel =
|
||||||
|
localStorage.getItem('chatModel') ||
|
||||||
|
(data.chatModelProviders &&
|
||||||
|
data.chatModelProviders[chatModelProvider]?.[0]) ||
|
||||||
|
'';
|
||||||
|
const embeddingModelProvider =
|
||||||
|
localStorage.getItem('embeddingModelProvider') ||
|
||||||
|
defaultEmbeddingModelProvider ||
|
||||||
|
'';
|
||||||
|
const embeddingModel =
|
||||||
|
localStorage.getItem('embeddingModel') ||
|
||||||
|
(data.embeddingModelProviders &&
|
||||||
|
data.embeddingModelProviders[embeddingModelProvider]?.[0]) ||
|
||||||
|
'';
|
||||||
|
|
||||||
|
setSelectedChatModelProvider(chatModelProvider);
|
||||||
|
setSelectedChatModel(chatModel);
|
||||||
|
setSelectedEmbeddingModelProvider(embeddingModelProvider);
|
||||||
|
setSelectedEmbeddingModel(embeddingModel);
|
||||||
|
setCustomOpenAIApiKey(localStorage.getItem('openAIApiKey') || '');
|
||||||
|
setCustomOpenAIBaseURL(localStorage.getItem('openAIBaseUrl') || '');
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,17 +98,6 @@ const SettingsDialog = ({
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setSelectedChatModelProvider(localStorage.getItem('chatModelProvider'));
|
|
||||||
setSelectedChatModel(localStorage.getItem('chatModel'));
|
|
||||||
setSelectedEmbeddingModelProvider(
|
|
||||||
localStorage.getItem('embeddingModelProvider'),
|
|
||||||
);
|
|
||||||
setSelectedEmbeddingModel(localStorage.getItem('embeddingModel'));
|
|
||||||
setCustomOpenAIApiKey(localStorage.getItem('openAIApiKey'));
|
|
||||||
setCustomOpenAIBaseURL(localStorage.getItem('openAIBaseUrl'));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
setIsUpdating(true);
|
setIsUpdating(true);
|
||||||
|
|
||||||
@@ -226,7 +252,7 @@ const SettingsDialog = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col space-y-1">
|
<div className="flex flex-col space-y-1">
|
||||||
<p className="text-white/70 text-sm">
|
<p className="text-white/70 text-sm">
|
||||||
Custom OpenAI API Key (optional)
|
Custom OpenAI API Key
|
||||||
</p>
|
</p>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "perplexica-frontend",
|
"name": "perplexica-frontend",
|
||||||
"version": "1.3.2",
|
"version": "1.3.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "ItzCrazyKns",
|
"author": "ItzCrazyKns",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user