feat: 文档支持设置命中处理方式(#56)

This commit is contained in:
shaohuzhang1 2024-04-25 10:44:14 +08:00 committed by GitHub
parent 6980704cce
commit 25aa4cd2b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 210 additions and 32 deletions

View File

@ -18,7 +18,8 @@ from dataset.models import Paragraph
class ParagraphPipelineModel: class ParagraphPipelineModel:
def __init__(self, _id: str, document_id: str, dataset_id: str, content: str, title: str, status: str, def __init__(self, _id: str, document_id: str, dataset_id: str, content: str, title: str, status: str,
is_active: bool, comprehensive_score: float, similarity: float, dataset_name: str, document_name: str): is_active: bool, comprehensive_score: float, similarity: float, dataset_name: str, document_name: str,
hit_handling_method: str):
self.id = _id self.id = _id
self.document_id = document_id self.document_id = document_id
self.dataset_id = dataset_id self.dataset_id = dataset_id
@ -30,6 +31,7 @@ class ParagraphPipelineModel:
self.similarity = similarity self.similarity = similarity
self.dataset_name = dataset_name self.dataset_name = dataset_name
self.document_name = document_name self.document_name = document_name
self.hit_handling_method = hit_handling_method
def to_dict(self): def to_dict(self):
return { return {
@ -53,6 +55,7 @@ class ParagraphPipelineModel:
self.comprehensive_score = None self.comprehensive_score = None
self.document_name = None self.document_name = None
self.dataset_name = None self.dataset_name = None
self.hit_handling_method = None
def add_paragraph(self, paragraph): def add_paragraph(self, paragraph):
if isinstance(paragraph, Paragraph): if isinstance(paragraph, Paragraph):
@ -76,6 +79,10 @@ class ParagraphPipelineModel:
self.document_name = document_name self.document_name = document_name
return self return self
def add_hit_handling_method(self, hit_handling_method):
self.hit_handling_method = hit_handling_method
return self
def add_comprehensive_score(self, comprehensive_score: float): def add_comprehensive_score(self, comprehensive_score: float):
self.comprehensive_score = comprehensive_score self.comprehensive_score = comprehensive_score
return self return self
@ -91,7 +98,7 @@ class ParagraphPipelineModel:
self.paragraph.get('status'), self.paragraph.get('status'),
self.paragraph.get('is_active'), self.paragraph.get('is_active'),
self.comprehensive_score, self.similarity, self.dataset_name, self.comprehensive_score, self.similarity, self.dataset_name,
self.document_name) self.document_name, self.hit_handling_method)
class IBaseChatPipelineStep: class IBaseChatPipelineStep:

View File

@ -145,6 +145,15 @@ class BaseChatStep(IChatStep):
if (paragraph_list is None or len(paragraph_list) == 0) and no_references_setting.get( if (paragraph_list is None or len(paragraph_list) == 0) and no_references_setting.get(
'status') == 'designated_answer': 'status') == 'designated_answer':
chat_result = iter([AIMessageChunk(content=no_references_setting.get('value'))]) chat_result = iter([AIMessageChunk(content=no_references_setting.get('value'))])
else:
if paragraph_list is not None and len(paragraph_list) > 0:
directly_return_chunk_list = [AIMessageChunk(content=paragraph.title + "\n" + paragraph.content)
for paragraph in paragraph_list if
paragraph.hit_handling_method == 'directly_return']
if directly_return_chunk_list is not None and len(directly_return_chunk_list) > 0:
chat_result = iter(directly_return_chunk_list)
else:
chat_result = chat_model.stream(message_list)
else: else:
chat_result = chat_model.stream(message_list) chat_result = chat_model.stream(message_list)
is_ai_chat = True is_ai_chat = True

View File

@ -35,8 +35,9 @@ class BaseSearchDatasetStep(ISearchDatasetStep):
exclude_paragraph_id_list, True, top_n, similarity, SearchMode(search_mode)) exclude_paragraph_id_list, True, top_n, similarity, SearchMode(search_mode))
if embedding_list is None: if embedding_list is None:
return [] return []
paragraph_list = self.list_paragraph([row.get('paragraph_id') for row in embedding_list], vector) paragraph_list = self.list_paragraph(embedding_list, vector)
return [self.reset_paragraph(paragraph, embedding_list) for paragraph in paragraph_list] result = [self.reset_paragraph(paragraph, embedding_list) for paragraph in paragraph_list]
return result
@staticmethod @staticmethod
def reset_paragraph(paragraph: Dict, embedding_list: List) -> ParagraphPipelineModel: def reset_paragraph(paragraph: Dict, embedding_list: List) -> ParagraphPipelineModel:
@ -50,10 +51,21 @@ class BaseSearchDatasetStep(ISearchDatasetStep):
.add_comprehensive_score(find_embedding.get('comprehensive_score')) .add_comprehensive_score(find_embedding.get('comprehensive_score'))
.add_dataset_name(paragraph.get('dataset_name')) .add_dataset_name(paragraph.get('dataset_name'))
.add_document_name(paragraph.get('document_name')) .add_document_name(paragraph.get('document_name'))
.add_hit_handling_method(paragraph.get('hit_handling_method'))
.build()) .build())
@staticmethod @staticmethod
def list_paragraph(paragraph_id_list: List, vector): def get_similarity(paragraph, embedding_list: List):
filter_embedding_list = [embedding for embedding in embedding_list if
str(embedding.get('paragraph_id')) == str(paragraph.get('id'))]
if filter_embedding_list is not None and len(filter_embedding_list) > 0:
find_embedding = filter_embedding_list[-1]
return find_embedding.get('comprehensive_score')
return 0
@staticmethod
def list_paragraph(embedding_list: List, vector):
paragraph_id_list = [row.get('paragraph_id') for row in embedding_list]
if paragraph_id_list is None or len(paragraph_id_list) == 0: if paragraph_id_list is None or len(paragraph_id_list) == 0:
return [] return []
paragraph_list = native_search(QuerySet(Paragraph).filter(id__in=paragraph_id_list), paragraph_list = native_search(QuerySet(Paragraph).filter(id__in=paragraph_id_list),
@ -67,6 +79,13 @@ class BaseSearchDatasetStep(ISearchDatasetStep):
for paragraph_id in paragraph_id_list: for paragraph_id in paragraph_id_list:
if not exist_paragraph_list.__contains__(paragraph_id): if not exist_paragraph_list.__contains__(paragraph_id):
vector.delete_by_paragraph_id(paragraph_id) vector.delete_by_paragraph_id(paragraph_id)
# 如果存在直接返回的则取直接返回段落
hit_handling_method_paragraph = [paragraph for paragraph in paragraph_list if
paragraph.get('hit_handling_method') == 'directly_return']
if len(hit_handling_method_paragraph) > 0:
# 找到评分最高的
return [sorted(hit_handling_method_paragraph,
key=lambda p: BaseSearchDatasetStep.get_similarity(p, embedding_list))[-1]]
return paragraph_list return paragraph_list
def get_details(self, manage, **kwargs): def get_details(self, manage, **kwargs):

View File

@ -196,9 +196,11 @@ class ChatMessageSerializer(serializers.Serializer):
exclude_paragraph_id_list = [] exclude_paragraph_id_list = []
# 相同问题是否需要排除已经查询到的段落 # 相同问题是否需要排除已经查询到的段落
if re_chat: if re_chat:
paragraph_id_list = flat_map([row.paragraph_id_list for row in paragraph_id_list = flat_map(
filter(lambda chat_record: chat_record == message, [[paragraph.get('id') for paragraph in chat_record.details['search_step']['paragraph_list']] for
chat_info.chat_record_list)]) chat_record in chat_info.chat_record_list if
chat_record.problem_text == message and 'search_step' in chat_record.details and 'paragraph_list' in
chat_record.details['search_step']])
exclude_paragraph_id_list = list(set(paragraph_id_list)) exclude_paragraph_id_list = list(set(paragraph_id_list))
# 构建运行参数 # 构建运行参数
params = chat_info.to_pipeline_manage_params(message, get_post_handler(chat_info), exclude_paragraph_id_list, params = chat_info.to_pipeline_manage_params(message, get_post_handler(chat_info), exclude_paragraph_id_list,

View File

@ -1,7 +1,8 @@
SELECT SELECT
paragraph.*, paragraph.*,
dataset."name" AS "dataset_name", dataset."name" AS "dataset_name",
"document"."name" AS "document_name" "document"."name" AS "document_name",
"document"."hit_handling_method" AS "hit_handling_method"
FROM FROM
paragraph paragraph paragraph paragraph
LEFT JOIN dataset dataset ON dataset."id" = paragraph.dataset_id LEFT JOIN dataset dataset ON dataset."id" = paragraph.dataset_id

View File

@ -0,0 +1,18 @@
# Generated by Django 4.1.13 on 2024-04-24 15:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dataset', '0002_image'),
]
operations = [
migrations.AddField(
model_name='document',
name='hit_handling_method',
field=models.CharField(choices=[('optimization', '模型优化'), ('directly_return', '直接返回')], default='optimization', max_length=20, verbose_name='命中处理方式'),
),
]

View File

@ -27,6 +27,11 @@ class Type(models.TextChoices):
web = 1, 'web站点类型' web = 1, 'web站点类型'
class HitHandlingMethod(models.TextChoices):
optimization = 'optimization', '模型优化'
directly_return = 'directly_return', '直接返回'
class DataSet(AppModelMixin): class DataSet(AppModelMixin):
""" """
数据集表 数据集表
@ -58,6 +63,9 @@ class Document(AppModelMixin):
type = models.CharField(verbose_name='类型', max_length=1, choices=Type.choices, type = models.CharField(verbose_name='类型', max_length=1, choices=Type.choices,
default=Type.base) default=Type.base)
hit_handling_method = models.CharField(verbose_name='命中处理方式', max_length=20,
choices=HitHandlingMethod.choices,
default=HitHandlingMethod.optimization)
meta = models.JSONField(verbose_name="元数据", default=dict) meta = models.JSONField(verbose_name="元数据", default=dict)

View File

@ -8,11 +8,13 @@
""" """
import logging import logging
import os import os
import re
import traceback import traceback
import uuid import uuid
from functools import reduce from functools import reduce
from typing import List, Dict from typing import List, Dict
from django.core import validators
from django.db import transaction from django.db import transaction
from django.db.models import QuerySet from django.db.models import QuerySet
from drf_yasg import openapi from drf_yasg import openapi
@ -42,6 +44,12 @@ class DocumentEditInstanceSerializer(ApiMixin, serializers.Serializer):
name = serializers.CharField(required=False, max_length=128, min_length=1, name = serializers.CharField(required=False, max_length=128, min_length=1,
error_messages=ErrMessage.char( error_messages=ErrMessage.char(
"文档名称")) "文档名称"))
hit_handling_method = serializers.CharField(required=False, validators=[
validators.RegexValidator(regex=re.compile("^optimization|directly_return$"),
message="类型只支持optimization|directly_return",
code=500)
], error_messages=ErrMessage.char("命中处理方式"))
is_active = serializers.BooleanField(required=False, error_messages=ErrMessage.char( is_active = serializers.BooleanField(required=False, error_messages=ErrMessage.char(
"文档是否可用")) "文档是否可用"))
@ -116,12 +124,15 @@ class DocumentSerializers(ApiMixin, serializers.Serializer):
min_length=1, min_length=1,
error_messages=ErrMessage.char( error_messages=ErrMessage.char(
"文档名称")) "文档名称"))
hit_handling_method = serializers.CharField(required=False, error_messages=ErrMessage.char("命中处理方式"))
def get_query_set(self): def get_query_set(self):
query_set = QuerySet(model=Document) query_set = QuerySet(model=Document)
query_set = query_set.filter(**{'dataset_id': self.data.get("dataset_id")}) query_set = query_set.filter(**{'dataset_id': self.data.get("dataset_id")})
if 'name' in self.data and self.data.get('name') is not None: if 'name' in self.data and self.data.get('name') is not None:
query_set = query_set.filter(**{'name__icontains': self.data.get('name')}) query_set = query_set.filter(**{'name__icontains': self.data.get('name')})
if 'hit_handling_method' in self.data and self.data.get('hit_handling_method') is not None:
query_set = query_set.filter(**{'hit_handling_method': self.data.get('hit_handling_method')})
query_set = query_set.order_by('-create_time') query_set = query_set.order_by('-create_time')
return query_set return query_set
@ -143,7 +154,11 @@ class DocumentSerializers(ApiMixin, serializers.Serializer):
in_=openapi.IN_QUERY, in_=openapi.IN_QUERY,
type=openapi.TYPE_STRING, type=openapi.TYPE_STRING,
required=False, required=False,
description='文档名称')] description='文档名称'),
openapi.Parameter(name='hit_handling_method', in_=openapi.IN_QUERY,
type=openapi.TYPE_STRING,
required=False,
description='文档命中处理方式')]
@staticmethod @staticmethod
def get_response_body_api(): def get_response_body_api():
@ -252,7 +267,7 @@ class DocumentSerializers(ApiMixin, serializers.Serializer):
_document = QuerySet(Document).get(id=self.data.get("document_id")) _document = QuerySet(Document).get(id=self.data.get("document_id"))
if with_valid: if with_valid:
DocumentEditInstanceSerializer(data=instance).is_valid(document=_document) DocumentEditInstanceSerializer(data=instance).is_valid(document=_document)
update_keys = ['name', 'is_active', 'meta'] update_keys = ['name', 'is_active', 'hit_handling_method', 'meta']
for update_key in update_keys: for update_key in update_keys:
if update_key in instance and instance.get(update_key) is not None: if update_key in instance and instance.get(update_key) is not None:
_document.__setattr__(update_key, instance.get(update_key)) _document.__setattr__(update_key, instance.get(update_key))
@ -320,6 +335,8 @@ class DocumentSerializers(ApiMixin, serializers.Serializer):
properties={ properties={
'name': openapi.Schema(type=openapi.TYPE_STRING, title="文档名称", description="文档名称"), 'name': openapi.Schema(type=openapi.TYPE_STRING, title="文档名称", description="文档名称"),
'is_active': openapi.Schema(type=openapi.TYPE_BOOLEAN, title="是否可用", description="是否可用"), 'is_active': openapi.Schema(type=openapi.TYPE_BOOLEAN, title="是否可用", description="是否可用"),
'hit_handling_method': openapi.Schema(type=openapi.TYPE_STRING, title="命中处理方式",
description="ai优化:optimization,直接返回:directly_return"),
'meta': openapi.Schema(type=openapi.TYPE_OBJECT, title="文档元数据", 'meta': openapi.Schema(type=openapi.TYPE_OBJECT, title="文档元数据",
description="文档元数据->web:{source_url:xxx,selector:'xxx'},base:{}"), description="文档元数据->web:{source_url:xxx,selector:'xxx'},base:{}"),
} }

