使用 Flutter 构建 ChatGPT 客户端应用程序

本文正在参加「金石计划」

介绍

最近ChatGPT风靡全球,网络上对 OpenAI 和 ChatGPT 进行了大量宣传,尤其是最近发布的 GPT-4。此类工具的大量用例不断涌现,人们使用它完成写论文、画美女、生成代码等等操作,但到目前为止,人们使用 ChatGPT 最广泛的方式是通过chat.openai.com。我也在上面使用 ChatGPT 干活,编写一些代码片段、优化代码、添加注释等,作为疲于应对日报的开发,现在已经利用ChatGPT解脱了。

以前的日报:

使用 Flutter 构建 ChatGPT 客户端应用程序

再看看现的日报多么内卷:

工作内容:

使用 Flutter 构建 ChatGPT 客户端应用程序

再也不用担心日报被领导批评了。

然而,OpenAI 官方聊天界面的体验并不好。它非常有限,而且聊天记录经常不能正常工作。作为开发人员,也想开发下自己的应用,方便自己使用,而在选择语言的时候考虑过 Compose 和 Flutter,作为 Flutter 长期使用人员,我觉得 Flutter 非常适合 ChatGPT 客户端应用程序!凭借其跨平台能力和丰富的 UI 组件,Flutter 是此类项目的完美选择,我们只需编写一次代码,就可以在网络、iOS、Android 以及桌面平台:Windows、macOS 和 Linux 上发布我们的应用程序。在这个文章里,我将构建一个简单的应用,包含通过 API 与 OpenAI 的 ChatGPT 聊天、并实现翻译、生成图片的功能,还带有日夜主题。

这篇文章其实也是利用ChatGPT写的。

入门

在我们开发应用之前,让我们对 ChatGPT API 的基础知识理有一个基本的了解。

OpenAI 有许多具有不同功能的 AI模型。但是我们今天要使用的模型**gpt-3.5-turbo** 是已知最有能力的模型,具有更高的准确性、更快的响应时间和改进的自然语言理解能力。

我们将使用以下 API:

Create chat completion

POST https://api.openai.com/v1/chat/completions
//Creates a completion for the chat message

Create imageBeta

POST https://api.openai.com/v1/images/generations
//Creates an image given a prompt.

要使用此 API,我们需要生成一个 API 密钥。可以在此处生成 API 密钥(需要在 OpenAI 上创建一个帐户)。

body它采用以下格式的JSON :

{
  "model": "gpt-3.5-turbo",
  "messages": [{"role": "user", "content": "Hello!"}]
}

并且,返回response这样的:

{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "Hello there, how may I assist you today?",
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 9,
    "completion_tokens": 12,
    "total_tokens": 21
  }
}

我们可以使用flutter_nb_net库发送携带带所需数据的请求,并解析响应。pub.dev 上也有一个可用的包:dart_openai,它可以直接发出 API 请求并返回解析后的响应,想走捷径的可以使用这个包。

应用程序

我们将只创建一个简单的应用程序,它能够接受用户输入,使用 API 获取响应,然后将它们显示在聊天气泡中。

最终界面将如下所示:

使用 Flutter 构建 ChatGPT 客户端应用程序

聊天机器人

UI的搭建分为三部分:

  • 标题栏:具有几个导航按钮。
  • 聊天列表:有用户气泡和 AI 气泡。
  • 输入框:接收用户输入并发送到 ChatGPT API。

状态管理依然使用getx,使用插件一键生成代码结构。

建立聊天气泡

聊天列表的item是一个自定义控件ChatWidget,参数index区别用户和 AI。

用户气泡:

class UserChatView extends StatelessWidget {
  const UserChatView({Key? key, required this.msg}) : super(key: key);

  final String msg;

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const SizedBox(width: 40.0),
        Expanded(
          child: Align(
            alignment: Alignment.centerRight,
            child: Container(
              padding: const EdgeInsets.all(8.0),
              decoration: BoxDecoration(
                color: Get.theme.colorScheme.secondaryContainer,
                borderRadius: BorderRadius.circular(16.0),
              ),
              child: Text(
                msg,
                style: TextStyle(
                  color: Get.theme.colorScheme.onSecondaryContainer,
                ),
              ),
            ),
          ),
        ),
        const SizedBox(width: 8.0),
        const CircleAvatar(
          backgroundImage: AssetImage(Assets.imagesPerson),
          radius: 16.0,
        )
      ],
    );
  }
}

