Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 58 additions & 44 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
.PHONY: help build up down logs shell exec pull-model test clean fireform logs-app logs-ollama logs-frontend super-clean
.PHONY: help init fireform build up down logs logs-app logs-ollama shell pull-model test clean super-clean

# The extraction model pulled into Ollama and used by src/llm.py. Override with
# `make pull-model OLLAMA_MODEL=...`. A 1.5B model keeps per-field fills fast.
OLLAMA_MODEL ?= qwen2.5:1.5b
COMPOSE = docker compose -f docker/dev/compose.yml --env-file docker/.env.dev
ENV_DEV = docker/.env.dev

# Read OLLAMA_MODEL from .env.dev at runtime; fall back to default if file absent.
OLLAMA_MODEL = $(shell grep -E '^OLLAMA_MODEL=' $(ENV_DEV) 2>/dev/null | cut -d= -f2 | tr -d '[:space:]' || echo qwen2.5:1.5b)

help:
@printf '%s\n' \
Expand All @@ -13,72 +15,84 @@ help:
'/_/ /_//_/ \___/ /_/ \____/_/ /_/ /_/ /_/ ' \
''
@echo ""
@echo "Fireform Development Commands"
@echo "FireForm Development Commands"
@echo "=============================="
@echo "make fireform - Build and start containers, then open a shell"
@echo "make init - First-time setup: check deps, create .env.dev, pick model"
@echo "make fireform - Build images, start containers, pull Ollama model"
@echo "make build - Build Docker images"
@echo "make up - Start all containers"
@echo "make up - Start all containers (detached)"
@echo "make down - Stop all containers"
@echo "make logs - View container logs"
@echo "make logs-app - View API container logs"
@echo "make logs-frontend - View frontend container logs"
@echo "make logs-ollama - View Ollama container logs"
@echo "make shell - Open Python shell in app container"
@echo "make exec - Execute Python script in container"
@echo "make pull-model - Pull the extraction model ($(OLLAMA_MODEL)) into Ollama"
@echo "make test - Run tests"
@echo "make clean - Remove containers"
@echo "make super-clean - [CAUTION] Use carefully. Cleans up ALL stopped containers, networks, build cache..."

# Fix #382 — pull-model is now part of the main setup flow
# The extraction model is pulled automatically before you need it
fireform: build up pull-model
@echo "make logs - Stream all container logs"
@echo "make logs-app - Stream app container logs"
@echo "make logs-ollama - Stream Ollama container logs"
@echo "make shell - Open shell in running app container"
@echo "make pull-model - Pull Ollama model from .env.dev ($(OLLAMA_MODEL))"
@echo "make test - Run test suite"
@echo "make clean - Stop containers (preserves volumes)"
@echo "make super-clean - [CAUTION] Stop containers, delete volumes, prune Docker"

init:
@chmod +x scripts/check-deps.sh scripts/init-env.sh scripts/select-model.sh
@sh scripts/check-deps.sh
@sh scripts/init-env.sh
@sh scripts/select-model.sh
@printf "Build containers and pull model now? [y/N] "; \
read answer; \
case "$$answer" in \
[yY]*) $(MAKE) fireform ;; \
*) echo "Run 'make fireform' when ready." ;; \
esac

fireform: build up
@printf "Waiting for Ollama to be ready..."
@until $(COMPOSE) exec -T ollama ollama list > /dev/null 2>&1; do \
printf '.'; sleep 2; \
done
@echo " ready."
@if $(COMPOSE) exec -T ollama ollama list 2>/dev/null | grep -q "^$(OLLAMA_MODEL)"; then \
echo " Model $(OLLAMA_MODEL) already pulled."; \
else \
echo " Pulling $(OLLAMA_MODEL)..."; \
$(COMPOSE) exec -T ollama ollama pull $(OLLAMA_MODEL); \
fi
@echo ""
@echo "✅ FireForm is ready!"
@echo " Frontend: http://localhost:5173"
@echo "FireForm is ready!"
@echo " API: http://localhost:8000"
@echo " API Docs: http://localhost:8000/docs"
@echo ""
@echo "Run 'make logs' to view live logs, 'make down' to stop."

build:
docker compose build
@$(COMPOSE) build --progress=quiet

up:
docker compose up -d
@$(COMPOSE) up -d

down:
docker compose down
@$(COMPOSE) down --remove-orphans

logs:
docker compose logs -f
@$(COMPOSE) logs -f

logs-app:
docker compose logs -f app
@$(COMPOSE) logs -f app

logs-ollama:
docker compose logs -f ollama

logs-frontend:
docker compose logs -f frontend
@$(COMPOSE) logs -f ollama

shell:
docker compose exec app /bin/bash

# Start the FastAPI server inside the running container
run:
docker compose exec app uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

@$(COMPOSE) exec app /bin/sh

pull-model:
docker compose exec ollama ollama pull $(OLLAMA_MODEL)
@$(COMPOSE) exec -T ollama ollama pull $(OLLAMA_MODEL)

# Fix — correct test directory (was src/test/ which doesn't exist)
test:
docker compose exec app python3 -m pytest tests/ -v
@$(COMPOSE) exec -T app python3 -m pytest tests/ -v

clean:
docker compose down -v
@$(COMPOSE) down

super-clean:
docker compose down -v
docker system prune
@echo "WARNING: this will delete all volumes (database, uploads, model weights)."
@$(COMPOSE) down -v
@docker system prune -f
51 changes: 51 additions & 0 deletions scripts/check-deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/sh
set -e

PASS=0
FAIL=1
errors=0

check() {
label="$1"
shift
if "$@" > /dev/null 2>&1; then
echo " [ok] $label"
else
echo " [!!] $label"
errors=$((errors + 1))
fi
}

echo ""
echo "Checking dependencies..."
echo "========================"