View File

@ -217,6 +217,10 @@ h4 {
align-items: baseline; align-items: baseline;
} }
.justify-center {
justify-content: center;
}
.text-left { .text-left {
text-align: left; text-align: left;
} }

View File

@ -24,6 +24,10 @@
background-color: var(--el-button-bg-color); background-color: var(--el-button-bg-color);
border-color: var(--el-button-border-color); border-color: var(--el-button-border-color);
} }
&.is-link:focus {
background: none;
border: none;
}
} }
.el-button--large { .el-button--large {
font-size: 16px; font-size: 16px;
@ -137,10 +141,16 @@
color: var(--app-text-color); color: var(--app-text-color);
font-weight: 400; font-weight: 400;
padding: 5px 11px; padding: 5px 11px;
&:not(.is-disabled):focus { &:not(.is-disabled):focus,
&:not(.is-active):focus {
background-color: var(--app-text-color-light-1); background-color: var(--app-text-color-light-1);
color: var(--app-text-color); color: var(--app-text-color);
} }
&.is-active,
&.is-active:hover {
color: var(--el-menu-active-color);
background: var(--el-color-primary-light-9);
}
} }
.el-tag { .el-tag {

View File

@ -21,15 +21,34 @@
type="textarea" type="textarea"
/> />
</el-form-item> </el-form-item>
<el-form-item v-else label="文档地址" prop="source_url"> <el-form-item v-else-if="documentType === '1'" label="文档地址" prop="source_url">
<el-input v-model="form.source_url" placeholder="请输入文档地址" /> <el-input v-model="form.source_url" placeholder="请输入文档地址" />
</el-form-item> </el-form-item>
<el-form-item label="选择器"> <el-form-item label="选择器" v-if="documentType === '1'">
<el-input <el-input
v-model="form.selector" v-model="form.selector"
placeholder="默认为 body可输入 .classname/#idname/tagname" placeholder="默认为 body可输入 .classname/#idname/tagname"
/> />
</el-form-item> </el-form-item>
<el-form-item v-if="!isImport">
<template #label>
<div class="flex align-center">
<span class="mr-4">命中处理方式</span>
<el-tooltip
effect="dark"
content="用户提问时,命中文档下的分段时按照设置的方式进行处理。"
placement="right"
>
<AppIcon iconName="app-warning" class="app-warning-icon"></AppIcon>
</el-tooltip>
</div>
</template>
<el-radio-group v-model="form.hit_handling_method">
<template v-for="(value, key) of hitHandlingMethod" :key="key">
<el-radio :value="key">{{ value }}</el-radio>
</template>
</el-radio-group>
</el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
@ -45,6 +64,7 @@ import { useRoute } from 'vue-router'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import documentApi from '@/api/document' import documentApi from '@/api/document'
import { MsgSuccess } from '@/utils/message' import { MsgSuccess } from '@/utils/message'
import { hitHandlingMethod } from '../utils'
const route = useRoute() const route = useRoute()
const { const {
@ -57,9 +77,11 @@ const loading = ref<boolean>(false)
const isImport = ref<boolean>(false) const isImport = ref<boolean>(false)
const form = ref<any>({ const form = ref<any>({
source_url: '', source_url: '',
selector: '' selector: '',
hit_handling_method: ''
}) })
const documentId = ref('') const documentId = ref('')
const documentType = ref<string | number>('') //1: web0:
const rules = reactive({ const rules = reactive({
source_url: [{ required: true, message: '请输入文档地址', trigger: 'blur' }] source_url: [{ required: true, message: '请输入文档地址', trigger: 'blur' }]
@ -71,16 +93,19 @@ watch(dialogVisible, (bool) => {
if (!bool) { if (!bool) {
form.value = { form.value = {
source_url: '', source_url: '',
selector: '' selector: '',
hit_handling_method: ''
} }
isImport.value = false isImport.value = false
documentType.value = ''
} }
}) })
const open = (row: any) => { const open = (row: any) => {
if (row) { if (row) {
documentType.value = row.type
documentId.value = row.id documentId.value = row.id
form.value = row.meta form.value = { hit_handling_method: row.hit_handling_method, ...row.meta }
isImport.value = false isImport.value = false
} else { } else {
isImport.value = true isImport.value = true
@ -104,7 +129,11 @@ const submit = async (formEl: FormInstance | undefined) => {
}) })
} else { } else {
const obj = { const obj = {
meta: form.value hit_handling_method: form.value.hit_handling_method,
meta: {
source_url: form.value.source_url,
selector: form.value.selector
}
} }
documentApi.putDocument(id, documentId.value, obj, loading).then((res) => { documentApi.putDocument(id, documentId.value, obj, loading).then((res) => {
MsgSuccess('设置成功') MsgSuccess('设置成功')

View File

@ -90,6 +90,39 @@
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column width="150">
<template #header>
<div>
<span>命中处理方式</span>
<el-dropdown trigger="click" @command="dropdownHandle">
<el-button style="margin-top: 1px" link :type="filterMethod ? 'primary' : ''">
<el-icon><Filter /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu style="width: 100px">
<el-dropdown-item
:class="filterMethod ? '' : 'is-active'"
command=""
class="justify-center"
>全部</el-dropdown-item
>
<template v-for="(value, key) of hitHandlingMethod" :key="key">
<el-dropdown-item
:class="filterMethod === key ? 'is-active' : ''"
class="justify-center"
:command="key"
>{{ value }}</el-dropdown-item
>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<template #default="{ row }">
{{ hitHandlingMethod[row.hit_handling_method] }}
</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" width="170"> <el-table-column prop="create_time" label="创建时间" width="170">
<template #default="{ row }"> <template #default="{ row }">
{{ datetimeFormat(row.create_time) }} {{ datetimeFormat(row.create_time) }}
@ -100,7 +133,7 @@
{{ datetimeFormat(row.update_time) }} {{ datetimeFormat(row.update_time) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="left"> <el-table-column label="操作" align="left" width="110">
<template #default="{ row }"> <template #default="{ row }">
<div v-if="datasetDetail.type === '0'"> <div v-if="datasetDetail.type === '0'">
<span v-if="row.status === '2'" class="mr-4"> <span v-if="row.status === '2'" class="mr-4">
@ -110,6 +143,13 @@
</el-button> </el-button>
</el-tooltip> </el-tooltip>
</span> </span>
<span class="mr-4">
<el-tooltip effect="dark" content="设置" placement="top">
<el-button type="primary" text @click.stop="settingDoc(row)">
<el-icon><Setting /></el-icon>
</el-button>
</el-tooltip>
</span>
<span> <span>
<el-tooltip effect="dark" content="删除" placement="top"> <el-tooltip effect="dark" content="删除" placement="top">
<el-button type="primary" text @click.stop="deleteDocument(row)"> <el-button type="primary" text @click.stop="deleteDocument(row)">
@ -165,6 +205,7 @@ import ImportDocumentDialog from './component/ImportDocumentDialog.vue'
import SyncWebDialog from '@/views/dataset/component/SyncWebDialog.vue' import SyncWebDialog from '@/views/dataset/component/SyncWebDialog.vue'
import { numberFormat } from '@/utils/utils' import { numberFormat } from '@/utils/utils'
import { datetimeFormat } from '@/utils/time' import { datetimeFormat } from '@/utils/time'
import { hitHandlingMethod } from './utils'
import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message' import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message'
import useStore from '@/stores' import useStore from '@/stores'
const router = useRouter() const router = useRouter()
@ -186,7 +227,10 @@ onBeforeRouteLeave((to: any, from: any) => {
common.savePage(storeKey, null) common.savePage(storeKey, null)
common.saveCondition(storeKey, null) common.saveCondition(storeKey, null)
} else { } else {
common.saveCondition(storeKey, filterText.value) common.saveCondition(storeKey, {
filterText: filterText.value,
filterMethod: filterMethod.value
})
} }
}) })
const beforePagination = computed(() => common.paginationConfig[storeKey]) const beforePagination = computed(() => common.paginationConfig[storeKey])
@ -196,6 +240,7 @@ const SyncWebDialogRef = ref()
const loading = ref(false) const loading = ref(false)
let interval: any let interval: any
const filterText = ref('') const filterText = ref('')
const filterMethod = ref<string | number>('')
const documentData = ref<any[]>([]) const documentData = ref<any[]>([])
const currentMouseId = ref(null) const currentMouseId = ref(null)
const datasetDetail = ref<any>({}) const datasetDetail = ref<any>({})
@ -211,6 +256,11 @@ const multipleTableRef = ref<InstanceType<typeof ElTable>>()
const multipleSelection = ref<any[]>([]) const multipleSelection = ref<any[]>([])
const title = ref('') const title = ref('')
function dropdownHandle(val: string) {
filterMethod.value = val
getList()
}
function syncDataset() { function syncDataset() {
SyncWebDialogRef.value.open(id) SyncWebDialogRef.value.open(id)
} }
@ -378,13 +428,12 @@ function handleSizeChange() {
} }
function getList(bool?: boolean) { function getList(bool?: boolean) {
const param = {
...(filterText.value && { name: filterText.value }),
...(filterMethod.value && { hit_handling_method: filterMethod.value })
}
documentApi documentApi
.getDocument( .getDocument(id as string, paginationConfig.value, param, bool ? undefined : loading)
id as string,
paginationConfig.value,
filterText.value && { name: filterText.value },
bool ? undefined : loading
)
.then((res) => { .then((res) => {
documentData.value = res.data.records documentData.value = res.data.records
paginationConfig.value.total = res.data.total paginationConfig.value.total = res.data.total
@ -408,7 +457,8 @@ onMounted(() => {
paginationConfig.value = beforePagination.value paginationConfig.value = beforePagination.value
} }
if (beforeSearch.value) { if (beforeSearch.value) {
filterText.value = beforeSearch.value filterText.value = beforeSearch.value['filterText']
filterMethod.value = beforeSearch.value['filterMethod']
} }
getList() getList()
// //

View File

@ -0,0 +1,4 @@
export const hitHandlingMethod: any = {
optimization: '模型优化',
directly_return: '直接回答'
}