AI 气泡需要有打字机的效果,文字一个一个显示,好像机器人在一个一个输入一样:

class AiChatView extends StatelessWidget {
  const AiChatView({super.key, required this.msg, required this.shouldAnimate});

  final String msg;
  final bool shouldAnimate;

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const CircleAvatar(
          backgroundImage: AssetImage(Assets.imagesOpenaiLogo),
          radius: 16.0,
        ),
        const SizedBox(width: 8.0),
        Expanded(
          child: Container(
            padding: const EdgeInsets.all(8.0),
            decoration: BoxDecoration(
              color: Get.theme.colorScheme.tertiaryContainer,
              borderRadius: BorderRadius.circular(16.0),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.05),
                  blurRadius: 5,
                  offset: const Offset(0, 2),
                ),
              ],
            ),
            child: shouldAnimate
                ? DefaultTextStyle(
                    style: TextStyle(
                        color: Get.theme.colorScheme.onTertiaryContainer,
                        fontWeight: FontWeight.w700,
                        fontSize: 16),
                    child: AnimatedTextKit(
                        isRepeatingAnimation: false,
                        repeatForever: false,
                        displayFullTextOnTap: true,
                        totalRepeatCount: 1,
                        animatedTexts: [
                          TyperAnimatedText(
                            msg.trim(),
                          ),
                        ]),
                  )
                : Text(
                    msg.trim(),
                    style: TextStyle(
                        color: Get.theme.colorScheme.onTertiaryContainer,
                        fontWeight: FontWeight.w700,
                        fontSize: 16),
                  ),
          ),
        ),
        const SizedBox(width: 40.0),
      ],
    );
  }
}

逻辑层

本来有选择模型的逻辑,后来去掉了,只有一个发消息和接受接收消息的逻辑:

Future<void> sendMessageAndGetAnswers({required String msg}) async {
  if (currentModel.toLowerCase().startsWith("gpt")) {
    chatList.addAll(await repository.sendMessageGPT(
      message: msg,
      modelId: currentModel,
    ));
  } else {
    chatList.addAll(await repository.sendMessage(
      message: msg,
      modelId: currentModel,
    ));
  }
  _isTyping = false;
  update();
}

下面是效果:

使用 Flutter 构建 ChatGPT 客户端应用程序

翻译

翻译的 UI 分为四部分:

  • 标题栏。
  • 翻译语言。
  • 输入框:接收用户输入并发送到 ChatGPT API。
  • 显示框:接收ChatGPT API 返回的翻译。

这里有一些待完成的功能:

  • 复制

  • 删除

  • 切换语言

  • 多语言选择

使用 Flutter 构建 ChatGPT 客户端应用程序

生成图片

点击首页标题栏的第二个 Action ,会跳转到生成图片页面,默认有一个图片展示。

使用 Flutter 构建 ChatGPT 客户端应用程序

UI 部分:

  • 标题栏。

  • 输入框。

  • 画廊:展示 ChatGPT API 返回的图片。

配置的接口数据是每次返回4张图片,尺寸是256×256:

    var result = await post<ImageModel, ImageModel>('/images/generations',
        data: jsonEncode({
          "prompt": message,
          "n": 4,
          "size": "256x256",
        }),
        decodeType: ImageModel());
  • prompt:要生成图片的文字描述。
  • n:返回的张数。
  • size:图片尺寸。

画廊是一个自定义控件。

使用 Flutter 构建 ChatGPT 客户端应用程序

浅色模式

除了上面的功能,这个 app 按照 Material 3 设计,包含浅色模式和深色模式:

使用 Flutter 构建 ChatGPT 客户端应用程序

原文链接:https://juejin.cn/post/7220793382021070903 作者:北海道浪子

(0)
上一篇 2023年4月12日 上午10:27
下一篇 2023年4月12日 上午10:38

相关推荐

发表回复

登录后才能评论