iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
Build on Google AI

用 Google AI 生態系 30 天從零打造一個全棧 AI SaaS 服務系列 第 8 篇

Day 08 -【長文本魔法】百萬 Token 實測:告別繁複 RAG!讓 Gemini 一次性吞下長篇 PDF 與研究報告

  • 分享至 

  • xImage
  •  

在昨天的 [Day 07] 中,我們成功在 Next.js 後端架設了第一支調用 Gemini 1.5 Flash 的 AI API Route。然而在真實的 SaaS 商業場景中,知識工作者很少會花時間把 50 頁的財報或技術白皮書手動複製、貼成純文字餵給 AI。

用戶最直覺的操作是:「把整份 PDF 檔案拖進來,30 秒內給我重點摘要與社群簡報!」

在過去,要實現這個需求是一場工程噩夢。今天我們就來聊聊為什麼 Gemini 的 百萬級 Token 上下文視窗(Long Context Window) 能對傳統文件檢索架構進行「降維打擊」,並用代碼實作 OmniVibe AI 的長篇 PDF 解析引擎!


💥 傳統 RAG 架構 vs. Gemini 超長上下文

在 Gemini 1.5 問世之前,業界處理長文件的標準架構是 RAG(檢索增強生成,Retrieval-Augmented Generation):

graph LR
    subgraph 傳統 RAG 繁複管線
        A[PDF 原始文件] --> B[文字萃取 PyPDF/OCR]
        B --> C[切塊 Chunking 500字]
        C --> D[計算 Embedding]
        D --> E[存入向量資料庫]
        E --> F[向量相似度檢索 Top-K]
        F --> G[拼裝碎片上下文]
        G --> H[LLM 產出回覆]
    end

傳統 RAG 在文件提煉上的三大硬傷:

  1. 上下文碎片化(Lost in the Middle):當文件被強行切成 500 字一塊時,跨頁面的邏輯因果關係(例如第一頁的假設對應第 40 頁的結論)會被完全割裂。
  2. 非文字元素遺失:PDF 中的複合圖表、統計表格、流程圖,在傳統文字轉譯過程中往往變成無意義的亂碼。
  3. 維護與運算成本高昂:需要額外維護 Embedding 模型、向量資料庫(Vector DB)以及調試檢索相似度權重。

Gemini 1.5 的破局解法:Native Long Context

Gemini 1.5 原生具備 100 萬至 200 萬 Token 的巨量上下文視窗(相當於約 1 小時影片、11 小時音訊或 70 萬字小說)。

我們不再需要切塊,更不需要向量資料庫! 整份 PDF 檔案以原生格式直通模型神經網絡,Gemini 能夠在毫秒級內全局縱覽全文,精確關聯首尾邏輯,甚至連 PDF 內的排版佈局與圖表結構都能直接理解。


🛠️ Gemini 處理大型檔案的兩條路徑

在 Google Gen AI SDK 中,餵入 PDF 檔案主要有兩種方式:

方案 適用場景 限制 實作方式
Inline Data (Base64) 適用於小於 20MB 的小型輕量檔案 請求 Payload 受限,過大會導致連線逾時 轉成 Base64 字串後放入 inlineData
Google AI File API 生產級 SaaS 首選! 支援高達 2GB 的大型檔案 檔案暫存於 Google 伺服器 48 小時,需做生命週期管理 使用 GoogleAIFileManager 上傳取得 URI

為了打造抗壓、穩健的 OmniVibe AI,我們採用 Google AI File API 來處理使用者的 PDF 上傳請求!


💻 實戰演練:打造 PDF 提煉 API Route

我們將在 Next.js 中新增一支專門處理多檔案表單(multipart/form-data)的 API 端點:src/app/api/ai/transform-pdf/route.ts。

1. 安裝必要依賴

除了 @google/generative-ai 之外,我們需要使用官方提供的伺服器端檔案管理工具:

