Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic collaborative chat #58

Merged
merged 6 commits into from
Apr 13, 2023
Merged

Basic collaborative chat #58

merged 6 commits into from
Apr 13, 2023

Conversation

dlqqq
Copy link
Collaborator

@dlqqq dlqqq commented Apr 12, 2023

Description

Enables collaborative chat by migrating to the new Chat WebSockets API implemented in #40.

Correctly handles selection inclusion + replacement. 馃榿

Demo (collaborative: false)

Screen.Recording.2023-04-12.at.4.06.00.PM.mov

Demo (collaborative: true)

Screen.Recording.2023-04-12.at.4.18.50.PM.mov

Backend changes

  • Each client is now identified with a unique UUID
  • Each message is also now identified with a unique UUID
  • Server message types are now declared via pydantic. There are currently 3:
    • ConnectionMessage: sent after a WebSocket connection is opened, providing the client with their client ID
    • HumanChatMessage: broadcast by server after receiving a ChatRequest. this is now broadcast to all clients, so that the sending client can also verify that the server received the message.
    • AgentChatMessage: broadcast by server after agent responds to a HumanChatMessage. The reply_to field stores the message ID of the HumanChatMessage it is replying to

Frontend changes

  • The ChatHandler class has a new interface:
    • async initialize(): must be awaited prior to usage
    • async send(): send a message and return a Promise. The Promise resolves when server acknowledges receipt by broadcasting the message back.
    • async replyFor(messageId: string): return a Promise that resolves when an agent replies to a message with ID messageId

In summary, this adds an awaitable fetch-like API for sending chats and waiting for agent replies. This is extremely powerful, and allowed me to implement this while making minimal changes to the Chat components 馃榿

Next steps

  • Handle client disconnects
  • User avatars

@dlqqq dlqqq added the enhancement New feature or request label Apr 12, 2023
@dlqqq dlqqq requested a review from 3coins April 12, 2023 23:35
@dlqqq dlqqq self-assigned this Apr 12, 2023
Copy link
Collaborator

@3coins 3coins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dlqqq
Thanks for making these changes. The request/reply design looks great, left some comments about some redundant code.
One consideration to keep in mind is that the initial version relied on hydrating the chat history from the conversation memory. With the new changes, this is no longer the case, so for instance, if we decide to use persistent memory it will not align with the chat history in the UI as these two are handled separately now. Let me know if I missed anything, and that's not the case.

packages/jupyter-ai/jupyter_ai/handlers.py Show resolved Hide resolved
packages/jupyter-ai/jupyter_ai/handlers.py Show resolved Hide resolved
packages/jupyter-ai/jupyter_ai/handlers.py Outdated Show resolved Hide resolved
@dlqqq
Copy link
Collaborator Author

dlqqq commented Apr 13, 2023

@3coins

The request/reply design looks great, left some comments about some redundant code.
One consideration to keep in mind is that the initial version relied on hydrating the chat history from the conversation memory. With the new changes, this is no longer the case, so for instance, if we decide to use persistent memory it will not align with the chat history in the UI as these two are handled separately now.

Yes, this is technically an instance of duplicate state. However, I would think of settings["chat_messages"] to be more like a "cache" of the agent's memory; it would be expensive to serialize the agent's memory to a list of ChatMessage objects if we did that dynamically every request. This cache is fairly straightforward to keep consistent in the serial execution model (i.e. prompts get executed in-order one-by-one). All you need to do is make sure that list gets appended to every time the agent executes.

When you parallelize model execution, you may run into issues with this strategy regarding process safety; feel free to change it as much as you'd like.

@3coins
Copy link
Collaborator

3coins commented Apr 13, 2023

@dlqqq
The changes look good, let's continue to the history discussion offline and merge these changes.

@dlqqq dlqqq merged commit 136e154 into jupyterlab:main Apr 13, 2023
@dlqqq dlqqq deleted the use-ws branch April 13, 2023 16:50
dbelgrod pushed a commit to dbelgrod/jupyter-ai that referenced this pull request Jun 10, 2024
* add .jupyter_ystore.db to .gitignore

* connect chat UI to use websockets handlers

* remove old Chat REST API

* remove console logs

* do not use identity provider username for client ID

* remove old messages property
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants