fix(query): 知识库更新

- 修复切换知识库之后,检索结果没有刷新
- 修复文件上传模块 UI的边距、配色有问题
This commit is contained in:
Wenjie Zhang 2025-08-05 22:58:30 +08:00
parent f1098f0c7d
commit b23bbe023f
4 changed files with 62 additions and 72 deletions

View File

@ -13,9 +13,11 @@
🐛**BUGs**
- [x] 智能体的工具切换有问题
- [ ] 知识图谱可视化页面的效果有点问题
- [x] 知识图谱可视化页面的效果有点问题
- [x] 处理失败的文件,在特定情况下会一直处于 processing 状态,且无法删除
- [ ] 与最新的 LightRAG 版本兼容性存在问题 #233
- [x] 与最新的 LightRAG 版本兼容性存在问题 #233
- [x] 切换知识库之后,检索结果没有刷新
- [x] 文件上传模块 UI的边距、配色有问题
# 💯 More:
@ -23,21 +25,6 @@
- [ ] 封装现有工具为 mcpstdio调用
- [ ] 支持额外 mcp 配置(代码端)
- [ ] 添加用户日志与用户反馈模块,可以在 AgentView 中查看信息(🌟🌟)
- [ ] 对话页面支持文档/图片临时上传(🌟🌟🌟🌟)
- [ ] 添加用户日志与用户反馈模块,可以在 AgentView 中查看信息
- [ ] 对话页面支持文档/图片临时上传
- [ ] 优化对文档信息的检索展示(检索结果页、详情页)
TODO1知识库页面的文档信息的查看检索结果页、详情页
根据这个模糊的分析,判断一下这个需求应该如何实现,务必阅读所有相关的文献,包括但不限于当前代码中,保存文本片段的时候所保存的信息是否支撑功能的实现,当某些需求无法实现的时候,能否采用退而求其次的方法实现略差一些的功能(不要过度增加代码的复杂度)。
模糊的需求如下:先实现在 FileTable.vue, FileDetailModal.vue 中,点击文件详情按钮,能够弹出文件详情的弹窗,显示的方法有两种,一种是以现在的 chunk 的形式展示,一种是以 markdown渲染全文的形式但是存在 overlap 拼接的问题。
关于全文 Markdown 的获取:目前 Milvus、Chroma 知识库里面没有存储 fulltext需要对现有的 chunk 片段做合并,但是因为存在 overlap所以需要想办法去除 overlap。如果有 start_idx 和 end_idx 就好办了(不一定有这两个参数)。请注意,直接读取源文件的方法是错的,因为源文件并不全是 markdown 格式,可能是 html、pdf 等结构文件,因此,只能想办法拼接,而不是尝试读取文件。项目中已经安装了 md-editor-v3 ,可以参考 AgentMessageComponent.vue 中对于 markdown 的渲染。
先告诉我你要如何实现这些功能,重点实现的是 milvus db 和 chroma db lightrag db 尽量实现,实现不了也没事。相关的上下文如下 knowledge_router.py knowledge_base.py DataBaseInfoView.vue。
TODO2检索以及知识库工具调用情况下的片段展示
result 中可以按照 file_id 聚合信息;信息的展示以结果卡片的形式展示,卡片之间有间隔,卡片中可以选择点击查看全文或者下载原文件。下载源文件需要根据 file_id 可以从后端获取文件的基本信息比如可下载的路径chunks 等信息;在 @web/src/components/ToolCallingResult/KnowledgeBaseResult.vue 文件中,添加点击某个片段的时候可以弹出信息预览框(最好可以提供源文件下载的功能)这里可以复用 FileDetailModal.vue 组件。

View File

