File size: 11,476 Bytes
c051efa 2142c80 f3ff1c7 2142c80 e7590dc 292b39a fce7101 5e7c2bd 61d867f 75e9167 7acd937 8b7994d 2142c80 97be484 75e9167 f3ff1c7 0e279cb 10b378e 2343f3f 0e279cb 292b39a 0e279cb 292b39a 75e9167 0e279cb e7590dc cb8389b 75e9167 5942ddb 42c9a95 7a7b7b1 292b39a e7590dc 292b39a e7590dc 292b39a e7590dc 8f42238 f3e1c89 61d867f e7590dc 292b39a e182566 5e7c2bd e182566 292b39a 3306257 292b39a 3306257 292b39a 3306257 9cb89a1 3306257 292b39a 5e7c2bd 3306257 292b39a 2203b4d 6328941 292b39a 3306257 292b39a 6328941 292b39a 3306257 75e9167 3306257 e15e9df 3306257 292b39a 75e9167 292b39a 0b9cf76 292b39a 7baf15a 292b39a e7590dc 85d90c4 292b39a 956d4f7 95cf217 292b39a |
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 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
import gradio as gr
import os
import json
import requests
import xml.etree.ElementTree as ET
import schedule
import time
import threading
from huggingface_hub import HfApi, create_repo
import warnings
# Gradio uyarılarını bastır
warnings.filterwarnings("ignore", category=UserWarning, module="gradio.components.chatbot")
# Log dosyası adı ve yolu
LOG_FILE = '/data/chat_logs.txt' if os.path.exists('/data') else 'chat_logs.txt'
print(f"Dosya yolu: {os.path.abspath(LOG_FILE)}")
# API ayarları
API_URL = "https://api.openai.com/v1/chat/completions"
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
if not OPENAI_API_KEY:
print("Hata: OPENAI_API_KEY çevre değişkeni ayarlanmamış!")
# Trek bisiklet ürünlerini çekme
url = 'https://www.trekbisiklet.com.tr/output/8582384479'
response = requests.get(url)
root = ET.fromstring(response.content)
products = []
for item in root.findall('item'):
if item.find('isOptionOfAProduct').text == '1' and item.find('stockAmount').text > '0':
name_words = item.find('rootlabel').text.lower().split()
name = name_words[0]
full_name = ' '.join(name_words)
stock_amount = "stokta"
price = item.find('priceWithTax').text
item_info = (stock_amount, price)
products.append((name, item_info, full_name))
# Hugging Face token
hfapi = os.getenv("hfapi")
if not hfapi:
raise ValueError("hfapi ortam değişkeni ayarlanmamış!")
create_repo("BF", token=hfapi, repo_type="space", space_sdk="gradio", exist_ok=True)
global_chat_history = [] # Tüm sohbet geçmişi
history_lock = threading.Lock() # Global geçmiş için kilit
file_lock = threading.Lock() # Dosya yazma için kilit
last_logged_index = 0 # Son kaydedilen mesaj indeksi
def run_scheduler(chat_history_ref):
def scheduled_save_and_upload():
global last_logged_index
if chat_history_ref:
print(f"Zamanlayıcı tetiklendi: {time.strftime('%Y-%m-%d %H:%M:%S')}")
try:
with file_lock: # Dosya yazma kilidi
with open(LOG_FILE, 'a', encoding='utf-8') as f:
f.write("\n--- Zamanlanmış Kayıt: {} ---\n".format(time.strftime("%Y-%m-%d %H:%M:%S")))
with history_lock: # Geçmiş kilidi
new_messages = chat_history_ref[last_logged_index:]
for msg in new_messages:
if msg["role"] in ["user", "assistant"]:
f.write(f"{msg['role'].capitalize()}: {msg['content']}\n")
last_logged_index = len(chat_history_ref) # Son indeksi güncelle
print(f"Sohbet dosyaya kaydedildi: {os.path.abspath(LOG_FILE)}")
except Exception as e:
print(f"Kayıt hatası: {e}")
time.sleep(5) # Hata sonrası tekrar denemeden önce bekle
return # Tekrar deneme için erken çıkış
HF_REPO_ID = "SamiKoen/BF"
api = HfApi(token=hfapi)
for attempt in range(3): # 3 kez tekrar deneme
try:
with file_lock:
api.upload_file(
path_or_fileobj=LOG_FILE,
path_in_repo="chat_logs.txt",
repo_id=HF_REPO_ID,
repo_type="space",
commit_message="Otomatik log güncellemesi - {}".format(time.strftime("%Y-%m-%d %H:%M:%S"))
)
print(f"Log dosyası HF'ye yüklendi: {LOG_FILE}")
break
except Exception as e:
print(f"HF yükleme hatası (deneme {attempt+1}/3): {e}")
time.sleep(5)
else:
print("HF yükleme başarısız, tüm denemeler tamamlandı.")
print(f"Zamanlanmış işlem tamamlandı: {time.strftime('%H:%M:%S')}")
schedule.every().day.at("11:32").do(scheduled_save_and_upload)
schedule.every().day.at("15:15").do(scheduled_save_and_upload)
schedule.every().day.at("15:30").do(scheduled_save_and_upload)
schedule.every().day.at("17:32").do(scheduled_save_and_upload)
schedule.every().day.at("19:15").do(scheduled_save_and_upload)
schedule.every().day.at("21:30").do(scheduled_save_and_upload)
print("Zamanlayıcı başlatıldı")
while True:
schedule.run_pending()
time.sleep(60)
def chatbot_fn(user_message, history):
if history is None:
history = []
# Log: Kullanıcı mesajını ekle
try:
with file_lock:
with open(LOG_FILE, 'a', encoding='utf-8') as f:
f.write(f"User: {user_message}\n")
except Exception as e:
print(f"Dosya yazma hatası (Kullanıcı): {e}")
# Sistem mesajları
system_messages = [
{"role": "system", "content": "Sen bir Trek bisiklet satış ve danışman asistanısın; Trek, Electra bisikletler, Bontrager aksesuarlar, Bryton yol bilgisayarları ve Trieye gözlükler konusunda uzmanım."},
{"role": "system", "content": "Başka markalar (ör. Specialized, Giant) hakkında bilgi vermem ve yorum yapmam."},
{"role": "system", "content": "Bir önceki sohbeti unuturum ve yalnızca aşağıda yan yana yazılan bilgilerden cevap veririm."},
{"role": "system", "content": "Stok kontrolüm gerçek zamanlıdır; stokta yoksa 'yok' derim."},
{"role": "system", "content": "Model adı rakamsız gelirse (ör. Madone SL), rakam eklenmesini rica ederim (ör. Madone SL 7)."},
{"role": "system", "content": "Madone SLR sorulursa Gen 7 kabul ederim."},
{"role": "system", "content": "Yol bisikletleri (Madone, Émonda, Domane, Checkpoint, Speed Concept) boyları 47-64 cm'dir."},
{"role": "system", "content": "Dağ bisikletleri (Marlin, Roscoe, Procaliber, Supercaliber, Fuel EX) boyları XXS-XL'dir."},
{"role": "system", "content": "Şehir bisikletleri FX ve DS’dir; elektrikli modeller Powerfly, Rail, Fuel EXe, Domane+ SLR, Verve+’dır; gravel için Checkpoint vardır."},
{"role": "system", "content": "Yeni Madone Gen 8 (27 Haziran 2024): Émonda kadar hafif (900 Serisi OCLV Karbon, 320g hafif) ve Madone Gen 7 kadar hızlıdır."},
{"role": "system", "content": "IsoFlow ile %80 konforludur; SL ekonomik, SLR üst seviyedir."},
{"role": "system", "content": "Stok ve fiyatlar için www.trekbisiklet.com.tr’ye bakarım; farklı boy/renk varsa söylerim, yoksa başka model öneririm."},
{"role": "system", "content": "En büyük/küçük boy sorusuna stoktan cevap veririm; üyelere özel fiyatlar için siteye üye olun derim."},
{"role": "system", "content": "İstanbul’da Caddebostan mağazamız (0216 6292432, 10:00-19:00, Bike Fit 3500 TL) ve Ortaköy mağazamız (0212 2271015, 10:00-19:00) bulunmaktadır."},
{"role": "system", "content": "Sarıyer mağazamız (0542 1371080, 10:00-19:00) elektrikli bisiklet odaklıdır."},
{"role": "system", "content": "İzmir Alsancak mağazası Nisan 2025’te açılacak ve Pazar günleri kapalı olacak."},
{"role": "system", "content": "Bontrager aksesuarlar, Bryton Rider S800 stokta ve Trieye gözlükler Norveç menşeli geri görüş aynalıdır."},
{"role": "system", "content": "Bike Finder olarak adım adım sorarım: 1) kategori (yol, dağ, hibrit, gravel, elektrikli), 2) amaç (ulaşım, spor, yarış), 3) özellik (performans, konfor)."},
{"role": "system", "content": "4) zemin (asfalt, off-road), 5) boy ve iç bacak ölçüsü, 6) ek tercih (renk, bütçe) sorularını sorarım; sonra stoktan öneri yapar www.trekbisiklet.com.tr’ye yönlendiririm."},
{"role": "system", "content": "Sipariş süreci: sepete ekle, bilgi gir, ödeme yap, tamamla; Trek kadroları ömür boyu garantilidir; 2000’den beri Alatin Bisiklet dağıtıyor; ASLA DURMA ve TREK RMK DYNAMIS’e sponsoruz; takas için www.bikeexchangehub.com, canlı sohbet için sitedeki yeşil düğme, bayiler için www.alatin.com.tr/sayfa/bayilerimiz/ kullanılır."}
]
# Kullanıcı mesajında ürün ismi geçiyorsa ekle
input_words = user_message.lower().split()
for product_info in products:
if product_info[0] in input_words:
new_msg = f"{product_info[2]} {product_info[1][0]} ve fiyatı EURO {product_info[1][1]}"
system_messages.append({"role": "system", "content": new_msg})
messages = system_messages + history + [{"role": "user", "content": user_message}]
payload = {
"model": "gpt-4o",
"messages": messages,
"temperature": 0.7,
"top_p": 0.9,
"n": 1,
"stream": True,
"presence_penalty": 0,
"frequency_penalty": 0,
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {OPENAI_API_KEY}"
}
response = requests.post(API_URL, headers=headers, json=payload, stream=True)
if response.status_code != 200:
yield [{"role": "user", "content": user_message}, {"role": "assistant", "content": "Bir hata oluştu."}]
return
partial_response = ""
current_pair = [{"role": "user", "content": user_message}, {"role": "assistant", "content": ""}]
for chunk in response.iter_lines():
if not chunk:
continue
chunk_str = chunk.decode('utf-8')
if chunk_str.startswith("data: ") and chunk_str != "data: [DONE]":
try:
chunk_data = json.loads(chunk_str[6:])
delta = chunk_data['choices'][0]['delta']
if 'content' in delta:
partial_response += delta['content']
current_pair[1]["content"] = partial_response
yield current_pair
except json.JSONDecodeError as e:
print(f"JSON parse hatası: {e} - Chunk: {chunk_str}")
elif chunk_str == "data: [DONE]":
break
# Log: Asistan cevabını ekle
try:
with file_lock:
with open(LOG_FILE, 'a', encoding='utf-8') as f:
f.write(f"Bot: {partial_response}\n")
except Exception as e:
print(f"Dosya yazma hatası (Bot): {e}")
# Global geçmişi güncelle
with history_lock:
global_chat_history.append({"role": "user", "content": user_message})
global_chat_history.append({"role": "assistant", "content": partial_response})
yield current_pair
# Slow echo (test için)
def slow_echo(message, history):
for i in range(len(message)):
time.sleep(0.05)
yield [{"role": "user", "content": message}, {"role": "assistant", "content": "You typed: " + message[: i + 1]}]
# Kullanım modu
USE_SLOW_ECHO = False
chat_fn = slow_echo if USE_SLOW_ECHO else chatbot_fn
if not USE_SLOW_ECHO:
scheduler_thread = threading.Thread(target=run_scheduler, args=(global_chat_history,), daemon=True)
scheduler_thread.start()
demo = gr.ChatInterface(
fn=chat_fn,
title="Trek Asistanı",
#description="Hoş geldiniz! Trek ile ilgili sorularınızı yanıtlıyorum.",
theme="default",
type="messages",
flagging_mode="manual",
flagging_options=["Doğru", "Yanlış", "Emin değilim", "Diğer"],
save_history=True
)
if __name__ == "__main__":
demo.launch(debug=True, share=True) |