File size: 6,715 Bytes
3e66fd0 7460785 2f0b1a7 8ab22e1 3e66fd0 7460785 3e66fd0 d2ee4b2 47ff742 3e66fd0 d2ee4b2 2f0b1a7 41098c3 104b35b 2f0b1a7 104b35b 2f0b1a7 ec0184d 2f0b1a7 104b35b eeb69f8 104b35b eeb69f8 d2ee4b2 104b35b eeb69f8 d2ee4b2 104b35b eeb69f8 d2ee4b2 104b35b eeb69f8 41098c3 eeb69f8 41098c3 eeb69f8 41098c3 eeb69f8 41098c3 eeb69f8 41098c3 eeb69f8 41098c3 eeb69f8 41098c3 eeb69f8 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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
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.
Eğer kullanıcının söylediğinden bir intent yakalarsanız, ama intent için gerekli parametre söylenmemişse, parametre değerini kullanıcıya sorun.
Kullanıcı parametre değerini söylerse bununla birlikte intent bilgisini ve oluşan ACTION_JSON'ı döndürün. Fakat kullanıcı eksik parametrenin
değerini söylemek yerine konuyu değiştirir ve farklı bir şey söylerse, ve eğer söylediğinde farklı bir intent varsa, bu intent akışını işletmelisiniz.
Eğer intent yoksa kullanıcı konuyu değiştirip normal sohbet ediyor anlamına gelir, sohbeti kullanıcıya cevap vererek sürdürünüz.
❗ 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, kullanıcının sohbet amaçlı söylediği ifadeye cevap vermelisiniz:
#ANSWER: <cevap metni>
#INTENT: NONE
#PARAMS: {}
#MISSING: []
#ACTION_JSON: {}
- Eğer intent bulunur ama eksik parametre varsa:
#ANSWER: NONE
#INTENT: <intent_adı>
#PARAMS: {elde edilen parametreler}
#MISSING: [eksik_parametreler]
#ACTION_JSON: {}
- Eğer tüm parametreler tamamlanmışsa:
#ANSWER: NONE
#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ı: "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"}
✅ Yol Durumu Eksik Parametre Tamamlama Akışı:
Kullanıcı: "Yol durumu"
#ANSWER: "Nereden nereye gitmek istiyorsunuz?"
#INTENT: "yol-durumu-intent"
#PARAMS: {}
#MISSING: ["from_location", "to_location"]
#ACTION_JSON: {}
Kullanıcı: "Ankara'dan İstanbul'a"
#ANSWER: NONE
#INTENT: "yol-durumu-intent"
#PARAMS: { "from_location": "Ankara", "to_location": "İstanbul"}
#MISSING: []
#ACTION_JSON: { "from_location": "Ankara", "to_location": "İstanbul" }
✅ Hava Durumu Eksik Parametre Tamamlama Akışı:
Kullanıcı: "Hava nasıl olacak, yağmur var mı?"
#ANSWER: "Hangi şehirdeki hava durumunu öğrenmek istiyorsunuz?"
#INTENT: hava-durumu-intent
#PARAMS: {}
#MISSING: ["city"]
#ACTION_JSON: {}
Kullanıcı: "İstanbul'u öğrenmek istiyorum"
#ANSWER: NONE
#INTENT: hava-durumu-intent
#PARAMS: { "city": "İstanbul" }
#MISSING: []
#ACTION_JSON: { "city": "İstanbul" }
✅ Eksik Parametre Tamamlama Akışında Kullanıcının Konuyu Değiştirmesi:
Kullanıcı: "Hava nasıl olacak, yağmur var mı?"
#ANSWER: "Hangi şehirdeki hava durumunu öğrenmek istiyorsunuz?"
#INTENT: hava-durumu-intent
#PARAMS: {}
#MISSING: ["city"]
#ACTION_JSON: {}
Kullanıcı: "Sence en şekerli meyve hangisidir?"
#ANSWER: "En şekerli meyve hurmadır."
#INTENT: NONE
#PARAMS: {}
#MISSING: []
#ACTION_JSON: {}
❗ 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"}
|