deep-chat icon indicating copy to clipboard operation
deep-chat copied to clipboard

Web Component keeps flashing repeatedly

Open venlon789 opened this issue 7 months ago • 6 comments

I want to display a chart, but when the content is being output, the chart loads first while the rest of the content hasn't finished outputting yet. During this time, the chart keeps flickering. It only stops flickering after all content has been fully output. How should I solve this problem? Here is my example code:

Image

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Deep Chat Development</title>
    <script type="module" src="src/deepChat.ts"></script>
    <script
      type="module"
      src="https://unpkg.com/@google-web-components/[email protected]/google-chart.js?module"
    ></script>
    <style>
      html,
      body {
        height: 100%;
        margin: 0px;
      }
    </style>
  </head>
  <body>
    <deep-chat
      id="chat-element"
      connect='{"stream": true}'
      remarkable='{"html": true, "typographer": true}'
      demo="true"
      style="width: 100vw; height: 100vh"
    ></deep-chat>
    <script type="module">
      const data = [
        ['Planet', 'Score'],
        ['Mercury', 98],
        ['Venus', 75],
        ['Earth', 88],
        ['Mars', 82],
        ['Jupiter', 95],
        ['Saturn', 90],
        ['Uranus', 68],
        ['Neptune', 72],
        ['Ceres', 60],
        ['Pluto', 58],
        ['Haumea', 55],
        ['Makemake', 53],
        ['Eris', 50],
        ['Sedna', 48],
        ['Quaoar', 45],
      ];

      const numDataPoints = data.length - 1;
      const barWidth = 50;
      const chartWidth = numDataPoints * barWidth;

      const html = `\n <div style="width: 100%; max-width: 80vw; min-width: 300px; height: 400px; margin: 10px auto; position: relative; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;"><div style="margin: 10px 0; color: #666">Sample Chart (responsive & scrollable):</div><div style="height: calc(100% - 40px); padding-bottom: 20px;"><google-chart style="width: ${chartWidth}px !important; height: 100% !important; min-height: 300px;" data='${JSON.stringify(
        data
      )}' options='{"title": "Planet Score Comparison","titleTextStyle": {"color": "#333","fontSize": 16,"bold": true,"alignment": "center"},"chartArea": {"width": "75%","height": "60%","top": 40,"left": 40},"legend": {"position": "bottom","maxLines": 2},"backgroundColor": "transparent"}'></google-chart></div></div> \n`

      const repeatedText = ` \n ## Global Survey Analysis Report \n ### Section One: Overview \n After processing all data, a total of 109,568 valid entries were found       \n`;
      const demoContent = repeatedText + html + repeatedText.repeat(4);

      const chatElementRef = document.getElementById('chat-element');
      chatElementRef.history = [
        { role: 'user', text: 'Hey, how are you today?' },
        { role: 'ai', text: 'I am doing very well!' },
      ];
      chatElementRef.demo = {
        response: {
          text: demoContent,
        },
      };
      chatElementRef.setAttribute(
        'introMessage',
        JSON.stringify({
          text: 'You are now running deep chat locally.',
        })
      );
    </script>
  </body>
</html>

venlon789 avatar Apr 10 '25 14:04 venlon789

Hey @venlon789. I can see you are streaming your response text. The way Deep Chat works is that every time more text is added to the response, the whole message bubble is re-rendered. The reason for this is because we run it through the remarkablehttps://github.com/jonschlinkert/remarkable library to render MarkDown into text here.

So you have two alternatives:

  • Don't stream your text and return the whole response in one go
  • Return your responses using html, not text

Let me know if this helps! Thanks!

OvidijusParsiunas avatar Apr 10 '25 14:04 OvidijusParsiunas

Hey @venlon789. I can see you are streaming your response text. The way Deep Chat works is that every time more text is added to the response, the whole message bubble is re-rendered. The reason for this is because we run it through the remarkablehttps://github.com/jonschlinkert/remarkable library to render MarkDown into text here.

So you have two alternatives:

  • Don't stream your text and return the whole response in one go
  • Return your responses using html, not text

Let me know if this helps! Thanks!

@venlon789 我看到你正在_流式传输_你的回复文本。Deep Chat 的工作方式是,每次在回复中添加更多文本时,整个消息气泡都会重新渲染。这样做的原因是,我们通过卓越的https://github.com/jonschlinkert/remarkable库来运行它,以便将 MarkDown 渲染为文本

