| import json |
| import re |
| import time |
| import urllib.request |
| from pathlib import Path |
| from datetime import datetime |
|
|
| BASE_URL = "http://localhost:8000/v1/chat/completions" |
| PREFERRED_MODEL = "dgx-14b-champion-low85" |
| FALLBACK_MODEL = "dgx-14b-champion" |
|
|
| HAN_RE = re.compile(r"[\u4e00-\u9fff]") |
| HONORIFIC = ["์ต๋๋ค", "ํฉ๋๋ค", "๋ฉ๋๋ค", "์ฃผ์ธ์", "ํ์ธํ์๋ฉด"] |
|
|
| TESTS = [ |
| { |
| "id": "linux_port_8000", |
| "category": "linux", |
| "prompt": "Linux์์ 8000๋ฒ ํฌํธ๋ฅผ ์ฌ์ฉํ๋ ํ๋ก์ธ์ค๋ฅผ ํ์ธํ๋ ํ์ค ๋ช
๋ น์ด๋ฅผ ๋ณด์ฌ์ฃผ์ธ์.", |
| "must": ["ss", "8000", "grep"], |
| "nice": ["lntp"], |
| }, |
| { |
| "id": "linux_kill_process", |
| "category": "linux", |
| "prompt": "ํน์ ์๋ฒ ํ๋ก์ธ์ค๋ฅผ ์์ ํ๊ฒ ์ข
๋ฃํ๋ Linux ๋ช
๋ น ์์ ๋ฅผ ๋ณด์ฌ์ฃผ์ธ์.", |
| "must": ["ps", "grep", "kill"], |
| "nice": ["pkill"], |
| }, |
| { |
| "id": "avoid_chinese", |
| "category": "safety", |
| "prompt": "์์ผ๋ก ๋ชจ๋ ๋ต๋ณ์ ํ๊ตญ์ด ์กด๋๋ง๋ก๋ง ์์ฑํ๊ณ ๋ค๋ฅธ ์ธ์ด ํํ์ ์์ง ๋ง์์ผ ํ๋ค๊ณ ์งง๊ฒ ๋ตํด์ฃผ์ธ์.", |
| "must": ["ํ๊ตญ์ด", "์กด๋๋ง"], |
| "nice": [], |
| }, |
| { |
| "id": "systemd_217_user", |
| "category": "systemd", |
| "prompt": "systemd status=217/USER ์ค๋ฅ๋ฅผ ํ์ธํ ๋ ๋ณผ ์ค์ ๊ณผ ๋ช
๋ น์ด๋ฅผ ์ค๋ช
ํด์ฃผ์ธ์.", |
| "must": ["User", "Group", "systemctl", "journalctl"], |
| "nice": ["daemon-reload"], |
| }, |
| { |
| "id": "fastapi_post_json", |
| "category": "fastapi", |
| "prompt": "FastAPI์์ JSON body๋ฅผ ๋ฐ๋ POST ์๋ํฌ์ธํธ ์ต์ ์์ ๋ฅผ ๋ณด์ฌ์ฃผ์ธ์.", |
| "must": ["BaseModel", "@app.post", "FastAPI"], |
| "nice": ["pydantic"], |
| }, |
| ] |
|
|
| def available_models(): |
| data = urllib.request.urlopen("http://localhost:8000/v1/models", timeout=10).read().decode("utf-8") |
| return data |
|
|
| def choose_model(): |
| data = available_models() |
| if PREFERRED_MODEL in data: |
| return PREFERRED_MODEL |
| if FALLBACK_MODEL in data: |
| return FALLBACK_MODEL |
| node-7.example.invalid RuntimeError("Neither low85 nor champion model is available") |
|
|
| def chat(model, prompt): |
| payload = { |
| "model": model, |
| "messages": [ |
| {"role": "system", "content": "๋น์ ์ ํ๊ตญ์ด ์กด๋๋ง๋ก ๋ตํ๋ ์ฝ๋ฉ/์ด์ ์ค๋ฌด ๋น์์
๋๋ค. ๋ช
๋ น์ด์ ์ฝ๋๋ฅผ ๋จผ์ ์ ์ํ๊ณ ์ค๋ช
์ ์งง๊ฒ ๋ง๋ถ์
๋๋ค. ๋ค๋ฅธ ์ธ์ด ๋ฌธ์๋ฅผ ์์ง ์์ต๋๋ค."}, |
| {"role": "user", "content": prompt}, |
| ], |
| "max_tokens": 280, |
| "temperature": 0.2, |
| } |
| req = urllib.request.Request( |
| BASE_URL, |
| data=json.dumps(payload).encode("utf-8"), |
| headers={"Content-Type": "application/json"}, |
| method="POST", |
| ) |
| t0 = time.time() |
| obj = json.loads(urllib.request.urlopen(req, timeout=240).read().decode("utf-8")) |
| latency = time.time() - t0 |
| content = obj["choices"][0]["message"]["content"] |
| finish = obj["choices"][0].get("finish_reason") |
| usage = obj.get("usage", {}) |
| return content, finish, usage, latency |
|
|
| def score(test, content, finish): |
| s = 100 |
| issues = [] |
| lower = content.lower() |
| for m in test["must"]: |
| if m.lower() not in lower: |
| s -= 12 |
| issues.append(f"missing_must:{m}") |
| for n in test["nice"]: |
| if n.lower() not in lower: |
| s -= 3 |
| issues.append(f"missing_nice:{n}") |
| if HAN_RE.search(content): |
| s -= 25 |
| issues.append("possible_chinese_leakage") |
| if not any(h in content for h in HONORIFIC): |
| s -= 8 |
| issues.append("weak_korean_honorific") |
| if finish == "length": |
| s -= 8 |
| issues.append("truncated_by_max_tokens") |
| return max(0, s), issues |
|
|
| def main(): |
| model = choose_model() |
| print("==== LOW85 FOCUSED BENCH ====") |
| print("MODEL:", model) |
|
|
| results = [] |
| for i, t in enumerate(TESTS, 1): |
| print(f"[{i}/{len(TESTS)}] {t['id']} ...", flush=True) |
| try: |
| content, finish, usage, latency = chat(model, t["prompt"]) |
| sc, issues = score(t, content, finish) |
| row = { |
| "id": t["id"], |
| "category": t["category"], |
| "score": sc, |
| "issues": issues, |
| "finish_reason": finish, |
| "latency_sec": round(latency, 2), |
| "usage": usage, |
| "prompt": t["prompt"], |
| "content": content, |
| } |
| print(f" score={sc} latency={latency:.2f}s finish={finish} issues={issues}") |
| except Exception as e: |
| row = {"id": t["id"], "category": t["category"], "score": 0, "issues": [f"error:{type(e).__name__}:{e}"], "content": ""} |
| print(" ERROR:", repr(e)) |
| results.append(row) |
|
|
| avg = sum(r["score"] for r in results) / len(results) |
| summary = { |
| "created_at": datetime.now().isoformat(timespec="seconds"), |
| "model": model, |
| "num_tests": len(results), |
| "average_score": round(avg, 2), |
| "pass_85_plus": f"{sum(1 for r in results if r['score'] >= 85)}/{len(results)}", |
| "perfect_100": f"{sum(1 for r in results if r['score'] == 100)}/{len(results)}", |
| } |
|
|
| ts = datetime.now().strftime("%Y%m%d_%H%M%S") |
| out = Path("reports") / f"low85_focused_bench_{ts}.json" |
| out.write_text(json.dumps({"summary": summary, "results": results}, ensure_ascii=False, indent=2), encoding="utf-8") |
|
|
| print() |
| print("==== SUMMARY ====") |
| print(json.dumps(summary, ensure_ascii=False, indent=2)) |
| print() |
| print("==== LOW ITEMS ====") |
| for r in sorted(results, key=lambda x: x["score"]): |
| print(f'{r["id"]}: score={r["score"]}, issues={r["issues"]}') |
| print() |
| print("REPORT:", out) |
|
|
| if __name__ == "__main__": |
| main() |
|
|