disha2005 commited on
Commit
1585e6e
·
1 Parent(s): a506622
Files changed (1) hide show
  1. inference.py +144 -64
inference.py CHANGED
@@ -1,46 +1,97 @@
1
  import os
 
2
  import pandas as pd
 
3
  from openai import OpenAI
4
  from env.environment import DataCleaningEnv
5
 
6
  # ------------------ ENV VARIABLES ------------------
7
- API_BASE_URL = os.getenv("API_BASE_URL")
8
- API_KEY = os.getenv("API_KEY") # their injected key
9
  MODEL_NAME = os.getenv("MODEL_NAME", "Qwen/Qwen2.5-72B-Instruct")
10
 
11
- # ------------------ DEBUG: print env at startup ------------------
12
- print(f"[DEBUG] API_BASE_URL={API_BASE_URL}")
13
- print(f"[DEBUG] API_KEY={'set' if API_KEY else 'MISSING'}")
14
- print(f"[DEBUG] MODEL_NAME={MODEL_NAME}")
15
-
16
  # ------------------ OPENAI CLIENT ------------------
17
- # Fail hard if env vars are missing — don't silently skip
18
- if not API_BASE_URL:
19
- raise RuntimeError("API_BASE_URL environment variable is not set!")
20
- if not API_KEY:
21
- raise RuntimeError("API_KEY environment variable is not set!")
22
 
23
- client = OpenAI(
24
- base_url=API_BASE_URL,
25
- api_key=API_KEY
26
- )
 
 
 
 
27
 
28
  MAX_STEPS = 6
29
 
30
  # ------------------ LOGGING ------------------
 
 
 
31
  def log_start(task, env, model):
32
- print(f"[START] task={task} env={env} model={model}")
33
 
34
  def log_step(step, action, reward, done, error):
35
- error_val = error if error else "null"
36
- print(f"[STEP] step={step} action={action} reward={reward:.2f} done={str(done).lower()} error={error_val}")
37
 
38
- def log_end(success, steps, score, rewards):
39
  rewards_str = ",".join(f"{r:.2f}" for r in rewards)
40
- print(f"[END] success={str(success).lower()} steps={steps} score={score:.3f} rewards={rewards_str}")
 
 
 
 
41
 
42
  # ------------------ LLM DECISION ------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  def get_action_from_llm(dataset, history):
 
 
 
44
  prompt = f"""
45
  You are an intelligent data cleaning agent.
46
 
@@ -57,78 +108,107 @@ Return ONLY:
57
  action_type,column_name
58
  """
59
 
60
- # ✅ No try/except — let it raise so we know if LLM call fails
61
- response = client.chat.completions.create(
62
- model=MODEL_NAME,
63
- messages=[{"role": "user", "content": prompt}],
64
- temperature=0.3,
65
- max_tokens=50
66
- )
67
 
68
- print(f"[DEBUG] LLM raw response: {response}") # ✅ confirm call went through
69
 
70
- output = response.choices[0].message.content.strip()
71
- print(f"[DEBUG] LLM output: {output}")
72
 
73
- parts = output.split(",")
74
- if len(parts) < 2:
75
- return {"type": "deduplicate", "column": "customer_id"}
76
 
77
- action_type, column = parts[0], parts[1]
78
- return {"type": action_type.strip(), "column": column.strip()}
 
 
 
 
79
 
80
  # ------------------ MAIN ------------------
81
  def main():
82
- env = DataCleaningEnv(task=1)
83
- obs = env.reset()
84
-
85
  rewards = []
86
  steps_taken = 0
87
  history = []
 
 
88
 
89
  log_start("task1", "data_cleaning", MODEL_NAME)
90
 
91
- for step in range(1, MAX_STEPS + 1):
 
 
92
 
93
- df = pd.DataFrame(obs["dataset"])
94
- col_info = {}
95
 
96
- for col in df.columns:
97
- col_info[col] = {
98
- "nulls": float(df[col].isnull().mean()),
99
- "dtype": str(df[col].dtype),
100
- "unique": int(df[col].nunique())
101
- }
102
 
