feat: application
This commit is contained in:
parent
b6ef007b45
commit
f4f39d8059
@ -39,10 +39,11 @@ const getApplication: (
|
|||||||
* @param 参数
|
* @param 参数
|
||||||
*/
|
*/
|
||||||
const postApplication: (
|
const postApplication: (
|
||||||
|
wordspace_id: string,
|
||||||
data: ApplicationFormType,
|
data: ApplicationFormType,
|
||||||
loading?: Ref<boolean>,
|
loading?: Ref<boolean>,
|
||||||
) => Promise<Result<any>> = (data, loading) => {
|
) => Promise<Result<any>> = (wordspace_id, data, loading) => {
|
||||||
return post(`${prefix}`, data, undefined, loading)
|
return post(`${prefix}/${wordspace_id}/application`, data, undefined, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
503
ui/src/api/type/application.ts
Normal file
503
ui/src/api/type/application.ts
Normal file
@ -0,0 +1,503 @@
|
|||||||
|
import { type Dict } from '@/api/type/common'
|
||||||
|
import { type Ref } from 'vue'
|
||||||
|
import bus from '@/bus'
|
||||||
|
interface ApplicationFormType {
|
||||||
|
name?: string
|
||||||
|
desc?: string
|
||||||
|
model_id?: string
|
||||||
|
dialogue_number?: number
|
||||||
|
prologue?: string
|
||||||
|
dataset_id_list?: string[]
|
||||||
|
dataset_setting?: any
|
||||||
|
model_setting?: any
|
||||||
|
problem_optimization?: boolean
|
||||||
|
problem_optimization_prompt?: string
|
||||||
|
icon?: string | undefined
|
||||||
|
type?: string
|
||||||
|
work_flow?: any
|
||||||
|
model_params_setting?: any
|
||||||
|
tts_model_params_setting?: any
|
||||||
|
stt_model_id?: string
|
||||||
|
tts_model_id?: string
|
||||||
|
stt_model_enable?: boolean
|
||||||
|
tts_model_enable?: boolean
|
||||||
|
tts_type?: string
|
||||||
|
tts_autoplay?: boolean
|
||||||
|
stt_autosend?: boolean
|
||||||
|
}
|
||||||
|
interface Chunk {
|
||||||
|
real_node_id: string
|
||||||
|
chat_id: string
|
||||||
|
chat_record_id: string
|
||||||
|
content: string
|
||||||
|
reasoning_content: string
|
||||||
|
node_id: string
|
||||||
|
up_node_id: string
|
||||||
|
is_end: boolean
|
||||||
|
node_is_end: boolean
|
||||||
|
node_type: string
|
||||||
|
view_type: string
|
||||||
|
runtime_node_id: string
|
||||||
|
child_node: any
|
||||||
|
}
|
||||||
|
interface chatType {
|
||||||
|
id: string
|
||||||
|
problem_text: string
|
||||||
|
answer_text: string
|
||||||
|
buffer: Array<String>
|
||||||
|
answer_text_list: Array<
|
||||||
|
Array<{
|
||||||
|
content: string
|
||||||
|
reasoning_content: string
|
||||||
|
chat_record_id?: string
|
||||||
|
runtime_node_id?: string
|
||||||
|
child_node?: any
|
||||||
|
real_node_id?: string
|
||||||
|
}>
|
||||||
|
>
|
||||||
|
/**
|
||||||
|
* 是否写入结束
|
||||||
|
*/
|
||||||
|
write_ed?: boolean
|
||||||
|
/**
|
||||||
|
* 是否暂停
|
||||||
|
*/
|
||||||
|
is_stop?: boolean
|
||||||
|
record_id: string
|
||||||
|
chat_id: string
|
||||||
|
vote_status: string
|
||||||
|
status?: number
|
||||||
|
execution_details: any[]
|
||||||
|
upload_meta?: {
|
||||||
|
document_list: Array<any>
|
||||||
|
image_list: Array<any>
|
||||||
|
audio_list: Array<any>
|
||||||
|
other_list: Array<any>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Node {
|
||||||
|
buffer: Array<string>
|
||||||
|
node_id: string
|
||||||
|
up_node_id: string
|
||||||
|
node_type: string
|
||||||
|
view_type: string
|
||||||
|
index: number
|
||||||
|
is_end: boolean
|
||||||
|
}
|
||||||
|
interface WriteNodeInfo {
|
||||||
|
current_node: any
|
||||||
|
answer_text_list_index: number
|
||||||
|
current_up_node?: any
|
||||||
|
divider_content?: Array<string>
|
||||||
|
divider_reasoning_content?: Array<string>
|
||||||
|
}
|
||||||
|
export class ChatRecordManage {
|
||||||
|
id?: any
|
||||||
|
ms: number
|
||||||
|
chat: chatType
|
||||||
|
is_close?: boolean
|
||||||
|
write_ed?: boolean
|
||||||
|
is_stop?: boolean
|
||||||
|
loading?: Ref<boolean>
|
||||||
|
node_list: Array<any>
|
||||||
|
write_node_info?: WriteNodeInfo
|
||||||
|
constructor(chat: chatType, ms?: number, loading?: Ref<boolean>) {
|
||||||
|
this.ms = ms ? ms : 10
|
||||||
|
this.chat = chat
|
||||||
|
this.loading = loading
|
||||||
|
this.is_stop = false
|
||||||
|
this.is_close = false
|
||||||
|
this.write_ed = false
|
||||||
|
this.node_list = []
|
||||||
|
}
|
||||||
|
append_answer(
|
||||||
|
chunk_answer: string,
|
||||||
|
reasoning_content: string,
|
||||||
|
index?: number,
|
||||||
|
chat_record_id?: string,
|
||||||
|
runtime_node_id?: string,
|
||||||
|
child_node?: any,
|
||||||
|
real_node_id?: string
|
||||||
|
) {
|
||||||
|
if (chunk_answer || reasoning_content) {
|
||||||
|
const set_index = index != undefined ? index : this.chat.answer_text_list.length - 1
|
||||||
|
let card_list = this.chat.answer_text_list[set_index]
|
||||||
|
if (!card_list) {
|
||||||
|
card_list = []
|
||||||
|
this.chat.answer_text_list[set_index] = card_list
|
||||||
|
}
|
||||||
|
const answer_value = card_list.find((item) => item.real_node_id == real_node_id)
|
||||||
|
const content = answer_value ? answer_value.content + chunk_answer : chunk_answer
|
||||||
|
const _reasoning_content = answer_value
|
||||||
|
? answer_value.reasoning_content + reasoning_content
|
||||||
|
: reasoning_content
|
||||||
|
if (answer_value) {
|
||||||
|
answer_value.content = content
|
||||||
|
answer_value.reasoning_content = _reasoning_content
|
||||||
|
} else {
|
||||||
|
card_list.push({
|
||||||
|
content: content,
|
||||||
|
reasoning_content: _reasoning_content,
|
||||||
|
chat_record_id,
|
||||||
|
runtime_node_id,
|
||||||
|
child_node,
|
||||||
|
real_node_id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.chat.answer_text = this.chat.answer_text + chunk_answer
|
||||||
|
bus.emit('change:answer', { record_id: this.chat.record_id, is_end: false })
|
||||||
|
}
|
||||||
|
get_current_up_node(run_node: any) {
|
||||||
|
const index = this.node_list.findIndex((item) => item == run_node)
|
||||||
|
if (index > 0) {
|
||||||
|
const n = this.node_list[index - 1]
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
get_run_node() {
|
||||||
|
if (
|
||||||
|
this.write_node_info &&
|
||||||
|
(this.write_node_info.current_node.reasoning_content_buffer.length > 0 ||
|
||||||
|
this.write_node_info.current_node.buffer.length > 0 ||
|
||||||
|
!this.write_node_info.current_node.is_end)
|
||||||
|
) {
|
||||||
|
return this.write_node_info
|
||||||
|
}
|
||||||
|
const run_node = this.node_list.filter(
|
||||||
|
(item) => item.reasoning_content_buffer.length > 0 || item.buffer.length > 0 || !item.is_end
|
||||||
|
)[0]
|
||||||
|
|
||||||
|
if (run_node) {
|
||||||
|
const index = this.node_list.indexOf(run_node)
|
||||||
|
let current_up_node = undefined
|
||||||
|
if (index > 0) {
|
||||||
|
current_up_node = this.get_current_up_node(run_node)
|
||||||
|
}
|
||||||
|
let answer_text_list_index = 0
|
||||||
|
if (
|
||||||
|
current_up_node == undefined ||
|
||||||
|
run_node.view_type == 'single_view' ||
|
||||||
|
current_up_node.view_type == 'single_view'
|
||||||
|
) {
|
||||||
|
const none_index = this.findIndex(
|
||||||
|
this.chat.answer_text_list,
|
||||||
|
(item) => (item.length == 1 && item[0].content == '') || item.length == 0,
|
||||||
|
'index'
|
||||||
|
)
|
||||||
|
if (none_index > -1) {
|
||||||
|
answer_text_list_index = none_index
|
||||||
|
} else {
|
||||||
|
answer_text_list_index = this.chat.answer_text_list.length
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const none_index = this.findIndex(
|
||||||
|
this.chat.answer_text_list,
|
||||||
|
(item) => (item.length == 1 && item[0].content == '') || item.length == 0,
|
||||||
|
'index'
|
||||||
|
)
|
||||||
|
if (none_index > -1) {
|
||||||
|
answer_text_list_index = none_index
|
||||||
|
} else {
|
||||||
|
answer_text_list_index = this.chat.answer_text_list.length - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.write_node_info = {
|
||||||
|
current_node: run_node,
|
||||||
|
current_up_node: current_up_node,
|
||||||
|
answer_text_list_index: answer_text_list_index
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.write_node_info
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
findIndex<T>(array: Array<T>, find: (item: T) => boolean, type: 'last' | 'index') {
|
||||||
|
let set_index = -1
|
||||||
|
for (let index = 0; index < array.length; index++) {
|
||||||
|
const element = array[index]
|
||||||
|
if (find(element)) {
|
||||||
|
set_index = index
|
||||||
|
if (type == 'index') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set_index
|
||||||
|
}
|
||||||
|
closeInterval() {
|
||||||
|
this.chat.write_ed = true
|
||||||
|
this.write_ed = true
|
||||||
|
if (this.loading) {
|
||||||
|
this.loading.value = false
|
||||||
|
}
|
||||||
|
bus.emit('change:answer', { record_id: this.chat.record_id, is_end: true })
|
||||||
|
if (this.id) {
|
||||||
|
clearInterval(this.id)
|
||||||
|
}
|
||||||
|
const last_index = this.findIndex(
|
||||||
|
this.chat.answer_text_list,
|
||||||
|
(item) => (item.length == 1 && item[0].content == '') || item.length == 0,
|
||||||
|
'last'
|
||||||
|
)
|
||||||
|
if (last_index > 0) {
|
||||||
|
this.chat.answer_text_list.splice(last_index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write() {
|
||||||
|
this.chat.is_stop = false
|
||||||
|
this.is_stop = false
|
||||||
|
if (!this.is_close) {
|
||||||
|
this.is_close = false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.write_ed = false
|
||||||
|
this.chat.write_ed = false
|
||||||
|
if (this.loading) {
|
||||||
|
this.loading.value = true
|
||||||
|
}
|
||||||
|
this.id = setInterval(() => {
|
||||||
|
const node_info = this.get_run_node()
|
||||||
|
if (node_info == undefined) {
|
||||||
|
if (this.is_close) {
|
||||||
|
this.closeInterval()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { current_node, answer_text_list_index } = node_info
|
||||||
|
|
||||||
|
if (current_node.buffer.length > 20) {
|
||||||
|
const context = current_node.is_end
|
||||||
|
? current_node.buffer.splice(0)
|
||||||
|
: current_node.buffer.splice(
|
||||||
|
0,
|
||||||
|
current_node.is_end ? undefined : current_node.buffer.length - 20
|
||||||
|
)
|
||||||
|
const reasoning_content = current_node.is_end
|
||||||
|
? current_node.reasoning_content_buffer.splice(0)
|
||||||
|
: current_node.reasoning_content_buffer.splice(
|
||||||
|
0,
|
||||||
|
current_node.is_end ? undefined : current_node.reasoning_content_buffer.length - 20
|
||||||
|
)
|
||||||
|
this.append_answer(
|
||||||
|
context.join(''),
|
||||||
|
reasoning_content.join(''),
|
||||||
|
answer_text_list_index,
|
||||||
|
current_node.chat_record_id,
|
||||||
|
current_node.runtime_node_id,
|
||||||
|
current_node.child_node,
|
||||||
|
current_node.real_node_id
|
||||||
|
)
|
||||||
|
} else if (this.is_close) {
|
||||||
|
while (true) {
|
||||||
|
const node_info = this.get_run_node()
|
||||||
|
|
||||||
|
if (node_info == undefined) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.append_answer(
|
||||||
|
node_info.current_node.buffer.splice(0).join(''),
|
||||||
|
node_info.current_node.reasoning_content_buffer.splice(0).join(''),
|
||||||
|
node_info.answer_text_list_index,
|
||||||
|
node_info.current_node.chat_record_id,
|
||||||
|
node_info.current_node.runtime_node_id,
|
||||||
|
node_info.current_node.child_node,
|
||||||
|
node_info.current_node.real_node_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if (
|
||||||
|
node_info.current_node.buffer.length == 0 &&
|
||||||
|
node_info.current_node.reasoning_content_buffer.length == 0
|
||||||
|
) {
|
||||||
|
node_info.current_node.is_end = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.closeInterval()
|
||||||
|
} else {
|
||||||
|
const s = current_node.buffer.shift()
|
||||||
|
const reasoning_content = current_node.reasoning_content_buffer.shift()
|
||||||
|
if (s !== undefined) {
|
||||||
|
this.append_answer(
|
||||||
|
s,
|
||||||
|
'',
|
||||||
|
answer_text_list_index,
|
||||||
|
current_node.chat_record_id,
|
||||||
|
current_node.runtime_node_id,
|
||||||
|
current_node.child_node,
|
||||||
|
current_node.real_node_id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (reasoning_content !== undefined) {
|
||||||
|
this.append_answer(
|
||||||
|
'',
|
||||||
|
reasoning_content,
|
||||||
|
answer_text_list_index,
|
||||||
|
current_node.chat_record_id,
|
||||||
|
current_node.runtime_node_id,
|
||||||
|
current_node.child_node,
|
||||||
|
current_node.real_node_id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this.ms)
|
||||||
|
}
|
||||||
|
stop() {
|
||||||
|
clearInterval(this.id)
|
||||||
|
this.is_stop = true
|
||||||
|
this.chat.is_stop = true
|
||||||
|
if (this.loading) {
|
||||||
|
this.loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close() {
|
||||||
|
this.is_close = true
|
||||||
|
}
|
||||||
|
open() {
|
||||||
|
this.is_close = false
|
||||||
|
this.is_stop = false
|
||||||
|
}
|
||||||
|
appendChunk(chunk: Chunk) {
|
||||||
|
let n = this.node_list.find((item) => item.real_node_id == chunk.real_node_id)
|
||||||
|
if (n) {
|
||||||
|
n.buffer.push(...chunk.content)
|
||||||
|
n.content += chunk.content
|
||||||
|
if (chunk.reasoning_content) {
|
||||||
|
n.reasoning_content_buffer.push(...chunk.reasoning_content)
|
||||||
|
n.reasoning_content += chunk.reasoning_content
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n = {
|
||||||
|
buffer: [...chunk.content],
|
||||||
|
reasoning_content_buffer: chunk.reasoning_content ? [...chunk.reasoning_content] : [],
|
||||||
|
reasoning_content: chunk.reasoning_content ? chunk.reasoning_content : '',
|
||||||
|
content: chunk.content,
|
||||||
|
real_node_id: chunk.real_node_id,
|
||||||
|
node_id: chunk.node_id,
|
||||||
|
chat_record_id: chunk.chat_record_id,
|
||||||
|
up_node_id: chunk.up_node_id,
|
||||||
|
runtime_node_id: chunk.runtime_node_id,
|
||||||
|
child_node: chunk.child_node,
|
||||||
|
node_type: chunk.node_type,
|
||||||
|
index: this.node_list.length,
|
||||||
|
view_type: chunk.view_type,
|
||||||
|
is_end: false
|
||||||
|
}
|
||||||
|
this.node_list.push(n)
|
||||||
|
}
|
||||||
|
if (chunk.node_is_end) {
|
||||||
|
n['is_end'] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
append(answer_text_block: string, reasoning_content?: string) {
|
||||||
|
let set_index = this.findIndex(
|
||||||
|
this.chat.answer_text_list,
|
||||||
|
(item) => item.length == 1 && item[0].content == '',
|
||||||
|
'index'
|
||||||
|
)
|
||||||
|
if (set_index <= -1) {
|
||||||
|
set_index = 0
|
||||||
|
}
|
||||||
|
this.chat.answer_text_list[set_index] = [
|
||||||
|
{
|
||||||
|
content: answer_text_block,
|
||||||
|
reasoning_content: reasoning_content ? reasoning_content : ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ChatManagement {
|
||||||
|
static chatMessageContainer: Dict<ChatRecordManage> = {}
|
||||||
|
|
||||||
|
static addChatRecord(chat: chatType, ms: number, loading?: Ref<boolean>) {
|
||||||
|
this.chatMessageContainer[chat.id] = new ChatRecordManage(chat, ms, loading)
|
||||||
|
}
|
||||||
|
static appendChunk(chatRecordId: string, chunk: Chunk) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
if (chatRecord) {
|
||||||
|
chatRecord.appendChunk(chunk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static append(chatRecordId: string, content: string, reasoning_content?: string) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
if (chatRecord) {
|
||||||
|
chatRecord.append(content, reasoning_content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static updateStatus(chatRecordId: string, code: number) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
if (chatRecord) {
|
||||||
|
chatRecord.chat.status = code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 持续从缓存区 写出数据
|
||||||
|
* @param chatRecordId 对话记录id
|
||||||
|
*/
|
||||||
|
static write(chatRecordId: string) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
if (chatRecord) {
|
||||||
|
chatRecord.write()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static open(chatRecordId: string) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
if (chatRecord) {
|
||||||
|
chatRecord.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 等待所有数据输出完毕后 才会关闭流
|
||||||
|
* @param chatRecordId 对话记录id
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
static close(chatRecordId: string) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
if (chatRecord) {
|
||||||
|
chatRecord.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 停止输出 立即关闭定时任务输出
|
||||||
|
* @param chatRecordId 对话记录id
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
static stop(chatRecordId: string) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
if (chatRecord) {
|
||||||
|
chatRecord.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 判断是否输出完成
|
||||||
|
* @param chatRecordId 对话记录id
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
static isClose(chatRecordId: string) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
return chatRecord ? chatRecord.is_close && chatRecord.write_ed : false
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 判断是否停止输出
|
||||||
|
* @param chatRecordId 对话记录id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static isStop(chatRecordId: string) {
|
||||||
|
const chatRecord = this.chatMessageContainer[chatRecordId]
|
||||||
|
return chatRecord ? chatRecord.is_stop : false
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 清除无用数据 也就是被close掉的和stop的数据
|
||||||
|
*/
|
||||||
|
static clean() {
|
||||||
|
for (const key in Object.keys(this.chatMessageContainer)) {
|
||||||
|
if (this.chatMessageContainer[key].is_close) {
|
||||||
|
delete this.chatMessageContainer[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type { ApplicationFormType, chatType }
|
||||||
8
ui/src/bus/index.ts
Normal file
8
ui/src/bus/index.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import mitt from "mitt";
|
||||||
|
const bus: any = {};
|
||||||
|
const emitter = mitt();
|
||||||
|
bus.on = emitter.on;
|
||||||
|
bus.off = emitter.off;
|
||||||
|
bus.emit = emitter.emit;
|
||||||
|
|
||||||
|
export default bus;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
title: 'APP',
|
title: 'APP',
|
||||||
createApplication: 'Create APP',
|
createApplication: 'Create Simple APP',
|
||||||
|
createWorkFlowApplication: 'Create Workflow APP',
|
||||||
importApplication: 'Import APP',
|
importApplication: 'Import APP',
|
||||||
copyApplication: 'Copy APP',
|
copyApplication: 'Copy APP',
|
||||||
workflow: 'WORKFLOW',
|
workflow: 'WORKFLOW',
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
title: '应用',
|
title: '应用',
|
||||||
createApplication: '创建应用',
|
createApplication: '创建简易应用',
|
||||||
|
createWorkFlowApplication: '创建高级编排应用',
|
||||||
importApplication: '导入应用',
|
importApplication: '导入应用',
|
||||||
copyApplication: '复制应用',
|
copyApplication: '复制应用',
|
||||||
workflow: '高级编排',
|
workflow: '高级编排',
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
title: '應用',
|
title: '應用',
|
||||||
createApplication: '建立應用',
|
createApplication: '建立簡易應用',
|
||||||
|
createWorkFlowApplication: '建立進階編排應用',
|
||||||
importApplication: '匯入應用',
|
importApplication: '匯入應用',
|
||||||
copyApplication: '複製應用',
|
copyApplication: '複製應用',
|
||||||
workflow: '進階編排',
|
workflow: '進階編排',
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:title="$t('views.application.createApplication')"
|
:title="
|
||||||
|
isWorkFlow(applicationForm.type)
|
||||||
|
? $t('views.application.createWorkFlowApplication')
|
||||||
|
: $t('views.application.createApplication')
|
||||||
|
"
|
||||||
v-model="dialogVisible"
|
v-model="dialogVisible"
|
||||||
width="650"
|
width="650"
|
||||||
append-to-body
|
append-to-body
|
||||||
@ -15,51 +19,26 @@
|
|||||||
require-asterisk-position="right"
|
require-asterisk-position="right"
|
||||||
@submit.prevent
|
@submit.prevent
|
||||||
>
|
>
|
||||||
<el-form-item :label="$t('views.application.applicationForm.form.appName.label')" prop="name">
|
<el-form-item :label="$t('views.application.form.appName.label')" prop="name">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="applicationForm.name"
|
v-model="applicationForm.name"
|
||||||
maxlength="64"
|
maxlength="64"
|
||||||
:placeholder="$t('views.application.applicationForm.form.appName.placeholder')"
|
:placeholder="$t('views.application.form.appName.placeholder')"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
@blur="applicationForm.name = applicationForm.name?.trim()"
|
@blur="applicationForm.name = applicationForm.name?.trim()"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('views.application.applicationForm.form.appDescription.label')">
|
<el-form-item :label="$t('views.application.form.appDescription.label')">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="applicationForm.desc"
|
v-model="applicationForm.desc"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:placeholder="$t('views.application.applicationForm.form.appDescription.placeholder')"
|
:placeholder="$t('views.application.form.appDescription.placeholder')"
|
||||||
:rows="3"
|
:rows="3"
|
||||||
maxlength="256"
|
maxlength="256"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('views.application.applicationForm.form.appType.label')">
|
|
||||||
<el-radio-group v-model="applicationForm.type" class="card__radio">
|
|
||||||
<el-row :gutter="16">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-card shadow="never" :class="applicationForm.type === 'SIMPLE' ? 'active' : ''">
|
|
||||||
<el-radio value="SIMPLE" size="large">
|
|
||||||
<p class="mb-4">{{ $t('views.application.simple') }}</p>
|
|
||||||
<el-text type="info">{{
|
|
||||||
$t('views.application.applicationForm.form.appType.simplePlaceholder')
|
|
||||||
}}</el-text>
|
|
||||||
</el-radio>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-card shadow="never" :class="isWorkFlow(applicationForm.type) ? 'active' : ''">
|
|
||||||
<el-radio value="WORK_FLOW" size="large">
|
|
||||||
<p class="mb-4">{{ $t('views.application.workflow') }}</p>
|
|
||||||
<el-text type="info">{{
|
|
||||||
$t('views.application.applicationForm.form.appType.workflowPlaceholder')
|
|
||||||
}}</el-text>
|
|
||||||
</el-radio>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
:label="$t('views.document.upload.template')"
|
:label="$t('views.document.upload.template')"
|
||||||
v-if="applicationForm.type === 'WORK_FLOW'"
|
v-if="applicationForm.type === 'WORK_FLOW'"
|
||||||
@ -73,7 +52,7 @@
|
|||||||
@click="selectedType('blank')"
|
@click="selectedType('blank')"
|
||||||
:class="appTemplate === 'blank' ? 'active' : ''"
|
:class="appTemplate === 'blank' ? 'active' : ''"
|
||||||
>
|
>
|
||||||
{{ $t('views.application.applicationForm.form.appTemplate.blankApp') }}
|
{{ $t('views.application.form.appTemplate.blankApp') }}
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@ -83,7 +62,7 @@
|
|||||||
:class="appTemplate === 'assistant' ? 'active' : ''"
|
:class="appTemplate === 'assistant' ? 'active' : ''"
|
||||||
@click="selectedType('assistant')"
|
@click="selectedType('assistant')"
|
||||||
>
|
>
|
||||||
{{ $t('views.application.applicationForm.form.appTemplate.assistantApp') }}
|
{{ $t('views.application.form.appTemplate.assistantApp') }}
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -116,21 +95,21 @@ const router = useRouter()
|
|||||||
const emit = defineEmits(['refresh'])
|
const emit = defineEmits(['refresh'])
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const defaultPrompt = t('views.application.applicationForm.form.prompt.defaultPrompt', {
|
const defaultPrompt = t('views.application.form.prompt.defaultPrompt', {
|
||||||
data: '{data}',
|
data: '{data}',
|
||||||
question: '{question}'
|
question: '{question}',
|
||||||
})
|
})
|
||||||
|
|
||||||
const optimizationPrompt =
|
const optimizationPrompt =
|
||||||
t('views.application.applicationForm.dialog.defaultPrompt1', {
|
t('views.application.dialog.defaultPrompt1', {
|
||||||
question: '{question}'
|
question: '{question}',
|
||||||
}) +
|
}) +
|
||||||
'<data></data>' +
|
'<data></data>' +
|
||||||
t('views.application.applicationForm.dialog.defaultPrompt2')
|
t('views.application.dialog.defaultPrompt2')
|
||||||
|
|
||||||
const workflowDefault = ref<any>({
|
const workflowDefault = ref<any>({
|
||||||
edges: [],
|
edges: [],
|
||||||
nodes: baseNodes
|
nodes: baseNodes,
|
||||||
})
|
})
|
||||||
const appTemplate = ref('blank')
|
const appTemplate = ref('blank')
|
||||||
|
|
||||||
@ -144,7 +123,7 @@ const applicationForm = ref<ApplicationFormType>({
|
|||||||
desc: '',
|
desc: '',
|
||||||
model_id: '',
|
model_id: '',
|
||||||
dialogue_number: 1,
|
dialogue_number: 1,
|
||||||
prologue: t('views.application.applicationForm.form.defaultPrologue'),
|
prologue: t('views.application.form.defaultPrologue'),
|
||||||
dataset_id_list: [],
|
dataset_id_list: [],
|
||||||
dataset_setting: {
|
dataset_setting: {
|
||||||
top_n: 3,
|
top_n: 3,
|
||||||
@ -153,13 +132,13 @@ const applicationForm = ref<ApplicationFormType>({
|
|||||||
search_mode: 'embedding',
|
search_mode: 'embedding',
|
||||||
no_references_setting: {
|
no_references_setting: {
|
||||||
status: 'ai_questioning',
|
status: 'ai_questioning',
|
||||||
value: '{question}'
|
value: '{question}',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
model_setting: {
|
model_setting: {
|
||||||
prompt: defaultPrompt,
|
prompt: defaultPrompt,
|
||||||
system: t('views.application.applicationForm.form.roleSettings.placeholder'),
|
system: t('views.application.form.roleSettings.placeholder'),
|
||||||
no_references_prompt: '{question}'
|
no_references_prompt: '{question}',
|
||||||
},
|
},
|
||||||
model_params_setting: {},
|
model_params_setting: {},
|
||||||
problem_optimization: false,
|
problem_optimization: false,
|
||||||
@ -169,26 +148,28 @@ const applicationForm = ref<ApplicationFormType>({
|
|||||||
stt_model_enable: false,
|
stt_model_enable: false,
|
||||||
tts_model_enable: false,
|
tts_model_enable: false,
|
||||||
tts_type: 'BROWSER',
|
tts_type: 'BROWSER',
|
||||||
type: 'SIMPLE'
|
type: 'SIMPLE',
|
||||||
})
|
})
|
||||||
|
|
||||||
const rules = reactive<FormRules<ApplicationFormType>>({
|
const rules = reactive<FormRules<ApplicationFormType>>({
|
||||||
name: [
|
name: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t('views.application.applicationForm.form.appName.placeholder'),
|
message: t('views.application.form.appName.placeholder'),
|
||||||
trigger: 'blur'
|
trigger: 'blur',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
model_id: [
|
model_id: [
|
||||||
{
|
{
|
||||||
required: false,
|
required: false,
|
||||||
message: t('views.application.applicationForm.form.aiModel.placeholder'),
|
message: t('views.application.form.aiModel.placeholder'),
|
||||||
trigger: 'change'
|
trigger: 'change',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const currentFolder = ref('')
|
||||||
|
|
||||||
watch(dialogVisible, (bool) => {
|
watch(dialogVisible, (bool) => {
|
||||||
if (!bool) {
|
if (!bool) {
|
||||||
applicationForm.value = {
|
applicationForm.value = {
|
||||||
@ -196,7 +177,7 @@ watch(dialogVisible, (bool) => {
|
|||||||
desc: '',
|
desc: '',
|
||||||
model_id: '',
|
model_id: '',
|
||||||
dialogue_number: 1,
|
dialogue_number: 1,
|
||||||
prologue: t('views.application.applicationForm.form.defaultPrologue'),
|
prologue: t('views.application.form.defaultPrologue'),
|
||||||
dataset_id_list: [],
|
dataset_id_list: [],
|
||||||
dataset_setting: {
|
dataset_setting: {
|
||||||
top_n: 3,
|
top_n: 3,
|
||||||
@ -205,13 +186,13 @@ watch(dialogVisible, (bool) => {
|
|||||||
search_mode: 'embedding',
|
search_mode: 'embedding',
|
||||||
no_references_setting: {
|
no_references_setting: {
|
||||||
status: 'ai_questioning',
|
status: 'ai_questioning',
|
||||||
value: '{question}'
|
value: '{question}',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
model_setting: {
|
model_setting: {
|
||||||
prompt: defaultPrompt,
|
prompt: defaultPrompt,
|
||||||
system: t('views.application.applicationForm.form.roleSettings.placeholder'),
|
system: t('views.application.form.roleSettings.placeholder'),
|
||||||
no_references_prompt: '{question}'
|
no_references_prompt: '{question}',
|
||||||
},
|
},
|
||||||
model_params_setting: {},
|
model_params_setting: {},
|
||||||
problem_optimization: false,
|
problem_optimization: false,
|
||||||
@ -221,13 +202,15 @@ watch(dialogVisible, (bool) => {
|
|||||||
stt_model_enable: false,
|
stt_model_enable: false,
|
||||||
tts_model_enable: false,
|
tts_model_enable: false,
|
||||||
tts_type: 'BROWSER',
|
tts_type: 'BROWSER',
|
||||||
type: 'SIMPLE'
|
type: 'SIMPLE',
|
||||||
}
|
}
|
||||||
applicationFormRef.value?.clearValidate()
|
applicationFormRef.value?.clearValidate()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const open = () => {
|
const open = (folder: string, type?: sting) => {
|
||||||
|
currentFolder.value = folder
|
||||||
|
applicationForm.value.type = type || 'SIMPLE'
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,12 +218,13 @@ const submitHandle = async (formEl: FormInstance | undefined) => {
|
|||||||
if (!formEl) return
|
if (!formEl) return
|
||||||
await formEl.validate((valid) => {
|
await formEl.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
applicationForm.value['folder_id'] = currentFolder.value
|
||||||
if (isWorkFlow(applicationForm.value.type) && appTemplate.value === 'blank') {
|
if (isWorkFlow(applicationForm.value.type) && appTemplate.value === 'blank') {
|
||||||
workflowDefault.value.nodes[0].properties.node_data.desc = applicationForm.value.desc
|
workflowDefault.value.nodes[0].properties.node_data.desc = applicationForm.value.desc
|
||||||
workflowDefault.value.nodes[0].properties.node_data.name = applicationForm.value.name
|
workflowDefault.value.nodes[0].properties.node_data.name = applicationForm.value.name
|
||||||
applicationForm.value['work_flow'] = workflowDefault.value
|
applicationForm.value['work_flow'] = workflowDefault.value
|
||||||
}
|
}
|
||||||
applicationApi.postApplication(applicationForm.value, loading).then((res) => {
|
applicationApi.postApplication('default', applicationForm.value, loading).then((res) => {
|
||||||
MsgSuccess(t('common.createSuccess'))
|
MsgSuccess(t('common.createSuccess'))
|
||||||
emit('refresh')
|
emit('refresh')
|
||||||
if (isWorkFlow(applicationForm.value.type)) {
|
if (isWorkFlow(applicationForm.value.type)) {
|
||||||
|
|||||||
@ -47,7 +47,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="create-dropdown">
|
<el-dropdown-menu class="create-dropdown">
|
||||||
<el-dropdown-item>
|
<el-dropdown-item @click="openCreateDialog">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-avatar shape="square" class="avatar-blue mt-4" :size="36">
|
<el-avatar shape="square" class="avatar-blue mt-4" :size="36">
|
||||||
<img
|
<img
|
||||||
@ -64,7 +64,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item>
|
<el-dropdown-item @click="openCreateDialog('WORK_FLOW')">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-avatar shape="square" class="avatar-purple mt-4" :size="36">
|
<el-avatar shape="square" class="avatar-purple mt-4" :size="36">
|
||||||
<img
|
<img
|
||||||
@ -235,11 +235,13 @@
|
|||||||
<el-empty :description="$t('common.noData')" v-else />
|
<el-empty :description="$t('common.noData')" v-else />
|
||||||
</div>
|
</div>
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
|
<CreateApplicationDialog ref="CreateApplicationDialogRef" />
|
||||||
</LayoutContainer>
|
</LayoutContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref, reactive, computed } from 'vue'
|
import { onMounted, ref, reactive, computed } from 'vue'
|
||||||
|
import CreateApplicationDialog from '@/views/application/component/CreateApplicationDialog.vue'
|
||||||
import ApplicaitonApi from '@/api/application/application'
|
import ApplicaitonApi from '@/api/application/application'
|
||||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
@ -271,18 +273,26 @@ const paginationConfig = reactive({
|
|||||||
|
|
||||||
const folderList = ref<any[]>([])
|
const folderList = ref<any[]>([])
|
||||||
const applicationList = ref<any[]>([])
|
const applicationList = ref<any[]>([])
|
||||||
const datasetFolderList = ref<any[]>([])
|
|
||||||
const currentFolder = ref<any>({})
|
const currentFolder = ref<any>({})
|
||||||
|
|
||||||
function reEmbeddingDataset(row: any) {
|
const CreateApplicationDialogRef = ref()
|
||||||
KnowledgeApi.putReEmbeddingDataset('default', row.id).then(() => {
|
|
||||||
MsgSuccess(t('common.submitSuccess'))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const SyncWebDialogRef = ref()
|
function openCreateDialog(type?: string) {
|
||||||
function syncDataset(row: any) {
|
CreateApplicationDialogRef.value.open(currentFolder.value?.id || 'root', type)
|
||||||
SyncWebDialogRef.value.open(row.id)
|
// common
|
||||||
|
// .asyncGetValid(ValidType.Application, ValidCount.Application, loading)
|
||||||
|
// .then(async (res: any) => {
|
||||||
|
// if (res?.data) {
|
||||||
|
// CreateApplicationDialogRef.value.open()
|
||||||
|
// } else if (res?.code === 400) {
|
||||||
|
// MsgConfirm(t('common.tip'), t('views.application.tip.professionalMessage'), {
|
||||||
|
// cancelButtonText: t('common.confirm'),
|
||||||
|
// confirmButtonText: t('common.professional'),
|
||||||
|
// }).then(() => {
|
||||||
|
// window.open('https://maxkb.cn/pricing.html', '_blank')
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
const search_type_change = () => {
|
const search_type_change = () => {
|
||||||
@ -310,7 +320,7 @@ function getFolder() {
|
|||||||
|
|
||||||
function folderClickHandel(row: any) {
|
function folderClickHandel(row: any) {
|
||||||
currentFolder.value = row
|
currentFolder.value = row
|
||||||
datasetFolderList.value = []
|
applicationList.value = []
|
||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user