| from fastapi import FastAPI, HTTPException |
| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.responses import PlainTextResponse |
| from pydantic import BaseModel |
| from typing import Optional, List |
| import os |
| from google import genai |
| from google.genai import types |
| import requests |
|
|
| from datetime import datetime |
| import pytz |
|
|
|
|
| url = os.getenv('url') |
| Api_key = os.getenv('API_KEY') |
| client = genai.Client(api_key=Api_key) |
|
|
| app = FastAPI(title="Notes Task Manager API") |
|
|
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| class Note(BaseModel): |
| project_name: Optional[str] = "" |
| details: Optional[str] = "" |
| type: str |
|
|
| class TaskRequest(BaseModel): |
| notes: list[Note] |
|
|
| class Task(BaseModel): |
| task_name: str |
| reason: str |
|
|
|
|
| sysPrompt = '''You are an elite Executive Personal Assistant specializing in cognitive load management and productivity. Your sole purpose is to transform a chaotic stream of notes, project details, and random thoughts into a streamlined, actionable plan. |
| |
| **Your Goal:** Eliminate the user's decision fatigue. Do not give them a long list of options; give them a clear path forward. |
| |
| **Input Data: |
| **1. **Projects:** The core goals and technical details of active work. |
| 2. **Random Notes:** Brain dumps, fleeting thoughts, anxieties, and unplanned ideas. |
| |
| **Processing Logic:** |
| - **Analyze:** Cross-reference 'Random Notes' with 'Projects'. If a random thought is a task for a project, categorize it. |
| - **Prioritize:** Identify the 'Critical Path.' What needs to happen *now* to move the needle? |
| - **Filter:** Ignore noise. If a note is just a venting session or a vague thought, acknowledge it internally but do not turn it into a task unless it's actionable. |
| |
| **Output Format (Strictly follow this): **For each day, provide exactly **3 High-Impact Tasks**. No more, no less. |
| |
| **Format:**📅 **Date: [Insert Date]** |
| |
| 1. **[Task Name]** → (Briefly explain *why* this is a priority based on the notes). |
| 2. **[Task Name]** → (Briefly explain *why* this is a priority). |
| 3. **[Task Name]** → (Briefly explain *why* this is a priority). |
| |
| **Closing Note:** Provide one sentence of encouragement or a 'Focus Tip' to help the user stay grounded and avoid distraction. |
| |
| **Tone:** Professional, decisive, calm, and supportive. You are the anchor that keeps the user focused.''' |
|
|
|
|
| def call_gemini(history: List[types.Content]): |
| try: |
| response = client.models.generate_content( |
| model="gemma-4-31b-it", |
| contents=history, |
| config=types.GenerateContentConfig( |
| thinking_config=types.ThinkingConfig(thinking_level="MINIMAL") |
| ), |
| ) |
| return response.text.rstrip() |
| except Exception as e: |
| print(f"GenAI Error: {e}") |
| raise HTTPException(status_code=500, detail="AI Generation Failed") |
|
|
|
|
| |
| @app.post("/gen/task") |
| def generate_tasks(req: TaskRequest): |
| project_notes = [n for n in req.notes if n.type == "project"] |
| random_notes = [n for n in req.notes if n.type == "random"] |
| |
| |
| tz = pytz.timezone('Asia/Kolkata') |
| current_date = datetime.now(tz).strftime("%A, %B %d, %Y") |
| |
| |
| userPrompt = f"Today's Date: {current_date}\n\n" |
| |
| for note in project_notes: |
| userPrompt = userPrompt + "Note:\n" + note.details + "\n\n" |
|
|
| for note in random_notes: |
| userPrompt = userPrompt + "Note:\n" + note.details + "\n\n" |
| |
| history = [ |
| types.Content(role="system", parts=[types.Part(text=sysPrompt)]), |
| types.Content(role="user", parts=[types.Part(text=userPrompt)]) |
| ] |
| |
| text = call_gemini(history) |
| if text: |
| payload = { |
| "input_notes": userPrompt, |
| "ai_response": text |
| } |
| |
| try: |
| response = requests.post(url, json=payload, timeout=5) |
| response.raise_for_status() |
| except Exception as e: |
| print(f"Failed to send data to server: {e}") |
| |
| return PlainTextResponse(text) |
| raise HTTPException(status_code=500, detail="AI returned empty response") |