所以你有两种选择:

  • 不要流式传输您的文本并一次性返回整个响应
  • 使用而不是返回您的回复html``text

如果有帮助的话请告诉我!谢谢!

Thank you for responding so quickly!

When my output includes Markdown formatting, the Markdown rendering doesn't work

If I want to use HTML for rendering while also ensuring Markdown is properly rendered, how can I achieve this?

venlon789 avatar Apr 10 '25 15:04 venlon789

Unfortunately the only other currently available solution is to return all of the text at once.

OvidijusParsiunas avatar Apr 11 '25 11:04 OvidijusParsiunas

Unfortunately the only other currently available solution is to return all of the text at once.

Thank you for your response! Just wanted to check – as you continue developing this component, when you work on the HTML implementation down the road, would it be possible to also have it render as Markdown by any chance?

venlon789 avatar Apr 11 '25 13:04 venlon789

The problem that you are facing comes from the fact that to render MarkDown in streams all of the bubble content is re-rendered due to individual stream events being able to return partial MarkDown syntax.

I am a little busy this weekend, but I will try to find some time next weekend to attempt to tackle this issue. But please note that text semantics are inherently a difficult problem, so providing a generic solution which fits all use-cases may be impossible, hence I cannot promise that I will be able to resolve this. I will update this issue once I had an attempt at it.

OvidijusParsiunas avatar Apr 11 '25 14:04 OvidijusParsiunas

您所面临的问题在于,为了在_流_中呈现 MarkDown ,由于各个流事件能够返回部分 MarkDown 语法,因此所有气泡内容都会重新呈现。

这个周末我有点忙,不过我会尽量在下个周末抽出时间尝试解决这个问题。不过请注意,文本语义本身就是一个难题,因此提供一个通用的解决方案可能不太现实,所以我无法保证一定能解决这个问题。一旦我尝试过,我会更新此问题。

Thank you so much! You really put your heart into this.

venlon789 avatar Apr 11 '25 14:04 venlon789

Hi @venlon789.

I have added a new feature to the streaming service that re-renders the latest paragraph of the streamed message, so the previous ones will not be re-rendered as the message is being populated.

New paragraphs are indicated by "\n\n" syntax, so if a sent back event contains this - it will immediately create a new paragraph and rendering of previous one will stop.

This is enabled by setting a new option called partialRender to true which will be available in the Stream object.

E.g. connect='{"stream": {"partialRender": true}}'

To note, if you using the demo mode or simulating a stream via simulation you may still see the graph temporarily flash, this is because the code iterates over every character of the response, so it takes 4 iterations to read "\n\n". Hence, if you are sending back real streamed events from a server, it is best to include the full "\n\n"syntax at its end so it can be read immediately.

This feature is currently available in deep-chat-dev and deep-chat-react-dev version 9.0.265. These packages work exactly the same as the core ones except their names are different.

I will keep this issue open until it is merged into the core package.

OvidijusParsiunas avatar May 15 '25 14:05 OvidijusParsiunas

Hi @venlon789.

I have added a new feature to the streaming service that re-renders the latest paragraph of the streamed message, so the previous ones will not be re-rendered as the message is being populated.

New paragraphs are indicated by "\n\n" syntax, so if a sent back event contains this - it will immediately create a new paragraph and rendering of previous one will stop.

This is enabled by setting a new option called partialRender to true which will be available in the Stream object.

E.g. connect='{"stream": {"partialRender": true}}'

To note, if you using the demo mode or simulating a stream via simulation you may still see the graph temporarily flash, this is because the code iterates over every character of the response, so it takes 4 iterations to read "\n\n". Hence, if you are sending back real streamed events from a server, it is best to include the full "\n\n"syntax at its end so it can be read immediately.

This feature is currently available in deep-chat-dev and deep-chat-react-dev version 9.0.265. These packages work exactly the same as the core ones except their names are different.

I will keep this issue open until it is merged into the core package.

Hi there, Thanks so much! I just saw your message today. We have a 3-day holiday coming up, so I'll try rolling out this version next week and see if the issue is fixed. I'll give you an update then! Cheers!

venlon789 avatar May 30 '25 07:05 venlon789

