概要
(日記)KotlinかJavaのSDKがあればよいのだが、無いものはしかたないのでの自前で型定義を。
環境
- Ubuntu 24.04
- Kotlin 2.0.20
- Node.js v22.4.1
Quick Start
build.gradle.kts
plugins {kotlin("multiplatform") version "2.0.20"}
repositories {mavenCentral()}
kotlin {
js {
nodejs()
binaries.executable()
}
sourceSets {
jsMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
implementation(npm("@google/generative-ai", "0.19.0"))
}
}
}
src/commonMain/kotlin/Main.kt - シンプルな一問一答
import google.generativeai.GEMINI_1_5_FLASH
import google.generativeai.GoogleGenerativeAI
import kotlinx.coroutines.await
import kotlin.js.json
suspend fun main() {
val apiKey = getApiKey()
val genai = GoogleGenerativeAI(apiKey)
val model = genai.getGenerativeModel(json("model" to GEMINI_1_5_FLASH))
val result = model.generateContent("三角、四角、五角形、の次は? 簡潔に").await()
println(result.response.text())
}
src/jsMain/kotlin/GoogleGenerativeAI.kt - 型情報の外部宣言(js依存コード)
@file:JsModule("@google/generative-ai") // NPMモジュール名
@file:JsNonModule
package google.generativeai
import kotlin.js.Json
import kotlin.js.Promise
actual external class GoogleGenerativeAI actual constructor(apiKey: String) {
actual fun getGenerativeModel(params: Json): GenerativeModel
}
actual external class GenerativeModel {
actual fun generateContent(request: String): Promise<GenerateContentResult>
}
// 以下略...
- 名前空間(複数クラス等)をexportするNPMモジュールを参照する場合、packageに対して@JsModuleを付与する
- suspend関数としてマップしたいが、まずはPropmse.await()
- multiplatformということで対応するexpect定義ファイルも必要(
src/commonMain/kotlin/GoogleGenerativeAI.kt
)
テスト実行
export GOOGLE_API_KEY=<your-api-key>
export kotest_filter_tests="generateContent" # テスト対象を指定する場合
sh gradlew jsNodeTest
テストレポート: build/reports/tests/jsNodeTest/index.html
チャット
以下kotest用のテストコード
src/commonTest/kotlin/Tests.kt
//..
test("startChat") {
val apiKey = getApiKey()
val genai = GoogleGenerativeAI(apiKey)
val model = genai.getGenerativeModel(json("model" to GEMINI_1_5_FLASH))
val chat = model.startChat()
chat.sendMessage("三角、四角、の次は? 簡潔に").await().response.text().also(::println) shouldContain "五角"
chat.sendMessage("その次は? 簡潔に").await().response.text().also(::println) shouldContain "六角"
chat.sendMessage("最後の答えの前は? 簡潔に").await().response.text()
.also(::println) shouldContain Regex("五角")
}
//..
※AIの答えなので必ずテストが成功するとは限らない...