Kotlin 지원
Kotlin 지원 (Kotlin Support)
Kotlin은 JVM(그리고 다른 플랫폼)을 대상으로 하는 정적 타입 언어로, Java 라이브러리와 원활한 상호운용성으로 간결하고 우아한 코드를 가능하게 해요. LangChain4j는 Kotlin 확장(extensions)과 type-safe builders를 활용해 Java API를 Kotlin 특유의 편의성으로 강화해요. 이를 통해 기존 Java 클래스를 Kotlin에 맞춰 추가 기능으로 확장할 수 있어요.
출처: 공식문서
:::warning
Kotlin 사용자에게 중요한 변경입니다. ChatModel은 이제 Java 멤버 chatAsync(ChatRequest): CompletableFuture<ChatResponse>를 선언해요. Kotlin에서는 같은 시그니처의 멤버가 확장보다 우선하므로, 이전에 suspend 확장(ChatResponse 반환)으로 해석되던 맨 단일-인자 호출이 이제 멤버(CompletableFuture<ChatResponse> 반환)로 해석돼요:
// Before - resolved to the suspend extension, returned ChatResponse:
val response: ChatResponse = model.chatAsync(request)
// After - the bare single-arg call resolves to the Java member (a CompletableFuture):
val future: CompletableFuture<ChatResponse> = model.chatAsync(request)
// Migration - await the future...
val response: ChatResponse = model.chatAsync(request).await()
// ...or supply a coroutineContext, which still selects the suspend extension:
val response: ChatResponse = model.chatAsync(request, Dispatchers.IO)
:::
시작하기 (Getting Started)
프로젝트 의존성에 langchain4j-kotlin 모듈을 추가해요:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-kotlin</artifactId>
<version>[LATEST_VERSION]</version>
</dependency>
데이터 클래스를 사용하려면 클래스패스에 Jackson module kotlin이 있는지 확인해요. Maven에서는 런타임 의존성으로 추가해요:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
<version>[LATEST_VERSION]</version>
<scope>runtime</scope>
</dependency>
ChatModel 확장
이 Kotlin 코드는 coroutines와 suspend functions과 type-safe builders를 사용해 LangChain4j의 ChatModel과 상호작용하는 방법을 보여줘요.
val model = OpenAiChatModel.builder()
.apiKey("YOUR_API_KEY")
// more configuration parameters here ...
.build()
CoroutineScope(Dispatchers.IO).launch {
val response = model.chat {
messages += systemMessage("You are a helpful assistant")
messages += userMessage("Hello!")
parameters {
temperature = 0.7
}
}
println(response.aiMessage().text())
}
상호작용은 Kotlin의 coroutines으로 비동기적으로 일어나요:
CoroutineScope(Dispatchers.IO).launch: 네트워크나 파일 I/O 같은 블로킹 작업에 최적화된 IO dispatcher에서 프로세스를 실행해요. 호출 스레드가 블로킹되는 것을 막아 응답성을 보장해요.model.chat은 suspend 함수로, 빌더 블록을 사용해 채팅 요청을 구조화해요. 이 접근 방식은 보일러플레이트를 줄이고 코드를 더 읽기 쉽고 유지보수 가능하게 만들어요.
고급 시나리오에서 커스텀 ChatRequestParameters를 지원하려면 type-safe builder 함수가 커스텀 빌더를 받아요:
fun <B : DefaultChatRequestParameters.Builder<*>> parameters(
builder: B = DefaultChatRequestParameters.builder() as B,
configurer: ChatRequestParametersBuilder<B>.() -> Unit
)
사용 예시:
model.chat {
messages += systemMessage("You are a helpful assistant")
messages += userMessage("Hello!")
parameters(OpenAiChatRequestParameters.builder()) {
temperature = 0.7 // DefaultChatRequestParameters.Builder property
builder.seed(42) // OpenAiChatRequestParameters.Builder property
}
}
스트리밍 사용 사례
StreamingChatModel 확장은 AI 모델이 생성할 때 응답을 점진적으로 처리해야 하는 사용 사례에 기능을 제공해요. 채팅 인터페이스, 라이브 편집기, 토큰 단위 스트리밍 상호작용 시스템처럼 실시간 피드백이 필요한 애플리케이션에서 특히 유용해요. Kotlin coroutines을 사용하면 chatFlow 확장 함수가 언어 모델의 스트리밍 응답을 구조화되고 취소 가능한 Flow 시퀀스로 변환해 coroutine 친화적이고 논블로킹인 구현을 가능하게 해요.
chatFlow로 완전한 상호작용을 구현하는 방법은 다음과 같아요:
val flow = model.chatFlow { // similar to non-streaming scenario
messages += userMessage("Can you explain how streaming works?")
parameters { // ChatRequestParameters
temperature = 0.7
maxOutputTokens = 42
}
}
runBlocking { // must run in a coroutine context
flow.collect { reply ->
when (reply) {
is StreamingChatModelReply.PartialResponse -> {
print(reply.partialResponse) // Stream output as it arrives
}
is StreamingChatModelReply.CompleteResponse -> {
println("\nComplete: ${reply.response.aiMessage().text()}")
}
is StreamingChatModelReply.Error -> {
println("Error occurred: ${reply.cause.message}")
}
}
}
}
이 테스트를 예시로 확인해요.
컴파일러 호환성
Kotlin에서 도구를 정의할 때 메서드 파라미터에 대한 Java 리플렉션 메타데이터를 보존하도록 javaParameters를 true로 설정해 Kotlin 컴파일을 구성해야 해요. 이 설정은 도구 명세에서 올바른 인자 이름을 유지하는 데 필요해요.
Gradle을 사용할 때는 다음 구성으로 할 수 있어요:
kotlin {
compilerOptions {
javaParameters = true
}
}