103
- summary = f"""
 
 
 
 
 
 
 
104
  Columns: {list(df.columns)}
105
  Column Info: {col_info}
106
  Duplicates: {df.duplicated().sum()}
107
  Sample: {df.head(3).to_dict()}
108
  """
109
 
110
- action = get_action_from_llm(summary, history)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
- if str(action) in history:
113
- action = {"type": "deduplicate", "column": "customer_id"}
114
 
115
- history.append(str(action))
116
 
117
- obs, reward, done, _ = env.step(action)
 
118
 
119
- rewards.append(reward)
120
- steps_taken = step
 
121
 
122
- log_step(step, str(action), reward, done, None)
 
 
 
123
 
124
- if done:
125
- break
 
 
 
 
126
 
127
- final = env.submit_cleaned_data(env.dirty_df)
128
- score = final["final_score"]
129
- success = score > 0.3
130
- log_end(success, steps_taken, score, rewards)
131
 
132
  # ------------------ RUN ------------------
133
  if __name__ == "__main__":
134
- main() # ✅ removed try/except so real errors surface
 
1
  import os
2
+ import sys
3
  import pandas as pd
4
+ import httpx
5
  from openai import OpenAI
6
  from env.environment import DataCleaningEnv
7
 
8
  # ------------------ ENV VARIABLES ------------------
9
+ API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1")
10
+ HF_TOKEN = os.getenv("HF_TOKEN") or os.getenv("API_KEY")
11
  MODEL_NAME = os.getenv("MODEL_NAME", "Qwen/Qwen2.5-72B-Instruct")
12
 
 
 
 
 
 
13
  # ------------------ OPENAI CLIENT ------------------
14
+ client = None
15
+
16
+ try:
17
+ if not HF_TOKEN:
18
+ raise RuntimeError("API_KEY or HF_TOKEN environment variable is not set")
19
 
20
+ client = OpenAI(
21
+ base_url=API_BASE_URL,
22
+ api_key=HF_TOKEN,
23
+ http_client=httpx.Client(timeout=30.0, trust_env=False)
24
+ )
25
+ except Exception as e:
26
+ print(f"[WARN] OpenAI client init failed: {e}", file=sys.stderr)
27
+ client = None
28
 
29
  MAX_STEPS = 6
30
 
31
  # ------------------ LOGGING ------------------
32
+ def clean_line(value):
33
+ return str(value).replace("\r", " ").replace("\n", " ")
34
+
35
  def log_start(task, env, model):
36
+ print(f"[START] task={clean_line(task)} env={clean_line(env)} model={clean_line(model)}")
37
 
38
  def log_step(step, action, reward, done, error):
39
+ error_val = clean_line(error) if error else "null"
40
+ print(f"[STEP] step={step} action={clean_line(action)} reward={reward:.2f} done={str(done).lower()} error={error_val}")
41
 
42
+ def log_end(success, steps, rewards, score=None):
43
  rewards_str = ",".join(f"{r:.2f}" for r in rewards)
44
+
45
+ if score is None:
46
+ print(f"[END] success={str(success).lower()} steps={steps} rewards={rewards_str}")
47
+ else:
48
+ print(f"[END] success={str(success).lower()} steps={steps} score={score:.4f} rewards={rewards_str}")
49
 
50
  # ------------------ LLM DECISION ------------------
51
+ def fallback_action(history):
52
+ actions = [
53
+ {"type": "fill_nulls", "column": "city"},
54
+ {"type": "deduplicate", "column": "customer_id"},
55
+ {"type": "convert_types", "column": "age"},
56
+ {"type": "trim_whitespace", "column": "city"},
57
+ {"type": "normalize", "column": "income"},
58
+ {"type": "remove_nulls", "column": "customer_id"},
59
+ ]
60
+
61
+ for action in actions:
62
+ if str(action) not in history:
63
+ return action
64
+
65
+ return {"type": "deduplicate", "column": "customer_id"}
66
+
67
+ def normalize_action(action, df, history):
68
+ valid_actions = {
69
+ "fill_nulls",
70
+ "remove_nulls",
71
+ "deduplicate",
72
+ "convert_types",
73
+ "trim_whitespace",
74
+ "normalize",
75
+ }
76
+
77
+ if not isinstance(action, dict):
78
+ return fallback_action(history)
79
+
80
+ action_type = action.get("type")
81
+ column = action.get("column")
82
+
83
+ if action_type not in valid_actions:
84
+ return fallback_action(history)
85
+
86
+ if action_type != "deduplicate" and column not in df.columns:
87
+ return fallback_action(history)
88
+
89
+ return action
90
+
91
  def get_action_from_llm(dataset, history):
