Chunking, embedding, and hybrid retrieval over the VTK knowledge artifact.
Takes the JSONL file produced by vtk-knowledge, splits it into searchable
chunks, embeds them with dense and sparse models, and stores them in Qdrant.
The Retriever class exposes hybrid search (dense + BM25 Reciprocal Rank
Fusion) over the resulting collections.
This is Layer 2 of a four-layer stack:
vtk-knowledge - schema, artifact, in-memory index
vtk-index - chunking, dense+sparse embeddings, Qdrant (this repo)
vtk-validate - AST-based VTK code validation
vtk-mcp - MCP gateway, 25 tools over stdio/http
Each layer only depends on layers below it.
vtk-index is not yet on PyPI.
Because vtk-index depends on vtk-knowledge (also not on PyPI), declare
both as git sources in your pyproject.toml before adding:
[tool.uv.sources]
vtk-knowledge = {git = "https://github.com/vicentebolea/vtk-knowledge.git"}
vtk-index = {git = "https://github.com/vicentebolea/vtk-index.git"}uv add vtk-indexWith pip:
pip install "vtk-knowledge @ git+https://github.com/vicentebolea/vtk-knowledge.git"
pip install "vtk-index @ git+https://github.com/vicentebolea/vtk-index.git"git clone https://github.com/vicentebolea/vtk-index
cd vtk-index
uv venv
uv pip install "vtk-knowledge @ git+https://github.com/vicentebolea/vtk-knowledge.git"
uv pip install -e ".[dev]"
pytest tests/
uv run vtk-index # run the CLI (venv does not need to be activated)If working inside the monorepo workspace, uv add --dev . installs vtk-index
into the shared workspace venv. Use uv run vtk-index to invoke the CLI — the
workspace venv is not automatically on PATH.
Downloads both the doc-chunks JSONL and the pre-built embedded Qdrant storage
to ~/.cache/vtk-index/ by default.
# download both artifacts (recommended — enables instant search)
vtk-index download 9.6.1
# write to a specific directory instead of ~/.cache/vtk-index/
vtk-index download 9.6.1 -o ./artifacts/
# only the embedded storage (skips doc-chunks JSONL)
vtk-index download 9.6.1 --no-chunks
# only the doc-chunks JSONL (skips embedded storage)
vtk-index download 9.6.1 --no-embedded
# pull from a different ghcr.io repository
vtk-index download 9.6.1 -r myorg/vtk-indexPulls from ghcr.io/{repository} via the OCI HTTP API — no docker or podman
required. Two artifacts are cached in ~/.cache/vtk-index/:
| File | Tag | Use with |
|---|---|---|
doc-chunks-9.6.1.jsonl |
9.6.1 |
search --chunks (embeds on the fly) |
storage-9.6.1/ |
9.6.1-embedded |
search --vtk-version (instant, no embedding) |
Three backends, pick the one that suits your setup:
# fastest: use pre-built embedded storage downloaded by 'vtk-index download'
vtk-index search --vtk-version 9.6.1 "sphere source"
vtk-index search --vtk-version 9.6.1 "read STL file" --role source -n 5
vtk-index search --vtk-version 9.6.1 "isosurface contour" --min-visibility 0.7
vtk-index search --vtk-version 9.6.1 "render window" --collection code
vtk-index search --vtk-version 9.6.1 "sphere source" --json
# alternative: load doc-chunks and embed on the fly (~30s startup)
vtk-index search "sphere source" --chunks doc-chunks-9.6.1.jsonl
# alternative: running Qdrant server
vtk-index search "sphere source" --qdrant-url http://myhost:6333--vtk-version downloads the embedded storage on first use and caches it.
Subsequent queries are instant — no server, no embedding models at query time.
vtk-index chunk vtk-knowledge-9.6.1.jsonl -o chunks/
# writes chunks/doc-chunks.jsonl# write to a local embedded storage directory (no server needed)
vtk-index index --doc-chunks chunks/doc-chunks.jsonl --path ./storage/
# upload to a running Qdrant server
vtk-index index --doc-chunks chunks/doc-chunks.jsonl --qdrant-url http://localhost:6333vtk-index snapshot --vtk-version 9.6.1 -o .
# writes vtk-index-9.6.1.snapshot.tar.gzvtk-index build vtk-knowledge-9.6.1.jsonl \
--qdrant-url http://localhost:6333 \
--output-dir ./artifacts/from vtk_index import Retriever
# zero-config: downloads pre-built storage on first call, instant after
retriever = Retriever.from_artifact("9.6.1")
chunks = retriever.search_docs("sphere source", k=5)
for c in chunks:
print(c.class_names, c.chunk_type, c.content[:120])
# explicit in-memory (requires indexing first)
retriever = Retriever()
# explicit server
retriever = Retriever(qdrant_url="http://localhost:6333")
# explicit local storage path
retriever = Retriever(qdrant_path="./storage-9.6.1")
# hybrid search with filter
from vtk_index.query.filters import PayloadFilter
chunks = retriever.hybrid_search(
"read STL file",
collection="vtk_docs",
k=10,
filters=PayloadFilter().by_role("source").min_visibility(0.6),
)Each VTKDocRecord is split into one or more Chunk objects stored in Qdrant:
chunk_type |
Content |
|---|---|
class_overview |
class name, module, synopsis, class doc excerpt, action phrase |
method_doc |
method signature(s) + docstring for each semantic method |
inheritance |
MRO chain as a single sentence |
pipeline_example |
whole-file or extracted pipeline segment from example scripts |
query_example |
extracted query/search segment from example scripts |
constructor |
constructor signatures |
property_group |
grouped property getter/setter pairs |
from vtk_index.query.filters import PayloadFilter, build_filter
# builder pattern
f = PayloadFilter().by_role("source").min_visibility(0.7).build()
# plain dict (same result)
f = build_filter({"role": "source", "visibility_score": {"gte": 0.7}})workflow_dispatch in .github/workflows/build-artifact.yml:
- Actions -> Build Chunks Artifact -> Run workflow
- Set the VTK version (must already have a
vtk-knowledgeartifact on ghcr.io)
The workflow:
- Downloads the
vtk-knowledgeJSONL artifact fromghcr.io/vicentebolea/vtk-knowledge - Runs
vtk-index chunkto producedoc-chunks.jsonl - Runs
vtk-index index --path storage/to build the embedded Qdrant storage - Pushes two FROM-scratch OCI images to ghcr.io:
ghcr.io/vicentebolea/vtk-index:{vtk_version}— doc-chunks JSONLghcr.io/vicentebolea/vtk-index:{vtk_version}-embedded— pre-built Qdrant storage
src/vtk_index/
chunking/base.py # Chunk model and ChunkType enum (Pydantic)
chunking/doc_chunker.py # VTKDocRecord -> list[Chunk]
chunking/code_chunker.py # Python example scripts -> list[Chunk]
embedding/dense.py # DenseEmbedder wrapping sentence-transformers
embedding/sparse.py # SparseEmbedder wrapping FastEmbed BM25
query/client.py # Retriever: from_artifact / search_docs / search_code / hybrid_search
query/filters.py # PayloadFilter builder and build_filter helper
pipeline/cli.py # Typer CLI: download / search / chunk / index / snapshot / build
artifact/fetcher.py # fetch_from_ghcr / fetch_embedded_storage: OCI pull without docker
artifact/snapshot.py # save_snapshot / load_snapshot for Qdrant server tarballs
| Repo | Layer | What it does |
|---|---|---|
| vtk-knowledge | 1 | Schema, artifact, index |
| vtk-index (here) | 2 | Chunking, embeddings, Qdrant |
| vtk-validate | 3 | AST validation of VTK code |
| vtk-mcp | 4 | MCP gateway for LLM assistants |