Add thinking budget slider to OpenRouter

This commit is contained in:
Saoud Rizwan 2025-03-01 01:31:16 -08:00
parent a838cf9a61
commit 0959438db8
4 changed files with 42 additions and 9 deletions

View file

@ -47,7 +47,7 @@ export class AnthropicHandler implements ApiHandler {
max_tokens: model.info.maxTokens || 8192,
// "Thinking isnt 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: reasoningOn ? undefined : 0,
system: [
{
text: systemPrompt,

View file

@ -40,6 +40,7 @@ export class OpenRouterHandler implements ApiHandler {
switch (model.id) {
case "anthropic/claude-3.7-sonnet":
case "anthropic/claude-3.7-sonnet:beta":
case "anthropic/claude-3.7-sonnet:thinking":
case "anthropic/claude-3-7-sonnet":
case "anthropic/claude-3-7-sonnet:beta":
case "anthropic/claude-3.5-sonnet":
@ -95,6 +96,7 @@ export class OpenRouterHandler implements ApiHandler {
switch (model.id) {
case "anthropic/claude-3.7-sonnet":
case "anthropic/claude-3.7-sonnet:beta":
case "anthropic/claude-3.7-sonnet:thinking":
case "anthropic/claude-3-7-sonnet":
case "anthropic/claude-3-7-sonnet:beta":
case "anthropic/claude-3.5-sonnet":
@ -109,7 +111,7 @@ export class OpenRouterHandler implements ApiHandler {
break
}
let temperature = 0
let temperature: number | undefined = 0
let topP: number | undefined = undefined
if (this.getModel().id.startsWith("deepseek/deepseek-r1") || this.getModel().id === "perplexity/sonar-reasoning") {
// Recommended values from DeepSeek
@ -118,6 +120,22 @@ export class OpenRouterHandler implements ApiHandler {
openAiMessages = convertToR1Format([{ role: "user", content: systemPrompt }, ...messages])
}
let reasoning: { max_tokens: number } | undefined = undefined
switch (model.id) {
case "anthropic/claude-3.7-sonnet":
case "anthropic/claude-3.7-sonnet:beta":
case "anthropic/claude-3.7-sonnet:thinking":
case "anthropic/claude-3-7-sonnet":
case "anthropic/claude-3-7-sonnet:beta":
let budget_tokens = this.options.thinkingBudgetTokens || 0
const reasoningOn = budget_tokens !== 0 ? true : false
if (reasoningOn) {
temperature = undefined // extended thinking does not support non-1 temperature
reasoning = { max_tokens: budget_tokens }
}
break
}
// Removes messages in the middle when close to context window limit. Should not be applied to models that support prompt caching since it would continuously break the cache.
let shouldApplyMiddleOutTransform = !model.info.supportsPromptCache
// except for deepseek (which we set supportsPromptCache to true for), where because the context window is so small our truncation algo might miss and we should use openrouter's middle-out transform as a fallback to ensure we don't exceed the context window (FIXME: once we have a more robust token estimator we should not rely on this)
@ -136,6 +154,7 @@ export class OpenRouterHandler implements ApiHandler {
transforms: shouldApplyMiddleOutTransform ? ["middle-out"] : undefined,
include_reasoning: true,
...(model.id === "openai/o3-mini" ? { reasoning_effort: this.options.o3MiniReasoningEffort || "medium" } : {}),
...(reasoning ? { reasoning } : {}),
})
let genId: string | undefined

View file

@ -1579,6 +1579,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
case "anthropic/claude-3-7-sonnet:beta":
case "anthropic/claude-3.7-sonnet":
case "anthropic/claude-3.7-sonnet:beta":
case "anthropic/claude-3.7-sonnet:thinking":
case "anthropic/claude-3.5-sonnet":
case "anthropic/claude-3.5-sonnet:beta":
// NOTE: this needs to be synced with api.ts/openrouter default model info

View file

@ -10,6 +10,7 @@ import { vscode } from "../../utils/vscode"
import { highlight } from "../history/HistoryView"
import { ModelInfoView, normalizeApiConfiguration } from "./ApiOptions"
import { CODE_BLOCK_BG_COLOR } from "../common/CodeBlock"
import ThinkingBudgetSlider from "./ThinkingBudgetSlider"
export interface OpenRouterModelPickerProps {
isPopup?: boolean
@ -135,6 +136,13 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup }
}
}, [selectedIndex])
const showBudgetSlider = useMemo(() => {
return (
selectedModelId?.toLowerCase().includes("claude-3-7-sonnet") ||
selectedModelId?.toLowerCase().includes("claude-3.7-sonnet")
)
}, [selectedModelId])
return (
<div style={{ width: "100%" }}>
<style>
@ -206,13 +214,18 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = ({ isPopup }
</div>
{hasInfo ? (
<ModelInfoView
selectedModelId={selectedModelId}
modelInfo={selectedModelInfo}
isDescriptionExpanded={isDescriptionExpanded}
setIsDescriptionExpanded={setIsDescriptionExpanded}
isPopup={isPopup}
/>
<>
{showBudgetSlider && (
<ThinkingBudgetSlider apiConfiguration={apiConfiguration} setApiConfiguration={setApiConfiguration} />
)}
<ModelInfoView
selectedModelId={selectedModelId}
modelInfo={selectedModelInfo}
isDescriptionExpanded={isDescriptionExpanded}
setIsDescriptionExpanded={setIsDescriptionExpanded}
isPopup={isPopup}
/>
</>
) : (
<p
style={{