chainlit icon indicating copy to clipboard operation
chainlit copied to clipboard

Message Elements Display Order is not Controllable

Open sunbc0120 opened this issue 1 year ago • 2 comments

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?

sunbc0120 avatar Dec 18 '23 06:12 sunbc0120

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?

willydouhard avatar Dec 18 '23 12:12 willydouhard

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.

FellowTraveler avatar Mar 31 '24 02:03 FellowTraveler

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()

hosmanadam avatar Aug 14 '24 11:08 hosmanadam

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

dokterbob avatar Aug 14 '24 11:08 dokterbob