Update app.py
Browse files
app.py
CHANGED
@@ -1,37 +1,377 @@
|
|
|
|
1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
-
|
4 |
-
|
|
|
|
|
|
|
5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
css = """
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
.gradio-container {
|
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 |
-
clear.click(lambda: [], None, chatbot)
|
36 |
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import base64
|
2 |
import gradio as gr
|
3 |
+
import json
|
4 |
+
import mimetypes
|
5 |
+
import os
|
6 |
+
import requests
|
7 |
+
import time
|
8 |
+
import modelscope_studio.components.antd as antd
|
9 |
+
import modelscope_studio.components.antdx as antdx
|
10 |
+
import modelscope_studio.components.base as ms
|
11 |
+
import modelscope_studio.components.pro as pro
|
12 |
+
from modelscope_studio.components.pro.chatbot import (
|
13 |
+
ChatbotActionConfig, ChatbotBotConfig, ChatbotMarkdownConfig,
|
14 |
+
ChatbotPromptsConfig, ChatbotUserConfig, ChatbotWelcomeConfig)
|
15 |
+
import re
|
16 |
|
17 |
+
# Environment variables
|
18 |
+
MODEL_VERSION = os.environ.get('MODEL_VERSION', 'alpdroid-v1')
|
19 |
+
API_URL = os.environ.get('API_URL', 'https://api.example.com/v1/chat/completions')
|
20 |
+
API_KEY = os.environ.get('API_KEY', 'your-api-key')
|
21 |
+
SYSTEM_PROMPT = os.environ.get('SYSTEM_PROMPT', 'You are AlpDroid, a helpful AI assistant.')
|
22 |
|
23 |
+
MODEL_NAME = 'AlpDroid'
|
24 |
+
LOGO_URL = "https://raw.githubusercontent.com/yourusername/alpdroid/main/logo.png" # GitHub logo linki
|
25 |
+
|
26 |
+
# Default prompts
|
27 |
+
DEFAULT_PROMPTS = [
|
28 |
+
{"title": "💻 Kod Yaz", "description": "Python kodu yazma konusunda yardım et"},
|
29 |
+
{"title": "🤖 AI Açıkla", "description": "Yapay zeka konularını basit şekilde açıkla"},
|
30 |
+
{"title": "📚 Öğren", "description": "Yeni bir konu öğrenmek istiyorum"},
|
31 |
+
{"title": "🔧 Problem Çöz", "description": "Teknik bir problemi çözmeye yardım et"}
|
32 |
+
]
|
33 |
+
|
34 |
+
# Simple examples for code playground
|
35 |
+
EXAMPLES = {
|
36 |
+
"Web Uygulamaları": [
|
37 |
+
{"title": "Todo App", "description": "Basit bir yapılacaklar listesi uygulaması"},
|
38 |
+
{"title": "Hesap Makinesi", "description": "JavaScript hesap makinesi"},
|
39 |
+
{"title": "Hava Durumu", "description": "Hava durumu gösterici widget"}
|
40 |
+
],
|
41 |
+
"Oyunlar": [
|
42 |
+
{"title": "Snake Oyunu", "description": "Klasik yılan oyunu"},
|
43 |
+
{"title": "Memory Oyunu", "description": "Hafıza kartları oyunu"},
|
44 |
+
{"title": "Tic Tac Toe", "description": "XOX oyunu"}
|
45 |
+
]
|
46 |
+
}
|
47 |
+
|
48 |
+
def clear():
|
49 |
+
return gr.update(value=None)
|
50 |
+
|
51 |
+
def submit(sender_value, chatbot_value):
|
52 |
+
if sender_value is not None:
|
53 |
+
chatbot_value.append({
|
54 |
+
"role": "user",
|
55 |
+
"content": sender_value,
|
56 |
+
})
|
57 |
+
|
58 |
+
chatbot_value.append({
|
59 |
+
"role": "assistant",
|
60 |
+
"content": "Düşünüyorum...",
|
61 |
+
"loading": True,
|
62 |
+
"status": "pending"
|
63 |
+
})
|
64 |
+
|
65 |
+
yield {
|
66 |
+
sender: gr.update(value=None, loading=True),
|
67 |
+
clear_btn: gr.update(disabled=True),
|
68 |
+
chatbot: gr.update(value=chatbot_value)
|
69 |
+
}
|
70 |
+
|
71 |
+
try:
|
72 |
+
# Simulate API call (replace with your actual API)
|
73 |
+
time.sleep(2) # Simulated thinking time
|
74 |
+
|
75 |
+
chatbot_value[-1]["content"] = "Bu bir test yanıtıdır. Gerçek API entegrasyonu için API_URL ve API_KEY değerlerini ayarlayın."
|
76 |
+
chatbot_value[-1]["loading"] = False
|
77 |
+
chatbot_value[-1]["status"] = "done"
|
78 |
+
chatbot_value[-1]["footer"] = "2.00s"
|
79 |
+
|
80 |
+
yield {
|
81 |
+
clear_btn: gr.update(disabled=False),
|
82 |
+
sender: gr.update(loading=False),
|
83 |
+
chatbot: gr.update(value=chatbot_value),
|
84 |
+
}
|
85 |
+
|
86 |
+
except Exception as e:
|
87 |
+
chatbot_value[-1]["loading"] = False
|
88 |
+
chatbot_value[-1]["status"] = "done"
|
89 |
+
chatbot_value[-1]["content"] = "Bir hata oluştu, lütfen tekrar deneyin."
|
90 |
+
yield {
|
91 |
+
clear_btn: gr.update(disabled=False),
|
92 |
+
sender: gr.update(loading=False),
|
93 |
+
chatbot: gr.update(value=chatbot_value),
|
94 |
+
}
|
95 |
+
|
96 |
+
def generate_code(query: str):
|
97 |
+
if not query:
|
98 |
+
return {
|
99 |
+
code_output: gr.update(value=""),
|
100 |
+
sandbox: gr.update(value=""),
|
101 |
+
state_tab: gr.update(active_key="empty")
|
102 |
+
}
|
103 |
+
|
104 |
+
# Simulate code generation
|
105 |
+
yield {
|
106 |
+
code_output: gr.update(value="Kod üretiliyor..."),
|
107 |
+
sandbox: gr.update(value=""),
|
108 |
+
state_tab: gr.update(active_key="loading")
|
109 |
+
}
|
110 |
+
|
111 |
+
time.sleep(3) # Simulate processing time
|
112 |
+
|
113 |
+
# Simple HTML example
|
114 |
+
sample_code = f"""<!DOCTYPE html>
|
115 |
+
<html>
|
116 |
+
<head>
|
117 |
+
<title>{query}</title>
|
118 |
+
<style>
|
119 |
+
body {{
|
120 |
+
font-family: Arial, sans-serif;
|
121 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
122 |
+
color: white;
|
123 |
+
padding: 20px;
|
124 |
+
text-align: center;
|
125 |
+
}}
|
126 |
+
.container {{
|
127 |
+
background: rgba(255,255,255,0.1);
|
128 |
+
padding: 30px;
|
129 |
+
border-radius: 15px;
|
130 |
+
max-width: 600px;
|
131 |
+
margin: 50px auto;
|
132 |
+
}}
|
133 |
+
</style>
|
134 |
+
</head>
|
135 |
+
<body>
|
136 |
+
<div class="container">
|
137 |
+
<h1>AlpDroid tarafından üretildi</h1>
|
138 |
+
<p>İstek: {query}</p>
|
139 |
+
<p>Bu basit bir örnek HTML kodu. Gerçek API entegrasyonu için kodu düzenleyin.</p>
|
140 |
+
</div>
|
141 |
+
</body>
|
142 |
+
</html>"""
|
143 |
+
|
144 |
+
encoded_html = base64.b64encode(sample_code.encode('utf-8')).decode('utf-8')
|
145 |
+
data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}"
|
146 |
+
iframe = f'<iframe src="{data_uri}" width="100%" height="500px" sandbox="allow-scripts"></iframe>'
|
147 |
+
|
148 |
+
yield {
|
149 |
+
code_output: gr.update(value=f"```html\n{sample_code}\n```"),
|
150 |
+
sandbox: gr.update(value=iframe),
|
151 |
+
state_tab: gr.update(active_key="render")
|
152 |
+
}
|
153 |
+
|
154 |
+
def select_example(example):
|
155 |
+
if isinstance(example, dict):
|
156 |
+
return example.get("description", "")
|
157 |
+
return ""
|
158 |
+
|
159 |
+
# Purple theme CSS
|
160 |
css = """
|
161 |
+
/* Purple Theme for AlpDroid */
|
162 |
+
:root {
|
163 |
+
--primary-color: #8B5CF6;
|
164 |
+
--secondary-color: #A78BFA;
|
165 |
+
--background: #1F1B24;
|
166 |
+
--surface: #2D2438;
|
167 |
+
--text-primary: #FFFFFF;
|
168 |
+
--text-secondary: #C4B5FD;
|
169 |
+
}
|
170 |
+
|
171 |
.gradio-container {
|
172 |
+
background: var(--background) !important;
|
173 |
+
}
|
174 |
+
|
175 |
+
/* Chat interface styling */
|
176 |
+
.ant-tabs-tab {
|
177 |
+
color: var(--text-secondary) !important;
|
178 |
+
}
|
179 |
+
|
180 |
+
.ant-tabs-tab-active {
|
181 |
+
color: var(--primary-color) !important;
|
182 |
+
}
|
183 |
+
|
184 |
+
/* Button styling */
|
185 |
+
.ant-btn-primary {
|
186 |
+
background: var(--primary-color) !important;
|
187 |
+
border-color: var(--primary-color) !important;
|
188 |
+
}
|
189 |
+
|
190 |
+
.ant-btn-primary:hover {
|
191 |
+
background: var(--secondary-color) !important;
|
192 |
+
border-color: var(--secondary-color) !important;
|
193 |
+
}
|
194 |
+
|
195 |
+
/* Input styling */
|
196 |
+
.ant-input, .ant-input-textarea {
|
197 |
+
background: var(--surface) !important;
|
198 |
+
border-color: var(--secondary-color) !important;
|
199 |
+
color: var(--text-primary) !important;
|
200 |
+
}
|
201 |
+
|
202 |
+
/* Card styling */
|
203 |
+
.ant-card {
|
204 |
+
background: var(--surface) !important;
|
205 |
+
border-color: var(--secondary-color) !important;
|
206 |
+
}
|
207 |
+
|
208 |
+
.ant-card-head-title {
|
209 |
+
color: var(--text-primary) !important;
|
210 |
+
}
|
211 |
+
|
212 |
+
/* Example cards */
|
213 |
+
.example-card {
|
214 |
+
background: var(--surface) !important;
|
215 |
+
border: 1px solid var(--secondary-color) !important;
|
216 |
+
border-radius: 12px;
|
217 |
+
margin: 8px;
|
218 |
+
transition: all 0.3s ease;
|
219 |
+
}
|
220 |
+
|
221 |
+
.example-card:hover {
|
222 |
+
transform: translateY(-2px);
|
223 |
+
box-shadow: 0 8px 25px rgba(139, 92, 246, 0.3) !important;
|
224 |
+
border-color: var(--primary-color) !important;
|
225 |
}
|
226 |
+
|
227 |
+
.example-card .ant-card-meta-title {
|
228 |
+
color: var(--text-primary) !important;
|
229 |
+
font-weight: 600;
|
230 |
+
}
|
231 |
+
|
232 |
+
.example-card .ant-card-meta-description {
|
233 |
+
color: var(--text-secondary) !important;
|
234 |
+
}
|
235 |
+
|
236 |
+
/* Output container */
|
237 |
+
.output-container {
|
238 |
+
background: var(--surface) !important;
|
239 |
+
border-radius: 12px;
|
240 |
+
min-height: 500px;
|
241 |
+
}
|
242 |
+
|
243 |
+
.output-empty {
|
244 |
+
color: var(--text-secondary) !important;
|
245 |
+
}
|
246 |
+
|
247 |
+
/* Loading spinner */
|
248 |
+
.ant-spin-text {
|
249 |
+
color: var(--text-secondary) !important;
|
250 |
+
}
|
251 |
+
|
252 |
+
/* Iframe container */
|
253 |
+
.output-html iframe {
|
254 |
+
border-radius: 8px;
|
255 |
+
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
256 |
+
}
|
257 |
+
|
258 |
+
/* Scrollbar */
|
259 |
+
::-webkit-scrollbar {
|
260 |
+
width: 8px;
|
261 |
+
}
|
262 |
+
|
263 |
+
::-webkit-scrollbar-track {
|
264 |
+
background: var(--surface);
|
265 |
+
}
|
266 |
+
|
267 |
+
::-webkit-scrollbar-thumb {
|
268 |
+
background: var(--primary-color);
|
269 |
+
border-radius: 4px;
|
270 |
+
}
|
271 |
+
|
272 |
+
::-webkit-scrollbar-thumb:hover {
|
273 |
+
background: var(--secondary-color);
|
274 |
}
|
275 |
"""
|
276 |
|
277 |
+
# Main interface
|
278 |
+
with gr.Blocks(css=css, theme=gr.themes.Base()) as demo, ms.Application(), antdx.XProvider():
|
279 |
+
with antd.Tabs() as tabs:
|
280 |
+
# Chat Tab
|
281 |
+
with antd.Tabs.Item(key="chat", label="💬 AlpDroid Chat"):
|
282 |
+
with antd.Flex(vertical=True, gap="middle", elem_style={"height": "80vh"}):
|
283 |
+
chatbot = pro.Chatbot(
|
284 |
+
elem_style={"flex": 1, "maxHeight": "600px"},
|
285 |
+
welcome_config=ChatbotWelcomeConfig(
|
286 |
+
variant="borderless",
|
287 |
+
icon=LOGO_URL,
|
288 |
+
title="Merhaba, Ben AlpDroid! 🤖",
|
289 |
+
description="Size nasıl yardımcı olabilirim?",
|
290 |
+
prompts=ChatbotPromptsConfig(
|
291 |
+
title="Bugün size nasıl yardımcı olabilirim?",
|
292 |
+
items=DEFAULT_PROMPTS
|
293 |
+
)
|
294 |
+
),
|
295 |
+
user_config=ChatbotUserConfig(actions=["copy"]),
|
296 |
+
bot_config=ChatbotBotConfig(
|
297 |
+
header=MODEL_NAME,
|
298 |
+
avatar=LOGO_URL,
|
299 |
+
actions=["copy"]
|
300 |
+
)
|
301 |
+
)
|
302 |
|
303 |
+
with antdx.Sender() as sender:
|
304 |
+
with ms.Slot("prefix"):
|
305 |
+
with antd.Button(color="default", variant="text") as clear_btn:
|
306 |
+
with ms.Slot("icon"):
|
307 |
+
antd.Icon("ClearOutlined")
|
308 |
|
309 |
+
# Code Playground Tab
|
310 |
+
with antd.Tabs.Item(key="code", label="💻 Kod Playground"):
|
311 |
+
with antd.Row(gutter=[24, 16]):
|
312 |
+
with antd.Col(span=24, md=12):
|
313 |
+
with antd.Card(title="📝 Kod Talep Et"):
|
314 |
+
code_input = antd.Input.Textarea(
|
315 |
+
size="large",
|
316 |
+
placeholder="Ne tür bir uygulama istiyorsunuz? (örn: Todo listesi, hesap makinesi)",
|
317 |
+
auto_size={"minRows": 3, "maxRows": 6}
|
318 |
+
)
|
319 |
+
|
320 |
+
with antd.Flex(gap="small", elem_style={"marginTop": "16px"}):
|
321 |
+
code_btn = antd.Button("🚀 Kod Üret", type="primary", size="large")
|
322 |
+
|
323 |
+
code_output = ms.Markdown(elem_style={"marginTop": "16px", "maxHeight": "300px", "overflow": "auto"})
|
324 |
|
325 |
+
# Examples
|
326 |
+
with antd.Card(title="💡 Örnekler", elem_style={"marginTop": "16px"}):
|
327 |
+
with antd.Tabs() as example_tabs:
|
328 |
+
for category, examples in EXAMPLES.items():
|
329 |
+
with antd.Tabs.Item(key=category, label=category):
|
330 |
+
with antd.Flex(gap="small", wrap=True):
|
331 |
+
for example in examples:
|
332 |
+
with antd.Card(elem_classes="example-card", hoverable=True) as example_card:
|
333 |
+
antd.Card.Meta(
|
334 |
+
title=example['title'],
|
335 |
+
description=example['description']
|
336 |
+
)
|
337 |
+
|
338 |
+
example_card.click(
|
339 |
+
fn=select_example,
|
340 |
+
inputs=[gr.State(example)],
|
341 |
+
outputs=[code_input]
|
342 |
+
)
|
343 |
+
|
344 |
+
with antd.Col(span=24, md=12):
|
345 |
+
with antd.Card(title="🎯 Sonuç", elem_classes="output-container"):
|
346 |
+
with antd.Tabs(active_key="empty", render_tab_bar="() => null") as state_tab:
|
347 |
+
with antd.Tabs.Item(key="empty"):
|
348 |
+
antd.Empty(
|
349 |
+
description="Kod üretmek için talebinizi girin",
|
350 |
+
elem_classes="output-empty"
|
351 |
+
)
|
352 |
+
with antd.Tabs.Item(key="loading"):
|
353 |
+
antd.Spin(True, tip="Kod üretiliyor...", size="large")
|
354 |
+
with antd.Tabs.Item(key="render"):
|
355 |
+
sandbox = gr.HTML()
|
356 |
+
|
357 |
+
# Event handlers
|
358 |
+
clear_btn.click(fn=clear, outputs=[chatbot])
|
359 |
+
|
360 |
+
submit_event = sender.submit(
|
361 |
+
fn=submit,
|
362 |
+
inputs=[sender, chatbot],
|
363 |
+
outputs=[sender, chatbot, clear_btn]
|
364 |
+
)
|
365 |
+
|
366 |
+
code_btn.click(
|
367 |
+
fn=generate_code,
|
368 |
+
inputs=[code_input],
|
369 |
+
outputs=[code_output, sandbox, state_tab]
|
370 |
)
|
|
|
371 |
|
372 |
+
if __name__ == '__main__':
|
373 |
+
demo.queue().launch(
|
374 |
+
server_name="0.0.0.0",
|
375 |
+
server_port=7860,
|
376 |
+
share=True
|
377 |
+
)
|