uncloseai.
Kotlin Examples - Free LLM & TTS AI Service
Kotlin Examples
This page demonstrates how to use the uncloseai. API endpoints with Kotlin using the openai-kotlin community library. All examples use the same OpenAI-compatible API interface, making it easy to switch between different models and endpoints.
Available Endpoints:
- hermes.ai.unturf.com:
https://hermes.ai.unturf.com/v1- chat completions on an RTX 4090 - qwen.ai.unturf.com:
https://qwen.ai.unturf.com/v1- chat completions on an RTX 3090 - TTS:
https://speech.ai.unturf.com/v1- Text-to-speech generation
Both chat hostnames currently serve the same model, turboderp/Qwen3.8-27B-exl3 (read live from /v1/models). Hostnames are routing labels, not model names: every example below asks the endpoint which model it serves instead of hard-coding an id, so a model swap on the cards never breaks your code. The served model reasons before it answers (the reasoning arrives in a separate reasoning field), so give it room: the samples ask for 600 tokens because at 150 the budget ran out before the answer began.
Many endpoints from environment variables
Our clients (uncloseai-cli, uncloseai.js, opencompletion and the downloadable implementation for every language on this site) share one convention, so an endpoint is configuration, never code:
| Variable | Meaning |
|---|---|
MODEL_ENDPOINT_N | Base URL of the N-th OpenAI-compatible endpoint, ending in /v1. The only required variable. Scan N from 0 upward and skip gaps: uncloseai-cli counts from 0, the per-language implementations from 1. |
MODEL_API_KEY_N | Bearer key for endpoint N. Unset means no key, which is all our free relay needs; a cloud endpoint sets one. |
MODEL_ID_N | Model id to send. Unset means ask /v1/models and take the first id, the rule used by every sample on this page. |
MODEL_LABEL_N | A display name for endpoint N; defaults to its hostname. |
TTS_ENDPOINT_N | The same shape for text-to-speech endpoints. |
export MODEL_ENDPOINT_0="https://hermes.ai.unturf.com/v1"
export MODEL_ENDPOINT_1="https://qwen.ai.unturf.com/v1"
# export MODEL_API_KEY_1="sk-..." # only for an endpoint that needs one
export TTS_ENDPOINT_0="https://speech.ai.unturf.com/v1"
The first endpoint is the default; the rest fail over, in order. The Kotlin implementation under /languages/ reads these variables and discovers each endpoint's models at startup.
Kotlin Client Installation
Add openai-kotlin to your build.gradle.kts:
dependencies {
implementation("com.aallam.openai:openai-client:3.8.2")
implementation("io.ktor:ktor-client-okhttp:2.3.12")
}
Non-Streaming Examples
Non-streaming mode waits for the complete response before returning. This is simpler to use but provides no intermediate feedback during generation.
Using hermes.ai.unturf.com (RTX 4090)
import com.aallam.openai.api.chat.*
import com.aallam.openai.client.OpenAI
import com.aallam.openai.client.OpenAIConfig
import com.aallam.openai.client.OpenAIHost
suspend fun main() {
val openAI = OpenAI(
OpenAIConfig(
token = "choose-any-value",
host = OpenAIHost("https://hermes.ai.unturf.com/v1")
)
)
// Ask the endpoint which model it serves; never hard-code an id.
val model = openAI.models().first().id
val chatCompletionRequest = ChatCompletionRequest(
model = model,
messages = listOf(
ChatMessage(
role = ChatRole.User,
content = "Give a Python Fizzbuzz solution in one line of code?"
)
),
temperature = 0.5,
maxTokens = 600
)
val completion = openAI.chatCompletion(chatCompletionRequest)
println(completion.choices[0].message.content)
}
Using qwen.ai.unturf.com (RTX 3090)
import com.aallam.openai.api.chat.*
import com.aallam.openai.client.OpenAI
import com.aallam.openai.client.OpenAIConfig
import com.aallam.openai.client.OpenAIHost
suspend fun main() {
val openAI = OpenAI(
OpenAIConfig(
token = "choose-any-value",
host = OpenAIHost("https://qwen.ai.unturf.com/v1")
)
)
// Ask the endpoint which model it serves; never hard-code an id.
val model = openAI.models().first().id
val chatCompletionRequest = ChatCompletionRequest(
model = model,
messages = listOf(
ChatMessage(
role = ChatRole.User,
content = "Give a Python Fizzbuzz solution in one line of code?"
)
),
temperature = 0.5,
maxTokens = 600
)
val completion = openAI.chatCompletion(chatCompletionRequest)
println(completion.choices[0].message.content)
}
Streaming Examples
Streaming mode returns chunks of the response as they are generated, providing real-time feedback. This is ideal for interactive applications and long responses.
Using hermes.ai.unturf.com (RTX 4090)
import com.aallam.openai.api.chat.*
import com.aallam.openai.client.OpenAI
import com.aallam.openai.client.OpenAIConfig
import com.aallam.openai.client.OpenAIHost
import kotlinx.coroutines.flow.collect
suspend fun main() {
val openAI = OpenAI(
OpenAIConfig(
token = "choose-any-value",
host = OpenAIHost("https://hermes.ai.unturf.com/v1")
)
)
// Ask the endpoint which model it serves; never hard-code an id.
val model = openAI.models().first().id
val chatCompletionRequest = ChatCompletionRequest(
model = model,
messages = listOf(
ChatMessage(
role = ChatRole.User,
content = "Give a Python Fizzbuzz solution in one line of code?"
)
),
temperature = 0.5,
maxTokens = 600
)
openAI.chatCompletions(chatCompletionRequest).collect { chunk ->
chunk.choices.forEach { choice ->
choice.delta.content?.let { print(it) }
}
}
}
Using qwen.ai.unturf.com (RTX 3090)
import com.aallam.openai.api.chat.*
import com.aallam.openai.client.OpenAI
import com.aallam.openai.client.OpenAIConfig
import com.aallam.openai.client.OpenAIHost
import kotlinx.coroutines.flow.collect
suspend fun main() {
val openAI = OpenAI(
OpenAIConfig(
token = "choose-any-value",
host = OpenAIHost("https://qwen.ai.unturf.com/v1")
)
)
// Ask the endpoint which model it serves; never hard-code an id.
val model = openAI.models().first().id
val chatCompletionRequest = ChatCompletionRequest(
model = model,
messages = listOf(
ChatMessage(
role = ChatRole.User,
content = "Give a Python Fizzbuzz solution in one line of code?"
)
),
temperature = 0.5,
maxTokens = 600
)
openAI.chatCompletions(chatCompletionRequest).collect { chunk ->
chunk.choices.forEach { choice ->
choice.delta.content?.let { print(it) }
}
}
}
Text-to-Speech Example
Generate audio speech from text using the TTS endpoint. The audio is saved as an MP3 file.
import com.aallam.openai.api.audio.SpeechRequest
import com.aallam.openai.api.audio.Voice
import com.aallam.openai.api.model.ModelId
import com.aallam.openai.client.OpenAI
import com.aallam.openai.client.OpenAIConfig
import com.aallam.openai.client.OpenAIHost
import java.io.File
suspend fun main() {
val openAI = OpenAI(
OpenAIConfig(
token = "YOLO",
host = OpenAIHost("https://speech.ai.unturf.com/v1")
)
)
val speechRequest = SpeechRequest(
model = ModelId("tts-1-f5"),
input = "I think so therefore, Today is a wonderful day to grow something people love!",
voice = Voice("foxhop"),
speed = 0.9
)
val speech = openAI.speech(speechRequest)
File("speech.mp3").writeBytes(speech)
}