Merge branch 'pr@main@application_flow' of github.com:1Panel-dev/MaxKB into pr@main@application_flow
Some checks failed
sync2gitee / repo-sync (push) Has been cancelled
Typos Check / Spell Check with Typos (push) Has been cancelled

This commit is contained in:
shaohuzhang1 2024-06-21 18:42:36 +08:00
commit c568d26d7e
8 changed files with 142 additions and 56 deletions

View File

@ -0,0 +1,56 @@
<template>
<div class="flex align-center mt-16">
<span class="mr-4 color-secondary">知识来源</span>
<el-divider direction="vertical" />
<el-button type="primary" class="mr-8" link @click="openParagraph(data)">
<AppIcon iconName="app-reference-outlined" class="mr-4"></AppIcon>
引用分段 {{ data.paragraph_list?.length || 0 }}</el-button
>
</div>
<div class="mt-8 mb-12">
<el-space wrap>
<el-button
v-for="(dataset, index) in data.dataset_list"
:key="index"
size="small"
class="source_dataset-button"
@click="openParagraph(data, dataset.id)"
>{{ dataset.name }}</el-button
>
</el-space>
</div>
<div class="border-t color-secondary" style="padding-top: 12px">
<span class="mr-8"> 消耗 tokens: {{ data?.message_tokens + data?.answer_tokens }} </span>
<span> 耗时: {{ data?.run_time?.toFixed(2) }} s</span>
</div>
<!-- 知识库引用 dialog -->
<ParagraphSourceDialog ref="ParagraphSourceDialogRef" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import ParagraphSourceDialog from './ParagraphSourceDialog.vue'
const props = defineProps({
data: {
type: Object,
default: () => {}
}
})
const ParagraphSourceDialogRef = ref()
function openParagraph(row: any, id?: string) {
ParagraphSourceDialogRef.value.open(row, id)
}
</script>
<style lang="scss" scoped>
.source_dataset-button {
background: var(--app-text-color-light-1);
border: 1px solid #ffffff;
&:hover {
border: 1px solid var(--el-color-primary);
background: var(--el-color-primary-light-9);
color: var(--el-text-color-primary);
}
}
</style>

View File

