sravaniamere commited on
Commit
51264be
·
1 Parent(s): 0a57921

Fix inference startup and healthcheck compatibility

Browse files
Files changed (3) hide show
  1. Dockerfile +1 -1
  2. inference.py +68 -60
  3. server.py +2 -1
Dockerfile CHANGED
@@ -19,6 +19,6 @@ EXPOSE 7860
19
 
20
  # health check so HF Space knows when it's ready
21
  HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 \
22
- CMD curl -f http://localhost:7860/health || exit 1
23
 
24
  CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
 
19
 
20
  # health check so HF Space knows when it's ready
21
  HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 \
22
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:7860/health', timeout=3)"
23
 
24
  CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
inference.py CHANGED
@@ -1,6 +1,6 @@
1
  """
2
- inference.py SQL Correction Environment Baseline Script
3
- ==========================================================
4
  MANDATORY - Place this file in the ROOT of the project.
5
 
6
  Required environment variables:
@@ -20,23 +20,27 @@ from typing import List, Optional
20
  import httpx
21
  from openai import OpenAI
22
 
23
- # ── Environment variables ─────────────────────────────────────
24
  API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1")
25
- MODEL_NAME = os.getenv("MODEL_NAME", "Qwen/Qwen2.5-72B-Instruct")
26
- API_KEY = os.getenv("HF_TOKEN") or os.getenv("API_KEY", "dummy")
27
- TASK_NAME = os.getenv("SQL_ENV_TASK", "easy")
28
- BENCHMARK = "sql-correction-env"
29
- ENV_URL = os.getenv("ENV_URL", "https://SyncShift-sql-correction-env.hf.space")
30
- MAX_STEPS = 8
31
  SUCCESS_SCORE_THRESHOLD = 0.5
32
 
33
- # ── Stdout loggers — DO NOT MODIFY FORMAT ────────────────────
34
 
35
  def log_start(task: str, env: str, model: str) -> None:
36
  print(f"[START] task={task} env={env} model={model}", flush=True)
37
 
38
- def log_step(step: int, action: str, reward: float,
39
- done: bool, error: Optional[str]) -> None:
 
 
 
 
 
 
40
  err = error if error else "null"
41
  done_val = str(done).lower()
42
  action_clean = action.replace("\n", " ").replace("\r", "").strip()
@@ -46,8 +50,8 @@ def log_step(step: int, action: str, reward: float,
46
  flush=True,
47
  )
48
 
49
- def log_end(success: bool, steps: int,
50
- score: float, rewards: List[float]) -> None:
51
  rewards_str = ",".join(f"{r:.2f}" for r in rewards)
52
  print(
53
  f"[END] success={str(success).lower()} steps={steps} "
@@ -55,40 +59,44 @@ def log_end(success: bool, steps: int,
55
  flush=True,
56
  )
57
 
58
- # ── System prompt ─────────────────────────────────────────────
59
- SYSTEM_PROMPT = textwrap.dedent("""
 
60
  You are an expert SQL debugger.
61
  You will be shown a broken SQL query that contains typos or keyword errors.
62
  Fix ALL errors and return ONLY the corrected SQL query.
63
  No explanation, no markdown, no code blocks, no backticks.
64
  Common errors: FORM->FROM, WEHRE->WHERE, GRUP->GROUP, HAVNG->HAVING,
65
  ORDR->ORDER, INNE->INNER, LFT->LEFT, BETWEN->BETWEEN, DSC->DESC, SELCT->SELECT.
66
- """).strip()
 
 
67
 
68
- # ── LLM call ──────────────────────────────────────────────────
69
  def get_model_action(client: OpenAI, obs: dict, history: List[str]) -> str:
70
  history_block = "\n".join(history[-4:]) if history else "None"
71
- user_prompt = textwrap.dedent(f"""
 
72
  Broken SQL query:
73
- {obs['broken_query']}
74
 
