fix(query): 知识库更新
- 修复切换知识库之后,检索结果没有刷新 - 修复文件上传模块 UI的边距、配色有问题
This commit is contained in:
parent
f1098f0c7d
commit
b23bbe023f
@ -13,9 +13,11 @@
|
||||
|
||||
🐛**BUGs**
|
||||
- [x] 智能体的工具切换有问题
|
||||
- [ ] 知识图谱可视化页面的效果有点问题
|
||||
- [x] 知识图谱可视化页面的效果有点问题
|
||||
- [x] 处理失败的文件,在特定情况下会一直处于 processing 状态,且无法删除
|
||||
- [ ] 与最新的 LightRAG 版本兼容性存在问题 #233
|
||||
- [x] 与最新的 LightRAG 版本兼容性存在问题 #233
|
||||
- [x] 切换知识库之后,检索结果没有刷新
|
||||
- [x] 文件上传模块 UI的边距、配色有问题
|
||||
|
||||
# 💯 More:
|
||||
|
||||
@ -23,21 +25,6 @@
|
||||
|
||||
- [ ] 封装现有工具为 mcp(stdio)调用
|
||||
- [ ] 支持额外 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 组件。
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) => {
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user