@@ -13,11 +13,17 @@ LLAMA_STACK_CONFIG ?= run.yaml
1313
1414# Container configuration
1515LLAMA_STACK_CONTAINER_NAME ?= lightspeed-llama-stack
16+ LLAMA_STACK_DEPS_IMAGE ?= lightspeed-llama-stack-deps:local
1617LLAMA_STACK_IMAGE ?= lightspeed-llama-stack:local
1718LLAMA_STACK_PORT ?= 8321
1819CONTAINER_RUNTIME ?= $(shell command -v podman 2>/dev/null || command -v docker 2>/dev/null)
1920
20- .PHONY : run run-stack build-llama-stack-image remove-llama-stack-container stop-llama-stack-container start-llama-stack-container wait-for-llama-stack-health clean-llama-stack
21+ # Dependency change detection
22+ DEPS_HASH_FILE := .llama-stack-deps.hash
23+ CURRENT_DEPS_HASH := $(shell cat pyproject.toml uv.lock providers/pyproject.toml providers/uv.lock 2>/dev/null | shasum -a 256 | cut -d' ' -f1)
24+ STORED_DEPS_HASH := $(shell cat $(DEPS_HASH_FILE ) 2>/dev/null)
25+
26+ .PHONY : run run-stack build-llama-stack-deps-image ensure-llama-stack-deps-image build-llama-stack-image remove-llama-stack-container stop-llama-stack-container start-llama-stack-container wait-for-llama-stack-health clean-llama-stack
2127
2228run-stack : # # Run lightspeed-stack directly, without building dependent service/s
2329 uv run src/lightspeed_stack.py -c $(CONFIG )
@@ -27,13 +33,44 @@ run: start-llama-stack-container ## Run the service locally with dependent servi
2733 @trap ' echo ""; echo "Stopping services..."; $(MAKE) stop-llama-stack-container' EXIT INT TERM; \
2834 $(MAKE ) run-stack
2935
30- build-llama-stack-image : remove-llama-stack-container # # Build llama-stack container image
31- @echo " Building llama-stack container image..."
36+ build-llama-stack-deps- image : # # Force rebuild the deps base image
37+ @echo " Building llama-stack deps image..."
3238 @if [ -z " $( CONTAINER_RUNTIME) " ]; then \
3339 echo " ERROR: No container runtime found. Install podman or docker." ; \
3440 exit 1; \
3541 fi
36- $(CONTAINER_RUNTIME ) build -f deploy/llama-stack/test.containerfile -t $(LLAMA_STACK_IMAGE ) .
42+ @if $(CONTAINER_RUNTIME ) image inspect $(LLAMA_STACK_DEPS_IMAGE ) > /dev/null 2>&1 ; then \
43+ echo " Removing existing deps image to avoid dangling images..." ; \
44+ $(CONTAINER_RUNTIME ) rmi $(LLAMA_STACK_DEPS_IMAGE ) ; \
45+ fi
46+ $(CONTAINER_RUNTIME ) build -f deploy/llama-stack/test.containerfile --target deps-builder -t $(LLAMA_STACK_DEPS_IMAGE ) .
47+ @echo " $( CURRENT_DEPS_HASH) " > $(DEPS_HASH_FILE )
48+ @echo " ✓ Deps image built and hash saved"
49+
50+ ensure-llama-stack-deps-image : # # Build deps image only if missing or dependencies changed
51+ @if [ -z " $( CONTAINER_RUNTIME) " ]; then \
52+ echo " ERROR: No container runtime found. Install podman or docker." ; \
53+ exit 1; \
54+ fi
55+ @if ! $(CONTAINER_RUNTIME ) image inspect $(LLAMA_STACK_DEPS_IMAGE ) > /dev/null 2>&1 ; then \
56+ echo " Deps image not found, building..." ; \
57+ $(MAKE ) build-llama-stack-deps-image; \
58+ elif [ " $( CURRENT_DEPS_HASH) " != " $( STORED_DEPS_HASH) " ]; then \
59+ echo " Dependencies changed (pyproject.toml or uv.lock), rebuilding deps image..." ; \
60+ $(MAKE ) build-llama-stack-deps-image; \
61+ else \
62+ echo " ✓ Deps image is up-to-date (skipping rebuild)" ; \
63+ fi
64+
65+ build-llama-stack-image : ensure-llama-stack-deps-image # # Build llama-stack app image (source-only layer on top of deps)
66+ @echo " Building llama-stack app image..."
67+ @if $(CONTAINER_RUNTIME ) image inspect $(LLAMA_STACK_IMAGE ) > /dev/null 2>&1 ; then \
68+ echo " Removing existing app image to avoid dangling images..." ; \
69+ $(CONTAINER_RUNTIME ) rmi $(LLAMA_STACK_IMAGE ) ; \
70+ fi
71+ $(CONTAINER_RUNTIME ) build -f deploy/llama-stack/test.containerfile \
72+ --build-arg DEPS_IMAGE=$(LLAMA_STACK_DEPS_IMAGE ) \
73+ -t $(LLAMA_STACK_IMAGE ) .
3774
3875stop-llama-stack-container : # # Gracefully stop llama-stack container
3976 @if [ -n " $( CONTAINER_RUNTIME) " ] && $(CONTAINER_RUNTIME ) inspect $(LLAMA_STACK_CONTAINER_NAME ) > /dev/null 2>&1 ; then \
@@ -57,7 +94,7 @@ remove-llama-stack-container: ## Remove llama-stack container (saves logs first)
5794 echo " ✓ Container removed (logs saved to /tmp/llama-stack-last-run.log)" ; \
5895 fi
5996
60- start-llama-stack-container : build-llama-stack-image # # Start llama-stack container
97+ start-llama-stack-container : remove-llama-stack-container build-llama-stack-image # # Start llama-stack container
6198 @echo " Starting llama-stack container..."
6299 $(CONTAINER_RUNTIME ) run -d \
63100 --name $(LLAMA_STACK_CONTAINER_NAME ) \
@@ -122,11 +159,16 @@ wait-for-llama-stack-health: ## Wait for llama-stack container to be healthy
122159 $(CONTAINER_RUNTIME ) logs $(LLAMA_STACK_CONTAINER_NAME ) ; \
123160 exit 1
124161
125- clean-llama-stack : remove-llama-stack-container # # Remove container and image
162+ clean-llama-stack : remove-llama-stack-container # # Remove containers, images, and deps hash
126163 @if [ -n " $( CONTAINER_RUNTIME) " ] && $(CONTAINER_RUNTIME ) images -q $(LLAMA_STACK_IMAGE ) | grep -q . ; then \
127- echo " Removing llama-stack image..." ; \
164+ echo " Removing llama-stack app image..." ; \
128165 $(CONTAINER_RUNTIME ) rmi $(LLAMA_STACK_IMAGE ) ; \
129166 fi
167+ @if [ -n " $( CONTAINER_RUNTIME) " ] && $(CONTAINER_RUNTIME ) images -q $(LLAMA_STACK_DEPS_IMAGE ) | grep -q . ; then \
168+ echo " Removing llama-stack deps image..." ; \
169+ $(CONTAINER_RUNTIME ) rmi $(LLAMA_STACK_DEPS_IMAGE ) ; \
170+ fi
171+ @rm -f $(DEPS_HASH_FILE )
130172
131173run-llama-stack : # # Start Llama Stack with enriched config (for local service mode)
132174 uv run src/llama_stack_configuration.py -c $(CONFIG ) -i $(LLAMA_STACK_CONFIG ) -o $(LLAMA_STACK_CONFIG ) && \
0 commit comments