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

如何在React Native(Expo)中实现ChatGPT Turbo API逐词流式输出?

在React Native(Expo)中实现ChatGPT Turbo API逐词流式输出

ChatGPT Turbo API完全支持逐词流式输出,只需在请求中开启流式参数并正确处理分块响应即可。以下是具体实现方案:

核心思路

开启API请求的stream: true参数后,OpenAI会将响应拆分为多个数据块逐步返回。我们需要在React Native中读取这些分块数据,提取增量文本并实时更新界面。

完整实现代码

import { useState } from 'react';
import { View, Text, TextInput, Button, ScrollView } from 'react-native';

const ChatScreen = () => {
  const [inputText, setInputText] = useState('');
  const [responseText, setResponseText] = useState('');
  const [isLoading, setIsLoading] = useState(false);

  const sendMessage = async () => {
    if (!inputText.trim() || isLoading) return;

    setIsLoading(true);
    setResponseText('');

    try {
      const response = await fetch('https://api.openai.com/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${process.env.EXPO_PUBLIC_OPENAI_API_KEY}`
        },
        body: JSON.stringify({
          model: 'gpt-3.5-turbo',
          messages: [{ role: 'user', content: inputText }],
          stream: true
        })
      });

      if (!response.ok) {
        throw new Error(`API请求失败: ${response.status}`);
      }

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

      while (!done) {
        const { value, done: streamDone } = await reader.read();
        done = streamDone;

        if (value) {
          const chunk = decoder.decode(value, { stream: true });
          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 || '';
                setResponseText(prev => prev + content);
              } catch (e) {
                console.error('解析响应块失败:', e);
              }
            }
          }
        }
      }
    } catch (error) {
      console.error('请求错误:', error);
      setResponseText(`请求失败: ${error.message}`);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <View style={{ flex: 1, padding: 16 }}>
      <ScrollView style={{ flex: 1, marginBottom: 16 }}>
        <Text style={{ fontSize: 16, lineHeight: 24 }}>
          {responseText}
        </Text>
      </ScrollView>
      <View style={{ flexDirection: 'row', gap: 8 }}>
        <TextInput
          style={{ flex: 1, borderWidth: 1, borderColor: '#ccc', padding: 8, borderRadius: 4 }}
          value={inputText}
          onChangeText={setInputText}
          placeholder="输入你的问题..."
          editable={!isLoading}
        />
        <Button
          title={isLoading ? "加载中..." : "发送"}
          onPress={sendMessage}
          disabled={isLoading}
        />
      </View>
    </View>
  );
};

export default ChatScreen;

关键注意事项

  • API密钥安全:不要硬编码API密钥,使用Expo环境变量(前缀EXPO_PUBLIC_)存储,生产环境建议通过自有后端代理请求,避免密钥暴露。
  • 响应解析逻辑:API返回的每块内容以data: 开头,需过滤空行并裁剪前缀后解析JSON,[DONE]标记代表流结束,直接忽略即可。
  • 状态更新方式:使用setResponseText(prev => prev + content)确保每次更新基于最新状态,避免异步更新导致的文本丢失。

失败原因排查

之前用JavaScript实现失败,大概率是没正确处理流式响应的分块格式,或是未使用TextDecoder解码二进制流。另外要确认API密钥权限、账户余额是否正常,以及请求参数是否正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:38:10