Streaming Server | Retrofit 2 with ChatGPT API

Vikas Soni
3 min readJan 14, 2024

--

Hey Devs, let’s start this blog with some background story, almost every one of us uses ChatGPT daily for quick help in our workplace. Usually, we search for something and get some response in the form of streaming as if someone is typing for us word by word which seems fascinating or human-like typing.
Recently, I saw an application available on Play Store which is basically for helping students in solving their problems in their academics. So, they just need to click/browse a picture of the question (cropping specific question) or type their question and upload/send that on the application and they get some solution for the question. Most of the time, the answer may or may not be clear as AI implemented in their backend directly answers students with minimal solving steps. This seems a little cumbersome, isn’t it? let’s hope for the solution.
What if students get the solution step by step to solve it with a description of each step? This looks way better than the current response state. So, we moving now to technical factors-

I came to a solution using ChatGPT’s Chat Completion API along with Retrofit @Streaming this problem can be solved. Let’s start then-

a) Create an Android application in Android Studio and set up the required dependencies i.e. Retrofit, Gson Converter, etc. Don’t forget to add Internet Permission in the Android Manifest file.

implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"

b) Create layout.xml according to your need i.e. an editable field to enter the question, two buttons to send the question to the server, and clear the views to ask fresh questions and one TextView for answers. Type your question and hit the send button-

private fun uploadQuestionToServer(inputText: String) {

val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

val gson = GsonBuilder()
.setLenient()
.create()

val okHttpClient = OkHttpClient.Builder()
.addInterceptor(OpenAiInterceptor())
.addNetworkInterceptor(interceptor)
.build()

val retrofit = Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpClient)
.build()

val retrofitAPI: ApiService = retrofit.create(ApiService::class.java)

val tempList = arrayListOf<MessageBody>()
val messageBody = MessageBody(
role = "user",
content = inputText
)
tempList.add(messageBody)

val modal = ChatGPTRequest(messages = tempList)

CoroutineScope(Dispatchers.IO).launch {

val str = StringBuilder()
getData(retrofitAPI, modal, gson).collectLatest {

withContext(Dispatchers.Main) {
str.append(it.choices[0].delta?.content)
activityPostsBinding.textAnswer.text = str
}
}
}
}
private fun getAnswer(retrofitAPI: ApiService, modal: ChatGPTRequest, gson: Gson) = flow {

val response = retrofitAPI.getStreams(modal).execute()

if (response.isSuccessful) {
if (response.isSuccessful) {
val input = response.body()?.byteStream()?.bufferedReader() ?: throw Exception()
try {
while (currentCoroutineContext().isActive) {
val line = input.readLine()
if (line != null && line.startsWith("data:")) {
try {
val answerDetailInfo = gson.fromJson(
line.substring(5).trim(),
ChatGPTResponse::class.java
)
emit(answerDetailInfo)
} catch (e: Exception) {
e.printStackTrace()
}
}
delay(100)
}
} catch (e: IOException) {
throw Exception(e)
} finally {
input.close()
}
} else {
throw HttpException(response)
}
}
}

Add the ChatGPT API key in the header to validate the request, you can get the ChatGPT API key from https://platform.openai.com/api-keys link.

class OpenAiInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request();
val authenticatedRequest = request.newBuilder()
.addHeader("Authorization", "Bearer ${BuildConfig.GPT_KEY}")
.build();

Log.d("headers", authenticatedRequest.headers["Authorization"]!!);
return chain.proceed(authenticatedRequest);
}
}
@Streaming
@POST("completions")
fun getStreams(@Body gptBody: Any?): Call<ResponseBody>

Add Base URL and API key in your app level build.gradle file. For reference-

buildConfigField 'String', 'BASE_URL', '"https://api.openai.com/v1/chat/"'
buildConfigField 'String', 'GPT_KEY', '"your-chat-gpt-api-key"'

Please refer below given link for ChatGPT’s chat/completions API reference-

https://platform.openai.com/docs/api-reference/chat

That’s it for now. Please visit the following GitHub repo for reference the project:

Please share your valuable opinion on this blog in the comment section along with how can I improve more. You guys are most welcome to contribute to the repository.

Happy Coding :)

--

--

Vikas Soni

Passionate Android Developer | Code Craftsman | Transforming ideas into elegant apps. Let's build something amazing together!