React与OpenAI流式传输结果在更新和显示响应时出现重复值

我正在尝试从OpenAI的流式响应中获取响应,并在聊天界面中向用户显示响应。然而,虽然响应的每个块本身是正确的,但我的状态最终会出现重复的词语… 问题出在哪里?

这是我的代码以及显示UI和控制台输出的截图:

useEffect(() => {  const doCompletion = async () => {    if (!newMessage) return;          try {      await handleCompletion(messages);      setNewMessage(false);    } catch (err) {      console.log("无法与模型服务通信: ", err)    }  }  doCompletion();}, [newMessage]);const handleNewMessage = async (formData: FormData) => {  const message = formData.get("message") as string;  addMessage({id: uuidv4(), data: {role: "user", content: message}});  setNewMessage(true);}const handleCompletion = async (messages: Message[]) => {  const formattedMessages = messages.map((message: Message)=> message.data)  const stream = await openai.chat.completions.create({    messages: formattedMessages,    model: "deepseek-chat",    stream: true  });      for await (const chunk of stream) {    const content = chunk.choices[0]?.delta?.content;    console.log("内容: ", content)          setMessages((prev) => {      let tmpMessages = [...prev];      const lastMessageIndex = tmpMessages.length-1;      if (tmpMessages[lastMessageIndex].data.role !== "assistant") {        tmpMessages.push({id: chunk.id, data: {role: "assistant", content: ""}});        return tmpMessages;      }      const prevContent = tmpMessages[lastMessageIndex].data.content;      console.log("之前的内容: ", prevContent)            const newContent = prevContent! + content!;      console.log("新的内容: ", newContent)              tmpMessages[lastMessageIndex].data.content = newContent;      return tmpMessages;    });  }}

输入图片说明


回答:

让我们尝试修复它!

你的问题是在React中流式传输OpenAI响应时,快速的块更新可能会导致状态过时,从而在显示的聊天中出现重复的词语。

我的建议是使用useRef来存储来自OpenAI流的最新累积内容。这样可以确保状态更新基于最新的数据。

import React, { useState, useEffect, useRef } from 'react';const YourComponent = () => {  const [messages, setMessages] = useState([]);  const assistantContentRef = useRef('');  const handleCompletion = async (messages) => {    // 设置OpenAI流    assistantContentRef.current = ''; // 重置ref    for await (const chunk of stream) {      const content = chunk.choices[0]?.delta?.content;      if(content){        assistantContentRef.current += content;        setMessages((prev) => {          // 使用assistantContentRef.current更新消息          let tmpMessages = [...prev];          const lastMessageIndex = tmpMessages.length - 1;          if (tmpMessages[lastMessageIndex]?.data.role !== 'assistant') {            tmpMessages.push({              id: chunk.id,              data: { role: 'assistant', content: assistantContentRef.current },            });          } else {            tmpMessages[lastMessageIndex].data.content = assistantContentRef.current;          }          return tmpMessages;        });      }    }  };  // 你的其他代码 };export default YourComponent;

这种方法可以保证你的React状态始终反映最新的AI响应,防止重复出现。:)

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注