oidlabs-com/lexoid/lexoid-python

Claude Code and agent skill by oidlabs-com/lexoid

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Parse and convert documents (PDFs, images, web pages, DOCX/XLSX/PPTX, audio) inside a Python program using the `lexoid` library. Use when the user is writing Python code that needs to extract markdown from documents, run schema-constrained extraction, convert files to LaTeX, get bounding boxes, recursively crawl URLs, or integrate document parsing into a larger pipeline. Triggers include `from lexoid` imports, "use lexoid in Python", "parse PDFs programmatically", "extract structured data with a Pydantic/dataclass schema", or any request to embed parsing into a Python app/notebook.

Install

npx vskill@latest install oidlabs-com/lexoid/lexoid-python

SKILL.md

Lexoid Python API

Lexoid's Python API is the right choice whenever the user is writing Python — notebooks, services, batch pipelines, or anything that needs the parsed result as a Python dict/list. For shell one-offs, use the lexoid-cli skill instead.

When to use this skill

  • The user is writing Python and wants to parse PDFs, images, URLs, DOCX/XLSX/PPTX, audio, or text-format files.
  • The user needs per-page segments, token usage, parser metadata, or bounding boxes in code.
  • The user wants schema-based structured extraction (dict, dataclass, or Pydantic BaseModel).
  • The user is integrating parsing into a larger app (Streamlit, FastAPI, RAG pipeline, etc.).

Setup checks

