Skip to content

hemlock stack

Local Docker-compose orchestration of the canonical four-framework RAG evaluation battery (ChromaDB + LangChain + LlamaIndex + Unstructured + Haystack pipes). The stack tree is embedded into the hemlock binary via go:embed and unpacked into ~/.hemlock/stack-<version>/ on first stack up. Subsequent invocations reuse the unpacked tree.

The four pipes are intentionally identical at the API layer (same /extract, /ingest, /query, /health endpoints) so attacks can be measured under matched-comparison discipline.

Synopsis

hemlock stack up      [--detach] [--build] [--path DIR]
hemlock stack down    [--volumes] [--path DIR]
hemlock stack status
hemlock stack path    [--path DIR]

Subcommands

Subcommand Purpose
up docker compose up -d (builds images on first run)
down docker compose down (preserves the chromadb volume by default)
status Ping each pipe's /health endpoint and print one row per service
path Print the unpacked stack directory and exit

Ports

Service Port Notes
chromadb 8000 Persistent volume chromadb-data (preserved across down unless --volumes)
pipe-langchain 8100 LangChain RetrievalQA
pipe-llamaindex 8101 LlamaIndex VectorStoreIndex query engine
pipe-unstructured 8102 Unstructured partition() loader chain
pipe-haystack 8103 Haystack BM25 + dense hybrid retriever

LLM and embedder configuration

The pipes default to a host-side ollama instance at host.docker.internal:11434 serving qwen2.5:7b for the LLM and bge-large for embeddings. Override any of these by creating .env next to the unpacked docker-compose.yml:

LLM_BASE_URL=http://host.docker.internal:11434/v1
LLM_MODEL=qwen2.5:7b
LLM_API_KEY=ollama

EMBED_BASE_URL=http://host.docker.internal:11434/v1
EMBED_MODEL=bge-large
EMBED_API_KEY=ollama

Any OpenAI-compatible endpoint works for LLM_BASE_URL and EMBED_BASE_URL — including a remote vLLM server. Find the unpacked stack with hemlock stack path.

Examples

Bring everything up and confirm health:

hemlock stack up
hemlock stack status
#   chromadb      :8000  ok  status=200
#   langchain     :8100  ok  langchain v0.3.35
#   llamaindex    :8101  ok  llamaindex v0.12.5
#   unstructured  :8102  ok  unstructured v0.16.11
#   haystack      :8103  ok  haystack v2.9.0

Stop everything but keep the indexed corpus:

hemlock stack down

Wipe the corpus too:

hemlock stack down --volumes

Use a custom unpack location:

hemlock stack up --path /tmp/hemlock-stack
hemlock stack down --path /tmp/hemlock-stack

Requirements

  • Docker installed and running on PATH
  • Around 6 GB of free space for the four pipe images (first build only)
  • Network access on first up (to pull chromadb/chroma:0.6.3 and resolve Python wheels for the pipe images)