@ -455,12 +455,16 @@ const chunkData = async () => {
</script>
<style scoped>
<style lang="less" scoped>
.add-files-content {
padding: 16px 0;
display: flex;
flex-direction: column;
height: 100%;
.ant-form-item {
margin: 0;
}
}
.upload-header {
@ -477,20 +481,20 @@ const chunkData = async () => {
.upload-mode-selector {
padding: 8px 16px;
border: 1px solid #d9d9d9;
border-radius: 4px;
border: 1px solid var(--gray-300);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
}
.upload-mode-selector:hover {
border-color: #1890ff;
border-color: var(--main-color);
}
.upload-mode-selector.active {
border-color: #1890ff;
background-color: #e6f7ff;
color: #1890ff;
border-color: var(--main-color);
background-color: var(--main-30);
color: var(--main-color);
}
.config-controls {
@ -502,8 +506,8 @@ const chunkData = async () => {
.qa-split-config {
margin-bottom: 20px;
padding: 16px;
background-color: #fafafa;
border-radius: 4px;
background-color: var(--gray-50);
border-radius: 6px;
}
.toggle-controls {
@ -513,7 +517,7 @@ const chunkData = async () => {
.param-description {
font-size: 12px;
color: #8c8c8c;
color: var(--gray-600);
margin-top: 4px;
}
@ -531,7 +535,7 @@ const chunkData = async () => {
.url-hint {
font-size: 12px;
color: #8c8c8c;
color: var(--gray-600);
margin-top: 8px;
}

View File

@ -110,6 +110,7 @@
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { useDatabaseStore } from '@/stores/database';
import { message } from 'ant-design-vue';
import { queryApi } from '@/apis/knowledge_api';
import {
SearchOutlined,
SettingOutlined,
@ -144,7 +145,7 @@ const meta = computed({
get: () => store.meta,
set: (value) => Object.assign(store.meta, value)
});
const queryResult = computed(() => store.queryResult);
const queryResult = ref('');
//
const queryText = ref('');
@ -171,12 +172,47 @@ const toggleVisible = () => {
emit('toggleVisible');
};
const onQuery = () => {
const onQuery = async () => {
if (!queryText.value.trim()) {
message.error('请输入查询内容');
return;
}
store.onQuery(queryText.value.trim());
store.state.searchLoading = true;
//
const supportedParamKeys = new Set(queryParams.value.map(param => param.key));
const queryMeta = {};
console.log('Supported param keys:', Array.from(supportedParamKeys));
console.log('All meta params:', meta.value);
console.log('Database info:', store.database);
// meta
for (const [key, value] of Object.entries(meta.value)) {
// db_id
if (key === 'db_id') continue;
//
if (supportedParamKeys.has(key)) {
queryMeta[key] = value;
} else {
console.log(`Skipping unsupported parameter: ${key}`);
}
}
console.log('Filtered query meta:', queryMeta);
try {
const data = await queryApi.queryTest(store.database.db_id, queryText.value.trim(), queryMeta);
queryResult.value = data;
} catch (error) {
console.error(error);
message.error(error.message);
queryResult.value = '';
} finally {
store.state.searchLoading = false;
}
};
const useQueryExample = (example) => {

View File

@ -12,7 +12,7 @@ export const useDatabaseStore = defineStore('database', () => {
const database = ref({});
const databaseId = ref(null);
const selectedFile = ref(null);
const queryResult = ref('');
const queryParams = ref([]);
const meta = reactive({});
const graphStats = ref({
@ -266,43 +266,7 @@ export const useDatabaseStore = defineStore('database', () => {
}
}
async function onQuery(queryText) {
state.searchLoading = true;
queryResult.value = '';
// 确保只传递当前知识库类型支持的参数
const supportedParamKeys = new Set(queryParams.value.map(param => param.key));
const queryMeta = {};
console.log('Supported param keys:', Array.from(supportedParamKeys));
console.log('All meta params:', meta);
console.log('Database info:', database.value);
// 遍历 meta 中的参数,只保留当前知识库类型支持的参数
for (const [key, value] of Object.entries(meta)) {
// 跳过 db_id 参数
if (key === 'db_id') continue;
// 只保留当前知识库类型支持的参数
if (supportedParamKeys.has(key)) {
queryMeta[key] = value;
} else {
console.log(`Skipping unsupported parameter: ${key}`);
}
}
console.log('Filtered query meta:', queryMeta);
try {
const data = await queryApi.queryTest(database.value.db_id, queryText, queryMeta);
queryResult.value = data;
} catch (error) {
console.error(error);
message.error(error.message);
} finally {
state.searchLoading = false;
}
}
function startAutoRefresh() {
if (state.autoRefresh && !refreshInterval) {
@ -348,7 +312,6 @@ export const useDatabaseStore = defineStore('database', () => {
database,
databaseId,
selectedFile,
queryResult,
queryParams,
meta,
graphStats,
@ -363,7 +326,7 @@ export const useDatabaseStore = defineStore('database', () => {
addFiles,
openFileDetail,
loadQueryParams,
onQuery,
startAutoRefresh,
stopAutoRefresh,
toggleAutoRefresh,