经 AI Skill Hub 精选评估,Llamatik 获评「强烈推荐」。这款AI工具在功能完整性、社区活跃度和易用性方面表现出色,AI 评分 8.0 分,适合有一定技术背景的用户使用。
Llamatik 是一款基于 Kotlin 开发的开源工具,专注于 ai、kotlin、android 等核心功能。作为 GitHub 开源项目,它拥有活跃的社区支持和持续的版本迭代,代码完全透明可审计,支持本地部署以保护数据隐私。无论是个人使用还是集成到企业工作流,都能提供稳定可靠的解决方案。
Llamatik 是一款基于 Kotlin 开发的开源工具,专注于 ai、kotlin、android 等核心功能。作为 GitHub 开源项目,它拥有活跃的社区支持和持续的版本迭代,代码完全透明可审计,支持本地部署以保护数据隐私。无论是个人使用还是集成到企业工作流,都能提供稳定可靠的解决方案。
# 克隆仓库 git clone https://github.com/ferranpons/Llamatik cd Llamatik # 查看安装说明 cat README.md # 按 README 完成环境依赖安装后即可使用
# 查看帮助 llamatik --help # 基本运行 llamatik [options] <input> # 详细使用说明请查阅文档 # https://github.com/ferranpons/Llamatik
# llamatik 配置说明 # 查看配置选项 llamatik --config-example > config.yml # 常见配置项 # output_dir: ./output # log_level: info # workers: 4 # 环境变量(覆盖配置文件) export LLAMATIK_CONFIG="/path/to/config.yml"
<p align="center"> <img src="https://raw.githubusercontent.com/ferranpons/llamatik/main/assets/llamatik-new-logo.png" alt="Llamatik Logo" width="150"/> </p>
<p align="center"> <b>Run AI locally on Android, iOS, Desktop and WASM — using a single Kotlin API.</b> </p>
<p align="center"> Offline-first · Privacy-preserving · True Kotlin Multiplatform </p>
<p align="center"> <a href="https://central.sonatype.com/artifact/com.llamatik/library"><img src="https://img.shields.io/maven-central/v/com.llamatik/library.svg" alt="maven central badge"/></a> <img src="https://img.shields.io/badge/Kotlin-Multiplatform-blueviolet" alt="kmp badge"/> <img src="https://img.shields.io/badge/Platforms-Android%20%7C%20iOS%20%7C%20Desktop%20%7C%20WASM-green" alt="platforms badge"/> <img src="https://img.shields.io/badge/LLM-llama.cpp-orange" alt="llama.cpp badge"/> <img src="https://img.shields.io/badge/STT-whisper.cpp-blue" alt="whisper.cpp badge"/> <img src="https://img.shields.io/badge/Image-stablediffusion.cpp-purple" alt="stablediffusion badge"/> <img src="https://img.shields.io/badge/License-MIT-lightgrey" alt="license badge"/> <a href="https://plugins.jetbrains.com/plugin/31304"><img src="https://img.shields.io/jetbrains/plugin/v/31304" alt="jetbrains plugin badge"/></a> </p>
---
<img align="right" width="0" height="368px" hspace="20"/> <img src="assets/androidScreenshots/phoneScreenshot3.png" height="368px" align="right" />
Want to see Llamatik in action before integrating it?
The Llamatik App showcases: - On-device inference - Streaming generation - Speech-to-text (Whisper) - Privacy-first AI (no cloud required) - Downloadable models
<a href="https://play.google.com/store/apps/details?id=com.llamatik.app.android"><img src="assets/google-play-button.png" width="200px"/></a> <a href="https://apple.co/3Md7EIh"><img src="assets/app-store-button.png" width="200px"/></a>
---
Llamatik is published on Maven Central and follows semantic versioning.
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
commonMain.dependencies {
implementation("com.llamatik:library:1.7.0")
}
---
---
// Resolve model path (place GGUF in assets / bundle)
val modelPath = LlamaBridge.getModelPath("phi-2.Q4_0.gguf")
// (Optional) tune parameters before loading — contextLength/useMmap/flashAttention/gpuLayers
// take effect at model init time; the others can be changed at any time
LlamaBridge.updateGenerateParams(
temperature = 0.7f,
maxTokens = 512,
topP = 0.95f,
topK = 40,
repeatPenalty = 1.1f,
contextLength = 4096,
numThreads = 4,
useMmap = true,
flashAttention = false,
gpuLayers = 0,
)
// Load model
LlamaBridge.initGenerateModel(modelPath)
// Generate text
val output = LlamaBridge.generate(
"Explain Kotlin Multiplatform in one sentence."
)
---
The public Kotlin API is defined in LlamaBridge (an expect object with platform-specific actual implementations).
The Llamatik backend server is now maintained in a dedicated repository.
👉 Llamatik Server Repository https://github.com/ferranpons/Llamatik-Server
Visit the repository for full setup instructions, configuration options, and usage details.
---
@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
expect object LlamaBridge {
// Utilities
fun getModelPath(modelFileName: String): String // copy asset/bundle model to app files dir and return absolute path
fun shutdown() // free native resources
// Embeddings
fun initEmbedModel(modelPath: String): Boolean // load embeddings model
fun embed(input: String): FloatArray // return embedding vector
// Text generation (non-streaming)
fun initGenerateModel(modelPath: String): Boolean // load generation model
fun generate(prompt: String): String
fun generateWithContext(
systemPrompt: String,
contextBlock: String,
userPrompt: String
): String
// Text generation (streaming)
fun generateStream(prompt: String, callback: GenStream)
fun generateStreamWithContext(
systemPrompt: String,
contextBlock: String,
userPrompt: String,
callback: GenStream
)
// Convenience streaming overload (lambda callbacks)
fun generateWithContextStream(
system: String,
context: String,
user: String,
onDelta: (String) -> Unit,
onDone: () -> Unit,
onError: (String) -> Unit
)
// Text generation with JSON schema (non-streaming)
fun generateJson(prompt: String, jsonSchema: String? = null): String
fun generateJsonWithContext(
systemPrompt: String,
contextBlock: String,
userPrompt: String,
jsonSchema: String? = null
): String
// Text generation with JSON schema (streaming)
fun generateJsonStream(prompt: String, jsonSchema: String? = null, callback: GenStream)
fun generateJsonStreamWithContext(
systemPrompt: String,
contextBlock: String,
userPrompt: String,
jsonSchema: String? = null,
callback: GenStream
)
// Model metadata
fun getModelFinetuneType(): String? // "general.finetune" GGUF key — e.g. "instruct", "chat"; null means base model
// Chat template support
fun getModelChatTemplate(): String? // returns the chat template embedded in the loaded GGUF, or null
fun applyChatTemplate(
messages: List<Pair<String, String>>, // list of (role, content) pairs
addAssistantPrefix: Boolean // true to append the assistant turn prefix
): String? // rendered prompt string, or null if model/template unavailable
// KV cache session support
fun sessionReset(): Boolean // clear KV state, keep model loaded
fun sessionSave(path: String): Boolean // persist KV state to file
fun sessionLoad(path: String): Boolean // restore KV state from file
fun generateContinue(prompt: String): String // generate using existing KV cache
// Concurrent sessions — each session owns an isolated KV cache; model weights are shared
fun createSession(name: String = ""): LlamaSession? // null on WASM (not supported)
// Generation parameters (applied on next generate call)
fun updateGenerateParams(
temperature: Float, // randomness (0.0–2.0)
maxTokens: Int, // max output tokens
topP: Float, // nucleus sampling threshold
topK: Int, // top-k sampling
repeatPenalty: Float, // penalty for repeated tokens
contextLength: Int, // KV context window size (requires model reload)
numThreads: Int, // CPU threads for inference
useMmap: Boolean, // memory-map model weights (requires model reload)
flashAttention: Boolean, // enable Flash Attention (requires model reload)
batchSize: Int, // token batch size for prompt processing (requires model reload)
gpuLayers: Int = 0, // layers to offload to GPU: 0 = CPU only, -1 = all layers, N = exactly N layers (requires model reload)
)
fun nativeCancelGenerate() // cancel ongoing generation
// Multi-Token Prediction (MTP) — speculative drafting
fun initMtp(modelPath: String, draftLen: Int = 3): Boolean // enable MTP; same GGUF as generation model
fun shutdownMtp() // disable MTP; generation continues without it
}
interface GenStream {
fun onDelta(text: String)
fun onComplete()
fun onError(message: String)
}
// Concurrent session handle — created via LlamaBridge.createSession()
expect class LlamaSession {
val name: String // human-readable label assigned at creation
fun stream(prompt: String, callback: GenStream) // run inference in this session's context
fun cancel() // cancel the in-progress stream
fun close() // release native KV cache resources
}
object WhisperBridge {
/** Returns a platform-specific absolute path for the model filename. */
fun getModelPath(modelFileName: String): String
/** Loads the model at [modelPath]. Returns true if loaded. */
fun initModel(modelPath: String): Boolean
/**
* Transcribes a WAV file and returns text.
* Tip: record WAV as 16 kHz, mono, 16-bit PCM for best compatibility.
*
* @param initialPrompt Optional text prepended to the decoder input (up to 224 tokens).
* Use it to bias transcription toward domain-specific vocabulary (e.g. medical terms).
*/
fun transcribeWav(wavPath: String, language: String? = null, initialPrompt: String? = null): String
/** Frees native resources. */
fun release()
}
import com.llamatik.library.platform.WhisperBridge
val modelPath = WhisperBridge.getModelPath("ggml-tiny-q8_0.bin")
// 1) Init once (e.g. app start)
WhisperBridge.initModel(modelPath)
// 2) Record to a WAV file (16kHz mono PCM16) using your own recorder
val wavPath: String = "/path/to/recording.wav"
// 3) Transcribe
val text = WhisperBridge.transcribeWav(wavPath, language = null).trim()
println(text)
// 4) Optional: release on app shutdown
WhisperBridge.release()
Note: WhisperBridge expects a WAV file path. Llamatik’s app uses AudioRecorder + AudioPaths.tempWavPath() to generate the WAV before calling transcribeWav(...).
object StableDiffusionBridge {
/** Returns absolute model path (copied from assets/bundle if needed). */
fun getModelPath(modelFileName: String): String
/**
* Loads the Stable Diffusion model.
* @param threads CPU threads to use; -1 lets the backend decide.
*/
fun initModel(modelPath: String, threads: Int = -1): Boolean
/**
* Text-to-image generation. Returns raw RGBA pixels (width * height * 4 bytes).
* Returns an empty array on failure.
*/
fun txt2img(
prompt: String,
negativePrompt: String? = null,
width: Int = 512,
height: Int = 512,
steps: Int = 20,
cfgScale: Float = 7.0f,
seed: Long = -1L,
): ByteArray
/**
* Image-to-image generation. Starts from [initImageRgba] and steers it with [prompt].
* [strength] controls how much the source image is preserved (0.0 = unchanged, 1.0 = ignored).
* Returns raw RGBA pixels (width * height * 4 bytes). Returns an empty array on failure.
*/
fun img2img(
initImageRgba: ByteArray,
initImageW: Int,
initImageH: Int,
prompt: String,
negativePrompt: String? = null,
width: Int = 512,
height: Int = 512,
steps: Int = 20,
cfgScale: Float = 7.0f,
strength: Float = 0.75f,
seed: Long = -1L,
): ByteArray
/** Releases native resources. */
fun release()
}
import com.llamatik.library.platform.StableDiffusionBridge
val modelPath = StableDiffusionBridge.getModelPath("dreamshaper.safetensors")
StableDiffusionBridge.initModel(modelPath, threads = 4)
val rgba = StableDiffusionBridge.txt2img(
prompt = "A cyberpunk llama in neon Tokyo",
negativePrompt = "blurry, low quality",
width = 512,
height = 512,
steps = 20,
cfgScale = 7.0f,
seed = 42L,
)
// Convert rgba (ByteArray, width*height*4) to a platform Bitmap / UIImage / BufferedImage
val sourceRgba: ByteArray = /* existing RGBA image bytes */
val rgba = StableDiffusionBridge.img2img(
initImageRgba = sourceRgba,
initImageW = 512,
initImageH = 512,
prompt = "The same scene as a watercolor painting",
negativePrompt = "low quality",
strength = 0.75f,
seed = 42L,
)
object MultimodalBridge {
/**
* Load the vision model and its multimodal projector (mmproj) side-by-side.
* Both files must be available on disk before calling this.
*
* @param modelPath Absolute path to the GGUF vision model.
* @param mmprojPath Absolute path to the GGUF mmproj file.
* @return true on success.
*/
fun initModel(modelPath: String, mmprojPath: String): Boolean
/**
* Analyze an image given as raw bytes (JPEG/PNG/BMP), streaming the response
* token by token via [callback].
*
* Must be called from a background thread/coroutine; blocks until generation completes.
*/
fun analyzeImageBytesStream(imageBytes: ByteArray, prompt: String, callback: GenStream)
/** Cancel an in-progress analyzeImageBytesStream call. */
fun cancelAnalysis()
/** Free all native resources (model, mmproj context, llama context). */
fun release()
}
import com.llamatik.library.platform.MultimodalBridge
// 1) Init once — both model and mmproj must be downloaded first
val loaded = MultimodalBridge.initModel(
modelPath = "/path/to/SmolVLM-256M-Instruct-Q8_0.gguf",
mmprojPath = "/path/to/mmproj-SmolVLM-256M-Instruct-f16.gguf"
)
// 2) Analyze an image (e.g. loaded from disk or camera)
val imageBytes: ByteArray = File("/path/to/photo.jpg").readBytes()
MultimodalBridge.analyzeImageBytesStream(
imageBytes = imageBytes,
prompt = "Describe what you see in this image.",
callback = object : GenStream {
override fun onDelta(text: String) { print(text) }
override fun onComplete() { println("\n[done]") }
override fun onError(message: String){ println("Error: $message") }
}
)
// 3) Optional: cancel mid-stream
MultimodalBridge.cancelAnalysis()
// 4) Optional: release on app shutdown
MultimodalBridge.release()
Note: MultimodalBridge requires both a vision model GGUF and a matching mmproj GGUF. Llamatik's app downloads both automatically when you select a VLM model.
---
高性能的AI工具,支持多平台
AI Skill Hub 为第三方内容聚合平台,本页面信息基于公开数据整理,不对工具功能和质量作任何法律背书。
建议在沙箱或测试环境中充分验证后,再部署至生产环境,并做好必要的安全评估。
✅ MIT 协议 — 最宽松的开源协议之一,可自由商用、修改、分发,仅需保留版权声明。
AI Skill Hub 点评:Llamatik 的核心功能完整,质量优秀。对于AI 技术爱好者来说,这是一个值得纳入个人工具库的选择。建议先在非生产环境试用,再逐步推广。
| 原始名称 | Llamatik |
| 原始描述 | 开源AI工具:True on-device AI for Kotlin Multiplatform (Android, iOS, Desktop, JVM, WASM). L。⭐150 · Kotlin |
| Topics | aikotlinandroiddesktop |
| GitHub | https://github.com/ferranpons/Llamatik |
| License | MIT |
| 语言 | Kotlin |
收录时间:2026-06-16 · 更新时间:2026-06-16 · License:MIT · AI Skill Hub 不对第三方内容的准确性作法律背书。