From 08b4e1ea933694f14a9d2bca9c71d55d8fe03e3e Mon Sep 17 00:00:00 2001
From: ranaalmaaz55 <50968377-ranaalmaaz55@users.noreply.replit.com>
Date: Sun, 25 Jan 2026 05:56:48 +0000
Subject: [PATCH 1/8] Integrate Replit AI features and update project
configuration
Update api.py to use Replit AI Integrations for OpenAI API key and base URL, and change the model to "gpt-4o-mini". Modify frontend.py to use "localhost" for the backend API URL and add error handling for connection issues. Update requirements.txt to include 'openai', 'pydantic', 'python-dotenv', and 'requests'. Create replit.md documentation detailing the project setup, architecture, and dependencies. Add run.py script to manage backend and frontend processes for Replit environment.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: c1582ad0-2a4d-421f-abef-a344959f5e0b
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 46394778-ce7b-485f-9526-7aef3b6794af
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/5e51078b-5ac9-4f4e-a1d5-c7167392f72e/c1582ad0-2a4d-421f-abef-a344959f5e0b/qTLLDNh
Replit-Helium-Checkpoint-Created: true
---
.replit | 44 ++++++++++++++++++++++++++++++++++++++++++++
api.py | 29 +++++++++++++----------------
frontend.py | 38 +++++++++++++++++++-------------------
replit.md | 34 ++++++++++++++++++++++++++++++++++
requirements.txt | 4 ++++
run.py | 25 +++++++++++++++++++++++++
6 files changed, 139 insertions(+), 35 deletions(-)
create mode 100644 .replit
create mode 100644 replit.md
create mode 100644 run.py
diff --git a/.replit b/.replit
new file mode 100644
index 0000000..055350d
--- /dev/null
+++ b/.replit
@@ -0,0 +1,44 @@
+modules = ["python-3.11"]
+[agent]
+expertMode = true
+integrations = ["python_openai_ai_integrations:1.0.0"]
+
+[nix]
+channel = "stable-25_05"
+packages = ["glibcLocales"]
+
+[workflows]
+runButton = "Project"
+
+[[workflows.workflow]]
+name = "Project"
+mode = "parallel"
+author = "agent"
+
+[[workflows.workflow.tasks]]
+task = "workflow.run"
+args = "AI Personal Trainer"
+
+[[workflows.workflow]]
+name = "AI Personal Trainer"
+author = "agent"
+
+[[workflows.workflow.tasks]]
+task = "shell.exec"
+args = "python run.py"
+waitForPort = 5000
+
+[workflows.workflow.metadata]
+outputType = "webview"
+
+[[ports]]
+localPort = 5000
+externalPort = 80
+
+[[ports]]
+localPort = 8000
+externalPort = 8000
+
+[deployment]
+deploymentTarget = "autoscale"
+run = ["python", "run.py"]
diff --git a/api.py b/api.py
index 41af6e1..4d4fd2e 100644
--- a/api.py
+++ b/api.py
@@ -1,18 +1,18 @@
-# personal_trainer_agent.py
-from fastapi import FastAPI, Request
+from fastapi import FastAPI
from pydantic import BaseModel
-import openai
-from dotenv import load_dotenv
+from openai import OpenAI
import os
-load_dotenv()
-client = openai.OpenAI()
-# Initialize FastAPI app
-app = FastAPI()
+AI_INTEGRATIONS_OPENAI_API_KEY = os.environ.get("AI_INTEGRATIONS_OPENAI_API_KEY")
+AI_INTEGRATIONS_OPENAI_BASE_URL = os.environ.get("AI_INTEGRATIONS_OPENAI_BASE_URL")
+
+client = OpenAI(
+ api_key=AI_INTEGRATIONS_OPENAI_API_KEY,
+ base_url=AI_INTEGRATIONS_OPENAI_BASE_URL
+)
-# ✅ Replace with your actual API key
+app = FastAPI()
-# Define data structure for user inputs
class UserInfo(BaseModel):
goal: str
experience: str
@@ -21,11 +21,6 @@ class UserInfo(BaseModel):
@app.post("/generate_plan/")
async def generate_plan(user: UserInfo):
- """
- Basic AI Agent:
- - Takes user's fitness info
- - Generates a simple gym plan
- """
prompt = f"""
You are a personal fitness trainer.
Create a 1-week gym plan for someone with:
@@ -37,8 +32,10 @@ async def generate_plan(user: UserInfo):
Return the plan as a simple, structured list (Day 1, Day 2, ...).
"""
+ # the newest OpenAI model is "gpt-5" which was released August 7, 2025.
+ # do not change this unless explicitly requested by the user
response = client.chat.completions.create(
- model="gpt-3.5-turbo",
+ model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.7
)
diff --git a/frontend.py b/frontend.py
index 7548d8d..9a35a53 100644
--- a/frontend.py
+++ b/frontend.py
@@ -1,38 +1,38 @@
import streamlit as st
import requests
+import os
-# --- Streamlit page setup ---
-st.set_page_config(page_title="AI Personal Trainer 💪", page_icon="🏋️")
+st.set_page_config(page_title="AI Personal Trainer", page_icon="💪")
st.title("💪 Your AI Personal Trainer")
st.write("Answer a few questions and get your personalized gym plan instantly.")
-# --- User input form ---
with st.form("trainer_form"):
- goal = st.text_input("🎯 What’s your fitness goal? (e.g. build muscle, lose fat, stay fit)")
+ goal = st.text_input("🎯 What's your fitness goal? (e.g. build muscle, lose fat, stay fit)")
experience = st.selectbox("🔥 Your experience level:", ["Beginner", "Intermediate", "Advanced"])
days_per_week = st.slider("📅 How many days per week can you train?", 1, 7, 4)
equipment = st.text_area("🏋️ What equipment do you have? (e.g. dumbbells, resistance bands, gym access)")
submitted = st.form_submit_button("Generate Plan 🚀")
-# --- Backend API URL ---
-API_URL = "http://127.0.0.1:8000/generate_plan/" # update if deployed
+API_URL = "http://localhost:8000/generate_plan/"
-# --- Call the FastAPI backend ---
if submitted:
if not goal or not equipment:
st.warning("⚠️ Please fill in all fields before submitting.")
else:
with st.spinner("Generating your gym plan..."):
- response = requests.post(API_URL, json={
- "goal": goal,
- "experience": experience,
- "days_per_week": days_per_week,
- "equipment": equipment
- })
+ try:
+ response = requests.post(API_URL, json={
+ "goal": goal,
+ "experience": experience,
+ "days_per_week": days_per_week,
+ "equipment": equipment
+ })
- if response.status_code == 200:
- plan = response.json()["gym_plan"]
- st.success("🏋️ Here’s your personalized plan:")
- st.markdown(plan)
- else:
- st.error("❌ Something went wrong. Make sure the FastAPI server is running.")
+ if response.status_code == 200:
+ plan = response.json()["gym_plan"]
+ st.success("🏋️ Here's your personalized plan:")
+ st.markdown(plan)
+ else:
+ st.error("❌ Something went wrong. Please try again.")
+ except requests.exceptions.ConnectionError:
+ st.error("❌ Could not connect to the backend. Please make sure the server is running.")
diff --git a/replit.md b/replit.md
new file mode 100644
index 0000000..55cef4b
--- /dev/null
+++ b/replit.md
@@ -0,0 +1,34 @@
+# AI Personal Trainer
+
+## Overview
+A full-stack AI application that generates personalized gym workout plans using OpenAI.
+
+## Architecture
+- **Frontend**: Streamlit (port 5000) - User interface for collecting fitness goals
+- **Backend**: FastAPI with uvicorn (port 8000) - API for generating workout plans
+- **AI**: OpenAI GPT-4o-mini via Replit AI Integrations
+
+## Running the Application
+The application is run via `python run.py` which:
+1. Starts the FastAPI backend on localhost:8000
+2. Starts the Streamlit frontend on 0.0.0.0:5000
+
+## Project Structure
+```
+├── api.py # FastAPI backend with OpenAI integration
+├── frontend.py # Streamlit frontend
+├── run.py # Launcher script for both services
+├── main.py # CLI version (not used in web app)
+├── requirements.txt
+└── replit.md
+```
+
+## Dependencies
+- fastapi, uvicorn - Web API framework
+- streamlit - Frontend framework
+- openai - AI integration (uses Replit AI Integrations)
+- pydantic - Data validation
+
+## Notes
+- OpenAI access is provided through Replit AI Integrations (no API key needed)
+- Backend runs on localhost, frontend binds to 0.0.0.0 for Replit proxy access
diff --git a/requirements.txt b/requirements.txt
index c40678e..195fd4c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,7 @@ streamlit
pandas
transformers
dotenv
+openai
+pydantic
+python-dotenv
+requests
diff --git a/run.py b/run.py
new file mode 100644
index 0000000..2fb440c
--- /dev/null
+++ b/run.py
@@ -0,0 +1,25 @@
+import subprocess
+import sys
+import time
+
+backend_process = subprocess.Popen(
+ [sys.executable, "-m", "uvicorn", "api:app", "--host", "localhost", "--port", "8000"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT
+)
+
+time.sleep(2)
+
+frontend_process = subprocess.Popen(
+ [sys.executable, "-m", "streamlit", "run", "frontend.py",
+ "--server.port", "5000",
+ "--server.address", "0.0.0.0",
+ "--server.headless", "true",
+ "--browser.gatherUsageStats", "false"],
+)
+
+try:
+ frontend_process.wait()
+except KeyboardInterrupt:
+ backend_process.terminate()
+ frontend_process.terminate()
From 95155992bbe04786e67b4cfe90d75810a0f4bb81 Mon Sep 17 00:00:00 2001
From: Rana <50968377-ranaalmaaz55@users.noreply.replit.com>
Date: Tue, 27 Jan 2026 20:06:27 +0000
Subject: [PATCH 2/8] New Update
---
.replit | 24 ++-
api.py | 44 ------
auth.py | 47 ++++++
backend/personal_trainer_agent.py | 104 +++++++++----
db.py | 78 ++++++++++
dbSQLAlchemy.py | 110 +++++++++++++
frontend.py | 251 ++++++++++++++++++++++++++----
frontend/step2_streamlit_app.py | 61 +++++---
main.py | 241 +++++++++++++++++++---------
my_database.db | Bin 0 -> 28672 bytes
run.py | 27 +---
11 files changed, 758 insertions(+), 229 deletions(-)
delete mode 100644 api.py
create mode 100644 auth.py
create mode 100644 db.py
create mode 100644 dbSQLAlchemy.py
create mode 100644 my_database.db
diff --git a/.replit b/.replit
index 055350d..481a96c 100644
--- a/.replit
+++ b/.replit
@@ -5,7 +5,7 @@ integrations = ["python_openai_ai_integrations:1.0.0"]
[nix]
channel = "stable-25_05"
-packages = ["glibcLocales"]
+packages = ["glibcLocales", "mailutils"]
[workflows]
runButton = "Project"
@@ -31,14 +31,30 @@ waitForPort = 5000
[workflows.workflow.metadata]
outputType = "webview"
+[[ports]]
+localPort = 3000
+externalPort = 3000
+
[[ports]]
localPort = 5000
externalPort = 80
[[ports]]
localPort = 8000
-externalPort = 8000
+externalPort = 8081
+
+[[ports]]
+localPort = 8080
+externalPort = 8080
+
+[[ports]]
+localPort = 8501
+externalPort = 8099
[deployment]
-deploymentTarget = "autoscale"
-run = ["python", "run.py"]
+run = "uvicorn main:app --host 0.0.0.0 --port 8000"
+
+[[ports]]
+localPort = 8000
+externalPort = 8081
+
diff --git a/api.py b/api.py
deleted file mode 100644
index 4d4fd2e..0000000
--- a/api.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from fastapi import FastAPI
-from pydantic import BaseModel
-from openai import OpenAI
-import os
-
-AI_INTEGRATIONS_OPENAI_API_KEY = os.environ.get("AI_INTEGRATIONS_OPENAI_API_KEY")
-AI_INTEGRATIONS_OPENAI_BASE_URL = os.environ.get("AI_INTEGRATIONS_OPENAI_BASE_URL")
-
-client = OpenAI(
- api_key=AI_INTEGRATIONS_OPENAI_API_KEY,
- base_url=AI_INTEGRATIONS_OPENAI_BASE_URL
-)
-
-app = FastAPI()
-
-class UserInfo(BaseModel):
- goal: str
- experience: str
- days_per_week: int
- equipment: str
-
-@app.post("/generate_plan/")
-async def generate_plan(user: UserInfo):
- prompt = f"""
- You are a personal fitness trainer.
- Create a 1-week gym plan for someone with:
- - Goal: {user.goal}
- - Experience level: {user.experience}
- - Days per week available: {user.days_per_week}
- - Available equipment: {user.equipment}
-
- Return the plan as a simple, structured list (Day 1, Day 2, ...).
- """
-
- # the newest OpenAI model is "gpt-5" which was released August 7, 2025.
- # do not change this unless explicitly requested by the user
- response = client.chat.completions.create(
- model="gpt-4o-mini",
- messages=[{"role": "user", "content": prompt}],
- temperature=0.7
- )
-
- plan = response.choices[0].message.content
- return {"gym_plan": plan}
diff --git a/auth.py b/auth.py
new file mode 100644
index 0000000..e1c4c05
--- /dev/null
+++ b/auth.py
@@ -0,0 +1,47 @@
+import streamlit as st
+import requests
+import uuid
+
+st.title("Login/Signup")
+username = st.text_input("Username")
+
+if "session_id" in st.session_state and "username" in st.session_state:
+ st.switch_page("frontend.py")
+
+
+if st.button("Login"):
+ if username:
+ st.session_state.session_id = str(uuid.uuid4())
+ API_BASE = "http://localhost:8000/login/"
+ # API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/login/"
+ response = requests.post(API_URL, json={"username": username, "session_id": st.session_state.session_id})
+
+ if response.status_code == 200:
+ if response.json()["exists"]:
+ st.session_state.username = username
+ st.success("Logged in successfully!")
+ st.switch_page("frontend.py")
+ else:
+ st.warning("User not found. Please sign up.")
+ else:
+ st.error("Failed to connect to the server.")
+ else:
+ st.error("Username is required")
+
+if st.button("Signup"):
+ if username:
+ st.session_state.session_id = str(uuid.uuid4())
+ API_BASE = "http://localhost:8000/signup/"
+ # API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/signup/"
+ response = requests.post(API_URL, json={"username": username, "session_id": st.session_state.session_id})
+ if response.status_code == 200:
+ if response.json()["exists"]:
+ st.warning("Username already exists. Please login or choose a different username.")
+ else:
+ st.session_state.username = username
+ st.success("Signed up successfully!")
+ st.switch_page("frontend.py")
+ else:
+ st.error("Failed to connect to the server.")
+ else:
+ st.error("Username is required")
diff --git a/backend/personal_trainer_agent.py b/backend/personal_trainer_agent.py
index 01bd007..8c7ada1 100644
--- a/backend/personal_trainer_agent.py
+++ b/backend/personal_trainer_agent.py
@@ -2,47 +2,84 @@
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from dotenv import load_dotenv
-from openai import OpenAI
import os
+from groq import Groq
-# Chemin vers le fichier .env (même dossier que ce script)
-dotenv_path = os.path.join(os.path.dirname(__file__), ".env")
-load_dotenv(dotenv_path)
+# # Chemin vers le fichier .env (même dossier que ce script)
+# dotenv_path = os.path.join(os.path.dirname(__file__), ".env")
+# load_dotenv(dotenv_path)
-# Vérifier que la clé est présente
-api_key = os.getenv("OPENAI_API_KEY")
-if not api_key:
- raise ValueError("Veuillez définir votre clé OpenAI dans le fichier .env !")
+# # Vérifier que la clé est présente
+# api_key = os.getenv("OPENAI_API_KEY")
+# if not api_key:
+# raise ValueError("Veuillez définir votre clé OpenAI dans le fichier .env !")
-print("Clé API détectée :", api_key is not None) # juste pour vérifier
+# print("Clé API détectée :", api_key is not None) # juste pour vérifier
-# Créer le client OpenAI avec la clé
-client = OpenAI(api_key=api_key)
+# # Créer le client OpenAI avec la clé
+# client = OpenAI(api_key=api_key)
-# Création de l'application FastAPI
-app = FastAPI()
+# # Création de l'application FastAPI
+# app = FastAPI()
+
+# app.add_middleware(
+# CORSMiddleware,
+# allow_origins=["*"],
+# allow_credentials=True,
+# allow_methods=["*"],
+# allow_headers=["*"],
+# )
+
+# # Modèle pour les entrées utilisateur
+# class UserInput(BaseModel):
+# goal: str
+# experience: str
+# days: int
+# equipment: str
+
+# # Route pour générer le plan
+# @app.post("/generate_plan")
+# def generate_plan(data: UserInput):
+# if data.days <= 0:
+# return {"error": "Le nombre de jours doit être supérieur à 0"}
+
+# prompt = f"""
+# You are an expert fitness coach.
+# Create a weekly workout plan:
+# - Goal: {data.goal}
+# - Experience: {data.experience}
+# - Days/week: {data.days}
+# - Equipment: {data.equipment}
+# """
+
+# try:
+# response = client.chat.completions.create(
+# model="gpt-4o-mini",
+# messages=[
+# {"role": "system", "content": "You are an expert fitness coach."},
+# {"role": "user", "content": prompt}
+# ]
+# )
+# plan_text = response.choices[0].message["content"]
+# return {"plan": plan_text}
-app.add_middleware(
- CORSMiddleware,
- allow_origins=["*"],
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
-)
+# except Exception as e:
+# return {"error": str(e)}
+
+load_dotenv()
+key = os.getenv("Groq_API")
+client = Groq(api_key=key)
-# Modèle pour les entrées utilisateur
class UserInput(BaseModel):
goal: str
experience: str
- days: int
+ days_per_week: int
equipment: str
-# Route pour générer le plan
-@app.post("/generate_plan")
-def generate_plan(data: UserInput):
- if data.days <= 0:
- return {"error": "Le nombre de jours doit être supérieur à 0"}
+app = FastAPI()
+@app. post("/generate_plan/")
+def generate_plan(data: UserInput):
prompt = f"""
You are an expert fitness coach.
Create a weekly workout plan:
@@ -51,17 +88,16 @@ def generate_plan(data: UserInput):
- Days/week: {data.days}
- Equipment: {data.equipment}
"""
-
try:
- response = client.chat.completions.create(
- model="gpt-4o-mini",
+ response = client.chat.completions.create(
+ model="llama3-8b-8192",
messages=[
{"role": "system", "content": "You are an expert fitness coach."},
{"role": "user", "content": prompt}
]
)
- plan_text = response.choices[0].message["content"]
- return {"plan": plan_text}
-
+ plan_text = response.choices[0].message.content
+ return {"gym_plan": plan_text}
+
except Exception as e:
- return {"error": str(e)}
+ return {"error": str(e)}
\ No newline at end of file
diff --git a/db.py b/db.py
new file mode 100644
index 0000000..bfad719
--- /dev/null
+++ b/db.py
@@ -0,0 +1,78 @@
+# db.py
+import sqlite3
+from contextlib import closing
+from pathlib import Path
+
+DB_PATH = Path("chat.db")
+
+
+def get_connection():
+ """Return a SQLite connection."""
+ return sqlite3.connect(DB_PATH, check_same_thread=False)
+
+
+def init_db():
+ """Create the users table if it does not exist."""
+ with closing(get_connection()) as conn:
+ cursor = conn.cursor()
+ cursor.execute("""
+ CREATE TABLE IF NOT EXISTS users (
+ username TEXT PRIMARY KEY,
+ session_id TEXT NOT NULL,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
+ );
+
+ CREATE TABLE IF NOT EXISTS chat_messages (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ session_id TEXT NOT NULL,
+ role TEXT CHECK(role IN ('user', 'assistant')),
+ content TEXT NOT NULL,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (session_id) REFERENCES users(session_id)
+ );
+ CREATE TABLE IF NOT EXISTS plans (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ username TEXT NOT NULL,
+ session_id TEXT NOT NULL,
+ plan_type TEXT,
+ content TEXT NOT NULL,
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (username) REFERENCES users(username)
+ FOREIGN KEY (session_id) REFERENCES users(session_id),
+ FOREIGN KEY (username) REFERENCES users(username)
+ );
+ CREATE TABLE IF NOT EXISTS user_preferences (
+ username TEXT PRIMARY KEY,
+ preferences_json TEXT,
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (username) REFERENCES users(username)
+ );
+ """)
+ conn.commit()
+
+
+# CRUD helpers
+def create_user(username: str, session_id: str):
+ with closing(get_connection()) as conn:
+ cursor = conn.cursor()
+ cursor.execute(
+ "INSERT INTO users (username, session_id) VALUES (?, ?)",
+ (username, session_id))
+ conn.commit()
+
+
+def get_user(username: str):
+ with closing(get_connection()) as conn:
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT username, session_id FROM users WHERE username = ?",
+ (username, ))
+ return cursor.fetchone()
+
+
+def update_session_id(username: str, session_id: str):
+ with closing(get_connection()) as conn:
+ cursor = conn.cursor()
+ cursor.execute("UPDATE users SET session_id = ? WHERE username = ?",
+ (session_id, username))
+ conn.commit()
diff --git a/dbSQLAlchemy.py b/dbSQLAlchemy.py
new file mode 100644
index 0000000..f1fc0a7
--- /dev/null
+++ b/dbSQLAlchemy.py
@@ -0,0 +1,110 @@
+# db_sqlalchemy.py
+from sqlalchemy import Column, String, DateTime, create_engine, Integer, ForeignKey
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.orm import sessionmaker
+from datetime import datetime
+from sqlalchemy import create_engine
+
+#connrct to db or create if not exists
+engine = create_engine('sqlite:///my_database.db', echo=True)
+Base = declarative_base()
+
+# User model
+class User(Base):
+ __tablename__ = "users"
+
+ username = Column(String, primary_key=True)
+ session_id = Column(String, nullable=False)
+ created_at = Column(DateTime, default=datetime.utcnow)
+
+class ChatMessage(Base):
+ __tablename__ = "chat_messages"
+
+ id = Column(Integer, primary_key=True, autoincrement=True)
+ username = Column(String, ForeignKey("users.username"), nullable=False)
+ role = Column(String, nullable=False)
+ content = Column(String, nullable=False)
+ created_at = Column(DateTime, default=datetime.utcnow)
+
+class Plan(Base):
+ __tablename__ = "plans"
+
+ id = Column(Integer, primary_key=True, autoincrement=True)
+ username = Column(String, ForeignKey("users.username"), nullable=False)
+ content = Column(String, nullable=False)
+ created_at = Column(DateTime, default=datetime.utcnow)
+
+class UserPreferences(Base):
+ __tablename__ = "user_preferences"
+ username = Column(String, ForeignKey("users.username"), primary_key=True)
+ preferences_json = Column(String, nullable=False)
+ updated_at = Column(DateTime, default=datetime.utcnow)
+
+
+# Create tables
+Base.metadata.create_all(bind=engine)
+
+#Session factory to interact with db
+SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
+session = SessionLocal()
+
+# CRUD helpers
+def get_user(db_session, username: str):
+ return db_session.query(User).filter_by(username=username).first()
+
+
+def create_user(db_session, username: str, session_id: str):
+ user = User(username=username, session_id=session_id)
+ db_session.add(user)
+ db_session.commit()
+ db_session.refresh(user)
+ return user
+
+
+def update_session(db_session, username: str, session_id: str):
+ user = get_user(db_session, username)
+ if user:
+ user.session_id = session_id
+ db_session.commit()
+ db_session.refresh(user)
+ return username
+
+
+def create_chat_message(db_session, username: str, role: str, content: str):
+ chat_message = ChatMessage(username=username, role=role, content=content)
+ db_session.add(chat_message)
+ db_session.commit()
+ db_session.refresh(chat_message)
+
+def create_plan(db_session, username: str, session_id: str, content: str):
+ plan = Plan(username=username, session_id=session_id, content=content)
+ db_session.add(plan)
+ db_session.commit()
+ db_session.refresh(plan)
+ return plan
+
+def create_user_preferences(db_session, username: str, preferences_json: str):
+ user_preferences = UserPreferences(username=username, preferences_json=preferences_json)
+ db_session.add(user_preferences)
+ db_session.commit()
+ db_session.refresh(user_preferences)
+ return user_preferences
+
+def get_user_preferences(db_session, username: str):
+ return db_session.query(UserPreferences).filter_by(username=username).first()
+
+def update_user_preferences(db_session, username: str, preferences_json: str):
+ user_preferences = get_user_preferences(db_session, username)
+ if user_preferences:
+ user_preferences.preferences_json = preferences_json
+ db_session.commit()
+ db_session.refresh(user_preferences)
+ return user_preferences
+ return None
+
+def get_chat_messages(db_session, username: str):
+ return db_session.query(ChatMessage).filter_by(username=username).order_by(ChatMessage.created_at.asc()).all()
+
+def get_plans(db_session, username: str):
+ return db_session.query(Plan).filter_by(username=username).all()
+
diff --git a/frontend.py b/frontend.py
index 9a35a53..6c6d914 100644
--- a/frontend.py
+++ b/frontend.py
@@ -1,38 +1,231 @@
+# import streamlit as st
+# import requests
+# import os
+
+# st.set_page_config(page_title="AI Personal Trainer", page_icon="💪")
+# st.title("💪 Your AI Personal Trainer")
+# st.write(
+# "Answer a few questions and get your personalized gym plan instantly.")
+
+# with st.form("trainer_form"):
+# goal = st.text_input(
+# "🎯 What's your fitness goal? (e.g. build muscle, lose fat, stay fit)")
+# experience = st.selectbox("🔥 Your experience level:",
+# ["Beginner", "Intermediate", "Advanced"])
+# days_per_week = st.slider("📅 How many days per week can you train?", 1, 7,
+# 4)
+# equipment = st.text_area(
+# "🏋️ What equipment do you have? (e.g. dumbbells, resistance bands, gym access)"
+# )
+# submitted = st.form_submit_button("Generate Plan 🚀")
+
+# API_URL = "http://buildinpublic.ranaalmaaz55.repl.co/generate_plan/"
+
+# if submitted:
+# if not goal or not equipment:
+# st.warning("⚠️ Please fill in all fields before submitting.")
+# else:
+# with st.spinner("Generating your gym plan..."):
+# try:
+# response = requests.post(API_URL,
+# json={
+# "goal": goal,
+# "experience": experience,
+# "days_per_week": days_per_week,
+# "equipment": equipment
+# })
+
+# if response.status_code == 200:
+# plan = response.json()["gym_plan"]
+# st.success("🏋️ Here's your personalized plan:")
+# st.markdown(plan)
+# else:
+# st.error("❌ Something went wrong. Please try again.")
+# except requests.exceptions.ConnectionError:
+# st.error(
+# "❌ Could not connect to the backend. Please make sure the server is running."
+# )
+
+
import streamlit as st
import requests
import os
+# -------------------------------
+# Page config
+# -------------------------------
st.set_page_config(page_title="AI Personal Trainer", page_icon="💪")
st.title("💪 Your AI Personal Trainer")
-st.write("Answer a few questions and get your personalized gym plan instantly.")
-
-with st.form("trainer_form"):
- goal = st.text_input("🎯 What's your fitness goal? (e.g. build muscle, lose fat, stay fit)")
- experience = st.selectbox("🔥 Your experience level:", ["Beginner", "Intermediate", "Advanced"])
- days_per_week = st.slider("📅 How many days per week can you train?", 1, 7, 4)
- equipment = st.text_area("🏋️ What equipment do you have? (e.g. dumbbells, resistance bands, gym access)")
- submitted = st.form_submit_button("Generate Plan 🚀")
-
-API_URL = "http://localhost:8000/generate_plan/"
-
-if submitted:
- if not goal or not equipment:
- st.warning("⚠️ Please fill in all fields before submitting.")
- else:
- with st.spinner("Generating your gym plan..."):
- try:
- response = requests.post(API_URL, json={
- "goal": goal,
- "experience": experience,
- "days_per_week": days_per_week,
- "equipment": equipment
- })
+
+# -------------------------------
+# Backend URLs
+# -------------------------------
+API_BASE = "http://localhost:8000"
+# API_BASE = "https://buildinpublic.ranaalmaaz55.repl.co"
+PREFERENCES_API = f"{API_BASE}/update_preferences"
+CHAT_API = f"{API_BASE}/chat"
+HISTORY_API = f"{API_BASE}/chat_history"
+
+# -------------------------------
+# Session guards
+# -------------------------------
+if "username" not in st.session_state or "session_id" not in st.session_state:
+ st.error("⚠️ You must be logged in to access this page.")
+ st.switch_page("auth.py")
+
+# -------------------------------
+# UI state
+# -------------------------------
+if "messages" not in st.session_state:
+ st.session_state.messages = []
+
+# -------------------------------
+# Tabs
+# -------------------------------
+tab_preferences, tab_chat = st.tabs(["⚙️ Preferences", "💬 Chatbot"])
+
+# =====================================================
+# TAB 1: USER PREFERENCES
+# =====================================================
+with tab_preferences:
+ st.subheader("⚙️ Personal Preferences")
+
+ with st.form("preferences_form"):
+ goal = st.text_input(
+ "🎯 Fitness goal",
+ placeholder="Build muscle, lose fat, stay fit..."
+ )
+
+ experience = st.selectbox(
+ "🔥 Experience level",
+ ["Beginner", "Intermediate", "Advanced"]
+ )
+
+ tone = st.selectbox(
+ "🗣️ Coaching tone",
+ ["Motivational", "Strict", "Friendly", "Neutral"]
+ )
+
+ days_per_week = st.slider(
+ "📅 Training days per week",
+ 1, 7, 4
+ )
+
+ equipment = st.text_area(
+ "🏋️ Available equipment",
+ placeholder="Dumbbells, resistance bands, gym access..."
+ )
+
+ save_preferences = st.form_submit_button("💾 Save Preferences")
+
+ if save_preferences:
+ if not goal or not equipment:
+ st.warning("⚠️ Please fill in all required fields.")
+ else:
+ with st.spinner("Saving your preferences..."):
+ response = requests.post(
+ PREFERENCES_API,
+ json={
+ "username": st.session_state.username,
+ "goal": goal,
+ "experience": experience,
+ "tone": tone,
+ "days_per_week": days_per_week,
+ "equipment": equipment,
+ }
+ )
if response.status_code == 200:
- plan = response.json()["gym_plan"]
- st.success("🏋️ Here's your personalized plan:")
- st.markdown(plan)
+ st.success("✅ Preferences saved successfully!")
else:
- st.error("❌ Something went wrong. Please try again.")
- except requests.exceptions.ConnectionError:
- st.error("❌ Could not connect to the backend. Please make sure the server is running.")
+ st.error("❌ Failed to save preferences.")
+
+# =====================================================
+# TAB 2: CHATBOT
+# =====================================================
+with tab_chat:
+ st.subheader("💬 Chat with your AI Trainer")
+
+ # -------------------------------
+ # Load previous messages once
+ # -------------------------------
+ if not st.session_state.messages:
+ history_response = requests.get(f"{HISTORY_API}/{st.session_state.username}")
+
+ if history_response.status_code == 200:
+ st.session_state.messages = history_response.json()["messages"]
+
+ # -------------------------------
+ # Display chat history
+ # -------------------------------
+ for msg in st.session_state.messages:
+ if msg.role == "user":
+ with st.chat_message("user"):
+ st.markdown(
+ f"
"
+ f"{msg.content}
",
+ unsafe_allow_html=True
+ )
+ else:
+ with st.chat_message("assistant"):
+ st.markdown(
+ f""
+ f"{msg.content}
",
+ unsafe_allow_html=True
+ )
+
+ # -------------------------------
+ # Input + Send button
+ # -------------------------------
+ col1, col2 = st.columns([5, 1])
+
+ with col1:
+ user_input = st.text_input(
+ "Type your message",
+ placeholder="Ask about workouts, nutrition, recovery..."
+ )
+
+ with col2:
+ send_clicked = st.button("Send ➤")
+
+ if send_clicked and user_input:
+ # Show user message
+ st.session_state.messages.append({
+ "role": "user",
+ "content": user_input
+ })
+
+ with st.chat_message("user"):
+ st.markdown(
+ f""
+ f"{user_input}
",
+ unsafe_allow_html=True
+ )
+
+ # Call backend
+ with st.chat_message("assistant"):
+ with st.spinner("Thinking..."):
+ response = requests.post(
+ CHAT_API,
+ json={
+ "username": st.session_state.username,
+ "message": user_input,
+ "messages": st.session_state.messages
+ }
+ )
+
+ if response.status_code == 200:
+ assistant_reply = response.json()["response"]
+ else:
+ assistant_reply = "❌ Something went wrong."
+
+ st.markdown(
+ f""
+ f"{assistant_reply}
",
+ unsafe_allow_html=True
+ )
+
+ st.session_state.messages.append({
+ "role": "assistant",
+ "content": assistant_reply
+ })
diff --git a/frontend/step2_streamlit_app.py b/frontend/step2_streamlit_app.py
index 99fef1a..420c5d9 100644
--- a/frontend/step2_streamlit_app.py
+++ b/frontend/step2_streamlit_app.py
@@ -1,28 +1,47 @@
import streamlit as st
import requests
+import os
-st.set_page_config(page_title="AI Trainer", page_icon="💪", layout="centered")
+st.set_page_config(page_title="AI Personal Trainer", page_icon="💪")
+st.title("💪 Your AI Personal Trainer")
+st.write(
+ "Answer a few questions and get your personalized gym plan instantly.")
-st.title("💪 AI Personal Trainer Agent")
-st.write("Fill the form and get your personalized gym plan instantly.")
+with st.form("trainer_form"):
+ goal = st.text_input(
+ "🎯 What's your fitness goal? (e.g. build muscle, lose fat, stay fit)")
+ experience = st.selectbox("🔥 Your experience level:",
+ ["Beginner", "Intermediate", "Advanced"])
+ days_per_week = st.slider("📅 How many days per week can you train?", 1, 7,
+ 4)
+ equipment = st.text_area(
+ "🏋️ What equipment do you have? (e.g. dumbbells, resistance bands, gym access)"
+ )
+ submitted = st.form_submit_button("Generate Plan 🚀")
-goal = st.selectbox("🎯 Your Goal", ["Lose weight", "Build muscle", "Endurance", "Get toned"])
-experience = st.selectbox("📊 Experience Level", ["Beginner", "Intermediate", Advanced"])
-days = st.slider("📅 Training Days per Week", 1, 7, 3)
-equipment = st.text_input("🏋️ Equipment Available")
+API_URL = "http://localhost:8000/generate_plan/"
-if st.button("Generate Plan 🚀"):
- data = {
- "goal": goal,
- "experience": experience,
- "days": days,
- "equipment": equipment
- }
-
- response = requests.post("http://localhost:8000/generate_plan", json=data)
-
- if response.status_code == 200:
- st.success("Your Personalized Plan:")
- st.write(response.json()["plan"])
+if submitted:
+ if not goal or not equipment:
+ st.warning("⚠️ Please fill in all fields before submitting.")
else:
- st.error("Error connecting to backend.")
+ with st.spinner("Generating your gym plan..."):
+ try:
+ response = requests.post(API_URL,
+ json={
+ "goal": goal,
+ "experience": experience,
+ "days_per_week": days_per_week,
+ "equipment": equipment
+ })
+
+ if response.status_code == 200:
+ plan = response.json()["gym_plan"]
+ st.success("🏋️ Here's your personalized plan:")
+ st.markdown(plan)
+ else:
+ st.error("❌ Something went wrong. Please try again.")
+ except requests.exceptions.ConnectionError:
+ st.error(
+ "❌ Could not connect to the backend. Please make sure the server is running."
+ )
diff --git a/main.py b/main.py
index 30324f9..636341b 100644
--- a/main.py
+++ b/main.py
@@ -1,82 +1,177 @@
-import openai
-from dotenv import load_dotenv
-import os
from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
-from typing import List
+from dotenv import load_dotenv
+import os
+from groq import Groq
+import dbSQLAlchemy as db
+from langchain_core.prompts import ChatPromptTemplate
+from langchain_groq import ChatGroq
+from langchain_core.runnables.history import RunnableWithMessageHistory
+from langchain_core.messages import AIMessage, HumanMessage
+from langchain_core.runnables import RunnableSequence
+
-# Load environment variables
load_dotenv()
-client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
-
-# -------------------
-# CLI: original script
-# -------------------
-def main():
- print("💪 Welcome to your AI Personal Trainer!")
- goal = input("What's your fitness goal? ")
- experience = input("What's your experience level (beginner/intermediate/advanced)? ")
- days = input("How many days per week can you train? ")
- equipment = input("What equipment do you have? ")
-
- prompt = f"""
- You are a personal trainer. Create a 1-week gym plan for someone with:
- Goal: {goal}
- Experience: {experience}
- Days per week: {days}
- Equipment: {equipment}
- Return it as a structured text plan (Day 1, Day 2...).
- """
-
- # UPDATED TO NEW API
- response = client.chat.completions.create(
- model="gpt-4o-mini",
- messages=[{"role": "user", "content": prompt}],
- temperature=0.7
- )
-
- print("\n🏋️ Your Gym Plan:\n")
- print(response.choices[0].message.content)
-
-# -------------------
-# Web API: FastAPI
-# -------------------
-app = FastAPI(title="AI Personal Trainer API")
-
-# Home route so you don't get 404
-@app.get("/")
-def home():
- return {"message": "API is running — go to /docs"}
-
-class UserData(BaseModel):
+key = os.getenv("GroqAPI")
+client = Groq(api_key=key)
+llm = ChatGroq(temperature=0.7, model="llama3-8b-8192", api_key=key)
+
+# Build LangChain memory
+def build_memory(messages: list):
+ history = [
+ HumanMessage(content=m["content"]) if m["role"] == "user"
+ else AIMessage(content=m["content"])
+ for m in messages
+ ]
+
+ return history
+
+
+# Build prompt template
+
+def build_prompt_template():
+ return ChatPromptTemplate.from_messages([
+ ("system",
+ """You are an AI personal trainer.
+
+ User preferences:
+ - Goal: {goal}
+ - Experience: {experience}
+ - Days per week: {days_per_week}
+ - Equipment: {equipment}
+ - Coaching tone: {tone}
+
+ Adapt all responses to these preferences."""
+ ),
+ ("ai", "{chat_history}"),
+ ("human", "{input}")
+ ])
+
+
+class UserInput(BaseModel):
+ username: str
goal: str
experience: str
days_per_week: int
- equipment: List[str] = []
-
-@app.post("/generate_plan")
-def generate_plan(user: UserData):
- prompt = f"""
- You are a personal trainer. Create a 1-week gym plan for someone with:
- Goal: {user.goal}
- Experience: {user.experience}
- Days per week: {user.days_per_week}
- Equipment: {', '.join(user.equipment)}
- Return it as a structured text plan (Day 1, Day 2...).
- """
-
- # CORRECT NEW API CALL
- response = client.chat.completions.create(
- model="gpt-4o-mini",
- messages=[{"role": "user", "content": prompt}],
- temperature=0.7
- )
-
- return {"plan": response.choices[0].message.content}
-
-# -------------------
-# Run CLI if script is executed directly
-# -------------------
+ equipment: str
+ tone: str
+
+class ChatInput(BaseModel):
+ username: str
+ message: str
+ messages: list
+
+class AuthInput(BaseModel):
+ username: str
+ session_id: str
+
+
+app = FastAPI()
+
+
+# @app.post("/generate_plan/")
+# def generate_plan(data: UserInput):
+# prompt = f"""
+# You are an expert fitness coach.
+# Create a weekly workout plan:
+# - Goal: {data.goal}
+# - Experience: {data.experience}
+# - Days/week: {data.days_per_week}
+# - Equipment: {data.equipment}
+# """
+# try:
+# response = client.chat.completions.create(
+# model="llama3-8b-8192",
+# messages=[{
+# "role": "system",
+# "content": "You are an expert fitness coach."
+# }, {
+# "role": "user",
+# "content": prompt
+# }])
+# plan_text = response.choices[0].message.content
+# return {"gym_plan": plan_text}
+
+# except Exception as e:
+# return {"error": str(e)}
+
+@app.post("/login/")
+def login(data: AuthInput):
+ if data.username:
+ user = db.get_user(db.session, data.username)
+ if user:
+ db.update_session(db.session, data.username, data.session_id)
+ return {"exists": True}
+ else:
+ return {"exists": False}
+
+@app.post("/signup/")
+def signup(data: AuthInput):
+ if data.username:
+ user = db.get_user(db.session, data.username)
+ if user:
+ return {"exists": True}
+ else:
+ db.create_user(db.session, data.username, data.session_id)
+ return {"exists": False}
+
+@app.post("/update_preferences/")
+def update_preferences(data: UserInput):
+ preferences_json = {
+ "goal": data.goal,
+ "experience": data.experience,
+ "days_per_week": data.days_per_week,
+ "equipment": data.equipment,
+ "tone": data.tone
+ }
+ db.update_user_preferences(db.session, data.username, str(preferences_json))
+
+@app.get("/chat_history/{username}")
+def get_chat_history(username: str):
+ messages = db.get_chat_messages(db.session, username)
+ return {"messages": messages}
+
+
+@app.post("/chat/")
+def chat(data: ChatInput):
+ # 1. Load user preferences
+ user_preferences = db.get_user_preferences(db.session, data.username)
+
+ # 2. Build memory
+ memory = build_memory(data.messages)
+
+ # 3. Build prompt template
+ prompt = build_prompt_template()
+
+ # 4. Combine prompt and LLM into a RunnableSequence
+ chain = RunnableSequence([prompt, llm])
+
+ # 5. Invoke chain with context
+ response = chain.invoke({
+ "goal": user_preferences.preferences_json["goal"],
+ "experience": user_preferences.preferences_json["experience"],
+ "days_per_week": user_preferences.preferences_json["days_per_week"],
+ "equipment": user_preferences.preferences_json["equipment"],
+ "tone": user_preferences.preferences_json["tone"],
+ "chat_history": memory.messages, # <-- new way to access messages
+ "input": data.message
+ })
+
+ assistant_reply = response.content
+
+ # 6. Save messages to DB
+ db.create_chat_message(db.session, data.username, "user", data.message)
+ db.create_chat_message(db.session, data.username, "assistant", assistant_reply)
+
+
+ return {"response": assistant_reply}
+
+
+
if __name__ == "__main__":
- main()
+ import uvicorn
+ port = int(os.environ.get("PORT", 8000))
+ uvicorn.run(app, host="0.0.0.0", port=port)
+
diff --git a/my_database.db b/my_database.db
new file mode 100644
index 0000000000000000000000000000000000000000..6c4049f23bb5a409d79ccf91d0be4ca6211a6093
GIT binary patch
literal 28672
zcmeI((Qnc~9Ki8*V;~L4-fH5@y=_gzM13}j*i9m1T5x7hO@*7oK+Ae1@s;h_Xa58L
z8~-1DvsY7H31Py2+lx#k;U(Dt5DJUfoTCcM~~RGWKV&Jd?2uhf*!~%WcnX4O}s3J?pw+c~tCMRedcCrc#`=
zy!MNhCwj*N(RGd2+uumJ-63(``J3xwMmxqq+GW9P16{MBl%HXOwuEkAIy^|
z>-)=b`45(_R4!|!ioLgIUcJrShUY=zPo+}9d#MVYoq||lNOO%xqSG6=hi(xnk8dSV
z98Fg94x=!UVX|`4FqSu}jz@p%xu|YeY}+;$7a7NF5`-#iN`>&VOKZaZ2LV{l;*OcE
z<+AZBrL#O%TZOe~;xs94$XJ!`={O4gbe~ow^q;8ad+At?vsJbq+w0O!{meDBojy)(
z=|@UkH@mu_Ab
Date: Wed, 28 Jan 2026 08:04:35 +0000
Subject: [PATCH 3/8] Update application to correctly start backend and
frontend services
Modify main.py to remove the local uvicorn run command, and introduce a start.sh script to properly launch the FastAPI backend on 0.0.0.0:8000 and the Streamlit frontend on 0.0.0.0:8081.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: c1582ad0-2a4d-421f-abef-a344959f5e0b
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 172a0ba0-d30c-436d-8a65-58905eebfa50
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/5e51078b-5ac9-4f4e-a1d5-c7167392f72e/c1582ad0-2a4d-421f-abef-a344959f5e0b/qTLLDNh
Replit-Helium-Checkpoint-Created: true
---
.replit | 8 +-------
main.py | 6 +-----
start.sh | 8 ++++++++
3 files changed, 10 insertions(+), 12 deletions(-)
create mode 100644 start.sh
diff --git a/.replit b/.replit
index 481a96c..0ef1153 100644
--- a/.replit
+++ b/.replit
@@ -41,7 +41,6 @@ externalPort = 80
[[ports]]
localPort = 8000
-externalPort = 8081
[[ports]]
localPort = 8080
@@ -49,12 +48,7 @@ externalPort = 8080
[[ports]]
localPort = 8501
-externalPort = 8099
[deployment]
-run = "uvicorn main:app --host 0.0.0.0 --port 8000"
-
-[[ports]]
-localPort = 8000
-externalPort = 8081
+run = "bash start.sh"
diff --git a/main.py b/main.py
index 636341b..bbc65c5 100644
--- a/main.py
+++ b/main.py
@@ -168,10 +168,6 @@ def chat(data: ChatInput):
return {"response": assistant_reply}
-
-if __name__ == "__main__":
- import uvicorn
- port = int(os.environ.get("PORT", 8000))
- uvicorn.run(app, host="0.0.0.0", port=port)
+
diff --git a/start.sh b/start.sh
new file mode 100644
index 0000000..f2ef606
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,8 @@
+# start.sh
+#!/bin/bash
+
+# Start FastAPI in the background on port 8000 (adjust if needed, but 8000 is common)
+uvicorn main:app --host 0.0.0.0 --port 8000 &
+
+# Start Streamlit in the foreground (Replit will show this in the web view)
+streamlit run auth.py --server.port 8081 --server.address 0.0.0.0
\ No newline at end of file
From 723da035311ae0be8afc6928c636a76dc03306f8 Mon Sep 17 00:00:00 2001
From: ranaalmaaz55 <50968377-ranaalmaaz55@users.noreply.replit.com>
Date: Wed, 28 Jan 2026 09:14:00 +0000
Subject: [PATCH 4/8] Update application to run both backend and frontend
services simultaneously
Fixes inconsistent API URL usage in auth.py and updates run.py to launch uvicorn backend on port 8000 and Streamlit frontend on port 5000.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: c1582ad0-2a4d-421f-abef-a344959f5e0b
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 770336d0-cc94-4f16-95dd-a702c8d3be20
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/5e51078b-5ac9-4f4e-a1d5-c7167392f72e/c1582ad0-2a4d-421f-abef-a344959f5e0b/qTLLDNh
Replit-Helium-Checkpoint-Created: true
---
auth.py | 4 ++--
frontend.py | 6 +++---
run.py | 27 ++++++++++++++++++++++++---
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/auth.py b/auth.py
index e1c4c05..ff04314 100644
--- a/auth.py
+++ b/auth.py
@@ -14,7 +14,7 @@
st.session_state.session_id = str(uuid.uuid4())
API_BASE = "http://localhost:8000/login/"
# API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/login/"
- response = requests.post(API_URL, json={"username": username, "session_id": st.session_state.session_id})
+ response = requests.post(API_BASE, json={"username": username, "session_id": st.session_state.session_id})
if response.status_code == 200:
if response.json()["exists"]:
@@ -33,7 +33,7 @@
st.session_state.session_id = str(uuid.uuid4())
API_BASE = "http://localhost:8000/signup/"
# API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/signup/"
- response = requests.post(API_URL, json={"username": username, "session_id": st.session_state.session_id})
+ response = requests.post(API_BASE, json={"username": username, "session_id": st.session_state.session_id})
if response.status_code == 200:
if response.json()["exists"]:
st.warning("Username already exists. Please login or choose a different username.")
diff --git a/frontend.py b/frontend.py
index 6c6d914..81bd6fd 100644
--- a/frontend.py
+++ b/frontend.py
@@ -62,9 +62,9 @@
# -------------------------------
API_BASE = "http://localhost:8000"
# API_BASE = "https://buildinpublic.ranaalmaaz55.repl.co"
-PREFERENCES_API = f"{API_BASE}/update_preferences"
-CHAT_API = f"{API_BASE}/chat"
-HISTORY_API = f"{API_BASE}/chat_history"
+PREFERENCES_API = f"{API_BASE}/update_preferences/"
+CHAT_API = f"{API_BASE}/chat/"
+HISTORY_API = f"{API_BASE}/chat_history/"
# -------------------------------
# Session guards
diff --git a/run.py b/run.py
index ab2ed63..a3bccd5 100644
--- a/run.py
+++ b/run.py
@@ -1,4 +1,25 @@
-import uvicorn
+import subprocess
+import sys
+import time
-if __name__ == "__main__":
- uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
+backend_process = subprocess.Popen(
+ [sys.executable, "-m", "uvicorn", "main:app", "--host", "localhost", "--port", "8000", "--reload"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT
+)
+
+time.sleep(2)
+
+frontend_process = subprocess.Popen(
+ [sys.executable, "-m", "streamlit", "run", "auth.py",
+ "--server.port", "5000",
+ "--server.address", "0.0.0.0",
+ "--server.headless", "true",
+ "--browser.gatherUsageStats", "false"],
+)
+
+try:
+ frontend_process.wait()
+except KeyboardInterrupt:
+ backend_process.terminate()
+ frontend_process.terminate()
From 7aeac507b084185c24041e609a1a8bf04104796b Mon Sep 17 00:00:00 2001
From: ranaalmaaz55 <50968377-ranaalmaaz55@users.noreply.replit.com>
Date: Wed, 28 Jan 2026 11:28:26 +0000
Subject: [PATCH 5/8] Fix chatbot errors and improve user preference handling
Refactor auth.py, remove unused frontend.py, and update main.py to address issues with user preference storage, access, and API endpoint redirection.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: c1582ad0-2a4d-421f-abef-a344959f5e0b
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 8ce81780-7bb8-42bd-a905-4e91d1694166
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/5e51078b-5ac9-4f4e-a1d5-c7167392f72e/c1582ad0-2a4d-421f-abef-a344959f5e0b/qTLLDNh
Replit-Helium-Checkpoint-Created: true
---
auth.py | 8 ++++----
main.py | 13 ++++++++-----
my_database.db | Bin 28672 -> 28672 bytes
frontend.py => pages/frontend.py | 0
4 files changed, 12 insertions(+), 9 deletions(-)
rename frontend.py => pages/frontend.py (100%)
diff --git a/auth.py b/auth.py
index ff04314..5337e9f 100644
--- a/auth.py
+++ b/auth.py
@@ -6,7 +6,7 @@
username = st.text_input("Username")
if "session_id" in st.session_state and "username" in st.session_state:
- st.switch_page("frontend.py")
+ st.switch_page("pages/frontend.py")
if st.button("Login"):
@@ -20,7 +20,7 @@
if response.json()["exists"]:
st.session_state.username = username
st.success("Logged in successfully!")
- st.switch_page("frontend.py")
+ st.switch_page("pages/frontend.py")
else:
st.warning("User not found. Please sign up.")
else:
@@ -33,14 +33,14 @@
st.session_state.session_id = str(uuid.uuid4())
API_BASE = "http://localhost:8000/signup/"
# API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/signup/"
- response = requests.post(API_BASE, json={"username": username, "session_id": st.session_state.session_id})
+ response = requests.post(API_BASEE, json={"username": username, "session_id": st.session_state.session_id})
if response.status_code == 200:
if response.json()["exists"]:
st.warning("Username already exists. Please login or choose a different username.")
else:
st.session_state.username = username
st.success("Signed up successfully!")
- st.switch_page("frontend.py")
+ st.switch_page(pages/"frontend.py")
else:
st.error("Failed to connect to the server.")
else:
diff --git a/main.py b/main.py
index bbc65c5..9fa2461 100644
--- a/main.py
+++ b/main.py
@@ -10,12 +10,14 @@
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.runnables import RunnableSequence
-
+from pydantic import SecretStr
load_dotenv()
key = os.getenv("GroqAPI")
+if not key:
+ raise ValueError("Groq API key not found in environment variables.")
client = Groq(api_key=key)
-llm = ChatGroq(temperature=0.7, model="llama3-8b-8192", api_key=key)
+llm = ChatGroq(temperature=0.7, model="llama3-8b-8192", api_key=SecretStr(key))
# Build LangChain memory
def build_memory(messages: list):
@@ -145,8 +147,9 @@ def chat(data: ChatInput):
prompt = build_prompt_template()
# 4. Combine prompt and LLM into a RunnableSequence
- chain = RunnableSequence([prompt, llm])
-
+ chain = RunnableSequence(prompt, llm)
+ if not user_preferences:
+ return {"response": "Please set your preferences first."}
# 5. Invoke chain with context
response = chain.invoke({
"goal": user_preferences.preferences_json["goal"],
@@ -154,7 +157,7 @@ def chat(data: ChatInput):
"days_per_week": user_preferences.preferences_json["days_per_week"],
"equipment": user_preferences.preferences_json["equipment"],
"tone": user_preferences.preferences_json["tone"],
- "chat_history": memory.messages, # <-- new way to access messages
+ "chat_history": memory,
"input": data.message
})
diff --git a/my_database.db b/my_database.db
index 6c4049f23bb5a409d79ccf91d0be4ca6211a6093..5dd75446040302524c3c9e6df84f921b21a36f4c 100644
GIT binary patch
delta 137
zcmZp8z}WDBae_1>&qNt#MxKocOZeFs`FAkz@7OFTu#P{-jgdt()G;VAFVP~=GC3v5
zB2_mv)yzQG#3I#9*TOV8N!KhT&B)x`Aj!niFv-Zk$V}J3P}j&p!NAhW$im9VT+h(b
n%-GPBi-CcGk^ct+{|}(K@Ax^{nMFB4rt)rPRQRvINI?Jq4tOKC
delta 33
pcmZp8z}WDBae_1>%S0JxMwX2UOZYdl1pJX-
Date: Wed, 28 Jan 2026 18:32:42 +0000
Subject: [PATCH 6/8] Update user profile and chat functionality for better
personalization
Fixes bugs in user preference handling, updates API calls, and refactors database models.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: c1582ad0-2a4d-421f-abef-a344959f5e0b
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: bfe3b6b8-cf3f-45aa-a18f-301e68c30b48
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/5e51078b-5ac9-4f4e-a1d5-c7167392f72e/c1582ad0-2a4d-421f-abef-a344959f5e0b/qTLLDNh
Replit-Helium-Checkpoint-Created: true
---
.replit | 2 +-
auth.py | 4 +--
dbSQLAlchemy.py | 31 +++++++++---------
main.py | 82 +++++++++++++++++++++++++++++++---------------
my_database.db | Bin 28672 -> 49152 bytes
pages/frontend.py | 14 ++++----
requirements.txt | 3 ++
7 files changed, 85 insertions(+), 51 deletions(-)
diff --git a/.replit b/.replit
index 0ef1153..b9f4c9b 100644
--- a/.replit
+++ b/.replit
@@ -5,7 +5,7 @@ integrations = ["python_openai_ai_integrations:1.0.0"]
[nix]
channel = "stable-25_05"
-packages = ["glibcLocales", "mailutils"]
+packages = ["glibcLocales", "libxcrypt", "mailutils"]
[workflows]
runButton = "Project"
diff --git a/auth.py b/auth.py
index 5337e9f..90c186c 100644
--- a/auth.py
+++ b/auth.py
@@ -33,14 +33,14 @@
st.session_state.session_id = str(uuid.uuid4())
API_BASE = "http://localhost:8000/signup/"
# API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/signup/"
- response = requests.post(API_BASEE, json={"username": username, "session_id": st.session_state.session_id})
+ response = requests.post(API_BASE, json={"username": username, "session_id": st.session_state.session_id})
if response.status_code == 200:
if response.json()["exists"]:
st.warning("Username already exists. Please login or choose a different username.")
else:
st.session_state.username = username
st.success("Signed up successfully!")
- st.switch_page(pages/"frontend.py")
+ st.switch_page("pages/frontend.py")
else:
st.error("Failed to connect to the server.")
else:
diff --git a/dbSQLAlchemy.py b/dbSQLAlchemy.py
index f1fc0a7..2d4504d 100644
--- a/dbSQLAlchemy.py
+++ b/dbSQLAlchemy.py
@@ -3,7 +3,6 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime
-from sqlalchemy import create_engine
#connrct to db or create if not exists
engine = create_engine('sqlite:///my_database.db', echo=True)
@@ -26,19 +25,21 @@ class ChatMessage(Base):
content = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
-class Plan(Base):
- __tablename__ = "plans"
+# class Plan(Base):
+# __tablename__ = "plans"
- id = Column(Integer, primary_key=True, autoincrement=True)
- username = Column(String, ForeignKey("users.username"), nullable=False)
- content = Column(String, nullable=False)
- created_at = Column(DateTime, default=datetime.utcnow)
+# id = Column(Integer, primary_key=True, autoincrement=True)
+# username = Column(String, ForeignKey("users.username"), nullable=False)
+# content = Column(String, nullable=False)
+# created_at = Column(DateTime, default=datetime.utcnow)
class UserPreferences(Base):
__tablename__ = "user_preferences"
username = Column(String, ForeignKey("users.username"), primary_key=True)
preferences_json = Column(String, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow)
+ age = Column(Integer)
+ gender = Column(String)
# Create tables
@@ -76,12 +77,12 @@ def create_chat_message(db_session, username: str, role: str, content: str):
db_session.commit()
db_session.refresh(chat_message)
-def create_plan(db_session, username: str, session_id: str, content: str):
- plan = Plan(username=username, session_id=session_id, content=content)
- db_session.add(plan)
- db_session.commit()
- db_session.refresh(plan)
- return plan
+# def create_plan(db_session, username: str, session_id: str, content: str):
+# plan = Plan(username=username, session_id=session_id, content=content)
+# db_session.add(plan)
+# db_session.commit()
+# db_session.refresh(plan)
+# return plan
def create_user_preferences(db_session, username: str, preferences_json: str):
user_preferences = UserPreferences(username=username, preferences_json=preferences_json)
@@ -105,6 +106,6 @@ def update_user_preferences(db_session, username: str, preferences_json: str):
def get_chat_messages(db_session, username: str):
return db_session.query(ChatMessage).filter_by(username=username).order_by(ChatMessage.created_at.asc()).all()
-def get_plans(db_session, username: str):
- return db_session.query(Plan).filter_by(username=username).all()
+# def get_plans(db_session, username: str):
+# return db_session.query(Plan).filter_by(username=username).all()
diff --git a/main.py b/main.py
index 9fa2461..725b563 100644
--- a/main.py
+++ b/main.py
@@ -5,37 +5,40 @@
import os
from groq import Groq
import dbSQLAlchemy as db
-from langchain_core.prompts import ChatPromptTemplate
+from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_groq import ChatGroq
from langchain_core.runnables.history import RunnableWithMessageHistory
-from langchain_core.messages import AIMessage, HumanMessage
+# from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.runnables import RunnableSequence
from pydantic import SecretStr
+import json
+from langchain.memory import ConversationBufferMemory
load_dotenv()
key = os.getenv("GroqAPI")
if not key:
raise ValueError("Groq API key not found in environment variables.")
client = Groq(api_key=key)
-llm = ChatGroq(temperature=0.7, model="llama3-8b-8192", api_key=SecretStr(key))
-
-# Build LangChain memory
-def build_memory(messages: list):
- history = [
- HumanMessage(content=m["content"]) if m["role"] == "user"
- else AIMessage(content=m["content"])
- for m in messages
- ]
+llm = ChatGroq(temperature=0.7, model="llama-3.1-8b-instant", api_key=SecretStr(key))
+
+# # Build LangChain memory
+# def build_memory(messages: list):
+# history = [
+# HumanMessage(content=m["content"]) if m["role"] == "user"
+# else AIMessage(content=m["content"])
+# for m in messages
+# ]
- return history
+# return history
# Build prompt template
def build_prompt_template():
return ChatPromptTemplate.from_messages([
- ("system",
- """You are an AI personal trainer.
+ (
+ "system",
+ """You are an AI personal trainer.
User preferences:
- Goal: {goal}
@@ -46,13 +49,16 @@ def build_prompt_template():
Adapt all responses to these preferences."""
),
- ("ai", "{chat_history}"),
+ MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}")
])
+
class UserInput(BaseModel):
username: str
+ age: int
+ gender: str
goal: str
experience: str
days_per_week: int
@@ -62,7 +68,6 @@ class UserInput(BaseModel):
class ChatInput(BaseModel):
username: str
message: str
- messages: list
class AuthInput(BaseModel):
username: str
@@ -121,47 +126,70 @@ def signup(data: AuthInput):
@app.post("/update_preferences/")
def update_preferences(data: UserInput):
preferences_json = {
+ "age": data.age,
+ "gender": data.gender,
"goal": data.goal,
"experience": data.experience,
"days_per_week": data.days_per_week,
"equipment": data.equipment,
"tone": data.tone
}
- db.update_user_preferences(db.session, data.username, str(preferences_json))
+ if not db.get_user_preferences(db.session, data.username):
+ db.create_user_preferences(db.session, data.username, json.dumps(preferences_json))
+ else:
+ db.update_user_preferences(db.session, data.username, json.dumps(preferences_json))
@app.get("/chat_history/{username}")
def get_chat_history(username: str):
messages = db.get_chat_messages(db.session, username)
- return {"messages": messages}
+ return {"messages": [
+ {"role": msg.role, "content": msg.content} for msg in messages
+ ]
+ }
@app.post("/chat/")
def chat(data: ChatInput):
+ print("connected to fastapi")
# 1. Load user preferences
user_preferences = db.get_user_preferences(db.session, data.username)
-
+ messages = db.get_chat_messages(db.session, data.username)
# 2. Build memory
- memory = build_memory(data.messages)
+ print("got preferences and history")
+ memory = build_memory([
+ {"role": msg.role, "content": msg.content}
+ for msg in messages
+ ])
+ print("memory built")
# 3. Build prompt template
prompt = build_prompt_template()
-
+ print("prompt built")
# 4. Combine prompt and LLM into a RunnableSequence
chain = RunnableSequence(prompt, llm)
+ print("chain built")
if not user_preferences:
return {"response": "Please set your preferences first."}
+
+ preferences = json.loads(str(user_preferences.preferences_json))
+ print("Memory:", memory)
# 5. Invoke chain with context
response = chain.invoke({
- "goal": user_preferences.preferences_json["goal"],
- "experience": user_preferences.preferences_json["experience"],
- "days_per_week": user_preferences.preferences_json["days_per_week"],
- "equipment": user_preferences.preferences_json["equipment"],
- "tone": user_preferences.preferences_json["tone"],
+ "goal":
+ preferences["goal"],
+ "experience":
+ preferences["experience"],
+ "days_per_week":
+ preferences["days_per_week"],
+ "equipment":
+ preferences["equipment"],
+ "tone":
+ preferences["tone"],
"chat_history": memory,
"input": data.message
})
- assistant_reply = response.content
+ assistant_reply = str(response.content)
# 6. Save messages to DB
db.create_chat_message(db.session, data.username, "user", data.message)
diff --git a/my_database.db b/my_database.db
index 5dd75446040302524c3c9e6df84f921b21a36f4c..6a3c51c1a7bbf197a2bbd865803a6a2e08d46dc7 100644
GIT binary patch
literal 49152
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
jVRZ5ccc+dX;d6ZU=gTX>KK%mmuQh_
znVgbjk*b@TYG$BoVv%a5Yhjw4q-&OvW@K(|kYr+Mm^AsByc|&b4+j1pn*|Nt@o)a2
Y&mk~r1IuO>gFpN*nvrWWqrrcE0Hr`B#{d8T
diff --git a/pages/frontend.py b/pages/frontend.py
index 81bd6fd..3787d26 100644
--- a/pages/frontend.py
+++ b/pages/frontend.py
@@ -91,6 +91,8 @@
st.subheader("⚙️ Personal Preferences")
with st.form("preferences_form"):
+ age = st.number_input("👶 Age", min_value=18, max_value=60, value=20)
+ gender = st.radio("👤 Gender", ["Male", "Female"])
goal = st.text_input(
"🎯 Fitness goal",
placeholder="Build muscle, lose fat, stay fit..."
@@ -159,18 +161,18 @@
# Display chat history
# -------------------------------
for msg in st.session_state.messages:
- if msg.role == "user":
+ if msg["role"] == "user":
with st.chat_message("user"):
st.markdown(
f""
- f"{msg.content}
",
+ f"{msg['content']}",
unsafe_allow_html=True
)
else:
with st.chat_message("assistant"):
st.markdown(
f""
- f"{msg.content}
",
+ f"{msg['content']}",
unsafe_allow_html=True
)
@@ -205,15 +207,15 @@
# Call backend
with st.chat_message("assistant"):
with st.spinner("Thinking..."):
+ st.write("⏳ Generating response...")
response = requests.post(
CHAT_API,
json={
"username": st.session_state.username,
- "message": user_input,
- "messages": st.session_state.messages
+ "message": user_input
}
)
-
+ st.write(response.status_code)
if response.status_code == 200:
assistant_reply = response.json()["response"]
else:
diff --git a/requirements.txt b/requirements.txt
index 195fd4c..02c1649 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,3 +9,6 @@ openai
pydantic
python-dotenv
requests
+groq
+langchain-core
+langchain-groq
From e1286ad0b1face0029f2b0566cff73c00dec2bfc Mon Sep 17 00:00:00 2001
From: Rana <50968377-ranaalmaaz55@users.noreply.replit.com>
Date: Thu, 29 Jan 2026 16:52:43 +0000
Subject: [PATCH 7/8] My updates
---
.gitignore | 8 +-
ai_personal_trainer.zip | Bin 6055 -> 0 bytes
auth.py | 75 ++++++------
backend/personal_trainer_agent.py | 103 -----------------
db.py | 78 -------------
dbSQLAlchemy.py | 22 +---
frontend/step2_streamlit_app.py | 47 --------
main.py | 51 +++-----
my_database.db | Bin 49152 -> 24576 bytes
pages/frontend.py | 185 +++++++++---------------------
replit.md | 34 ------
requirement.txt/fastapi.txt | 6 -
12 files changed, 120 insertions(+), 489 deletions(-)
delete mode 100644 ai_personal_trainer.zip
delete mode 100644 backend/personal_trainer_agent.py
delete mode 100644 db.py
delete mode 100644 frontend/step2_streamlit_app.py
delete mode 100644 replit.md
delete mode 100644 requirement.txt/fastapi.txt
diff --git a/.gitignore b/.gitignore
index 8a5d4a6..21650ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -215,4 +215,10 @@ marimo/_lsp/
__marimo__/
# Streamlit
-.streamlit/secrets.toml
\ No newline at end of file
+.streamlit/secrets.toml
+
+# Replit
+.replit
+replit.nix
+replit.md
+BuildInPublic/
\ No newline at end of file
diff --git a/ai_personal_trainer.zip b/ai_personal_trainer.zip
deleted file mode 100644
index 0dda8d675b9c2010594b6619433018b7b22f649a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 6055
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
ZiugD6B62SR0JzA{J7kBw4`~|!_z#N1S(5+&
diff --git a/auth.py b/auth.py
index 90c186c..24f1488 100644
--- a/auth.py
+++ b/auth.py
@@ -6,42 +6,51 @@
username = st.text_input("Username")
if "session_id" in st.session_state and "username" in st.session_state:
- st.switch_page("pages/frontend.py")
-
+ st.switch_page("pages/frontend.py")
+# Logging in
if st.button("Login"):
- if username:
- st.session_state.session_id = str(uuid.uuid4())
- API_BASE = "http://localhost:8000/login/"
- # API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/login/"
- response = requests.post(API_BASE, json={"username": username, "session_id": st.session_state.session_id})
-
- if response.status_code == 200:
- if response.json()["exists"]:
- st.session_state.username = username
- st.success("Logged in successfully!")
- st.switch_page("pages/frontend.py")
- else:
- st.warning("User not found. Please sign up.")
- else:
+ if username:
+ st.session_state.session_id = str(uuid.uuid4())
+ API_BASE = "http://localhost:8000/login/"
+ response = requests.post(API_BASE,
+ json={
+ "username": username,
+ "session_id": st.session_state.session_id
+ })
+
+ if response.status_code == 200:
+ if response.json()["exists"]:
+ st.session_state.username = username
+ st.success("Logged in successfully!")
+ st.switch_page("pages/frontend.py")
+ else:
+ st.warning("User not found. Please sign up.")
+ else:
st.error("Failed to connect to the server.")
- else:
- st.error("Username is required")
+ else:
+ st.error("Username is required")
+# Signing up
if st.button("Signup"):
- if username:
- st.session_state.session_id = str(uuid.uuid4())
- API_BASE = "http://localhost:8000/signup/"
- # API_BASE = "http://buildinpublic.ranaalmaaz55.repl.co/signup/"
- response = requests.post(API_BASE, json={"username": username, "session_id": st.session_state.session_id})
- if response.status_code == 200:
- if response.json()["exists"]:
- st.warning("Username already exists. Please login or choose a different username.")
- else:
- st.session_state.username = username
- st.success("Signed up successfully!")
- st.switch_page("pages/frontend.py")
- else:
+ if username:
+ st.session_state.session_id = str(uuid.uuid4())
+ API_BASE = "http://localhost:8000/signup/"
+ response = requests.post(API_BASE,
+ json={
+ "username": username,
+ "session_id": st.session_state.session_id
+ })
+ if response.status_code == 200:
+ if response.json()["exists"]:
+ st.warning(
+ "Username already exists. Please login or choose a different username."
+ )
+ else:
+ st.session_state.username = username
+ st.success("Signed up successfully!")
+ st.switch_page("pages/frontend.py")
+ else:
st.error("Failed to connect to the server.")
- else:
- st.error("Username is required")
+ else:
+ st.error("Username is required")
diff --git a/backend/personal_trainer_agent.py b/backend/personal_trainer_agent.py
deleted file mode 100644
index 8c7ada1..0000000
--- a/backend/personal_trainer_agent.py
+++ /dev/null
@@ -1,103 +0,0 @@
-from fastapi import FastAPI
-from fastapi.middleware.cors import CORSMiddleware
-from pydantic import BaseModel
-from dotenv import load_dotenv
-import os
-from groq import Groq
-
-# # Chemin vers le fichier .env (même dossier que ce script)
-# dotenv_path = os.path.join(os.path.dirname(__file__), ".env")
-# load_dotenv(dotenv_path)
-
-# # Vérifier que la clé est présente
-# api_key = os.getenv("OPENAI_API_KEY")
-# if not api_key:
-# raise ValueError("Veuillez définir votre clé OpenAI dans le fichier .env !")
-
-# print("Clé API détectée :", api_key is not None) # juste pour vérifier
-
-# # Créer le client OpenAI avec la clé
-# client = OpenAI(api_key=api_key)
-
-# # Création de l'application FastAPI
-# app = FastAPI()
-
-# app.add_middleware(
-# CORSMiddleware,
-# allow_origins=["*"],
-# allow_credentials=True,
-# allow_methods=["*"],
-# allow_headers=["*"],
-# )
-
-# # Modèle pour les entrées utilisateur
-# class UserInput(BaseModel):
-# goal: str
-# experience: str
-# days: int
-# equipment: str
-
-# # Route pour générer le plan
-# @app.post("/generate_plan")
-# def generate_plan(data: UserInput):
-# if data.days <= 0:
-# return {"error": "Le nombre de jours doit être supérieur à 0"}
-
-# prompt = f"""
-# You are an expert fitness coach.
-# Create a weekly workout plan:
-# - Goal: {data.goal}
-# - Experience: {data.experience}
-# - Days/week: {data.days}
-# - Equipment: {data.equipment}
-# """
-
-# try:
-# response = client.chat.completions.create(
-# model="gpt-4o-mini",
-# messages=[
-# {"role": "system", "content": "You are an expert fitness coach."},
-# {"role": "user", "content": prompt}
-# ]
-# )
-# plan_text = response.choices[0].message["content"]
-# return {"plan": plan_text}
-
-# except Exception as e:
-# return {"error": str(e)}
-
-load_dotenv()
-key = os.getenv("Groq_API")
-client = Groq(api_key=key)
-
-class UserInput(BaseModel):
- goal: str
- experience: str
- days_per_week: int
- equipment: str
-
-app = FastAPI()
-
-@app. post("/generate_plan/")
-def generate_plan(data: UserInput):
- prompt = f"""
- You are an expert fitness coach.
- Create a weekly workout plan:
- - Goal: {data.goal}
- - Experience: {data.experience}
- - Days/week: {data.days}
- - Equipment: {data.equipment}
- """
- try:
- response = client.chat.completions.create(
- model="llama3-8b-8192",
- messages=[
- {"role": "system", "content": "You are an expert fitness coach."},
- {"role": "user", "content": prompt}
- ]
- )
- plan_text = response.choices[0].message.content
- return {"gym_plan": plan_text}
-
- except Exception as e:
- return {"error": str(e)}
\ No newline at end of file
diff --git a/db.py b/db.py
deleted file mode 100644
index bfad719..0000000
--- a/db.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# db.py
-import sqlite3
-from contextlib import closing
-from pathlib import Path
-
-DB_PATH = Path("chat.db")
-
-
-def get_connection():
- """Return a SQLite connection."""
- return sqlite3.connect(DB_PATH, check_same_thread=False)
-
-
-def init_db():
- """Create the users table if it does not exist."""
- with closing(get_connection()) as conn:
- cursor = conn.cursor()
- cursor.execute("""
- CREATE TABLE IF NOT EXISTS users (
- username TEXT PRIMARY KEY,
- session_id TEXT NOT NULL,
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP
- );
-
- CREATE TABLE IF NOT EXISTS chat_messages (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- session_id TEXT NOT NULL,
- role TEXT CHECK(role IN ('user', 'assistant')),
- content TEXT NOT NULL,
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (session_id) REFERENCES users(session_id)
- );
- CREATE TABLE IF NOT EXISTS plans (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- username TEXT NOT NULL,
- session_id TEXT NOT NULL,
- plan_type TEXT,
- content TEXT NOT NULL,
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (username) REFERENCES users(username)
- FOREIGN KEY (session_id) REFERENCES users(session_id),
- FOREIGN KEY (username) REFERENCES users(username)
- );
- CREATE TABLE IF NOT EXISTS user_preferences (
- username TEXT PRIMARY KEY,
- preferences_json TEXT,
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (username) REFERENCES users(username)
- );
- """)
- conn.commit()
-
-
-# CRUD helpers
-def create_user(username: str, session_id: str):
- with closing(get_connection()) as conn:
- cursor = conn.cursor()
- cursor.execute(
- "INSERT INTO users (username, session_id) VALUES (?, ?)",
- (username, session_id))
- conn.commit()
-
-
-def get_user(username: str):
- with closing(get_connection()) as conn:
- cursor = conn.cursor()
- cursor.execute(
- "SELECT username, session_id FROM users WHERE username = ?",
- (username, ))
- return cursor.fetchone()
-
-
-def update_session_id(username: str, session_id: str):
- with closing(get_connection()) as conn:
- cursor = conn.cursor()
- cursor.execute("UPDATE users SET session_id = ? WHERE username = ?",
- (session_id, username))
- conn.commit()
diff --git a/dbSQLAlchemy.py b/dbSQLAlchemy.py
index 2d4504d..c2c2e79 100644
--- a/dbSQLAlchemy.py
+++ b/dbSQLAlchemy.py
@@ -1,14 +1,12 @@
-# db_sqlalchemy.py
from sqlalchemy import Column, String, DateTime, create_engine, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime
-#connrct to db or create if not exists
+#connect to db or create if not exists
engine = create_engine('sqlite:///my_database.db', echo=True)
Base = declarative_base()
-# User model
class User(Base):
__tablename__ = "users"
@@ -25,13 +23,6 @@ class ChatMessage(Base):
content = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
-# class Plan(Base):
-# __tablename__ = "plans"
-
-# id = Column(Integer, primary_key=True, autoincrement=True)
-# username = Column(String, ForeignKey("users.username"), nullable=False)
-# content = Column(String, nullable=False)
-# created_at = Column(DateTime, default=datetime.utcnow)
class UserPreferences(Base):
__tablename__ = "user_preferences"
@@ -77,12 +68,7 @@ def create_chat_message(db_session, username: str, role: str, content: str):
db_session.commit()
db_session.refresh(chat_message)
-# def create_plan(db_session, username: str, session_id: str, content: str):
-# plan = Plan(username=username, session_id=session_id, content=content)
-# db_session.add(plan)
-# db_session.commit()
-# db_session.refresh(plan)
-# return plan
+
def create_user_preferences(db_session, username: str, preferences_json: str):
user_preferences = UserPreferences(username=username, preferences_json=preferences_json)
@@ -105,7 +91,3 @@ def update_user_preferences(db_session, username: str, preferences_json: str):
def get_chat_messages(db_session, username: str):
return db_session.query(ChatMessage).filter_by(username=username).order_by(ChatMessage.created_at.asc()).all()
-
-# def get_plans(db_session, username: str):
-# return db_session.query(Plan).filter_by(username=username).all()
-
diff --git a/frontend/step2_streamlit_app.py b/frontend/step2_streamlit_app.py
deleted file mode 100644
index 420c5d9..0000000
--- a/frontend/step2_streamlit_app.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import streamlit as st
-import requests
-import os
-
-st.set_page_config(page_title="AI Personal Trainer", page_icon="💪")
-st.title("💪 Your AI Personal Trainer")
-st.write(
- "Answer a few questions and get your personalized gym plan instantly.")
-
-with st.form("trainer_form"):
- goal = st.text_input(
- "🎯 What's your fitness goal? (e.g. build muscle, lose fat, stay fit)")
- experience = st.selectbox("🔥 Your experience level:",
- ["Beginner", "Intermediate", "Advanced"])
- days_per_week = st.slider("📅 How many days per week can you train?", 1, 7,
- 4)
- equipment = st.text_area(
- "🏋️ What equipment do you have? (e.g. dumbbells, resistance bands, gym access)"
- )
- submitted = st.form_submit_button("Generate Plan 🚀")
-
-API_URL = "http://localhost:8000/generate_plan/"
-
-if submitted:
- if not goal or not equipment:
- st.warning("⚠️ Please fill in all fields before submitting.")
- else:
- with st.spinner("Generating your gym plan..."):
- try:
- response = requests.post(API_URL,
- json={
- "goal": goal,
- "experience": experience,
- "days_per_week": days_per_week,
- "equipment": equipment
- })
-
- if response.status_code == 200:
- plan = response.json()["gym_plan"]
- st.success("🏋️ Here's your personalized plan:")
- st.markdown(plan)
- else:
- st.error("❌ Something went wrong. Please try again.")
- except requests.exceptions.ConnectionError:
- st.error(
- "❌ Could not connect to the backend. Please make sure the server is running."
- )
diff --git a/main.py b/main.py
index 725b563..2f3c447 100644
--- a/main.py
+++ b/main.py
@@ -8,11 +8,10 @@
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_groq import ChatGroq
from langchain_core.runnables.history import RunnableWithMessageHistory
-# from langchain_core.messages import AIMessage, HumanMessage
+from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.runnables import RunnableSequence
from pydantic import SecretStr
import json
-from langchain.memory import ConversationBufferMemory
load_dotenv()
key = os.getenv("GroqAPI")
@@ -21,15 +20,15 @@
client = Groq(api_key=key)
llm = ChatGroq(temperature=0.7, model="llama-3.1-8b-instant", api_key=SecretStr(key))
-# # Build LangChain memory
-# def build_memory(messages: list):
-# history = [
-# HumanMessage(content=m["content"]) if m["role"] == "user"
-# else AIMessage(content=m["content"])
-# for m in messages
-# ]
+# Build LangChain memory
+def build_memory(messages: list):
+ history = [
+ HumanMessage(content=m["content"]) if m["role"] == "user"
+ else AIMessage(content=m["content"])
+ for m in messages
+ ]
-# return history
+ return history
# Build prompt template
@@ -64,6 +63,8 @@ class UserInput(BaseModel):
days_per_week: int
equipment: str
tone: str
+ weight: int
+ height: int
class ChatInput(BaseModel):
username: str
@@ -77,32 +78,6 @@ class AuthInput(BaseModel):
app = FastAPI()
-# @app.post("/generate_plan/")
-# def generate_plan(data: UserInput):
-# prompt = f"""
-# You are an expert fitness coach.
-# Create a weekly workout plan:
-# - Goal: {data.goal}
-# - Experience: {data.experience}
-# - Days/week: {data.days_per_week}
-# - Equipment: {data.equipment}
-# """
-# try:
-# response = client.chat.completions.create(
-# model="llama3-8b-8192",
-# messages=[{
-# "role": "system",
-# "content": "You are an expert fitness coach."
-# }, {
-# "role": "user",
-# "content": prompt
-# }])
-# plan_text = response.choices[0].message.content
-# return {"gym_plan": plan_text}
-
-# except Exception as e:
-# return {"error": str(e)}
-
@app.post("/login/")
def login(data: AuthInput):
if data.username:
@@ -132,7 +107,9 @@ def update_preferences(data: UserInput):
"experience": data.experience,
"days_per_week": data.days_per_week,
"equipment": data.equipment,
- "tone": data.tone
+ "tone": data.tone,
+ "weight": data.weight,
+ "height": data.height
}
if not db.get_user_preferences(db.session, data.username):
db.create_user_preferences(db.session, data.username, json.dumps(preferences_json))
diff --git a/my_database.db b/my_database.db
index 6a3c51c1a7bbf197a2bbd865803a6a2e08d46dc7..3971ede501f456fe9e9ff410f891c000eff0501f 100644
GIT binary patch
literal 24576
zcmeI4OK;mo5P+#X>_kZFUJUovsSCt$V5)lg5fw!%JG3LzkyA;okwYP@$g#+nB5Ce2
zj#2c`&aNcKa+TK2sR%}pY;hm6v)|6ng3DR8zu65G!eN{a
zgo29op_R*7UjbN_b%Q=L^clad(wA%F3;Lfs_x){OZ&-y_f8L(^!@7R!wKZ3s`}KoQ
zZ@s?#+uMqBIul?5On?b60Vco%m;e)C0!-jC1YXQvn_aN&+{^Ej=!KX`OuI>nhnQmI
zqP%#0eXHfvI}UW}o4XEN%!Rx8n>sBL1B7qut*wXk7Bu%d(A?kMU4i_~bCSDHWgJZ{
zlqH@}=ymDN>H)RYX*_atUC~EqG&|0Y)6$oHj66)o0(8pbR^w5<^#s0lp1|F)8p}Fo
zd#~j*cA7fpO$M}_ZKvflx16@=h&)#*zx?I(nT58UvjS@6xjYW(cCRZk6`Sks#g2DN
z7gJ_l+`2luu(XtWd0@c0zEIr(N=e<26BpMekWOT2o`E;+^#sXr|Hc3&GSfJm&fkqA
zg^`+C$xU$@_6e$i_pUsD{3tiOu&|JOF?VKX#<=8_iSFxe(Lnr*8A;+8#8H>nOtZ4f
z^kmF$IlsJoWoF@vg?}1qIUHZ9@8$LVy>**Dxw)S$dh?43FaajO1egF5U;<2l2`~XB
zzyz286ZoGI*v?&>->NfC(@GCh(pS
zn7ulGQ|}(==l@r3{BF(tLVx(h1egF5U;<2l2{3{8g}|$WE3?-8$3Jz=0~0|Zmr{vH
zQBd!r$Bn(_3Ow1{U;0+Z0)Oo^q4Usz?MAEJfp*7v44u7$dh0hJzI1l-h}0e|cKfN@3LEf38_2ok9^EotIiE+7c;}
z*aJTfz5ME#Uih4Xi*;b`nRYZ(q!%%!A=Z$mYB$1CuEC~oj|`Q~^H4V5j8Ph&oXHks
z5+@kyo)c+fn>6e_f;zPo!nc{F3F1_^M9B1$M)OSzm(rdH8EwJM((p{VOI0Ou2SOWu
zp#FjH2v4O3Ep0SpT-sPV;s|N*2|#FjNKwLEuwmzCHDGkvxObhTN&X#BzphzPs
z5-6H}Lp!Y2U>Eyi(`z4RLQQ2uP6$n9+ggUK)55-#)DjacV0}
zv~}x1`%ByIIY<+7FIeHIPpig!)-FpefcpFVN0OgwUZmS<_9}G^XhQvV`U%oe$UG
zT^~;3^oab#&_}G=r6LT1h=`dP9vc7Siqs2YqbqqeRIX2q3M9`AJBfm|qJ6(eenHPY
zId&_?Pv~OXW1p6!aY9|xhtrKTg{~h3#~Fe)2-C4BGZc)IN~Ess5G-=Zf+o95X5t0p
z`?Mb<2j+$uSs0L5g+XMK!}3XZOezpXnI%a~ZhPc``!s))uLZUh*`a^xrTS2T(L=ja
zjN+{CgA5T9xVvuOCm)ifa(PH8(jbT|EiAA@$3{928|@VsFF2o=1*he}Ueg&aGF!W}
zrnG3SnYzqOKEAK4*H+gHYa7KNfC(@GCcp%k026pu0zV$)X6IiV*DXswGyi^(
ze)?ds2Ib-kEDnFYfvy&}aUeom)M>E@b;_pM+Z}Ew=yZHe+ZloWISP|I+BMcWwACfM
zl-Z^I)g#KR>eA!AUR}5uE4_=N%PQKL)k%+H6+AOr%G4UA4>u-tWv!QQwkheVv{wA#
yZ}Ccp%k025#WOn?b60Vco%m;e*_{}UL;|NjNJU#zhJ
literal 49152
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
jVRZ5ccc+dX;d6ZU="
f"{msg['content']}",
- unsafe_allow_html=True
- )
+ unsafe_allow_html=True)
else:
with st.chat_message("assistant"):
st.markdown(
f""
f"{msg['content']}
",
- unsafe_allow_html=True
- )
+ unsafe_allow_html=True)
- # -------------------------------
- # Input + Send button
- # -------------------------------
+ # Chat input
col1, col2 = st.columns([5, 1])
with col1:
user_input = st.text_input(
"Type your message",
- placeholder="Ask about workouts, nutrition, recovery..."
- )
+ placeholder="Ask about workouts, nutrition, recovery...")
with col2:
send_clicked = st.button("Send ➤")
@@ -201,20 +129,18 @@
st.markdown(
f""
f"{user_input}
",
- unsafe_allow_html=True
- )
+ unsafe_allow_html=True)
# Call backend
with st.chat_message("assistant"):
with st.spinner("Thinking..."):
st.write("⏳ Generating response...")
- response = requests.post(
- CHAT_API,
- json={
- "username": st.session_state.username,
- "message": user_input
- }
- )
+ response = requests.post(CHAT_API,
+ json={
+ "username":
+ st.session_state.username,
+ "message": user_input
+ })
st.write(response.status_code)
if response.status_code == 200:
assistant_reply = response.json()["response"]
@@ -224,8 +150,7 @@
st.markdown(
f""
f"{assistant_reply}
",
- unsafe_allow_html=True
- )
+ unsafe_allow_html=True)
st.session_state.messages.append({
"role": "assistant",
diff --git a/replit.md b/replit.md
deleted file mode 100644
index 55cef4b..0000000
--- a/replit.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# AI Personal Trainer
-
-## Overview
-A full-stack AI application that generates personalized gym workout plans using OpenAI.
-
-## Architecture
-- **Frontend**: Streamlit (port 5000) - User interface for collecting fitness goals
-- **Backend**: FastAPI with uvicorn (port 8000) - API for generating workout plans
-- **AI**: OpenAI GPT-4o-mini via Replit AI Integrations
-
-## Running the Application
-The application is run via `python run.py` which:
-1. Starts the FastAPI backend on localhost:8000
-2. Starts the Streamlit frontend on 0.0.0.0:5000
-
-## Project Structure
-```
-├── api.py # FastAPI backend with OpenAI integration
-├── frontend.py # Streamlit frontend
-├── run.py # Launcher script for both services
-├── main.py # CLI version (not used in web app)
-├── requirements.txt
-└── replit.md
-```
-
-## Dependencies
-- fastapi, uvicorn - Web API framework
-- streamlit - Frontend framework
-- openai - AI integration (uses Replit AI Integrations)
-- pydantic - Data validation
-
-## Notes
-- OpenAI access is provided through Replit AI Integrations (no API key needed)
-- Backend runs on localhost, frontend binds to 0.0.0.0 for Replit proxy access
diff --git a/requirement.txt/fastapi.txt b/requirement.txt/fastapi.txt
deleted file mode 100644
index 8e559cf..0000000
--- a/requirement.txt/fastapi.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-fastapi
-uvicorn
-openai
-python-dotenv
-streamlit
-requests
From b491e722848dc527f0391a6df1e6bc35ae0f779a Mon Sep 17 00:00:00 2001
From: Rana <50968377-ranaalmaaz55@users.noreply.replit.com>
Date: Thu, 29 Jan 2026 17:35:39 +0000
Subject: [PATCH 8/8] Final
---
.replit | 54 -------------------------------------------------
.sample.env | 1 -
my_database.db | Bin 24576 -> 0 bytes
3 files changed, 55 deletions(-)
delete mode 100644 .replit
delete mode 100644 .sample.env
delete mode 100644 my_database.db
diff --git a/.replit b/.replit
deleted file mode 100644
index b9f4c9b..0000000
--- a/.replit
+++ /dev/null
@@ -1,54 +0,0 @@
-modules = ["python-3.11"]
-[agent]
-expertMode = true
-integrations = ["python_openai_ai_integrations:1.0.0"]
-
-[nix]
-channel = "stable-25_05"
-packages = ["glibcLocales", "libxcrypt", "mailutils"]
-
-[workflows]
-runButton = "Project"
-
-[[workflows.workflow]]
-name = "Project"
-mode = "parallel"
-author = "agent"
-
-[[workflows.workflow.tasks]]
-task = "workflow.run"
-args = "AI Personal Trainer"
-
-[[workflows.workflow]]
-name = "AI Personal Trainer"
-author = "agent"
-
-[[workflows.workflow.tasks]]
-task = "shell.exec"
-args = "python run.py"
-waitForPort = 5000
-
-[workflows.workflow.metadata]
-outputType = "webview"
-
-[[ports]]
-localPort = 3000
-externalPort = 3000
-
-[[ports]]
-localPort = 5000
-externalPort = 80
-
-[[ports]]
-localPort = 8000
-
-[[ports]]
-localPort = 8080
-externalPort = 8080
-
-[[ports]]
-localPort = 8501
-
-[deployment]
-run = "bash start.sh"
-
diff --git a/.sample.env b/.sample.env
deleted file mode 100644
index ac74257..0000000
--- a/.sample.env
+++ /dev/null
@@ -1 +0,0 @@
-OPENAI_API_KEY=''
\ No newline at end of file
diff --git a/my_database.db b/my_database.db
deleted file mode 100644
index 3971ede501f456fe9e9ff410f891c000eff0501f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 24576
zcmeI4OK;mo5P+#X>_kZFUJUovsSCt$V5)lg5fw!%JG3LzkyA;okwYP@$g#+nB5Ce2
zj#2c`&aNcKa+TK2sR%}pY;hm6v)|6ng3DR8zu65G!eN{a
zgo29op_R*7UjbN_b%Q=L^clad(wA%F3;Lfs_x){OZ&-y_f8L(^!@7R!wKZ3s`}KoQ
zZ@s?#+uMqBIul?5On?b60Vco%m;e)C0!-jC1YXQvn_aN&+{^Ej=!KX`OuI>nhnQmI
zqP%#0eXHfvI}UW}o4XEN%!Rx8n>sBL1B7qut*wXk7Bu%d(A?kMU4i_~bCSDHWgJZ{
zlqH@}=ymDN>H)RYX*_atUC~EqG&|0Y)6$oHj66)o0(8pbR^w5<^#s0lp1|F)8p}Fo
zd#~j*cA7fpO$M}_ZKvflx16@=h&)#*zx?I(nT58UvjS@6xjYW(cCRZk6`Sks#g2DN
z7gJ_l+`2luu(XtWd0@c0zEIr(N=e<26BpMekWOT2o`E;+^#sXr|Hc3&GSfJm&fkqA
zg^`+C$xU$@_6e$i_pUsD{3tiOu&|JOF?VKX#<=8_iSFxe(Lnr*8A;+8#8H>nOtZ4f
z^kmF$IlsJoWoF@vg?}1qIUHZ9@8$LVy>**Dxw)S$dh?43FaajO1egF5U;<2l2`~XB
zzyz286ZoGI*v?&>->NfC(@GCh(pS
zn7ulGQ|}(==l@r3{BF(tLVx(h1egF5U;<2l2{3{8g}|$WE3?-8$3Jz=0~0|Zmr{vH
zQBd!r$Bn(_3Ow1{U;0+Z0)Oo^q4Usz?MAEJfp*7v44u7$dh0hJzI1l-h}0e|cKfN@3LEf38_2ok9^EotIiE+7c;}
z*aJTfz5ME#Uih4Xi*;b`nRYZ(q!%%!A=Z$mYB$1CuEC~oj|`Q~^H4V5j8Ph&oXHks
z5+@kyo)c+fn>6e_f;zPo!nc{F3F1_^M9B1$M)OSzm(rdH8EwJM((p{VOI0Ou2SOWu
zp#FjH2v4O3Ep0SpT-sPV;s|N*2|#FjNKwLEuwmzCHDGkvxObhTN&X#BzphzPs
z5-6H}Lp!Y2U>Eyi(`z4RLQQ2uP6$n9+ggUK)55-#)DjacV0}
zv~}x1`%ByIIY<+7FIeHIPpig!)-FpefcpFVN0OgwUZmS<_9}G^XhQvV`U%oe$UG
zT^~;3^oab#&_}G=r6LT1h=`dP9vc7Siqs2YqbqqeRIX2q3M9`AJBfm|qJ6(eenHPY
zId&_?Pv~OXW1p6!aY9|xhtrKTg{~h3#~Fe)2-C4BGZc)IN~Ess5G-=Zf+o95X5t0p
z`?Mb<2j+$uSs0L5g+XMK!}3XZOezpXnI%a~ZhPc``!s))uLZUh*`a^xrTS2T(L=ja
zjN+{CgA5T9xVvuOCm)ifa(PH8(jbT|EiAA@$3{928|@VsFF2o=1*he}Ueg&aGF!W}
zrnG3SnYzqOKEAK4*H+gHYa7KNfC(@GCcp%k026pu0zV$)X6IiV*DXswGyi^(
ze)?ds2Ib-kEDnFYfvy&}aUeom)M>E@b;_pM+Z}Ew=yZHe+ZloWISP|I+BMcWwACfM
zl-Z^I)g#KR>eA!AUR}5uE4_=N%PQKL)k%+H6+AOr%G4UA4>u-tWv!QQwkheVv{wA#
yZ}Ccp%k025#WOn?b60Vco%m;e*_{}UL;|NjNJU#zhJ