用react搞定一个大模型对话效果

怎么用react实现一个类似文心一言那样的对话效果呢?

最近AI盛行,关注几个大模型网站都能发现,跟AI对话的时候,返回的文本是逐字展示的,就给人一种AI边解析边返回的感觉(不知道是为了装X还是真的需要这样)。正好部门内也有这么个需求,那就开干呗。
先看看效果:

在这里插入图片描述
ok
由于我这边后端返回是一次性返回所有回复,而天煞的产品经理要求做出逐字展示效果,于是我只能纯前端控制展示。
废发不多梭,开始搞代码。
先上个图,看看页面结构
在这里插入图片描述
列表的的格式是这样:

const [list, setList] = useState([
    {
      id: -1,
      type: 1,
      content: <Introduction chooseChatType={(v) => chatInit(v)} />,  // 渲染对象
    },
  ]); // 对话列表, type: 1 机器人, type: 2 用户 -1 初始介绍 -2 loading

整体编码过程不难,有几个细节需要注意:
1.发送消息后到后端返回消息钱,需要展示一个loading过渡
2.后端返回字符串后,需要逐字切割展示。这里我注意考虑两个方案,
第一个:用个定时器,把时差设置为变量delay,每次都随机生成delay,固定展示三个字符,直到展示完全。简单来讲就是,速度不固定,每次展示长度固定
第二个:速度固定,每次展示不同长度内容

这里我选用的第一种方案。

需要注意的是每次更新最后一条的内容都需要把list的最后一项pop出去,需要记录返回的内容切割后的内容,这里我用的useRef生成的变量来记录内容,主要代码如下:

const loading = useCallback(() => {
    resetMsgList({
      id: -2,
      type: 1,
      content: (
        <Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} />
      ),
    });
  }, []);
// 删除字符串前三位,不满前三位直接返回空
export const deleteStr = (str) => {
  try {
    if (str.length < 3) return '';

    let arr = str.split('');
    arr.splice(0, 3);
    return arr.join('');
  } catch (err) {
    console.warn(err);
  }
};

  // 记录最新的回复内容
  const currentReply = useRef('');
// 随机产生时差来展示字符
  const clear = useInterval(() => {
    if (currentReply.current.length < 1) {
      clear();
    } else {
    //  固定切割字符串三位
      const str = currentReply.current.substr(0, 3);
      currentReply.current = deleteStr(currentReply.current);
      setList((oldList) => {
        const last = oldList.pop();
        return [
          ...oldList,
          {
            id: replyId,
            type: 1,
            content:
              typeof last?.content === 'string' && !isRegenerate.current
                ? last.content + str
                : str,
          },
        ];
      });
	
	// 随机生成时差,1 - 500 毫秒
      const randomTime = Math.floor(Math.random() * 10) * 50 + 1;
      setDelay(randomTime);
    }
    isRegenerate.current = false;
  }, delay);

  const send = throttle(async (e, msg) => {
    try {
      e?.preventDefault();
      // 判断是否是alt+enter,是则识别位换行
      if (e?.altKey) {
        setInputMsg(inputMsg + '\n');
        return;
      }
      // if (eventSourceObj) eventSourceObj.current = null;

      const input = msg || inputMsg;
      if (!input) {
        message.warn('请输入对话内容');
        return;
      }

      resetMsgList({ id: -1, type: 2, content: input });
      loading();

      setInputMsg('');
      setCompareVisible(false);
      let res = await sendMsgHttp({ content: input, quType: questionType });
      if (res.code === 0) {
        quId.current = res.data.quId;
        setReplyId(res.data.replyId);

        currentReply.current = res.data.reply;
        setDelay(100);
      }
    } catch (err) {
      console.warn('err');
    }
  }, 300);

整体实现并不难,但要做好每个细节还是需要一点思考的,

ok,,我要拿去装逼了,拜拜!!!

### 大模型 ReAct 架构与应用介绍 #### ReAct 框架概述 ReAct框架作为一种基于强化学习的AI Agent开发工具,通过引入组合动作空间(compositional action space)和时间抽象(temporal abstraction),使得AI代理能够在处理复杂任务时表现得更加出色[^4]。 #### 技术细节 为了增强ReAct框架下的大语言模型性能,可以采用多种先进技术手段。其中包括但不限于多头注意力机制、残差连接以及前馈神经网络的应用,这些方法有助于显著改善模型的表现力并优化计算资源利用率[^2]。 #### 应用场景实例 在实际部署方面,以智能客服系统为例,在该领域内部署经过改进后的ReAct框架支持的大规模预训练语言模型,不仅能够提供更为精准的服务响应,而且还能依据特定业务需求灵活调整策略,从而达到更好的用户体验效果[^3]。 #### 进一步提升路径 除了上述提到的技术外,实践过程中还可以探索更大规模更高强度的预训练模型,并结合多样化的微调技术和精细化参数调节措施,力求突破现有水平,实现更高级别的智能化服务目标。 ```python # 示例代码展示如何加载预训练好的大型语言模型 from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "gpt-neo-1.3B" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained(model_name) text = "Once upon a time," input_ids = tokenizer.encode(text, return_tensors='pt') output = model.generate(input_ids, max_length=50) print(tokenizer.decode(output[0], skip_special_tokens=True)) ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值