Add textbook formalization pipeline (extract -> LLM formalize -> elaboration check -> library assembly)

- extract_section.py: slice a book section out of a pdftotext -layout dump and
  list its labeled Theorem/Proposition/Lemma/Corollary/Definition items.
- formalize.py: LLM-formalize a section into Lean 4 candidate statements
  (preferring Mathlib vocabulary) plus a definitions manifest.
- check_statements.py: elaboration-only sanity check against a real
  Mathlib-backed Lean project (must run outside the Cowork sandbox, which has
  no Lean toolchain and can't run macOS binaries anyway).
- build_library.py: assemble solved lean-bench results into a reusable .lean
  file, reusing each winning proof verbatim.
- llm.py: standalone OpenAI-compatible chat client + .env loader, kept
  independent of lean_agent so this pipeline works without it installed.
- Source PDFs and raw/layout text dumps are gitignored (copyrighted material);
  only code and the final short Lean statement datasets are tracked.
This commit is contained in:
2026-09-17 17:04:19 +00:00
parent 99638be637
commit caedf2e6f4
13 changed files with 871 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
import unittest
from textbook.extract_section import extract_section, labeled_statements
FIXTURE = """\
1.6. Divisibility in the Integers
intro text
Proposition 1.6.1.
body
Theorem 1.6.6. There are infinitely many prime numbers.
Proof. blah
36 1. ALGEBRAIC THEMES
Theorem 1.6.6. There are infinitely many prime numbers.
Proof continues after a page break, repeats the label.
1.7. Modular Arithmetic
next section text
"""
class ExtractSectionTests(unittest.TestCase):
def test_extract_section_slices_between_headings(self):
section = extract_section(FIXTURE, '1.6. Divisibility in the Integers', '1.7. Modular Arithmetic')
self.assertIn('Theorem 1.6.6', section)
self.assertNotIn('next section text', section)
def test_extract_section_missing_heading_raises(self):
with self.assertRaises(ValueError):
extract_section(FIXTURE, '1.6. Divisibility in the Integers', '9.9. Does Not Exist')
def test_labeled_statements_dedupes_and_orders(self):
section = extract_section(FIXTURE, '1.6. Divisibility in the Integers', '1.7. Modular Arithmetic')
items = labeled_statements(section, '1.6.')
labels = [item['label'] for item in items]
# Theorem 1.6.6 appears twice (page-break repeat) but must be kept once, and
# book order (1.6.1 before 1.6.6) must be preserved.
self.assertEqual(labels, ['1.6.1', '1.6.6'])
def test_labeled_statements_filters_by_prefix(self):
section = extract_section(FIXTURE, '1.6. Divisibility in the Integers', '1.7. Modular Arithmetic')
items = labeled_statements(section, '1.7.')
self.assertEqual(items, [])
if __name__ == '__main__':
unittest.main()