in prompt/prompt-executor/prompt-executor-clients/prompt-executor-google-client/src/commonMain/kotlin/ai/koog/prompt/executor/clients/google/GoogleLLMClient.kt [166:221]
override fun executeStreaming(
prompt: Prompt,
model: LLModel,
tools: List<ToolDescriptor>
): Flow<StreamFrame> = streamFrameFlow {
logger.debug { "Executing streaming prompt: $prompt with model: $model" }
require(model.capabilities.contains(LLMCapability.Completion)) {
"Model ${model.id} does not support chat completions"
}
val request = createGoogleRequest(prompt, model, tools)
try {
httpClient.sse(
path = "${settings.defaultPath}/${model.id}:${settings.streamGenerateContentMethod}",
request = request,
requestBodyType = GoogleRequest::class,
dataFilter = { it != "[DONE]" },
decodeStreamingResponse = { json.decodeFromString<GoogleResponse>(it) },
parameters = mapOf("alt" to "sse"),
processStreamingChunk = { it }
).collect { response ->
val meta = response.usageMetadata?.let {
ResponseMetaInfo.create(
clock = clock,
totalTokensCount = it.totalTokenCount,
inputTokensCount = it.promptTokenCount,
outputTokensCount = it.candidatesTokenCount,
)
}
response.candidates.firstOrNull()?.let { candidate ->
candidate.content?.parts?.forEach { part ->
when (part) {
is GooglePart.FunctionCall -> emitToolCall(
id = part.functionCall.id,
name = part.functionCall.name,
content = part.functionCall.args?.toString() ?: "{}"
)
is GooglePart.Text -> emitAppend(part.text)
else -> Unit
}
}
candidate.finishReason?.let { emitEnd(it, meta) }
}
}
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
throw LLMClientException(
clientName = clientName,
message = e.message,
cause = e
)
}
}