Installation¶
openodke needs Python 3.11, 3.12 or 3.13.
openodke is on PyPI; 0.2.1 is the
current release.
pip install openodke
pip install "openodke[neo4j,yaml]" # with extras
pip install "openodke[all]" # every extra
uv add "openodke[neo4j]" # or with uv
These pages track main. For changes not yet released, install from the
repository: pip install "openodke @ git+https://github.com/deepskandpal/odke".
The base install talks to nothing¶
The base install pulls in two dependencies, pydantic and typer: no model
provider, no database driver, no HTTP client. Compiling and inspecting an
ontology is useful offline, and it should not need credentials to exist
(DECISIONS #1). This is checked rather than promised:
scripts/verify.sh step 8 imports the package with the base dependencies alone,
in a throwaway environment, on every push.
On the base install you already have:
- the data model, the thirteen stage Protocols and
Pipeline; - ontologies from dicts, JSON and pydantic models, plus
validate,diff, snippets,freezeand theodke ontologycommands; - ontology inference with the deterministic proposers (
odke ontology infer --no-llm, writing a.jsondraft), and with a model over the standard-library client; - the loaders for text, Markdown, HTML, directories, JSON, JSONL, CSV and TSV, the
sentence chunker, and the extractors in
openodke.extract; SpanGrounder, andLLMGrounderover the standard-library OpenAI-compatible client;- the normalise, resolve, corroborate and score stages in
openodke.corroborate; JsonlSink,CypherFileSinkandNeo4jAdminCsvSink, andimport openodke.sinks.neo4jincluding printing its DDL and write plan (only connecting to a server needs the driver);odke runwith a JSON config, and all ofopenodke.evalandodke eval.
Extras¶
These are the extras pyproject.toml declares, exactly:
| Extra | Pulls in | What uses it on main |
|---|---|---|
llm |
litellm>=1.55,<2 |
Model strings the built-in client does not serve (see below) |
neo4j |
neo4j>=5.20,<7 |
Neo4jSink connecting to a server; Ontology.from_neo4j given a URI |
rdf |
rdflib>=7.0,<8 |
RdfSink; Ontology.from_owl |
networkx |
networkx>=3.2,<4 |
NetworkXSink |
docs |
pypdf>=5.0,<7, python-docx>=1.1,<2 |
The document readers together, so it covers what pdf and docx do. HTML needs no extra: HtmlLoader runs on the standard library. This extra is not this site's tooling: that is the docs dependency group (below). |
pdf |
pypdf>=5.0,<7 |
PdfLoader, which imports pypdf when it reads a file |
docx |
python-docx>=1.1,<2 |
DocxLoader, which imports python-docx when it reads a file |
yaml |
pyyaml>=6,<7 |
Ontology.from_yaml; YAML run configs; the odke ontology commands on .yaml/.yml files, including writing a YAML draft or frozen file |
parquet |
pyarrow>=15 |
ParquetLoader, which imports pyarrow when it reads a file |
all |
llm, neo4j, rdf, networkx, docs, pdf, docx, yaml, parquet |
Which model strings need llm¶
Every model call goes through one LLMClient Protocol. A model string such as
ollama/llama3.1 is served by the first client that matches:
- an adapter you registered for that provider with
openodke.llm.register(provider, factory); - the standard-library OpenAI-compatible client, when the provider has a default
endpoint or the
ModelSpecsets abase_url(a proxy, a gateway or a local server). This needs no extra; - litellm, for everything else. This needs
openodke[llm].
odke models prints which of the three serves each provider, in the environment
you are in, and says which providers the missing extra excludes. Every provider,
its key variable and how to address it is on one page:
Models and providers.
ModelRoles.single("ollama/llama3.1") on the base install, with a local Ollama,
is a complete setup.
A missing extra says which one¶
Nothing fails at import. The error comes when the feature is used, and it names the fix:
| Used without its extra | Raises |
|---|---|
Ontology.from_yaml |
ImportError: PyYAML is not installed. Run: pip install "openodke[yaml]" |
a YAML config in odke run |
ImportError: reading a YAML config needs PyYAML. Run: pip install "openodke[yaml]", or write the same keys as JSON |
Neo4jSink(uri, auth) |
ImportError: the neo4j driver is not installed; run: pip install 'openodke[neo4j]' |
RdfSink(path) |
ImportError: rdflib is not installed; run: pip install 'openodke[rdf]' |
Ontology.from_owl |
ImportError: rdflib is not installed. Run: pip install "openodke[rdf]" |
NetworkXSink() |
ImportError: networkx is not installed; run: pip install 'openodke[networkx]' |
PdfLoader, reading a file |
MissingExtraError: reading PDF needs pypdf. Run: pip install "openodke[pdf]" |
DocxLoader, reading a file |
MissingExtraError: reading Word documents needs python-docx. Run: pip install "openodke[docx]" |
ParquetLoader, reading a file |
MissingExtraError: reading Parquet needs pyarrow. Run: pip install "openodke[parquet]" |
DirectoryLoader, meeting one of those files |
a MissingExtraWarning naming the file and the install line; the file is skipped and the walk goes on |
| a model string that needs litellm | ProviderNotInstalled, listing pip install "openodke[llm]", a base_url, or openodke.llm.register |
a short name in odke run whose extra is missing (pdf, docx, parquet, rdf, networkx) |
exit 2 while the config is built, before anything is loaded or opened: stages.sink: RdfSink needs rdflib, which is not installed. Run: pip install "openodke[rdf]" |
MissingExtraError is an ImportError.
Working on openodke¶
git clone https://github.com/deepskandpal/odke && cd odke
./scripts/verify.sh # the whole check: ten steps, same as CI
uv run --group docs mkdocs serve # this site, at http://127.0.0.1:8000
uv run --group docs mkdocs build --strict # what the docs workflow runs
The site's tooling (mkdocs and mkdocs-material) is the docs dependency group,
not the docs extra: a group never reaches a user's install, and groups and extras
are separate namespaces.
verify.sh needs uv. Its first step refuses to run
if a provider key or NEO4J_URI / NEO4J_PASSWORD is in the environment, because
the suite must never spend money or write to somebody's real graph. The tests
that do need a real Neo4j run in their own CI job, against a throwaway container.