Skip to content

Commit e56908f

Browse files
committed
Thinking settings tweaks
1 parent 06f98ca commit e56908f

File tree

4 files changed

+51
-48
lines changed

4 files changed

+51
-48
lines changed

src/api/providers/anthropic.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import { ApiStream } from "../transform/stream"
1414

1515
const ANTHROPIC_DEFAULT_TEMPERATURE = 0
1616

17-
const THINKING_MODELS = ["claude-3-7-sonnet-20250219"]
18-
1917
export class AnthropicHandler implements ApiHandler, SingleCompletionHandler {
2018
private options: ApiHandlerOptions
2119
private client: Anthropic
@@ -32,16 +30,19 @@ export class AnthropicHandler implements ApiHandler, SingleCompletionHandler {
3230
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
3331
let stream: AnthropicStream<Anthropic.Messages.RawMessageStreamEvent>
3432
const cacheControl: CacheControlEphemeral = { type: "ephemeral" }
35-
const modelId = this.getModel().id
36-
const maxTokens = this.getModel().info.maxTokens || 8192
33+
let { id: modelId, info: modelInfo } = this.getModel()
34+
const maxTokens = modelInfo.maxTokens || 8192
35+
const budgetTokens = this.options.anthropicThinking ?? Math.min(maxTokens - 1, 8192)
3736
let temperature = this.options.modelTemperature ?? ANTHROPIC_DEFAULT_TEMPERATURE
3837
let thinking: BetaThinkingConfigParam | undefined = undefined
3938

40-
if (THINKING_MODELS.includes(modelId)) {
41-
thinking = this.options.anthropicThinking
42-
? { type: "enabled", budget_tokens: this.options.anthropicThinking }
43-
: { type: "disabled" }
44-
39+
// Anthropic "Thinking" models require a temperature of 1.0.
40+
if (modelId === "claude-3-7-sonnet-20250219:thinking") {
41+
// The `:thinking` variant is a virtual identifier for the
42+
// `claude-3-7-sonnet-20250219` model with a thinking budget.
43+
// We can handle this more elegantly in the future.
44+
modelId = "claude-3-7-sonnet-20250219"
45+
thinking = { type: "enabled", budget_tokens: budgetTokens }
4546
temperature = 1.0
4647
}
4748

@@ -114,8 +115,8 @@ export class AnthropicHandler implements ApiHandler, SingleCompletionHandler {
114115
default: {
115116
stream = (await this.client.messages.create({
116117
model: modelId,
117-
max_tokens: this.getModel().info.maxTokens || 8192,
118-
temperature: this.options.modelTemperature ?? ANTHROPIC_DEFAULT_TEMPERATURE,
118+
max_tokens: maxTokens,
119+
temperature,
119120
system: [{ text: systemPrompt, type: "text" }],
120121
messages,
121122
// tools,

src/api/providers/openrouter.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Anthropic } from "@anthropic-ai/sdk"
2+
import { BetaThinkingConfigParam } from "@anthropic-ai/sdk/resources/beta"
23
import axios from "axios"
34
import OpenAI from "openai"
45
import delay from "delay"
@@ -17,6 +18,7 @@ const OPENROUTER_DEFAULT_TEMPERATURE = 0
1718
type OpenRouterChatCompletionParams = OpenAI.Chat.ChatCompletionCreateParams & {
1819
transforms?: string[]
1920
include_reasoning?: boolean
21+
thinking?: BetaThinkingConfigParam
2022
}
2123

2224
// Add custom interface for OpenRouter usage chunk.
@@ -57,7 +59,7 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler {
5759
// prompt caching: https://openrouter.ai/docs/prompt-caching
5860
// this is specifically for claude models (some models may 'support prompt caching' automatically without this)
5961
switch (true) {
60-
case this.getModel().id.startsWith("anthropic/"):
62+
case modelId.startsWith("anthropic/"):
6163
openAiMessages[0] = {
6264
role: "system",
6365
content: [
@@ -108,8 +110,13 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler {
108110

109111
let temperature = this.options.modelTemperature ?? defaultTemperature
110112

113+
const maxTokens = modelInfo.maxTokens
114+
const budgetTokens = this.options.anthropicThinking ?? Math.min((maxTokens ?? 8192) - 1, 8192)
115+
let thinking: BetaThinkingConfigParam | undefined = undefined
116+
111117
// Anthropic "Thinking" models require a temperature of 1.0.
112118
if (modelInfo.thinking) {
119+
thinking = { type: "enabled", budget_tokens: budgetTokens }
113120
temperature = 1.0
114121
}
115122

@@ -118,8 +125,9 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler {
118125

119126
const completionParams: OpenRouterChatCompletionParams = {
120127
model: modelId,
121-
max_tokens: modelInfo.maxTokens,
128+
max_tokens: maxTokens,
122129
temperature,
130+
thinking, // OpenRouter is temporarily supporting this.
123131
top_p: topP,
124132
messages: openAiMessages,
125133
stream: true,

src/shared/api.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export const THINKING_BUDGET = {
103103
export type AnthropicModelId = keyof typeof anthropicModels
104104
export const anthropicDefaultModelId: AnthropicModelId = "claude-3-7-sonnet-20250219"
105105
export const anthropicModels = {
106-
"claude-3-7-sonnet-20250219": {
106+
"claude-3-7-sonnet-20250219:thinking": {
107107
maxTokens: 16384,
108108
contextWindow: 200_000,
109109
supportsImages: true,
@@ -115,6 +115,18 @@ export const anthropicModels = {
115115
cacheReadsPrice: 0.3, // $0.30 per million tokens
116116
thinking: true,
117117
},
118+
"claude-3-7-sonnet-20250219": {
119+
maxTokens: 16384,
120+
contextWindow: 200_000,
121+
supportsImages: true,
122+
supportsComputerUse: true,
123+
supportsPromptCache: true,
124+
inputPrice: 3.0, // $3 per million input tokens
125+
outputPrice: 15.0, // $15 per million output tokens
126+
cacheWritesPrice: 3.75, // $3.75 per million tokens
127+
cacheReadsPrice: 0.3, // $0.30 per million tokens
128+
thinking: false,
129+
},
118130
"claude-3-5-sonnet-20241022": {
119131
maxTokens: 8192,
120132
contextWindow: 200_000,

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const ApiOptions = ({
7373
const [openRouterBaseUrlSelected, setOpenRouterBaseUrlSelected] = useState(!!apiConfiguration?.openRouterBaseUrl)
7474
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
7575

76-
const anthropicThinkingBudget = apiConfiguration?.anthropicThinking
76+
const anthropicThinkingBudget = apiConfiguration?.anthropicThinking ?? THINKING_BUDGET.default
7777

7878
const noTransform = <T,>(value: T) => value
7979
const inputEventTransform = <E,>(event: E) => (event as { target: HTMLInputElement })?.target?.value as any
@@ -1272,39 +1272,21 @@ const ApiOptions = ({
12721272
)}
12731273

12741274
{selectedModelInfo && selectedModelInfo.thinking && (
1275-
<div className="flex flex-col gap-2 mt-2">
1276-
<Checkbox
1277-
checked={!!anthropicThinkingBudget}
1278-
onChange={(checked) =>
1279-
setApiConfigurationField(
1280-
"anthropicThinking",
1281-
checked
1282-
? Math.min(
1283-
THINKING_BUDGET.default,
1284-
selectedModelInfo.maxTokens ?? THINKING_BUDGET.default,
1285-
)
1286-
: undefined,
1287-
)
1288-
}>
1289-
Thinking?
1290-
</Checkbox>
1291-
{anthropicThinkingBudget && (
1292-
<>
1293-
<div className="text-muted-foreground text-sm">
1294-
Number of tokens Claude is allowed to use for its internal reasoning process.
1295-
</div>
1296-
<div className="flex items-center gap-2">
1297-
<Slider
1298-
min={THINKING_BUDGET.min}
1299-
max={(selectedModelInfo.maxTokens ?? THINKING_BUDGET.default) - 1}
1300-
step={THINKING_BUDGET.step}
1301-
value={[anthropicThinkingBudget]}
1302-
onValueChange={(value) => setApiConfigurationField("anthropicThinking", value[0])}
1303-
/>
1304-
<div className="w-12">{anthropicThinkingBudget}</div>
1305-
</div>
1306-
</>
1307-
)}
1275+
<div className="flex flex-col gap-1 mt-2">
1276+
<div className="font-medium">Thinking Budget</div>
1277+
<div className="flex items-center gap-1">
1278+
<Slider
1279+
min={THINKING_BUDGET.min}
1280+
max={(selectedModelInfo.maxTokens ?? THINKING_BUDGET.default) - 1}
1281+
step={THINKING_BUDGET.step}
1282+
value={[anthropicThinkingBudget]}
1283+
onValueChange={(value) => setApiConfigurationField("anthropicThinking", value[0])}
1284+
/>
1285+
<div className="w-12 text-sm text-center">{anthropicThinkingBudget}</div>
1286+
</div>
1287+
<div className="text-muted-foreground text-sm">
1288+
Number of tokens Claude is allowed to use for its internal reasoning process.
1289+
</div>
13081290
</div>
13091291
)}
13101292

0 commit comments

Comments
 (0)