Skip to content

Commit cd0cba5

Browse files
DavidAPiercewhhe
authored andcommitted
Transition to flash GA model when experiment flag is present. (google-gemini#27570)
1 parent d6c196b commit cd0cba5

25 files changed

Lines changed: 707 additions & 28 deletions

docs/reference/configuration.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,12 @@ their corresponding top-level category object in your `settings.json` file.
602602
"model": "gemini-3.1-flash-lite"
603603
}
604604
},
605+
"gemini-3.5-flash": {
606+
"extends": "chat-base-3",
607+
"modelConfig": {
608+
"model": "gemini-3.5-flash"
609+
}
610+
},
605611
"gemma-4-31b-it": {
606612
"extends": "chat-base-3",
607613
"modelConfig": {
@@ -626,6 +632,12 @@ their corresponding top-level category object in your `settings.json` file.
626632
"model": "gemini-3-flash-preview"
627633
}
628634
},
635+
"gemini-3.5-flash-base": {
636+
"extends": "base",
637+
"modelConfig": {
638+
"model": "gemini-3.5-flash"
639+
}
640+
},
629641
"classifier": {
630642
"extends": "base",
631643
"modelConfig": {
@@ -868,6 +880,16 @@ their corresponding top-level category object in your `settings.json` file.
868880
"multimodalToolUse": true
869881
}
870882
},
883+
"gemini-3.5-flash": {
884+
"tier": "flash",
885+
"family": "gemini-3",
886+
"isPreview": false,
887+
"isVisible": true,
888+
"features": {
889+
"thinking": false,
890+
"multimodalToolUse": true
891+
}
892+
},
871893
"gemini-2.5-pro": {
872894
"tier": "pro",
873895
"family": "gemini-2.5",
@@ -1020,9 +1042,44 @@ their corresponding top-level category object in your `settings.json` file.
10201042
"contexts": [
10211043
{
10221044
"condition": {
1045+
"useGemini3_5Flash": true
1046+
},
1047+
"target": "gemini-3.5-flash"
1048+
},
1049+
{
1050+
"condition": {
1051+
"hasAccessToPreview": false
1052+
},
1053+
"target": "gemini-2.5-flash"
1054+
}
1055+
]
1056+
},
1057+
"gemini-3.5-flash": {
1058+
"default": "gemini-3.5-flash",
1059+
"contexts": [
1060+
{
1061+
"condition": {
1062+
"useGemini3_5Flash": false,
10231063
"hasAccessToPreview": false
10241064
},
10251065
"target": "gemini-2.5-flash"
1066+
},
1067+
{
1068+
"condition": {
1069+
"useGemini3_5Flash": false
1070+
},
1071+
"target": "gemini-3-flash-preview"
1072+
}
1073+
]
1074+
},
1075+
"gemini-2.5-flash": {
1076+
"default": "gemini-2.5-flash",
1077+
"contexts": [
1078+
{
1079+
"condition": {
1080+
"useGemini3_5Flash": true
1081+
},
1082+
"target": "gemini-3.5-flash"
10261083
}
10271084
]
10281085
},
@@ -1104,6 +1161,12 @@ their corresponding top-level category object in your `settings.json` file.
11041161
"flash": {
11051162
"default": "gemini-3-flash-preview",
11061163
"contexts": [
1164+
{
1165+
"condition": {
1166+
"useGemini3_5Flash": true
1167+
},
1168+
"target": "gemini-3.5-flash"
1169+
},
11071170
{
11081171
"condition": {
11091172
"hasAccessToPreview": false
@@ -1157,6 +1220,12 @@ their corresponding top-level category object in your `settings.json` file.
11571220
"flash": {
11581221
"default": "gemini-3-flash-preview",
11591222
"contexts": [
1223+
{
1224+
"condition": {
1225+
"useGemini3_5Flash": true
1226+
},
1227+
"target": "gemini-3.5-flash"
1228+
},
11601229
{
11611230
"condition": {
11621231
"hasAccessToPreview": false

evals/llm-judge.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,30 @@ export class LLMJudge {
7676

7777
for (const res of rawResults) {
7878
// Remove any punctuation the model might have appended
79-
const cleanRes = res.replace(/[^A-Z]/g, '');
80-
if (cleanRes.startsWith('YES')) yes++;
81-
else if (cleanRes.startsWith('NO')) no++;
82-
else other++;
79+
const cleanRes = res.replace(/[^A-Z ]/g, '');
80+
if (
81+
cleanRes.includes('THE ANSWER IS YES') ||
82+
cleanRes.includes('ANSWER IS YES') ||
83+
cleanRes.endsWith('YES')
84+
) {
85+
yes++;
86+
} else if (
87+
cleanRes.includes('THE ANSWER IS NO') ||
88+
cleanRes.includes('ANSWER IS NO') ||
89+
cleanRes.endsWith('NO')
90+
) {
91+
no++;
92+
} else if (cleanRes.trim() === 'YES') {
93+
yes++;
94+
} else if (cleanRes.trim() === 'NO') {
95+
no++;
96+
} else {
97+
// Fallback: look for YES or NO as standalone words or at the end
98+
const words = cleanRes.split(/\s+/);
99+
if (words.includes('YES')) yes++;
100+
else if (words.includes('NO')) no++;
101+
else other++;
102+
}
83103
}
84104

85105
// Pass if YES > NO and YES > OTHER (plurality)

packages/core/src/availability/policyCatalog.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export interface ModelPolicyOptions {
3333
useGemini31?: boolean;
3434
useGemini31FlashLite?: boolean;
3535
useCustomToolModel?: boolean;
36+
useGemini3_5Flash?: boolean;
3637
}
3738

3839
const DEFAULT_ACTIONS: ModelPolicyActionMap = {
@@ -94,6 +95,9 @@ export function getModelPolicyChain(
9495
PREVIEW_GEMINI_MODEL,
9596
options.useGemini31,
9697
options.useCustomToolModel,
98+
true,
99+
undefined,
100+
options.useGemini3_5Flash,
97101
);
98102
return [
99103
definePolicy({

packages/core/src/availability/policyHelpers.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export function resolvePolicyChain(
5454
const useGemini31 = config.getGemini31LaunchedSync?.() ?? false;
5555
const useCustomToolModel = config.getUseCustomToolModelSync?.() ?? false;
5656
const hasAccessToPreview = config.getHasAccessToPreviewModel?.() ?? false;
57+
const useGemini3_5Flash = config.hasGemini35FlashGAAccess?.() ?? false;
5758

5859
// Capture the original family intent before any normalization or early downgrade.
5960
const isOriginallyGemini3 = isGemini3Model(modelFromConfig, config);
@@ -65,6 +66,7 @@ export function resolvePolicyChain(
6566
useCustomToolModel,
6667
hasAccessToPreview,
6768
config,
69+
useGemini3_5Flash,
6870
),
6971
);
7072
const isAutoPreferred = normalizedPreferredModel
@@ -82,6 +84,7 @@ export function resolvePolicyChain(
8284
const context = {
8385
useGemini3_1: useGemini31,
8486
useCustomTools: useCustomToolModel,
87+
useGemini3_5Flash,
8588
};
8689

8790
if (resolvedModel === DEFAULT_GEMINI_FLASH_LITE_MODEL) {
@@ -136,6 +139,7 @@ export function resolvePolicyChain(
136139
userTier: config.getUserTier(),
137140
useGemini31,
138141
useCustomToolModel,
142+
useGemini3_5Flash,
139143
});
140144
} else {
141145
// User requested Gemini 3 but has no access. Proactively downgrade
@@ -146,6 +150,7 @@ export function resolvePolicyChain(
146150
userTier: config.getUserTier(),
147151
useGemini31,
148152
useCustomToolModel,
153+
useGemini3_5Flash,
149154
});
150155
}
151156
} else {

packages/core/src/code_assist/experiments/flagNames.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const ExperimentFlags = {
1919
GEMINI_3_1_PRO_LAUNCHED: 45760185,
2020
PRO_MODEL_NO_ACCESS: 45768879,
2121
DEFAULT_REQUEST_TIMEOUT: 45773134,
22+
GEMINI_3_5_FLASH_GA_LAUNCHED: 45780819,
2223
} as const;
2324

2425
export type ExperimentFlagName =

packages/core/src/config/config.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import {
6969
DEFAULT_GEMINI_MODEL_AUTO,
7070
PREVIEW_GEMINI_MODEL_AUTO,
7171
PREVIEW_GEMINI_FLASH_MODEL,
72+
DEFAULT_GEMINI_FLASH_MODEL,
7273
} from './models.js';
7374
import { Storage } from './storage.js';
7475
import type { AgentLoopContext } from './agent-loop-context.js';
@@ -4346,3 +4347,34 @@ describe('ADKSettings', () => {
43464347
expect(config.getAgentSessionNoninteractiveEnabled()).toBe(true);
43474348
});
43484349
});
4350+
4351+
describe('hasGemini35FlashGAAccess model setting', () => {
4352+
const baseParams: ConfigParameters = {
4353+
sessionId: 'test',
4354+
targetDir: '.',
4355+
debugMode: false,
4356+
model: 'test-model',
4357+
cwd: '.',
4358+
};
4359+
4360+
it('should set DEFAULT_GEMINI_FLASH_MODEL and PREVIEW_GEMINI_FLASH_MODEL to gemini-3.5-flash if hasGemini35FlashGAAccess returns true', () => {
4361+
const config = new Config(baseParams);
4362+
4363+
// Set experiment to return true for GEMINI_3_5_FLASH_GA_LAUNCHED
4364+
config.setExperiments({
4365+
experimentIds: [],
4366+
flags: {
4367+
[ExperimentFlags.GEMINI_3_5_FLASH_GA_LAUNCHED]: {
4368+
boolValue: true,
4369+
},
4370+
},
4371+
});
4372+
4373+
// Call the method
4374+
const result = config.hasGemini35FlashGAAccess();
4375+
expect(result).toBe(true);
4376+
4377+
expect(DEFAULT_GEMINI_FLASH_MODEL).toBe('gemini-3.5-flash');
4378+
expect(PREVIEW_GEMINI_FLASH_MODEL).toBe('gemini-3.5-flash');
4379+
});
4380+
});

packages/core/src/config/config.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ import {
8686
isGemini2Model,
8787
PREVIEW_GEMINI_FLASH_MODEL,
8888
resolveModel,
89+
setFlashModels,
8990
} from './models.js';
9091
import { shouldAttemptBrowserLaunch } from '../utils/browser.js';
9192
import type { MCPOAuthConfig } from '../mcp/oauth-provider.js';
@@ -2054,6 +2055,7 @@ export class Config implements McpContext, AgentLoopContext {
20542055
this.getUseCustomToolModelSync(),
20552056
this.getHasAccessToPreviewModel(),
20562057
this,
2058+
this.hasGemini35FlashGAAccess(),
20572059
);
20582060

20592061
const isPreview = isPreviewModel(primaryModel, this);
@@ -2093,6 +2095,7 @@ export class Config implements McpContext, AgentLoopContext {
20932095
this.getUseCustomToolModelSync(),
20942096
this.getHasAccessToPreviewModel(),
20952097
this,
2098+
this.hasGemini35FlashGAAccess(),
20962099
);
20972100
return this.modelQuotas.get(primaryModel)?.remaining;
20982101
}
@@ -2108,6 +2111,7 @@ export class Config implements McpContext, AgentLoopContext {
21082111
this.getUseCustomToolModelSync(),
21092112
this.getHasAccessToPreviewModel(),
21102113
this,
2114+
this.hasGemini35FlashGAAccess(),
21112115
);
21122116
return this.modelQuotas.get(primaryModel)?.limit;
21132117
}
@@ -2123,6 +2127,7 @@ export class Config implements McpContext, AgentLoopContext {
21232127
this.getUseCustomToolModelSync(),
21242128
this.getHasAccessToPreviewModel(),
21252129
this,
2130+
this.hasGemini35FlashGAAccess(),
21262131
);
21272132
return this.modelQuotas.get(primaryModel)?.resetTime;
21282133
}
@@ -3537,6 +3542,32 @@ export class Config implements McpContext, AgentLoopContext {
35373542
);
35383543
}
35393544

3545+
/**
3546+
* Returns whether Gemini 3.5 Flash GA has been launched.
3547+
*
3548+
* Note: This method should only be called after startup, once experiments have been loaded.
3549+
*/
3550+
hasGemini35FlashGAAccess(): boolean {
3551+
const authType = this.contentGeneratorConfig?.authType;
3552+
const hasAccess = (() => {
3553+
if (this.isGemini31LaunchedForAuthType(authType)) {
3554+
return true;
3555+
}
3556+
return (
3557+
this.experiments?.flags[ExperimentFlags.GEMINI_3_5_FLASH_GA_LAUNCHED]
3558+
?.boolValue ?? false
3559+
);
3560+
})();
3561+
// Used to set default flash models based on access
3562+
// TODO: Remove once the experiment for 3_5 flash rollut can be cleaned up.
3563+
if (hasAccess) {
3564+
setFlashModels('gemini-3.5-flash', 'gemini-3.5-flash');
3565+
} else {
3566+
setFlashModels('gemini-3-flash-preview', 'gemini-2.5-flash');
3567+
}
3568+
return hasAccess;
3569+
}
3570+
35403571
/**
35413572
* Returns whether Gemini 3.1 has been launched.
35423573
*

0 commit comments

Comments
 (0)