如果你是正在寫 Vue3 / React 後台的前端工程師,最近大概會發現:老闆或產品經理開始問「我們的系統能不能加一個 AI 助手?」。上一篇我們聊過「用 AI 工具輔助你寫程式」,這一篇要講的是另一件事——把大模型(LLM)接進你的應用裡,讓產品自己會說話。別被「AI 應用」四個字嚇到,它的核心其實就是:發一個 HTTP 請求、把使用者的話送過去、把模型的回答渲染出來。今天我們就從零開始,一步步做出一個會聊天的前端。
一、先搞懂:大模型應用到底在呼叫什麼?
打個比方:大模型 API 就像一家「翻譯社」,你把需求(prompt)寄過去,它把成品(回答)寄回來。所有主流大模型都遵循一套幾乎相同的呼叫格式——OpenAI 相容格式。先記住四個名詞:
- Token:模型計算文字的基本單位,一個中文字大約 1~2 個 token,也是計費單位。
- 上下文視窗(Context Window):模型一次能「記住」的對話長度上限,超出就要自己裁剪歷史。
- Temperature:隨機度,0 最嚴謹穩定,越高越有創意但越容易胡說。
- System Prompt:給模型的「人設與規則」,決定它用什麼身份、什麼口吻回答。
重點:呼叫大模型的本質就是一個 HTTP POST,body 裡帶一個 messages 陣列——這對前端工程師來說,沒有任何新知識門檻。
二、步驟 1:用 fetch 發出第一次對話請求
假設要接一個 OpenAI 相容的接口,最小可用代碼長這樣:
async function askLLM(userText: string) {
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: '你是一個嚴謹的客服助理,只回答與產品相關的問題。' },
{ role: 'user', content: userText },
],
temperature: 0.3,
}),
});
const data = await res.json();
return data.choices[0].message.content;
}
你可能注意到請求是發到 /api/chat 而不是模型官網——因為金鑰絕對不能放在前端代碼裡。正確做法是由自己的後端(或 BFF / Serverless 函數)持有 API Key,前端只呼叫自家接口做代理。
重點:前端直連模型官方 API 等於把你的錢包公諸於世——API Key 一旦被扒走,帳單會教你看懂什麼叫「惡意刷量」。
三、步驟 2:管理對話上下文,讓它真的「會聊天」
大模型是沒有記憶的——它每次都只看你這次傳過去的內容。所謂「多輪對話」,就是前端每次把歷史訊息整包帶回去。用 Vue3 管理一個訊息列表:
const messages = ref<{ role: 'user' | 'assistant'; content: string }[]>([]);
async function sendMessage(text: string) {
messages.value.push({ role: 'user', content: text });
const history = messages.value.map(({ role, content }) => ({ role, content }));
const reply = await askLLM(history);
messages.value.push({ role: 'assistant', content: reply });
}
當對話越來越長,就要注意上下文視窗:常見策略是保留 system prompt + 最近 N 輪對話,更早的歷史可以摘要成一則壓縮訊息再帶回去,省 token 又不丟重點。
四、步驟 3:用 SSE 串流輸出,打造「打字機」體驗
等模型把整段話寫完才回應,使用者會盯著空白畫面等到懷疑人生。所以主流應用都是串流輸出——伺服器用 SSE(Server-Sent Events)一個 token 一個 token 地推,前端邊收邊渲染:
async function askLLMStream(history: Message[], onChunk: (t: string) => void) {
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model: 'gpt-4o-mini', messages: history, stream: true }),
});
const reader = res.body!.pipeThrough(new TextDecoderStream()).getReader();
let buffer = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += value;
const lines = buffer.split('\n');
buffer = lines.pop() ?? '';
for (const line of lines) {
if (!line.startsWith('data:')) continue;
const payload = line.slice(5).trim();
if (payload === '[DONE]') return;
const json = JSON.parse(payload);
onChunk(json.choices[0]?.delta?.content ?? '');
}
}
}
重點:串流一定要處理「半包」問題——一個 SSE 訊息可能被網路拆成兩次收到,所以要用 buffer 攢齊完整行再解析,拿到片段就暴衝 JSON.parse 遲早出鬼。
五、進階:Function Calling,讓模型幫你「查資料」
模型的知識是死的,但你的系統資料是活的。Function Calling 的思路是:你告訴模型「有哪些函數可用」,模型判斷需要時回傳一個「函數名 + 參數」的 JSON,前端(或後端)真正執行後把結果再餵回去。例如使用者問「我今天有幾條待處理告警?」,模型不會瞎猜,而是回傳:
{ "name": "getAlarmCount", "arguments": { "status": "unhandled", "date": "today" } }
你呼叫自家 API 查到「23 條」,再把結果交還模型,它就會用人話回答「您今天有 23 條待處理告警」。這就是現在所有「AI Agent」的地基——模型負責理解與決策,你的程式負責真正幹活。
六、上線前的三個工程細節
- 金鑰與代理:API Key 只存在後端,前端走自家接口,順便做鑑權與用量配額。
- 失敗與降級:模型接口會超時、會限流,要有重試(指數退避)與「AI 功能暫不可用」的降級 UI。
- 輸出不可全信:模型會一本正經地胡說(幻覺),涉及金額、數量的展示務必以自家資料為準,模型只負責「組織語言」。
總結一下:大模型應用 = HTTP 請求 + 上下文管理 + 串流渲染 三件套,再加 Function Calling 就能從「會聊天」升級到「會辦事」。對前端工程師來說,這是離 AI 最近的一次機會——門檻沒有想像中高,值得親手做一個玩玩。
互動話題:你的專案裡有沒有正在規劃或已經上線的 AI 功能?你在接入大模型時踩過最深的坑是什麼——串流半包、上下文爆掉、還是帳單爆炸?歡迎留言聊聊!