vanishingradient commited on
Commit
681342c
·
verified ·
1 Parent(s): 2c121ec

Add kaggle/train_grpo.py

Browse files
Files changed (1) hide show
  1. kaggle/train_grpo.py +57 -13
kaggle/train_grpo.py CHANGED
@@ -202,6 +202,11 @@ _TOOL_CALL_RE = re.compile(
202
  r"<tool_call>\s*(\{.*?\})\s*</tool_call>",
203
  re.DOTALL,
204
  )
 
 
 
 
 
205
 
206
 
207
  def _env_tool_callables(env: Any) -> list[Callable[..., str]]:
@@ -214,22 +219,61 @@ def _env_tool_callables(env: Any) -> list[Callable[..., str]]:
214
  return [getattr(env, name) for name in names]
215
 
216
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  def _parse_tool_calls(text: str) -> list[dict[str, Any]]:
 
218
  calls: list[dict[str, Any]] = []
219
- for m in _TOOL_CALL_RE.finditer(text or ""):
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  try:
221
- obj = json.loads(m.group(1))
222
- name = obj.get("name") or obj.get("function", {}).get("name")
223
- args = obj.get("arguments") or obj.get("parameters") or obj.get("function", {}).get("arguments") or {}
224
- if isinstance(args, str):
225
- try:
226
- args = json.loads(args)
227
- except json.JSONDecodeError:
228
- args = {"input": args}
229
- if name:
230
- calls.append({"name": str(name), "arguments": args if isinstance(args, dict) else {}})
231
  except json.JSONDecodeError:
232
  continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  return calls
234
 
235
 
@@ -994,8 +1038,8 @@ def main(cfg: Cfg | None = None) -> None:
994
  bf16=use_bf16,
995
  fp16=use_fp16,
996
  remove_unused_columns=False,
997
- # log_completions_reward (0) + DeepAgentSWEEnv.get_reward (1)
998
- reward_weights=[0.0, 1.0],
999
  hub_model_id=cfg.hub_model_id,
1000
  hub_token=os.environ["HF_TOKEN"],
1001
  push_to_hub=False,
 
202
  r"<tool_call>\s*(\{.*?\})\s*</tool_call>",
203
  re.DOTALL,
204
  )
205
+ _JSON_FENCE_RE = re.compile(r"```(?:json)?\s*(\{.*?\})\s*```", re.DOTALL)
206
+ _BARE_JSON_RE = re.compile(
207
+ r"\{\s*\"name\"\s*:\s*\"[^\"]+\"\s*,\s*\"arguments\"\s*:\s*\{.*?\}\s*\}",
208
+ re.DOTALL,
209
+ )
210
 
211
 
212
  def _env_tool_callables(env: Any) -> list[Callable[..., str]]:
 
219
  return [getattr(env, name) for name in names]
220
 
221
 
222
+ def _parse_one_tool_obj(obj: dict[str, Any]) -> dict[str, Any] | None:
223
+ name = obj.get("name") or obj.get("function", {}).get("name")
224
+ args = (
225
+ obj.get("arguments")
226
+ or obj.get("parameters")
227
+ or obj.get("function", {}).get("arguments")
228
+ or {}
229
+ )
230
+ if isinstance(args, str):
231
+ try:
232
+ args = json.loads(args)
233
+ except json.JSONDecodeError:
234
+ args = {"input": args}
235
+ if not name:
236
+ return None
237
+ return {"name": str(name), "arguments": args if isinstance(args, dict) else {}}
238
+
239
+
240
  def _parse_tool_calls(text: str) -> list[dict[str, Any]]:
241
+ """Parse Qwen-style tool calls: <tool_call>, ```json fences, or bare {name,arguments}."""
242
  calls: list[dict[str, Any]] = []
243
+ seen: set[str] = set()
244
+ raw = text or ""
245
+
246
+ candidates: list[str] = []
247
+ candidates.extend(m.group(1) for m in _TOOL_CALL_RE.finditer(raw))
248
+ candidates.extend(m.group(1) for m in _JSON_FENCE_RE.finditer(raw))
249
+ candidates.extend(m.group(0) for m in _BARE_JSON_RE.finditer(raw))
250
+
251
+ # Whole-string JSON object / list fallback
252
+ stripped = raw.strip()
253
+ if stripped.startswith("{") or stripped.startswith("["):
254
+ candidates.append(stripped)
255
+
256
+ for blob in candidates:
257
  try:
258
+ obj = json.loads(blob)
 
 
 
 
 
 
 
 
 
259
  except json.JSONDecodeError:
260
  continue
261
+ items = obj if isinstance(obj, list) else [obj]
262
+ for item in items:
263
+ if not isinstance(item, dict):
264
+ continue
265
+ # unwrap {"type":"function","function":{...}}
266
+ if "function" in item and isinstance(item["function"], dict):
267
+ parsed = _parse_one_tool_obj(item["function"])
268
+ else:
269
+ parsed = _parse_one_tool_obj(item)
270
+ if parsed is None:
271
+ continue
272
+ key = json.dumps(parsed, sort_keys=True)
273
+ if key in seen:
274
+ continue
275
+ seen.add(key)
276
+ calls.append(parsed)
277
  return calls
278
 
279
 
 
1038
  bf16=use_bf16,
1039
  fp16=use_fp16,
1040
  remove_unused_columns=False,
1041
+ # Do not set reward_weights here: env get_reward is appended after init,
1042
+ # so a fixed [0,1] length mismatches and crashes GRPOTrainer.
1043
  hub_model_id=cfg.hub_model_id,
1044
  hub_token=os.environ["HF_TOKEN"],
1045
  push_to_hub=False,