Hi, @OvidijusParsiunas

I just quickly tested it, and the issue has indeed been resolved. Thank you so much, that's really impressive! Looking forward to this feature being released in the stable version.

venlon789 avatar May 30 '25 09:05 venlon789

Hello! @OvidijusParsiunas I'm using the deep-chat-react-dev version 9.0.265 and I've discovered a bug. When the string \n\n is rendered, and I then try to use the overwrite option to clear and replace the previously rendered content, it fails to properly clear the previous content.

Example:

signals.onResponse({ text: "Test  \n\n  " });
signals.onResponse({ text: "Hello!", overwrite: true });

This results in the following display:

Test
Hello!

But it should only display:

Hello!

venlon789 avatar Jun 09 '25 08:06 venlon789

@venlon789 that is strange. I tried to replicate your bug using the following connect property in demo mode:

{
  stream: true,
  handler: (_, signals) => {
    signals.onOpen();
    setTimeout(() => {
      signals.onResponse({text: 'Test  \n\n  '});
      signals.onResponse({text: 'Hello!', overwrite: true});
    });
  },
}

But the screen outputs just 'Hello!'.

Can you try to see if upgrading to the latest -dev version of 9.0.276 might fix the problem for you. Thanks!

OvidijusParsiunas avatar Jun 09 '25 13:06 OvidijusParsiunas

@OvidijusParsiunas

I have upgraded to the latest version (9.0.276) as you suggested, but the issue still persists.


Have you used the following attribute?

connect='{"stream": {"partialRender": true}}'

Note:

If you only use:

connect='{"stream": true}'

then overwrite: true works as expected.

However, once you add the partialRender property, it stops working.

venlon789 avatar Jun 10 '25 03:06 venlon789

@OvidijusParsiunas

I made a mistake. Try using it like this:

connect = {
    stream: { partialRender: true },
    handler: (_, signals) => {
      signals.onOpen()
      setTimeout(() => {
        signals.onResponse({ text: 'Test  \n\n  ' })
        signals.onResponse({ text: 'Hello! \n\n', overwrite: true })
      })
    }
  }

Image

connect = {
    stream: { partialRender: true },
    handler: (_, signals) => {
      signals.onOpen()
      setTimeout(() => {
        signals.onResponse({ text: 'Test1  \n\n  ' })
        signals.onResponse({ text: 'Test2  \n\n  ' })
        signals.onResponse({ text: 'Test3', overwrite: true })
      })
    }
  }

Image

venlon789 avatar Jun 10 '25 03:06 venlon789

Thankyou for the clarification.

I was able to fix the problem and have released the solution in deep-chat-dev and deep-chat-react-dev version 9.0.277.

Let me know if it fixes your issue!

Thanks!

OvidijusParsiunas avatar Jun 10 '25 15:06 OvidijusParsiunas

@OvidijusParsiunas Thank you so much! This problem has been solved. Thanks for your hard work.

venlon789 avatar Jun 16 '25 01:06 venlon789

partialRender is now available in deep-chat and deep-chat-react version 2.2.2. See release notes for more information. Thankyou.

OvidijusParsiunas avatar Jul 07 '25 13:07 OvidijusParsiunas

partialRender is now available in deep-chat and deep-chat-react version 2.2.2. See release notes for more information. Thankyou.

I really appreciate you taking my feedback seriously and fixing the issue—thanks again!

venlon789 avatar Jul 30 '25 01:07 venlon789

@OvidijusParsiunas Hello, In version 2.2.2, I've noticed an issue: when the sequence '\n\n---\n\n' appears, it fails to render correctly during streaming output rendering.

