CLI Tools
Most command-line workflows should go through just. The recipes wrap the maintained scripts and preserve shell quoting for JSON arguments.
Authentication
The search and embed scripts read INFOCONNECT_API_KEY when no explicit API key is passed.
export INFOCONNECT_API_KEY=super-secret-key
Use this for local terminals and CI jobs where the API key is already provided by the environment.
Search from the terminal
just search "quarterly risk report"
just search "quarterly risk report" -- --json
just search "compliance" -- --filter document_id=doc-123 --rerank
just search "ledger" -- --field document --field chunk --field score
just search calls scripts/search.py and supports the same query controls as POST /search: filters, pagination, alpha, reranking, score thresholds, and field projection.
Observed just search output from a historical 2026-06-11 run (before v0.3.1; the current default is alpha=0.5):
Query: quarterly risk report
Results: 10
Total Matches: 20
Query Time: 16 ms
Alpha: 0.70
Top result: malaysia-wiki-001, score 0.500, categories sustainability
Embed files and folders
just embed ./documents
just embed ./documents/report.pdf
just embed ./documents --max-pages 5
just embed ./documents --metadata '{"department":"Finance"}'
just embed calls scripts/embed_folder.py, uploads supported files (PDF, DOCX, PPTX, XLSX, legacy PPT/XLS, TXT, MD, images) through the public /embed API, polls /status/{job_id}, and reports successes and failures. It uses runtime concurrency from .runtime/prod.env when available; pass --concurrency to override it for a one-off run.
Monitor services
just status
just status live
just status docker
just status local
Use just status live while a batch ingest is running. It shows API health, Redis/Qdrant readiness, worker state, queue counts, resource pressure, and recent alerts in a Rich terminal dashboard.
Operational scripts
| Script | Purpose |
|---|---|
scripts/download_models.py | Pre-cache FastEmbed, spaCy, reranker, and ModernBERT assets before first boot or for offline deployments |
scripts/verify_hybrid_collection.py | Verify Qdrant hybrid collection setup with a small upsert/search check |
scripts/backfill_qdrant_fuzzy_vectors.py | Backfill the client-scoped spelling vocabulary for documents embedded before typo correction was enabled |
scripts/backfill_embedding_version.py | Backfill filterable version stamps for legacy and v1-signature embedding points |
scripts/reembed_documents.py | Select stale live chunks and enqueue vectors-only re-embedding from stored chunk text |
scripts/evaluate_retrieval.py | Compare BM25, hybrid, and hybrid+rerank retrieval quality |
scripts/generate_ndcg_toy_dataset.py | Create a small graded retrieval dataset from existing chunks |
scripts/benchmark_pr_classification.py | Benchmark ModernBERT classification behavior |
Prefer the matching just recipe when one exists. Use scripts directly only for specialized diagnostics or automation.
Backfill embedding versions
New /embed writes carry an indexed top-level embedding_version and detailed
metadata.embedding provenance. Classify older points for one client with the
read-only default:
uv run python scripts/backfill_embedding_version.py \
--client-id client-a \
--json
Apply mode creates and verifies the INTEGER payload index first. It stamps points without
captured provenance as legacy version 0, stamps the known v1 signature as version 1,
and leaves non-default captured signatures un-stamped for operator review:
uv run python scripts/backfill_embedding_version.py \
--client-id client-a \
--apply \
--json
Re-embed stale documents
The targeted driver selects live points where embedding_version is below the running
pipeline version, including points with no stamp. It groups them by client, document,
and document version. Dry-run is the default:
uv run python scripts/reembed_documents.py \
--client-id client-a \
--document-id doc-123 \
--json
Use --apply to enqueue one embedding-queue task per matching document. The task reads
stored chunk_text, updates dense and sparse vectors, then writes detailed provenance
and the indexed root stamp. It does not rebuild payloads, rerun classification, or
touch the fuzzy-terms collection. Historical chunks without captured chunker or
extraction lineage are stamped with explicit unknown values. Known lineage must match
the running chunker and extraction/OCR pipeline; incompatible documents must be re-ingested.
Automatic runs exclude documents with captured non-default model or chunker signatures,
including stale stamped versions, and log their identities as re-ingest-only. An explicit
--document-id selection also refuses these documents with a clear instruction to re-ingest
them from the original source; they cannot be repaired truthfully from stored chunk text.
uv run python scripts/reembed_documents.py \
--client-id client-a \
--document-id doc-123 \
--apply \
--json
One embedding model is active per collection. A model swap requires a full re-embed of every document from stored chunk text before model-swap cutover; targeted runs are for per-document or same-model pipeline fixes.
Backfill typo-correction vocabulary
Newly embedded chunks maintain their spelling vocabulary automatically. For existing Qdrant data, run the backfill once per client. Start with its read-only dry run:
uv run python scripts/backfill_qdrant_fuzzy_vectors.py \
--client-id client-a \
--json
Before applying, quiesce ingestion and document delete/restore operations for that client. The
apply command reconciles the entire client vocabulary, so --limit is intentionally available
only for dry runs:
uv run python scripts/backfill_qdrant_fuzzy_vectors.py \
--client-id client-a \
--apply \
--quiesced-ingestion \
--json
--quiesced-ingestion is an explicit maintenance-window acknowledgement; the script does not
pause writers itself. Use --qdrant-url and --collection-name when the deployment differs from
the configured defaults. A nonzero exit reports one or more skipped write batches as errors.
Related docs
- Justfile Commands lists every recipe.
- Search API documents the underlying search request shape.
- Document Upload API documents upload constraints.