mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
feat: 知识来源
This commit is contained in:
parent
cd9fe3c6f2
commit
af7c28868d
|
|
@ -116,10 +116,29 @@ const getMarkRecord: (
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对话记录详情
|
||||
* @param 参数
|
||||
* application_id, chart_id, chart_record_id
|
||||
*/
|
||||
const getRecordDetail: (
|
||||
applicaiton_id: String,
|
||||
chart_id: String,
|
||||
chart_record_id: String,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (applicaiton_id, chart_id, chart_record_id, loading) => {
|
||||
return get(
|
||||
`${prefix}/${applicaiton_id}/chat/${chart_id}/chat_record/${chart_record_id}`,
|
||||
undefined,
|
||||
loading
|
||||
)
|
||||
}
|
||||
|
||||
export default {
|
||||
getChatLog,
|
||||
delChatLog,
|
||||
getChatRecordLog,
|
||||
putChatRecordLog,
|
||||
getMarkRecord
|
||||
getMarkRecord,
|
||||
getRecordDetail
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<el-dialog title="知识库引用" v-model="dialogVisible" destroy-on-close>
|
||||
<el-scrollbar height="450">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="用户问题">
|
||||
<el-input v-model="detail.problem_text" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="优化后问题">
|
||||
<el-input v-model="detail.padding_problem_text" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="引用分段">
|
||||
<template v-for="(item, index) in detail.paragraph_list" :key="index">
|
||||
<CardBox
|
||||
shadow="hover"
|
||||
:title="item.title || '-'"
|
||||
:description="item.content"
|
||||
class="paragraph-source-card cursor mb-8"
|
||||
:class="item.is_active ? '' : 'disabled'"
|
||||
:showIcon="false"
|
||||
@click="editParagraph(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<AppAvatar :name="index + 1 + ''" class="mr-12 avatar-light" :size="22" />
|
||||
</template>
|
||||
<div class="active-button primary">{{ item.similarity?.toFixed(3) }}</div>
|
||||
<template #footer>
|
||||
<div class="footer-content flex-between">
|
||||
<el-text>
|
||||
<el-icon>
|
||||
<Document />
|
||||
</el-icon>
|
||||
{{ item?.document_name }}
|
||||
</el-text>
|
||||
<div class="flex align-center">
|
||||
<AppAvatar class="mr-8" shape="square" :size="18">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
|
||||
<span class="ellipsis"> {{ item?.dataset_name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<ParagraphDialog ref="ParagraphDialogRef" title="分段详情" @refresh="refresh" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, nextTick } from 'vue'
|
||||
import ParagraphDialog from '@/views/paragraph/component/ParagraphDialog.vue'
|
||||
|
||||
const emit = defineEmits(['refresh'])
|
||||
|
||||
const ParagraphDialogRef = ref()
|
||||
const dialogVisible = ref(false)
|
||||
const detail = ref<any>({})
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
detail.value = {}
|
||||
}
|
||||
})
|
||||
|
||||
const open = (data: any) => {
|
||||
detail.value = data
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
function editParagraph(row: any) {
|
||||
ParagraphDialogRef.value.open(row)
|
||||
}
|
||||
|
||||
function refresh(data: any) {
|
||||
if (data) {
|
||||
const index = detail.value.paragraph_list.findIndex((v) => v.id === data.id)
|
||||
detail.value.paragraph_list.splice(index, 1, data)
|
||||
}
|
||||
}
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.paragraph-source-card {
|
||||
height: 210px;
|
||||
width: 100%;
|
||||
:deep(.description) {
|
||||
-webkit-line-clamp: 5 !important;
|
||||
height: 110px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
|
||||
<el-card v-else shadow="always" class="dialog-card">
|
||||
<MdRenderer :source="item.answer_text"></MdRenderer>
|
||||
<div v-if="item.write_ed || log">
|
||||
<div v-if="(id && !props.appId && item.write_ed) || log">
|
||||
<el-divider> <el-text type="info">知识来源</el-text> </el-divider>
|
||||
<div class="mb-8">
|
||||
<el-space wrap>
|
||||
|
|
@ -72,20 +72,26 @@
|
|||
type="primary"
|
||||
plain
|
||||
size="small"
|
||||
@click="openParagraph(item, dataset.id)"
|
||||
>{{ dataset.name }}</el-button
|
||||
>
|
||||
</el-space>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<el-button class="mr-8" type="primary" plain size="small"
|
||||
>引用分段:{{ item.paragraph_list.length }}</el-button
|
||||
<el-button
|
||||
class="mr-8"
|
||||
type="primary"
|
||||
plain
|
||||
size="small"
|
||||
@click="openParagraph(item)"
|
||||
>引用分段:{{ item.paragraph_list?.length }}</el-button
|
||||
>
|
||||
<el-tag type="info" effect="plain">
|
||||
消耗 tokens: {{ item?.message_tokens + item?.answer_tokens }}
|
||||
</el-tag>
|
||||
<el-tag class="ml-8" type="info" effect="plain">
|
||||
耗时: {{ item.run_time.toFixed(2) }} s
|
||||
耗时: {{ item.run_time?.toFixed(2) }} s
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -149,6 +155,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 知识库引用 dialog -->
|
||||
<ParagraphSourceDialog ref="ParagraphSourceDialogRef" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
@ -156,7 +164,9 @@ import { ref, nextTick, computed, watch } from 'vue'
|
|||
import { useRoute } from 'vue-router'
|
||||
import LogOperationButton from './LogOperationButton.vue'
|
||||
import OperationButton from './OperationButton.vue'
|
||||
import ParagraphSourceDialog from './ParagraphSourceDialog.vue'
|
||||
import applicationApi from '@/api/application'
|
||||
import logApi from '@/api/log'
|
||||
import { ChatManagement, type chatType } from '@/api/type/application'
|
||||
import { randomId } from '@/utils/utils'
|
||||
import useStore from '@/stores'
|
||||
|
|
@ -165,7 +175,7 @@ import { MdPreview } from 'md-editor-v3'
|
|||
defineOptions({ name: 'AiChat' })
|
||||
const route = useRoute()
|
||||
const {
|
||||
params: { accessToken }
|
||||
params: { accessToken, id }
|
||||
} = route as any
|
||||
const props = defineProps({
|
||||
data: {
|
||||
|
|
@ -181,6 +191,7 @@ const props = defineProps({
|
|||
})
|
||||
const { application } = useStore()
|
||||
|
||||
const ParagraphSourceDialogRef = ref()
|
||||
const aiChatRef = ref()
|
||||
const quickInputRef = ref()
|
||||
const scrollDiv = ref()
|
||||
|
|
@ -213,6 +224,10 @@ watch(
|
|||
}
|
||||
)
|
||||
|
||||
function openParagraph(row: any, id?: string) {
|
||||
ParagraphSourceDialogRef.value.open(row, id)
|
||||
}
|
||||
|
||||
function quickProblemHandel(val: string) {
|
||||
if (!props.log) {
|
||||
inputValue.value = val
|
||||
|
|
@ -348,6 +363,9 @@ function chatMessage() {
|
|||
reader
|
||||
.read()
|
||||
.then(write)
|
||||
.then((ok: any) => {
|
||||
getSourceDetail(row)
|
||||
})
|
||||
.finally((ok: any) => {
|
||||
ChatManagement.close(id)
|
||||
})
|
||||
|
|
@ -364,6 +382,14 @@ function regenerationChart(item: chatType) {
|
|||
chatMessage()
|
||||
}
|
||||
|
||||
function getSourceDetail(row: chatType) {
|
||||
logApi.getRecordDetail(id, row.id, row.record_id, loading).then((res) => {
|
||||
const obj = { row, ...res.data }
|
||||
const index = chatList.value.findIndex((v) => v.id === row.id)
|
||||
chatList.value.splice(index, 1, obj)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 滚动条距离最上面的高度
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
</div>
|
||||
</slot>
|
||||
</div>
|
||||
<div class="description pre-line mt-12" v-if="$slots.description || description">
|
||||
<div class="description mt-12" v-if="$slots.description || description">
|
||||
<slot name="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
|
|
|
|||
|
|
@ -225,7 +225,11 @@
|
|||
<template #label>
|
||||
<div class="flex align-center">
|
||||
<span>问题优化</span>
|
||||
<el-tooltip effect="dark" content="根据历史聊天优化完善当前问题,更利于匹配知识点。" placement="right">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
content="根据历史聊天优化完善当前问题,更利于匹配知识点。"
|
||||
placement="right"
|
||||
>
|
||||
<el-icon style="font-size: 16px">
|
||||
<Warning />
|
||||
</el-icon>
|
||||
|
|
@ -259,7 +263,12 @@
|
|||
<p>通过调整提示词内容,可以引导大模型聊天方向,该提示词会被固定在上下文的开头。</p>
|
||||
<p>可以使用变量:{data} 是携带知识库中已知信息;{question}是用户提出的问题。</p>
|
||||
</el-alert>
|
||||
<el-input v-model="model_setting_prompt" :rows="13" type="textarea" />
|
||||
<el-input
|
||||
v-model="model_setting_prompt"
|
||||
:rows="13"
|
||||
type="textarea"
|
||||
:placeholder="defaultPrompt"
|
||||
/>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">取消</el-button>
|
||||
|
|
@ -357,7 +366,7 @@ const applicationForm = ref<ApplicationFormType>({
|
|||
model_setting: {
|
||||
prompt: defaultPrompt
|
||||
},
|
||||
problem_optimization: true
|
||||
problem_optimization: false
|
||||
})
|
||||
|
||||
const popoverVisible = ref(false)
|
||||
|
|
|
|||
Loading…
Reference in New Issue