chore: init monorepo snapshot

This commit is contained in:
liaibo
2025-11-23 10:55:04 +08:00
commit c70ff52869
941 changed files with 246586 additions and 0 deletions
@@ -0,0 +1,19 @@
"""LightRAG 集成占位。阶段 1 会在这里封装真正的查询与索引。"""
from app.config import settings
class LightRAGService:
def __init__(self) -> None:
self.collection = settings.lightrag_collection
async def queue_index(self, document_id: str, raw_text: str) -> None:
"""预留方法:后续调用 LightRAG.update_index。"""
return None
async def query(self, query_text: str, user_id: str) -> str:
"""预留方法:后续调用 LightRAG.query,当前返回占位回答。"""
return f"[mock] {query_text}"
lightrag_service = LightRAGService()
@@ -0,0 +1,13 @@
"""MinerU OCR 占位服务。"""
class MinerUService:
async def extract_markdown(self, file_url: str) -> str:
"""
阶段 0:直接返回固定内容,保证前端流程贯通。
阶段 1:调用 MinerU CLI / SDK,从 Supabase Storage 下载文件后解析。
"""
return f"# OCR Placeholder\n\n源文件:{file_url}"
mineru_service = MinerUService()
@@ -0,0 +1,57 @@
from __future__ import annotations
from typing import Any, Dict, Optional
import httpx
from app.config import settings
class SupabaseRestClient:
"""轻量封装 Supabase RESTful API,兼容本地 sb_secret 密钥。"""
def __init__(self) -> None:
base_url = settings.supabase_url.rstrip("/")
self.client = httpx.Client(
base_url=f"{base_url}/rest/v1",
headers={
"apikey": settings.supabase_service_role_key,
"Authorization": f"Bearer {settings.supabase_service_role_key}",
},
timeout=10.0,
)
def insert(self, table: str, payload: Dict[str, Any]) -> Dict[str, Any]:
response = self.client.post(
f"/{table}",
json=payload,
headers={"Prefer": "return=representation"},
)
response.raise_for_status()
data = response.json()
if isinstance(data, list):
return data[0]
return data
def select_one(self, table: str, filters: Dict[str, Any]) -> Optional[Dict[str, Any]]:
params = {key: f"eq.{value}" for key, value in filters.items()}
params["select"] = "*"
response = self.client.get(f"/{table}", params=params)
response.raise_for_status()
data = response.json()
if isinstance(data, list) and data:
return data[0]
return None
def update(self, table: str, filters: Dict[str, Any], payload: Dict[str, Any]) -> None:
params = {key: f"eq.{value}" for key, value in filters.items()}
response = self.client.patch(
f"/{table}",
params=params,
json=payload,
headers={"Prefer": "return=minimal"},
)
response.raise_for_status()
supabase_rest = SupabaseRestClient()
@@ -0,0 +1,43 @@
from __future__ import annotations
from typing import Any, Dict, Optional
from app.schemas.tasks import TaskStatusResponse
from app.services.supabase_rest import supabase_rest
class SupabaseTaskTracker:
"""利用 Supabase background_tasks 表追踪进度。"""
def create_task(self, *, user_id: str, document_id: str, task_type: str = "ocr") -> TaskStatusResponse:
payload = {
"user_id": user_id,
"document_id": document_id,
"task_type": task_type,
"status": "pending",
"progress": 0,
}
record = supabase_rest.insert("background_tasks", payload)
return self._to_response(record)
def get_task(self, *, task_id: str, user_id: str) -> Optional[TaskStatusResponse]:
record = supabase_rest.select_one("background_tasks", {"id": task_id, "user_id": user_id})
if not record:
return None
return self._to_response(record)
def update_task(self, *, task_id: str, **kwargs: Any) -> None:
supabase_rest.update("background_tasks", {"id": task_id}, kwargs)
def _to_response(self, record: Optional[Dict[str, Any]]) -> TaskStatusResponse:
if not record:
raise ValueError("Task record missing")
return TaskStatusResponse(
task_id=str(record["id"]),
status=record.get("status", "pending"),
progress=record.get("progress", 0),
message=record.get("message"),
)
task_tracker = SupabaseTaskTracker()