File size: 6,710 Bytes
8c1b9fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
656439d
 
 
 
8c1b9fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# Auralynq — Talk to Your Data. Podman-first, local at $0.
.DEFAULT_GOAL := help
SHELL := /usr/bin/env bash

# Use uv if present, else fall back to python -m venv + pip.
UV := $(shell command -v uv 2>/dev/null)
VENV := .venv
PY := $(VENV)/bin/python
PYTEST := $(VENV)/bin/pytest
RUFF := $(VENV)/bin/ruff
MYPY := $(VENV)/bin/mypy

# Resolve the Podman Compose command lazily inside stack targets.
COMPOSE = $$(./scripts/check_container_runtime.sh)
COMPOSE_FILE := compose.yml

.PHONY: help
help: ## Show this help
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
		awk 'BEGIN {FS = ":.*?## "}; {printf "  \033[36m%-16s\033[0m %s\n", $$1, $$2}'

# ---------------------------------------------------------------- setup -----
.PHONY: setup
setup: ## Create venv and install dev + light deps (no heavy ML stack)
ifeq ($(UV),)
	python3 -m venv $(VENV)
	$(PY) -m pip install -U pip
	$(PY) -m pip install -e ".[dev,ingest,eval]"
else
	uv venv $(VENV)
	uv pip install --python $(PY) -e ".[dev,ingest,eval]"
endif
	@echo "✓ setup complete. Activate with: source $(VENV)/bin/activate"

.PHONY: setup-all
setup-all: ## Install ALL extras (heavy: embeddings, voice, vector, agent, telemetry, mcp)
ifeq ($(UV),)
	$(PY) -m pip install -e ".[all,dev]"
else
	uv pip install --python $(PY) -e ".[all,dev]"
endif

# ----------------------------------------------------------- containers -----
.PHONY: runtime-check
runtime-check: ## Verify Podman Compose is available
	@echo "Using: $$(./scripts/check_container_runtime.sh)"

.PHONY: stack-build build
stack-build build: ## Build container images via Podman Compose
	$(COMPOSE) -f $(COMPOSE_FILE) build

.PHONY: images
images: ## Build versioned images (X.Y.Z, X.Y, git-sha, latest) + OCI labels
	./scripts/build_images.sh

.PHONY: push
push: ## Push versioned images to the registry (GHCR; needs `registry login`)
	./scripts/push_images.sh

.PHONY: version
version: ## Print the resolved image version + tags
	@bash -c 'source scripts/image_env.sh; echo "version: $$AURALYNQ_VERSION"; echo "tags   : $$(image_tags)"; echo "registry: $$AURALYNQ_REGISTRY/$$AURALYNQ_IMAGE_NAMESPACE"'

.PHONY: stack-up up
stack-up up: ## Start Qdrant, API, worker, web UI, Phoenix (hardened ordering)
	./scripts/stack_up.sh

.PHONY: stack-down
stack-down: ## Stop the stack
	$(COMPOSE) -f $(COMPOSE_FILE) down

.PHONY: stack-logs
stack-logs: ## Tail stack logs
	$(COMPOSE) -f $(COMPOSE_FILE) logs -f

.PHONY: start
start: ## Run locally on <host>:2002 (ports 2002/2004-2010)
	./scripts/run_local.sh start

.PHONY: stop
stop: ## Stop the local run
	./scripts/run_local.sh stop

.PHONY: restart
restart: ## Restart the local run
	./scripts/run_local.sh restart

.PHONY: status
status: ## Show local run container status
	./scripts/run_local.sh status

.PHONY: fresh
fresh: ## Wipe corpus volumes (auralynq-data + auralynq-qdrant) and start clean
	./scripts/run_local.sh fresh

# ----------------------------------------------------------------- data -----
.PHONY: data
data: ## Download sample text + voice datasets (no paid keys)
	$(PY) scripts/download_data.py --sample

.PHONY: data-full
data-full: ## Download full datasets
	$(PY) scripts/download_data.py --full

