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

如何在Laravel中中断OpenAI流式响应并避免Token浪费?

流式响应中途停止功能实现方案

前端JS实现

核心是利用浏览器原生的AbortController中断流式请求,搭配停止按钮触发中断操作:

// 全局存储中断控制器实例
let abortController;

// 发起流式聊天请求
async function startChatStream() {
  abortController = new AbortController();
  const signal = abortController.signal;

  try {
    const response = await fetch('/api/chat-stream', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
      },
      body: JSON.stringify({ prompt: document.getElementById('user-prompt').value }),
      signal: signal
    });

    const reader = response.body.getReader();
    const decoder = new TextDecoder('utf-8');
    const chatContent = document.getElementById('chat-content');

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      // 追加流式返回的内容到聊天框
      chatContent.textContent += decoder.decode(value);
    }
  } catch (error) {
    // 忽略主动中断的错误
    if (error.name !== 'AbortError') {
      console.error('请求异常:', error);
    }
  }
}

// 绑定停止按钮事件
document.getElementById('stop-response-btn').addEventListener('click', () => {
  if (abortController) {
    abortController.abort();
    abortController = null;
    // 更新UI状态
    document.getElementById('status-indicator').textContent = '已停止响应';
  }
});

后端Laravel实现

需要检测客户端连接状态,一旦断开就终止OpenAI流式API调用,避免资源浪费:

use Illuminate\Http\Request;
use OpenAI\Client;

Route::post('/api/chat-stream', function (Request $request, Client $openai) {
    $prompt = $request->input('prompt');

    return response()->stream(function () use ($openai, $prompt) {
        // 调用OpenAI流式接口
        $stream = $openai->chat()->createStreamed([
            'model' => 'gpt-3.5-turbo',
            'messages' => [['role' => 'user', 'content' => $prompt]],
        ]);

        foreach ($stream as $chunk) {
            // 检查客户端是否断开连接
            if (connection_aborted()) {
                break;
            }

            $content = $chunk->choices[0]->delta->content ?? '';
            echo $content;
            // 强制刷新缓冲区,确保内容实时返回前端
            ob_flush();
            flush();
        }
    }, 200, [
        'Content-Type' => 'text/plain; charset=utf-8',
        'Transfer-Encoding' => 'chunked',
    ]);
});

关键注意事项

  • 前端必须通过AbortController中断请求,这是目前浏览器支持的标准中断Fetch请求的方式
  • 后端通过connection_aborted()函数检测客户端连接状态,一旦返回true立即终止循环和API调用
  • 后端每次输出内容后必须调用ob_flush()和flush(),避免内容被服务器缓冲区缓存,确保流式传输的实时性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:43:21