Spaces:
Runtime error
Runtime error
import re | |
import os | |
import panel as pn | |
from mistralai.async_client import MistralAsyncClient | |
from mistralai.models.chat_completion import ChatMessage | |
from panel.io.mime_render import exec_with_return | |
pn.extension("codeeditor", sizing_mode="stretch_width") | |
LLM_MODEL = "mistral-small" | |
SYSTEM_MESSAGE = ChatMessage( | |
role="system", | |
content=( | |
"You are a renowned data visualization expert " | |
"with a strong background in matplotlib. " | |
"Your primary goal is to assist the user " | |
"in edit the code based on user request " | |
"using best practices. Simply provide code " | |
"in code fences (```python). You must have `fig` " | |
"as the last line of code" | |
), | |
) | |
USER_CONTENT_FORMAT = """ | |
Request: | |
{content} | |
Code: | |
```python | |
{code} | |
``` | |
""".strip() | |
DEFAULT_MATPLOTLIB = """ | |
import numpy as np | |
import matplotlib.pyplot as plt | |
fig = plt.figure() | |
ax = plt.axes(title="Plot Title", xlabel="X Label", ylabel="Y Label") | |
x = np.linspace(1, 10) | |
y = np.sin(x) | |
z = np.cos(x) | |
c = np.log(x) | |
ax.plot(x, y, c="blue", label="sin") | |
ax.plot(x, z, c="orange", label="cos") | |
img = ax.scatter(x, c, c=c, label="log") | |
plt.colorbar(img, label="Colorbar") | |
plt.legend() | |
# must have fig at the end! | |
fig | |
""".strip() | |
async def callback(content: str, user: str, instance: pn.chat.ChatInterface): | |
if not api_key_input.value: | |
yield "Please first enter your Mistral API key" | |
return | |
client = MistralAsyncClient(api_key=api_key_input.value) | |
# system | |
messages = [SYSTEM_MESSAGE] | |
# history | |
messages.extend([ChatMessage(**message) for message in instance.serialize()[1:-1]]) | |
# new user contents | |
user_content = USER_CONTENT_FORMAT.format( | |
content=content, code=code_editor.value | |
) | |
messages.append(ChatMessage(role="user", content=user_content)) | |
# stream LLM tokens | |
message = "" | |
async for chunk in client.chat_stream(model=LLM_MODEL, messages=messages): | |
if chunk.choices[0].delta.content is not None: | |
message += chunk.choices[0].delta.content | |
yield message | |
# extract code | |
llm_code = re.findall(r"```python\n(.*)\n```", message, re.DOTALL)[0] | |
if llm_code.splitlines()[-1].strip() != "fig": | |
llm_code += "\nfig" | |
code_editor.value = llm_code | |
def update_plot(event): | |
matplotlib_pane.object = exec_with_return(event.new) | |
# instantiate widgets and panes | |
api_key_input = pn.widgets.PasswordInput(placeholder="Enter your MistralAI API Key") | |
chat_interface = pn.chat.ChatInterface( | |
callback=callback, | |
show_clear=False, | |
show_undo=False, | |
show_button_name=False, | |
message_params=dict( | |
show_reaction_icons=False, | |
show_copy_icon=False, | |
), | |
height=650, | |
callback_exception="verbose", | |
) | |
matplotlib_pane = pn.pane.Matplotlib( | |
exec_with_return(DEFAULT_MATPLOTLIB), | |
sizing_mode="stretch_both", | |
tight=True, | |
) | |
code_editor = pn.widgets.CodeEditor( | |
value=DEFAULT_MATPLOTLIB, | |
language="python", | |
sizing_mode="stretch_both", | |
) | |
# watch for code changes | |
code_editor.param.watch(update_plot, "value") | |
# lay them out | |
tabs = pn.Tabs( | |
("Plot", matplotlib_pane), | |
("Code", code_editor), | |
) | |
sidebar = [api_key_input, chat_interface] | |
main = [tabs] | |
template = pn.template.FastListTemplate( | |
sidebar=sidebar, | |
main=main, | |
sidebar_width=600, | |
main_layout=None, | |
accent_base_color="#fd7000", | |
header_background="#fd7000", | |
title="Chat with Plot" | |
) | |
template.servable() | |