# Docker daemon running
check "Docker daemon is running" docker info

# docker compose v2 (plugin form, not legacy docker-compose)
check "docker compose v2 available" docker compose version

# Minimum Docker version: 24 (BuildKit cache mounts stable)
DOCKER_VERSION=$(docker version --format '{{.Server.Version}}' 2>/dev/null | cut -d. -f1)
if [ -n "$DOCKER_VERSION" ] && [ "$DOCKER_VERSION" -ge 24 ] 2>/dev/null; then
echo " [ok] Docker version >= 24 (found $(docker version --format '{{.Server.Version}}' 2>/dev/null))"
else
echo " [!!] Docker version >= 24 required (found $(docker version --format '{{.Server.Version}}' 2>/dev/null || echo 'unknown'))"
echo " BuildKit cache mounts in docker/dev/Dockerfile require Docker 24+."
errors=$((errors + 1))
fi

echo ""

if [ "$errors" -gt 0 ]; then
echo "$errors check(s) failed. Fix the above before continuing."
echo ""
echo " Install Docker: https://docs.docker.com/get-docker/"
echo " Upgrade Docker Desktop: https://docs.docker.com/desktop/release-notes/"
echo ""
exit 1
fi

echo "All checks passed."
echo ""
35 changes: 35 additions & 0 deletions scripts/init-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/sh
set -e

ENV_EXAMPLE="docker/.env.example"
ENV_DEV="docker/.env.dev"

echo ""
echo "Setting up environment..."
echo "========================="

if [ ! -f "$ENV_EXAMPLE" ]; then
echo "Error: $ENV_EXAMPLE not found. Are you running from the repo root?"
exit 1
fi

if [ -f "$ENV_DEV" ]; then
printf " %s already exists. Overwrite? [y/N] " "$ENV_DEV"
read -r answer
case "$answer" in
[yY]*)
cp "$ENV_EXAMPLE" "$ENV_DEV"
echo " Overwritten."
;;
*)
echo " Kept existing $ENV_DEV."
;;
esac
else
cp "$ENV_EXAMPLE" "$ENV_DEV"
echo " Created $ENV_DEV from $ENV_EXAMPLE."
fi

echo ""
echo " Review docker/.env.dev and adjust values if needed before running 'make fireform'."
echo ""
107 changes: 107 additions & 0 deletions scripts/select-model.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/bin/sh
set -e

ENV_DEV="docker/.env.dev"
COMPOSE="docker compose -f docker/dev/compose.yml --env-file $ENV_DEV"

# model name | approx size
MODELS="qwen2.5:1.5b|~1GB qwen2.5:3b|~2GB qwen2.5:7b|~4GB llama3.2:3b|~2GB mistral:7b|~4GB"

current_model=""
if [ -f "$ENV_DEV" ]; then
current_model=$(grep -E '^OLLAMA_MODEL=' "$ENV_DEV" | cut -d= -f2 | tr -d '[:space:]')
fi

echo ""
echo "Select Ollama model"
echo "==================="
[ -n "$current_model" ] && echo " Current: $current_model"
echo ""

i=1
for entry in $MODELS; do
name=$(echo "$entry" | cut -d'|' -f1)
size=$(echo "$entry" | cut -d'|' -f2)
if [ "$name" = "${current_model}" ]; then
echo " $i) $name $size [current]"
else
echo " $i) $name $size"
fi
i=$((i + 1))
done
echo " $i) Enter custom model name"
i=$((i + 1))
echo " $i) Keep current"
echo ""
printf "Choice [1-$i]: "
read -r choice

total=$(echo "$MODELS" | wc -w | tr -d '[:space:]')
keep_choice=$((total + 2))
custom_choice=$((total + 1))

if [ "$choice" = "$keep_choice" ] || [ -z "$choice" ]; then
echo " Keeping current model: ${current_model:-qwen2.5:1.5b}"
echo ""
exit 0
fi

if [ "$choice" = "$custom_choice" ]; then
printf " Enter model name (e.g. phi3:mini): "
read -r selected
if [ -z "$selected" ]; then
echo " No model entered. Keeping current."
echo ""
exit 0
fi
selected_size="unknown size"
else
# Validate numeric choice in range
if ! echo "$choice" | grep -qE '^[0-9]+$' || [ "$choice" -lt 1 ] || [ "$choice" -gt "$total" ]; then
echo " Invalid choice. Keeping current model."
echo ""
exit 0
fi
i=1
for entry in $MODELS; do
if [ "$i" = "$choice" ]; then
selected=$(echo "$entry" | cut -d'|' -f1)
selected_size=$(echo "$entry" | cut -d'|' -f2)
fi
i=$((i + 1))
done
fi

# Patch OLLAMA_MODEL in .env.dev
tmp=$(mktemp)
sed "s|^OLLAMA_MODEL=.*|OLLAMA_MODEL=$selected|" "$ENV_DEV" > "$tmp"
mv "$tmp" "$ENV_DEV"
echo ""
echo " OLLAMA_MODEL set to: $selected"

# If container is running, check and optionally pull immediately.
# If not running, the caller (make init) handles the pull prompt.
if $COMPOSE ps ollama 2>/dev/null | grep -q "running"; then
if $COMPOSE exec -T ollama ollama list 2>/dev/null | grep -q "^$selected"; then
echo " Model already pulled. Nothing to download."
echo ""
exit 0
fi

echo ""
printf " Model not yet downloaded ($selected_size). Pull now? [y/N] "
read -r pull_answer
case "$pull_answer" in
[yY]*)
echo ""
$COMPOSE exec -T ollama ollama pull "$selected"
echo ""
echo " Model ready."
;;
*)
echo " Skipped. Run 'make pull-model' when ready."
;;
esac
fi

echo ""