Rozwinięcie kodu dla Androida: Integracja z TensorFlow Lite
Dla trybu online możesz użyć API (np. Grok 3) do wyszukiwania/analizy, ale dla offline/hybrydowego – TensorFlow Lite (TFLite) do uruchamiania zoptymalizowanych modeli LLM (np. Llama 3 lub Phi-3) na urządzeniu. TFLite jest lekkie, działa na CPU/GPU Androida i wspiera kwantyzację (zmniejszanie modelu do 4-bit, by zmieścił się w 4-8 GB RAM).Krok 1: Przygotowanie modeluPrzykład kodu: Prosta app z polem tekstowym, przyciskiem do zapytania i odpowiedzią od modelu. Hybrydowy tryb: Offline via TFLite, online via HTTP do API (np. Grok).Krok 3: Dodatkowe funkcje
- Pobierz model open-source (np. Llama 3 7B z Hugging Face).
- Skonwertuj do formatu TFLite:bash
# Użyj Pythona z TensorFlow (na komputerze) pip install tensorflow transformers
pythonimport tensorflow as tf from transformers import AutoModelForCausalLM, AutoTokenizer import torch model_name = "meta-llama/Llama-3-7b" model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float16) tokenizer = AutoTokenizer.from_pretrained(model_name) # Konwersja do TFLite (uproszczona; użyj full guide z TensorFlow docs) converter = tf.lite.TFLiteConverter.from_saved_model("./optimized_model") converter.optimizations = [tf.lite.Optimize.DEFAULT] # Kwantyzacja tflite_model = converter.convert() with open("model.tflite", "wb") as f: f.write(tflite_model) tokenizer.save_pretrained("./tokenizer")
- Przenieś model.tflite i tokenizer do assets w Android Studio.
kotlin
dependencies {
implementation("org.tensorflow:tensorflow-lite:2.15.0")
implementation("org.tensorflow:tensorflow-lite-support:0.4.4")
implementation("androidx.compose.ui:ui:1.6.0") // Dla UI
// ... inne
}
kotlin
// MainActivity.kt
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import org.tensorflow.lite.Interpreter
import java.nio.MappedByteBuffer
import java.io.FileInputStream
import java.io.IOException
import java.nio.channels.FileChannel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.* // Dodaj OkHttp dla online
import java.io.InputStream
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
AgentScreen()
}
}
}
}
}
@Composable
fun AgentScreen() {
var inputText by remember { mutableStateOf("") }
var outputText by remember { mutableStateOf("") }
var isOnline by remember { mutableStateOf(true) } // Przełącznik trybu
Column(modifier = Modifier.padding(16.dp)) {
TextField(
value = inputText,
onValueChange = { inputText = it },
label = { Text("Twoje zapytanie") },
modifier = Modifier.fillMaxWidth()
)
Button(onClick = {
// Wywołaj funkcję odpowiedzi
outputText = if (isOnline) {
// Online: API call (np. Grok)
fetchOnlineResponse(inputText)
} else {
// Offline: TFLite
runTFLiteInference(inputText)
}
}) {
Text("Wyślij")
}
Text("Odpowiedź: $outputText")
Switch(checked = isOnline, onCheckedChange = { isOnline = it })
Text("Tryb online: $isOnline")
}
}
// Funkcja offline: TFLite inference
fun runTFLiteInference(input: String): String {
// Wczytaj model z assets
val modelBuffer = loadModelFile("model.tflite") // Implementuj loadModelFile poniżej
val tflite = Interpreter(modelBuffer)
// Tokenizacja (uproszczona; użyj full tokenizer)
val tokenizerInput = tokenizeInput(input) // Zaimplementuj z HuggingFace tokenizer (lub prosty)
// Uruchom inferencję
val output = Array(1) { FloatArray(1000) } // Dostosuj wymiary
tflite.run(tokenizerInput, output)
tflite.close()
return decodeOutput(output) // Dekoduj do tekstu
}
// Ładowanie modelu z assets
@Throws(IOException::class)
private fun loadModelFile(modelPath: String): MappedByteBuffer {
val fileDescriptor = assets.openFd(modelPath)
val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
val fileChannel = inputStream.channel
val startOffset = fileDescriptor.startOffset
val declaredLength = fileDescriptor.declaredLength
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
// Online: Przykładowy call do API (np. Grok)
suspend fun fetchOnlineResponse(query: String): String = withContext(Dispatchers.IO) {
val client = OkHttpClient()
val apiKey = "TWÓJ_KLUCZ" // Z https://x.ai/api
val json = """{"prompt": "$query"}"""
val body = RequestBody.create("application/json".toMediaTypeOrNull(), json)
val request = Request.Builder()
.url("https://api.x.ai/grok3") // Przykładowy endpoint
.addHeader("Authorization", "Bearer $apiKey")
.post(body)
.build()
val response = client.newCall(request).execute()
return@withContext response.body?.string() ?: "Błąd"
}
// Helpery: tokenizeInput i decodeOutput – zaimplementuj z biblioteką jak SentencePiece lub prostym dict
fun tokenizeInput(text: String): FloatArray { /* ... */ return floatArrayOf() }
fun decodeOutput(output: Array<FloatArray>): String { /* ... */ return "Przykładowa odpowiedź" }
- Wyszukiwanie/analiza online: W fetchOnlineResponse dodaj logikę do scraping'u (np. via Jsoup) lub API jak Google Search.
- Lokalna baza: Użyj Room (SQLite) do przechowywania historii zapytań.
- Testowanie: Uruchom na emulatorze z GPU. Dla voice: Dodaj SpeechRecognizer.
- Optymalizacja: Użyj NNAPI dla przyspieszenia na nowszych Androidach.
Brak komentarzy:
Prześlij komentarz