From 04f6cb5a7996b6361f569f998cb367300fbf2caf Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Sun, 27 Jul 2025 13:02:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(milvus=5Fkb):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=88=A0=E9=99=A4=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=87=E4=BB=B6=E5=AD=98=E5=9C=A8=E6=80=A7?= =?UTF-8?q?=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/knowledge/milvus_kb.py | 36 +++++++++++++++-------- web/src/views/DataBaseInfoView.vue | 46 ++++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/knowledge/milvus_kb.py b/src/knowledge/milvus_kb.py index be4d6fae..f0a7727a 100644 --- a/src/knowledge/milvus_kb.py +++ b/src/knowledge/milvus_kb.py @@ -311,8 +311,8 @@ class MilvusKB(KnowledgeBase): try: # 设置查询参数 - Milvus 知识库特有的参数 - top_k = kwargs.get("top_k", 10) - similarity_threshold = kwargs.get("similarity_threshold", 0.0) # 相似度阈值 + top_k = kwargs.get("top_k", 30) + similarity_threshold = kwargs.get("similarity_threshold", 0.2) # 相似度阈值 include_distances = kwargs.get("include_distances", True) # 是否包含距离信息 metric_type = kwargs.get("metric_type", "COSINE") # 距离度量类型 @@ -367,19 +367,31 @@ class MilvusKB(KnowledgeBase): """删除文件""" collection = await self._get_milvus_collection(db_id) - def _delete_from_milvus(): - """同步执行 Milvus 删除操作的辅助函数""" + if collection: + # 先查询文件是否存在,避免不必要的删除操作 try: expr = f'file_id == "{file_id}"' - collection.delete(expr) - collection.flush() - logger.info(f"Deleted chunks for file {file_id} from Milvus") + results = collection.query( + expr=expr, + output_fields=["id"], + limit=1 + ) + + if not results: + logger.info(f"File {file_id} not found in Milvus, skipping delete operation") + else: + # 只有在文件确实存在时才执行删除 + def _delete_from_milvus(): + try: + collection.delete(expr) + collection.flush() + logger.info(f"Deleted chunks for file {file_id} from Milvus") + except Exception as e: + logger.error(f"Error deleting file {file_id} from Milvus: {e}") + + await asyncio.to_thread(_delete_from_milvus) except Exception as e: - logger.error(f"Error deleting file {file_id} from Milvus: {e}") - - if collection: - await asyncio.to_thread(_delete_from_milvus) - + logger.error(f"Error checking file existence in Milvus: {e}") # 使用锁确保元数据操作的原子性 async with self._metadata_lock: if file_id in self.files_meta: diff --git a/web/src/views/DataBaseInfoView.vue b/web/src/views/DataBaseInfoView.vue index f13fed45..9ef11399 100644 --- a/web/src/views/DataBaseInfoView.vue +++ b/web/src/views/DataBaseInfoView.vue @@ -271,7 +271,7 @@
- {{ formatRelativeTime(Math.round(selectedFile.created_at*1000)) }} + {{ formatStandardTime(Math.round(selectedFile.created_at*1000)) }}
@@ -1033,9 +1033,10 @@ const openFileDetail = (record) => { } } +// Format relative time with more granularity: days ago, weeks ago, months ago const formatRelativeTime = (timestamp, offset = 0) => { - // 如果调整为东八区时间(UTC+8),则offset为8,否则为0 - const timezoneOffset = offset * 60 * 60 * 1000; // 东八区偏移量(毫秒) + // If you want to adjust to UTC+8, set offset to 8, otherwise 0 + const timezoneOffset = offset * 60 * 60 * 1000; // offset in milliseconds const adjustedTimestamp = timestamp + timezoneOffset; const now = Date.now(); @@ -1047,7 +1048,17 @@ const formatRelativeTime = (timestamp, offset = 0) => { return Math.round(secondsPast / 60) + ' 分钟前'; } else if (secondsPast < 86400) { return Math.round(secondsPast / 3600) + ' 小时前'; + } else if (secondsPast < 86400 * 7) { + // Less than 7 days + return Math.round(secondsPast / 86400) + ' 天前'; + } else if (secondsPast < 86400 * 30) { + // Less than 30 days, show in weeks + return Math.round(secondsPast / (86400 * 7)) + ' 周前'; + } else if (secondsPast < 86400 * 365) { + // Less than 1 year, show in months + return Math.round(secondsPast / (86400 * 30)) + ' 月前'; } else { + // More than 1 year, show full date const date = new Date(adjustedTimestamp); const year = date.getFullYear(); const month = date.getMonth() + 1; @@ -1056,6 +1067,17 @@ const formatRelativeTime = (timestamp, offset = 0) => { } } +const formatStandardTime = (timestamp) => { + const date = new Date(timestamp); + const year = date.getFullYear(); + const month = date.getMonth() + 1; + const day = date.getDate(); + const hour = date.getHours(); + const minute = date.getMinutes(); + const second = date.getSeconds(); + return `${year} 年 ${month} 月 ${day} 日 ${hour}:${minute}:${second}`; +} + const getDatabaseInfo = () => { const db_id = databaseId.value @@ -1654,6 +1676,15 @@ const columnsCompact = [ sorter: (a, b) => (a.filename || '').localeCompare(b.filename || ''), sortDirections: ['ascend', 'descend'] }, + { + title: '时间', + dataIndex: 'created_at', + key: 'created_at', + width: 120, + align: 'right', + sorter: (a, b) => (a.created_at || 0) - (b.created_at || 0), + sortDirections: ['ascend', 'descend'] + }, { title: '状态', dataIndex: 'status', @@ -1666,15 +1697,6 @@ const columnsCompact = [ }, sortDirections: ['ascend', 'descend'] }, - { - title: '时间', - dataIndex: 'created_at', - key: 'created_at', - width: 80, - align: 'right', - sorter: (a, b) => (a.created_at || 0) - (b.created_at || 0), - sortDirections: ['ascend', 'descend'] - }, { title: '', key: 'action', dataIndex: 'file_id', width: 40, align: 'center' } ];