Customize chatinterface

Code:

def callback(contents: str, user: str, instance: pn.chat.ChatInterface):
    promptActualGUI=contents
    promptsGUI.append(promptActualGUI)
   # chat_history.append({'role':'user', 'content':f"{prompt}"})
    response = llama_chat_openaiGUI(promptsGUI, responsesGUI) 
    responsesGUI.append(response)
    return response


text_input = pn.widgets.TextInput(placeholder="Escribe tu pregunta aqui")

chat_interface = pn.chat.ChatInterface(
    callback=callback, widgets=[text_input]
)
chat_interface.send(
    "Hola, soy EduBot, tu asistente personal CON MEMORIA...puedes preguntar y dar a Enviar ",
    user="EduBot",
    respond=False,
)
chat_interface.servable()

So id like some doc or examples of code about customization:
1 - How to hide buttons like rerun, clear and delete. Which buttons hide or made visible.
2 - How to customize the icons or avatar of help assistant and user…which avatars are avalaible and if i can use a custom image.
3 - Change text format and background, paddings, border of responses…

Thanks

See ChatMessage — Panel v1.4.0rc3

Should answer most of your questions.

note you need to pip install panel>=1.4.0rc for item 3

Sorry but i didnt found for example how many avatars are avalaible, how can i put a concrete avatar, if i can use avatar with a custom image or icon…

Avatar only can be emojis ? or can i use a custom image/icon like a photo of my face or R2D2 ?

User is the tag of the assistant ?

user="Wise guy", avatar="🤓

Yes you can use custom images. User is the name of the messenger

How can i attach a custom image to avatar ?

Thanks for your help

Looks like we are both struggling with similar issues. Here is how far I got with ChatInterface:

message_params = dict(
    default_avatars = {"System": "☂️", "User": "👤"},   # this does not apply to creating a ChatMessage. Does ChatFeed have a creation function?
    reaction_icons  = {},
    show_user       = False,
    show_timestamp  = False,
    show_copy_icon  = False,
    sizing_mode     = "scale_width",
)
STYLE = """
.avatar {
    border-radius:50%;
    margin-top: 0;
    margin-left: 0;
    margin-right: 0;
}
.left {
    min-height: 10px;
    height: 18px;
}
.center {
    /* background-color: yellow; */
    margin-right:0px;
    width: calc(100% - 5px); 
}
.message {
    min-height: 15px;
}
.right {
  margin-left: 0;
  /* background-color: gray; */
}
"""
gui = pn.chat.ChatInterface( message_params=message_params,
                             show_rerun=False, show_undo=False,
                             stylesheets=[STYLE],
                             #css_classes=[STYLE],
                             widgets=pn.widgets.TextAreaInput(  placeholder=">", auto_grow=True, max_rows=10 ),
                             height=500,
                           )
gui

I can use the send button, or add a message directly, with somewhat different results:

msg = gui.send( pn.chat.ChatMessage(
                 avatar          = "☂️",
                 stylesheets     = [STYLE],
                 show_user       = False,
                 show_timestamp  = False,
                 show_copy_icon  = False,
                 sizing_mode     = "stretch_width",
))
txt=""
for n in "Updating the message works, streaming to it does not.... ":
    txt += n 
    msg.update(txt)

Comments

  • I instantiated the gui turning some of the buttons off, adding avatars and specifying a style for chat message components.
  • using the send button has the avatar out of place for some reason
  • using python to send a messages fixes that issue

Hope some of this helps you out…

Provide a URL or pn.pane.Image to avatar.

from panel/chat/message.py


    avatar = param.ClassSelector(default="", class_=(str, BytesIO, bytes, ImageBase), doc="""
        The avatar to use for the user. Can be a single character
        text, an emoji, or anything supported by `pn.pane.Image`. If
        not set, checks if the user is available in the
        default_avatars mapping; else uses the first character of the
        name.""")

Can you put an example of attaching a custom image to avatar . Also can be any image or has to have some size, like icon-size 48x48px or 64x64 or can be any size and then Panel resize it automatically ?

Also would like to change avatar of the assistant.

Thanks

you could just try it :grin:

