Skip to content

Commit 2ace1ea

Browse files
committed
local deployment
1 parent 979cda3 commit 2ace1ea

File tree

6 files changed

+151
-45
lines changed

6 files changed

+151
-45
lines changed

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ PROD_CORS_ORIGIN=http://localhost:3000
2020
# RAG (Retrieval-Augmented Generation) Configuration
2121
# ============================================================================
2222
EMBEDDINGS_LLM_URL=http://localhost:8080
23+
# RAG Service URL (microservice endpoint)
24+
# Backend communicates with RAG service via HTTP
25+
# Default: http://alm-rag:8002 (for Kubernetes) or http://localhost:8002 (for local)
26+
RAG_SERVICE_URL=http://localhost:8002
2327
# Enable/disable RAG functionality (default: true)
2428
RAG_ENABLED=true
2529

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# This makefile routes targets to local or helm specific makefiles
2-
.PHONY: all local helm help
2+
.PHONY: all local helm help rag-status test-rag
33

44
# ifneq (,$(wildcard .env))
55
# # ifneq (,$(filter local,$(MAKECMDGOALS)))
@@ -34,3 +34,7 @@ local/%: ## Route local targets to deploy/local/Makefile
3434

3535
cluster/%: ## Route deploy targets to deploy/helm/Makefile
3636
@$(MAKE) -C deploy/helm $*
37+
38+
# Convenience targets for common local commands
39+
rag-status: local/rag-status ## Check RAG service status
40+
test-rag: local/test-rag ## Test RAG service

deploy/local/Makefile

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: deploy start stop status help postgres phoenix loki-stack aap-mock replay stop-replay backend ui annotation health logs restart clean stop-postgres stop-phoenix stop-loki-stack stop-aap-mock embedding stop-embedding wait-for-embedding test-embedding test-rag
1+
.PHONY: deploy start stop status help postgres phoenix loki-stack aap-mock replay stop-replay backend ui annotation health logs restart clean stop-postgres stop-phoenix stop-loki-stack stop-aap-mock embedding stop-embedding wait-for-embedding rag stop-rag test-embedding test-rag
22
.DEFAULT_GOAL := help
33

44
include ../../.env
@@ -36,8 +36,10 @@ help: ## Show this help message
3636
@echo ""
3737
@echo "📚 RAG Setup:"
3838
@echo " 1. Place PDF files in data/knowledge_base/"
39-
@echo " 2. Run 'make run-whole-training-pipeline' to build RAG index"
40-
@echo " 3. Ensure RAG_ENABLED=true in .env file"
39+
@echo " 2. Start services: 'make start' (includes RAG service)"
40+
@echo " 3. Run 'make run-whole-training-pipeline' to build RAG embeddings in PostgreSQL"
41+
@echo " 4. RAG service will automatically load embeddings when available"
42+
@echo " 5. Ensure RAG_ENABLED=true and RAG_SERVICE_URL=http://alm-rag:8002 in .env file"
4143
@echo ""
4244

4345

@@ -51,6 +53,7 @@ start: stop ## 🚀 Start all services locally
5153
@$(MAKE) -s embedding
5254
@echo " ⚠️ Note: Embedding service may take 3-5 minutes to load the model"
5355
@echo " You can check status with: make test-embedding"
56+
@$(MAKE) -s rag
5457
@$(MAKE) -s aap-mock
5558
@$(MAKE) -s backend
5659
@$(MAKE) -s ui
@@ -79,6 +82,12 @@ embedding: ## 🤖 Start Embedding Service (TEI)
7982
@echo " Starting Embedding Service (TEI)..."
8083
@$(COMPOSE_CMD) -f compose.yaml up -d alm-embedding
8184

