Skip to content

Commit 7205b14

Browse files
committed
Refactor tests and enhance async service documentation
Updated test to use `runTest` for coroutines and refactored a function to be `suspend`. Expanded README to provide detailed documentation on `AsyncAiServices`, including usage scenarios, benefits, and example implementations.
1 parent cd360f7 commit 7205b14

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-5
lines changed

README.md

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ model.chatFlow {
139139

140140
### Async AI Services
141141

142-
The library adds support for coroutine-based async AI services:
142+
The library adds support for coroutine-based async AI services through the `AsyncAiServices` class, which leverages
143+
Kotlin's coroutines for efficient asynchronous operations:
143144

144145
```kotlin
145146
// Define your service interface with suspending function
@@ -150,7 +151,7 @@ interface Assistant {
150151

151152
// Create the service using AsyncAiServicesFactory
152153
val assistant = createAiService(
153-
serviceClass = AsyncAssistant::class.java,
154+
serviceClass = Assistant::class.java,
154155
factory = AsyncAiServicesFactory(),
155156
).chatModel(model)
156157
.build()
@@ -160,9 +161,44 @@ runBlocking {
160161
val response = assistant.chat("John", "What is Kotlin?")
161162
println(response)
162163
}
164+
```
165+
166+
#### Advanced Usage Scenarios
167+
168+
The `AsyncAiServices` implementation uses `HybridVirtualThreadInvocationHandler` under the hood,
169+
which supports multiple invocation patterns:
170+
171+
1. **Suspend Functions**: Native Kotlin coroutines support
172+
2. **CompletionStage/CompletableFuture**: For Java-style async operations
173+
3. **Blocking Operations**: Automatically run on virtual threads (Java 21+)
174+
175+
Example with different return types:
163176

177+
```kotlin
178+
interface AdvancedAssistant {
179+
// Suspend function
180+
@UserMessage("Summarize: {{text}}")
181+
suspend fun summarize(text: String): String
182+
183+
// CompletionStage return type for Java interoperability
184+
@UserMessage("Analyze sentiment: {{text}}")
185+
fun analyzeSentiment(text: String): CompletionStage<String>
186+
187+
// Blocking operation (runs on virtual thread)
188+
@Blocking
189+
@UserMessage("Process document: {{document}}")
190+
fun processDocument(document: String): String
191+
}
164192
```
165193

194+
#### Benefits
195+
196+
- **Efficient Resource Usage**: Suspending functions don't block threads during I/O or waiting
197+
- **Java Interoperability**: Support for CompletionStage/CompletableFuture return types
198+
- **Virtual Thread Integration**: Automatic handling of blocking operations on virtual threads
199+
- **Simplified Error Handling**: Leverage Kotlin's structured concurrency for error propagation
200+
- **Reduced Boilerplate**: No need for manual callback handling or future chaining
201+
166202
### Kotlin Notebook
167203

168204
The [Kotlin Notebook](https://kotlinlang.org/docs/kotlin-notebook-overview.html) environment allows you to:
@@ -174,7 +210,7 @@ The [Kotlin Notebook](https://kotlinlang.org/docs/kotlin-notebook-overview.html)
174210

175211
You can easily get started with LangChain4j-Kotlin notebooks:
176212

177-
```kotlin notebook
213+
```kotlin
178214
%useLatestDescriptors
179215
%use coroutines
180216

langchain4j-kotlin/src/test/kotlin/me/kpavlov/langchain4j/kotlin/service/ServiceWithPromptTemplatesTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ import dev.langchain4j.service.UserName
1313
import dev.langchain4j.service.V
1414
import io.kotest.matchers.collections.shouldHaveSize
1515
import io.kotest.matchers.shouldBe
16+
import kotlinx.coroutines.test.runTest
1617
import org.junit.jupiter.api.Test
1718

1819
internal class ServiceWithPromptTemplatesTest {
1920
@Test
20-
fun `Should use System and User Prompt Templates`() {
21+
fun `Should use System and User Prompt Templates`() = runTest {
2122
val chatResponse =
2223
ChatResponse
2324
.builder()
@@ -62,7 +63,7 @@ internal class ServiceWithPromptTemplatesTest {
6263
@dev.langchain4j.service.UserMessage(
6364
"prompts/ServiceWithTemplatesTest/default-user-prompt.mustache",
6465
)
65-
fun askQuestion(
66+
suspend fun askQuestion(
6667
@UserName userName: String,
6768
@V("message") question: String,
6869
): String

0 commit comments

Comments
 (0)