Skip to content

webui : put DeepSeek R1 CoT in a collapsible <details> element #11364

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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 24, 2025

Conversation

stduhpf
Copy link
Contributor

@stduhpf stduhpf commented Jan 23, 2025

This hides the <think> and </think> tags from the user, and moves the content beetween these tags to a collipsable element that closes itself for compactness once the model is done generating the answer.

This only works for R1 tags, other reasoning models lik QwQ will not generate those tags by themselves.

It could be interesting to use this work as a basis to remove the previous chains of thoughts from the prompts during multi-turn conversations, as suggested here: #11325 (comment)

@stduhpf
Copy link
Contributor Author

stduhpf commented Jan 23, 2025

I'm not sure why the CI is failing, Could be due to a difference in the gzip versions used between my computer and the CI?

Copy link
Collaborator

@ngxson ngxson left a comment

Choose a reason for hiding this comment

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

The idea is ok but I don't really like the implementation. Instead of modifying the shape of pendingMsg, you should make a new function that transform content into pair of cot, content and call it from html vue code.

In other words, in a MVC model, what you're changing is M while you can just do it in V with functional programming approach.

@stduhpf
Copy link
Contributor Author

stduhpf commented Jan 23, 2025

The idea is ok but I don't really like the implementation. Instead of modifying the shape of pendingMsg, you should make a new function that transform content into pair of cot, content and call it from html vue code.

In other words, in a MVC model, what you're changing is M while you can just do it in V with functional programming approach.

I agree that the implementation is a bit hacky for now, I'll try to improve it.

@ngxson
Copy link
Collaborator

ngxson commented Jan 23, 2025

What I added:

  • Improve the aesthetic a little bit
  • Add setting options to expand the thought by default
  • Add option to exclude the <think>...</think> from past message upon sending to API, which is recommended for DeepSeek-R1

Demo:

Screen.Recording.2025-01-24.at.00.17.28.mov

CC @ggerganov for your info

@ngxson
Copy link
Collaborator

ngxson commented Jan 23, 2025

Merging this once the CI pass

@ngxson ngxson merged commit c07e87f into ggml-org:master Jan 24, 2025
6 checks passed
@ggerganov
Copy link
Member

Cool!

anagri pushed a commit to BodhiSearch/llama.cpp that referenced this pull request Jan 26, 2025
…nt (ggml-org#11364)

* webui : put DeepSeek R1 CoT in a collapsible <details> element

* webui: refactor split

* webui: don't use regex to split cot and response

* webui: format+qol

* webui: no loading icon if the model isn't generating

* ui fix, add configs

* add jsdoc types

* only filter </think> for assistant msg

* build

* update build

---------

Co-authored-by: Xuan Son Nguyen <[email protected]>
Comment on lines +208 to +221
let thinkSplit = content.split('<think>', 2);
actualContent += thinkSplit[0];
while (thinkSplit[1] !== undefined) {
// <think> tag found
thinkSplit = thinkSplit[1].split('</think>', 2);
cot += thinkSplit[0];
isThinking = true;
if (thinkSplit[1] !== undefined) {
// </think> closing tag found
isThinking = false;
thinkSplit = thinkSplit[1].split('<think>', 2);
actualContent += thinkSplit[0];
}
}
Copy link
Contributor Author

@stduhpf stduhpf Feb 10, 2025

Choose a reason for hiding this comment

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

I just found out I was mistaken about the behavior of javascript's String.prototype.split() with a limit. I assumed it would keep all the content including the separators in the last element but I was wrong.

This shouldn't cause problems for R1 models since it typically uses the chain of thought only once per reply, but if, for example, the user specifies in the system prompt "You can hide your thoughts to the user by surrounding them with <think> and </think>. You can use it multiple times per answer.", then everything after the second <think> is never going to be displayed.

tinglou pushed a commit to tinglou/llama.cpp that referenced this pull request Feb 13, 2025
…nt (ggml-org#11364)

* webui : put DeepSeek R1 CoT in a collapsible <details> element

* webui: refactor split

* webui: don't use regex to split cot and response

* webui: format+qol

* webui: no loading icon if the model isn't generating

* ui fix, add configs

* add jsdoc types

* only filter </think> for assistant msg

* build

* update build

---------

Co-authored-by: Xuan Son Nguyen <[email protected]>
arthw pushed a commit to arthw/llama.cpp that referenced this pull request Feb 26, 2025
…nt (ggml-org#11364)

* webui : put DeepSeek R1 CoT in a collapsible <details> element

* webui: refactor split

* webui: don't use regex to split cot and response

* webui: format+qol

* webui: no loading icon if the model isn't generating

* ui fix, add configs

* add jsdoc types

* only filter </think> for assistant msg

* build

* update build

---------

Co-authored-by: Xuan Son Nguyen <[email protected]>
mglambda pushed a commit to mglambda/llama.cpp that referenced this pull request Mar 8, 2025
…nt (ggml-org#11364)

* webui : put DeepSeek R1 CoT in a collapsible <details> element

* webui: refactor split

* webui: don't use regex to split cot and response

* webui: format+qol

* webui: no loading icon if the model isn't generating

* ui fix, add configs

* add jsdoc types

* only filter </think> for assistant msg

* build

* update build

---------

Co-authored-by: Xuan Son Nguyen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants