From 32dfe1b6b012e40be77aaf34243088354d6a63da Mon Sep 17 00:00:00 2001 From: Robin1987China <41602358+Robin1987China@users.noreply.github.com> Date: Mon, 22 Jun 2026 16:55:39 +0800 Subject: [PATCH] fix(llm): forward frequencyPenalty, presencePenalty, seed to Gemini GenerationOptions defines frequencyPenalty, presencePenalty, and seed as user-settable generation parameters, and the OpenAI-chat protocol forwards all three. The Gemini protocol dropped them: GeminiGenerationConfig only declared maxOutputTokens/temperature/topP/topK/stopSequences/thinkingConfig and the request builder forwarded only those. Gemini's generateContent generationConfig supports all three, so values a user sets were honored on OpenAI but silently ignored on Gemini. Add the three fields to the schema and forward them, gated by the existing all-undefined guard so unset requests are unchanged. Closes #33325 --- packages/llm/src/protocols/gemini.ts | 6 ++++++ packages/llm/test/provider/gemini.test.ts | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/llm/src/protocols/gemini.ts b/packages/llm/src/protocols/gemini.ts index c8fa34b50965..53dd84ae8d39 100644 --- a/packages/llm/src/protocols/gemini.ts +++ b/packages/llm/src/protocols/gemini.ts @@ -99,6 +99,9 @@ const GeminiGenerationConfig = Schema.Struct({ temperature: Schema.optional(Schema.Number), topP: Schema.optional(Schema.Number), topK: Schema.optional(Schema.Number), + frequencyPenalty: Schema.optional(Schema.Number), + presencePenalty: Schema.optional(Schema.Number), + seed: Schema.optional(Schema.Number), stopSequences: optionalArray(Schema.String), thinkingConfig: Schema.optional(GeminiThinkingConfig), }) @@ -305,6 +308,9 @@ const fromRequest = Effect.fn("Gemini.fromRequest")(function* (request: LLMReque temperature: generation?.temperature, topP: generation?.topP, topK: generation?.topK, + frequencyPenalty: generation?.frequencyPenalty, + presencePenalty: generation?.presencePenalty, + seed: generation?.seed, stopSequences: generation?.stop, thinkingConfig: thinkingConfig(request), } diff --git a/packages/llm/test/provider/gemini.test.ts b/packages/llm/test/provider/gemini.test.ts index d30742c47d35..a7e52c503cab 100644 --- a/packages/llm/test/provider/gemini.test.ts +++ b/packages/llm/test/provider/gemini.test.ts @@ -36,6 +36,24 @@ describe("Gemini route", () => { }), ) + it.effect("forwards frequencyPenalty, presencePenalty, and seed to generationConfig", () => + Effect.gen(function* () { + const prepared = yield* LLMClient.prepare( + LLM.request({ + model, + prompt: "Say hello.", + generation: { frequencyPenalty: 0.5, presencePenalty: 0.25, seed: 7 }, + }), + ) + + expect(prepared.body.generationConfig).toMatchObject({ + frequencyPenalty: 0.5, + presencePenalty: 0.25, + seed: 7, + }) + }), + ) + it.effect("lowers chronological system updates to wrapped user text in order", () => Effect.gen(function* () { const prepared = yield* LLMClient.prepare(