Merge pull request #1200 from RooVetGit/cte/thinking-tweaks

Thinking settings tweaks
This commit is contained in:
Chris Estreich 2025-02-25 16:31:06 -08:00 committed by GitHub
commit ebe294bec1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 54 additions and 48 deletions

View file

@ -0,0 +1,5 @@
---
"roo-cline": patch
---
Pass "thinking" params to OpenRouter

View file

@ -14,8 +14,6 @@ import { ApiStream } from "../transform/stream"
const ANTHROPIC_DEFAULT_TEMPERATURE = 0
const THINKING_MODELS = ["claude-3-7-sonnet-20250219"]
export class AnthropicHandler implements ApiHandler, SingleCompletionHandler {
private options: ApiHandlerOptions
private client: Anthropic
@ -32,16 +30,19 @@ export class AnthropicHandler implements ApiHandler, SingleCompletionHandler {
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
let stream: AnthropicStream<Anthropic.Messages.RawMessageStreamEvent>
const cacheControl: CacheControlEphemeral = { type: "ephemeral" }
const modelId = this.getModel().id
const maxTokens = this.getModel().info.maxTokens || 8192
let { id: modelId, info: modelInfo } = this.getModel()
const maxTokens = modelInfo.maxTokens || 8192
let temperature = this.options.modelTemperature ?? ANTHROPIC_DEFAULT_TEMPERATURE
let thinking: BetaThinkingConfigParam | undefined = undefined
if (THINKING_MODELS.includes(modelId)) {
thinking = this.options.anthropicThinking
? { type: "enabled", budget_tokens: this.options.anthropicThinking }
: { type: "disabled" }
// Anthropic "Thinking" models require a temperature of 1.0.
if (modelId === "claude-3-7-sonnet-20250219:thinking") {
// The `:thinking` variant is a virtual identifier for the
// `claude-3-7-sonnet-20250219` model with a thinking budget.
// We can handle this more elegantly in the future.
modelId = "claude-3-7-sonnet-20250219"
const budgetTokens = this.options.anthropicThinking ?? Math.max(maxTokens * 0.8, 1024)
thinking = { type: "enabled", budget_tokens: budgetTokens }
temperature = 1.0
}
@ -114,8 +115,8 @@ export class AnthropicHandler implements ApiHandler, SingleCompletionHandler {
default: {
stream = (await this.client.messages.create({
model: modelId,
max_tokens: this.getModel().info.maxTokens || 8192,
temperature: this.options.modelTemperature ?? ANTHROPIC_DEFAULT_TEMPERATURE,
max_tokens: maxTokens,
temperature,
system: [{ text: systemPrompt, type: "text" }],
messages,
// tools,

View file

@ -1,4 +1,5 @@
import { Anthropic } from "@anthropic-ai/sdk"
import { BetaThinkingConfigParam } from "@anthropic-ai/sdk/resources/beta"
import axios from "axios"
import OpenAI from "openai"
import delay from "delay"
@ -17,6 +18,7 @@ const OPENROUTER_DEFAULT_TEMPERATURE = 0
type OpenRouterChatCompletionParams = OpenAI.Chat.ChatCompletionCreateParams & {
transforms?: string[]
include_reasoning?: boolean
thinking?: BetaThinkingConfigParam
}
// Add custom interface for OpenRouter usage chunk.
@ -57,7 +59,7 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler {
// prompt caching: https://openrouter.ai/docs/prompt-caching
// this is specifically for claude models (some models may 'support prompt caching' automatically without this)
switch (true) {
case this.getModel().id.startsWith("anthropic/"):
case modelId.startsWith("anthropic/"):
openAiMessages[0] = {
role: "system",
content: [
@ -107,9 +109,12 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler {
}
let temperature = this.options.modelTemperature ?? defaultTemperature
let thinking: BetaThinkingConfigParam | undefined = undefined
// Anthropic "Thinking" models require a temperature of 1.0.
if (modelInfo.thinking) {
const maxTokens = modelInfo.maxTokens || 8192
const budgetTokens = this.options.anthropicThinking ?? Math.max(maxTokens * 0.8, 1024)
thinking = { type: "enabled", budget_tokens: budgetTokens }
temperature = 1.0
}
@ -120,6 +125,7 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler {
model: modelId,
max_tokens: modelInfo.maxTokens,
temperature,
thinking, // OpenRouter is temporarily supporting this.
top_p: topP,
messages: openAiMessages,
stream: true,

View file

@ -103,7 +103,7 @@ export const THINKING_BUDGET = {
export type AnthropicModelId = keyof typeof anthropicModels
export const anthropicDefaultModelId: AnthropicModelId = "claude-3-7-sonnet-20250219"
export const anthropicModels = {
"claude-3-7-sonnet-20250219": {
"claude-3-7-sonnet-20250219:thinking": {
maxTokens: 16384,
contextWindow: 200_000,
supportsImages: true,
@ -115,6 +115,18 @@ export const anthropicModels = {
cacheReadsPrice: 0.3, // $0.30 per million tokens
thinking: true,
},
"claude-3-7-sonnet-20250219": {
maxTokens: 16384,
contextWindow: 200_000,
supportsImages: true,
supportsComputerUse: true,
supportsPromptCache: true,
inputPrice: 3.0, // $3 per million input tokens
outputPrice: 15.0, // $15 per million output tokens
cacheWritesPrice: 3.75, // $3.75 per million tokens
cacheReadsPrice: 0.3, // $0.30 per million tokens
thinking: false,
},
"claude-3-5-sonnet-20241022": {
maxTokens: 8192,
contextWindow: 200_000,

View file

@ -73,7 +73,7 @@ const ApiOptions = ({
const [openRouterBaseUrlSelected, setOpenRouterBaseUrlSelected] = useState(!!apiConfiguration?.openRouterBaseUrl)
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
const anthropicThinkingBudget = apiConfiguration?.anthropicThinking
const anthropicThinkingBudget = apiConfiguration?.anthropicThinking ?? THINKING_BUDGET.default
const noTransform = <T,>(value: T) => value
const inputEventTransform = <E,>(event: E) => (event as { target: HTMLInputElement })?.target?.value as any
@ -1272,39 +1272,21 @@ const ApiOptions = ({
)}
{selectedModelInfo && selectedModelInfo.thinking && (
<div className="flex flex-col gap-2 mt-2">
<Checkbox
checked={!!anthropicThinkingBudget}
onChange={(checked) =>
setApiConfigurationField(
"anthropicThinking",
checked
? Math.min(
THINKING_BUDGET.default,
selectedModelInfo.maxTokens ?? THINKING_BUDGET.default,
)
: undefined,
)
}>
Thinking?
</Checkbox>
{anthropicThinkingBudget && (
<>
<div className="text-muted-foreground text-sm">
Number of tokens Claude is allowed to use for its internal reasoning process.
</div>
<div className="flex items-center gap-2">
<Slider
min={THINKING_BUDGET.min}
max={(selectedModelInfo.maxTokens ?? THINKING_BUDGET.default) - 1}
step={THINKING_BUDGET.step}
value={[anthropicThinkingBudget]}
onValueChange={(value) => setApiConfigurationField("anthropicThinking", value[0])}
/>
<div className="w-12">{anthropicThinkingBudget}</div>
</div>
</>
)}
<div className="flex flex-col gap-1 mt-2">
<div className="font-medium">Thinking Budget</div>
<div className="flex items-center gap-1">
<Slider
min={THINKING_BUDGET.min}
max={(selectedModelInfo.maxTokens ?? THINKING_BUDGET.default) - 1}
step={THINKING_BUDGET.step}
value={[anthropicThinkingBudget]}
onValueChange={(value) => setApiConfigurationField("anthropicThinking", value[0])}
/>
<div className="w-12 text-sm text-center">{anthropicThinkingBudget}</div>
</div>
<div className="text-muted-foreground text-sm">
Number of tokens Claude is allowed to use for its internal reasoning process.
</div>
</div>
)}