Spaces:
Running
Running
feat: init
Browse files- .gitignore +2 -0
- app.py +254 -0
- requirements.txt +2 -0
.gitignore
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
venv
|
2 |
+
.idea
|
app.py
ADDED
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import aiohttp
|
3 |
+
import asyncio
|
4 |
+
import json
|
5 |
+
|
6 |
+
# Define the types and their associated models with labels and values
|
7 |
+
types_and_models = {
|
8 |
+
'deepinfra': [
|
9 |
+
('Llama 8B', 'meta-llama/Meta-Llama-3.1-8B-Instruct'),
|
10 |
+
('Llama 70B', 'meta-llama/Meta-Llama-3.1-70B-Instruct'),
|
11 |
+
('Llama 405B', 'meta-llama/Meta-Llama-3.1-405B-Instruct'),
|
12 |
+
('Qwen 72B', 'Qwen/Qwen2.5-72B-Instruct'),
|
13 |
+
],
|
14 |
+
'groq': [
|
15 |
+
('Llama 3.1 8B Instant', 'llama-3.1-8b-instant'),
|
16 |
+
('Llama 3.1 70B Versatile', 'llama-3.1-70b-versatile'),
|
17 |
+
('Gemma 9B IT', 'gemma2-9b-it'),
|
18 |
+
('Llama3 Groq 70B Preview', 'llama3-groq-70b-8192-tool-use-preview'),
|
19 |
+
('Llama3 Groq 8B Preview', 'llama3-groq-8b-8192-tool-use-preview'),
|
20 |
+
],
|
21 |
+
'openai': [
|
22 |
+
('GPT-4o Mini', 'gpt-4o-mini'),
|
23 |
+
('GPT-4o', 'gpt-4o'),
|
24 |
+
],
|
25 |
+
}
|
26 |
+
|
27 |
+
|
28 |
+
def update_models(selected_type):
|
29 |
+
# Update the models dropdown based on the selected type
|
30 |
+
choices = types_and_models[selected_type]
|
31 |
+
default_value = choices[0][1] # The value of the first model
|
32 |
+
return gr.update(choices=choices, value=default_value)
|
33 |
+
|
34 |
+
|
35 |
+
async def chat_with_server(chat_history, api_key, base_url, selected_type, selected_model, temperature, max_tokens):
|
36 |
+
headers = {
|
37 |
+
'Content-Type': 'application/json',
|
38 |
+
'Authorization': f'Bearer {api_key}',
|
39 |
+
}
|
40 |
+
|
41 |
+
if base_url:
|
42 |
+
base_url = base_url
|
43 |
+
else:
|
44 |
+
base_url = 'http://localhost:3000' # Default base URL
|
45 |
+
|
46 |
+
# Prepare the messages for the API
|
47 |
+
api_messages = []
|
48 |
+
for user_msg, assistant_msg in chat_history:
|
49 |
+
if user_msg is not None:
|
50 |
+
api_messages.append({'role': 'user', 'content': user_msg})
|
51 |
+
if assistant_msg is not None and not assistant_msg.startswith("Assistant is typing"):
|
52 |
+
api_messages.append({'role': 'assistant', 'content': assistant_msg})
|
53 |
+
|
54 |
+
payload = {
|
55 |
+
'type': selected_type, # Include the selected type
|
56 |
+
'model': selected_model,
|
57 |
+
'messages': api_messages,
|
58 |
+
'temperature': temperature,
|
59 |
+
'max_tokens': int(max_tokens),
|
60 |
+
'stream': True, # Enable streaming
|
61 |
+
}
|
62 |
+
|
63 |
+
# Initialize typing animation
|
64 |
+
if chat_history:
|
65 |
+
chat_history[-1][1] = "Assistant is typing"
|
66 |
+
yield chat_history
|
67 |
+
|
68 |
+
async with aiohttp.ClientSession() as session:
|
69 |
+
try:
|
70 |
+
# Start the server request asynchronously
|
71 |
+
response_task = asyncio.create_task(session.post(
|
72 |
+
f'{base_url}/v1/chat/completions',
|
73 |
+
headers=headers,
|
74 |
+
json=payload,
|
75 |
+
timeout=300
|
76 |
+
))
|
77 |
+
|
78 |
+
# Typing animation variables
|
79 |
+
dots_count = 0
|
80 |
+
assistant_message = ''
|
81 |
+
|
82 |
+
while not response_task.done():
|
83 |
+
# Update typing animation
|
84 |
+
dots = '.' * ((dots_count % 3) + 1)
|
85 |
+
dots_count += 1
|
86 |
+
if chat_history:
|
87 |
+
chat_history[-1][1] = f"Assistant is typing{dots}"
|
88 |
+
yield chat_history
|
89 |
+
await asyncio.sleep(0.5) # Wait before updating again
|
90 |
+
|
91 |
+
# Now get the response
|
92 |
+
response = await response_task
|
93 |
+
if response.status != 200:
|
94 |
+
error_message = f"Error {response.status}: {await response.text()}"
|
95 |
+
chat_history[-1][1] = error_message
|
96 |
+
yield chat_history
|
97 |
+
return
|
98 |
+
|
99 |
+
assistant_message = ''
|
100 |
+
# Read the streaming response
|
101 |
+
async for line in response.content:
|
102 |
+
line = line.decode('utf-8').strip()
|
103 |
+
if line == '':
|
104 |
+
continue
|
105 |
+
if line == 'data: [DONE]':
|
106 |
+
break
|
107 |
+
if line.startswith('data: '):
|
108 |
+
data_str = line[6:].strip()
|
109 |
+
if data_str:
|
110 |
+
data = json.loads(data_str)
|
111 |
+
if 'choices' in data and len(data['choices']) > 0:
|
112 |
+
delta = data['choices'][0]['delta']
|
113 |
+
if 'content' in delta:
|
114 |
+
content = delta['content']
|
115 |
+
assistant_message += content
|
116 |
+
# Update the assistant's message in the chat
|
117 |
+
chat_history[-1][1] = assistant_message
|
118 |
+
yield chat_history
|
119 |
+
# Final update to the conversation
|
120 |
+
yield chat_history
|
121 |
+
|
122 |
+
except Exception as e:
|
123 |
+
error_message = f"Error: {str(e)}"
|
124 |
+
chat_history[-1][1] = error_message
|
125 |
+
yield chat_history
|
126 |
+
|
127 |
+
|
128 |
+
def reset_chat():
|
129 |
+
return []
|
130 |
+
|
131 |
+
|
132 |
+
with gr.Blocks() as demo:
|
133 |
+
gr.Markdown("# Chat Application")
|
134 |
+
|
135 |
+
with gr.Row():
|
136 |
+
api_key = gr.Textbox(label="API Key", placeholder="Enter your API Key",
|
137 |
+
value="ggkjgf", type="password", lines=1)
|
138 |
+
base_url = gr.Textbox(label="Base URL", placeholder="https://api.groq.com/openai/v1", lines=1)
|
139 |
+
selected_type = gr.Dropdown(
|
140 |
+
label="Type",
|
141 |
+
choices=list(types_and_models.keys()),
|
142 |
+
value=list(types_and_models.keys())[0]
|
143 |
+
)
|
144 |
+
# Initialize the selected_model with choices and value
|
145 |
+
initial_type = list(types_and_models.keys())[0]
|
146 |
+
initial_choices = types_and_models[initial_type]
|
147 |
+
selected_model = gr.Dropdown(
|
148 |
+
label="Model",
|
149 |
+
choices=initial_choices,
|
150 |
+
value=initial_choices[0][1] # First model's value
|
151 |
+
)
|
152 |
+
temperature = gr.Slider(label="Temperature", minimum=0, maximum=1, value=0.3, step=0.1)
|
153 |
+
max_tokens = gr.Number(label="Max Tokens", value=4096)
|
154 |
+
|
155 |
+
# Initialize the chatbot component
|
156 |
+
chatbot = gr.Chatbot(elem_id="chatbot", height=400)
|
157 |
+
|
158 |
+
with gr.Row():
|
159 |
+
with gr.Column(scale=10):
|
160 |
+
user_input = gr.Textbox(
|
161 |
+
show_label=False,
|
162 |
+
placeholder="Type your message here...",
|
163 |
+
lines=5,
|
164 |
+
container=False
|
165 |
+
)
|
166 |
+
with gr.Column(min_width=50, scale=1):
|
167 |
+
send_button = gr.Button("Send", variant="primary")
|
168 |
+
reset_button = gr.Button("Reset Chat")
|
169 |
+
|
170 |
+
# Update the models dropdown when the type changes
|
171 |
+
selected_type.change(
|
172 |
+
update_models,
|
173 |
+
inputs=selected_type,
|
174 |
+
outputs=selected_model
|
175 |
+
)
|
176 |
+
|
177 |
+
|
178 |
+
def user(user_message, chat_history):
|
179 |
+
# Append the user's message to the chat history
|
180 |
+
if not chat_history:
|
181 |
+
chat_history = []
|
182 |
+
chat_history = chat_history + [[user_message, None]]
|
183 |
+
return user_message, chat_history
|
184 |
+
|
185 |
+
# Set up the event handlers
|
186 |
+
|
187 |
+
|
188 |
+
send_button.click(
|
189 |
+
user,
|
190 |
+
inputs=[user_input, chatbot],
|
191 |
+
outputs=[user_input, chatbot]
|
192 |
+
).then(
|
193 |
+
chat_with_server,
|
194 |
+
inputs=[chatbot, api_key, base_url, selected_type, selected_model, temperature, max_tokens],
|
195 |
+
outputs=chatbot,
|
196 |
+
)
|
197 |
+
|
198 |
+
reset_button.click(reset_chat, outputs=chatbot)
|
199 |
+
|
200 |
+
# Include CSS to format code blocks and other markdown elements
|
201 |
+
gr.HTML("""
|
202 |
+
<style>
|
203 |
+
.message pre {
|
204 |
+
background-color: #f0f0f0;
|
205 |
+
padding: 10px;
|
206 |
+
border-radius: 5px;
|
207 |
+
overflow-x: auto;
|
208 |
+
}
|
209 |
+
.message code {
|
210 |
+
background-color: #f0f0f0;
|
211 |
+
padding: 2px 4px;
|
212 |
+
border-radius: 3px;
|
213 |
+
}
|
214 |
+
</style>
|
215 |
+
""")
|
216 |
+
|
217 |
+
# Add JavaScript for rendering Markdown and LaTeX
|
218 |
+
gr.HTML("""
|
219 |
+
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
220 |
+
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" crossorigin="anonymous"></script>
|
221 |
+
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" crossorigin="anonymous"></script>
|
222 |
+
<script>
|
223 |
+
function renderContent() {
|
224 |
+
const messages = document.querySelectorAll('.message');
|
225 |
+
messages.forEach((message) => {
|
226 |
+
// Render Markdown
|
227 |
+
message.innerHTML = marked.parse(message.innerHTML);
|
228 |
+
// Render LaTeX
|
229 |
+
renderMathInElement(message, {
|
230 |
+
delimiters: [
|
231 |
+
{left: "$$", right: "$$", display: true},
|
232 |
+
{left: "$", right: "$", display: false},
|
233 |
+
{left: "\\(", right: "\\)", display: false},
|
234 |
+
{left: "\\[", right: "\\]", display: true}
|
235 |
+
],
|
236 |
+
throwOnError: false
|
237 |
+
});
|
238 |
+
});
|
239 |
+
}
|
240 |
+
// Observe changes in the chatbox to render content
|
241 |
+
const chatbox = document.querySelector('#chatbot');
|
242 |
+
const observer = new MutationObserver((mutations) => {
|
243 |
+
for (let mutation of mutations) {
|
244 |
+
if (mutation.addedNodes.length > 0) {
|
245 |
+
renderContent();
|
246 |
+
}
|
247 |
+
}
|
248 |
+
});
|
249 |
+
observer.observe(chatbox, {childList: true, subtree: true});
|
250 |
+
</script>
|
251 |
+
""")
|
252 |
+
|
253 |
+
demo.queue()
|
254 |
+
demo.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
aiohttp
|