API¶
Every call has an async twin with the same arguments, prefixed a: convert → aconvert, detect → adetect, describe → adescribe.
convert¶
document = ad.convert("report.docx")
document.markdown # '# Quarterly Report\n\n## Summary\n\nRevenue grew by **18 percent** ...'
document.title # 'Quarterly Report'
ad.convert(b"Name,Age\nAlice,30\n", format="csv").markdown
# '| Name | Age |\n|---|---|\n| Alice | 30 |\n'
Returns a Document.
| Argument | Type | Default | |
|---|---|---|---|
source |
str \| PathLike \| bytes \| bytearray |
— | A path, or the content itself |
format |
str \| None |
None |
Needed for bytes ("docx", ".CSV"…); for a path, overrides detection |
images |
bool |
False |
Return embedded images in document.images |
comments |
bool |
False |
Append DOCX/PPTX comments as a # Comments section |
strict |
bool |
False |
Raise on the first warning instead of collecting it |
ocr |
bool |
True |
Read the text inside images, when [ocr] is installed |
vision |
VisionSpec \| None |
None |
Vision model for descriptions; None reads ANYTOMD_VISION_* |
max_input_bytes |
int |
8 GiB | Largest input accepted |
max_image_bytes |
int |
4 GiB | Budget for image bytes held in memory |
max_zip_bytes |
int |
16 GiB | Limit for Office archives once decompressed (ZIP bombs) |
Raises → Errors.
aconvert¶
import asyncio
documents = await asyncio.gather(
ad.aconvert("report.docx"),
ad.aconvert("deck.pptx"),
ad.aconvert("scan.pdf"),
)
Same arguments and result as convert. Conversion runs off the event loop; the images of one document are read and described concurrently, at most VisionSpec.concurrency at once. Cancelling the task cancels the conversion.
detect¶
ad.detect("report.docx") # 'docx'
ad.detect("export.dat") # 'xlsx' — by content
ad.detect(data, name="table.csv") # 'csv'
ad.detect("mystery.bin") # None
Returns the format as str, or None. Office files are recognized by content; the result is valid as convert(..., format=).
| Argument | Type | Default | |
|---|---|---|---|
source |
str \| PathLike \| bytes \| bytearray |
— | A path or the content |
name |
str \| None |
None |
A filename hint for bytes |
adetect¶
await ad.adetect("report.docx") — same, off the event loop.
describe¶
Asks the vision model only, with no OCR. For an image without text, the result equals what convert returns. For an image full of text, you get a description of it, not a transcription. Needs anytomd[vlm] and a model.
Returns a Document whose markdown and text are the labeled description.
| Argument | Type | Default | |
|---|---|---|---|
source |
str \| PathLike \| bytes \| bytearray |
— | An image |
format |
str \| None |
None |
Needed for bytes ("png") |
vision |
VisionSpec \| None |
None |
None reads ANYTOMD_VISION_* |
| Raises | When |
|---|---|
UnknownFormatError |
The source is not an image |
MissingExtraError |
anytomd[vlm] is not installed |
DescriptionError |
No model is configured, or the provider failed |
adescribe¶
await ad.adescribe("cat.png") — same, off the event loop.
Document¶
What convert and describe return. Frozen.
document = ad.convert("report.docx", images=True)
document.markdown # str
document.text # same content, no Markdown syntax
document.title # 'Quarterly Report' | None
document.images # (('chart.png', b'\x89PNG...'),)
document.warnings # (DocumentWarning(...), ...)
document.pages # PDF page count | None
DocumentWarning¶
Something recoverable went wrong; the rest converted.
ad.convert(b"Caf\xe9", format="txt").warnings[0]
# DocumentWarning(code='unsupported_feature', message='decoded from windows-1252 encoding (fallback)', location=None)
code |
|
|---|---|
skipped_element |
Something was left out — e.g. a vision call failed |
unsupported_feature |
A fallback was used — e.g. a text encoding |
resource_limit_reached |
A limit dropped part of the output |
malformed_segment |
Damaged data was repaired |
VisionSpec¶
The vision model behind descriptions. Any OpenAI-compatible endpoint works: base_url picks the provider.
vision = ad.VisionSpec(
model="claude-sonnet-5-5",
base_url="https://api.anthropic.com/v1/",
api_key="sk-ant-...",
)
ad.convert("deck.pptx", vision=vision)
| Field | Default | |
|---|---|---|
model |
— | Model name at the endpoint |
base_url |
None |
None is OpenAI |
api_key |
None |
None lets the SDK read OPENAI_API_KEY |
prompt |
"Describe this image concisely for use as alt text." |
|
max_tokens |
256 |
|
concurrency |
4 |
Images described at once by aconvert |
Or configure it once from the environment, and every call picks it up:
export ANYTOMD_VISION_MODEL=gpt-4.1-mini
export ANYTOMD_VISION_API_KEY=sk-...
export ANYTOMD_VISION_BASE_URL=... # optional
No model configured: the vision fallback stays off, and describe raises DescriptionError.
Versions¶
Logging¶
anytomd logs its decisions under the anytomd logger at DEBUG: the route taken, OCR finding text or not, the vision fallback switching on or off. It is silent by default.
import logging
logging.basicConfig(level=logging.DEBUG)
ad.convert("cat.png")
# DEBUG:anytomd.logic.conversion:converting cat.png as 'png' through the image route
# DEBUG:anytomd.backends.registry:vision fallback on with 'gpt-4.1-mini'
# DEBUG:anytomd.logic.fallback:standalone image: ocr found nothing