gui.send( pn.chat.ChatMessage(
                 avatar          = pn.pane.PNG('https://panel.pyviz.org/_images/JPG.png'),
                 stylesheets     = [STYLE],
                 show_user       = False,
                 show_timestamp  = False,
                 show_copy_icon  = False,
                 sizing_mode     = "stretch_width",
))

Sorry but made lots of tests and changes and doesnt work at all…

import panel as pnci
from panel.chat import ChatMessage

pnci.extension()  #In notebook

panels =[]

promptsGUI=[]
responsesGUI=[]

message_params = dict(
    default_avatars = {"System": "☂️", "User": "👤"},   # this does not apply to creating a ChatMessage. Does ChatFeed have a creation function?
    reaction_icons  = {},
    show_user       = True,
    show_timestamp  = False,
    show_copy_icon  = False,
    sizing_mode     = "scale_width",
)
STYLE = """
.avatar {
    border-radius: 50% 20% / 10% 40%;;
    margin-top: 0;
    margin-left: 0;
    margin-right: 0;
}
.left {
    min-height: 10px;
    height: 18px;
}
.center {
    /* background-color: yellow; */
    margin-right:0px;
    width: calc(100% - 5px); 
}
.message {
    min-height: 15px;
}
.right {
  margin-left: 0;
  /* background-color: gray; */
}
"""

def system_response(contents: str, user: str, instance: pnci.chat.ChatInterface):
    promptActualGUI=contents
    promptsGUI.append(promptActualGUI)
   # chat_history.append({'role':'user', 'content':f"{prompt}"})
    #response = llama_chat_openaiGUI(promptsGUI, responsesGUI) 
    response ="hola" + promptActualGUI
    responsesGUI.append(response)
    response ="hola" + promptActualGUI
    return  response

gui.send("Hi, Ima an assistant of the system, my name is EduBot.. Ask me a question..", user="EduBot", avatar="🎶")

gui = pnci.chat.ChatInterface( message_params=message_params,
                             show_rerun=False, show_undo=False,
                             stylesheets=[STYLE],
                             #css_classes=[STYLE],
                             widgets=pnci.widgets.TextAreaInput(  placeholder="Escribe tu pregunta aqui", auto_grow=True, max_rows=5 ),
                             height=350,
                             callback=system_response,
                             user="Client",
                             avatar = pnci.pane.PNG('https://panel.pyviz.org/_images/JPG.png'),
                           )


gui

What i want to do:
1 - ( dont know if possible, but if not could be a feature request). A welcome message of assistant, WITHOUT any response…For example: Hi im EduBot and im here to help you…please write any question and id try to help you…
With this message no response of callback and the textinput for user to write his her question.

2 - Assistant: name Edubot, avatar custom image or select one avatar different to default one.

3 - Client name: instead of user, Client, and another custom avatar.

Actually it does nothing:

ps. First question is related to other post : Textinput sends a empty string or "[" string first time panel is built - #5 by ejgutierrez74 that the first Hi message from assistant is responded by callback function…

Panel 1.3.8

I am using pip install panel>=1.4.0rc2
This is what I see with the following code:

import panel as pn
pn.extension('texteditor', design="material")
# .....
gui = pn.chat.ChatInterface(
    message_params=message_params,
    stylesheets=[STYLE],
    show_rerun=False,
    show_undo=False,
    # css_classes=[STYLE],
    widgets=pn.widgets.TextAreaInput(placeholder=">", auto_grow=True, max_rows=10),
    height=250,
)
gui

msg = gui.send( pn.chat.ChatMessage( “Explícame cómo puedo usar la interfaz de ChatInterface”,
avatar = “:open_umbrella:”,
stylesheets = [STYLE],
show_user = False,
show_timestamp = False,
show_copy_icon = False,
sizing_mode = “stretch_width”,
))
gui.send(“Hi, Ima an assistant of the system, my name is EduBot… Ask me a question…”, user=“EduBot”, avatar=“:notes:”)

