Panel Chat Interface

Hi. I’m having a tough time with this. I have a crewai application I’m building. One version runs great. However I have a second version where I would like to post a question to the screen, pause code execution and ask the user to indicate a preference. This preference would be assigned to a variable named user_preference and then code execution would continue via an if else statement based around the value of the user_preference variable. How can I halt program execution until the user responds?

The three strategies I know if is

  • Change the widgets of the ChatInterface or
  • Put widgets into the ChatMessages displayed in the chat interface and then temporarily disable the
    ChatInterface.widgets or
  • Compose your own custom Chat Interface from some of the lower level chat components of Panel like ChatAreaInput, ChatFeed or event ChatMessage.

I tried to find some receipies at Panel Chat Examples without success.

One place to look for inspiration is maybe in some of Yeyu Labs Autogen videos

image

Maybe @ahuang11 has some suggestions or receipies?

Change the widgets of the ChatInterface

The below is one strategy you might be able to extend upon.

import panel as pn
import param

pn.extension()

QUESTION_STATE = "Ask Question"
PREFERENCE_STATE = "Ask Preference"

class ChatHandler(param.Parameterized):
    state = param.Selector(default=QUESTION_STATE, objects=[QUESTION_STATE, PREFERENCE_STATE])

    def __init__(self, **params):
        super().__init__(**params)

        self.state = QUESTION_STATE

        self._preference_widget = self._preference_widget = pn.widgets.RadioBoxGroup(options=["blue", "red", "green"], value="blue", inline=True)
        

    def callback(self, contents, user, instance: pn.chat.ChatInterface):
        if self.state == QUESTION_STATE:
            self.state = PREFERENCE_STATE
            instance.widgets=[self._preference_widget]
            return "What is your preference?"
        elif self.state == PREFERENCE_STATE:
            self.state = QUESTION_STATE
            instance.widgets=[pn.chat.ChatAreaInput()]
            return f"Since your preference is {contents} then the answer is ..."

chat_handler = ChatHandler()

pn.chat.ChatInterface(callback=chat_handler.callback).servable()

How can I halt program execution until the user responds

This is how I would approach it:

import asyncio
import panel as pn

pn.extension()


async def _prompt_input():
    auto_input = pn.widgets.AutocompleteInput(
        options=["Vanilla", "Chocolate", "Strawberry"]
    )
    inputs = pn.Column("What's your favorite flavor?", auto_input)
    message = chat.send(inputs, user="Assistant", respond=False)
    for i in range(0, 120):
        if auto_input.value:
            message.object = f"Nice! I like {auto_input.value} too!"
        await asyncio.sleep(0.2)
    else:
        message.object = "Seems like you're not interested in ice cream..."


async def callback(message, *args):
    if "ice cream" in message.lower():
        await _prompt_input()
        return
    return f"I don't care about {message}"


chat = pn.chat.ChatInterface(callback=callback)
chat.show()

Another version inspired by Marc’s

import panel as pn
import param

pn.extension()


class PreferenceInput(pn.widgets.CompositeWidget):
    value = param.Parameter()

    def __init__(self, **params):
        super().__init__(**params)

        self._preference_widget = pn.widgets.RadioBoxGroup(
            options=["", "blue", "red", "green"], name="preference"
        )
        pn.bind(self._update_value, self._preference_widget, watch=True)
        self._composite[:] = [
            "What is your preference?",
            self._preference_widget,
        ]

    def _update_value(self, preference):
        self.value = f"My preference is {preference}."
        chat.stream(f"I like {preference} too")
        chat.widgets = [pn.chat.ChatAreaInput()]


def choose_a_color(contents, user, instance):
    if "color" in contents:
        instance.widgets = [preference_input]
        return "What is your preference?"
    return contents


preference_input = PreferenceInput()
chat = pn.chat.ChatInterface(callback=choose_a_color)
chat.show()