chainlit icon indicating copy to clipboard operation
chainlit copied to clipboard

cl.Step.remove() not persisting in data layer?

Open dominpm opened this issue 7 months ago • 2 comments
trafficstars

When using cl.Step.remove() to remove a step from the current chat session, the step is successfully removed from the in-memory state and no longer appears in the UI. However, when the same chat is resumed via on_chat_resume, the removed step reappears.

It appears that cl.Step.remove() only affects the session's runtime state and does not delete the step from the data layer (if persistence is enabled).


Expected Behavior

Calling cl.Step.remove() should either:

  1. Automatically persist the deletion in the configured data layer (e.g., call delete_step(step_id) internally), or
  2. Be clearly documented as an in-memory-only operation, with guidance on how to persist deletions manually.

Steps to Reproduce

  1. Create and send a cl.Step.
  2. Call .remove() on that step.
  3. Resume the chat using on_chat_resume.
  4. The previously removed step is still present.

Environment

  • Chainlit version: 2.4.400
  • Data layer: LiteralAI
  • Persistence: Enabled

Suggested Solution

  • Add support for persistent deletion via the data layer (e.g., use delete_step(step_id) if implemented).
  • Alternatively, introduce a method like step.delete(persist=True) or a built-in mechanism to opt into data layer sync.
  • Update documentation to clarify the current behavior of .remove().

dominpm avatar Apr 15 '25 08:04 dominpm

The current behavior of cl.Step.remove() is to remove a step from the in-memory state and the UI, but it does not persist the deletion in the data layer. This is why the step reappears when the chat is resumed using on_chat_resume [1].

To achieve persistent deletion, you would need to manually delete the step from the data layer. The Chainlit backend does have functionality for persistent deletion, as seen in the remove method in backend/chainlit/message.py, which uses data_layer.delete_step(step_dict["id"]) to delete a step from the data layer [2].

For a solution, you could implement a custom method to handle persistent deletions by calling the appropriate data layer deletion function. Alternatively, you could suggest a feature enhancement to Chainlit to include a built-in mechanism for persistent deletions, as you mentioned in your suggested solution.

To continue talking to Dosu, mention @dosu.


Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other

dosubot[bot] avatar Apr 15 '25 08:04 dosubot[bot]

I am using Context Manager:

async with cl.Step(name="X") as step: ...

The __aexit__ should have this implemented (also the __enter__):

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        self.end = utc_now()

        if exc_type:
            self.output = str(exc_val)
            self.is_error = True

        current_steps = local_steps.get()
        if current_steps and self in current_steps:
            current_steps.remove(self)
            local_steps.set(current_steps)

        await self.update()

Which seems to have it, but it either is not working properly or there is a better way to deal with this.

Thanks in advance!

dominpm avatar Apr 15 '25 09:04 dominpm

This issue is stale because it has been open for 14 days with no activity.

github-actions[bot] avatar Jul 27 '25 02:07 github-actions[bot]

This issue was closed because it has been inactive for 7 days since being marked as stale.

github-actions[bot] avatar Aug 04 '25 02:08 github-actions[bot]