const repeatedText = "**Prediction**: Although Mexico is not currently in the global top ten, its rapidly growing economy and export-oriented model make it possible for it to enter the top ten within the next five years.\n\n---\n\n### **4. Saudi Arabia**\n- **GDP growth potential**: Saudi Arabia's economic growth has been stable in recent years, despite being affected by geopolitical and economic volatility.\n- **Driving factors**:\n  - Regional economic hub: Saudi Arabia is located at the crossroads of major trade routes and serves as an important bridge connecting Asia, Africa, and Europe.\n  - Upgrading of manufacturing and services: Saudi Arabia has strong competitiveness in petrochemicals, renewable energy, and tourism.\n  - Policy support: The Saudi government is promoting a series of economic reforms to attract foreign investment.\n- **Prediction**: Saudi Arabia could enter the global top ten within the next five years, especially if its regional economic status further strengthens.\n\n---\n\n### **5. Australia (already in the top ten, but with limited growth potential)**\n- **GDP growth potential**: Australia's economic growth has been relatively slow in recent years, but it still has considerable economic potential.\n- **Driving factors**:\n  - Abundant natural resources: Australia is one of the world's largest exporters of minerals and agricultural products.\n  - Industrialization process: Australia has significant growth potential in advanced manufacturing and technology.\n  - Consumer market: Australia has a stable and affluent consumer market that could further expand in the coming years.\n- **Prediction**: Australia may maintain its position in the global top ten over the next five years, but its growth potential is relatively limited.\n\n---\n\n### **Summary**\nOver the next five years, India, Mexico, Saudi Arabia, and South Korea are the emerging markets most likely to enter the global top ten by GDP. These countries have advantages such as a youthful demographic dividend, structural upgrades in their economies, and policy support, and are expected to play a more important role in the global economy in the coming years."


const demoContent = repeatedText

const chatElementRef = ref()

onMounted(() => {
  chatElementRef.value.onComponentRender = () => {
    chatElementRef.value.history = [
      { role: 'user', text: 'Hey, how are you today?' },
      { role: 'ai', text: 'I am doing very well!' }
    ]
    chatElementRef.value.demo = {
      response: {
        text: demoContent
      }
    }
    deepChatStyle(chatElementRef)
  }
})
</script>

<template>
  <div class="app-layout">
    <deep-chat
      ref="chatElementRef"
      :remarkable='{"html": true, "typographer": true}'
      :connect='{"stream": {"partialRender": true}}'
      class="deep-chat"
      demo="true"
      style="
        width: 100vw;
        height: 100vh;
        background-color: transparent;
        border: none;
      "
    >
    </deep-chat>
  </div>
</template>

Image Image The phrase "---" should normally render like this. Image

venlon789 avatar Aug 09 '25 08:08 venlon789

Hi, I am currently on a holiday with limited free time, I will look into this as soon as I can in the next couple of days.

OvidijusParsiunas avatar Aug 11 '25 06:08 OvidijusParsiunas

Hi @venlon789.

I investigated the issue and the reason why this is happening is when partialRender is set to true it causes the first \n\n that it finds in the text to immediately be interpreted as a new text bubble (so it wouldn't be re-rendered again).

I have updated deep-chat-dev and deep-chat-react-dev packages to version 9.0.292 to check if the text property has any hyphens after \n\n to see if it should be interpreted as a new text bubble.

Please note, the response should contain full {text: \n\n---\n\n} string in the same for this to work. If the server responds with three text messages with {text: \n\n}, {text: ---} and {text: \n\n} this will not work. (Therefore when using the demo or stream simulation it will not work correctly due to the text being segmented into individual characters.

Let me know if this helps.

OvidijusParsiunas avatar Aug 12 '25 10:08 OvidijusParsiunas

Hi @venlon789.

I investigated the issue and the reason why this is happening is when partialRender is set to true it causes the first \n\n that it finds in the text to immediately be interpreted as a new text bubble (so it wouldn't be re-rendered again).

I have updated deep-chat-dev and deep-chat-react-dev packages to version 9.0.292 to check if the text property has any hyphens after \n\n to see if it should be interpreted as a new text bubble.

Please note, the response should contain full {text: \n\n---\n\n} string in the same for this to work. If the server responds with three text messages with {text: \n\n}, {text: ---} and {text: \n\n} this will not work. (Therefore when using the demo or stream simulation it will not work correctly due to the text being segmented into individual characters.

Let me know if this helps.

@OvidijusParsiunas { text: \n\n}, { text: --- }, and { text: \n\n }—this is indeed the current situation returned by the server, and it is not very consistent. Therefore, this does cause unsuccessful rendering. Thank you very much for your reply.I wonder if there is a better solution.

venlon789 avatar Aug 13 '25 07:08 venlon789

Would allowing you to choose what the new partial render area marker is be useful? It is \n\n right now, but would allowing you to choose something else help?

OvidijusParsiunas avatar Aug 13 '25 12:08 OvidijusParsiunas