Fristtry01 / app.py
proti0070's picture
Update app.py
fde406c verified
import gradio as gr
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import logging
import time
import os
import sys
import traceback
from typing import Optional
import psutil
# লগিং কনফিগারেশন
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger(__name__)
# ============================================
# Hugging Face মডেল কনফিগারেশন
# ============================================
# সরাসরি Hugging Face থেকে মডেল
MODEL_NAME = "Qwen/Qwen3-0.6B" # এই মডেলটি Hugging Face এ আছে
# ============================================
# FastAPI অ্যাপ
# ============================================
app = FastAPI(
title="Qwen3-0.6B API from Hugging Face",
description="Hugging Face থেকে সরাসরি লোড করা Qwen3-0.6B মডেল",
version="1.0.0"
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# গ্লোবাল ভেরিয়েবল
model = None
tokenizer = None
model_loaded = False
load_error = None
load_time = None
# Pydantic মডেল
class GenerationRequest(BaseModel):
prompt: str
max_length: Optional[int] = 200
temperature: Optional[float] = 0.7
class GenerationResponse(BaseModel):
success: bool
prompt: str
generated_text: str
model_name: str
inference_time: float
device_used: str
model_source: str = "Hugging Face"
# ============================================
# Hugging Face থেকে মডেল লোড করার ফাংশন
# ============================================
def load_model_from_huggingface():
"""Hugging Face থেকে সরাসরি মডেল লোড করা"""
global model, tokenizer, model_loaded, load_error, load_time
try:
start_load = time.time()
logger.info("=" * 60)
logger.info("🤗 Hugging Face থেকে মডেল লোড করা শুরু")
logger.info("=" * 60)
logger.info(f"মডেল: {MODEL_NAME}")
logger.info(f"প্ল্যাটফর্ম: Hugging Face Hub")
# সিস্টেম ইনফো
logger.info(f"পাইথন: {sys.version}")
logger.info(f"PyTorch: {torch.__version__}")
logger.info(f"CPU Cores: {psutil.cpu_count()}")
memory = psutil.virtual_memory()
logger.info(f"RAM: {memory.total / (1024**3):.2f} GB")
# Hugging Face কানেকশন টেস্ট
logger.info("🔗 Hugging Face এ কানেক্ট করা হচ্ছে...")
# Step 1: টোকেনাইজার লোড
logger.info("📝 Step 1/3: টোকেনাইজার লোড করা হচ্ছে...")
logger.info(f"হাগিং ফেস থেকে ফেচ: {MODEL_NAME}")
tokenizer = AutoTokenizer.from_pretrained(
MODEL_NAME,
trust_remote_code=True,
use_fast=True
)
logger.info("✅ টোকেনাইজার লোড হয়েছে")
# Step 2: Padding token সেট করা
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
logger.info("✅ Pad token সেট করা হয়েছে")
# Step 3: মডেল লোড
logger.info("🤖 Step 2/3: মডেল লোড করা হচ্ছে...")
logger.info(f"হাগিং ফেস থেকে ডাউনলোড: {MODEL_NAME}")
# CPU-র জন্য অপ্টিমাইজড লোডিং
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
trust_remote_code=True,
torch_dtype=torch.float32,
low_cpu_mem_usage=True,
use_cache=True
)
logger.info("✅ মডেল ডাউনলোড সম্পন্ন")
# Step 4: মডেল CPU-তে সেট করা
logger.info("💻 Step 3/3: মডেল CPU-তে সেট করা হচ্ছে...")
model.eval()
logger.info("✅ মডেল ready")
# লোড টাইম
load_time = time.time() - start_load
logger.info(f"✅ মডেল সফলভাবে লোড হয়েছে!")
logger.info(f"⏱ লোড টাইম: {load_time:.2f} সেকেন্ড")
logger.info(f"📊 মডেল সাইজ: {model.num_parameters():,} প্যারামিটার")
# টেস্ট ইনফারেন্স
logger.info("🧪 টেস্ট ইনফারেন্স চলছে...")
test_prompt = "Hello"
inputs = tokenizer(test_prompt, return_tensors="pt")
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=5,
do_sample=False
)
test_output = tokenizer.decode(outputs[0], skip_special_tokens=True)
logger.info(f"✅ টেস্ট সফল: '{test_prompt}' -> '{test_output}'")
model_loaded = True
return True
except Exception as e:
load_error = str(e)
logger.error(f"❌ Hugging Face থেকে মডেল লোড করতে সমস্যা: {str(e)}")
logger.error(traceback.format_exc())
# ডিটেইলড এরর
if "404" in str(e):
logger.error("মডেলটি Hugging Face এ খুঁজে পাওয়া যায়নি। নাম চেক করুন: Qwen/Qwen3-0.6B")
elif "connection" in str(e).lower():
logger.error("Hugging Face এ কানেক্ট করা যাচ্ছে না। ইন্টারনেট চেক করুন")
elif "memory" in str(e).lower():
logger.error("RAM কম! মডেল লোড করার জন্য পর্যাপ্ত মেমোরি নেই")
return False
# Startup ইভেন্ট
@app.on_event("startup")
async def startup_event():
"""অ্যাপ স্টার্টআপে Hugging Face থেকে মডেল লোড"""
success = load_model_from_huggingface()
if success:
logger.info("🚀 সার্ভার চালু হয়েছে - Hugging Face মডেল ready")
else:
logger.error("❌ সার্ভার চালু হয়েছে কিন্তু মডেল লোড হয়নি")
# ============================================
# API এন্ডপয়েন্ট
# ============================================
@app.get("/health")
async def health_check():
"""হেলথ চেক - মডেলের অবস্থা দেখায়"""
memory = psutil.virtual_memory()
return {
"status": "healthy" if model_loaded else "unhealthy",
"model": {
"name": MODEL_NAME,
"loaded": model_loaded,
"source": "Hugging Face",
"load_time": load_time,
"parameters": model.num_parameters() if model else None
},
"system": {
"device": "cpu",
"cpu_cores": psutil.cpu_count(),
"ram_total_gb": round(memory.total / (1024**3), 2),
"ram_available_gb": round(memory.available / (1024**3), 2),
"ram_used_percent": memory.percent
},
"error": load_error if not model_loaded else None,
"timestamp": time.time()
}
@app.get("/generate", response_model=GenerationResponse)
async def generate_text_get(
prompt: str = Query(..., description="আপনার প্রশ্ন/প্রম্পট"),
max_length: Optional[int] = Query(200, description="জেনারেট করার সর্বোচ্চ দৈর্ঘ্য"),
temperature: Optional[float] = Query(0.7, description="টেম্পারেচার (0-1)")
):
"""GET Method - Hugging Face মডেল দিয়ে টেক্সট জেনারেশন"""
if not model_loaded or model is None or tokenizer is None:
error_msg = load_error if load_error else "মডেল লোড হয়নি"
raise HTTPException(status_code=503, detail=f"Hugging Face মডেল লোড হয়নি: {error_msg}")
try:
start_time = time.time()
logger.info(f"📥 প্রম্পট: {prompt[:100]}...")
# ইনপুট টোকেনাইজ
inputs = tokenizer(
prompt,
return_tensors="pt",
truncation=True,
max_length=512
)
input_tokens = inputs['input_ids'].shape[1]
logger.info(f"ইনপুট টোকেন: {input_tokens}")
# জেনারেশন
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=max_length,
temperature=temperature,
do_sample=True if temperature > 0 else False,
top_p=0.9,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id
)
# ডিকোড
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
# প্রম্পট বাদ দিয়ে শুধু জেনারেটেড টেক্সট
if generated_text.startswith(prompt):
generated_text = generated_text[len(prompt):].strip()
output_tokens = outputs.shape[1] - input_tokens
inference_time = time.time() - start_time
logger.info(f"✅ জেনারেটেড: {len(generated_text)} chars, {output_tokens} tokens, {inference_time:.2f}s")
return GenerationResponse(
success=True,
prompt=prompt,
generated_text=generated_text,
model_name=MODEL_NAME,
inference_time=round(inference_time, 3),
device_used="cpu",
model_source="Hugging Face"
)
except Exception as e:
logger.error(f"জেনারেশন এরর: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
# ============================================
# Gradio UI (Hugging Face Space এর জন্য)
# ============================================
def generate_with_gradio(prompt, max_length, temperature):
"""Gradio UI এর জন্য জেনারেশন ফাংশন"""
if not model_loaded:
return f"❌ মডেল লোড হয়নি: {load_error}", 0
try:
start_time = time.time()
inputs = tokenizer(prompt, return_tensors="pt")
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=int(max_length),
temperature=float(temperature),
do_sample=True if temperature > 0 else False,
top_p=0.9,
pad_token_id=tokenizer.pad_token_id,
eos_token_id=tokenizer.eos_token_id
)
generated = tokenizer.decode(outputs[0], skip_special_tokens=True)
if generated.startswith(prompt):
generated = generated[len(prompt):].strip()
inference_time = time.time() - start_time
return generated, round(inference_time, 3)
except Exception as e:
return f"❌ Error: {str(e)}", 0
# Gradio UI তৈরি
with gr.Blocks(title="Qwen3-0.6B from Hugging Face", theme=gr.themes.Soft()) as demo:
gr.Markdown(f"""
# 🤗 Hugging Face মডেল: {MODEL_NAME}
এই মডেলটি সরাসরি Hugging Face থেকে লোড করা হয়েছে।
""")
with gr.Row():
with gr.Column(scale=2):
prompt_input = gr.Textbox(
label="আপনার প্রম্পট",
placeholder="এখানে লিখুন...",
lines=3
)
with gr.Row():
max_length_slider = gr.Slider(50, 500, value=200, label="Max Length")
temp_slider = gr.Slider(0.1, 1.5, value=0.7, label="Temperature")
generate_btn = gr.Button("🚀 Generate", variant="primary")
# Status
model_status = gr.Label(
value=f"✅ {MODEL_NAME} লোড হয়েছে" if model_loaded else f"❌ মডেল লোড হয়নি",
label="মডেল স্ট্যাটাস"
)
with gr.Column(scale=2):
output_text = gr.Textbox(label="Generated Text", lines=10)
inference_time = gr.Number(label="Time (seconds)")
generate_btn.click(
fn=generate_with_gradio,
inputs=[prompt_input, max_length_slider, temp_slider],
outputs=[output_text, inference_time]
)
gr.Markdown(f"""
## 🌐 API Endpoints
**মডেল সোর্স:** Hugging Face 🤗
**মডেল নাম:** {MODEL_NAME}
### GET Request:
```
/generate?prompt=Hello&max_length=100&temperature=0.7
```
### Response:
```json
{{
"success": true,
"prompt": "Hello",
"generated_text": "World",
"model_name": "Qwen/Qwen3-0.6B",
"model_source": "Hugging Face",
"inference_time": 0.5
}}
```
### Health Check:
```
/health
```
""")
# Hugging Face Space এ মাউন্ট
gr.mount_gradio_app(app, demo, path="/")
# ============================================
# রুট এন্ডপয়েন্ট
# ============================================
@app.get("/")
async def root():
"""API রুট"""
return {
"name": "Qwen3-0.6B API",
"source": "Hugging Face 🤗",
"model": MODEL_NAME,
"status": "loaded" if model_loaded else f"error: {load_error}",
"endpoints": {
"GET /health": "Health check",
"GET /generate?prompt=Hello": "Generate text",
"GET /": "This info",
"UI": "/ (Gradio UI)"
},
"docs": "/docs"
}
@app.get("/model-info")
async def model_info():
"""মডেল সম্পর্কে বিস্তারিত তথ্য"""
if not model:
raise HTTPException(status_code=503, detail="মডেল লোড হয়নি")
return {
"model_name": MODEL_NAME,
"source": "Hugging Face",
"parameters": model.num_parameters(),
"device": "cpu",
"tokenizer": tokenizer.__class__.__name__,
"vocab_size": tokenizer.vocab_size,
"hf_link": f"https://huggingface.co/{MODEL_NAME}"
}