diff --git a/generativeai/src/main/java/com/google/ai/client/generativeai/type/Type.kt b/generativeai/src/main/java/com/google/ai/client/generativeai/type/Type.kt index 8486edab..3a693143 100644 --- a/generativeai/src/main/java/com/google/ai/client/generativeai/type/Type.kt +++ b/generativeai/src/main/java/com/google/ai/client/generativeai/type/Type.kt @@ -29,15 +29,22 @@ import org.json.JSONObject */ class FunctionType(val name: String, val parse: (String?) -> T?) { companion object { + @JvmField val STRING = FunctionType("STRING") { it } + @JvmField val INTEGER = FunctionType("INTEGER") { it?.toIntOrNull() } + @JvmField val LONG = FunctionType("INTEGER") { it?.toLongOrNull() } + @JvmField val NUMBER = FunctionType("NUMBER") { it?.toDoubleOrNull() } + @JvmField val BOOLEAN = FunctionType("BOOLEAN") { it?.toBoolean() } + @JvmField val ARRAY = FunctionType>("ARRAY") { it -> it?.let { Json.parseToJsonElement(it).jsonArray.map { element -> element.toString() } } } + @JvmField val OBJECT = FunctionType("OBJECT") { it?.let { JSONObject(it) } } } } diff --git a/samples/src/main/java/com/google/ai/client/generative/samples/controlled_generation.kt b/samples/src/main/java/com/google/ai/client/generative/samples/controlled_generation.kt index 011c1370..38df2a8f 100644 --- a/samples/src/main/java/com/google/ai/client/generative/samples/controlled_generation.kt +++ b/samples/src/main/java/com/google/ai/client/generative/samples/controlled_generation.kt @@ -70,7 +70,6 @@ suspend fun json_controlled_generation() { suspend fun json_no_schema() { // [START json_no_schema] - val generativeModel = GenerativeModel( // Specify a Gemini model appropriate for your use case diff --git a/samples/src/main/java/com/google/ai/client/generative/samples/java/code_execution.java b/samples/src/main/java/com/google/ai/client/generative/samples/java/code_execution.java index 9bc2a5cc..637f3d83 100644 --- a/samples/src/main/java/com/google/ai/client/generative/samples/java/code_execution.java +++ b/samples/src/main/java/com/google/ai/client/generative/samples/java/code_execution.java @@ -51,7 +51,7 @@ void codeExecutionBasic() { /* generationConfig */ null, /* safetySettings */ null, /* requestOptions */ new RequestOptions(), - /* tools */ Collections.singletonList(Tool.Companion.getCODE_EXECUTION())); + /* tools */ Collections.singletonList(Tool.CODE_EXECUTION)); GenerativeModelFutures model = GenerativeModelFutures.from(gm); Content inputContent = @@ -91,7 +91,7 @@ void codeExecutionChat() { /* generationConfig */ null, /* safetySettings */ null, /* requestOptions */ new RequestOptions(), - /* tools */ Collections.singletonList(Tool.Companion.getCODE_EXECUTION())); + /* tools */ Collections.singletonList(Tool.CODE_EXECUTION)); GenerativeModelFutures model = GenerativeModelFutures.from(gm); Content inputContent = diff --git a/samples/src/main/java/com/google/ai/client/generative/samples/java/controlled_generation.java b/samples/src/main/java/com/google/ai/client/generative/samples/java/controlled_generation.java index d42eee4b..f3015553 100644 --- a/samples/src/main/java/com/google/ai/client/generative/samples/java/controlled_generation.java +++ b/samples/src/main/java/com/google/ai/client/generative/samples/java/controlled_generation.java @@ -21,6 +21,141 @@ // the "Set up your API Key section" in the [Gemini API // quickstart](https://ai.google.dev/gemini-api/docs/quickstart?lang=android#set-up-api-key). +import com.google.ai.client.generativeai.GenerativeModel; +import com.google.ai.client.generativeai.java.GenerativeModelFutures; +import com.google.ai.client.generativeai.type.Content; +import com.google.ai.client.generativeai.type.FunctionType; +import com.google.ai.client.generativeai.type.GenerateContentResponse; +import com.google.ai.client.generativeai.type.GenerationConfig; +import com.google.ai.client.generativeai.type.Schema; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + class ControlledGeneration { - // TODO + void jsonControlledGeneration() { + // [START json_controlled_generation] + + Schema> schema = + new Schema( + /* name */ "recipes", + /* description */ "List of recipes", + /* format */ null, + /* nullable */ false, + /* list */ null, + /* properties */ null, + /* required */ null, + /* items */ new Schema( + /* name */ "recipe", + /* description */ "A recipe", + /* format */ null, + /* nullable */ false, + /* list */ null, + /* properties */ Map.of( + "recipeName", + new Schema( + /* name */ "recipeName", + /* description */ "Name of the recipe", + /* format */ null, + /* nullable */ false, + /* list */ null, + /* properties */ null, + /* required */ null, + /* items */ null, + /* type */ FunctionType.STRING)), + /* required */ null, + /* items */ null, + /* type */ FunctionType.OBJECT), + /* type */ FunctionType.ARRAY); + + GenerationConfig.Builder configBuilder = new GenerationConfig.Builder(); + configBuilder.responseMimeType = "application/json"; + configBuilder.responseSchema = schema; + + GenerationConfig generationConfig = configBuilder.build(); + + // Specify a Gemini model appropriate for your use case + GenerativeModel gm = + new GenerativeModel( + /* modelName */ "gemini-1.5-pro", + // Access your API key as a Build Configuration variable (see "Set up your API key" + // above) + /* apiKey */ BuildConfig.apiKey, + /* generationConfig */ generationConfig); + GenerativeModelFutures model = GenerativeModelFutures.from(gm); + + Content content = new Content.Builder().addText("List a few popular cookie recipes.").build(); + + // For illustrative purposes only. You should use an executor that fits your needs. + Executor executor = Executors.newSingleThreadExecutor(); + + ListenableFuture response = model.generateContent(content); + Futures.addCallback( + response, + new FutureCallback() { + @Override + public void onSuccess(GenerateContentResponse result) { + String resultText = result.getText(); + System.out.println(resultText); + } + + @Override + public void onFailure(Throwable t) { + t.printStackTrace(); + } + }, + executor); + // [END json_controlled_generation] + } + + void json_no_schema() { + // [START json_no_schema] + GenerationConfig.Builder configBuilder = new GenerationConfig.Builder(); + configBuilder.responseMimeType = "application/json"; + + GenerationConfig generationConfig = configBuilder.build(); + + // Specify a Gemini model appropriate for your use case + GenerativeModel gm = + new GenerativeModel( + /* modelName */ "gemini-1.5-flash", + // Access your API key as a Build Configuration variable (see "Set up your API key" + // above) + /* apiKey */ BuildConfig.apiKey, + /* generationConfig */ generationConfig); + GenerativeModelFutures model = GenerativeModelFutures.from(gm); + + Content content = + new Content.Builder() + .addText( + "List a few popular cookie recipes using this JSON schema:\n" + + "Recipe = {'recipeName': string}\n" + + "Return: Array") + .build(); + + // For illustrative purposes only. You should use an executor that fits your needs. + Executor executor = Executors.newSingleThreadExecutor(); + + ListenableFuture response = model.generateContent(content); + Futures.addCallback( + response, + new FutureCallback() { + @Override + public void onSuccess(GenerateContentResponse result) { + String resultText = result.getText(); + System.out.println(resultText); + } + + @Override + public void onFailure(Throwable t) { + t.printStackTrace(); + } + }, + executor); + // [END json_no_schema] + } }