Download src/api.py from IamBatman07/Diagram-Structure-Extractor: direct link, hf CLI and curl.
- Browser
- Download file 2.85 kB
-
https://huggingface.co/spaces/IamBatman07/Diagram-Structure-Extractor/resolve/main/src/api.py
- Command line
-
hf download hf://spaces/IamBatman07/Diagram-Structure-Extractor/src/api.py
-
curl -L -o api.py https://huggingface.co/spaces/IamBatman07/Diagram-Structure-Extractor/resolve/main/src/api.py
2.85 kB
| """FastAPI service for DiagraMine. | |
| POST /extract multipart image upload -> structured JSON + annotated PNG | |
| (base64) + relationship CSV (text). Always returns | |
| schema-valid JSON (the reliability guarantee). | |
| GET /health liveness probe. | |
| Run: uvicorn src.api:app --port 8000 | |
| """ | |
| from __future__ import annotations | |
| import base64 | |
| import csv | |
| import io | |
| import os | |
| import tempfile | |
| import cv2 | |
| from fastapi import FastAPI, File, Query, UploadFile | |
| from fastapi.responses import JSONResponse, RedirectResponse | |
| from pydantic import BaseModel | |
| from src import pipeline | |
| from src.schemas import ExtractionResult, PipelineConfig | |
| app = FastAPI( | |
| title="DiagraMine", | |
| description="Diagram understanding & structure extraction (data-driven, no hardcoded connections).", | |
| version="4.0", | |
| ) | |
| class ExtractResponse(BaseModel): | |
| structure: ExtractionResult | |
| annotated_png_base64: str | |
| relationship_csv: str | |
| def _csv_string(result: ExtractionResult) -> str: | |
| buf = io.StringIO() | |
| w = csv.writer(buf) | |
| w.writerow(["source", "target", "line_style", "direction", "relationship", "bidirectional"]) | |
| for r in result.relationships: | |
| w.writerow([r.source, r.target, r.line_style, r.direction, r.relationship, r.bidirectional]) | |
| return buf.getvalue() | |
| async def root() -> RedirectResponse: | |
| """The service has no page of its own; send visitors to the interactive docs.""" | |
| return RedirectResponse(url="/docs") | |
| async def health() -> dict: | |
| return {"status": "ok", "service": "diagramine", "version": "4.0"} | |
| async def extract( | |
| file: UploadFile = File(...), | |
| text: str = Query("paddleocr"), | |
| box: str = Query("canny_contours"), | |
| arrow: str = Query("directed_lines"), | |
| icon: str = Query("template_matching"), | |
| outside_box_gate: bool = Query(False), | |
| ) -> JSONResponse: | |
| config = PipelineConfig( | |
| text_detector=text, box_detector=box, arrow_detector=arrow, | |
| icon_detector=icon, outside_box_gate=outside_box_gate, | |
| ) | |
| suffix = os.path.splitext(file.filename or "upload.png")[1] or ".png" | |
| data = await file.read() | |
| tmp = tempfile.NamedTemporaryFile(delete=False, suffix=suffix) | |
| try: | |
| tmp.write(data) | |
| tmp.close() | |
| result = pipeline.extract(tmp.name, config) | |
| annotated = pipeline.annotate(tmp.name, result) | |
| ok, png = cv2.imencode(".png", annotated) | |
| png_b64 = base64.b64encode(png.tobytes()).decode("ascii") if ok else "" | |
| finally: | |
| os.unlink(tmp.name) | |
| payload = ExtractResponse( | |
| structure=result, | |
| annotated_png_base64=png_b64, | |
| relationship_csv=_csv_string(result), | |
| ) | |
| return JSONResponse(content=payload.model_dump()) | |