您的浏览器需要启用 JavaScript 才能正常访问此网站。
諮詢熱線:15911225507
龍霄
登入
首頁-所有文章tw-WordPress繁体-正文

WordPress Headless 架構下基於 GraphQL 實現 AI 流式輸出

龍霄龍霄WordPress繁体13小时前001

前言

在構建現代 Web 應用時,Headless WordPress + Nuxt.js 的架構組合越來越受到開發者的青睞。WordPress 提供強大的內容管理後端,Nuxt.js 負責高效能的前端渲染,而 GraphQL 則作為兩者之間的資料橋樑。但當我們需要在前端展示 AI 生成的內容時——尤其是需要流式輸出(Streaming)的場景,傳統 REST API 方案就顯得力不從心了。本文將詳細介紹如何在這一架構中透過 GraphQL 實現 AI 內容的流式輸出。

為什麼選擇 GraphQL + SSE?

傳統的 REST API 在處理 AI 流式輸出時面臨幾個核心問題:

請求-回應模型限制:REST 是一次請求一次回應,無法持續推送資料。要實現流式輸出,通常需要借助 WebSocket,但這會增加架構的複雜度和維護成本。

資料過載:REST 介面返回固定結構的資料,前端可能只需要部分欄位,卻不得不同時接收大量冗餘資訊。在 Headless 架構中,頁面通常需要請求多個 REST 端點才能組裝完整資料,這無疑增加了網路開銷和頁面載入時間。

擴展性不足:當 AI 服務升級或切換模型時,REST 介面往往需要同步修改,前後端耦合度高。

GraphQL 的優勢在於按需查詢——前端精確指定所需欄位,減少資料傳輸量;所有資料透過一個 GraphQL 端點獲取,免去多次請求的煩惱;透過自訂 Mutation 和 Subscription 可以靈活擴展 AI 能力。結合 SSE(Server-Sent Events),我們可以在 GraphQL 框架內實現高效的即時資料推送。

架構設計

整體架構分為三層,清晰且解耦:

Nuxt.js 前端 (SSE Consumer)
    ↕ SSE (text/event-stream)
WordPress + WPGraphQL 外掛
    ↕ GraphQL Mutation + REST SSE Endpoint
AI 服務 (DeepSeek / OpenAI / Claude)

在 WordPress 端,我們透過 WPGraphQL 外掛註冊自訂 Mutation,該 Mutation 接收使用者輸入的 prompt,呼叫 AI 服務並返回一個流 ID。前端拿到流 ID 後,透過獨立的 SSE 端點消費流式資料。這種設計將 GraphQL 的查詢能力與 SSE 的即時推送能力有機結合,各司其職。

後端實現:WordPress + WPGraphQL

第一步:註冊 GraphQL Mutation

首先在主題或外掛的 functions.php 中註冊一個自訂 Mutation,用於接收 prompt 並生成流 ID:

add_action('graphql_register_types', function () {
    register_graphql_mutation('generateAiContent', [
        'inputFields' => [
            'prompt' => ['type' => 'String'],
            'model'  => ['type' => 'String'],
        ],
        'outputFields' => [
            'streamId' => ['type' => 'String'],
        ],
        'mutateAndGetPayload' => function ($input) {
            $prompt = sanitize_text_field($input['prompt']);
            $model  = $input['model'] ?? 'deepseek-chat';
            $stream_id = wp_generate_uuid4();
            set_transient("ai_stream_{$stream_id}", [
                'prompt' => $prompt,
                'model'  => $model,
            ], 300);
            return ['streamId' => $stream_id];
        },
    ]);
});

這裡使用 WordPress Transients API 暫存請求資訊,設定 5 分鐘過期時間,避免記憶體洩漏。

第二步:建立 SSE 端點

註冊一個自訂 REST API 端點來流式輸出 AI 生成內容。關鍵點:設定正確的回應頭、使用 cURL 的 CURLOPT_WRITEFUNCTION 逐塊傳輸資料、禁用 Nginx 緩衝:

add_action('rest_api_init', function () {
    register_rest_route('longxiao/v1', '/ai/stream/(?P<id>[a-zA-Z0-9-]+)', [
        'methods'  => 'GET',
        'callback' => function ($request) {
            $stream_id = $request->get_param('id');
            $data = get_transient("ai_stream_{$stream_id}");
            if (!$data) {
                return new WP_Error('not_found', 'Stream not found', ['status' => 404]);
            }

            header('Content-Type: text/event-stream');
            header('Cache-Control: no-cache');
            header('Connection: keep-alive');
            header('X-Accel-Buffering: no');

            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => 'https://api.deepseek.com/v1/chat/completions',
                CURLOPT_POST => true,
                CURLOPT_HTTPHEADER => [
                    'Authorization: Bearer ' . DEEPSEEK_API_KEY,
                    'Content-Type: application/json',
                ],
                CURLOPT_POSTFIELDS => json_encode([
                    'model'    => $data['model'],
                    'messages' => [['role' => 'user', 'content' => $data['prompt']]],
                    'stream'   => true,
                ]),
                CURLOPT_WRITEFUNCTION => function ($ch, $chunk) {
                    $lines = explode("n", $chunk);
                    foreach ($lines as $line) {
                        $line = trim($line);
                        if (str_starts_with($line, 'data: ')) {
                            $json = substr($line, 6);
                            if ($json === '[DONE]') {
                                echo "data: [DONE]nn";
                            } else {
                                $decoded = json_decode($json, true);
                                $content = $decoded['choices'][0]['delta']['content'] ?? '';
                                if ($content) {
                                    echo "data: " . json_encode(['content' => $content]) . "nn";
                                }
                            }
                            ob_flush();
                            flush();
                        }
                    }
                    return strlen($chunk);
                },
            ]);
            curl_exec($ch);
            curl_close($ch);
            delete_transient("ai_stream_{$stream_id}");
            exit;
        },
    ]);
});

需要注意:CURLOPT_WRITEFUNCTION 回呼中必須使用 ob_flush() 和 flush() 確保資料即時輸出到客戶端;處理完請求後及時刪除 transient 釋放資源。

前端實現:Nuxt.js Composable

在 Nuxt.js 端,封裝一個 Composable 來處理 GraphQL 請求與 SSE 流消費。核心思路分兩步:先透過 GraphQL Mutation 取得 streamId,再透過 fetch API 消費 SSE 流:

// composables/useAiStream.ts
export function useAiStream() {
  const content = ref('')
  const isStreaming = ref(false)
  const error = ref<string | null>(null)

  async function streamGenerate(prompt: string, model = 'deepseek-chat') {
    content.value = ''
    isStreaming.value = true
    error.value = null

    try {
      const mutation = `
        mutation GenerateAiContent($prompt: String!, $model: String!) {
          generateAiContent(input: { prompt: $prompt, model: $model }) {
            streamId
          }
        }
      `
      const { data } = await useGql({ query: mutation, variables: { prompt, model } })
      const streamId = data.value?.generateAiContent?.streamId
      if (!streamId) throw new Error('無法獲取流 ID')

      const streamUrl = `https://api.your-site.com/wp-json/longxiao/v1/ai/stream/${streamId}`
      const controller = new AbortController()
      const timeout = setTimeout(() => controller.abort(), 120000)

      const response = await fetch(streamUrl, { signal: controller.signal })
      const reader = response.body?.getReader()
      const decoder = new TextDecoder()
      if (!reader) throw new Error('無法讀取回應流')

      while (true) {
        const { done, value } = await reader.read()
        if (done) break
        const chunk = decoder.decode(value, { stream: true })
        const lines = chunk.split('n')
        for (const line of lines) {
          if (line.startsWith('data: ')) {
            const data = line.slice(6)
            if (data === '[DONE]') break
            try {
              const parsed = JSON.parse(data)
              content.value += parsed.content || ''
            } catch {}
          }
        }
      }
      clearTimeout(timeout)
    } catch (e: any) {
      if (e.name !== 'AbortError') {
        error.value = e.message || '流式輸出異常'
      }
    } finally {
      isStreaming.value = false
    }
  }

  return { content, isStreaming, error, streamGenerate }
}

關鍵設計:使用 AbortController 實現 2 分鐘逾時保護;透過 ref 響應式綁定讓 Vue 元件自動更新 UI;區分 AbortError 和其他錯誤,避免逾時顯示錯誤提示。

Vue 元件整合

<template>
  <div class="ai-chat">
    <textarea v-model="prompt" placeholder="請輸入你的問題..." />
    <button @click="handleGenerate" :disabled="isStreaming">
      {{ isStreaming ? '生成中...' : '發送' }}
    </button>
    <div class="ai-output" v-html="renderedContent" />
    <p v-if="error" class="error">{{ error }}</p>
  </div>
</template>

<script setup>
const prompt = ref('')
const { content, isStreaming, error, streamGenerate } = useAiStream()
const renderedContent = computed(() => content.value.replace(/n/g, '<br>'))
function handleGenerate() {
  if (!prompt.value.trim() || isStreaming.value) return
  streamGenerate(prompt.value)
}
</script>

效能最佳化與生產實踐

Nginx 緩衝設定

在 Nginx 反向代理中預設會緩衝後端回應,導致 SSE 流無法即時推送。必須對 SSE 端點禁用緩衝:

location /wp-json/longxiao/v1/ai/stream/ {
    proxy_buffering off;
    proxy_cache off;
    proxy_set_header X-Accel-Buffering no;
    proxy_read_timeout 300s;
    chunked_transfer_encoding on;
}

連線池與並發控制

在高並發場景下,建議使用 Redis 管理 AI 請求佇列,避免大量請求同時打到 AI 服務導致限流或逾時。可以在 WordPress 端實現一個簡單的令牌桶演算法來控制請求速率。

錯誤處理與重連

SSE 連線可能因網路波動而中斷,建議在 Composable 中實現自動重連邏輯。當偵測到連線異常斷開時,可以攜帶已接收的內容長度發起續傳請求,避免使用者看到內容中斷。

總結

透過 WPGraphQL + SSE 的組合方案,我們成功在 WordPress Headless 架構中實現了 AI 內容的流式輸出。這套方案的優勢在於架構簡潔——無需額外引入 WebSocket 伺服器,降低了維運成本;漸進式渲染——使用者無需等待完整回應即可看到內容逐字出現,互動體驗極佳;靈活擴展——可以輕鬆切換 DeepSeek、OpenAI、Claude 等不同 AI 模型;與現有技術堆疊無縫整合——充分利用了 WordPress 的外掛生態和 Nuxt.js 的全端能力。在實際專案中,你還可以進一步擴展這套架構,比如整合 Markdown 渲染、程式碼高亮、歷史對話管理等功能,構建完整的 AI 對話應用。

標籤:
本文来源萨龙网络,经授权后由龍霄发布,观点不代表龙霄的立场,转载请联系原作者。
龍霄

龍霄

Lv1Rec2
以 Nuxt.js 之力,煥新 WordPress 體驗
207.70W119
載入中…
分享:
1
Nuxt.js Headless WordPress 專案中的資料快取最佳化策略
Nuxt.js Headless WordPress 專案中的資料快取最佳化策略上一篇
相关文章
總數:12
一鍵智能·三語通達:龍霄AI翻譯如何讓多語言網站管理效率翻倍

一鍵智能·三語通達:龍霄AI翻譯如何讓多語言網站管理效率翻倍

一、痛點:多語言網站管理的「三座大山」運營一個中文(簡體)、中文(繁體)和英文三語並行的網站,開發者與內容管理者每天都要面對三大難題:…
龍霄龍霄Nuxt.js繁体, Vue.js繁体, WordPress繁体2个月前00820
龍霄主題-知識付費課程外掛:核心功能與學習黏性提升策略

龍霄主題-知識付費課程外掛:核心功能與學習黏性提升策略

在知識經濟時代,如何將專業知識轉化為可持續的線上課程產品?本文深入解析基於 Nuxt.js + WordPress 架構的知識付費課程外掛,從核…
龍霄龍霄Nuxt.js繁体, WordPress繁体3个月前003.18K0
Nuxt.js + WordPress 架構:效能、速度、安全與快取的全方位解析

Nuxt.js + WordPress 架構:效能、速度、安全與快取的全方位解析

