feat: workflow application debug chat (#3245)
This commit is contained in:
parent
c7e30bb098
commit
bf630b9d07
@ -82,7 +82,7 @@ class WorkFlowPostHandler:
|
|||||||
index=0)
|
index=0)
|
||||||
|
|
||||||
self.chat_info.append_chat_record(chat_record)
|
self.chat_info.append_chat_record(chat_record)
|
||||||
self.chat_info.set_cahce()
|
self.chat_info.set_cache()
|
||||||
if [ChatUserType.ANONYMOUS_USER.value, ChatUserType.CHAT_USER.value].__contains__(
|
if [ChatUserType.ANONYMOUS_USER.value, ChatUserType.CHAT_USER.value].__contains__(
|
||||||
workflow_body.get('chat_user_type')):
|
workflow_body.get('chat_user_type')):
|
||||||
application_public_access_client = (QuerySet(ApplicationChatUserStats)
|
application_public_access_client = (QuerySet(ApplicationChatUserStats)
|
||||||
|
|||||||
@ -219,12 +219,17 @@ class ChatSerializers(serializers.Serializer):
|
|||||||
other_list = instance.get('other_list')
|
other_list = instance.get('other_list')
|
||||||
workspace_id = chat_info.application.workspace_id
|
workspace_id = chat_info.application.workspace_id
|
||||||
chat_record_id = instance.get('chat_record_id')
|
chat_record_id = instance.get('chat_record_id')
|
||||||
|
debug = self.data.get('debug', False)
|
||||||
chat_record = None
|
chat_record = None
|
||||||
history_chat_record = chat_info.chat_record_list
|
history_chat_record = chat_info.chat_record_list
|
||||||
if chat_record_id is not None:
|
if chat_record_id is not None:
|
||||||
chat_record = self.get_chat_record(chat_info, chat_record_id)
|
chat_record = self.get_chat_record(chat_info, chat_record_id)
|
||||||
history_chat_record = [r for r in chat_info.chat_record_list if str(r.id) != chat_record_id]
|
history_chat_record = [r for r in chat_info.chat_record_list if str(r.id) != chat_record_id]
|
||||||
work_flow_manage = WorkflowManage(Flow.new_instance(chat_info.work_flow_version.work_flow),
|
if not debug:
|
||||||
|
work_flow = chat_info.work_flow_version.work_flow
|
||||||
|
else:
|
||||||
|
work_flow = chat_info.application.work_flow
|
||||||
|
work_flow_manage = WorkflowManage(Flow.new_instance(work_flow),
|
||||||
{'history_chat_record': history_chat_record, 'question': message,
|
{'history_chat_record': history_chat_record, 'question': message,
|
||||||
'chat_id': chat_info.chat_id, 'chat_record_id': str(
|
'chat_id': chat_info.chat_id, 'chat_record_id': str(
|
||||||
uuid.uuid1()) if chat_record is None else chat_record.id,
|
uuid.uuid1()) if chat_record is None else chat_record.id,
|
||||||
@ -233,7 +238,7 @@ class ChatSerializers(serializers.Serializer):
|
|||||||
'chat_user_id': chat_user_id,
|
'chat_user_id': chat_user_id,
|
||||||
'chat_user_type': chat_user_type,
|
'chat_user_type': chat_user_type,
|
||||||
'workspace_id': workspace_id,
|
'workspace_id': workspace_id,
|
||||||
'debug': self.data.get('debug', False)},
|
'debug': debug},
|
||||||
WorkFlowPostHandler(chat_info),
|
WorkFlowPostHandler(chat_info),
|
||||||
base_to_response, form_data, image_list, document_list, audio_list,
|
base_to_response, form_data, image_list, document_list, audio_list,
|
||||||
other_list,
|
other_list,
|
||||||
@ -339,12 +344,14 @@ class OpenChatSerializers(serializers.Serializer):
|
|||||||
chat_user_type = self.data.get("chat_user_type")
|
chat_user_type = self.data.get("chat_user_type")
|
||||||
debug = self.data.get("debug")
|
debug = self.data.get("debug")
|
||||||
chat_id = str(uuid.uuid7())
|
chat_id = str(uuid.uuid7())
|
||||||
work_flow_version = QuerySet(WorkFlowVersion).filter(application_id=application_id).order_by(
|
work_flow_version = None
|
||||||
'-create_time')[0:1].first()
|
if not debug:
|
||||||
if work_flow_version is None:
|
work_flow_version = QuerySet(WorkFlowVersion).filter(application_id=application_id).order_by(
|
||||||
raise AppApiException(500,
|
'-create_time')[0:1].first()
|
||||||
gettext(
|
if work_flow_version is None:
|
||||||
"The application has not been published. Please use it after publishing."))
|
raise AppApiException(500,
|
||||||
|
gettext(
|
||||||
|
"The application has not been published. Please use it after publishing."))
|
||||||
ChatInfo(chat_id, chat_user_id, chat_user_type, [],
|
ChatInfo(chat_id, chat_user_id, chat_user_type, [],
|
||||||
[],
|
[],
|
||||||
application_id,
|
application_id,
|
||||||
|
|||||||
@ -17,8 +17,8 @@
|
|||||||
"@codemirror/lang-json": "^6.0.1",
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@codemirror/lang-python": "^6.2.1",
|
"@codemirror/lang-python": "^6.2.1",
|
||||||
"@codemirror/theme-one-dark": "^6.1.2",
|
"@codemirror/theme-one-dark": "^6.1.2",
|
||||||
"@logicflow/core": "^2.0.15",
|
"@logicflow/core": "^1.2.27",
|
||||||
"@logicflow/extension": "^2.0.20",
|
"@logicflow/extension": "^1.2.27",
|
||||||
"@vavt/cm-extension": "^1.9.1",
|
"@vavt/cm-extension": "^1.9.1",
|
||||||
"@vueuse/core": "^13.3.0",
|
"@vueuse/core": "^13.3.0",
|
||||||
"@wecom/jssdk": "^2.3.1",
|
"@wecom/jssdk": "^2.3.1",
|
||||||
|
|||||||
@ -22,60 +22,55 @@ const getModel: (
|
|||||||
return get(`${prefix}/model`, data, loading)
|
return get(`${prefix}/model`, data, loading)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 获取当前用户可使用的模型列表
|
* 获取工作空间下重排模型列表
|
||||||
* @param application_id
|
* @param loading 加载器
|
||||||
* @param loading
|
* @returns 重排模型列表
|
||||||
* @query { query_text: string, top_number: number, similarity: number }
|
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
const getApplicationRerankerModel: (
|
const getRerankerModel: (loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (loading) => {
|
||||||
application_id: string,
|
|
||||||
loading?: Ref<boolean>,
|
|
||||||
) => Promise<Result<Array<any>>> = (application_id, loading) => {
|
|
||||||
return get(`${prefix}/model`, { model_type: 'RERANKER' }, loading)
|
return get(`${prefix}/model`, { model_type: 'RERANKER' }, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前用户可使用的模型列表
|
* 获取语音转文本模型列表
|
||||||
* @param application_id
|
|
||||||
* @param loading
|
* @param loading
|
||||||
* @query { query_text: string, top_number: number, similarity: number }
|
* @returns 语音转文本模型列表
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
const getApplicationSTTModel: (
|
const getSTTModel: (loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (loading) => {
|
||||||
application_id: string,
|
|
||||||
loading?: Ref<boolean>,
|
|
||||||
) => Promise<Result<Array<any>>> = (application_id, loading) => {
|
|
||||||
return get(`${prefix}/model`, { model_type: 'STT' }, loading)
|
return get(`${prefix}/model`, { model_type: 'STT' }, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前用户可使用的模型列表
|
* 获取文本转语音模型列表
|
||||||
* @param application_id
|
|
||||||
* @param loading
|
* @param loading
|
||||||
* @query { query_text: string, top_number: number, similarity: number }
|
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const getApplicationTTSModel: (
|
const getTTSModel: (loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (loading) => {
|
||||||
application_id: string,
|
|
||||||
loading?: Ref<boolean>,
|
|
||||||
) => Promise<Result<Array<any>>> = (application_id, loading) => {
|
|
||||||
return get(`${prefix}/model`, { model_type: 'TTS' }, loading)
|
return get(`${prefix}/model`, { model_type: 'TTS' }, loading)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
const getApplicationImageModel: (
|
* 获取图片理解模型列表
|
||||||
application_id: string,
|
* @param loading
|
||||||
loading?: Ref<boolean>,
|
* @returns 图片理解模型列表
|
||||||
) => Promise<Result<Array<any>>> = (application_id, loading) => {
|
*/
|
||||||
|
const getImageModel: (loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (loading) => {
|
||||||
return get(`${prefix}/model`, { model_type: 'IMAGE' }, loading)
|
return get(`${prefix}/model`, { model_type: 'IMAGE' }, loading)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
const getApplicationTTIModel: (
|
* 获取图片生成模型列表
|
||||||
application_id: string,
|
* @param loading
|
||||||
loading?: Ref<boolean>,
|
* @returns 图片生成模型列表
|
||||||
) => Promise<Result<Array<any>>> = (application_id, loading) => {
|
*/
|
||||||
|
const getTTIModel: (loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (loading) => {
|
||||||
return get(`${prefix}/model`, { model_type: 'TTI' }, loading)
|
return get(`${prefix}/model`, { model_type: 'TTI' }, loading)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取大语言模型列表
|
||||||
|
* @param loading
|
||||||
|
* @returns 大语言模型列表
|
||||||
|
*/
|
||||||
|
const getLLMModel: (loading?: Ref<boolean>) => Promise<Result<Array<any>>> = (loading) => {
|
||||||
|
return get(`${prefix}/model`, { model_type: 'LLM' }, loading)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 获取模型参数表单
|
* 获取模型参数表单
|
||||||
* @param model_id 模型id
|
* @param model_id 模型id
|
||||||
@ -182,9 +177,10 @@ export default {
|
|||||||
pauseDownload,
|
pauseDownload,
|
||||||
getModelParamsForm,
|
getModelParamsForm,
|
||||||
updateModelParamsForm,
|
updateModelParamsForm,
|
||||||
getApplicationRerankerModel,
|
getRerankerModel,
|
||||||
getApplicationSTTModel,
|
getSTTModel,
|
||||||
getApplicationTTSModel,
|
getTTSModel,
|
||||||
getApplicationImageModel,
|
getImageModel,
|
||||||
getApplicationTTIModel,
|
getTTIModel,
|
||||||
|
getLLMModel,
|
||||||
}
|
}
|
||||||
|
|||||||
31
ui/src/directives/resize.ts
Normal file
31
ui/src/directives/resize.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
export default {
|
||||||
|
install: (app: App) => {
|
||||||
|
app.directive('resize', {
|
||||||
|
created(el: any, binding: any) {
|
||||||
|
// 记录长宽
|
||||||
|
let width = ''
|
||||||
|
let height = ''
|
||||||
|
function getSize() {
|
||||||
|
const style = (document.defaultView as any).getComputedStyle(el)
|
||||||
|
// 如果当前长宽和历史长宽不同
|
||||||
|
if (width !== style.width || height !== style.height) {
|
||||||
|
// binding.value在这里就是下面的resizeChart函数
|
||||||
|
|
||||||
|
binding.value({
|
||||||
|
width: parseFloat(style.width),
|
||||||
|
height: parseFloat(style.height)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
width = style.width
|
||||||
|
height = style.height
|
||||||
|
}
|
||||||
|
|
||||||
|
;(el as any).__vueDomResize__ = setInterval(getSize, 500)
|
||||||
|
},
|
||||||
|
unmounted(el: any, binding: any) {
|
||||||
|
clearInterval((el as any).__vueDomResize__)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -673,7 +673,7 @@ function getKnowledge() {
|
|||||||
function getModel() {
|
function getModel() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
modelAPI
|
modelAPI
|
||||||
.getModel({})
|
.getLLMModel()
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
modelOptions.value = groupBy(res?.data, 'provider')
|
modelOptions.value = groupBy(res?.data, 'provider')
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@ -686,7 +686,7 @@ function getModel() {
|
|||||||
function getSTTModel() {
|
function getSTTModel() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
modelAPI
|
modelAPI
|
||||||
.getApplicationSTTModel(id)
|
.getSTTModel()
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
sttModelOptions.value = groupBy(res?.data, 'provider')
|
sttModelOptions.value = groupBy(res?.data, 'provider')
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@ -699,7 +699,7 @@ function getSTTModel() {
|
|||||||
function getTTSModel() {
|
function getTTSModel() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
modelAPI
|
modelAPI
|
||||||
.getApplicationTTSModel(id)
|
.getTTSModel()
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
ttsModelOptions.value = groupBy(res?.data, 'provider')
|
ttsModelOptions.value = groupBy(res?.data, 'provider')
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|||||||
@ -144,8 +144,8 @@
|
|||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: $t('common.inputPlaceholder'),
|
message: $t('common.inputPlaceholder'),
|
||||||
trigger: 'blur'
|
trigger: 'blur',
|
||||||
}
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<el-input v-model="form.title" @blur="form.title = form.title.trim()" />
|
<el-input v-model="form.title" @blur="form.title = form.title.trim()" />
|
||||||
@ -176,7 +176,7 @@ import { MsgError, MsgConfirm } from '@/utils/message'
|
|||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
const {
|
const {
|
||||||
params: { id }
|
params: { id },
|
||||||
} = app.config.globalProperties.$route as any
|
} = app.config.globalProperties.$route as any
|
||||||
|
|
||||||
const height = ref<{
|
const height = ref<{
|
||||||
@ -186,14 +186,14 @@ const height = ref<{
|
|||||||
}>({
|
}>({
|
||||||
stepContainerHeight: 0,
|
stepContainerHeight: 0,
|
||||||
inputContainerHeight: 0,
|
inputContainerHeight: 0,
|
||||||
outputContainerHeight: 0
|
outputContainerHeight: 0,
|
||||||
})
|
})
|
||||||
const showAnchor = ref<boolean>(false)
|
const showAnchor = ref<boolean>(false)
|
||||||
const anchorData = ref<any>()
|
const anchorData = ref<any>()
|
||||||
const titleFormRef = ref()
|
const titleFormRef = ref()
|
||||||
const nodeNameDialogVisible = ref<boolean>(false)
|
const nodeNameDialogVisible = ref<boolean>(false)
|
||||||
const form = ref<any>({
|
const form = ref<any>({
|
||||||
title: ''
|
title: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const condition = computed({
|
const condition = computed({
|
||||||
@ -206,7 +206,7 @@ const condition = computed({
|
|||||||
}
|
}
|
||||||
set(props.nodeModel.properties, 'condition', 'AND')
|
set(props.nodeModel.properties, 'condition', 'AND')
|
||||||
return true
|
return true
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const showNode = computed({
|
const showNode = computed({
|
||||||
set: (v) => {
|
set: (v) => {
|
||||||
@ -218,7 +218,7 @@ const showNode = computed({
|
|||||||
}
|
}
|
||||||
set(props.nodeModel.properties, 'showNode', true)
|
set(props.nodeModel.properties, 'showNode', true)
|
||||||
return true
|
return true
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleWheel = (event: any) => {
|
const handleWheel = (event: any) => {
|
||||||
@ -244,7 +244,7 @@ const editName = async (formEl: FormInstance | undefined) => {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
if (
|
if (
|
||||||
!props.nodeModel.graphModel.nodes?.some(
|
!props.nodeModel.graphModel.nodes?.some(
|
||||||
(node: any) => node.properties.stepName === form.value.title
|
(node: any) => node.properties.stepName === form.value.title,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
set(props.nodeModel.properties, 'stepName', form.value.title)
|
set(props.nodeModel.properties, 'stepName', form.value.title)
|
||||||
@ -274,7 +274,7 @@ const copyNode = () => {
|
|||||||
const deleteNode = () => {
|
const deleteNode = () => {
|
||||||
MsgConfirm(t('common.tip'), t('views.applicationWorkflow.delete.confirmTitle'), {
|
MsgConfirm(t('common.tip'), t('views.applicationWorkflow.delete.confirmTitle'), {
|
||||||
confirmButtonText: t('common.confirm'),
|
confirmButtonText: t('common.confirm'),
|
||||||
confirmButtonClass: 'danger'
|
confirmButtonClass: 'danger',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
props.nodeModel.graphModel.deleteNode(props.nodeModel.id)
|
props.nodeModel.graphModel.deleteNode(props.nodeModel.id)
|
||||||
})
|
})
|
||||||
@ -295,13 +295,13 @@ function clickNodes(item: any) {
|
|||||||
type: item.type,
|
type: item.type,
|
||||||
properties: item.properties,
|
properties: item.properties,
|
||||||
x: anchorData.value?.x + width / 2 + 200,
|
x: anchorData.value?.x + width / 2 + 200,
|
||||||
y: anchorData.value?.y - item.height
|
y: anchorData.value?.y - item.height,
|
||||||
})
|
})
|
||||||
props.nodeModel.graphModel.addEdge({
|
props.nodeModel.graphModel.addEdge({
|
||||||
type: 'app-edge',
|
type: 'app-edge',
|
||||||
sourceNodeId: props.nodeModel.id,
|
sourceNodeId: props.nodeModel.id,
|
||||||
sourceAnchorId: anchorData.value?.id,
|
sourceAnchorId: anchorData.value?.id,
|
||||||
targetNodeId: nodeModel.id
|
targetNodeId: nodeModel.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
closeNodeMenu()
|
closeNodeMenu()
|
||||||
@ -317,7 +317,7 @@ const nodeFields = computed(() => {
|
|||||||
label: field.label,
|
label: field.label,
|
||||||
value: field.value,
|
value: field.value,
|
||||||
globeLabel: `{{${props.nodeModel.properties.stepName}.${field.value}}}`,
|
globeLabel: `{{${props.nodeModel.properties.stepName}.${field.value}}}`,
|
||||||
globeValue: `{{context['${props.nodeModel.id}'].${field.value}}}`
|
globeValue: `{{context['${props.nodeModel.id}'].${field.value}}}`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return fields
|
return fields
|
||||||
@ -364,4 +364,9 @@ onMounted(() => {
|
|||||||
:deep(.el-card) {
|
:deep(.el-card) {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
.app-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0px 2px 4px 0px rgba(31, 35, 41, 0.12);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import AppEdge from './common/edge'
|
|||||||
import Control from './common/NodeControl.vue'
|
import Control from './common/NodeControl.vue'
|
||||||
import { baseNodes } from '@/workflow/common/data'
|
import { baseNodes } from '@/workflow/common/data'
|
||||||
import '@logicflow/extension/lib/style/index.css'
|
import '@logicflow/extension/lib/style/index.css'
|
||||||
import '@logicflow/core/dist/index.css'
|
import '@logicflow/core/dist/style/index.css'
|
||||||
import { initDefaultShortcut } from '@/workflow/common/shortcut'
|
import { initDefaultShortcut } from '@/workflow/common/shortcut'
|
||||||
import Dagre from '@/workflow/plugins/dagre'
|
import Dagre from '@/workflow/plugins/dagre'
|
||||||
import { getTeleport } from '@/workflow/common/teleport'
|
import { getTeleport } from '@/workflow/common/teleport'
|
||||||
@ -32,11 +32,11 @@ type ShapeItem = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: Object || null
|
data: Object || null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const defaultData = {
|
const defaultData = {
|
||||||
nodes: [...baseNodes]
|
nodes: [...baseNodes],
|
||||||
}
|
}
|
||||||
const graphData = computed({
|
const graphData = computed({
|
||||||
get: () => {
|
get: () => {
|
||||||
@ -48,7 +48,7 @@ const graphData = computed({
|
|||||||
},
|
},
|
||||||
set: (value) => {
|
set: (value) => {
|
||||||
return value
|
return value
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const lf = ref()
|
const lf = ref()
|
||||||
@ -67,27 +67,27 @@ const renderGraphData = (data?: any) => {
|
|||||||
adjustEdge: false,
|
adjustEdge: false,
|
||||||
adjustEdgeStartAndEnd: false,
|
adjustEdgeStartAndEnd: false,
|
||||||
background: {
|
background: {
|
||||||
backgroundColor: '#f5f6f7'
|
backgroundColor: '#f5f6f7',
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
size: 10,
|
size: 10,
|
||||||
type: 'dot',
|
type: 'dot',
|
||||||
config: {
|
config: {
|
||||||
color: '#DEE0E3',
|
color: '#DEE0E3',
|
||||||
thickness: 1
|
thickness: 1,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
keyboard: {
|
keyboard: {
|
||||||
enabled: true
|
enabled: true,
|
||||||
},
|
},
|
||||||
isSilentMode: false,
|
isSilentMode: false,
|
||||||
container: container
|
container: container,
|
||||||
})
|
})
|
||||||
lf.value.setTheme({
|
lf.value.setTheme({
|
||||||
bezier: {
|
bezier: {
|
||||||
stroke: '#afafaf',
|
stroke: '#afafaf',
|
||||||
strokeWidth: 1
|
strokeWidth: 1,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
lf.value.on('graph:rendered', () => {
|
lf.value.on('graph:rendered', () => {
|
||||||
flowId.value = lf.value.graphModel.flowId
|
flowId.value = lf.value.graphModel.flowId
|
||||||
@ -124,7 +124,7 @@ const onmousedown = (shapeItem: ShapeItem) => {
|
|||||||
if (shapeItem.type) {
|
if (shapeItem.type) {
|
||||||
lf.value.dnd.startDrag({
|
lf.value.dnd.startDrag({
|
||||||
type: shapeItem.type,
|
type: shapeItem.type,
|
||||||
properties: { ...shapeItem.properties }
|
properties: { ...shapeItem.properties },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (shapeItem.callback) {
|
if (shapeItem.callback) {
|
||||||
@ -139,7 +139,7 @@ const addNode = (shapeItem: ShapeItem) => {
|
|||||||
type: shapeItem.type,
|
type: shapeItem.type,
|
||||||
properties: shapeItem.properties,
|
properties: shapeItem.properties,
|
||||||
x: virtualRectCenterPositionX,
|
x: virtualRectCenterPositionX,
|
||||||
y: virtualRectCenterPositionY - lf.value.graphModel.height / 2
|
y: virtualRectCenterPositionY - lf.value.graphModel.height / 2,
|
||||||
})
|
})
|
||||||
newNode.isSelected = true
|
newNode.isSelected = true
|
||||||
newNode.isHovered = true
|
newNode.isHovered = true
|
||||||
@ -157,7 +157,7 @@ defineExpose({
|
|||||||
addNode,
|
addNode,
|
||||||
clearGraphData,
|
clearGraphData,
|
||||||
renderGraphData,
|
renderGraphData,
|
||||||
render
|
render,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
:rules="{
|
:rules="{
|
||||||
required: true,
|
required: true,
|
||||||
message: $t('views.application.form.aiModel.placeholder'),
|
message: $t('views.application.form.aiModel.placeholder'),
|
||||||
trigger: 'change'
|
trigger: 'change',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
@ -68,7 +68,7 @@
|
|||||||
:rules="{
|
:rules="{
|
||||||
required: true,
|
required: true,
|
||||||
message: $t('views.application.form.prompt.requiredMessage'),
|
message: $t('views.application.form.prompt.requiredMessage'),
|
||||||
trigger: 'blur'
|
trigger: 'blur',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
@ -80,9 +80,7 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<el-tooltip effect="dark" placement="right" popper-class="max-w-200">
|
<el-tooltip effect="dark" placement="right" popper-class="max-w-200">
|
||||||
<template #content
|
<template #content>{{ $t('views.application.form.prompt.tooltip') }} </template>
|
||||||
>{{ $t('views.application.form.prompt.tooltip') }}
|
|
||||||
</template>
|
|
||||||
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
|
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
@ -127,9 +125,7 @@
|
|||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-between w-full">
|
<div class="flex-between w-full">
|
||||||
<div>
|
<div>
|
||||||
<span>{{
|
<span>{{ $t('views.application.form.reasoningContent.label') }}</span>
|
||||||
$t('views.application.form.reasoningContent.label')
|
|
||||||
}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@ -179,6 +175,7 @@ import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
|||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import applicationApi from '@/api/application/application'
|
import applicationApi from '@/api/application/application'
|
||||||
|
import modelAPI from '@/api/model/model.ts'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
import { isLastNode } from '@/workflow/common/data'
|
import { isLastNode } from '@/workflow/common/data'
|
||||||
import AIModeParamSettingDialog from '@/views/application/component/AIModeParamSettingDialog.vue'
|
import AIModeParamSettingDialog from '@/views/application/component/AIModeParamSettingDialog.vue'
|
||||||
@ -213,7 +210,7 @@ const model_change = (model_id?: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const {
|
const {
|
||||||
params: { id }
|
params: { id },
|
||||||
} = app.config.globalProperties.$route as any
|
} = app.config.globalProperties.$route as any
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -234,8 +231,8 @@ const form = {
|
|||||||
model_setting: {
|
model_setting: {
|
||||||
reasoning_content_start: '<think>',
|
reasoning_content_start: '<think>',
|
||||||
reasoning_content_end: '</think>',
|
reasoning_content_end: '</think>',
|
||||||
reasoning_content_enable: false
|
reasoning_content_enable: false,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const chat_data = computed({
|
const chat_data = computed({
|
||||||
@ -245,7 +242,7 @@ const chat_data = computed({
|
|||||||
set(props.nodeModel.properties.node_data, 'model_setting', {
|
set(props.nodeModel.properties.node_data, 'model_setting', {
|
||||||
reasoning_content_start: '<think>',
|
reasoning_content_start: '<think>',
|
||||||
reasoning_content_end: '</think>',
|
reasoning_content_end: '</think>',
|
||||||
reasoning_content_enable: false
|
reasoning_content_enable: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return props.nodeModel.properties.node_data
|
return props.nodeModel.properties.node_data
|
||||||
@ -257,7 +254,7 @@ const chat_data = computed({
|
|||||||
},
|
},
|
||||||
set: (value) => {
|
set: (value) => {
|
||||||
set(props.nodeModel.properties, 'node_data', value)
|
set(props.nodeModel.properties, 'node_data', value)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const props = defineProps<{ nodeModel: any }>()
|
const props = defineProps<{ nodeModel: any }>()
|
||||||
|
|
||||||
@ -274,7 +271,7 @@ const validate = () => {
|
|||||||
|
|
||||||
function getModel() {
|
function getModel() {
|
||||||
if (id) {
|
if (id) {
|
||||||
applicationApi.getApplicationModel(id).then((res: any) => {
|
modelAPI.getLLMModel().then((res: any) => {
|
||||||
modelOptions.value = groupBy(res?.data, 'provider')
|
modelOptions.value = groupBy(res?.data, 'provider')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -302,7 +299,7 @@ function submitReasoningDialog(val: any) {
|
|||||||
let model_setting = cloneDeep(props.nodeModel.properties.node_data.model_setting)
|
let model_setting = cloneDeep(props.nodeModel.properties.node_data.model_setting)
|
||||||
model_setting = {
|
model_setting = {
|
||||||
...model_setting,
|
...model_setting,
|
||||||
...val
|
...val,
|
||||||
}
|
}
|
||||||
|
|
||||||
set(props.nodeModel.properties.node_data, 'model_setting', model_setting)
|
set(props.nodeModel.properties.node_data, 'model_setting', model_setting)
|
||||||
@ -312,7 +309,7 @@ const mcpServersDialogRef = ref()
|
|||||||
function openMcpServersDialog() {
|
function openMcpServersDialog() {
|
||||||
const config = {
|
const config = {
|
||||||
mcp_servers: chat_data.value.mcp_servers,
|
mcp_servers: chat_data.value.mcp_servers,
|
||||||
mcp_enable: chat_data.value.mcp_enable
|
mcp_enable: chat_data.value.mcp_enable,
|
||||||
}
|
}
|
||||||
mcpServersDialogRef.value.open(config)
|
mcpServersDialogRef.value.open(config)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
:rules="{
|
:rules="{
|
||||||
message: t('views.application.form.appName.requiredMessage'),
|
message: t('views.application.form.appName.requiredMessage'),
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
required: true
|
required: true,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<el-input
|
<el-input
|
||||||
@ -86,9 +86,7 @@
|
|||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-between">
|
<div class="flex-between">
|
||||||
<span class="mr-4">{{
|
<span class="mr-4">{{ $t('views.application.form.voiceInput.label') }}</span>
|
||||||
$t('views.application.form.voiceInput.label')
|
|
||||||
}}</span>
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-checkbox v-if="form_data.stt_model_enable" v-model="form_data.stt_autosend">{{
|
<el-checkbox v-if="form_data.stt_model_enable" v-model="form_data.stt_autosend">{{
|
||||||
$t('views.application.form.voiceInput.autoSend')
|
$t('views.application.form.voiceInput.autoSend')
|
||||||
@ -115,9 +113,7 @@
|
|||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-between">
|
<div class="flex-between">
|
||||||
<span class="mr-4">{{
|
<span class="mr-4">{{ $t('views.application.form.voicePlay.label') }}</span>
|
||||||
$t('views.application.form.voicePlay.label')
|
|
||||||
}}</span>
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-checkbox v-if="form_data.tts_model_enable" v-model="form_data.tts_autoplay">{{
|
<el-checkbox v-if="form_data.tts_model_enable" v-model="form_data.tts_autoplay">{{
|
||||||
$t('views.application.form.voicePlay.autoPlay')
|
$t('views.application.form.voicePlay.autoPlay')
|
||||||
@ -133,14 +129,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<el-radio-group v-model="form_data.tts_type" v-show="form_data.tts_model_enable">
|
<el-radio-group v-model="form_data.tts_type" v-show="form_data.tts_model_enable">
|
||||||
<el-radio
|
<el-radio :label="$t('views.application.form.voicePlay.browser')" value="BROWSER" />
|
||||||
:label="$t('views.application.form.voicePlay.browser')"
|
<el-radio :label="$t('views.application.form.voicePlay.tts')" value="TTS" />
|
||||||
value="BROWSER"
|
|
||||||
/>
|
|
||||||
<el-radio
|
|
||||||
:label="$t('views.application.form.voicePlay.tts')"
|
|
||||||
value="TTS"
|
|
||||||
/>
|
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-between w-full">
|
<div class="flex-between w-full">
|
||||||
@ -183,6 +173,7 @@ import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
|||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import applicationApi from '@/api/application/application'
|
import applicationApi from '@/api/application/application'
|
||||||
|
import modelAPI from '@/api/model/model.ts'
|
||||||
import { MsgError, MsgSuccess, MsgWarning } from '@/utils/message'
|
import { MsgError, MsgSuccess, MsgWarning } from '@/utils/message'
|
||||||
import { t } from '@/locales'
|
import { t } from '@/locales'
|
||||||
import TTSModeParamSettingDialog from '@/views/application/component/TTSModeParamSettingDialog.vue'
|
import TTSModeParamSettingDialog from '@/views/application/component/TTSModeParamSettingDialog.vue'
|
||||||
@ -191,7 +182,7 @@ import UserInputFieldTable from './component/UserInputFieldTable.vue'
|
|||||||
import FileUploadSettingDialog from '@/workflow/nodes/base-node/component/FileUploadSettingDialog.vue'
|
import FileUploadSettingDialog from '@/workflow/nodes/base-node/component/FileUploadSettingDialog.vue'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
params: { id }
|
params: { id },
|
||||||
} = app.config.globalProperties.$route as any
|
} = app.config.globalProperties.$route as any
|
||||||
|
|
||||||
const props = defineProps<{ nodeModel: any }>()
|
const props = defineProps<{ nodeModel: any }>()
|
||||||
@ -206,7 +197,7 @@ const FileUploadSettingDialogRef = ref<InstanceType<typeof FileUploadSettingDial
|
|||||||
const form = {
|
const form = {
|
||||||
name: '',
|
name: '',
|
||||||
desc: '',
|
desc: '',
|
||||||
prologue: t('views.application.form.defaultPrologue')
|
prologue: t('views.application.form.defaultPrologue'),
|
||||||
}
|
}
|
||||||
|
|
||||||
const wheel = (e: any) => {
|
const wheel = (e: any) => {
|
||||||
@ -234,7 +225,7 @@ const form_data = computed({
|
|||||||
},
|
},
|
||||||
set: (value) => {
|
set: (value) => {
|
||||||
set(props.nodeModel.properties, 'node_data', value)
|
set(props.nodeModel.properties, 'node_data', value)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const baseNodeFormRef = ref<FormInstance>()
|
const baseNodeFormRef = ref<FormInstance>()
|
||||||
@ -247,13 +238,13 @@ const validate = () => {
|
|||||||
) {
|
) {
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
node: props.nodeModel,
|
node: props.nodeModel,
|
||||||
errMessage: t('views.application.form.voicePlay.requiredMessage')
|
errMessage: t('views.application.form.voicePlay.requiredMessage'),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (form_data.value.stt_model_enable && !form_data.value.stt_model_id) {
|
if (form_data.value.stt_model_enable && !form_data.value.stt_model_id) {
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
node: props.nodeModel,
|
node: props.nodeModel,
|
||||||
errMessage: t('views.application.form.voiceInput.requiredMessage')
|
errMessage: t('views.application.form.voiceInput.requiredMessage'),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return baseNodeFormRef.value?.validate().catch((err) => {
|
return baseNodeFormRef.value?.validate().catch((err) => {
|
||||||
@ -262,13 +253,13 @@ const validate = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSTTModel() {
|
function getSTTModel() {
|
||||||
applicationApi.getApplicationSTTModel(id).then((res: any) => {
|
modelAPI.getSTTModel().then((res: any) => {
|
||||||
sttModelOptions.value = groupBy(res?.data, 'provider')
|
sttModelOptions.value = groupBy(res?.data, 'provider')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTTSModel() {
|
function getTTSModel() {
|
||||||
applicationApi.getApplicationTTSModel(id).then((res: any) => {
|
modelAPI.getTTSModel().then((res: any) => {
|
||||||
ttsModelOptions.value = groupBy(res?.data, 'provider')
|
ttsModelOptions.value = groupBy(res?.data, 'provider')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -316,7 +307,7 @@ const switchFileUpload = () => {
|
|||||||
audio: false,
|
audio: false,
|
||||||
video: false,
|
video: false,
|
||||||
other: false,
|
other: false,
|
||||||
otherExtensions: ['ppt', 'doc']
|
otherExtensions: ['ppt', 'doc'],
|
||||||
}
|
}
|
||||||
|
|
||||||
if (form_data.value.file_upload_enable) {
|
if (form_data.value.file_upload_enable) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user