Skip to content

Commit e98a4b6

Browse files
authored
Use kotlin's explicit API in vertexAI (#6313)
This option forces you to define the visibility of your code in Kotlin, ignoring the default visibility of `public` For more context, see https://kotlinlang.org/docs/whatsnew14.html#explicit-api-mode-for-library-authors https://umang91.medium.com/explicit-api-mode-kotlin-a527843d94f3
1 parent 7bab838 commit e98a4b6

28 files changed

+243
-196
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/java/ChatFutures.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,25 @@ import org.reactivestreams.Publisher
2929
*
3030
* @see from
3131
*/
32-
abstract class ChatFutures internal constructor() {
32+
public abstract class ChatFutures internal constructor() {
3333

3434
/**
3535
* Generates a response from the backend with the provided [Content], and any previous ones
3636
* sent/returned from this chat.
3737
*
3838
* @param prompt A [Content] to send to the model.
3939
*/
40-
abstract fun sendMessage(prompt: Content): ListenableFuture<GenerateContentResponse>
40+
public abstract fun sendMessage(prompt: Content): ListenableFuture<GenerateContentResponse>
4141

4242
/**
4343
* Generates a streaming response from the backend with the provided [Content].
4444
*
4545
* @param prompt A [Content] to send to the model.
4646
*/
47-
abstract fun sendMessageStream(prompt: Content): Publisher<GenerateContentResponse>
47+
public abstract fun sendMessageStream(prompt: Content): Publisher<GenerateContentResponse>
4848

4949
/** Returns the [Chat] instance that was used to create this instance */
50-
abstract fun getChat(): Chat
50+
public abstract fun getChat(): Chat
5151

5252
private class FuturesImpl(private val chat: Chat) : ChatFutures() {
5353
override fun sendMessage(prompt: Content): ListenableFuture<GenerateContentResponse> =
@@ -59,9 +59,9 @@ abstract class ChatFutures internal constructor() {
5959
override fun getChat(): Chat = chat
6060
}
6161

62-
companion object {
62+
public companion object {
6363

6464
/** @return a [ChatFutures] created around the provided [Chat] */
65-
@JvmStatic fun from(chat: Chat): ChatFutures = FuturesImpl(chat)
65+
@JvmStatic public fun from(chat: Chat): ChatFutures = FuturesImpl(chat)
6666
}
6767
}

firebase-vertexai/src/main/kotlin/com/google/firebase/vertexai/java/GenerativeModelFutures.kt

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,41 +31,45 @@ import org.reactivestreams.Publisher
3131
*
3232
* @see from
3333
*/
34-
abstract class GenerativeModelFutures internal constructor() {
34+
public abstract class GenerativeModelFutures internal constructor() {
3535

3636
/**
3737
* Generates a response from the backend with the provided [Content].
3838
*
3939
* @param prompt A group of [Content] to send to the model.
4040
*/
41-
abstract fun generateContent(vararg prompt: Content): ListenableFuture<GenerateContentResponse>
41+
public abstract fun generateContent(
42+
vararg prompt: Content
43+
): ListenableFuture<GenerateContentResponse>
4244

4345
/**
4446
* Generates a streaming response from the backend with the provided [Content].
4547
*
4648
* @param prompt A group of [Content] to send to the model.
4749
*/
48-
abstract fun generateContentStream(vararg prompt: Content): Publisher<GenerateContentResponse>
50+
public abstract fun generateContentStream(
51+
vararg prompt: Content
52+
): Publisher<GenerateContentResponse>
4953

5054
/**
5155
* Counts the number of tokens used in a prompt.
5256
*
5357
* @param prompt A group of [Content] to count tokens of.
5458
*/
55-
abstract fun countTokens(vararg prompt: Content): ListenableFuture<CountTokensResponse>
59+
public abstract fun countTokens(vararg prompt: Content): ListenableFuture<CountTokensResponse>
5660

5761
/** Creates a chat instance which internally tracks the ongoing conversation with the model */
58-
abstract fun startChat(): ChatFutures
62+
public abstract fun startChat(): ChatFutures
5963

6064
/**
6165
* Creates a chat instance which internally tracks the ongoing conversation with the model
6266
*
6367
* @param history an existing history of context to use as a starting point
6468
*/
65-
abstract fun startChat(history: List<Content>): ChatFutures
69+
public abstract fun startChat(history: List<Content>): ChatFutures
6670

6771
/** Returns the [GenerativeModel] instance that was used to create this object */
68-
abstract fun getGenerativeModel(): GenerativeModel
72+
public abstract fun getGenerativeModel(): GenerativeModel
6973

7074
private class FuturesImpl(private val model: GenerativeModel) : GenerativeModelFutures() {
7175
override fun generateContent(
@@ -86,9 +90,9 @@ abstract class GenerativeModelFutures internal constructor() {
8690
override fun getGenerativeModel(): GenerativeModel = model
8791
}
8892

89-
companion object {
93+
public companion object {
9094

9195
/** @return a [GenerativeModelFutures] created around the provided [GenerativeModel] */
92-
@JvmStatic fun from(model: GenerativeModel): GenerativeModelFutures = FuturesImpl(model)
96+
@JvmStatic public fun from(model: GenerativeModel): GenerativeModelFutures = FuturesImpl(model)
9397
}
9498
}

0 commit comments

Comments
 (0)