体验在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库

implementation 'com.android.volley:volley:1.1.1'

3. 开启联网权限

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

// 开启联网权限
<uses-permission android:name="android.permission.INTERNET"/>

4. 编写代码

4.1 分析

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

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

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

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

在这里插入图片描述

4.2 准备数据类-消息

data class ChatMessage(var text: String, var type: Int)

4.3 准备消息列表

这个List用来存放消息

val messageList = remember { mutableStateListOf<ChatMessage>() }

4.4 发送网络请求

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

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表示内容

@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方法

@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

@Composable
fun chatList(messageList: SnapshotStateList<ChatMessage>, modifier: Modifier){
    LazyColumn(modifier = modifier){
        items(messageList){
            DialogBox(text = it.text, type = it.type)
        }
    }
}

  • 组合起来
@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. 最终效果

在这里插入图片描述

如果你看到了这里,觉得文章写得不错就给个赞呗?
更多Android进阶指南 可以扫码 解锁更多Android进阶资料

在这里插入图片描述
敲代码不易,关注一下吧。ღ( ´・ᴗ・` )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值