![Gui|690x162](upload://kpoTz0tuVuxOrQ1KVIsodLRtSWx.png)

But you code can you put it for example in pastebin ?

Seems there is not any callback function, so seems that you cant chat with LLM or Assistant isnt it ?

Im trying some kind to add the gui.send to the chatinterface…dont know even if possible…

1 - You send a gui.send or chat message send with presentation of Assistant: For example "hi im Edubot, im here to help you… Write any question below and ido my best to help you.
This with EduBot user name, and avatar for example umbrella.

2 - Then below this message should appear a textareainput with send button. Placeholder " Enter your question here", user should be Client, and avatar a robot for example. When you hit button send, a callback function should be called…so we begin the conversation with llm.

3 - When callback is called, a message with EduBot and umbrella avatar should write or send a message that would appear in the conversation history… and so on…

Thanks

The last code example I gave you is complete. Just run it.
You can also try each of the following:

# sending messages
msg = gui.send("Hi",   user="System")
msg = gui.send("Hola", user="User"  )
msg = gui.send("¿Cómo puedo ayudarte?", avatar="🎶")
msg = gui.send( pn.chat.ChatMessage( "Explícame cómo puedo usar la interfaz de ChatInterface",
                 avatar          = "☂️",
                 stylesheets     = [STYLE],
                 show_user       = False,
                 show_timestamp  = False,
                 show_copy_icon  = False,
                 show_reaction_icons=False,
                 sizing_mode     = "stretch_width",
))

# foo = add_message(gui)
msg = gui.send( "", user="System" )
for n in "Updating a message inserted with send....":
    msg.stream(n)

But i need this function:

def system_response(contents: str, user: str, instance: pnci.chat.ChatInterface):
    promptActualGUI=contents
    promptsGUI.append(promptActualGUI)
   # chat_history.append({'role':'user', 'content':f"{prompt}"})
    #response = llama_chat_openaiGUI(promptsGUI, responsesGUI) 
    response ="hola" + promptActualGUI
    responsesGUI.append(response)
    response ="hola" + promptActualGUI
    return  response

If everything works id uncomment the line

response = llama_chat_openaiGUI(promptsGUI, responsesGUI)

in which i call my LLM ( llama2 running in local) to get a response…and this response has to be added to chat conversation…

Really thanks for your help and sorry my bad english…

What keeps you from using the functions I have shown you to in order to implement the function you want? You can get the user input by setting a callback on ChatInterface()

One choice would be to make the callback invoke the llm.
Another would be to have the callback set a param with the content, and have a watcher that invokes the above function.

I made some progress:

import panel as pnci
from panel.chat import ChatMessage


pnci.extension()  #In notebook



promptsGUI=[]
responsesGUI=[]

message_params = dict(
    default_avatars = {"System": "☂️", "User": "👤", "Asker": "?", "EduBot" :pnci.pane.PNG('https://panel.pyviz.org/_images/JPG.png') },   # this does not apply to creating a ChatMessage. Does ChatFeed have a creation function?
    reaction_icons  = {},
    show_user       = True,
    show_timestamp  = False,
    show_copy_icon  = False,
    sizing_mode     = "scale_width",
)
STYLE = """
.avatar {
    border-radius: 50% 20% / 10% 40%;;
    margin-top: 0;
    margin-left: 0;
    margin-right: 0;
}
.left {
    min-height: 10px;
    height: 18px;
}
.center {
    /* background-color: yellow; */
    margin-right:0px;
    width: calc(100% - 5px); 
}
.message {
    min-height: 15px;
}
.right {
  margin-left: 0;
  /* background-color: gray; */
}
"""

welcome= "Hi im Edubot, im here to help you...write your question please"

def system_response(contents: str, user: str, instance: pnci.chat.ChatInterface):
    promptActualGUI=contents
    promptsGUI.append(promptActualGUI)
   # chat_history.append({'role':'user', 'content':f"{prompt}"})
    #response = llama_chat_openaiGUI(promptsGUI, responsesGUI) 
    response ="hola" + promptActualGUI
    responsesGUI.append(response)
    if contents == welcome:
        None
    else:
        response =f'The result is: {promptActualGUI}'
        return response

gui = pnci.chat.ChatInterface( message_params=message_params,
                             show_rerun=False, show_undo=False,show_stop=False,
                             stylesheets=[STYLE],
                             #css_classes=[STYLE],
                             widgets=pnci.widgets.TextAreaInput(  placeholder="Escribe tu pregunta aqui", auto_grow=True, max_rows=5 ),
                             height=400,
                             callback=system_response,
                            # avatar = pnci.pane.PNG('https://panel.pyviz.org/_images/JPG.png'),
                             user="Asker",
                             callback_user="EduBot"
                           )

# sending messages
initialmsg = gui.send( pnci.chat.ChatMessage( welcome,
                 avatar          = "🤖",
                 stylesheets     = [STYLE],
                 show_user       = True,
                 show_timestamp  = False,
                 show_copy_icon  = False,
                 show_reaction_icons=False,
                 sizing_mode     = "stretch_width",
                 user="EduBot",
))


initialmsg

gui


And this is the result:

1 - I made a trick to bypass the problem that the welcome or initial message got also a response of the system…with if the contents in callback function is the welcome message then does nothing, else returns the response…Hope someone could give me a better answer or solution…but for now works…

2 - Seem that message_params dont work very well, as the EduBot avatar is changed… if i delete the robot avatar in gui.send to generate initialmsg…then a E appears as avatar, instead the one defined in params ( perhaps a bug) ??

3 - In the callback function, seems callbac_user name EduBot, works fine, but the name and avatar of the user ( should be Asker and the avatar again is defined in params) doesnt work… It gets a user name that dont know where it cames from…

4 - tried to put all params in messsageparams avalaible i thought to all definitions and all chatinterface…but didnt work: show_user = True,
show_timestamp = False,
show_copy_icon = False,
show_reaction_icons=False,
has to be redefined again in gui.send…and i think you should avoid these params if they have already been declared/defined in the messageparams dict.

5 - Similar to 4 happens to show_rerun=False, show_undo=False,show_stop=False, in gui = pnci.chat.ChatInterface … i had to define again because if not it took another values than desired…

Wouldn be easier to have a messageparams defined at the begining/top of the code, and all the params stored there, and very ChatInterface or ChatMEssage take their values. If you want to change the predefined values then change it in the call.

Any help would be apreciated

This is what I did:

class Dialogue(param.Parameterized):
    user_input = param.String( "" )

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

    @param.depends( "user_input", watch=True)
    def process_user_input( self):
        self.gui.send( f"Processing: {self.user_input}", user="System")

def mk_replaceable_fn( func=lambda x: x ):
    actual_function = func

    def function(*y): return actual_function(*y)

    def set_actual_function(new_actual_function ):
        nonlocal actual_function
        actual_function = new_actual_function

    return function, set_actual_function

def do_nothing(contents, user, instance):
    return

callback_function, set_callback_function = mk_replaceable_fn( do_nothing )
gui = pn.chat.ChatInterface(
    callback       = callback_function,
    callback_user  = "User",
    message_params = message_params,
    stylesheets    = [STYLE],
    show_rerun     = False,
    show_undo      = False,
    widgets        = pn.widgets.TextAreaInput(placeholder=">", auto_grow=True, max_rows=10),
    height         = 300,
)
gui

then

dialogue = Dialogue(gui)

def blue_echo(contents, user, instance):
    if user == "User":
        dialogue.user_input = f"""{user} <strong style="color:blue;">{contents}</strong>"""
    return

def count_chars( contents, user, instance ):
    if user == "User":
        dialogue.user_input = f"""[{user}] Found {len(contents)} characters in <strong style="color:red;">{contents}</strong>"""
    return

set_callback_function( blue_echo )

add any number of user inputs…
then

set_callback_function( count_chars )

add any number of user inputs…

@ea42gh are you a dev ?
@ahuang11

Did you read points 2,3 and 5 ? Seems something not working well with message params and ChatInterface…ChatInterface dont care about some message-params values…

Also would be nice to implement an “optional” initial or presentation message in ChatInterface without answer of the callback function…like: “Hi im Edubot, im here to try to help you… Write your question below”

Thanks

Longtime user of the pyviz tools…
You declare two users in chat_message, named “X” and “Y” together with their avatars.
when you send a message gui.send( whatever, user = "X"),
the message will appear with the corresponding avatar for “X”.
Use gui.send( whatever, user = 'Z') the message will get a default avatar.
You could instead use gui.send(whatever, avatar='x' to get a message with
the avatar x

Re initial message, gui=ChtaInterface(...); gui
then gui.send(. greeting, user='X') will insert the iinitial greeting you are asking for.

It does work consistently for me!