diff --git a/.changeset/lovely-zoos-glow.md b/.changeset/lovely-zoos-glow.md new file mode 100644 index 0000000000..0b28485cf2 --- /dev/null +++ b/.changeset/lovely-zoos-glow.md @@ -0,0 +1,5 @@ +--- +"claude-dev": minor +--- + +Separate Sonnet 3.7 thinking into a separate model diff --git a/package.json b/package.json index 7d8880c743..c35828547d 100644 --- a/package.json +++ b/package.json @@ -215,7 +215,7 @@ "cline.modelSettings.anthropic.thinkingBudgetTokens": { "type": "number", "default": 0, - "description": "Controls the token budget for Claude's thinking capability. Set to 0 to disable thinking. When enabled, must be ≥1024 and less than the model's max token output." + "description": "Controls the token budget for Claude's thinking capability. Set to 0 to disable thinking. When enabled, must be ≥ 1024 and less than the model's max token output." } } } diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index 7c9582145c..ae4fd3bb21 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -1,7 +1,14 @@ import { Anthropic } from "@anthropic-ai/sdk" import { Stream as AnthropicStream } from "@anthropic-ai/sdk/streaming" import { withRetry } from "../retry" -import { anthropicDefaultModelId, AnthropicModelId, anthropicModels, ApiHandlerOptions, ModelInfo } from "../../shared/api" +import { + ANTHROPIC_THINKING_BUDGET_TOKENS_MIN, + anthropicDefaultModelId, + AnthropicModelId, + anthropicModels, + ApiHandlerOptions, + ModelInfo, +} from "../../shared/api" import { ApiHandler } from "../index" import { ApiStream } from "../transform/stream" @@ -19,14 +26,13 @@ export class AnthropicHandler implements ApiHandler { @withRetry() async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream { - let budget_tokens = this.options.thinkingBudgetTokens || 0 - const reasoningOn = budget_tokens !== 0 ? true : false const model = this.getModel() let stream: AnthropicStream const modelId = model.id switch (modelId) { // 'latest' alias does not support cache_control case "claude-3-7-sonnet-20250219": + case "claude-3-7-sonnet-20250219:thinking": case "claude-3-5-sonnet-20241022": case "claude-3-5-haiku-20241022": case "claude-3-opus-20240229": @@ -42,12 +48,18 @@ export class AnthropicHandler implements ApiHandler { const secondLastMsgUserIndex = userMsgIndices[userMsgIndices.length - 2] ?? -1 stream = await this.client.messages.create( { - model: modelId, - thinking: reasoningOn ? { type: "enabled", budget_tokens: budget_tokens } : undefined, + model: modelId === "claude-3-7-sonnet-20250219:thinking" ? "claude-3-7-sonnet-20250219" : modelId, + thinking: + modelId === "claude-3-7-sonnet-20250219:thinking" + ? { + type: "enabled", + budget_tokens: this.options.thinkingBudgetTokens || ANTHROPIC_THINKING_BUDGET_TOKENS_MIN, + } + : undefined, max_tokens: model.info.maxTokens || 8192, // "Thinking isn’t compatible with temperature, top_p, or top_k modifications as well as forced tool use." // (https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking#important-considerations-when-using-extended-thinking) - temperature: reasoningOn ? 1 : 0, + temperature: modelId === "claude-3-7-sonnet-20250219:thinking" ? 1 : 0, system: [ { text: systemPrompt, @@ -95,6 +107,7 @@ export class AnthropicHandler implements ApiHandler { // https://github.com/anthropics/anthropic-sdk-typescript/commit/c920b77fc67bd839bfeb6716ceab9d7c9bbe7393 switch (modelId) { case "claude-3-7-sonnet-20250219": + case "claude-3-7-sonnet-20250219:thinking": case "claude-3-5-sonnet-20241022": case "claude-3-5-haiku-20241022": case "claude-3-opus-20240229": diff --git a/src/shared/api.ts b/src/shared/api.ts index 7a052a8d5e..3e14f3bd55 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -84,6 +84,7 @@ export interface ModelInfo { // https://docs.anthropic.com/en/docs/about-claude/models // prices updated 2025-01-02 export type AnthropicModelId = keyof typeof anthropicModels export const anthropicDefaultModelId: AnthropicModelId = "claude-3-7-sonnet-20250219" +export const ANTHROPIC_THINKING_BUDGET_TOKENS_MIN = 1024 export const anthropicModels = { "claude-3-7-sonnet-20250219": { maxTokens: 8192, @@ -96,6 +97,17 @@ export const anthropicModels = { cacheWritesPrice: 3.75, cacheReadsPrice: 0.3, }, + "claude-3-7-sonnet-20250219:thinking": { + maxTokens: 8192, + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 3.0, + outputPrice: 15.0, + cacheWritesPrice: 3.75, + cacheReadsPrice: 0.3, + }, "claude-3-5-sonnet-20241022": { maxTokens: 8192, contextWindow: 200_000, diff --git a/src/utils/validation.ts b/src/utils/validation.ts index d285e20c0d..37c74cf4d2 100644 --- a/src/utils/validation.ts +++ b/src/utils/validation.ts @@ -1,4 +1,4 @@ -import { anthropicModels } from "../shared/api" +import { ANTHROPIC_THINKING_BUDGET_TOKENS_MIN, anthropicModels } from "../shared/api" /** * Validates the thinking budget token value according to the specified rules: @@ -21,8 +21,8 @@ export function validateThinkingBudget( } // If enabled but less than minimum, set to minimum - if (value > 0 && value < 1024) { - return 1024 + if (value > 0 && value < ANTHROPIC_THINKING_BUDGET_TOKENS_MIN) { + return ANTHROPIC_THINKING_BUDGET_TOKENS_MIN } // If greater than or equal to max allowed tokens (80% of max tokens), cap at that value diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index f05cb3d56f..d04b2c364b 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -8,7 +8,6 @@ import { VSCodeTextField, } from "@vscode/webview-ui-toolkit/react" import { Fragment, memo, useCallback, useEffect, useMemo, useState } from "react" -import ThinkingBudgetSlider from "./ThinkingBudgetSlider" import { useEvent, useInterval } from "react-use" import styled from "styled-components" import * as vscodemodels from "vscode" @@ -1201,10 +1200,6 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is {selectedProvider === "xai" && createDropdown(xaiModels)} - {selectedProvider === "anthropic" && selectedModelId === "claude-3-7-sonnet-20250219" && ( - - )} - {