The current version is #ident "@(#)$Format:LocalFoodAI_lanfr144:Technical_Document.md:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
This document provides a comprehensive technical overview of the Local Food AI system. It details the installation and configuration procedures, technologies used, Antigravity agent usage/permissions, agent engineering reflections, local LLM design decisions, local microservice component communication, and data privacy verification.
The Local Food AI system is a privacy-first, locally-hosted clinical dietitian platform. It is designed to run in environments with strict network restrictions (such as clinics or hospitals) while delivering sub-second database lookups and medical advice.
The diagram below represents how the system components communicate locally inside the closed network boundary. All request-response loops are processed within the host server limits.
flowchart TD
subgraph "Client Layer"
Browser["Clinician Browser"]
end
subgraph "Gateway & Application Nodes"
Nginx["Nginx Reverse Proxy
(Port 80)"]
Streamlit["Streamlit Web App
(Port 8502 / Docker Container)"]
end
subgraph "Intelligence & Search Nodes"
Ollama["Ollama Daemon
(Port 11434 / Docker Container)"]
SearXNG["SearXNG Meta-Search
(Port 8085 / Docker Container)"]
end
subgraph "Data Storage & Observability Nodes"
MySQL["MySQL Database Server
(Port 3306 / Docker Container)"]
Zabbix["Zabbix Server & Agent
(Ports 10051 & 10050)"]
ZabbixWeb["Zabbix Web Dashboard
(Port 8081)"]
end
%% Communication paths
Browser -->|HTTP| Nginx
Nginx -->|Reverse Proxy Pass| Streamlit
Streamlit -->|EAV & FULLTEXT SQL queries| MySQL
Streamlit -->|Local Chat Inference / RAG| Ollama
Streamlit -->|Tool-Calling search queries| SearXNG
Streamlit -->|SNMP Traps / Telemetry| Zabbix
ZabbixWeb -->|Queries metrics| Zabbix
To deploy the Local Food AI system, follow the sequential commands below:
The notebook workstation must have at least 16 GB of RAM, Docker, and Docker Compose installed.
Host Environment File (.env):
Configure database credentials, active network mode, and the target model name:
NETWORK_MODE=server
LLM_MODEL=llama3.2:3b
MYSQL_ROOT_PASSWORD=your_db_password_here
DB_READER_PASS=your_db_password_here
DB_LOADER_PASS=your_db_password_here
DB_APP_AUTH_PASS=your_db_password_here
MYSQL_ZABBIX_PASSWORD=your_db_password_here
SERVER_HOST=192.168.130.170
SERVER_USER=francois
SERVER_PASS=your_db_password_here
Compose Topology Mappings:
The app container maps the host's .env config file dynamically using environment bindings and volume mounts inside docker-compose.yml:
app:
build:
context: .
dockerfile: docker/app/Dockerfile
ports:
- "8502:8501"
environment:
- DB_HOST=mysql
- DB_USER=food_reader
- DB_PASS=${DB_READER_PASS}
- LLM_MODEL=${LLM_MODEL}
volumes:
- ./.env:/app/.env
Production Build & Launch:
docker compose up -d --build
Offline Local Fallback Build & Launch:
docker compose -f docker-compose_skip.yml up -d --build
Sequential Shutdown & Restart (Safe Ordering): Run the sequential operations script to prevent dependency hangs:
chmod +x manage_services.sh
./manage_services.sh restart
During the capstone engineering lifecycle, specialized Antigravity models were utilized to orchestrate task domains. To maintain strict repository security, agent permissions were configured with the narrowest scope possible.
app.py, identifying structural vulnerabilities and syntax errors.docs/ folder, ensuring they stayed synchronized with file changes.$Format: dynamic headers.To restrict the agent's capability and protect the developer environment, permissions were set under the following restrictions:
read_file & write_file: Limited exclusively to the workspace directory c:\Users\lanfr144\Documents\DOPRO1\Antigravity\Food (excluding system-level directories like /tmp or .gemini).command (Shell Execution): Sandboxed to standard non-root terminal commands. Command prefixes were limited to git, python, chmod, docker-compose, and Get-Content within the workspace path.read_url & execute_url: Restrained solely to local network nodes (192.168.130.170 for docker orchestration and 192.168.130.161 for Taiga API requests) to prevent external DNS lookups or unauthorized egress.During the deployment and configuration phases, the Antigravity agent encountered several technical struggles, which were successfully resolved as follows:
git-ident-filter.py used a greedy wildcard matching pattern .*?[^$]*?$ which matched across lines. During checkouts, this matched from the $Format: string literal on line 403 of app.py directly to the regex search string on line 404, corrupting the code block into a single invalid tag and triggering a SyntaxError: unterminated string literal.[^
$]+\$), ensuring it never matches across newline boundaries.app.py so they are physically split across concatenated strings (e.g. "$Form" + "at:"), which prevents the filter from ever matching the source code strings.local_tools/git-ident-filter.py from the disk. When git began restoring other files, it attempted to call the smudge filter, but since the script was missing, Python threw file-not-found errors and checkouts failed.git checkout HEAD -- local_tools/git-ident-filter.py), and then executing checkout on the rest of the repository.ç in Lange François) in the smudged Git headers were written using different system encoding tables. Python's default text readers choked on these characters with decode errors, blocking file writes.errors='replace', stripped out replacement characters, and forced them to overwrite as clean UTF-8 strings.The Local Food AI system is configured to run llama3.2:3b (quantized 3-Billion parameter Llama 3.2 model) natively using Ollama.
food-ollama-1 container on the local network, bypassing any latency or dependency associated with commercial cloud models.To prove and guarantee that no clinical user details or dietary profiles leave the local server boundary, we executed the following verification procedures:
/var/log/nginx/access.log) and Streamlit access logs. All connections originate exclusively from local subnet IPs (e.g., 192.168.1.50 or loopback 127.0.0.1).mysql and app services inside docker-compose.yml run inside a custom bridge network. The database container has no external port bindings to the public internet, and the app container only exposes port 8502 to the local LAN.Traffic Sniffing (TCPDump Verification):
We ran tcpdump on the server interface during active chat sessions:
tcpdump -i eth0 dst port not 80 and dst port not 22 and dst port not 161
No packet transmissions were detected routing data outside the local network, proving that LLM prompts, dietitian responses, and plate nutritional configurations remain entirely inside the local node boundary.