refigure 0.3.2__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {refigure-0.3.2 → refigure-0.3.4}/.gitignore +1 -0
- {refigure-0.3.2 → refigure-0.3.4}/PKG-INFO +153 -87
- {refigure-0.3.2 → refigure-0.3.4}/README.md +152 -86
- {refigure-0.3.2 → refigure-0.3.4}/pyproject.toml +1 -1
- {refigure-0.3.2 → refigure-0.3.4}/ATTRIBUTION.md +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/LICENSE +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/NOTICE +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/__main__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/_io.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/api.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/cli.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/core/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/core/chart_data.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/core/chart_render.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/core/zipsafe.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/docx/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/docx_groups.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/_lru.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/auth.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/cli.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/exceptions.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/server.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/state.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/mcp/vlm_cache.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/py.typed +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/vlm/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/vlm/cache.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/vlm/client.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/xlsx/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/refigure/xlsx/charts.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/support.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/core/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/core/test_chart_data.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/core/test_chart_render.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/core/test_chart_render_missing_mermaidx.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/core/test_chart_render_visual.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/docx/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/docx/test_docx.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/conftest.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_auth.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_batch.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_bridge.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_cli.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_http.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_lru.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_prompts.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_resources.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_schema_pin.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_state.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_tools.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/mcp/test_vlm_cache.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_cli.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_concurrency.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_docx_chart_group_coexistence.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_docx_groups.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_io.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_optional_dependency_guards.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_property_based.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_robustness.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_vlm_max_markers.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/test_xml_security.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/vlm/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/vlm/test_soffice_profile_isolation.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/vlm/test_vlm.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/vlm/test_vlm_cache.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/vlm/test_vlm_client.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/xlsx/__init__.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/xlsx/test_xlsx.py +0 -0
- {refigure-0.3.2 → refigure-0.3.4}/tests/unit/xlsx/test_xlsx_charts.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: refigure
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: DOCX/XLSX -> Markdown conversion with native OOXML chart-data extraction (no rasterize/OCR/VLM needed) + optional VLM interpretation for figures with no native chart data
|
|
5
5
|
Project-URL: Homepage, https://github.com/HelgDemidov/refigure
|
|
6
6
|
Project-URL: Repository, https://github.com/HelgDemidov/refigure
|
|
@@ -46,15 +46,66 @@ Description-Content-Type: text/markdown
|
|
|
46
46
|
[](https://github.com/HelgDemidov/refigure/actions/workflows/ci.yml)
|
|
47
47
|
[](LICENSE)
|
|
48
48
|
[](pyproject.toml)
|
|
49
|
+
[](https://pypi.org/project/refigure/)
|
|
50
|
+
[](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
|
|
51
|
+
[](https://registry.modelcontextprotocol.io/?q=refigure)
|
|
52
|
+
[](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
|
|
49
53
|
|
|
50
54
|
<!-- mcp-name: io.github.HelgDemidov/refigure -->
|
|
51
55
|
|
|
52
|
-
DOCX
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
DOCX/XLSX → Markdown that keeps charts and infographics machine-readable
|
|
57
|
+
instead of losing them to OCR or a vision model: native OOXML chart data
|
|
58
|
+
(`numCache`/`strCache`) recovers exact numbers with zero GPU calls, zero
|
|
59
|
+
VLM calls, zero lost precision — by default, not as a fallback.
|
|
60
|
+
|
|
61
|
+
That default path is also why the base install (`pip install
|
|
62
|
+
"refigure[docx,xlsx]"`) is **~500x lighter than PyTorch-based
|
|
63
|
+
alternatives** (5.6MB vs. multi-GB) — the core conversion needs no ML
|
|
64
|
+
model at all. That number is about the core architecture, not every
|
|
65
|
+
distribution format: the Docker image trades it back deliberately,
|
|
66
|
+
bundling VLM providers + LibreOffice for a turnkey composite-figure path
|
|
67
|
+
(see Docker below).
|
|
68
|
+
|
|
69
|
+
VLM interpretation itself is there for the rare figure with no native
|
|
70
|
+
data at all (a dashboard screenshot) — never required just to get real
|
|
71
|
+
numbers out of a chart, on any distribution format.
|
|
72
|
+
|
|
73
|
+
Ships as a library, CLI, MCP server, and a one-click Claude Desktop
|
|
74
|
+
bundle — every surface returns the same native-fidelity output, not a
|
|
75
|
+
degraded summary for agents.
|
|
76
|
+
|
|
77
|
+
## Features
|
|
78
|
+
|
|
79
|
+
- **Native chart-data extraction** — reads OOXML `numCache`/`strCache`
|
|
80
|
+
directly; no rasterize/OCR/VLM step for charts, real numbers every time.
|
|
81
|
+
- **Positioned zero-loss markers for composite figures** (DOCX) — grouped
|
|
82
|
+
shapes/infographics that mammoth would otherwise silently fragment into
|
|
83
|
+
disconnected pieces get a clean marker instead, with position and any
|
|
84
|
+
caption text preserved. Absent even in well-funded incumbents — see
|
|
85
|
+
[Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
|
|
86
|
+
- **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
|
|
87
|
+
`--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
|
|
88
|
+
mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
|
|
89
|
+
sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
|
|
90
|
+
Status below) on top of the zero-loss floor, for figures with no native
|
|
91
|
+
chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
|
|
92
|
+
OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
|
|
93
|
+
via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
|
|
94
|
+
specific failure (the system `soffice`/LibreOffice binary missing) from
|
|
95
|
+
a graceful skip to a hard error; every other VLM failure still degrades.
|
|
96
|
+
- **Rich, typed result** — `ConversionResult` (markdown + warnings +
|
|
97
|
+
chart/group counts + `vlm_used`), not a bare string.
|
|
98
|
+
- **CLI included** — `refigure` console command, stdin/stdout-first, native
|
|
99
|
+
batch mode, typed exit codes (see below).
|
|
100
|
+
- **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
|
|
101
|
+
stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
|
|
102
|
+
per-file isolation (see below).
|
|
103
|
+
- **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
|
|
104
|
+
on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
|
|
105
|
+
path works turnkey, no manual LibreOffice install. Multi-arch —
|
|
106
|
+
`linux/amd64` + `linux/arm64`, native Apple Silicon (see below).
|
|
107
|
+
- **`.mcpb` bundle for Claude Desktop** — one-click install, no terminal
|
|
108
|
+
(`docx`+`xlsx` only, see below).
|
|
58
109
|
|
|
59
110
|
## Demo
|
|
60
111
|
|
|
@@ -64,7 +115,10 @@ construct either (a dense radial sunburst — nothing in the 4 original
|
|
|
64
115
|
mermaid types could represent it), `--vlm` both recovers the real content
|
|
65
116
|
and produces a genuinely renderable diagram, not just recovered text:
|
|
66
117
|
|
|
67
|
-
<
|
|
118
|
+
<picture>
|
|
119
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/demo-vlm-dark.svg">
|
|
120
|
+
<img src="docs/assets/demo-vlm-light.svg" alt="A real docx image (a dense wireless-technology sunburst chart with no native chart data) converted by refigure.docx.convert(use_vlm=True) into a rich VLM-generated description and a real rendered mermaid mindmap diagram, laid out radially instead of the unreadable flat strip a generic flowchart construct would have produced">
|
|
121
|
+
</picture>
|
|
68
122
|
|
|
69
123
|
**Native chart-data extraction** — real OOXML `numCache`, not a screenshot,
|
|
70
124
|
not OCR:
|
|
@@ -117,7 +171,7 @@ uvx --from "refigure[docx,xlsx]" refigure report.docx
|
|
|
117
171
|
```
|
|
118
172
|
|
|
119
173
|
Optional VLM interpretation, for a composite figure the chart engine can't
|
|
120
|
-
reconstruct on its own (see Features
|
|
174
|
+
reconstruct on its own (see Features above):
|
|
121
175
|
|
|
122
176
|
```bash
|
|
123
177
|
pip install "refigure[docx,vlm]"
|
|
@@ -125,37 +179,13 @@ export OPENROUTER_API_KEY=... # or --vlm-api-key-file/--vlm-prov
|
|
|
125
179
|
refigure report.docx --vlm # needs the system soffice/LibreOffice binary too
|
|
126
180
|
```
|
|
127
181
|
|
|
128
|
-
##
|
|
182
|
+
## Installation & usage
|
|
129
183
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
- **Positioned zero-loss markers for composite figures** (DOCX) — grouped
|
|
133
|
-
shapes/infographics that mammoth would otherwise silently fragment into
|
|
134
|
-
disconnected pieces get a clean marker instead, with position and any
|
|
135
|
-
caption text preserved. Absent even in well-funded incumbents — see
|
|
136
|
-
[Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
|
|
137
|
-
- **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
|
|
138
|
-
`--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
|
|
139
|
-
mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
|
|
140
|
-
sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
|
|
141
|
-
Status below) on top of the zero-loss floor, for figures with no native
|
|
142
|
-
chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
|
|
143
|
-
OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
|
|
144
|
-
via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
|
|
145
|
-
specific failure (the system `soffice`/LibreOffice binary missing) from
|
|
146
|
-
a graceful skip to a hard error; every other VLM failure still degrades.
|
|
147
|
-
- **Rich, typed result** — `ConversionResult` (markdown + warnings +
|
|
148
|
-
chart/group counts + `vlm_used`), not a bare string.
|
|
149
|
-
- **CLI included** — `refigure` console command, stdin/stdout-first, native
|
|
150
|
-
batch mode, typed exit codes (see below).
|
|
151
|
-
- **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
|
|
152
|
-
stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
|
|
153
|
-
per-file isolation (see below).
|
|
154
|
-
- **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
|
|
155
|
-
on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
|
|
156
|
-
path works turnkey, no manual LibreOffice install (see below).
|
|
184
|
+
One converter, four ways to run it — pick whichever fits your pipeline.
|
|
185
|
+
Click a heading to expand it.
|
|
157
186
|
|
|
158
|
-
|
|
187
|
+
<details>
|
|
188
|
+
<summary><b>CLI</b> — a console command, stdin/stdout-first, native batch mode</summary>
|
|
159
189
|
|
|
160
190
|
`refigure` installs a console command — a thin wrapper over the same
|
|
161
191
|
`convert()` used programmatically, no separate logic:
|
|
@@ -187,12 +217,17 @@ Exit codes:
|
|
|
187
217
|
| 5 | the format's extra (`[docx]`/`[xlsx]`) isn't installed |
|
|
188
218
|
| 6 | unexpected internal error |
|
|
189
219
|
|
|
190
|
-
|
|
220
|
+
</details>
|
|
221
|
+
|
|
222
|
+
<details>
|
|
223
|
+
<summary><b>MCP server</b> — for agents/IDEs that speak the protocol directly</summary>
|
|
191
224
|
|
|
192
225
|
`refigure-mcp` — the same converters as an
|
|
193
226
|
[MCP](https://modelcontextprotocol.io) server, for agents/IDEs that speak
|
|
194
227
|
the protocol directly instead of shelling out to a CLI or importing the
|
|
195
|
-
library
|
|
228
|
+
library. Listed on the official
|
|
229
|
+
[MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
|
|
230
|
+
`io.github.HelgDemidov/refigure`:
|
|
196
231
|
|
|
197
232
|
```bash
|
|
198
233
|
pip install "refigure[mcp,docx,xlsx]"
|
|
@@ -246,22 +281,31 @@ fairness soft-cap once 2+ callers are configured; `refigure-mcp --help`
|
|
|
246
281
|
covers every tuning flag (concurrency, timeouts, resource-store limits,
|
|
247
282
|
batch size, VLM ceiling).
|
|
248
283
|
|
|
249
|
-
|
|
284
|
+
</details>
|
|
285
|
+
|
|
286
|
+
<details>
|
|
287
|
+
<summary><b>Docker</b> — one image, CLI and MCP server both on PATH, soffice baked in</summary>
|
|
250
288
|
|
|
251
289
|
One image, both surfaces — `refigure` and `refigure-mcp` are already on
|
|
252
290
|
`PATH`, no separate CLI/MCP builds to choose between. The one thing this
|
|
253
291
|
format buys over `pip`/`uvx` that neither can: the system `soffice`/
|
|
254
292
|
LibreOffice binary the VLM composite-figure path needs is baked in, not a
|
|
255
|
-
manual install.
|
|
293
|
+
manual install. Multi-arch manifest (`linux/amd64` + `linux/arm64`) —
|
|
294
|
+
`docker pull` resolves the right layer automatically, including on
|
|
295
|
+
Apple Silicon.
|
|
256
296
|
|
|
257
297
|
```bash
|
|
258
|
-
docker pull ghcr.io/helgdemidov/refigure:
|
|
298
|
+
docker pull ghcr.io/helgdemidov/refigure:latest
|
|
259
299
|
```
|
|
260
300
|
|
|
301
|
+
Pin an exact version instead of `:latest` for reproducibility — e.g.
|
|
302
|
+
`:0.3.3` — see the [package page](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
|
|
303
|
+
for available tags.
|
|
304
|
+
|
|
261
305
|
CLI, via a bind mount (the image's working directory is already `/data`):
|
|
262
306
|
|
|
263
307
|
```bash
|
|
264
|
-
docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:
|
|
308
|
+
docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:latest \
|
|
265
309
|
refigure /data/report.docx
|
|
266
310
|
```
|
|
267
311
|
|
|
@@ -272,7 +316,7 @@ MCP, stdio — the client launches the container itself:
|
|
|
272
316
|
"mcpServers": {
|
|
273
317
|
"refigure": {
|
|
274
318
|
"command": "docker",
|
|
275
|
-
"args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:
|
|
319
|
+
"args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:latest", "refigure-mcp"]
|
|
276
320
|
}
|
|
277
321
|
}
|
|
278
322
|
}
|
|
@@ -287,24 +331,43 @@ flag would silently never respond:
|
|
|
287
331
|
```bash
|
|
288
332
|
echo "sk-... = alice" > tokens.txt
|
|
289
333
|
docker run --rm -p 8000:8000 -v "$PWD/tokens.txt:/data/tokens.txt:ro" \
|
|
290
|
-
ghcr.io/helgdemidov/refigure:
|
|
334
|
+
ghcr.io/helgdemidov/refigure:latest \
|
|
291
335
|
refigure-mcp --transport http --mcp-http-host 0.0.0.0 \
|
|
292
336
|
--mcp-auth-token-file /data/tokens.txt
|
|
293
337
|
```
|
|
294
338
|
|
|
339
|
+
</details>
|
|
340
|
+
|
|
341
|
+
<details>
|
|
342
|
+
<summary><b>Claude Desktop (<code>.mcpb</code>)</b> — download, double-click, done</summary>
|
|
343
|
+
|
|
344
|
+
The simplest install for a non-technical user: download, double-click,
|
|
345
|
+
done — no terminal, no `pip`/`uvx`/`docker`. Covers `docx`+`xlsx`
|
|
346
|
+
conversion only (no VLM — that needs the `[vlm]` extra, deliberately
|
|
347
|
+
not carried by this bundle); dependencies resolve fresh from PyPI via
|
|
348
|
+
`uv` on first launch, the same mechanism `uvx` uses under the hood,
|
|
349
|
+
just one click instead of a config snippet.
|
|
350
|
+
|
|
351
|
+
[**Download refigure.mcpb**](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
|
|
352
|
+
— open it with Claude Desktop to install.
|
|
353
|
+
|
|
354
|
+
</details>
|
|
355
|
+
|
|
295
356
|
## Real examples
|
|
296
357
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
358
|
+
Concentrated excerpts (≤200 lines each) of real `convert()` output on
|
|
359
|
+
real, openly-licensed documents — the actual markdown a pipeline would
|
|
360
|
+
ingest, not a screenshot or a cherry-picked one-liner. Each file's own
|
|
361
|
+
header states its source, license and attribution; trimmed sections are
|
|
362
|
+
marked inline, never fabricated to fill space.
|
|
300
363
|
|
|
301
364
|
| Source | Demonstrates | Output |
|
|
302
365
|
| --- | --- | --- |
|
|
303
|
-
| `hackair-d7.7-pilot-evaluation.docx` | native chart extraction —
|
|
304
|
-
| `swd2018-254-marine-litter-ia-annex.docx` |
|
|
305
|
-
| `govtech-2025-charts.xlsx` | XLSX
|
|
306
|
-
| `swd2021-396-platform-work-ia.docx` | native pie
|
|
307
|
-
| `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation —
|
|
366
|
+
| `hackair-d7.7-pilot-evaluation.docx` | native chart extraction — real survey tables + `xychart-beta` bar charts | [examples/hackair-native-charts.md](examples/hackair-native-charts.md) |
|
|
367
|
+
| `swd2018-254-marine-litter-ia-annex.docx` | honest fallback — a chart that fails render-verification degrades to a clean table, plus 2 composite-figure zero-loss markers | [examples/swd2018-combo.md](examples/swd2018-combo.md) |
|
|
368
|
+
| `govtech-2025-charts.xlsx` | XLSX native charts — 3 distinct types (`xychart-beta`/`radar-beta`/`pie`) from one workbook | [examples/govtech-xlsx-charts.md](examples/govtech-xlsx-charts.md) |
|
|
369
|
+
| `swd2021-396-platform-work-ia.docx` | native pie + a 23-year time series, real EU-survey labels | [examples/swd2021-pie-chart.md](examples/swd2021-pie-chart.md) |
|
|
370
|
+
| `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation — 2 screenshot figures recovered as a bar chart and a UI flowchart, real numbers | [examples/efsa-trichinella-vlm.md](examples/efsa-trichinella-vlm.md) |
|
|
308
371
|
|
|
309
372
|
Open any of these on GitHub and both views are right there: the raw
|
|
310
373
|
```` ```mermaid ```` fence an LLM/RAG pipeline would read, and its native
|
|
@@ -312,37 +375,42 @@ GitHub rendering — no extra step, that's GitHub's own Markdown support.
|
|
|
312
375
|
|
|
313
376
|
## Status
|
|
314
377
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
[`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
378
|
+
- **Validated** against 27 real documents (15 DOCX + 12 XLSX) — 407 native
|
|
379
|
+
charts found (400 rendered), 35 composite figures recovered as
|
|
380
|
+
positioned zero-loss markers. Full provenance:
|
|
381
|
+
[`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml).
|
|
382
|
+
- **Tested**: CI gates on a combined unit+integration coverage floor of 95%.
|
|
383
|
+
- **Published** as `v0.3.3` — [PyPI](https://pypi.org/project/refigure/)
|
|
384
|
+
(trusted publishing, no stored tokens),
|
|
385
|
+
[GHCR](https://github.com/HelgDemidov/refigure/pkgs/container/refigure),
|
|
386
|
+
and the official
|
|
387
|
+
[MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
|
|
388
|
+
`io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
|
|
389
|
+
name, not an active release.
|
|
390
|
+
|
|
391
|
+
Extracted from a working document-analysis pipeline (a government
|
|
392
|
+
AI-policy research corpus), not built from scratch for this release.
|
|
393
|
+
|
|
394
|
+
VLM interpretation of composite figures the chart engine can't reconstruct
|
|
395
|
+
is fully implemented and tested, not a stub — `[vlm]` extra,
|
|
396
|
+
provider-agnostic (direct OpenAI/Anthropic via `[vlm-direct]`), also needs
|
|
397
|
+
the system `soffice`/LibreOffice binary.
|
|
398
|
+
|
|
399
|
+
Mermaid-diagram recognition depends on diagram type and on what the
|
|
400
|
+
source figure actually contains:
|
|
401
|
+
|
|
402
|
+
- Common types (flowcharts, pie/xy charts) are picked reliably.
|
|
403
|
+
- More specialized ones need an unambiguous visual cue on the source figure.
|
|
404
|
+
- Not every figure produces a diagram — a plain-text description is an
|
|
405
|
+
honest fallback, not a failure.
|
|
335
406
|
|
|
336
407
|
**PDF is out of scope, on purpose — a boundary, not a gap.** PDF has no
|
|
337
408
|
equivalent of OOXML's cached chart data (`numCache`/`strCache`) for any
|
|
338
|
-
mainstream chart generator, so the native, rasterize-free extraction
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
[Docling](https://github.com/docling-project/docling) or
|
|
344
|
-
[MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
|
|
345
|
-
for DOCX/XLSX where the chart data actually survives in the file:
|
|
409
|
+
mainstream chart generator, so the native, rasterize-free extraction this
|
|
410
|
+
project is built on doesn't transfer to it — confirmed by research into
|
|
411
|
+
PDF's own structure and how leading PDF converters handle charts today,
|
|
412
|
+
not assumed. For mixed-format corpora, route by extension instead of
|
|
413
|
+
expecting one tool to cover everything:
|
|
346
414
|
|
|
347
415
|
```python
|
|
348
416
|
import refigure.docx
|
|
@@ -356,11 +424,9 @@ else:
|
|
|
356
424
|
markdown = refigure.xlsx.convert(path).markdown
|
|
357
425
|
```
|
|
358
426
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
`io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
|
|
363
|
-
name, not an active release.
|
|
427
|
+
Use [Docling](https://github.com/docling-project/docling) or
|
|
428
|
+
[MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
|
|
429
|
+
for DOCX/XLSX where the chart data actually survives in the file.
|
|
364
430
|
|
|
365
431
|
## License
|
|
366
432
|
|
|
@@ -6,15 +6,66 @@
|
|
|
6
6
|
[](https://github.com/HelgDemidov/refigure/actions/workflows/ci.yml)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](pyproject.toml)
|
|
9
|
+
[](https://pypi.org/project/refigure/)
|
|
10
|
+
[](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
|
|
11
|
+
[](https://registry.modelcontextprotocol.io/?q=refigure)
|
|
12
|
+
[](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
|
|
9
13
|
|
|
10
14
|
<!-- mcp-name: io.github.HelgDemidov/refigure -->
|
|
11
15
|
|
|
12
|
-
DOCX
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
DOCX/XLSX → Markdown that keeps charts and infographics machine-readable
|
|
17
|
+
instead of losing them to OCR or a vision model: native OOXML chart data
|
|
18
|
+
(`numCache`/`strCache`) recovers exact numbers with zero GPU calls, zero
|
|
19
|
+
VLM calls, zero lost precision — by default, not as a fallback.
|
|
20
|
+
|
|
21
|
+
That default path is also why the base install (`pip install
|
|
22
|
+
"refigure[docx,xlsx]"`) is **~500x lighter than PyTorch-based
|
|
23
|
+
alternatives** (5.6MB vs. multi-GB) — the core conversion needs no ML
|
|
24
|
+
model at all. That number is about the core architecture, not every
|
|
25
|
+
distribution format: the Docker image trades it back deliberately,
|
|
26
|
+
bundling VLM providers + LibreOffice for a turnkey composite-figure path
|
|
27
|
+
(see Docker below).
|
|
28
|
+
|
|
29
|
+
VLM interpretation itself is there for the rare figure with no native
|
|
30
|
+
data at all (a dashboard screenshot) — never required just to get real
|
|
31
|
+
numbers out of a chart, on any distribution format.
|
|
32
|
+
|
|
33
|
+
Ships as a library, CLI, MCP server, and a one-click Claude Desktop
|
|
34
|
+
bundle — every surface returns the same native-fidelity output, not a
|
|
35
|
+
degraded summary for agents.
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- **Native chart-data extraction** — reads OOXML `numCache`/`strCache`
|
|
40
|
+
directly; no rasterize/OCR/VLM step for charts, real numbers every time.
|
|
41
|
+
- **Positioned zero-loss markers for composite figures** (DOCX) — grouped
|
|
42
|
+
shapes/infographics that mammoth would otherwise silently fragment into
|
|
43
|
+
disconnected pieces get a clean marker instead, with position and any
|
|
44
|
+
caption text preserved. Absent even in well-funded incumbents — see
|
|
45
|
+
[Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
|
|
46
|
+
- **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
|
|
47
|
+
`--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
|
|
48
|
+
mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
|
|
49
|
+
sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
|
|
50
|
+
Status below) on top of the zero-loss floor, for figures with no native
|
|
51
|
+
chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
|
|
52
|
+
OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
|
|
53
|
+
via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
|
|
54
|
+
specific failure (the system `soffice`/LibreOffice binary missing) from
|
|
55
|
+
a graceful skip to a hard error; every other VLM failure still degrades.
|
|
56
|
+
- **Rich, typed result** — `ConversionResult` (markdown + warnings +
|
|
57
|
+
chart/group counts + `vlm_used`), not a bare string.
|
|
58
|
+
- **CLI included** — `refigure` console command, stdin/stdout-first, native
|
|
59
|
+
batch mode, typed exit codes (see below).
|
|
60
|
+
- **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
|
|
61
|
+
stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
|
|
62
|
+
per-file isolation (see below).
|
|
63
|
+
- **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
|
|
64
|
+
on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
|
|
65
|
+
path works turnkey, no manual LibreOffice install. Multi-arch —
|
|
66
|
+
`linux/amd64` + `linux/arm64`, native Apple Silicon (see below).
|
|
67
|
+
- **`.mcpb` bundle for Claude Desktop** — one-click install, no terminal
|
|
68
|
+
(`docx`+`xlsx` only, see below).
|
|
18
69
|
|
|
19
70
|
## Demo
|
|
20
71
|
|
|
@@ -24,7 +75,10 @@ construct either (a dense radial sunburst — nothing in the 4 original
|
|
|
24
75
|
mermaid types could represent it), `--vlm` both recovers the real content
|
|
25
76
|
and produces a genuinely renderable diagram, not just recovered text:
|
|
26
77
|
|
|
27
|
-
<
|
|
78
|
+
<picture>
|
|
79
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/demo-vlm-dark.svg">
|
|
80
|
+
<img src="docs/assets/demo-vlm-light.svg" alt="A real docx image (a dense wireless-technology sunburst chart with no native chart data) converted by refigure.docx.convert(use_vlm=True) into a rich VLM-generated description and a real rendered mermaid mindmap diagram, laid out radially instead of the unreadable flat strip a generic flowchart construct would have produced">
|
|
81
|
+
</picture>
|
|
28
82
|
|
|
29
83
|
**Native chart-data extraction** — real OOXML `numCache`, not a screenshot,
|
|
30
84
|
not OCR:
|
|
@@ -77,7 +131,7 @@ uvx --from "refigure[docx,xlsx]" refigure report.docx
|
|
|
77
131
|
```
|
|
78
132
|
|
|
79
133
|
Optional VLM interpretation, for a composite figure the chart engine can't
|
|
80
|
-
reconstruct on its own (see Features
|
|
134
|
+
reconstruct on its own (see Features above):
|
|
81
135
|
|
|
82
136
|
```bash
|
|
83
137
|
pip install "refigure[docx,vlm]"
|
|
@@ -85,37 +139,13 @@ export OPENROUTER_API_KEY=... # or --vlm-api-key-file/--vlm-prov
|
|
|
85
139
|
refigure report.docx --vlm # needs the system soffice/LibreOffice binary too
|
|
86
140
|
```
|
|
87
141
|
|
|
88
|
-
##
|
|
142
|
+
## Installation & usage
|
|
89
143
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- **Positioned zero-loss markers for composite figures** (DOCX) — grouped
|
|
93
|
-
shapes/infographics that mammoth would otherwise silently fragment into
|
|
94
|
-
disconnected pieces get a clean marker instead, with position and any
|
|
95
|
-
caption text preserved. Absent even in well-funded incumbents — see
|
|
96
|
-
[Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
|
|
97
|
-
- **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
|
|
98
|
-
`--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
|
|
99
|
-
mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
|
|
100
|
-
sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
|
|
101
|
-
Status below) on top of the zero-loss floor, for figures with no native
|
|
102
|
-
chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
|
|
103
|
-
OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
|
|
104
|
-
via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
|
|
105
|
-
specific failure (the system `soffice`/LibreOffice binary missing) from
|
|
106
|
-
a graceful skip to a hard error; every other VLM failure still degrades.
|
|
107
|
-
- **Rich, typed result** — `ConversionResult` (markdown + warnings +
|
|
108
|
-
chart/group counts + `vlm_used`), not a bare string.
|
|
109
|
-
- **CLI included** — `refigure` console command, stdin/stdout-first, native
|
|
110
|
-
batch mode, typed exit codes (see below).
|
|
111
|
-
- **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
|
|
112
|
-
stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
|
|
113
|
-
per-file isolation (see below).
|
|
114
|
-
- **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
|
|
115
|
-
on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
|
|
116
|
-
path works turnkey, no manual LibreOffice install (see below).
|
|
144
|
+
One converter, four ways to run it — pick whichever fits your pipeline.
|
|
145
|
+
Click a heading to expand it.
|
|
117
146
|
|
|
118
|
-
|
|
147
|
+
<details>
|
|
148
|
+
<summary><b>CLI</b> — a console command, stdin/stdout-first, native batch mode</summary>
|
|
119
149
|
|
|
120
150
|
`refigure` installs a console command — a thin wrapper over the same
|
|
121
151
|
`convert()` used programmatically, no separate logic:
|
|
@@ -147,12 +177,17 @@ Exit codes:
|
|
|
147
177
|
| 5 | the format's extra (`[docx]`/`[xlsx]`) isn't installed |
|
|
148
178
|
| 6 | unexpected internal error |
|
|
149
179
|
|
|
150
|
-
|
|
180
|
+
</details>
|
|
181
|
+
|
|
182
|
+
<details>
|
|
183
|
+
<summary><b>MCP server</b> — for agents/IDEs that speak the protocol directly</summary>
|
|
151
184
|
|
|
152
185
|
`refigure-mcp` — the same converters as an
|
|
153
186
|
[MCP](https://modelcontextprotocol.io) server, for agents/IDEs that speak
|
|
154
187
|
the protocol directly instead of shelling out to a CLI or importing the
|
|
155
|
-
library
|
|
188
|
+
library. Listed on the official
|
|
189
|
+
[MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
|
|
190
|
+
`io.github.HelgDemidov/refigure`:
|
|
156
191
|
|
|
157
192
|
```bash
|
|
158
193
|
pip install "refigure[mcp,docx,xlsx]"
|
|
@@ -206,22 +241,31 @@ fairness soft-cap once 2+ callers are configured; `refigure-mcp --help`
|
|
|
206
241
|
covers every tuning flag (concurrency, timeouts, resource-store limits,
|
|
207
242
|
batch size, VLM ceiling).
|
|
208
243
|
|
|
209
|
-
|
|
244
|
+
</details>
|
|
245
|
+
|
|
246
|
+
<details>
|
|
247
|
+
<summary><b>Docker</b> — one image, CLI and MCP server both on PATH, soffice baked in</summary>
|
|
210
248
|
|
|
211
249
|
One image, both surfaces — `refigure` and `refigure-mcp` are already on
|
|
212
250
|
`PATH`, no separate CLI/MCP builds to choose between. The one thing this
|
|
213
251
|
format buys over `pip`/`uvx` that neither can: the system `soffice`/
|
|
214
252
|
LibreOffice binary the VLM composite-figure path needs is baked in, not a
|
|
215
|
-
manual install.
|
|
253
|
+
manual install. Multi-arch manifest (`linux/amd64` + `linux/arm64`) —
|
|
254
|
+
`docker pull` resolves the right layer automatically, including on
|
|
255
|
+
Apple Silicon.
|
|
216
256
|
|
|
217
257
|
```bash
|
|
218
|
-
docker pull ghcr.io/helgdemidov/refigure:
|
|
258
|
+
docker pull ghcr.io/helgdemidov/refigure:latest
|
|
219
259
|
```
|
|
220
260
|
|
|
261
|
+
Pin an exact version instead of `:latest` for reproducibility — e.g.
|
|
262
|
+
`:0.3.3` — see the [package page](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
|
|
263
|
+
for available tags.
|
|
264
|
+
|
|
221
265
|
CLI, via a bind mount (the image's working directory is already `/data`):
|
|
222
266
|
|
|
223
267
|
```bash
|
|
224
|
-
docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:
|
|
268
|
+
docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:latest \
|
|
225
269
|
refigure /data/report.docx
|
|
226
270
|
```
|
|
227
271
|
|
|
@@ -232,7 +276,7 @@ MCP, stdio — the client launches the container itself:
|
|
|
232
276
|
"mcpServers": {
|
|
233
277
|
"refigure": {
|
|
234
278
|
"command": "docker",
|
|
235
|
-
"args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:
|
|
279
|
+
"args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:latest", "refigure-mcp"]
|
|
236
280
|
}
|
|
237
281
|
}
|
|
238
282
|
}
|
|
@@ -247,24 +291,43 @@ flag would silently never respond:
|
|
|
247
291
|
```bash
|
|
248
292
|
echo "sk-... = alice" > tokens.txt
|
|
249
293
|
docker run --rm -p 8000:8000 -v "$PWD/tokens.txt:/data/tokens.txt:ro" \
|
|
250
|
-
ghcr.io/helgdemidov/refigure:
|
|
294
|
+
ghcr.io/helgdemidov/refigure:latest \
|
|
251
295
|
refigure-mcp --transport http --mcp-http-host 0.0.0.0 \
|
|
252
296
|
--mcp-auth-token-file /data/tokens.txt
|
|
253
297
|
```
|
|
254
298
|
|
|
299
|
+
</details>
|
|
300
|
+
|
|
301
|
+
<details>
|
|
302
|
+
<summary><b>Claude Desktop (<code>.mcpb</code>)</b> — download, double-click, done</summary>
|
|
303
|
+
|
|
304
|
+
The simplest install for a non-technical user: download, double-click,
|
|
305
|
+
done — no terminal, no `pip`/`uvx`/`docker`. Covers `docx`+`xlsx`
|
|
306
|
+
conversion only (no VLM — that needs the `[vlm]` extra, deliberately
|
|
307
|
+
not carried by this bundle); dependencies resolve fresh from PyPI via
|
|
308
|
+
`uv` on first launch, the same mechanism `uvx` uses under the hood,
|
|
309
|
+
just one click instead of a config snippet.
|
|
310
|
+
|
|
311
|
+
[**Download refigure.mcpb**](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
|
|
312
|
+
— open it with Claude Desktop to install.
|
|
313
|
+
|
|
314
|
+
</details>
|
|
315
|
+
|
|
255
316
|
## Real examples
|
|
256
317
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
318
|
+
Concentrated excerpts (≤200 lines each) of real `convert()` output on
|
|
319
|
+
real, openly-licensed documents — the actual markdown a pipeline would
|
|
320
|
+
ingest, not a screenshot or a cherry-picked one-liner. Each file's own
|
|
321
|
+
header states its source, license and attribution; trimmed sections are
|
|
322
|
+
marked inline, never fabricated to fill space.
|
|
260
323
|
|
|
261
324
|
| Source | Demonstrates | Output |
|
|
262
325
|
| --- | --- | --- |
|
|
263
|
-
| `hackair-d7.7-pilot-evaluation.docx` | native chart extraction —
|
|
264
|
-
| `swd2018-254-marine-litter-ia-annex.docx` |
|
|
265
|
-
| `govtech-2025-charts.xlsx` | XLSX
|
|
266
|
-
| `swd2021-396-platform-work-ia.docx` | native pie
|
|
267
|
-
| `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation —
|
|
326
|
+
| `hackair-d7.7-pilot-evaluation.docx` | native chart extraction — real survey tables + `xychart-beta` bar charts | [examples/hackair-native-charts.md](examples/hackair-native-charts.md) |
|
|
327
|
+
| `swd2018-254-marine-litter-ia-annex.docx` | honest fallback — a chart that fails render-verification degrades to a clean table, plus 2 composite-figure zero-loss markers | [examples/swd2018-combo.md](examples/swd2018-combo.md) |
|
|
328
|
+
| `govtech-2025-charts.xlsx` | XLSX native charts — 3 distinct types (`xychart-beta`/`radar-beta`/`pie`) from one workbook | [examples/govtech-xlsx-charts.md](examples/govtech-xlsx-charts.md) |
|
|
329
|
+
| `swd2021-396-platform-work-ia.docx` | native pie + a 23-year time series, real EU-survey labels | [examples/swd2021-pie-chart.md](examples/swd2021-pie-chart.md) |
|
|
330
|
+
| `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation — 2 screenshot figures recovered as a bar chart and a UI flowchart, real numbers | [examples/efsa-trichinella-vlm.md](examples/efsa-trichinella-vlm.md) |
|
|
268
331
|
|
|
269
332
|
Open any of these on GitHub and both views are right there: the raw
|
|
270
333
|
```` ```mermaid ```` fence an LLM/RAG pipeline would read, and its native
|
|
@@ -272,37 +335,42 @@ GitHub rendering — no extra step, that's GitHub's own Markdown support.
|
|
|
272
335
|
|
|
273
336
|
## Status
|
|
274
337
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
[`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
338
|
+
- **Validated** against 27 real documents (15 DOCX + 12 XLSX) — 407 native
|
|
339
|
+
charts found (400 rendered), 35 composite figures recovered as
|
|
340
|
+
positioned zero-loss markers. Full provenance:
|
|
341
|
+
[`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml).
|
|
342
|
+
- **Tested**: CI gates on a combined unit+integration coverage floor of 95%.
|
|
343
|
+
- **Published** as `v0.3.3` — [PyPI](https://pypi.org/project/refigure/)
|
|
344
|
+
(trusted publishing, no stored tokens),
|
|
345
|
+
[GHCR](https://github.com/HelgDemidov/refigure/pkgs/container/refigure),
|
|
346
|
+
and the official
|
|
347
|
+
[MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
|
|
348
|
+
`io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
|
|
349
|
+
name, not an active release.
|
|
350
|
+
|
|
351
|
+
Extracted from a working document-analysis pipeline (a government
|
|
352
|
+
AI-policy research corpus), not built from scratch for this release.
|
|
353
|
+
|
|
354
|
+
VLM interpretation of composite figures the chart engine can't reconstruct
|
|
355
|
+
is fully implemented and tested, not a stub — `[vlm]` extra,
|
|
356
|
+
provider-agnostic (direct OpenAI/Anthropic via `[vlm-direct]`), also needs
|
|
357
|
+
the system `soffice`/LibreOffice binary.
|
|
358
|
+
|
|
359
|
+
Mermaid-diagram recognition depends on diagram type and on what the
|
|
360
|
+
source figure actually contains:
|
|
361
|
+
|
|
362
|
+
- Common types (flowcharts, pie/xy charts) are picked reliably.
|
|
363
|
+
- More specialized ones need an unambiguous visual cue on the source figure.
|
|
364
|
+
- Not every figure produces a diagram — a plain-text description is an
|
|
365
|
+
honest fallback, not a failure.
|
|
295
366
|
|
|
296
367
|
**PDF is out of scope, on purpose — a boundary, not a gap.** PDF has no
|
|
297
368
|
equivalent of OOXML's cached chart data (`numCache`/`strCache`) for any
|
|
298
|
-
mainstream chart generator, so the native, rasterize-free extraction
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
[Docling](https://github.com/docling-project/docling) or
|
|
304
|
-
[MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
|
|
305
|
-
for DOCX/XLSX where the chart data actually survives in the file:
|
|
369
|
+
mainstream chart generator, so the native, rasterize-free extraction this
|
|
370
|
+
project is built on doesn't transfer to it — confirmed by research into
|
|
371
|
+
PDF's own structure and how leading PDF converters handle charts today,
|
|
372
|
+
not assumed. For mixed-format corpora, route by extension instead of
|
|
373
|
+
expecting one tool to cover everything:
|
|
306
374
|
|
|
307
375
|
```python
|
|
308
376
|
import refigure.docx
|
|
@@ -316,11 +384,9 @@ else:
|
|
|
316
384
|
markdown = refigure.xlsx.convert(path).markdown
|
|
317
385
|
```
|
|
318
386
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
`io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
|
|
323
|
-
name, not an active release.
|
|
387
|
+
Use [Docling](https://github.com/docling-project/docling) or
|
|
388
|
+
[MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
|
|
389
|
+
for DOCX/XLSX where the chart data actually survives in the file.
|
|
324
390
|
|
|
325
391
|
## License
|
|
326
392
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "refigure"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.4"
|
|
8
8
|
description = "DOCX/XLSX -> Markdown conversion with native OOXML chart-data extraction (no rasterize/OCR/VLM needed) + optional VLM interpretation for figures with no native chart data"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|