demeter
Autonomous Hydroponic Intelligencegit clone https://github.com/maydayv7/demeter
backend/server/main.py (2707B)
1import sys
2import os
3from dotenv import load_dotenv
4
5# --- PATH FIX ---
6current_dir = os.path.dirname(os.path.abspath(__file__))
7# Adjust this depending on where main.py sits relative to root folder
8project_root = os.path.abspath(os.path.join(current_dir, "../../"))
9sys.path.append(project_root)
10
11agent_root = os.path.abspath(os.path.join(project_root, "agent"))
12sys.path.append(agent_root)
13
14# Load env from root
15env_path = os.path.join(project_root, ".env")
16if os.path.exists(env_path):
17 load_dotenv(env_path)
18# ----------------
19
20from fastapi import FastAPI, UploadFile, File, Form
21from fastapi.middleware.cors import CORSMiddleware
22from fastapi.responses import StreamingResponse
23
24from Sentinel.agent import FMUBuilder
25
26# Import the logic functions
27from backend.server.functions import (
28 process_ingest,
29 process_search,
30 process_text_query,
31 process_audio_search,
32 process_cycle_stream,
33 process_ask_query,
34 process_similar_crops,
35)
36
37app = FastAPI()
38
39app.add_middleware(
40 CORSMiddleware,
41 allow_origins=["*"], # Allow all for dev
42 allow_credentials=True,
43 allow_methods=["*"],
44 allow_headers=["*"],
45)
46
47print("🌱 Server Starting...")
48
49builder = FMUBuilder()
50
51print("✅ Server Ready.")
52
53
54@app.post("/ingest")
55async def ingest_endpoint(
56 file: UploadFile = File(...), sensors: str = Form(...), metadata: str = Form(...)
57):
58 return await process_ingest(file, sensors, metadata, builder)
59
60
61@app.post("/search")
62async def search_endpoint(file: UploadFile = File(...), sensors: str = Form(...)):
63 return await process_search(file, sensors, builder)
64
65
66@app.post("/run-cycle-stream")
67async def run_cycle_stream_endpoint(
68 file: UploadFile = File(...), sensors: str = Form(...)
69):
70 return StreamingResponse(
71 process_cycle_stream(file, sensors, builder),
72 media_type="text/event-stream",
73 )
74
75
76@app.post("/query-text")
77async def text_query_endpoint(
78 query: str = Form(...),
79 crop_id: str = Form(None), # optional
80):
81 return await process_text_query(query, crop_id)
82
83
84@app.post("/query-similar")
85async def similar_crops_endpoint(
86 crop_id: str = Form(...),
87 crop_name: str = Form(...),
88 payload: str = Form(...),
89):
90 return await process_similar_crops(crop_id, crop_name, payload)
91
92
93@app.post("/query-audio")
94async def audio_query_endpoint(file: UploadFile = File(...)):
95 return await process_audio_search(file)
96
97
98@app.post("/ask-demeter")
99async def ask_demeter_endpoint(
100 query: str = Form(...), context: str = Form(...), language: str = Form(...)
101):
102 return await process_ask_query(query, context, language)
103
104
105if __name__ == "__main__":
106 import uvicorn
107
108 uvicorn.run(app, host="0.0.0.0", port=8000)