Suya OCR API — vLLM-backed, OpenAI-compatible OCR service
FastAPI service wrapping the Surya-OCR-2 model (datalab-to) served through vLLM: legacy /v1/api/ai/* endpoints, an OpenAI-compatible /v1/chat/completions endpoint, a coalescing request batcher, a local OCR CLI, Docker packaging, multilingual example outputs, and quantization/concurrency benchmarks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
"""Speed-vs-accuracy Pareto scatter and per-method bar charts."""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List
|
||||
|
||||
import matplotlib
|
||||
|
||||
matplotlib.use("Agg") # headless
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
|
||||
|
||||
def pareto_points(rows: List[Dict[str, Any]], x_key: str, y_key: str) -> List[Dict[str, Any]]:
|
||||
points = []
|
||||
for row in rows:
|
||||
if row.get("status") != "ok":
|
||||
continue
|
||||
if row.get(x_key) is None or row.get(y_key) is None:
|
||||
continue
|
||||
points.append({
|
||||
"method": row["method"],
|
||||
"x": row[x_key],
|
||||
"y": row[y_key],
|
||||
"t4_deployable": row.get("t4_deployable"),
|
||||
})
|
||||
return points
|
||||
|
||||
|
||||
def _scatter(points, x_label, y_label, title, out_path: Path) -> None:
|
||||
fig, ax = plt.subplots(figsize=(7, 5))
|
||||
for p in points:
|
||||
marker = "o" if p["t4_deployable"] else "x"
|
||||
ax.scatter(p["x"], p["y"], marker=marker, s=80)
|
||||
ax.annotate(p["method"], (p["x"], p["y"]), textcoords="offset points", xytext=(5, 5))
|
||||
ax.set_xlabel(x_label)
|
||||
ax.set_ylabel(y_label)
|
||||
ax.set_title(title + " (o = T4-deployable, x = A100-only)")
|
||||
fig.tight_layout()
|
||||
fig.savefig(out_path, dpi=120)
|
||||
plt.close(fig)
|
||||
|
||||
|
||||
def _bar(rows, metric_key, y_label, out_path: Path) -> None:
|
||||
ok = [r for r in rows if r.get("status") == "ok" and r.get(metric_key) is not None]
|
||||
fig, ax = plt.subplots(figsize=(7, 5))
|
||||
ax.bar([r["method"] for r in ok], [r[metric_key] for r in ok])
|
||||
ax.set_ylabel(y_label)
|
||||
ax.set_title(metric_key)
|
||||
fig.tight_layout()
|
||||
fig.savefig(out_path, dpi=120)
|
||||
plt.close(fig)
|
||||
|
||||
|
||||
def render_all(rows: List[Dict[str, Any]], out_dir: Path) -> List[Path]:
|
||||
out_dir = Path(out_dir)
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
written: List[Path] = []
|
||||
|
||||
p1 = out_dir / "pareto_latency_cer.png"
|
||||
_scatter(pareto_points(rows, "mean_latency_s", "mean_cer"),
|
||||
"mean latency (s) [lower=faster]", "CER vs BF16 [lower=better]",
|
||||
"Speed vs recognition accuracy", p1)
|
||||
written.append(p1)
|
||||
|
||||
p2 = out_dir / "pareto_latency_iou.png"
|
||||
_scatter(pareto_points(rows, "mean_latency_s", "mean_bbox_iou"),
|
||||
"mean latency (s) [lower=faster]", "bbox IoU vs BF16 [higher=better]",
|
||||
"Speed vs detection accuracy", p2)
|
||||
written.append(p2)
|
||||
|
||||
for metric, label in [("mean_latency_s", "mean latency (s)"),
|
||||
("mean_cer", "CER vs BF16"),
|
||||
("mean_bbox_iou", "bbox IoU vs BF16")]:
|
||||
bp = out_dir / f"bar_{metric}.png"
|
||||
_bar(rows, metric, label, bp)
|
||||
written.append(bp)
|
||||
|
||||
return written
|
||||
Reference in New Issue
Block a user