') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - TensorHub-ORG/MathCraft: Open and verifiable infrastructure for mathematical information, workflows, and reasoning. · GitHub
Skip to content

Repository files navigation

TensorHub MathCraft

**MathCraft(数理工坊)**是 TensorHub 旗下一个面向数学信息载体的开放、可验证、可扩展的 智能处理与推理平台。PDF 是首个 输入形式,MathIR 才是连接解析、推理、验证、知识与输出能力的长期核心协议。

当前仓库首先建设稳定的 MathCraft Core:把扫描 PDF 和图片转换为具有来源坐标、 候选结果与完整溯源信息的 MathIR,并为 OCR、LaTeX 重构、文档结构理解和质量评测 提供可靠基础。Agent、形式化验证和翻译等高级能力将在核心稳定后以 Skill 形式接入。

TensorHub MathCraft
├── MathCraft Core
├── MathCraft Flow
├── MathCraft Studio
├── MathCraft Skills
└── MathIR

M1 实际成果

首个里程碑已经完成从扫描 PDF、300 DPI 页面 artifact、MinerU GPU 解析,到块级 Golden 复核与可复现评测的完整闭环。Golden Annotation Workbench 支持页面与阅读顺序校验、 原图裁剪、KaTeX 公式对照、风险队列和稳定文本抽样。

MathCraft Golden Annotation Workbench

首份基线的适用范围、指标和辅助标注限制见 MinerU 3.4.5 M1 解析基线

当前能力

  • 数学文档中间表示 MathIR;
  • 基于 PyMuPDF 的只读 PDF 探测;
  • 基于 PyMuPDF 的高分辨率页面渲染;
  • 内容寻址、可复现且带坐标映射的页面 artifact;
  • 带引擎、版本和置信度的内容候选;
  • 文本字符错误率和保守的公式精确匹配评测;
  • 响应式 Golden Annotation Workbench;
  • 隔离的 MinerU 3.4.5 CPU/CUDA 运行时;
  • 可作为未来 Tauri sidecar 使用的 CLI;
  • pytest、Ruff、mypy strict 质量门。

MinerU 和 GPU 模型通过独立适配器与隔离运行时接入,不属于 Core 基础环境。Agent Runtime 将在后续里程碑通过明确端口接入。

项目文档

上述文档是项目决策依据。代码实现与产品愿景冲突时,应先更新并评审文档,而不是在 代码中静默改变产品方向。

环境配置

项目使用 uv 管理 Python、依赖和锁文件。uv 二进制默认安装在项目内,避免污染系统环境:

$env:UV_UNMANAGED_INSTALL="$PWD\.tools"
irm https://astral.sh/uv/install.ps1 | iex
.tools\uv sync

常用命令

检查本地运行环境:

.tools\uv run mathcraft doctor

探测扫描或矢量 PDF:

.tools\uv run mathcraft inspect "path\to\document.pdf"--max-pages 10

将指定页面以 300 DPI 渲染为不可变 artifact:

.tools\uv run mathcraft render "path\to\document.pdf"--page 1--page 4--output-dir artifacts

每个页面写入以 artifact ID 寻址的独立目录,其中包含 page.pngmanifest.json。 manifest 记录源文件哈希、页码、DPI、像素尺寸、PDF 点坐标到像素坐标的映射、引擎版本 和配置哈希。省略 --page 时渲染全部页面;大型文档建议显式选择页面。

运行 JSONL golden dataset 评测:

.tools\uv run mathcraft evaluate tests\fixtures\evaluation.jsonl

评测数据每行格式如下:

{"id":"formula-001","kind":"formula","reference":"x^2+1","prediction":"x^2 + 1"}

开发检查

.tools\uv run pytest --cov=mathcraft --cov-report=term-missing
.tools\uv run ruff check .
.tools\uv run ruff format --check .
.tools\uv run mypy -p mathcraft

运行产物放在 artifacts/workspace/,两者均不进入版本控制。不要把原始 PDF、 模型权重、OCR 缓存或用户文档复制到源码目录。

Golden Annotation Workbench

构建独立前端并启动本地标注工作台:

cd studio
npm ci
npm run build
cd ..
.tools\uv run mathcraft golden-studio workspace\golden\reference.json `--artifact-dir workspace\golden\artifacts `--prediction workspace\mineru-page-7-retry\mathcraft-parse-result.json

浏览器打开 http://127.0.0.1:8765。完整标注规则和复核门禁见 Golden Dataset 文档

前端类型检查与浏览器交互测试:

cd studio
npm run typecheck
npm run test:e2e

许可证

MathCraft 采用双重授权:

闭源集成、私有修改、白标、OEM 及其他商业授权需求,请联系 2245924824@qq.com。详细说明见授权文档

About

Open and verifiable infrastructure for mathematical information, workflows, and reasoning.

Resources

Contributing

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages