Spaces:
Sleeping
Sleeping
File size: 13,863 Bytes
c8a5c43 29b6bc4 7eb1fb9 1359a02 a245ee7 c8a5c43 a245ee7 c8a5c43 29b6bc4 c8a5c43 7eb1fb9 f565471 5bf6ac7 ae68c7f 653b1c0 5af0503 ae68c7f d385e4b 5af0503 ae68c7f 6da6133 5af0503 ae68c7f d385e4b 42de6fe ae68c7f befce47 c8a5c43 481e164 42de6fe ae68c7f 481e164 ae68c7f 5af0503 ae68c7f 3411c78 f565471 ae68c7f f565471 befce47 5af0503 ae68c7f f565471 ff8ac04 1a5e59e 42de6fe ae68c7f 653b1c0 2827a07 befce47 f565471 5bf6ac7 4b21cf5 7eb1fb9 7d7d5bc 7eb1fb9 3029284 ae68c7f 7eb1fb9 5c97131 b140149 4b21cf5 7eb1fb9 d1f1b10 4b21cf5 ae68c7f 4b21cf5 5dadbe6 c8a5c43 3f1142b 4b21cf5 72ece84 4b21cf5 72ece84 4b21cf5 5dadbe6 ae68c7f c8a5c43 ae68c7f 7ff88b6 c8a5c43 21504b7 c8a5c43 7ff88b6 21504b7 c8a5c43 69d9b19 c8a5c43 69d9b19 c8a5c43 69d9b19 8bc6026 7ff88b6 7cc787f e86b8d9 c8a5c43 b7116ff 954d993 4f30ba8 ae68c7f e35061d c331c08 ae68c7f 5a754ac 42de6fe 5dadbe6 42de6fe 7ff88b6 c8a5c43 653b1c0 7ff88b6 ae68c7f 653b1c0 ae68c7f 653b1c0 ae68c7f fd820f8 63f6ecc ae68c7f 1aa927f c8a5c43 1aa927f ae68c7f 2827a07 8000fad ae68c7f 676013c 8000fad ae68c7f 8000fad ae68c7f 00bd42e 8000fad 1a5e59e ae68c7f 0646e2a 5a754ac af6836b ae68c7f 954d993 1a5e59e ae68c7f 954d993 ae68c7f 954d993 ae68c7f 954d993 ae68c7f 954d993 ae68c7f 954d993 ae68c7f 954d993 ae68c7f d1a2d46 1571e20 7ff88b6 |
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 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
import bleach
import gradio as gr
import requests
import json
import os
import markdown
from markdown.extensions.codehilite import CodeHiliteExtension
from markdown.extensions.fenced_code import FencedCodeExtension
import markdown.extensions.fenced_code
import html
import re
ALLOWED_TAGS = [
'b', 'i', 'strong', 'em', 'a', 'p', 'ul', 'ol', 'li', 'br', 'hr',
'blockquote', 'code', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img'
]
ALLOWED_ATTRIBUTES = {
'a': ['href', 'title', 'target'],
'img': ['src', 'alt', 'title', 'width', 'height']
}
API_URL = "https://host.palple.polrambora.com/pmsq"
sessions = {}
PRIMARY_SYSTEM_INSTRUCTIONS = "You are P-MSQ (Messaging Service Query), a friendly AI Chatbot that can help in any situations"
ASSISTANT_PIC_PATH = "https://huggingface.co/spaces/PLRMB/P-MSQ-API-PREVIEW/resolve/main/API.png"
USER_PIC_PATH = "https://huggingface.co/spaces/PLRMB/P-MSQ-API-PREVIEW/resolve/main/usr.png"
def render_avatars(userid):
try:
response = requests.post(
'https://host.palple.polrambora.com/userexistence',
json={
'userid': userid
},
timeout=10
)
if response.status_code == 200:
response_json = response.json()
return response_json["avatar"]["link"]
except Exception as e:
return None
except requests.exceptions.Timeout:
return None
def authorize(user, api_key, system_message):
test_data = {
"user": user,
"key": api_key
}
try:
response = requests.post(
"https://host.palple.polrambora.com/check_key_impv",
json=test_data,
)
if response.status_code == 200:
response_json = response.json()
avatar = render_avatars(user) or USER_PIC_PATH
if api_key not in sessions:
sessions[api_key] = {
"history": [],
"headers": {
"authorization": api_key,
"Content-Type": 'application/json'
},
"avatar": avatar,
"system_message": system_message
}
return True
elif response.status_code == 403:
return 403
else:
return False
except Exception as e:
return False
def respond(message, api_key, max_tokens, top_p, temperature):
session = sessions.get(api_key, {})
headers = session.get("headers", {})
system_message = session.get("system_message", PRIMARY_SYSTEM_INSTRUCTIONS)
messages = [
{"role": "system", "content": system_message},
*[
{"role": "user", "content": user_msg} if user_msg else {"role": "assistant", "content": assistant_msg}
for user_msg, assistant_msg, _, _, _, _ in session.get("history", [])
],
{"role": "user", "content": message}
]
data = {
"preferences": {
"max_char": max_tokens,
"temperature": temperature,
"top_p": top_p,
"system_message": system_message,
},
"conversation_history": messages,
"input": message,
"stream": True,
}
assistant_reply = ""
try:
response = requests.post(API_URL, headers=headers, data=json.dumps(data), stream=True)
if response.status_code == 200:
for line in response.iter_lines():
line = line.decode('utf-8')
if line.strip():
try:
if line.startswith("data:"):
line = line[5:].strip()
if line:
chunk = json.loads(line)
chunk_message = chunk.get("delta", {}).get("content", "")
assistant_reply += chunk_message
yield assistant_reply # Stream the response incrementally
except json.JSONDecodeError:
pass
session["history"].append((message, assistant_reply, "You", "P-ALPLE", session["avatar"], ASSISTANT_PIC_PATH))
else:
yield f"Error: {response.status_code} - {response.text}"
except Exception as e:
yield f"Error: {str(e)}"
def format_code_blocks(text):
code_pattern = re.compile(r'```(.*?)```', re.DOTALL)
return code_pattern.sub(lambda match: f"<pre><code>{html.escape(match.group(1))}</code></pre>", text)
def render_markdown(text):
return markdown.markdown(text, extensions=[FencedCodeExtension()])
import re
def render_message(history):
messages_html = """
<div id="chatbox-container" class="chatbox" style="height: 400px; overflow: auto; border: 1px solid #262626; padding: 10px; background-color: #171717; display: flex; flex-direction: column-reverse;">
<div id="messages" style="display: block; margin-bottom: 10px;">"""
seen_messages = set()
for user_message, assistant_message, user_profile, assistant_profile, user_pic, assistant_pic in history:
if user_message and ("user", user_message) not in seen_messages:
seen_messages.add(("user", user_message))
user_message_html = process_message(user_message)
messages_html += f"""
<div style='display: flex; flex-direction: column; align-items: flex-start; margin-bottom: 10px;'>
<img src='{user_pic}' style='width: 40px; height: 40px; border-radius: 50%; margin-bottom: 5px;'>
<div style='color: white; white-space: pre-wrap;'>{user_message_html}</div>
</div>"""
if assistant_message and ("assistant", assistant_message) not in seen_messages:
seen_messages.add(("assistant", assistant_message))
assistant_message_html = process_message(assistant_message)
messages_html += f"""
<div style='display: flex; flex-direction: column; align-items: flex-start; margin-bottom: 10px;'>
<img src='{assistant_pic}' style='width: 40px; height: 40px; border-radius: 50%; margin-bottom: 5px;'>
<div style='color: white; white-space: pre-wrap;'>{assistant_message_html}</div>
</div>"""
messages_html += "</div></div>"
return messages_html
def process_message(message):
code_block_pattern = re.compile(r"```(\w+)?\n(.*?)```", re.DOTALL)
parts = code_block_pattern.split(message)
for i in range(len(parts)):
if i % 3 == 0:
parts[i] = escape_html(parts[i])
parts[i] = render_inline_markdown(parts[i])
elif i % 3 == 1:
continue
else:
lang_class = parts[i - 1] or ""
parts[i] = f"<pre><code class='language-{lang_class}'>{escape_html(parts[i])}</code></pre>"
return "".join(parts)
def escape_html(text):
return (text
.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace('"', """)
.replace("'", "'"))
def render_inline_markdown(text):
text = markdown.markdown(text, output_format='xhtml')
return text
css="""
.chatbox {height: 400px; overflow: auto; border: 1px solid #262626; padding: 10px; background-color: #171717; display: flex; flex-direction: column-reverse;}
"""
with gr.Blocks(css=css) as demo:
with gr.Column(visible=False) as auth_view:
gr.Markdown("## P-MSQ Authorization")
gr.Markdown("P-MSQ is in closed alpha test! The model, api and more are subject to change.")
api_user_input = gr.Textbox(placeholder="snowflake", label="UserID", type='email')
api_key_input = gr.Textbox(placeholder="Enter your API key", label="Token", type='password')
auth_button = gr.Button("Authorize")
auth_status = gr.Textbox(label="Authorization Status", interactive=False)
with gr.Column(visible=False) as chat_view:
gr.HTML("""
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js"></script>
<script>
MathJax = {
tex: { inlineMath: [['\\(', '\\)'], ['\\[', '\\]']] },
svg: { scale: 1.2 }
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.min.js"></script>
""")
gr.Markdown("## P-MSQ Chat Interface")
chatbot_output = gr.HTML(elem_id="chatbox-container")
gr.Markdown(elem_id="chatbox-container")
msg_input = gr.Text(
show_label=False,
placeholder="Type your message and press Shift+Enter...",
lines=2,
elem_id="input-text"
)
send_btn = gr.Button("Send")
regen_btn = gr.Button("Clear")
system_instructions_input = gr.Textbox(placeholder="Enter custom instructions (optional)",
label="Custom System Instructions",
lines=2)
save_instructions_btn = gr.Button("Save Instructions")
gr.Markdown("### Settings")
max_tokens = gr.Slider(minimum=1, maximum=2048, value=1024, step=1, label="Max new tokens")
top_p = gr.Slider(minimum=0, maximum=2, value=0.8, step=0.1, label="Top P")
temperature = gr.Slider(minimum=0.1, maximum=1, value=0.7, step=0.1, label="Temperature")
history_state = gr.State([])
last_message_state = gr.State("")
def user_interaction(message, history, api_key, max_tokens, top_p, temperature):
loading_message = history + [(message, "Loading...", "You", "P-ALPLE", sessions[api_key]["avatar"], ASSISTANT_PIC_PATH)]
yield render_message(loading_message), loading_message, ""
assistant_response = ""
for partial_reply in respond(message, api_key, max_tokens, top_p, temperature):
assistant_response = partial_reply # Accumulate streamed response
partial_history = history + [(message, assistant_response, "You", "P-ALPLE", sessions[api_key]["avatar"], ASSISTANT_PIC_PATH)]
yield render_message(partial_history), partial_history, ""
final_history = history + [(message, assistant_response, "You", "P-ALPLE", sessions[api_key]["avatar"], ASSISTANT_PIC_PATH)]
yield render_message(final_history), final_history, ""
def regenerate_response(history, last_message, max_tokens, top_p, temperature):
return "", []
def clear_history(api_key):
if api_key in sessions:
sessions[api_key]["history"] = []
return "", []
def load_conversation(api_key):
session = sessions.get(api_key, {})
history = session.get("history", [])
return render_message(history), history
msg_input.submit(
user_interaction,
inputs=[msg_input, history_state, api_key_input, max_tokens, top_p, temperature],
outputs=[chatbot_output, history_state, msg_input],
)
send_btn.click(
user_interaction,
inputs=[msg_input, history_state, api_key_input, max_tokens, top_p, temperature],
outputs=[chatbot_output, history_state, msg_input],
)
regen_btn.click(clear_history,
inputs=[api_key_input],
outputs=[chatbot_output, history_state])
with gr.Column(visible=True) as blacklist_view:
gr.Markdown("## Sunsetting gradio P-MSQ interface")
gr.Markdown("P-MSQ Gradio Interface is moving to another - [Next.js powered PMSQ](https://pmsq.polrambora.com)")
def authorize_and_proceed(user, api_key):
if authorize(user, api_key, PRIMARY_SYSTEM_INSTRUCTIONS):
gr.Info("Loading, please wait.")
messages_html, history = load_conversation(api_key)
return (
gr.update(visible=False),
gr.update(visible=True),
messages_html,
history
)
elif authorize(user, api_key, PRIMARY_SYSTEM_INSTRUCTIONS) == 403:
return (
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=True),
)
else:
gr.Warning("Incorrect userid/token")
return (
gr.update(visible=True),
gr.update(visible=False),
auth_status.update(value="Invalid userid/token")
)
def save_custom_instructions(api_key, custom_instructions):
if api_key in sessions:
gr.Info("Instructions updated, we recommend to start the new conversation to make it more efficient.")
sessions[api_key]["system_message"] = custom_instructions
return "Instructions updated!", gr.update(value="")
else:
gr.Warning("Your session has been expired, please refresh the page and login again.")
return "Session not found.", gr.update(value="")
auth_button.click(authorize_and_proceed, inputs=[api_user_input, api_key_input], outputs=[auth_view, chat_view, chatbot_output, history_state])
save_instructions_btn.click(save_custom_instructions, inputs=[api_key_input, system_instructions_input], outputs=auth_status)
demo.launch(show_api=False)
if __name__ == "__main__":
demo.queue = False |