Quickstart
Five minutes from git clone to a working retrieval query against DASH.
Prerequisites
- Docker (recommended) - Docker Engine 20+ and Docker Compose v2
- OR Rust 1.83+ and
cargo, for the build-from-source path curlfor the example commands
Option 1: Docker (recommended)
Clone the repo and start the two-service stack (ingestion on :8081, retrieval on :8080):
git clone https://github.com/BHAWESHBHASKAR/DASH.git
cd DASH
# compose runs with DASH_STRICT_SECRETS=1 and fails fast without secrets
./scripts/generate-secrets.sh
docker compose -f deploy/container/docker-compose.yml up -dBoth services come up healthy; confirm with:
curl http://localhost:8080/health
curl http://localhost:8081/healthTo stop and remove the stack:
docker compose -f deploy/container/docker-compose.yml downOption 2: Build from source
git clone https://github.com/BHAWESHBHASKAR/DASH.git
cd DASH
# Build the two services you'll run for ingestion and retrieval
cargo build --release -p ingestion -p retrievalIn one terminal, start the ingestion service:
cargo run --release -p ingestion -- --serveIn a second terminal, start the retrieval service:
cargo run --release -p retrieval -- --serveDefaults: ingestion binds 127.0.0.1:8081, retrieval binds 127.0.0.1:8080. Health endpoints are at /health, Prometheus metrics at /metrics.
To run with a durable WAL, set DASH_INGEST_WAL_PATH and DASH_RETRIEVAL_WAL_PATH to the same file before starting the services, and DASH_INGEST_API_KEY / DASH_RETRIEVAL_API_KEY to a shared key.
Ingest your first claim
A DASH claim is { claim, evidence[], edges[] }. The claim is the atomic assertion; each piece of evidence records the source that supports, contradicts, or is neutral toward the claim. Edges connect this claim to other claims (supports, contradicts, refines, duplicates, depends_on).
curl -X POST http://localhost:8081/v1/ingest \
-H "Content-Type: application/json" \
-d '{
"claim": {
"claim_id": "c1",
"tenant_id": "t1",
"canonical_text": "Company X acquired Company Y",
"confidence": 0.95
},
"evidence": [{
"evidence_id": "e1",
"claim_id": "c1",
"source_id": "news://nyt/2025-09-03",
"stance": "supports",
"source_quality": 0.95
}],
"edges": []
}'The response is 200 OK with { "ingested_claim_id": "c1", ... }. Every field is validated server-side: confidence and source_quality must be in [0.0, 1.0], valid_from <= valid_to, IDs must be non-empty.
For high-volume ingest, use POST /v1/ingest/batch with an items array, or POST /v1/ingest/document to extract claims from a raw document blob.
Retrieve with citations
Retrieve returns ranked claims with supporting/contradicting evidence as inline citations:
curl -X POST http://localhost:8080/v1/retrieve \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "t1",
"query": "Company X acquired Company Y",
"top_k": 5,
"stance_mode": "support_only"
}'Response:
{
"results": [{
"claim_id": "c1",
"canonical_text": "Company X acquired Company Y",
"score": 0.93,
"supports": 1,
"contradicts": 0,
"citations": [{
"evidence_id": "e1",
"source_id": "news://nyt/2025-09-03",
"stance": "supports",
"source_quality": 0.95
}]
}]
}You can also constrain the result set with time_range: { "from_unix": 1700000000, "to_unix": 1800000000 }, filter by entity, or pass a precomputed query_embedding instead of a string. stance_mode: "balanced" (the default) keeps contradicted claims but demotes them in the score; support_only removes them.
The contradiction walkthrough
This is the part that doesn't exist in any other vector database. Ingest the same claim twice with conflicting evidence:
- Ingest claim
c1with one supporting source (news://nyt, stancesupports). - Ingest
c1again with a contradicting source (news://reuters, stancecontradicts, a differentevidence_id). - Retrieve in default
balancedmode: the claim appears with"supports": 1, "contradicts": 1and a demoted score. - Retrieve with
stance_mode: "support_only": the result is empty - the contradicted claim is dropped.
Your retrieval layer doesn't just find "similar text" - it knows when the evidence graph says the claim is no longer true.
Use the OpenAI-compatible API
DASH exposes POST /v1/embeddings byte-compatible with the OpenAI v1 embeddings API. The default backend is the deterministic HashEmbeddingProvider (no network, no API key); swap in Ollama, OpenAI, or a custom model by implementing the EmbeddingProvider trait.
From curl:
curl -X POST http://localhost:8080/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"input": "Company X acquired Company Y", "model": "text-embedding-3-small"}'From the OpenAI Python SDK - point base_url at DASH and it is a drop-in replacement:
import openai
client = openai.OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-needed",
)
response = client.embeddings.create(
input="hello world",
model="text-embedding-3-small",
)
print(response.data[0].embedding[:5])The same pattern works for langchain, llama-index, semantic-kernel, the openai CLI, and any other client that speaks the OpenAI embeddings protocol - set OPENAI_API_BASE=http://localhost:8080/v1.