Spaces:
Running
Running
deploy: v35 document-level chunking (DP split + parallel chunks), progress view, Supabase logbook
8debb9c verified | """์ฌ์ฉ์ ์ ๋ ฅยท๊ต์ด ๊ฒฐ๊ณผ ๊ธฐ๋ก โ 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), | |
| }, | |
| ) | |