From b08a3a2ee2ef8c1855697747651d6286bf453339 Mon Sep 17 00:00:00 2001
From: xiao12feng8 <16507319+xiao12feng8@user.noreply.gitee.com>
Date: Mon, 22 Dec 2025 12:12:08 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9ERAG=E6=97=A5=E5=BF=97?=
=?UTF-8?q?=E4=B8=8E=E4=BA=8B=E4=BB=B6=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9D=83?=
=?UTF-8?q?=E9=99=90=E9=A1=B5=E9=9D=A2=E7=A7=BB=E9=99=A4=E5=88=A0=E9=99=A4?=
=?UTF-8?q?=E6=8C=89=E9=92=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
rag-python/app.py | 65 ++++++++++++++++---
rag-python/event_store.py | 29 +++++++++
.../src/views/psychology/permission/index.vue | 3 -
3 files changed, 86 insertions(+), 11 deletions(-)
create mode 100644 rag-python/event_store.py
diff --git a/rag-python/app.py b/rag-python/app.py
index 2e952195..7b4b26ad 100644
--- a/rag-python/app.py
+++ b/rag-python/app.py
@@ -5,15 +5,46 @@ RAG 知识库服务 - Flask API
"""
import os
import sys
+import logging
+from logging.handlers import RotatingFileHandler
from flask import Flask, request, jsonify
from flask_cors import CORS
from config import HOST, PORT, KNOWLEDGE_DIR, BASE_DIR
from knowledge_service import knowledge_service
from file_watcher import FileWatcher
+from event_store import get_events, record_event
app = Flask(__name__)
CORS(app) # 允许跨域请求
+
+def _setup_logging():
+ log_dir = os.path.join(BASE_DIR, "logs")
+ os.makedirs(log_dir, exist_ok=True)
+ log_path = os.path.join(log_dir, "rag-python.log")
+
+ root = logging.getLogger()
+ if root.handlers:
+ return
+
+ root.setLevel(logging.INFO)
+ file_handler = RotatingFileHandler(
+ log_path,
+ maxBytes=10 * 1024 * 1024,
+ backupCount=10,
+ encoding="utf-8",
+ )
+ formatter = logging.Formatter(
+ fmt="%(asctime)s [%(levelname)s] %(name)s - %(message)s",
+ datefmt="%Y-%m-%d %H:%M:%S",
+ )
+ file_handler.setFormatter(formatter)
+ root.addHandler(file_handler)
+
+
+_setup_logging()
+log = logging.getLogger("rag.app")
+
# 文件监控器
file_watcher = None
@@ -27,6 +58,18 @@ def health_check():
'base_dir': BASE_DIR
})
+
+@app.route('/api/events', methods=['GET'])
+def list_events():
+ """返回最近的索引事件(用于隐藏窗口时查看索引更新情况)"""
+ try:
+ limit = request.args.get('limit', default=None, type=int)
+ events = get_events(limit=limit, newest_first=True)
+ return jsonify({'success': True, 'data': events})
+ except Exception as e:
+ log.exception("Failed to list events")
+ return jsonify({'success': False, 'error': str(e)}), 500
+
@app.route('/api/documents', methods=['GET'])
def list_documents():
"""列出所有文档"""
@@ -210,25 +253,31 @@ def rag_analyze():
def init_service():
"""初始化服务"""
- print("=" * 50)
- print("RAG 知识库服务启动中...")
- print("=" * 50)
+ log.info("%s", "=" * 50)
+ log.info("RAG 知识库服务启动中...")
+ log.info("%s", "=" * 50)
+ record_event("service_start", knowledge_dir=KNOWLEDGE_DIR, base_dir=BASE_DIR)
# 初始化知识库服务
knowledge_service.init()
+ record_event("index_loaded")
# 扫描并索引新文件
- knowledge_service.scan_and_index_folder()
+ scan_result = knowledge_service.scan_and_index_folder()
+ record_event("startup_scan", result=scan_result)
# 启动文件监控
global file_watcher
file_watcher = FileWatcher(knowledge_service)
file_watcher.start()
+
+ record_event("watcher_started", path=KNOWLEDGE_DIR)
- print("=" * 50)
- print(f"服务已启动: http://{HOST}:{PORT}")
- print(f"知识库文件夹: {KNOWLEDGE_DIR}")
- print("=" * 50)
+ log.info("%s", "=" * 50)
+ log.info("服务已启动: http://%s:%s", HOST, PORT)
+ log.info("知识库文件夹: %s", KNOWLEDGE_DIR)
+ log.info("%s", "=" * 50)
+ record_event("service_ready", host=HOST, port=PORT)
if __name__ == '__main__':
init_service()
diff --git a/rag-python/event_store.py b/rag-python/event_store.py
new file mode 100644
index 00000000..c2337989
--- /dev/null
+++ b/rag-python/event_store.py
@@ -0,0 +1,29 @@
+from __future__ import annotations
+
+from collections import deque
+from datetime import datetime, timezone
+from threading import Lock
+from typing import Any, Dict, List, Optional
+
+_events: "deque[Dict[str, Any]]" = deque(maxlen=2000)
+_lock = Lock()
+
+
+def record_event(event_type: str, **payload: Any) -> None:
+ event = {
+ "ts": datetime.now(timezone.utc).isoformat(),
+ "type": event_type,
+ "payload": payload,
+ }
+ with _lock:
+ _events.append(event)
+
+
+def get_events(limit: Optional[int] = None, newest_first: bool = True) -> List[Dict[str, Any]]:
+ with _lock:
+ items = list(_events)
+ if newest_first:
+ items.reverse()
+ if limit is not None:
+ return items[: max(0, limit)]
+ return items
diff --git a/xinli-ui/src/views/psychology/permission/index.vue b/xinli-ui/src/views/psychology/permission/index.vue
index 66c739ae..b92e8f96 100644
--- a/xinli-ui/src/views/psychology/permission/index.vue
+++ b/xinli-ui/src/views/psychology/permission/index.vue
@@ -62,9 +62,6 @@
新增
-
- 删除
-