「とりあえずOpenAI APIを呼び出すだけでチャットbot作れるでしょ?」
そう思ったことのある方、いませんか? 私も最初まったく同じ気持ちでした。でも現実は甘くなかった……というエピソードが海外の技術コミュニティで話題になっています。今回はその内容をもとに、ストリーミングAIチャットエンドポイントの正しい作り方を一緒に学んでいきましょう! 🚀
何が起きたのか?
あるエンジニアが個人サイト向けの簡単なチャットbotを作ろうとしました。ユーザーが質問を入力 → AIに送る → 回答を表示、というシンプルな構成です。
Node.js + Express でAPIを組んで、OpenAI APIを呼び出すだけ……のはずが、デモ中にチャットbotが何度もフリーズ。そして見慣れない数字が画面に現れます。
429 Too Many Requests
これがいわゆるレートリミット(Rate Limit)エラーです。「一定時間内にAPIを叩きすぎですよ」という警告ですね。
そもそもストリーミングとは?
ChatGPTを使ったことがある方なら、回答がひと文字ずつ順番に表示されていくのを見たことがあると思います。あれがまさにストリーミングです。
イメージとしては——
- ❌ 通常のAPI: 全部の回答が生成されてから「どーん」と一気に返ってくる
- ✅ ストリーミングAPI: 生成された文字をリアルタイムで少しずつ流してくれる
ユーザー体験がぜんぜん違いますよね。待ち時間のストレスが激減します。
実際のコード例を見てみましょう
Node.js(Express)でストリーミングを実装するとこんな感じです。ポイントをまとめるとこんな感じです👇
// ストリーミングAIチャットエンドポイントの例
const express = require('express');
const OpenAI = require('openai');
const app = express();
app.use(express.json());
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
app.post('/chat', async (req, res) => {
const { message } = req.body;
// ストリーミング用のレスポンスヘッダーを設定
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
try {
// stream: true でストリーミングモードをON
const stream = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: message }],
stream: true,
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content || '';
if (text) {
// チャンクをSSE形式でクライアントに送信
res.write(`data: ${JSON.stringify({ text })}
`);
}
}
res.write('data: [DONE]
');
res.end();
} catch (err) {
// 429エラー(レートリミット)を個別にハンドリング
if (err.status === 429) {
res.write('data: {





