update
Signed-off-by: James <james@jan.ai>
This commit is contained in:
parent
d982dce090
commit
773bbaf4cc
@ -116,22 +116,10 @@ function storeModel(params: any) {
|
||||
model.nsfw,
|
||||
modelTags,
|
||||
model.greeting,
|
||||
model.type,
|
||||
function (err: any) {
|
||||
if (err) {
|
||||
// Handle the insertion error here
|
||||
console.error(err.message);
|
||||
res(undefined);
|
||||
return;
|
||||
}
|
||||
// @ts-ignoreF
|
||||
const id = this.lastID;
|
||||
res(id);
|
||||
return;
|
||||
}
|
||||
model.type
|
||||
);
|
||||
stmt.finalize();
|
||||
|
||||
// insert modelVersion to MODEL_VERSION_TABLE_INSERTION
|
||||
const stmt2 = db.prepare(MODEL_VERSION_TABLE_INSERTION);
|
||||
stmt2.run(
|
||||
modelVersion.id,
|
||||
@ -143,25 +131,14 @@ function storeModel(params: any) {
|
||||
modelVersion.usecase,
|
||||
modelVersion.downloadLink,
|
||||
model.id,
|
||||
modelVersion.startDownloadAt,
|
||||
function (err: any) {
|
||||
if (err) {
|
||||
// Handle the insertion error here
|
||||
console.error(err.message);
|
||||
res(undefined);
|
||||
return;
|
||||
}
|
||||
// @ts-ignoreF
|
||||
const id = this.lastID;
|
||||
res(id);
|
||||
return;
|
||||
}
|
||||
modelVersion.startDownloadAt
|
||||
);
|
||||
stmt.finalize();
|
||||
|
||||
stmt2.finalize();
|
||||
});
|
||||
|
||||
db.close();
|
||||
res(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
@ -171,7 +148,7 @@ function storeModel(params: any) {
|
||||
* @param model Product
|
||||
*/
|
||||
function updateFinishedDownloadAt(modelVersionId: string) {
|
||||
return new Promise((res) => {
|
||||
return new Promise((res, rej) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
const time = Date.now();
|
||||
console.debug(
|
||||
@ -181,7 +158,7 @@ function updateFinishedDownloadAt(modelVersionId: string) {
|
||||
db.run(stmt, [time, modelVersionId], (err: any) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
res(undefined);
|
||||
rej(err);
|
||||
} else {
|
||||
console.log("Updated 1 row");
|
||||
res("Updated");
|
||||
@ -299,7 +276,7 @@ function deleteDownloadModel(modelId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchModelVersion(db: any, versionId: string) {
|
||||
function fetchModelVersion(db: any, versionId: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.get(
|
||||
"SELECT * FROM model_versions WHERE id = ?",
|
||||
@ -308,32 +285,7 @@ async function fetchModelVersion(db: any, versionId: string) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
if (row) {
|
||||
const product = {
|
||||
id: row.id,
|
||||
slug: row.slug,
|
||||
name: row.name,
|
||||
description: row.description,
|
||||
avatarUrl: row.avatar_url,
|
||||
longDescription: row.long_description,
|
||||
technicalDescription: row.technical_description,
|
||||
author: row.author,
|
||||
version: row.version,
|
||||
modelUrl: row.model_url,
|
||||
nsfw: row.nsfw,
|
||||
greeting: row.greeting,
|
||||
type: row.type,
|
||||
inputs: row.inputs,
|
||||
outputs: row.outputs,
|
||||
createdAt: new Date(row.created_at),
|
||||
updatedAt: new Date(row.updated_at),
|
||||
fileName: row.file_name,
|
||||
downloadUrl: row.download_url,
|
||||
};
|
||||
resolve(product);
|
||||
} else {
|
||||
resolve(undefined);
|
||||
}
|
||||
resolve(row);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "data-plugin",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "Jan Database Plugin efficiently stores conversation and model data using SQLite, providing accessible data management",
|
||||
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/circle-stack.svg",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const MODULE_PATH = "model-management-plugin/dist/module.js";
|
||||
|
||||
const getDownloadedModels = async () =>
|
||||
const getDownloadedModels = () =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
@ -9,7 +9,7 @@ const getDownloadedModels = async () =>
|
||||
}
|
||||
});
|
||||
|
||||
const getAvailableModels = async () =>
|
||||
const getAvailableModels = () =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
@ -18,7 +18,7 @@ const getAvailableModels = async () =>
|
||||
}
|
||||
});
|
||||
|
||||
const downloadModel = async (product) =>
|
||||
const downloadModel = (product) =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
@ -29,7 +29,7 @@ const downloadModel = async (product) =>
|
||||
}
|
||||
});
|
||||
|
||||
const deleteModel = async (path) =>
|
||||
const deleteModel = (path) =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
console.debug(`Delete model model management plugin: ${path}`);
|
||||
@ -38,7 +38,7 @@ const deleteModel = async (path) =>
|
||||
}
|
||||
});
|
||||
|
||||
const searchModels = async (params) =>
|
||||
const searchModels = (params) =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
@ -47,7 +47,7 @@ const searchModels = async (params) =>
|
||||
}
|
||||
});
|
||||
|
||||
const getConfiguredModels = async () =>
|
||||
const getConfiguredModels = () =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
|
||||
@ -6,10 +6,10 @@ import ExploreModelFilter from "../ExploreModelFilter";
|
||||
const ExploreModelContainer: React.FC = () => (
|
||||
<div className="flex flex-col flex-1 px-16 pt-14 overflow-hidden">
|
||||
<HeaderTitle title="Explore Models" />
|
||||
<SearchBar
|
||||
{/* <SearchBar
|
||||
type={SearchType.Model}
|
||||
placeholder="Owner name like TheBloke, bhlim etc.."
|
||||
/>
|
||||
/> */}
|
||||
<div className="flex flex-1 gap-x-10 mt-9 overflow-hidden">
|
||||
<ExploreModelFilter />
|
||||
<ExploreModelList />
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import React from "react";
|
||||
import SearchBar from "../SearchBar";
|
||||
import SimpleCheckbox from "../SimpleCheckbox";
|
||||
import SimpleTag, { TagType } from "../SimpleTag";
|
||||
import SimpleTag from "../SimpleTag";
|
||||
import { TagType } from "../SimpleTag/TagType";
|
||||
|
||||
const tags = [
|
||||
"Roleplay",
|
||||
|
||||
@ -4,10 +4,11 @@
|
||||
|
||||
import ExploreModelItemHeader from "../ExploreModelItemHeader";
|
||||
import ModelVersionList from "../ModelVersionList";
|
||||
import { Fragment, forwardRef, useState } from "react";
|
||||
import SimpleTag, { TagType } from "../SimpleTag";
|
||||
import { Fragment, forwardRef, useEffect, useState } from "react";
|
||||
import SimpleTag from "../SimpleTag";
|
||||
import { displayDate } from "@/_utils/datetime";
|
||||
import { Product } from "@/_models/Product";
|
||||
import useGetMostSuitableModelVersion from "@/_hooks/useGetMostSuitableModelVersion";
|
||||
|
||||
type Props = {
|
||||
model: Product;
|
||||
@ -16,15 +17,26 @@ type Props = {
|
||||
const ExploreModelItem = forwardRef<HTMLDivElement, Props>(({ model }, ref) => {
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
const { availableVersions } = model;
|
||||
const { suitableModel, getMostSuitableModelVersion } =
|
||||
useGetMostSuitableModelVersion();
|
||||
|
||||
useEffect(() => {
|
||||
getMostSuitableModelVersion(availableVersions);
|
||||
}, [availableVersions]);
|
||||
|
||||
if (!suitableModel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="flex flex-col border border-gray-200 rounded-md mb-4"
|
||||
>
|
||||
<ExploreModelItemHeader
|
||||
name={model.name}
|
||||
status={TagType.Recommended}
|
||||
versions={model.availableVersions}
|
||||
suitableModel={suitableModel}
|
||||
exploreModel={model}
|
||||
/>
|
||||
<div className="flex flex-col px-[26px] py-[22px]">
|
||||
<div className="flex justify-between">
|
||||
@ -42,11 +54,11 @@ const ExploreModelItem = forwardRef<HTMLDivElement, Props>(({ model }, ref) => {
|
||||
Hardware Compatibility
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<SimpleTag
|
||||
{/* <SimpleTag
|
||||
clickable={false}
|
||||
title={TagType.Compatible}
|
||||
type={TagType.Compatible}
|
||||
/>
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -63,11 +75,11 @@ const ExploreModelItem = forwardRef<HTMLDivElement, Props>(({ model }, ref) => {
|
||||
<div className="text-sm font-medium text-gray-500">
|
||||
Expected Performance
|
||||
</div>
|
||||
<SimpleTag
|
||||
{/* <SimpleTag
|
||||
title={TagType.Medium}
|
||||
type={TagType.Medium}
|
||||
clickable={false}
|
||||
/>
|
||||
/> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -77,8 +89,14 @@ const ExploreModelItem = forwardRef<HTMLDivElement, Props>(({ model }, ref) => {
|
||||
{model.longDescription}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col mt-5">
|
||||
<span className="text-sm font-medium text-gray-500">Tags</span>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{model.tags.map((tag) => (
|
||||
// @ts-ignore
|
||||
<SimpleTag key={tag} title={tag} type={tag} clickable={false} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{model.availableVersions?.length > 0 && (
|
||||
@ -87,6 +105,7 @@ const ExploreModelItem = forwardRef<HTMLDivElement, Props>(({ model }, ref) => {
|
||||
<ModelVersionList
|
||||
model={model}
|
||||
versions={model.availableVersions}
|
||||
recommendedVersion={suitableModel?.id ?? ""}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
|
||||
@ -1,34 +1,74 @@
|
||||
import SimpleTag, { TagType } from "../SimpleTag";
|
||||
import SimpleTag from "../SimpleTag";
|
||||
import PrimaryButton from "../PrimaryButton";
|
||||
import { formatDownloadPercentage, toGigabytes } from "@/_utils/converter";
|
||||
import { DownloadState } from "@/_models/DownloadState";
|
||||
import SecondaryButton from "../SecondaryButton";
|
||||
import { Product } from "@/_models/Product";
|
||||
import { useCallback, useEffect, useMemo } from "react";
|
||||
import { ModelVersion } from "@/_models/ModelVersion";
|
||||
import useGetPerformanceTag from "@/_hooks/useGetPerformanceTag";
|
||||
import useDownloadModel from "@/_hooks/useDownloadModel";
|
||||
import { useGetDownloadedModels } from "@/_hooks/useGetDownloadedModels";
|
||||
import { modelDownloadStateAtom } from "@/_helpers/atoms/DownloadState.atom";
|
||||
import { atom, useAtomValue, useSetAtom } from "jotai";
|
||||
import {
|
||||
MainViewState,
|
||||
setMainViewStateAtom,
|
||||
} from "@/_helpers/atoms/MainView.atom";
|
||||
|
||||
type Props = {
|
||||
name: string;
|
||||
status: TagType;
|
||||
versions: ModelVersion[];
|
||||
size?: number;
|
||||
downloadState?: DownloadState;
|
||||
onDownloadClick?: () => void;
|
||||
suitableModel: ModelVersion;
|
||||
exploreModel: Product;
|
||||
};
|
||||
|
||||
const ExploreModelItemHeader: React.FC<Props> = ({
|
||||
name,
|
||||
status,
|
||||
size,
|
||||
versions,
|
||||
downloadState,
|
||||
onDownloadClick,
|
||||
suitableModel,
|
||||
exploreModel,
|
||||
}) => {
|
||||
const { downloadModel } = useDownloadModel();
|
||||
const { downloadedModels } = useGetDownloadedModels();
|
||||
const { performanceTag, title, getPerformanceForModel } =
|
||||
useGetPerformanceTag();
|
||||
const downloadAtom = useMemo(
|
||||
() => atom((get) => get(modelDownloadStateAtom)[suitableModel.id]),
|
||||
[suitableModel.id]
|
||||
);
|
||||
const downloadState = useAtomValue(downloadAtom);
|
||||
const setMainViewState = useSetAtom(setMainViewStateAtom);
|
||||
|
||||
useEffect(() => {
|
||||
getPerformanceForModel(suitableModel);
|
||||
}, [suitableModel]);
|
||||
|
||||
const onDownloadClick = useCallback(() => {
|
||||
downloadModel(exploreModel, suitableModel);
|
||||
}, [exploreModel, suitableModel]);
|
||||
|
||||
const isDownloaded =
|
||||
downloadedModels.find((model) => model.id === suitableModel.id) != null;
|
||||
|
||||
let downloadButton = (
|
||||
<PrimaryButton
|
||||
title={size ? `Download (${toGigabytes(size)})` : "Download"}
|
||||
onClick={() => onDownloadClick?.()}
|
||||
title={
|
||||
suitableModel.size
|
||||
? `Download (${toGigabytes(suitableModel.size)})`
|
||||
: "Download"
|
||||
}
|
||||
onClick={() => onDownloadClick()}
|
||||
/>
|
||||
);
|
||||
|
||||
if (isDownloaded) {
|
||||
downloadButton = (
|
||||
<PrimaryButton
|
||||
title="View Downloaded Model"
|
||||
onClick={() => {
|
||||
setMainViewState(MainViewState.MyModel);
|
||||
}}
|
||||
className="bg-green-500 hover:bg-green-400"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (downloadState != null) {
|
||||
// downloading
|
||||
downloadButton = (
|
||||
@ -39,15 +79,15 @@ const ExploreModelItemHeader: React.FC<Props> = ({
|
||||
)})`}
|
||||
/>
|
||||
);
|
||||
} else if (versions.length === 0) {
|
||||
downloadButton = <SecondaryButton disabled title="No files available" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between p-4 border-b border-gray-200">
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{name}</span>
|
||||
<SimpleTag title={status} type={status} clickable={false} />
|
||||
<span>{exploreModel.name}</span>
|
||||
{performanceTag && (
|
||||
<SimpleTag title={title} type={performanceTag} clickable={false} />
|
||||
)}
|
||||
</div>
|
||||
{downloadButton}
|
||||
</div>
|
||||
|
||||
@ -6,14 +6,26 @@ import useDownloadModel from "@/_hooks/useDownloadModel";
|
||||
import { modelDownloadStateAtom } from "@/_helpers/atoms/DownloadState.atom";
|
||||
import { atom, useAtomValue } from "jotai";
|
||||
import { ModelVersion } from "@/_models/ModelVersion";
|
||||
import { useGetDownloadedModels } from "@/_hooks/useGetDownloadedModels";
|
||||
import SimpleTag from "../SimpleTag";
|
||||
import { ModelPerformance } from "../SimpleTag/TagType";
|
||||
|
||||
type Props = {
|
||||
model: Product;
|
||||
modelVersion: ModelVersion;
|
||||
isRecommended: boolean;
|
||||
};
|
||||
|
||||
const ModelVersionItem: React.FC<Props> = ({ model, modelVersion }) => {
|
||||
const ModelVersionItem: React.FC<Props> = ({
|
||||
model,
|
||||
modelVersion,
|
||||
isRecommended,
|
||||
}) => {
|
||||
const { downloadModel } = useDownloadModel();
|
||||
const { downloadedModels } = useGetDownloadedModels();
|
||||
const isDownloaded =
|
||||
downloadedModels.find((model) => model.id === modelVersion.id) != null;
|
||||
|
||||
const downloadAtom = useMemo(
|
||||
() => atom((get) => get(modelDownloadStateAtom)[modelVersion.id ?? ""]),
|
||||
[modelVersion.id ?? ""]
|
||||
@ -37,6 +49,8 @@ const ModelVersionItem: React.FC<Props> = ({ model, modelVersion }) => {
|
||||
downloadButton = (
|
||||
<div>{formatDownloadPercentage(downloadState.percent)}</div>
|
||||
);
|
||||
} else if (isDownloaded) {
|
||||
downloadButton = <div>Downloaded</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -46,6 +60,13 @@ const ModelVersionItem: React.FC<Props> = ({ model, modelVersion }) => {
|
||||
<span className="font-sm text-gray-900">{modelVersion.name}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
{isRecommended && (
|
||||
<SimpleTag
|
||||
title={"Recommended"}
|
||||
type={ModelPerformance.PerformancePositive}
|
||||
clickable={false}
|
||||
/>
|
||||
)}
|
||||
<div className="px-2.5 py-0.5 bg-gray-200 text-xs font-medium rounded">
|
||||
{toGigabytes(modelVersion.size)}
|
||||
</div>
|
||||
|
||||
@ -6,17 +6,31 @@ import { ModelVersion } from "@/_models/ModelVersion";
|
||||
type Props = {
|
||||
model: Product;
|
||||
versions: ModelVersion[];
|
||||
recommendedVersion: string;
|
||||
};
|
||||
|
||||
const ModelVersionList: React.FC<Props> = ({ model, versions }) => (
|
||||
<div className="px-4 py-5 border-t border-gray-200">
|
||||
<div className="text-sm font-medium text-gray-500">Available Versions</div>
|
||||
<div className="border border-gray-200 rounded-lg overflow-hidden">
|
||||
{versions.map((item) => (
|
||||
<ModelVersionItem key={item.id} model={model} modelVersion={item} />
|
||||
))}
|
||||
const ModelVersionList: React.FC<Props> = ({
|
||||
model,
|
||||
versions,
|
||||
recommendedVersion,
|
||||
}) => {
|
||||
return (
|
||||
<div className="px-4 py-5 border-t border-gray-200">
|
||||
<div className="text-sm font-medium text-gray-500">
|
||||
Available Versions
|
||||
</div>
|
||||
<div className="border border-gray-200 rounded-lg overflow-hidden">
|
||||
{versions.map((item) => (
|
||||
<ModelVersionItem
|
||||
key={item.id}
|
||||
model={model}
|
||||
modelVersion={item}
|
||||
isRecommended={item.id === recommendedVersion}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default ModelVersionList;
|
||||
|
||||
16
web/app/_components/SimpleTag/TagStyleMapper.ts
Normal file
16
web/app/_components/SimpleTag/TagStyleMapper.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { TagType } from "./TagType";
|
||||
|
||||
export const tagStyleMapper: Record<TagType, string> = {
|
||||
GGUF: "bg-yellow-100 text-yellow-800",
|
||||
PerformancePositive:
|
||||
"text-green-700 ring-1 ring-inset ring-green-600/20 bg-green-50",
|
||||
PerformanceNeutral:
|
||||
"bg-yellow-50 text-yellow-800 ring-1 ring-inset ring-yellow-600/20",
|
||||
PerformanceNegative:
|
||||
"bg-red-50 ext-red-700 ring-1 ring-inset ring-red-600/10",
|
||||
HardwareCompatible: "bg-red-50 ext-red-700 ring-1 ring-inset ring-red-600/10",
|
||||
HardwareIncompatible:
|
||||
"bg-red-50 ext-red-700 ring-1 ring-inset ring-red-600/10",
|
||||
FreeStyle: "bg-gray-100 text-gray-800",
|
||||
ExpectPerformanceMedium: "bg-yellow-100 text-yellow-800",
|
||||
};
|
||||
32
web/app/_components/SimpleTag/TagType.ts
Normal file
32
web/app/_components/SimpleTag/TagType.ts
Normal file
@ -0,0 +1,32 @@
|
||||
export enum ModelPerformance {
|
||||
PerformancePositive = "PerformancePositive",
|
||||
|
||||
PerformanceNeutral = "PerformanceNeutral",
|
||||
|
||||
PerformanceNegative = "PerformanceNegative",
|
||||
}
|
||||
|
||||
export enum HardwareCompatibility {
|
||||
HardwareCompatible = "HardwareCompatible",
|
||||
|
||||
HardwareIncompatible = "HardwareIncompatible",
|
||||
}
|
||||
|
||||
export enum ExpectedPerformance {
|
||||
ExpectPerformanceMedium = "ExpectPerformanceMedium",
|
||||
}
|
||||
|
||||
export enum ModelFormat {
|
||||
GGUF = "GGUF",
|
||||
}
|
||||
|
||||
export enum FreestyleTag {
|
||||
FreeStyle = "FreeStyle",
|
||||
}
|
||||
|
||||
export type TagType =
|
||||
| ModelPerformance
|
||||
| HardwareCompatibility
|
||||
| ExpectedPerformance
|
||||
| ModelFormat
|
||||
| FreestyleTag;
|
||||
@ -1,57 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
export enum TagType {
|
||||
Roleplay = "Roleplay",
|
||||
Llama = "Llama",
|
||||
Story = "Story",
|
||||
Casual = "Casual",
|
||||
Professional = "Professional",
|
||||
CodeLlama = "CodeLlama",
|
||||
Coding = "Coding",
|
||||
|
||||
// Positive
|
||||
Recommended = "Recommended",
|
||||
Compatible = "Compatible",
|
||||
|
||||
// Neutral
|
||||
SlowOnDevice = "This model will be slow on your device",
|
||||
|
||||
// Negative
|
||||
InsufficientRam = "Insufficient RAM",
|
||||
Incompatible = "Incompatible with your device",
|
||||
TooLarge = "This model is too large for your device",
|
||||
|
||||
// Performance
|
||||
Medium = "Medium",
|
||||
BalancedQuality = "Balanced Quality",
|
||||
}
|
||||
|
||||
const tagStyleMapper: Record<TagType, string> = {
|
||||
[TagType.Roleplay]: "bg-red-100 text-red-800",
|
||||
[TagType.Llama]: "bg-green-100 text-green-800",
|
||||
[TagType.Story]: "bg-blue-100 text-blue-800",
|
||||
[TagType.Casual]: "bg-yellow-100 text-yellow-800",
|
||||
[TagType.Professional]: "text-indigo-800 bg-indigo-100",
|
||||
[TagType.CodeLlama]: "bg-pink-100 text-pink-800",
|
||||
[TagType.Coding]: "text-purple-800 bg-purple-100",
|
||||
|
||||
[TagType.Recommended]:
|
||||
"text-green-700 ring-1 ring-inset ring-green-600/20 bg-green-50",
|
||||
[TagType.Compatible]:
|
||||
"bg-red-50 ext-red-700 ring-1 ring-inset ring-red-600/10",
|
||||
|
||||
[TagType.SlowOnDevice]:
|
||||
"bg-yellow-50 text-yellow-800 ring-1 ring-inset ring-yellow-600/20",
|
||||
|
||||
[TagType.Incompatible]:
|
||||
"bg-red-50 ext-red-700 ring-1 ring-inset ring-red-600/10",
|
||||
[TagType.InsufficientRam]:
|
||||
"bg-red-50 ext-red-700 ring-1 ring-inset ring-red-600/10",
|
||||
[TagType.TooLarge]: "bg-red-50 ext-red-700 ring-1 ring-inset ring-red-600/10",
|
||||
|
||||
[TagType.Medium]: "bg-yellow-100 text-yellow-800",
|
||||
[TagType.BalancedQuality]: "bg-yellow-100 text-yellow-800",
|
||||
};
|
||||
import { TagType } from "./TagType";
|
||||
import { tagStyleMapper } from "./TagStyleMapper";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { searchModels } from "./useGetDownloadedModels";
|
||||
import { SearchModelParamHf } from "@/_models/hf/SearchModelParam.hf";
|
||||
import { Product } from "@/_models/Product";
|
||||
import { useSetAtom } from "jotai";
|
||||
@ -22,14 +21,14 @@ export default function useGetHuggingFaceModel() {
|
||||
search: { owner },
|
||||
limit: 5,
|
||||
};
|
||||
const result = await searchModels(searchParams);
|
||||
console.debug("result", JSON.stringify(result));
|
||||
if (owner !== currentOwner) {
|
||||
setModelList(result.data);
|
||||
setCurrentOwner(owner);
|
||||
} else {
|
||||
setModelList([...modelList, ...result.data]);
|
||||
}
|
||||
// const result = await searchModels(searchParams);
|
||||
// console.debug("result", JSON.stringify(result));
|
||||
// if (owner !== currentOwner) {
|
||||
// setModelList(result.data);
|
||||
// setCurrentOwner(owner);
|
||||
// } else {
|
||||
// setModelList([...modelList, ...result.data]);
|
||||
// }
|
||||
setLoadMoreInProgress(false);
|
||||
};
|
||||
|
||||
|
||||
29
web/app/_hooks/useGetMostSuitableModelVersion.ts
Normal file
29
web/app/_hooks/useGetMostSuitableModelVersion.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { SystemMonitoringService } from "../../shared/coreService";
|
||||
import { ModelVersion } from "@/_models/ModelVersion";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function useGetMostSuitableModelVersion() {
|
||||
const [suitableModel, setSuitableModel] = useState<ModelVersion | undefined>();
|
||||
|
||||
const getMostSuitableModelVersion = async (modelVersions: ModelVersion[]) => {
|
||||
const resourceInfo = await executeSerial(
|
||||
SystemMonitoringService.GET_RESOURCES_INFORMATION
|
||||
);
|
||||
const totalRam = resourceInfo.mem.total;
|
||||
|
||||
// find the model version with the highest required RAM that is still below the user's RAM by 80%
|
||||
const modelVersion = modelVersions.reduce((prev, current) => {
|
||||
if (current.maxRamRequired > prev.maxRamRequired) {
|
||||
if (current.maxRamRequired < totalRam * 0.8) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
|
||||
setSuitableModel(modelVersion);
|
||||
};
|
||||
|
||||
return { suitableModel, getMostSuitableModelVersion };
|
||||
}
|
||||
53
web/app/_hooks/useGetPerformanceTag.ts
Normal file
53
web/app/_hooks/useGetPerformanceTag.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { executeSerial } from "../../../electron/core/plugin-manager/execution/extension-manager";
|
||||
import { SystemMonitoringService } from "../../shared/coreService";
|
||||
import { useState } from "react";
|
||||
import { ModelVersion } from "@/_models/ModelVersion";
|
||||
import { ModelPerformance, TagType } from "@/_components/SimpleTag/TagType";
|
||||
|
||||
// Recommendation:
|
||||
// `Recommended (green)`: "Max RAM required" is 80% of users max RAM.
|
||||
// `Slow on your device (yellow)`: Max RAM required is 80-100% of users max RAM
|
||||
// `Not enough RAM (red)`: User RAM is below "Max RAM required"
|
||||
|
||||
export default function useGetPerformanceTag() {
|
||||
const [performanceTag, setPerformanceTag] = useState<TagType | undefined>();
|
||||
|
||||
const getPerformanceForModel = async (modelVersion: ModelVersion) => {
|
||||
const resourceInfo = await executeSerial(
|
||||
SystemMonitoringService.GET_RESOURCES_INFORMATION
|
||||
);
|
||||
const totalRam = resourceInfo.mem.total;
|
||||
const requiredRam = modelVersion.maxRamRequired;
|
||||
setPerformanceTag(calculateRamPerformance(requiredRam, totalRam));
|
||||
};
|
||||
|
||||
let title = "";
|
||||
switch (performanceTag) {
|
||||
case ModelPerformance.PerformancePositive:
|
||||
title = "Recommended";
|
||||
break;
|
||||
case ModelPerformance.PerformanceNeutral:
|
||||
title = "Slow on your device";
|
||||
break;
|
||||
case ModelPerformance.PerformanceNegative:
|
||||
title = "Not enough RAM";
|
||||
break;
|
||||
}
|
||||
|
||||
return { performanceTag, title, getPerformanceForModel };
|
||||
}
|
||||
|
||||
const calculateRamPerformance = (
|
||||
requiredRamAmt: number,
|
||||
totalRamAmt: number
|
||||
) => {
|
||||
const percentage = requiredRamAmt / totalRamAmt;
|
||||
|
||||
if (percentage < 0.8) {
|
||||
return ModelPerformance.PerformancePositive;
|
||||
} else if (percentage >= 0.8 && percentage < 1) {
|
||||
return ModelPerformance.PerformanceNeutral;
|
||||
} else {
|
||||
return ModelPerformance.PerformanceNegative;
|
||||
}
|
||||
};
|
||||
@ -57,9 +57,9 @@ export type AssistantModel = {
|
||||
|
||||
updatedAt?: number;
|
||||
|
||||
status: string; // TODO: add this in the database // Downloaded, Active
|
||||
status: string;
|
||||
|
||||
releaseDate: number; // TODO: add this in the database
|
||||
releaseDate: number;
|
||||
|
||||
tags: string[];
|
||||
};
|
||||
|
||||
@ -24,8 +24,8 @@ export interface Product {
|
||||
outputs?: ProductOutput;
|
||||
createdAt: number;
|
||||
updatedAt?: number;
|
||||
status: string; // TODO: add this in the database // Downloaded, Active
|
||||
releaseDate: number; // TODO: add this in the database
|
||||
status: string;
|
||||
releaseDate: number;
|
||||
tags: string[];
|
||||
availableVersions: ModelVersion[];
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user