chore: init monorepo snapshot
This commit is contained in:
@@ -0,0 +1 @@
|
||||
# 空文件用于标记包
|
||||
@@ -0,0 +1 @@
|
||||
# API 模块包声明
|
||||
@@ -0,0 +1,46 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.services.rag_service import RagService
|
||||
|
||||
router = APIRouter()
|
||||
rag_service = RagService()
|
||||
|
||||
|
||||
class QueryRequest(BaseModel):
|
||||
query: str = Field(..., description="用户查询")
|
||||
top_k: int = Field(8, description="返回条数")
|
||||
|
||||
|
||||
class PathRequest(BaseModel):
|
||||
source: str
|
||||
target: str
|
||||
|
||||
|
||||
@router.post("/query")
|
||||
async def query(payload: QueryRequest):
|
||||
"""优先调用 LightRAG,失败自动降级 Supabase"""
|
||||
result = await rag_service.query(payload.query, payload.top_k)
|
||||
return {"data": result}
|
||||
|
||||
|
||||
@router.post("/graph")
|
||||
async def graph(payload: QueryRequest):
|
||||
result = await rag_service.graph(payload.query)
|
||||
return {"data": result}
|
||||
|
||||
|
||||
@router.post("/path")
|
||||
async def path(payload: PathRequest):
|
||||
result = await rag_service.path(payload.source, payload.target)
|
||||
return {"data": result}
|
||||
|
||||
|
||||
@router.get("/health/full")
|
||||
async def health() -> dict:
|
||||
"""最小化健康检查,后续补充依赖自检"""
|
||||
try:
|
||||
_ = await rag_service.query("ping", top_k=1)
|
||||
return {"status": "ok"}
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise HTTPException(status_code=500, detail=str(exc))
|
||||
@@ -0,0 +1 @@
|
||||
# 配置与日志模块包声明
|
||||
@@ -0,0 +1,22 @@
|
||||
from functools import lru_cache
|
||||
from pydantic import BaseSettings, Field
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
app_name: str = Field("AIMNOTE RAG Gateway", env="RAG_GATEWAY_APP_NAME")
|
||||
api_prefix: str = "/rag"
|
||||
environment: str = Field("development", env="RAG_GATEWAY_ENV")
|
||||
lightrag_url: str = Field("http://127.0.0.1:7777", env="LIGHTRAG_URL")
|
||||
supabase_rest_url: str = Field("http://127.0.0.1:54321/rest/v1", env="SUPABASE_REST_URL")
|
||||
supabase_key: str = Field("", env="SUPABASE_SERVICE_ROLE_KEY")
|
||||
embedding_base_url: str = Field("http://127.0.0.1:11434/v1", env="EMBEDDING_BASE_URL")
|
||||
embedding_model: str = Field("qwen3-embedding:8b", env="EMBEDDING_MODEL")
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
case_sensitive = False
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def get_gateway_settings() -> Settings:
|
||||
return Settings()
|
||||
@@ -0,0 +1,27 @@
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
class JsonFormatter(logging.Formatter):
|
||||
"""统一 JSON 日志,方便跨服务链路排查"""
|
||||
|
||||
def format(self, record: logging.LogRecord) -> str: # type: ignore[override]
|
||||
log: Dict[str, Any] = {
|
||||
"ts": self.formatTime(record, datefmt="%Y-%m-%dT%H:%M:%S%z"),
|
||||
"level": record.levelname,
|
||||
"logger": record.name,
|
||||
"message": record.getMessage(),
|
||||
}
|
||||
if record.exc_info:
|
||||
log["exc_info"] = self.formatException(record.exc_info)
|
||||
for key, value in getattr(record, "extra", {}).items():
|
||||
log[key] = value
|
||||
return json.dumps(log, ensure_ascii=False)
|
||||
|
||||
|
||||
def setup_logging(level: str = "INFO") -> None:
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
handler.setFormatter(JsonFormatter())
|
||||
logging.basicConfig(handlers=[handler], level=level, force=True)
|
||||
@@ -0,0 +1,12 @@
|
||||
from fastapi import FastAPI
|
||||
|
||||
from app.api.routes import router as api_router
|
||||
from app.core.config import get_gateway_settings
|
||||
from app.core.logging import setup_logging
|
||||
|
||||
settings = get_gateway_settings()
|
||||
|
||||
setup_logging()
|
||||
|
||||
app = FastAPI(title=settings.app_name)
|
||||
app.include_router(api_router, prefix=settings.api_prefix)
|
||||
@@ -0,0 +1 @@
|
||||
# 服务层包声明
|
||||
@@ -0,0 +1,37 @@
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
from app.core.config import get_gateway_settings
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
sys.path.append(str(ROOT / "siyuan-rag-llm-main"))
|
||||
from utils.rag.rag_knowledge_base import HybridRAGKnowledgeBase # type: ignore # noqa: E402
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RagService:
|
||||
"""包装 HybridRAGKnowledgeBase,供路由调用"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
settings = get_gateway_settings()
|
||||
self.kb = HybridRAGKnowledgeBase(
|
||||
lightrag_url=settings.lightrag_url,
|
||||
supabase_rest_url=settings.supabase_rest_url,
|
||||
supabase_service_key=settings.supabase_key,
|
||||
embedding_base_url=settings.embedding_base_url,
|
||||
embedding_model=settings.embedding_model,
|
||||
)
|
||||
|
||||
async def query(self, query: str, top_k: int = 8) -> Dict[str, Any]:
|
||||
return await self.kb.query(query=query, top_k=top_k)
|
||||
|
||||
async def graph(self, query: str) -> Dict[str, Any]:
|
||||
result = await self.kb.lightrag.graph(query=query)
|
||||
await self.kb.sync_graph_metadata(result)
|
||||
return result
|
||||
|
||||
async def path(self, source: str, target: str) -> Dict[str, Any]:
|
||||
return await self.kb.lightrag.path(source=source, target=target)
|
||||
Reference in New Issue
Block a user