Claude: add web search tool, adjust prefill voiding Closes #3968

c1c77a6a60b30cbe85bed3b4d8a3e8c67c2fa4ac

Cohee <18619528+Cohee1207@users.noreply.github.com>

2 files changed, +14 -9Showing whitespace changes
public/index.html+1 -1
@@ -1963,7 +1963,7 @@
19631963 </span>
19641964 </div>
19651965 </div>
19661966 <div class="range-block" data-source="makersuite,openrouter,claude">
19671967 <label for="openai_enable_web_search" class="checkbox_label flexWrap widthFreeExpand">
19681968 <input id="openai_enable_web_search" type="checkbox" />
19691969 <span data-i18n="Enable web search">Enable web search</span>
src/endpoints/backends/chat-completions.js+13 -8
@@ -148,7 +148,8 @@ async function sendClaudeRequest(request, response) {
148148 const useSystemPrompt = (request.body.model.startsWith('claude-2') || request.body.model.startsWith('claude-3')) && request.body.claude_use_sysprompt;
149149 const convertedPrompt = convertClaudeMessages(request.body.messages, request.body.assistant_prefill, useSystemPrompt, useTools, getPromptNames(request));
150150 const useThinking = request.body.model.startsWith('claude-3-7') && Boolean(request.body.include_reasoning);
151- let voidPrefill = false;
151+ const useWebSearch = /^claude-3-(5|7)/.test(request.body.model) && Boolean(request.body.enable_web_search);
152+ let fixThinkingPrefill = false;
152153 // Add custom stop sequences
153154 const stopSequences = [];
154155 if (Array.isArray(request.body.stop)) {
@@ -183,15 +184,19 @@ async function sendClaudeRequest(request, response) {
183184 .map(tool => tool.function)
184185 .map(fn => ({ name: fn.name, description: fn.description, input_schema: fn.parameters }));
185186
186- if (requestBody.tools.length) {
187- // No prefill when using tools
188- voidPrefill = true;
189- }
190187 if (enableSystemPromptCache && requestBody.tools.length) {
191188 requestBody.tools[requestBody.tools.length - 1]['cache_control'] = { type: 'ephemeral' };
192189 }
193190 }
194191
192+ if (useWebSearch) {
193+ const webSearchTool = [{
194+ 'type': 'web_search_20250305',
195+ 'name': 'web_search',
196+ }];
197+ requestBody.tools = [...(requestBody.tools || []), ...webSearchTool];
198+ }
199+
195200 if (cachingAtDepth !== -1) {
196201 cachingAtDepthForClaude(convertedPrompt.messages, cachingAtDepth);
197202 }
@@ -205,7 +210,7 @@ async function sendClaudeRequest(request, response) {
205210
206211 if (useThinking && Number.isInteger(budgetTokens)) {
207212 // No prefill when thinking
208213 voidPrefillfixThinkingPrefill = true;
209214 const minThinkTokens = 1024;
210215 if (requestBody.max_tokens <= minThinkTokens) {
211216 const newValue = requestBody.max_tokens + minThinkTokens;
@@ -224,8 +229,8 @@ async function sendClaudeRequest(request, response) {
224229 delete requestBody.top_k;
225230 }
226231
227232 if (voidPrefillfixThinkingPrefill && convertedPrompt.messages.length && convertedPrompt.messages[convertedPrompt.messages.length - 1].role === 'assistant') {
228- convertedPrompt.messages.push({ role: 'user', content: [{ type: 'text', text: '\u200b' }] });
233+ convertedPrompt.messages[convertedPrompt.messages.length - 1].role = 'user';
229234 }
230235
231236 if (betaHeaders.length) {