-
Notifications
You must be signed in to change notification settings - Fork 3k
Expand file tree
/
Copy pathmodel-params.ts
More file actions
190 lines (168 loc) · 6.2 KB
/
model-params.ts
File metadata and controls
190 lines (168 loc) · 6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import {
type ModelInfo,
type ProviderSettings,
type VerbosityLevel,
type ReasoningEffortExtended,
ANTHROPIC_DEFAULT_MAX_TOKENS,
} from "@roo-code/types"
import {
DEFAULT_HYBRID_REASONING_MODEL_MAX_TOKENS,
DEFAULT_HYBRID_REASONING_MODEL_THINKING_TOKENS,
GEMINI_25_PRO_MIN_THINKING_TOKENS,
shouldUseReasoningBudget,
shouldUseReasoningEffort,
getModelMaxOutputTokens,
} from "../../shared/api"
import {
type AnthropicReasoningParams,
type OpenAiReasoningParams,
type GeminiReasoningParams,
type OpenRouterReasoningParams,
getAnthropicReasoning,
getOpenAiReasoning,
getGeminiReasoning,
getOpenRouterReasoning,
} from "./reasoning"
type Format = "anthropic" | "openai" | "gemini" | "openrouter"
type GetModelParamsOptions<T extends Format> = {
format: T
modelId: string
model: ModelInfo
settings: ProviderSettings
defaultTemperature: number | undefined
}
type BaseModelParams = {
maxTokens: number | undefined
temperature: number | undefined
reasoningEffort: ReasoningEffortExtended | undefined
reasoningBudget: number | undefined
verbosity: VerbosityLevel | undefined
tools?: boolean
}
type AnthropicModelParams = {
format: "anthropic"
reasoning: AnthropicReasoningParams | undefined
} & BaseModelParams
type OpenAiModelParams = {
format: "openai"
reasoning: OpenAiReasoningParams | undefined
} & BaseModelParams
type GeminiModelParams = {
format: "gemini"
reasoning: GeminiReasoningParams | undefined
} & BaseModelParams
type OpenRouterModelParams = {
format: "openrouter"
reasoning: OpenRouterReasoningParams | undefined
} & BaseModelParams
export type ModelParams = AnthropicModelParams | OpenAiModelParams | GeminiModelParams | OpenRouterModelParams
// Function overloads for specific return types
export function getModelParams(options: GetModelParamsOptions<"anthropic">): AnthropicModelParams
export function getModelParams(options: GetModelParamsOptions<"openai">): OpenAiModelParams
export function getModelParams(options: GetModelParamsOptions<"gemini">): GeminiModelParams
export function getModelParams(options: GetModelParamsOptions<"openrouter">): OpenRouterModelParams
export function getModelParams({
format,
modelId,
model,
settings,
defaultTemperature,
}: GetModelParamsOptions<Format>): ModelParams {
const {
modelMaxTokens: customMaxTokens,
modelMaxThinkingTokens: customMaxThinkingTokens,
modelTemperature: customTemperature,
reasoningEffort: customReasoningEffort,
verbosity: customVerbosity,
} = settings
// Use the centralized logic for computing maxTokens
const maxTokens = getModelMaxOutputTokens({
modelId,
model,
settings,
format,
})
let temperature = customTemperature ?? model.defaultTemperature ?? defaultTemperature
let reasoningBudget: ModelParams["reasoningBudget"] = undefined
let reasoningEffort: ModelParams["reasoningEffort"] = undefined
let verbosity: VerbosityLevel | undefined = customVerbosity
if (shouldUseReasoningBudget({ model, settings })) {
// Check if this is a Gemini 2.5 Pro model
const isGemini25Pro = modelId.includes("gemini-2.5-pro")
// If `customMaxThinkingTokens` is not specified use the default.
// For Gemini 2.5 Pro, default to 128 instead of 8192
const defaultThinkingTokens = isGemini25Pro
? GEMINI_25_PRO_MIN_THINKING_TOKENS
: DEFAULT_HYBRID_REASONING_MODEL_THINKING_TOKENS
reasoningBudget = customMaxThinkingTokens ?? defaultThinkingTokens
// Reasoning cannot exceed 80% of the `maxTokens` value.
// maxTokens should always be defined for reasoning budget models, but add a guard just in case
if (maxTokens && reasoningBudget > Math.floor(maxTokens * 0.8)) {
reasoningBudget = Math.floor(maxTokens * 0.8)
}
// Reasoning cannot be less than minimum tokens.
// For Gemini 2.5 Pro models, the minimum is 128 tokens
// For other models, the minimum is 1024 tokens
const minThinkingTokens = isGemini25Pro ? GEMINI_25_PRO_MIN_THINKING_TOKENS : 1024
if (reasoningBudget < minThinkingTokens) {
reasoningBudget = minThinkingTokens
}
// Let's assume that "Hybrid" reasoning models require a temperature of
// 1.0 since Anthropic does.
temperature = 1.0
} else if (shouldUseReasoningEffort({ model, settings })) {
// "Traditional" reasoning models use the `reasoningEffort` parameter.
// Only fallback to model default if user hasn't explicitly set a value.
// If customReasoningEffort is "disable", don't fallback to model default.
const effort =
customReasoningEffort !== undefined
? customReasoningEffort
: (model.reasoningEffort as ReasoningEffortExtended | "disable" | undefined)
// Capability and settings checks are handled by shouldUseReasoningEffort.
// Here we simply propagate the resolved effort into the params, while
// still treating "disable" as an omission.
if (effort && effort !== "disable") {
reasoningEffort = effort as ReasoningEffortExtended
}
}
const params: BaseModelParams = { maxTokens, temperature, reasoningEffort, reasoningBudget, verbosity }
if (format === "anthropic") {
return {
format,
...params,
reasoning: getAnthropicReasoning({ model, reasoningBudget, reasoningEffort, settings }),
}
} else if (format === "openai") {
// Special case for o1 and o3-mini, which don't support temperature.
// TODO: Add a `supportsTemperature` field to the model info.
if (modelId.startsWith("o1") || modelId.startsWith("o3-mini")) {
params.temperature = undefined
}
return {
format,
...params,
reasoning: getOpenAiReasoning({ model, reasoningBudget, reasoningEffort, settings }),
// Whether tools are included is determined by whether the caller provided tool definitions.
}
} else if (format === "gemini") {
return {
format,
...params,
reasoning: getGeminiReasoning({ model, reasoningBudget, reasoningEffort, settings }),
}
} else {
// Special case for o1-pro, which doesn't support temperature.
// Note that OpenRouter's `supported_parameters` field includes
// `temperature`, which is probably a bug.
// TODO: Add a `supportsTemperature` field to the model info and populate
// it appropriately in the OpenRouter fetcher.
if (modelId === "openai/o1-pro") {
params.temperature = undefined
}
return {
format,
...params,
reasoning: getOpenRouterReasoning({ model, reasoningBudget, reasoningEffort, settings }),
}
}
}