隨著大型語言模型(LLM)技術的飛速發展,越來越多的 Web 應用開始整合 AI 能力——從智慧客服、內容摘要到自動翻譯,AI 正在重塑前端開發的工作方式。對於使用 Nuxt 3 構建全端應用的開發者來說,如何在專案中安全、高效地呼叫 AI API 是一個值得深入探討的話題。本文將帶你一步步實作在 Nuxt 3 專案中整合 OpenAI 相容 API,完成智慧內容生成與多語言翻譯功能。
一、為什麼選擇伺服器端呼叫
在 Nuxt 3 專案中呼叫 AI API,首要考慮的是安全性。所有主流 AI 服務(OpenAI、Claude、DeepSeek 等)都要求透過 API Key 進行身份認證。如果將 API Key 寫在前端程式碼中,任何人都能透過瀏覽器開發者工具取得你的金鑰,造成嚴重的安全隱患和費用損失。
Nuxt 3 的 server/api 目錄提供了完美的解決方案:API 路由執行在伺服器端(Nitro 引擎),API Key 儲存在 .env 環境變數中,前端透過 $fetch 呼叫自己的介面,再由伺服器端轉發請求到 AI 服務。這樣 API Key 永遠不會暴露給客戶端。
二、環境準備
首先在 Nuxt 3 專案根目錄建立 .env 檔案:
NUXT_OPENAI_API_KEY=sk-your-api-key-here
NUXT_OPENAI_BASE_URL=https://api.openai.com/v1
NUXT_AI_MODEL=gpt-4o-mini在 nuxt.config.ts 中不需要額外配置,Nitro 會自動讀取以 NUXT_ 開頭的環境變數並透過 useRuntimeConfig() 暴露給伺服器端。
三、建立 AI 服務層
為了程式碼復用和可維護性,我們先建立一個通用的 AI 服務封裝。在 server/utils/ai.ts 中:
interface ChatMessage {
role: 'system' | 'user' | 'assistant'
content: string
}
interface ChatOptions {
messages: ChatMessage[]
temperature?: number
maxTokens?: number
stream?: boolean
}
export async function chatCompletion(options: ChatOptions) {
const config = useRuntimeConfig()
const response = await $fetch(`${config.openaiBaseUrl}/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${config.openaiApiKey}`,
'Content-Type': 'application/json',
},
body: {
model: config.aiModel,
messages: options.messages,
temperature: options.temperature ?? 0.7,
max_tokens: options.maxTokens ?? 2048,
stream: options.stream ?? false,
},
})
return response
}四、實作內容生成 API 路由
建立 server/api/ai/generate.post.ts:
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const { prompt, systemPrompt } = body
if (!prompt) {
throw createError({
statusCode: 400,
message: 'prompt 參數不能為空',
})
}
try {
const result = await chatCompletion({
messages: [
{ role: 'system', content: systemPrompt || '你是一個專業的技術內容創作者。' },
{ role: 'user', content: prompt },
],
temperature: 0.8,
})
return {
success: true,
content: result.choices[0].message.content,
usage: result.usage,
}
} catch (error: any) {
throw createError({
statusCode: 500,
message: error.message || 'AI 服務呼叫失敗',
})
}
})五、實作流式回應(SSE)
對於內容生成場景,流式回應能大幅提升使用者體驗——使用者可以看到文字逐字生成,而不是等待幾秒鐘後一次性展示。建立 server/api/ai/stream.post.ts:
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const { prompt, systemPrompt } = body
const config = useRuntimeConfig()
setHeader(event, 'Content-Type', 'text/event-stream')
setHeader(event, 'Cache-Control', 'no-cache')
setHeader(event, 'Connection', 'keep-alive')
const response = await fetch(
`${config.openaiBaseUrl}/chat/completions`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${config.openaiApiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: config.aiModel,
messages: [
{ role: 'system', content: systemPrompt || '你是一個專業助手。' },
{ role: 'user', content: prompt },
],
stream: true,
}),
}
)
const reader = response.body?.getReader()
if (!reader) throw createError({ statusCode: 500 })
const decoder = new TextDecoder()
let buffer = ''
while (true) {
const { done, value } = await reader.read()
if (done) {
sendEventStream(event, { data: '[DONE]' })
break
}
buffer += decoder.decode(value, { stream: true })
const lines = buffer.split('n')
buffer = lines.pop() || ''
for (const line of lines) {
if (line.startsWith('data: ') && line !== 'data: [DONE]') {
try {
const parsed = JSON.parse(line.slice(6))
const content = parsed.choices[0]?.delta?.content
if (content) {
sendEventStream(event, { data: content })
}
} catch {}
}
}
}
})六、前端 Vue 元件整合
建立一個可重複使用的 AI 內容生成元件:
<script setup lang="ts">
const prompt = ref('')
const generatedContent = ref('')
const isLoading = ref(false)
const isStreaming = ref(false)
async function generateContent() {
if (!prompt.value.trim()) return
isLoading.value = true
generatedContent.value = ''
try {
const data = await $fetch('/api/ai/generate', {
method: 'POST',
body: { prompt: prompt.value },
})
generatedContent.value = data.content
} catch (error) {
console.error('生成失敗:', error)
} finally {
isLoading.value = false
}
}
async function generateStream() {
if (!prompt.value.trim()) return
isStreaming.value = true
generatedContent.value = ''
const eventSource = new EventSource(
`/api/ai/stream?${new URLSearchParams({ prompt: prompt.value })}`
)
eventSource.onmessage = (event) => {
if (event.data === '[DONE]') {
eventSource.close()
isStreaming.value = false
return
}
generatedContent.value += event.data
}
eventSource.onerror = () => {
eventSource.close()
isStreaming.value = false
}
}
</script>七、多語言翻譯實作
基於上述 AI 服務層,實作多語言翻譯非常簡單。建立 server/api/ai/translate.post.ts:
export default defineEventHandler(async (event) => {
const { text, targetLang, sourceLang } = await readBody(event)
const langMap: Record<string, string> = {
'zh-cn': '簡體中文',
'zh-tw': '繁體中文',
'en': 'English',
'ja': '日本語',
}
const result = await chatCompletion({
messages: [
{
role: 'system',
content: `你是一個專業翻譯。將使用者輸入的${sourceLang ? langMap[sourceLang] || sourceLang : ''}內容翻譯為${langMap[targetLang] || targetLang}。只返回翻譯結果,不要新增任何解釋。`,
},
{ role: 'user', content: text },
],
temperature: 0.3,
})
return {
success: true,
translation: result.choices[0].message.content,
sourceLang,
targetLang,
}
})八、錯誤處理與速率限制
在生產環境中,AI API 呼叫可能因各種原因失敗——網路逾時、速率限制、餘額不足等。我們需要健全的錯誤處理機制。
在 server/utils/ai.ts 中新增重試邏輯:
export async function chatCompletionWithRetry(
options: ChatOptions,
maxRetries = 3
) {
for (let i = 0; i < maxRetries; i++) {
try {
return await chatCompletion(options)
} catch (error: any) {
if (error.statusCode === 429) {
// 速率限制,等待後重試
const retryAfter = error.headers?.get('retry-after') || 5
await new Promise(r => setTimeout(r, retryAfter * 1000))
continue
}
if (i === maxRetries - 1) throw error
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)))
}
}
}同時建議在 Nitro 配置中設定請求體大小限制:
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
routeRules: {
'/api/ai/**': {
maxBodySize: '1mb',
},
},
},
})九、總結
透過 Nuxt 3 的 Server API 路由,我們以安全、高效的方式整合了 AI 能力。核心要點回顧:
- 安全性:API Key 儲存在伺服器端環境變數,絕不暴露給客戶端
- 流式回應:使用 SSE 實現即時內容生成,提升使用者體驗
- 可復用架構:透過服務層封裝,content generation 和 translation 共享同一套 AI 呼叫邏輯
- 健全性:指數退避重試策略處理速率限制和網路異常
這套架構已經在薩龍網路的多個專案中穩定執行,無論是自動生成技術文章、產品描述,還是實現多語言站點的內容翻譯,都能高效勝任。希望本文能幫助你在 Nuxt 3 專案中順利整合 AI 能力。





