镇楼图

OpenAI API

OpenAI API

You can interact with the API through HTTP

OpenAI 供给了开放API、各渠道都能够经过HTTP与其建立连接进行调用。开发者能够尝试在不同渠道上对接。这篇文章尝试将开放API对接到ComposeUnit

免费额度: API方式调用官方明确是需求收费的。当然了注册之后默许有 $18.00的免费运用额度。对于调试API这些应该足够了。

OpenAI API

充值相关: 当然了咱们能够选择付费充值,对于国内可能在充值方面比较麻烦。当然了咱们能够经过 欧易渠道购买USDT->提现到Depay钱包->兑换成美刀Depay信用->充值升级到ChatGPT Plus。(开发者根据实际情况,选择是否升级注册**ChatGPT Plus**)

一、官方UI

官方布局UI 想必咱们都看到过,如下所示。ComposeUnit OpenAI模块的UI款式也沿用官方进行,接下来对官网布局剖析,好进行规划咱们APP中的UI布局。

OpenAI API

1、布局模块

官方布局,右侧UI大约包含,对话列表、输入框、重定向恳求这三大模块。如下所示:

  • 音讯列表

    OpenAI API

  • 输入框

    OpenAI API

  • 重定向恳求

    OpenAI API

2、模块剖析
  • 音讯列表

    能够看到音讯部分,是常见的问答列表款式。文章由于时间问题,不做本地数据库文件缓存等,数据操作都根据viewModel中可调查调集进行。此事例运用compose+viewModel+rerofit+协程方式进行代码编写。列表部分,运用Compose库供给的LazyColumn进行布局。

    在对话中能够调查到对应的文字有输入效果。应该不是印度小哥后台的一顿疯狂操作。开个玩笑,先看看官方输出文字效果。这个是需求安排的小动画。

    OpenAI API

  • 输入框

    输入框内不也有许多细节,未输入之前的提示Send a message和文字颜色,以及输入之后的文字颜色等都是不同。

    1、文字颜色改变

    2、输入框右侧发送按钮和加载动画由网络是否恳求而决定。

    3、加载进程中右侧是三个小点加载动画。

    4、加载进程中输入框是能够输入的,可是无法进行发送恳求。

  • 重定向恳求

    在输入框上部有个Regenerate response和Stop generating能够切换的按钮。当恳求加载数据进程能够停止,而数据停止之后,能够点击Regenerate response再次恳求。

二、规划页面UI

1、UI全体布局

同官方UI,进行移动端页面规划,全体UI色调只用灰色系深浅两种:

val openAiDark = Color(52, 54, 65, 255)
val openAiLight = Color(68, 70, 84, 255)

对比如下:

OpenAI API

经过Scaffold构建根本的页面结构。结构代码如下:

@Composable
fun OpenAIPage(viewModel: OpenAiViewModel) {
  Scaffold(
    backgroundColor = openAiDark,
    topBar = {//1、顶部TopBar
      OpenAITopBar()
     }) {
    OpenAIUI(//2、列表和底部输入框
     )
   }
}
2、TopBar

TopBar布景色取主题色的亮色,整个UI布局只用用灰色的深亮种色,我是比较喜爱简约风。文字部分加粗且增加暗影。

//topBar部分,标题文字加粗增暗影
@Composable
fun OpenAITopBar() {
  Box(
    Modifier
       .fillMaxWidth()
       .height(70.dp)
       .background(
        openAiLight
       ),
    contentAlignment = Alignment.Center
   ) {
    Text(
      text = "OpenAI",
      fontSize = 18.sp,
      textAlign = TextAlign.Center,
      color = Color.White,
      fontWeight = FontWeight.Bold,
      style = TextStyle(
        shadow = Shadow(
          Color(43, 43, 43, 255),
          offset = Offset(2f, 6f),
          blurRadius = 11f
         )
       )
     )
   }
}

效果如下:

OpenAI API

3、列表

对话列表和输入框部分,咱们能够用Box进行层次布局。

 @Composable
