Spaces:
Running
Running
Download evaluate_formulas.py from Baiyinyou/PDF2TEX_Formula: direct link, hf CLI and curl.
- Browser
- Download file 4.8 kB
-
https://huggingface.co/spaces/Baiyinyou/PDF2TEX_Formula/resolve/main/evaluate_formulas.py
- Command line
-
hf download hf://spaces/Baiyinyou/PDF2TEX_Formula/evaluate_formulas.py
-
curl -L -o evaluate_formulas.py https://huggingface.co/spaces/Baiyinyou/PDF2TEX_Formula/resolve/main/evaluate_formulas.py
4.8 kB
| #evaluate_formulas.py | |
| import re | |
| import json | |
| import os | |
| from typing import List | |
| from semantic_head import FormulaEvaluator, ExplanationLLM | |
| # ------------------------------------------------- | |
| # 0. Preprocessing / Cleaning garbled LaTeX | |
| # ------------------------------------------------- | |
| def clean_garbled_latex(formula: str) -> str: | |
| formula = re.sub(r"\\underline\{\{.*?\}\}", "", formula) # remove \underline{{...}} | |
| formula = re.sub(r"\\mit|\\bf", "", formula) # remove OCR font artifacts | |
| formula = re.sub(r"\\l\\ell|\\L", "", formula) # remove garbled letters | |
| formula = formula.replace(r"\rlap/", "") # remove broken \rlap/ | |
| formula = re.sub(r"[\^\_]{2,}", "", formula) # remove multiple consecutive ^ or _ | |
| formula = re.sub(r"\{\s*\}", "", formula) # remove empty braces | |
| formula = formula.strip() | |
| if len(formula) < 2: | |
| return "" | |
| return formula | |
| # ------------------------------------------------- | |
| # 1. Extract formulas from LaTeX | |
| # ------------------------------------------------- | |
| MATH_ENV_PATTERNS = [ | |
| r"\$(.*?)\$", | |
| r"\\\((.*?)\\\)", | |
| r"\\\[(.*?)\\\]", | |
| r"\\begin\{equation\}(.*?)\\end\{equation\}", | |
| ] | |
| def extract_formulas_from_tex(tex_content: str) -> List[str]: | |
| formulas = [] | |
| for pattern in MATH_ENV_PATTERNS: | |
| matches = re.findall(pattern, tex_content, re.DOTALL) | |
| formulas.extend([m.strip() for m in matches]) | |
| return formulas | |
| # ------------------------------------------------- | |
| # 2. Automatic minor LaTeX fixes | |
| # ------------------------------------------------- | |
| def fix_latex(formula: str) -> str: | |
| # Common minor fixes | |
| formula = re.sub(r"\\backslash\s*([A-Za-z])", r"\\setminus \1", formula) | |
| formula = formula.replace(r"\implies", r"\Rightarrow") | |
| return formula | |
| # ------------------------------------------------- | |
| # 3. Evaluate formulas and store results | |
| # ------------------------------------------------- | |
| def evaluate_tex_file(tex_path: str, output_dir: str, base_model=None, lora_dir=None): | |
| os.makedirs(output_dir, exist_ok=True) | |
| with open(tex_path, "r", encoding="utf-8") as f: | |
| tex_content = f.read() | |
| formulas = extract_formulas_from_tex(tex_content) | |
| print(f"Found {len(formulas)} formulas.") | |
| explainer = ExplanationLLM(base_model=base_model, lora_dir=lora_dir) | |
| evaluator = FormulaEvaluator(explainer) | |
| results = [] | |
| for formula in formulas: | |
| cleaned = clean_garbled_latex(formula) | |
| if not cleaned: | |
| print(f"Skipping garbled formula: {formula[:30]}...") | |
| continue | |
| fixed_formula = fix_latex(cleaned) | |
| res = evaluator.evaluate(fixed_formula) | |
| res_entry = { | |
| "original_formula": formula, | |
| "fixed_formula": fixed_formula, | |
| **res | |
| } | |
| results.append(res_entry) | |
| # Save as JSON | |
| json_path = os.path.join(output_dir, "results_final.json") | |
| with open(json_path, "w", encoding="utf-8") as f: | |
| json.dump(results, f, indent=2) | |
| # Save as TXT summary | |
| txt_path = os.path.join(output_dir, "results_final.txt") | |
| with open(txt_path, "w", encoding="utf-8") as f: | |
| for r in results: | |
| f.write(f"Original Formula: {r['original_formula']}\n") | |
| f.write(f"Fixed Formula: {r['fixed_formula']}\n") | |
| f.write(f"Syntactically correct: {r['syntactically_correct']}\n") | |
| f.write(f"Mathematically correct: {r['mathematically_correct']}\n") | |
| f.write(f"Error type: {r['error_type']}\n") | |
| f.write(f"Confidence: {r['confidence']}\n") | |
| f.write(f"Source: {r['source']}\n") | |
| f.write(f"Suggested fix: {r.get('suggested_fix')}\n") | |
| f.write(f"Explanation:\n{r['explanation']}\n") | |
| f.write("="*80 + "\n") | |
| print(f"Results saved to {json_path} and {txt_path}") | |
| # ------------------------------------------------- | |
| # 4. CLI usage | |
| # ------------------------------------------------- | |
| if __name__ == "__main__": | |
| import argparse | |
| parser = argparse.ArgumentParser( | |
| description="Evaluate formulas in a LaTeX file with automatic minor fixes and optional LoRA model." | |
| ) | |
| parser.add_argument("tex_file", help="Path to the LaTeX file") | |
| parser.add_argument("--out", default="output", help="Output directory") | |
| parser.add_argument("--base_model", default="Qwen/Qwen2.5-Math-1.5B-Instruct", | |
| help="Base model name") | |
| parser.add_argument("--lora_dir", default=None, | |
| help="LoRA directory for fine-tuned model") | |
| args = parser.parse_args() | |
| evaluate_tex_file( | |
| tex_path=args.tex_file, | |
| output_dir=args.out, | |
| base_model=args.base_model, | |
| lora_dir=args.lora_dir | |
| ) |