181 lines
4.5 KiB
TypeScript
181 lines
4.5 KiB
TypeScript
import {
|
|
ModelExtension,
|
|
Model,
|
|
InferenceEngine,
|
|
joinPath,
|
|
dirName,
|
|
} from '@janhq/core'
|
|
import { CortexAPI } from './cortex'
|
|
import { scanModelsFolder } from './model-json'
|
|
|
|
declare const SETTINGS: Array<any>
|
|
|
|
/**
|
|
* Extension enum
|
|
*/
|
|
enum ExtensionEnum {
|
|
downloadedModels = 'downloadedModels',
|
|
}
|
|
|
|
/**
|
|
* A extension for models
|
|
*/
|
|
export default class JanModelExtension extends ModelExtension {
|
|
cortexAPI: CortexAPI = new CortexAPI()
|
|
|
|
/**
|
|
* Called when the extension is loaded.
|
|
* @override
|
|
*/
|
|
async onLoad() {
|
|
this.registerSettings(SETTINGS)
|
|
|
|
// Try get models from cortex.cpp
|
|
this.getModels().then((models) => {
|
|
this.registerModels(models)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Called when the extension is unloaded.
|
|
* @override
|
|
*/
|
|
async onUnload() {}
|
|
|
|
/**
|
|
* Downloads a machine learning model.
|
|
* @param model - The model to download.
|
|
* @returns A Promise that resolves when the model is downloaded.
|
|
*/
|
|
async pullModel(model: string, id?: string): Promise<void> {
|
|
/**
|
|
* Sending POST to /models/pull/{id} endpoint to pull the model
|
|
*/
|
|
return this.cortexAPI.pullModel(model, id)
|
|
}
|
|
|
|
/**
|
|
* Cancels the download of a specific machine learning model.
|
|
*
|
|
* @param {string} model - The ID of the model whose download is to be cancelled.
|
|
* @returns {Promise<void>} A promise that resolves when the download has been cancelled.
|
|
*/
|
|
async cancelModelPull(model: string): Promise<void> {
|
|
/**
|
|
* Sending DELETE to /models/pull/{id} endpoint to cancel a model pull
|
|
*/
|
|
this.cortexAPI.cancelModelPull(model)
|
|
}
|
|
|
|
/**
|
|
* Deletes a pulled model
|
|
* @param model - The model to delete
|
|
* @returns A Promise that resolves when the model is deleted.
|
|
*/
|
|
async deleteModel(model: string): Promise<void> {
|
|
return this.cortexAPI.deleteModel(model)
|
|
}
|
|
|
|
/**
|
|
* Gets all pulled models
|
|
* @returns A Promise that resolves with an array of all models.
|
|
*/
|
|
async getModels(): Promise<Model[]> {
|
|
/**
|
|
* In this action, if return empty array right away
|
|
* it would reset app cache and app will not function properly
|
|
* should compare and try import
|
|
*/
|
|
|
|
if (!localStorage.getItem(ExtensionEnum.downloadedModels)) {
|
|
// Updated from an older version than 0.5.5
|
|
// Scan through the models folder and import them (Legacy flow)
|
|
// Return models immediately
|
|
return scanModelsFolder().then((models) => {
|
|
return models ?? []
|
|
})
|
|
}
|
|
|
|
let currentModels: Model[] = []
|
|
|
|
try {
|
|
currentModels = JSON.parse(
|
|
localStorage.getItem(ExtensionEnum.downloadedModels)
|
|
) as Model[]
|
|
} catch (e) {
|
|
currentModels = []
|
|
console.error(e)
|
|
}
|
|
|
|
/**
|
|
* Here we are filtering out the models that are not imported
|
|
* and are not using llama.cpp engine
|
|
*/
|
|
var toImportModels = currentModels.filter(
|
|
(e) => e.engine === InferenceEngine.nitro
|
|
)
|
|
|
|
await this.cortexAPI.getModels().then((models) => {
|
|
const existingIds = models.map((e) => e.id)
|
|
toImportModels = toImportModels.filter(
|
|
(e: Model) => !existingIds.includes(e.id)
|
|
)
|
|
})
|
|
|
|
console.log('To import models:', toImportModels.length)
|
|
/**
|
|
* There are models to import
|
|
* do not return models from cortex.cpp yet
|
|
* otherwise it will reset the app cache
|
|
* */
|
|
if (toImportModels.length > 0) {
|
|
// Import models
|
|
await Promise.all(
|
|
toImportModels.map(async (model: Model & { file_path: string }) =>
|
|
this.importModel(
|
|
model.id,
|
|
await joinPath([
|
|
await dirName(model.file_path),
|
|
model.sources[0]?.filename ??
|
|
model.settings?.llama_model_path ??
|
|
model.sources[0]?.url.split('/').pop() ??
|
|
model.id,
|
|
])
|
|
)
|
|
)
|
|
)
|
|
|
|
return currentModels
|
|
}
|
|
|
|
/**
|
|
* All models are imported successfully before
|
|
* just return models from cortex.cpp
|
|
*/
|
|
return (
|
|
this.cortexAPI.getModels().then((models) => {
|
|
return models
|
|
}) ?? Promise.resolve([])
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Update a pulled model metadata
|
|
* @param model - The metadata of the model
|
|
*/
|
|
async updateModel(model: Partial<Model>): Promise<Model> {
|
|
return this.cortexAPI
|
|
?.updateModel(model)
|
|
.then(() => this.cortexAPI!.getModel(model.id))
|
|
}
|
|
|
|
/**
|
|
* Import an existing model file
|
|
* @param model
|
|
* @param optionType
|
|
*/
|
|
async importModel(model: string, modelPath: string): Promise<void> {
|
|
return this.cortexAPI.importModel(model, modelPath)
|
|
}
|
|
}
|