You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GPT生成响应时即时显示用户输入的指令?

实现即时显示用户输入+流式AI回复的方案

核心思路

  1. 发送消息时立即将用户指令加入对话列表,AI回复先留空(或显示加载状态),让用户输入立刻显示在页面上
  2. 调用OpenAI API时启用流式响应(stream: true),逐字接收AI生成的内容,实时更新对话中的AI回复,模拟ChatGPT的打字效果
  3. 使用React的函数式状态更新,确保每次对话修改都基于最新的列表数据,避免异步状态冲突

修改后的完整代码

import React, { useState } from 'react';

function TextInput({ label, ...props }) {
    return (
        <div>
            <input
                type="text"
                {...props}
                value={props.instruction}
                onChange={props.handleInstructionChange}
                placeholder="输入你的问题..."
            />
            <button onClick={props.startChat}>Send Message</button>
            <label htmlFor={props.id}>{label}</label>
        </div>
    );
}

const Chat = () => {
    const [conversation, setConversation] = useState([]);
    const [instruction, setInstruction] = useState('');

    const handleInstructionChange = (event) => {
        setInstruction(event.target.value);
    };

    const startChat = async () => {
        if (!instruction.trim()) return;

        // 1. 立即添加用户消息到对话列表,AI回复先占位
        const userMessage = { role: 'user', content: instruction };
        setConversation(prev => [...prev, userMessage]);
        setInstruction(''); // 清空输入框

        // 添加AI消息占位,后续实时更新内容
        setConversation(prev => [...prev, { role: 'assistant', content: '' }]);
        const aiMessageIndex = conversation.length + 1;

        try {
            const response = await fetch('https://api.openai.com/v1/chat/completions', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${process.env.REACT_APP_OPENAI_API_KEY}`
                },
                body: JSON.stringify({
                    model: 'gpt-3.5-turbo',
                    messages: [...conversation, userMessage].map(msg => ({ role: msg.role, content: msg.content })),
                    stream: true // 开启流式响应
                })
            });

            if (!response.ok) throw new Error('API请求失败');

            const reader = response.body.getReader();
            const decoder = new TextDecoder('utf-8');

            // 2. 逐段读取流式数据,实时更新AI回复
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;

                const chunk = decoder.decode(value);
                const lines = chunk.split('\n').filter(line => line.trim() !== '');
                for (const line of lines) {
                    if (line.startsWith('data: ')) {
                        const data = line.slice(6);
                        if (data === '[DONE]') continue;
                        try {
                            const json = JSON.parse(data);
                            const content = json.choices[0].delta.content || '';
                            // 函数式更新,基于最新对话列表追加内容
                            setConversation(prev => {
                                const newConversation = [...prev];
                                newConversation[aiMessageIndex].content += content;
                                return newConversation;
                            });
                        } catch (e) {
                            console.error('解析流式数据失败:', e);
                        }
                    }
                }
            }
        } catch (error) {
            console.error('对话出错:', error);
            // 更新AI消息为错误提示
            setConversation(prev => {
                const newConversation = [...prev];
                newConversation[aiMessageIndex].content = '抱歉,生成回复时出错了,请重试。';
                return newConversation;
            });
        }
    };

    return (
        <div style={{ marginLeft: 20, maxWidth: 800 }}>
            {conversation.map((message, index) => (
                <div key={index} style={{ marginBottom: 12, padding: 10, borderRadius: 8, backgroundColor: message.role === 'user' ? '#f0f4f8' : '#ffffff', border: '1px solid #e2e8f0' }}>
                    <div style={{ fontWeight: 'bold', marginBottom: 4 }}>
                        {message.role === 'user' ? '你' : 'AI'}
                    </div>
                    <div style={{ whiteSpace: 'pre-wrap' }}>
                        {message.content || (message.role === 'assistant' ? '正在思考...' : '')}
                    </div>
                </div>
            ))}
            <div style={{ marginTop: 20 }}>
                <TextInput
                    label="输入问题"
                    name="chat-input"
                    autoComplete="off"
                    startChat={startChat}
                    handleInstructionChange={handleInstructionChange}
                    instruction={instruction}
                />
            </div>
        </div>
    );
};

export default Chat;

关键代码说明

  1. 即时显示用户输入:点击发送后立刻将用户消息插入对话列表,同时清空输入框,页面会瞬间渲染用户输入内容
  2. 流式响应处理:通过stream: true开启OpenAI的流式输出,逐块读取服务器返回的数据,解析出每一段生成的文本并追加到AI回复中,实现打字机效果
  3. 函数式状态更新:所有对话列表的更新都使用setConversation(prev => ...),确保每次修改都基于最新的状态,避免异步更新导致的内容覆盖
  4. 加载与错误提示:AI生成回复时显示"正在思考...",请求出错时更新为错误提示,提升用户体验

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:34:57