You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

380 lines
9.5 KiB

import { defineStore } from "pinia";
import { ref } from "vue";
import { db } from "./db.ts"
import { aiLabels } from "./labels/index.ts"
import { fetchGet, getSystemKey } from "@/system/config"
const modelEngines = [
{
name: "ollama",
cpp: "llama.cpp",
needQuant: true
},
{
name: "sd",
cpp: "stable-diffusion.cpp",
needQuant: false
},
{
name: "voice",
cpp: "sherpa.cpp",
needQuant: false
}
]
const llamaQuant = [
"q2_K",
"q3_K",
"q3_K_S",
"q3_K_M",
"q3_K_L",
"q4_0",
"q4_1",
"q4_K",
"q4_K_S",
"q4_K_M",
"q5_0",
"q5_1",
"q5_K",
"q5_K_S",
"q5_K_M",
"q6_K",
"q8_0",
"f16",
]
export const useModelStore = defineStore('modelStore', () => {
const labelList: any = ref([])
const cateList: any = ["chat", "translation", "code", "img2txt", "image", "tts", "audio", "embeddings"]
const modelList: any = ref([])
const downList: any = ref([])
const chatConfig: any = ref({
chat: {
key: "chat",
contextLength: 10,
num_keep: 5, //保留多少个最有可能的预测结果。这与top_k一起使用,决定模型在生成下一个词时考虑的词汇范围。
num_predict: 3, //生成多少个预测结果
top_p: 0.95,
top_k: 40, //影响生成的随机性。较高的top_k值将使模型考虑更多的词汇
temperature: 0.7, //影响生成的随机性。较低的温度产生更保守的输出,较高的温度产生更随机的输出。
},
translation: {
key: "translation",
num_keep: 5,
num_predict: 1,
top_k: 40,
top_p: 0.95,
temperature: 0.2,
},
creation: {
key: "creation",
num_keep: 3,
num_predict: 1,
top_k: 40,
top_p: 0.95,
temperature: 0.2,
},
knowledge: {
key: "knowledge",
contextLength: 10,
num_keep: 5,
num_predict: 1,
top_k: 40,
top_p: 0.95,
temperature: 0.2,
},
spoken: {
key: "spoken",
contextLength: 10,
num_keep: 5,
num_predict: 1,
top_k: 40,
top_p: 0.95,
temperature: 0.2,
}
})
const aiUrl = getSystemKey("aiUrl")
async function getLabelCate(cateName: string) {
const list = await getLabelList()
labelList.value = list.filter((d: any) => {
if (cateName == 'all') {
return true
} else {
return d.action == cateName
}
})
}
async function getLabelSearch(keyword: string) {
const list = await getLabelList()
if (!keyword || keyword == "") {
labelList.value = list
}
labelList.value = list.filter((d: any) => d.name.toLowerCase().includes(keyword.toLowerCase()))
}
async function getLabelList() {
return await db.getAll("modelslabel")
//return await db.getByField("modelslabel", "chanel", getSystemKey("currentChanel"))
}
async function delLabel(id: number) {
await db.delete("modelslabel", id)
labelList.value = await getLabelList()
}
async function checkLabelData(data: any) {
const labelData = await db.get("modelslabel", { name: data.label })
if (!labelData) {
return
}
if (labelData.models.find((d: any) => d.model == data.model)) {
return
}
labelData.models.push(data)
await db.update("modelslabel", labelData.id, labelData)
}
async function getModelList() {
const res = await fetchGet(`${aiUrl}/ai/tags`)
//console.log(res)
if (res.ok) {
await resetData(res)
}
return modelList.value
}
async function resetData(res: any) {
const data = await res.json();
// console.log(data);
if (data && data.length > 0) {
// 获取当前modelList中的模型名称
const existingModels:any = [];
const has = await db.getAll("modelslist");
has.forEach((model: any) => {
if(model.isdef && model.isdef > 0) {
existingModels.push(model.model)
}
})
data.forEach((d:any) => {
if (existingModels.includes(d.model)) {
d.isdef = 1
}
});
await db.clear("modelslist");
await db.addAll("modelslist", data);
modelList.value = data;
}
// 重新获取所有模型列表
}
async function refreshOllama() {
const res = await fetchGet(`${aiUrl}/ai/refreshOllama`)
//console.log(res)
if (res.ok) {
resetData(res)
}
}
function getModelInfo(model: string) {
return modelList.value.find((d: any) => d.model == model)
}
async function getModel(action: string) {
const model = await db.get("modelslist", { action, isdef: 1 })
if (!model) {
return await db.addOne("modelslist", { action })
} else {
return model
}
}
async function getList() {
labelList.value = await getLabelList()
await getModelList()
downList.value.forEach((_: any, index: number) => {
downList.value[index].isLoading = 0
})
}
async function setCurrentModel(action: string, model?: string) {
await db.modify("modelslist", "action", action, { isdef: 0 })
//console.log(model)
if (model !== "") {
const data = await db.get("modelslist", { model })
if (data) {
return await db.update("modelslist", data.id, { isdef: 1 })
}
} else {
const data = await db.get("modelslist", { action })
if (data) {
return await db.update("modelslist", data.id, { isdef: 1 })
}
}
}
async function setDefModel(action: string) {
const has = await db.get("modelslist", { action, isdef: 1 })
if (!has) {
const data = await db.get("modelslist", { action })
if (data) {
return await db.update("modelslist", data.id, { isdef: 1 })
}
}
}
function getCurrentModelList(action: string) {
//if (!modelList || modelList.length == 0) return
return modelList.value.filter((d: any) => d.action == action)
}
async function deleteModelList(data: any) {
//console.log(data)
if (!data || !data.model) return
const postData = {
method: "POST",
body: JSON.stringify(data),
};
const delUrl = aiUrl + "/ai/delete";
const completion = await fetch(delUrl, postData);
if (completion.status === 404) {
return completion.statusText;
}
if (completion.status === 200) {
modelList.value.forEach((d: any, index: number) => {
if (d.model == data.model) {
modelList.value.splice(index, 1);
}
});
await db.deleteByField("modelslist", "model", data.model)
if (data.isdef * 1 == 1) {
await setCurrentModel(data.action, "")
}
}
//await db.delete("modelslist", data.id)
//await getModelList()
}
function checkDownload(name: string) {
return modelList.value.find((d: any) => d.model === name);
}
function addDownload(data: any) {
const has = downList.value.find((d: any) => d.model === data.model)
if (!has) {
downList.value.unshift(data)
} else {
updateDownload(data)
}
return data
}
function deleteDownload(model: string) {
//console.log(model)
downList.value.forEach((d: any, index: number) => {
if (d.model == model) {
downList.value.splice(index, 1);
}
});
}
async function updateDownload(modelData: any) {
const index = downList.value.findIndex((d: any) => d.model === modelData.model);
if (index !== -1) {
// 或者使用splice方法替换对象
downList.value.splice(index, 1, {
...downList.value[index],
status: modelData.status,
progress: modelData.progress,
isLoading: modelData.isLoading ?? 0,
});
if (modelData.status === "success") {
//await addDownList(modelData);
await getModelList();
await setDefModel(modelData.action);
await checkLabelData(modelData);
}
}
}
function parseJson(str: string): any {
try {
return JSON.parse(str);
} catch (e) {
return undefined;
}
}
function parseMsg(str: string) {
const nres = { status: "" }
try {
//console.log(str)
if (str == 'has done!') {
return { status: 'success' }
}
const raw: any = str.split("\n")
if (raw.length < 1) return nres
// deno-lint-ignore no-explicit-any
const rt: string[] = raw.filter((d: string) => d.trim() !== "");
//console.log(rt)
if (rt.length > 0) {
let res: any[] = [];
rt.forEach((d: string) => {
const msg = parseJson(d);
if (msg) {
res.push(msg);
}
});
if (res.length > 0) {
return res[res.length - 1]
} else {
return nres
}
} else {
return nres;
}
} catch (error) {
console.log(error);
return nres
}
}
async function initModel() {
await db.clear("modelslabel")
await db.addAll("modelslabel", aiLabels);
}
return {
cateList,
labelList,
modelList,
downList,
modelEngines,
llamaQuant,
chatConfig,
getList,
getModelList,
getModelInfo,
getModel,
checkDownload,
addDownload,
deleteDownload,
updateDownload,
checkLabelData,
getLabelCate,
getLabelSearch,
getLabelList,
delLabel,
//addDownList,
deleteModelList,
initModel,
setCurrentModel,
getCurrentModelList,
parseMsg,
refreshOllama
}
}, {
persist: {
enabled: true,
strategies: [
{
storage: localStorage,
paths: [
"downList",
"chatConfig"
]
}, // name 字段用localstorage存储
],
}
})