Skip to content

Commit 22ab754

Browse files
GuinersGuinersmsampathkumargericdong
authored
feat(genai): controlled generation (#4148)
* bumping version and fixing tests * bumping version and fixing tests * bumping version and fixing tests * bumping version and fixing tests * adding tests * adding tests * fixing filenames * fixing code from code review and adding linters * adding samples, test, lints * adding samples, test, lints * adding samples, test, lints * adding samples, test, lints * fixing functions names --------- Co-authored-by: Guiners <rkoza@softserveinc.com> Co-authored-by: Sampath Kumar <sampathm@google.com> Co-authored-by: Eric Dong <itseric@google.com>
1 parent 3465677 commit 22ab754

12 files changed

+564
-4
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// [START googlegenaisdk_ctrlgen_with_class_schema]
18+
const {GoogleGenAI} = require('@google/genai');
19+
20+
const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
21+
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
23+
async function generateClassSchema(
24+
projectId = GOOGLE_CLOUD_PROJECT,
25+
location = GOOGLE_CLOUD_LOCATION
26+
) {
27+
const client = new GoogleGenAI({
28+
vertexai: true,
29+
project: projectId,
30+
location: location,
31+
});
32+
33+
class Recipe {
34+
/**
35+
* @param {string} recipeName
36+
* @param {string[]} ingredients
37+
*/
38+
constructor(recipeName, ingredients) {
39+
this.recipeName = recipeName;
40+
this.ingredients = ingredients;
41+
}
42+
}
43+
44+
const response = await client.models.generateContent({
45+
model: 'gemini-2.5-flash',
46+
contents: 'List a few popular cookie recipes?',
47+
config: {
48+
responseMimeType: 'application/json',
49+
responseSchema: Recipe,
50+
},
51+
});
52+
53+
console.log(response.text);
54+
55+
// Example output:
56+
// [Recipe(recipe_name='Chocolate Chip Cookies', ingredients=['2 1/4 cups all-purpose flour'
57+
// {
58+
// "ingredients": [
59+
// "2 1/4 cups all-purpose flour",
60+
// "1 teaspoon baking soda",
61+
// "1 teaspoon salt",
62+
// "1 cup (2 sticks) unsalted butter, softened",
63+
// "3/4 cup granulated sugar",
64+
// "3/4 cup packed brown sugar",
65+
// "1 teaspoon vanilla extract",
66+
// "2 large eggs",
67+
// "2 cups chocolate chips"
68+
// ],
69+
// "recipe_name": "Classic Chocolate Chip Cookies"
70+
// }, ... ]
71+
72+
return response.text;
73+
}
74+
75+
// [END googlegenaisdk_ctrlgen_with_class_schema]
76+
77+
module.exports = {
78+
generateClassSchema,
79+
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// [START googlegenaisdk_ctrlgen_with_enum_class_schema]
18+
const {GoogleGenAI} = require('@google/genai');
19+
20+
const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
21+
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
23+
async function generateEnumClassSchema(
24+
projectId = GOOGLE_CLOUD_PROJECT,
25+
location = GOOGLE_CLOUD_LOCATION
26+
) {
27+
const client = new GoogleGenAI({
28+
vertexai: true,
29+
project: projectId,
30+
location: location,
31+
});
32+
33+
class InstrumentClass {
34+
static values() {
35+
return [
36+
InstrumentClass.PERCUSSION,
37+
InstrumentClass.STRING,
38+
InstrumentClass.WOODWIND,
39+
InstrumentClass.BRASS,
40+
InstrumentClass.KEYBOARD,
41+
];
42+
}
43+
}
44+
45+
InstrumentClass.PERCUSSION = 'Percussion';
46+
InstrumentClass.STRING = 'String';
47+
InstrumentClass.WOODWIND = 'Woodwind';
48+
InstrumentClass.BRASS = 'Brass';
49+
InstrumentClass.KEYBOARD = 'Keyboard';
50+
51+
const responseSchema = {
52+
type: 'string',
53+
enum: InstrumentClass.values(),
54+
};
55+
56+
const response = await client.models.generateContent({
57+
model: 'gemini-2.5-flash',
58+
contents: 'What type of instrument is a guitar?',
59+
config: {
60+
responseMimeType: 'text/x.enum',
61+
responseSchema: responseSchema,
62+
},
63+
});
64+
65+
console.log(response.text);
66+
67+
// Example output:
68+
// String
69+
70+
return response.text;
71+
}
72+
73+
// [END googlegenaisdk_ctrlgen_with_enum_class_schema]
74+
75+
module.exports = {
76+
generateEnumClassSchema,
77+
};

genai/controlled-generation/ctrlgen-with-enum-schema.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ async function generateContent(
2424
projectId = GOOGLE_CLOUD_PROJECT,
2525
location = GOOGLE_CLOUD_LOCATION
2626
) {
27-
const ai = new GoogleGenAI({
27+
const client = new GoogleGenAI({
2828
vertexai: true,
2929
project: projectId,
3030
location: location,
@@ -35,7 +35,7 @@ async function generateContent(
3535
enum: ['Percussion', 'String', 'Woodwind', 'Brass', 'Keyboard'],
3636
};
3737

38-
const response = await ai.models.generateContent({
38+
const response = await client.models.generateContent({
3939
model: 'gemini-2.5-flash',
4040
contents: 'What type of instrument is an oboe?',
4141
config: {
@@ -45,9 +45,11 @@ async function generateContent(
4545
});
4646

4747
console.log(response.text);
48-
48+
// Example output:
49+
// Woodwind
4950
return response.text;
5051
}
52+
5153
// [END googlegenaisdk_ctrlgen_with_enum_schema]
5254

5355
module.exports = {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// [START googlegenaisdk_ctrlgen_with_nested_class_schema]
18+
const {GoogleGenAI} = require('@google/genai');
19+
20+
const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
21+
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
23+
async function generateNestedClassSchema(
24+
projectId = GOOGLE_CLOUD_PROJECT,
25+
location = GOOGLE_CLOUD_LOCATION
26+
) {
27+
const client = new GoogleGenAI({
28+
vertexai: true,
29+
project: projectId,
30+
location: location,
31+
});
32+
33+
const Grade = Object.freeze({
34+
A_PLUS: 'a+',
35+
A: 'a',
36+
B: 'b',
37+
C: 'c',
38+
D: 'd',
39+
F: 'f',
40+
});
41+
42+
class Recipe {
43+
/**
44+
* @param {string} recipeName
45+
* @param {string} rating - Must be one of Grade enum values
46+
*/
47+
constructor(recipeName, rating) {
48+
if (!Object.values(Grade).includes(rating)) {
49+
throw new Error(`Invalid rating: ${rating}`);
50+
}
51+
this.recipeName = recipeName;
52+
this.rating = rating;
53+
}
54+
}
55+
56+
const response = await client.models.generateContent({
57+
model: 'gemini-2.5-flash',
58+
contents:
59+
'List about 10 home-baked cookies and give them grades based on tastiness.',
60+
config: {
61+
responseMimeType: 'application/json',
62+
responseSchema: Recipe,
63+
},
64+
});
65+
66+
console.log(response.text);
67+
68+
// Example output:
69+
// [{"rating": "a+", "recipe_name": "Classic Chocolate Chip Cookies"}, ...]
70+
71+
return response.text;
72+
}
73+
74+
// [END googlegenaisdk_ctrlgen_with_nested_class_schema]
75+
76+
module.exports = {
77+
generateNestedClassSchema,
78+
};
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// [START googlegenaisdk_ctrlgen_with_nullable_schema]
18+
const {GoogleGenAI} = require('@google/genai');
19+
20+
const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
21+
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22+
23+
async function generateNullableSchema(
24+
projectId = GOOGLE_CLOUD_PROJECT,
25+
location = GOOGLE_CLOUD_LOCATION
26+
) {
27+
const client = new GoogleGenAI({
28+
vertexai: true,
29+
project: projectId,
30+
location: location,
31+
});
32+
33+
const prompt = `
34+
The week ahead brings a mix of weather conditions.
35+
Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. Winds will be light at around 10 km/h.
36+
Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds will pick up slightly to around 15 km/h.
37+
Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%.
38+
Wednesday may see thunderstorms, with a temperature of 68°F.
39+
Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%.
40+
Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be light at 12 km/h.
41+
Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity level of 40%. Winds will be gentle at 8 km/h.
42+
`;
43+
44+
const responseSchema = {
45+
type: 'object',
46+
properties: {
47+
forecast: {
48+
type: 'array',
49+
items: {
50+
type: 'object',
51+
properties: {
52+
Day: {type: 'string', nullable: true},
53+
Forecast: {type: 'string', nullable: true},
54+
Temperature: {type: 'integer', nullable: true},
55+
Humidity: {type: 'string', nullable: true},
56+
WindSpeed: {type: 'integer', nullable: true},
57+
},
58+
required: ['Day', 'Temperature', 'Forecast', 'WindSpeed'],
59+
},
60+
},
61+
},
62+
};
63+
64+
const response = await client.models.generateContent({
65+
model: 'gemini-2.5-flash',
66+
contents: prompt,
67+
config: {
68+
responseMimeType: 'application/json',
69+
responseSchema: responseSchema,
70+
},
71+
});
72+
console.log(response.text);
73+
74+
// Example output:
75+
// {"forecast": [{"Day": "Sunday", "Forecast": "sunny", "Temperature": 77, "Wind Speed": 10, "Humidity": "50%"},
76+
// {"Day": "Monday", "Forecast": "partly cloudy", "Temperature": 72, "Wind Speed": 15},
77+
// {"Day": "Tuesday", "Forecast": "rain showers", "Temperature": 64, "Wind Speed": null, "Humidity": "70%"},
78+
// {"Day": "Wednesday", "Forecast": "thunderstorms", "Temperature": 68, "Wind Speed": null},
79+
// {"Day": "Thursday", "Forecast": "cloudy", "Temperature": 66, "Wind Speed": null, "Humidity": "60%"},
80+
// {"Day": "Friday", "Forecast": "partly cloudy", "Temperature": 73, "Wind Speed": 12},
81+
// {"Day": "Saturday", "Forecast": "sunny", "Temperature": 80, "Wind Speed": 8, "Humidity": "40%"}]}
82+
83+
return response.text;
84+
}
85+
86+
// [END googlegenaisdk_ctrlgen_with_nullable_schema]
87+
88+
module.exports = {
89+
generateNullableSchema,
90+
};

0 commit comments

Comments
 (0)