From 760cdd29d2e04ed2659ddf2508ef0b4727a47534 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 04:39:01 +0000 Subject: [PATCH 01/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index faa04e70a..5418f1e74 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 0f3c0e34e46ce5365a921ac62f172d9b7673ae44 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 05:02:59 +0000 Subject: [PATCH 02/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5418f1e74..e75725c31 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 045e544007bd24a36c0a4940ef9c2b33bee5d9ec Mon Sep 17 00:00:00 2001 From: avb-is-me <104213687+avb-is-me@users.noreply.github.com> Date: Thu, 25 Jan 2024 06:14:47 +0000 Subject: [PATCH 03/65] adds devcontainer --- .devcontainer/devcontainer.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..f980b9df7 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "name": "jan", + "image": "node:20" +} \ No newline at end of file From 3b8e2c55852d03dbf9ed6642639e93ecbb2164d3 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 06:39:28 +0000 Subject: [PATCH 04/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e75725c31..82c3ae79b 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 0e48be67e831eccd3d501970a5c2f98eb6b37987 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 25 Jan 2024 14:05:33 +0700 Subject: [PATCH 05/65] feat: support multiple model binaries (#1659) * feat: Support multiple model binaries * fix: Update downloadModel with multiple binaries handler * feat: Add 3 models with multiple binaries * chore: fix model download * fix: model file lookup & model path * chore: add .prettierrc * chore: refactor docs * chore: bump model version * fix(capybara): add filename * fix(codeninja): add file name + llama model path * fix(default): add llama model path * fix(deepseek coder): add filename * fix(deepseek 33B): add filename * fix(dolphin mixtral): add filename * fix(llama2-chat): add filename * fix(llama2-70B): add filename * fix(mistral 7b): add filename + model path * fix(bakllava): correct size model * fix(llava-7b): correct size model * fix(llava-13b): correct size model * fix(mixtral-8x7b): add file name + modelpath * fix(noramaid-7b): add file name + modelpath * fix(openchat-7b): add file name + modelpath * fix(openhermes-7b): add file name + modelpath * fix(phi2-3b): add file name + modelpath * fix(phind): add file name + modelpath * fix(solarslerp): add file name + modelpath * fix(starling): add file name + modelpath * fix(stealth): add file name + modelpath * fix(tinyllama): add file name + modelpath * fix(trinity): add file name + modelpath * fix(tulu): add file name + modelpath * fix(wizardcoder): add file name + modelpath * fix(yi): add file name + modelpath * update from source -> sources Signed-off-by: James --------- Signed-off-by: James Co-authored-by: hiro Co-authored-by: hahuyhoang411 Co-authored-by: James --- core/.prettierignore | 5 ++ core/src/node/api/common/builder.ts | 27 ++++---- core/src/types/model/modelEntity.ts | 9 ++- docs/docs/docs/03-engineering/models.md | 54 +++++++++------- .../04-using-models/02-import-manually.mdx | 20 +++--- .../03-integrate-with-remote-server.mdx | 20 ++++-- .../02-integrate-openrouter.mdx | 10 ++- .../03-integrate-azure-openai-service.mdx | 10 ++- docs/openapi/specs/models.yaml | 56 +++++++++++------ .../src/node/index.ts | 10 ++- extensions/model-extension/package.json | 2 +- extensions/model-extension/src/index.ts | 53 +++++++++++++--- models/bakllava-1/model.json | 33 ++++++++++ models/capybara-34b/model.json | 61 +++++++++--------- models/codeninja-1.0-7b/model.json | 60 +++++++++--------- models/config/default-model.json | 10 ++- models/deepseek-coder-1.3b/model.json | 61 +++++++++--------- models/deepseek-coder-34b/model.json | 61 +++++++++--------- models/dolphin-2.7-mixtral-8x7b/model.json | 60 ++++++++++-------- models/gpt-3.5-turbo-16k-0613/model.json | 34 +++++----- models/gpt-3.5-turbo/model.json | 34 +++++----- models/gpt-4/model.json | 34 +++++----- models/llama2-chat-70b-q4/model.json | 61 +++++++++--------- models/llama2-chat-7b-q4/model.json | 61 +++++++++--------- models/llava-1.5-13b-q5/model.json | 33 ++++++++++ models/llava-1.5-7b-q5/model.json | 33 ++++++++++ models/mistral-ins-7b-q4/model.json | 63 ++++++++++--------- models/mixtral-8x7b-instruct/model.json | 59 +++++++++-------- models/noromaid-7b/model.json | 61 +++++++++--------- models/openchat-3.5-7b/model.json | 60 ++++++++++-------- models/openhermes-neural-7b/model.json | 61 +++++++++--------- models/phi-2-3b/model.json | 61 +++++++++--------- models/phind-34b/model.json | 61 +++++++++--------- models/solar-10.7b-slerp/model.json | 60 +++++++++--------- models/starling-7b/model.json | 61 +++++++++--------- models/stealth-v1.2-7b/model.json | 63 ++++++++++--------- models/tinyllama-1.1b/model.json | 20 +++--- models/trinity-v1.2-7b/model.json | 61 +++++++++--------- models/tulu-2-70b/model.json | 59 +++++++++-------- models/wizardcoder-13b/model.json | 61 +++++++++--------- models/yarn-mistral-7b/model.json | 58 ++++++++--------- models/yi-34b/model.json | 61 +++++++++--------- web/containers/Providers/EventListener.tsx | 1 + web/hooks/useDownloadModel.ts | 20 ++++++ web/hooks/useGetConfiguredModels.ts | 4 +- web/hooks/useGetDownloadedModels.ts | 5 +- web/hooks/useRecommendedModel.ts | 1 + web/hooks/useSettings.ts | 1 + web/package.json | 2 +- .../ExploreModelItemHeader/index.tsx | 10 ++- web/types/downloadState.d.ts | 2 + web/utils/model.ts | 2 +- web/utils/modelParam.ts | 2 + 53 files changed, 1117 insertions(+), 775 deletions(-) create mode 100644 core/.prettierignore create mode 100644 models/bakllava-1/model.json create mode 100644 models/llava-1.5-13b-q5/model.json create mode 100644 models/llava-1.5-7b-q5/model.json diff --git a/core/.prettierignore b/core/.prettierignore new file mode 100644 index 000000000..02d9145c1 --- /dev/null +++ b/core/.prettierignore @@ -0,0 +1,5 @@ +.next/ +node_modules/ +dist/ +*.hbs +*.mdx \ No newline at end of file diff --git a/core/src/node/api/common/builder.ts b/core/src/node/api/common/builder.ts index 14946f415..a9819bce6 100644 --- a/core/src/node/api/common/builder.ts +++ b/core/src/node/api/common/builder.ts @@ -265,19 +265,22 @@ export const downloadModel = async ( const modelBinaryPath = join(directoryPath, modelId) const request = require('request') - const rq = request({ url: model.source_url, strictSSL, proxy }) const progress = require('request-progress') - progress(rq, {}) - .on('progress', function (state: any) { - console.log('progress', JSON.stringify(state, null, 2)) - }) - .on('error', function (err: Error) { - console.error('error', err) - }) - .on('end', function () { - console.log('end') - }) - .pipe(fs.createWriteStream(modelBinaryPath)) + + for (const source of model.sources) { + const rq = request({ url: source, strictSSL, proxy }) + progress(rq, {}) + .on('progress', function (state: any) { + console.debug('progress', JSON.stringify(state, null, 2)) + }) + .on('error', function (err: Error) { + console.error('error', err) + }) + .on('end', function () { + console.debug('end') + }) + .pipe(fs.createWriteStream(modelBinaryPath)) + } return { message: `Starting download ${modelId}`, diff --git a/core/src/types/model/modelEntity.ts b/core/src/types/model/modelEntity.ts index 80adc9e96..c60ab7650 100644 --- a/core/src/types/model/modelEntity.ts +++ b/core/src/types/model/modelEntity.ts @@ -21,6 +21,11 @@ export enum InferenceEngine { hf_endpoint = 'hf_endpoint', } +export type ModelArtifact = { + filename: string + url: string +} + /** * Model type defines the shape of a model object. * @stored @@ -45,7 +50,7 @@ export type Model = { /** * The model download source. It can be an external url or a local filepath. */ - source_url: string + sources: ModelArtifact[] /** * The model identifier, which can be referenced in the API endpoints. @@ -107,6 +112,8 @@ export type ModelSettingParams = { system_prompt?: string ai_prompt?: string user_prompt?: string + llama_model_path?: string + mmproj?: string } /** diff --git a/docs/docs/docs/03-engineering/models.md b/docs/docs/docs/03-engineering/models.md index cb0b44f41..4e4c3c604 100644 --- a/docs/docs/docs/03-engineering/models.md +++ b/docs/docs/docs/03-engineering/models.md @@ -56,7 +56,6 @@ jan/ # Jan root folder - Each `model` folder contains a `model.json` file, which is a representation of a model. - `model.json` contains metadata and default parameters used to run a model. -- The only required field is `source_url`. ### Example @@ -64,36 +63,43 @@ Here's a standard example `model.json` for a GGUF model. ```js { -"id": "zephyr-7b", // Defaults to foldername -"object": "model", // Defaults to "model" -"source_url": "https://huggingface.co/TheBloke/zephyr-7B-beta-GGUF/blob/main/zephyr-7b-beta.Q4_K_M.gguf", -"name": "Zephyr 7B", // Defaults to foldername -"owned_by": "you", // Defaults to "you" -"version": "1", // Defaults to 1 -"created": 1231231, // Defaults to file creation time -"description": null, // Defaults to null -"state": enum[null, "ready"] -"format": "ggufv3", // Defaults to "ggufv3" -"engine": "nitro", // engine_id specified in jan/engine folder -"engine_parameters": { // Engine parameters inside model.json can override - "ctx_len": 2048, // the value inside the base engine.json + "id": "zephyr-7b", // Defaults to foldername + "object": "model", // Defaults to "model" + "sources": [ + { + "filename": "zephyr-7b-beta.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/zephyr-7B-beta-GGUF/blob/main/zephyr-7b-beta.Q4_K_M.gguf" + } + ], + "name": "Zephyr 7B", // Defaults to foldername + "owned_by": "you", // Defaults to "you" + "version": "1", // Defaults to 1 + "created": 1231231, // Defaults to file creation time + "description": null, // Defaults to null + "format": "ggufv3", // Defaults to "ggufv3" + "engine": "nitro", // engine_id specified in jan/engine folder + "engine_parameters": { + // Engine parameters inside model.json can override + "ctx_len": 4096, // the value inside the base engine.json "ngl": 100, "embedding": true, - "n_parallel": 4, -}, -"model_parameters": { // Models are called parameters + "n_parallel": 4 + }, + "model_parameters": { + // Models are called parameters "stream": true, - "max_tokens": 2048, - "stop": [""], // This usually can be left blank, only used with specific need from model author + "max_tokens": 4096, + "stop": [""], // This usually can be left blank, only used with specific need from model author "frequency_penalty": 0, "presence_penalty": 0, "temperature": 0.7, "top_p": 0.95 -}, -"metadata": {}, // Defaults to {} -"assets": [ // Defaults to current dir - "file://.../zephyr-7b-q4_k_m.bin", -] + }, + "metadata": {}, // Defaults to {} + "assets": [ + // Defaults to current dir + "file://.../zephyr-7b-q4_k_m.bin" + ] } ``` diff --git a/docs/docs/guides/04-using-models/02-import-manually.mdx b/docs/docs/guides/04-using-models/02-import-manually.mdx index f5ecb5259..68142a8af 100644 --- a/docs/docs/guides/04-using-models/02-import-manually.mdx +++ b/docs/docs/guides/04-using-models/02-import-manually.mdx @@ -31,7 +31,6 @@ In this section, we will show you how to import a GGUF model from [HuggingFace]( ## Manually Importing a Downloaded Model (nightly versions and v0.4.4+) - ### 1. Create a Model Folder Navigate to the `~/jan/models` folder. You can find this folder by going to `App Settings` > `Advanced` > `Open App Directory`. @@ -92,7 +91,7 @@ Drag and drop your model binary into this folder, ensuring the `modelname.gguf` #### 3. Voila -If your model doesn't show up in the Model Selector in conversations, please restart the app. +If your model doesn't show up in the Model Selector in conversations, please restart the app. If that doesn't work, please feel free to join our [Discord community](https://discord.gg/Dt7MxDyNNZ) for support, updates, and discussions. @@ -190,14 +189,18 @@ Edit `model.json` and include the following configurations: - Ensure the filename must be `model.json`. - Ensure the `id` property matches the folder name you created. - Ensure the GGUF filename should match the `id` property exactly. -- Ensure the `source_url` property is the direct binary download link ending in `.gguf`. In HuggingFace, you can find the direct links in the `Files and versions` tab. +- Ensure the `source.url` property is the direct binary download link ending in `.gguf`. In HuggingFace, you can find the direct links in the `Files and versions` tab. - Ensure you are using the correct `prompt_template`. This is usually provided in the HuggingFace model's description page. -- Ensure the `state` property is set to `ready`. ```json title="model.json" { // highlight-start - "source_url": "https://huggingface.co/janhq/trinity-v1-GGUF/resolve/main/trinity-v1.Q4_K_M.gguf", + "sources": [ + { + "filename": "trinity-v1.Q4_K_M.gguf", + "url": "https://huggingface.co/janhq/trinity-v1-GGUF/resolve/main/trinity-v1.Q4_K_M.gguf" + } + ], "id": "trinity-v1-7b", // highlight-end "object": "model", @@ -208,7 +211,8 @@ Edit `model.json` and include the following configurations: "settings": { "ctx_len": 4096, // highlight-next-line - "prompt_template": "{system_message}\n### Instruction:\n{prompt}\n### Response:" + "prompt_template": "{system_message}\n### Instruction:\n{prompt}\n### Response:", + "llama_model_path": "trinity-v1.Q4_K_M.gguf" }, "parameters": { "max_tokens": 4096 @@ -218,9 +222,7 @@ Edit `model.json` and include the following configurations: "tags": ["7B", "Merged"], "size": 4370000000 }, - "engine": "nitro", - // highlight-next-line - "state": "ready" + "engine": "nitro" } ``` diff --git a/docs/docs/guides/04-using-models/03-integrate-with-remote-server.mdx b/docs/docs/guides/04-using-models/03-integrate-with-remote-server.mdx index 3ed15bc9f..533797fca 100644 --- a/docs/docs/guides/04-using-models/03-integrate-with-remote-server.mdx +++ b/docs/docs/guides/04-using-models/03-integrate-with-remote-server.mdx @@ -40,7 +40,12 @@ Navigate to the `~/jan/models` folder. Create a folder named `gpt-3.5-turbo-16k` ```json title="~/jan/models/gpt-3.5-turbo-16k/model.json" { - "source_url": "https://openai.com", + "sources": [ + { + "filename": "openai", + "url": "https://openai.com" + } + ], // highlight-next-line "id": "gpt-3.5-turbo-16k", "object": "model", @@ -55,8 +60,7 @@ Navigate to the `~/jan/models` folder. Create a folder named `gpt-3.5-turbo-16k` "author": "OpenAI", "tags": ["General", "Big Context Length"] }, - "engine": "openai", - "state": "ready" + "engine": "openai" // highlight-end } ``` @@ -118,7 +122,12 @@ Navigate to the `~/jan/models` folder. Create a folder named `mistral-ins-7b-q4` ```json title="~/jan/models/mistral-ins-7b-q4/model.json" { - "source_url": "https://jan.ai", + "sources": [ + { + "filename": "janai", + "url": "https://jan.ai" + } + ], // highlight-next-line "id": "mistral-ins-7b-q4", "object": "model", @@ -134,8 +143,7 @@ Navigate to the `~/jan/models` folder. Create a folder named `mistral-ins-7b-q4` "tags": ["remote", "awesome"] }, // highlight-start - "engine": "openai", - "state": "ready" + "engine": "openai" // highlight-end } ``` diff --git a/docs/docs/guides/07-integrations/02-integrate-openrouter.mdx b/docs/docs/guides/07-integrations/02-integrate-openrouter.mdx index 8623a1a4a..e0db0e336 100644 --- a/docs/docs/guides/07-integrations/02-integrate-openrouter.mdx +++ b/docs/docs/guides/07-integrations/02-integrate-openrouter.mdx @@ -49,7 +49,12 @@ Navigate to the `~/jan/models` folder. Create a folder named ` 1) { + // path to model binaries + for (const source of model.sources) { + let path = this.extractFileName(source.url) + if (source.filename) { + path = await joinPath([modelDirPath, source.filename]) + } + + downloadFile(source.url, path, network) + } + } else { + const fileName = this.extractFileName(model.sources[0]?.url) + const path = await joinPath([modelDirPath, fileName]) + downloadFile(model.sources[0]?.url, path, network) + } + } + + /** + * try to retrieve the download file name from the source url + */ + private extractFileName(url: string): string { + const extractedFileName = url.split('/').pop() const fileName = extractedFileName .toLowerCase() .endsWith(JanModelExtension._supportedModelFormat) ? extractedFileName - : model.id - const path = await joinPath([modelDirPath, fileName]) - downloadFile(model.source_url, path, network) + : extractedFileName + JanModelExtension._supportedModelFormat + return fileName } /** @@ -98,6 +116,7 @@ export default class JanModelExtension extends ModelExtension { * @returns {Promise} A promise that resolves when the download has been cancelled. */ async cancelModelDownload(modelId: string): Promise { + const model = await this.getConfiguredModels() return abortDownload( await joinPath([JanModelExtension._homeDir, modelId, modelId]) ).then(async () => { @@ -163,15 +182,16 @@ export default class JanModelExtension extends ModelExtension { .then((files: string[]) => { // or model binary exists in the directory // model binary name can match model ID or be a .gguf file and not be an incompleted model file + // TODO: Check diff between urls, filenames return ( files.includes(modelDir) || - files.some( + files.filter( (file) => file .toLowerCase() .includes(JanModelExtension._supportedModelFormat) && !file.endsWith(JanModelExtension._incompletedModelFileName) - ) + )?.length >= model.sources.length ) }) } @@ -198,7 +218,6 @@ export default class JanModelExtension extends ModelExtension { const readJsonPromises = allDirectories.map(async (dirName) => { // filter out directories that don't match the selector - // read model.json const jsonPath = await joinPath([ JanModelExtension._homeDir, @@ -226,7 +245,21 @@ export default class JanModelExtension extends ModelExtension { const modelData = results.map((result) => { if (result.status === 'fulfilled') { try { - return result.value as Model + // This to ensure backward compatibility with `model.json` with `source_url` + const tmpModel = + typeof result.value === 'object' + ? result.value + : JSON.parse(result.value) + if (tmpModel['source_url'] != null) { + tmpModel['source'] = [ + { + filename: tmpModel.id, + url: tmpModel['source_url'], + }, + ] + } + + return tmpModel as Model } catch { console.debug(`Unable to parse model metadata: ${result.value}`) return undefined diff --git a/models/bakllava-1/model.json b/models/bakllava-1/model.json new file mode 100644 index 000000000..91f6f4136 --- /dev/null +++ b/models/bakllava-1/model.json @@ -0,0 +1,33 @@ +{ + "sources": [ + { + "filename": "ggml-model-q5_k.gguf", + "url": "https://huggingface.co/mys/ggml_bakllava-1/resolve/main/ggml-model-q5_k.gguf" + }, + { + "filename": "mmproj-model-f16.gguf", + "url": "https://huggingface.co/mys/ggml_bakllava-1/resolve/main/mmproj-model-f16.gguf" + } + ], + "id": "bakllava-1", + "object": "model", + "name": "BakLlava 1", + "version": "1.0", + "description": "BakLlava 1 can bring vision understanding to Jan", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "\n### Instruction:\n{prompt}\n### Response:\n", + "llama_model_path": "ggml-model-q5_k.gguf", + "mmproj": "mmproj-model-f16.gguf" + }, + "parameters": { + "max_tokens": 4096 + }, + "metadata": { + "author": "Mys", + "tags": ["Vision"], + "size": 5750000000 + }, + "engine": "nitro" +} diff --git a/models/capybara-34b/model.json b/models/capybara-34b/model.json index ffca28c6d..af029bbb0 100644 --- a/models/capybara-34b/model.json +++ b/models/capybara-34b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/Nous-Capybara-34B-GGUF/resolve/main/nous-capybara-34b.Q5_K_M.gguf", - "id": "capybara-34b", - "object": "model", - "name": "Capybara 200k 34B Q5", - "version": "1.0", - "description": "Nous Capybara 34B is a long context length model that supports 200K tokens.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "USER:\n{prompt}\nASSISTANT:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "NousResearch, The Bloke", - "tags": ["34B", "Finetuned"], - "size": 24320000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "nous-capybara-34b.Q5_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Nous-Capybara-34B-GGUF/resolve/main/nous-capybara-34b.Q5_K_M.gguf" + } + ], + "id": "capybara-34b", + "object": "model", + "name": "Capybara 200k 34B Q5", + "version": "1.0", + "description": "Nous Capybara 34B is a long context length model that supports 200K tokens.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "USER:\n{prompt}\nASSISTANT:", + "llama_model_path": "nous-capybara-34b.Q5_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": "NousResearch, The Bloke", + "tags": ["34B", "Finetuned"], + "size": 24320000000 + }, + "engine": "nitro" +} diff --git a/models/codeninja-1.0-7b/model.json b/models/codeninja-1.0-7b/model.json index 98fbac5df..4ffe355d1 100644 --- a/models/codeninja-1.0-7b/model.json +++ b/models/codeninja-1.0-7b/model.json @@ -1,29 +1,33 @@ { - "source_url": "https://huggingface.co/beowolx/CodeNinja-1.0-OpenChat-7B-GGUF/resolve/main/codeninja-1.0-openchat-7b.Q4_K_M.gguf", - "id": "codeninja-1.0-7b", - "object": "model", - "name": "CodeNinja 7B Q4", - "version": "1.0", - "description": "CodeNinja is good for coding tasks and can handle various languages including Python, C, C++, Rust, Java, JavaScript, and more.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "GPT4 Correct User: {prompt}<|end_of_turn|>GPT4 Correct Assistant:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": ["<|end_of_turn|>"], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Beowolx", - "tags": ["7B", "Finetuned"], - "size": 4370000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "codeninja-1.0-openchat-7b.Q4_K_M.gguf", + "url": "https://huggingface.co/beowolx/CodeNinja-1.0-OpenChat-7B-GGUF/resolve/main/codeninja-1.0-openchat-7b.Q4_K_M.gguf" + } + ], + "id": "codeninja-1.0-7b", + "object": "model", + "name": "CodeNinja 7B Q4", + "version": "1.0", + "description": "CodeNinja is good for coding tasks and can handle various languages including Python, C, C++, Rust, Java, JavaScript, and more.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "GPT4 Correct User: {prompt}<|end_of_turn|>GPT4 Correct Assistant:", + "llama_model_path": "codeninja-1.0-openchat-7b.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Beowolx", + "tags": ["7B", "Finetuned"], + "size": 4370000000 + }, + "engine": "nitro" +} diff --git a/models/config/default-model.json b/models/config/default-model.json index 2263625f4..2fa2df2ee 100644 --- a/models/config/default-model.json +++ b/models/config/default-model.json @@ -2,7 +2,12 @@ "object": "model", "version": 1, "format": "gguf", - "source_url": "N/A", + "sources": [ + { + "url": "N/A", + "filename": "N/A" + } + ], "id": "N/A", "name": "N/A", "created": 0, @@ -10,7 +15,8 @@ "settings": { "ctx_len": 4096, "embedding": false, - "prompt_template": "{system_message}\n### Instruction: {prompt}\n### Response:" + "prompt_template": "{system_message}\n### Instruction: {prompt}\n### Response:", + "llama_model_path": "N/A" }, "parameters": { "temperature": 0.7, diff --git a/models/deepseek-coder-1.3b/model.json b/models/deepseek-coder-1.3b/model.json index 8c454802f..365dbfd2f 100644 --- a/models/deepseek-coder-1.3b/model.json +++ b/models/deepseek-coder-1.3b/model.json @@ -1,29 +1,34 @@ - { - "source_url": "https://huggingface.co/TheBloke/deepseek-coder-1.3b-instruct-GGUF/resolve/main/deepseek-coder-1.3b-instruct.Q8_0.gguf", - "id": "deepseek-coder-1.3b", - "object": "model", - "name": "Deepseek Coder 1.3B Q8", - "version": "1.0", - "description": "Deepseek Coder excelled in project-level code completion with advanced capabilities across multiple programming languages.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "### Instruction:\n{prompt}\n### Response:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Deepseek, The Bloke", - "tags": ["Tiny", "Foundational Model"], - "size": 1430000000 - }, - "engine": "nitro" - } + "sources": [ + { + "filename": "deepseek-coder-1.3b-instruct.Q8_0.gguf", + "url": "https://huggingface.co/TheBloke/deepseek-coder-1.3b-instruct-GGUF/resolve/main/deepseek-coder-1.3b-instruct.Q8_0.gguf" + } + ], + "id": "deepseek-coder-1.3b", + "object": "model", + "name": "Deepseek Coder 1.3B Q8", + "version": "1.0", + "description": "Deepseek Coder excelled in project-level code completion with advanced capabilities across multiple programming languages.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "### Instruction:\n{prompt}\n### Response:", + "llama_model_path": "deepseek-coder-1.3b-instruct.Q8_0.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "stop": [], + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Deepseek, The Bloke", + "tags": ["Tiny", "Foundational Model"], + "size": 1430000000 + }, + "engine": "nitro" +} diff --git a/models/deepseek-coder-34b/model.json b/models/deepseek-coder-34b/model.json index 905a66033..8e17b9563 100644 --- a/models/deepseek-coder-34b/model.json +++ b/models/deepseek-coder-34b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/deepseek-coder-33B-instruct-GGUF/resolve/main/deepseek-coder-33b-instruct.Q5_K_M.gguf", - "id": "deepseek-coder-34b", - "object": "model", - "name": "Deepseek Coder 33B Q5", - "version": "1.0", - "description": "Deepseek Coder excelled in project-level code completion with advanced capabilities across multiple programming languages.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "### Instruction:\n{prompt}\n### Response:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Deepseek, The Bloke", - "tags": ["34B", "Foundational Model"], - "size": 19940000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "deepseek-coder-33b-instruct.Q5_K_M.gguf", + "url": "https://huggingface.co/TheBloke/deepseek-coder-33B-instruct-GGUF/resolve/main/deepseek-coder-33b-instruct.Q5_K_M.gguf" + } + ], + "id": "deepseek-coder-34b", + "object": "model", + "name": "Deepseek Coder 33B Q5", + "version": "1.0", + "description": "Deepseek Coder excelled in project-level code completion with advanced capabilities across multiple programming languages.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "### Instruction:\n{prompt}\n### Response:", + "llama_model_path": "deepseek-coder-33b-instruct.Q5_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": "Deepseek, The Bloke", + "tags": ["34B", "Foundational Model"], + "size": 19940000000 + }, + "engine": "nitro" +} diff --git a/models/dolphin-2.7-mixtral-8x7b/model.json b/models/dolphin-2.7-mixtral-8x7b/model.json index 67bc6737c..7df4fbfbd 100644 --- a/models/dolphin-2.7-mixtral-8x7b/model.json +++ b/models/dolphin-2.7-mixtral-8x7b/model.json @@ -1,28 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/dolphin-2.7-mixtral-8x7b-GGUF/resolve/main/dolphin-2.7-mixtral-8x7b.Q4_K_M.gguf", - "id": "dolphin-2.7-mixtral-8x7b", - "object": "model", - "name": "Dolphin 8x7B Q4", - "version": "1.0", - "description": "Dolphin is an uncensored model built on Mixtral-8x7b. It is good at programming 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" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Cognitive Computations, TheBloke", - "tags": ["70B", "Finetuned"], - "size": 26440000000 - }, - "engine": "nitro" - } + "sources": [ + { + "filename": "dolphin-2.7-mixtral-8x7b.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/dolphin-2.7-mixtral-8x7b-GGUF/resolve/main/dolphin-2.7-mixtral-8x7b.Q4_K_M.gguf" + } + ], + "id": "dolphin-2.7-mixtral-8x7b", + "object": "model", + "name": "Dolphin 8x7B Q4", + "version": "1.0", + "description": "Dolphin is an uncensored model built on Mixtral-8x7b. It is good at programming 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": "dolphin-2.7-mixtral-8x7b.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": "Cognitive Computations, TheBloke", + "tags": ["70B", "Finetuned"], + "size": 26440000000 + }, + "engine": "nitro" +} diff --git a/models/gpt-3.5-turbo-16k-0613/model.json b/models/gpt-3.5-turbo-16k-0613/model.json index 0df4119a5..aa57e1154 100644 --- a/models/gpt-3.5-turbo-16k-0613/model.json +++ b/models/gpt-3.5-turbo-16k-0613/model.json @@ -1,18 +1,20 @@ { - "source_url": "https://openai.com", - "id": "gpt-3.5-turbo-16k-0613", - "object": "model", - "name": "OpenAI GPT 3.5 Turbo 16k 0613", - "version": "1.0", - "description": "OpenAI GPT 3.5 Turbo 16k 0613 model is extremely good", - "format": "api", - "settings": {}, - "parameters": {}, - "metadata": { - "author": "OpenAI", - "tags": ["General", "Big Context Length"] - }, - "engine": "openai", - "state": "ready" + "sources": [ + { + "url": "https://openai.com" + } + ], + "id": "gpt-3.5-turbo-16k-0613", + "object": "model", + "name": "OpenAI GPT 3.5 Turbo 16k 0613", + "version": "1.0", + "description": "OpenAI GPT 3.5 Turbo 16k 0613 model is extremely good", + "format": "api", + "settings": {}, + "parameters": {}, + "metadata": { + "author": "OpenAI", + "tags": ["General", "Big Context Length"] + }, + "engine": "openai" } - \ No newline at end of file diff --git a/models/gpt-3.5-turbo/model.json b/models/gpt-3.5-turbo/model.json index a7dbf3d4e..617f0d056 100644 --- a/models/gpt-3.5-turbo/model.json +++ b/models/gpt-3.5-turbo/model.json @@ -1,18 +1,20 @@ { - "source_url": "https://openai.com", - "id": "gpt-3.5-turbo", - "object": "model", - "name": "OpenAI GPT 3.5 Turbo", - "version": "1.0", - "description": "OpenAI GPT 3.5 Turbo model is extremely good", - "format": "api", - "settings": {}, - "parameters": {}, - "metadata": { - "author": "OpenAI", - "tags": ["General", "Big Context Length"] - }, - "engine": "openai", - "state": "ready" + "sources": [ + { + "url": "https://openai.com" + } + ], + "id": "gpt-3.5-turbo", + "object": "model", + "name": "OpenAI GPT 3.5 Turbo", + "version": "1.0", + "description": "OpenAI GPT 3.5 Turbo model is extremely good", + "format": "api", + "settings": {}, + "parameters": {}, + "metadata": { + "author": "OpenAI", + "tags": ["General", "Big Context Length"] + }, + "engine": "openai" } - \ No newline at end of file diff --git a/models/gpt-4/model.json b/models/gpt-4/model.json index 3f17e65cb..7aa2338e3 100644 --- a/models/gpt-4/model.json +++ b/models/gpt-4/model.json @@ -1,18 +1,20 @@ { - "source_url": "https://openai.com", - "id": "gpt-4", - "object": "model", - "name": "OpenAI GPT 4", - "version": "1.0", - "description": "OpenAI GPT 4 model is extremely good", - "format": "api", - "settings": {}, - "parameters": {}, - "metadata": { - "author": "OpenAI", - "tags": ["General", "Big Context Length"] - }, - "engine": "openai", - "state": "ready" + "sources": [ + { + "url": "https://openai.com" + } + ], + "id": "gpt-4", + "object": "model", + "name": "OpenAI GPT 4", + "version": "1.0", + "description": "OpenAI GPT 4 model is extremely good", + "format": "api", + "settings": {}, + "parameters": {}, + "metadata": { + "author": "OpenAI", + "tags": ["General", "Big Context Length"] + }, + "engine": "openai" } - \ No newline at end of file diff --git a/models/llama2-chat-70b-q4/model.json b/models/llama2-chat-70b-q4/model.json index 2595ab677..2459e426f 100644 --- a/models/llama2-chat-70b-q4/model.json +++ b/models/llama2-chat-70b-q4/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/Llama-2-70B-Chat-GGUF/resolve/main/llama-2-70b-chat.Q4_K_M.gguf", - "id": "llama2-chat-70b-q4", - "object": "model", - "name": "Llama 2 Chat 70B Q4", - "version": "1.0", - "description": "Llama 2 Chat 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "[INST] <>\n{system_message}<>\n{prompt}[/INST]" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "MetaAI, The Bloke", - "tags": ["70B", "Foundational Model"], - "size": 43920000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "llama-2-70b-chat.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Llama-2-70B-Chat-GGUF/resolve/main/llama-2-70b-chat.Q4_K_M.gguf" + } + ], + "id": "llama2-chat-70b-q4", + "object": "model", + "name": "Llama 2 Chat 70B Q4", + "version": "1.0", + "description": "Llama 2 Chat 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "[INST] <>\n{system_message}<>\n{prompt}[/INST]", + "llama_model_path": "llama-2-70b-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": "MetaAI, The Bloke", + "tags": ["70B", "Foundational Model"], + "size": 43920000000 + }, + "engine": "nitro" +} diff --git a/models/llama2-chat-7b-q4/model.json b/models/llama2-chat-7b-q4/model.json index 68eab3790..bc9847eef 100644 --- a/models/llama2-chat-7b-q4/model.json +++ b/models/llama2-chat-7b-q4/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf", - "id": "llama2-chat-7b-q4", - "object": "model", - "name": "Llama 2 Chat 7B Q4", - "version": "1.0", - "description": "Llama 2 Chat 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "[INST] <>\n{system_message}<>\n{prompt}[/INST]" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "MetaAI, The Bloke", - "tags": ["7B", "Foundational Model"], - "size": 4080000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "llama-2-7b-chat.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf" + } + ], + "id": "llama2-chat-7b-q4", + "object": "model", + "name": "Llama 2 Chat 7B Q4", + "version": "1.0", + "description": "Llama 2 Chat 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "[INST] <>\n{system_message}<>\n{prompt}[/INST]", + "llama_model_path": "llama-2-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": "MetaAI, The Bloke", + "tags": ["7B", "Foundational Model"], + "size": 4080000000 + }, + "engine": "nitro" +} diff --git a/models/llava-1.5-13b-q5/model.json b/models/llava-1.5-13b-q5/model.json new file mode 100644 index 000000000..027b8398f --- /dev/null +++ b/models/llava-1.5-13b-q5/model.json @@ -0,0 +1,33 @@ +{ + "sources": [ + { + "filename": "ggml-model-q5_k.gguf", + "url": "https://huggingface.co/mys/ggml_llava-v1.5-13b/resolve/main/ggml-model-q5_k.gguf" + }, + { + "filename": "mmproj-model-f16.gguf", + "url": "https://huggingface.co/mys/ggml_llava-v1.5-13b/resolve/main/mmproj-model-f16.gguf" + } + ], + "id": "llava-1.5-13b-q5", + "object": "model", + "name": "LlaVa 1.5 13B Q5 K", + "version": "1.0", + "description": "LlaVa 1.5 can bring vision understanding to Jan", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "\n### Instruction:\n{prompt}\n### Response:\n", + "llama_model_path": "ggml-model-q5_k.gguf", + "mmproj": "mmproj-model-f16.gguf" + }, + "parameters": { + "max_tokens": 4096 + }, + "metadata": { + "author": "Mys", + "tags": ["Vision"], + "size": 9850000000 + }, + "engine": "nitro" +} diff --git a/models/llava-1.5-7b-q5/model.json b/models/llava-1.5-7b-q5/model.json new file mode 100644 index 000000000..658b98880 --- /dev/null +++ b/models/llava-1.5-7b-q5/model.json @@ -0,0 +1,33 @@ +{ + "sources": [ + { + "filename": "ggml-model-q5_k.gguf", + "url": "https://huggingface.co/mys/ggml_llava-v1.5-7b/resolve/main/ggml-model-q5_k.gguf" + }, + { + "filename": "mmproj-model-f16.gguf", + "url": "https://huggingface.co/mys/ggml_llava-v1.5-7b/resolve/main/mmproj-model-f16.gguf" + } + ], + "id": "llava-1.5-7b-q5", + "object": "model", + "name": "LlaVa 1.5 7B Q5 K", + "version": "1.0", + "description": "LlaVa 1.5 can bring vision understanding to Jan", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "\n### Instruction:\n{prompt}\n### Response:\n", + "llama_model_path": "ggml-model-q5_k.gguf", + "mmproj": "mmproj-model-f16.gguf" + }, + "parameters": { + "max_tokens": 4096 + }, + "metadata": { + "author": "Mys", + "tags": ["Vision"], + "size": 5400000000 + }, + "engine": "nitro" +} diff --git a/models/mistral-ins-7b-q4/model.json b/models/mistral-ins-7b-q4/model.json index 6db1aa35b..bfdaffa90 100644 --- a/models/mistral-ins-7b-q4/model.json +++ b/models/mistral-ins-7b-q4/model.json @@ -1,30 +1,35 @@ { - "source_url": "https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF/resolve/main/mistral-7b-instruct-v0.2.Q4_K_M.gguf", - "id": "mistral-ins-7b-q4", - "object": "model", - "name": "Mistral Instruct 7B Q4", - "version": "1.0", - "description": "Mistral Instruct 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "[INST] {prompt} [/INST]" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "MistralAI, The Bloke", - "tags": ["Featured", "7B", "Foundational Model"], - "size": 4370000000, - "cover": "https://raw.githubusercontent.com/janhq/jan/main/models/mistral-ins-7b-q4/cover.png" - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "mistral-7b-instruct-v0.2.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF/resolve/main/mistral-7b-instruct-v0.2.Q4_K_M.gguf" + } + ], + "id": "mistral-ins-7b-q4", + "object": "model", + "name": "Mistral Instruct 7B Q4", + "version": "1.0", + "description": "Mistral Instruct 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "[INST] {prompt} [/INST]", + "llama_model_path": "mistral-7b-instruct-v0.2.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": "MistralAI, The Bloke", + "tags": ["Featured", "7B", "Foundational Model"], + "size": 4370000000, + "cover": "https://raw.githubusercontent.com/janhq/jan/main/models/mistral-ins-7b-q4/cover.png" + }, + "engine": "nitro" +} diff --git a/models/mixtral-8x7b-instruct/model.json b/models/mixtral-8x7b-instruct/model.json index 31ff2838a..e0a0ee040 100644 --- a/models/mixtral-8x7b-instruct/model.json +++ b/models/mixtral-8x7b-instruct/model.json @@ -1,28 +1,33 @@ { - "source_url": "https://huggingface.co/TheBloke/Mixtral-8x7B-Instruct-v0.1-GGUF/resolve/main/mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf", - "id": "mixtral-8x7b-instruct", - "object": "model", - "name": "Mixtral 8x7B Instruct Q4", - "version": "1.0", - "description": "The Mixtral-8x7B is a pretrained generative Sparse Mixture of Experts. The Mixtral-8x7B outperforms 70B models on most benchmarks.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "[INST] {prompt} [/INST]" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "MistralAI, TheBloke", - "tags": ["70B", "Foundational Model"], - "size": 26440000000 - }, - "engine": "nitro" - } + "sources": [ + { + "filename": "mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Mixtral-8x7B-Instruct-v0.1-GGUF/resolve/main/mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf" + } + ], + "id": "mixtral-8x7b-instruct", + "object": "model", + "name": "Mixtral 8x7B Instruct Q4", + "version": "1.0", + "description": "The Mixtral-8x7B is a pretrained generative Sparse Mixture of Experts. The Mixtral-8x7B outperforms 70B models on most benchmarks.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "[INST] {prompt} [/INST]", + "llama_model_path": "mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "MistralAI, TheBloke", + "tags": ["70B", "Foundational Model"], + "size": 26440000000 + }, + "engine": "nitro" +} diff --git a/models/noromaid-7b/model.json b/models/noromaid-7b/model.json index fbb7858e1..78d579a64 100644 --- a/models/noromaid-7b/model.json +++ b/models/noromaid-7b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/NeverSleep/Noromaid-7b-v0.1.1-GGUF/resolve/main/Noromaid-7b-v0.1.1.q5_k_m.gguf", - "id": "noromaid-7b", - "object": "model", - "name": "Noromaid 7B Q5", - "version": "1.0", - "description": "The Noromaid 7b model is designed for role-playing with human-like behavior.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "### Instruction:{prompt}\n### Response:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "NeverSleep", - "tags": ["7B", "Merged"], - "size": 4370000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "Noromaid-7b-v0.1.1.q5_k_m.gguf", + "url": "https://huggingface.co/NeverSleep/Noromaid-7b-v0.1.1-GGUF/resolve/main/Noromaid-7b-v0.1.1.q5_k_m.gguf" + } + ], + "id": "noromaid-7b", + "object": "model", + "name": "Noromaid 7B Q5", + "version": "1.0", + "description": "The Noromaid 7b model is designed for role-playing with human-like behavior.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "### Instruction:{prompt}\n### Response:", + "llama_model_path": "Noromaid-7b-v0.1.1.q5_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": "NeverSleep", + "tags": ["7B", "Merged"], + "size": 4370000000 + }, + "engine": "nitro" +} diff --git a/models/openchat-3.5-7b/model.json b/models/openchat-3.5-7b/model.json index e4b72f9c6..294f7d269 100644 --- a/models/openchat-3.5-7b/model.json +++ b/models/openchat-3.5-7b/model.json @@ -1,28 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/openchat-3.5-1210-GGUF/resolve/main/openchat-3.5-1210.Q4_K_M.gguf", - "id": "openchat-3.5-7b", - "object": "model", - "name": "Openchat-3.5 7B Q4", - "version": "1.0", - "description": "The performance of this open-source model surpasses that of ChatGPT-3.5 and Grok-1 across various benchmarks.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "GPT4 Correct User: {prompt}<|end_of_turn|>GPT4 Correct Assistant:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": ["<|end_of_turn|>"], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Openchat", - "tags": ["Recommended", "7B", "Finetuned"], - "size": 4370000000 - }, - "engine": "nitro" - } + "sources": [ + { + "filename": "openchat-3.5-1210.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/openchat-3.5-1210-GGUF/resolve/main/openchat-3.5-1210.Q4_K_M.gguf" + } + ], + "id": "openchat-3.5-7b", + "object": "model", + "name": "Openchat-3.5 7B Q4", + "version": "1.0", + "description": "The performance of this open-source model surpasses that of ChatGPT-3.5 and Grok-1 across various benchmarks.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "GPT4 Correct User: {prompt}<|end_of_turn|>GPT4 Correct Assistant:", + "llama_model_path": "openchat-3.5-1210.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "stop": ["<|end_of_turn|>"], + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Openchat", + "tags": ["Recommended", "7B", "Finetuned"], + "size": 4370000000 + }, + "engine": "nitro" +} diff --git a/models/openhermes-neural-7b/model.json b/models/openhermes-neural-7b/model.json index ca3e88502..87e1df143 100644 --- a/models/openhermes-neural-7b/model.json +++ b/models/openhermes-neural-7b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/janhq/openhermes-2.5-neural-chat-v3-3-slerp-GGUF/resolve/main/openhermes-2.5-neural-chat-v3-3-slerp.Q4_K_M.gguf", - "id": "openhermes-neural-7b", - "object": "model", - "name": "OpenHermes Neural 7B Q4", - "version": "1.0", - "description": "OpenHermes Neural is a merged model using the TIES method. It performs well in various benchmarks.", - "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" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Intel, Jan", - "tags": ["7B", "Merged", "Featured"], - "size": 4370000000, - "cover": "https://raw.githubusercontent.com/janhq/jan/main/models/openhermes-neural-7b/cover.png" - }, - "engine": "nitro" - } + "sources": [ + { + "filename": "openhermes-2.5-neural-chat-v3-3-slerp.Q4_K_M.gguf", + "url": "https://huggingface.co/janhq/openhermes-2.5-neural-chat-v3-3-slerp-GGUF/resolve/main/openhermes-2.5-neural-chat-v3-3-slerp.Q4_K_M.gguf" + } + ], + "id": "openhermes-neural-7b", + "object": "model", + "name": "OpenHermes Neural 7B Q4", + "version": "1.0", + "description": "OpenHermes Neural is a merged model using the TIES method. It performs well in various benchmarks.", + "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": "openhermes-2.5-neural-chat-v3-3-slerp.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Intel, Jan", + "tags": ["7B", "Merged", "Featured"], + "size": 4370000000, + "cover": "https://raw.githubusercontent.com/janhq/jan/main/models/openhermes-neural-7b/cover.png" + }, + "engine": "nitro" +} diff --git a/models/phi-2-3b/model.json b/models/phi-2-3b/model.json index 97ff369e7..e452fdb55 100644 --- a/models/phi-2-3b/model.json +++ b/models/phi-2-3b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/phi-2-GGUF/resolve/main/phi-2.Q8_0.gguf", - "id": "phi-2-3b", - "object": "model", - "name": "Phi-2 3B Q8", - "version": "1.0", - "description": "Phi-2 is a 2.7B model, excelling in common sense and logical reasoning benchmarks, trained with synthetic texts and filtered websites.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "Intruct:\n{prompt}\nOutput:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Microsoft", - "tags": ["3B","Foundational Model"], - "size": 2960000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "phi-2.Q8_0.gguf", + "url": "https://huggingface.co/TheBloke/phi-2-GGUF/resolve/main/phi-2.Q8_0.gguf" + } + ], + "id": "phi-2-3b", + "object": "model", + "name": "Phi-2 3B Q8", + "version": "1.0", + "description": "Phi-2 is a 2.7B model, excelling in common sense and logical reasoning benchmarks, trained with synthetic texts and filtered websites.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "Intruct:\n{prompt}\nOutput:", + "llama_model_path": "phi-2.Q8_0.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "stop": [], + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Microsoft", + "tags": ["3B", "Foundational Model"], + "size": 2960000000 + }, + "engine": "nitro" +} diff --git a/models/phind-34b/model.json b/models/phind-34b/model.json index 7fc77ed71..60309cb9b 100644 --- a/models/phind-34b/model.json +++ b/models/phind-34b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/Phind-CodeLlama-34B-v2-GGUF/resolve/main/phind-codellama-34b-v2.Q5_K_M.gguf", - "id": "phind-34b", - "object": "model", - "name": "Phind 34B Q5", - "version": "1.0", - "description": "Phind 34B is fine-tuned on 1.5B tokens of high-quality programming data. This multi-lingual model excels in various programming languages and is designed to be steerable and user-friendly.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "### System Prompt\n{system_message}\n### User Message\n{prompt}\n### Assistant" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Phind, The Bloke", - "tags": ["34B", "Finetuned"], - "size": 20220000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "phind-codellama-34b-v2.Q5_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Phind-CodeLlama-34B-v2-GGUF/resolve/main/phind-codellama-34b-v2.Q5_K_M.gguf" + } + ], + "id": "phind-34b", + "object": "model", + "name": "Phind 34B Q5", + "version": "1.0", + "description": "Phind 34B is fine-tuned on 1.5B tokens of high-quality programming data. This multi-lingual model excels in various programming languages and is designed to be steerable and user-friendly.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "### System Prompt\n{system_message}\n### User Message\n{prompt}\n### Assistant", + "llama_model_path": "phind-codellama-34b-v2.Q5_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": "Phind, The Bloke", + "tags": ["34B", "Finetuned"], + "size": 20220000000 + }, + "engine": "nitro" +} diff --git a/models/solar-10.7b-slerp/model.json b/models/solar-10.7b-slerp/model.json index 9177fa013..8e62fa25b 100644 --- a/models/solar-10.7b-slerp/model.json +++ b/models/solar-10.7b-slerp/model.json @@ -1,29 +1,33 @@ { - "source_url": "https://huggingface.co/janhq/Solar-10.7B-SLERP-GGUF/resolve/main/solar-10.7b-slerp.Q4_K_M.gguf", - "id": "solar-10.7b-slerp", - "object": "model", - "name": "Solar Slerp 10.7B Q4", - "version": "1.0", - "description": "This model uses the Slerp merge method from SOLAR Instruct and Pandora-v1", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "### User: {prompt}\n### Assistant:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Jan", - "tags": ["13B","Finetuned"], - "size": 6360000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "solar-10.7b-slerp.Q4_K_M.gguf", + "url": "https://huggingface.co/janhq/Solar-10.7B-SLERP-GGUF/resolve/main/solar-10.7b-slerp.Q4_K_M.gguf" + } + ], + "id": "solar-10.7b-slerp", + "object": "model", + "name": "Solar Slerp 10.7B Q4", + "version": "1.0", + "description": "This model uses the Slerp merge method from SOLAR Instruct and Pandora-v1", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "### User: {prompt}\n### Assistant:", + "llama_model_path": "solar-10.7b-slerp.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Jan", + "tags": ["13B", "Finetuned"], + "size": 6360000000 + }, + "engine": "nitro" +} diff --git a/models/starling-7b/model.json b/models/starling-7b/model.json index 1a6d7e55c..eaa540bd9 100644 --- a/models/starling-7b/model.json +++ b/models/starling-7b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/Starling-LM-7B-alpha-GGUF/resolve/main/starling-lm-7b-alpha.Q4_K_M.gguf", - "id": "starling-7b", - "object": "model", - "name": "Starling alpha 7B Q4", - "version": "1.0", - "description": "Starling 7B, an upgrade of Openchat 3.5 using RLAIF, is really good at various benchmarks, especially with GPT-4 judging its performance.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "GPT4 User: {prompt}<|end_of_turn|>GPT4 Assistant:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": ["<|end_of_turn|>"], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Berkeley-nest, The Bloke", - "tags": ["7B","Finetuned"], - "size": 4370000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "starling-lm-7b-alpha.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Starling-LM-7B-alpha-GGUF/resolve/main/starling-lm-7b-alpha.Q4_K_M.gguf" + } + ], + "id": "starling-7b", + "object": "model", + "name": "Starling alpha 7B Q4", + "version": "1.0", + "description": "Starling 7B, an upgrade of Openchat 3.5 using RLAIF, is really good at various benchmarks, especially with GPT-4 judging its performance.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "GPT4 User: {prompt}<|end_of_turn|>GPT4 Assistant:", + "llama_model_path": "starling-lm-7b-alpha.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "stop": ["<|end_of_turn|>"], + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Berkeley-nest, The Bloke", + "tags": ["7B", "Finetuned"], + "size": 4370000000 + }, + "engine": "nitro" +} diff --git a/models/stealth-v1.2-7b/model.json b/models/stealth-v1.2-7b/model.json index 92bfe46e1..235cbbb88 100644 --- a/models/stealth-v1.2-7b/model.json +++ b/models/stealth-v1.2-7b/model.json @@ -1,32 +1,33 @@ { - "source_url": "https://huggingface.co/janhq/stealth-v1.3-GGUF/resolve/main/stealth-v1.3.Q4_K_M.gguf", - "id": "stealth-v1.2-7b", - "object": "model", - "name": "Stealth 7B Q4", - "version": "1.0", - "description": "This is a new experimental family designed to enhance Mathematical and Logical abilities.", - "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" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Jan", - "tags": [ - "7B", - "Finetuned", - "Featured" - ], - "size": 4370000000 - }, - "engine": "nitro" - } \ No newline at end of file + "sources": [ + { + "filename": "stealth-v1.3.Q4_K_M.gguf", + "url": "https://huggingface.co/janhq/stealth-v1.3-GGUF/resolve/main/stealth-v1.3.Q4_K_M.gguf" + } + ], + "id": "stealth-v1.2-7b", + "object": "model", + "name": "Stealth 7B Q4", + "version": "1.0", + "description": "This is a new experimental family designed to enhance Mathematical and Logical abilities.", + "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": "stealth-v1.3.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Jan", + "tags": ["7B", "Finetuned", "Featured"], + "size": 4370000000 + }, + "engine": "nitro" +} diff --git a/models/tinyllama-1.1b/model.json b/models/tinyllama-1.1b/model.json index 641511569..6a9187fa5 100644 --- a/models/tinyllama-1.1b/model.json +++ b/models/tinyllama-1.1b/model.json @@ -1,5 +1,10 @@ { - "source_url": "https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", + "sources": [ + { + "filename": "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf" + } + ], "id": "tinyllama-1.1b", "object": "model", "name": "TinyLlama Chat 1.1B Q4", @@ -7,8 +12,9 @@ "description": "TinyLlama is a tiny model with only 1.1B. It's a good model for less powerful computers.", "format": "gguf", "settings": { - "ctx_len": 2048, - "prompt_template": "<|system|>\n{system_message}<|user|>\n{prompt}<|assistant|>" + "ctx_len": 4096, + "prompt_template": "<|system|>\n{system_message}<|user|>\n{prompt}<|assistant|>", + "llama_model_path": "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf" }, "parameters": { "temperature": 0.7, @@ -20,9 +26,9 @@ "presence_penalty": 0 }, "metadata": { - "author": "TinyLlama", - "tags": ["Tiny", "Foundation Model"], - "size": 669000000 + "author": "TinyLlama", + "tags": ["Tiny", "Foundation Model"], + "size": 669000000 }, "engine": "nitro" -} \ No newline at end of file +} diff --git a/models/trinity-v1.2-7b/model.json b/models/trinity-v1.2-7b/model.json index ce5e7a4cf..2dda120e6 100644 --- a/models/trinity-v1.2-7b/model.json +++ b/models/trinity-v1.2-7b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/janhq/trinity-v1.2-GGUF/resolve/main/trinity-v1.2.Q4_K_M.gguf", - "id": "trinity-v1.2-7b", - "object": "model", - "name": "Trinity-v1.2 7B Q4", - "version": "1.0", - "description": "Trinity is an experimental model merge using the Slerp method. Recommended for daily assistance purposes.", - "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" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Jan", - "tags": ["7B", "Merged", "Featured"], - "size": 4370000000, - "cover": "https://raw.githubusercontent.com/janhq/jan/main/models/trinity-v1.2-7b/cover.png" - }, - "engine": "nitro" - } \ No newline at end of file + "sources": [ + { + "filename": "trinity-v1.2.Q4_K_M.gguf", + "url": "https://huggingface.co/janhq/trinity-v1.2-GGUF/resolve/main/trinity-v1.2.Q4_K_M.gguf" + } + ], + "id": "trinity-v1.2-7b", + "object": "model", + "name": "Trinity-v1.2 7B Q4", + "version": "1.0", + "description": "Trinity is an experimental model merge using the Slerp method. Recommended for daily assistance purposes.", + "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": "trinity-v1.2.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Jan", + "tags": ["7B", "Merged", "Featured"], + "size": 4370000000, + "cover": "https://raw.githubusercontent.com/janhq/jan/main/models/trinity-v1.2-7b/cover.png" + }, + "engine": "nitro" +} diff --git a/models/tulu-2-70b/model.json b/models/tulu-2-70b/model.json index ae95b870d..06b96e50d 100644 --- a/models/tulu-2-70b/model.json +++ b/models/tulu-2-70b/model.json @@ -1,28 +1,33 @@ { - "source_url": "https://huggingface.co/TheBloke/tulu-2-dpo-70B-GGUF/resolve/main/tulu-2-dpo-70b.Q4_K_M.gguf", - "id": "tulu-2-70b", - "object": "model", - "name": "Tulu 2 70B Q4", - "version": "1.0", - "description": "Tulu 70B is a strong alternative to Llama 2 70b Chat to act as helpful assistants.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "<|user|>\n{prompt}\n<|assistant|>" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "Lizpreciatior, The Bloke", - "tags": ["70B", "Finetuned"], - "size": 41400000000 - }, - "engine": "nitro" - } \ No newline at end of file + "sources": [ + { + "filename": "tulu-2-dpo-70b.Q4_K_M.gguf", + "url": "https://huggingface.co/TheBloke/tulu-2-dpo-70B-GGUF/resolve/main/tulu-2-dpo-70b.Q4_K_M.gguf" + } + ], + "id": "tulu-2-70b", + "object": "model", + "name": "Tulu 2 70B Q4", + "version": "1.0", + "description": "Tulu 70B is a strong alternative to Llama 2 70b Chat to act as helpful assistants.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "<|user|>\n{prompt}\n<|assistant|>", + "llama_model_path": "tulu-2-dpo-70b.Q4_K_M.gguf" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "Lizpreciatior, The Bloke", + "tags": ["70B", "Finetuned"], + "size": 41400000000 + }, + "engine": "nitro" +} diff --git a/models/wizardcoder-13b/model.json b/models/wizardcoder-13b/model.json index 1605ed362..051c739a0 100644 --- a/models/wizardcoder-13b/model.json +++ b/models/wizardcoder-13b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/WizardCoder-Python-13B-V1.0-GGUF/resolve/main/wizardcoder-python-13b-v1.0.Q5_K_M.gguf", - "id": "wizardcoder-13b", - "object": "model", - "name": "Wizard Coder Python 13B Q5", - "version": "1.0", - "description": "WizardCoder 13B is a Python coding model. This model demonstrate high proficiency in specific domains like coding and mathematics.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "### Instruction:\n{prompt}\n### Response:" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "WizardLM, The Bloke", - "tags": ["Recommended", "13B", "Finetuned"], - "size": 7870000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "wizardcoder-python-13b-v1.0.Q5_K_M.gguf", + "url": "https://huggingface.co/TheBloke/WizardCoder-Python-13B-V1.0-GGUF/resolve/main/wizardcoder-python-13b-v1.0.Q5_K_M.gguf" + } + ], + "id": "wizardcoder-13b", + "object": "model", + "name": "Wizard Coder Python 13B Q5", + "version": "1.0", + "description": "WizardCoder 13B is a Python coding model. This model demonstrate high proficiency in specific domains like coding and mathematics.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "### Instruction:\n{prompt}\n### Response:", + "llama_model_path": "wizardcoder-python-13b-v1.0.Q5_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": "WizardLM, The Bloke", + "tags": ["Recommended", "13B", "Finetuned"], + "size": 7870000000 + }, + "engine": "nitro" +} diff --git a/models/yarn-mistral-7b/model.json b/models/yarn-mistral-7b/model.json index 2676fbb58..ee6de1319 100644 --- a/models/yarn-mistral-7b/model.json +++ b/models/yarn-mistral-7b/model.json @@ -1,29 +1,31 @@ { - "source_url": "https://huggingface.co/TheBloke/Yarn-Mistral-7B-128k-GGUF/resolve/main/yarn-mistral-7b-128k.Q4_K_M.gguf", - "id": "yarn-mistral-7b", - "object": "model", - "name": "Yarn Mistral 7B Q4", - "version": "1.0", - "description": "Yarn Mistral 7B is a language model for long context and supports a 128k token context window.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "prompt_template": "{prompt}" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "NousResearch, The Bloke", - "tags": ["7B","Finetuned"], - "size": 4370000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "url": "https://huggingface.co/TheBloke/Yarn-Mistral-7B-128k-GGUF/resolve/main/yarn-mistral-7b-128k.Q4_K_M.gguf" + } + ], + "id": "yarn-mistral-7b", + "object": "model", + "name": "Yarn Mistral 7B Q4", + "version": "1.0", + "description": "Yarn Mistral 7B is a language model for long context and supports a 128k token context window.", + "format": "gguf", + "settings": { + "ctx_len": 4096, + "prompt_template": "{prompt}" + }, + "parameters": { + "temperature": 0.7, + "top_p": 0.95, + "stream": true, + "max_tokens": 4096, + "frequency_penalty": 0, + "presence_penalty": 0 + }, + "metadata": { + "author": "NousResearch, The Bloke", + "tags": ["7B", "Finetuned"], + "size": 4370000000 + }, + "engine": "nitro" +} diff --git a/models/yi-34b/model.json b/models/yi-34b/model.json index 8ff23aaa0..3697a9e22 100644 --- a/models/yi-34b/model.json +++ b/models/yi-34b/model.json @@ -1,29 +1,34 @@ { - "source_url": "https://huggingface.co/TheBloke/Yi-34B-Chat-GGUF/resolve/main/yi-34b-chat.Q5_K_M.gguf", - "id": "yi-34b", - "object": "model", - "name": "Yi 34B Q5", - "version": "1.0", - "description": "Yi-34B, a specialized chat model, is known for its diverse and creative responses and excels across various NLP tasks and benchmarks.", - "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" - }, - "parameters": { - "temperature": 0.7, - "top_p": 0.95, - "stream": true, - "max_tokens": 4096, - "stop": [], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "metadata": { - "author": "01-ai, The Bloke", - "tags": ["34B", "Foundational Model"], - "size": 20660000000 - }, - "engine": "nitro" - } - \ No newline at end of file + "sources": [ + { + "filename": "yi-34b-chat.Q5_K_M.gguf", + "url": "https://huggingface.co/TheBloke/Yi-34B-Chat-GGUF/resolve/main/yi-34b-chat.Q5_K_M.gguf" + } + ], + "id": "yi-34b", + "object": "model", + "name": "Yi 34B Q5", + "version": "1.0", + "description": "Yi-34B, a specialized chat model, is known for its diverse and creative responses and excels across various NLP tasks and benchmarks.", + "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": "yi-34b-chat.Q5_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": "01-ai, The Bloke", + "tags": ["34B", "Foundational Model"], + "size": 20660000000 + }, + "engine": "nitro" +} diff --git a/web/containers/Providers/EventListener.tsx b/web/containers/Providers/EventListener.tsx index d91a877d6..2816c88e2 100644 --- a/web/containers/Providers/EventListener.tsx +++ b/web/containers/Providers/EventListener.tsx @@ -105,6 +105,7 @@ export default function EventListenerWrapper({ children }: PropsWithChildren) { }) } return () => {} + // eslint-disable-next-line react-hooks/exhaustive-deps }, []) return ( diff --git a/web/hooks/useDownloadModel.ts b/web/hooks/useDownloadModel.ts index 49dbe1d5b..528108d18 100644 --- a/web/hooks/useDownloadModel.ts +++ b/web/hooks/useDownloadModel.ts @@ -6,6 +6,7 @@ import { ModelExtension, abortDownload, joinPath, + ModelArtifact, } from '@janhq/core' import { useSetAtom } from 'jotai' @@ -25,6 +26,23 @@ export default function useDownloadModel() { const addNewDownloadingModel = useSetAtom(addNewDownloadingModelAtom) const downloadModel = async (model: Model) => { + const childrenDownloadProgress: DownloadState[] = [] + model.sources.forEach((source: ModelArtifact) => { + childrenDownloadProgress.push({ + modelId: source.filename, + time: { + elapsed: 0, + remaining: 0, + }, + speed: 0, + percent: 0, + size: { + total: 0, + transferred: 0, + }, + }) + }) + // set an initial download state setDownloadState({ modelId: model.id, @@ -38,6 +56,7 @@ export default function useDownloadModel() { total: 0, transferred: 0, }, + children: childrenDownloadProgress, }) addNewDownloadingModel(model) @@ -46,6 +65,7 @@ export default function useDownloadModel() { .get(ExtensionTypeEnum.Model) ?.downloadModel(model, { ignoreSSL, proxy }) } + const abortModelDownload = async (model: Model) => { await abortDownload( await joinPath(['models', model.id, modelBinFileName(model)]) diff --git a/web/hooks/useGetConfiguredModels.ts b/web/hooks/useGetConfiguredModels.ts index 5662d534e..919f43754 100644 --- a/web/hooks/useGetConfiguredModels.ts +++ b/web/hooks/useGetConfiguredModels.ts @@ -1,7 +1,6 @@ import { useEffect, useState } from 'react' -import { ExtensionTypeEnum, ModelExtension } from '@janhq/core' -import { Model } from '@janhq/core' +import { ExtensionTypeEnum, ModelExtension, Model } from '@janhq/core' import { extensionManager } from '@/extension/ExtensionManager' @@ -25,6 +24,7 @@ export function useGetConfiguredModels() { useEffect(() => { fetchModels() + // eslint-disable-next-line react-hooks/exhaustive-deps }, []) return { loading, models } diff --git a/web/hooks/useGetDownloadedModels.ts b/web/hooks/useGetDownloadedModels.ts index f509fce63..bba420858 100644 --- a/web/hooks/useGetDownloadedModels.ts +++ b/web/hooks/useGetDownloadedModels.ts @@ -6,7 +6,7 @@ import { atom, useAtom } from 'jotai' import { extensionManager } from '@/extension/ExtensionManager' -const downloadedModelsAtom = atom([]) +export const downloadedModelsAtom = atom([]) export function useGetDownloadedModels() { const [downloadedModels, setDownloadedModels] = useAtom(downloadedModelsAtom) @@ -15,7 +15,8 @@ export function useGetDownloadedModels() { getDownloadedModels().then((downloadedModels) => { setDownloadedModels(downloadedModels) }) - }, [setDownloadedModels]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) return { downloadedModels, setDownloadedModels } } diff --git a/web/hooks/useRecommendedModel.ts b/web/hooks/useRecommendedModel.ts index dd474d0b5..2ee4c1a7f 100644 --- a/web/hooks/useRecommendedModel.ts +++ b/web/hooks/useRecommendedModel.ts @@ -110,6 +110,7 @@ export default function useRecommendedModel() { console.debug(`Using last used model ${lastUsedModel.id}`) setRecommendedModel(lastUsedModel) + // eslint-disable-next-line react-hooks/exhaustive-deps }, [getAndSortDownloadedModels, activeThread]) useEffect(() => { diff --git a/web/hooks/useSettings.ts b/web/hooks/useSettings.ts index 34d123359..ef4e08480 100644 --- a/web/hooks/useSettings.ts +++ b/web/hooks/useSettings.ts @@ -13,6 +13,7 @@ export const useSettings = () => { useEffect(() => { setTimeout(() => validateSettings, 3000) + // eslint-disable-next-line react-hooks/exhaustive-deps }, []) const validateSettings = async () => { diff --git a/web/package.json b/web/package.json index bba3dd48b..5293cf765 100644 --- a/web/package.json +++ b/web/package.json @@ -21,7 +21,7 @@ "class-variance-authority": "^0.7.0", "framer-motion": "^10.16.4", "highlight.js": "^11.9.0", - "jotai": "^2.4.0", + "jotai": "^2.6.0", "lodash": "^4.17.21", "lucide-react": "^0.291.0", "marked": "^9.1.2", diff --git a/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx b/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx index b56e20404..656a671c7 100644 --- a/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx +++ b/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx @@ -26,7 +26,7 @@ import { useCreateNewThread } from '@/hooks/useCreateNewThread' import useDownloadModel from '@/hooks/useDownloadModel' import { useDownloadState } from '@/hooks/useDownloadState' import { getAssistants } from '@/hooks/useGetAssistants' -import { useGetDownloadedModels } from '@/hooks/useGetDownloadedModels' +import { downloadedModelsAtom } from '@/hooks/useGetDownloadedModels' import { useMainViewState } from '@/hooks/useMainViewState' import { toGibibytes } from '@/utils/converter' @@ -43,8 +43,8 @@ type Props = { const ExploreModelItemHeader: React.FC = ({ model, onClick, open }) => { const { downloadModel } = useDownloadModel() - const { downloadedModels } = useGetDownloadedModels() - const { modelDownloadStateAtom, downloadStates } = useDownloadState() + const downloadedModels = useAtomValue(downloadedModelsAtom) + const { modelDownloadStateAtom } = useDownloadState() const { requestCreateNewThread } = useCreateNewThread() const totalRam = useAtomValue(totalRamAtom) const serverEnabled = useAtomValue(serverEnabledAtom) @@ -100,9 +100,7 @@ const ExploreModelItemHeader: React.FC = ({ model, onClick, open }) => { )} ) - } - - if (downloadState != null && downloadStates.length > 0) { + } else if (downloadState != null) { downloadButton = } diff --git a/web/types/downloadState.d.ts b/web/types/downloadState.d.ts index 3c3389b4f..cca526bf1 100644 --- a/web/types/downloadState.d.ts +++ b/web/types/downloadState.d.ts @@ -4,6 +4,8 @@ type DownloadState = { speed: number percent: number size: DownloadSize + isFinished?: boolean + children?: DownloadState[] error?: string } diff --git a/web/utils/model.ts b/web/utils/model.ts index 2dd6fbdd3..eab4076d8 100644 --- a/web/utils/model.ts +++ b/web/utils/model.ts @@ -2,7 +2,7 @@ import { Model } from '@janhq/core' export const modelBinFileName = (model: Model) => { const modelFormatExt = '.gguf' - const extractedFileName = model.source_url?.split('/').pop() ?? model.id + const extractedFileName = model.sources[0]?.url.split('/').pop() ?? model.id const fileName = extractedFileName.toLowerCase().endsWith(modelFormatExt) ? extractedFileName : model.id diff --git a/web/utils/modelParam.ts b/web/utils/modelParam.ts index 7d559c313..2deffce66 100644 --- a/web/utils/modelParam.ts +++ b/web/utils/modelParam.ts @@ -40,6 +40,8 @@ export const toSettingParams = ( n_parallel: undefined, cpu_threads: undefined, prompt_template: undefined, + llama_model_path: undefined, + mmproj: undefined, } const settingParams: ModelSettingParams = {} From dea35dad9e366e60afa3bb3f1bb8d586812ebe1d Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 09:18:42 +0000 Subject: [PATCH 06/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 82c3ae79b..d69c9cde5 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 01fcfb7097237c20c1ea93640e5753e0147a20fa Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 10:35:24 +0000 Subject: [PATCH 07/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d69c9cde5..b45cd8413 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 75f32614e7838e48ad37c3a42972720c1e1db4f1 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 11:27:46 +0000 Subject: [PATCH 08/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b45cd8413..6c1fc44a4 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From b291b3da7164252af5c25ba4a38ce285450e0852 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 13:12:20 +0000 Subject: [PATCH 09/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6c1fc44a4..2722a2870 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 837fa8a82dbb185050aaa2a39ef11823b188d08d Mon Sep 17 00:00:00 2001 From: hiento09 <136591877+hiento09@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:18:45 +0700 Subject: [PATCH 10/65] Docs publish to github page trigger on push to docs branch (#1782) Co-authored-by: Hien To --- .github/workflows/jan-docs.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jan-docs.yml b/.github/workflows/jan-docs.yml index 8ce4e91ed..8135935bd 100644 --- a/.github/workflows/jan-docs.yml +++ b/.github/workflows/jan-docs.yml @@ -5,6 +5,7 @@ on: branches: - main - dev + - docs paths: - 'docs/**' - '.github/workflows/jan-docs.yml' @@ -12,6 +13,7 @@ on: branches: - main - dev + - docs paths: - 'docs/**' - '.github/workflows/jan-docs.yml' @@ -91,13 +93,13 @@ jobs: Preview URL: ${{ steps.deployCloudflarePages.outputs.url }} - name: Add Custome Domain file - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.pull_request.head.repo.full_name != github.repository + if: github.event_name == 'push' && github.ref == 'refs/heads/docs' && github.event.pull_request.head.repo.full_name != github.repository run: echo "${{ vars.DOCUSAURUS_DOMAIN }}" > ./docs/build/CNAME # Popular action to deploy to GitHub Pages: # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus - name: Deploy to GitHub Pages - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.pull_request.head.repo.full_name != github.repository + if: github.event_name == 'push' && github.ref == 'refs/heads/docs' && github.event.pull_request.head.repo.full_name != github.repository uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} From b2b1479fc34a34a10129a765ac37906e86d7ee54 Mon Sep 17 00:00:00 2001 From: copyhold Date: Thu, 25 Jan 2024 16:38:32 +0200 Subject: [PATCH 11/65] Added focus --- web/screens/Chat/index.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/screens/Chat/index.tsx b/web/screens/Chat/index.tsx index 684027e49..f86460f1c 100644 --- a/web/screens/Chat/index.tsx +++ b/web/screens/Chat/index.tsx @@ -74,6 +74,9 @@ const ChatScreen = () => { } useEffect(() => { + if (textareaRef.current) { + textareaRef.current.focus() + } if (isWaitingToSend && activeThreadId) { setIsWaitingToSend(false) sendChatMessage() @@ -85,6 +88,7 @@ const ChatScreen = () => { if (textareaRef.current) { textareaRef.current.style.height = '40px' textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px' + textareaRef.current.focus() } }, [currentPrompt]) From a78e183eeb71825de3341fb11ac7719dd6bb1ac8 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 15:36:30 +0000 Subject: [PATCH 12/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2722a2870..fb11cfbde 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From e8796a7ad860536a91fb45f56a2cb181bbaa3b81 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 15:43:16 +0000 Subject: [PATCH 13/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fb11cfbde..53558185c 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From b0d63c988d6fff570130e5b4fcba471b7951c107 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 16:30:09 +0000 Subject: [PATCH 14/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 53558185c..8811dbe0c 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From a52d81c79a979b234882c468ad056049f7c8d757 Mon Sep 17 00:00:00 2001 From: Service Account Date: Thu, 25 Jan 2024 20:16:35 +0000 Subject: [PATCH 15/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8811dbe0c..9183b0652 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 99025cb02f6affabd2c4786b6e5247e5177ffc37 Mon Sep 17 00:00:00 2001 From: hiento09 <136591877+hiento09@users.noreply.github.com> Date: Fri, 26 Jan 2024 09:24:09 +0700 Subject: [PATCH 16/65] CI nightly update trigger to 3AM UTC +7 Tuesday, Wednesday, and Thursday (#1798) Co-authored-by: Hien To --- .github/workflows/jan-electron-build-nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/jan-electron-build-nightly.yml b/.github/workflows/jan-electron-build-nightly.yml index f961ccd6f..08b6ad476 100644 --- a/.github/workflows/jan-electron-build-nightly.yml +++ b/.github/workflows/jan-electron-build-nightly.yml @@ -2,7 +2,7 @@ name: Jan Build Electron App Nightly or Manual on: schedule: - - cron: '0 20 * * 2,3,4' # At 8 PM UTC on Tuesday, Wednesday, and Thursday, which is 3 AM UTC+7 + - cron: '0 20 * * 1,2,3' # At 8 PM UTC on Monday, Tuesday, and Wednesday which is 3 AM UTC+7 Tuesday, Wednesday, and Thursday workflow_dispatch: inputs: public_provider: From 85b58eb82400cb9d75af4f16ca6e1b4ef96c8224 Mon Sep 17 00:00:00 2001 From: Service Account Date: Fri, 26 Jan 2024 04:00:07 +0000 Subject: [PATCH 17/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9183b0652..770b88266 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 143e76a0dedcf49fb3d32a9715fc3958aaad6907 Mon Sep 17 00:00:00 2001 From: NamH Date: Fri, 26 Jan 2024 12:19:02 +0700 Subject: [PATCH 18/65] chore: clean up code and remove some lint suppression (#1777) * chore: clean up code and remove some lint suppression Signed-off-by: James * Update .gitignore --------- Signed-off-by: James Co-authored-by: James Co-authored-by: Louis --- .gitignore | 3 + extensions/assistant-extension/src/index.ts | 3 +- extensions/monitoring-extension/src/index.ts | 3 +- web/containers/Layout/index.tsx | 2 +- web/containers/Providers/EventHandler.tsx | 118 +++++++++++-------- web/containers/Providers/EventListener.tsx | 16 +-- web/hooks/useGetConfiguredModels.ts | 23 ++-- web/screens/Chat/MessageToolbar/index.tsx | 2 +- 8 files changed, 96 insertions(+), 74 deletions(-) diff --git a/.gitignore b/.gitignore index e3e4635fc..4540e5c7a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ build electron/renderer electron/models electron/docs +electron/engines +server/pre-install package-lock.json *.log @@ -26,3 +28,4 @@ extensions/inference-nitro-extension/bin/*/*.exp extensions/inference-nitro-extension/bin/*/*.lib extensions/inference-nitro-extension/bin/saved-* extensions/inference-nitro-extension/bin/*.tar.gz + diff --git a/extensions/assistant-extension/src/index.ts b/extensions/assistant-extension/src/index.ts index 96de33b7b..098ab1f54 100644 --- a/extensions/assistant-extension/src/index.ts +++ b/extensions/assistant-extension/src/index.ts @@ -1,5 +1,4 @@ -import { fs, Assistant } from "@janhq/core"; -import { AssistantExtension } from "@janhq/core"; +import { fs, Assistant, AssistantExtension } from "@janhq/core"; import { join } from "path"; export default class JanAssistantExtension extends AssistantExtension { diff --git a/extensions/monitoring-extension/src/index.ts b/extensions/monitoring-extension/src/index.ts index d3f20b437..9297a770f 100644 --- a/extensions/monitoring-extension/src/index.ts +++ b/extensions/monitoring-extension/src/index.ts @@ -1,5 +1,4 @@ -import { MonitoringExtension } from "@janhq/core"; -import { executeOnMain } from "@janhq/core"; +import { MonitoringExtension, executeOnMain } from "@janhq/core"; /** * JanMonitoringExtension is a extension that provides system monitoring functionality. diff --git a/web/containers/Layout/index.tsx b/web/containers/Layout/index.tsx index 54a7845a4..e7bde49c0 100644 --- a/web/containers/Layout/index.tsx +++ b/web/containers/Layout/index.tsx @@ -28,7 +28,7 @@ const BaseLayout = (props: PropsWithChildren) => { if (localStorage.getItem(SUCCESS_SET_NEW_DESTINATION) === 'true') { setMainViewState(MainViewState.Settings) } - }, []) + }, [setMainViewState]) return (
diff --git a/web/containers/Providers/EventHandler.tsx b/web/containers/Providers/EventHandler.tsx index 1f9d6d7af..114370359 100644 --- a/web/containers/Providers/EventHandler.tsx +++ b/web/containers/Providers/EventHandler.tsx @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { ReactNode, useEffect, useRef } from 'react' +import { ReactNode, useCallback, useEffect, useRef } from 'react' import { events, @@ -48,48 +48,61 @@ export default function EventHandler({ children }: { children: ReactNode }) { modelsRef.current = downloadedModels }, [downloadedModels]) - async function handleNewMessageResponse(message: ThreadMessage) { - addNewMessage(message) - } + const onNewMessageResponse = useCallback( + (message: ThreadMessage) => { + addNewMessage(message) + }, + [addNewMessage] + ) - async function handleModelReady(model: Model) { - setActiveModel(model) - toaster({ - title: 'Success!', - description: `Model ${model.id} has been started.`, - }) - setStateModel(() => ({ - state: 'stop', - loading: false, - model: model.id, - })) - } + const onModelReady = useCallback( + (model: Model) => { + setActiveModel(model) + toaster({ + title: 'Success!', + description: `Model ${model.id} has been started.`, + }) + setStateModel(() => ({ + state: 'stop', + loading: false, + model: model.id, + })) + }, + [setActiveModel, setStateModel] + ) - async function handleModelStopped() { - setTimeout(async () => { + const onModelStopped = useCallback(() => { + setTimeout(() => { setActiveModel(undefined) setStateModel({ state: 'start', loading: false, model: '' }) }, 500) - } + }, [setActiveModel, setStateModel]) - async function handleModelFail(res: any) { - const errorMessage = `${res.error}` - alert(errorMessage) - setStateModel(() => ({ - state: 'start', - loading: false, - model: res.modelId, - })) - } + const onModelInitFailed = useCallback( + (res: any) => { + const errorMessage = `${res.error}` + console.error('Failed to load model: ' + errorMessage) + setStateModel(() => ({ + state: 'start', + loading: false, + model: res.modelId, + })) + }, + [setStateModel] + ) + + const onMessageResponseUpdate = useCallback( + (message: ThreadMessage) => { + updateMessage( + message.id, + message.thread_id, + message.content, + message.status + ) + if (message.status === MessageStatus.Pending) { + return + } - async function handleMessageResponseUpdate(message: ThreadMessage) { - updateMessage( - message.id, - message.thread_id, - message.content, - message.status - ) - if (message.status !== MessageStatus.Pending) { // Mark the thread as not waiting for response updateThreadWaiting(message.thread_id, false) @@ -111,26 +124,33 @@ export default function EventHandler({ children }: { children: ReactNode }) { .get(ExtensionTypeEnum.Conversational) ?.addNewMessage(message) } - } - } + }, + [updateMessage, updateThreadWaiting] + ) useEffect(() => { + console.log('Registering events') if (window.core?.events) { - events.on(MessageEvent.OnMessageResponse, handleNewMessageResponse) - events.on(MessageEvent.OnMessageUpdate, handleMessageResponseUpdate) - events.on(ModelEvent.OnModelReady, handleModelReady) - events.on(ModelEvent.OnModelFail, handleModelFail) - events.on(ModelEvent.OnModelStopped, handleModelStopped) + events.on(MessageEvent.OnMessageResponse, onNewMessageResponse) + events.on(MessageEvent.OnMessageUpdate, onMessageResponseUpdate) + + events.on(ModelEvent.OnModelReady, onModelReady) + events.on(ModelEvent.OnModelFail, onModelInitFailed) + events.on(ModelEvent.OnModelStopped, onModelStopped) } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [ + onNewMessageResponse, + onMessageResponseUpdate, + onModelReady, + onModelInitFailed, + onModelStopped, + ]) useEffect(() => { return () => { - events.off(MessageEvent.OnMessageResponse, handleNewMessageResponse) - events.off(MessageEvent.OnMessageUpdate, handleMessageResponseUpdate) + events.off(MessageEvent.OnMessageResponse, onNewMessageResponse) + events.off(MessageEvent.OnMessageUpdate, onMessageResponseUpdate) } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [onNewMessageResponse, onMessageResponseUpdate]) return <>{children} } diff --git a/web/containers/Providers/EventListener.tsx b/web/containers/Providers/EventListener.tsx index 2816c88e2..62d4cacb6 100644 --- a/web/containers/Providers/EventListener.tsx +++ b/web/containers/Providers/EventListener.tsx @@ -105,12 +105,14 @@ export default function EventListenerWrapper({ children }: PropsWithChildren) { }) } return () => {} - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [ + setDownloadState, + setDownloadStateCancelled, + setDownloadStateFailed, + setDownloadStateSuccess, + setDownloadedModels, + setProgress, + ]) - return ( -
- {children} -
- ) + return {children} } diff --git a/web/hooks/useGetConfiguredModels.ts b/web/hooks/useGetConfiguredModels.ts index 919f43754..8be052ae2 100644 --- a/web/hooks/useGetConfiguredModels.ts +++ b/web/hooks/useGetConfiguredModels.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { ExtensionTypeEnum, ModelExtension, Model } from '@janhq/core' @@ -8,24 +8,23 @@ export function useGetConfiguredModels() { const [loading, setLoading] = useState(false) const [models, setModels] = useState([]) - const getConfiguredModels = async (): Promise => { - const models = await extensionManager - .get(ExtensionTypeEnum.Model) - ?.getConfiguredModels() - return models ?? [] - } - - async function fetchModels() { + const fetchModels = useCallback(async () => { setLoading(true) const models = await getConfiguredModels() setLoading(false) setModels(models) - } + }, []) useEffect(() => { fetchModels() - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [fetchModels]) return { loading, models } } + +const getConfiguredModels = async (): Promise => { + const models = await extensionManager + .get(ExtensionTypeEnum.Model) + ?.getConfiguredModels() + return models ?? [] +} diff --git a/web/screens/Chat/MessageToolbar/index.tsx b/web/screens/Chat/MessageToolbar/index.tsx index 183eae814..dfa8d63c6 100644 --- a/web/screens/Chat/MessageToolbar/index.tsx +++ b/web/screens/Chat/MessageToolbar/index.tsx @@ -3,8 +3,8 @@ import { ExtensionTypeEnum, ThreadMessage, ChatCompletionRole, + ConversationalExtension, } from '@janhq/core' -import { ConversationalExtension } from '@janhq/core' import { useAtomValue, useSetAtom } from 'jotai' import { RefreshCcw, CopyIcon, Trash2Icon, CheckIcon } from 'lucide-react' From b15650269e406d9119bc10d24993bc5e7202c1cf Mon Sep 17 00:00:00 2001 From: Service Account Date: Fri, 26 Jan 2024 05:35:57 +0000 Subject: [PATCH 19/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 770b88266..20f7e4f34 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 2d96b69fdc47bdc11c10f237662671cf84f835d2 Mon Sep 17 00:00:00 2001 From: Service Account Date: Fri, 26 Jan 2024 06:02:39 +0000 Subject: [PATCH 20/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 20f7e4f34..68035beca 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From c4d56362e2bc2e2157cc119268a15d79360e6647 Mon Sep 17 00:00:00 2001 From: Service Account Date: Fri, 26 Jan 2024 06:05:46 +0000 Subject: [PATCH 21/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 68035beca..36e8a171f 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From ba07f92636f39ef82646d19a638c605d47c85246 Mon Sep 17 00:00:00 2001 From: Service Account Date: Fri, 26 Jan 2024 07:58:45 +0000 Subject: [PATCH 22/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 36e8a171f..d7397a8da 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 8bd539aac518277e8bf07e3dda20e76ff5e25736 Mon Sep 17 00:00:00 2001 From: Service Account Date: Fri, 26 Jan 2024 12:13:58 +0000 Subject: [PATCH 23/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d7397a8da..e20fb5dbe 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 38f757dd4d8a3463f0a53f8dcd5437681b16a7b9 Mon Sep 17 00:00:00 2001 From: Service Account Date: Fri, 26 Jan 2024 13:26:21 +0000 Subject: [PATCH 24/65] janhq/jan: Update README.md with nightly build artifact URL --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e20fb5dbe..f5ce84e70 100644 --- a/README.md +++ b/README.md @@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage From 28e4405498c5de9558b1e39d890b17aa6689c42a Mon Sep 17 00:00:00 2001 From: hiro Date: Tue, 19 Dec 2023 23:33:27 +0700 Subject: [PATCH 25/65] feat: support RAG chore: Update new model.json with multiple binaries feat: Add updates for handling multiple model binaries chore: jan can see Update Model.json (#1005) * add(mixtral): add model.json for mixtral * archived some models + update the model.json * add(model): add pandora 10.7b * fix(model): update description * fix(model): pump vers and change the featured model to trinity * fix(model): archive neuralchat * fix(model): decapriated all old models * fix(trinity): add cover image and change description * fix(trinity): update cover png * add(pandora): cover image * fix(pandora): cover image * add(mixtral): add model.json for mixtral * archived some models + update the model.json * add(model): add pandora 10.7b * fix(model): update description * fix(model): pump vers and change the featured model to trinity * fix(model): archive neuralchat * fix(model): decapriated all old models * fix(trinity): add cover image and change description * fix(trinity): update cover png * add(pandora): cover image * fix(pandora): cover image * chore: model desc nits * fix(models): adjust the size for solars and pandoras * add(mixtral): description --------- Co-authored-by: 0xSage chore: reformat model.json and use new template fix(Model): download/abort model (#1163) * fix(Model): download/abort model * fix: image preview Signed-off-by: James --------- Signed-off-by: James Co-authored-by: James Co-authored-by: Louis add preview and reduce time re-render all chat screen Signed-off-by: James store files under thread_id/files Signed-off-by: James fix: Update llava 1.5 size fix: Nitro extension path resolver feat: Add upload preview clearance chore: Update FileType to multiple targets fix: delete file preview once new thread created chore: Add langchain import support storing pdf file Signed-off-by: James feat: add retrieval tool in node runtime fix: import module done Co-authored-by: Louis feat: Add type assistant tool chore: Add tool_retrieval_enabled to InferenceEngine chore: Add AssistantTool to thread entity chore: refactor tool retrieval base class feat: Add handler for assistant with rag enabled chore: Update inferenceEngine type properly chore: Update inferenceEngine type properly fix: Update retrieval tool chore: main entry correction refactor: tsconfig files chore: Update ModelRuntimeParams type refactor: Remove unused files fix: wip chore: remove unused console.log for FileUploadPreview fix: Update mapping correctly for engine and proxyEngine feat: Add proxyEngine to type ModelInfo fix: WIP with test route fix: Add bundleDependencies to package.json chore: remove conversational history memory fix: refactor data passing reafactor: remove unused code fix: Update module chore: export import correction fix conflict Signed-off-by: James fix: resolve after rebased fix: Update llava 1.5 model json feat: Add bakllava 1 model json refactor: node module export, ES syntax and langchain import fix: WIP fix: WIP fix: WIP fix: external module import fix: WIP Add UI attachment fot file upload Prepare Thumbnail UI image chore: rebase model folder to dev branch chore: remove multiple binaries related commits fix: remove multiple binaries related commits part 2 fix: Remove transformer.js related deps Fix truncate file name attachment remove unused code image preview attachment fix: remove multi binaries error chore: remove commented code for ModelArtifacts type Dropzone for drag and drop attachment Avoid conditional showing 0 using length fix symbol windows avoid undefined tools fix: add tool retrieval to true by default and disable the change chore: remove unused code fix: Enable nitro embedding by default fix: Update code WIP with nitro embedding chore: remove unused running function fix: assistant extension missing module feat: Retrieval ingest, query and reforward fix: Update hnswlib version conflict fix: Add tool settings fix: Update path to thread_id/memory fix: Add support for nitro embedding usage fix: RAG does not work with plain content message fix(Model): #1662 imported model does not use gpu (#1723) Signed-off-by: James Co-authored-by: James feat: allow users to update retrieval settings chore: pass thread assistant settings to assistant extensions chore: eslint fix fix bug border right panel showing in thread while not have active thread Update setting layout retrieval assistant Renaming file settingcomponent change default value in core extention add fake loader generate response fix conditional fake loader remove unused import Proper error message on file typr fix: loading indicator fix: chunk size and overlap constraint conditional drag and drop when retrieval off fix: enable retrieval middleware as soon as its tool is enabled fix: configure embedding engine according to request fix: Retrieval false by default fix: engine json chore: migrate assistant disabled collapse panel when retrieval or children null chore: remove unused log chore: Bump nitro version to 0.2.14 for batch embedding chore: remove unused console.log --- core/src/api/index.ts | 1 + core/src/fs.ts | 16 +- core/src/node/api/routes/fs.ts | 9 +- core/src/types/assistant/assistantEntity.ts | 9 +- core/src/types/inference/inferenceEntity.ts | 29 +- core/src/types/message/messageEntity.ts | 15 +- core/src/types/model/modelEntity.ts | 12 +- core/src/types/thread/index.ts | 1 + core/src/types/thread/threadEntity.ts | 2 + core/src/types/thread/threadEvent.ts | 4 + electron/handlers/fileManager.ts | 16 + electron/handlers/fs.ts | 8 +- extensions/assistant-extension/package.json | 28 +- .../assistant-extension/rollup.config.ts | 81 +++++ .../src/@types/global.d.ts | 4 +- extensions/assistant-extension/src/index.ts | 197 +++++++++++- .../assistant-extension/src/node/engine.ts | 13 + .../assistant-extension/src/node/index.ts | 39 +++ .../src/node/tools/retrieval/index.ts | 78 +++++ extensions/assistant-extension/tsconfig.json | 22 +- .../assistant-extension/webpack.config.js | 38 --- .../conversational-extension/src/index.ts | 56 +++- .../inference-nitro-extension/bin/version.txt | 2 +- .../inference-nitro-extension/package.json | 1 + .../inference-nitro-extension/src/index.ts | 14 +- .../src/node/index.ts | 23 +- .../inference-openai-extension/src/index.ts | 15 +- .../inference-openai-extension/tsconfig.json | 5 +- .../tsconfig.json | 5 +- web/containers/CardSidebar/index.tsx | 44 +-- web/containers/Checkbox/index.tsx | 50 +-- web/containers/Layout/TopBar/index.tsx | 18 +- web/containers/Loader/GenerateResponse.tsx | 39 +++ web/containers/ModelConfigInput/index.tsx | 51 +--- web/containers/Providers/EventHandler.tsx | 5 +- web/containers/Providers/Jotai.tsx | 8 + web/containers/Shortcut/index.tsx | 2 +- web/containers/SliderRightPanel/index.tsx | 58 +--- web/helpers/atoms/ChatMessage.atom.ts | 2 + web/hooks/useCreateNewThread.ts | 10 +- web/hooks/usePath.ts | 17 ++ web/hooks/useSendChatMessage.ts | 100 +++++- web/hooks/useSetActiveThread.ts | 2 + web/next.config.js | 3 - web/package.json | 2 + web/screens/Chat/AssistantSetting/index.tsx | 78 +++++ web/screens/Chat/ChatBody/index.tsx | 24 +- web/screens/Chat/ChatInput/index.tsx | 254 ++++++++++++++++ web/screens/Chat/EngineSetting/index.tsx | 17 +- web/screens/Chat/FileUploadPreview/Icon.tsx | 95 ++++++ web/screens/Chat/FileUploadPreview/index.tsx | 47 +++ web/screens/Chat/ImageUploadPreview/index.tsx | 54 ++++ .../Chat/MessageQueuedBanner/index.tsx | 19 ++ ...ponentBuilder.tsx => SettingComponent.tsx} | 73 ++++- web/screens/Chat/ModelSetting/index.tsx | 7 +- .../Chat/ModelSetting/predefinedComponent.ts | 50 ++- .../Chat/RequestDownloadModel/index.tsx | 42 +++ web/screens/Chat/Sidebar/index.tsx | 108 +++++-- web/screens/Chat/SimpleTextMessage/index.tsx | 114 +++++-- web/screens/Chat/ThreadList/index.tsx | 1 + web/screens/Chat/index.tsx | 286 +++++++++--------- .../ExploreModelItemHeader/index.tsx | 2 + web/screens/LocalServer/index.tsx | 10 +- web/tsconfig.json | 10 +- web/types/index.d.ts | 1 - web/utils/base64.ts | 9 + web/utils/componentSettings.ts | 25 +- web/utils/modelParam.ts | 4 +- 68 files changed, 1959 insertions(+), 525 deletions(-) create mode 100644 core/src/types/thread/threadEvent.ts create mode 100644 extensions/assistant-extension/rollup.config.ts create mode 100644 extensions/assistant-extension/src/node/engine.ts create mode 100644 extensions/assistant-extension/src/node/index.ts create mode 100644 extensions/assistant-extension/src/node/tools/retrieval/index.ts delete mode 100644 extensions/assistant-extension/webpack.config.js create mode 100644 web/containers/Loader/GenerateResponse.tsx create mode 100644 web/screens/Chat/AssistantSetting/index.tsx create mode 100644 web/screens/Chat/ChatInput/index.tsx create mode 100644 web/screens/Chat/FileUploadPreview/Icon.tsx create mode 100644 web/screens/Chat/FileUploadPreview/index.tsx create mode 100644 web/screens/Chat/ImageUploadPreview/index.tsx create mode 100644 web/screens/Chat/MessageQueuedBanner/index.tsx rename web/screens/Chat/ModelSetting/{settingComponentBuilder.tsx => SettingComponent.tsx} (50%) create mode 100644 web/screens/Chat/RequestDownloadModel/index.tsx create mode 100644 web/utils/base64.ts diff --git a/core/src/api/index.ts b/core/src/api/index.ts index a3d0361e7..a232c4090 100644 --- a/core/src/api/index.ts +++ b/core/src/api/index.ts @@ -62,6 +62,7 @@ export enum FileManagerRoute { getJanDataFolderPath = 'getJanDataFolderPath', getResourcePath = 'getResourcePath', fileStat = 'fileStat', + writeBlob = 'writeBlob', } export type ApiFunction = (...args: any[]) => any diff --git a/core/src/fs.ts b/core/src/fs.ts index ea636977a..0e570d1f5 100644 --- a/core/src/fs.ts +++ b/core/src/fs.ts @@ -1,4 +1,4 @@ -import { FileStat } from "./types" +import { FileStat } from './types' /** * Writes data to a file at the specified path. @@ -6,6 +6,15 @@ import { FileStat } from "./types" */ const writeFileSync = (...args: any[]) => global.core.api?.writeFileSync(...args) +/** + * Writes blob data to a file at the specified path. + * @param path - The path to file. + * @param data - The blob data. + * @returns + */ +const writeBlob: (path: string, data: string) => Promise = (path, data) => + global.core.api?.writeBlob(path, data) + /** * Reads the contents of a file at the specified path. * @returns {Promise} A Promise that resolves with the contents of the file. @@ -60,7 +69,6 @@ const syncFile: (src: string, dest: string) => Promise = (src, dest) => */ const copyFileSync = (...args: any[]) => global.core.api?.copyFileSync(...args) - /** * Gets the file's stats. * @@ -70,7 +78,6 @@ const copyFileSync = (...args: any[]) => global.core.api?.copyFileSync(...args) const fileStat: (path: string) => Promise = (path) => global.core.api?.fileStat(path) - // TODO: Export `dummy` fs functions automatically // Currently adding these manually export const fs = { @@ -84,5 +91,6 @@ export const fs = { appendFileSync, copyFileSync, syncFile, - fileStat + fileStat, + writeBlob, } diff --git a/core/src/node/api/routes/fs.ts b/core/src/node/api/routes/fs.ts index 5f511af27..c5404ccce 100644 --- a/core/src/node/api/routes/fs.ts +++ b/core/src/node/api/routes/fs.ts @@ -2,6 +2,7 @@ import { FileSystemRoute } from '../../../api' import { join } from 'path' import { HttpServer } from '../HttpServer' import { getJanDataFolderPath } from '../../utils' +import { normalizeFilePath } from '../../path' export const fsRouter = async (app: HttpServer) => { const moduleName = 'fs' @@ -13,10 +14,10 @@ export const fsRouter = async (app: HttpServer) => { const result = await import(moduleName).then((mdl) => { return mdl[route]( ...body.map((arg: any) => - typeof arg === 'string' && arg.includes('file:/') - ? join(getJanDataFolderPath(), arg.replace('file:/', '')) - : arg, - ), + typeof arg === 'string' && (arg.startsWith(`file:/`) || arg.startsWith(`file:\\`)) + ? join(getJanDataFolderPath(), normalizeFilePath(arg)) + : arg + ) ) }) res.status(200).send(result) diff --git a/core/src/types/assistant/assistantEntity.ts b/core/src/types/assistant/assistantEntity.ts index 91bb2bb22..733dbea8d 100644 --- a/core/src/types/assistant/assistantEntity.ts +++ b/core/src/types/assistant/assistantEntity.ts @@ -2,6 +2,13 @@ * Assistant type defines the shape of an assistant object. * @stored */ + +export type AssistantTool = { + type: string + enabled: boolean + settings: any +} + export type Assistant = { /** Represents the avatar of the user. */ avatar: string @@ -22,7 +29,7 @@ export type Assistant = { /** Represents the instructions for the object. */ instructions?: string /** Represents the tools associated with the object. */ - tools?: any + tools?: AssistantTool[] /** Represents the file identifiers associated with the object. */ file_ids: string[] /** Represents the metadata of the object. */ diff --git a/core/src/types/inference/inferenceEntity.ts b/core/src/types/inference/inferenceEntity.ts index 58b838ae7..c37e3b079 100644 --- a/core/src/types/inference/inferenceEntity.ts +++ b/core/src/types/inference/inferenceEntity.ts @@ -1,3 +1,5 @@ +import { ContentType, ContentValue } from '../message' + /** * The role of the author of this message. */ @@ -13,7 +15,32 @@ export enum ChatCompletionRole { */ export type ChatCompletionMessage = { /** The contents of the message. **/ - content?: string + content?: ChatCompletionMessageContent /** The role of the author of this message. **/ role: ChatCompletionRole } + +export type ChatCompletionMessageContent = + | string + | (ChatCompletionMessageContentText & + ChatCompletionMessageContentImage & + ChatCompletionMessageContentDoc)[] + +export enum ChatCompletionMessageContentType { + Text = 'text', + Image = 'image_url', + Doc = 'doc_url', +} + +export type ChatCompletionMessageContentText = { + type: ChatCompletionMessageContentType + text: string +} +export type ChatCompletionMessageContentImage = { + type: ChatCompletionMessageContentType + image_url: { url: string } +} +export type ChatCompletionMessageContentDoc = { + type: ChatCompletionMessageContentType + doc_url: { url: string } +} diff --git a/core/src/types/message/messageEntity.ts b/core/src/types/message/messageEntity.ts index 199743796..87e4b1997 100644 --- a/core/src/types/message/messageEntity.ts +++ b/core/src/types/message/messageEntity.ts @@ -1,5 +1,6 @@ import { ChatCompletionMessage, ChatCompletionRole } from '../inference' import { ModelInfo } from '../model' +import { Thread } from '../thread' /** * The `ThreadMessage` type defines the shape of a thread's message object. @@ -35,7 +36,10 @@ export type ThreadMessage = { export type MessageRequest = { id?: string - /** The thread id of the message request. **/ + /** + * @deprecated Use thread object instead + * The thread id of the message request. + */ threadId: string /** @@ -48,6 +52,10 @@ export type MessageRequest = { /** Settings for constructing a chat completion request **/ model?: ModelInfo + + /** The thread of this message is belong to. **/ + // TODO: deprecate threadId field + thread?: Thread } /** @@ -62,7 +70,7 @@ export enum MessageStatus { /** Message loaded with error. **/ Error = 'error', /** Message is cancelled streaming */ - Stopped = "stopped" + Stopped = 'stopped', } /** @@ -71,6 +79,7 @@ export enum MessageStatus { export enum ContentType { Text = 'text', Image = 'image', + Pdf = 'pdf', } /** @@ -80,6 +89,8 @@ export enum ContentType { export type ContentValue = { value: string annotations: string[] + name?: string + size?: number } /** diff --git a/core/src/types/model/modelEntity.ts b/core/src/types/model/modelEntity.ts index c60ab7650..727ff085f 100644 --- a/core/src/types/model/modelEntity.ts +++ b/core/src/types/model/modelEntity.ts @@ -7,6 +7,7 @@ export type ModelInfo = { settings: ModelSettingParams parameters: ModelRuntimeParams engine?: InferenceEngine + proxyEngine?: InferenceEngine } /** @@ -18,7 +19,8 @@ export enum InferenceEngine { nitro = 'nitro', openai = 'openai', triton_trtllm = 'triton_trtllm', - hf_endpoint = 'hf_endpoint', + + tool_retrieval_enabled = 'tool_retrieval_enabled', } export type ModelArtifact = { @@ -90,6 +92,13 @@ export type Model = { * The model engine. */ engine: InferenceEngine + + proxyEngine?: InferenceEngine + + /** + * Is multimodal or not. + */ + visionModel?: boolean } export type ModelMetadata = { @@ -129,4 +138,5 @@ export type ModelRuntimeParams = { stop?: string[] frequency_penalty?: number presence_penalty?: number + engine?: string } diff --git a/core/src/types/thread/index.ts b/core/src/types/thread/index.ts index c6ff6204a..32155e1cd 100644 --- a/core/src/types/thread/index.ts +++ b/core/src/types/thread/index.ts @@ -1,2 +1,3 @@ export * from './threadEntity' export * from './threadInterface' +export * from './threadEvent' diff --git a/core/src/types/thread/threadEntity.ts b/core/src/types/thread/threadEntity.ts index 4ff3aa1fc..37136eae6 100644 --- a/core/src/types/thread/threadEntity.ts +++ b/core/src/types/thread/threadEntity.ts @@ -1,3 +1,4 @@ +import { AssistantTool } from '../assistant' import { ModelInfo } from '../model' /** @@ -30,6 +31,7 @@ export type ThreadAssistantInfo = { assistant_name: string model: ModelInfo instructions?: string + tools?: AssistantTool[] } /** diff --git a/core/src/types/thread/threadEvent.ts b/core/src/types/thread/threadEvent.ts new file mode 100644 index 000000000..4b19b09c1 --- /dev/null +++ b/core/src/types/thread/threadEvent.ts @@ -0,0 +1,4 @@ +export enum ThreadEvent { + /** The `OnThreadStarted` event is emitted when a thread is started. */ + OnThreadStarted = 'OnThreadStarted', +} diff --git a/electron/handlers/fileManager.ts b/electron/handlers/fileManager.ts index f41286934..2528aef71 100644 --- a/electron/handlers/fileManager.ts +++ b/electron/handlers/fileManager.ts @@ -59,4 +59,20 @@ export function handleFileMangerIPCs() { return fileStat } ) + + ipcMain.handle( + FileManagerRoute.writeBlob, + async (_event, path: string, data: string): Promise => { + try { + const normalizedPath = normalizeFilePath(path) + const dataBuffer = Buffer.from(data, 'base64') + fs.writeFileSync( + join(getJanDataFolderPath(), normalizedPath), + dataBuffer + ) + } catch (err) { + console.error(`writeFile ${path} result: ${err}`) + } + } + ) } diff --git a/electron/handlers/fs.ts b/electron/handlers/fs.ts index 408a5fd10..34026b940 100644 --- a/electron/handlers/fs.ts +++ b/electron/handlers/fs.ts @@ -1,9 +1,9 @@ import { ipcMain } from 'electron' -import { FileSystemRoute } from '@janhq/core' -import { join } from 'path' import { getJanDataFolderPath, normalizeFilePath } from '@janhq/core/node' - +import fs from 'fs' +import { FileManagerRoute, FileSystemRoute } from '@janhq/core' +import { join } from 'path' /** * Handles file system operations. */ @@ -15,7 +15,7 @@ export function handleFsIPCs() { mdl[route]( ...args.map((arg) => typeof arg === 'string' && - (arg.includes(`file:/`) || arg.includes(`file:\\`)) + (arg.startsWith(`file:/`) || arg.startsWith(`file:\\`)) ? join(getJanDataFolderPath(), normalizeFilePath(arg)) : arg ) diff --git a/extensions/assistant-extension/package.json b/extensions/assistant-extension/package.json index 4e84aa573..f4e4dd825 100644 --- a/extensions/assistant-extension/package.json +++ b/extensions/assistant-extension/package.json @@ -3,26 +3,46 @@ "version": "1.0.0", "description": "This extension enables assistants, including Jan, a default assistant that can call all downloaded models", "main": "dist/index.js", - "module": "dist/module.js", + "node": "dist/node/index.js", "author": "Jan ", "license": "AGPL-3.0", "scripts": { - "build": "tsc -b . && webpack --config webpack.config.js", + "build": "tsc --module commonjs && rollup -c rollup.config.ts", "build:publish": "rimraf *.tgz --glob && npm run build && npm pack && cpx *.tgz ../../electron/pre-install" }, "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-replace": "^5.0.5", + "@types/pdf-parse": "^1.1.4", + "cpx": "^1.5.0", "rimraf": "^3.0.2", - "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" + "rollup": "^2.38.5", + "rollup-plugin-define": "^1.0.1", + "rollup-plugin-sourcemaps": "^0.6.3", + "rollup-plugin-typescript2": "^0.36.0", + "typescript": "^5.3.3" }, "dependencies": { "@janhq/core": "file:../../core", + "@langchain/community": "0.0.13", + "hnswlib-node": "^1.4.2", + "langchain": "^0.0.214", "path-browserify": "^1.0.1", + "pdf-parse": "^1.1.1", "ts-loader": "^9.5.0" }, "files": [ "dist/*", "package.json", "README.md" + ], + "bundleDependencies": [ + "@janhq/core", + "@langchain/community", + "hnswlib-node", + "langchain", + "pdf-parse" ] } diff --git a/extensions/assistant-extension/rollup.config.ts b/extensions/assistant-extension/rollup.config.ts new file mode 100644 index 000000000..7916ef9c8 --- /dev/null +++ b/extensions/assistant-extension/rollup.config.ts @@ -0,0 +1,81 @@ +import resolve from "@rollup/plugin-node-resolve"; +import commonjs from "@rollup/plugin-commonjs"; +import sourceMaps from "rollup-plugin-sourcemaps"; +import typescript from "rollup-plugin-typescript2"; +import json from "@rollup/plugin-json"; +import replace from "@rollup/plugin-replace"; + +const packageJson = require("./package.json"); + +const pkg = require("./package.json"); + +export default [ + { + input: `src/index.ts`, + output: [{ file: pkg.main, format: "es", sourcemap: true }], + // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') + external: [], + watch: { + include: "src/**", + }, + plugins: [ + replace({ + NODE: JSON.stringify(`${packageJson.name}/${packageJson.node}`), + EXTENSION_NAME: JSON.stringify(packageJson.name), + VERSION: JSON.stringify(packageJson.version), + }), + // Allow json resolution + json(), + // Compile TypeScript files + typescript({ useTsconfigDeclarationDir: true }), + // Compile TypeScript files + // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) + commonjs(), + // Allow node_modules resolution, so you can use 'external' to control + // which external modules to include in the bundle + // https://github.com/rollup/rollup-plugin-node-resolve#usage + resolve({ + extensions: [".js", ".ts", ".svelte"], + }), + + // Resolve source maps to the original source + sourceMaps(), + ], + }, + { + input: `src/node/index.ts`, + output: [{ dir: "dist/node", format: "cjs", sourcemap: false }], + // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') + external: [ + "@janhq/core/node", + "@langchain/community", + "langchain", + "langsmith", + "path", + "hnswlib-node", + ], + watch: { + include: "src/node/**", + }, + // inlineDynamicImports: true, + plugins: [ + // Allow json resolution + json(), + // Compile TypeScript files + typescript({ useTsconfigDeclarationDir: true }), + // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) + commonjs({ + ignoreDynamicRequires: true, + }), + // Allow node_modules resolution, so you can use 'external' to control + // which external modules to include in the bundle + // https://github.com/rollup/rollup-plugin-node-resolve#usage + resolve({ + extensions: [".ts", ".js", ".json"], + }), + + // Resolve source maps to the original source + // sourceMaps(), + ], + }, +]; diff --git a/extensions/assistant-extension/src/@types/global.d.ts b/extensions/assistant-extension/src/@types/global.d.ts index 3b45ccc5a..dc11709a4 100644 --- a/extensions/assistant-extension/src/@types/global.d.ts +++ b/extensions/assistant-extension/src/@types/global.d.ts @@ -1 +1,3 @@ -declare const MODULE: string; +declare const NODE: string; +declare const EXTENSION_NAME: string; +declare const VERSION: string; diff --git a/extensions/assistant-extension/src/index.ts b/extensions/assistant-extension/src/index.ts index 098ab1f54..6495ea786 100644 --- a/extensions/assistant-extension/src/index.ts +++ b/extensions/assistant-extension/src/index.ts @@ -1,15 +1,151 @@ -import { fs, Assistant, AssistantExtension } from "@janhq/core"; -import { join } from "path"; +import { + fs, + Assistant, + MessageRequest, + events, + InferenceEngine, + MessageEvent, + InferenceEvent, + joinPath, + executeOnMain, + AssistantExtension, +} from "@janhq/core"; export default class JanAssistantExtension extends AssistantExtension { private static readonly _homeDir = "file://assistants"; + controller = new AbortController(); + isCancelled = false; + retrievalThreadId: string | undefined = undefined; + async onLoad() { // making the assistant directory - if (!(await fs.existsSync(JanAssistantExtension._homeDir))) - fs.mkdirSync(JanAssistantExtension._homeDir).then(() => { - this.createJanAssistant(); - }); + const assistantDirExist = await fs.existsSync( + JanAssistantExtension._homeDir, + ); + if ( + localStorage.getItem(`${EXTENSION_NAME}-version`) !== VERSION || + !assistantDirExist + ) { + if (!assistantDirExist) + await fs.mkdirSync(JanAssistantExtension._homeDir); + + // Write assistant metadata + this.createJanAssistant(); + // Finished migration + localStorage.setItem(`${EXTENSION_NAME}-version`, VERSION); + } + + // Events subscription + events.on(MessageEvent.OnMessageSent, (data: MessageRequest) => + JanAssistantExtension.handleMessageRequest(data, this), + ); + + events.on(InferenceEvent.OnInferenceStopped, () => { + JanAssistantExtension.handleInferenceStopped(this); + }); + } + + private static async handleInferenceStopped(instance: JanAssistantExtension) { + instance.isCancelled = true; + instance.controller?.abort(); + } + + private static async handleMessageRequest( + data: MessageRequest, + instance: JanAssistantExtension, + ) { + instance.isCancelled = false; + instance.controller = new AbortController(); + + if ( + data.model?.engine !== InferenceEngine.tool_retrieval_enabled || + !data.messages || + !data.thread?.assistants[0]?.tools + ) { + return; + } + + const latestMessage = data.messages[data.messages.length - 1]; + + // Ingest the document if needed + if ( + latestMessage && + latestMessage.content && + typeof latestMessage.content !== "string" + ) { + const docFile = latestMessage.content[1]?.doc_url?.url; + if (docFile) { + await executeOnMain( + NODE, + "toolRetrievalIngestNewDocument", + docFile, + data.model?.proxyEngine, + ); + } + } + + // Load agent on thread changed + if (instance.retrievalThreadId !== data.threadId) { + await executeOnMain(NODE, "toolRetrievalLoadThreadMemory", data.threadId); + + instance.retrievalThreadId = data.threadId; + + // Update the text splitter + await executeOnMain( + NODE, + "toolRetrievalUpdateTextSplitter", + data.thread.assistants[0].tools[0]?.settings?.chunk_size ?? 4000, + data.thread.assistants[0].tools[0]?.settings?.chunk_overlap ?? 200, + ); + } + + if (latestMessage.content) { + const prompt = + typeof latestMessage.content === "string" + ? latestMessage.content + : latestMessage.content[0].text; + // Retrieve the result + console.debug("toolRetrievalQuery", latestMessage.content); + const retrievalResult = await executeOnMain( + NODE, + "toolRetrievalQueryResult", + prompt, + ); + + // Update the message content + // Using the retrieval template with the result and query + if (data.thread?.assistants[0].tools) + data.messages[data.messages.length - 1].content = + data.thread.assistants[0].tools[0].settings?.retrieval_template + ?.replace("{CONTEXT}", retrievalResult) + .replace("{QUESTION}", prompt); + } + + // Filter out all the messages that are not text + data.messages = data.messages.map((message) => { + if ( + message.content && + typeof message.content !== "string" && + (message.content.length ?? 0) > 0 + ) { + return { + ...message, + content: [message.content[0]], + }; + } + return message; + }); + + // Reroute the result to inference engine + const output = { + ...data, + model: { + ...data.model, + engine: data.model.proxyEngine, + }, + }; + events.emit(MessageEvent.OnMessageSent, output); } /** @@ -18,15 +154,21 @@ export default class JanAssistantExtension extends AssistantExtension { onUnload(): void {} async createAssistant(assistant: Assistant): Promise { - const assistantDir = join(JanAssistantExtension._homeDir, assistant.id); + const assistantDir = await joinPath([ + JanAssistantExtension._homeDir, + assistant.id, + ]); if (!(await fs.existsSync(assistantDir))) await fs.mkdirSync(assistantDir); // store the assistant metadata json - const assistantMetadataPath = join(assistantDir, "assistant.json"); + const assistantMetadataPath = await joinPath([ + assistantDir, + "assistant.json", + ]); try { await fs.writeFileSync( assistantMetadataPath, - JSON.stringify(assistant, null, 2) + JSON.stringify(assistant, null, 2), ); } catch (err) { console.error(err); @@ -38,14 +180,17 @@ export default class JanAssistantExtension extends AssistantExtension { // get all the assistant metadata json const results: Assistant[] = []; const allFileName: string[] = await fs.readdirSync( - JanAssistantExtension._homeDir + JanAssistantExtension._homeDir, ); for (const fileName of allFileName) { - const filePath = join(JanAssistantExtension._homeDir, fileName); + const filePath = await joinPath([ + JanAssistantExtension._homeDir, + fileName, + ]); if (filePath.includes(".DS_Store")) continue; const jsonFiles: string[] = (await fs.readdirSync(filePath)).filter( - (file: string) => file === "assistant.json" + (file: string) => file === "assistant.json", ); if (jsonFiles.length !== 1) { @@ -54,8 +199,8 @@ export default class JanAssistantExtension extends AssistantExtension { } const content = await fs.readFileSync( - join(filePath, jsonFiles[0]), - "utf-8" + await joinPath([filePath, jsonFiles[0]]), + "utf-8", ); const assistant: Assistant = typeof content === "object" ? content : JSON.parse(content); @@ -72,7 +217,10 @@ export default class JanAssistantExtension extends AssistantExtension { } // remove the directory - const assistantDir = join(JanAssistantExtension._homeDir, assistant.id); + const assistantDir = await joinPath([ + JanAssistantExtension._homeDir, + assistant.id, + ]); await fs.rmdirSync(assistantDir); return Promise.resolve(); } @@ -88,7 +236,24 @@ export default class JanAssistantExtension extends AssistantExtension { description: "A default assistant that can use all downloaded models", model: "*", instructions: "", - tools: undefined, + tools: [ + { + type: "retrieval", + enabled: false, + settings: { + top_k: 2, + chunk_size: 1024, + chunk_overlap: 64, + retrieval_template: `Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. + ---------------- + CONTEXT: {CONTEXT} + ---------------- + QUESTION: {QUESTION} + ---------------- + Helpful Answer:`, + }, + }, + ], file_ids: [], metadata: undefined, }; diff --git a/extensions/assistant-extension/src/node/engine.ts b/extensions/assistant-extension/src/node/engine.ts new file mode 100644 index 000000000..54b2a6ba1 --- /dev/null +++ b/extensions/assistant-extension/src/node/engine.ts @@ -0,0 +1,13 @@ +import fs from "fs"; +import path from "path"; +import { getJanDataFolderPath } from "@janhq/core/node"; + +// Sec: Do not send engine settings over requests +// Read it manually instead +export const readEmbeddingEngine = (engineName: string) => { + const engineSettings = fs.readFileSync( + path.join(getJanDataFolderPath(), "engines", `${engineName}.json`), + "utf-8", + ); + return JSON.parse(engineSettings); +}; diff --git a/extensions/assistant-extension/src/node/index.ts b/extensions/assistant-extension/src/node/index.ts new file mode 100644 index 000000000..95a7243a4 --- /dev/null +++ b/extensions/assistant-extension/src/node/index.ts @@ -0,0 +1,39 @@ +import { getJanDataFolderPath, normalizeFilePath } from "@janhq/core/node"; +import { Retrieval } from "./tools/retrieval"; +import path from "path"; + +const retrieval = new Retrieval(); + +export async function toolRetrievalUpdateTextSplitter( + chunkSize: number, + chunkOverlap: number, +) { + retrieval.updateTextSplitter(chunkSize, chunkOverlap); + return Promise.resolve(); +} +export async function toolRetrievalIngestNewDocument( + file: string, + engine: string, +) { + const filePath = path.join(getJanDataFolderPath(), normalizeFilePath(file)); + const threadPath = path.dirname(filePath.replace("files", "")); + retrieval.updateEmbeddingEngine(engine); + await retrieval.ingestAgentKnowledge(filePath, `${threadPath}/memory`); + return Promise.resolve(); +} + +export async function toolRetrievalLoadThreadMemory(threadId: string) { + try { + await retrieval.loadRetrievalAgent( + path.join(getJanDataFolderPath(), "threads", threadId, "memory"), + ); + return Promise.resolve(); + } catch (err) { + console.debug(err); + } +} + +export async function toolRetrievalQueryResult(query: string) { + const res = await retrieval.generateResult(query); + return Promise.resolve(res); +} diff --git a/extensions/assistant-extension/src/node/tools/retrieval/index.ts b/extensions/assistant-extension/src/node/tools/retrieval/index.ts new file mode 100644 index 000000000..f9d5c4029 --- /dev/null +++ b/extensions/assistant-extension/src/node/tools/retrieval/index.ts @@ -0,0 +1,78 @@ +import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"; +import { formatDocumentsAsString } from "langchain/util/document"; +import { PDFLoader } from "langchain/document_loaders/fs/pdf"; + +import { HNSWLib } from "langchain/vectorstores/hnswlib"; + +import { OpenAIEmbeddings } from "langchain/embeddings/openai"; +import { readEmbeddingEngine } from "../../engine"; + +export class Retrieval { + public chunkSize: number = 100; + public chunkOverlap?: number = 0; + private retriever: any; + + private embeddingModel: any = undefined; + private textSplitter?: RecursiveCharacterTextSplitter; + + constructor(chunkSize: number = 4000, chunkOverlap: number = 200) { + this.updateTextSplitter(chunkSize, chunkOverlap); + this.embeddingModel = new OpenAIEmbeddings({}); + } + + public updateTextSplitter(chunkSize: number, chunkOverlap: number): void { + this.chunkSize = chunkSize; + this.chunkOverlap = chunkOverlap; + this.textSplitter = new RecursiveCharacterTextSplitter({ + chunkSize: chunkSize, + chunkOverlap: chunkOverlap, + }); + } + + public updateEmbeddingEngine(engine: string): void { + // Engine settings are not compatible with the current embedding model params + // Switch case manually for now + const settings = readEmbeddingEngine(engine); + if (engine === "nitro") { + this.embeddingModel = new OpenAIEmbeddings( + { openAIApiKey: "nitro-embedding" }, + { basePath: "http://127.0.0.1:3928/v1" }, + ); + } else { + // Fallback to OpenAI Settings + this.embeddingModel = new OpenAIEmbeddings({ + configuration: { + apiKey: settings.api_key, + }, + }); + } + } + + public ingestAgentKnowledge = async ( + filePath: string, + memoryPath: string, + ): Promise => { + const loader = new PDFLoader(filePath, { + splitPages: true, + }); + const doc = await loader.load(); + const docs = await this.textSplitter!.splitDocuments(doc); + const vectorStore = await HNSWLib.fromDocuments(docs, this.embeddingModel); + return vectorStore.save(memoryPath); + }; + + public loadRetrievalAgent = async (memoryPath: string): Promise => { + const vectorStore = await HNSWLib.load(memoryPath, this.embeddingModel); + this.retriever = vectorStore.asRetriever(2); + return Promise.resolve(); + }; + + public generateResult = async (query: string): Promise => { + if (!this.retriever) { + return Promise.resolve(" "); + } + const relevantDocs = await this.retriever.getRelevantDocuments(query); + const serializedDoc = formatDocumentsAsString(relevantDocs); + return Promise.resolve(serializedDoc); + }; +} diff --git a/extensions/assistant-extension/tsconfig.json b/extensions/assistant-extension/tsconfig.json index 2477d58ce..d3794cace 100644 --- a/extensions/assistant-extension/tsconfig.json +++ b/extensions/assistant-extension/tsconfig.json @@ -1,14 +1,20 @@ { "compilerOptions": { - "target": "es2016", - "module": "ES6", "moduleResolution": "node", - "outDir": "./dist", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": false, + "target": "es5", + "module": "ES2020", + "lib": ["es2015", "es2016", "es2017", "dom"], + "strict": true, + "sourceMap": true, + "declaration": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "declarationDir": "dist/types", + "outDir": "dist", + "importHelpers": true, + "typeRoots": ["node_modules/@types"], "skipLibCheck": true, - "rootDir": "./src" }, - "include": ["./src"] + "include": ["src"], } diff --git a/extensions/assistant-extension/webpack.config.js b/extensions/assistant-extension/webpack.config.js deleted file mode 100644 index 74d16fc8e..000000000 --- a/extensions/assistant-extension/webpack.config.js +++ /dev/null @@ -1,38 +0,0 @@ -const path = require("path"); -const webpack = require("webpack"); -const packageJson = require("./package.json"); - -module.exports = { - experiments: { outputModule: true }, - entry: "./src/index.ts", // Adjust the entry point to match your project's main file - mode: "production", - module: { - rules: [ - { - test: /\.tsx?$/, - use: "ts-loader", - exclude: /node_modules/, - }, - ], - }, - output: { - filename: "index.js", // Adjust the output file name as needed - path: path.resolve(__dirname, "dist"), - library: { type: "module" }, // Specify ESM output format - }, - plugins: [ - new webpack.DefinePlugin({ - MODULE: JSON.stringify(`${packageJson.name}/${packageJson.module}`), - }), - ], - resolve: { - extensions: [".ts", ".js"], - fallback: { - path: require.resolve("path-browserify"), - }, - }, - optimization: { - minimize: false, - }, - // Add loaders and other configuration as needed for your project -}; diff --git a/extensions/conversational-extension/src/index.ts b/extensions/conversational-extension/src/index.ts index 66becb748..61f0fd0e9 100644 --- a/extensions/conversational-extension/src/index.ts +++ b/extensions/conversational-extension/src/index.ts @@ -4,15 +4,14 @@ import { ConversationalExtension, Thread, ThreadMessage, + events, } from '@janhq/core' /** * JSONConversationalExtension is a ConversationalExtension implementation that provides * functionality for managing threads. */ -export default class JSONConversationalExtension - extends ConversationalExtension -{ +export default class JSONConversationalExtension extends ConversationalExtension { private static readonly _homeDir = 'file://threads' private static readonly _threadInfoFileName = 'thread.json' private static readonly _threadMessagesFileName = 'messages.jsonl' @@ -119,6 +118,32 @@ export default class JSONConversationalExtension ]) if (!(await fs.existsSync(threadDirPath))) await fs.mkdirSync(threadDirPath) + + if (message.content[0].type === 'image') { + const filesPath = await joinPath([threadDirPath, 'files']) + if (!(await fs.existsSync(filesPath))) await fs.mkdirSync(filesPath) + + const imagePath = await joinPath([filesPath, `${message.id}.png`]) + const base64 = message.content[0].text.annotations[0] + await this.storeImage(base64, imagePath) + // if (fs.existsSync(imagePath)) { + // message.content[0].text.annotations[0] = imagePath + // } + } + + if (message.content[0].type === 'pdf') { + const filesPath = await joinPath([threadDirPath, 'files']) + if (!(await fs.existsSync(filesPath))) await fs.mkdirSync(filesPath) + + const filePath = await joinPath([filesPath, `${message.id}.pdf`]) + const blob = message.content[0].text.annotations[0] + await this.storeFile(blob, filePath) + + if (await fs.existsSync(filePath)) { + // Use file path instead of blob + message.content[0].text.annotations[0] = `threads/${message.thread_id}/files/${message.id}.pdf` + } + } await fs.appendFileSync(threadMessagePath, JSON.stringify(message) + '\n') Promise.resolve() } catch (err) { @@ -126,6 +151,25 @@ export default class JSONConversationalExtension } } + async storeImage(base64: string, filePath: string): Promise { + const base64Data = base64.replace(/^data:image\/\w+;base64,/, '') + + try { + await fs.writeBlob(filePath, base64Data) + } catch (err) { + console.error(err) + } + } + + async storeFile(base64: string, filePath: string): Promise { + const base64Data = base64.replace(/^data:application\/pdf;base64,/, '') + try { + await fs.writeBlob(filePath, base64Data) + } catch (err) { + console.error(err) + } + } + async writeMessages( threadId: string, messages: ThreadMessage[] @@ -229,7 +273,11 @@ export default class JSONConversationalExtension const messages: ThreadMessage[] = [] result.forEach((line: string) => { - messages.push(JSON.parse(line) as ThreadMessage) + try { + messages.push(JSON.parse(line) as ThreadMessage) + } catch (err) { + console.error(err) + } }) return messages } catch (err) { diff --git a/extensions/inference-nitro-extension/bin/version.txt b/extensions/inference-nitro-extension/bin/version.txt index f2722b133..769ed6ae7 100644 --- a/extensions/inference-nitro-extension/bin/version.txt +++ b/extensions/inference-nitro-extension/bin/version.txt @@ -1 +1 @@ -0.2.12 +0.2.14 diff --git a/extensions/inference-nitro-extension/package.json b/extensions/inference-nitro-extension/package.json index 9379e194b..44727eb70 100644 --- a/extensions/inference-nitro-extension/package.json +++ b/extensions/inference-nitro-extension/package.json @@ -40,6 +40,7 @@ "dependencies": { "@janhq/core": "file:../../core", "@rollup/plugin-replace": "^5.0.5", + "@types/os-utils": "^0.0.4", "fetch-retry": "^5.0.6", "path-browserify": "^1.0.1", "rxjs": "^7.8.1", diff --git a/extensions/inference-nitro-extension/src/index.ts b/extensions/inference-nitro-extension/src/index.ts index 735383a61..0e6edb992 100644 --- a/extensions/inference-nitro-extension/src/index.ts +++ b/extensions/inference-nitro-extension/src/index.ts @@ -50,7 +50,7 @@ export default class JanInferenceNitroExtension extends InferenceExtension { ngl: 100, cpu_threads: 1, cont_batching: false, - embedding: false, + embedding: true, }; controller = new AbortController(); @@ -83,19 +83,19 @@ export default class JanInferenceNitroExtension extends InferenceExtension { // Events subscription events.on(MessageEvent.OnMessageSent, (data: MessageRequest) => - this.onMessageRequest(data) + this.onMessageRequest(data), ); events.on(ModelEvent.OnModelInit, (model: Model) => - this.onModelInit(model) + this.onModelInit(model), ); events.on(ModelEvent.OnModelStop, (model: Model) => - this.onModelStop(model) + this.onModelStop(model), ); events.on(InferenceEvent.OnInferenceStopped, () => - this.onInferenceStopped() + this.onInferenceStopped(), ); // Attempt to fetch nvidia info @@ -120,7 +120,7 @@ export default class JanInferenceNitroExtension extends InferenceExtension { } else { await fs.writeFileSync( engineFile, - JSON.stringify(this._engineSettings, null, 2) + JSON.stringify(this._engineSettings, null, 2), ); } } catch (err) { @@ -148,7 +148,7 @@ export default class JanInferenceNitroExtension extends InferenceExtension { this.getNitroProcesHealthIntervalId = setInterval( () => this.periodicallyGetNitroHealth(), - JanInferenceNitroExtension._intervalHealthCheck + JanInferenceNitroExtension._intervalHealthCheck, ); } diff --git a/extensions/inference-nitro-extension/src/node/index.ts b/extensions/inference-nitro-extension/src/node/index.ts index a75f33df2..77060e414 100644 --- a/extensions/inference-nitro-extension/src/node/index.ts +++ b/extensions/inference-nitro-extension/src/node/index.ts @@ -78,7 +78,7 @@ function stopModel(): Promise { * TODO: Should pass absolute of the model file instead of just the name - So we can modurize the module.ts to npm package */ async function runModel( - wrapper: ModelInitOptions + wrapper: ModelInitOptions, ): Promise { if (wrapper.model.engine !== InferenceEngine.nitro) { // Not a nitro model @@ -96,7 +96,7 @@ async function runModel( const ggufBinFile = files.find( (file) => file === path.basename(currentModelFile) || - file.toLowerCase().includes(SUPPORTED_MODEL_FORMAT) + file.toLowerCase().includes(SUPPORTED_MODEL_FORMAT), ); if (!ggufBinFile) return Promise.reject("No GGUF model file found"); @@ -133,7 +133,6 @@ async function runModel( mmproj: path.join(modelFolderPath, wrapper.model.settings.mmproj), }), }; - console.log(currentSettings); return runNitroAndLoadModel(); } } @@ -192,10 +191,10 @@ function promptTemplateConverter(promptTemplate: string): PromptTemplate { const system_prompt = promptTemplate.substring(0, systemIndex); const user_prompt = promptTemplate.substring( systemIndex + systemMarker.length, - promptIndex + promptIndex, ); const ai_prompt = promptTemplate.substring( - promptIndex + promptMarker.length + promptIndex + promptMarker.length, ); // Return the split parts @@ -205,7 +204,7 @@ function promptTemplateConverter(promptTemplate: string): PromptTemplate { const promptIndex = promptTemplate.indexOf(promptMarker); const user_prompt = promptTemplate.substring(0, promptIndex); const ai_prompt = promptTemplate.substring( - promptIndex + promptMarker.length + promptIndex + promptMarker.length, ); // Return the split parts @@ -234,8 +233,8 @@ function loadLLMModel(settings: any): Promise { .then((res) => { log( `[NITRO]::Debug: Load model success with response ${JSON.stringify( - res - )}` + res, + )}`, ); return Promise.resolve(res); }) @@ -264,8 +263,8 @@ async function validateModelStatus(): Promise { }).then(async (res: Response) => { log( `[NITRO]::Debug: Validate model state success with response ${JSON.stringify( - res - )}` + res, + )}`, ); // If the response is OK, check model_loaded status. if (res.ok) { @@ -316,7 +315,7 @@ function spawnNitroProcess(): Promise { const args: string[] = ["1", LOCAL_HOST, PORT.toString()]; // Execute the binary log( - `[NITRO]::Debug: Spawn nitro at path: ${executableOptions.executablePath}, and args: ${args}` + `[NITRO]::Debug: Spawn nitro at path: ${executableOptions.executablePath}, and args: ${args}`, ); subprocess = spawn( executableOptions.executablePath, @@ -327,7 +326,7 @@ function spawnNitroProcess(): Promise { ...process.env, CUDA_VISIBLE_DEVICES: executableOptions.cudaVisibleDevices, }, - } + }, ); // Handle subprocess output diff --git a/extensions/inference-openai-extension/src/index.ts b/extensions/inference-openai-extension/src/index.ts index 54572041d..44525b631 100644 --- a/extensions/inference-openai-extension/src/index.ts +++ b/extensions/inference-openai-extension/src/index.ts @@ -15,6 +15,7 @@ import { ThreadMessage, events, fs, + InferenceEngine, BaseExtension, MessageEvent, ModelEvent, @@ -57,7 +58,7 @@ export default class JanInferenceOpenAIExtension extends BaseExtension { // Events subscription events.on(MessageEvent.OnMessageSent, (data) => - JanInferenceOpenAIExtension.handleMessageRequest(data, this) + JanInferenceOpenAIExtension.handleMessageRequest(data, this), ); events.on(ModelEvent.OnModelInit, (model: OpenAIModel) => { @@ -81,7 +82,7 @@ export default class JanInferenceOpenAIExtension extends BaseExtension { try { const engineFile = join( JanInferenceOpenAIExtension._homeDir, - JanInferenceOpenAIExtension._engineMetadataFileName + JanInferenceOpenAIExtension._engineMetadataFileName, ); if (await fs.existsSync(engineFile)) { const engine = await fs.readFileSync(engineFile, "utf-8"); @@ -90,7 +91,7 @@ export default class JanInferenceOpenAIExtension extends BaseExtension { } else { await fs.writeFileSync( engineFile, - JSON.stringify(JanInferenceOpenAIExtension._engineSettings, null, 2) + JSON.stringify(JanInferenceOpenAIExtension._engineSettings, null, 2), ); } } catch (err) { @@ -98,7 +99,7 @@ export default class JanInferenceOpenAIExtension extends BaseExtension { } } private static async handleModelInit(model: OpenAIModel) { - if (model.engine !== "openai") { + if (model.engine !== InferenceEngine.openai) { return; } else { JanInferenceOpenAIExtension._currentModel = model; @@ -116,7 +117,7 @@ export default class JanInferenceOpenAIExtension extends BaseExtension { } private static async handleInferenceStopped( - instance: JanInferenceOpenAIExtension + instance: JanInferenceOpenAIExtension, ) { instance.isCancelled = true; instance.controller?.abort(); @@ -130,7 +131,7 @@ export default class JanInferenceOpenAIExtension extends BaseExtension { */ private static async handleMessageRequest( data: MessageRequest, - instance: JanInferenceOpenAIExtension + instance: JanInferenceOpenAIExtension, ) { if (data.model.engine !== "openai") { return; @@ -160,7 +161,7 @@ export default class JanInferenceOpenAIExtension extends BaseExtension { ...JanInferenceOpenAIExtension._currentModel, parameters: data.model.parameters, }, - instance.controller + instance.controller, ).subscribe({ next: (content) => { const messageContent: ThreadContent = { diff --git a/extensions/inference-openai-extension/tsconfig.json b/extensions/inference-openai-extension/tsconfig.json index b48175a16..7bfdd9009 100644 --- a/extensions/inference-openai-extension/tsconfig.json +++ b/extensions/inference-openai-extension/tsconfig.json @@ -3,13 +3,12 @@ "target": "es2016", "module": "ES6", "moduleResolution": "node", - "outDir": "./dist", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": false, "skipLibCheck": true, - "rootDir": "./src" + "rootDir": "./src", }, - "include": ["./src"] + "include": ["./src"], } diff --git a/extensions/inference-triton-trtllm-extension/tsconfig.json b/extensions/inference-triton-trtllm-extension/tsconfig.json index b48175a16..7bfdd9009 100644 --- a/extensions/inference-triton-trtllm-extension/tsconfig.json +++ b/extensions/inference-triton-trtllm-extension/tsconfig.json @@ -3,13 +3,12 @@ "target": "es2016", "module": "ES6", "moduleResolution": "node", - "outDir": "./dist", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": false, "skipLibCheck": true, - "rootDir": "./src" + "rootDir": "./src", }, - "include": ["./src"] + "include": ["./src"], } diff --git a/web/containers/CardSidebar/index.tsx b/web/containers/CardSidebar/index.tsx index bc5047497..c0dd19ba5 100644 --- a/web/containers/CardSidebar/index.tsx +++ b/web/containers/CardSidebar/index.tsx @@ -17,6 +17,7 @@ import { activeThreadAtom } from '@/helpers/atoms/Thread.atom' interface Props { children: ReactNode + rightAction?: ReactNode title: string asChild?: boolean hideMoreVerticalAction?: boolean @@ -25,6 +26,7 @@ export default function CardSidebar({ children, title, asChild, + rightAction, hideMoreVerticalAction, }: Props) { const [show, setShow] = useState(true) @@ -53,27 +55,16 @@ export default function CardSidebar({
- {title} -
- {!asChild && ( - <> - {!hideMoreVerticalAction && ( -
setMore(!more)} - > - -
- )} - - )} +
+ {title} +
+
+ {rightAction && rightAction} + {!asChild && ( + <> + {!hideMoreVerticalAction && ( +
setMore(!more)} + > + +
+ )} + + )}
{more && ( diff --git a/web/containers/Checkbox/index.tsx b/web/containers/Checkbox/index.tsx index e8f916d98..a545771b6 100644 --- a/web/containers/Checkbox/index.tsx +++ b/web/containers/Checkbox/index.tsx @@ -9,54 +9,26 @@ import { TooltipTrigger, } from '@janhq/uikit' -import { useAtomValue, useSetAtom } from 'jotai' import { InfoIcon } from 'lucide-react' -import { useActiveModel } from '@/hooks/useActiveModel' -import useUpdateModelParameters from '@/hooks/useUpdateModelParameters' - -import { getConfigurationsData } from '@/utils/componentSettings' -import { toSettingParams } from '@/utils/modelParam' - -import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' -import { - engineParamsUpdateAtom, - getActiveThreadIdAtom, - getActiveThreadModelParamsAtom, -} from '@/helpers/atoms/Thread.atom' - type Props = { name: string title: string + enabled?: boolean description: string checked: boolean + onValueChanged?: (e: string | number | boolean) => void } -const Checkbox: React.FC = ({ name, title, checked, description }) => { - const { updateModelParameter } = useUpdateModelParameters() - const threadId = useAtomValue(getActiveThreadIdAtom) - - const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom) - - const modelSettingParams = toSettingParams(activeModelParams) - - const engineParams = getConfigurationsData(modelSettingParams) - - const setEngineParamsUpdate = useSetAtom(engineParamsUpdateAtom) - - const serverEnabled = useAtomValue(serverEnabledAtom) - - const { stopModel } = useActiveModel() - +const Checkbox: React.FC = ({ + title, + checked, + enabled = true, + description, + onValueChanged, +}) => { const onCheckedChange = (checked: boolean) => { - if (!threadId) return - if (engineParams.some((x) => x.name.includes(name))) { - setEngineParamsUpdate(true) - stopModel() - } else { - setEngineParamsUpdate(false) - } - updateModelParameter(threadId, name, checked) + onValueChanged?.(checked) } return ( @@ -80,7 +52,7 @@ const Checkbox: React.FC = ({ name, title, checked, description }) => {
) diff --git a/web/containers/Layout/TopBar/index.tsx b/web/containers/Layout/TopBar/index.tsx index ac05e4e1a..ab67cb3b7 100644 --- a/web/containers/Layout/TopBar/index.tsx +++ b/web/containers/Layout/TopBar/index.tsx @@ -120,13 +120,13 @@ const TopBar = () => {
-
- {activeThread && ( + {activeThread && ( +
{showing && (
@@ -227,8 +227,8 @@ const TopBar = () => { />
- )} -
+
+ )} )} diff --git a/web/containers/Loader/GenerateResponse.tsx b/web/containers/Loader/GenerateResponse.tsx new file mode 100644 index 000000000..457c44987 --- /dev/null +++ b/web/containers/Loader/GenerateResponse.tsx @@ -0,0 +1,39 @@ +import React, { useEffect, useState } from 'react' + +export default function GenerateResponse() { + const [loader, setLoader] = useState(0) + + // This is fake loader please fix this when we have realtime percentage when load model + useEffect(() => { + if (loader === 24) { + setTimeout(() => { + setLoader(loader + 1) + }, 250) + } else if (loader === 50) { + setTimeout(() => { + setLoader(loader + 1) + }, 250) + } else if (loader === 78) { + setTimeout(() => { + setLoader(loader + 1) + }, 250) + } else if (loader === 85) { + setLoader(85) + } else { + setLoader(loader + 1) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [loader]) + + return ( +
+
+
+ Generating response... +
+
+ ) +} diff --git a/web/containers/ModelConfigInput/index.tsx b/web/containers/ModelConfigInput/index.tsx index e409fd424..d573a0bf9 100644 --- a/web/containers/ModelConfigInput/index.tsx +++ b/web/containers/ModelConfigInput/index.tsx @@ -7,65 +7,26 @@ import { TooltipTrigger, } from '@janhq/uikit' -import { useAtomValue, useSetAtom } from 'jotai' - import { InfoIcon } from 'lucide-react' -import { useActiveModel } from '@/hooks/useActiveModel' -import useUpdateModelParameters from '@/hooks/useUpdateModelParameters' - -import { getConfigurationsData } from '@/utils/componentSettings' - -import { toSettingParams } from '@/utils/modelParam' - -import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' -import { - engineParamsUpdateAtom, - getActiveThreadIdAtom, - getActiveThreadModelParamsAtom, -} from '@/helpers/atoms/Thread.atom' - type Props = { title: string + enabled?: boolean name: string description: string placeholder: string value: string + onValueChanged?: (e: string | number | boolean) => void } const ModelConfigInput: React.FC = ({ title, - name, + enabled = true, value, description, placeholder, + onValueChanged, }) => { - const { updateModelParameter } = useUpdateModelParameters() - const threadId = useAtomValue(getActiveThreadIdAtom) - - const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom) - - const modelSettingParams = toSettingParams(activeModelParams) - - const engineParams = getConfigurationsData(modelSettingParams) - - const setEngineParamsUpdate = useSetAtom(engineParamsUpdateAtom) - - const { stopModel } = useActiveModel() - - const serverEnabled = useAtomValue(serverEnabledAtom) - - const onValueChanged = (e: React.ChangeEvent) => { - if (!threadId) return - if (engineParams.some((x) => x.name.includes(name))) { - setEngineParamsUpdate(true) - stopModel() - } else { - setEngineParamsUpdate(false) - } - updateModelParameter(threadId, name, e.target.value) - } - return (
@@ -86,9 +47,9 @@ const ModelConfigInput: React.FC = ({