Update app.py
Browse files
app.py
CHANGED
@@ -4,19 +4,16 @@ import json
|
|
4 |
import requests
|
5 |
import xml.etree.ElementTree as ET
|
6 |
|
7 |
-
#
|
8 |
API_URL = "https://api.openai.com/v1/chat/completions"
|
9 |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
10 |
|
|
|
11 |
url = 'https://www.trekbisiklet.com.tr/output/8582384479'
|
12 |
-
|
13 |
response = requests.get(url)
|
14 |
-
|
15 |
-
|
16 |
root = ET.fromstring(response.content)
|
17 |
|
18 |
products = []
|
19 |
-
|
20 |
for item in root.findall('item'):
|
21 |
if item.find('isOptionOfAProduct').text == '1':
|
22 |
if item.find('stockAmount').text > '0':
|
@@ -26,7 +23,7 @@ for item in root.findall('item'):
|
|
26 |
stockAmount = "stokta"
|
27 |
price = item.find('priceWithTax').text
|
28 |
item_info = (stockAmount, price)
|
29 |
-
# name: ilk kelime (marka), item_info: (stok
|
30 |
products.append((name, item_info, full_name))
|
31 |
|
32 |
|
@@ -36,18 +33,19 @@ def predict(system_msg, inputs, top_p, temperature, chat_counter, chatbot=[], hi
|
|
36 |
"Authorization": f"Bearer {OPENAI_API_KEY}"
|
37 |
}
|
38 |
print(f"system message is ^^ {system_msg}")
|
39 |
-
initial_message = [{"role": "user", "content": f"{inputs}"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
-
multi_turn_message = [{"role": "system", "content": "Sen bir Bıke Finder asistanısın. Görevin insanların doğru bisiklet modeli seçimini sağlamak. Kişilere sorucağın bir takım sorularala, kişileri tanıyıp, onlara stoklarımızda bulunan bisikletlerin model, boylarını tavsiye edeceksin. "} ,
|
42 |
-
{"role": "system", "content": "Merhaba, ben Trek Stok Danısmanı Asistanıyım! Size en uygun Trek bisiklet modelini belirleyebilmem için birkaç sorum olacak. Verdiğiniz bilgiler doğrultusunda, elimizdeki güncel stoklardan ihtiyaçlarınıza en uygun modeli seçip, satin alma sürecine yonlendirecegim. Unutmayin, tum Trek bisikletlerimiz omur boyu garantilidir! Adim 1: Bisiklet Kategorisi - Hangi tur Trek bisikletiyle ilgileniyorsunuz? Lutfen asagidaki seceneklerden birini belirtiniz: Yol Bisikleti ornek: Trek Emonda, Trek Domane; Dag Bisikleti ornek: Trek Fuel EX, Trek Remedy, Trek Procaliber; Hibrit Sehir Bisikleti; Gravel Bisikleti ornek: Trek Checkpoint; Elektrikli Bisikleti ornek: Trek Powerfly, Trek Allant+. Adim 2: Kullanim Amaci - Bisikletinizi hangi amaclarla kullanmayi planliyorsunuz? ornek: gunluk ulasim, spor, uzun mesafe turlari, yaris, offroad maceralari, dag yollari. Adim 3: Beklentiler - Trek bisikletinizde hangi ozellikler sizin icin en onemli? ornek: performans, konfor, dayaniklilik, teknoloji yenilik, estetk, diger. Adim 4: Zemin Kosullari - Bisikletinizi hangi zeminlerde kullanacaksiniz? ornek: sehir ici asfalt, hafif engebeli parkurlar, orman dogal parkurlar, zorlu dag yollari offroad, karisik kullanim. Adim 5: Fiziksel Olculer - Dogru model ve cerceve boyutunu belirleyebilmem icin lutfen boyunuzu ve ic bacak boyunuzu paylasir misiniz? ornek: Boyum 180 cm, ic bacak boyum 85 cm. Adim 6: Ek Tercihler - Ek olarak, bisikletinizde tercih ettiginiz baska ozellikler var mi? ornek: ekstra donanim, ozel renk, aksesuar tercihi veya butce araliginiz. Adim 7: Oneri ve Satisa Yonlendirme - Verdigimiz bilgiler dogrultusunda, stoklarimizda bulunan ve ihtiyaclariniza en uygun olan Onerilen Model modelini oneriyorum. Bu model, kisa teknik ozellikler, kullanim avantajlari ve hedeflenen zemin alan ile beklentilerinize hitap ediyor. Ustelik, tum Trek bisikletlerimiz omur boyu garantilidir! Su an stok durumumuz: Stokta mevcut, Sinirli stok. Urun detaylari ve satin alma islemi icin lutfen su linke tiklayin: Trek Onerilen Model Urun Sayfasi https:orneksite.comtrek-ornek-model. Kargo ve Teslimat - Siparisiniz odeme onayindan sonra en gec 24 saat icinde paketlenip kargoya verilir; Yuritici Kargo, MNG veya Aras Kargo ile gonderim yapilir. Kargo takip numarasi SMS ve eposta ile iletilecek; gonderim sureci 3-5 is gunu surer. Belirli tutar uzerindeki siparislerde ucretsiz kargo kampanyasi uygulanir. Lutfen yukaridaki linke tiklayarak satin alma isleminizi tamamlayin. Herhangi bir sorunuz veya ek isteginiz olursa, ben buradayim. Hadi, siparisinizi tamamlayalim ve maceraya baslayalim!"} ,
|
43 |
-
{"role": "system", "content": "Stokları ve fiyatları https://www.trekbisiklet.com.tr den bakacaksın, diğer markalarla ilgigi soru gelirse kibarca cevaplayamayacağını ve trek in neden farklı olduğunu anlat. Yol bisikletlerinde Türkiye stoklarımızda, Madone, Domane, Emonda, CheckMate, CheckPoint ve SpeedConcept modelleri bulunuyor. Dağ bisikletlerinde ise Marlin, Procaliber, Supercaliber modeller, full amortisörlülerde ise Fuel Ex modeli bulunmakta. Şehir kullanımı için FX ve DS modelini stoklarda bulunduruyoruz. "} ]
|
44 |
messages = multi_turn_message
|
45 |
-
input_words = []
|
46 |
-
for input in inputs.split():
|
47 |
-
input_words.append(str(input).lower())
|
48 |
|
49 |
for product_info in products:
|
50 |
-
|
51 |
if product_info[0] in input_words:
|
52 |
new_msg = f"{product_info[2]} {product_info[1][0]} ve fiyatı EURO {product_info[1][1]}"
|
53 |
print(new_msg)
|
@@ -55,55 +53,48 @@ def predict(system_msg, inputs, top_p, temperature, chat_counter, chatbot=[], hi
|
|
55 |
messages.append(product_msg)
|
56 |
|
57 |
for data in chatbot:
|
58 |
-
user = {}
|
59 |
-
|
60 |
-
user["content"] = data[0]
|
61 |
-
assistant = {}
|
62 |
-
assistant["role"] = "assistant"
|
63 |
-
assistant["content"] = data[1]
|
64 |
messages.append(user)
|
65 |
messages.append(assistant)
|
66 |
-
|
67 |
-
|
68 |
-
temp["content"] = inputs
|
69 |
-
messages.append(temp)
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
chat_counter += 1
|
76 |
-
|
77 |
history.append(inputs)
|
78 |
print(f"Logging : payload is - {payload}")
|
79 |
|
80 |
-
response = requests.post(API_URL, headers=headers,
|
81 |
-
json=payload, stream=True)
|
82 |
print(f"Logging : response code - {response}")
|
|
|
83 |
token_counter = 0
|
84 |
partial_words = ""
|
85 |
-
|
86 |
counter = 0
|
87 |
for chunk in response.iter_lines():
|
88 |
-
|
89 |
if counter == 0:
|
90 |
counter += 1
|
91 |
continue
|
92 |
-
|
93 |
if chunk.decode():
|
94 |
chunk = chunk.decode()
|
95 |
-
|
96 |
if len(chunk) > 12 and "content" in json.loads(chunk[6:])['choices'][0]['delta']:
|
97 |
-
partial_words
|
98 |
-
json.loads(chunk[6:])['choices'][0]["delta"]["content"]
|
99 |
if token_counter == 0:
|
100 |
history.append(" " + partial_words)
|
101 |
else:
|
102 |
history[-1] = partial_words
|
103 |
-
chat = [(history[i], history[i + 1]) for i in range(0,
|
104 |
-
len(history) - 1, 2)] # convert to tuples of list
|
105 |
token_counter += 1
|
106 |
-
# resembles {chatbot: chat, state: history}
|
107 |
yield chat, history, chat_counter, response
|
108 |
|
109 |
|
@@ -119,35 +110,100 @@ def set_visible_true():
|
|
119 |
return gr.update(visible=False)
|
120 |
|
121 |
|
122 |
-
|
123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
theme = gr.themes.Base(
|
125 |
-
neutral_hue="
|
126 |
text_size="sm",
|
127 |
spacing_size="sm",
|
128 |
)
|
129 |
|
130 |
-
with gr.Blocks(theme=theme) as demo:
|
131 |
-
|
132 |
-
|
|
|
133 |
with gr.Column(elem_id="col_container"):
|
134 |
with gr.Accordion("", open=False, visible=False):
|
135 |
system_msg = gr.Textbox(value="")
|
136 |
new_msg = gr.Textbox(value="")
|
137 |
accordion_msg = gr.HTML(value="", visible=False)
|
|
|
138 |
chatbot = gr.Chatbot(label='Trek Bike Finder', elem_id="chatbot")
|
139 |
inputs = gr.Textbox(
|
140 |
-
placeholder="Buraya yazın,
|
141 |
state = gr.State([])
|
142 |
with gr.Accordion("", open=False, visible=False):
|
143 |
-
top_p = gr.Slider(minimum
|
144 |
-
|
145 |
-
temperature = gr.Slider(
|
146 |
-
minimum=-0, maximum=5.0, value=0.1, step=0.1, interactive=False, visible=False)
|
147 |
chat_counter = gr.Number(value=0, visible=False, precision=0)
|
148 |
|
149 |
-
inputs.submit(
|
|
|
|
|
|
|
|
|
150 |
inputs.submit(reset_textbox, [], [inputs])
|
151 |
|
152 |
-
|
153 |
-
demo.queue(max_size=10).launch(debug=True)
|
|
|
4 |
import requests
|
5 |
import xml.etree.ElementTree as ET
|
6 |
|
7 |
+
# API URL ve API KEY ayarları
|
8 |
API_URL = "https://api.openai.com/v1/chat/completions"
|
9 |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
10 |
|
11 |
+
# Ürün verilerini çekme işlemi
|
12 |
url = 'https://www.trekbisiklet.com.tr/output/8582384479'
|
|
|
13 |
response = requests.get(url)
|
|
|
|
|
14 |
root = ET.fromstring(response.content)
|
15 |
|
16 |
products = []
|
|
|
17 |
for item in root.findall('item'):
|
18 |
if item.find('isOptionOfAProduct').text == '1':
|
19 |
if item.find('stockAmount').text > '0':
|
|
|
23 |
stockAmount = "stokta"
|
24 |
price = item.find('priceWithTax').text
|
25 |
item_info = (stockAmount, price)
|
26 |
+
# name: ilk kelime (marka), item_info: (stok durumu, fiyat)
|
27 |
products.append((name, item_info, full_name))
|
28 |
|
29 |
|
|
|
33 |
"Authorization": f"Bearer {OPENAI_API_KEY}"
|
34 |
}
|
35 |
print(f"system message is ^^ {system_msg}")
|
36 |
+
initial_message = [{"role": "user", "content": f"{inputs}"}]
|
37 |
+
|
38 |
+
multi_turn_message = [
|
39 |
+
{"role": "system", "content": "Sen bir Bıke Finder asistanısın. Görevin insanların doğru bisiklet modeli seçimini sağlamak. Kişilere sorucağın bir takım sorularala, kişileri tanıyıp, onlara stoklarımızda bulunan bisikletlerin model, boylarını tavsiye edeceksin."},
|
40 |
+
{"role": "system", "content": "Merhaba, ben Trek Stok Danısmanı Asistanıyım! Size en uygun Trek bisiklet modelini belirleyebilmem için birkaç sorum olacak. Verdiğiniz bilgiler doğrultusunda, elimizdeki güncel stoklardan ihtiyaçlarınıza en uygun modeli seçip, satin alma sürecine yonlendirecegim. Unutmayin, tum Trek bisikletlerimiz omur boyu garantilidir! Adim 1: Bisiklet Kategorisi - Hangi tur Trek bisikletiyle ilgileniyorsunuz? Lutfen asagidaki seceneklerden birini belirtiniz: Yol Bisikleti ornek: Trek Emonda, Trek Domane; Dag Bisikleti ornek: Trek Fuel EX, Trek Remedy, Trek Procaliber; Hibrit Sehir Bisikleti; Gravel Bisikleti ornek: Trek Checkpoint; Elektrikli Bisikleti ornek: Trek Powerfly, Trek Allant+."},
|
41 |
+
{"role": "system", "content": "Adim 2: Kullanim Amaci - Bisikletinizi hangi amaclarla kullanmayi planliyorsunuz? ornek: gunluk ulasim, spor, uzun mesafe turlari, yaris, offroad maceralari, dag yollari. Adim 3: Beklentiler - Trek bisikletinizde hangi ozellikler sizin icin en onemli? ornek: performans, konfor, dayaniklilik, teknoloji yenilik, estetk, diger. Adim 4: Zemin Kosullari - Bisikletinizi hangi zeminlerde kullanacaksiniz? ornek: sehir ici asfalt, hafif engebeli parkurlar, orman dogal parkurlar, zorlu dag yollari offroad, karisik kullanim. Adim 5: Fiziksel Olculer - Dogru model ve cerceve boyutunu belirleyebilmem icin lutfen boyunuzu ve ic bacak boyunuzu paylasir misiniz? ornek: Boyum 180 cm, ic bacak boyum 85 cm. Adim 6: Ek Tercihler - Ek olarak, bisikletinizde tercih ettiginiz baska ozellikler var mi? ornek: ekstra donanim, ozel renk, aksesuar tercihi veya butce araliginiz. Adim 7: Oneri ve Satisa Yonlendirme - Verdigimiz bilgiler dogrultusunda, stoklarimizda bulunan ve ihtiyaclariniza en uygun olan Onerilen Model modelini oneriyorum. Bu model, kisa teknik ozellikler, kullanim avantajlari ve hedeflenen zemin alan ile beklentilerinize hitap ediyor. Ustelik, tum Trek bisikletlerimiz omur boyu garantilidir! Su an stok durumumuz: Stokta mevcut, Sinirli stok. Urun detaylari ve satin alma islemi icin lutfen su linke tiklayin: Trek Onerilen Model Urun Sayfasi https:orneksite.comtrek-ornek-model. Kargo ve Teslimat - Siparisiniz odeme onayindan sonra en gec 24 saat icinde paketlenip kargoya verilir; Yuritici Kargo, MNG veya Aras Kargo ile gonderim yapilir. Kargo takip numarasi SMS ve eposta ile iletilecek; gonderim sureci 3-5 is gunu surer. Belirli tutar uzerindeki siparislerde ucretsiz kargo kampanyasi uygulanir."},
|
42 |
+
{"role": "system", "content": "Stokları ve fiyatları https://www.trekbisiklet.com.tr den bakacaksın, diğer markalarla ilgigi soru gelirse kibarca cevaplayamayacağını ve trek in neden farklı olduğunu anlat. Yol bisikletlerinde Türkiye stoklarımızda, Madone, Domane, Emonda, CheckMate, CheckPoint ve SpeedConcept modelleri bulunuyor. Dağ bisikletlerinde ise Marlin, Procaliber, Supercaliber modeller, full amortisörlülerde ise Fuel Ex modeli bulunmakta. Şehir kullanımı için FX ve DS modelini stoklarda bulunduruyoruz."}
|
43 |
+
]
|
44 |
|
|
|
|
|
|
|
45 |
messages = multi_turn_message
|
46 |
+
input_words = [str(word).lower() for word in inputs.split()]
|
|
|
|
|
47 |
|
48 |
for product_info in products:
|
|
|
49 |
if product_info[0] in input_words:
|
50 |
new_msg = f"{product_info[2]} {product_info[1][0]} ve fiyatı EURO {product_info[1][1]}"
|
51 |
print(new_msg)
|
|
|
53 |
messages.append(product_msg)
|
54 |
|
55 |
for data in chatbot:
|
56 |
+
user = {"role": "user", "content": data[0]}
|
57 |
+
assistant = {"role": "assistant", "content": data[1]}
|
|
|
|
|
|
|
|
|
58 |
messages.append(user)
|
59 |
messages.append(assistant)
|
60 |
+
|
61 |
+
messages.append({"role": "user", "content": inputs})
|
|
|
|
|
62 |
|
63 |
+
payload = {
|
64 |
+
"model": "gpt-4o",
|
65 |
+
"messages": messages,
|
66 |
+
"temperature": 0.7,
|
67 |
+
"top_p": 0.9,
|
68 |
+
"n": 1,
|
69 |
+
"stream": True,
|
70 |
+
"presence_penalty": 0,
|
71 |
+
"frequency_penalty": 0,
|
72 |
+
}
|
73 |
|
74 |
chat_counter += 1
|
|
|
75 |
history.append(inputs)
|
76 |
print(f"Logging : payload is - {payload}")
|
77 |
|
78 |
+
response = requests.post(API_URL, headers=headers, json=payload, stream=True)
|
|
|
79 |
print(f"Logging : response code - {response}")
|
80 |
+
|
81 |
token_counter = 0
|
82 |
partial_words = ""
|
|
|
83 |
counter = 0
|
84 |
for chunk in response.iter_lines():
|
|
|
85 |
if counter == 0:
|
86 |
counter += 1
|
87 |
continue
|
|
|
88 |
if chunk.decode():
|
89 |
chunk = chunk.decode()
|
|
|
90 |
if len(chunk) > 12 and "content" in json.loads(chunk[6:])['choices'][0]['delta']:
|
91 |
+
partial_words += json.loads(chunk[6:])['choices'][0]["delta"]["content"]
|
|
|
92 |
if token_counter == 0:
|
93 |
history.append(" " + partial_words)
|
94 |
else:
|
95 |
history[-1] = partial_words
|
96 |
+
chat = [(history[i], history[i + 1]) for i in range(0, len(history) - 1, 2)]
|
|
|
97 |
token_counter += 1
|
|
|
98 |
yield chat, history, chat_counter, response
|
99 |
|
100 |
|
|
|
110 |
return gr.update(visible=False)
|
111 |
|
112 |
|
113 |
+
# WhatsApp tarzı görünüm için özel CSS
|
114 |
+
css = """
|
115 |
+
/* Chat Başlığı: WhatsApp koyu yeşili */
|
116 |
+
.chat-header {
|
117 |
+
background-color: #075e54;
|
118 |
+
color: #fff;
|
119 |
+
padding: 15px;
|
120 |
+
text-align: center;
|
121 |
+
font-size: 20px;
|
122 |
+
font-weight: bold;
|
123 |
+
}
|
124 |
+
|
125 |
+
/* Chat penceresi: arka plan rengi */
|
126 |
+
#chatbot {
|
127 |
+
background-color: #ece5dd;
|
128 |
+
border: none;
|
129 |
+
padding: 10px;
|
130 |
+
}
|
131 |
+
|
132 |
+
/* Kullanıcı mesajı (sağa hizalı, açık yeşil) */
|
133 |
+
.chat-bubble.user {
|
134 |
+
background-color: #dcf8c6 !important;
|
135 |
+
align-self: flex-end;
|
136 |
+
border-radius: 20px;
|
137 |
+
padding: 10px 15px;
|
138 |
+
margin: 8px 0;
|
139 |
+
max-width: 70%;
|
140 |
+
word-wrap: break-word;
|
141 |
+
}
|
142 |
+
|
143 |
+
/* Bot mesajı (sola hizalı, beyaz) */
|
144 |
+
.chat-bubble.bot {
|
145 |
+
background-color: #fff !important;
|
146 |
+
align-self: flex-start;
|
147 |
+
border: 1px solid #ccc;
|
148 |
+
border-radius: 20px;
|
149 |
+
padding: 10px 15px;
|
150 |
+
margin: 8px 0;
|
151 |
+
max-width: 70%;
|
152 |
+
word-wrap: break-word;
|
153 |
+
}
|
154 |
+
|
155 |
+
/* Mesaj gönderme alanı */
|
156 |
+
.chat-input-container {
|
157 |
+
display: flex;
|
158 |
+
padding: 10px;
|
159 |
+
border-top: 1px solid #ddd;
|
160 |
+
background-color: #f0f0f0;
|
161 |
+
}
|
162 |
+
|
163 |
+
/* Gönder butonu */
|
164 |
+
.send-button {
|
165 |
+
background-color: #075e54;
|
166 |
+
border: none;
|
167 |
+
color: #fff;
|
168 |
+
padding: 10px 15px;
|
169 |
+
margin-left: 10px;
|
170 |
+
border-radius: 20px;
|
171 |
+
font-size: 16px;
|
172 |
+
cursor: pointer;
|
173 |
+
}
|
174 |
+
"""
|
175 |
+
|
176 |
+
# Tema ayarını güncelliyoruz: neutral_hue 'green' ile WhatsApp benzeri yeşil ton
|
177 |
theme = gr.themes.Base(
|
178 |
+
neutral_hue="green",
|
179 |
text_size="sm",
|
180 |
spacing_size="sm",
|
181 |
)
|
182 |
|
183 |
+
with gr.Blocks(theme=theme, css=css) as demo:
|
184 |
+
# WhatsApp tarzı chat başlığı
|
185 |
+
gr.Markdown("<div class='chat-header'>Trek Bike Finder Chatbot</div>")
|
186 |
+
|
187 |
with gr.Column(elem_id="col_container"):
|
188 |
with gr.Accordion("", open=False, visible=False):
|
189 |
system_msg = gr.Textbox(value="")
|
190 |
new_msg = gr.Textbox(value="")
|
191 |
accordion_msg = gr.HTML(value="", visible=False)
|
192 |
+
# Gradio'nun Chatbot bileşeni; özel CSS #chatbot ile stil veriyoruz
|
193 |
chatbot = gr.Chatbot(label='Trek Bike Finder', elem_id="chatbot")
|
194 |
inputs = gr.Textbox(
|
195 |
+
placeholder="Buraya yazın, istediğiniz modeli beraber bulalım.", show_label=False)
|
196 |
state = gr.State([])
|
197 |
with gr.Accordion("", open=False, visible=False):
|
198 |
+
top_p = gr.Slider(minimum=0, maximum=1.0, value=0.5, step=0.05, interactive=False, visible=False)
|
199 |
+
temperature = gr.Slider(minimum=0, maximum=5.0, value=0.1, step=0.1, interactive=False, visible=False)
|
|
|
|
|
200 |
chat_counter = gr.Number(value=0, visible=False, precision=0)
|
201 |
|
202 |
+
inputs.submit(
|
203 |
+
predict,
|
204 |
+
[system_msg, inputs, top_p, temperature, chat_counter, chatbot, state],
|
205 |
+
[chatbot, state, chat_counter]
|
206 |
+
)
|
207 |
inputs.submit(reset_textbox, [], [inputs])
|
208 |
|
209 |
+
demo.queue(max_size=10).launch(debug=True)
|
|