85+
rag: ## 🔍 Start RAG Service
86+
@echo " Starting RAG Service..."
87+
@$(COMPOSE_CMD) -f compose.yaml up -d alm-rag
88+
@echo " ⚠️ Note: RAG service will poll PostgreSQL for embeddings"
89+
@echo " It will become ready once embeddings are available (after init job runs)"
90+
8291
wait-for-embedding: ## ⏳ Wait for embedding service to be ready (optional, for manual use)
8392
@echo " Waiting for embedding service to be ready (this may take 3-5 minutes for model loading)..."
8493
@timeout=300; \
@@ -167,6 +176,7 @@ stop: ## 🛑 Stop all services
167176
@$(MAKE) -s stop-postgres
168177
@$(MAKE) -s stop-phoenix
169178
@$(MAKE) -s stop-embedding
179+
@$(MAKE) -s stop-rag
170180
@$(MAKE) -s kill-ports
171181
@echo "👋 All services stopped"
172182

@@ -190,6 +200,10 @@ stop-embedding: ## 🛑 Stop Embedding Service
190200
@$(COMPOSE_CMD) -f compose.yaml down alm-embedding || true
191201
@echo " ✓ Embedding service stopped and removed"
192202

203+
stop-rag: ## 🛑 Stop RAG Service
204+
@$(COMPOSE_CMD) -f compose.yaml down alm-rag || true
205+
@echo " ✓ RAG service stopped and removed"
206+
193207
kill-ports: ## 🔌 Kill processes using required ports
194208
@if [ "$$(uname)" = "Darwin" ]; then \
195209
lsof -ti :7860 | xargs kill -9 2>/dev/null || true; \
@@ -239,6 +253,12 @@ kill-ports: ## 🔌 Kill processes using required ports
239253
fuser -k 8081/tcp 2>/dev/null || true; \
240254
fi
241255
@echo " ✓ Loki MCP Server 8081 killed"
256+
@if [ "$$(uname)" = "Darwin" ]; then \
257+
lsof -ti :8002 | xargs kill -9 2>/dev/null || true; \
258+
else \
259+
fuser -k 8002/tcp 2>/dev/null || true; \
260+
fi
261+
@echo " ✓ RAG Service 8002 killed"
242262
@if [ "$$(uname)" = "Darwin" ]; then \
243263
lsof -ti :3000 | xargs kill -9 2>/dev/null || true; \
244264
else \
@@ -259,6 +279,7 @@ status: ## 📊 Show status of all services
259279
@echo " 📊 Loki: $(shell $(COMPOSE_CMD) ps 2>/dev/null | grep 'loki' | grep -v 'loki-mcp' | grep -q 'Up' && echo 'Running' || echo 'Stopped') - http://localhost:3100"
260280
@echo " 🔍 Loki MCP Server: $(shell $(COMPOSE_CMD) ps 2>/dev/null | grep 'loki-mcp-server' | grep -q 'Up' && echo 'Running' || echo 'Stopped') - http://localhost:8081"
261281
@echo " 🤖 Embedding Service: $(shell $(COMPOSE_CMD) ps 2>/dev/null | grep 'alm-embedding' | grep -q 'Up' && echo 'Running' || echo 'Stopped') - http://localhost:8080"
282+
@echo " 🔍 RAG Service: $(shell $(COMPOSE_CMD) ps 2>/dev/null | grep 'alm-rag' | grep -q 'Up' && echo 'Running' || echo 'Stopped') - http://localhost:8002"
262283
@echo " 📈 Grafana: $(shell $(COMPOSE_CMD) ps 2>/dev/null | grep 'grafana' | grep -q 'Up' && echo 'Running' || echo 'Stopped') - http://localhost:3000"
263284
@echo " 📝 Promtail: $(shell $(COMPOSE_CMD) ps 2>/dev/null | grep 'promtail' | grep -q 'Up' && echo 'Running' || echo 'Stopped')"
264285
@echo " 🎭 AAP Mock: $(shell $(COMPOSE_CMD) ps 2>/dev/null | grep 'aap-mock' | grep -q 'Up' && echo 'Running' || echo 'Stopped') - http://localhost:8082"
@@ -293,14 +314,20 @@ run-whole-training-pipeline: ## 🔍 Run whole training pipeline (builds RAG ind
293314
@( cd ../.. && uv run init_pipeline.py )
294315

