หากเคยใช้ OpenAI API อาจสังเกตว่ามันช่อนิดหน่อย และบางครั้งไม่ตอบสนองเลย โดยเฉพาะ GPT-4 Model มี Latency สูง นอกจากนี้ยังจ่ายเงินต่อทุก Response เหล่านี้เป็นเหตุผลหลีกเลี่ยงการ Serve Responses โดยตรง
เก็บ Responses ไว้ใน Upstash Redis แทน หาก Serve Response เดียวกันให้หลาย Clients จะประหยัดเงินได้มาก และด้วย Global Deployments ผู้ใช้ได้ข้อมูลเร็วที่สุด
บทความนี้แนะนำการ Cache OpenAI API Responses ไป Upstash Redis Database
Features - ฟีเจอร์
สร้าง Web App แสดง History Jokes ให้ Visitors:
- Query OpenAI API ทุกวันเพื่อขอ History Joke ตามวันที่ปัจจุบัน
- Cache Joke ไว้สำหรับส่งต่อ
- แสดง Jokes ทั้งหมด
Technology - เทคโนโลยี
- Node.js เป็น HTTP Server
- OpenAI API Generate History Jokes
- Upstash QStash Trigger Joke Request จาก HTTP Server ไป OpenAI API
- Upstash Redis เก็บ Joke สำหรับใช้ภายหลัง
Prerequisites - เงื่อนไขก่อนเริ่ม
- OpenAI Account พร้อม API Access
- Upstash Account ส่ง Request ไป OpenAI และ Cache Responses ใน Upstash Redis
- Node.js Installation เรียก OpenAI และ Upstash APIs
Implementation - การทำงาน
Setting Up the Project - ตั้งค่าโปรเจกต์
สร้าง Node.js Project ใหม่ Install Dependencies:
$ mkdir history-jokes & cd history-jokes
$ npm init -y
$ npm i dotenv express axios @upstash/redis @upstash/qstash
Implementing the Server - Implement Server
สร้าง index.js ใส่โค้ด:
require("dotenv").config();
const axios = require("axios");
const express = require("express");
const { Redis } = require("@upstash/redis");
const { Receiver } = require("@upstash/qstash");
const redisClient = new Redis({ url: process.env.UPSTASH_REDIS_URL, token: process.env.UPSTASH_REDIS_TOKEN });
const qstashReceiver = new Receiver({ currentSigningKey: process.env.UPSTASH_QSTASH_CURRENT_SIGNING_KEY, nextSigningKey: process.env.UPSTASH_QSTASH_CURRENT_NEXT_KEY });
const openaiApiClient = axios.create({ baseURL: "https://api.openai.com/v1", headers: { Authorization: "Bearer " + process.env.OPENAI_TOKEN, "Content-Type": "application/json" } });
const server = express();
server.use("/generate", async (request, response, next) => {
let validRequest = false;
try { validRequest = await qstashReceiver.verify({ signature: request.headers["upstash-signature"], body: "" }); } catch (e) {}
if (!validRequest) return response.status(403).end("Forbidden");
return next();
});
server.post("/generate", async (_request, response) => {
const today = new Date();
const month = today.toLocaleString("default", { month: "long" });
let day = today.toLocaleString("default", { day: "numeric" });
day = day == 1 ? "1st" : day == 2 ? "2nd" : day == "3" ? "3rd" : day + "th";
const { data } = await openaiApiClient.post("/chat/completions", { model: "gpt-3.5-turbo", messages: [ { role: "system", content: "You are a comedian that tells short history jokes." }, { role: "user", content: `Please tell me a joke for ${month} the ${day}.` } ] });
const joke = JSON.stringify({ date: month + " the " + day, text: data.choices[0].message.content });
await redisClient.lpush("jokes", joke);
response.end();
});
server.get("/", async (_request, response) => {
let html = "<h1>History Jokes for Every Day</h1>";
const jokes = await redisClient.lrange("jokes", 0, -1);
html += "<ul>" + jokes.map(({ date, text }) => `<li><b>${date}</b><br><pre>${text}</pre></li>`).join("") + "</ul>";
response.setHeader("Content-Type", "text/html");
response.end(html);
});
server.listen(3000);
ส่วนสำคัญของโค้ด:
ใช้ redisClient Save/Load Responses ใน Upstash Redis
qstashReceiver Verify Daily Calls จาก Upstash QStash รับรองว่าแค่ QStash เรียก /generate Endpoint
ใช้ Axios สร้าง OpenAI API Client ไม่ต้องส่ง baseUrl และ Authentication Header ทุกครั้ง
สร้าง Express Middleware ใช้ qstashReceiver Verify Requests ไป /generate ใช้ Empty String เป็น body เพราะ QStash Trigger เท่านั้นไม่ส่งค่า
Note: Middleware อนุญาตทั้งหมดถ้า Un-comment // return next() ใช้ Test /generate บน localhost
/generate Endpoint Listen POST Requests สร้างและเก็บ Jokes คำนวณ month และ day สร้าง Prompts 2 อัน: บอก AI เป็น Comedian และขอ History Joke ตามเดือน/วัน เรียก OpenAI API Save Result ใน LIST Upstash Redis
/ Endpoint Listen GET Requests แสดง Jokes โหลด LIST จาก Upstash Redis Format HTML List Elements ส่ง Client
Deployment - การ Deploy
Server Ready สร้าง Cloud Resources และใส่ API Credentials
Creating a Credential File - สร้าง Credential File
สร้าง .env ด้วยเนื้อหา:
OPENAI_TOKEN=""
UPSTASH_REDIS_REST_URL=""
UPSTASH_REDIS_REST_TOKEN=""
UPSTASH_QSTASH_CURRENT_SIGNING_KEY=""
UPSTASH_QSTASH_NEXT_SIGNING_KEY=""
ขั้นตอนต่อไป Fill Strings เหล่านี้
Creating an OpenAI API Token - สร้าง OpenAI API Token
เริ่ม OpenAI API ต้องการ Key เฉพาะ ไม่ต้อง Deploy ไป OpenAI Web Console กด "Create New Secret Key" ตั้งชื่อ กด "Create Secret Key" Copy Key ใส่ .env เป็น OPENAI_TOKEN
Deploying a Recurring Request with QStash - Deploy Recurring Request ด้วย QStash
บอก QStash ให้ส่ง Request ไป /generate วันละครั้ง ใช้ "Request Builder" ใน Upstash Console Figure 1 แสดง Config:

Figure 1: QStash Request Builder
แทนที่ <HOSTNAME> ด้วย Domain ที่ Host Server ต้องมี Publicly Accessible Hostname สำหรับ QStash
Signing Keys QStash ใช้ อยู่ใน Upstash Console Section "Request Builder" กด Grey "Signing Keys" Dropdown Copy Keys ใส่ .env ให้ถูกต้อง
Deploying an Upstash Redis Database - Deploy Upstash Redis Database
สร้าง Upstash Redis Database ไป Upstash Console กด "Create Database" Button
Dialog Config Database Figure 2 แสดงค่าที่ควรใช้:

Figure 2: Upstash Redis Configuration
สร้างเสร็จ Scroll ลง "REST API" Section มี Buttons "UPSTASH_REDIS_REST_URL" และ "UPSTASH_REDIS_REST_TOKEN" กด Copy Credentials ใส่ .env ให้ถูก
Testing the Website - ทดสอบ Website
Test Local Machine Deactivate QStash Validation Middleware Un-comment // return next() ใน index.js
Run Server:
$ node .
เปิด / Route ใน Browser ควรเห็นแค่ "History Jokes for Every Day" เพราะยังไม่มี Jokes Generated
ส่ง POST Request ไป /generate Generate Joke:
$ curl -X POST https://localhost/generate
Refresh Browser ควรเห็น Joke เหมือน Figure 3:

Figure 3: Joke Website
Joke นี้ Cached ใน Upstash Redis แล้ว ไม่มี OpenAI API Requests ตอน User Visit Website ได้ Sub-second Response Times ประหยัดเงินมาก
Summary - สรุป
AI APIs เป็น Tools หลากหลายจะ Transform Internet แต่วันนี้ Slow และ Expensive Caching Vital ตอนใช้ APIs นี้ Upstash Redis คือวิธีง่ายที่สุดเพิ่มใน Stack แค่ไม่กี่คลิก