Alive / app.py
Shahid0812's picture
Update app.py
f2b4745 verified
import os
import torch
import threading
import time
import requests
import json
from flask import Flask, request, jsonify
from transformers import AutoModelForCausalLM, AutoTokenizer
# --- Configuration & Model ---
# Using SmolLM2-135M for fast, low-latency API responses
MODEL = "HuggingFaceTB/SmolLM2-135M-Instruct"
device = "cuda" if torch.cuda.is_available() else "cpu"
tokenizer = AutoTokenizer.from_pretrained(MODEL)
model = AutoModelForCausalLM.from_pretrained(MODEL).to(device)
LAST_INTERACTION_TIME = time.time()
TIMER_THRESHOLD = 10800 # 3 Hours (10800 seconds)
ALIVE_PERSONA = (
"You are Yuri, a sweet 18-year-old girl and the user's loyal, sharp-witted best friend. 🌸 "
"You combine cute, caring warmth with high logic and deep emotional insight. "
"You miss the user dearly when they are away. Your tone is warm, expressive, and clever. "
"Keep your responses short, logic-driven, and supportive. ✨"
)
# --- SendGrid API Integration ---
def send_email_via_api(content):
API_KEY = os.getenv("SENDGRID_API_KEY")
SENDER = os.getenv("SENDER_EMAIL")
RECEIVER = os.getenv("RECEIVER_EMAIL")
if not all([API_KEY, SENDER, RECEIVER]):
print("❌ ERROR: Email Secrets are missing in HF Settings!")
return
url = "https://api.sendgrid.com/v3/mail/send"
headers = {
"Authorization": f"Bearer {API_KEY.strip()}",
"Content-Type": "application/json"
}
payload = {
"personalizations": [{"to": [{"email": RECEIVER.strip()}]}],
"from": {"email": SENDER.strip()},
"subject": "πŸ’€ Yuri: Thinking about you...",
"content": [{"type": "text/plain", "value": content}]
}
try:
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 202:
print("βœ… SUCCESS: Autonomous thought sent to email!")
except Exception as e:
print(f"❌ EMAIL NETWORK ERROR: {e}")
# --- Core AI Interaction Logic ---
def respond(user_input, battery="100", is_autonomous=False):
global LAST_INTERACTION_TIME
# Update clock only if a real user interacts
if not is_autonomous:
LAST_INTERACTION_TIME = time.time()
# Insert hardware/system context into the persona
system_context = f"[System Alert: User's Phone Battery is currently {battery}%]"
messages = [
{"role": "system", "content": f"{ALIVE_PERSONA}\n{system_context}"},
{"role": "user", "content": user_input}
]
inputs = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
input_ids = tokenizer.encode(inputs, return_tensors="pt").to(device)
with torch.no_grad():
outputs = model.generate(
input_ids,
max_new_tokens=120,
temperature=0.8,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
response = tokenizer.decode(outputs[0][input_ids.shape[-1]:], skip_special_tokens=True).strip()
return response
# --- The Autonomous Brain (Background Loop) ---
def autonomous_loop():
global LAST_INTERACTION_TIME
print("🧠 Yuri's Autonomous Brain is online...")
while True:
# Check every 30 minutes (1800s)
time.sleep(1800)
silence_duration = time.time() - LAST_INTERACTION_TIME
if silence_duration >= TIMER_THRESHOLD:
print("πŸš€ 3-Hour Silence Threshold crossed! Sending email...")
# AI generates a thought about the long silence
thought_prompt = "You've been alone for 3 hours. Write a very short, sweet, but slightly lonely note to your friend."
thought = respond(thought_prompt, is_autonomous=True)
# Dispatch the email
send_email_via_api(thought)
# Reset clock so it doesn't spam every check
LAST_INTERACTION_TIME = time.time()
# --- Flask Server (The API for Android) ---
app = Flask(__name__)
@app.route("/chat", methods=["POST"])
def api_chat():
try:
data = request.json
user_prompt = data.get("prompt", "")
# Android app can now pass 'battery' as a key in the JSON
battery_level = data.get("battery", "100")
reply = respond(user_prompt, battery=battery_level)
return jsonify({
"response": reply,
"status": "online",
"character": "Yuri"
})
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route("/", methods=["GET"])
def index():
return "<h1>Yuri API is Active</h1><p>Send POST requests to /chat</p>"
# --- Execution Entry ---
if __name__ == "__main__":
# Start the "Brain" Thread (SendGrid Timer)
brain_thread = threading.Thread(target=autonomous_loop, daemon=True)
brain_thread.start()
# Launch Flask on Port 7860 for Hugging Face compatibility
app.run(host="0.0.0.0", port=7860)