瀏覽代碼

feat:添加知识库表信息获取

ZengChao 1 月之前
父節點
當前提交
231cf30e78

+ 4 - 4
.env

@@ -40,17 +40,17 @@ SMTP_SSL=False
 # 文件上传配置
 UPLOAD_DIR=./uploads
 MAX_FILE_SIZE=5242880
-ALLOWED_EXTENSIONS=jpg,jpeg,png,gif
+ALLOWED_EXTENSIONS=["jpg","jpeg","png","gif"]
 
 # 日志配置
 LOG_LEVEL=INFO
 LOG_FILE=./logs/app.log
 
 # CORS配置
-CORS_ORIGINS=http://localhost:3000,http://localhost:8080,http://localhost:3001
+CORS_ORIGINS=["http://localhost:3000","http://localhost:8080","http://localhost:3001"]
 CORS_CREDENTIALS=True
-CORS_METHODS=*
-CORS_HEADERS=*
+CORS_METHODS=["*"]
+CORS_HEADERS=["*"]
 
 # 安全配置
 BCRYPT_ROUNDS=12

+ 3 - 0
.gitignore

@@ -2,3 +2,6 @@
 __pycache__/
 *.py[cod]
 *$py.class
+
+# cursor
+.cursorrules

+ 4 - 1
requirements/base.txt

@@ -41,4 +41,7 @@ celery==5.3.4
 flower==2.0.1
 
 # 开发工具
-python-dotenv==1.0.0
+python-dotenv==1.0.0
+
+# 向量数据库
+pymilvus==2.3.4

+ 0 - 0
src/__init__.py


+ 0 - 0
src/app/api/v1/document/knowledge_base.py


+ 43 - 0
src/app/config/milvus.py

@@ -0,0 +1,43 @@
+"""
+Milvus 管理器:只负责初始化并持有 MilvusClient(单 DB、单 Client)
+"""
+from __future__ import annotations
+
+import logging
+from typing import Optional
+
+from pymilvus import MilvusClient
+from .settings import settings
+
+logger = logging.getLogger(__name__)
+
+
+class MilvusManager:
+    def __init__(self):
+        self.host: str = settings.MILVUS_HOST
+        self.port: int = settings.MILVUS_PORT
+        self.db_name: str = settings.MILVUS_DB
+        self.user: Optional[str] = settings.MILVUS_USER
+        self.password: Optional[str] = settings.MILVUS_PASSWORD
+
+        self.uri = f"http://{self.host}:{self.port}"
+        logger.info(f"Init MilvusClient uri={self.uri}, db={self.db_name}")
+
+        # ✅ 只初始化一次
+        self.client = MilvusClient(
+            uri=self.uri,
+            user=self.user or "",
+            password=self.password or "",
+            db_name=self.db_name,
+        )
+
+    def close(self) -> None:
+        self.client.close()
+
+
+# 全局单例
+milvus_manager = MilvusManager()
+
+
+def get_milvus_manager() -> MilvusManager:
+    return milvus_manager

+ 12 - 5
src/app/config/settings.py