fun OpenAIUI(
  modifier: Modifier,
  textFieldAlignment: Alignment = Alignment.BottomCenter,
 ) {
  Box(modifier = modifier,
    contentAlignment = textFieldAlignmen) {
    //列表布局
    OpenAIListView()
    //输入和重定向布局
    Column(
      Modifier
         .fillMaxWidth()
      horizontalAlignment = Alignment.CenterHorizontally,
     ) {
      OpenAIReRequestUI()
      Box(Modifier.height(5.dp))
      OpenAIBottomInputUI()
     }
   }
}

列表OpenAIListView部分,假数据进行填充,增加布景配色。

@Composable
fun OpenAIListView1() {
  LazyColumn(
    Modifier
       .fillMaxSize()
       .padding(bottom = 80.dp)
   ) {
    items(2, key = { index ->
      index
     }) { index ->
      if (index % 2 == 0)
        Box(
          Modifier
             .fillMaxWidth()
             .background(Color(52, 54, 65, 255))
             .padding(top = 20.dp)
         ) {
          Text(
            text = "我是假数据,用户数据",
            color = Color.White,
            modifier = Modifier
               .padding(start = 20.dp, bottom = 20.dp, end = 20.dp)
           )
         }
      else
        Box(
          Modifier
             .fillMaxWidth()
             .background(openAiLight)
             .padding(top = 20.dp)
         ) {
          Text(
            text = "我是假数据,OpenAI返回数据,假如答复有问题,我期望你能够给我一些主张,我持续生成,文字不行两行。",
            color = Color.White,
            modifier = Modifier
               .padding(start = 20.dp, bottom = 20.dp, end = 20.dp)
           )
         }
     }
   }
}

OpenAI API

当然了,用户和AI头像咱们不难用Row之类的容器进行摆放。代码如下:

  LazyColumn(
    Modifier
       .fillMaxSize()
       .padding(bottom = 80.dp)
   ) {
    items(2, key = { index ->
      index
     }) { index ->
      if (index % 2 == 0)
        Row(
          Modifier
             .fillMaxWidth()
             .background(Color(52, 54, 65, 255))
             .padding(top = 20.dp)
         ) {
          Box(Modifier.width(20.dp))
          Box(
            Modifier
               .size(30.dp)
               .background(
                color = Color(
                  3,
                  149,
                  135,
                  255
                 ),
                shape = RoundedCornerShape(5.dp)
               ),
            contentAlignment = Alignment.Center
           ) {
            Text(
              text = "11",
              color = Color.White,
             )
           }
          Text(
            text = "我是假数据,用户数据",
            color = Color.White,
            modifier = Modifier
               .padding(start = 20.dp, bottom = 20.dp, end = 20.dp)
           )
         }
      else
        Row(
          Modifier
             .fillMaxWidth()
             .background(openAiLight)
             .padding(top = 20.dp)
         ) {
          Box(Modifier.width(20.dp))
          Image(
            painter = painterResource(id = R.mipmap.open_ai_head),
            contentDescription = "head",
            contentScale = ContentScale.Fit,
              modifier = Modifier.size(30.dp)
           )
          Text(
            text = "我是假数据,OpenAI返回数据,假如答复有问题,我期望你能够给我一些主张,我持续生成,文字不行两行。",
            color = Color.White,
            modifier = Modifier
               .padding(start = 20.dp, bottom = 20.dp, end = 20.dp)
           )
         }
     }
   }

当然了代码别学上面堆屎山。

