Skip to content

Commit 71ba00c

Browse files
committed
feat: Base node parameter
1 parent b523f7b commit 71ba00c

14 files changed

Lines changed: 633 additions & 14 deletions

File tree

ui/src/components/ai-chat/index.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,21 @@ import { t } from '@/locales'
185185
import bus from '@/bus'
186186
import { throttle } from 'lodash-es'
187187
import { copyClick } from '@/utils/clipboard'
188+
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
189+
188190
provide('upload', (file: any, loading?: Ref<boolean>) => {
189191
return props.type === 'debug-ai-chat'
190192
? applicationApi.postUploadFile(file, 'TEMPORARY_120_MINUTE', 'TEMPORARY_120_MINUTE', loading)
191193
: chatAPI.postUploadFile(file, chartOpenId.value, 'CHAT', loading)
192194
})
195+
provide('getSelectModelList', (params: any) => {
196+
if (route.path.includes('resource-management')) {
197+
return loadSharedApi({ type: 'model', systemType: 'systemManage' }).getSelectModelList(params)
198+
} else {
199+
return loadSharedApi({ type: 'model', systemType: 'workspace' }).getSelectModelList(params)
200+
}
201+
})
202+
193203
const transcribing = ref<boolean>(false)
194204
defineOptions({ name: 'AiChat' })
195205
const route = useRoute()