當 Nuxt.js 的現代化前端工程能力遇上 WordPress 強大的內容管理生態,兩者透過 Headless 架構結合,打造出一套兼顧極致效…
龍霄龍霄Nuxt.js繁体, WordPress繁体3个月前002.72K0
WordPress龍霄加盟推廣系統 —— 數據一目了然,結算一步到位:多語系電商推廣管理後台

WordPress龍霄加盟推廣系統 —— 數據一目了然,結算一步到位:多語系電商推廣管理後台

一、開發背景與定位龍霄加盟推廣外掛(LongXiao Affiliate)由薩龍網路出品,是一款深度 WordPress 電商加盟推廣管…
龍霄龍霄WordPress繁体1个月前00750
Nuxt.js Headless WordPress 專案中的資料快取最佳化策略

Nuxt.js Headless WordPress 專案中的資料快取最佳化策略

在 Headless WordPress + Nuxt.js 的架構中,WordPress 作為內容後端透過 REST API 提供資料,Nux…
龍霄龍霄Nuxt.js繁体, WordPress繁体1个月前00490
擁抱現代Web開發:Nuxt.js + WordPress 架構革新指南

擁抱現代Web開發:Nuxt.js + WordPress 架構革新指南

一、效能優化:靜態生成與動態渲染的完美平衡在當今快節奏的數位時代,網站效能直接關係到用戶體驗和業務轉化。傳統的WordPress主題開發…
龍霄龍霄Nuxt.js繁体, WordPress繁体3个月前005.44K0
活動外掛-活動管理外掛:從策劃到落地,一站式活動營運解決方案

活動外掛-活動管理外掛:從策劃到落地,一站式活動營運解決方案

一場成功的活動,背後是場地管理、嘉賓邀約、報名簽到、票務結算的複雜協作。活動管理外掛將全流程數位化——從活動建立、嘉賓管理、線上報名到現場簽到,…
龍霄龍霄Nuxt.js繁体, WordPress繁体3个月前002.84K0
龍霄主題-視覺化頁面建構器:一個人、一個下午,搭建專業級網站

龍霄主題-視覺化頁面建構器:一個人、一個下午,搭建專業級網站

告別寫程式碼、調樣式、接 API 的傳統建站模式。拖拽模組、配置參數、一鍵發布——讓頁面建構器成為你的效率槓桿,用十分之一的時間,交付十倍品質的…
龍霄龍霄Nuxt.js繁体, WordPress繁体3个月前002.36K0
WordPress 自訂 REST API 安全加固與微信公眾號排版自動化實踐

WordPress 自訂 REST API 安全加固與微信公眾號排版自動化實踐

概述在 Headless WordPress 架構中,自訂 REST API 端點是與外部系統互動的核心通道。然而,生產環境常常面臨兩大…
龍霄龍霄WordPress繁体1个月前00500
龍霄主題-電商與會員一體化產品外掛:讓內容變現從[能賣]到[賣得好]

龍霄主題-電商與會員一體化產品外掛:讓內容變現從[能賣]到[賣得好]

一套完整的電商交易鏈路,配合多級會員權限體系——從商品展示、購物車、優惠券到訂單支付,從免費試讀到 VIP 專屬內容,用系統化的商業工具把你的知…
龍霄龍霄Nuxt.js繁体, WordPress繁体3个月前003.87K0
龍霄(LongXiao)WordPress 主題:後端專屬企業級功能全景解析

龍霄(LongXiao)WordPress 主題:後端專屬企業級功能全景解析

一、開篇引言龍霄(LongXiao)主題是薩龍網絡傾力打造的一款以 WordPress 為後端核心、以 Nuxt.js + Vue.js…
龍霄龍霄WordPress繁体1个月前00490
Nuxt 4 + WordPress GraphQL:資料管理策略與效能最佳化深度指南

Nuxt 4 + WordPress GraphQL:資料管理策略與效能最佳化深度指南

本文深入剖析基於 Nuxt 4 + WordPress GraphQL 的生產級資料層架構,從服務端 SHA-256 快取代理、飛行中請求去重、…
龍霄龍霄Nuxt.js繁体, Vue.js繁体, WordPress繁体3个月前003.77K0
评论表单游客 您好,欢迎参与讨论。
載入中…
评论列表
總數:0
龍霄
沒有相關內容