posit-dev / posit-dev/shinychat

Streaming chat messages can result in large data transfer

Open
#281 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

ai-triage:done Priority: Medium
Dominant language
TypeScript
Stars
139
Forks
28
Avg merge
23h 44m
Merged PRs (30d)
50

Description

The transferring of chat messages can result in large amounts of data transferred when the message is streaming. For example, I found that when streaming in a response that was 5800 bytes, it transferred 3.5MB from the Python process to the browser.

(Note that this was counting only the length of the content, and did not include the additional length of the JSON custom message wrapper that is sent to the browser. The wrapper is 187 bytes for each message, and with 1200 individual messages, this results in another 0.2MB.)

This app illustrates. For each chunk, it prints out a line with:

  • total number of chunks
  • size of content
  • cumulative size of all content blocks that have been sent
import ollama

from shiny.express import ui

chat = ui.Chat(id="chat")
chat.ui()

total_count = 0
total_length = 0

@chat.on_user_submit
async def _():
    total_count = 0
    total_length = 0

    messages = chat.messages(format="ollama")
    # Assumes you've run `ollama run llama3.1` to start the server
    response = ollama.chat(
        model="llama3.1",
        messages=messages,
        stream=True,
    )
    await chat.append_message_stream(response)

@chat.transform_assistant_response()
async def transform_response(content: str, chunk: str, done: bool) -> str:
    global total_count, total_length
    total_count += 1
    total_length += len(content)
    print(f"{total_count} : {len(content)} : {total_length}")
    return content

To reduce the amount of data sent, we could do the following:

  • Use a text diffing algorithm so that we don't send the entire content over and over as it grows.
  • Throttle the responses. I think a ~0.05-0.1s delay still results in a responsive-feeling app. If the throttling results in 2 words sent at a time instead of 1, that would reduce traffic by half.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing chat.append_message_stream and the transform_assistant_response hook, using the supplied reproduction to measure cumulative content and wrapper transfer. Compare the proposed diffing and throttling approaches, then verify that streaming remains responsive while substantially reducing repeated data sent from the Python process to the browser.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, typescript
Domain
full-stack, performance
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.