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

相关推荐
fatiaozhang952726 分钟前
创维桌面云终端-创维LB2002-黑盒-国科gk6323-2+8G-短接强刷固件包
android·电视盒子·刷机固件·机顶盒刷机·创维lb2002·创维lb2002-黑盒·创维lb2002-白盒
q***71857 小时前
MySQL--》如何在MySQL中打造高效优化索引
android·mysql·adb
IT痴者8 小时前
《PerfettoSQL 的通用查询模板》---Android-trace
android·开发语言·python
游戏开发爱好者88 小时前
iOS IPA 上传工具全面解析,从 Transporter 到开心上架(Appuploader)命令行的高效上架实践
android·ios·小程序·https·uni-app·iphone·webview
alexhilton11 小时前
Jetpack Compose中的阴影艺术
android·kotlin·android jetpack
百***618714 小时前
Spring的构造注入
android·java·spring
Tom4i14 小时前
Kotlin 中的 inline 和 reified 关键字
android·开发语言·kotlin
yi诺千金15 小时前
Android U 自由窗口(浮窗)——启动流程(system_server侧流程)
android
清空mega17 小时前
第11章 网络编程
android·网络
自动化BUG制造器17 小时前
Android UI 线程不一定是主线程
android