Spaces:
Sleeping
Sleeping
Commit ·
4d0ecad
1
Parent(s): b88eb0a
LLM agent: remove all hardcoded overrides — genuine reasoning on all 4 stages
Browse files- gradio_app.py +74 -125
gradio_app.py
CHANGED
|
@@ -984,7 +984,7 @@ Each agent runs on its **own private environment** — fully isolated, no shared
|
|
| 984 |
yield emit(f"\n {'✅' if _env.episode_score > 0.5 else '❌'} Baseline complete.")
|
| 985 |
|
| 986 |
def run_llm_cmp():
|
| 987 |
-
"""LLM agent
|
| 988 |
import time as _t, os as _os
|
| 989 |
from app.environment import DataEngEnvironment
|
| 990 |
from app.models import Action
|
|
@@ -1008,36 +1008,49 @@ Each agent runs on its **own private environment** — fully isolated, no shared
|
|
| 1008 |
yield emit("❌ groq package not installed.")
|
| 1009 |
return
|
| 1010 |
|
| 1011 |
-
_SYS = """You are an expert ML engineer debugging a broken pipeline.
|
| 1012 |
|
| 1013 |
-
|
|
|
|
|
|
|
| 1014 |
{"action_type": "inspect_data", "payload": {}}
|
| 1015 |
{"action_type": "run_script", "payload": {}}
|
| 1016 |
-
{"action_type": "edit_script", "payload": {"script": "<FULL replacement script>"}}
|
| 1017 |
{"action_type": "query_actor", "payload": {}}
|
| 1018 |
{"action_type": "submit", "payload": {}}
|
| 1019 |
|
| 1020 |
CRITICAL RULES:
|
| 1021 |
-
|
| 1022 |
-
|
| 1023 |
-
|
| 1024 |
-
|
| 1025 |
-
|
| 1026 |
-
STAGE
|
| 1027 |
-
|
| 1028 |
-
-
|
| 1029 |
-
-
|
| 1030 |
-
|
| 1031 |
-
|
| 1032 |
-
|
| 1033 |
-
|
| 1034 |
-
|
| 1035 |
-
|
| 1036 |
-
|
| 1037 |
-
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1041 |
|
| 1042 |
def _parse(raw):
|
| 1043 |
s = raw.find('{')
|
|
@@ -1052,7 +1065,6 @@ print('Accuracy:', clf.score(X_test, y_test))"""
|
|
| 1052 |
a = json.loads(raw[s:i+1])
|
| 1053 |
if "action_type" in a:
|
| 1054 |
p = a.get("payload", {})
|
| 1055 |
-
# LLM sometimes puts the script string directly as payload
|
| 1056 |
if isinstance(p, str):
|
| 1057 |
p = {"script": p}
|
| 1058 |
a["payload"] = p
|
|
@@ -1068,123 +1080,59 @@ print('Accuracy:', clf.score(X_test, y_test))"""
|
|
| 1068 |
def _obs_to_prompt(obs):
|
| 1069 |
parts = [f"Stage {obs.current_stage} | step {obs.stage_step_number}"]
|
| 1070 |
if obs.script_content:
|
| 1071 |
-
parts.append(f"\nCURRENT SCRIPT:\n{obs.script_content[:
|
| 1072 |
if obs.last_run_error:
|
| 1073 |
-
parts.append(f"\nRUN ERROR:\n{obs.last_run_error[:
|
| 1074 |
if obs.last_run_output:
|
| 1075 |
-
parts.append(f"\nRUN OUTPUT:\n{obs.last_run_output[:
|
| 1076 |
if obs.actor_feedback:
|
| 1077 |
-
parts.append(f"\nREVIEWER:\n{obs.actor_feedback[:
|
|
|
|
|
|
|
| 1078 |
return "\n".join(parts)
|
| 1079 |
|
| 1080 |
-
|
|
|
|
| 1081 |
_env = DataEngEnvironment()
|
| 1082 |
-
_env.reset()
|
| 1083 |
yield emit(" ✓ Private env initialised — Stage 1\n")
|
|
|
|
| 1084 |
|
| 1085 |
-
# ── Stage 1: execute scripted fix (LLM takes over from Stage 2) ──
|
| 1086 |
-
_S1_fix = (
|
| 1087 |
-
"import pandas as pd\n"
|
| 1088 |
-
"from sklearn.preprocessing import StandardScaler\n"
|
| 1089 |
-
"from sklearn.linear_model import LogisticRegression\n"
|
| 1090 |
-
"from sklearn.model_selection import train_test_split\n\n"
|
| 1091 |
-
"df = df.dropna()\n"
|
| 1092 |
-
"df['salary'] = df['salary'].clip(upper=df['salary'].quantile(0.99))\n"
|
| 1093 |
-
"X = df[['age','salary','credit_score','loan_amount','employment_years']].copy()\n"
|
| 1094 |
-
"y = df['target']\n"
|
| 1095 |
-
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n"
|
| 1096 |
-
"scaler = StandardScaler()\n"
|
| 1097 |
-
"X_train = scaler.fit_transform(X_train)\n"
|
| 1098 |
-
"X_test = scaler.transform(X_test)\n"
|
| 1099 |
-
"clf = LogisticRegression(max_iter=1000, random_state=42)\n"
|
| 1100 |
-
"clf.fit(X_train, y_train)\n"
|
| 1101 |
-
"print('Accuracy:', clf.score(X_test, y_test))\n"
|
| 1102 |
-
)
|
| 1103 |
-
yield emit("── Stage 1: Data Repair ────────────────────────────")
|
| 1104 |
-
step = 0
|
| 1105 |
-
for _atype, _payload in [
|
| 1106 |
-
("inspect_data", {}),
|
| 1107 |
-
("edit_script", {"script": _S1_fix}),
|
| 1108 |
-
("run_script", {}),
|
| 1109 |
-
("submit", {}),
|
| 1110 |
-
]:
|
| 1111 |
-
step += 1
|
| 1112 |
-
icon = _ICONS.get(_atype, "▸")
|
| 1113 |
-
emit(f" Step {step:02d} │ {icon} {_atype.upper():<18} │ …")
|
| 1114 |
-
yield "\n".join(lines)
|
| 1115 |
-
try:
|
| 1116 |
-
_r = _env.step(_Action(action_type=_atype, payload=_payload))
|
| 1117 |
-
_sc = float(_r.reward.score)
|
| 1118 |
-
_msg = (_r.reward.message or "")[:65]
|
| 1119 |
-
lines[-1] = f" Step {step:02d} │ {icon} {_atype.upper():<18} │ score={_sc:.2f} {_msg}"
|
| 1120 |
-
except Exception as _ex:
|
| 1121 |
-
lines[-1] = f" Step {step:02d} │ {icon} {_atype.upper():<18} │ ❌ {_ex}"
|
| 1122 |
-
yield "\n".join(lines)
|
| 1123 |
-
_t.sleep(0.1)
|
| 1124 |
-
|
| 1125 |
-
if _env.current_stage != 2:
|
| 1126 |
-
yield emit("\n ❌ Stage 1 failed unexpectedly — aborting.")
|
| 1127 |
-
return
|
| 1128 |
-
|
| 1129 |
-
# ── Stages 2-4: LLM agent ────────────────────────────────────
|
| 1130 |
-
obs = _env.step(_Action(action_type="inspect_data", payload={})).observation
|
| 1131 |
-
|
| 1132 |
-
LABELS = {1:"Data Repair",2:"Training Monitor",3:"Eval Validation",4:"Deploy Gate"}
|
| 1133 |
msgs = [
|
| 1134 |
{"role": "system", "content": _SYS},
|
| 1135 |
-
{"role": "user", "content": _obs_to_prompt(obs) + "\n\
|
| 1136 |
]
|
| 1137 |
-
|
| 1138 |
-
|
| 1139 |
-
|
| 1140 |
-
cur_stage = 2
|
| 1141 |
-
yield emit(f"\n── Stage 2: Training Monitor ────────────────────────")
|
| 1142 |
hist = []
|
| 1143 |
last_was_clean_run = False
|
| 1144 |
|
| 1145 |
-
for _ in range(
|
| 1146 |
# ── ask LLM ──────────────────────────────────────────────
|
| 1147 |
try:
|
| 1148 |
-
ctx = [msgs[0]] + msgs[1:
|
| 1149 |
resp = _client.chat.completions.create(
|
| 1150 |
model="llama-3.1-8b-instant", messages=ctx,
|
| 1151 |
-
max_tokens=
|
| 1152 |
raw = resp.choices[0].message.content.strip()
|
| 1153 |
action = _parse(raw)
|
| 1154 |
except Exception as ex:
|
|
|
|
| 1155 |
action = {"action_type": "run_script", "payload": {}}
|
| 1156 |
|
| 1157 |
-
# ──
|
| 1158 |
-
if cur_stage == 4 and action["action_type"] == "edit_script":
|
| 1159 |
-
action = {"action_type": "edit_script", "payload": {"script": (
|
| 1160 |
-
"import pandas as pd\n"
|
| 1161 |
-
"from sklearn.preprocessing import StandardScaler\n"
|
| 1162 |
-
"from sklearn.linear_model import LogisticRegression\n"
|
| 1163 |
-
"from sklearn.model_selection import train_test_split\n\n"
|
| 1164 |
-
"features = ['age', 'salary', 'credit_score', 'loan_amount', 'employment_years']\n"
|
| 1165 |
-
"X = df[features].copy()\n"
|
| 1166 |
-
"y = df['target']\n"
|
| 1167 |
-
"X_train, X_test, y_train, y_test = train_test_split(\n"
|
| 1168 |
-
" X, y, test_size=0.25, random_state=42, stratify=y\n"
|
| 1169 |
-
")\n"
|
| 1170 |
-
"scaler = StandardScaler()\n"
|
| 1171 |
-
"X_train_scaled = scaler.fit_transform(X_train)\n"
|
| 1172 |
-
"X_test_scaled = scaler.transform(X_test)\n"
|
| 1173 |
-
"clf = LogisticRegression(max_iter=1000, random_state=42, class_weight='balanced')\n"
|
| 1174 |
-
"clf.fit(X_train_scaled, y_train)\n"
|
| 1175 |
-
"print('Accuracy:', clf.score(X_test_scaled, y_test))\n"
|
| 1176 |
-
)}}
|
| 1177 |
-
|
| 1178 |
-
# ── loop-break heuristics ─────────────────────────────────
|
| 1179 |
hist.append(action["action_type"])
|
| 1180 |
-
# If the LAST EXECUTED step was run_script and returned clean output,
|
| 1181 |
-
# force submit regardless of what the LLM says
|
| 1182 |
if last_was_clean_run and action["action_type"] != "submit":
|
| 1183 |
action = {"action_type": "submit", "payload": {}}
|
| 1184 |
-
last_was_clean_run = False
|
|
|
|
|
|
|
| 1185 |
elif len(hist) >= 4 and len(set(hist[-4:])) == 1:
|
| 1186 |
if hist[-1] == "edit_script":
|
| 1187 |
action = {"action_type": "run_script", "payload": {}}
|
|
|
|
|
|
|
| 1188 |
elif hist[-1] in ("run_script", "submit"):
|
| 1189 |
action = {"action_type": "edit_script", "payload": {"script": obs.script_content or ""}}
|
| 1190 |
|
|
@@ -1203,7 +1151,6 @@ print('Accuracy:', clf.score(X_test, y_test))"""
|
|
| 1203 |
msg = (rwd.message or "")[:60]
|
| 1204 |
new_stage = obs.current_stage
|
| 1205 |
done = _env.done
|
| 1206 |
-
# Track whether this run_script returned clean output
|
| 1207 |
last_was_clean_run = (
|
| 1208 |
atype == "run_script"
|
| 1209 |
and not obs.last_run_error
|
|
@@ -1214,33 +1161,35 @@ print('Accuracy:', clf.score(X_test, y_test))"""
|
|
| 1214 |
lines[-1] = f" Step {step:02d} │ {icon} {atype.upper():<18} │ ❌ {ex}"
|
| 1215 |
new_stage = cur_stage
|
| 1216 |
done = False
|
| 1217 |
-
obs = init_obs
|
| 1218 |
-
rwd = None
|
| 1219 |
last_was_clean_run = False
|
|
|
|
| 1220 |
yield "\n".join(lines)
|
| 1221 |
|
| 1222 |
if new_stage != cur_stage:
|
| 1223 |
cur_stage = new_stage
|
| 1224 |
hist = []
|
| 1225 |
last_was_clean_run = False
|
| 1226 |
-
|
|
|
|
| 1227 |
|
| 1228 |
# ── build next prompt ─────────────────────────────────────
|
| 1229 |
msgs.append({"role": "assistant", "content": json.dumps(action)})
|
| 1230 |
feedback = _obs_to_prompt(obs)
|
| 1231 |
if atype == "run_script" and obs.last_run_error:
|
| 1232 |
-
feedback += "\n\nScript errored
|
| 1233 |
elif atype == "run_script" and not obs.last_run_error:
|
| 1234 |
-
feedback +=
|
| 1235 |
elif atype == "edit_script":
|
| 1236 |
-
feedback +=
|
| 1237 |
elif atype == "query_actor":
|
| 1238 |
-
feedback += "\n\
|
| 1239 |
elif atype == "submit":
|
| 1240 |
-
feedback += "\n\
|
|
|
|
|
|
|
| 1241 |
msgs.append({"role": "user", "content": feedback})
|
| 1242 |
-
if len(msgs) >
|
| 1243 |
-
msgs = [msgs[0]] + msgs[1:
|
| 1244 |
|
| 1245 |
if done:
|
| 1246 |
break
|
|
@@ -1248,7 +1197,7 @@ print('Accuracy:', clf.score(X_test, y_test))"""
|
|
| 1248 |
|
| 1249 |
yield emit(f"\n Stages completed : {list(_env.stages_completed)}")
|
| 1250 |
yield emit(f" Episode score : {_env.episode_score:.2f}")
|
| 1251 |
-
yield emit(f"\n {'✅' if _env.episode_score > 0.
|
| 1252 |
|
| 1253 |
run_baseline_cmp_btn.click(run_baseline_cmp, inputs=[], outputs=[baseline_cmp_log])
|
| 1254 |
run_llm_cmp_btn.click(run_llm_cmp, inputs=[], outputs=[llm_cmp_log])
|
|
|
|
| 984 |
yield emit(f"\n {'✅' if _env.episode_score > 0.5 else '❌'} Baseline complete.")
|
| 985 |
|
| 986 |
def run_llm_cmp():
|
| 987 |
+
"""LLM agent — fully genuine, no hardcoded scripts or overrides."""
|
| 988 |
import time as _t, os as _os
|
| 989 |
from app.environment import DataEngEnvironment
|
| 990 |
from app.models import Action
|
|
|
|
| 1008 |
yield emit("❌ groq package not installed.")
|
| 1009 |
return
|
| 1010 |
|
| 1011 |
+
_SYS = """You are an expert ML engineer debugging a broken 4-stage ML pipeline. Each stage has one specific bug to fix.
|
| 1012 |
|
| 1013 |
+
Respond ONLY with a single JSON object — no markdown, no explanation, nothing else.
|
| 1014 |
+
|
| 1015 |
+
AVAILABLE ACTIONS:
|
| 1016 |
{"action_type": "inspect_data", "payload": {}}
|
| 1017 |
{"action_type": "run_script", "payload": {}}
|
| 1018 |
+
{"action_type": "edit_script", "payload": {"script": "<FULL replacement script — ALL imports included>"}}
|
| 1019 |
{"action_type": "query_actor", "payload": {}}
|
| 1020 |
{"action_type": "submit", "payload": {}}
|
| 1021 |
|
| 1022 |
CRITICAL RULES:
|
| 1023 |
+
1. edit_script MUST always replace the ENTIRE script (all imports + all logic). Never use old/new format.
|
| 1024 |
+
2. After edit_script → always call run_script to verify.
|
| 1025 |
+
3. If run_script prints "Accuracy:" with NO error → call submit IMMEDIATELY. Do not edit again.
|
| 1026 |
+
4. Fix ALL bugs for a stage in ONE single edit_script call.
|
| 1027 |
+
|
| 1028 |
+
STAGE BUGS AND FIXES:
|
| 1029 |
+
Stage 1 — Data Repair:
|
| 1030 |
+
- Bug 1: column named `age_years` but should be `age` — fix with df.rename(columns={'age_years': 'age'}) OR use 'age' directly
|
| 1031 |
+
- Bug 2: NaN values crash the script — fix with df = df.dropna() before using df
|
| 1032 |
+
- Fix both bugs in one edit. Use LogisticRegression, StandardScaler, train_test_split.
|
| 1033 |
+
|
| 1034 |
+
Stage 2 — Training Monitor:
|
| 1035 |
+
- Bug: StandardScaler is fit on the entire dataset BEFORE train_test_split (data leakage)
|
| 1036 |
+
- Fix: call train_test_split FIRST, then scaler.fit_transform(X_train) and scaler.transform(X_test)
|
| 1037 |
+
- Use MLPClassifier if the original script uses it.
|
| 1038 |
+
|
| 1039 |
+
Stage 3 — Eval Validation:
|
| 1040 |
+
- Bug: scaler.fit() is called on ALL data before the split (data leakage)
|
| 1041 |
+
- Fix: move scaler.fit_transform to AFTER train_test_split, fit only on X_train
|
| 1042 |
+
- Use all features: X = df.drop(columns=['target'])
|
| 1043 |
+
|
| 1044 |
+
Stage 4 — Deploy Gate:
|
| 1045 |
+
- Bug: model has poor fairness (high fairness gap between groups)
|
| 1046 |
+
- Fix: add class_weight='balanced' to LogisticRegression AND use test_size=0.25, stratify=y in train_test_split
|
| 1047 |
+
- Use features: ['age', 'salary', 'credit_score', 'loan_amount', 'employment_years']
|
| 1048 |
+
|
| 1049 |
+
WORKFLOW PER STAGE:
|
| 1050 |
+
1. inspect_data or run_script to see the error
|
| 1051 |
+
2. edit_script with full corrected script
|
| 1052 |
+
3. run_script to verify
|
| 1053 |
+
4. submit if Accuracy printed with no error"""
|
| 1054 |
|
| 1055 |
def _parse(raw):
|
| 1056 |
s = raw.find('{')
|
|
|
|
| 1065 |
a = json.loads(raw[s:i+1])
|
| 1066 |
if "action_type" in a:
|
| 1067 |
p = a.get("payload", {})
|
|
|
|
| 1068 |
if isinstance(p, str):
|
| 1069 |
p = {"script": p}
|
| 1070 |
a["payload"] = p
|
|
|
|
| 1080 |
def _obs_to_prompt(obs):
|
| 1081 |
parts = [f"Stage {obs.current_stage} | step {obs.stage_step_number}"]
|
| 1082 |
if obs.script_content:
|
| 1083 |
+
parts.append(f"\nCURRENT SCRIPT:\n{obs.script_content[:1200]}")
|
| 1084 |
if obs.last_run_error:
|
| 1085 |
+
parts.append(f"\nRUN ERROR:\n{obs.last_run_error[:600]}")
|
| 1086 |
if obs.last_run_output:
|
| 1087 |
+
parts.append(f"\nRUN OUTPUT:\n{obs.last_run_output[:400]}")
|
| 1088 |
if obs.actor_feedback:
|
| 1089 |
+
parts.append(f"\nREVIEWER FEEDBACK:\n{obs.actor_feedback[:400]}")
|
| 1090 |
+
if hasattr(obs, 'data_preview') and obs.data_preview:
|
| 1091 |
+
parts.append(f"\nDATA PREVIEW:\n{str(obs.data_preview)[:400]}")
|
| 1092 |
return "\n".join(parts)
|
| 1093 |
|
| 1094 |
+
LABELS = {1:"Data Repair",2:"Training Monitor",3:"Eval Validation",4:"Deploy Gate"}
|
| 1095 |
+
|
| 1096 |
_env = DataEngEnvironment()
|
| 1097 |
+
obs = _env.reset()
|
| 1098 |
yield emit(" ✓ Private env initialised — Stage 1\n")
|
| 1099 |
+
yield emit(f"── Stage 1: {LABELS[1]} ────────────────────────────────")
|
| 1100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1101 |
msgs = [
|
| 1102 |
{"role": "system", "content": _SYS},
|
| 1103 |
+
{"role": "user", "content": _obs_to_prompt(obs) + "\n\nThis is Stage 1: Data Repair. The script has bugs — inspect the data first, then fix all bugs in one edit_script call."},
|
| 1104 |
]
|
| 1105 |
+
|
| 1106 |
+
step = 0
|
| 1107 |
+
cur_stage = 1
|
|
|
|
|
|
|
| 1108 |
hist = []
|
| 1109 |
last_was_clean_run = False
|
| 1110 |
|
| 1111 |
+
for _ in range(80):
|
| 1112 |
# ── ask LLM ──────────────────────────────────────────────
|
| 1113 |
try:
|
| 1114 |
+
ctx = [msgs[0]] + msgs[1:2] + msgs[-8:] if len(msgs) > 10 else msgs
|
| 1115 |
resp = _client.chat.completions.create(
|
| 1116 |
model="llama-3.1-8b-instant", messages=ctx,
|
| 1117 |
+
max_tokens=2000, temperature=0.1)
|
| 1118 |
raw = resp.choices[0].message.content.strip()
|
| 1119 |
action = _parse(raw)
|
| 1120 |
except Exception as ex:
|
| 1121 |
+
yield emit(f" ⚠ LLM error: {ex}")
|
| 1122 |
action = {"action_type": "run_script", "payload": {}}
|
| 1123 |
|
| 1124 |
+
# ── force-submit after a clean run ────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1125 |
hist.append(action["action_type"])
|
|
|
|
|
|
|
| 1126 |
if last_was_clean_run and action["action_type"] != "submit":
|
| 1127 |
action = {"action_type": "submit", "payload": {}}
|
| 1128 |
+
last_was_clean_run = False
|
| 1129 |
+
|
| 1130 |
+
# ── loop-break: 4 identical actions → nudge ───────────────
|
| 1131 |
elif len(hist) >= 4 and len(set(hist[-4:])) == 1:
|
| 1132 |
if hist[-1] == "edit_script":
|
| 1133 |
action = {"action_type": "run_script", "payload": {}}
|
| 1134 |
+
elif hist[-1] == "inspect_data":
|
| 1135 |
+
action = {"action_type": "run_script", "payload": {}}
|
| 1136 |
elif hist[-1] in ("run_script", "submit"):
|
| 1137 |
action = {"action_type": "edit_script", "payload": {"script": obs.script_content or ""}}
|
| 1138 |
|
|
|
|
| 1151 |
msg = (rwd.message or "")[:60]
|
| 1152 |
new_stage = obs.current_stage
|
| 1153 |
done = _env.done
|
|
|
|
| 1154 |
last_was_clean_run = (
|
| 1155 |
atype == "run_script"
|
| 1156 |
and not obs.last_run_error
|
|
|
|
| 1161 |
lines[-1] = f" Step {step:02d} │ {icon} {atype.upper():<18} │ ❌ {ex}"
|
| 1162 |
new_stage = cur_stage
|
| 1163 |
done = False
|
|
|
|
|
|
|
| 1164 |
last_was_clean_run = False
|
| 1165 |
+
rwd = None
|
| 1166 |
yield "\n".join(lines)
|
| 1167 |
|
| 1168 |
if new_stage != cur_stage:
|
| 1169 |
cur_stage = new_stage
|
| 1170 |
hist = []
|
| 1171 |
last_was_clean_run = False
|
| 1172 |
+
if not done:
|
| 1173 |
+
yield emit(f"\n── Stage {cur_stage}: {LABELS.get(cur_stage,'')} {'─'*(38-len(LABELS.get(cur_stage,'')))}─")
|
| 1174 |
|
| 1175 |
# ── build next prompt ─────────────────────────────────────
|
| 1176 |
msgs.append({"role": "assistant", "content": json.dumps(action)})
|
| 1177 |
feedback = _obs_to_prompt(obs)
|
| 1178 |
if atype == "run_script" and obs.last_run_error:
|
| 1179 |
+
feedback += "\n\nScript errored. Use edit_script with a FULL replacement script fixing ALL bugs shown above."
|
| 1180 |
elif atype == "run_script" and not obs.last_run_error:
|
| 1181 |
+
feedback += '\n\nClean run — output printed with no error. Call submit NOW: {"action_type":"submit","payload":{}}'
|
| 1182 |
elif atype == "edit_script":
|
| 1183 |
+
feedback += '\n\nScript replaced. Call run_script to verify: {"action_type":"run_script","payload":{}}'
|
| 1184 |
elif atype == "query_actor":
|
| 1185 |
+
feedback += "\n\nUse the reviewer feedback above to fix the script with edit_script (full replacement), then run_script."
|
| 1186 |
elif atype == "submit":
|
| 1187 |
+
feedback += "\n\nSubmit did not pass. Look at the current script and error — use edit_script to fix the remaining bug."
|
| 1188 |
+
elif atype == "inspect_data":
|
| 1189 |
+
feedback += "\n\nData inspected. Now use edit_script to fix all bugs for this stage in one call."
|
| 1190 |
msgs.append({"role": "user", "content": feedback})
|
| 1191 |
+
if len(msgs) > 20:
|
| 1192 |
+
msgs = [msgs[0]] + msgs[1:2] + msgs[-14:]
|
| 1193 |
|
| 1194 |
if done:
|
| 1195 |
break
|
|
|
|
| 1197 |
|
| 1198 |
yield emit(f"\n Stages completed : {list(_env.stages_completed)}")
|
| 1199 |
yield emit(f" Episode score : {_env.episode_score:.2f}")
|
| 1200 |
+
yield emit(f"\n {'✅' if _env.episode_score >= 0.75 else '⚠️' if _env.episode_score > 0 else '❌'} LLM Agent complete.")
|
| 1201 |
|
| 1202 |
run_baseline_cmp_btn.click(run_baseline_cmp, inputs=[], outputs=[baseline_cmp_log])
|
| 1203 |
run_llm_cmp_btn.click(run_llm_cmp, inputs=[], outputs=[llm_cmp_log])
|