@ -73,38 +73,9 @@
<el-card v-else shadow="always" class="dialog-card">
<MdRenderer :source="item.answer_text"></MdRenderer>
<!-- 知识来源 -->
<div v-if="showSource(item)">
<el-divider> <el-text type="info">知识来源</el-text> </el-divider>
<div>
<el-space wrap>
<el-button
v-for="(dataset, index) in item.dataset_list"
:key="index"
type="primary"
plain
size="small"
@click="openParagraph(item, dataset.id)"
>{{ dataset.name }}</el-button
>
</el-space>
</div>
<div>
<el-button
class="mr-8 mt-8"
type="primary"
plain
size="small"
@click="openParagraph(item)"
>引用分段{{ item.paragraph_list?.length || 0 }}</el-button
>
<el-tag type="info" effect="plain" class="mr-8 mt-8">
消耗 tokens: {{ item?.message_tokens + item?.answer_tokens }}
</el-tag>
<el-tag type="info" effect="plain" class="mt-8">
耗时: {{ item.run_time?.toFixed(2) }} s
</el-tag>
</div>
<KnowledgeSource :data="item" />
</div>
</el-card>
<div class="flex-between mt-8" v-if="log">
@ -168,8 +139,6 @@
</div>
</div>
</div>
<!-- 知识库引用 dialog -->
<ParagraphSourceDialog ref="ParagraphSourceDialogRef" />
</div>
</template>
<script setup lang="ts">
@ -177,7 +146,7 @@ import { ref, nextTick, computed, watch, reactive, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import LogOperationButton from './LogOperationButton.vue'
import OperationButton from './OperationButton.vue'
import ParagraphSourceDialog from './ParagraphSourceDialog.vue'
import KnowledgeSource from './KnowledgeSource.vue'
import applicationApi from '@/api/application'
import logApi from '@/api/log'
import { ChatManagement, type chatType } from '@/api/type/application'
@ -222,7 +191,6 @@ const isMobile = computed(() => {
return common.isMobile() || mode === 'embed'
})
const ParagraphSourceDialogRef = ref()
const aiChatRef = ref()
const quickInputRef = ref()
const scrollDiv = ref()
@ -313,10 +281,6 @@ function showSource(row: any) {
}
}
function openParagraph(row: any, id?: string) {
ParagraphSourceDialogRef.value.open(row, id)
}
function quickProblemHandle(val: string) {
if (!loading.value && props.data?.name) {
handleDebounceClick(val)

View File

@ -1017,5 +1017,59 @@ export const iconMap: any = {
)
])
}
}
},
'app-save-outlined': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 14 14',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg'
},
[
h('path', {
d: 'M1.16666 2.53734C1.16666 1.78025 1.7804 1.1665 2.53749 1.1665H11.4625C12.2196 1.1665 12.8333 1.78025 12.8333 2.53734V11.4623C12.8333 12.2194 12.2196 12.8332 11.4625 12.8332H2.53749C1.7804 12.8332 1.16666 12.2194 1.16666 11.4623V2.53734ZM2.53749 2.33317C2.42473 2.33317 2.33332 2.42458 2.33332 2.53734V11.4623C2.33332 11.5751 2.42473 11.6665 2.53749 11.6665H11.4625C11.5753 11.6665 11.6667 11.5751 11.6667 11.4623V2.53734C11.6667 2.42457 11.5753 2.33317 11.4625 2.33317H2.53749Z',
fill: 'currentColor'
}),
h('path', {
d: 'M3.79166 1.74984C3.79166 1.42767 4.05282 1.1665 4.37499 1.1665H9.33332C9.65549 1.1665 9.91666 1.42767 9.91666 1.74984V6.99984C9.91666 7.322 9.65549 7.58317 9.33332 7.58317H4.37499C4.05282 7.58317 3.79166 7.322 3.79166 6.99984V1.74984ZM4.95832 2.33317V6.4165H8.74999V2.33317H4.95832Z',
fill: 'currentColor'
}),
h('path', {
d: 'M7.58333 3.2085C7.9055 3.2085 8.16667 3.46966 8.16667 3.79183V4.9585C8.16667 5.28066 7.9055 5.54183 7.58333 5.54183C7.26117 5.54183 7 5.28066 7 4.9585V3.79183C7 3.46966 7.26117 3.2085 7.58333 3.2085Z',
fill: 'currentColor'
}),
h('path', {
d: 'M2.62415 1.74984C2.62415 1.42767 2.88531 1.1665 3.20748 1.1665H10.4996C10.8217 1.1665 11.0829 1.42767 11.0829 1.74984C11.0829 2.072 10.8217 2.33317 10.4996 2.33317H3.20748C2.88531 2.33317 2.62415 2.072 2.62415 1.74984Z',
fill: 'currentColor'
})
]
)
])
}
},
'app-reference-outlined': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 1024 1024',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg'
},
[
h('path', {
d: 'M121.216 714.368c-7.082667-17.493333-7.466667-83.413333-7.424-104.32 0.341333-142.72 34.048-256.426667 88.32-330.112C262.4 198.229333 351.701333 161.024 460.8 172.8c7.893333 0.853333 11.946667 7.338667 10.581333 16.981333l-7.381333 51.285334c-1.749333 12.202667-9.813333 12.885333-17.621333 12.202666-138.709333-11.946667-232.576 84.053333-245.76 296.704a165.632 165.632 0 0 1 83.754666-22.528c91.050667 0 164.906667 72.96 164.906667 162.944C449.28 780.373333 375.466667 853.333333 284.373333 853.333333c-82.858667 0-151.424-60.330667-163.157333-138.965333z m438.570667 0c-7.082667-17.493333-7.509333-83.413333-7.466667-104.32 0.426667-142.72 34.090667-256.426667 88.405333-330.112 60.202667-81.706667 149.504-118.912 258.645334-107.136 7.893333 0.853333 11.946667 7.338667 10.581333 16.981333l-7.381333 51.285334c-1.749333 12.202667-9.813333 12.885333-17.621334 12.202666-138.752-11.946667-232.576 84.053333-245.76 296.704a165.632 165.632 0 0 1 83.712-22.528c91.093333 0 164.906667 72.96 164.906667 162.944 0 90.026667-73.813333 162.944-164.906667 162.944-82.773333 0-151.381333-60.330667-163.114666-138.965333z',
fill: 'currentColor'
})
]
)
])
}
},
}

