Spaces:
Sleeping
Sleeping
File size: 6,138 Bytes
5716a3a | 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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | """
inference.py β SQL Correction Environment Baseline Script
==========================================================
MANDATORY - Place this file in the ROOT of the project.
Required environment variables:
API_BASE_URL The API endpoint for the LLM
MODEL_NAME The model identifier to use for inference
HF_TOKEN Your Hugging Face / API key
ENV_URL URL of the running environment (default: http://localhost:7860)
SQL_ENV_TASK Task difficulty: easy | medium | hard (default: easy)
"""
import asyncio
import os
import textwrap
from typing import List, Optional
import httpx
from openai import OpenAI
# ββ Environment variables βββββββββββββββββββββββββββββββββββββ
API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1")
MODEL_NAME = os.getenv("MODEL_NAME", "Qwen/Qwen2.5-72B-Instruct")
API_KEY = os.getenv("HF_TOKEN") or os.getenv("API_KEY", "dummy")
TASK_NAME = os.getenv("SQL_ENV_TASK", "easy")
BENCHMARK = "sql-correction-env"
ENV_URL = os.getenv("ENV_URL", "http://localhost:7860")
MAX_STEPS = 8
SUCCESS_SCORE_THRESHOLD = 0.5
# ββ Stdout loggers β DO NOT MODIFY FORMAT ββββββββββββββββββββ
def log_start(task: str, env: str, model: str) -> None:
print(f"[START] task={task} env={env} model={model}", flush=True)
def log_step(step: int, action: str, reward: float,
done: bool, error: Optional[str]) -> None:
err = error if error else "null"
done_val = str(done).lower()
action_clean = action.replace("\n", " ").replace("\r", "").strip()
print(
f"[STEP] step={step} action={action_clean} "
f"reward={reward:.2f} done={done_val} error={err}",
flush=True,
)
def log_end(success: bool, steps: int,
score: float, rewards: List[float]) -> None:
rewards_str = ",".join(f"{r:.2f}" for r in rewards)
print(
f"[END] success={str(success).lower()} steps={steps} "
f"score={score:.3f} rewards={rewards_str}",
flush=True,
)
# ββ System prompt βββββββββββββββββββββββββββββββββββββββββββββ
SYSTEM_PROMPT = textwrap.dedent("""
You are an expert SQL debugger.
You will be shown a broken SQL query that contains typos or keyword errors.
Fix ALL errors and return ONLY the corrected SQL query.
No explanation, no markdown, no code blocks, no backticks.
Common errors: FORM->FROM, WEHRE->WHERE, GRUP->GROUP, HAVNG->HAVING,
ORDR->ORDER, INNE->INNER, LFT->LEFT, BETWEN->BETWEEN, DSC->DESC, SELCT->SELECT.
""").strip()
# ββ LLM call ββββββββββββββββββββββββββββββββββββββββββββββββββ
def get_model_action(client: OpenAI, obs: dict, history: List[str]) -> str:
history_block = "\n".join(history[-4:]) if history else "None"
user_prompt = textwrap.dedent(f"""
Broken SQL query:
{obs['broken_query']}
Schema context: {obs.get('schema_context') or 'Not provided'}
Error hint: {obs.get('error_hint') or 'None'}
Your previous attempt: {obs.get('previous_attempt') or 'None'}
Feedback: {obs.get('feedback') or 'None'}
Recent history:
{history_block}
Return ONLY the corrected SQL query.
""").strip()
try:
completion = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_prompt},
],
temperature=0.2,
max_tokens=300,
stream=False,
)
text = (completion.choices[0].message.content or "").strip()
return text if text else "SELECT 1"
except Exception as exc:
print(f"[DEBUG] LLM call failed: {exc}", flush=True)
return "SELECT 1"
# ββ Main episode loop βββββββββββββββββββββββββββββββββββββββββ
async def run_task(task_name: str) -> None:
client = OpenAI(base_url=API_BASE_URL, api_key=API_KEY)
http = httpx.AsyncClient(base_url=ENV_URL, timeout=30.0)
rewards: List[float] = []
history: List[str] = []
steps_taken: int = 0
score: float = 0.0
success: bool = False
log_start(task_name, BENCHMARK, MODEL_NAME)
try:
reset_resp = await http.post("/reset", json={"difficulty": task_name})
reset_resp.raise_for_status()
obs = reset_resp.json()
for step in range(1, MAX_STEPS + 1):
action_str = get_model_action(client, obs, history)
step_resp = await http.post("/step", json={"corrected_query": action_str})
step_resp.raise_for_status()
result = step_resp.json()
obs = result["observation"]
reward = float(result["reward"])
done = bool(result["done"])
error = result.get("info", {}).get("error")
rewards.append(reward)
steps_taken = step
history.append(f"Step {step}: attempt={action_str!r} reward={reward:+.2f}")
log_step(step, action_str, reward, done, error)
if done:
break
score = min(max(sum(rewards) / len(rewards) if rewards else 0.0, 0.0), 1.0)
success = score >= SUCCESS_SCORE_THRESHOLD
except Exception as exc:
print(f"[DEBUG] Episode error: {exc}", flush=True)
finally:
try:
await http.aclose()
except Exception as e:
print(f"[DEBUG] HTTP client close error: {e}", flush=True)
log_end(success, steps_taken, score, rewards)
async def main() -> None:
for difficulty in ("easy", "medium", "hard"):
await run_task(difficulty)
print("", flush=True)
if __name__ == "__main__":
asyncio.run(main())
|