Before writing code, confirm:

  1. lexoid is installed (pip install lexoid).
  2. Required API key env vars are set for the chosen provider (see below).
  3. For Linux DOCX → PDF conversion, LibreOffice (lowriter) is on PATH.
  4. For api_provider="ollama": an ollama serve process is running at OLLAMA_BASE_URL (default http://localhost:11434) and the target model has been pulled with ollama pull <model>.
  5. For api_provider="local" (SmolDocling/granite-docling, PaddleOCR-VL): no server needed — these models run in-process via transformers / PaddleOCR. The first call downloads weights from Hugging Face, so the host needs network access (or pre-cached weights) and enough disk/RAM/GPU for the chosen model.

API keys by provider:

ProviderEnv var
geminiGOOGLE_API_KEY
openaiOPENAI_API_KEY
anthropicANTHROPIC_API_KEY
mistralMISTRAL_API_KEY
huggingfaceHUGGINGFACEHUB_API_TOKEN
togetherTOGETHER_API_KEY
openrouterOPENROUTER_API_KEY
fireworksFIREWORKS_API_KEY
ollamanone (uses OLLAMA_BASE_URL)
localnone
Loading API keys from .env

Lexoid reads API keys from the process environment; it does not load a .env file on its own. When keys live in a project .env, load them before calling any LLM-based API (LLM_PARSE, parse_with_schema, parse_to_latex, or AUTO when it routes to an LLM). python-dotenv ships as a Lexoid dependency, so it is already available:

python
from dotenv import load_dotenv
# Loads .env from the current dir (or a parent) into os.environ if the file
# exists; a no-op that returns False when no .env is found. Existing env vars
# are not overwritten unless override=True is passed.
load_dotenv()
from lexoid.api import parse
result = parse("document.pdf", parser_type="LLM_PARSE", model="gpt-4o")

Call load_dotenv() once at program/notebook startup, before the first parse(...) call. If the keys are already exported in the environment, this step is unnecessary (and harmless).

Public API

Four entry points in lexoid.api:

  • parse(path, parser_type="AUTO", pages_per_split=4, max_processes=4, **kwargs) — main function. Returns a dict.
  • parse_with_schema(path, schema, api=None, model="gpt-4o-mini", **kwargs) — structured JSON extraction. Returns a Python list whose shape depends on the mode and the model's output (see "Schema return shape" below).
  • parse_to_latex(path, api=None, model="gpt-4o-mini", **kwargs) — returns a LaTeX string.
  • parse_chunk(path, parser_type, **kwargs) — low-level single-chunk parser; users rarely need this.

ParserType enum: LLM_PARSE, STATIC_PARSE, AUTO.

parse() return shape

python
{
"raw": str, # full markdown
"segments": [ # one dict per page / section; may be empty
# bboxes is included only when return_bboxes=True
{"metadata": {"page": int}, "content": str, "bboxes": [(text, [x0, top, x1, bottom]), ...]},
...
],
"title": str,
"url": str, # input URL or "" if input was a local file
"parent_title": str, # parent doc title when recursive; "" otherwise
"recursive_docs": [...], # empty unless depth > 1
# --- optional keys below ---
"token_usage": {"input": int, "output": int, "total": int, "llm_page_count": int},
# zeros under STATIC_PARSE-only; ABSENT on the HTML/recursive-URL path
# (URL input that isn't a file-typed URL and as_pdf is not set)
"parsers_used": [str, ...], # ABSENT on the HTML/recursive-URL path (same condition)
"token_cost": {...}, # only when api_cost_mapping is supplied
"pdf_path": str, # only when as_pdf=True; file is removed unless save_dir is also set
}

For URL inputs that resolve to HTML (no .pdf/image extension, and as_pdf=False), parse() short-circuits to recursive_read_html(), which returns only raw, segments, title, url, parent_title, and recursive_docs. Code that always reads result["token_usage"] or result["parsers_used"] will KeyError on that path — use .get(...) or guard with if "token_usage" in result.

Common recipes

Basic parsing
python
from lexoid.api import parse
result = parse("document.pdf")
markdown = result["raw"]
for seg in result["segments"]:
print(seg["metadata"]["page"], seg["content"][:80])
Choose a parser explicitly
python
# Native-text PDFs — fastest, no API key
parse("document.pdf", parser_type="STATIC_PARSE", framework="pdfplumber")
# Scanned PDFs / images — local OCR, no API key
parse("scanned.pdf", parser_type="STATIC_PARSE", framework="paddleocr")
# LLM parsing
parse("document.pdf", parser_type="LLM_PARSE", model="gpt-4o")
parse("document.pdf", parser_type="LLM_PARSE", model="gemini-3.5-flash-lite")
parse("document.pdf", parser_type="LLM_PARSE", model="claude-haiku-5-5")
AUTO routing with a priority
python
# Speed (default): static if no images, LLM otherwise
parse("doc.pdf", parser_type="AUTO", router_priority="speed")
# Accuracy: prefers LLM, except PDFs with hidden hyperlinks
parse("doc.pdf", parser_type="AUTO", router_priority="accuracy")
# Cost: tries PaddleOCR first; LLM fallback if extracted text is too short
parse("doc.pdf", parser_type="AUTO", router_priority="cost", character_threshold=100)
# ML-based LLM auto-selection (uses lexoid/core/llm_selector.py)
parse("doc.pdf", parser_type="AUTO", autoselect_llm=True)
Local inference (no API key)
python
# Ollama — Lexoid forces max_processes=1 for Ollama
parse("doc.pdf", parser_type="LLM_PARSE",
api_provider="ollama", model="gemma4:latest", max_processes=1)
# SmolDocling / granite-docling
parse("doc.pdf", parser_type="LLM_PARSE",
api_provider="local", model="ds4sd/SmolDocling-256M-preview")
# PaddleOCR-VL
parse("doc.pdf", parser_type="LLM_PARSE",
api_provider="local", model="PaddlePaddle/PaddleOCR-VL")
Schema-based structured extraction
Schema return shape

parse_with_schema returns a Python list. The exact shape depends on the mode and on what JSON the model emits:

  • Default (per-page) mode — one entry per page. Each entry is the JSON

the model returned for that page: a single dict for single-record schemas, or a list of dicts for multi-record schemas (e.g., a page of table rows). Index as result[page_index] for the page's value, and result[page_index][record_index] when each page has multiple records.

  • `fill_single_schema=True` — a single-element list whose element is

the JSON for the whole document (typically one dict).

If you need to support both single- and multi-record schemas in the same code path, normalize the per-page entries yourself (e.g., wrap a dict in [dict]).

python
from lexoid.api import parse_with_schema
from pydantic import BaseModel
class Invoice(BaseModel):
invoice_number: str
total: float
# Per-page extraction. `pages` is a list with one entry per page;
# each entry is whatever JSON the model returned for that page.
pages = parse_with_schema("invoice.pdf", schema=Invoice, model="gpt-4o-mini")
# e.g., pages[0] -> {"invoice_number": "...", "total": ...}
# pages[0][0] -> first record if the model returned a list per page
# Single instance for the whole document — returns a one-element list.
[full] = parse_with_schema("contract.pdf", schema=Invoice,
model="gpt-4o", fill_single_schema=True)
# Dict schema with example data + alternate keys (improves match)
pages = parse_with_schema(
"invoice.pdf",
schema={"invoice_number": "string", "total": "number"},
example_schema={"invoice_number": "INV-001", "total": 199.95},
alternate_keys={"invoice_number": ["Invoice #", "Invoice No."]},
)
# Dataclass schemas also work
from dataclasses import dataclass
@dataclass
class Receipt:
merchant: str
amount: float
parse_with_schema("receipt.pdf", schema=Receipt)
LaTeX conversion
python
from lexoid.api import parse_to_latex
latex_source = parse_to_latex("paper.pdf", model="gpt-4o")
URLs and recursive crawling
python
# Single page
parse("https://example.com")
# Crawl 2 levels deep
parse("https://example.com", depth=2)
# Render webpage → PDF first, then parse and keep the intermediate PDF
result = parse(
"https://example.com",
as_pdf=True,
save_dir="output/",
save_filename="example.pdf",
)
intermediate = result["pdf_path"]
Bounding boxes
python
result = parse("doc.pdf", return_bboxes=True, bbox_framework="auto")
for seg in result["segments"]:
for text, bbox in seg.get("bboxes", []):
# bbox = [x0, top, x1, bottom], normalized [0, 1]
...
Audio

Audio inputs require a Gemini model (the only provider with audio support).

python
result = parse("interview.mp3", model="gemini-3.1-pro-preview")
print(result["raw"])
Token cost tracking
python
result = parse(
"doc.pdf",
model="gpt-4o",
api_cost_mapping="tests/api_cost_mapping.json",
)
print(result["token_cost"]) # {"input": ..., "output": ..., "input-image": ..., "total": ...}

Key kwargs reference

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
108
Repository forks
14
7-day trend score
23

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 30 Aug 2026, 2 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/oidlabs-com/lexoid/lexoid-python/badge)](https://verified-skill.com/skills/oidlabs-com/lexoid/lexoid-python)

Something wrong with this skill or its page? Tell us.