Includes the first version of a rudimentary chat app, still without the SQL capabilities that we want later. For now, we can connect to the Azure OpenAI source and then have the response displayed in a plotly dash webapp. Some styling and UI elements were also added, such as logos. UI components are designed that the user cannot enter the same query twice and cannot click the submit button as long as the query is running.
145 lines
4.0 KiB
Python
145 lines
4.0 KiB
Python
from typing import Any, Dict, Tuple
|
|
|
|
from dash import (
|
|
Dash,
|
|
Input,
|
|
Output,
|
|
State,
|
|
callback,
|
|
dcc,
|
|
get_asset_url,
|
|
html,
|
|
no_update,
|
|
)
|
|
from dash.exceptions import PreventUpdate
|
|
|
|
from .app_styles import header_style
|
|
from .data_chat import send_message
|
|
|
|
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
|
|
|
|
app = Dash(__name__, external_stylesheets=external_stylesheets)
|
|
app.index_string = header_style
|
|
|
|
err_style = {
|
|
"height": "0px",
|
|
"overflow": "hidden",
|
|
"transition": "height 0.5s ease-in-out",
|
|
"border-radius": "15px",
|
|
"background-color": "#FFCCCB",
|
|
"text-align": "center",
|
|
"color": "#FF6B6B",
|
|
"margin-top": "20px",
|
|
"margin-left": "20px",
|
|
"margin-right": "20px",
|
|
"font-weight": "bold",
|
|
"display": "flex",
|
|
"justify-content": "center",
|
|
"align-items": "center",
|
|
}
|
|
|
|
start_value = "Stelle deine Frage an die Datenbank..."
|
|
app.layout = html.Div(
|
|
[
|
|
html.Div(
|
|
[
|
|
html.H1("Datenbank-Chat", className="heading"),
|
|
html.Img(src=get_asset_url("logo.png"), className="logo"),
|
|
],
|
|
className="header-container",
|
|
), # Header
|
|
dcc.Store(
|
|
id="tmp-value", data=start_value, storage_type="session"
|
|
), # Store previous prompt
|
|
dcc.Textarea(
|
|
id="input-field",
|
|
value=start_value,
|
|
style={"width": "96%", "height": 200, "margin-left": "20px"},
|
|
), # Input field
|
|
html.Div([]), # Needed for keeping the layout clean
|
|
html.Button(
|
|
"Abschicken",
|
|
id="submit-button",
|
|
n_clicks=0,
|
|
disabled=False,
|
|
style={"margin-left": "20px"},
|
|
), # Submit button
|
|
html.Div(
|
|
[html.P("Bitte eine neue Anfrage eingeben.")], id="error", style=err_style
|
|
), # Error message (only visible if input is not updated but submit button is clicked)
|
|
dcc.Loading(
|
|
id="loading",
|
|
type="default",
|
|
children=[
|
|
html.Div(
|
|
"Hier erscheint die Antwort der Datenbank.",
|
|
id="text-output",
|
|
style={
|
|
"whiteSpace": "pre-line",
|
|
"margin-top": "30px",
|
|
"margin-left": "20px",
|
|
"margin-right": "20px",
|
|
"border": "2px solid #86bc25",
|
|
"border-radius": "15px",
|
|
"padding": "20px",
|
|
},
|
|
)
|
|
],
|
|
),
|
|
], # Output field
|
|
className="container",
|
|
)
|
|
|
|
|
|
@callback(
|
|
Output("text-output", "children"),
|
|
Output("tmp-value", "data"),
|
|
Output("error", "style"),
|
|
Input("submit-button", "n_clicks"),
|
|
State("input-field", "value"),
|
|
State("tmp-value", "data"),
|
|
prevent_initial_call=True,
|
|
running=[
|
|
(Output("submit-button", "disabled"), True, False),
|
|
(
|
|
Output("submit-button", "style"),
|
|
{"opacity": 0.5, "margin-left": "20px"},
|
|
{"opacity": 1.0, "margin-left": "20px"},
|
|
),
|
|
],
|
|
)
|
|
def update_output(n_clicks: int, value: str, data: str) -> Tuple[str, str, Dict[str, Any]]:
|
|
"""Update the output based on user input and button clicks.
|
|
|
|
Parameters
|
|
----------
|
|
n_clicks : int
|
|
Number of times the submit button has been clicked.
|
|
value : str
|
|
Current value of the input field.
|
|
data : str
|
|
Previously stored value.
|
|
|
|
Returns
|
|
-------
|
|
Tuple[str, str, Dict[str, Any]]
|
|
Updated output text, new stored value, and error style.
|
|
"""
|
|
global err_style
|
|
if n_clicks > 0 and value != data:
|
|
result = send_message(value)
|
|
err_style["height"] = "0px"
|
|
return result, value, err_style
|
|
elif value == data:
|
|
|
|
err_style["height"] = "50px"
|
|
return no_update, no_update, err_style
|
|
|
|
raise PreventUpdate
|
|
|
|
|
|
server = app.server
|
|
|
|
if __name__ == "__main__":
|
|
app.run(debug=True)
|