#how to implement the chatGPT DOM update effect?

21 messages · Page 1 of 1 (latest)

wraith night
#

Ask a question, on the chatGPT web, with the typewriter effect output, you will find that when it outputs the second line, the first line can already be copied and will not be updated again. It is truly incremental DOM updates.

Imagine implementing something similar with Vue/React:

  1. Fetch the GPT API, stream the result incrementally, and each time parse the content containing markdown tags, then text += content (executed once per return)
  2. Parse the text into HTML tags: result = markdownIt(text) (executed once per return)
  3. v-html/innerHTML = result, rendering the final markdown form of HTML.

Here is a problem: constantly parsing the markdown text into the result will lead to re-rendering the entire HTML output. While the output screen appears incremental, the entire rendered DOM content keeps refreshing, causing the already output content to be unselectable, which results in a poor experience and performance issues. Any optimization suggestions?

quartz sonnetBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

unkempt grail
#

it's just that the markdown renderer it uses is very performant

#

and i guess they use a lot of memoisation techniques like useMemo, memo and whatnot

wraith night
#
text += content
result = markdownIt(text)
// then render the whole result

this is a very easy way to do that, but my problem is, when I just render the whole result every time, the whole markdown is always repainted. It's not updated line by line. (but seems like chatGPT web implement that)

unkempt grail
# wraith night ```js text += content result = markdownIt(text) // then render the whole result ...

chatgpt web does not implement this. as you see above, there is a link in progress, chatgpt renders it as plain text "[issue tracker](https:/".

when the link is complete, the frontend makes it a full link. if it really does incremental computation like that, it would have to delete the "[issue tracker](https:/" part and add "issue tracker" in. that's technically possible but extremely complicated, since markdown syntax is not as simple as it looks, a markdown line can influence many previous lines.

chatgpt web also becomes slow when the conversation gets long, which further proves there is no magic going on in there. its markdown parser is just performant and its syntax highlighting library lightweight, that's pretty much it.

wraith night
unkempt grail
#

here new markdown tokens being added doesn't change the previous paragraphs so the output is the same

wraith night
#

so I need to handle the <pre>? seems like chatgpt handle it specialy, when the code streaming , the pre label is very stable

#

My entire pre tag is flashing and constantly updating, but ChatGPT's pre tag looks very stable, with code only being added at the end, even the pre tag hasn't closed yet.

unkempt grail
wraith night
#

Let's think about how ChatGPT achieves such stable output with minimal DOM updates. (That's the point)

text += content
result = markdownIt(text)
// then render the whole result

I'm just updating like this, and the experience is very poor.

unkempt grail
#

though i have never attempted to use anything except the heavy shiki for this, so i don't know of more lightweight libs like prism or highlight.js would "just work"

unkempt grail
#

i just use react-markdown here, without any of that text += content shenanigan, and the performance is smooth until at least 10 long messages later

#

sure, i don't have syntax highlighting, but that's because i tried once with shiki which is heavy af and it was indeed laggy. i never tried with more lightweight libraries

wraith night
# wraith night Pay attention to that pre element

checkout out the second record here (the tag is flashing when straming, So you can't copy the already outputted code, which is the biggest difference, because it's flickering and constantly updating.)

unkempt grail
#

oh so it's indeed about the pre tag, this one then i have no comment because i haven't done it myself