Try to fix badly encoded json tex commands from the flash-lite calls
This commit is contained in:
1 parent
32764c101b
commit
6a6ed178ef
4 files changed
+75
-8
No files matched your search
@@ -22,6 +22,7 @@ from copienator import (
|
||||
workspace_from_args,
|
||||
)
|
||||
from copienator.platform import validate_windows_labels
|
||||
from copienator.latex_json import repair_latex_json
|
||||
from copienator.filesystem import staged_directory
|
||||
from copienator.utils import compile_to_pdf
|
||||
|
||||
@@ -69,7 +70,7 @@ class ExamContext(BaseModel):
|
||||
# --- Modèles pour la Requête 4 (Barèmes) ---
|
||||
class RubricItem(BaseModel):
|
||||
label: str = Field(description="Label exact de la question, à conserver sans traduction.")
|
||||
rubric_content: str = Field(description="Barème détaillé sur 4 points : toutes les consignes, explications et justifications doivent être rédigées en français.")
|
||||
rubric_content: str = Field(description="Barème détaillé sur 4 points, en français, avec formules LaTeX. Échapper chaque antislash LaTeX conformément à la syntaxe JSON.")
|
||||
|
||||
class GroupRubrics(BaseModel):
|
||||
rubrics: list[RubricItem]
|
||||
@@ -101,6 +102,27 @@ question fournie, cette liste contient un objet avec son `label` exact et
|
||||
son barème en français dans `rubric_content`.
|
||||
"""
|
||||
|
||||
LATEX_JSON_INSTRUCTION = r"""
|
||||
IMPORTANT — Échappement JSON du LaTeX :
|
||||
Dans les chaînes JSON, chaque antislash LaTeX doit être doublé.
|
||||
Exemple d’échappement dans un barème (adapte les clés au schéma demandé) :
|
||||
{"rubrics":[{"label":"1)","rubric_content":"1 point : $\\frac{1}{2}$ et $f \\circ g$.\n1 point : $x \\rightarrow 0$ et $x \\not=0$."}]}
|
||||
Ne confonds pas les commandes LaTeX avec les échappements JSON :
|
||||
\\frac, \\rightarrow, \\not, \\theta et \\begin sont des commandes LaTeX ;
|
||||
\n est réservé à un véritable saut de ligne du texte.
|
||||
"""
|
||||
|
||||
|
||||
def validate_rubric_content(content: str) -> str:
|
||||
"""Catch decoded control escapes; ordinary JSON newlines remain valid.
|
||||
|
||||
A misescaped LaTeX command starting with n is indistinguishable from
|
||||
an intentional newline. Do not guess or rewrite those after decoding.
|
||||
"""
|
||||
if any((ord(char) < 32 and char != "\n") or ord(char) == 127 for char in content):
|
||||
raise ValueError("Rubric contains control characters, likely from unescaped LaTeX")
|
||||
return content
|
||||
|
||||
# --- Modèle fusionné (pour le reste du script) ---
|
||||
class QuestionItem(BaseModel):
|
||||
label: str
|
||||
@@ -178,6 +200,12 @@ traduire, et conserve le LaTeX ainsi que les labels exacts.
|
||||
Renvoie le résultat dans la liste `contexts` de l'objet JSON attendu.
|
||||
"""
|
||||
|
||||
PROMPT_1 += LATEX_JSON_INSTRUCTION
|
||||
PROMPT_2 += LATEX_JSON_INSTRUCTION
|
||||
PROMPT_3 += LATEX_JSON_INSTRUCTION
|
||||
PROMPT_4 += LATEX_JSON_INSTRUCTION
|
||||
|
||||
|
||||
def find_file(folder: Path, base_name: str) -> Path | None:
|
||||
for ext in [".org", ".tex"]:
|
||||
path = folder / f"{base_name}{ext}"
|
||||
@@ -202,10 +230,10 @@ def generate_rubrics(client, group_context_text: str) -> dict[str, str]:
|
||||
response_json_schema=GroupRubrics.model_json_schema(),
|
||||
),
|
||||
)
|
||||
rubrics = GroupRubrics.model_validate_json(response.text).rubrics
|
||||
rubrics = GroupRubrics.model_validate_json(repair_latex_json(response.text)).rubrics
|
||||
if len({item.label for item in rubrics}) != len(rubrics):
|
||||
raise ValueError("Gemini returned duplicate rubric labels")
|
||||
return {item.label: item.rubric_content for item in rubrics}
|
||||
return {item.label: validate_rubric_content(item.rubric_content) for item in rubrics}
|
||||
|
||||
|
||||
def validate_groups(groups: list[list[str]], labels: list[str]) -> None:
|
||||
@@ -364,7 +392,7 @@ def process_exam(
|
||||
print("Saving questions to cache...")
|
||||
atomic_write_text(cache_q_file, response_q_text)
|
||||
|
||||
questions_data = ExamQuestions.model_validate_json(response_q_text)
|
||||
questions_data = ExamQuestions.model_validate_json(repair_latex_json(response_q_text))
|
||||
|
||||
# ==========================================
|
||||
# REQUÊTE 2 : Extraction des Corrections
|
||||
@@ -403,7 +431,7 @@ def process_exam(
|
||||
print("Saving solutions to cache...")
|
||||
atomic_write_text(cache_s_file, response_s_text)
|
||||
|
||||
solutions_data = ExamSolutions.model_validate_json(response_s_text)
|
||||
solutions_data = ExamSolutions.model_validate_json(repair_latex_json(response_s_text))
|
||||
|
||||
# ==========================================
|
||||
# REQUÊTE 3 : Extraction du Contexte (Notations, etc.)
|
||||
@@ -440,7 +468,7 @@ def process_exam(
|
||||
print("Saving context to cache...")
|
||||
atomic_write_text(cache_c_file, response_c_text)
|
||||
|
||||
context_data = ExamContext.model_validate_json(response_c_text)
|
||||
context_data = ExamContext.model_validate_json(repair_latex_json(response_c_text))
|
||||
|
||||
# ==========================================
|
||||
# FUSION des trois résultats
|
||||
|
||||
Reference in new issue
Block a user