Prechádzať zdrojové kódy

[#1] docs: update README.md grading criteria, add Technical Document and User Manual, fix app.py version parsing

Lange François 3 týždňov pred
rodič
commit
6080faa196

+ 4 - 3
.gitattributes

@@ -7,14 +7,14 @@
 # git config filter.ident-dynamic.smudge '
 #   proj=$(basename "$(git rev-parse --show-toplevel)");
 #   file="%f";
-#   perl -pe "s|\\\$Format:PROJECT_NAME:FILE_NAME:(.*?)\\\$|\\\$Format:\$proj:\$file:\$1\\\$|g" | \
+#   perl -pe "s|\\\$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$|\\\$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$proj:\$file:\$1\\\$|g" | \
 #   git archive --subst-vars | cat
 # '
 # 
 # # 3. Configurer le filtre "Clean" (Nettoyage avant le commit pour éviter les conflits)
 # # The LEFT PART OF THE PIPE MUST BE "$Format:PROJECT_NAME:FILE_NAME"
 # git config filter.ident-dynamic.clean '
-#   perl -pe "s|\\\$Format:[^:]+:[^:]+(:.*?)\\\$|\\\$Format:PROJECT_NAME:FILE_NAME\$1\\\$|g"
+#   perl -pe "s|\\\$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$|\\\$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$1\\\$|g"
 # '
 # 
 # 1. Protection du script de filtre pour Unix/WSL
@@ -25,7 +25,8 @@
 *.bat filter=ident-dynamic eol=crlf
 
 # Git filter configurations for dynamic identifiers
-git-ident-filter.py text eol=lf
+.gitattributes filter=ident-dynamic
+local_tools/git-ident-filter.py filter=ident-dynamic eol=lf
 *.md filter=ident-dynamic
 *.py filter=ident-dynamic
 *.sh filter=ident-dynamic

BIN
Project.pdf


+ 16 - 1
README.md

@@ -38,4 +38,19 @@ This project leverages specialized AI skills to maintain code quality, documenta
 - **Git Commit**: Enforces strict Git governance, Taiga tracking (`TG-123`), and a single `main` branch workflow. For every commit, a task in Taiga must be associated. If the task does not exist, it must be created and added to a user story and a sprint.
 - **Refactor Coach**: Refactors code to improve readability, performance, and modularity without changing external behavior.
 - **SQL Optimizer**: Enforces DBA standards for MySQL, Oracle, and PostgreSQL, ensuring proper indexing, transaction management, and secure access.
-- **Test Generator**: Generates comprehensive unit and integration tests focusing on boundary conditions and logical coverage.
+- **Test Generator**: Generates comprehensive unit and integration tests focusing on boundary conditions and logical coverage.
+
+## Grading
+There will be 6 grades in total: 3 for Project Management 1 (PM1) and 3 for Domain-specifc Project 1 (DSP1).
+
+### PM1:
+* Requirements analysis and assessment.
+* Overall project planning and execution.
+* Project presentation.
+
+### DSP1:
+* The final product shipped to the customer.
+* The product documentation:
+  * **Technical document**, explaining how to install and configure the final product as well as the technologies used (LLM, DB, etc.) for an IT audience. Explain which Antigravity models you used for which tasks as well as how and why you configured agent permissions. Also reflect on what Antigravity struggled with and you handled this. Explain which local LLM the app uses and why. Explain the app infrastructure via a diagram showing how the app components communicate locally. Explain how you've verified that no user data leaves the server.
+  * **User manual**, explaining how to use the final product from an end user (non developer) perspective.
+* The presentation to the customer.

BIN
Retro Planning.pdf


+ 6 - 12
app.py

@@ -2,7 +2,7 @@
 # $Id$
 # $Author$
 # $log$
-#ident "@(#)LocalFoodAI:app.py:$Format:%D:%ci:%cN:%h$"
+#ident "@(#)LocalFoodAI:app.py:$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
 #ident "@(#)$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
 import streamlit as st
 import extra_streamlit_components as stx
@@ -410,13 +410,13 @@ def render_version():
                     line = f.readline()
                     if not line:
                         break
-                    if "$Form" + "at:LocalFoodAI:app.py:" in line:
-                        match = re.search(r'\$For' + r'mat:LocalFoodAI:app\.py:(.*?)\$', line)
+                    if "$Form" + "at:" in line:
+                        match = re.search(r'\$For' + r'mat:[^:]+:[^:]+:(.*?)\$', line)
                         if match:
                             parts = match.group(1).split(':')
-                            if len(parts) >= 7 and not parts[0].startswith('%an'):
-                                git_version = parts[5] # %cd (committer date)
-                                git_hash = parts[6][:7] if parts[6] else ""
+                            if len(parts) >= 11 and not parts[0].startswith('%an'):
+                                git_version = f"{parts[7]}:{parts[8]}:{parts[9]}" # %cd (committer date)
+                                git_hash = parts[10][:7] if parts[10] else ""
                                 break
     except Exception:
         pass
@@ -435,12 +435,6 @@ def render_version():
         except Exception:
             pass
 
-    # 3. Default fallback values
-    if not git_version:
-        git_version = "2026/06/11 08:26:59"
-    if not git_hash:
-        git_hash = "1701828"
-
     st.caption(f"🚀 Version: {git_version}")
     st.caption(f"📅 Git ID: {git_version} {git_hash}")
     st.caption(f"Model: {get_active_model()}")

BIN
docs/Backup_Procedure.pdf


BIN
docs/Data_Ingestion.pdf


BIN
docs/Final_Report.pdf


BIN
docs/Installation_Guide.pdf


BIN
docs/Operator_Installation_Guide.pdf


BIN
docs/Scrum_Artifacts.pdf


BIN
docs/Scrum_Daily.pdf


BIN
docs/Scrum_Plan.pdf


BIN
docs/Scrum_Retro.pdf


BIN
docs/Scrum_Review.pdf


BIN
docs/Scrum_Wiki.pdf


BIN
docs/Start_Stop_Procedures.pdf


+ 186 - 0
docs/Technical_Document.md

@@ -0,0 +1,186 @@
+#ident "@(#)$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+# Local Food AI - Capstone Technical Document
+
+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.
+
+---
+
+## 1. System Overview & Technologies Used
+
+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.
+
+### Technology Stack
+* **Frontend Web UI**: Streamlit (Python) - hosts search tabs, plate builder, and RAG chat portal.
+* **Database**: MySQL 8.0 - stores OpenFoodFacts records with dynamic vertical partitioning.
+* **Database Migrations**: Alembic - automates schema migrations and relational view definitions.
+* **AI NLP Inference Engine**: Ollama (locally hosted daemon) - runs quantized local models.
+* **Private Web Meta-Search**: SearXNG - provides anonymous web search fallback without cookies or tracking.
+* **Observability Suite**: Zabbix (Server, Web UI, and Agent) - captures SNMP telemetry, custom application traps, and status loops.
+* **Web Server Proxy Gateway**: Nginx - acts as a secure reverse proxy on standard network Port 80.
+* **Task Pipelines**: Apache Airflow - schedules and monitors data ingestion flows.
+
+---
+
+## 2. Dynamic Component Infrastructure Diagram
+
+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.
+
+```mermaid
+flowchart TD
+    subgraph "Client Layer"
+        Browser["Clinician Browser"]
+    end
+
+    subgraph "Gateway & Application Nodes"
+        Nginx["Nginx Reverse Proxy\n(Port 80)"]
+        Streamlit["Streamlit Web App\n(Port 8502 / Docker Container)"]
+    end
+
+    subgraph "Intelligence & Search Nodes"
+        Ollama["Ollama Daemon\n(Port 11434 / Docker Container)"]
+        SearXNG["SearXNG Meta-Search\n(Port 8085 / Docker Container)"]
+    end
+
+    subgraph "Data Storage & Observability Nodes"
+        MySQL["MySQL Database Server\n(Port 3306 / Docker Container)"]
+        Zabbix["Zabbix Server & Agent\n(Ports 10051 & 10050)"]
+        ZabbixWeb["Zabbix Web Dashboard\n(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
+```
+
+---
+
+## 3. Installation & Configuration Guide
+
+To deploy the Local Food AI system, follow the sequential commands below:
+
+### 3.1 Prerequisite Environment Setup
+The notebook workstation must have at least 16 GB of RAM, Docker, and Docker Compose installed.
+
+### 3.2 Dynamic Double-Mode Configuration
+1. **Host Environment File (`.env`)**:
+   Configure database credentials, active network mode, and the target model name:
+   ```ini
+   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
+   ```
+
+2. **Compose Topology Mappings**:
+   The `app` container maps the host's `.env` config file dynamically using environment bindings and volume mounts inside [docker-compose.yml](file:///c:/Users/lanfr144/Documents/DOPRO1/Antigravity/Food/docker-compose.yml):
+   ```yaml
+     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
+   ```
+
+### 3.3 Execution Commands
+* **Production Build & Launch**:
+  ```bash
+  docker compose up -d --build
+  ```
+* **Offline Local Fallback Build & Launch**:
+  ```bash
+  docker compose -f docker-compose_skip.yml up -d --build
+  ```
+* **Sequential Shutdown & Restart (Safe Ordering)**:
+  Run the sequential operations script to prevent dependency hangs:
+  ```bash
+  chmod +x manage_services.sh
+  ./manage_services.sh restart
+  ```
+
+---
+
+## 4. Antigravity Models, Agent Tasks & Permissions
+
+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.
+
+### 4.1 Antigravity Models & Task Domains
+* **Code Review Subagent**: Analyzed pull requests and code modifications in `app.py`, identifying structural vulnerabilities and syntax errors.
+* **Doc Writer Subagent**: Maintained and generated the markdown manuals inside the `docs/` folder, ensuring they stayed synchronized with file changes.
+* **Expert Coach Subagent**: Guided architectural patterns, enforced optimal EAV vertical partitioning schemas in MySQL, and checked the validity of `$Format:` dynamic headers.
+* **Git Commit Governance Subagent**: Linked repository commits directly to the Taiga task board using strict Taiga hooks and validated task creation.
+* **SQL Optimizer Subagent**: Reviewed indices, FULLTEXT query structures, and partitioning tables to prevent Cartesian query time increases.
+
+### 4.2 Agent Permissions Configuration
+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.
+
+---
+
+## 5. Reflections: Engineering Struggles & Solutions
+
+During the deployment and configuration phases, the Antigravity agent encountered several technical struggles, which were successfully resolved as follows:
+
+### 5.1 Regex Greediness Corrupting Python Literals
+* **The Struggle**: The dynamic git filter `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`.
+* **The Resolution**:
+  1. We modified the pattern in the filter to be line-restricted (`[^\r\n$]+\$`), ensuring it never matches across newline boundaries.
+  2. We split the string literal searches inside `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.
+
+### 5.2 Git Checkout Filter Self-Mod Loops
+* **The Struggle**: When performing cache resets or major checkouts, Git deleted `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.
+* **The Resolution**: We separated the checkout process by checking out the filter script first (`git checkout HEAD -- local_tools/git-ident-filter.py`), and then executing checkout on the rest of the repository.
+
+### 5.3 Character Encoding Conflicts
+* **The Struggle**: French accent characters (such as `ç` 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.
+* **The Resolution**: We built custom Python encoding sanitizer scripts that opened markdown and python files with `errors='replace'`, stripped out replacement characters, and forced them to overwrite as clean UTF-8 strings.
+
+---
+
+## 6. Local LLM Rationale
+
+The Local Food AI system is configured to run **`llama3.2:3b`** (quantized 3-Billion parameter Llama 3.2 model) natively using Ollama.
+
+### Rationale
+1. **Hardware Memory Footprint**: The model utilizes 4-bit quantization, requiring roughly 2.2 GB of RAM. This fits comfortably inside the minimal hardware constraint (16 GB total notebook memory) alongside the MySQL and Zabbix containers.
+2. **Clinical Dialogue Proficiency**: Despite its small size, Llama 3.2 is highly optimized for instruction-following and tool-calling. This allows the Streamlit app to reliably execute RAG lookups (generating SQL queries or meta-search requests) and format responses using clinical CoT templates.
+3. **Completely Local Inference**: The model runs entirely inside the `food-ollama-1` container on the local network, bypassing any latency or dependency associated with commercial cloud models.
+
+---
+
+## 7. Data Privacy Verification: Keeping User Data on the Server
+
+To prove and guarantee that no clinical user details or dietary profiles leave the local server boundary, we executed the following verification procedures:
+
+1. **Proxy Access Log Audits**:
+   Audited Nginx (`/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`).
+2. **Network Egress Block (Docker Configuration)**:
+   The `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.
+3. **Private Web Meta-Search (SearXNG)**:
+   The SearXNG meta-search container redirects external queries locally. Standard search APIs route traffic anonymously through local proxy rotators to prevent search engines from linking queries to the clinician's IP or user profile.
+4. **Traffic Sniffing (TCPDump Verification)**:
+   We ran `tcpdump` on the server interface during active chat sessions:
+   ```bash
+   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.

BIN
docs/Technical_Document.pdf


BIN
docs/Test_Cases_Sprint8.pdf


BIN
docs/User_Description.pdf


+ 65 - 8
docs/User_Guide.md

@@ -1,11 +1,68 @@
-# $Id: 03cbc893f143c3ae43fc35e97913bedb89b41e23 Lange François lanfr144@school.lu 2026/06/11 10:38:26 Lange François lanfr144@school.lu 2026/06/11 10:38:26   [#1] chore: fix git-ident-filter self-modification regex bug by concatenating search strings [PreRelease-1.0-28-g03cbc89] $
-# User Guide
+#ident "@(#)$Format:LocalFoodAI:app.py:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+# Local Food AI - Clinician User Manual
 
-## 1. Clinical Data Search
-Search for products using keywords. The system utilizes FULLTEXT matching to instantly return the top 10 relevant matches alongside macronutrient data.
+Welcome to the **Local Food AI** clinical dietitian explorer. This guide explains how to use the platform to search for products, build custom recipe plates, calculate cumulative nutritional statistics, and consult the privacy-safe AI assistant.
 
-## 2. My Plate Builder
-Add portion sizes of different foods to calculate cumulative nutritional intake. Use the 🗑️ icon to remove items.
+---
 
-## 3. Chat with AI
-Ask the `qwen2.5:7b` model complex dietary questions. It natively utilizes RAG Tool Calling to silently search the database and formulate clinical answers.
+## 1. Accessing the Application
+
+To access the platform on your local network:
+1. Open your web browser (Chrome, Firefox, or Safari).
+2. Enter the host address provided by your IT administrator (e.g., `http://192.168.130.170:8502/` or `http://localhost:8502/`).
+3. You will be greeted by the secure login screen.
+
+---
+
+## 2. Account Login & Security
+
+To protect patient information, the system requires credentials:
+* **Login**: Enter your standard clinician username and password.
+* **Request Reset**: If you have forgotten your password, select **Reset Password** in the sidebar. Enter your username, and a secure password recovery link will be dispatched to your registered email.
+* **Active Session**: The application uses secure local browser cookies to retain your login session for a convenient experience. Select **Logout** in the sidebar at any time to terminate your session.
+
+---
+
+## 3. Sidebar Features & Controls
+
+The left-hand sidebar houses several global settings:
+* **Network Status**: Visual indicator of whether you are in *Online/Server* mode or *Offline/Local Fallback* mode.
+* **LLM Engine Status**: Displays the active local AI model being queried (e.g., `llama3.2:3b`).
+* **Active User Info**: Shows the logged-in clinician profile.
+* **Dynamic Version Header**: Displays the system Git version, date, and commit code for auditable change management.
+
+---
+
+## 4. Feature Guides
+
+The application dashboard is split into three interactive workspace tabs:
+
+### 4.1. Clinical Data Search Tab 🔍
+Use this tab to browse the local OpenFoodFacts food database.
+1. **Keyword Input**: Type a product name, brand, or barcode (e.g., "whole wheat bread" or "unpasteurized cheese").
+2. **Dynamic Results**: The database performs a rapid search, displaying the top 10 matched products.
+3. **Nutritional Score**: Shows the Nutri-Score grade (A to E) and details (Proteins, Carbs, Fats, Energy in kcal) per 100g.
+4. **Allergen Warnings**: Shows highlight flags if the product contains common allergens matching your client's needs.
+
+### 4.2. My Plate Builder Tab 🍽️
+Build custom meals or recipe portions to calculate total client nutritional intake.
+1. **Adding Items**: When browsing foods in the Search Tab, click **Add to Plate**.
+2. **Specifying Portions**: Input the quantity using either decimal weights (in grams) or common volume descriptors (e.g., "1.5 cups", "2 tablespoons"). The converter translates volume to metric weight based on the product density.
+3. **Cumulative Intake Table**: The tab renders a table summarizing individual macros and total energy.
+4. **Visual Metrics**: Renders a dynamic bar chart comparing Carbs, Proteins, and Fats against recommended clinical intake thresholds.
+5. **Editing the Plate**: Use the trash bin icon (🗑️) to instantly remove any item from the calculation.
+
+### 4.3. Consultation Chat Tab 💬
+Consult the built-in clinical AI dietitian assistant for recipe validation, medical profile warnings, and meal plans.
+1. **Client Profile Selection**: Select active dietary constraints (e.g., pregnancy, diabetes, kidney disease, vegetarian) in the dropdown.
+2. **Asking Questions**: Type your prompt (e.g., "Is unpasteurized brie cheese safe for a pregnant client?" or "Design a low-sodium, high-protein menu").
+3. **RAG-Augmented Output**: The local AI assistant automatically searches the SQL database to fetch exact ingredient and macro rows before writing its response.
+4. **Chain-of-Thought Explanation**: The AI displays its reasoning process step-by-step to explain how it formulated the final diet recommendation or safety warning.
+
+---
+
+## 5. Privacy and Offline Support
+
+Because patient privacy is critical:
+* **No Cloud Overhead**: All search strings, chat prompts, and plate records are processed locally inside the host node.
+* **Safe External Searches**: When asking about foods not indexed in the database, the AI queries a local private search wrapper (SearXNG) that strips metadata and cookies, ensuring no identifying queries are sent to external web engines.

BIN
docs/User_Guide.pdf


BIN
docs/WSL_Deployment.pdf


BIN
docs/Wiki_Home.pdf


BIN
docs/architecture.pdf


BIN
docs/disaster_recovery_plan.pdf


BIN
docs/distributed_deployment.pdf


BIN
docs/docker_connection.pdf


BIN
docs/project_report.pdf


BIN
docs/retro_planning.pdf


BIN
docs/taiga_audit_report.pdf


BIN
docs/zabbix_monitoring.pdf