chore: resolve fetch models api limit rate (#383)
* chore: resolve fetch models api limit rate * chore: delete module cache * chore: update latest npm module * chore: typo
This commit is contained in:
parent
94b8d2d57c
commit
b5d520fe10
@ -5,7 +5,7 @@
|
|||||||
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/circle-stack.svg",
|
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/circle-stack.svg",
|
||||||
"main": "dist/esm/index.js",
|
"main": "dist/esm/index.js",
|
||||||
"module": "dist/cjs/module.js",
|
"module": "dist/cjs/module.js",
|
||||||
"author": "Jan",
|
"author": "Jan <service@jan.ai>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"activationPoints": [
|
"activationPoints": [
|
||||||
"init"
|
"init"
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/command-line.svg",
|
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/command-line.svg",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/module.js",
|
"module": "dist/module.js",
|
||||||
"author": "Jan",
|
"author": "Jan <service@jan.ai>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"activationPoints": [
|
"activationPoints": [
|
||||||
"init"
|
"init"
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
declare const PLUGIN_NAME: string;
|
declare const PLUGIN_NAME: string;
|
||||||
declare const MODULE_PATH: string;
|
declare const MODULE_PATH: string;
|
||||||
|
declare const MODEL_CATALOG_URL: string;
|
||||||
|
|||||||
37
plugins/model-management-plugin/helper.ts
Normal file
37
plugins/model-management-plugin/helper.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
export const parseToModel = (model) => {
|
||||||
|
const modelVersions = [];
|
||||||
|
model.versions.forEach((v) => {
|
||||||
|
const version = {
|
||||||
|
_id: `${model.author}-${v.name}`,
|
||||||
|
name: v.name,
|
||||||
|
quantMethod: v.quantMethod,
|
||||||
|
bits: v.bits,
|
||||||
|
size: v.size,
|
||||||
|
maxRamRequired: v.maxRamRequired,
|
||||||
|
usecase: v.usecase,
|
||||||
|
downloadLink: v.downloadLink,
|
||||||
|
productId: model.id,
|
||||||
|
};
|
||||||
|
modelVersions.push(version);
|
||||||
|
});
|
||||||
|
|
||||||
|
const product = {
|
||||||
|
_id: model.id,
|
||||||
|
name: model.name,
|
||||||
|
shortDescription: model.shortDescription,
|
||||||
|
avatarUrl: model.avatarUrl,
|
||||||
|
author: model.author,
|
||||||
|
version: model.version,
|
||||||
|
modelUrl: model.modelUrl,
|
||||||
|
nsfw: model.nsfw,
|
||||||
|
tags: model.tags,
|
||||||
|
greeting: model.defaultGreeting,
|
||||||
|
type: model.type,
|
||||||
|
createdAt: model.createdAt,
|
||||||
|
longDescription: model.longDescription,
|
||||||
|
status: "Downloadable",
|
||||||
|
releaseDate: 0,
|
||||||
|
availableVersions: modelVersions,
|
||||||
|
};
|
||||||
|
return product;
|
||||||
|
};
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { ModelManagementService, PluginService, RegisterExtensionPoint, core, store } from "@janhq/core";
|
import { ModelManagementService, PluginService, RegisterExtensionPoint, core, store } from "@janhq/core";
|
||||||
|
import { parseToModel } from "./helper";
|
||||||
|
|
||||||
const getDownloadedModels = () => core.invokePluginFunc(MODULE_PATH, "getDownloadedModels");
|
const getDownloadedModels = () => core.invokePluginFunc(MODULE_PATH, "getDownloadedModels");
|
||||||
|
|
||||||
@ -10,7 +11,16 @@ const deleteModel = (path) => core.deleteFile(path);
|
|||||||
|
|
||||||
const searchModels = (params) => core.invokePluginFunc(MODULE_PATH, "searchModels", params);
|
const searchModels = (params) => core.invokePluginFunc(MODULE_PATH, "searchModels", params);
|
||||||
|
|
||||||
const getConfiguredModels = () => core.invokePluginFunc(MODULE_PATH, "getConfiguredModels");
|
async function getConfiguredModels() {
|
||||||
|
// Clear cache to get the latest model catalog
|
||||||
|
delete require.cache[MODEL_CATALOG_URL];
|
||||||
|
|
||||||
|
// Import the remote model catalog
|
||||||
|
const module = require(MODEL_CATALOG_URL);
|
||||||
|
return module.default.map((e) => {
|
||||||
|
return parseToModel(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a model in the database when user start downloading it
|
* Store a model in the database when user start downloading it
|
||||||
|
|||||||
@ -1,212 +1 @@
|
|||||||
const { listModels, listFiles, fileDownloadInfo } = require("@huggingface/hub");
|
module.exports = {};
|
||||||
const https = require("https");
|
|
||||||
|
|
||||||
let modelsIterator = undefined;
|
|
||||||
let currentSearchOwner = undefined;
|
|
||||||
|
|
||||||
// Github API
|
|
||||||
const githubHostName = "api.github.com";
|
|
||||||
const githubHeaders = {
|
|
||||||
"User-Agent": "node.js",
|
|
||||||
Accept: "application/vnd.github.v3+json",
|
|
||||||
};
|
|
||||||
const githubPath = "/repos/janhq/models/contents";
|
|
||||||
|
|
||||||
const getNextModels = async (count) => {
|
|
||||||
const models = [];
|
|
||||||
let hasMore = true;
|
|
||||||
|
|
||||||
while (models.length < count) {
|
|
||||||
const next = await modelsIterator.next();
|
|
||||||
|
|
||||||
// end if we reached the end
|
|
||||||
if (next.done) {
|
|
||||||
hasMore = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const model = next.value;
|
|
||||||
const files = await listFilesByName(model.name);
|
|
||||||
|
|
||||||
models.push({
|
|
||||||
...model,
|
|
||||||
files,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
data: models,
|
|
||||||
hasMore,
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const searchModels = async (params) => {
|
|
||||||
if (currentSearchOwner === params.search.owner && modelsIterator != null) {
|
|
||||||
// paginated search
|
|
||||||
console.debug(`Paginated search owner: ${params.search.owner}`);
|
|
||||||
const models = await getNextModels(params.limit);
|
|
||||||
return models;
|
|
||||||
} else {
|
|
||||||
// new search
|
|
||||||
console.debug(`Init new search owner: ${params.search.owner}`);
|
|
||||||
currentSearchOwner = params.search.owner;
|
|
||||||
modelsIterator = listModels({
|
|
||||||
search: params.search,
|
|
||||||
credentials: params.credentials,
|
|
||||||
});
|
|
||||||
|
|
||||||
const models = await getNextModels(params.limit);
|
|
||||||
return models;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const listFilesByName = async (modelName) => {
|
|
||||||
const repo = { type: "model", name: modelName };
|
|
||||||
const fileDownloadInfoMap = {};
|
|
||||||
for await (const file of listFiles({
|
|
||||||
repo: repo,
|
|
||||||
})) {
|
|
||||||
if (file.type === "file" && file.path.endsWith(".bin")) {
|
|
||||||
const downloadInfo = await fileDownloadInfo({
|
|
||||||
repo: repo,
|
|
||||||
path: file.path,
|
|
||||||
});
|
|
||||||
fileDownloadInfoMap[file.path] = {
|
|
||||||
...file,
|
|
||||||
...downloadInfo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileDownloadInfoMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getConfiguredModels() {
|
|
||||||
const files: any = await getModelFiles();
|
|
||||||
|
|
||||||
const promises = files.map((file) => getContent(file));
|
|
||||||
const response = await Promise.all(promises);
|
|
||||||
|
|
||||||
const models = [];
|
|
||||||
response.forEach((model) => {
|
|
||||||
models.push(parseToModel(model));
|
|
||||||
});
|
|
||||||
|
|
||||||
return models;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseToModel = (model) => {
|
|
||||||
const modelVersions = [];
|
|
||||||
model.versions.forEach((v) => {
|
|
||||||
const version = {
|
|
||||||
_id: `${model.author}-${v.name}`,
|
|
||||||
name: v.name,
|
|
||||||
quantMethod: v.quantMethod,
|
|
||||||
bits: v.bits,
|
|
||||||
size: v.size,
|
|
||||||
maxRamRequired: v.maxRamRequired,
|
|
||||||
usecase: v.usecase,
|
|
||||||
downloadLink: v.downloadLink,
|
|
||||||
productId: model.id,
|
|
||||||
};
|
|
||||||
modelVersions.push(version);
|
|
||||||
});
|
|
||||||
|
|
||||||
const product = {
|
|
||||||
_id: model.id,
|
|
||||||
name: model.name,
|
|
||||||
shortDescription: model.shortDescription,
|
|
||||||
avatarUrl: model.avatarUrl,
|
|
||||||
author: model.author,
|
|
||||||
version: model.version,
|
|
||||||
modelUrl: model.modelUrl,
|
|
||||||
nsfw: model.nsfw,
|
|
||||||
tags: model.tags,
|
|
||||||
greeting: model.defaultGreeting,
|
|
||||||
type: model.type,
|
|
||||||
createdAt: model.createdAt,
|
|
||||||
longDescription: model.longDescription,
|
|
||||||
status: "Downloadable",
|
|
||||||
releaseDate: 0,
|
|
||||||
availableVersions: modelVersions,
|
|
||||||
};
|
|
||||||
return product;
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getModelFiles() {
|
|
||||||
const options = {
|
|
||||||
hostname: githubHostName,
|
|
||||||
path: githubPath,
|
|
||||||
headers: githubHeaders,
|
|
||||||
};
|
|
||||||
|
|
||||||
const data = await new Promise((resolve, reject) => {
|
|
||||||
const req = https.request(options, (res) => {
|
|
||||||
let data = "";
|
|
||||||
|
|
||||||
res.on("data", (chunk) => {
|
|
||||||
data += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("end", () => {
|
|
||||||
const files = JSON.parse(data);
|
|
||||||
|
|
||||||
if (files.filter == null) {
|
|
||||||
console.error(files.message);
|
|
||||||
reject(files.message ?? "No files found");
|
|
||||||
}
|
|
||||||
if (!files || files.length === 0) {
|
|
||||||
resolve([]);
|
|
||||||
}
|
|
||||||
const jsonFiles = files.filter((file) => file.name.endsWith(".json"));
|
|
||||||
resolve(jsonFiles);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on("error", (error) => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
req.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getContent(file) {
|
|
||||||
const options = {
|
|
||||||
hostname: githubHostName,
|
|
||||||
path: `${githubPath}/${file.path}`,
|
|
||||||
headers: githubHeaders,
|
|
||||||
};
|
|
||||||
|
|
||||||
const data = await new Promise((resolve) => {
|
|
||||||
const req = https.request(options, (res) => {
|
|
||||||
let data = "";
|
|
||||||
|
|
||||||
res.on("data", (chunk) => {
|
|
||||||
data += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("end", () => {
|
|
||||||
const fileData = JSON.parse(data);
|
|
||||||
const fileContent = Buffer.from(fileData.content, "base64").toString();
|
|
||||||
resolve(JSON.parse(fileContent));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on("error", (error) => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
req.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
searchModels,
|
|
||||||
getConfiguredModels,
|
|
||||||
};
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/queue-list.svg",
|
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/queue-list.svg",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/module.js",
|
"module": "dist/module.js",
|
||||||
"author": "James",
|
"author": "Jan <service@jan.ai>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"activationPoints": [
|
"activationPoints": [
|
||||||
"init"
|
"init"
|
||||||
@ -27,11 +27,7 @@
|
|||||||
"README.md"
|
"README.md"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@huggingface/hub": "^0.8.5",
|
|
||||||
"@janhq/core": "^0.1.1",
|
"@janhq/core": "^0.1.1",
|
||||||
"ts-loader": "^9.5.0"
|
"ts-loader": "^9.5.0"
|
||||||
},
|
}
|
||||||
"bundledDependencies": [
|
|
||||||
"@huggingface/hub"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2016",
|
"target": "es2016",
|
||||||
"module": "ES6",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
|||||||
@ -19,6 +19,9 @@ module.exports = {
|
|||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
PLUGIN_NAME: JSON.stringify(packageJson.name),
|
PLUGIN_NAME: JSON.stringify(packageJson.name),
|
||||||
MODULE_PATH: JSON.stringify(`${packageJson.name}/${packageJson.module}`),
|
MODULE_PATH: JSON.stringify(`${packageJson.name}/${packageJson.module}`),
|
||||||
|
MODEL_CATALOG_URL: JSON.stringify(
|
||||||
|
"https://cdn.jsdelivr.net/npm/@janhq/models@latest/dist/index.js"
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
output: {
|
output: {
|
||||||
@ -30,7 +33,7 @@ module.exports = {
|
|||||||
extensions: [".ts", ".js"],
|
extensions: [".ts", ".js"],
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
minimize: false
|
minimize: false,
|
||||||
},
|
},
|
||||||
// Add loaders and other configuration as needed for your project
|
// Add loaders and other configuration as needed for your project
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/cpu-chip.svg",
|
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/cpu-chip.svg",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/module.js",
|
"module": "dist/module.js",
|
||||||
"author": "Jan",
|
"author": "Jan <service@jan.ai>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"activationPoints": [
|
"activationPoints": [
|
||||||
"init"
|
"init"
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"icon": "https://static-assets.jan.ai/openai-icon.jpg",
|
"icon": "https://static-assets.jan.ai/openai-icon.jpg",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/module.js",
|
"module": "dist/module.js",
|
||||||
"author": "Jan",
|
"author": "Jan <service@jan.ai>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"activationPoints": [
|
"activationPoints": [
|
||||||
"init"
|
"init"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user