123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- <template>
- <div class="bm-main-box">
- <div class="bm-main-box-title">
- 召回测试
- <span>根据给定的查询文本测试知识的召回效果</span>
- </div>
- <div class="mt-[var(--czr-gap)] flex flex-1 overflow-hidden">
- <div class="card rounded-bl-2 flex flex-1 flex-col gap-4">
- <div class="text-main" v-loading="state.loading">
- <div class="text-head">
- 源文本
- <div class="__hover" @click="onModelConfig">
- {{ SearchMethodTypeMap.get(state.modelConfig.indexConfig?.type) }}
- </div>
- </div>
- <div class="text-content">
- <CzrFormColumn
- label-width="0px"
- width="100%"
- v-model:param="state.text"
- type="textarea"
- :transparent="true"
- :clearable="false"
- />
- <CzrButton
- class="test"
- type="primary"
- title="测试"
- @click="onTest"
- />
- </div>
- </div>
- <div class="flex flex-1 flex-col">
- <div class="__czr-title_1">记录</div>
- <div class="flex-1">
- <CzrTable
- v-loading="state.query.loading"
- :data="state.query.result.data"
- :head="state.query.head"
- :total="state.query.result.total"
- :page="state.query.page.pageNum"
- :pageSize="state.query.page.pageSize"
- @handlePage="onPage"
- @row-click="(row) => (state.text = row.content)"
- >
- </CzrTable>
- </div>
- </div>
- </div>
- <div
- class="card rounded-br-2 flex w-[26.25rem] flex-col space-y-4"
- v-loading="state.loading"
- >
- <div class="__czr-title_1">{{ state.backList.length }} 个召回段落</div>
- <div class="flex flex-1 flex-col gap-4 overflow-y-auto">
- <template v-for="(item, index) in state.backList">
- <div
- class="back-item"
- :style="{
- backgroundColor: `rgba(${colors[index % colors.length]}, 0.05)`,
- }"
- >
- <div class="back-item-head">
- <div
- :style="{
- backgroundColor: `rgba(${colors[index % colors.length]}, 1)`,
- }"
- >
- <SvgIcon name="box" color="#ffffff" size="15" />
- </div>
- Chunk-{{ index + 1 }}·{{ item.wordCount }} 字符
- </div>
- <div class="mt-2 text-[1.25rem] font-bold text-[#21262D]">
- {{ item.text }}
- </div>
- <div
- class="mt-[var(--czr-gap)] flex flex-wrap gap-2 text-sm text-[#576275]"
- >
- <template v-for="s in item.keywords?.split(',') || []">
- <span>#{{ s }}</span>
- </template>
- </div>
- <div
- class="mt-4 h-[1px] w-full"
- :style="{
- backgroundColor: `rgba(${colors[index % colors.length]}, 0.2)`,
- }"
- />
- <div
- class="mt-4 flex items-center gap-2 text-[0.75rem] text-[#576275]"
- >
- <img
- :src="DictionaryStore.getFileIcon(item.name)"
- class="h-4"
- />
- {{ item.name }}
- </div>
- </div>
- </template>
- </div>
- </div>
- </div>
- </div>
- <CzrDialog
- :show="state.modelConfig.show"
- title="检索方式"
- @onClose="state.modelConfig.show = false"
- @onSubmit="onSubmitModelConfig"
- width="62.5rem"
- height="auto"
- max-height="90%"
- >
- <CzrForm ref="ref_form" label-width="6.1rem">
- <modelConfig
- :index-method="false"
- :embedding="false"
- ref="ref_modelConfig"
- />
- </CzrForm>
- </CzrDialog>
- </template>
- <script setup lang="ts">
- import { getCurrentInstance, nextTick, onMounted, reactive, ref } from 'vue'
- import { v4 } from 'uuid'
- import modelConfig from '@/views/manage/knowledge/model-config.vue'
- import { SearchMethodTypeMap } from '@/types/knowledge'
- import { datasetsCallback, queriesAnswer } from '@/api/modules/knowledge/test'
- import { ElMessage } from 'element-plus'
- import { useDictionaryStore } from '@/stores'
- const DictionaryStore = useDictionaryStore()
- const emit = defineEmits(['refresh'])
- const props = defineProps({
- knowledge: <any>{},
- })
- const { proxy }: any = getCurrentInstance()
- const colors = ['46, 155, 62', '0, 159, 188', '119, 69, 222', '255, 162, 84']
- const state: any = reactive({
- loading: false,
- text: '',
- backList: [],
- query: {
- loading: false,
- head: [
- { value: 'source', label: '数据源', show: true },
- { value: 'content', label: '文本', show: true },
- {
- value: 'createTime',
- label: '时间',
- show: true,
- datetime: true,
- width: 180,
- },
- ],
- page: {
- pageNum: 1,
- pageSize: 20,
- },
- result: {
- total: 0,
- data: [],
- },
- },
- modelConfig: {
- show: false,
- indexConfig: null,
- },
- })
- const ref_modelConfig = ref()
- const ref_form = ref()
- const onPage = (pageNum, pageSize) => {
- state.query.page = {
- pageNum: pageNum,
- pageSize: pageSize,
- }
- const params = {
- datesetId: props.knowledge.id,
- page: state.query.page.pageNum,
- size: state.query.page.pageSize,
- }
- state.query.loading = true
- queriesAnswer(params)
- .then(({ data }: any) => {
- state.query.result.total = data.totalElements
- state.query.result.data = data.content
- })
- .catch(() => {})
- .finally(() => {
- state.query.loading = false
- })
- }
- const onModelConfig = () => {
- state.modelConfig.show = true
- nextTick(() => {
- ref_modelConfig.value.init({ indexConfig: state.modelConfig.indexConfig })
- })
- }
- const onSubmitModelConfig = () => {
- ref_form.value.submit().then(() => {
- state.modelConfig.indexConfig = ref_modelConfig.value.getData().indexConfig
- state.modelConfig.show = false
- })
- }
- const onTest = () => {
- if (!state.text.trim()) {
- ElMessage.warning('请输入源文本')
- return
- }
- state.loading = true
- datasetsCallback({
- datasetId: props.knowledge.id,
- indexConfig: JSON.stringify(state.modelConfig.indexConfig),
- context: state.text,
- })
- .then(({ data }: any) => {
- state.backList = data
- })
- .catch(() => {})
- .finally(() => {
- state.loading = false
- })
- }
- onMounted(() => {
- onPage(1, 10)
- state.modelConfig.indexConfig = JSON.parse(
- JSON.stringify(props.knowledge.indexConfig),
- )
- })
- </script>
- <style lang="scss" scoped>
- .bm-main-box {
- padding-left: 0;
- padding-right: 0;
- padding-bottom: 0;
- }
- .card {
- background-color: #ffffff;
- box-shadow: 0rem 0.06rem 0.25rem 0rem rgba(38, 110, 255, 0.2);
- border: 0.06rem solid #e6e8ea;
- padding: 1rem;
- }
- .text-main {
- flex: 1;
- display: flex;
- flex-direction: column;
- border-radius: 0.25rem;
- .text-head {
- display: flex;
- align-items: center;
- padding: 0 1.5rem;
- background-image: url('@/assets/images/knowledge/knowledge-back-test.png');
- background-repeat: no-repeat;
- background-size: 100% 100%;
- height: 3.75rem;
- border-radius: 0.25rem 0.25rem 0 0;
- border: var(--czr-border);
- font-weight: bold;
- font-size: 1.25rem;
- color: #303133;
- > div {
- margin-left: auto;
- width: 5.63rem;
- height: 1.75rem;
- background: #ebf2ff;
- border-radius: 0.25rem;
- border: 1px solid rgba(var(--czr-main-color-rgb), 0.3);
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 0.75rem;
- color: var(--czr-main-color);
- }
- }
- .text-content {
- flex: 1;
- position: relative;
- :deep(.czr-form-column) {
- width: 100%;
- height: 100%;
- .el-form-item {
- width: 100%;
- height: 100%;
- .el-textarea__inner {
- width: 100%;
- height: 100%;
- padding: 0.75rem;
- resize: none;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- }
- }
- }
- .test {
- position: absolute;
- right: 1.5rem;
- bottom: 0.75rem;
- }
- }
- }
- .back-item {
- border-radius: 0.5rem;
- width: 100%;
- padding: 2rem 1rem 1rem;
- position: relative;
- .back-item-head {
- position: absolute;
- top: 0;
- left: 0;
- display: flex;
- align-items: center;
- font-size: 0.75rem;
- color: #576275;
- gap: 0.5rem;
- > div:first-child {
- width: 2.5rem;
- height: 1.63rem;
- box-shadow: 0 0.13rem 0.13rem 0 rgba(0, 0, 0, 0.25);
- border-radius: 0.25rem 0 0.25rem 0;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
- }
- </style>
|