🚀 打造你的第一個 ChatGPT Node.js 客戶端
前言:在這個 AI 時代,如何將 ChatGPT 整合到自己的應用程式中已經成為許多開發者的必備技能。今天,我們將從零開始,用純 Node.js 打造一個功能完整的 ChatGPT 客戶端,不需要任何第三方 HTTP 套件,只用 Node.js 原生的 https 模組。讓我們開始這段精彩的旅程吧!
為什麼要自己寫 ChatGPT 客戶端?
你可能會問:市面上已經有那麼多現成的套件,為什麼還要自己寫?原因很簡單:
- 深入理解 API 運作原理:透過自己實作,你會更清楚 HTTP 請求、串流處理、錯誤處理等核心概念
- 完全掌控:不依賴第三方套件,你可以根據需求自由客製化功能
- 學習價值:這是一個很好的學習專案,涵蓋了 Node.js 開發的多個重要面向
- 輕量化:沒有多餘的依賴,程式更輕量、更容易維護
核心架構設計
我們的 ChatGPT 客戶端將採用物件導向的設計方式,封裝成一個 ChatGPTClient 類別。這個類別將提供兩個主要方法:
- sendMessage():發送訊息並等待完整回應
- sendMessageStream():使用串流方式即時接收回應
第一步:建立 ChatGPTClient 類別
讓我們從基礎架構開始。首先引入 Node.js 的原生 https 模組,然後建立我們的類別框架:
const https = require('https'); class ChatGPTClient { constructor(apiKey) { this.apiKey = apiKey; this.apiUrl = 'api.openai.com'; this.apiPath = '/v1/chat/completions'; } } module.exports = ChatGPTClient;
💡 設計說明:為什麼要分開儲存 apiUrl 和 apiPath?這樣的設計讓我們在測試或使用代理伺服器時,可以輕鬆修改 API 端點,提高了程式的靈活性。
實作核心功能:sendMessage()
這是客戶端的核心方法,負責發送訊息到 OpenAI 並處理回應。讓我們逐步解析每個部分:
1. 準備請求資料
首先,我們需要準備要發送給 OpenAI API 的資料。這包括對話歷史和新訊息:
async sendMessage(message, conversationHistory = [], model = 'gpt-3.5-turbo') { // 組合完整的對話訊息陣列 const messages = [ ...conversationHistory, { role: 'user', content: message } ]; // 準備 API 請求的資料 const requestData = JSON.stringify({ model: model, messages: messages, temperature: 0.7, // 控制創造性 (0-2) max_tokens: 1000 // 最大回應長度 });
⚠️ 重要參數說明:
- temperature:控制回應的隨機性,0 表示確定性回答,2 表示高度創造性
- max_tokens:限制回應的最大長度,避免過長的回應消耗太多 token
2. 設定 HTTPS 請求選項
接下來設定 HTTP 請求的標頭和參數。特別注意要包含 API Key 進行身份驗證:
const options = { hostname: this.apiUrl, path: this.apiPath, method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}`, 'Content-Length': Buffer.byteLength(requestData) } };
3. 發送請求並處理回應
這是最關鍵的部分。我們使用 Promise 來處理非同步操作,讓程式碼更易讀、更好維護:
return new Promise((resolve, reject) => { const req = https.request(options, (res) => { let data = ''; // 接收資料片段 res.on('data', (chunk) => { data += chunk; }); // 資料接收完成 res.on('end', () => { try { const response = JSON.parse(data); if (res.statusCode === 200) { resolve({ success: true, message: response.choices[0].message.content, fullResponse: response }); } else { reject({ success: false, error: response.error || 'Unknown error', statusCode: res.statusCode }); } } catch (error) { reject({ success: false, error: 'Failed to parse response', details: error.message }); } }); }); // 處理網路錯誤 req.on('error', (error) => { reject({ success: false, error: 'Request failed', details: error.message }); }); // 發送請求資料 req.write(requestData); req.end(); });
🔍 程式碼解析:
- data 事件:當接收到資料片段時觸發,我們將它們累積起來
- end 事件:當所有資料接收完畢時觸發,此時解析 JSON 並回傳結果
- error 事件:當網路請求失敗時觸發,需要妥善處理錯誤
進階功能:串流回應
當 ChatGPT 回應較長時,等待完整回應可能需要較長時間。串流模式可以讓我們即時看到 AI 的回應,就像在 ChatGPT 網頁版看到的那樣:
async sendMessageStream(message, conversationHistory = [], onChunk, model = 'gpt-3.5-turbo') { const messages = [ ...conversationHistory, { role: 'user', content: message } ]; const requestData = JSON.stringify({ model: model, messages: messages, temperature: 0.7, max_tokens: 1000, stream: true // 啟用串流模式! }); // ... 設定 options(同上)... return new Promise((resolve, reject) => { const req = https.request(options, (res) => { let fullMessage = ''; res.on('data', (chunk) => { // 解析 Server-Sent Events 格式 const lines = chunk.toString().split('\n') .filter(line => line.trim() !== ''); for (const line of lines) { if (line.includes('[DONE]')) { resolve(fullMessage); return; } if (line.startsWith('data: ')) { try { const jsonData = JSON.parse(line.slice(6)); const content = jsonData.choices[0]?.delta?.content; if (content) { fullMessage += content; onChunk(content); // 呼叫回調函數 } } catch (error) { // 忽略解析錯誤 } } } }); res.on('end', () => { resolve(fullMessage); }); }); req.on('error', (error) => { reject({ success: false, error: 'Request failed', details: error.message }); }); req.write(requestData); req.end(); }); }
✨ 串流模式的優勢:
- 使用者體驗更好:即時看到回應,不用等待
- 適合長回應:即使回應很長,也能立即開始顯示
- 更有互動感:就像真人對話一樣自然
實際使用範例
現在讓我們看看如何使用這個客戶端。以下是一個簡單的範例:
const ChatGPTClient = require('./chatgpt-client'); // 初始化客戶端 const chatGPT = new ChatGPTClient('your-api-key-here'); // 範例 1: 簡單對話 async function simpleChat() { const response = await chatGPT.sendMessage('請介紹一下 Node.js'); console.log(response.message); } // 範例 2: 多輪對話 async function conversation() { const history = []; // 第一輪 const response1 = await chatGPT.sendMessage('我想學程式', history); history.push({ role: 'user', content: '我想學程式' }); history.push({ role: 'assistant', content: response1.message }); // 第二輪(記得上一輪的內容) const response2 = await chatGPT.sendMessage('該從哪裡開始?', history); console.log(response2.message); } // 範例 3: 串流回應 async function streamChat() { await chatGPT.sendMessageStream( '寫一個故事', [], (chunk) => { process.stdout.write(chunk); // 即時顯示 } ); }
關鍵學習要點
🎯 這個專案教會我們:
- HTTP 通訊基礎:理解如何使用原生模組發送 HTTPS 請求
- 非同步程式設計:熟練使用 Promise 處理非同步操作
- 串流處理:學會處理 Server-Sent Events 串流資料
- 錯誤處理:建立完善的錯誤處理機制
- 物件導向設計:用類別封裝功能,讓程式碼更易維護
後續擴展方向
有了這個基礎,你可以繼續擴展更多功能:
- 加入重試機制,處理網路不穩定的情況
- 實作對話歷史的自動管理和優化
- 支援多模態輸入(圖片、文件等)
- 建立 Web 介面,讓使用者更方便使用
- 加入 token 計數和成本估算功能
- 實作對話分支和版本控制
結語
通過這篇文章,我們從零開始建構了一個功能完整的 ChatGPT 客戶端。這不僅是一個實用的工具,更是一個絕佳的學習專案。你學會了如何處理 HTTP 請求、管理非同步操作、處理串流資料等重要技能。
最重要的是,你現在擁有了一個完全可控、可客製化的 ChatGPT 客戶端。無論是整合到現有專案,還是作為學習 AI 應用開發的起點,這個客戶端都將是你的得力助手。
💪 下一步行動:
- 取得你的 OpenAI API Key
- 動手實作這個客戶端
- 試著加入自己的創意功能
- 將它整合到你的專案中
記住,最好的學習方式就是動手實作。現在就開始你的 AI 應用開發之旅吧!如果你在實作過程中遇到問題,歡迎在留言區分享,讓我們一起討論和學習。