File size: 3,579 Bytes
3e66fd0
 
7460785
 
2f0b1a7
8ab22e1
3e66fd0
 
7460785
 
 
3e66fd0
d2ee4b2
 
 
 
 
 
 
47ff742
 
 
 
3e66fd0
d2ee4b2
2f0b1a7
 
104b35b
2f0b1a7
104b35b
2f0b1a7
ec0184d
2f0b1a7
 
 
 
104b35b
 
 
d2ee4b2
104b35b
 
 
 
 
d2ee4b2
104b35b
 
 
 
 
 
d2ee4b2
104b35b
 
 
 
 
 
2f0b1a7
 
 
 
 
 
3e66fd0
 
7460785
47ff742
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e66fd0
2f0b1a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a0585f
 
 
 
 
 
 
 
ec0184d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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 ve ACTION_JSON formatları:
1️⃣ doviz-kuru-intent → Döviz kuru sorgusu
ACTION_JSON:
{
  "currency": "<currency>"
}

2️⃣ yol-durumu-intent → Yol durumu sorgusu
ACTION_JSON:
{
  "from_location": "<from_location>",
  "to_location": "<to_location>"
}

3️⃣ hava-durumu-intent → Hava durumu sorgusu
ACTION_JSON:
{
  "city": "<city>"
}

❗ Eksik parametre varsa, sadece eksik olanları #MISSING listesine ekleyiniz ve #ACTION_JSON boş döndürünüz.
❗ Parametreler tamamsa, ilgili ACTION_JSON formatına uygun json hazırlayınız.
❗ Kullanıcıya hitap ederken formal bir dil kullanınız, sadece bu formatlı blokları döndürünüz.
"""

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"}