295316
# Add new target to check RAG status
296-
rag-status: ## 📊 Check RAG index status
297-
@echo "📊 RAG Index Status:"
298-
@if [ -f "../../data/ansible_errors.index" ] && [ -f "../../data/error_metadata.pkl" ]; then \
299-
echo " ✅ RAG index exists"; \
300-
ls -lh ../../data/ansible_errors.index ../../data/error_metadata.pkl; \
317+
rag-status: ## 📊 Check RAG service and index status
318+
@echo "📊 RAG Service Status:"
319+
@if curl -s -f http://localhost:8002/health >/dev/null 2>&1; then \
320+
echo " ✅ RAG service is running"; \
321+
if curl -s -f http://localhost:8002/ready >/dev/null 2>&1; then \
322+
index_size=$$(curl -s http://localhost:8002/ready | grep -o '"index_size":[0-9]*' | grep -o '[0-9]*' || echo "unknown"); \
323+
echo " ✅ RAG index is loaded ($$index_size embeddings)"; \
324+
else \
325+
echo " ⚠️ RAG index not loaded yet (waiting for embeddings)"; \
326+
echo " Run 'make run-whole-training-pipeline' to build embeddings"; \
327+
fi; \
301328
else \
302-
echo " ❌ RAG index not found"; \
303-
echo " Run 'make run-whole-training-pipeline' to build it"; \
329+
echo " ❌ RAG service is not running"; \
330+
echo " Start it with: make rag"; \
304331
fi
305332
@if [ -d "../../data/knowledge_base" ]; then \
306333
pdf_count=$$(ls -1 ../../data/knowledge_base/*.pdf 2>/dev/null | wc -l); \
@@ -335,14 +362,40 @@ test-embedding: ## 🧪 Test embedding service
335362
@echo ""
336363
@echo "✅ Embedding service test passed!"
337364

338-
test-rag: ## 🧪 Test RAG system (requires RAG index)
339-
@echo "🧪 Testing RAG System..."
340-
@if [ ! -f "../../data/ansible_errors.index" ]; then \
341-
echo "❌ RAG index not found. Run 'make run-whole-training-pipeline' first."; \
365+
test-rag: ## 🧪 Test RAG service (requires RAG service running and embeddings in PostgreSQL)
366+
@echo "🧪 Testing RAG Service..."
367+
@echo ""
368+
@echo "1. Health Check:"
369+
@if curl -s -f http://localhost:8002/health >/dev/null 2>&1; then \
370+
echo " ✅ Service is healthy"; \
371+
else \
372+
echo " ❌ Service is not responding"; \
373+
exit 1; \
374+
fi
375+
@echo ""
376+
@echo "2. Readiness Check:"
377+
@if curl -s -f http://localhost:8002/ready >/dev/null 2>&1; then \
378+
echo " ✅ Service is ready (index loaded)"; \
379+
else \
380+
echo " ⚠️ Service is not ready (index not loaded yet)"; \
381+
echo " Run 'make run-whole-training-pipeline' to build embeddings"; \
382+
exit 1; \
383+
fi
384+
@echo ""
385+
@echo "3. Test Query:"
386+
@response=$$(curl -s -X POST http://localhost:8002/rag/query \
387+
-H "Content-Type: application/json" \
388+
-d '{"query": "ansible playbook execution failed", "top_k": 5, "top_n": 3, "similarity_threshold": 0.6}'); \
389+
if echo "$$response" | grep -q '"results"'; then \
390+
echo " ✅ Query successful"; \
391+
echo " Response preview: $$(echo $$response | head -c 200)..."; \
392+
else \
393+
echo " ❌ Query failed"; \
394+
echo " Response: $$response"; \
342395
exit 1; \
343396
fi
344-
@echo "Running RAG test script..."
345-
@(cd ../.. && uv run python tests/rag/test_embeddings.py)
397+
@echo ""
398+
@echo "✅ RAG service test passed!"
346399

347400
health: ## 🔍 Check health of running services
348401
@echo "🔍 Health Checks:"
@@ -381,6 +434,16 @@ health: ## 🔍 Check health of running services
381434
else \
382435
echo " 🤖 Embedding Service http://localhost:8080: Unhealthy (may still be loading model)"; \
383436
fi
437+
@if curl -s http://localhost:8002/health >/dev/null 2>&1; then \
438+
echo " 🔍 RAG Service http://localhost:8002: Healthy"; \
439+
if curl -s http://localhost:8002/ready >/dev/null 2>&1; then \
440+
echo " 🔍 RAG Service http://localhost:8002: Ready (index loaded)"; \
441+
else \
442+
echo " 🔍 RAG Service http://localhost:8002: Not ready (index not loaded yet)"; \
443+
fi; \
444+
else \
445+
echo " 🔍 RAG Service http://localhost:8002: Unhealthy"; \
446+
fi
384447
@if curl -s http://localhost:3000 >/dev/null 2>&1; then \
385448
echo " 📈 Grafana http://localhost:3000: Healthy"; \
386449
else \

deploy/local/compose.yaml

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ services:
125125
restart: unless-stopped
126126

127127
postgres:
128-
image: postgres:15
128+
image: pgvector/pgvector:pg15 # PostgreSQL with pgvector extension
129129
environment:
130130
- POSTGRES_USER=user
131131
- POSTGRES_PASSWORD=password
@@ -173,6 +173,7 @@ services:
173173
- PROD_CORS_ORIGIN=${PROD_CORS_ORIGIN}
174174
# RAG Configuration
175175
- RAG_ENABLED=${RAG_ENABLED}
176+
- RAG_SERVICE_URL=${RAG_SERVICE_URL:-http://alm-rag:8002}
176177
- DATA_DIR=${DATA_DIR}
177178
- KNOWLEDGE_BASE_DIR=${KNOWLEDGE_BASE_DIR}
178179
- RAG_TOP_K=${RAG_TOP_K}
@@ -194,6 +195,8 @@ services:
194195
condition: service_healthy
195196
alm-embedding:
196197
condition: service_healthy
198+
alm-rag:
199+
condition: service_started # RAG service can start before embeddings are ready
197200
restart: unless-stopped
198201
healthcheck:
199202
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
@@ -244,6 +247,35 @@ services:
244247
# Note: This service requires significant memory (8Gi recommended)
245248
# Adjust resources based on your system capabilities
246249

250+
alm-rag:
251+
build:
252+
context: ../..
253+
dockerfile: services/rag/Containerfile
254+
container_name: alm-rag
255+
ports:
256+
- "8002:8002"
257+
environment:
258+
# Use container network name for PostgreSQL (not localhost)
259+
# Override any local DATABASE_URL to use container network
260+
- DATABASE_URL=postgresql+asyncpg://user:password@postgres:5432/logsdb
261+
- EMBEDDINGS_LLM_URL=http://alm-embedding:8080
262+
- RAG_MODEL_NAME=nomic-ai/nomic-embed-text-v1.5
263+
- PORT=8002
264+
networks:
265+
- alm
266+
depends_on:
267+
postgres:
268+
condition: service_healthy
269+
alm-embedding:
270+
condition: service_healthy
271+
restart: unless-stopped
272+
healthcheck:
273+
test: ["CMD", "curl", "-f", "http://localhost:8002/health"]
274+
interval: 30s
275+
timeout: 10s
276+
retries: 3
277+
start_period: 30s # Service starts immediately, but index may take time to load
278+
247279
volumes:
248280
postgres_data:
249281
aap_mock_data:

init_pipeline.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,21 @@ def setup_data_directories():
2929
print(f" ✓ {data_dir}")
3030
print(f" ✓ {logs_dir}")
3131

32-
# Check for knowledge base PDFs in image
33-
image_kb_dir = Path("/app/data/knowledge_base")
34-
if image_kb_dir.exists():
35-
image_pdfs = list(image_kb_dir.glob("*.pdf"))
36-
if image_pdfs:
37-
print(f"\n✓ Found {len(image_pdfs)} PDF file(s) in container image:")
38-
for pdf in image_pdfs:
32+
# Check for knowledge base PDFs
33+
# Use config path (works for both local and container)
34+
kb_dir = Path(config.storage.knowledge_base_dir)
35+
if kb_dir.exists():
36+
pdfs = list(kb_dir.glob("*.pdf"))
37+
if pdfs:
38+
print(f"\n✓ Found {len(pdfs)} PDF file(s) in knowledge base ({kb_dir}):")
39+
for pdf in pdfs:
3940
print(f" - {pdf.name}")
4041
else:
41-
print(f"\n⚠ No PDF files found in image at {image_kb_dir}")
42+
print(f"\n⚠ No PDF files found in {kb_dir}")
43+
print(" Add PDF files to the knowledge base directory to enable RAG")
4244
else:
43-
print(f"\n⚠ Knowledge base directory not found in image at {image_kb_dir}")
44-
print(
45-
" PDFs should be baked into the container image at /app/data/knowledge_base"
46-
)
45+
print(f"\n⚠ Knowledge base directory not found at {kb_dir}")
46+
print(" Create the directory and add PDF files to enable RAG")
4747

4848
print("=" * 70)
4949

@@ -108,13 +108,13 @@ async def build_rag_index():
108108
parser = AnsibleErrorParser()
109109
embedder = AnsibleErrorEmbedder()
110110

111-
# Find PDFs in knowledge base (from container image)
112-
# PDFs should be baked into the image at /app/data/knowledge_base
113-
image_kb_dir = Path("/app/data/knowledge_base")
114-
pdf_files = sorted(glob.glob(str(image_kb_dir / "*.pdf")))
111+
# Find PDFs in knowledge base
112+
# Use config path (works for both local and container)
113+
kb_dir = Path(config.storage.knowledge_base_dir)
114+
pdf_files = sorted(glob.glob(str(kb_dir / "*.pdf")))
115115

116116
if not pdf_files:
117-
print(f"⚠ WARNING: No PDF files found in {image_kb_dir}")
117+
print(f"⚠ WARNING: No PDF files found in {kb_dir}")
118118
print(" RAG index will not be created")
119119
return
120120

src/alm/database.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@
2424

2525
# Create tables
2626
async def init_tables(delete_tables=False):
27+
# First, try to enable pgvector extension in a separate transaction
28+
# This prevents transaction abort errors if extension creation fails
29+
try:
30+
async with engine.begin() as ext_conn:
31+
await ext_conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
32+
logger.info("pgvector extension enabled")
33+
except Exception as e:
34+
logger.warning(f"Could not enable pgvector extension: {e}")
35+
logger.warning("This is OK if extension is already enabled or not available")
36+
# For local dev without pgvector, we'll continue but RAG won't work
37+
# In production, this should fail
38+
39+
# Now create tables in a separate transaction
2740
async with engine.begin() as conn:
2841
if delete_tables:
2942
logger.info("Starting to delete tables")
@@ -32,16 +45,6 @@ async def init_tables(delete_tables=False):
3245
await conn.run_sync(GrafanaAlert.metadata.drop_all)
3346
# RAGEmbedding table is NOT deleted - it persists across runs
3447

35-
# Ensure pgvector extension is enabled (must be done before creating tables)
36-
try:
37-
await conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
38-
logger.info("pgvector extension enabled")
39-
except Exception as e:
40-
logger.warning(f"Could not enable pgvector extension: {e}")
41-
logger.warning(
42-
"This is OK if extension is already enabled or not available"
43-
)
44-
4548
# Create all tables
4649
await conn.run_sync(GrafanaAlert.metadata.create_all)
4750
await conn.run_sync(RAGEmbedding.metadata.create_all)

0 commit comments

Comments
 (0)