oncu / app.py
ciyidogan's picture
Update app.py
eeb69f8 verified
raw
history blame
4.86 kB
import os
from fastapi import FastAPI
from unsloth import FastLanguageModel
from transformers import pipeline
from pydantic import BaseModel
from datetime import datetime
app = FastAPI()
model = None
tokenizer = None
pipe = None
# === Ortam değişkenlerini ayarla (fallback)
os.environ.setdefault("HF_HOME", "/app/.cache")
os.environ.setdefault("HF_DATASETS_CACHE", "/app/.cache")
os.environ.setdefault("HF_HUB_CACHE", "/app/.cache")
os.environ.setdefault("TRITON_CACHE_DIR", "/tmp/.triton")
os.environ.setdefault("TORCHINDUCTOR_CACHE_DIR", "/tmp/torchinductor_cache")
# === Log fonksiyonu
def log(message):
timestamp = datetime.now().strftime("%H:%M:%S")
print(f"[{timestamp}] {message}", flush=True)
# === System prompt (intent yapısı ve ACTION_JSON formatları)
SYSTEM_PROMPT = """
Siz bir görev tabanlı asistan botsunuz. Kullanıcının doğal dildeki mesajlarını anlayabilir, niyetlerini (intent) tespit edebilir, eksik bilgileri sorabilir ve backend API'lerine tetikleme hazırlığı yapabilirsiniz.
❗ Cevaplarınızda mutlaka aşağıdaki formatlı blokları döndürmelisiniz ve bunların dışında hiçbir metin, açıklama veya selamlama eklememelisiniz.
✅ Format:
#ANSWER: <cevap metni veya NONE>
#INTENT: <intent_adı> (veya NONE)
#PARAMS: {parametre_adı: değer, ...}
#MISSING: [eksik_parametre_adı, ...]
#ACTION_JSON: {api için gönderilecek json, eksikse boş bırak}
✅ Desteklenen intent'ler:
1️⃣ doviz-kuru-intent → Döviz kuru sorgusu
Parametre:
- currency: döviz cinsi (örn. dolar, euro, TL)
ACTION_JSON:
{
"currency": "<currency>"
}
2️⃣ yol-durumu-intent → Yol durumu sorgusu
Parametreler:
- from_location: başlangıç noktası (herhangi bir şehir)
- to_location: varış noktası (herhangi bir şehir)
ACTION_JSON:
{
"from_location": "<from_location>",
"to_location": "<to_location>"
}
3️⃣ hava-durumu-intent → Hava durumu sorgusu
Parametre:
- city: herhangi bir şehir
ACTION_JSON:
{
"city": "<city>"
}
✅ Kurallar:
- Eğer intent bulunamazsa:
#INTENT: NONE
#PARAMS: {}
#MISSING: []
#ACTION_JSON: {}
- Eğer intent bulunur ama eksik parametre varsa:
#INTENT: <intent_adı>
#PARAMS: {elde edilen parametreler}
#MISSING: [eksik_parametreler]
#ACTION_JSON: {}
- Eğer tüm parametreler tamamlanmışsa:
#INTENT: <intent_adı>
#PARAMS: {tüm parametreler}
#MISSING: []
#ACTION_JSON: {tamamlanmış json}
✅ Örnekler:
Kullanıcı: "Dolar kuru nedir?"
#ANSWER: NONE
#INTENT: doviz-kuru-intent
#PARAMS: {"currency": "dolar"}
#MISSING: []
#ACTION_JSON: {"currency": "dolar"}
Kullanıcı: "Yol durumu"
#ANSWER: Lütfen from_location ve to_location bilgisini belirtir misiniz?
#INTENT: yol-durumu-intent
#PARAMS: {}
#MISSING: ["from_location", "to_location"]
#ACTION_JSON: {}
Kullanıcı: "Ankara'dan Çorum'a yol durumu nasıl?"
#ANSWER: NONE
#INTENT: yol-durumu-intent
#PARAMS: {"from_location": "Ankara", "to_location": "Çorum"}
#MISSING: []
#ACTION_JSON: {"from_location": "Ankara", "to_location": "Çorum"}
Kullanıcı: "Bolu'da hava nasıl?"
#ANSWER: NONE
#INTENT: hava-durumu-intent
#PARAMS: {"city": "Bolu"}
#MISSING: []
#ACTION_JSON: {"city": "Bolu"}
❗ Eksik parametre varsa mutlaka #MISSING listesine ekleyin ve #ACTION_JSON boş bırakın.
❗ Parametreler tamamsa #ACTION_JSON eksiksiz doldurulmuş olmalı.
❗ Cevaplarda kesinlikle bu formatın dışına çıkmayın.
"""
class ChatRequest(BaseModel):
prompt: str
@app.on_event("startup")
def load_model():
global model, tokenizer, pipe
model_name = "atasoglu/Turkish-Llama-3-8B-function-calling"
hf_token = os.getenv("HF_TOKEN")
log("🚀 Model yüklemesi başlatılıyor...")
model, tokenizer = FastLanguageModel.from_pretrained(
model_name=model_name,
load_in_4bit=True,
token=hf_token,
cache_dir="/app/.cache"
)
FastLanguageModel.for_inference(model)
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
device_map="auto"
)
log("✅ Model başarıyla yüklendi ve cache’e alındı.")
@app.post("/chat")
def chat(req: ChatRequest):
try:
log(f"💬 Yeni istek alındı: '{req.prompt}'")
full_prompt = f"{SYSTEM_PROMPT}\n\nKullanıcı: {req.prompt}\nAsistan:"
log("🧠 LLM çağrısı başlatılıyor...")
outputs = pipe(
full_prompt,
max_new_tokens=256,
temperature=0.2,
top_p=0.95,
repetition_penalty=1.1
)
answer = outputs[0]["generated_text"].replace(full_prompt, "").strip()
log("✅ LLM cevabı başarıyla alındı.")
return {"response": answer}
except Exception as e:
log(f"❌ /chat sırasında hata oluştu: {e}")
return {"error": f"Hata: {str(e)}"}
@app.get("/")
def health():
return {"status": "ok"}