feat: model

This commit is contained in:
wangdan-fit2cloud 2025-05-13 19:18:27 +08:00
parent d14b47373a
commit e6dc404867
13 changed files with 435 additions and 402 deletions

View File

@ -30,10 +30,11 @@ const getModel: (
* @returns
*/
const getModelParamsForm: (
wordspace_id: string,
model_id: string,
loading?: Ref<boolean>,
) => Promise<Result<Array<FormField>>> = (model_id, loading) => {
return get(`model/${model_id}/model_params_form`, {}, loading)
) => Promise<Result<Array<FormField>>> = (wordspace_id, model_id, loading) => {
return get(`${prefix}/${wordspace_id}/model/${model_id}/model_params_form`, {}, loading)
}
/**
@ -43,10 +44,11 @@ const getModelParamsForm: (
* @returns
*/
const createModel: (
wordspace_id: string,
request: CreateModelRequest,
loading?: Ref<boolean>,
) => Promise<Result<Model>> = (request, loading) => {
return post(`${prefix}`, request, {}, loading)
) => Promise<Result<Model>> = (wordspace_id, request, loading) => {
return post(`${prefix}/${wordspace_id}/model`, request, {}, loading)
}
/**
@ -56,11 +58,12 @@ const createModel: (
* @returns
*/
const updateModel: (
wordspace_id: string,
model_id: string,
request: EditModelRequest,
loading?: Ref<boolean>,
) => Promise<Result<Model>> = (model_id, request, loading) => {
return put(`${prefix}/${model_id}`, request, {}, loading)
) => Promise<Result<Model>> = (wordspace_id, model_id, request, loading) => {
return put(`${prefix}/${wordspace_id}/model/${model_id}`, request, {}, loading)
}
/**
@ -70,11 +73,12 @@ const updateModel: (
* @returns
*/
const updateModelParamsForm: (
wordspace_id: string,
model_id: string,
request: any[],
loading?: Ref<boolean>,
) => Promise<Result<Model>> = (model_id, request, loading) => {
return put(`${prefix}/${model_id}/model_params_form`, request, {}, loading)
) => Promise<Result<Model>> = (wordspace_id, model_id, request, loading) => {
return put(`${prefix}/${wordspace_id}/model/${model_id}/model_params_form`, request, {}, loading)
}
/**
@ -83,11 +87,12 @@ const updateModelParamsForm: (
* @param loading
* @returns
*/
const getModelById: (model_id: string, loading?: Ref<boolean>) => Promise<Result<Model>> = (
model_id,
loading,
) => {
return get(`${prefix}/${model_id}`, {}, loading)
const getModelById: (
wordspace_id: string,
model_id: string,
loading?: Ref<boolean>,
) => Promise<Result<Model>> = (wordspace_id, model_id, loading) => {
return get(`${prefix}/${wordspace_id}/model/${model_id}`, {}, loading)
}
/**
* id
@ -95,11 +100,12 @@ const getModelById: (model_id: string, loading?: Ref<boolean>) => Promise<Result
* @param loading
* @returns
*/
const getModelMetaById: (model_id: string, loading?: Ref<boolean>) => Promise<Result<Model>> = (
model_id,
loading,
) => {
return get(`${prefix}/${model_id}/meta`, {}, loading)
const getModelMetaById: (
wordspace_id: string,
model_id: string,
loading?: Ref<boolean>,
) => Promise<Result<Model>> = (wordspace_id, model_id, loading) => {
return get(`${prefix}/${wordspace_id}/model/${model_id}/meta`, {}, loading)
}
/**
*
@ -107,17 +113,19 @@ const getModelMetaById: (model_id: string, loading?: Ref<boolean>) => Promise<Re
* @param loading
* @returns
*/
const pauseDownload: (model_id: string, loading?: Ref<boolean>) => Promise<Result<boolean>> = (
model_id,
loading,
) => {
return put(`${prefix}/${model_id}/pause_download`, undefined, {}, loading)
const pauseDownload: (
wordspace_id: string,
model_id: string,
loading?: Ref<boolean>,
) => Promise<Result<boolean>> = (wordspace_id, model_id, loading) => {
return put(`${prefix}/${wordspace_id}/model/${model_id}/pause_download`, undefined, {}, loading)
}
const deleteModel: (model_id: string, loading?: Ref<boolean>) => Promise<Result<boolean>> = (
model_id,
loading,
) => {
return del(`${prefix}/${model_id}`, undefined, {}, loading)
const deleteModel: (
wordspace_id: string,
model_id: string,
loading?: Ref<boolean>,
) => Promise<Result<boolean>> = (wordspace_id, model_id, loading) => {
return del(`${prefix}/${wordspace_id}/model/${model_id}`, undefined, {}, loading)
}
export default {
getModel,

View File

@ -3,8 +3,8 @@ export enum PermissionType {
PUBLIC = 'common.public'
}
export enum PermissionDesc {
PRIVATE = 'views.model.templateForm.form.permissionType.privateDesc',
PUBLIC = 'views.model.templateForm.form.permissionType.publicDesc',
PRIVATE = 'views.model.modelForm.permissionType.privateDesc',
PUBLIC = 'views.model.modelForm.permissionType.publicDesc',
}
export enum modelType {

View File

@ -4,11 +4,11 @@ export default {
providerPlaceholder: 'Select Provider',
addModel: 'Add Model',
searchBar: {
placeholder: 'Search by name'
placeholder: 'Search by name',
},
delete: {
confirmTitle: 'Delete Model',
confirmMessage: 'Are you sure you want to delete the model:'
confirmMessage: 'Are you sure you want to delete the model:',
},
tip: {
createSuccessMessage: 'Model created successfully',
@ -19,7 +19,7 @@ export default {
updateSuccessMessage: 'Model updated successfully',
saveSuccessMessage: 'Model parameters saved successfully',
downloadError: 'Download failed',
noModel: 'Model does not exist in Ollama'
noModel: 'Model does not exist in Ollama',
},
model: {
allModel: 'All Models',
@ -31,7 +31,7 @@ export default {
STT: 'Speech2Text',
TTS: 'TTS',
IMAGE: 'Vision Model',
TTI: 'Image Generation'
TTI: 'Image Generation',
},
modelForm: {
title: {
@ -41,49 +41,44 @@ export default {
editParam: 'Edit Parameter',
addParam: 'Add Parameter',
paramSetting: 'Model Parameter Settings',
apiParamPassing: 'Interface Parameters'
apiParamPassing: 'Interface Parameters',
},
modeName: {
label: 'Model Name',
placeholder: 'Set a name for the base model',
tooltip: 'Custom model name in MaxKB',
requiredMessage: 'Model name cannot be empty',
},
permissionType: {
label: 'Permission',
privateDesc: 'Available only to current user',
publicDesc: 'Available to all users',
requiredMessage: 'Permission cannot be empty',
},
model_type: {
label: 'Model Type',
placeholder: 'Select a model type',
tooltip1: 'LLM: An inference model for AI chats in the APP.',
tooltip2: 'Embedding Model: A model for vectorizing document content in the knowledge.',
tooltip3: 'Speech2Text: A model used for speech recognition in the APP.',
tooltip4: 'TTS: A model used for TTS in the APP.',
tooltip5:
'Rerank: A model used to reorder candidate segments when using multi-route recall in advanced orchestration APP.',
tooltip6:
'Vision Model: A visual model used for image understanding in advanced orchestration APP.',
tooltip7:
'Image Generation: A visual model used for image generation in advanced orchestration APP.',
requiredMessage: 'Model type cannot be empty',
},
base_model: {
label: 'Base Model',
tooltip: 'For models not listed, enter the model name and press Enter',
placeholder: 'Enter the base model name and press Enter to add',
requiredMessage: 'Base model cannot be empty',
},
form: {
templateName: {
label: 'Model Name',
placeholder: 'Set a name for the base model',
tooltip: 'Custom model name in MaxKB',
requiredMessage: 'Model name cannot be empty'
},
permissionType: {
label: 'Permission',
privateDesc: 'Available only to current user',
publicDesc: 'Available to all users',
requiredMessage: 'Permission cannot be empty'
},
model_type: {
label: 'Model Type',
placeholder: 'Select a model type',
tooltip1:
'LLM: An inference model for AI chats in the APP.',
tooltip2:
'Embedding Model: A model for vectorizing document content in the knowledge.',
tooltip3: 'Speech2Text: A model used for speech recognition in the APP.',
tooltip4: 'TTS: A model used for TTS in the APP.',
tooltip5:
'Rerank: A model used to reorder candidate segments when using multi-route recall in advanced orchestration APP.',
tooltip6:
'Vision Model: A visual model used for image understanding in advanced orchestration APP.',
tooltip7:
'Image Generation: A visual model used for image generation in advanced orchestration APP.',
requiredMessage: 'Model type cannot be empty'
},
base_model: {
label: 'Base Model',
tooltip:
'For models not listed, enter the model name and press Enter',
placeholder: 'Enter the base model name and press Enter to add',
requiredMessage: 'Base model cannot be empty'
}
}
},
download: {
downloading: 'Downloading...',
cancelDownload: 'Cancel Download'
}
cancelDownload: 'Cancel Download',
},
}

View File

@ -4,11 +4,11 @@ export default {
providerPlaceholder: '选择供应商',
addModel: '添加模型',
searchBar: {
placeholder: '按名称搜索'
placeholder: '按名称搜索',
},
delete: {
confirmTitle: '删除模型',
confirmMessage: '是否删除模型:'
confirmMessage: '是否删除模型:',
},
tip: {
createSuccessMessage: '创建模型成功',
@ -19,7 +19,7 @@ export default {
updateSuccessMessage: '修改模型成功',
saveSuccessMessage: '模型参数保存成功',
downloadError: '下载失败',
noModel: '模型在Ollama不存在'
noModel: '模型在Ollama不存在',
},
modelType: {
allModel: '全部模型',
@ -31,7 +31,7 @@ export default {
STT: '语音识别',
TTS: '语音合成',
IMAGE: '视觉模型',
TTI: '图片生成'
TTI: '图片生成',
},
modelForm: {
title: {
@ -41,43 +41,41 @@ export default {
editParam: '编辑参数',
addParam: '添加参数',
paramSetting: '模型参数设置',
apiParamPassing: '接口传参'
apiParamPassing: '接口传参',
},
modeName: {
label: '模型名称',
placeholder: '请给基础模型设置一个名称',
tooltip: 'MaxKB 中自定义的模型名称',
requiredMessage: '模型名称不能为空',
},
permissionType: {
label: '权限',
privateDesc: '仅当前用户使用',
publicDesc: '所有用户都可使用',
requiredMessage: '权限不能为空',
},
model_type: {
label: '模型类型',
placeholder: '请选择模型类型',
tooltip1: '大语言模型在应用中与AI对话的推理模型。',
tooltip2: '向量模型:在知识库中对文档内容进行向量化的模型。',
tooltip3: '语音识别:在应用中开启语音识别后用于语音转文字的模型。',
tooltip4: '语音合成:在应用中开启语音播放后用于文字转语音的模型。',
tooltip5: '重排模型:在高级编排应用中使用多路召回时,对候选分段进行重新排序的模型。',
tooltip6: '视觉模型:在高级编排应用中用于图片理解的视觉模型。',
tooltip7: '图片生成:在高级编排应用中用于图片生成的视觉模型。',
requiredMessage: '模型类型不能为空',
},
base_model: {
label: '基础模型',
tooltip: '列表中未列出的模型,直接输入模型名称,回车即可添加',
placeholder: '自定义输入基础模型后回车即可',
requiredMessage: '基础模型不能为空',
},
form: {
templateName: {
label: '模型名称',
placeholder: '请给基础模型设置一个名称',
tooltip: 'MaxKB 中自定义的模型名称',
requiredMessage: '模型名称不能为空'
},
permissionType: {
label: '权限',
privateDesc: '仅当前用户使用',
publicDesc: '所有用户都可使用',
requiredMessage: '权限不能为空'
},
model_type: {
label: '模型类型',
placeholder: '请选择模型类型',
tooltip1: '大语言模型在应用中与AI对话的推理模型。',
tooltip2: '向量模型:在知识库中对文档内容进行向量化的模型。',
tooltip3: '语音识别:在应用中开启语音识别后用于语音转文字的模型。',
tooltip4: '语音合成:在应用中开启语音播放后用于文字转语音的模型。',
tooltip5: '重排模型:在高级编排应用中使用多路召回时,对候选分段进行重新排序的模型。',
tooltip6: '视觉模型:在高级编排应用中用于图片理解的视觉模型。',
tooltip7: '图片生成:在高级编排应用中用于图片生成的视觉模型。',
requiredMessage: '模型类型不能为空'
},
base_model: {
label: '基础模型',
tooltip: '列表中未列出的模型,直接输入模型名称,回车即可添加',
placeholder: '自定义输入基础模型后回车即可',
requiredMessage: '基础模型不能为空'
}
}
},
download: {
downloading: '正在下载中',
cancelDownload: '取消下载'
}
cancelDownload: '取消下载',
},
}

View File

@ -4,11 +4,11 @@ export default {
providerPlaceholder: '選擇供應商',
addModel: '新增模型',
searchBar: {
placeholder: '按名稱搜尋'
placeholder: '按名稱搜尋',
},
delete: {
confirmTitle: '刪除模型',
confirmMessage: '是否刪除模型:'
confirmMessage: '是否刪除模型:',
},
tip: {
createSuccessMessage: '創建模型成功',
@ -19,7 +19,7 @@ export default {
updateSuccessMessage: '修改模型成功',
saveSuccessMessage: '模型參數儲存成功',
downloadError: '下載失敗',
noModel: '模型在Ollama不存在'
noModel: '模型在Ollama不存在',
},
model: {
allModel: '全部模型',
@ -31,7 +31,7 @@ export default {
STT: '語音辨識',
TTS: '語音合成',
IMAGE: '圖片理解',
TTI: '圖片生成'
TTI: '圖片生成',
},
modelForm: {
title: {
@ -41,43 +41,41 @@ export default {
editParam: '編輯參數',
addParam: '新增參數',
paramSetting: '模型參數設定',
apiParamPassing: '接口傳參'
apiParamPassing: '接口傳參',
},
modeName: {
label: '模型名稱',
placeholder: '請給基礎模型設定一個名稱',
tooltip: 'MaxKB 中自訂的模型名稱',
requiredMessage: '模型名稱不能為空',
},
permissionType: {
label: '權限',
privateDesc: '僅當前使用者使用',
publicDesc: '所有使用者都可使用',
requiredMessage: '權限不能為空',
},
model_type: {
label: '模型類型',
placeholder: '請選擇模型類型',
tooltip1: '大語言模型在應用中與AI對話的推理模型。',
tooltip2: '向量模型:在知識庫中對文件內容進行向量化化的模型。',
tooltip3: '語音辨識:在應用中開啟語音辨識後用於語音轉文字的模型。',
tooltip4: '語音合成:在應用中開啟語音播放後用於文字轉語音的模型。',
tooltip5: '重排模型:在高階編排應用中使用多路召回時,對候選分段進行重新排序的模型。',
tooltip6: '圖片理解:在高階編排應用中用於圖片理解的視覺模型。',
tooltip7: '圖片生成:在高階編排應用中用於圖片生成的視覺模型。',
requiredMessage: '模型類型不能為空',
},
base_model: {
label: '基礎模型',
tooltip: '列表中未列出的模型,直接輸入模型名稱,按 Enter 即可新增',
placeholder: '自訂輸入基礎模型後按 Enter 即可',
requiredMessage: '基礎模型不能為空',
},
form: {
templateName: {
label: '模型名稱',
placeholder: '請給基礎模型設定一個名稱',
tooltip: 'MaxKB 中自訂的模型名稱',
requiredMessage: '模型名稱不能為空'
},
permissionType: {
label: '權限',
privateDesc: '僅當前使用者使用',
publicDesc: '所有使用者都可使用',
requiredMessage: '權限不能為空'
},
model_type: {
label: '模型類型',
placeholder: '請選擇模型類型',
tooltip1: '大語言模型在應用中與AI對話的推理模型。',
tooltip2: '向量模型:在知識庫中對文件內容進行向量化化的模型。',
tooltip3: '語音辨識:在應用中開啟語音辨識後用於語音轉文字的模型。',
tooltip4: '語音合成:在應用中開啟語音播放後用於文字轉語音的模型。',
tooltip5: '重排模型:在高階編排應用中使用多路召回時,對候選分段進行重新排序的模型。',
tooltip6: '圖片理解:在高階編排應用中用於圖片理解的視覺模型。',
tooltip7: '圖片生成:在高階編排應用中用於圖片生成的視覺模型。',
requiredMessage: '模型類型不能為空'
},
base_model: {
label: '基礎模型',
tooltip: '列表中未列出的模型,直接輸入模型名稱,按 Enter 即可新增',
placeholder: '自訂輸入基礎模型後按 Enter 即可',
requiredMessage: '基礎模型不能為空'
}
}
},
download: {
downloading: '正在下載中',
cancelDownload: '取消下載'
}
cancelDownload: '取消下載',
},
}

View File

@ -39,11 +39,11 @@
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span> {{ $t('views.model.modelForm.form.templateName.label') }} </span>
<span> {{ $t('views.model.modelForm.modeName.label') }} </span>
</div>
<el-tooltip effect="dark" placement="right">
<template #content>
<p>{{ $t('views.model.modelForm.form.templateName.tooltip') }}</p>
<p>{{ $t('views.model.modelForm.modeName.tooltip') }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
@ -53,12 +53,12 @@
v-model="base_form_data.name"
maxlength="64"
show-word-limit
:placeholder="$t('views.model.modelForm.form.templateName.placeholder')"
:placeholder="$t('views.model.modelForm.modeName.placeholder')"
/>
</el-form-item>
<el-form-item prop="permission_type" :rules="base_form_data_rule.permission_type">
<template #label>
<span>{{ $t('views.model.modelForm.form.permissionType.label') }}</span>
<span>{{ $t('views.model.modelForm.permissionType.label') }}</span>
</template>
<el-radio-group v-model="base_form_data.permission_type" class="card__radio">
<el-row :gutter="16">
@ -84,18 +84,16 @@
<el-form-item prop="model_type" :rules="base_form_data_rule.model_type">
<template #label>
<div class="flex align-center" style="display: inline-flex">
<span class="mr-4"
>{{ $t('views.model.modelForm.form.model_type.label') }}
</span>
<span class="mr-4">{{ $t('views.model.modelForm.model_type.label') }} </span>
<el-tooltip effect="dark" placement="right">
<template #content>
<p>{{ $t('views.model.modelForm.form.model_type.tooltip1') }}</p>
<p>{{ $t('views.model.modelForm.form.model_type.tooltip2') }}</p>
<p>{{ $t('views.model.modelForm.form.model_type.tooltip3') }}</p>
<p>{{ $t('views.model.modelForm.form.model_type.tooltip4') }}</p>
<p>{{ $t('views.model.modelForm.form.model_type.tooltip5') }}</p>
<p>{{ $t('views.model.modelForm.form.model_type.tooltip6') }}</p>
<p>{{ $t('views.model.modelForm.form.model_type.tooltip7') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip1') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip2') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip3') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip4') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip5') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip6') }}</p>
<p>{{ $t('views.model.modelForm.model_type.tooltip7') }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
@ -106,7 +104,7 @@
@change="list_base_model($event, true)"
v-model="base_form_data.model_type"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.form.model_type.placeholder')"
:placeholder="$t('views.model.modelForm.model_type.placeholder')"
>
<el-option
v-for="item in model_type_list"
@ -121,9 +119,9 @@
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span>{{ $t('views.model.modelForm.form.base_model.label') }} </span>
<span>{{ $t('views.model.modelForm.base_model.label') }} </span>
<span class="danger ml-4">{{
$t('views.model.modelForm.form.base_model.tooltip')
$t('views.model.modelForm.base_model.tooltip')
}}</span>
</div>
</div>
@ -133,7 +131,7 @@
v-loading="base_model_loading"
v-model="base_form_data.model_name"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.form.base_model.placeholder')"
:placeholder="$t('views.model.modelForm.base_model.placeholder')"
filterable
allow-create
default-first-option
@ -158,10 +156,7 @@
</template>
</DynamicsForm>
</el-tab-pane>
<el-tab-pane
:label="$t('views.model.modelForm.title.advancedInfo')"
name="advanced-info"
>
<el-tab-pane :label="$t('views.model.modelForm.title.advancedInfo')" name="advanced-info">
<el-empty
v-if="!base_form_data.model_type || !base_form_data.model_name"
:description="$t('views.model.tip.emptyMessage1')"
@ -269,6 +264,7 @@ import { ref, computed } from 'vue'
import type { Provider, BaseModel } from '@/api/type/model'
import type { Dict, KeyValue } from '@/api/type/common'
import ModelApi from '@/api/model/model'
import ProviderApi from '@/api/model/provider'
import type { FormField } from '@/components/dynamics-form/type'
import DynamicsForm from '@/components/dynamics-form/index.vue'
import type { FormRules } from 'element-plus'
@ -296,23 +292,23 @@ const base_form_data_rule = ref<FormRules>({
name: {
required: true,
trigger: 'blur',
message: t('views.model.modelForm.form.templateName.requiredMessage')
message: t('views.model.modelForm.modeName.requiredMessage'),
},
permission_type: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.form.permissionType.requiredMessage')
message: t('views.model.modelForm.permissionType.requiredMessage'),
},
model_type: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.form.model_type.requiredMessage')
message: t('views.model.modelForm.model_type.requiredMessage'),
},
model_name: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.form.base_model.requiredMessage')
}
message: t('views.model.modelForm.base_model.requiredMessage'),
},
})
const base_form_data = ref<{
@ -333,36 +329,36 @@ const form_data = computed({
model_type: base_form_data.value.model_type,
model_name: base_form_data.value.model_name,
permission_type: base_form_data.value.permission_type,
model_params_form: base_form_data.value.model_params_form
model_params_form: base_form_data.value.model_params_form,
}
},
set: (event: any) => {
credential_form_data.value = event
}
},
})
const getModelForm = (model_name: string) => {
if (!form_data.value.model_type) {
MsgWarning(t('views.model.modelForm.form.model_type.requiredMessage'))
MsgWarning(t('views.model.modelForm.model_type.requiredMessage'))
base_form_data.value.model_name = ''
return
}
if (providerValue.value) {
ModelApi.getModelCreateForm(
ProviderApi.getModelCreateForm(
providerValue.value.provider,
form_data.value.model_type,
model_name
model_name,
).then((ok) => {
model_form_field.value = ok.data
//
dynamicsFormRef.value?.render(model_form_field.value, undefined)
})
ModelApi.listBaseModelParamsForm(
ProviderApi.listBaseModelParamsForm(
providerValue.value.provider,
form_data.value.model_type,
model_name,
base_model_loading
base_model_loading,
).then((ok) => {
base_form_data.value.model_params_form = ok.data
})
@ -370,7 +366,7 @@ const getModelForm = (model_name: string) => {
}
const open = (provider: Provider, model_type?: string) => {
ModelApi.listModelType(provider.provider, model_type_loading).then((ok) => {
ProviderApi.listModelType(provider.provider, model_type_loading).then((ok) => {
model_type_list.value = ok.data
})
providerValue.value = provider
@ -388,10 +384,10 @@ const list_base_model = (model_type: any, change?: boolean) => {
base_form_data.value.model_params_form = []
}
if (providerValue.value) {
ModelApi.listBaseModel(providerValue.value.provider, model_type, base_model_loading).then(
ProviderApi.listBaseModel(providerValue.value.provider, model_type, base_model_loading).then(
(ok) => {
base_model_list.value = ok.data
}
},
)
}
}
@ -402,7 +398,7 @@ const close = () => {
model_type: '',
model_name: '',
permission_type: 'PRIVATE',
model_params_form: []
model_params_form: [],
}
credential_form_data.value = {}
model_form_field.value = []
@ -416,12 +412,13 @@ const submit = () => {
.then(() => {
if (providerValue.value) {
ModelApi.createModel(
'default',
{
...base_form_data.value,
credential: credential_form_data.value,
provider: providerValue.value.provider
provider: providerValue.value.provider,
},
loading
loading,
).then((ok) => {
close()
MsgSuccess(t('views.model.tip.createSuccessMessage'))

View File

@ -31,11 +31,11 @@
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span>{{ $t('views.model.modelForm.form.templateName.label') }} </span>
<span>{{ $t('views.model.modelForm.modeName.label') }} </span>
</div>
<el-tooltip effect="dark" placement="right">
<template #content>
<p>{{ $t('views.model.modelForm.form.templateName.tooltip') }}</p>
<p>{{ $t('views.model.modelForm.modeName.tooltip') }}</p>
</template>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
@ -45,12 +45,12 @@
v-model="base_form_data.name"
maxlength="64"
show-word-limit
:placeholder="$t('views.model.modelForm.form.templateName.placeholder')"
:placeholder="$t('views.model.modelForm.modeName.placeholder')"
/>
</el-form-item>
<el-form-item prop="permission_type" :rules="base_form_data_rule.permission_type">
<template #label>
<span>{{ $t('views.model.modelForm.form.permissionType.label') }}</span>
<span>{{ $t('views.model.modelForm.permissionType.label') }}</span>
</template>
<el-radio-group v-model="base_form_data.permission_type" class="card__radio">
@ -76,7 +76,7 @@
</el-form-item>
<el-form-item prop="model_type" :rules="base_form_data_rule.model_type">
<template #label>
<span>{{ $t('views.model.modelForm.form.model_type.label') }}</span>
<span>{{ $t('views.model.modelForm.model_type.label') }}</span>
</template>
<el-select
disabled
@ -84,7 +84,7 @@
@change="list_base_model($event, true)"
v-model="base_form_data.model_type"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.form.model_type.placeholder')"
:placeholder="$t('views.model.modelForm.model_type.placeholder')"
>
<el-option
v-for="item in model_type_list"
@ -98,9 +98,9 @@
<template #label>
<div class="flex align-center" style="display: inline-flex">
<div class="mr-4">
<span>{{ $t('views.model.modelForm.form.base_model.label') }} </span>
<span>{{ $t('views.model.modelForm.base_model.label') }} </span>
<span class="danger ml-4">{{
$t('views.model.modelForm.form.base_model.tooltip')
$t('views.model.modelForm.base_model.tooltip')
}}</span>
</div>
</div>
@ -110,7 +110,7 @@
v-loading="base_model_loading"
v-model="base_form_data.model_name"
class="w-full m-2"
:placeholder="$t('views.model.modelForm.form.base_model.requiredMessage')"
:placeholder="$t('views.model.modelForm.base_model.requiredMessage')"
filterable
allow-create
default-first-option
@ -149,6 +149,7 @@ import { ref, computed } from 'vue'
import type { Provider, BaseModel, Model } from '@/api/type/model'
import type { Dict, KeyValue } from '@/api/type/common'
import ModelApi from '@/api/model/model'
import ProviderApi from '@/api/model/provider'
import type { FormField } from '@/components/dynamics-form/type'
import DynamicsForm from '@/components/dynamics-form/index.vue'
import type { FormRules } from 'element-plus'
@ -173,18 +174,18 @@ const base_form_data_rule = ref<FormRules>({
name: {
required: true,
trigger: 'blur',
message: t('views.model.modelForm.form.templateName.requiredMessage')
message: t('views.model.modelForm.modeName.requiredMessage'),
},
model_type: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.form.model_type.requiredMessage')
message: t('views.model.modelForm.model_type.requiredMessage'),
},
model_name: {
required: true,
trigger: 'change',
message: t('views.model.modelForm.form.base_model.requiredMessage')
}
message: t('views.model.modelForm.base_model.requiredMessage'),
},
})
const base_form_data = ref<{
@ -203,15 +204,15 @@ const form_data = computed({
},
set: (event: any) => {
credential_form_data.value = event
}
},
})
const getModelForm = (model_name: string) => {
if (providerValue.value) {
ModelApi.getModelCreateForm(
ProviderApi.getModelCreateForm(
providerValue.value.provider,
form_data.value.model_type,
model_name
model_name,
).then((ok) => {
model_form_field.value = ok.data
if (modelValue.value) {
@ -226,18 +227,18 @@ const list_base_model = (model_type: any, change?: boolean) => {
base_form_data.value.model_name = ''
}
if (providerValue.value) {
ModelApi.listBaseModel(providerValue.value.provider, model_type, base_model_loading).then(
ProviderApi.listBaseModel(providerValue.value.provider, model_type, base_model_loading).then(
(ok) => {
base_model_list.value = ok.data
}
},
)
}
}
const open = (provider: Provider, model: Model) => {
modelValue.value = model
ModelApi.getModelById(model.id, formLoading).then((ok) => {
ModelApi.getModelById('default', model.id, formLoading).then((ok) => {
modelValue.value = ok.data
ModelApi.listModelType(model.provider, model_type_loading).then((ok) => {
ProviderApi.listModelType(model.provider, model_type_loading).then((ok) => {
model_type_list.value = ok.data
list_base_model(model.model_type)
})
@ -247,7 +248,7 @@ const open = (provider: Provider, model: Model) => {
name: model.name,
permission_type: model.permission_type,
model_type: model.model_type,
model_name: model.model_name
model_name: model.model_name,
}
form_data.value = model.credential
getModelForm(model.model_name)
@ -268,12 +269,13 @@ const submit = () => {
dynamicsFormRef.value?.validate().then(() => {
if (modelValue.value) {
ModelApi.updateModel(
'default',
modelValue.value.id,
{
...base_form_data.value,
credential: credential_form_data.value
credential: credential_form_data.value,
},
loading
loading,
).then((ok) => {
MsgSuccess(t('views.model.tip.updateSuccessMessage'))
close()

View File

@ -14,7 +14,7 @@
<span v-if="currentModel.status === 'PAUSE_DOWNLOAD'">
<el-tooltip
effect="dark"
:content="`${$t('views.model.modelForm.form.base_model.label')}: ${props.model.model_name} ${$t('views.model.tip.downloadError')}`"
:content="`${$t('views.model.modelForm.base_model.label')}: ${props.model.model_name} ${$t('views.model.tip.downloadError')}`"
placement="top"
>
<el-icon class="danger ml-4" size="18"><Warning /></el-icon>
@ -30,7 +30,7 @@
<ul>
<li class="flex">
<el-text type="info" class="color-secondary">{{
$t('views.model.modelForm.form.model_type.label')
$t('views.model.modelForm.model_type.label')
}}</el-text>
<span class="ellipsis ml-16">
{{ $t(modelType[model.model_type as keyof typeof modelType]) }}</span
@ -38,7 +38,7 @@
</li>
<li class="flex">
<el-text type="info" class="color-secondary">{{
$t('views.model.modelForm.form.base_model.label')
$t('views.model.modelForm.base_model.label')
}}</el-text>
<span class="ellipsis-1 ml-16" style="height: 20px; width: 70%">
{{ model.model_name }}</span
@ -163,7 +163,7 @@ const deleteModel = () => {
},
)
.then(() => {
ModelApi.deleteModel(props.model.id).then(() => {
ModelApi.deleteModel('default', props.model.id).then(() => {
emit('change')
})
})
@ -171,7 +171,7 @@ const deleteModel = () => {
}
const cancelDownload = () => {
ModelApi.pauseDownload(props.model.id).then(() => {
ModelApi.pauseDownload('default', props.model.id).then(() => {
downModel.value = undefined
emit('change')
})
@ -192,7 +192,7 @@ const icon = computed(() => {
const initInterval = () => {
interval = setInterval(() => {
if (currentModel.value.status === 'DOWNLOAD') {
ModelApi.getModelMetaById(props.model.id).then((ok) => {
ModelApi.getModelMetaById('default', props.model.id).then((ok) => {
downModel.value = ok.data
})
} else {

View File

@ -12,7 +12,11 @@
{{ $t('views.model.modelForm.title.addParam') }}
</el-button>
<el-table :data="modelParamsForm" class="mb-16">
<el-table-column prop="label" :label="$t('dynamicsForm.paramForm.name.label')" show-overflow-tooltip>
<el-table-column
prop="label"
:label="$t('dynamicsForm.paramForm.name.label')"
show-overflow-tooltip
>
<template #default="{ row }">
<span v-if="row.label && row.label.input_type === 'TooltipLabel'">{{
row.label.label
@ -20,7 +24,11 @@
<span v-else>{{ row.label }}</span>
</template>
</el-table-column>
<el-table-column prop="field" :label="$t('dynamicsForm.paramForm.field.label')" show-overflow-tooltip />
<el-table-column
prop="field"
:label="$t('dynamicsForm.paramForm.field.label')"
show-overflow-tooltip
/>
<el-table-column :label="$t('dynamicsForm.paramForm.input_type.label')" width="110px">
<template #default="{ row }">
<el-tag type="info" class="info-tag">{{
@ -92,7 +100,7 @@ const AddParamRef = ref()
const open = () => {
dialogVisible.value = true
loading.value = true
ModelApi.getModelParamsForm(props.model.id, loading)
ModelApi.getModelParamsForm('default', props.model.id, loading)
.then((ok) => {
loading.value = false
modelParamsForm.value = ok.data
@ -143,11 +151,13 @@ function refresh(data: any, index: any) {
}
function submit() {
ModelApi.updateModelParamsForm(props.model.id, modelParamsForm.value, loading).then((ok) => {
MsgSuccess(t('views.model.tip.saveSuccessMessage'))
close()
// emit('submit')
})
ModelApi.updateModelParamsForm('default', props.model.id, modelParamsForm.value, loading).then(
(ok) => {
MsgSuccess(t('views.model.tip.saveSuccessMessage'))
close()
// emit('submit')
},
)
}
defineExpose({ open, close })

View File

@ -1,3 +1,178 @@
<template>
111
<div class="provider-list">
<el-scrollbar>
<div class="p-8">
<div
class="all-mode flex cursor"
@click="clickListHandle(allObj as Provider)"
:class="!active?.provider ? 'all-mode-active color-primary-1' : ''"
>
<AppIcon
class="mr-8 color-primary"
style="height: 20px; width: 20px"
:iconName="'app-all-menu-active'"
></AppIcon>
<span>{{ $t('views.model.modelType.allModel') }}</span>
</div>
<el-collapse class="model-collapse" expand-icon-position="left">
<el-collapse-item
:title="$t('views.model.modelType.publicModel')"
name="1"
icon="CaretRight"
>
<template #title>
<div class="flex align-center">
<AppIcon iconName="app-folder" style="font-size: 20px"></AppIcon>
<span class="ml-8">
{{ $t('views.model.modelType.publicModel') }}
</span>
</div>
</template>
<common-list
:data="online_provider_list"
v-loading="loading"
@click="clickListHandle"
value-key="provider"
default-active=""
ref="commonList1"
>
<template #default="{ row }">
<div class="flex align-center">
<span
:innerHTML="row.icon"
alt=""
style="height: 20px; width: 20px"
class="mr-8"
/>
<span class="ellipsis-1" :title="row.name">{{ row.name }}</span>
</div>
</template>
</common-list>
</el-collapse-item>
<el-collapse-item
:title="$t('views.model.modelType.privateModel')"
name="2"
icon="CaretRight"
>
<template #title>
<div class="flex align-center">
<AppIcon iconName="app-folder" style="font-size: 20px"></AppIcon>
<span class="ml-8">
{{ $t('views.model.modelType.privateModel') }}
</span>
</div>
</template>
<common-list
:data="local_provider_list"
v-loading="loading"
@click="clickListHandle"
value-key="provider"
default-active=""
ref="commonList2"
>
<template #default="{ row }">
<div class="flex align-center">
<span
:innerHTML="row.icon"
alt=""
style="height: 20px; width: 20px"
class="mr-8"
/>
<span class="ellipsis-1" :title="row.name">{{ row.name }}</span>
</div>
</template>
</common-list>
</el-collapse-item>
</el-collapse>
</div>
</el-scrollbar>
</div>
</template>
<script lang="ts" setup>
import { watch, ref } from 'vue'
import type { Provider, Model } from '@/api/type/model'
import { modelTypeList, allObj } from '@/views/model/component/data'
const props = defineProps<{
data: Array<Provider>
loading: boolean
active: Provider
}>()
const emit = defineEmits(['click'])
const online_provider_list = ref<Array<Provider>>([])
const local_provider_list = ref<Array<Provider>>([])
watch(
() => props.data,
(list) => {
const local_provider = [
'model_ollama_provider',
'model_local_provider',
'model_xinference_provider',
'model_vllm_provider',
]
list
.filter((v) => v.provider)
?.forEach((item) => {
if (local_provider.indexOf(item.provider) > -1) {
local_provider_list.value.push(item)
} else {
online_provider_list.value.push(item)
}
})
online_provider_list.value.sort((a, b) => a.provider.localeCompare(b.provider))
local_provider_list.value.sort((a, b) => a.provider.localeCompare(b.provider))
},
{ immediate: true },
)
const clickListHandle = (item: Provider) => {
emit('click', item)
}
</script>
<style lang="scss" scoped>
.provider-list {
height: calc(var(--app-main-height));
.all-mode {
padding: 10px 8px;
font-weight: 400;
}
.all-mode-active {
border-radius: 4px;
color: var(--el-color-primary);
font-weight: 500 !important;
}
.model-collapse {
border-top: none !important;
border-bottom: none !important;
:deep(.el-collapse-item__header) {
border-bottom: none !important;
padding-left: 8px;
font-size: 14px;
font-weight: 400;
height: 40px;
background: none;
&:hover {
background: var(--app-text-color-light-1);
border-radius: 4px;
}
}
:deep(.el-collapse-item) {
margin-top: 2px;
}
:deep(.common-list) {
li {
padding-left: 50px !important;
}
}
:deep(.el-collapse-item__wrap) {
border-bottom: none !important;
background: none !important;
}
:deep(.el-collapse-item__content) {
padding-bottom: 0 !important;
}
}
}
</style>

View File

@ -47,7 +47,7 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import ModelApi from '@/api/model/model'
import ProviderApi from '@/api/model/provider'
import type { Provider } from '@/api/type/model'
import { modelTypeList } from './data'
import { t } from '@/locales'
@ -72,8 +72,8 @@ const close = () => {
const checkModelType = (model_type: string) => {
selectModelType.value = model_type
currentModelType.value = modelTypeOptions.filter((item) => item.value === model_type)[0].text
ModelApi.getProviderByModelType(model_type, loading).then((ok) => {
list_provider.value = ok
ProviderApi.getProviderByModelType(model_type, loading).then((ok) => {
list_provider.value = ok.data
list_provider.value.sort((a, b) => a.provider.localeCompare(b.provider))
})
}

View File

@ -9,3 +9,10 @@ export const modelTypeList = [
{ text: t(modelType['IMAGE']), value: 'IMAGE' },
{ text: t(modelType['TTI']), value: 'TTI' }
]
export const allObj = {
icon: '',
provider: '',
name: t('views.model.modelType.allModel'),
}

View File

@ -2,95 +2,12 @@
<LayoutContainer class="model-manage">
<template #left>
<h4 class="p-16 mb-8 pb-0">{{ $t('views.model.provider') }}</h4>
<div class="model-manage-height-left">
<el-scrollbar>
<div class="p-8">
<div
class="all-mode flex cursor"
@click="clickListHandle(allObj as Provider)"
:class="!active_provider?.provider ? 'all-mode-active color-primary-1' : ''"
>
<AppIcon
class="mr-8 color-primary"
style="height: 20px; width: 20px"
:iconName="'app-all-menu-active'"
></AppIcon>
<span>{{ $t('views.model.modelType.allModel') }}</span>
</div>
<el-collapse class="model-collapse" expand-icon-position="left">
<el-collapse-item
:title="$t('views.model.modelType.publicModel')"
name="1"
icon="CaretRight"
>
<template #title>
<div class="flex align-center">
<AppIcon iconName="app-folder" style="font-size: 20px"></AppIcon>
<span class="ml-8">
{{ $t('views.model.modelType.publicModel') }}
</span>
</div>
</template>
<common-list
:data="online_provider_list"
v-loading="loading"
@click="clickListHandle"
value-key="provider"
default-active=""
ref="commonList1"
>
<template #default="{ row }">
<div class="flex align-center">
<span
:innerHTML="row.icon"
alt=""
style="height: 20px; width: 20px"
class="mr-8"
/>
<span class="ellipsis-1" :title="row.name">{{ row.name }}</span>
</div>
</template>
</common-list>
</el-collapse-item>
<el-collapse-item
:title="$t('views.model.modelType.privateModel')"
name="2"
icon="CaretRight"
>
<template #title>
<div class="flex align-center">
<AppIcon iconName="app-folder" style="font-size: 20px"></AppIcon>
<span class="ml-8">
{{ $t('views.model.modelType.privateModel') }}
</span>
</div>
</template>
<common-list
:data="local_provider_list"
v-loading="loading"
@click="clickListHandle"
value-key="provider"
default-active=""
ref="commonList2"
>
<template #default="{ row }">
<div class="flex align-center">
<span
:innerHTML="row.icon"
alt=""
style="height: 20px; width: 20px"
class="mr-8"
/>
<span class="ellipsis-1" :title="row.name">{{ row.name }}</span>
</div>
</template>
</common-list>
</el-collapse-item>
</el-collapse>
</div>
</el-scrollbar>
</div>
<ProviderComponent
:data="provider_list"
@click="clickListHandle"
:loading="loading"
:active="active_provider"
/>
</template>
<ContentContainer :header="active_provider?.name" v-loading="list_model_loading">
<template #search>
@ -104,17 +21,11 @@
>
<el-option :label="$t('common.creator')" value="create_user" />
<el-option
:label="$t('views.model.modelForm.form.permissionType.label')"
:label="$t('views.model.modelForm.permissionType.label')"
value="permission_type"
/>
<el-option
:label="$t('views.model.modelForm.form.model_type.label')"
value="model_type"
/>
<el-option
:label="$t('views.model.modelForm.form.templateName.label')"
value="name"
/>
<el-option :label="$t('views.model.modelForm.model_type.label')" value="model_type" />
<el-option :label="$t('views.model.modelForm.modeName.label')" value="name" />
</el-select>
<el-input
v-if="search_type === 'name'"
@ -210,18 +121,13 @@ import ModelApi from '@/api/model/model'
import ProviderApi from '@/api/model/provider'
import type { Provider, Model } from '@/api/type/model'
import ModelCard from '@/views/model/component/ModelCard.vue'
import ProviderComponent from '@/views/model/component/Provider.vue'
import { splitArray } from '@/utils/common'
import { modelTypeList } from '@/views/model/component/data'
import { modelTypeList, allObj } from '@/views/model/component/data'
import CreateModelDialog from '@/views/model/component/CreateModelDialog.vue'
import SelectProviderDialog from '@/views/model/component/SelectProviderDialog.vue'
import { t } from '@/locales'
const allObj = {
icon: '',
provider: '',
name: t('views.model.modelType.allModel'),
}
const commonList1 = ref()
const commonList2 = ref()
const loading = ref<boolean>(false)
@ -242,8 +148,6 @@ const model_search_form = ref<{
const user_options = ref<any[]>([])
const list_model_loading = ref<boolean>(false)
const provider_list = ref<Array<Provider>>([])
const online_provider_list = ref<Array<Provider>>([])
const local_provider_list = ref<Array<Provider>>([])
const model_list = ref<Array<Model>>([])
@ -270,8 +174,6 @@ const clickListHandle = (item: Provider) => {
}
const openCreateModel = (provider?: Provider, model_type?: string) => {
console.log(provider)
console.log(model_type)
if (provider && provider.provider) {
createModelRef.value?.open(provider, model_type)
} else {
@ -301,21 +203,6 @@ onMounted(() => {
active_provider.value = allObj
provider_list.value = [allObj, ...ok.data]
const local_provider = [
'model_ollama_provider',
'model_local_provider',
'model_xinference_provider',
'model_vllm_provider',
]
ok.data.forEach((item) => {
if (local_provider.indexOf(item.provider) > -1) {
local_provider_list.value.push(item)
} else {
online_provider_list.value.push(item)
}
})
online_provider_list.value.sort((a, b) => a.provider.localeCompare(b.provider))
local_provider_list.value.sort((a, b) => a.provider.localeCompare(b.provider))
list_model()
})
})
@ -326,49 +213,5 @@ onMounted(() => {
.model-list-height {
height: calc(var(--app-main-height));
}
.model-manage-height-left {
height: calc(var(--app-main-height));
}
.all-mode {
padding: 10px 8px;
font-weight: 400;
}
.all-mode-active {
border-radius: 4px;
color: var(--el-color-primary);
font-weight: 500 !important;
}
.model-collapse {
border-top: none !important;
border-bottom: none !important;
:deep(.el-collapse-item__header) {
border-bottom: none !important;
padding-left: 8px;
font-size: 14px;
font-weight: 400;
height: 40px;
background: none;
&:hover {
background: var(--app-text-color-light-1);
border-radius: 4px;
}
}
:deep(.el-collapse-item) {
margin-top: 2px;
}
:deep(.common-list) {
li {
padding-left: 50px !important;
}
}
:deep(.el-collapse-item__wrap) {
border-bottom: none !important;
background: none !important;
}
:deep(.el-collapse-item__content) {
padding-bottom: 0 !important;
}
}
}
</style>