ui/src/components/dynamics-form/constructor/data.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,10 @@ const input_type_list = [
5454
label: t('dynamicsForm.input_type_list.UploadInput'),
5555
value: 'UploadInput',
5656
},
57+
58+
{
59+
label: t('dynamicsForm.input_type_list.Model'),
60+
value: 'Model',
61+
},
5762
]
5863
export { input_type_list }
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
<template>
2+
<el-form-item
3+
:label="$t('views.model.modelForm.model_type.label')"
4+
required
5+
prop="model_type"
6+
:rules="[{ required: true, message: $t('views.model.modelForm.model_type.requiredMessage') }]"
7+
>
8+
<el-select
9+
v-model="formValue.model_type"
10+
:placeholder="$t('views.model.modelForm.model_type.placeholder')"
11+
@change="handleModelTypeChange"
12+
>
13+
<el-option
14+
v-for="item in modelTypeList"
15+
:key="item.value"
16+
:label="item.text"
17+
:value="item.value"
18+
/>
19+
</el-select>
20+
</el-form-item>
21+
22+
<el-form-item
23+
:label="$t('views.model.modelForm.model_type.kexuan', '可选模型')"
24+
required
25+
prop="provider_list"
26+
:rules="[
27+
{
28+
required: true,
29+
message: $t('views.model.modelForm.model_type.requiredMessage'),
30+
type: 'array',
31+
},
32+
]"
33+
>
34+
<div class="flex-between w-full">
35+
<ModelSelect
36+
multiple
37+
v-model="selectedIds"
38+
:placeholder="$t('views.application.form.voicePlay.placeholder')"
39+
:options="groupedModelOptions"
40+
@change="handleProviderListChange"
41+
:model-type="formValue.model_type"
42+
>
43+
<template #tag>
44+
<el-tag
45+
v-for="provider in formValue.provider_list"
46+
:key="provider.model_id"
47+
closable
48+
type="info"
49+
@close="removeSelectedModel(provider.model_id)"
50+
style="margin-right: 4px"
51+
>
52+
<div class="flex align-center">
53+
<span
54+
v-html="
55+
relatedObject(
56+
providerOptions,
57+
getModelInfo(provider.model_id)?.provider,
58+
'provider',
59+
)?.icon
60+
"
61+
class="model-icon mr-4"
62+
></span>
63+
<span class="mr-4">{{
64+
relatedObject(
65+
providerOptions,
66+
getModelInfo(provider.model_id)?.provider,
67+
'provider',
68+
)?.name
69+
}}</span>
70+
<span class="mr-4"> > </span>
71+
<span>{{ getModelInfo(provider.model_id)?.name }}</span>
72+
</div>
73+
</el-tag>
74+
</template>
75+
</ModelSelect>
76+
</div>
77+
</el-form-item>
78+
<el-form-item
79+
:label="$t('views.model.modelForm.model_type.moren', '默认模型')"
80+
required
81+
:rules="[
82+
{
83+
required: true,
84+
message: $t('views.model.modelForm.model_type.requiredMessage'),
85+
},
86+
]"
87+
v-if="formValue.provider_list && formValue.provider_list.length > 0"
88+
>
89+
<div class="flex-between w-full">
90+
<el-select
91+
v-model="formValue.default_value"
92+
value-key="model_id"
93+
placeholder="请选择默认模型"
94+
>
95+
<el-option-group
96+
v-for="(modelList, providerName) in selectedModelsOptions"
97+
:key="providerName"
98+
:label="relatedObject(providerOptions, providerName, 'provider')?.name"
99+
>
100+
<el-option
101+
v-for="item in modelList"
102+
:key="item.id"
103+
:label="item.name"
104+
:value="getProviderItem(item.id)"
105+
>
106+
<div class="flex">
107+
<span
108+
v-html="relatedObject(providerOptions, providerName, 'provider')?.icon"
109+
class="model-icon mr-8"
110+
></span>
111+
<span>{{ item.name }}</span>
112+
</div>
113+
</el-option>
114+
</el-option-group>
115+
</el-select>
116+
<div class="ml-8">
117+
<el-button @click="openParamSetting" @refreshForm="handleParamRefresh">
118+
<el-icon>
119+
<Operation />
120+
</el-icon>
121+
</el-button>
122+
</div>
123+
</div>
124+
</el-form-item>
125+
<AIModeParamSettingDialog ref="AIModeParamSettingDialogRef" @refresh="handleParamRefresh" />
126+
</template>
127+
<script setup lang="ts">
128+
import { computed, onMounted, inject, ref } from 'vue'
129+
import { modelTypeList } from '@/views/model/component/data'
130+
import AIModeParamSettingDialog from '@/views/application/component/AIModeParamSettingDialog.vue'
131+
import { groupBy } from 'lodash'
132+
import { providerList as providerOptions } from '../../items/model/provider-data'
133+
import { relatedObject } from '@/utils/array'
134+
135+
const getSelectModelList = inject('getSelectModelList') as Function
136+
const getModelParamsForm = inject('getModelParamsForm') as Function
137+
138+
const props = defineProps<{
139+
modelValue: any
140+
}>()
141+
142+
const emit = defineEmits(['update:modelValue'])
143+
144+
const formValue = computed({
145+
set: (item: any) => {
146+
emit('update:modelValue', item)
147+
},
148+
get: () => {
149+
return props.modelValue
150+
},
151+
})
152+
153+
const selectedIds = computed({
154+
get: () => (formValue.value.provider_list || []).map((p: any) => p.model_id),
155+
set: (newIds: string[]) => {
156+
const oldList = formValue.value.provider_list || []
157+
const newList = newIds.map((id: string) => {
158+
const existing = oldList.find((p: any) => p.model_id === id)
159+
return existing || { model_id: id, model_params_setting: {} }
160+
})
161+
formValue.value.provider_list = newList
162+
// find new model then get it default value
163+
const oldIds = oldList.map((p: any) => p.model_id)
164+
const addedIds = newIds.filter((id: string) => !oldIds.includes(id))
165+
addedIds.forEach((id: string) => {
166+
fetchDefaultParams(id)
167+
})
168+
},
169+
})
170+
171+
const selectedModelsOptions = computed(() => {
172+
const ids = (formValue.value.provider_list || []).map((p: any) => p.model_id)
173+
const filtered = rawModelOptions.value.filter((m: any) => ids.includes(m.id))
174+
return groupBy(filtered, 'provider')
175+
})
176+
177+
function fetchDefaultParams(modelId: string) {
178+
if (!getModelParamsForm) return
179+
getModelParamsForm(modelId).then((res: any) => {
180+
const formFields = res?.data || []
181+
const defaults = (res?.data || [])
182+
.map((item: any) => {
183+
if (item.show_default_value === false) {
184+
return { [item.field]: undefined }
185+
} else {
186+
return { [item.field]: item.default_value }
187+
}
188+
})
189+
.reduce((x: any, y: any) => ({ ...x, ...y }), {})
190+
// update to model_params_setting
191+
const target = formValue.value.provider_list.find((p: any) => p.model_id === modelId)
192+
if (target) {
193+
target.model_params_setting = defaults
194+
target.model_form_field = formFields
195+
}
196+
})
197+
}
198+
const AIModeParamSettingDialogRef = ref<InstanceType<typeof AIModeParamSettingDialog>>()
199+
200+
const openParamSetting = () => {
201+
const dv = formValue.value.default_value
202+
if (!dv?.model_id) return
203+
AIModeParamSettingDialogRef.value?.open(dv.model_id, undefined, dv?.model_params_setting)
204+
}
205+
206+
const handleParamRefresh = (paramData: any) => {
207+
const dv = formValue.value.default_value
208+
if (dv?.model_id) {
209+
formValue.value.default_value = { ...dv, model_params_setting: paramData }
210+
const target = formValue.value.provider_list.find((p: any) => p.model_id === dv.model_id)
211+
if (target) {
212+
target.model_params_setting = paramData
213+
}
214+
}
215+
}
216+
217+
const rawModelOptions = ref<any[]>([])
218+
const groupedModelOptions = ref<Record<string, any[]>>({})
219+
220+
const fetchModelByType = (type: string) => {
221+
if (!type || !getSelectModelList) return
222+
223+
getSelectModelList({ model_type: type }).then((res: any) => {
224+
rawModelOptions.value = res?.data || []
225+
226+
groupedModelOptions.value = groupBy(res?.data, 'provider')
227+
})
228+
}
229+
230+
const handleModelTypeChange = (val: string) => {
231+
formValue.value.provider_list = []
232+
formValue.value.default_value = ''
233+
234+
if (val) {
235+
fetchModelByType(val)
236+
} else {
237+
rawModelOptions.value = []
238+
groupedModelOptions.value = {}
239+
}
240+
}
241+
242+
const getModelInfo = (modelId: string) => {
243+
return rawModelOptions.value.find((item: any) => item.id === modelId)
244+
}
245+
246+
// default_value 赋值
247+
const getProviderItem = (modelId: string) => {
248+
const found = formValue.value.provider_list.find((p: any) => p.model_id === modelId)
249+
if (found) {
250+
const { model_form_field, ...rest } = found
251+
return rest
252+
}
253+
return { model_id: modelId, model_params_setting: {} }
254+
}
255+
256+
function handleProviderListChange() {
257+
const ids = (formValue.value.provider_list || []).map((p: any) => p.model_id)
258+
const currentId = formValue.value.default_value?.model_id
259+
260+
if (currentId && !ids.includes(currentId)) {
261+
formValue.value.default_value = {}
262+
}
263+
}
264+
265+
function removeSelectedModel(modelId: string) {
266+
formValue.value.provider_list = formValue.value.provider_list.filter(
267+
(p: any) => p.model_id !== modelId,
268+
)
269+
handleProviderListChange()
270+
}
271+
272+
const getData = () => {
273+
const providerList = (formValue.value.provider_list || []).map((p: any) => {
274+
const modelInfo = getModelInfo(p.model_id)
275+
return {
276+
model_id: p.model_id,
277+
model_name: modelInfo?.name || '',
278+
provider: modelInfo?.provider || '',
279+
model_params_setting: p.model_params_setting || {},
280+
model_form_field: p.model_form_field || [],
281+
}
282+
})
283+
return {
284+
input_type: 'Model',
285+
model_type: formValue.value.model_type,
286+
default_value: formValue.value.default_value,
287+
attrs: {
288+
provider_list: providerList,
289+
},
290+
}
291+
}
292+
293+
const rander = (form_data: any) => {
294+
formValue.value.model_type = form_data.model_type
295+
formValue.value.provider_list = form_data.attrs?.provider_list || []
296+
formValue.value.default_value = form_data.default_value || ''
297+
298+
if (form_data.model_type) {
299+
fetchModelByType(form_data.model_type)
300+
}
301+
}
302+
303+
defineExpose({ getData, rander })
304+
</script>
305+
<style lang="scss" scoped>
306+
// AI模型选择:添加模型hover样式
307+
308+
.model-icon {
309+
width: 18px;
310+
}
311+
</style>

ui/src/components/dynamics-form/index.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ const render = (
215215
| (() => Promise<Result<Array<FormField>>>),
216216
data?: Dict<any>,
217217
) => {
218+
console.log(data, '-----')
218219
formFieldList.value = []
219220
nextTick(() => {
220221
if (typeof render_data == 'string') {
@@ -246,6 +247,7 @@ const render = (
246247
}
247248
const getFormDefaultValue = (fieldList: Array<any>, form_data?: any) => {
248249
form_data = form_data ? form_data : {}
250+
console.log(form_data)
249251
const value = fieldList
250252
.map((item) => {
251253
if (form_data[item.field] !== undefined) {
@@ -274,6 +276,7 @@ const getFormDefaultValue = (fieldList: Array<any>, form_data?: any) => {
274276
return {}
275277
})
276278
.reduce((x, y) => ({ ...x, ...y }), {})
279+
console.log(value)
277280
return value
278281
}
279282
/**

0 commit comments

Comments
 (0)