I cant work out why my callback is not working properly

Hi All,

I am sure this is going to be a stupid error, but having watched several videos (Yes Adam, yours) on callbacks and reading the callback docs, I can’t fathom where I am going wrong.

I have a very simple dash app. I have marked it up with the respective ID’s

The Basic App

This is the callback that is not working

# Callback to clear the question-input, answer-output and reset the model-dropdown value when reset-button is clicked
@app.callback(
    [
        Output("question-input", "value"),
        Output('answer-output', 'value'),
        Output("model-dropdown", "value"),
    ],
    Input("reset-button", "n_clicks"),
)
def reset_values(
    n: int,
):  # the function argument comes from the component property of the Input
    if n > 0:
        # Reset text input fields to empty strings and the dropdown to its default value
        return (
            "",
            "",
            "codellama-34b-instruct",
        )  # the returned object is assigned to the component property of the Output

    # If reset button has not been clicked, don't update component values
    return no_update, no_update, no_update

If I comment out output-answer and click reset, the app will clear any text in the question-input textarea and reset the model-dropdown back to its default value of codellama-34b-instruct.

This is the callback that is working

# Callback to clear the question-input, answer-output and reset the model-dropdown value when reset-button is clicked
@app.callback(
    [
        Output("question-input", "value"),
        # Output('answer-output', 'value'),
        Output("model-dropdown", "value"),
    ],
    Input("reset-button", "n_clicks"),
)
def reset_values(
    n: int,
):  # the function argument comes from the component property of the Input
    if n > 0:
        # Reset text input fields to empty strings and the dropdown to its default value
        return (
            "",
            "codellama-34b-instruct",
        )  # the returned object is assigned to the component property of the Output

    # If reset button has not been clicked, don't update component values
    return no_update, no_update

Submit button clicked

This shows the submit button working.

If I click the reset button the app resets to a clear text area for question-input, and resets the model-dropdown to the default tone.

I have looked at this too long now and can’t see the wood for the trees. Any ideas?

Full code below

import dash
from dash import dcc, html, no_update
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
import os
import requests
import json
from dotenv import load_dotenv
from typing import Union

# load our environment variabled
load_dotenv()


# API key Load funktion
def load_api_key() -> str:
    """
    Load the API key from the .env file.

    Returns:
        str: The API key.
    """
    return os.getenv("API_KEY")


# load our API key
api_key = load_api_key()


app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container(
    [
        dbc.Row(
            [
                html.H4("Select Your Model", style={"color": "white"}),
                dcc.Dropdown(
                    id="model-dropdown",
                    options=[
                        {
                            "label": "codellama-34b-instruct",
                            "value": "codellama-34b-instruct",
                        },
                        {"label": "llama-2-70b-chat", "value": "llama-2-70b-chat"},
                        {
                            "label": "mistral-7b-instruct",
                            "value": "mistral-7b-instruct",
                        },
                        {"label": "pplx-7b-chat", "value": "pplx-7b-chat"},
                        {"label": "pplx-70b-chat", "value": "pplx-70b-chat"},
                        {"label": "pplx-7b-online", "value": "pplx-7b-online"},
                        {"label": "llava-7b-chat", "value": "llava-7b-chat"},
                        {
                            "label": "mixtral-8x7b-instruct",
                            "value": "mixtral-8x7b-instruct",
                        },
                        {"label": "mistral-medium", "value": "mistral-medium"},
                        {"label": "related", "value": "related"},
                    ],
                    value="codellama-34b-instruct",
                ),
            ],
            style={
                "align-items": "left",
            },
        ),
        dbc.Row(
            [
                html.H4(
                    "Ask your question", style={"color": "white", "margin-top": "5px"}
                ),
                dbc.Textarea(
                    id="question-input",
                    placeholder="Enter a question...",
                    style={"borderRadius": "5px", "height": "30vh", "color": "black"},
                ),
            ],
            style={"align-items": "left", "marginBottom": "1vh"},
        ),
        dbc.Row(
            [
                html.H4("Your Question Answered", style={"color": "white"}),
                dbc.Textarea(
                    id="answer-output",
                    placeholder="Answer will be displayed here...",
                    style={"borderRadius": "5px", "height": "30vh", "color": "black"},
                    className="mb-10",
                ),
            ],
            style={"align-items": "left", "marginBottom": "1vh"},
        ),
        dbc.Row(
            [
                dbc.Button(
                    "Submit",
                    id="submit-button",
                    n_clicks=0,
                    style={
                        "borderRadius": "5px",
                        "maxWidth": "150px",
                        "margin-top": "10px",
                    },
                ),
                dbc.Button(
                    "Reset",
                    id="reset-button",
                    n_clicks=0,
                    style={
                        "borderRadius": "5px",
                        "maxWidth": "150px",
                        "margin-top": "10px",
                        "margin-left": "20px",
                    },
                ),
            ],
            justify="left",
        ),
    ],
    style={"padding": "30px", "backgroundColor": "#006635", "height": "100vh"},
    fluid=True,
)


# Modify your submit callback
@app.callback(
    Output("answer-output", "value"),
    Input("submit-button", "n_clicks"),
    [
        State("model-dropdown", "value"),
        State("question-input", "value"),
    ],
)
def update_output(n_clicks, model_value, question_value):
    if n_clicks > 0 and question_value is not None and model_value is not None:
        return f"Model {model_value} got the following question: {question_value}"
    else:
        return ""


# Callback to clear the question-input, answer-output and reset the model-dropdown value when reset-button is clicked
@app.callback(
    [
        Output("question-input", "value"),
        Output('answer-output', 'value'),
        Output("model-dropdown", "value"),
    ],
    Input("reset-button", "n_clicks"),
)
def reset_values(
    n: int,
):  # the function argument comes from the component property of the Input
    if n > 0:
        # Reset text input fields to empty strings and the dropdown to its default value
        return (
            "",
            "",
            "codellama-34b-instruct",
        )  # the returned object is assigned to the component property of the Output

    # If reset button has not been clicked, don't update component values
    return no_update, no_update, no_update


if __name__ == "__main__":
    app.run_server(port=8000)

Hi @twelsh37

If you change this to include debug=True, you will see this handy error message:

if __name__ == "__main__":
    app.run_server(port=8000, debug=True)

1 Like

Thanks. I thought allow_duplicates was dangerous?

It’s not “dangerous” - it’s just that on page load, the order of the of the callbacks targeting the same output is not guaranteed. If that’s important in your application, you can combine the callbacks and use ctx to determine which input triggered the callback.

1 Like

ah, the good old context. I haven’t played with that yet. I don’t think I need it in this one. It’s a case of clicking the submit button, and the callback will run, pull the model and question and send it to the API endpoint along with my bearer token. so it’s quite a simple function.

This is mostly testing for my biggie. No callbacks on this, yet.

1 Like