拥抱AI

624 阅读4分钟

来到掘金的第一篇文章,话不多说开始进入正题;openai携带者chatgpt席卷全球之际,我们却被拒之门外,以往的科学上网也只是前提条件,国内的邮箱也无法使用,下面是目前使用 chatgpt的准备条件:

  1. 科学上网
  2. 注册一个Google账号
  3. 准备一个国外的手机号(虚拟号码不能是漂亮国的,他们有校验),因为用谷歌账号登录完还需要短信验证码进行验证,虚拟手机号获取可以使用接码平台

关于chatgpt的注册教程网上有很多,大家可以搜索一下,这里主要介绍一下chatgpt对程序员的帮助。这里以flutter举例,比如我现在有一个需求:

做一个聊天的页面,内容包括

  1. 封装一个气泡widegt
  2. 消息内容要求一个字一个字的显示
  3. 消息内容支持换行
  4. 底部有一个输入框,支持用户输入、发送消息
  5. 输入框最多显示3行,超出部分支持滚动

我们看看chatgpt帮我们写的代码

1. bubble.dart

import 'package:flutter/material.dart';

import 'chat_page.dart';

class AnimatedText extends StatefulWidget {
  final String message;
  final bool isMe;
  final bool shouldAnimate;
  final bool isLast;

  const AnimatedText({required this.message, required this.isMe, required this.shouldAnimate, this.isLast = false});

  @override
  _AnimatedTextState createState() => _AnimatedTextState();
}

class _AnimatedTextState extends State<AnimatedText> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<int> _animation;

  @override
  void initState() {
    super.initState();
    if (widget.shouldAnimate) {
    _controller = AnimationController(vsync: this, duration: Duration(milliseconds: 5000));
    _animation = IntTween(begin: 0, end: widget.message.length).animate(_controller)
      ..addListener(() {
        setState(() {});
      });
    _controller.forward();
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final text = widget.shouldAnimate? widget.message.substring(0, _animation.value) : widget.message;
    if (widget.isLast) {
      ChatScreenState? chatState = context.findAncestorStateOfType<ChatScreenState>();
      chatState?.scrollToBottom();
    }

    return Wrap(
      alignment: widget.isMe ? WrapAlignment.end : WrapAlignment.start,
      children: <Widget>[
        Container(
          decoration: BoxDecoration(
            color: widget.isMe ? Colors.blueAccent : Colors.grey[300],
            borderRadius: BorderRadius.circular(20.0),
          ),
          padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
          margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0),
          child: Text(
            text,
            style: TextStyle(
              color: widget.isMe ? Colors.white : Colors.black,
              fontSize: 16.0,
            ),
          ),
        ),
      ],
    );
  }
}

2. chatScreen.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'bubble.dart';

class ChatScreen extends StatefulWidget {
  @override
  State<ChatScreen> createState() => ChatScreenState();
}

class ChatScreenState extends State<ChatScreen> {
  final List<Map<String, dynamic>> messages = [
    {"text":'Hello, how are you?', "isMe":true},
    {"text":'I'm doing well,thanks. How about you?', "isMe":false},
    {"text":"去你的,还不错,不错个毛。喵的找你聊天都找不到,跟小签学会了是吧", "isMe": true},
    {"text":"对不起,我错了,以后再也不敢了", "isMe": false},
  ];

  final TextEditingController _controller = TextEditingController();
  final ScrollController _scrollController = ScrollController();
  var _isInputed = false;
  void _sendMessage(String message) {
    _isInputed = true;
    setState(() {
      messages.add({"text":message, "isMe":true});
    });

    Future.delayed(Duration(seconds: 2)).then((value) {
      messages.add({"text":"自动回复消息:你好!请稍后再聊", "isMe":false});
      setState(() {
      });
    });
    _controller.clear();

  }

  //滚动到底部
  scrollToBottom() {
    // Future.delayed(Duration(seconds: 1)).then((value) {
      _scrollController.animateTo(_scrollController.position.maxScrollExtent,
          duration: Duration(milliseconds: 300), curve: Curves.easeOut);
    // });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Chat Screen')),
      body: GestureDetector(
        onTap: () => FocusScope.of(context).unfocus(),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Expanded(child: getListView()),
            getInputView(),
            SizedBox(
              height: 20,
            )
          ],
        ),
      ),
    );
  }

  Widget getListView() {
    return ListView.builder(
      controller: _scrollController,
      itemCount: messages.length,
      itemBuilder: (BuildContext context, int index) {
        bool isLast = index == messages.length-1;
        return AnimatedText(
          message: messages[index]["text"],
            isMe:messages[index]["isMe"],
          shouldAnimate:_isInputed && isLast && !messages[index]["isMe"],
          isLast: _isInputed && isLast,
        );
      },
    );
  }

  Widget getInputView() {
    return Row(
      children: [
        SizedBox(width: 8,),
        Expanded(
          child: TextField(
          controller: _controller,
            decoration: InputDecoration(
              contentPadding: EdgeInsets.all(4),
              hintText: '请输入消息...',
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(16.0),
              ),
            ),
            textInputAction: TextInputAction.newline,
            keyboardType: TextInputType.multiline,
            minLines: 1,
            maxLines: 3,
            // expands: false,
            maxLengthEnforcement: MaxLengthEnforcement.enforced,
          ),
        ),
        IconButton(
        icon: Icon(Icons.send),
        onPressed: () => _sendMessage(_controller.text),
        ),
        // SizedBox(width: 16,),
      ],
    );
  }
}

3. 我们把chartScreen 在main.dart里面调用一下

import 'package:flutter/material.dart';

import 'chat_page.dart';

void main() => runApp(const App());

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ChatScreen()
    );
  }
}

4. 运行看看效果

总结

1. 感叹ai的强大

以前碰到im大家可能会觉得恐惧,又要写气泡,适配,支持换行,计算高度等,现在交给ai就可以了,他可以帮我们把整体功能实现,我们只需要在这个基础上少做调整,当然以上代码并非100%由chatgpt生成的,其中有一丢丢是我在它提供的代码基础上稍作调整的,比如自动回复、初始化的聊天内容是我后加的。当然了有兴趣也可以试一下,让chatgpt帮我们做一个登录界面,因为这个需求比较好描述,ai理解起来比较明确,所以生成的代码是可以直接用的。后续扩展需的功能也比较简单,比如对邮箱加正则校验、密码长度大小写混合校验等,都是直接可以直接生成的

2. 插件

现在也有很多好用的插件可以集成进IDE,不过大多是要收费的,对于Android studio这样比较笨重IDE,我试了几个不过效果都不太好;对于使用vscode的推荐一个免费的插件codeium,这个对于python的支持尤其强大,开发的过程中,可以把需求档注释写,写完注释代码自动生成。

3.openai提示1020的错误

今天发现openai不能访问了,提示1020的错误,对于这个问题我是很迷惑的,因为我一直是通过日本的IP访问的,不知道怎么就无法访问了。好在尝试几次可以继续访问了,我主要是先把coockie清掉,然后换到新加坡的IP就可以了