edited messages disappearing in ChatInterface UI#12997
edited messages disappearing in ChatInterface UI#12997freddyaboulton merged 5 commits intogradio-app:mainfrom
Conversation
🪼 branch checks and previews
Install Gradio from this PR pip install https://gradio-pypi-previews.s3.amazonaws.com/f6e1c4dd110ec5eaaf0c8b8634b9b5ac0ccae3dd/gradio-6.9.0-py3-none-any.whlInstall Gradio Python Client from this PR pip install "gradio-client @ git+https://github.com/gradio-app/gradio@f6e1c4dd110ec5eaaf0c8b8634b9b5ac0ccae3dd#subdirectory=client/python"Install Gradio JS Client from this PR npm install https://gradio-npm-previews.s3.amazonaws.com/f6e1c4dd110ec5eaaf0c8b8634b9b5ac0ccae3dd/gradio-client-2.1.0.tgz |
🦄 change detectedThis Pull Request includes changes to the following packages.
✅ Changeset approved by @freddyaboulton
|
gradio/chat_interface.py
Outdated
| [self.chatbot], | ||
| api_visibility="undocumented", | ||
| queue=False, | ||
| ).then( |
There was a problem hiding this comment.
Thanks @jeremy-dolan ! Setting the textbox to be non-interactive is a problem though because this event chain does not re-set it to be interactive. I actually think we don't have to set the textbox to be non-interactive in this code block.
Other than that, this lgtm though
There was a problem hiding this comment.
Yes, absolutely right, interactive is never reset to True. That's bad!
I removed the chain that sets interactive=False. Two things to note:
-
this makes it different to the normal message submission behavior, which disables the textbox until the response is completed. (I'm not sure why that behavior was chosen for the message submission and don't love it, but I also don't love inconsistency.)
-
In ~25 tests with this update(interactive) event removed, I had one un-reproducable crash when editing a message and resubmitting. "ValueError: An event handler (_submit_fn) didn't receive enough input values (needed: 2, got: 0)." I could not find a cause for this and can't tell if it's related, but maybe the full trace makes more sense to a dev here.
Traceback (most recent call last):
File "[project path]/.venv/lib/python3.13/site-packages/gradio/queueing.py", line 766, in process_events
response = await route_utils.call_process_api(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<5 lines>...
)
^
File "[project path]/.venv/lib/python3.13/site-packages/gradio/route_utils.py", line 355, in call_process_api
output = await app.get_blocks().process_api(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<11 lines>...
)
^
File "[project path]/.venv/lib/python3.13/site-packages/gradio/blocks.py", line 2154, in process_api
inputs = await self.preprocess_data(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
block_fn, inputs, state, explicit_call
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "[project path]/.venv/lib/python3.13/site-packages/gradio/blocks.py", line 1753, in preprocess_data
self.validate_inputs(block_fn, inputs)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "[project path]/.venv/lib/python3.13/site-packages/gradio/blocks.py", line 1735, in validate_inputs
raise ValueError(
...<6 lines>...
)
ValueError: An event handler (_submit_fn) didn't receive enough input values (needed: 2, got: 0).
Check if the event handler calls a Javascript function, and make sure its return value is correct.
Wanted inputs:
[<gradio.components.state.State object at 0x114058a50>, <gradio.components.state.State object at 0x114058e10>]
Received inputs:
[]
There was a problem hiding this comment.
I am not sure. Let me know if you still see the issue with the updated diff I sent in a different comment
There was a problem hiding this comment.
What test did you run?
There was a problem hiding this comment.
I was just interactively testing, editing messages in various ways, while running gradio app.py. That one-off error occurred as I clicked the 'checkmark' to submit an edited message which was part of a larger conversation chain. But I cannot reproduce it, even with the exact same series of inputs. Still testing with your disable textbox/re-enable textbox patch.
651c18d to
5681c8f
Compare
this time without interactive=False
5681c8f to
ae74a9f
Compare
| [self.chatbot], | ||
| [self.chatbot, self.chatbot_state, self.saved_input], | ||
| api_visibility="undocumented", | ||
| ).then( |
There was a problem hiding this comment.
Ok yea best to keep everything consistent and make the textbox non-interactive during edits. The following chain should work
if self.editable:
self.chatbot.edit(
self._edit_message,
[self.chatbot],
[self.chatbot, self.chatbot_state, self.saved_input],
api_visibility="undocumented",
).then(
self._append_message_to_history,
[self.saved_input, self.chatbot_state],
[self.chatbot],
api_visibility="undocumented",
queue=False,
).success(
lambda: update(interactive=False),
outputs=[self.textbox],
api_visibility="undocumented",
).success(**submit_fn_kwargs).success(**synchronize_chat_state_kwargs).then(
lambda: update(interactive=True),
outputs=[self.textbox],
api_visibility="undocumented",
).then(**save_fn_kwargs)There was a problem hiding this comment.
My PR is updated with that chain, and it has been working well for me.
Just to flag it as a UI nicety, I'd love it if the textbox stayed interactive and focused (with only the submit function disabled) during model processing for normal input, but that's outside the scope of this issue, and beyond my current availability/familiarity. Can't see why, during normal textbox.submit(), _clear_and_save_textbox() is called and it sets the textbox to interactive=False until processing is done.

Description
With editable=True on ChatInterface, editing a user message causes it to disappear from the chatbot UI while waiting for the callback to yield or return a response. The edited message does correctly reappear once the callback returns/yields.
apparent cause
The edit event handler in chat_interface.py doesn't use _append_message_to_history as normal message input and and retry events do.
Closes: #12996
AI Disclosure
We encourage the use of AI tooling in creating PRs, but the any non-trivial use of AI needs be disclosed. E.g. if you used Claude to write a first draft, you should mention that. Trivial tab-completion doesn't need to be disclosed. You should self-review all PRs, especially if they were generated with AI.