npm install @google/generative-ai

(註:GoogleAIFileManager 已內建在 @google/generative-ai/server 子模組中)


2. 實作完整後端處理邏輯 (src/app/api/ai/transform-pdf/route.ts)

以下代碼展示了完整的工業級流程:

  1. 接收前端上傳的 PDF 二進制數據。
  2. 將檔案暫存至本地 /tmp 目錄。
  3. 透過 GoogleAIFileManager 推送至 Google File API。
  4. 呼叫 gemini-1.5-flash 進行深度全文多模態解析。
  5. 完成後主動觸發清理機制,刪除雲端暫存檔與本地臨時檔,確保不留隱私垃圾。
// src/app/api/ai/transform-pdf/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { GoogleGenerativeAI } from '@google/generative-ai';
import { GoogleAIFileManager } from '@google/generative-ai/server';
import { OMNIVIBE_SYSTEM_INSTRUCTION } from '@/lib/gemini/prompts';
import { writeFile, unlink } from 'fs/promises';
import path from 'path';
import os from 'os';

const apiKey = process.env.GEMINI_API_KEY || '';
const genAI = new GoogleGenerativeAI(apiKey);
const fileManager = new GoogleAIFileManager(apiKey);

export async function POST(req: NextRequest) {
  let tempFilePath: string | null = null;
  let uploadedFileResource: any = null;

  try {
    // 1. 解析 multipart/form-data
    const formData = await req.formData();
    const file = formData.get('file') as File | null;

    if (!file) {
      return NextResponse.json(
        { error: 'Bad Request', message: '請上傳 PDF 檔案' },
        { status: 400 }
      );
    }

    if (file.type !== 'application/pdf') {
      return NextResponse.json(
        { error: 'Bad Request', message: '僅支援 PDF 格式文件' },
        { status: 400 }
      );
    }

    // 2. 將上傳檔案寫入伺服器暫存目錄 (/tmp)
    const arrayBuffer = await file.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);
    const fileName = `upload_${Date.now()}_${file.name}`;
    tempFilePath = path.join(os.tmpdir(), fileName);
    await writeFile(tempFilePath, buffer);

    // 3. 上傳檔案至 Google AI File API
    uploadedFileResource = await fileManager.uploadFile(tempFilePath, {
      mimeType: 'application/pdf',
      displayName: file.name,
    });

    console.log(`[Google File API] 上傳成功: ${uploadedFileResource.file.uri}`);

    // 4. 初始化 Gemini 1.5 Flash 模型
    const model = genAI.getGenerativeModel({
      model: 'gemini-1.5-flash',
      systemInstruction: OMNIVIBE_SYSTEM_INSTRUCTION,
      generationConfig: {
        temperature: 0.3, // 閱讀長篇正式報告時,略微調低以增強事實精準度
        maxOutputTokens: 4096,
      },
    });

    // 5. 構建多模態 Prompt 請求
    const prompt = `
請通讀這份完整的 PDF 報告,並依據你的系統人設,產出高價值的提煉成果:
1. 【核心摘要】:以金字塔結構提煉出 3~5 點全局洞見,務必保留文件中的關鍵數據與重要結論。
2. 【社群爆款矩陣】:產出一篇適合發在 LinkedIn 或 Threads 上的乾貨長文。
3. 【關鍵數據表】:將文中散落的核心指標整理為 Markdown 表格。
`;

    const result = await model.generateContent([
      {
        fileData: {
          mimeType: uploadedFileResource.file.mimeType,
          fileUri: uploadedFileResource.file.uri,
        },
      },
      { text: prompt },
    ]);

    const response = await result.response;
    const outputText = response.text();

    // 6. 回傳成果與用量監控
    return NextResponse.json({
      success: true,
      data: {
        rawOutput: outputText,
        usageMetadata: response.usageMetadata,
      },
      fileInfo: {
        name: file.name,
        sizeBytes: file.size,
      },
    });
  } catch (error: any) {
    console.error('[PDF Transform Error]:', error);
    return NextResponse.json(
      { error: 'Internal Server Error', message: error.message || 'PDF 解析失敗' },
      { status: 500 }
    );
  } finally {
    // 7. 清理機制:無論成功失敗,均清理伺服器暫存與 Google 雲端臨時檔
    if (tempFilePath) {
      await unlink(tempFilePath).catch((err) =>
        console.error('刪除本機暫存失敗:', err)
      );
    }
    if (uploadedFileResource?.file?.name) {
      await fileManager
        .deleteFile(uploadedFileResource.file.name)
        .catch((err) => console.error('清理 Google File API 暫存失敗:', err));
    }
  }
}


