init: RAG 知识库服务初始提交

- 后端 API(Flask + Gunicorn)
- RAG 引擎(混合检索 + 云端 Reranker + 引用溯源)
- 文档解析(MinerU + 多格式支持)
- Docker 生产部署配置
- 排除前端项目、敏感配置、模型文件
This commit is contained in:
lacerate551
2026-06-04 17:35:27 +08:00
commit 100d1a06eb
158 changed files with 64534 additions and 0 deletions

311
api/sync_routes.py Normal file
View File

@@ -0,0 +1,311 @@
"""
知识库同步 API
本模块提供文档同步服务的管理接口,包括:
- 手动触发同步
- 同步状态查询
- 文件监控控制
路由列表:
POST /sync : 手动触发同步
GET /sync/status : 获取同步状态
GET /sync/history : 同步历史记录
GET /sync/changes : 变更日志
POST /sync/start : 启动文件监控
POST /sync/stop : 停止文件监控
架构说明:
- 同步服务负责检测文档变更并自动向量化
- 订阅通知功能由后端服务负责
- 权限验证由后端网关完成
同步流程:
1. 扫描文档目录
2. 计算文件哈希,与历史记录对比
3. 检测新增、修改、删除的文件
4. 解析变更文件并更新向量库
Example:
curl -X POST http://localhost:5001/sync \\
-H "Authorization: Bearer mock-token-admin"
"""
from typing import Optional, Tuple, Any
from flask import Blueprint, request, jsonify, current_app
import logging
logger = logging.getLogger(__name__)
from auth.gateway import require_gateway_auth
from core.status_codes import SYNC_SUCCESS, SYNC_ERROR, INTERNAL_ERROR
from api.response_utils import success_response, error_response
sync_bp = Blueprint('sync', __name__)
def _get_sync_service() -> Optional[Any]:
"""
获取同步服务实例
Returns:
同步服务实例,不可用时返回 None
"""
try:
return current_app.config.get('SYNC_SERVICE')
except Exception as e:
logger.debug(f"获取同步服务失败: {e}")
return None
def _require_sync_service() -> Tuple[Optional[Any], Optional[Tuple]]:
"""
检查同步服务是否可用
Returns:
元组 (sync_service, error_response)
- 成功时 error_response 为 None
- 失败时 sync_service 为 None
"""
service = _get_sync_service()
if not service:
return None, error_response(
error="SERVICE_UNAVAILABLE",
error_code=INTERNAL_ERROR,
message="同步服务未启用",
http_status=503
)
return service, None
# ==================== 同步 API ====================
@sync_bp.route('/sync', methods=['POST'])
@require_gateway_auth
def trigger_sync() -> Tuple[Any, int]:
"""
手动触发知识库同步
扫描文档目录,检测变更并执行向量化处理。
请求体 (可选):
{
"collection": "向量库名称", // 可选,不传则同步所有
"full_sync": false // 是否全量同步
}
Returns:
成功: {"success": true, "data": {"result": {...}}}
失败: {"error": "...", "error_code": "..."}
Example:
curl -X POST http://localhost:5001/sync \\
-H "Authorization: Bearer mock-token-admin"
"""
service, err = _require_sync_service()
if err:
return err
try:
result = service.sync_now()
return success_response(
data={"result": result.to_dict() if hasattr(result, 'to_dict') else result},
status_code=SYNC_SUCCESS,
message="同步完成"
)
except Exception as e:
return error_response(
error="SYNC_ERROR",
error_code=SYNC_ERROR,
message=str(e),
http_status=500
)
@sync_bp.route('/sync/status', methods=['GET'])
@require_gateway_auth
def get_sync_status() -> Tuple[Any, int]:
"""
获取同步状态
返回同步服务的当前状态,包括:
- 是否启用
- 文件监控是否运行
- 最后同步时间
- 跟踪的文档数量
Returns:
{
"enabled": bool,
"monitoring": bool,
"last_sync": "ISO 8601",
"documents_tracked": N
}
"""
service, err = _require_sync_service()
if err:
return jsonify({
"status": "failed",
"status_code": INTERNAL_ERROR,
"enabled": False,
"message": "同步服务未启用"
})
try:
# 获取状态信息
status = {
"enabled": True,
"monitoring": service.is_running() if hasattr(service, 'is_running') else False,
"last_sync": None,
"documents_tracked": 0
}
# 尝试获取更多状态信息
if hasattr(service, 'get_status'):
status.update(service.get_status())
return jsonify(status)
except Exception as e:
return jsonify({
"status": "failed",
"status_code": INTERNAL_ERROR,
"enabled": True,
"error": str(e)
})
@sync_bp.route('/sync/history', methods=['GET'])
@require_gateway_auth
def get_sync_history() -> Tuple[Any, int]:
"""
获取同步历史
返回最近的同步操作记录。
查询参数:
limit: 返回数量限制(默认 20
Returns:
{"history": [...]}
"""
service, err = _require_sync_service()
if err:
return err
limit = request.args.get('limit', 20, type=int)
try:
history = service.get_sync_history(limit=limit) if hasattr(service, 'get_sync_history') else []
return jsonify({"history": history})
except Exception as e:
return error_response(
error="SYNC_ERROR",
error_code=SYNC_ERROR,
message=str(e),
http_status=500
)
@sync_bp.route('/sync/changes', methods=['GET'])
@require_gateway_auth
def get_change_logs() -> Tuple[Any, int]:
"""
获取变更日志
返回文档变更的详细记录,包括新增、修改、删除等操作。
查询参数:
limit: 返回数量限制(默认 50
collection: 过滤指定向量库(可选)
Returns:
{"changes": [...]}
"""
service, err = _require_sync_service()
if err:
return err
limit = request.args.get('limit', 50, type=int)
collection = request.args.get('collection')
try:
changes = service.get_change_logs(limit=limit, collection=collection) if hasattr(service, 'get_change_logs') else []
return jsonify({"changes": changes})
except Exception as e:
return error_response(
error="SYNC_ERROR",
error_code=SYNC_ERROR,
message=str(e),
http_status=500
)
@sync_bp.route('/sync/start', methods=['POST'])
@require_gateway_auth
def start_sync_monitor() -> Tuple[Any, int]:
"""
启动文件监控
启用实时文件监控,自动检测文档变更并触发同步。
适用于需要实时更新的场景。
Returns:
{"status": "success", "message": "文件监控已启动"}
Note:
文件监控会持续运行,直到调用 /sync/stop 或服务重启
"""
service, err = _require_sync_service()
if err:
return err
try:
if hasattr(service, 'is_running') and service.is_running():
return jsonify({"status": "success", "status_code": SYNC_SUCCESS, "message": "文件监控已在运行"})
if hasattr(service, 'start'):
success = service.start()
if success:
return jsonify({"status": "success", "status_code": SYNC_SUCCESS, "message": "文件监控已启动"})
else:
return error_response(
error="SYNC_ERROR",
error_code=SYNC_ERROR,
message="启动文件监控失败",
http_status=500
)
else:
return jsonify({"status": "success", "message": "文件监控功能不可用"})
except Exception as e:
return error_response(
error="SYNC_ERROR",
error_code=SYNC_ERROR,
message=str(e),
http_status=500
)
@sync_bp.route('/sync/stop', methods=['POST'])
@require_gateway_auth
def stop_sync_monitor() -> Tuple[Any, int]:
"""
停止文件监控
停止实时文件监控服务。已同步的数据保持不变。
Returns:
{"status": "success", "message": "文件监控已停止"}
"""
service, err = _require_sync_service()
if err:
return err
try:
if hasattr(service, 'stop'):
service.stop()
return jsonify({"status": "success", "status_code": SYNC_SUCCESS, "message": "文件监控已停止"})
except Exception as e:
return error_response(
error="SYNC_ERROR",
error_code=SYNC_ERROR,
message=str(e),
http_status=500
)