View File

@ -76,14 +76,6 @@ const applicationRouter = {
component: () => import('@/views/log/index.vue')
}
]
},
// 创建编排
{
path: '/application/:id/workflow',
name: 'ApplicationWorkflow',
meta: { activeMenu: '/application' },
component: () => import('@/views/application-workflow/index.vue'),
hidden: true
}
]
}

View File

@ -13,6 +13,14 @@ export const routes: Array<RouteRecordRaw> = [
children: [...rolesRoutes]
},
// 高级编排
{
path: '/application/:id/workflow',
name: 'ApplicationWorkflow',
meta: { activeMenu: '/application' },
component: () => import('@/views/application-workflow/index.vue')
},
{
path: '/chat/:accessToken',
name: 'Chat',

View File

@ -203,6 +203,9 @@ h5 {
.p-8-12 {
padding: calc(var(--app-base-px)) calc(var(--app-base-px) + 4px);
}
.p-12-24 {
padding: calc(var(--app-base-px) + 4px) calc(var(--app-base-px) * 3);
}
.p-16-24 {
padding: calc(var(--app-base-px) * 2) calc(var(--app-base-px) * 3);
}

View File

@ -1,10 +1,10 @@
<template>
<div class="application-workflow" v-loading="loading">
<div class="header border-b flex-between p-16-24">
<div class="header border-b flex-between p-12-24">
<div class="flex align-center">
<back-button to="-1"></back-button>
<h4>{{ detail?.name }}</h4>
<el-text type="info" class="ml-16" v-if="saveTime"
<el-text type="info" class="ml-16 color-secondary" v-if="saveTime"
>保存时间{{ datetimeFormat(saveTime) }}</el-text
>
</div>
@ -16,7 +16,10 @@
<AppIcon iconName="app-play-outlined" class="mr-4"></AppIcon>
调试</el-button
>
<el-button @click="saveApplication"> 保存 </el-button>
<el-button @click="saveApplication">
<AppIcon iconName="app-save-outlined" class="mr-4"></AppIcon>
保存
</el-button>
<el-button type="primary" @click="publicHandle"> 发布 </el-button>
</div>
</div>
@ -202,11 +205,14 @@ onBeforeUnmount(() => {
</script>
<style lang="scss">
.application-workflow {
background: var(--app-layout-bg-color);
height: 100%;
.header {
background: #ffffff;
}
.workflow-main {
height: calc(100vh - var(--app-header-height) - 70px);
height: calc(100vh - 62px);
box-sizing: border-box;
}
.workflow-dropdown-menu {
-moz-user-select: none; /* Firefox */
@ -216,10 +222,10 @@ onBeforeUnmount(() => {
-o-user-select: none; /* Opera */
user-select: none; /* CSS3属性 */
position: absolute;
top: 110px;
right: 77px;
top: 49px;
right: 90px;
z-index: 99;
width: 263px;
width: 268px;
box-shadow: 0px 4px 8px 0px var(--app-text-color-light-1);
background: #ffffff;
padding-bottom: 8px;

View File

@ -62,10 +62,11 @@ function visibleChange(bool: boolean) {
function getIncomingNode(id: string) {
const list = props.nodeModel.graphModel.getNodeIncomingNode(id)
const firstElement = options.value.shift()
if (list.length > 0) {
list.forEach((item: any) => {
if (!options.value.some((obj: any) => obj.id === item.id)) {
options.value.splice(1, 1, {
options.value.unshift({
value: item.id,
label: item.properties.stepName,
type: item.type,
@ -73,10 +74,12 @@ function getIncomingNode(id: string) {
})
}
})
list.forEach((item: any) => {
getIncomingNode(item.id)
})
}
options.value.unshift(firstElement)
}
onMounted(() => {
getIncomingNode(props.nodeModel.id)