Esp32 / app.py
huynhkimthien's picture
Update app.py
e4cdaf0 verified
from fastapi import FastAPI, Request
from pydantic import BaseModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from datetime import datetime
from zoneinfo import ZoneInfo
import httpx
from functools import lru_cache
app = FastAPI()
# --- Tải model ---
MODEL_NAME = "Qwen/Qwen2.5-1.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
device_map="auto"
)
# --- Request body ---
class GenerateRequest(BaseModel):
prompt: str | list[str]
# --- Cache IP info ---
@lru_cache(maxsize=100)
def cache_location(ip: str, city: str, country: str, timezone: str):
return city, country, timezone
# --- Hàm lấy vị trí từ IP ---
async def get_location_from_ip(ip: str):
try:
async with httpx.AsyncClient(timeout=3) as client:
res = await client.get(f"https://ipinfo.io/{ip}?token=2d478668dc5662")
data = res.json()
city = data.get("city", "Ho Chi Minh City")
country = data.get("country", "VN")
timezone = data.get("timezone", "Asia/Ho_Chi_Minh")
cache_location(ip, city, country, timezone)
return city, country, timezone
except:
return "Ho Chi Minh City", "VN", "Asia/Ho_Chi_Minh"
# --- Cache thời tiết ---
@lru_cache(maxsize=100)
def cache_weather(city: str, desc: str, temp: float):
return desc, temp
async def get_weather(city: str):
try:
api_key = "b7d49ff5de091794a9adc8ea62ef0ac7"
async with httpx.AsyncClient(timeout=3) as client:
url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric&lang=vi"
res = await client.get(url)
data = res.json()
temp = data["main"]["temp"]
desc = data["weather"][0]["description"]
cache_weather(city, desc, temp)
return desc, temp
except:
return None, None
@app.get("/")
def home():
return {"message": "API FastAI đã sẵn sàng phục vụ Túc chủ 👑"}
@app.post("/generate")
async def generate(req: GenerateRequest, request: Request):
prompt = req.prompt
if isinstance(prompt, list):
prompt = " ".join(prompt)
# Lấy IP từ request
client_ip = request.client.host
city, country, timezone = await get_location_from_ip(client_ip)
# --- Logic đặc biệt ---
# 1. Thời gian hiện tại
if "mấy giờ" in prompt or "thời gian" in prompt:
tz = ZoneInfo(timezone)
current_time = datetime.now(tz).strftime("%H:%M")
return {"response": f"Bây giờ ở {city}{current_time}"}
# 2. Ngày hôm nay
if "ngày hôm nay" in prompt or "hôm nay là ngày" in prompt:
tz = ZoneInfo(timezone)
today = datetime.now(tz).strftime("%d/%m/%Y")
return {"response": f"Hôm nay ở {city} là ngày {today}"}
# 3. Thời tiết
if "thời tiết" in prompt:
desc, temp = await get_weather(city)
if desc and temp:
return {"response": f"Thời tiết ở {city}: {desc}, nhiệt độ {temp}°C"}
else:
return {"response": "Không lấy được dữ liệu thời tiết."}
# --- Fallback sang mô hình ---
final_prompt = f"Trả lời bằng tiếng Việt, ngắn gọn, đầy đủ câu, không lặp lại câu hỏi và tiêu đề trang trích dẫn: {prompt}"
inputs = tokenizer(final_prompt, return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=250, # Giảm để tăng tốc
temperature=0.5,
top_p=0.8,
do_sample=True,
repetition_penalty=1.3,
eos_token_id=tokenizer.eos_token_id,
pad_token_id=tokenizer.pad_token_id
)
result = tokenizer.decode(outputs[0], skip_special_tokens=True)
clean_result = result[len(final_prompt):].strip()
if not clean_result.endswith((".", "!", "?")):
clean_result += "..."
return {"response": clean_result}