From 3b87b7ae3a4ff9e9857141025f1afbe44aaee348 Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Thu, 15 Aug 2024 21:21:10 +0700 Subject: [PATCH 1/7] chore: update model dropdown and my model with collapsible chevron --- core/src/types/model/modelEntity.ts | 4 + web/containers/ModelDropdown/index.tsx | 486 ++++++++++-------- web/containers/SetupRemoteModel/index.tsx | 21 +- web/helpers/atoms/Model.atom.ts | 6 +- web/public/images/ModelProvider/anthropic.svg | 10 +- web/public/images/ModelProvider/cohere.svg | 39 +- web/public/images/ModelProvider/cortex.svg | 14 + web/public/images/ModelProvider/dot.svg | 3 + web/public/images/ModelProvider/google.svg | 9 + web/public/images/ModelProvider/groq.svg | 9 + .../images/ModelProvider/hugging-face.svg | 8 + web/public/images/ModelProvider/martian.svg | 12 +- web/public/images/ModelProvider/meta.svg | 72 +++ web/public/images/ModelProvider/mistral.svg | 58 +-- web/public/images/ModelProvider/nitro.svg | 6 + web/public/images/ModelProvider/nvidia.svg | 10 + .../images/ModelProvider/openRouter.svg | 14 + web/public/images/ModelProvider/openai.svg | 33 +- web/public/images/ModelProvider/send.svg | 3 + .../Settings/MyModels/MyModelList/index.tsx | 27 +- web/screens/Settings/MyModels/index.tsx | 174 +++++-- web/utils/modelEngine.ts | 66 +++ 22 files changed, 716 insertions(+), 368 deletions(-) create mode 100644 web/public/images/ModelProvider/cortex.svg create mode 100644 web/public/images/ModelProvider/dot.svg create mode 100644 web/public/images/ModelProvider/google.svg create mode 100644 web/public/images/ModelProvider/groq.svg create mode 100644 web/public/images/ModelProvider/hugging-face.svg create mode 100644 web/public/images/ModelProvider/meta.svg create mode 100644 web/public/images/ModelProvider/nitro.svg create mode 100644 web/public/images/ModelProvider/nvidia.svg create mode 100644 web/public/images/ModelProvider/openRouter.svg create mode 100644 web/public/images/ModelProvider/send.svg create mode 100644 web/utils/modelEngine.ts diff --git a/core/src/types/model/modelEntity.ts b/core/src/types/model/modelEntity.ts index 426b30846..f3520a4e0 100644 --- a/core/src/types/model/modelEntity.ts +++ b/core/src/types/model/modelEntity.ts @@ -25,6 +25,10 @@ export enum InferenceEngine { triton_trtllm = 'triton_trtllm', nitro_tensorrt_llm = 'nitro-tensorrt-llm', cohere = 'cohere', + nvdia = 'nvidia', + cortex_llamacpp = 'cortex.llamacpp', + cortex_onnx = 'cortex.onnx', + cortex_tensorrtllm = 'cortex.tensorrtllm', } export type ModelArtifact = { diff --git a/web/containers/ModelDropdown/index.tsx b/web/containers/ModelDropdown/index.tsx index c19fb64bd..981ce3276 100644 --- a/web/containers/ModelDropdown/index.tsx +++ b/web/containers/ModelDropdown/index.tsx @@ -1,11 +1,25 @@ import { useState, useMemo, useEffect, useCallback, useRef } from 'react' +import Image from 'next/image' + import { InferenceEngine } from '@janhq/core' -import { Badge, Input, ScrollArea, Select, useClickOutside } from '@janhq/joi' +import { + Badge, + Button, + Input, + ScrollArea, + Select, + useClickOutside, +} from '@janhq/joi' import { useAtom, useAtomValue, useSetAtom } from 'jotai' -import { ChevronDownIcon, DownloadCloudIcon, XIcon } from 'lucide-react' +import { + ChevronDownIcon, + ChevronUpIcon, + DownloadCloudIcon, + XIcon, +} from 'lucide-react' import { twMerge } from 'tailwind-merge' import ProgressCircle from '@/containers/Loader/ProgressCircle' @@ -22,6 +36,13 @@ import useUpdateModelParameters from '@/hooks/useUpdateModelParameters' import { formatDownloadPercentage, toGibibytes } from '@/utils/converter' +import { + getLogoEngine, + getTitleByEngine, + localEngines, + priorityEngine, +} from '@/utils/modelEngine' + import { extensionManager } from '@/extension' import { inActiveEngineProviderAtom } from '@/helpers/atoms/Extension.atom' @@ -29,6 +50,7 @@ import { configuredModelsAtom, getDownloadingModelAtom, selectedModelAtom, + showEngineListModelAtom, } from '@/helpers/atoms/Model.atom' import { activeThreadAtom, @@ -41,14 +63,6 @@ type Props = { disabled?: boolean } -const engineHasLogo = [ - InferenceEngine.anthropic, - InferenceEngine.cohere, - InferenceEngine.martian, - InferenceEngine.mistral, - InferenceEngine.openai, -] - const ModelDropdown = ({ disabled, chatInputMode, @@ -81,6 +95,10 @@ const ModelDropdown = ({ toggle, ]) + const [showEngineListModel, setShowEngineListModel] = useAtom( + showEngineListModelAtom + ) + const filteredDownloadedModels = useMemo( () => configuredModels @@ -92,16 +110,10 @@ const ModelDropdown = ({ return e.engine } if (searchFilter === 'local') { - return ( - e.engine === InferenceEngine.nitro || - e.engine === InferenceEngine.nitro_tensorrt_llm - ) + return localEngines.includes(e.engine) } if (searchFilter === 'remote') { - return ( - e.engine !== InferenceEngine.nitro && - e.engine !== InferenceEngine.nitro_tensorrt_llm - ) + return !localEngines.includes(e.engine) } }) .sort((a, b) => a.name.localeCompare(b.name)) @@ -230,10 +242,37 @@ const ModelDropdown = ({ .filter((x) => !inActiveEngineProvider.includes(x.engine)) .map((x) => x.engine) - const groupByEngine = findByEngine.filter(function (item, index) { - if (findByEngine.indexOf(item) === index) - return item !== InferenceEngine.nitro - }) + const groupByEngine = findByEngine + .filter(function (item, index) { + if (findByEngine.indexOf(item) === index) return item + }) + .sort((a, b) => { + if (priorityEngine.includes(a) && priorityEngine.includes(b)) { + return priorityEngine.indexOf(a) - priorityEngine.indexOf(b) + } else if (priorityEngine.includes(a)) { + return -1 + } else if (priorityEngine.includes(b)) { + return 1 + } else { + return 0 // Leave the rest in their original order + } + }) + + const getEngineStatusReady: InferenceEngine[] = extensionHasSettings + ?.filter((e) => e.apiKey.length > 0) + .map((x) => x.provider as InferenceEngine) + + useEffect(() => { + setShowEngineListModel((prev) => [ + ...prev, + ...(getEngineStatusReady as InferenceEngine[]), + ]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [setShowEngineListModel, extensionHasSettings]) + + const isDownloadALocalModel = downloadedModels.some((x) => + localEngines.includes(x.engine) + ) if (strictedThread && !activeThread) { return null @@ -312,161 +351,22 @@ const ModelDropdown = ({ - {searchFilter !== 'remote' && ( -
-
-
- Cortex -
-
- {filteredDownloadedModels - .filter((x) => { - if (searchText.length === 0) { - return downloadedModels.find((c) => c.id === x.id) - } else { - return x - } - }) - .filter((x) => x.engine === InferenceEngine.nitro).length !== - 0 ? ( -
    - {filteredDownloadedModels - ? filteredDownloadedModels - .filter((x) => x.engine === InferenceEngine.nitro) - .filter((x) => { - if (searchText.length === 0) { - return downloadedModels.find((c) => c.id === x.id) - } else { - return x - } - }) - .map((model) => { - const isDownloading = downloadingModels.some( - (md) => md.id === model.id - ) - const isdDownloaded = downloadedModels.some( - (c) => c.id === model.id - ) - return ( -
  • { - if (isdDownloaded) { - onClickModelItem(model.id) - } - }} - > -
    -

    - {model.name} -

    - -
    -
    - {!isdDownloaded && ( - - {toGibibytes(model.metadata.size)} - - )} - {!isDownloading && !isdDownloaded ? ( - downloadModel(model)} - /> - ) : ( - Object.values(downloadStates) - .filter((x) => x.modelId === model.id) - .map((item) => ( - - )) - )} -
    -
  • - ) - }) - : null} -
- ) : ( -
    - {featuredModel.map((model) => { - const isDownloading = downloadingModels.some( - (md) => md.id === model.id - ) - return ( -
  • -
    -

    - {model.name} -

    - -
    -
    - - {toGibibytes(model.metadata.size)} - - {!isDownloading ? ( - downloadModel(model)} - /> - ) : ( - Object.values(downloadStates) - .filter((x) => x.modelId === model.id) - .map((item) => ( - - )) - )} -
    -
  • - ) - })} -
- )} -
- )} - {groupByEngine.map((engine, i) => { - const apiKey = - extensionHasSettings.filter((x) => x.provider === engine)[0] - ?.apiKey.length > 1 + const apiKey = !localEngines.includes(engine) + ? extensionHasSettings.filter((x) => x.provider === engine)[0] + ?.apiKey.length > 1 + : true + const engineLogo = getLogoEngine(engine as InferenceEngine) + const showModel = showEngineListModel.includes(engine) + const onClickChevron = () => { + if (showModel) { + setShowEngineListModel((prev) => + prev.filter((item) => item !== engine) + ) + } else { + setShowEngineListModel((prev) => [...prev, engine]) + } + } return (
-
- {engine} -
-
- +
+ {engineLogo && ( + logo + )} +
+ {getTitleByEngine(engine)} +
+
+
+ {!localEngines.includes(engine) && ( + + )} + {!showModel ? ( + + ) : ( + + )}
+ + {engine === InferenceEngine.nitro && + !isDownloadALocalModel && + showModel && ( + <> + {!searchText.length ? ( +
    + {featuredModel.map((model) => { + const isDownloading = downloadingModels.some( + (md) => md.id === model.id + ) + return ( +
  • +
    +

    + {model.name} +

    + +
    +
    + + {toGibibytes(model.metadata.size)} + + {!isDownloading ? ( + downloadModel(model)} + /> + ) : ( + Object.values(downloadStates) + .filter((x) => x.modelId === model.id) + .map((item) => ( + + )) + )} +
    +
  • + ) + })} +
+ ) : ( + <> + {filteredDownloadedModels + .filter( + (x) => x.engine === InferenceEngine.nitro + ) + .filter((x) => { + if (searchText.length === 0) { + return downloadedModels.find( + (c) => c.id === x.id + ) + } else { + return x + } + }) + .map((model) => { + const isDownloading = downloadingModels.some( + (md) => md.id === model.id + ) + const isdDownloaded = downloadedModels.some( + (c) => c.id === model.id + ) + return ( +
  • { + if (isdDownloaded) { + onClickModelItem(model.id) + } + }} + > +
    +

    + {model.name} +

    + +
    +
    + {!isdDownloaded && ( + + {toGibibytes(model.metadata.size)} + + )} + {!isDownloading && !isdDownloaded ? ( + downloadModel(model)} + /> + ) : ( + Object.values(downloadStates) + .filter( + (x) => x.modelId === model.id + ) + .map((item) => ( + + )) + )} +
    +
  • + ) + })} + + )} + + )} +
      {filteredDownloadedModels .filter((x) => x.engine === engine) + .filter((y) => { + if (localEngines.includes(y.engine)) { + return downloadedModels.find((c) => c.id === y.id) + } else { + return y + } + }) .map((model) => { + if (!showModel) return null return (
    • { - if ( - apiKey || - model.engine === - InferenceEngine.nitro_tensorrt_llm - ) { - onClickModelItem(model.id) - } + onClickModelItem(model.id) }} >
      - {engineHasLogo.map((x) => { - if (x === model.engine) { - return ( -
      - Model Provider -
      - ) - } - })} -

      +

      {model.name}

      diff --git a/web/containers/SetupRemoteModel/index.tsx b/web/containers/SetupRemoteModel/index.tsx index ab71240af..914f240de 100644 --- a/web/containers/SetupRemoteModel/index.tsx +++ b/web/containers/SetupRemoteModel/index.tsx @@ -4,10 +4,12 @@ import { InferenceEngine } from '@janhq/core' import { Button } from '@janhq/joi' import { useSetAtom } from 'jotai' -import { SettingsIcon } from 'lucide-react' +import { SettingsIcon, PlusIcon } from 'lucide-react' import { MainViewState } from '@/constants/screens' +import { localEngines } from '@/utils/modelEngine' + import { extensionManager } from '@/extension' import { mainViewStateAtom } from '@/helpers/atoms/App.atom' import { selectedSettingAtom } from '@/helpers/atoms/Setting.atom' @@ -72,6 +74,11 @@ const SetupRemoteModel = ({ engine }: Props) => { ) } + const apiKey = !localEngines.includes(engine) + ? extensionHasSettings.filter((x) => x.provider === engine)[0]?.apiKey + .length > 1 + : true + return ( ) } diff --git a/web/helpers/atoms/Model.atom.ts b/web/helpers/atoms/Model.atom.ts index 7ad65a15e..deb7b8622 100644 --- a/web/helpers/atoms/Model.atom.ts +++ b/web/helpers/atoms/Model.atom.ts @@ -1,6 +1,8 @@ -import { ImportingModel, Model } from '@janhq/core' +import { ImportingModel, Model, InferenceEngine } from '@janhq/core' import { atom } from 'jotai' +import { localEngines } from '@/utils/modelEngine' + export const stateModel = atom({ state: 'start', loading: false, model: '' }) export const activeAssistantModelAtom = atom(undefined) @@ -132,3 +134,5 @@ export const updateImportingModelAtom = atom( ) export const selectedModelAtom = atom(undefined) + +export const showEngineListModelAtom = atom(localEngines) diff --git a/web/public/images/ModelProvider/anthropic.svg b/web/public/images/ModelProvider/anthropic.svg index 7bb86df4a..1f3f18dcf 100644 --- a/web/public/images/ModelProvider/anthropic.svg +++ b/web/public/images/ModelProvider/anthropic.svg @@ -1,9 +1,9 @@ - - + + - - + + - + diff --git a/web/public/images/ModelProvider/cohere.svg b/web/public/images/ModelProvider/cohere.svg index 543bc2d6c..0ff4f0029 100644 --- a/web/public/images/ModelProvider/cohere.svg +++ b/web/public/images/ModelProvider/cohere.svg @@ -1,30 +1,9 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/web/public/images/ModelProvider/cortex.svg b/web/public/images/ModelProvider/cortex.svg new file mode 100644 index 000000000..c0ebd58bf --- /dev/null +++ b/web/public/images/ModelProvider/cortex.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/web/public/images/ModelProvider/dot.svg b/web/public/images/ModelProvider/dot.svg new file mode 100644 index 000000000..f667c20b1 --- /dev/null +++ b/web/public/images/ModelProvider/dot.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/public/images/ModelProvider/google.svg b/web/public/images/ModelProvider/google.svg new file mode 100644 index 000000000..1c44dd330 --- /dev/null +++ b/web/public/images/ModelProvider/google.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/web/public/images/ModelProvider/groq.svg b/web/public/images/ModelProvider/groq.svg new file mode 100644 index 000000000..9c2e0a34a --- /dev/null +++ b/web/public/images/ModelProvider/groq.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/web/public/images/ModelProvider/hugging-face.svg b/web/public/images/ModelProvider/hugging-face.svg new file mode 100644 index 000000000..9ac72080a --- /dev/null +++ b/web/public/images/ModelProvider/hugging-face.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/web/public/images/ModelProvider/martian.svg b/web/public/images/ModelProvider/martian.svg index f63ded55a..b5ceacdf8 100644 --- a/web/public/images/ModelProvider/martian.svg +++ b/web/public/images/ModelProvider/martian.svg @@ -1,11 +1,11 @@ - - - - + + + + - - + + diff --git a/web/public/images/ModelProvider/meta.svg b/web/public/images/ModelProvider/meta.svg new file mode 100644 index 000000000..91bdf9783 --- /dev/null +++ b/web/public/images/ModelProvider/meta.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/public/images/ModelProvider/mistral.svg b/web/public/images/ModelProvider/mistral.svg index 2bb14b9bc..22233c55c 100644 --- a/web/public/images/ModelProvider/mistral.svg +++ b/web/public/images/ModelProvider/mistral.svg @@ -1,32 +1,28 @@ - - - Mistral AI - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/public/images/ModelProvider/nitro.svg b/web/public/images/ModelProvider/nitro.svg new file mode 100644 index 000000000..775517a75 --- /dev/null +++ b/web/public/images/ModelProvider/nitro.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/web/public/images/ModelProvider/nvidia.svg b/web/public/images/ModelProvider/nvidia.svg new file mode 100644 index 000000000..09c2194ec --- /dev/null +++ b/web/public/images/ModelProvider/nvidia.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/web/public/images/ModelProvider/openRouter.svg b/web/public/images/ModelProvider/openRouter.svg new file mode 100644 index 000000000..62ff2b424 --- /dev/null +++ b/web/public/images/ModelProvider/openRouter.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/web/public/images/ModelProvider/openai.svg b/web/public/images/ModelProvider/openai.svg index 433ae3d45..8f0785415 100644 --- a/web/public/images/ModelProvider/openai.svg +++ b/web/public/images/ModelProvider/openai.svg @@ -1,24 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/web/public/images/ModelProvider/send.svg b/web/public/images/ModelProvider/send.svg new file mode 100644 index 000000000..28d30299f --- /dev/null +++ b/web/public/images/ModelProvider/send.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/screens/Settings/MyModels/MyModelList/index.tsx b/web/screens/Settings/MyModels/MyModelList/index.tsx index 045f454c0..ae9c344cb 100644 --- a/web/screens/Settings/MyModels/MyModelList/index.tsx +++ b/web/screens/Settings/MyModels/MyModelList/index.tsx @@ -16,6 +16,8 @@ import useDeleteModel from '@/hooks/useDeleteModel' import { toGibibytes } from '@/utils/converter' +import { localEngines } from '@/utils/modelEngine' + import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' type Props = { @@ -44,33 +46,10 @@ const MyModelList = ({ model }: Props) => { } } - const engineHasLogo = [ - InferenceEngine.anthropic, - InferenceEngine.cohere, - InferenceEngine.martian, - InferenceEngine.mistral, - InferenceEngine.openai, - ] - return (
      - {engineHasLogo.map((x) => { - if (x === model.engine) { - return ( -
      - Model Provider -
      - ) - } - })}
      {
      - {model.engine === InferenceEngine.nitro && ( + {localEngines.includes(model.engine) && (
      {toGibibytes(model.metadata.size)} diff --git a/web/screens/Settings/MyModels/index.tsx b/web/screens/Settings/MyModels/index.tsx index d90081b6c..80402a548 100644 --- a/web/screens/Settings/MyModels/index.tsx +++ b/web/screens/Settings/MyModels/index.tsx @@ -1,13 +1,20 @@ -import { useCallback, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { useDropzone } from 'react-dropzone' +import Image from 'next/image' + import { InferenceEngine } from '@janhq/core' import { Button, ScrollArea } from '@janhq/joi' -import { useAtomValue, useSetAtom } from 'jotai' -import { UploadCloudIcon, UploadIcon } from 'lucide-react' +import { useAtom, useAtomValue, useSetAtom } from 'jotai' +import { + ChevronDownIcon, + ChevronUpIcon, + UploadCloudIcon, + UploadIcon, +} from 'lucide-react' import { twMerge } from 'tailwind-merge' @@ -18,15 +25,32 @@ import SetupRemoteModel from '@/containers/SetupRemoteModel' import useDropModelBinaries from '@/hooks/useDropModelBinaries' import { setImportModelStageAtom } from '@/hooks/useImportModel' +import { + getLogoEngine, + getTitleByEngine, + localEngines, + priorityEngine, +} from '@/utils/modelEngine' + import MyModelList from './MyModelList' -import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom' +import { extensionManager } from '@/extension' +import { + downloadedModelsAtom, + showEngineListModelAtom, +} from '@/helpers/atoms/Model.atom' const MyModels = () => { const downloadedModels = useAtomValue(downloadedModelsAtom) const setImportModelStage = useSetAtom(setImportModelStageAtom) const { onDropModels } = useDropModelBinaries() const [searchText, setSearchText] = useState('') + const [showEngineListModel, setShowEngineListModel] = useAtom( + showEngineListModelAtom + ) + const [extensionHasSettings, setExtensionHasSettings] = useState< + { name?: string; setting: string; apiKey: string; provider: string }[] + >([]) const filteredDownloadedModels = useMemo( () => @@ -52,11 +76,73 @@ const MyModels = () => { setSearchText(input) }, []) + useEffect(() => { + const getAllSettings = async () => { + const extensionsMenu: { + name?: string + setting: string + apiKey: string + provider: string + }[] = [] + const extensions = extensionManager.getAll() + + for (const extension of extensions) { + if (typeof extension.getSettings === 'function') { + const settings = await extension.getSettings() + + if ( + (settings && settings.length > 0) || + (await extension.installationState()) !== 'NotRequired' + ) { + extensionsMenu.push({ + name: extension.productName, + setting: extension.name, + apiKey: + 'apiKey' in extension && typeof extension.apiKey === 'string' + ? extension.apiKey + : '', + provider: + 'provider' in extension && + typeof extension.provider === 'string' + ? extension.provider + : '', + }) + } + } + } + setExtensionHasSettings(extensionsMenu) + } + getAllSettings() + }, []) + const findByEngine = filteredDownloadedModels.map((x) => x.engine) - const groupByEngine = findByEngine.filter(function (item, index) { - if (findByEngine.indexOf(item) === index) - return item !== InferenceEngine.nitro - }) + const groupByEngine = findByEngine + .filter(function (item, index) { + if (findByEngine.indexOf(item) === index) return item + }) + .sort((a, b) => { + if (priorityEngine.includes(a) && priorityEngine.includes(b)) { + return priorityEngine.indexOf(a) - priorityEngine.indexOf(b) + } else if (priorityEngine.includes(a)) { + return -1 + } else if (priorityEngine.includes(b)) { + return 1 + } else { + return 0 // Leave the rest in their original order + } + }) + + const getEngineStatusReady: InferenceEngine[] = extensionHasSettings + ?.filter((e) => e.apiKey.length > 0) + .map((x) => x.provider as InferenceEngine) + + useEffect(() => { + setShowEngineListModel((prev) => [ + ...prev, + ...(getEngineStatusReady as InferenceEngine[]), + ]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [setShowEngineListModel, extensionHasSettings]) return (
      @@ -97,39 +183,65 @@ const MyModels = () => {
      - {filteredDownloadedModels.filter( - (x) => x.engine === InferenceEngine.nitro - ).length !== 0 && ( -
      -
      -
      Cortex
      -
      -
      - {filteredDownloadedModels - ? filteredDownloadedModels - .filter((x) => x.engine === InferenceEngine.nitro) - .map((model) => { - return - }) - : null} -
      -
      - )} - {groupByEngine.map((engine, i) => { + const engineLogo = getLogoEngine(engine as InferenceEngine) + const showModel = showEngineListModel.includes(engine) + const onClickChevron = () => { + if (showModel) { + setShowEngineListModel((prev) => + prev.filter((item) => item !== engine) + ) + } else { + setShowEngineListModel((prev) => [...prev, engine]) + } + } return (
      -
      - {engine} -
      - +
      + {engineLogo && ( + logo + )} +
      + {getTitleByEngine(engine)} +
      +
      +
      + {!localEngines.includes(engine) && ( + + )} + {!showModel ? ( + + ) : ( + + )} +
      {filteredDownloadedModels ? filteredDownloadedModels .filter((x) => x.engine === engine) .map((model) => { + if (!showModel) return null return }) : null} diff --git a/web/utils/modelEngine.ts b/web/utils/modelEngine.ts new file mode 100644 index 000000000..9e7ea0146 --- /dev/null +++ b/web/utils/modelEngine.ts @@ -0,0 +1,66 @@ +import { InferenceEngine } from '@janhq/core' + +export const getLogoEngine = (engine: InferenceEngine) => { + switch (engine) { + case 'anthropic': + return 'images/ModelProvider/anthropic.svg' + case 'nitro': + return 'images/ModelProvider/nitro.svg' + case 'cortex.llamacpp': + case 'cortex.onnx': + case 'cortex.tensorrtllm': + return 'images/ModelProvider/cortex.svg' + case 'mistral': + return 'images/ModelProvider/mistral.svg' + case 'martian': + return 'images/ModelProvider/martian.svg' + case 'openrouter': + return 'images/ModelProvider/openrouter.svg' + case 'openai': + return 'images/ModelProvider/openai.svg' + case 'groq': + return 'images/ModelProvider/groq.svg' + case 'triton_trtllm': + return 'images/ModelProvider/triton_trtllm.svg' + case 'cohere': + return 'images/ModelProvider/cohere.svg' + case 'nvidia': + return 'images/ModelProvider/nvidia.svg' + default: + return undefined + } +} + +export const localEngines = [ + InferenceEngine.nitro, + InferenceEngine.nitro_tensorrt_llm, + InferenceEngine.cortex_llamacpp, + InferenceEngine.cortex_onnx, + InferenceEngine.cortex_tensorrtllm, +] + +export const getTitleByEngine = (engine: InferenceEngine) => { + switch (engine) { + case 'nitro': + return 'Llama.cpp (Nitro)' + case 'cortex.llamacpp': + return 'Llama.cpp (Cortex)' + case 'cortex.onnx': + return 'Onnx (Cortex)' + case 'cortex.tensorrtllm': + return 'TensorRT-LLM (Cortex)' + case 'openai': + return 'OpenAI' + case 'openrouter': + return 'OpenRouter' + default: + return engine.charAt(0).toUpperCase() + engine.slice(1) + } +} + +export const priorityEngine = [ + InferenceEngine.cortex_llamacpp, + InferenceEngine.cortex_onnx, + InferenceEngine.cortex_tensorrtllm, + InferenceEngine.nitro, +] From 19510fc4dcb43fcb250e2ef63904b8e4cc1d02ad Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Fri, 16 Aug 2024 13:41:15 +0700 Subject: [PATCH 2/7] fix: modelEntity and clickable model engine --- web/containers/ModelDropdown/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/containers/ModelDropdown/index.tsx b/web/containers/ModelDropdown/index.tsx index 981ce3276..f124bc2e4 100644 --- a/web/containers/ModelDropdown/index.tsx +++ b/web/containers/ModelDropdown/index.tsx @@ -375,7 +375,7 @@ const ModelDropdown = ({
      {engineLogo && ( From 80b23d10b130bc5b1d8d0ba096075f17dd69cb24 Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Fri, 16 Aug 2024 15:08:21 +0700 Subject: [PATCH 3/7] chore: fix engine entity --- core/src/types/model/modelEntity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/types/model/modelEntity.ts b/core/src/types/model/modelEntity.ts index f3520a4e0..1e3ecbb9c 100644 --- a/core/src/types/model/modelEntity.ts +++ b/core/src/types/model/modelEntity.ts @@ -28,7 +28,7 @@ export enum InferenceEngine { nvdia = 'nvidia', cortex_llamacpp = 'cortex.llamacpp', cortex_onnx = 'cortex.onnx', - cortex_tensorrtllm = 'cortex.tensorrtllm', + cortex_tensorrtllm = 'cortex.tensorrt-llm', } export type ModelArtifact = { From 098492d1c58ce52242bfa27c03d9ed0c580d034c Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Fri, 16 Aug 2024 15:22:36 +0700 Subject: [PATCH 4/7] chore: update utils model entity --- core/src/types/model/modelEntity.ts | 2 +- web/utils/modelEngine.ts | 38 ++++++++++++++--------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/core/src/types/model/modelEntity.ts b/core/src/types/model/modelEntity.ts index 1e3ecbb9c..ef6d59316 100644 --- a/core/src/types/model/modelEntity.ts +++ b/core/src/types/model/modelEntity.ts @@ -25,7 +25,7 @@ export enum InferenceEngine { triton_trtllm = 'triton_trtllm', nitro_tensorrt_llm = 'nitro-tensorrt-llm', cohere = 'cohere', - nvdia = 'nvidia', + nvidia = 'nvidia', cortex_llamacpp = 'cortex.llamacpp', cortex_onnx = 'cortex.onnx', cortex_tensorrtllm = 'cortex.tensorrt-llm', diff --git a/web/utils/modelEngine.ts b/web/utils/modelEngine.ts index 9e7ea0146..610e3c128 100644 --- a/web/utils/modelEngine.ts +++ b/web/utils/modelEngine.ts @@ -2,29 +2,29 @@ import { InferenceEngine } from '@janhq/core' export const getLogoEngine = (engine: InferenceEngine) => { switch (engine) { - case 'anthropic': + case InferenceEngine.anthropic: return 'images/ModelProvider/anthropic.svg' - case 'nitro': + case InferenceEngine.nitro: return 'images/ModelProvider/nitro.svg' - case 'cortex.llamacpp': - case 'cortex.onnx': - case 'cortex.tensorrtllm': + case InferenceEngine.cortex_llamacpp': + case InferenceEngine.cortex_onnx: + case InferenceEngine.cortex_tensorrtllm: return 'images/ModelProvider/cortex.svg' - case 'mistral': + case InferenceEngine.mistral: return 'images/ModelProvider/mistral.svg' - case 'martian': + case InferenceEngine.martian: return 'images/ModelProvider/martian.svg' - case 'openrouter': + case InferenceEngine.openrouter: return 'images/ModelProvider/openrouter.svg' - case 'openai': + case InferenceEngine.openai: return 'images/ModelProvider/openai.svg' - case 'groq': + case InferenceEngine.groq: return 'images/ModelProvider/groq.svg' - case 'triton_trtllm': + case InferenceEngine.triton_trtllm: return 'images/ModelProvider/triton_trtllm.svg' - case 'cohere': + case InferenceEngine.cohere: return 'images/ModelProvider/cohere.svg' - case 'nvidia': + case InferenceEngine.nvidia: return 'images/ModelProvider/nvidia.svg' default: return undefined @@ -41,17 +41,17 @@ export const localEngines = [ export const getTitleByEngine = (engine: InferenceEngine) => { switch (engine) { - case 'nitro': + case InferenceEngine.nitro: return 'Llama.cpp (Nitro)' - case 'cortex.llamacpp': + case InferenceEngine.cortex_llamacpp: return 'Llama.cpp (Cortex)' - case 'cortex.onnx': + case InferenceEngine.cortex_onnx: return 'Onnx (Cortex)' - case 'cortex.tensorrtllm': + case InferenceEngine.cortex_tensorrtllm: return 'TensorRT-LLM (Cortex)' - case 'openai': + case InferenceEngine.openai: return 'OpenAI' - case 'openrouter': + case InferenceEngine.openrouter: return 'OpenRouter' default: return engine.charAt(0).toUpperCase() + engine.slice(1) From 0fe98a837337589d98faa8520be810f73158ecc0 Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Fri, 16 Aug 2024 15:23:03 +0700 Subject: [PATCH 5/7] chore: update utils --- web/utils/modelEngine.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/utils/modelEngine.ts b/web/utils/modelEngine.ts index 610e3c128..0e87be517 100644 --- a/web/utils/modelEngine.ts +++ b/web/utils/modelEngine.ts @@ -6,7 +6,7 @@ export const getLogoEngine = (engine: InferenceEngine) => { return 'images/ModelProvider/anthropic.svg' case InferenceEngine.nitro: return 'images/ModelProvider/nitro.svg' - case InferenceEngine.cortex_llamacpp': + case InferenceEngine.cortex_llamacpp: case InferenceEngine.cortex_onnx: case InferenceEngine.cortex_tensorrtllm: return 'images/ModelProvider/cortex.svg' From a57d6d849584b9b31e94771f9e8aa174a1f2111c Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Fri, 16 Aug 2024 15:44:38 +0700 Subject: [PATCH 6/7] chore: fix openrouter logo --- web/utils/modelEngine.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/utils/modelEngine.ts b/web/utils/modelEngine.ts index 0e87be517..a12e9bb0e 100644 --- a/web/utils/modelEngine.ts +++ b/web/utils/modelEngine.ts @@ -15,7 +15,7 @@ export const getLogoEngine = (engine: InferenceEngine) => { case InferenceEngine.martian: return 'images/ModelProvider/martian.svg' case InferenceEngine.openrouter: - return 'images/ModelProvider/openrouter.svg' + return 'images/ModelProvider/openRouter.svg' case InferenceEngine.openai: return 'images/ModelProvider/openai.svg' case InferenceEngine.groq: From 6c13b4627b0f99d4b834cb90fd2ceaa85d9ca205 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 16 Aug 2024 16:54:56 +0700 Subject: [PATCH 7/7] chore: ignore empty state of janDataFolder --- web/hooks/useLoadTheme.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/web/hooks/useLoadTheme.ts b/web/hooks/useLoadTheme.ts index 8afba27c4..314aaf8be 100644 --- a/web/hooks/useLoadTheme.ts +++ b/web/hooks/useLoadTheme.ts @@ -42,6 +42,7 @@ export const useLoadTheme = async () => { ) const getThemes = useCallback(async () => { + if (!janDataFolderPath.length) return const folderPath = await joinPath([janDataFolderPath, 'themes']) const installedThemes = await fs.readdirSync(folderPath)