新增RAG日志与事件接口,权限页面移除删除按钮
This commit is contained in:
parent
ca07f08e67
commit
b08a3a2ee2
|
|
@ -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()
|
||||
|
||||
print("=" * 50)
|
||||
print(f"服务已启动: http://{HOST}:{PORT}")
|
||||
print(f"知识库文件夹: {KNOWLEDGE_DIR}")
|
||||
print("=" * 50)
|
||||
record_event("watcher_started", path=KNOWLEDGE_DIR)
|
||||
|
||||
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()
|
||||
|
|
|
|||
29
rag-python/event_store.py
Normal file
29
rag-python/event_store.py
Normal file
|
|
@ -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
|
||||
|
|
@ -62,9 +62,6 @@
|
|||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['psychology:permission:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['psychology:permission:remove']">删除</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user