@@ -2,7 +2,7 @@
 应用配置模块
 """
 from typing import List, Optional
-from pydantic import field_validator
+from pydantic import field_validator, Field
 from pydantic_settings import BaseSettings
 from functools import lru_cache
 import os
@@ -52,17 +52,17 @@ class Settings(BaseSettings):
     # 文件上传配置
     UPLOAD_DIR: str = "./uploads"
     MAX_FILE_SIZE: int = 5242880  # 5MB
-    ALLOWED_EXTENSIONS: str = "jpg,jpeg,png,gif"
+    ALLOWED_EXTENSIONS: list[str] = Field(default_factory=lambda: ["jpg", "jpeg", "png", "gif"])
     
     # 日志配置
     LOG_LEVEL: str = "INFO"
     LOG_FILE: str = "./logs/app.log"
     
     # CORS配置
-    CORS_ORIGINS: str = "http://localhost:3000,http://localhost:8080,http://localhost:3001"
+    CORS_ORIGINS: list[str] = Field(default_factory=list)
     CORS_CREDENTIALS: bool = True
-    CORS_METHODS: str = "*"
-    CORS_HEADERS: str = "*"
+    CORS_METHODS: list[str] = Field(default_factory=lambda: ["*"])
+    CORS_HEADERS: list[str] = Field(default_factory=lambda: ["*"])
     
     # 安全配置
     BCRYPT_ROUNDS: int = 12
@@ -78,6 +78,13 @@ class Settings(BaseSettings):
     CELERY_BROKER_URL: str = "redis://localhost:6379/1"
     CELERY_RESULT_BACKEND: str = "redis://localhost:6379/2"
     
+    # Milvus配置
+    MILVUS_HOST: str = "192.168.92.61"
+    MILVUS_PORT: int = 19530
+    MILVUS_DB: str = "lq_db"
+    MILVUS_USER: Optional[str] = "lq"
+    MILVUS_PASSWORD: Optional[str] = "lq123456!"
+    
     @field_validator("ALLOWED_EXTENSIONS", mode="before")
     @classmethod
     def parse_allowed_extensions(cls, v):

+ 1 - 1
src/app/services/__init__.py

@@ -1 +1 @@
-"""服务模块"""
+"""服务模块"""

+ 81 - 0
src/app/services/milvus_service.py

@@ -0,0 +1,81 @@
+"""
+Milvus Service:业务层(直接用 manager.client 调 Milvus 原生方法)
+"""
+from __future__ import annotations
+
+import logging
+from typing import List, Dict, Any
+from datetime import datetime
+
+from src.app.config.milvus import get_milvus_manager
+
+logger = logging.getLogger(__name__)
+
+
+class MilvusService:
+    def __init__(self):
+        self.client = get_milvus_manager().client
+
+    def get_collection_details(self) -> List[Dict[str, Any]]:
+        """
+        获取所有 Collections 详细信息(按你的要求):
+        - 时间转换直接写在这里:physical_ms = ts_int >> 18
+        - load state / row_count 不保底:拿不到就让异常抛出
+        - 直接调用 MilvusClient 原生方法(不再二次封装)
+        """
+        details: List[Dict[str, Any]] = []
+
+        names = self.client.list_collections()
+
+        for name in names:
+            desc = self.client.describe_collection(collection_name=name)
+            stats = self.client.get_collection_stats(collection_name=name)
+            load_state = self.client.get_load_state(collection_name=name)
+
+            # ===== 时间戳转换(按你指定写法,无封装)=====
+            created_time = None
+            updated_time = None
+
+            if desc.get("created_timestamp") is not None:
+                ts_int = int(desc["created_timestamp"])
+                physical_ms = ts_int >> 18
+                created_time = datetime.fromtimestamp(physical_ms / 1000).strftime("%Y-%m-%d %H:%M:%S")
+
+            if desc.get("update_timestamp") is not None:
+                ts_int = int(desc["update_timestamp"])
+                physical_ms = ts_int >> 18
+                updated_time = datetime.fromtimestamp(physical_ms / 1000).strftime("%Y-%m-%d %H:%M:%S")
+
+            # ===== 数量:不保底(要求返回结构必须有 row_count)=====
+            entity_count = stats["row_count"]
+
+            # ===== 状态:不保底(要求返回结构必须有 state)=====
+            status = load_state["state"]
+
+            details.append(
+                {
+                    "name": name,
+                    "status": status,
+                    "entity_count": entity_count,
+                    "description": desc.get("description", ""),
+                    "created_time": created_time,
+                    "updated_time": updated_time,
+                }
+            )
+
+        logger.info(f"成功获取Collections详细信息,共{len(details)}个")
+        return details
+
+
+# 可选:单例
+milvus_service = MilvusService()
+
+
+if __name__ == "__main__":
+    # 推荐这样跑:
+    # uv run python -m src.app.services.milvus_service
+    import json
+
+    data = MilvusService().get_collection_details()
+    for item in data:
+        print(json.dumps(item, ensure_ascii=False, indent=2))