.PHONY: index
index: ## Build vector index + knowledge graph from ingested data
	$(PY) -m auralynq.cli index --input data/corpus

# ------------------------------------------------------------- run/demo -----
.PHONY: run
run: ## Ask a sample question end-to-end (CLI)
	$(PY) -m auralynq.cli ask "What is Auralynq and how does PathRAG work?"

.PHONY: serve
serve: ## Start the FastAPI backend
	$(PY) -m auralynq.cli serve

.PHONY: mcp
mcp: ## Start the auralynq-mcp server (stdio)
	$(PY) -m auralynq.mcp_server.server

.PHONY: demo
demo: ## Reproducible end-to-end demo (ingest -> index -> ask, text + voice)
	$(PY) scripts/demo.py

# --------------------------------------------------------- demo corpus -----
.PHONY: demo-data
demo-data: ## Copy the safe, license-clear public demo corpus into data/corpus/
	mkdir -p data/corpus
	cp -r examples/demo_corpus/docs/. data/corpus/
	@echo "✓ demo corpus copied to data/corpus/ (see examples/demo_corpus/README.md)"

.PHONY: demo-index
demo-index: demo-data ## Index the public demo corpus (vector index + knowledge graph)
	$(PY) -m auralynq.cli index --input data/corpus

.PHONY: demo-query
demo-query: ## Ask every question in examples/demo_corpus/questions.json
	$(PY) scripts/demo_query.py

# --------------------------------------------------------------- quality ----
.PHONY: test
test: ## Run the test suite
	$(PYTEST)

.PHONY: coverage
coverage: ## Run tests with coverage (core threshold enforced)
	$(PYTEST) --cov=auralynq --cov-report=term-missing --cov-report=xml \
		--cov-fail-under=80 \
		tests/

.PHONY: lint
lint: ## Ruff lint + format check
	$(RUFF) check auralynq tests scripts
	$(RUFF) format --check auralynq tests scripts

.PHONY: fmt
fmt: ## Auto-format with ruff
	$(RUFF) check --fix auralynq tests scripts
	$(RUFF) format auralynq tests scripts

.PHONY: typecheck
typecheck: ## mypy type check
	$(MYPY) auralynq

.PHONY: name-audit
name-audit: ## Verify consistent Auralynq naming across the repo
	$(PY) scripts/name_audit.py

.PHONY: check-docs
check-docs: ## Verify doc links, referenced make targets, and env.example vars
	$(PY) scripts/check_docs.py

# ----------------------------------------------------------- eval/bench -----
.PHONY: eval
eval: ## Run evaluation harness, write reports/
	$(PY) -m auralynq.cli eval --report

.PHONY: eval-gate
eval-gate: ## Run the trust gate (faithfulness/citation/calibration) — exits non-zero on regression
	$(PY) -m auralynq.cli eval --report --gate

.PHONY: bench
bench: ## Benchmark Qdrant recall/latency/memory trade-offs
	$(PY) -m auralynq.cli bench --report

.PHONY: bench-rag
bench-rag: ## RAG-quality benchmark (groundedness/citation/abstention); needs Ollama + MODEL
	$(PY) scripts/bench_rag.py --model $${MODEL:-ollama:llama3.2:3b}

.PHONY: bench-modelfit
bench-modelfit: ## Snapshot ModelFit Index rankings for this machine's hardware
	$(PY) scripts/bench_modelfit.py --task $${TASK:-rag}

.PHONY: bench-visual-grounding
bench-visual-grounding: ## Visual grounding span/segment/page/unavailable rates over the golden set
	$(PY) scripts/bench_visual_grounding.py

.PHONY: export-paper-tables
export-paper-tables: ## Render reports/*.json into reports/paper_tables.md
	$(PY) scripts/export_paper_tables.py

# --------------------------------------------------------------- misc -------
.PHONY: clean
clean: ## Remove caches and build artifacts
	rm -rf .pytest_cache .ruff_cache .mypy_cache htmlcov .coverage coverage.xml build dist
	find . -type d -name __pycache__ -prune -exec rm -rf {} +