KI-generierten Text zu deiner Android-App mit Jetpack Compose und GPT hinzufuegen

Dieses Tutorial zeigt, wie man einen GPT-Client fuer Android mit Jetpack Compose in Kotlin erstellt. Es behandelt das Senden einer Anfrage an die OpenAI GPT API und das Dekodieren der JSON-Antwort, um den generierten Text anzuzeigen.

Hinweis: Dieses Tutorial konzentriert sich auf die Logik zum Senden und Empfangen von Anfragen an/von der OpenAI GPT API; es behandelt nicht alle UI-Details.

Den vollstaendigen Code, einschliesslich der UI-Implementierung, findest du in meinem GitHub-Repo mit funktionierenden iOS- und Android-Beispielen.

Was ist GPT?

GPT (Generative Pre-trained Transformer) ist ein Machine-Learning-Modell, das natuerlichsprachlichen Text generiert. Es ist auf grossen Textmengen vortrainiert und kann fuer bestimmte Aufgaben fein abgestimmt werden, wie zum Beispiel das Produzieren von Text als Antwort auf einen Prompt.

Was werden wir bauen?

Wir werden eine App bauen, die:

  • Benutzereingaben aus einem TextField akzeptiert
  • Die Eingabe an die GPT API sendet
  • Die JSON-Antwort empfaengt und dekodiert
  • Die Antwort als animierten Text anzeigt

Die sendRequest-Funktion handhabt die Kommunikation mit der OpenAI GPT API. Sie kodiert die Frage als JSON-Payload und sendet eine POST-Anfrage. Wenn die API mit Statuscode 200 antwortet, extrahiert die Funktion den generierten Text aus der JSON-Antwort und zeigt ihn in einer Text-View an. Wenn die API mit einem Fehler antwortet, zeigt die Funktion eine Fehlermeldung an.

Hier ist ein animierter Screenshot der fertigen App:

2023-03-07 gpt.gif

Eine Anfrage an die GPT API senden

Unten ist der Code, der benoetigt wird, um eine Anfrage an die GPT API zu senden. Eine Schritt-fuer-Schritt-Erklaerung folgt.

data class GptRequest(
  val prompt: String,
  val max_tokens: Int,
  val model: String
)
 
data class GptResponse(
  val choices: List<Choice>
)
 
data class Choice(
  val text: String
)
 
interface GptApi {
  @Headers(
    "Content-Type: application/json",
    "Authorization: Bearer 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"
  )
  @POST("/v1/completions")
  fun getCompletion(
    @Body requestBody: GptRequest
  ): Call<GptResponse>
}
 
class ContentViewModel: ViewModel() {
 
  var answer by mutableStateOf("")
    private set
 
  var isLoading by mutableStateOf(false)
    private set
 
  val retrofit = Retrofit.Builder()
   .baseUrl("https://api.openai.com")
   .addConverterFactory(GsonConverterFactory.create())
   .build()
 
  val api = retrofit.create(GptApi::class.java)
 
  fun sendRequest(question: String) {
    val request = GptRequest(
      prompt = question,
      max_tokens = 100,
      model = "text-davinci-003"
    )
 
    viewModelScope.launch(Dispatchers.IO) {
      isLoading = true
      val call = api.getCompletion(request)
      val response = call.execute()
      isLoading = false
 
      if (response.isSuccessful) {
        val choice = response.body()?.choices?.get(0)
        viewModelScope.launch(Dispatchers.Main) {
          choice?.text?.let {
            answer = it
          }
        }
      } else {
        viewModelScope.launch(Dispatchers.Main) {
          answer = "Error: ${response.code()} - ${response.message()}"
        }
      }
    }
  }
}

Der obige Quellcode ermoeglicht der App die Kommunikation mit der OpenAI GPT API. Unten ist eine praegnante Erklaerung der Hauptteile:

  • data class GptRequest repraesentiert die JSON-Payload, die an die OpenAI API gesendet wird, um generierten Text anzufordern.
  • data class GptResponse repraesentiert die JSON-Antwort, die von der OpenAI API zurueckgegeben wird, und enthaelt den generierten Text.
  • data class Choice ist eine verschachtelte Datenklasse innerhalb von GptResponse, die den generierten Text enthaelt.
  • interface GptApi definiert die REST API, die zur Kommunikation mit der OpenAI API verwendet wird. Die getCompletion-Funktion sendet eine POST-Anfrage an den v1/completions-Endpunkt mit einem Content-Type: application/json-Header und einem Authorization-Header, der den API-Schluessel enthaelt.
  • class ContentViewModel ist ein ViewModel, das die Daten und Logik der App handhabt. Es enthaelt eine sendRequest-Funktion, die eine Benutzerfrage nimmt, sie an die OpenAI API sendet und die answer-Variable auf den generierten Text setzt.
  • var answer by mutableStateOf("") ist eine reaktive Variable, die den generierten Text haelt und von der UI zur Anzeige beobachtet werden kann.
  • var isLoading by mutableStateOf(false) ist eine reaktive Variable, die anzeigt, ob eine Anfrage laeuft, und von der UI beobachtet werden kann, um einen Lade-Spinner anzuzeigen.
  • val retrofit = Retrofit.Builder() erstellt eine Retrofit-Instanz zur Kommunikation mit der OpenAI API.
  • val api = retrofit.create(GptApi::class.java) erstellt eine Instanz des GptApi-Interface mit der Retrofit-Instanz.
  • fun sendRequest(question: String) konstruiert einen GptRequest, sendet ihn ueber api.getCompletion(request) und setzt answer auf den generierten Text, wenn die Antwort erfolgreich ist; andernfalls zeigt sie eine Fehlermeldung an.
  • Dispatchers.IO und Dispatchers.Main werden verwendet, um Netzwerkanfragen und UI-Updates auf den entsprechenden Threads auszufuehren.

Hinweis: Der Authorization-Header im obigen Code enthaelt einen API-Schluessel, der dem Entwickler (mir) gehoert. Ersetze ihn durch deinen eigenen API-Schluessel - die Verwendung des bereitgestellten Schluessels fuehrt zu einem Fehler, da er vor der Veroeffentlichung dieses Tutorials ungueltig gemacht wurde.

Um einen OpenAI API-Schluessel zu erhalten, erstelle ein Konto auf openai.com, gehe zum API-Bereich und folge den Anweisungen, um einen Schluessel zu generieren. Halte deinen API-Schluessel sicher und teile ihn nicht.

Fazit

In diesem Tutorial haben wir eine Android-App gebaut, die Benutzereingaben akzeptiert, sie an die OpenAI GPT API sendet und den generierten Text anzeigt.

Ich hoffe, du fandest dieses Tutorial informativ und dass es dich inspiriert hat, dein eigenes Projekt mit der GPT API zu erstellen.

Der vollstaendige Code ist in meinem Repo mit funktionierenden Beispielen fuer iOS und Android verfuegbar: https://github.com/twissmueller/mobile-snippets

Vielen Dank fuers Lesen!