Gemini: Thought toggle Closes #3220
| @@ -1975,6 +1975,20 @@ | ||
| 1975 | 1975 | </span> |
| 1976 | 1976 | </div> |
| 1977 | 1977 | </div> |
| 1978 | + <div class="range-block" data-source="makersuite"> | |
| 1979 | + <label for="openai_show_thoughts" class="checkbox_label widthFreeExpand"> | |
| 1980 | + <input id="openai_show_thoughts" type="checkbox" /> | |
| 1981 | + <span> | |
| 1982 | + <span data-i18n="Show model thoughts">Show model thoughts</span> | |
| 1983 | + <i class="opacity50p fa-solid fa-circle-info" title="Gemini 2.0 Thinking"></i> | |
| 1984 | + </span> | |
| 1985 | + </label> | |
| 1986 | + <div class="toggle-description justifyLeft marginBot5"> | |
| 1987 | + <span data-i18n="Display the model's internal thoughts in the response."> | |
| 1988 | + Display the model's internal thoughts in the response. | |
| 1989 | + </span> | |
| 1990 | + </div> | |
| 1991 | + </div> | |
| 1978 | 1992 | <div class="range-block" data-source="claude"> |
| 1979 | 1993 | <div class="wide100p"> |
| 1980 | 1994 | <div class="flex-container alignItemsCenter"> |
| @@ -295,6 +295,7 @@ const default_settings = { | ||
| 295 | 295 | names_behavior: character_names_behavior.DEFAULT, |
| 296 | 296 | continue_postfix: continue_postfix_types.SPACE, |
| 297 | 297 | custom_prompt_post_processing: custom_prompt_post_processing_types.NONE, |
| 298 | + show_thoughts: false, | |
| 298 | 299 | seed: -1, |
| 299 | 300 | n: 1, |
| 300 | 301 | }; |
| @@ -372,6 +373,7 @@ const oai_settings = { | ||
| 372 | 373 | names_behavior: character_names_behavior.DEFAULT, |
| 373 | 374 | continue_postfix: continue_postfix_types.SPACE, |
| 374 | 375 | custom_prompt_post_processing: custom_prompt_post_processing_types.NONE, |
| 376 | + show_thoughts: false, | |
| 375 | 377 | seed: -1, |
| 376 | 378 | n: 1, |
| 377 | 379 | }; |
| @@ -1884,6 +1886,7 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1884 | 1886 | 'user_name': name1, |
| 1885 | 1887 | 'char_name': name2, |
| 1886 | 1888 | 'group_names': getGroupNames(), |
| 1889 | + 'show_thoughts': Boolean(oai_settings.show_thoughts), | |
| 1887 | 1890 | }; |
| 1888 | 1891 | |
| 1889 | 1892 | // Empty array will produce a validation error |
| @@ -2098,7 +2101,7 @@ function getStreamingReply(data) { | ||
| 2098 | 2101 | if (oai_settings.chat_completion_source === chat_completion_sources.CLAUDE) { |
| 2099 | 2102 | return data?.delta?.text || ''; |
| 2100 | 2103 | } else if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) { |
| 2101 | 2104 | return data?.candidates?.[0]?.content?.parts?.filter(x => oai_settings.show_thoughts || !x.thought)?.map(x => x.text)?.filter(x => x)?.join('\n\n') || ''; |
| 2102 | 2105 | } else if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { |
| 2103 | 2106 | return data?.delta?.message?.content?.text || data?.delta?.message?.tool_plan || ''; |
| 2104 | 2107 | } else { |
| @@ -3056,6 +3059,7 @@ function loadOpenAISettings(data, settings) { | ||
| 3056 | 3059 | oai_settings.image_inlining = settings.image_inlining ?? default_settings.image_inlining; |
| 3057 | 3060 | oai_settings.inline_image_quality = settings.inline_image_quality ?? default_settings.inline_image_quality; |
| 3058 | 3061 | oai_settings.bypass_status_check = settings.bypass_status_check ?? default_settings.bypass_status_check; |
| 3062 | + oai_settings.show_thoughts = settings.show_thoughts ?? default_settings.show_thoughts; | |
| 3059 | 3063 | oai_settings.seed = settings.seed ?? default_settings.seed; |
| 3060 | 3064 | oai_settings.n = settings.n ?? default_settings.n; |
| 3061 | 3065 | |
| @@ -3181,6 +3185,7 @@ function loadOpenAISettings(data, settings) { | ||
| 3181 | 3185 | $('#repetition_penalty_counter_openai').val(Number(oai_settings.repetition_penalty_openai)); |
| 3182 | 3186 | $('#seed_openai').val(oai_settings.seed); |
| 3183 | 3187 | $('#n_openai').val(oai_settings.n); |
| 3188 | + $('#openai_show_thoughts').prop('checked', oai_settings.show_thoughts); | |
| 3184 | 3189 | |
| 3185 | 3190 | if (settings.reverse_proxy !== undefined) oai_settings.reverse_proxy = settings.reverse_proxy; |
| 3186 | 3191 | $('#openai_reverse_proxy').val(oai_settings.reverse_proxy); |
| @@ -3441,6 +3446,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | ||
| 3441 | 3446 | continue_prefill: settings.continue_prefill, |
| 3442 | 3447 | continue_postfix: settings.continue_postfix, |
| 3443 | 3448 | function_calling: settings.function_calling, |
| 3449 | + show_thoughts: settings.show_thoughts, | |
| 3444 | 3450 | seed: settings.seed, |
| 3445 | 3451 | n: settings.n, |
| 3446 | 3452 | }; |
| @@ -3897,6 +3903,7 @@ function onSettingsPresetChange() { | ||
| 3897 | 3903 | continue_prefill: ['#continue_prefill', 'continue_prefill', true], |
| 3898 | 3904 | continue_postfix: ['#continue_postfix', 'continue_postfix', false], |
| 3899 | 3905 | function_calling: ['#openai_function_calling', 'function_calling', true], |
| 3906 | + show_thoughts: ['#openai_show_thoughts', 'show_thoughts', true], | |
| 3900 | 3907 | seed: ['#seed_openai', 'seed', false], |
| 3901 | 3908 | n: ['#n_openai', 'n', false], |
| 3902 | 3909 | }; |
| @@ -5390,6 +5397,11 @@ export function initOpenAI() { | ||
| 5390 | 5397 | saveSettingsDebounced(); |
| 5391 | 5398 | }); |
| 5392 | 5399 | |
| 5400 | + $('#openai_show_thoughts').on('input', function () { | |
| 5401 | + oai_settings.show_thoughts = !!$(this).prop('checked'); | |
| 5402 | + saveSettingsDebounced(); | |
| 5403 | + }); | |
| 5404 | + | |
| 5393 | 5405 | if (!CSS.supports('field-sizing', 'content')) { |
| 5394 | 5406 | $(document).on('input', '#openai_settings .autoSetHeight', function () { |
| 5395 | 5407 | resetScrollHeight($(this)); |
| @@ -144,9 +144,14 @@ async function* parseStreamData(json) { | ||
| 144 | 144 | for (let j = 0; j < json.candidates[i].content.parts.length; j++) { |
| 145 | 145 | if (typeof json.candidates[i].content.parts[j].text === 'string') { |
| 146 | 146 | for (let k = 0; k < json.candidates[i].content.parts[j].text.length; k++) { |
| 147 | 147 | const strmoreThanOnePart = json.candidates[i].content.parts[j].text[k]length > 1; |
| 148 | + const isNotLastPart = j !== json.candidates[i].content.parts.length - 1; | |
| 149 | + const isLastSymbol = k === json.candidates[i].content.parts[j].text.length - 1; | |
| 150 | + const addNewline = moreThanOnePart && isNotLastPart && isLastSymbol; | |
| 151 | + const str = json.candidates[i].content.parts[j].text[k] + (addNewline ? '\n\n' : ''); | |
| 148 | 152 | const candidateClone = structuredClone(json.candidates[0]); |
| 149 | 153 | candidateClone.content.parts[j].text = str; |
| 154 | + candidateClone.content.parts = [candidateClone.content.parts[j]]; | |
| 150 | 155 | const candidates = [candidateClone]; |
| 151 | 156 | yield { |
| 152 | 157 | data: { ...json, candidates }, |
| @@ -278,6 +278,7 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 278 | 278 | |
| 279 | 279 | const model = String(request.body.model); |
| 280 | 280 | const stream = Boolean(request.body.stream); |
| 281 | + const showThoughts = Boolean(request.body.show_thoughts); | |
| 281 | 282 | |
| 282 | 283 | const generationConfig = { |
| 283 | 284 | stopSequences: request.body.stop, |
| @@ -325,7 +326,8 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 325 | 326 | controller.abort(); |
| 326 | 327 | }); |
| 327 | 328 | |
| 328 | 329 | const apiVersionisThinking = model.includes('v1betathinking'); |
| 330 | + const apiVersion = isThinking ? 'v1alpha' : 'v1beta'; | |
| 329 | 331 | const responseType = (stream ? 'streamGenerateContent' : 'generateContent'); |
| 330 | 332 | |
| 331 | 333 | const generateResponse = await fetch(`${apiUrl.toString().replace(/\/$/, '')}/${apiVersion}/models/${model}:${responseType}?key=${apiKey}${stream ? '&alt=sse' : ''}`, { |
| @@ -369,6 +371,10 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 369 | 371 | const responseContent = candidates[0].content ?? candidates[0].output; |
| 370 | 372 | console.log('Google AI Studio response:', responseContent); |
| 371 | 373 | |
| 374 | + if (Array.isArray(responseContent?.parts) && isThinking && !showThoughts) { | |
| 375 | + responseContent.parts = responseContent.parts.filter(part => !part.thought); | |
| 376 | + } | |
| 377 | + | |
| 372 | 378 | const responseText = typeof responseContent === 'string' ? responseContent : responseContent?.parts?.map(part => part.text)?.join('\n\n'); |
| 373 | 379 | if (!responseText) { |
| 374 | 380 | let message = 'Google AI Studio Candidate text empty'; |