75
- Schema context: {obs.get('schema_context') or 'Not provided'}
76
- Error hint: {obs.get('error_hint') or 'None'}
77
- Your previous attempt: {obs.get('previous_attempt') or 'None'}
78
- Feedback: {obs.get('feedback') or 'None'}
79
 
80
  Recent history:
81
  {history_block}
82
 
83
  Return ONLY the corrected SQL query.
84
- """).strip()
 
85
 
86
  try:
87
  completion = client.chat.completions.create(
88
  model=MODEL_NAME,
89
  messages=[
90
  {"role": "system", "content": SYSTEM_PROMPT},
91
- {"role": "user", "content": user_prompt},
92
  ],
93
  temperature=0.2,
94
  max_tokens=300,
@@ -100,15 +108,15 @@ def get_model_action(client: OpenAI, obs: dict, history: List[str]) -> str:
100
  print(f"[DEBUG] LLM call failed: {exc}", flush=True)
101
  return "SELECT 1"
102
 
103
- # ── Main episode loop ─────────────────────────────────────────
104
  async def run_task(task_name: str) -> None:
105
  client = OpenAI(base_url=API_BASE_URL, api_key=API_KEY)
106
 
107
- rewards: List[float] = []
108
- history: List[str] = []
109
- steps_taken: int = 0
110
- score: float = 0.0
111
- success: bool = False
112
 
113
  log_start(task_name, BENCHMARK, MODEL_NAME)
114
 
@@ -117,48 +125,43 @@ async def run_task(task_name: str) -> None:
117
  http = httpx.AsyncClient(base_url=ENV_URL, timeout=60.0)
118
 
119
  try:
120
- reset_resp = await http.post("/reset", json={"task_name": task_name})
121
  reset_resp.raise_for_status()
122
  obs = reset_resp.json()
123
- except Exception as e:
124
- print(f"[DEBUG] Reset failed: {e}", flush=True)
125
  return
126
 
127
  for step in range(1, MAX_STEPS + 1):
128
  try:
129
  action_str = get_model_action(client, obs, history)
130
- except Exception as e:
131
- print(f"[DEBUG] Model failed: {e}", flush=True)
132
  action_str = "SELECT 1"
133
 
134
  try:
135
- step_resp = await http.post(
136
- "/step",
137
- json={"corrected_query": action_str},
138
- )
139
  step_resp.raise_for_status()
140
  result = step_resp.json()
141
- except Exception as e:
142
- print(f"[DEBUG] Step failed: {e}", flush=True)
143
  break
144
 
145
- obs = result["observation"]
146
- reward = float(result["reward"])
147
- done = bool(result["done"])
148
- error = result.get("info", {}).get("error")
149
 
150
  rewards.append(reward)
151
  steps_taken = step
152
- history.append(
153
- f"Step {step}: attempt={action_str!r} reward={reward:+.2f}"
154
- )
155
 
156
  log_step(step, action_str, reward, done, error)
157
 
158
  if done:
159
  break
160
 
161
- score = min(max(sum(rewards) / len(rewards) if rewards else 0.0, 0.0), 1.0)
162
  success = score >= SUCCESS_SCORE_THRESHOLD
163
 
164
  except Exception as exc:
@@ -168,22 +171,27 @@ async def run_task(task_name: str) -> None:
168
  if http is not None:
169
  try:
170
  await http.aclose()
171
- except Exception as e:
172
- print(f"[DEBUG] HTTP close error: {e}", flush=True)
173
  log_end(success, steps_taken, score, rewards)
174
 
 
175
  async def main() -> None:
176
  try:
177
- for difficulty in ("easy", "medium", "hard"):
 
 
 
178
  await run_task(difficulty)
179
  print("", flush=True)
180
- except Exception as e:
181
- print(f"[DEBUG] Main error: {e}", flush=True)
 
182
 
183
  if __name__ == "__main__":
184
  try:
185
  asyncio.run(main())
186
- except Exception as e:
187
- print(f"[DEBUG] Fatal error: {e}", flush=True)
188
- finally:
189
- sys.exit(0)
 
1
  """
