Merge pull request #2264 from janhq/dev
This commit is contained in:
commit
21848a93d1
10
README.md
10
README.md
@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute
|
|||||||
<tr style="text-align:center">
|
<tr style="text-align:center">
|
||||||
<td style="text-align:center"><b>Experimental (Nightly Build)</b></td>
|
<td style="text-align:center"><b>Experimental (Nightly Build)</b></td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-win-x64-0.4.7-297.exe'>
|
<a href='https://delta.jan.ai/latest/jan-win-x64-0.4.7-300.exe'>
|
||||||
<img src='./docs/static/img/windows.png' style="height:14px; width: 14px" />
|
<img src='./docs/static/img/windows.png' style="height:14px; width: 14px" />
|
||||||
<b>jan.exe</b>
|
<b>jan.exe</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-mac-x64-0.4.7-297.dmg'>
|
<a href='https://delta.jan.ai/latest/jan-mac-x64-0.4.7-300.dmg'>
|
||||||
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
||||||
<b>Intel</b>
|
<b>Intel</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-mac-arm64-0.4.7-297.dmg'>
|
<a href='https://delta.jan.ai/latest/jan-mac-arm64-0.4.7-300.dmg'>
|
||||||
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
||||||
<b>M1/M2</b>
|
<b>M1/M2</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-linux-amd64-0.4.7-297.deb'>
|
<a href='https://delta.jan.ai/latest/jan-linux-amd64-0.4.7-300.deb'>
|
||||||
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
||||||
<b>jan.deb</b>
|
<b>jan.deb</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-linux-x86_64-0.4.7-297.AppImage'>
|
<a href='https://delta.jan.ai/latest/jan-linux-x86_64-0.4.7-300.AppImage'>
|
||||||
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
||||||
<b>jan.AppImage</b>
|
<b>jan.AppImage</b>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -29,6 +29,9 @@ export type ThreadMessage = {
|
|||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown>
|
||||||
|
|
||||||
type?: string
|
type?: string
|
||||||
|
|
||||||
|
/** The error code which explain what error type. Used in conjunction with MessageStatus.Error */
|
||||||
|
error_code?: ErrorCode
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,6 +80,12 @@ export enum MessageStatus {
|
|||||||
Stopped = 'stopped',
|
Stopped = 'stopped',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ErrorCode {
|
||||||
|
InvalidApiKey = 'invalid_api_key',
|
||||||
|
|
||||||
|
Unknown = 'unknown',
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The content type of the message.
|
* The content type of the message.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -23,26 +23,26 @@ Jan is a versatile platform offering solutions for integrating AI locally across
|
|||||||
The [quickstart guide](quickstart.mdx) is designed to facilitate a quick setup process. It provides a clear instruction and simple steps to get you up and running with Jan.ai quickly. Even, if you are inexperienced in AI, the quickstart can offer valuable insights and tips to help you get started quickly.
|
The [quickstart guide](quickstart.mdx) is designed to facilitate a quick setup process. It provides a clear instruction and simple steps to get you up and running with Jan.ai quickly. Even, if you are inexperienced in AI, the quickstart can offer valuable insights and tips to help you get started quickly.
|
||||||
|
|
||||||
## Setting up the Right Models
|
## Setting up the Right Models
|
||||||
Jan offers a range of pre-configured AI models that is tailored to different tasks and industries. You should indentify which on that aligns with your objectives. There are model's factors to be considered:
|
Jan offers a range of pre-configured AI models that are tailored to different tasks and industries. You should identify which on that aligns with your objectives. There are factors to be considered:
|
||||||
- Capabilities
|
- Capabilities
|
||||||
- Accuracy
|
- Accuracy
|
||||||
- Processing Speed
|
- Processing Speed
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
Some of these factors also depends on your hardware, please see [Hardware Requirement](hardware-requiement.mdx).
|
- Some of these factors also depend on your hardware, please see Hardware Requirement.
|
||||||
|
- Choosing the right model is important to achieve the best performance.
|
||||||
:::
|
:::
|
||||||
Choosing the right model is important to achieve the best performance.
|
|
||||||
|
|
||||||
## Setting up Jan
|
## Setting up Jan
|
||||||
Ensure that you familiarize yourself with the Jan application. Jan offers advanced settings that you can adjust. These settings may influence how your AI behaves locally. Please see the [Advanced Settings](./advanced-settings/advanced-settings.mdx) article for a complete list of Jan's configurations and instructions on how to configure them.
|
Ensure that you familiarize yourself with the Jan application. Jan offers advanced settings that you can adjust. These settings may influence how your AI behaves locally. Please see the [Advanced Settings](./advanced-settings/advanced-settings.mdx) article for a complete list of Jan's configurations and instructions on how to configure them.
|
||||||
|
|
||||||
## Integrations
|
## Integrations
|
||||||
One of Jan.ai key features is its ability to integrate with many FileSystemWritableFileStream. Whether you are incorporating Jan.ai with any open-source LLM provider or other WebTransportBidirectionalStream, it is important to understand the integration capabilities and limitations.
|
One of Jan's key features is its ability to integrate with many systems. Whether you are incorporating Jan.ai with any open-source LLM provider or other tools, it is important to understand the integration capabilities and limitations.
|
||||||
|
|
||||||
## Mastering the Prompt Engineering
|
## Mastering the Prompt Engineering
|
||||||
Prompt engineering is an important aspect when dealing with AI models to generate the desired outputs. Mastering this skill can significantly enhance the performance and the responses of the AI. Below are some tips that you can do for promptengineering:
|
Prompt engineering is an important aspect when dealing with AI models to generate the desired outputs. Mastering this skill can significantly enhance the performance and the responses of the AI. Below are some tips that you can do for prompt engineering:
|
||||||
- Ask the model to adopt a persona
|
- Ask the model to adopt a persona
|
||||||
- Be specific and details get a more specific answers
|
- Be specific and details get a more specific answers
|
||||||
- Provide examples or preference text or context at the beginning
|
- Provide examples or preference text or context at the beginning
|
||||||
- Use a clear and concise language
|
- Use a clear and concise language
|
||||||
- Use a certain keywords and phrases
|
- Use certain keywords and phrases
|
||||||
|
|||||||
49
docs/docs/guides/error-codes/how-to-get-error-logs.mdx
Normal file
49
docs/docs/guides/error-codes/how-to-get-error-logs.mdx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
title: How to Get Error Logs
|
||||||
|
sidebar_position: 5
|
||||||
|
description: A step-by-step guide to get the Jan app error logs.
|
||||||
|
keywords:
|
||||||
|
[
|
||||||
|
Jan AI,
|
||||||
|
Jan,
|
||||||
|
ChatGPT alternative,
|
||||||
|
local AI,
|
||||||
|
private AI,
|
||||||
|
conversational AI,
|
||||||
|
no-subscription fee,
|
||||||
|
large language model,
|
||||||
|
troubleshooting,
|
||||||
|
permission denied,
|
||||||
|
]
|
||||||
|
---
|
||||||
|
|
||||||
|
To get the error logs of your Jan application, follow the steps below:
|
||||||
|
### Jan Application
|
||||||
|
1. Navigate to the main dashboard.
|
||||||
|
2. Click the **gear icon (⚙️)** on the bottom left of your screen.
|
||||||
|
3. Under the **Settings screen**, click the **Advanced Settings**.
|
||||||
|
4. On the **Jan Data Folder** click the **folder icon (📂)** to access the data.
|
||||||
|
5. Click the **logs** folder.
|
||||||
|
|
||||||
|
### Jan UI
|
||||||
|
1. Open your Unix or Linux terminal.
|
||||||
|
2. Use the following commands to get the recent 50 lines of log files:
|
||||||
|
```bash
|
||||||
|
tail -n 50 ~/jan/logs/app.log
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Jan API Server
|
||||||
|
1. Open your Unix or Linux terminal.
|
||||||
|
2. Use the following commands to get the recent 50 lines of log files:
|
||||||
|
```bash
|
||||||
|
tail -n 50 ~/jan/logs/server.log
|
||||||
|
|
||||||
|
```
|
||||||
|
:::warning
|
||||||
|
Ensure to redact any private or sensitive information when sharing logs or error details.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you have any questions or are looking for support, please don't hesitate to contact us via our [Discord community](https://discord.gg/Dt7MxDyNNZ) or create a new issue in our [GitHub repository](https://github.com/janhq/jan/issues/new/choose).
|
||||||
|
:::
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Manual Import
|
title: Manual Import
|
||||||
|
slug: /guides/using-models/import-manually/
|
||||||
sidebar_position: 3
|
sidebar_position: 3
|
||||||
description: A step-by-step guide on how to perform manual import feature.
|
description: A step-by-step guide on how to perform manual import feature.
|
||||||
keywords:
|
keywords:
|
||||||
|
|||||||
@ -5,58 +5,45 @@ hide_table_of_contents: true
|
|||||||
description: Manage your interaction with AI locally.
|
description: Manage your interaction with AI locally.
|
||||||
---
|
---
|
||||||
|
|
||||||
import Tabs from '@theme/Tabs';
|
|
||||||
import TabItem from '@theme/TabItem';
|
|
||||||
|
|
||||||
Jan provides a straightforward and private solution for managing your threads with AI on your own device. As you interact with AI using Jan, you'll accumulate a history of threads.
|
Jan provides a straightforward and private solution for managing your threads with AI on your own device. As you interact with AI using Jan, you'll accumulate a history of threads.
|
||||||
Jan offers easy tools to organize, delete, or review your past threads with AI. This guide will show you how to keep your threads private and well-organized.
|
Jan offers easy tools to organize, delete, or review your past threads with AI. This guide will show you how to keep your threads private and well-organized.
|
||||||
|
|
||||||
<Tabs>
|
|
||||||
<TabItem value="view" label = "View Thread History" default>
|
|
||||||
|
|
||||||
### View Thread History
|
### View Thread History
|
||||||
To view your threads history, follow the steps below:
|
To view your thread history, follow the steps below:
|
||||||
1. Navigate to the main dashboard.
|
1. Navigate to the main dashboard.
|
||||||
2. Locate the list of threads screen on the left side.
|
2. Locate the list of threads screen on the left side.
|
||||||
3. To view a specific thread, simply choose the one you're interested in and then scroll up or down to explore the entire conversation.
|
3. To view a specific thread, simply choose the one you're interested in and then scroll up or down to explore the entire conversation.
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value = "manage" label = "Managing Threads">
|
|
||||||
|
|
||||||
### Manage the Threads via Folder
|
### Manage Thread via Jan Data Folder
|
||||||
To manage your threads history and configurations, follow the steps below:
|
To manage your thread history and configurations, follow the steps below:
|
||||||
1. Navigate to the Thread that you want to manage via the list of threads on the left side of the dashboard.
|
1. Navigate to the Thread that you want to manage via the list of threads on the left side of the dashboard.
|
||||||
2. Click on the **three dots (⋮)** on the Thread section.
|
2. Click on the **three dots (⋮)** in the Thread section.
|
||||||
3. There are two available options to select:
|
3. There are two available options to select:
|
||||||
- **Reveal in Finder**: Opens the folder containing the thread history and configurations.
|
- **Reveal in Finder**: Opens the folder containing the thread history and configurations.
|
||||||
- **View as JSON**: Opens the thread.json file in your default browser.
|
- **View as JSON**: Opens the thread.json file in your default browser.
|
||||||
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value = "clean" label = "Clean Threads">
|
|
||||||
|
|
||||||
### Clean Threads History
|
### Clean Threads History
|
||||||
To clean all the messages from a thread, follow the steps below:
|
To clean all the messages from a thread, follow the steps below:
|
||||||
1. Navigate to the Thread that you want to clean.
|
1. Navigate to the Thread that you want to clean.
|
||||||
2. Click on the **three dots (⋮)** on the Thread section.
|
2. Click on the **three dots (⋮)** in the Thread section.
|
||||||
3. Sleect the **Clean Thread** button.
|
3. Sleect the **Clean Thread** button.
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
This will delete all messages in the thread, while keeping the thread settings.
|
This will delete all messages in the thread while keeping the thread settings.
|
||||||
:::
|
:::
|
||||||
</TabItem>
|
|
||||||
<TabItem value="delete" label = "Delete Thread" default>
|
|
||||||
|
|
||||||
### Delete Threads History
|
### Delete Threads History
|
||||||
To delete a thread, follow the steps below:
|
To delete a thread, follow the steps below:
|
||||||
1. Navigate to the Thread that you want to delete.
|
1. Navigate to the Thread that you want to delete.
|
||||||
2. Click on the **three dots (⋮)** on the Thread section.
|
2. Click on the **three dots (⋮)** in the Thread section.
|
||||||
3. Sleect the **Delete Thread** button.
|
3. Sleect the **Delete Thread** button.
|
||||||
|
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
This will delete all messages and the thread settings.
|
This will delete all messages and the thread settings.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</Tabs>
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: Changelog
|
title: Changelog
|
||||||
slug: /guides/changelog/
|
sidebar_position: 1
|
||||||
sidebar_position: 5
|
slug: /changelog
|
||||||
description: Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.
|
description: Jan is a ChatGPT-alternative that runs on your own computer, with a local API server.
|
||||||
keywords:
|
keywords:
|
||||||
[
|
[
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 16
|
sidebar_position: 16
|
||||||
|
slug: /changelog/changelog-v0.2.0
|
||||||
---
|
---
|
||||||
# v0.2.0
|
# v0.2.0
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 15
|
sidebar_position: 15
|
||||||
|
slug: /changelog/changelog-v0.2.1
|
||||||
---
|
---
|
||||||
# v0.2.1
|
# v0.2.1
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 14
|
sidebar_position: 14
|
||||||
|
slug: /changelog/changelog-v0.2.2
|
||||||
---
|
---
|
||||||
# v0.2.2
|
# v0.2.2
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 13
|
sidebar_position: 13
|
||||||
|
slug: /changelog/changelog-v0.2.3
|
||||||
---
|
---
|
||||||
# v0.2.3
|
# v0.2.3
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 12
|
sidebar_position: 12
|
||||||
|
slug: /changelog/changelog-v0.3.0
|
||||||
---
|
---
|
||||||
# v0.3.0
|
# v0.3.0
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 11
|
sidebar_position: 11
|
||||||
|
slug: /changelog/changelog-v0.3.1
|
||||||
---
|
---
|
||||||
# v0.3.1
|
# v0.3.1
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 10
|
sidebar_position: 10
|
||||||
|
slug: /changelog/changelog-v0.3.2
|
||||||
---
|
---
|
||||||
# v0.3.2
|
# v0.3.2
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 9
|
sidebar_position: 9
|
||||||
|
slug: /changelog/changelog-v0.3.3
|
||||||
---
|
---
|
||||||
# v0.3.3
|
# v0.3.3
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 8
|
sidebar_position: 8
|
||||||
|
slug: /changelog/changelog-v0.4.0
|
||||||
---
|
---
|
||||||
# v0.4.0
|
# v0.4.0
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 7
|
sidebar_position: 7
|
||||||
|
slug: /changelog/changelog-v0.4.1
|
||||||
---
|
---
|
||||||
# v0.4.1
|
# v0.4.1
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 6
|
sidebar_position: 6
|
||||||
|
slug: /changelog/changelog-v0.4.2
|
||||||
---
|
---
|
||||||
# v0.4.2
|
# v0.4.2
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 5
|
sidebar_position: 5
|
||||||
|
slug: /changelog/changelog-v0.4.3
|
||||||
---
|
---
|
||||||
# v0.4.3
|
# v0.4.3
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 4
|
sidebar_position: 4
|
||||||
|
slug: /changelog/changelog-v0.4.4
|
||||||
---
|
---
|
||||||
# v0.4.4
|
# v0.4.4
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 3
|
sidebar_position: 3
|
||||||
|
slug: /changelog/changelog-v0.4.5
|
||||||
---
|
---
|
||||||
# v0.4.5
|
# v0.4.5
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 2
|
sidebar_position: 2
|
||||||
|
slug: /changelog/changelog-v0.4.6
|
||||||
---
|
---
|
||||||
# v0.4.6
|
# v0.4.6
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 1
|
sidebar_position: 1
|
||||||
|
slug: /changelog/changelog-v0.4.7
|
||||||
---
|
---
|
||||||
# v0.4.7
|
# v0.4.7
|
||||||
|
|
||||||
@ -74,6 +74,38 @@ const config = {
|
|||||||
from: "/guides/troubleshooting/gpu-not-used/",
|
from: "/guides/troubleshooting/gpu-not-used/",
|
||||||
to: "/guides/common-error/not-using-gpu/",
|
to: "/guides/common-error/not-using-gpu/",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
from: "/guides/troubleshooting/",
|
||||||
|
to: "/guides/error-codes/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: "/troubleshooting/stuck-on-broken-build/",
|
||||||
|
to: "/guides/common-error/broken-build/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: "/guides/troubleshooting/",
|
||||||
|
to: "/guides/error-codes/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: "/troubleshooting/somethings-amiss/",
|
||||||
|
to: "/guides/error-codes/something-amiss/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: "/troubleshooting/how-to-get-error-logs/",
|
||||||
|
to: "/guides/error-codes/how-to-get-error-logs/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: "/troubleshooting/permission-denied/",
|
||||||
|
to: "/guides/error-codes/permission-denied/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: "/troubleshooting/unexpected-token/",
|
||||||
|
to: "/guides/error-codes/unexpected-token/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: "/troubleshooting/undefined-issue/",
|
||||||
|
to: "/guides/error-codes/undefined-issue/",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -299,7 +331,7 @@ const config = {
|
|||||||
{
|
{
|
||||||
type: "docSidebar",
|
type: "docSidebar",
|
||||||
sidebarId: "guidesSidebar",
|
sidebarId: "guidesSidebar",
|
||||||
label: "User Guide",
|
label: "Guides",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "docSidebar",
|
type: "docSidebar",
|
||||||
@ -310,6 +342,11 @@ const config = {
|
|||||||
to: "/api-reference",
|
to: "/api-reference",
|
||||||
label: "API Reference",
|
label: "API Reference",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "docSidebar",
|
||||||
|
sidebarId: "releasesSidebar",
|
||||||
|
label: "Changelog",
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// type: "docSidebar",
|
// type: "docSidebar",
|
||||||
// sidebarId: "docsSidebar",
|
// sidebarId: "docsSidebar",
|
||||||
@ -343,10 +380,6 @@ const config = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
customFields: {
|
|
||||||
githubAccessToken: process.env.GITHUB_ACCESS_TOKEN || "XXXX",
|
|
||||||
},
|
|
||||||
|
|
||||||
themes: ["@docusaurus/theme-live-codeblock", "@docusaurus/theme-mermaid"],
|
themes: ["@docusaurus/theme-live-codeblock", "@docusaurus/theme-mermaid"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -162,6 +162,12 @@ const sidebars = {
|
|||||||
dirName: "developer",
|
dirName: "developer",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
releasesSidebar: [
|
||||||
|
{
|
||||||
|
type: "autogenerated",
|
||||||
|
dirName: "releases",
|
||||||
|
},
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = sidebars;
|
module.exports = sidebars;
|
||||||
|
|||||||
BIN
docs/src/theme/DocCard/assets/logs-error.png
Normal file
BIN
docs/src/theme/DocCard/assets/logs-error.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
@ -45,6 +45,7 @@ import gpu from './assets/gpu.png';
|
|||||||
import mistral from './assets/mistral.png';
|
import mistral from './assets/mistral.png';
|
||||||
import lm from './assets/lm.png';
|
import lm from './assets/lm.png';
|
||||||
import ollama from './assets/ollama.png';
|
import ollama from './assets/ollama.png';
|
||||||
|
import logsError from './assets/logs-error.png';
|
||||||
|
|
||||||
function CardContainer({href, children}) {
|
function CardContainer({href, children}) {
|
||||||
return (
|
return (
|
||||||
@ -166,7 +167,7 @@ function CardLink({item}) {
|
|||||||
<img src={amiss} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
<img src={amiss} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
||||||
) : (item.label === "Broken Build") ? (
|
) : (item.label === "Broken Build") ? (
|
||||||
<img src={broken} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
<img src={broken} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
||||||
) : (item.label === "Jan not using GPU") ? (
|
) : (item.label === "Troubleshooting NVIDIA GPU") ? (
|
||||||
<img src={gpu} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
<img src={gpu} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
||||||
) : (item.label === "Mistral AI") ? (
|
) : (item.label === "Mistral AI") ? (
|
||||||
<img src={mistral} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
<img src={mistral} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
||||||
@ -174,10 +175,15 @@ function CardLink({item}) {
|
|||||||
<img src={lm} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
<img src={lm} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
||||||
) : (item.label === "Ollama") ? (
|
) : (item.label === "Ollama") ? (
|
||||||
<img src={ollama} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
<img src={ollama} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
||||||
|
) : (item.label === "How to Get Error Logs") ? (
|
||||||
|
<img src={logsError} alt="Logo" width={'20px'} height={'20px'} style={{marginRight: '5px'}} />
|
||||||
) : (
|
) : (
|
||||||
// If not "Customize Engine Settings", use default icon
|
// If not "Customize Engine Settings", use default icon
|
||||||
'📄️'
|
'📄️'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const doc = useDocById(item.docId ?? undefined);
|
const doc = useDocById(item.docId ?? undefined);
|
||||||
return (
|
return (
|
||||||
<CardLayout
|
<CardLayout
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import styles from "./styles.module.scss";
|
|||||||
import NavBarExtension from "../NavbarExtension";
|
import NavBarExtension from "../NavbarExtension";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
const allowedPaths = ["/docs/", "/developer/", "/api-reference/", "/guides/", "/guides", "/docs", "/developer", "/api-reference", "/guides/changelog"];
|
const allowedPaths = ["/docs/", "/developer/", "/api-reference/", "/guides/", "/guides", "/docs", "/developer", "/api-reference", "/changelog"];
|
||||||
|
|
||||||
export default function Layout(props) {
|
export default function Layout(props) {
|
||||||
const {
|
const {
|
||||||
@ -32,7 +32,8 @@ export default function Layout(props) {
|
|||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const isAllowedPath = allowedPaths.includes(location.pathname);
|
const isAllowedPath = allowedPaths.some(path => location.pathname.startsWith(path));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutProvider>
|
<LayoutProvider>
|
||||||
<PageMetadata title={title} description={description} />
|
<PageMetadata title={title} description={description} />
|
||||||
|
|||||||
@ -17,9 +17,9 @@ export default function NavBarExtension() {
|
|||||||
<NavLink
|
<NavLink
|
||||||
to="/guides"
|
to="/guides"
|
||||||
className="text-gray-700 font-medium hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-200"
|
className="text-gray-700 font-medium hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-200"
|
||||||
activeClassName={location.pathname !== "/guides/changelog" && location.pathname === "/guides" ? "text-gray-900 dark:text-gray-100 font-semibold border-b-2 border-gray-900 dark:border-gray-100" : ""}
|
activeClassName="text-gray-900 dark:text-gray-100 font-bold border-b-2 border-gray-900 dark:border-gray-100"
|
||||||
>
|
>
|
||||||
Guide
|
Guides
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/developer"
|
to="/developer"
|
||||||
@ -36,9 +36,9 @@ export default function NavBarExtension() {
|
|||||||
API Reference
|
API Reference
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/guides/changelog"
|
to="/changelog"
|
||||||
className="text-gray-700 font-medium hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-200"
|
className="text-gray-700 font-medium hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-200"
|
||||||
activeClassName={location.pathname === "/guides/changelog" ? "text-gray-900 dark:text-gray-100 font-semibold border-b-2 border-gray-900 dark:border-gray-100" : ""}
|
activeClassName="text-gray-900 dark:text-gray-100 font-bold border-b-2 border-gray-900 dark:border-gray-100"
|
||||||
>
|
>
|
||||||
Changelog
|
Changelog
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { ErrorCode } from '@janhq/core'
|
||||||
import { Observable } from 'rxjs'
|
import { Observable } from 'rxjs'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,9 +41,12 @@ export function requestInference(
|
|||||||
})
|
})
|
||||||
.then(async (response) => {
|
.then(async (response) => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
subscriber.next(
|
const data = await response.json()
|
||||||
(await response.json()).error?.message ?? 'Error occurred.'
|
const error = {
|
||||||
)
|
message: data.error?.message ?? 'An error occurred.',
|
||||||
|
code: data.error?.code ?? ErrorCode.Unknown,
|
||||||
|
}
|
||||||
|
subscriber.error(error)
|
||||||
subscriber.complete()
|
subscriber.complete()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -210,12 +210,13 @@ export default class JanInferenceOpenAIExtension extends BaseExtension {
|
|||||||
const messageContent: ThreadContent = {
|
const messageContent: ThreadContent = {
|
||||||
type: ContentType.Text,
|
type: ContentType.Text,
|
||||||
text: {
|
text: {
|
||||||
value: 'Error occurred: ' + err.message,
|
value: 'An error occurred. ' + err.message,
|
||||||
annotations: [],
|
annotations: [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
message.content = [messageContent]
|
message.content = [messageContent]
|
||||||
message.status = MessageStatus.Error
|
message.status = MessageStatus.Error
|
||||||
|
message.error_code = err.code
|
||||||
events.emit(MessageEvent.OnMessageUpdate, message)
|
events.emit(MessageEvent.OnMessageUpdate, message)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -205,7 +205,7 @@ export default class JanInferenceTritonTrtLLMExtension extends BaseExtension {
|
|||||||
const messageContent: ThreadContent = {
|
const messageContent: ThreadContent = {
|
||||||
type: ContentType.Text,
|
type: ContentType.Text,
|
||||||
text: {
|
text: {
|
||||||
value: 'Error occurred: ' + err.message,
|
value: 'An error occurred. ' + err.message,
|
||||||
annotations: [],
|
annotations: [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@janhq/model-extension",
|
"name": "@janhq/model-extension",
|
||||||
"version": "1.0.25",
|
"version": "1.0.27",
|
||||||
"description": "Model Management Extension provides model exploration and seamless downloads",
|
"description": "Model Management Extension provides model exploration and seamless downloads",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/module.js",
|
"module": "dist/module.js",
|
||||||
|
|||||||
34
models/gemma-2b/model.json
Normal file
34
models/gemma-2b/model.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"filename": "gemma-2b-it-q4_k_m.gguf",
|
||||||
|
"url": "https://huggingface.co/lmstudio-ai/gemma-2b-it-GGUF/resolve/main/gemma-2b-it-q4_k_m.gguf"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "gemma-2b",
|
||||||
|
"object": "model",
|
||||||
|
"name": "Gemma 2B Q4",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Gemma is built from the same technology with Google's Gemini.",
|
||||||
|
"format": "gguf",
|
||||||
|
"settings": {
|
||||||
|
"ctx_len": 4096,
|
||||||
|
"prompt_template": "<start_of_turn>user\n{prompt}<end_of_turn>\n<start_of_turn>model",
|
||||||
|
"llama_model_path": "gemma-2b-it-q4_k_m.gguf"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"temperature": 0.7,
|
||||||
|
"top_p": 0.95,
|
||||||
|
"stream": true,
|
||||||
|
"max_tokens": 4096,
|
||||||
|
"stop": [],
|
||||||
|
"frequency_penalty": 0,
|
||||||
|
"presence_penalty": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"author": "Google",
|
||||||
|
"tags": ["2B", "Finetuned"],
|
||||||
|
"size": 1500000000
|
||||||
|
},
|
||||||
|
"engine": "nitro"
|
||||||
|
}
|
||||||
34
models/gemma-7b/model.json
Normal file
34
models/gemma-7b/model.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"filename": "gemma-7b-it-q4_K_M.gguf",
|
||||||
|
"url": "https://huggingface.co/mmnga/gemma-7b-it-gguf/resolve/main/gemma-7b-it-q4_K_M.gguf"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "gemma-7b",
|
||||||
|
"object": "model",
|
||||||
|
"name": "Gemma 7B Q4",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Gemma is built from the same technology with Google's Gemini.",
|
||||||
|
"format": "gguf",
|
||||||
|
"settings": {
|
||||||
|
"ctx_len": 4096,
|
||||||
|
"prompt_template": "<start_of_turn>user\n{prompt}<end_of_turn>\n<start_of_turn>model",
|
||||||
|
"llama_model_path": "gemma-7b-it-q4_K_M.gguf"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"temperature": 0.7,
|
||||||
|
"top_p": 0.95,
|
||||||
|
"stream": true,
|
||||||
|
"max_tokens": 4096,
|
||||||
|
"stop": [],
|
||||||
|
"frequency_penalty": 0,
|
||||||
|
"presence_penalty": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"author": "Google",
|
||||||
|
"tags": ["7B", "Finetuned"],
|
||||||
|
"size": 5330000000
|
||||||
|
},
|
||||||
|
"engine": "nitro"
|
||||||
|
}
|
||||||
@ -28,7 +28,7 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"author": "NeverSleep",
|
"author": "NeverSleep",
|
||||||
"tags": ["7B", "Merged"],
|
"tags": ["7B", "Merged"],
|
||||||
"size": 4370000000
|
"size": 5130000000
|
||||||
},
|
},
|
||||||
"engine": "nitro"
|
"engine": "nitro"
|
||||||
}
|
}
|
||||||
|
|||||||
34
models/qwen-7b/model.json
Normal file
34
models/qwen-7b/model.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"filename": "qwen1_5-7b-chat-q4_k_m.gguf",
|
||||||
|
"url": "https://huggingface.co/Qwen/Qwen1.5-7B-Chat-GGUF/resolve/main/qwen1_5-7b-chat-q4_k_m.gguf"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "qwen-7b",
|
||||||
|
"object": "model",
|
||||||
|
"name": "Qwen Chat 7B Q4",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Qwen is optimized at Chinese, ideal for everyday tasks.",
|
||||||
|
"format": "gguf",
|
||||||
|
"settings": {
|
||||||
|
"ctx_len": 4096,
|
||||||
|
"prompt_template": "<|im_start|>system\n{system_message}<|im_end|>\n<|im_start|>user\n{prompt}<|im_end|>\n<|im_start|>assistant",
|
||||||
|
"llama_model_path": "qwen1_5-7b-chat-q4_k_m.gguf"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"temperature": 0.7,
|
||||||
|
"top_p": 0.95,
|
||||||
|
"stream": true,
|
||||||
|
"max_tokens": 4096,
|
||||||
|
"stop": [],
|
||||||
|
"frequency_penalty": 0,
|
||||||
|
"presence_penalty": 0
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"author": "Alibaba",
|
||||||
|
"tags": ["7B", "Finetuned"],
|
||||||
|
"size": 4770000000
|
||||||
|
},
|
||||||
|
"engine": "nitro"
|
||||||
|
}
|
||||||
@ -139,16 +139,11 @@ const DropdownListSidebar = ({
|
|||||||
|
|
||||||
// Update model parameter to the thread file
|
// Update model parameter to the thread file
|
||||||
if (model)
|
if (model)
|
||||||
updateModelParameter(
|
updateModelParameter(activeThread.id, {
|
||||||
activeThread.id,
|
params: modelParams,
|
||||||
{
|
modelId: model.id,
|
||||||
params: modelParams,
|
engine: model.engine,
|
||||||
modelId: model.id,
|
})
|
||||||
engine: model.engine,
|
|
||||||
},
|
|
||||||
// Overwrite the existing model parameter
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
|||||||
@ -110,7 +110,10 @@ export const deleteMessageAtom = atom(null, (get, set, id: string) => {
|
|||||||
}
|
}
|
||||||
const threadId = get(getActiveThreadIdAtom)
|
const threadId = get(getActiveThreadIdAtom)
|
||||||
if (threadId) {
|
if (threadId) {
|
||||||
newData[threadId] = newData[threadId].filter((e) => e.id !== id)
|
// Should also delete error messages to clear out the error state
|
||||||
|
newData[threadId] = newData[threadId].filter(
|
||||||
|
(e) => e.id !== id && e.status !== MessageStatus.Error
|
||||||
|
)
|
||||||
set(chatMessages, newData)
|
set(chatMessages, newData)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -109,8 +109,9 @@ export default function useSendChatMessage() {
|
|||||||
currentMessages
|
currentMessages
|
||||||
.filter(
|
.filter(
|
||||||
(e) =>
|
(e) =>
|
||||||
currentMessage.role === ChatCompletionRole.User ||
|
(currentMessage.role === ChatCompletionRole.User ||
|
||||||
e.id !== currentMessage.id
|
e.id !== currentMessage.id) &&
|
||||||
|
e.status !== MessageStatus.Error
|
||||||
)
|
)
|
||||||
.map<ChatCompletionMessage>((msg) => ({
|
.map<ChatCompletionMessage>((msg) => ({
|
||||||
role: msg.role,
|
role: msg.role,
|
||||||
@ -198,6 +199,7 @@ export default function useSendChatMessage() {
|
|||||||
})
|
})
|
||||||
.concat(
|
.concat(
|
||||||
currentMessages
|
currentMessages
|
||||||
|
.filter((e) => e.status !== MessageStatus.Error)
|
||||||
.map<ChatCompletionMessage>((msg) => ({
|
.map<ChatCompletionMessage>((msg) => ({
|
||||||
role: msg.role,
|
role: msg.role,
|
||||||
content: msg.content[0]?.text.value ?? '',
|
content: msg.content[0]?.text.value ?? '',
|
||||||
|
|||||||
@ -37,8 +37,7 @@ export default function useUpdateModelParameters() {
|
|||||||
|
|
||||||
const updateModelParameter = async (
|
const updateModelParameter = async (
|
||||||
threadId: string,
|
threadId: string,
|
||||||
settings: UpdateModelParameter,
|
settings: UpdateModelParameter
|
||||||
overwrite: boolean = false
|
|
||||||
) => {
|
) => {
|
||||||
const thread = threads.find((thread) => thread.id === threadId)
|
const thread = threads.find((thread) => thread.id === threadId)
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
@ -67,14 +66,8 @@ export default function useUpdateModelParameters() {
|
|||||||
const runtimeParams = toRuntimeParams(updatedModelParams)
|
const runtimeParams = toRuntimeParams(updatedModelParams)
|
||||||
const settingParams = toSettingParams(updatedModelParams)
|
const settingParams = toSettingParams(updatedModelParams)
|
||||||
|
|
||||||
assistant.model.parameters = {
|
assistant.model.parameters = runtimeParams
|
||||||
...(overwrite ? {} : assistant.model.parameters),
|
assistant.model.settings = settingParams
|
||||||
...runtimeParams,
|
|
||||||
}
|
|
||||||
assistant.model.settings = {
|
|
||||||
...(overwrite ? {} : assistant.model.settings),
|
|
||||||
...settingParams,
|
|
||||||
}
|
|
||||||
if (selectedModel) {
|
if (selectedModel) {
|
||||||
assistant.model.id = settings.modelId ?? selectedModel?.id
|
assistant.model.id = settings.modelId ?? selectedModel?.id
|
||||||
assistant.model.engine = settings.engine ?? selectedModel?.engine
|
assistant.model.engine = settings.engine ?? selectedModel?.engine
|
||||||
|
|||||||
@ -78,11 +78,11 @@ const ChatBody: React.FC = () => {
|
|||||||
<ScrollToBottom className="flex h-full w-full flex-col">
|
<ScrollToBottom className="flex h-full w-full flex-col">
|
||||||
{messages.map((message, index) => (
|
{messages.map((message, index) => (
|
||||||
<div key={message.id}>
|
<div key={message.id}>
|
||||||
{((message.status !== MessageStatus.Error &&
|
{message.status !== MessageStatus.Error &&
|
||||||
message.status !== MessageStatus.Pending) ||
|
message.content.length > 0 && (
|
||||||
message.content.length > 0) && (
|
<ChatItem {...message} key={message.id} />
|
||||||
<ChatItem {...message} key={message.id} />
|
)}
|
||||||
)}
|
|
||||||
{(message.status === MessageStatus.Error ||
|
{(message.status === MessageStatus.Error ||
|
||||||
message.status === MessageStatus.Stopped) &&
|
message.status === MessageStatus.Stopped) &&
|
||||||
index === messages.length - 1 && (
|
index === messages.length - 1 && (
|
||||||
|
|||||||
@ -53,10 +53,10 @@ const ChatInput: React.FC = () => {
|
|||||||
const activeThreadId = useAtomValue(getActiveThreadIdAtom)
|
const activeThreadId = useAtomValue(getActiveThreadIdAtom)
|
||||||
const [isWaitingToSend, setIsWaitingToSend] = useAtom(waitingToSendMessage)
|
const [isWaitingToSend, setIsWaitingToSend] = useAtom(waitingToSendMessage)
|
||||||
const [fileUpload, setFileUpload] = useAtom(fileUploadAtom)
|
const [fileUpload, setFileUpload] = useAtom(fileUploadAtom)
|
||||||
|
const [showAttacmentMenus, setShowAttacmentMenus] = useState(false)
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||||
const imageInputRef = useRef<HTMLInputElement>(null)
|
const imageInputRef = useRef<HTMLInputElement>(null)
|
||||||
const [showAttacmentMenus, setShowAttacmentMenus] = useState(false)
|
|
||||||
const experimentalFeature = useAtomValue(experimentalFeatureEnabledAtom)
|
const experimentalFeature = useAtomValue(experimentalFeatureEnabledAtom)
|
||||||
const isGeneratingResponse = useAtomValue(isGeneratingResponseAtom)
|
const isGeneratingResponse = useAtomValue(isGeneratingResponseAtom)
|
||||||
const threadStates = useAtomValue(threadStatesAtom)
|
const threadStates = useAtomValue(threadStatesAtom)
|
||||||
@ -165,7 +165,8 @@ const ChatInput: React.FC = () => {
|
|||||||
if (
|
if (
|
||||||
fileUpload.length > 0 ||
|
fileUpload.length > 0 ||
|
||||||
(activeThread?.assistants[0].tools &&
|
(activeThread?.assistants[0].tools &&
|
||||||
!activeThread?.assistants[0].tools[0]?.enabled)
|
!activeThread?.assistants[0].tools[0]?.enabled &&
|
||||||
|
!activeThread?.assistants[0].model.settings.vision_model)
|
||||||
) {
|
) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
} else {
|
} else {
|
||||||
@ -177,12 +178,13 @@ const ChatInput: React.FC = () => {
|
|||||||
<TooltipPortal>
|
<TooltipPortal>
|
||||||
{fileUpload.length > 0 ||
|
{fileUpload.length > 0 ||
|
||||||
(activeThread?.assistants[0].tools &&
|
(activeThread?.assistants[0].tools &&
|
||||||
!activeThread?.assistants[0].tools[0]?.enabled && (
|
!activeThread?.assistants[0].tools[0]?.enabled &&
|
||||||
|
!activeThread?.assistants[0].model.settings.vision_model && (
|
||||||
<TooltipContent side="top" className="max-w-[154px] px-3">
|
<TooltipContent side="top" className="max-w-[154px] px-3">
|
||||||
{fileUpload.length !== 0 && (
|
{fileUpload.length !== 0 && (
|
||||||
<span>
|
<span>
|
||||||
Currently, we only support 1 attachment at the same
|
Currently, we only support 1 attachment at the same
|
||||||
time
|
time.
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{activeThread?.assistants[0].tools &&
|
{activeThread?.assistants[0].tools &&
|
||||||
@ -190,7 +192,7 @@ const ChatInput: React.FC = () => {
|
|||||||
false && (
|
false && (
|
||||||
<span>
|
<span>
|
||||||
Turn on Retrieval in Assistant Settings to use this
|
Turn on Retrieval in Assistant Settings to use this
|
||||||
feature
|
feature.
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<TooltipArrow />
|
<TooltipArrow />
|
||||||
@ -206,46 +208,86 @@ const ChatInput: React.FC = () => {
|
|||||||
className="absolute bottom-10 right-0 z-30 w-36 cursor-pointer rounded-lg border border-border bg-background py-1 shadow"
|
className="absolute bottom-10 right-0 z-30 w-36 cursor-pointer rounded-lg border border-border bg-background py-1 shadow"
|
||||||
>
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<Tooltip>
|
||||||
className={twMerge(
|
<TooltipTrigger asChild>
|
||||||
'flex w-full items-center space-x-2 px-4 py-2 text-muted-foreground hover:bg-secondary',
|
<li
|
||||||
activeThread?.assistants[0].model.settings.vision_model
|
className={twMerge(
|
||||||
? 'cursor-pointer'
|
'flex w-full items-center space-x-2 px-4 py-2 text-muted-foreground hover:bg-secondary',
|
||||||
: 'cursor-not-allowed opacity-50'
|
activeThread?.assistants[0].model.settings.vision_model
|
||||||
)}
|
? 'cursor-pointer'
|
||||||
onClick={() => {
|
: 'cursor-not-allowed opacity-50'
|
||||||
if (activeThread?.assistants[0].model.settings.vision_model) {
|
)}
|
||||||
imageInputRef.current?.click()
|
onClick={() => {
|
||||||
setShowAttacmentMenus(false)
|
if (
|
||||||
}
|
activeThread?.assistants[0].model.settings.vision_model
|
||||||
}}
|
) {
|
||||||
>
|
imageInputRef.current?.click()
|
||||||
<ImageIcon size={16} />
|
setShowAttacmentMenus(false)
|
||||||
<span className="font-medium">Image</span>
|
}
|
||||||
</li>
|
}}
|
||||||
<li
|
>
|
||||||
className={twMerge(
|
<ImageIcon size={16} />
|
||||||
'flex w-full cursor-pointer items-center space-x-2 px-4 py-2 text-muted-foreground hover:bg-secondary',
|
<span className="font-medium">Image</span>
|
||||||
activeThread?.assistants[0].model.settings.vision_model &&
|
</li>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPortal>
|
||||||
|
{!activeThread?.assistants[0].model.settings.vision_model && (
|
||||||
|
<TooltipContent side="top" className="max-w-[154px] px-3">
|
||||||
|
<span>This feature only supports multimodal models.</span>
|
||||||
|
<TooltipArrow />
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</TooltipPortal>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<li
|
||||||
|
className={twMerge(
|
||||||
|
'flex w-full cursor-pointer items-center space-x-2 px-4 py-2 text-muted-foreground hover:bg-secondary',
|
||||||
|
activeThread?.assistants[0].model.settings.vision_model &&
|
||||||
|
activeThread?.assistants[0].model.settings
|
||||||
|
.text_model === false
|
||||||
|
? 'cursor-not-allowed opacity-50'
|
||||||
|
: 'cursor-pointer'
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
if (
|
||||||
|
!activeThread?.assistants[0].model.settings
|
||||||
|
.vision_model ||
|
||||||
|
activeThread?.assistants[0].model.settings
|
||||||
|
.text_model !== false
|
||||||
|
) {
|
||||||
|
fileInputRef.current?.click()
|
||||||
|
setShowAttacmentMenus(false)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FileTextIcon size={16} />
|
||||||
|
<span className="font-medium">Document</span>
|
||||||
|
</li>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPortal>
|
||||||
|
{(!activeThread?.assistants[0].tools ||
|
||||||
|
!activeThread?.assistants[0].tools[0]?.enabled ||
|
||||||
activeThread?.assistants[0].model.settings.text_model ===
|
activeThread?.assistants[0].model.settings.text_model ===
|
||||||
false
|
false) && (
|
||||||
? 'cursor-not-allowed opacity-50'
|
<TooltipContent side="top" className="max-w-[154px] px-3">
|
||||||
: 'cursor-pointer'
|
{activeThread?.assistants[0].model.settings.text_model ===
|
||||||
)}
|
false ? (
|
||||||
onClick={() => {
|
<span>
|
||||||
if (
|
This model does not support text-based retrieval.
|
||||||
!activeThread?.assistants[0].model.settings.vision_model ||
|
</span>
|
||||||
activeThread?.assistants[0].model.settings.text_model !==
|
) : (
|
||||||
false
|
<span>
|
||||||
) {
|
Turn on Retrieval in Assistant Settings to use this
|
||||||
fileInputRef.current?.click()
|
feature.
|
||||||
setShowAttacmentMenus(false)
|
</span>
|
||||||
}
|
)}
|
||||||
}}
|
<TooltipArrow />
|
||||||
>
|
</TooltipContent>
|
||||||
<FileTextIcon size={16} />
|
)}
|
||||||
<span className="font-medium">Document</span>
|
</TooltipPortal>
|
||||||
</li>
|
</Tooltip>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { MessageStatus, ThreadMessage } from '@janhq/core'
|
import { ErrorCode, MessageStatus, ThreadMessage } from '@janhq/core'
|
||||||
import { Button } from '@janhq/uikit'
|
import { Button } from '@janhq/uikit'
|
||||||
import { useAtomValue, useSetAtom } from 'jotai'
|
import { useAtomValue, useSetAtom } from 'jotai'
|
||||||
import { RefreshCcw } from 'lucide-react'
|
import { RefreshCcw } from 'lucide-react'
|
||||||
@ -10,6 +10,8 @@ import ModalTroubleShooting, {
|
|||||||
import { loadModelErrorAtom } from '@/hooks/useActiveModel'
|
import { loadModelErrorAtom } from '@/hooks/useActiveModel'
|
||||||
import useSendChatMessage from '@/hooks/useSendChatMessage'
|
import useSendChatMessage from '@/hooks/useSendChatMessage'
|
||||||
|
|
||||||
|
import { getErrorTitle } from '@/utils/errorMessage'
|
||||||
|
|
||||||
import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
|
import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
|
||||||
|
|
||||||
const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
|
const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
|
||||||
@ -25,6 +27,11 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
|
|||||||
resendChatMessage(message)
|
resendChatMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errorTitle = getErrorTitle(
|
||||||
|
message.error_code ?? ErrorCode.Unknown,
|
||||||
|
message.content[0]?.text?.value
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-10">
|
<div className="mt-10">
|
||||||
{message.status === MessageStatus.Stopped && (
|
{message.status === MessageStatus.Stopped && (
|
||||||
@ -68,7 +75,7 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
|
|||||||
key={message.id}
|
key={message.id}
|
||||||
className="flex flex-col items-center text-center text-sm font-medium text-gray-500"
|
className="flex flex-col items-center text-center text-sm font-medium text-gray-500"
|
||||||
>
|
>
|
||||||
<p>{`Apologies, something’s amiss!`}</p>
|
<p>{errorTitle}</p>
|
||||||
<p>
|
<p>
|
||||||
Jan’s in beta. Access
|
Jan’s in beta. Access
|
||||||
<span
|
<span
|
||||||
|
|||||||
@ -39,11 +39,14 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
|
|||||||
const onDeleteClick = async () => {
|
const onDeleteClick = async () => {
|
||||||
deleteMessage(message.id ?? '')
|
deleteMessage(message.id ?? '')
|
||||||
if (thread) {
|
if (thread) {
|
||||||
|
// Should also delete error messages to clear out the error state
|
||||||
await extensionManager
|
await extensionManager
|
||||||
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
.get<ConversationalExtension>(ExtensionTypeEnum.Conversational)
|
||||||
?.writeMessages(
|
?.writeMessages(
|
||||||
thread.id,
|
thread.id,
|
||||||
messages.filter((msg) => msg.id !== message.id)
|
messages.filter(
|
||||||
|
(msg) => msg.id !== message.id && msg.status !== MessageStatus.Error
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,8 +90,9 @@ const ChatScreen: React.FC = () => {
|
|||||||
if (!experimentalFeature) return
|
if (!experimentalFeature) return
|
||||||
if (
|
if (
|
||||||
e.dataTransfer.items.length === 1 &&
|
e.dataTransfer.items.length === 1 &&
|
||||||
activeThread?.assistants[0].tools &&
|
((activeThread?.assistants[0].tools &&
|
||||||
activeThread?.assistants[0].tools[0]?.enabled
|
activeThread?.assistants[0].tools[0]?.enabled) ||
|
||||||
|
activeThread?.assistants[0].model.settings.vision_model)
|
||||||
) {
|
) {
|
||||||
setDragOver(true)
|
setDragOver(true)
|
||||||
} else if (
|
} else if (
|
||||||
@ -112,7 +113,8 @@ const ChatScreen: React.FC = () => {
|
|||||||
files.length !== 1 ||
|
files.length !== 1 ||
|
||||||
rejectFiles.length !== 0 ||
|
rejectFiles.length !== 0 ||
|
||||||
(activeThread?.assistants[0].tools &&
|
(activeThread?.assistants[0].tools &&
|
||||||
!activeThread?.assistants[0].tools[0]?.enabled)
|
!activeThread?.assistants[0].tools[0]?.enabled &&
|
||||||
|
!activeThread?.assistants[0].model.settings.vision_model)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
const imageType = files[0]?.type.includes('image')
|
const imageType = files[0]?.type.includes('image')
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const ModalErrorSetDestGlobal = () => {
|
|||||||
<ModalPortal />
|
<ModalPortal />
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<ModalTitle>Error Occurred</ModalTitle>
|
<ModalTitle>An Error Occurred</ModalTitle>
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
Oops! Something went wrong. Jan data folder remains the same. Please
|
Oops! Something went wrong. Jan data folder remains the same. Please
|
||||||
|
|||||||
15
web/utils/errorMessage.ts
Normal file
15
web/utils/errorMessage.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { ErrorCode } from '@janhq/core'
|
||||||
|
|
||||||
|
export const getErrorTitle = (
|
||||||
|
errorCode: ErrorCode,
|
||||||
|
errorMessage: string | undefined
|
||||||
|
) => {
|
||||||
|
switch (errorCode) {
|
||||||
|
case ErrorCode.Unknown:
|
||||||
|
return 'Apologies, something’s amiss!'
|
||||||
|
case ErrorCode.InvalidApiKey:
|
||||||
|
return 'Invalid API key. Please check your API key and try again.'
|
||||||
|
default:
|
||||||
|
return errorMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -42,6 +42,8 @@ export const toSettingParams = (
|
|||||||
prompt_template: undefined,
|
prompt_template: undefined,
|
||||||
llama_model_path: undefined,
|
llama_model_path: undefined,
|
||||||
mmproj: undefined,
|
mmproj: undefined,
|
||||||
|
vision_model: undefined,
|
||||||
|
text_model: undefined,
|
||||||
}
|
}
|
||||||
const settingParams: ModelSettingParams = {}
|
const settingParams: ModelSettingParams = {}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user