体验在Android中使用ChatGPT API

1. 前言

这篇文章旨在教大家快速构建一个可以使用ChatGPT api进行聊天的App。

代码仓库:github.com/leiteorz/Ch...

2. 引入相关依赖

我们使用Volley来进行网络请求。

Volley是一个能够让Android应用更轻松、更快捷地联网的 HTTP 库,在API调用中经常使用

了解volley: developer.android.com/training/vo...

在build.gradle中引入Volley库

gradle 复制代码
implementation 'com.android.volley:volley:1.1.1'

3. 开启联网权限

在AndroidManifest.xml中输入以下代码:

xml 复制代码
// 开启联网权限
<uses-permission android:name="android.permission.INTERNET"/>

4. 编写代码

4.1 分析

我们知道一个聊天软件,或者说网页版的ChatGPT,就是上面一个聊天界面下面一个聊天框

聊天框肯定不用多说,就是一个TextField(EditText)。

上面的聊天界面也不过就是一个列表罢了,可以根据是ChatGPT说的话还是用户自己发送的话来判断气泡框的左右。

下图是OpenAI官网给出的样图,那么我们可以模仿他来写一个。

4.2 准备数据类-消息

kotlin 复制代码
data class ChatMessage(var text: String, var type: Int)

4.3 准备消息列表

这个List用来存放消息

kotlin 复制代码
val messageList = remember { mutableStateListOf<ChatMessage>() }

4.4 发送网络请求

参照官网给出的文档,构建一个JSONObject来发送请求,收到Response后将消息放进messageList中。

kotlin 复制代码
private fun sendQuestion(question: String, messageList: SnapshotStateList<ChatMessage>){
    val url = "https://api.openai.com/v1/completions"
    // 创建一个请求队列
    val queue: RequestQueue = Volley.newRequestQueue(applicationContext)
    // 提问
    val jsonObject = JSONObject()
    jsonObject.put("model", "text-davinci-003")
    jsonObject.put("prompt", question)
    jsonObject.put("temperature", 0)
    jsonObject.put("max_tokens", 300)
    jsonObject.put("top_p", 1)
    jsonObject.put("frequency_penalty", 0.0)
    jsonObject.put("presence_penalty", 0.0)

    val postRequest: JsonObjectRequest =
        object : JsonObjectRequest(Method.POST, url, jsonObject,
            Response.Listener { response ->
                val responseMsg: String = response.getJSONArray("choices").getJSONObject(0).getString("text")
                Log.d("reply", "getResponse: " + responseMsg)
                messageList.add(ChatMessage(responseMsg.trim(), 1))
            },
            Response.ErrorListener { error ->
                Log.d("OpenAI", "getResponse: " + error.message + "\n" + error)
            }){
            override fun getHeaders(): MutableMap<String, String> {
                val params: MutableMap<String, String> = HashMap()
                params["Content-Type"] = "application/json"
                params["Authorization"] = "Bearer sk-xxx"
                return params
            }
        }

    queue.add(postRequest)
}

4.5 编写界面

  • 聊天框

分析一下聊天框

传入的参数是text(对话内容),type(身份)

根据type确定对话框的颜色和身份显示

首先是一个纵向布局:Text显示身份("ChatGPT"或者"Me"),Row里面的内容是对话框

Row里面的Divider是对话框左边的线,Text表示内容

kotlin 复制代码
@Composable
fun DialogBox(text: String, type: Int){
    val identity: String = if(type == 0) "Me" else "ChatGPT"
    val dialogColor: Color = if(type == 0) Color(0xFFE91E63) else Color(0xFF64B5F6)

    Column(
        modifier = Modifier.offset(x = 20.dp, y = 5.dp)
    ) {
        Text(text = identity, color = dialogColor, fontWeight = FontWeight.Bold)
        // 对话框
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .height(IntrinsicSize.Min)
                .offset(y = 2.dp)
        ) {
            Divider(
                color = dialogColor,
                modifier = Modifier
                    .width(3.dp)
                    .fillMaxHeight()
                    .padding(0.dp, 8.dp)
            )
            Text(
                text = text,
                modifier = Modifier
                    .width(320.dp)
                    .padding(5.dp)
            )
        }
    }
}

显示效果:

  • 输入框

输入框没什么好说的,就是一个TextField设置一下形状和颜色。

按回车发送的时候调用刚刚写的sendQuestion方法

kotlin 复制代码
@Composable
fun inputBox(messageList: SnapshotStateList<ChatMessage>, modifier: Modifier){
    var userInput by remember { mutableStateOf("") }    // 用户输入
    val context = LocalContext.current

    TextField(
        value = userInput,
        onValueChange = {userInput = it},
        placeholder = {
            Text(text = "Send a chat")
        },
        shape = CircleShape,
        modifier = Modifier
            .fillMaxWidth()
            .padding(10.dp),
        colors = TextFieldDefaults.textFieldColors(
            backgroundColor = Color(0xFFEEEEEE),
            focusedIndicatorColor = Color.Transparent,
            unfocusedIndicatorColor = Color.Transparent,
            disabledIndicatorColor = Color.Transparent
        ),
        singleLine = true,
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Send),
        keyboardActions = KeyboardActions(onSend = {
            if (userInput.isEmpty()) Toast.makeText(context, "聊天内容不能为空", Toast.LENGTH_SHORT).show()
            else{
                messageList.add(ChatMessage(userInput, 0))

                val question = userInput
                userInput = ""

                sendQuestion(question, messageList)
            }
        })
    )
}

显示效果:

  • 聊天列表

聊天列表使用LazyColumn

kotlin 复制代码
@Composable
fun chatList(messageList: SnapshotStateList<ChatMessage>, modifier: Modifier){
    LazyColumn(modifier = modifier){
        items(messageList){
            DialogBox(text = it.text, type = it.type)
        }
    }
}
  • 组合起来
kotlin 复制代码
@Composable
fun chatApp(messageList: SnapshotStateList<ChatMessage>){
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight(),
    ) {
        TopAppBar(
            title = {Text("ChatGPT APP", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center)},
            backgroundColor = Color(0xFF0288D1),
            contentColor = Color.White,
            modifier = Modifier
        )
        chatList(messageList = messageList, modifier = Modifier.weight(1f))
        inputBox(messageList = messageList, modifier = Modifier)
    }
}

5. 最终效果

相关推荐
Estar.Lee4 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
温辉_xh4 小时前
uiautomator案例
android
工业甲酰苯胺6 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
少说多做3436 小时前
Android 不同情况下使用 runOnUiThread
android·java
Estar.Lee7 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯8 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey9 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!11 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟12 小时前
Android音频采集
android·音视频
小白也想学C13 小时前
Android 功耗分析(底层篇)
android·功耗