docs
This commit is contained in:
79
ontology_platform/ont_platform/api/routes/graph.py
Normal file
79
ontology_platform/ont_platform/api/routes/graph.py
Normal file
@@ -0,0 +1,79 @@
|
||||
"""Phase 5 projection and GraphRAG search routes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Any
|
||||
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException, Query
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ont_platform.api.db_deps import get_db
|
||||
from ont_platform.config import load_settings
|
||||
from ont_platform.core.graph.cypher_guard import ReadOnlyCypherGuard, UnsafeCypherError
|
||||
from ont_platform.core.graph.search import CandidateGraphSearchService
|
||||
from ont_platform.core.projection.rdf_to_neo4j import RDFToNeo4jProjector
|
||||
|
||||
router = APIRouter(prefix="/api/v1/graph", tags=["graph"])
|
||||
|
||||
|
||||
class ProjectionPreviewRequest(BaseModel):
|
||||
project_id: str = "default"
|
||||
triples: list[tuple[str, str, str]]
|
||||
provenance: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class ReadOnlyCypherRequest(BaseModel):
|
||||
query: str
|
||||
limit: int | None = None
|
||||
|
||||
|
||||
@router.post("/projection/preview")
|
||||
async def preview_projection(request: Annotated[ProjectionPreviewRequest, Body()]) -> dict:
|
||||
projector = RDFToNeo4jProjector(project_id=request.project_id)
|
||||
result = await projector.preview_projection(
|
||||
request.triples,
|
||||
provenance=request.provenance,
|
||||
)
|
||||
return {"status": "success", "projection": result.to_dict()}
|
||||
|
||||
|
||||
@router.post("/cypher/read")
|
||||
def sanitize_read_only_cypher(request: Annotated[ReadOnlyCypherRequest, Body()]) -> dict:
|
||||
settings = load_settings()
|
||||
guard = ReadOnlyCypherGuard(max_limit=settings.text2cypher_result_limit)
|
||||
try:
|
||||
sanitized = guard.sanitize(request.query, limit=request.limit)
|
||||
except UnsafeCypherError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
return {
|
||||
"status": "success",
|
||||
"read_only": True,
|
||||
"query": sanitized.query,
|
||||
"limit": sanitized.limit,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/search")
|
||||
def search_graph(
|
||||
db: Annotated[Session, Depends(get_db)],
|
||||
q: Annotated[str, Query(min_length=1)],
|
||||
project_id: Annotated[str, Query()] = "default",
|
||||
limit: Annotated[int, Query(ge=1, le=100)] = 20,
|
||||
) -> dict:
|
||||
settings = load_settings()
|
||||
effective_limit = min(limit, settings.graph_search_result_limit)
|
||||
results = CandidateGraphSearchService(db).search(
|
||||
project_id=project_id,
|
||||
query=q,
|
||||
limit=effective_limit,
|
||||
)
|
||||
return {
|
||||
"status": "success",
|
||||
"query": q,
|
||||
"result_count": len(results),
|
||||
"results": [result.to_dict() for result in results],
|
||||
}
|
||||
|
||||
|
||||
__all__ = ["router"]
|
||||
Reference in New Issue
Block a user