Diseñe un canal RLVR multimodal completo con Open-MM-RL, indicaciones de visión y lenguaje, puntuación de recompensas y exportación GRPO
EXTRACT_PATS = [
r”\\boxed\{([^{}]+)\}”, r”final\s+respuesta\s*[:=]\s*([^\n]+)”, r”respuesta\s*[:=]\s*([^\n]+)”, ]def extract_final(texto): si no texto: devuelve “” para p en EXTRACT_PATS: m = re.search(p, text, flags=re.IGNORECASE) si m: devuelve m.group(1).strip().strip(“.,;”) líneas = [l.strip() for l in str(text).strip().splitlines() if l.strip()]
lineas de retorno[-1] si las líneas else “” def latex_to_sympy(s): s = (s o “”).strip().strip(“$”).strip() s = re.sub(r”^\\[\[\(]”, “”, s); s = re.sub(r”\\[\]\)]$”, “”, s) s = (s.replace(“\\pi”, “pi”).replace(“\\cdot”, “*”).replace(“\\times”, “*”) .replace(“\\,”, “”).replace(“\\;”, “”).replace(“\\!”, “”)) s = re.sub(r”\\frac\s*\{([^{}]+)\}\s*\{([^{}]+)\}”, r”((\1)/(\2))”, s) s = re.sub(r”\\sqrt\s*\{([^{}]+)\}”, r”sqrt(\1)”, s) s = s.replace(“^”, “**”) s = re.sub(r”\\[a-zA-Z]+”, “”, s) s = s.replace(“{“, “(“).replace(“}”, “)”) return s def grade(pred, gold, tol=1e-4): “””Recompensa verificable en [0,1]: exacto > numérico > sympy-simbólico > parcial.””” si pred es Ninguno o el oro es Ninguno: devuelve 0.0 p = extract_final(str(pred)).strip() g = str(gold).strip() norma = lambda x: re.sub(r”\s+”, “”, x.lower()).strip(“$.,;[]()”) si norma(p) == norma(g): devolver 1.0 def to_float(x): intentar: devolver float(latex_to_sympy(x)) excepto Excepción: intentar: devolver float(sp.sympify(latex_to_sympy(x)).evalf()) excepto Excepción: devolver Ninguna fp, fg = to_float(p), to_float(g) si fp no es Ninguno y fg no lo es Ninguno: si abs(fp – fg) / max(1.0, abs(fg)) < tol: devuelve 1.0 prueba: ep = sp.sympify(latex_to_sympy(p)); por ejemplo = sp.sympify(latex_to_sympy(g)) if sp.simplify(ep - eg) == 0: devuelve 1.0 excepto Excepción: pasa si norma(g) y norma(g) en norma(p): return 0.5 return 0.0 print("\n=== Comprobaciones de cordura del evaluador ===") para pred, gold, want in [ ("The answer is \\boxed{120}", "[120]", 1.0), ("Después de calcular: 7396 \\pi", "7396\\pi", 1.0), ("Respuesta final: -71/4", "-\\frac{71}{4}", 1.0), ("Por lo tanto el resultado es 0.0074", "0.0074", 1.0), ("Respuesta final: nucleus accumbens", "Nucleus accumbens",1.0), ("No lo sé", "12", 0.0), ]: print(f" pred={pred[:38]!r:42s} gold={gold!r:22s} -> r={grade(pred, gold)} (want {want})”) SYSTEM = (“Eres un experto en STEM que resuelve problemas de razonamiento multimodal. ” “Verás una pregunta y una o más cifras. ” “Razona paso a paso, luego termina exactamente con una línea:\n” “Respuesta final: “) def build_prompt(ex): img_tags = “\n”.unirse(f”[Image {i+1}]”para i en el rango(len(ex[“images”]))) return f”{SYSTEM}\n\n{img_tags}\n\nPregunta:\n{ex[‘question’]}\n\nPensemos paso a paso.” print(“\n=== Ejemplo de mensaje (truncado) ===”) print(build_prompt(ds[0])[:600]”…\n”)