commit 18aea8cef9ffcaf03bd611a3bc59365d3c13d89f parent 70b8c766f549dd981c396889ef97ebfdc3ef05cb Author: arnav0103 <66205884+arnav0103@users.noreply.github.com> Date: Sun, 29 Mar 2026 18:50:24 +0530 Merge branch 'main' of https://github.com/arnav0103/demeter Diffstat:
29 files changed, 96 insertions(+), 284 deletions(-)
diff --git a/assets/screenshots/Alerts.png b/assets/screenshots/Alerts.png Binary files differ. diff --git a/assets/screenshots/Analytics.png b/assets/screenshots/Analytics.png Binary files differ. diff --git a/assets/screenshots/CropDetailsLog.png b/assets/screenshots/CropDetailsLog.png Binary files differ. diff --git a/assets/screenshots/CropDetailsOverview.png b/assets/screenshots/CropDetailsOverview.png Binary files differ. diff --git a/assets/screenshots/Dashboard.png b/assets/screenshots/Dashboard.png Binary files differ. diff --git a/assets/screenshots/Help.png b/assets/screenshots/Help.png Binary files differ. diff --git a/assets/screenshots/Hindi.png b/assets/screenshots/Hindi.png Binary files differ. diff --git a/assets/screenshots/Intelligence.png b/assets/screenshots/Intelligence.png Binary files differ. diff --git a/assets/screenshots/landing_page.png b/assets/screenshots/Landing.png Binary files differ. diff --git a/assets/screenshots/LightMode.png b/assets/screenshots/LightMode.png Binary files differ. diff --git a/assets/screenshots/Onboarding1.png b/assets/screenshots/Onboarding1.png Binary files differ. diff --git a/assets/screenshots/Onboarding2.png b/assets/screenshots/Onboarding2.png Binary files differ. diff --git a/assets/screenshots/RunCycle.png b/assets/screenshots/RunCycle.png Binary files differ. diff --git a/assets/screenshots/console_log.png b/assets/screenshots/console_log.png Binary files differ. diff --git a/backend/node_server/index.js b/backend/node_server/index.js @@ -6,6 +6,9 @@ const { initDB, connectMongoDB } = require("./config/db"); const farmRoutes = require("./routes/farmRoutes"); const cropRoutes = require("./routes/cropRoutes"); +const dns = require("node:dns/promises"); +dns.setServers(["1.1.1.1"]); + const app = express(); const PORT = process.env.PORT || 3001; diff --git a/frontend/src/assets/basil.jpg b/frontend/src/assets/basil.jpg Binary files differ. diff --git a/frontend/src/assets/lettuce.jpg b/frontend/src/assets/lettuce.jpg Binary files differ. diff --git a/frontend/src/assets/strawberry.jpg b/frontend/src/assets/strawberry.jpg Binary files differ. diff --git a/frontend/src/assets/tomato.jpg b/frontend/src/assets/tomato.jpg Binary files differ. diff --git a/frontend/src/pages/Dashboard.jsx b/frontend/src/pages/Dashboard.jsx @@ -37,6 +37,10 @@ import { EmptyState, LoadingShimmer, } from "../components/ui"; +import tomatoImg from "../assets/tomato.jpg"; +import basilImg from "../assets/basil.jpg"; +import strawberryImg from "../assets/strawberry.jpg"; +import lettuceImg from "../assets/lettuce.jpg"; const STAGES_KEYS = [ "stage_all", @@ -398,14 +402,10 @@ export default function Dashboard() { const getImg = (name) => { if (!name) return null; const n = name.toLowerCase(); - if (n.includes("tomato")) - return "https://images.unsplash.com/photo-1571680322279-a226e6a4cc2a?q=80&w=400"; - if (n.includes("basil")) - return "https://images.unsplash.com/photo-1618375569909-3c8616cf7733?q=80&w=400"; - if (n.includes("strawberry")) - return "https://images.unsplash.com/photo-1677694682771-f2a1eaa7b8d9?q=80&w=400"; - // Default: lettuce - return "https://images.unsplash.com/photo-1622206151226-18ca2c9ab4a1?q=80&w=400"; + if (n.includes("tomato")) return tomatoImg; + if (n.includes("basil")) return basilImg; + if (n.includes("strawberry")) return strawberryImg; + return lettuceImg; }; useEffect(() => { @@ -423,7 +423,7 @@ export default function Dashboard() { cropId: p.crop_id || "-", name: p.crop || t("common_unknown"), statusMsg: rawStage || t("dash_status_growing"), - image: p.image_url || getImg(p.crop), + image: getImg(p.crop) || p.image_url, status: deriveCropStatus(p), maturity: calculateMaturity(p), harvestReady: isReadyToHarvest(p), diff --git a/frontend/src/pages/RunCycle.jsx b/frontend/src/pages/RunCycle.jsx @@ -1009,8 +1009,11 @@ export default function RunCycle() { > <div style={{ display: "flex", alignItems: "center", gap: 8 }}> <div className="section-label"> - phase === "running" ? t("add_log_live") : phase === "done" ? - t("add_log_done") : t("add_log_idle") + {phase === "running" + ? t("add_log_live") + : phase === "done" + ? t("add_log_done") + : t("add_log_idle")} </div> {phase === "running" && ( <span @@ -1023,7 +1026,7 @@ export default function RunCycle() { color: "var(--red)", border: "1px solid rgba(248,113,113,0.3)", animation: "pulse 1.5s ease-in-out infinite", - alignSelf: "center", + marginTop: "-12px", }} > {t("run_streaming")} diff --git a/readme.md b/readme.md @@ -11,7 +11,25 @@ Built for the **Microsoft AI Unlocked - AI for India** hackathon, Demeter addres ## Screenshots - +<div align="center"> + <img src="./assets/screenshots/Landing.png" width="900" alt="Landing Page"> + <p><em>Landing Page</em></p> +</div> + +| Dashboard | Analytics | Intelligence | +| :----------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------: | +| <img src="./assets/screenshots/Dashboard.png" width="350" alt="Dashboard"> | <img src="./assets/screenshots/Analytics.png" width="350" alt="Analytics"> | <img src="./assets/screenshots/Intelligence.png" width="350" alt="Intelligence"> | +| **Alerts** | **Run Cycle** | **Hindi Support** | +| <img src="./assets/screenshots/Alerts.png" width="350" alt="Alerts"> | <img src="./assets/screenshots/RunCycle.png" width="350" alt="Run Cycle"> | <img src="./assets/screenshots/Hindi.png" width="350" alt="Hindi Support"> | +| **Crop Details (Overview)** | **Crop Details (Log)** | **Light Mode** | +| <img src="./assets/screenshots/CropDetailsOverview.png" width="350" alt="Crop Details Overview"> | <img src="./assets/screenshots/CropDetailsLog.png" width="350" alt="Crop Details Log"> | <img src="./assets/screenshots/LightMode.png" width="350" alt="Light Mode"> | +| **Onboarding 1** | **Onboarding 2** | | +| <img src="./assets/screenshots/Onboarding1.png" width="350" alt="Onboarding 1"> | <img src="./assets/screenshots/Onboarding2.png" width="350" alt="Onboarding 2"> | | + +<div align="center"> + <img src="./assets/screenshots/Help.png" width="900" alt="Help Section"> + <p><em>Help Page</em></p> +</div> --- @@ -246,88 +264,88 @@ schema_version String (current: "1.2") ``` demeter/ ├── agent/ -│ ├── main_agent.py # Orchestration loop (runs the 7-agent cycle) -│ ├── memory.py # FarmMemory class (Mem0 + Qdrant) +│ ├── main_agent.py # Orchestration loop (runs the 7-agent cycle) +│ ├── memory.py # FarmMemory class (Mem0 + Qdrant) │ ├── guardrails/ -│ │ ├── README.md # Guardrails documentation -│ │ └── validation.py # Input sanitization, bounds checking, injection detection +│ │ ├── README.md # Guardrails documentation +│ │ └── validation.py # Input sanitization, bounds checking, injection detection │ ├── model/ -│ │ └── plant_disease_model.pt # Plant disease detection model +│ │ └── plant_disease_model.pt # Plant disease detection model │ ├── Marl/ -│ │ ├── bandit.py # Contextual Bandit (LinGreedy, 15 arms) -│ │ ├── strategies.py # Strategy definitions -│ │ ├── train-bandit.py # Offline training script +│ │ ├── bandit.py # Contextual Bandit (LinGreedy, 15 arms) +│ │ ├── strategies.py # Strategy definitions +│ │ ├── train-bandit.py # Offline training script │ │ └── model_bandit_greedy.pkl # Trained bandit model weights │ ├── Sentinel/ -│ │ ├── agent.py # FMUBuilder - creates fused vectors -│ │ ├── fmu.py # FMU dataclass +│ │ ├── agent.py # FMUBuilder - creates fused vectors +│ │ ├── fmu.py # FMU dataclass │ │ └── Encoders/ -│ │ ├── Vision.py # CLIP ViT-B/32 image encoder -│ │ └── TimeSeries.py # LSTM-based sensor encoder +│ │ ├── Vision.py # CLIP ViT-B/32 image encoder +│ │ └── TimeSeries.py # LSTM-based sensor encoder │ ├── Qdrant/ -│ │ ├── Client.py # Qdrant client singleton -│ │ ├── Setup.py # Collection initialization -│ │ ├── Store.py # FMU storage helpers -│ │ └── Search.py # Similarity search helpers +│ │ ├── Client.py # Qdrant client singleton +│ │ ├── Setup.py # Collection initialization +│ │ ├── Store.py # FMU storage helpers +│ │ └── Search.py # Similarity search helpers │ ├── sub_agents/ -│ │ ├── base_agent.py # BaseReasoningAgent (Azure OpenAI client) -│ │ ├── fetching_agent.py # FetchingAgent - polls simulator, builds FMU -│ │ ├── judge_agent.py # JudgeAgent - reward evaluation (LangGraph) -│ │ ├── atmospheric_agent.py # AtmosphericAgent - climate planning (LangGraph) -│ │ ├── water_agent.py # WaterAgent - nutrient planning (LangGraph) -│ │ ├── Supervisor.py # SupervisorAgent - strategy + synthesis -│ │ ├── Researcher.py # ResearcherAgent - RAG knowledge retrieval -│ │ ├── Explainer.py # ExplainerAgent - chain-of-thought log generation -│ │ ├── Doctor.py # VisionAgent - plant disease detection (Azure Custom Vision) +│ │ ├── base_agent.py # BaseReasoningAgent (Azure OpenAI client) +│ │ ├── fetching_agent.py # FetchingAgent - polls simulator, builds FMU +│ │ ├── judge_agent.py # JudgeAgent - reward evaluation (LangGraph) +│ │ ├── atmospheric_agent.py # AtmosphericAgent - climate planning (LangGraph) +│ │ ├── water_agent.py # WaterAgent - nutrient planning (LangGraph) +│ │ ├── Supervisor.py # SupervisorAgent - strategy + synthesis +│ │ ├── Researcher.py # ResearcherAgent - RAG knowledge retrieval +│ │ ├── Explainer.py # ExplainerAgent - chain-of-thought log generation +│ │ ├── Doctor.py # VisionAgent - plant disease detection (Azure Custom Vision) │ │ └── water_and_atmospheric_dependencies/ -│ │ ├── state.py # LangGraph AgentState definition -│ │ ├── nodes.py # LangGraph node functions -│ │ ├── tools.py # LangChain tools (calculate_vpd, web_search) -│ │ ├── physics_engine.py# LLM-based plan safety simulator -│ │ └── retrieval.py # LangChain tools (ask_rag, diagnose_plant, ask_memory) +│ │ ├── state.py # LangGraph AgentState definition +│ │ ├── nodes.py # LangGraph node functions +│ │ ├── tools.py # LangChain tools (calculate_vpd, web_search) +│ │ ├── physics_engine.py # LLM-based plan safety simulator +│ │ └── retrieval.py # LangChain tools (ask_rag, diagnose_plant, ask_memory) │ └── tools/ -│ ├── actuation.py # Actuator command builders -│ ├── db_tools.py # Database utility tools -│ ├── processing_tools.py # Sensor processing utilities -│ └── reset_memory.py # Memory reset utility +│ ├── actuation.py # Actuator command builders +│ ├── db_tools.py # Database utility tools +│ ├── processing_tools.py # Sensor processing utilities +│ └── reset_memory.py # Memory reset utility │ ├── backend/ │ ├── server/ -│ │ ├── main.py # FastAPI server (Python) - agent HTTP endpoints -│ │ ├── functions.py # Backend utility functions -│ │ ├── rag_brain.py # PDF ingestion pipeline for Knowledge Base -│ │ ├── create-index.py # Qdrant index setup script -│ │ └── reset-db.py # Database reset utility +│ │ ├── main.py # FastAPI server (Python) - agent HTTP endpoints +│ │ ├── functions.py # Backend utility functions +│ │ ├── rag_brain.py # PDF ingestion pipeline for Knowledge Base +│ │ ├── create-index.py # Qdrant index setup script +│ │ └── reset-db.py # Database reset utility │ └── node_server/ -│ ├── index.js # Express.js server - crop CRUD API + MongoDB init +│ ├── index.js # Express.js server - crop CRUD API + MongoDB init │ ├── routes/ -│ │ ├── farmRoutes.js # Farm/Qdrant history routes -│ │ └── cropRoutes.js # Crop CRUD routes +│ │ ├── farmRoutes.js # Farm/Qdrant history routes +│ │ └── cropRoutes.js # Crop CRUD routes │ ├── controllers/ │ │ ├── farmController.js │ │ └── cropController.js │ ├── schema/ -│ │ └── cropSchema.js # Mongoose schema (v1.2) -│ └── config/db.js # MongoDB + legacy DB connection +│ │ └── cropSchema.js # Mongoose schema (v1.2) +│ └── config/db.js # MongoDB + legacy DB connection │ ├── frontend/ │ ├── src/ -│ │ ├── App.js # Router, providers, onboarding gate -│ │ ├── pages/ # All 10 page components -│ │ ├── components/ # Sidebar, AgentWidgets, Onboarding -│ │ ├── hooks/ # useFarmData, useSettings, useTranslation +│ │ ├── App.js # Router, providers, onboarding gate +│ │ ├── pages/ # All 10 page components +│ │ ├── components/ # Sidebar, AgentWidgets, Onboarding +│ │ ├── hooks/ # useFarmData, useSettings, useTranslation │ │ ├── api/ │ │ │ ├── agentApi.js -│ │ │ └── farmApi.jsx # MongoDB CRUD calls -│ │ ├── utils/ # translations.js, dataUtils.js -│ │ └── data/mockData.js # Mock data for testing +│ │ │ └── farmApi.jsx # MongoDB CRUD calls +│ │ ├── utils/ # translations.js, dataUtils.js +│ │ └── data/mockData.js # Mock data for testing │ └── tailwind.config.js │ ├── simulator/ -│ └── main.py # Multi-batch DigitalTwin fleet + Azure ADT sync +│ └── main.py # Multi-batch DigitalTwin fleet + Azure ADT sync │ -├── yolov8n.pt # Pre-trained YOLOv8 model -├── Knowledge_Base/ # Drop agronomic PDFs here for RAG ingestion +├── yolov8n.pt # Pre-trained YOLOv8 model +├── Knowledge_Base/ # Drop agronomic PDFs here for RAG ingestion ├── requirements.txt └── README.md ``` diff --git a/runs/detect/train/args.yaml b/runs/detect/train/args.yaml @@ -1,108 +0,0 @@ -task: detect -mode: train -model: yolov8n.pt -data: agent/training_data/data.yaml -epochs: 10 -time: null -patience: 100 -batch: 16 -imgsz: 416 -save: true -save_period: -1 -cache: false -device: cpu -workers: 8 -project: null -name: train -exist_ok: false -pretrained: true -optimizer: auto -verbose: true -seed: 0 -deterministic: true -single_cls: false -rect: false -cos_lr: false -close_mosaic: 10 -resume: false -amp: true -fraction: 1.0 -profile: false -freeze: null -multi_scale: 0.0 -compile: false -overlap_mask: true -mask_ratio: 4 -dropout: 0.0 -val: true -split: val -save_json: false -conf: null -iou: 0.7 -max_det: 300 -half: false -dnn: false -plots: true -source: null -vid_stride: 1 -stream_buffer: false -visualize: false -augment: false -agnostic_nms: false -classes: null -retina_masks: false -embed: null -show: false -save_frames: false -save_txt: false -save_conf: false -save_crop: false -show_labels: true -show_conf: true -show_boxes: true -line_width: null -format: torchscript -keras: false -optimize: false -int8: false -dynamic: false -simplify: true -opset: null -workspace: null -nms: false -lr0: 0.01 -lrf: 0.01 -momentum: 0.937 -weight_decay: 0.0005 -warmup_epochs: 3.0 -warmup_momentum: 0.8 -warmup_bias_lr: 0.1 -box: 7.5 -cls: 0.5 -dfl: 1.5 -pose: 12.0 -kobj: 1.0 -rle: 1.0 -angle: 1.0 -nbs: 64 -hsv_h: 0.015 -hsv_s: 0.7 -hsv_v: 0.4 -degrees: 0.0 -translate: 0.1 -scale: 0.5 -shear: 0.0 -perspective: 0.0 -flipud: 0.0 -fliplr: 0.5 -bgr: 0.0 -mosaic: 1.0 -mixup: 0.0 -cutmix: 0.0 -copy_paste: 0.0 -copy_paste_mode: flip -auto_augment: randaugment -erasing: 0.4 -cfg: null -tracker: botsort.yaml -save_dir: C:\Debarghya\IIT Guwahati\Second Year\Sem 4\Convolve\Code\runs\detect\train diff --git a/runs/detect/train2/args.yaml b/runs/detect/train2/args.yaml @@ -1,108 +0,0 @@ -task: detect -mode: train -model: yolov8n.pt -data: agent/training_data/data.yaml -epochs: 10 -time: null -patience: 100 -batch: 16 -imgsz: 416 -save: true -save_period: -1 -cache: false -device: cpu -workers: 8 -project: null -name: train2 -exist_ok: false -pretrained: true -optimizer: auto -verbose: true -seed: 0 -deterministic: true -single_cls: false -rect: false -cos_lr: false -close_mosaic: 10 -resume: false -amp: true -fraction: 1.0 -profile: false -freeze: null -multi_scale: 0.0 -compile: false -overlap_mask: true -mask_ratio: 4 -dropout: 0.0 -val: true -split: val -save_json: false -conf: null -iou: 0.7 -max_det: 300 -half: false -dnn: false -plots: true -source: null -vid_stride: 1 -stream_buffer: false -visualize: false -augment: false -agnostic_nms: false -classes: null -retina_masks: false -embed: null -show: false -save_frames: false -save_txt: false -save_conf: false -save_crop: false -show_labels: true -show_conf: true -show_boxes: true -line_width: null -format: torchscript -keras: false -optimize: false -int8: false -dynamic: false -simplify: true -opset: null -workspace: null -nms: false -lr0: 0.01 -lrf: 0.01 -momentum: 0.937 -weight_decay: 0.0005 -warmup_epochs: 3.0 -warmup_momentum: 0.8 -warmup_bias_lr: 0.1 -box: 7.5 -cls: 0.5 -dfl: 1.5 -pose: 12.0 -kobj: 1.0 -rle: 1.0 -angle: 1.0 -nbs: 64 -hsv_h: 0.015 -hsv_s: 0.7 -hsv_v: 0.4 -degrees: 0.0 -translate: 0.1 -scale: 0.5 -shear: 0.0 -perspective: 0.0 -flipud: 0.0 -fliplr: 0.5 -bgr: 0.0 -mosaic: 1.0 -mixup: 0.0 -cutmix: 0.0 -copy_paste: 0.0 -copy_paste_mode: flip -auto_augment: randaugment -erasing: 0.4 -cfg: null -tracker: botsort.yaml -save_dir: C:\Debarghya\IIT Guwahati\Second Year\Sem 4\Convolve\Code\runs\detect\train2 diff --git a/runs/detect/train2/labels.jpg b/runs/detect/train2/labels.jpg Binary files differ. diff --git a/runs/detect/train2/train_batch0.jpg b/runs/detect/train2/train_batch0.jpg Binary files differ. diff --git a/runs/detect/train2/train_batch1.jpg b/runs/detect/train2/train_batch1.jpg Binary files differ. diff --git a/runs/detect/train2/train_batch2.jpg b/runs/detect/train2/train_batch2.jpg Binary files differ. diff --git a/simulator/main.py b/simulator/main.py @@ -11,6 +11,7 @@ from typing import List from PIL import Image from dotenv import load_dotenv from pymongo import MongoClient, ReturnDocument +from pymongo.errors import ConfigurationError from datetime import datetime # Load env from root @@ -20,7 +21,10 @@ load_dotenv(env_path) MONGO_URI = os.environ.get("MONGODB_URI") mongo_client = MongoClient(MONGO_URI) -db = mongo_client.get_default_database() +try: + db = mongo_client.get_default_database() +except ConfigurationError: + db = mongo_client["test"] crops_collection = db["cropstates"] sim_state_collection = db["simulator_state"]