Chainlit / chainlit

Build Conversational AI in minutes ⚡️
https://docs.chainlit.io
Apache License 2.0
6.91k stars 910 forks source link

Message Elements Display Order is not Controllable #602

Open sunbc0120 opened 9 months ago

sunbc0120 commented 9 months ago

In previous few versions, the order of elements to display on message UI is guaranteed, therefore user could select item using number, because the order they see on the UI is consistent with the order of the underlying elements.

https://github.com/Chainlit/chainlit/blob/00d1ddb18d969991e5b43873fcc49a016a8aee6a/backend/chainlit/message.py#L226C9-L226C9

        for element in self.elements:
            await element.send(for_id=str(id))

Now, all the elements are send async therefore the order is no longer guaranteed.

https://github.com/Chainlit/chainlit/blob/b373e73db4a7069dbb7f9ad0ee581099e9cbde6f/backend/chainlit/message.py#L253

What would be the solution if need to control the elements order on Message? Possible to make the 2 options both above available as a parameter for Message?

willydouhard commented 9 months ago

Good point. We started to send elements concurrently to decrease latency but it indeed makes it unpredictable. Another parameter just for that seems unideal. Maybe sorting by name in the UI?

FellowTraveler commented 6 months ago

Suggestion: Allow optional sequence number on elements so that they show up in the designated order. Otherwise defaults to 0 and order is not guaranteed.

hosmanadam commented 1 month ago

This is still an issue and a quite annoying one. Sometimes elements need to be sent in order.

This will be out of order:

    await cl.Message(
        content='blabla'
        elements = [
            cl.Text(name='name1', content='content1', display="inline"),
            cl.Text(name='name2', content='content2', display="inline"),
    ]).send()

This is an ugly workaround I use now:

    elements = [
        cl.Text(name='name1', content='content1', display="inline"),
        cl.Text(name='name2', content='content2', display="inline"),
    ]
    message = cl.Message(content='blabla')
    await message.send()
    for element in elements:
        message.elements += [element]
        await message.send()

Possible solution with element.order:

    await cl.Message(
        content='blabla'
        elements = [
            cl.Text(name='name1', content='content1', display="inline", order=0),
            cl.Text(name='name2', content='content2', display="inline", order=1),
    ]).send()

Or keep_element_order which could disable async sending:

    await cl.Message(
        content='blabla'
        elements = [
            cl.Text(name='name1', content='content1', display="inline"),
            cl.Text(name='name2', content='content2', display="inline"),
        keep_element_order=True, # default False
    ]).send()
dokterbob commented 1 month ago

Thanks for the feedback @hosmanadam!

Would anyone be able to make a concrete suggestion towards fixing this?

Basically, a spec which we can decide on beforehand and evaluate a PR on afterwards.

@FellowTraveler @sunbc0120