openenv / inference.py
AnkushRaheja's picture
Upload 22 files
042e419 verified
Raw
History Blame Contribute Delete
5.19 kB
from __future__ import annotations
import json
import os
import re
from dotenv import load_dotenv
from openai import OpenAI
from env.environment import DataCleaningEnv
from env.models import Action
load_dotenv()
API_BASE_URL = os.getenv("API_BASE_URL", "https://api.groq.com/openai/v1")
MODEL_NAME = os.getenv("MODEL_NAME", "meta-llama/llama-4-scout-17b-16e-instruct")
HF_TOKEN = os.getenv("HF_TOKEN")
TASK_ID = os.getenv("TASK_ID", "task1_easy")
MAX_STEPS = int(os.getenv("MAX_STEPS", "15"))
ENV_NAME = "data-cleaning-benchmark"
if HF_TOKEN is None:
raise ValueError("HF_TOKEN environment variable is required")
client = OpenAI(base_url=API_BASE_URL, api_key=HF_TOKEN)
SYSTEM_PROMPT = """You are a data cleaning agent. Analyse the observation and choose ONE cleaning action.
Available action types and required fields:
fill_missing -> column (str), strategy (mean|median|mode|constant), value (if constant)
standardize_values -> column (str), mapping (dict old->new)
remove_duplicates -> (no extra fields)
remove_row -> row_id (int from _row_id column in preview)
convert_type -> column (str), target_type (float|int|str|datetime)
clip_outliers -> column (str), lower (float|null), upper (float|null)
submit -> (no extra fields; use when dataset is clean)
Rules:
- Respond with a SINGLE valid JSON object and NOTHING else.
- No markdown fences, no explanation.
- When no issues remain, always respond with: {"type": "submit"}
Examples:
{"type": "remove_duplicates"}
{"type": "fill_missing", "column": "age", "strategy": "median"}
{"type": "standardize_values", "column": "country", "mapping": {"USA": "United States", "US": "United States", "UK": "United Kingdom", "CAN": "Canada", "australia": "Australia", "AUS": "Australia"}}
{"type": "convert_type", "column": "date", "target_type": "datetime"}
{"type": "convert_type", "column": "price", "target_type": "float"}
{"type": "clip_outliers", "column": "session_duration", "lower": 0.0, "upper": 1000.0}
{"type": "submit"}
"""
def get_action(obs_dict: dict, history: list[dict]) -> dict:
user_msg = {
"role": "user",
"content": (
"Current observation:\n" + json.dumps(obs_dict, indent=2, default=str) + "\n\nNext action (JSON only):"
),
}
history.append(user_msg)
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role": "system", "content": SYSTEM_PROMPT}] + history,
max_tokens=256,
temperature=0,
)
raw = response.choices[0].message.content.strip()
history.append({"role": "assistant", "content": raw})
clean = re.sub(r"```[a-z]*\n?", "", raw).replace("```", "").strip()
try:
return json.loads(clean)
except json.JSONDecodeError:
match = re.search(r"\{.*\}", clean, re.DOTALL)
if match:
return json.loads(match.group())
return {"type": "submit"}
def run_inference() -> None:
env = DataCleaningEnv()
rewards: list[float] = []
history: list[dict] = []
step = 0
done = False
success = False
print(f"[START] task={TASK_ID} env={ENV_NAME} model={MODEL_NAME}", flush=True)
try:
obs = env.reset(task_id=TASK_ID)
while not done and step < MAX_STEPS:
try:
action_dict = get_action(obs.model_dump(), history)
action = Action(**action_dict)
except Exception:
action_dict = {"type": "submit"}
action = Action(type="submit")
result = env.step(action)
obs = result.observation
done = result.done
reward = result.reward
error = result.info.get("error")
rewards.append(reward)
step += 1
action_str = json.dumps(action_dict, separators=(",", ":"), default=str)
print(
f"[STEP] step={step} action={action_str} "
f"reward={reward:.2f} done={'true' if done else 'false'} "
f"error={error if error else 'null'}",
flush=True,
)
if not done:
result = env.step(Action(type="submit"))
rewards.append(result.reward)
step += 1
print(
f"[STEP] step={step} action={{\"type\":\"submit\"}} "
f"reward={result.reward:.2f} done=true error={result.info.get('error') or 'null'}",
flush=True,
)
success = bool(env.final_score >= 0.5)
except Exception:
success = False
finally:
try:
if hasattr(env, "close"):
env.close()
except Exception:
pass
rewards_str = ",".join(f"{reward:.2f}" for reward in rewards)
print(
f"[END] success={'true' if success else 'false'} "
f"steps={step} score={env.final_score:.2f} rewards={rewards_str}",
flush=True,
)
if __name__ == "__main__":
run_inference()