92
+ if client is None:
93
+ return fallback_action(history)
94
+
95
  prompt = f"""
96
  You are an intelligent data cleaning agent.
97
 
 
108
  action_type,column_name
109
  """
110
 
111
+ try:
112
+ response = client.chat.completions.create(
113
+ model=MODEL_NAME,
114
+ messages=[{"role": "user", "content": prompt}],
115
+ temperature=0.3,
116
+ max_tokens=50
117
+ )
118
 
119
+ output = response.choices[0].message.content.strip()
120
 
121
+ first_line = output.splitlines()[0].strip()
122
+ parts = first_line.split(",", 1)
123
 
124
+ if len(parts) < 2:
125
+ return fallback_action(history)
 
126
 
127
+ action_type, column = parts[0], parts[1]
128
+ return {"type": action_type.strip(), "column": column.strip()}
129
+
130
+ except Exception as e:
131
+ print(f"[WARN] LLM call failed: {e}", file=sys.stderr)
132
+ return fallback_action(history)
133
 
134
  # ------------------ MAIN ------------------
135
  def main():
136
+ env = None
 
 
137
  rewards = []
138
  steps_taken = 0
139
  history = []
140
+ success = False
141
+ score = None
142
 
143
  log_start("task1", "data_cleaning", MODEL_NAME)
144
 
145
+ try:
146
+ env = DataCleaningEnv(task=1)
147
+ obs = env.reset()
148
 
149
+ for step in range(1, MAX_STEPS + 1):
 
150
 
151
+ df = pd.DataFrame(obs["dataset"])
152
+ col_info = {}
 
 
 
 
153
 
154
+ for col in df.columns:
155
+ col_info[col] = {
156
+ "nulls": float(df[col].isnull().mean()),
157
+ "dtype": str(df[col].dtype),
158
+ "unique": int(df[col].nunique())
159
+ }
160
+
161
+ summary = f"""
162
  Columns: {list(df.columns)}
163
  Column Info: {col_info}
164
  Duplicates: {df.duplicated().sum()}
165
  Sample: {df.head(3).to_dict()}
166
  """
167
 
168
+ action = get_action_from_llm(summary, history)
169
+ action = normalize_action(action, df, history)
170
+
171
+ if str(action) in history:
172
+ action = fallback_action(history)
173
+ action = normalize_action(action, df, history)
174
+
175
+ history.append(str(action))
176
+
177
+ error = None
178
+
179
+ try:
180
+ obs, reward, done, _ = env.step(action)
181
+ except Exception as e:
182
+ error = str(e)
183
+ reward = 0.0
184
+ done = True
185
 
186
+ rewards.append(reward)
187
+ steps_taken = step
188
 
189
+ log_step(step, str(action), reward, done, error)
190
 
191
+ if done:
192
+ break
193
 
194
+ final = env.submit_cleaned_data(env.dirty_df)
195
+ score = final["final_score"]
196
+ success = score > 0.3
197
 
198
+ except Exception as e:
199
+ print(f"[WARN] inference failed: {e}", file=sys.stderr)
200
+ success = False
201
+ score = None
202
 
203
+ finally:
204
+ if env is not None and hasattr(env, "close"):
205
+ try:
206
+ env.close()
207
+ except Exception as e:
208
+ print(f"[WARN] env.close failed: {e}", file=sys.stderr)
209
 
210
+ log_end(success, steps_taken, rewards, score)
 
 
 
211
 
212
  # ------------------ RUN ------------------
213
  if __name__ == "__main__":
214
+ main()