@Composable
fun OpenAIListView() {
  LazyColumn(
    Modifier
       .fillMaxSize()
       .padding(bottom = 80.dp)
   ) {
    items(2, key = { index ->
      index
     }) { index ->
      if (index % 2 == 0)
        UserMessagesUI()
      else
        OpenAIMessageUI()
   }
}
​

OpenAI API

当然了后期还会持续优化代码的,有网络恳求过错或许异常恳求之类的头像以及文字颜色显示效果等。

OpenAI API

大约用约束布局进行设置一个网络恳求异常的状况布局。

ConstraintLayout {
            val (imageView, errorView) = createRefs()
            Image(
              painter = painterResource(id = R.mipmap.open_ai_head),
              contentDescription = "head",
              contentScale = ContentScale.Fit,
              modifier = Modifier
                 .constrainAs(imageView) {
                  top.linkTo(parent.top)
                  start.linkTo(parent.start)
                 }
                 .size(30.dp)
             )
            if (netErro)
              Image(
                painter = painterResource(id = R.mipmap.open_ai_error),
                colorFilter = ColorFilter.tint(Color.Red),
                contentDescription = "error",
                contentScale = ContentScale.Fit,
                modifier = Modifier
                   .constrainAs(errorView) {
                    bottom.linkTo(imageView.bottom)
                    end.linkTo(imageView.end)
                   }
                   .offset(x = 6.dp, y = 8.dp)
                   .size(16.dp)
               )
           }

OpenAI API

4、输入框

官方效果如下:

OpenAI API

输入框部分,运用TextField,经过Modifier设置background设置布景色和裁剪布景有四角弧度,border设置增加边框。TexField的placeholder特点进行设置Send a message… 提示语,确保在无输入内容以及无焦点是显示提示语。经过TextField的shape进行设置输入内容部分的形状保持和布景共同。trailingIcon可用于设置最后边部分的发送按钮和加载中动画部分。

OpenAIBottomInputUI(){
 TextField(
    textStyle = TextStyle(
      color = (inputColor(isFocused, textFieldValue.value.text, loading))
     ), colors = TextFieldDefaults.textFieldColors(
      unfocusedIndicatorColor = Color.Transparent,
      focusedIndicatorColor = Color.Transparent,
      backgroundColor = Color(64, 65, 79, 255)
     ),
    interactionSource = interactionSource,
    modifier = Modifier
       .fillMaxWidth(0.8f)
       .height(50.dp)
       .focusRequester(focusRequester)
       .background(
        color = Color(64, 65, 79, 255), RoundedCornerShape(10)
       )
       .border(
        0.5.dp, Color(47, 49, 56, 166), RoundedCornerShape(10)
       ),
    placeholder = {
      Text(
        text = "Send a message...",
        color = (inputColor(isFocused, textFieldValue.value.text))
       )
     },
    shape = RoundedCornerShape(10),
    value = textFieldValue.value,
    onValueChange = {
      if (!isFocused && it.text.isNotEmpty()) {
        textFieldValue.value = TextFieldValue(
          text = it.text, selection = TextRange(0, it.text.lastIndex + 1)
         )
       } else {
        textFieldValue.value = TextFieldValue(
          text = it.text,
          selection = TextRange(it.text.lastIndex + 1)
         )
       }
     }, trailingIcon = {
      Icon(
          modifier = Modifier.clickable {
            if (textFieldValue.value.text.isNotEmpty()) {
              viewModel.setLoadValue(true)
              viewModel.getChatGTPMessage(textFieldValue.value.text)
              viewModel.setRegenerateInfo(textFieldValue.value.text)
              textFieldValue.value = TextFieldValue(
                text = ""
               )
              focusManager.clearFocus()
             }
           },
          painter = painterResource(R.mipmap.send_icon),
          contentDescription = "sendIcon",
          tint = submitColor(isFocused, textFieldValue.value.text)
         )
     })
}
​

重定向恳求部分比较简单,不在阐述

@Composable
private fun OpenAIReRequestUI(
  pageList: ArrayList<ChatGTPModel>,
) {
    Row(
      Modifier
         .background(color = Color(52, 54, 65, 255))
         .border(
          0.6.dp,
          Color(85, 87, 104, 255),
          RoundedCornerShape(5.dp),
         )
         .clickable {
          //点击网络操作
         },
      horizontalArrangement = Arrangement.Center,
      verticalAlignment = Alignment.CenterVertically
     ) {
      Icon(
        modifier = Modifier
           .height(18.dp)
           .width(18.dp)
           .padding(start = 5.dp),
        painter = painterResource(
          id = if (loading)
            R.mipmap.open_ai_stop else
            R.mipmap.open_ai_reload
         ),
        contentDescription = "reload",
        tint = Color(216, 216, 226, 255)
       )
      Text(
        text = "Regenerate response",
        Modifier.padding(5.dp),
        color = Color(216, 216, 226, 255)
       )
     }
}

OpenAI API

至此根本布局完成,接下来咱们看看对应官方的API,逐步接入数据部分。

OpenAI API

三、Chat API

四、Images API

五、Audio API

六、Audio API

七、Edits API

八、最终效果

OpenAI API
OpenAI API
OpenAI API