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 theChatInterface
or - Put widgets into the
ChatMessage
s 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 eventChatMessage
.
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
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()