体验在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. 最终效果

相关推荐
CYRUS_STUDIO6 小时前
Frida 检测与对抗实战:进程、maps、线程、符号全特征清除
android·逆向
csj507 小时前
安卓基础之《(28)—Service组件》
android
lhbian9 小时前
PHP、C++和C语言对比:哪个更适合你?
android·数据库·spring boot·mysql·kafka
catoop10 小时前
Android 最佳实践、分层架构与全流程解析(2025)
android
ZHANG13HAO11 小时前
Android 13 特权应用(Android Studio 开发)调用 AOSP 隐藏 API 完整教程
android·ide·android studio
田梓燊11 小时前
leetcode 142
android·java·leetcode
angerdream11 小时前
Android手把手编写儿童手机远程监控App之JAVA基础
android
菠萝地亚狂想曲12 小时前
Zephyr_01, environment
android·java·javascript
sTone8737512 小时前
跨端框架通信机制全解析:从 URL Schema 到 JSI 到 Platform Channel
android·前端
sTone8737512 小时前
Java 注解完全指南:从 "这是什么" 到 "自己写一个"
android·前端