用 Bun + Vercel 打造免費、有記憶的 Serverless Telegram AI Bot
想做一個 AI Telegram Bot,但不想租伺服器?
這篇文章教你用 Bun + Vercel Functions 打造一個完全免費、反應極快且擁有對話記憶的 AI 機器人。
我們將解決以下關鍵挑戰:
- Serverless Timeout:如何讓 Webhook 在 10秒內回應,同時處理 AI 長時間運算?
- AI 對話記憶:在無狀態的 Serverless 環境,如何讓 AI 記得你的名字?
- SDK 相容性地雷:Vercel AI SDK 與 OpenRouter 目前的 Bug 及解決方案。
為什麼選擇 Bun + Vercel?
- Bun:啟動速度極快,比 Node.js 更適合 Serverless 冷啟動 (Cold Start)。
- Vercel Functions:免費額度大,部署簡單,支援
waitUntil(背景執行)。 - OpenRouter:提供 Google Gemini 2.0 Flash 等免費且強大的模型。
- Upstash KV:Vercel 原生整合的 Redis,用來存對話記憶剛好。
步驟 1:初始化專案
使用 Bun 快速建立專案:
mkdir telegram-ai-bot
cd telegram-ai-bot
bun init
bun add @vercel/functions @vercel/kv
建立 vercel.json 設定檔,告訴 Vercel 使用 Bun runtime:
{
"bunVersion": "1.x", // 關鍵:使用 Bun 1.x 版本
"crons": [
{
"path": "/api/cron-notify",
"schedule": "0 4 * * *"
}
]
}
步驟 2:實作 Webhook (關鍵:waitUntil)
Telegram 要求 Webhook 必須在短時間內回應 200 OK,否則會重複發送訊息。但 AI 生成通常需要幾秒鐘。
解決方案:使用 Vercel 的 waitUntil,先回應 200,再於背景處理 AI。
建立 api/telegram-webhook.ts:
import { waitUntil } from '@vercel/functions';
export async function POST(request: Request) {
let update;
try {
update = await request.json();
} catch (e) {
return new Response('Invalid JSON', { status: 400 });
}
// 1. 立即回應 Telegram "收到!"
const response = new Response('OK', { status: 200 });
// 2. 背景執行繁重的 AI 任務
waitUntil(handleTelegramUpdate(update));
return response;
}
async function handleTelegramUpdate(update: any) {
const chatId = update.message?.chat?.id;
const text = update.message?.text;
if (!chatId || !text) return;
// 呼叫 AI 並回傳訊息的邏輯寫在這裡...
}
步驟 3:整合 AI 與記憶 (Sliding Window)
要讓 AI 記得對話,我們不能依賴 Server 的記憶體 (因為 Serverless 隨時會回收)。我們必須將對話存入資料庫 (Upstash KV)。
⚠️ 特別注意:Vercel AI SDK vs OpenRouter
原本想用 Vercel AI SDK (ai 套件) 來簡化開發,但發現目前 (2026.01) Vercel AI SDK 與 OpenRouter 存在相容性問題 (會報錯 APICallError)。
因此,我們回歸最穩定的做法:使用原生 fetch + 手動 Sliding Window。
實作記憶邏輯
import { kv } from '@vercel/kv';
// ... Inside handleTelegramUpdate ...
const conversationKey = `chat:${chatId}`;
// 1. 從 KV 讀取歷史訊息 (預設空陣列)
const history = await kv.get<Array<{role: string, content: string}>>(conversationKey) || [];
// 2. 組合 API Payload (System + History + Current User Message)
const messages = [
{
role: 'system',
content: '你是一個友善的 Telegram 助理,請用 HTML 格式回覆 (<b>粗體</b>, <i>斜體</i>)...'
},
...history, // 帶入舊記憶
{ role: 'user', content: text }
];
// 3. 呼叫 OpenRouter API (使用 fetch)
const aiRes = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'google/gemini-2.0-flash-exp:free', // 免費又快!
messages: messages,
}),
});
const aiData = await aiRes.json();
const replyText = aiData.choices?.[0]?.message?.content || '思考中斷...';
// 4. 更新記憶 (Sliding Window:只留最近 10 則)
const updatedHistory = [
...history,
{ role: 'user', content: text },
{ role: 'assistant', content: replyText }
].slice(-10); // 關鍵:避免 Token 爆炸,只留最後 5 輪對話
await kv.set(conversationKey, updatedHistory);
// 5. 回傳給 Telegram
await fetch(`https://api.telegram.org/bot${process.env.TELEGRAM_TOKEN}/sendMessage`, {
method: 'POST',
body: JSON.stringify({
chat_id: chatId,
text: replyText,
parse_mode: 'HTML' // 支援格式化輸出
})
});
步驟 4:設定環境變數與部署
- 在 Vercel 建立新專案。
- 在 Storage 頁籤新增 Upstash KV (Vercel 會自動幫你設定 KV 相關變數)。
- 在 Settings > Environment Variables 加入:
TELEGRAM_TOKEN: 從 BotFather 取得。OPENROUTER_API_KEY: OpenRouter 金鑰。
- 部署:
bunx vercel --prod
取得部署網址,例如:https://my-bot.vercel.app。
步驟 5:綁定 Webhook
最後一步,告訴 Telegram 把訊息往哪裡送。使用 curl 設定:
curl -F "url=https://my-bot.vercel.app/api/telegram-webhook" \
https://api.telegram.org/bot<YOUR_TELEGRAM_TOKEN>/setWebhook
如果看到 Webhook was set,恭喜你!你的 AI 機器人已經上線了 🎉
總結
我們完成了一個強大的架構:
- Bun + Vercel:免費、快速、自動擴展。
- WaitUntil:優雅解決 Webhook Timeout 問題。
- Upstash KV + Sliding Window:極低成本實現 AI 記憶。
- OpenRouter Free Model:享受 Google Gemini 2.0 的強大能力而不花一分錢。
雖然我們遇到了 Vercel AI SDK 的小坑,但回歸 fetch 反而讓我們更清楚底層的運作原理,系統也更輕量穩定了!
- ← Previous
從 Serverless 到 PaaS:Vercel、Railway 與 Fly.io 多語言 API 部署全解析 - Next →
Telegram Bot 進化:整合 xAI Grok Responses API 與圖片分析