fix(streaming): strip Gemma 4 thinking token delimiter in all paths — closes #607
Fixes <|turn|>thinking delimiter (was wrong as <|turn>thinking) in api/streaming.py, static/messages.js, and static/ui.js. Adds 13 regression tests. Independent review by @nesquena.
This commit is contained in:
@@ -591,7 +591,7 @@
|
||||
<div class="settings-section-title">System</div>
|
||||
<div class="settings-section-meta">Instance version and access controls.</div>
|
||||
</div>
|
||||
<span class="settings-version-badge">v0.50.77</span>
|
||||
<span class="settings-version-badge">v0.50.78</span>
|
||||
</div>
|
||||
<div class="settings-field" style="border-top:1px solid var(--border);padding-top:12px;margin-top:8px">
|
||||
<label for="settingsPassword" data-i18n="settings_label_password">Access Password</label>
|
||||
|
||||
@@ -144,7 +144,8 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){
|
||||
// Thinking tag patterns for streaming display
|
||||
const _thinkPairs=[
|
||||
{open:'<think>',close:'</think>'},
|
||||
{open:'<|channel>thought\n',close:'<channel|>'}
|
||||
{open:'<|channel>thought\n',close:'<channel|>'},
|
||||
{open:'<|turn|>thinking\n',close:'<turn|>'} // Gemma 4
|
||||
];
|
||||
|
||||
function _isActiveSession(){
|
||||
|
||||
11
static/ui.js
11
static/ui.js
@@ -1095,7 +1095,7 @@ function _messageHasReasoningPayload(m){
|
||||
if(!m||m.role!=='assistant') return false;
|
||||
if(m.reasoning) return true;
|
||||
if(Array.isArray(m.content)) return m.content.some(p=>p&&(p.type==='thinking'||p.type==='reasoning'));
|
||||
return /<think>[\s\S]*?<\/think>|<\|channel>thought\n[\s\S]*?<channel\|>/.test(String(m.content||''));
|
||||
return /<think>[\s\S]*?<\/think>|<\|channel>thought\n[\s\S]*?<channel\|>|<\|turn\|>thinking\n[\s\S]*?<turn\|>/.test(String(m.content||''));
|
||||
}
|
||||
function _assistantRoleHtml(tsTitle=''){
|
||||
const _bn=window._botName||'Hermes';
|
||||
@@ -1167,12 +1167,21 @@ function renderMessages(){
|
||||
content=content.replace(/<think>[\s\S]*?<\/think>\s*/,'').trimStart();
|
||||
}
|
||||
if(!thinkingText){
|
||||
// Historical name "gemmaMatch" refers to MiniMax <|channel>thought format.
|
||||
const gemmaMatch=content.match(/<\|channel>thought\n([\s\S]*?)<channel\|>/);
|
||||
if(gemmaMatch){
|
||||
thinkingText=gemmaMatch[1].trim();
|
||||
content=content.replace(/<\|channel>thought\n[\s\S]*?<channel\|>\s*/,'').trimStart();
|
||||
}
|
||||
}
|
||||
if(!thinkingText){
|
||||
// Gemma 4 uses asymmetric <|turn|>thinking\n...<turn|> delimiters.
|
||||
const gemmaTurnMatch=content.match(/<\|turn\|>thinking\n([\s\S]*?)<turn\|>/);
|
||||
if(gemmaTurnMatch){
|
||||
thinkingText=gemmaTurnMatch[1].trim();
|
||||
content=content.replace(/<\|turn\|>thinking\n[\s\S]*?<turn\|>\s*/,'').trimStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
const isUser=m.role==='user';
|
||||
const isLastAssistant=!isUser&&vi===visWithIdx.length-1;
|
||||
|
||||
Reference in New Issue
Block a user