dce9e31bde
- 新增 JWT 认证模块,支持登录/注册/用户管理 - 新增文件上传接口,支持 .txt/.md/.html/.pdf/.docx 等格式解析入库 - 新增检索结果 AI 总结功能 - 新增文本去重缓存机制 - 新增全局认证夹具简化测试 - 新增配置项与环境变量支持 - 完善文档与测试覆盖
60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
"""检索 API:POST /api/v1/search"""
|
||
|
||
from hashlib import sha256
|
||
from typing import Any
|
||
|
||
import structlog
|
||
from fastapi import APIRouter, Depends
|
||
|
||
from app.api.response import ApiError, ok
|
||
from app.core.auth import AuthUser, get_current_user
|
||
from app.core.retriever import Retriever
|
||
from app.models.search import SearchRequest
|
||
from app.services.redis import get_cache
|
||
|
||
logger = structlog.get_logger()
|
||
|
||
router = APIRouter(prefix="/api/v1", tags=["search"])
|
||
|
||
# 模块级懒加载单例,避免每请求重建 Qdrant/Embedding client
|
||
_retriever: Retriever | None = None
|
||
|
||
|
||
def _get_retriever() -> Retriever:
|
||
global _retriever
|
||
if _retriever is None:
|
||
_retriever = Retriever()
|
||
return _retriever
|
||
|
||
|
||
def _cache_key(request: SearchRequest) -> str:
|
||
"""检索缓存键:query + top_k + summarize 的短哈希(三者均影响结果集,需参与键计算)"""
|
||
digest = sha256((request.query + "|" + str(request.top_k) + "|" + str(request.summarize)).encode()).hexdigest()[:16]
|
||
return f"search:{digest}"
|
||
|
||
|
||
@router.post("/search")
|
||
async def search(request: SearchRequest, user: AuthUser = Depends(get_current_user)) -> dict[str, Any]:
|
||
"""分层检索入口,返回统一包装的 SearchResponse
|
||
|
||
先查 Redis 缓存:命中直接返回缓存的响应;未命中走检索流程并回写缓存。
|
||
缓存读写失败均降级为无缓存行为,不影响检索。
|
||
"""
|
||
cache_key = _cache_key(request)
|
||
cached = await get_cache().get_json(cache_key)
|
||
if cached is not None:
|
||
logger.info("检索缓存命中", query=request.query, cache_key=cache_key)
|
||
return cached
|
||
|
||
try:
|
||
response = await _get_retriever().search(request)
|
||
except ApiError:
|
||
raise
|
||
except Exception as exc:
|
||
logger.exception("检索失败", query=request.query)
|
||
raise ApiError(2000, f"检索失败: {exc}") from exc
|
||
|
||
result = ok(response.model_dump())
|
||
await get_cache().set_json(cache_key, result)
|
||
return result
|