🧪 實測震撼:吞下一份 30 頁白皮書!

我們拿一份近 30 頁、包含大量圖表與排版的「2026 AI 產業趨勢白皮書」PDF 進行測試:

curl -X POST http://localhost:3000/api/ai/transform-pdf \
  -F "file=@/path/to/AI_Trends_2026_Report.pdf"

回傳結構亮點:

{
  "success": true,
  "data": {
    "rawOutput": "### 💡 核心洞見 (Core Takeaways)\n1. **長上下文普及引發架構顛覆**:報告第 12 頁數據指出,超過 64% 的企業開始簡化向量檢索管線...\n\n### 📊 關鍵數據對照表\n| 技術指標 | 2025 年水準 | 2026 年預測 | 成長幅度 |\n| :--- | :--- | :--- | :--- |\n| Context Window | 128k Tokens | 2M+ Tokens | 15.6x |\n| 推論成本/百萬Token | $1.50 | $0.15 | -90% |",
    "usageMetadata": {
      "promptTokenCount": 42810,
      "candidatesTokenCount": 850,
      "totalTokenCount": 43660
    }
  },
  "fileInfo": {
    "name": "AI_Trends_2026_Report.pdf",
    "sizeBytes": 8421050
  }
}

可以看到:

  • Token 消耗:這份 30 頁的圖文 PDF 換算約 42,810 Tokens。對於具備 100 萬上下文的 Gemini 而言,僅僅使用了其容量的 4.2%!
  • 速度:Gemini 1.5 Flash 僅花了約 4.8 秒 即回傳了包含精確 Markdown 表格與交叉引用的全面報告。
  • 事實保真度:Gemini 能準確指稱「報告第 12 頁」的數據點,徹底免去 RAG 切塊可能帶來的頁碼遺失與脈絡斷裂。

🎯 總結與明日預告

今天我們見證了大模型時代的長文本革命:

  1. 深入分析了「傳統 RAG」在跨頁理解與維護成本上的硬傷,以及「Gemini 原生超長上下文」帶來的破局優勢。
  2. 掌握了 Google AI File API 的運作機制,實作了可容納大檔案的雙向上傳與生命週期清理機制。
  3. 成功打造出能吃下數十頁 PDF 並完整輸出結構化提煉筆記的後端端點。

既然 PDF 都能秒級消化,那麼難度更高的「長影片」與「Podcast 音訊」呢?

👉 明天(Day 09),我們將進入【多模態震撼篇】:影音不求人!我們不再需要任何額外的語音轉文字(STT)工具,看我們如何直接將 MP4 影片與 MP3 音訊餵入 Gemini,秒產具備時間軸標記的分段精華!

精彩內容不容錯過,我們明天見!🔥


上一篇
Day 07 -【Gemini API】快速串接 Google Gen AI SDK:在 Next.js 後端打造第一支生產級 AI Route Handler
下一篇
Day 09 -【多模態震撼】影音不求人:告別 Whisper!直接上傳音訊與影片,讓 Gemini 辨識語意與時間戳記切片
系列文
用 Google AI 生態系 30 天從零打造一個全棧 AI SaaS 服務 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言