Skip to content

Commit 3b8c801

Browse files
committed
fix: delete topK, topP and maxOutputTokens from Gemini
1 parent 847756c commit 3b8c801

File tree

6 files changed

+97
-192
lines changed

6 files changed

+97
-192
lines changed

packages/types/src/provider-settings.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,6 @@ const lmStudioSchema = baseProviderSettingsSchema.extend({
164164
const geminiSchema = apiModelIdProviderModelSchema.extend({
165165
geminiApiKey: z.string().optional(),
166166
googleGeminiBaseUrl: z.string().optional(),
167-
topP: z.number().optional(),
168-
topK: z.number().optional(),
169-
maxOutputTokens: z.number().optional(),
170167
enableUrlContext: z.boolean().optional(),
171168
enableGrounding: z.boolean().optional(),
172169
})

src/api/providers/__tests__/gemini-handler.spec.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@ import { GeminiHandler } from "../gemini"
33
import type { ApiHandlerOptions } from "../../../shared/api"
44

55
describe("GeminiHandler backend support", () => {
6-
it("passes maxOutputTokens, topP, topK, and tools for URL context and grounding in config", async () => {
6+
it("passes tools for URL context and grounding in config", async () => {
77
const options = {
88
apiProvider: "gemini",
9-
maxOutputTokens: 5,
10-
topP: 0.5,
11-
topK: 10,
129
enableUrlContext: true,
1310
enableGrounding: true,
1411
} as ApiHandlerOptions
@@ -18,18 +15,12 @@ describe("GeminiHandler backend support", () => {
1815
handler["client"].models.generateContentStream = stub
1916
await handler.createMessage("instr", [] as any).next()
2017
const config = stub.mock.calls[0][0].config
21-
expect(config.maxOutputTokens).toBe(5)
22-
expect(config.topP).toBe(0.5)
23-
expect(config.topK).toBe(10)
2418
expect(config.tools).toEqual([{ urlContext: {} }, { googleSearch: {} }])
2519
})
2620

2721
it("completePrompt passes config overrides without tools when URL context and grounding disabled", async () => {
2822
const options = {
2923
apiProvider: "gemini",
30-
maxOutputTokens: 7,
31-
topP: 0.7,
32-
topK: 3,
3324
enableUrlContext: false,
3425
enableGrounding: false,
3526
} as ApiHandlerOptions
@@ -39,15 +30,6 @@ describe("GeminiHandler backend support", () => {
3930
handler["client"].models.generateContent = stub
4031
const res = await handler.completePrompt("hi")
4132
expect(res).toBe("ok")
42-
expect(stub).toHaveBeenCalledWith(
43-
expect.objectContaining({
44-
config: expect.objectContaining({
45-
maxOutputTokens: 7,
46-
topP: 0.7,
47-
topK: 3,
48-
}),
49-
}),
50-
)
5133
const promptConfig = stub.mock.calls[0][0].config
5234
expect(promptConfig.tools).toBeUndefined()
5335
})

src/api/providers/gemini.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
7979
systemInstruction,
8080
httpOptions: this.options.googleGeminiBaseUrl ? { baseUrl: this.options.googleGeminiBaseUrl } : undefined,
8181
thinkingConfig,
82-
maxOutputTokens: this.options.maxOutputTokens ?? this.options.modelMaxTokens ?? maxTokens ?? undefined,
8382
temperature: this.options.modelTemperature ?? 0,
84-
topP: this.options.topP,
85-
topK: this.options.topK,
8683
...(tools.length > 0 ? { tools } : {}),
8784
}
8885
const config = rawConfig as unknown as GenerateContentConfig
@@ -215,9 +212,6 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
215212
? { baseUrl: this.options.googleGeminiBaseUrl }
216213
: undefined,
217214
temperature: this.options.modelTemperature ?? 0,
218-
maxOutputTokens: this.options.maxOutputTokens ?? this.options.modelMaxTokens,
219-
topP: this.options.topP,
220-
topK: this.options.topK,
221215
...(tools.length > 0 ? { tools } : {}),
222216
}
223217
const promptConfig = rawPromptConfig as unknown as GenerateContentConfig

webview-ui/src/components/settings/providers/Gemini.tsx

Lines changed: 2 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
import { useCallback, useState, useMemo } from "react"
1+
import { useCallback, useState } from "react"
22
import { Checkbox } from "vscrui"
33
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
4-
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@src/components/ui/collapsible"
5-
import { Slider } from "@src/components/ui"
6-
import { ChevronRight } from "lucide-react"
74

85
import type { ProviderSettings } from "@roo-code/types"
9-
import { geminiModels, geminiDefaultModelId, type GeminiModelId } from "@roo-code/types"
106

117
import { useAppTranslation } from "@src/i18n/TranslationContext"
128
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
@@ -19,20 +15,12 @@ type GeminiProps = {
1915
currentModelId?: string
2016
}
2117

22-
export const Gemini = ({ apiConfiguration, setApiConfigurationField, currentModelId }: GeminiProps) => {
18+
export const Gemini = ({ apiConfiguration, setApiConfigurationField }: GeminiProps) => {
2319
const { t } = useAppTranslation()
2420

2521
const [googleGeminiBaseUrlSelected, setGoogleGeminiBaseUrlSelected] = useState(
2622
!!apiConfiguration?.googleGeminiBaseUrl,
2723
)
28-
const [isModelParametersOpen, setIsModelParametersOpen] = useState(false)
29-
30-
const modelInfo = useMemo(() => {
31-
const modelId = (
32-
currentModelId && currentModelId in geminiModels ? currentModelId : geminiDefaultModelId
33-
) as GeminiModelId
34-
return geminiModels[modelId]
35-
}, [currentModelId])
3624

3725
const handleInputChange = useCallback(
3826
<K extends keyof ProviderSettings, E>(
@@ -106,110 +94,6 @@ export const Gemini = ({ apiConfiguration, setApiConfigurationField, currentMode
10694
<div className="text-sm text-vscode-descriptionForeground mb-3">
10795
{t("settings:providers.geminiParameters.groundingSearch.description")}
10896
</div>
109-
110-
<div className="mb-2">
111-
<Collapsible onOpenChange={setIsModelParametersOpen}>
112-
<CollapsibleTrigger className="w-full text-left">
113-
<div className="flex items-center justify-between">
114-
<div className="flex flex-col">
115-
<h3 className="font-semibold text-base">
116-
{t("settings:providers.geminiSections.modelParameters.title")}
117-
</h3>
118-
<p className="text-sm text-vscode-descriptionForeground -mt-3">
119-
{t("settings:providers.geminiSections.modelParameters.description")}
120-
</p>
121-
</div>
122-
<ChevronRight
123-
className={`transform transition-transform duration-200 mr-2 ${
124-
isModelParametersOpen ? "rotate-90" : ""
125-
}`}
126-
size={20}
127-
/>
128-
</div>
129-
</CollapsibleTrigger>
130-
<CollapsibleContent>
131-
<div className="mt-4">
132-
<label className="block font-medium mb-1">
133-
{t("settings:providers.geminiParameters.topP.title")}
134-
</label>
135-
<div className="flex items-center space-x-2">
136-
<Slider
137-
data-testid="slider-top-p"
138-
min={0}
139-
max={1}
140-
step={0.01}
141-
value={[apiConfiguration.topP ?? 0.95]}
142-
onValueChange={(values: number[]) =>
143-
setApiConfigurationField("topP", values[0])
144-
}
145-
className="flex-grow"
146-
/>
147-
<span className="w-10 text-right">
148-
{(apiConfiguration.topP ?? 0.95).toFixed(2)}
149-
</span>
150-
</div>
151-
<div className="text-sm text-vscode-descriptionForeground">
152-
{t("settings:providers.geminiParameters.topP.description")}
153-
</div>
154-
</div>
155-
156-
<div className="mt-4">
157-
<label className="block font-medium mb-1">
158-
{t("settings:providers.geminiParameters.topK.title")}
159-
</label>
160-
<div className="flex items-center space-x-2">
161-
<Slider
162-
data-testid="slider-top-k"
163-
min={0}
164-
max={100}
165-
step={1}
166-
value={[apiConfiguration.topK ?? 64]}
167-
onValueChange={(values: number[]) =>
168-
setApiConfigurationField("topK", values[0])
169-
}
170-
className="flex-grow"
171-
/>
172-
<span className="w-10 text-right">{apiConfiguration.topK ?? 64}</span>
173-
</div>
174-
<div className="text-sm text-vscode-descriptionForeground">
175-
{t("settings:providers.geminiParameters.topK.description")}
176-
</div>
177-
</div>
178-
179-
<div className="mt-4">
180-
<label className="block font-medium mb-1">
181-
{t("settings:providers.geminiParameters.maxOutputTokens.title")}
182-
</label>
183-
<div className="flex items-center space-x-2">
184-
<Slider
185-
data-testid="slider-max-output-tokens"
186-
min={3000}
187-
max={modelInfo.maxTokens}
188-
step={1}
189-
value={[apiConfiguration.maxOutputTokens ?? modelInfo.maxTokens]}
190-
onValueChange={(values: number[]) =>
191-
setApiConfigurationField("maxOutputTokens", values[0])
192-
}
193-
className="flex-grow"
194-
/>
195-
<VSCodeTextField
196-
value={(apiConfiguration.maxOutputTokens ?? modelInfo.maxTokens).toString()}
197-
type="text"
198-
inputMode="numeric"
199-
onInput={handleInputChange("maxOutputTokens", (e) => {
200-
const val = parseInt((e as any).target.value, 10)
201-
return Number.isNaN(val) ? 0 : Math.min(val, modelInfo.maxTokens)
202-
})}
203-
className="w-16"
204-
/>
205-
</div>
206-
<div className="text-sm text-vscode-descriptionForeground">
207-
{t("settings:providers.geminiParameters.maxOutputTokens.description")}_{" "}
208-
</div>
209-
</div>
210-
</CollapsibleContent>
211-
</Collapsible>
212-
</div>
21397
</div>
21498
</>
21599
)

webview-ui/src/components/settings/providers/__tests__/Gemini.spec.tsx

Lines changed: 94 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,6 @@ vi.mock("vscrui", () => ({
2121
),
2222
}))
2323

24-
vi.mock("@src/components/ui", () => ({
25-
Slider: ({ min, max, step, value, onValueChange, "data-testid": testId, _ }: any) => (
26-
<input
27-
data-testid={testId}
28-
type="range"
29-
min={min}
30-
max={max}
31-
step={step}
32-
value={value[0]}
33-
onChange={(e) => onValueChange([Number(e.target.value)])}
34-
/>
35-
),
36-
}))
37-
3824
vi.mock("@src/i18n/TranslationContext", () => ({
3925
useAppTranslation: () => ({ t: (key: string) => key }),
4026
}))
@@ -43,22 +29,102 @@ vi.mock("@src/components/common/VSCodeButtonLink", () => ({
4329
VSCodeButtonLink: ({ children, href }: any) => <a href={href}>{children}</a>,
4430
}))
4531

46-
describe("Gemini provider settings", () => {
47-
it("renders sliders for topP, topK and maxOutputTokens after expanding", async () => {
48-
const user = userEvent.setup()
49-
const setApiField = vi.fn()
50-
const config: ProviderSettings = {}
51-
render(<Gemini apiConfiguration={config} setApiConfigurationField={setApiField} />)
32+
describe("Gemini", () => {
33+
const defaultApiConfiguration: ProviderSettings = {
34+
geminiApiKey: "",
35+
enableUrlContext: false,
36+
enableGrounding: false,
37+
}
38+
39+
const mockSetApiConfigurationField = vi.fn()
40+
41+
beforeEach(() => {
42+
vi.clearAllMocks()
43+
})
44+
45+
describe("URL Context Checkbox", () => {
46+
it("should render URL context checkbox unchecked by default", () => {
47+
render(
48+
<Gemini
49+
apiConfiguration={defaultApiConfiguration}
50+
setApiConfigurationField={mockSetApiConfigurationField}
51+
/>,
52+
)
53+
54+
const urlContextCheckbox = screen.getByTestId("checkbox-url-context")
55+
const checkbox = urlContextCheckbox.querySelector("input[type='checkbox']") as HTMLInputElement
56+
expect(checkbox.checked).toBe(false)
57+
})
58+
59+
it("should render URL context checkbox checked when enableUrlContext is true", () => {
60+
const apiConfiguration = { ...defaultApiConfiguration, enableUrlContext: true }
61+
render(
62+
<Gemini apiConfiguration={apiConfiguration} setApiConfigurationField={mockSetApiConfigurationField} />,
63+
)
64+
65+
const urlContextCheckbox = screen.getByTestId("checkbox-url-context")
66+
const checkbox = urlContextCheckbox.querySelector("input[type='checkbox']") as HTMLInputElement
67+
expect(checkbox.checked).toBe(true)
68+
})
69+
70+
it("should call setApiConfigurationField with correct parameters when URL context checkbox is toggled", async () => {
71+
const user = userEvent.setup()
72+
render(
73+
<Gemini
74+
apiConfiguration={defaultApiConfiguration}
75+
setApiConfigurationField={mockSetApiConfigurationField}
76+
/>,
77+
)
78+
79+
const urlContextCheckbox = screen.getByTestId("checkbox-url-context")
80+
const checkbox = urlContextCheckbox.querySelector("input[type='checkbox']") as HTMLInputElement
81+
82+
await user.click(checkbox)
83+
84+
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("enableUrlContext", true)
85+
})
86+
})
87+
88+
describe("Grounding with Google Search Checkbox", () => {
89+
it("should render grounding search checkbox unchecked by default", () => {
90+
render(
91+
<Gemini
92+
apiConfiguration={defaultApiConfiguration}
93+
setApiConfigurationField={mockSetApiConfigurationField}
94+
/>,
95+
)
96+
97+
const groundingCheckbox = screen.getByTestId("checkbox-grounding-search")
98+
const checkbox = groundingCheckbox.querySelector("input[type='checkbox']") as HTMLInputElement
99+
expect(checkbox.checked).toBe(false)
100+
})
101+
102+
it("should render grounding search checkbox checked when enableGrounding is true", () => {
103+
const apiConfiguration = { ...defaultApiConfiguration, enableGrounding: true }
104+
render(
105+
<Gemini apiConfiguration={apiConfiguration} setApiConfigurationField={mockSetApiConfigurationField} />,
106+
)
107+
108+
const groundingCheckbox = screen.getByTestId("checkbox-grounding-search")
109+
const checkbox = groundingCheckbox.querySelector("input[type='checkbox']") as HTMLInputElement
110+
expect(checkbox.checked).toBe(true)
111+
})
112+
113+
it("should call setApiConfigurationField with correct parameters when grounding search checkbox is toggled", async () => {
114+
const user = userEvent.setup()
115+
render(
116+
<Gemini
117+
apiConfiguration={defaultApiConfiguration}
118+
setApiConfigurationField={mockSetApiConfigurationField}
119+
/>,
120+
)
52121

53-
expect(screen.queryByTestId("slider-top-p")).not.toBeInTheDocument()
54-
expect(screen.queryByTestId("slider-top-k")).not.toBeInTheDocument()
55-
expect(screen.queryByTestId("slider-max-output-tokens")).not.toBeInTheDocument()
122+
const groundingCheckbox = screen.getByTestId("checkbox-grounding-search")
123+
const checkbox = groundingCheckbox.querySelector("input[type='checkbox']") as HTMLInputElement
56124

57-
const trigger = screen.getByText("settings:providers.geminiSections.modelParameters.title")
58-
await user.click(trigger)
125+
await user.click(checkbox)
59126

60-
expect(screen.getByTestId("slider-top-p")).toBeInTheDocument()
61-
expect(screen.getByTestId("slider-top-k")).toBeInTheDocument()
62-
expect(screen.getByTestId("slider-max-output-tokens")).toBeInTheDocument()
127+
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("enableGrounding", true)
128+
})
63129
})
64130
})

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -283,25 +283,7 @@
283283
"cacheUsageNote": "Note: If you don't see cache usage, try selecting a different model and then selecting your desired model again.",
284284
"vscodeLmModel": "Language Model",
285285
"vscodeLmWarning": "Note: This is a very experimental integration and provider support will vary. If you get an error about a model not being supported, that's an issue on the provider's end.",
286-
"geminiSections": {
287-
"modelParameters": {
288-
"title": "Output Controls",
289-
"description": "Fine-tune topP, topK and maxOutputTokens"
290-
}
291-
},
292286
"geminiParameters": {
293-
"topK": {
294-
"title": "Top K",
295-
"description": "A low value makes the text more predictable, while a high value makes it more creative."
296-
},
297-
"topP": {
298-
"title": "Top P",
299-
"description": "A low value leads to more focused text, while a high value results in more diverse outcomes."
300-
},
301-
"maxOutputTokens": {
302-
"title": "Max Output Tokens",
303-
"description": "This parameter sets the maximum length of the response the model is allowed to generate."
304-
},
305287
"urlContext": {
306288
"title": "Enable URL Context",
307289
"description": "Lets Gemini read linked pages to extract, compare, and synthesize their content into informed responses."

0 commit comments

Comments
 (0)