Skip to content

Commit 503a2d2

Browse files
committed
add basic classes
1 parent ffb7e2e commit 503a2d2

File tree

6 files changed

+359
-0
lines changed

6 files changed

+359
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.vertexai
18+
19+
import android.graphics.Bitmap
20+
import com.google.firebase.appcheck.interop.InteropAppCheckTokenProvider
21+
import com.google.firebase.auth.internal.InternalAuthProvider
22+
import com.google.firebase.vertexai.common.APIController
23+
import com.google.firebase.vertexai.common.AppCheckHeaderProvider
24+
import com.google.firebase.vertexai.common.CountTokensRequest
25+
import com.google.firebase.vertexai.common.GenerateContentRequest
26+
import com.google.firebase.vertexai.type.Content
27+
import com.google.firebase.vertexai.type.CountTokensResponse
28+
import com.google.firebase.vertexai.type.FinishReason
29+
import com.google.firebase.vertexai.type.FirebaseVertexAIException
30+
import com.google.firebase.vertexai.type.GenerateContentResponse
31+
import com.google.firebase.vertexai.type.GenerationConfig
32+
import com.google.firebase.vertexai.type.LiveGenerationConfig
33+
import com.google.firebase.vertexai.type.LiveSession
34+
import com.google.firebase.vertexai.type.PromptBlockedException
35+
import com.google.firebase.vertexai.type.RequestOptions
36+
import com.google.firebase.vertexai.type.ResponseStoppedException
37+
import com.google.firebase.vertexai.type.SafetySetting
38+
import com.google.firebase.vertexai.type.SerializationException
39+
import com.google.firebase.vertexai.type.Tool
40+
import com.google.firebase.vertexai.type.ToolConfig
41+
import com.google.firebase.vertexai.type.content
42+
import kotlinx.coroutines.flow.Flow
43+
import kotlinx.coroutines.flow.catch
44+
import kotlinx.coroutines.flow.map
45+
import kotlinx.serialization.ExperimentalSerializationApi
46+
47+
/**
48+
* Represents a multimodal model (like Gemini), capable of generating content based on various input
49+
* types.
50+
*/
51+
public class LiveGenerativeModel
52+
internal constructor(
53+
private val modelName: String,
54+
private val config: LiveGenerationConfig? = null,
55+
private val tools: List<Tool>? = null,
56+
private val toolConfig: ToolConfig? = null,
57+
private val systemInstruction: Content? = null,
58+
private val controller: APIController,
59+
) {
60+
internal constructor(
61+
modelName: String,
62+
apiKey: String,
63+
config: LiveGenerationConfig? = null,
64+
tools: List<Tool>? = null,
65+
toolConfig: ToolConfig? = null,
66+
systemInstruction: Content? = null,
67+
requestOptions: RequestOptions = RequestOptions(),
68+
appCheckTokenProvider: InteropAppCheckTokenProvider? = null,
69+
internalAuthProvider: InternalAuthProvider? = null,
70+
) : this(
71+
modelName,
72+
config,
73+
tools,
74+
toolConfig,
75+
systemInstruction,
76+
APIController(
77+
apiKey,
78+
modelName,
79+
requestOptions,
80+
"gl-kotlin/${KotlinVersion.CURRENT} fire/${BuildConfig.VERSION_NAME}",
81+
AppCheckHeaderProvider(TAG, appCheckTokenProvider, internalAuthProvider),
82+
),
83+
)
84+
85+
public suspend fun connect(): LiveSession = LiveSession()
86+
87+
}
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.vertexai.type
18+
19+
import kotlinx.serialization.SerialName
20+
import kotlinx.serialization.Serializable
21+
22+
/**
23+
* Configuration parameters to use for content generation.
24+
*
25+
* @property temperature A parameter controlling the degree of randomness in token selection. A
26+
* temperature of 0 means that the highest probability tokens are always selected. In this case,
27+
* responses for a given prompt are mostly deterministic, but a small amount of variation is still
28+
* possible.
29+
*
30+
* @property topK The `topK` parameter changes how the model selects tokens for output. A `topK` of
31+
* 1 means the selected token is the most probable among all the tokens in the model's vocabulary,
32+
* while a `topK` of 3 means that the next token is selected from among the 3 most probable using
33+
* the `temperature`. For each token selection step, the `topK` tokens with the highest
34+
* probabilities are sampled. Tokens are then further filtered based on `topP` with the final token
35+
* selected using `temperature` sampling. Defaults to 40 if unspecified.
36+
*
37+
* @property topP The `topP` parameter changes how the model selects tokens for output. Tokens are
38+
* selected from the most to least probable until the sum of their probabilities equals the `topP`
39+
* value. For example, if tokens A, B, and C have probabilities of 0.3, 0.2, and 0.1 respectively
40+
* and the topP value is 0.5, then the model will select either A or B as the next token by using
41+
* the `temperature` and exclude C as a candidate. Defaults to 0.95 if unset.
42+
*
43+
* @property candidateCount The maximum number of generated response messages to return. This value
44+
* must be between [1, 8], inclusive. If unset, this will default to 1.
45+
*
46+
* - Note: Only unique candidates are returned. Higher temperatures are more likely to produce
47+
* unique candidates. Setting `temperature` to 0 will always produce exactly one candidate
48+
* regardless of the `candidateCount`.
49+
*
50+
* @property presencePenalty Positive penalties.
51+
*
52+
* @property frequencyPenalty Frequency penalties.
53+
*
54+
* @property maxOutputTokens Specifies the maximum number of tokens that can be generated in the
55+
* response. The number of tokens per word varies depending on the language outputted. Defaults to 0
56+
* (unbounded).
57+
*
58+
* @property stopSequences A set of up to 5 `String`s that will stop output generation. If
59+
* specified, the API will stop at the first appearance of a stop sequence. The stop sequence will
60+
* not be included as part of the response.
61+
*
62+
* @property responseMimeType Output response MIME type of the generated candidate text (IANA
63+
* standard).
64+
*
65+
* Supported MIME types depend on the model used, but could include:
66+
* - `text/plain`: Text output; the default behavior if unspecified.
67+
* - `application/json`: JSON response in the candidates.
68+
*
69+
* @property responseSchema Output schema of the generated candidate text. If set, a compatible
70+
* [responseMimeType] must also be set.
71+
*
72+
* Compatible MIME types:
73+
* - `application/json`: Schema for JSON response.
74+
*
75+
* Refer to the
76+
* [Control generated output](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output)
77+
* guide for more details.
78+
*/
79+
public class LiveGenerationConfig
80+
private constructor(
81+
internal val temperature: Float?,
82+
internal val topK: Int?,
83+
internal val topP: Float?,
84+
internal val candidateCount: Int?,
85+
internal val maxOutputTokens: Int?,
86+
internal val presencePenalty: Float?,
87+
internal val frequencyPenalty: Float?,
88+
internal val responseModalities: List<ContentModality>?
89+
internal val speechConfig: SpeechConfig?
90+
) {
91+
92+
/**
93+
* Builder for creating a [GenerationConfig].
94+
*
95+
* Mainly intended for Java interop. Kotlin consumers should use [generationConfig] for a more
96+
* idiomatic experience.
97+
*
98+
* @property temperature See [GenerationConfig.temperature].
99+
*
100+
* @property topK See [GenerationConfig.topK].
101+
*
102+
* @property topP See [GenerationConfig.topP].
103+
*
104+
* @property presencePenalty See [GenerationConfig.presencePenalty]
105+
*
106+
* @property frequencyPenalty See [GenerationConfig.frequencyPenalty]
107+
*
108+
* @property candidateCount See [GenerationConfig.candidateCount].
109+
*
110+
* @property maxOutputTokens See [GenerationConfig.maxOutputTokens].
111+
*
112+
* @property stopSequences See [GenerationConfig.stopSequences].
113+
*
114+
* @property responseMimeType See [GenerationConfig.responseMimeType].
115+
*
116+
* @property responseSchema See [GenerationConfig.responseSchema].
117+
* @see [generationConfig]
118+
*/
119+
public class Builder {
120+
@JvmField public var temperature: Float? = null
121+
@JvmField public var topK: Int? = null
122+
@JvmField public var topP: Float? = null
123+
@JvmField public var candidateCount: Int? = null
124+
@JvmField public var maxOutputTokens: Int? = null
125+
@JvmField public var presencePenalty: Float? = null
126+
@JvmField public var frequencyPenalty: Float? = null
127+
@JvmField public var responseModalities: List<SpeechConfig>? = null
128+
@JvmField public var speechConfig: SpeechConfig? = null
129+
130+
/** Create a new [GenerationConfig] with the attached arguments. */
131+
public fun build(): LiveGenerationConfig =
132+
LiveGenerationConfig(
133+
temperature = temperature,
134+
topK = topK,
135+
topP = topP,
136+
candidateCount = candidateCount,
137+
maxOutputTokens = maxOutputTokens,
138+
presencePenalty = presencePenalty,
139+
frequencyPenalty = frequencyPenalty,
140+
responseModalities = responseModalities,
141+
speechConfig = speechConfig
142+
)
143+
}
144+
145+
internal fun toInternal() =
146+
Internal(
147+
temperature = temperature,
148+
topP = topP,
149+
topK = topK,
150+
candidateCount = candidateCount,
151+
maxOutputTokens = maxOutputTokens,
152+
frequencyPenalty = frequencyPenalty,
153+
presencePenalty = presencePenalty,
154+
speechConfig = speechConfig,
155+
responseModalities = responseModalities
156+
)
157+
158+
@Serializable
159+
internal data class Internal(
160+
val temperature: Float?,
161+
@SerialName("top_p") val topP: Float?,
162+
@SerialName("top_k") val topK: Int?,
163+
@SerialName("candidate_count") val candidateCount: Int?,
164+
@SerialName("max_output_tokens") val maxOutputTokens: Int?,
165+
@SerialName("presence_penalty") val presencePenalty: Float? = null,
166+
@SerialName("frequency_penalty") val frequencyPenalty: Float? = null,
167+
@SerialName("speech_config") val speechConfig: SpeechConfig? = null,
168+
@SerialName("response_modalities") val responseModalities: List<ContentModality>? = null
169+
)
170+
171+
public companion object {
172+
173+
/**
174+
* Alternative casing for [GenerationConfig.Builder]:
175+
* ```
176+
* val config = GenerationConfig.builder()
177+
* ```
178+
*/
179+
public fun builder(): Builder = Builder()
180+
}
181+
}
182+
183+
/**
184+
* Helper method to construct a [GenerationConfig] in a DSL-like manner.
185+
*
186+
* Example Usage:
187+
* ```
188+
* generationConfig {
189+
* temperature = 0.75f
190+
* topP = 0.5f
191+
* topK = 30
192+
* candidateCount = 4
193+
* maxOutputTokens = 300
194+
* stopSequences = listOf("in conclusion", "-----", "do you need")
195+
* }
196+
* ```
197+
*/
198+
public fun liveGenerationConfig(init: LiveGenerationConfig.Builder.() -> Unit): LiveGenerationConfig {
199+
val builder = LiveGenerationConfig.builder()
200+
builder.init()
201+
return builder.build()
202+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.google.firebase.vertexai.type
2+
3+
public class LiveSession {
4+
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.google.firebase.vertexai.type
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
class SpeechConfig(val voice_config: VoiceConfig)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.google.firebase.vertexai.type
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
class SpeechConfig(val voice: Voices)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.vertexai.type
18+
19+
import com.google.firebase.vertexai.common.util.FirstOrdinalSerializer
20+
import kotlinx.serialization.KSerializer
21+
import kotlinx.serialization.SerialName
22+
import kotlinx.serialization.Serializable
23+
24+
/** Content part modality. */
25+
public class Voices private constructor(public val ordinal: Int) {
26+
27+
@Serializable(Internal.Serializer::class)
28+
internal enum class Internal {
29+
@SerialName("VOICES_UNSPECIFIED") UNSPECIFIED,
30+
CHARON,
31+
AOEDE
32+
33+
internal object Serializer : KSerializer<Internal> by FirstOrdinalSerializer(Internal::class)
34+
35+
internal fun toPublic() =
36+
when (this) {
37+
CHARON -> Voices.CHARON
38+
AOEDE -> Voices.AOEDE
39+
else -> Voices.UNSPECIFIED
40+
}
41+
}
42+
43+
public companion object {
44+
/** Unspecified modality. */
45+
@JvmField public val UNSPECIFIED: Voices = Voices(0)
46+
47+
/** Plain text. */
48+
@JvmField public val CHARON: Voices = Voices(1)
49+
50+
/** Image. */
51+
@JvmField public val AOEDE: Voices = Voices(2)
52+
}
53+
}

0 commit comments

Comments
 (0)