Spaces:
Running
Running
File size: 3,200 Bytes
8debb9c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | """์ฌ์ฉ์ ์
๋ ฅยท๊ต์ด ๊ฒฐ๊ณผ ๊ธฐ๋ก โ Supabase(PostgREST) ์ ์ง์ REST ํธ์ถ.
์ gradio ๋ฐ๋ชจ(`services/prj-chosun-gradio/blindtest/db.py`)์ `articles` ยท `pipeline_runs` ๋ ํ
์ด๋ธ์
๊ทธ๋๋ก ์ด๋ค(์คํค๋ง๋ `schema.sql`). SDK ๋์ httpx ๋ก REST ๋ฅผ ๋ถ๋ฅด๋ ๊ฒ๋ ๊ทธ๋์ ๊ฐ๋ค โ `supabase`
ํจํค์ง๊ฐ ๋๊ณ ์ค๋ `realtime`/`websockets` ํ์ด ๋ค๋ฅธ ์์กด์ฑ๊ณผ ์ถฉ๋ํ๋ ์ ๋ ฅ ๋๋ฌธ.
ํ๊ฒฝ ๋ณ์:
SUPABASE_URL โ ํ๋ก์ ํธ URL (https://xxx.supabase.co)
SUPABASE_KEY (๋๋ SUPABASE_ANON_KEY) โ anon ํค (RLS ์ ์ฑ
์ schema.sql)
๋ ์ค ํ๋๋ผ๋ ์์ผ๋ฉด ๋ชจ๋ ์ฐ๊ธฐ๋ no-op ์ด๊ณ `is_configured()` ๊ฐ False ๋ค. ๊ธฐ๋ก ์คํจ๋ ์ ๋ ๋ฐ๋ชจ๋ฅผ
๋ฉ์ถ์ง ์๋๋ค โ `last_error()` ์ ํ ์ค ๋จ๊ธฐ๊ณ None ์ ๋๋ ค์ค๋ค.
"""
from __future__ import annotations
import os
import httpx
TIMEOUT_S = 10.0
_last_error: str | None = None
def _url() -> str:
return os.environ.get("SUPABASE_URL", "").strip().rstrip("/")
def _key() -> str:
# ์ gradio ๋ฐ๋ชจ๋ SUPABASE_KEY, ์ต๊ทผ .env ๋ SUPABASE_ANON_KEY ๋ฅผ ์ด๋ค -- ๋ ๋ค ๋ฐ๋๋ค
return (os.environ.get("SUPABASE_KEY") or os.environ.get("SUPABASE_ANON_KEY") or "").strip()
def is_configured() -> bool:
return bool(_url() and _key())
def last_error() -> str | None:
return _last_error
def _post(table: str, row: dict) -> list[dict]:
headers = {
"apikey": _key(),
"Authorization": f"Bearer {_key()}",
"Content-Type": "application/json",
"Prefer": "return=representation",
}
with httpx.Client(timeout=TIMEOUT_S) as client:
resp = client.post(f"{_url()}/rest/v1/{table}", headers=headers, json=row)
if resp.status_code >= 300:
raise RuntimeError(f"{resp.status_code} {resp.text[:200]}")
return resp.json() if resp.content else []
def _insert(table: str, row: dict) -> int | None:
global _last_error
if not is_configured():
return None
try:
data = _post(table, row)
_last_error = None
return data[0]["id"] if data else None
except Exception as exc: # noqa: BLE001 โ ๊ธฐ๋ก์ ๋ฐ๋ชจ์ ๋ถ์ ๊ธฐ๋ฅ, ์ด๋ค ์คํจ๋ ์ผ์ผ์ ํ ์ค๋ง ๋จ๊ธด๋ค
_last_error = f"{table}: {type(exc).__name__}: {exc}"
return None
def save_article(source_text: str) -> int | None:
"""์ฌ์ฉ์ ์
๋ ฅ ์๋ฌธ 1๊ฑด. ๊ต์ด ์คํ **์ **์ ๋ถ๋ฅธ๋ค โ ์คํ์ด ์คํจํด๋ ์
๋ ฅ์ ๋จ๊ฒ."""
return _insert("articles", {"source_text": source_text})
def save_run(
article_id: int | None,
*,
pipeline_key: str,
prompt_key: str,
model: str,
output: str,
processing_time_s: float,
) -> int | None:
"""๊ต์ด ๊ฒฐ๊ณผ 1๊ฑด. `article_id` ๊ฐ ์์ผ๋ฉด(์
๋ ฅ ๊ธฐ๋ก ์คํจ) ๊ฒฐ๊ณผ๋ ๊ธฐ๋กํ์ง ์๋๋ค."""
if article_id is None:
return None
return _insert(
"pipeline_runs",
{
"article_id": article_id,
"pipeline_key": pipeline_key,
"prompt_key": prompt_key,
"model": model,
"output": output,
"processing_time_s": round(processing_time_s, 2),
},
)
|