Skip to content

Commit 6002848

Browse files
authored
Merge branch 'main' into dconeybe/GradlePluginVersionIntoLibsVersionsToml
2 parents cff8484 + e98a4b6 commit 6002848

30 files changed

+309
-226
lines changed

firebase-vertexai/firebase-vertexai.gradle.kts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
@file:Suppress("UnstableApiUsage")
1818

19+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
20+
21+
1922
plugins {
2023
id("firebase-library")
2124
id("kotlin-android")
@@ -66,6 +69,21 @@ android {
6669
}
6770
}
6871

72+
// Enable Kotlin "Explicit API Mode". This causes the Kotlin compiler to fail if any
73+
// classes, methods, or properties have implicit `public` visibility. This check helps
74+
// avoid accidentally leaking elements into the public API, requiring that any public
75+
// element be explicitly declared as `public`.
76+
// https://github.com/Kotlin/KEEP/blob/master/proposals/explicit-api-mode.md
77+
// https://chao2zhang.medium.com/explicit-api-mode-for-kotlin-on-android-b8264fdd76d1
78+
tasks.withType<KotlinCompile>().all {
79+
if (!name.contains("test", ignoreCase = true)) {
80+
if (!kotlinOptions.freeCompilerArgs.contains("-Xexplicit-api=strict")) {
81+
kotlinOptions.freeCompilerArgs += "-Xexplicit-api=strict"
82+
}
83+
}
84+
}
85+
86+
6987
dependencies {
7088
val ktorVersion = "2.3.2"
7189

firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/Chat.kt

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ import kotlinx.coroutines.flow.onEach
4242
* @param model The model to use for the interaction
4343
* @property history The previous interactions with the model
4444
*/
45-
class Chat(private val model: GenerativeModel, val history: MutableList<Content> = ArrayList()) {
45+
public class Chat(
46+
private val model: GenerativeModel,
47+
public val history: MutableList<Content> = ArrayList()
48+
) {
4649
private var lock = Semaphore(1)
4750

4851
/**
@@ -53,7 +56,7 @@ class Chat(private val model: GenerativeModel, val history: MutableList<Content>
5356
* @throws InvalidStateException if the prompt is not coming from the 'user' role
5457
* @throws InvalidStateException if the [Chat] instance has an active request.
5558
*/
56-
suspend fun sendMessage(prompt: Content): GenerateContentResponse {
59+
public suspend fun sendMessage(prompt: Content): GenerateContentResponse {
5760
prompt.assertComesFromUser()
5861
attemptLock()
5962
try {
@@ -72,7 +75,7 @@ class Chat(private val model: GenerativeModel, val history: MutableList<Content>
7275
* @param prompt The text to be converted into a single piece of [Content] to send to the model.
7376
* @throws InvalidStateException if the [Chat] instance has an active request.
7477
*/
75-
suspend fun sendMessage(prompt: String): GenerateContentResponse {
78+
public suspend fun sendMessage(prompt: String): GenerateContentResponse {
7679
val content = content { text(prompt) }
7780
return sendMessage(content)
7881
}
@@ -83,7 +86,7 @@ class Chat(private val model: GenerativeModel, val history: MutableList<Content>
8386
* @param prompt The image to be converted into a single piece of [Content] to send to the model.
8487
* @throws InvalidStateException if the [Chat] instance has an active request.
8588
*/
86-
suspend fun sendMessage(prompt: Bitmap): GenerateContentResponse {
89+
public suspend fun sendMessage(prompt: Bitmap): GenerateContentResponse {
8790
val content = content { image(prompt) }
8891
return sendMessage(content)
8992
}
@@ -96,7 +99,7 @@ class Chat(private val model: GenerativeModel, val history: MutableList<Content>
9699
* @throws InvalidStateException if the prompt is not coming from the 'user' role
97100
* @throws InvalidStateException if the [Chat] instance has an active request.
98101
*/
99-
fun sendMessageStream(prompt: Content): Flow<GenerateContentResponse> {
102+
public fun sendMessageStream(prompt: Content): Flow<GenerateContentResponse> {
100103
prompt.assertComesFromUser()
101104
attemptLock()
102105

@@ -149,7 +152,7 @@ class Chat(private val model: GenerativeModel, val history: MutableList<Content>
149152
* @return A [Flow] which will emit responses as they are returned from the model.
150153
* @throws InvalidStateException if the [Chat] instance has an active request.
151154
*/
152-
fun sendMessageStream(prompt: String): Flow<GenerateContentResponse> {
155+
public fun sendMessageStream(prompt: String): Flow<GenerateContentResponse> {
153156
val content = content { text(prompt) }
154157
return sendMessageStream(content)
155158
}
@@ -161,7 +164,7 @@ class Chat(private val model: GenerativeModel, val history: MutableList<Content>
161164
* @return A [Flow] which will emit responses as they are returned from the model.
162165
* @throws InvalidStateException if the [Chat] instance has an active request.
163166
*/
164-
fun sendMessageStream(prompt: Bitmap): Flow<GenerateContentResponse> {
167+
public fun sendMessageStream(prompt: Bitmap): Flow<GenerateContentResponse> {
165168
val content = content { image(prompt) }
166169
return sendMessageStream(content)
167170
}

firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/FirebaseVertexAI.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import com.google.firebase.vertexai.type.Tool
3131
import com.google.firebase.vertexai.type.ToolConfig
3232

3333
/** Entry point for all _Vertex AI for Firebase_ functionality. */
34-
class FirebaseVertexAI
34+
public class FirebaseVertexAI
3535
internal constructor(
3636
private val firebaseApp: FirebaseApp,
3737
private val location: String,
@@ -51,7 +51,7 @@ internal constructor(
5151
* @param systemInstruction contains a [Content] that directs the model to behave a certain way
5252
*/
5353
@JvmOverloads
54-
fun generativeModel(
54+
public fun generativeModel(
5555
modelName: String,
5656
generationConfig: GenerationConfig? = null,
5757
safetySettings: List<SafetySetting>? = null,
@@ -77,13 +77,13 @@ internal constructor(
7777
)
7878
}
7979

80-
companion object {
80+
public companion object {
8181
/** The [FirebaseVertexAI] instance for the default [FirebaseApp] */
8282
@JvmStatic
83-
val instance: FirebaseVertexAI
83+
public val instance: FirebaseVertexAI
8484
get() = getInstance(location = "us-central1")
8585

86-
@JvmStatic fun getInstance(app: FirebaseApp): FirebaseVertexAI = getInstance(app)
86+
@JvmStatic public fun getInstance(app: FirebaseApp): FirebaseVertexAI = getInstance(app)
8787

8888
/**
8989
* Returns the [FirebaseVertexAI] instance for the provided [FirebaseApp] and [location]
@@ -93,19 +93,19 @@ internal constructor(
9393
*/
9494
@JvmStatic
9595
@JvmOverloads
96-
fun getInstance(app: FirebaseApp = Firebase.app, location: String): FirebaseVertexAI {
96+
public fun getInstance(app: FirebaseApp = Firebase.app, location: String): FirebaseVertexAI {
9797
val multiResourceComponent = app[FirebaseVertexAIMultiResourceComponent::class.java]
9898
return multiResourceComponent.get(location)
9999
}
100100
}
101101
}
102102

103103
/** Returns the [FirebaseVertexAI] instance of the default [FirebaseApp]. */
104-
val Firebase.vertexAI: FirebaseVertexAI
104+
public val Firebase.vertexAI: FirebaseVertexAI
105105
get() = FirebaseVertexAI.instance
106106

107107
/** Returns the [FirebaseVertexAI] instance of a given [FirebaseApp]. */
108-
fun Firebase.vertexAI(
108+
public fun Firebase.vertexAI(
109109
app: FirebaseApp = Firebase.app,
110110
location: String = "us-central1"
111111
): FirebaseVertexAI = FirebaseVertexAI.getInstance(app, location)

firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/GenerativeModel.kt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import kotlinx.coroutines.tasks.await
5050
/**
5151
* A controller for communicating with the API of a given multimodal model (for example, Gemini).
5252
*/
53-
class GenerativeModel
53+
public class GenerativeModel
5454
internal constructor(
5555
private val modelName: String,
5656
private val generationConfig: GenerationConfig? = null,
@@ -128,7 +128,7 @@ internal constructor(
128128
* @return A [GenerateContentResponse]. Function should be called within a suspend context to
129129
* properly manage concurrency.
130130
*/
131-
suspend fun generateContent(vararg prompt: Content): GenerateContentResponse =
131+
public suspend fun generateContent(vararg prompt: Content): GenerateContentResponse =
132132
try {
133133
controller.generateContent(constructRequest(*prompt)).toPublic().validate()
134134
} catch (e: Throwable) {
@@ -141,7 +141,7 @@ internal constructor(
141141
* @param prompt [Content] to send to the model.
142142
* @return A [Flow] which will emit responses as they are returned from the model.
143143
*/
144-
fun generateContentStream(vararg prompt: Content): Flow<GenerateContentResponse> =
144+
public fun generateContentStream(vararg prompt: Content): Flow<GenerateContentResponse> =
145145
controller
146146
.generateContentStream(constructRequest(*prompt))
147147
.catch { throw FirebaseVertexAIException.from(it) }
@@ -154,7 +154,7 @@ internal constructor(
154154
* @return A [GenerateContentResponse] after some delay. Function should be called within a
155155
* suspend context to properly manage concurrency.
156156
*/
157-
suspend fun generateContent(prompt: String): GenerateContentResponse =
157+
public suspend fun generateContent(prompt: String): GenerateContentResponse =
158158
generateContent(content { text(prompt) })
159159

160160
/**
@@ -163,7 +163,7 @@ internal constructor(
163163
* @param prompt The text to be converted into a single piece of [Content] to send to the model.
164164
* @return A [Flow] which will emit responses as they are returned from the model.
165165
*/
166-
fun generateContentStream(prompt: String): Flow<GenerateContentResponse> =
166+
public fun generateContentStream(prompt: String): Flow<GenerateContentResponse> =
167167
generateContentStream(content { text(prompt) })
168168

169169
/**
@@ -173,7 +173,7 @@ internal constructor(
173173
* @return A [GenerateContentResponse] after some delay. Function should be called within a
174174
* suspend context to properly manage concurrency.
175175
*/
176-
suspend fun generateContent(prompt: Bitmap): GenerateContentResponse =
176+
public suspend fun generateContent(prompt: Bitmap): GenerateContentResponse =
177177
generateContent(content { image(prompt) })
178178

179179
/**
@@ -182,19 +182,20 @@ internal constructor(
182182
* @param prompt The image to be converted into a single piece of [Content] to send to the model.
183183
* @return A [Flow] which will emit responses as they are returned from the model.
184184
*/
185-
fun generateContentStream(prompt: Bitmap): Flow<GenerateContentResponse> =
185+
public fun generateContentStream(prompt: Bitmap): Flow<GenerateContentResponse> =
186186
generateContentStream(content { image(prompt) })
187187

188188
/** Creates a [Chat] instance which internally tracks the ongoing conversation with the model */
189-
fun startChat(history: List<Content> = emptyList()): Chat = Chat(this, history.toMutableList())
189+
public fun startChat(history: List<Content> = emptyList()): Chat =
190+
Chat(this, history.toMutableList())
190191

191192
/**
192193
* Counts the amount of tokens in a prompt.
193194
*
194195
* @param prompt A group of [Content] to count tokens of.
195196
* @return A [CountTokensResponse] containing the amount of tokens in the prompt.
196197
*/
197-
suspend fun countTokens(vararg prompt: Content): CountTokensResponse {
198+
public suspend fun countTokens(vararg prompt: Content): CountTokensResponse {
198199
try {
199200
return controller.countTokens(constructCountTokensRequest(*prompt)).toPublic()
200201
} catch (e: Throwable) {
@@ -208,7 +209,7 @@ internal constructor(
208209
* @param prompt The text to be converted to a single piece of [Content] to count the tokens of.
209210
* @return A [CountTokensResponse] containing the amount of tokens in the prompt.
210211
*/
211-
suspend fun countTokens(prompt: String): CountTokensResponse {
212+
public suspend fun countTokens(prompt: String): CountTokensResponse {
212213
return countTokens(content { text(prompt) })
213214
}
214215

@@ -218,7 +219,7 @@ internal constructor(
218219
* @param prompt The image to be converted to a single piece of [Content] to count the tokens of.
219220
* @return A [CountTokensResponse] containing the amount of tokens in the prompt.
220221
*/
221-
suspend fun countTokens(prompt: Bitmap): CountTokensResponse {
222+
public suspend fun countTokens(prompt: Bitmap): CountTokensResponse {
222223
return countTokens(content { image(prompt) })
223224
}
224225

@@ -247,7 +248,7 @@ internal constructor(
247248
?.let { throw ResponseStoppedException(this) }
248249
}
249250

250-
companion object {
251+
private companion object {
251252
private val TAG = GenerativeModel::class.java.simpleName
252253
}
253254
}

firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/common/shared/Types.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ internal enum class HarmCategory {
4141
@SerialName("HARM_CATEGORY_DANGEROUS_CONTENT") DANGEROUS_CONTENT
4242
}
4343

44-
typealias Base64 = String
44+
internal typealias Base64 = String
4545

4646
@ExperimentalSerializationApi
4747
@Serializable

firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/internal/util/conversions.kt

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ import android.graphics.BitmapFactory
2121
import android.util.Base64
2222
import com.google.firebase.vertexai.common.client.Schema
2323
import com.google.firebase.vertexai.common.shared.FileData
24-
import com.google.firebase.vertexai.common.shared.FunctionCall
25-
import com.google.firebase.vertexai.common.shared.FunctionCallPart
26-
import com.google.firebase.vertexai.common.shared.FunctionResponse
27-
import com.google.firebase.vertexai.common.shared.FunctionResponsePart
2824
import com.google.firebase.vertexai.common.shared.InlineData
2925
import com.google.firebase.vertexai.type.BlockReason
3026
import com.google.firebase.vertexai.type.Candidate
@@ -34,8 +30,12 @@ import com.google.firebase.vertexai.type.Content
3430
import com.google.firebase.vertexai.type.CountTokensResponse
3531
import com.google.firebase.vertexai.type.FileDataPart
3632
import com.google.firebase.vertexai.type.FinishReason
33+
import com.google.firebase.vertexai.type.FunctionCall
34+
import com.google.firebase.vertexai.type.FunctionCallPart
3735
import com.google.firebase.vertexai.type.FunctionCallingConfig
3836
import com.google.firebase.vertexai.type.FunctionDeclaration
37+
import com.google.firebase.vertexai.type.FunctionResponse
38+
import com.google.firebase.vertexai.type.FunctionResponsePart
3939
import com.google.firebase.vertexai.type.GenerateContentResponse
4040
import com.google.firebase.vertexai.type.GenerationConfig
4141
import com.google.firebase.vertexai.type.HarmBlockMethod
@@ -59,6 +59,7 @@ import java.io.ByteArrayOutputStream
5959
import java.util.Calendar
6060
import kotlinx.serialization.json.Json
6161
import kotlinx.serialization.json.JsonObject
62+
import kotlinx.serialization.json.JsonPrimitive
6263
import org.json.JSONObject
6364

6465
private const val BASE_64_FLAGS = Base64.NO_WRAP
@@ -80,10 +81,10 @@ internal fun Part.toInternal(): com.google.firebase.vertexai.common.shared.Part
8081
com.google.firebase.vertexai.common.shared.InlineDataPart(
8182
InlineData(mimeType, Base64.encodeToString(inlineData, BASE_64_FLAGS))
8283
)
83-
is com.google.firebase.vertexai.type.FunctionCallPart ->
84-
FunctionCallPart(FunctionCall(name, args.orEmpty()))
85-
is com.google.firebase.vertexai.type.FunctionResponsePart ->
86-
FunctionResponsePart(FunctionResponse(name, response.toInternal()))
84+
is FunctionCallPart ->
85+
com.google.firebase.vertexai.common.shared.FunctionCallPart(functionCall.toInternal())
86+
is FunctionResponsePart ->
87+
com.google.firebase.vertexai.common.shared.FunctionResponsePart(functionResponse.toInternal())
8788
is FileDataPart ->
8889
com.google.firebase.vertexai.common.shared.FileDataPart(
8990
FileData(mimeType = mimeType, fileUri = uri)
@@ -95,6 +96,15 @@ internal fun Part.toInternal(): com.google.firebase.vertexai.common.shared.Part
9596
}
9697
}
9798

99+
internal fun FunctionCall.toInternal() =
100+
com.google.firebase.vertexai.common.shared.FunctionCall(
101+
name,
102+
args.orEmpty().mapValues { it.value.toString() }
103+
)
104+
105+
internal fun FunctionResponse.toInternal() =
106+
com.google.firebase.vertexai.common.shared.FunctionResponse(name, response)
107+
98108
internal fun SafetySetting.toInternal() =
99109
com.google.firebase.vertexai.common.shared.SafetySetting(
100110
harmCategory.toInternal(),
@@ -213,16 +223,10 @@ internal fun com.google.firebase.vertexai.common.shared.Part.toPublic(): Part {
213223
InlineDataPart(inlineData.mimeType, data)
214224
}
215225
}
216-
is FunctionCallPart ->
217-
com.google.firebase.vertexai.type.FunctionCallPart(
218-
functionCall.name,
219-
functionCall.args.orEmpty(),
220-
)
221-
is FunctionResponsePart ->
222-
com.google.firebase.vertexai.type.FunctionResponsePart(
223-
functionResponse.name,
224-
functionResponse.response.toPublic(),
225-
)
226+
is com.google.firebase.vertexai.common.shared.FunctionCallPart ->
227+
FunctionCallPart(functionCall.toPublic())
228+
is com.google.firebase.vertexai.common.shared.FunctionResponsePart ->
229+
FunctionResponsePart(functionResponse.toPublic())
226230
is com.google.firebase.vertexai.common.shared.FileDataPart ->
227231
FileDataPart(fileData.mimeType, fileData.fileUri)
228232
else ->
@@ -232,6 +236,21 @@ internal fun com.google.firebase.vertexai.common.shared.Part.toPublic(): Part {
232236
}
233237
}
234238

239+
internal fun com.google.firebase.vertexai.common.shared.FunctionCall.toPublic() =
240+
FunctionCall(
241+
name,
242+
args.orEmpty().mapValues {
243+
val argValue = it.value
244+
if (argValue == null) JsonPrimitive(null) else Json.parseToJsonElement(argValue)
245+
}
246+
)
247+
248+
internal fun com.google.firebase.vertexai.common.shared.FunctionResponse.toPublic() =
249+
FunctionResponse(
250+
name,
251+
response,
252+
)
253+
235254
internal fun com.google.firebase.vertexai.common.server.CitationSources.toPublic(): Citation {
236255
val publicationDateAsCalendar =
237256
publicationDate?.let {

0 commit comments

Comments
 (0)