2
+ inference.py - SQL Correction Environment Baseline Script
3
+ =========================================================
4
  MANDATORY - Place this file in the ROOT of the project.
5
 
6
  Required environment variables:
 
20
  import httpx
21
  from openai import OpenAI
22
 
 
23
  API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1")
24
+ MODEL_NAME = os.getenv("MODEL_NAME", "Qwen/Qwen2.5-72B-Instruct")
25
+ API_KEY = os.getenv("HF_TOKEN") or os.getenv("API_KEY", "dummy")
26
+ TASK_NAME = os.getenv("SQL_ENV_TASK", "easy")
27
+ BENCHMARK = "sql-correction-env"
28
+ ENV_URL = os.getenv("ENV_URL", "http://localhost:7860")
29
+ MAX_STEPS = 8
30
  SUCCESS_SCORE_THRESHOLD = 0.5
31
 
 
32
 
33
  def log_start(task: str, env: str, model: str) -> None:
34
  print(f"[START] task={task} env={env} model={model}", flush=True)
35
 
36
+
37
+ def log_step(
38
+ step: int,
39
+ action: str,
40
+ reward: float,
41
+ done: bool,
42
+ error: Optional[str],
43
+ ) -> None:
44
  err = error if error else "null"
45
  done_val = str(done).lower()
46
  action_clean = action.replace("\n", " ").replace("\r", "").strip()
 
50
  flush=True,
51
  )
52
 
53
+
54
+ def log_end(success: bool, steps: int, score: float, rewards: List[float]) -> None:
55
  rewards_str = ",".join(f"{r:.2f}" for r in rewards)
56
  print(
57
  f"[END] success={str(success).lower()} steps={steps} "
 
59
  flush=True,
60
  )
61
 
62
+
63
+ SYSTEM_PROMPT = textwrap.dedent(
64
+ """
65
  You are an expert SQL debugger.
66
  You will be shown a broken SQL query that contains typos or keyword errors.
67
  Fix ALL errors and return ONLY the corrected SQL query.
68
  No explanation, no markdown, no code blocks, no backticks.
69
  Common errors: FORM->FROM, WEHRE->WHERE, GRUP->GROUP, HAVNG->HAVING,
70
  ORDR->ORDER, INNE->INNER, LFT->LEFT, BETWEN->BETWEEN, DSC->DESC, SELCT->SELECT.
71
+ """
72
+ ).strip()
73
+
74
 
 
75
  def get_model_action(client: OpenAI, obs: dict, history: List[str]) -> str:
76
  history_block = "\n".join(history[-4:]) if history else "None"
77
+ user_prompt = textwrap.dedent(
78
+ f"""
79
  Broken SQL query:
80
+ {obs["broken_query"]}
81
 
82
+ Schema context: {obs.get("schema_context") or "Not provided"}
83
+ Error hint: {obs.get("error_hint") or "None"}
84
+ Your previous attempt: {obs.get("previous_attempt") or "None"}
85
+ Feedback: {obs.get("feedback") or "None"}
86
 
87
  Recent history:
88
  {history_block}
89
 
90
  Return ONLY the corrected SQL query.
91
+ """
92
+ ).strip()
93
 
94
  try:
95
  completion = client.chat.completions.create(
96
  model=MODEL_NAME,
97
  messages=[
98
  {"role": "system", "content": SYSTEM_PROMPT},
99
+ {"role": "user", "content": user_prompt},
100
  ],
101
  temperature=0.2,
102
  max_tokens=300,
 
108
  print(f"[DEBUG] LLM call failed: {exc}", flush=True)
109
  return "SELECT 1"
110
 
111
+
112
  async def run_task(task_name: str) -> None:
113
  client = OpenAI(base_url=API_BASE_URL, api_key=API_KEY)
114
 
115
+ rewards: List[float] = []
116
+ history: List[str] = []
117
+ steps_taken = 0
118
+ score = 0.0
119
+ success = False
120
 
121
  log_start(task_name, BENCHMARK, MODEL_NAME)
122
 
 
125
  http = httpx.AsyncClient(base_url=ENV_URL, timeout=60.0)
126
 
127
  try:
128
+ reset_resp = await http.post("/reset", json={"difficulty": task_name})
129
  reset_resp.raise_for_status()
130
  obs = reset_resp.json()
131
+ except Exception as exc:
132
+ print(f"[DEBUG] Reset failed: {exc}", flush=True)
133
  return
134
 
135
  for step in range(1, MAX_STEPS + 1):
136
  try:
137
  action_str = get_model_action(client, obs, history)
138
+ except Exception as exc:
139
+ print(f"[DEBUG] Model failed: {exc}", flush=True)
140
  action_str = "SELECT 1"
141
 
142
  try:
143
+ step_resp = await http.post("/step", json={"corrected_query": action_str})
 
 
 
144
  step_resp.raise_for_status()
145
  result = step_resp.json()
146
+ except Exception as exc:
147
+ print(f"[DEBUG] Step failed: {exc}", flush=True)
148
  break
149
 
150
+ obs = result["observation"]
151
+ reward = float(result["reward"])
152
+ done = bool(result["done"])
153
+ error = result.get("info", {}).get("error")
154
 
155
  rewards.append(reward)
156
  steps_taken = step
157
+ history.append(f"Step {step}: attempt={action_str!r} reward={reward:+.2f}")
 
 
158
 
159
  log_step(step, action_str, reward, done, error)
160
 
161
  if done:
162
  break
163
 
164
+ score = min(max(sum(rewards) / len(rewards) if rewards else 0.0, 0.0), 1.0)
165
  success = score >= SUCCESS_SCORE_THRESHOLD
166
 
167
  except Exception as exc:
 
171
  if http is not None:
172
  try:
173
  await http.aclose()
174
+ except Exception as exc:
175
+ print(f"[DEBUG] HTTP close error: {exc}", flush=True)
176
  log_end(success, steps_taken, score, rewards)
177
 
178
+
179
  async def main() -> None:
180
  try:
181
+ difficulties = (
182
+ (TASK_NAME,) if TASK_NAME in {"easy", "medium", "hard"} else ("easy", "medium", "hard")
183
+ )
184
+ for difficulty in difficulties:
185
  await run_task(difficulty)
186
  print("", flush=True)
187
+ except Exception as exc:
188
+ print(f"[DEBUG] Main error: {exc}", flush=True)
189
+
190
 
191
  if __name__ == "__main__":
192
  try:
193
  asyncio.run(main())
194
+ except Exception as exc:
195
+ print(f"[DEBUG] Fatal error: {exc}", flush=True)
196
+ finally:
197
+ sys.exit(0)
server.py CHANGED
@@ -18,6 +18,7 @@ from sql_env import SQLCorrectionEnv, SQLAction
18
 
19
  class ResetRequest(BaseModel):
20
  difficulty: Optional[str] = "easy"
 
21
  task_index: Optional[int] = None
22
 
23
 
@@ -60,7 +61,7 @@ app.add_middleware(
60
  async def reset(request: ResetRequest = ResetRequest()):
61
  """Reset the environment. Returns initial observation."""
62
  global env
63
- difficulty = request.difficulty or "easy"
64
  if difficulty not in ("easy", "medium", "hard"):
65
  raise HTTPException(status_code=400, detail="difficulty must be easy, medium, or hard")
66
 
 
18
 
19
  class ResetRequest(BaseModel):
20
  difficulty: Optional[str] = "easy"
21
+ task_name: Optional[str] = None
22
  task_index: Optional[int] = None
23
 
24
 
 
61
  async def reset(request: ResetRequest = ResetRequest()):
62
  """Reset the environment. Returns initial observation."""
63
  global env
64
+ difficulty = request.task_name or request.difficulty or "easy"
65
  if difficulty not in ("easy", "medium", "hard"):
66
  raise HTTPException(status_code=400, detail="difficulty must be easy, medium, or hard")
67