跳至主要內容

使用 RAG 建立研究論文助手

在本指南中,你將建立一個 AI 研究助手,運用檢索增強生成(RAG)分析學術論文,並回答與論文內容相關的特定問題。

你會以 Transformer 原始論文 「Attention Is All You Need」作為範例,並使用本機 libSQL 資料庫。

前置條件
前置條件 的直接連結

  • 已安裝 Node.js v22.13.0 或更新版本
  • 受支援的 Model Provider 所提供的 API 金鑰
  • 現有的 Mastra 項目(按照安裝指南設定新項目)

RAG 的運作方式
RAG 的運作方式 的直接連結

先了解 RAG 的運作方式,以及你會如何實作各個組件。

知識儲存庫/索引
知識儲存庫/索引 的直接連結

  • 將文字轉換為向量表示
  • 建立內容的數值表示
  • 實作:使用 OpenAI 的 text-embedding-3-small 建立嵌入,並儲存在 LibSQLVector 中

檢索器
檢索器 的直接連結

  • 透過相似度搜尋找出相關內容
  • 將查詢嵌入與已儲存的向量配對
  • 實作:使用 LibSQLVector 對已儲存的嵌入執行相似度搜尋

生成器
生成器 的直接連結

  • 使用 LLM 處理檢索到的內容
  • 建立結合情境的回應
  • 實作:使用 OpenAI 模型,根據檢索到的內容產生答案

你的實作將會:

  1. 將 Transformer 論文處理成嵌入
  2. 將它們儲存在 LibSQLVector 中,以便快速檢索
  3. 使用相似度搜尋找出相關章節
  4. 使用檢索到的情境產生準確回應

建立 Agent
建立 Agent 的直接連結

現在定義 Agent 的行為、將它連接至 Mastra 項目,並建立向量儲存庫。

  1. 安裝額外依賴套件

    按照安裝指南操作後,你需要安裝額外依賴套件:

    npm install @mastra/rag@latest ai
  2. 現在建立支援 RAG 的研究助手。此 Agent 使用:

    • Vector Query Tool,用於對向量儲存庫執行語意搜尋,以找出論文中的相關內容
    • OpenAI 模型,用於理解查詢並產生回應
    • 自訂指示,引導 Agent 分析論文、有效使用檢索到的內容,並承認其限制

    建立新檔案 src/mastra/agents/researchAgent.ts 並定義 Agent:

    src/mastra/agents/researchAgent.ts
    import { Agent } from '@mastra/core/agent'
    import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
    import { createVectorQueryTool } from '@mastra/rag'

    // Create a tool for semantic search over the paper embeddings
    const vectorQueryTool = createVectorQueryTool({
    vectorStoreName: 'libSqlVector',
    indexName: 'papers',
    model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
    })

    export const researchAgent = new Agent({
    id: 'research-agent',
    name: 'Research Assistant',
    instructions: `You are a helpful research assistant that analyzes academic papers and technical documents.
    Use the provided vector query tool to find relevant information from your knowledge base,
    and provide accurate, well-supported answers based on the retrieved content.
    Focus on the specific content available in the tool and acknowledge if you cannot find sufficient information to answer a question.
    Base your responses only on the content provided, not on general knowledge.`,
    model: 'openai/gpt-5.6-sol',
    tools: {
    vectorQueryTool,
    },
    })
  3. 在項目根目錄使用 pwd 命令取得絕對路徑。路徑可能與以下相似:

    > pwd
    /Users/your-name/guides/research-assistant

    src/mastra/index.ts 的現有檔案及設定中加入以下內容:

    src/mastra/index.ts
    import { Mastra } from '@mastra/core'
    import { LibSQLVector } from '@mastra/libsql'

    const libSqlVector = new LibSQLVector({
    id: 'research-vectors',
    url: 'file:/Users/your-name/guides/research-assistant/vector.db',
    })

    export const mastra = new Mastra({
    vectors: { libSqlVector },
    })

    url 請使用從 pwd 命令取得的絕對路徑。這樣便會在項目根目錄建立 vector.db 檔案。

    備註

    本指南為方便示範而使用寫死的絕對路徑,指向本機 libSQL 檔案;但這種做法不適用於正式環境。屆時你應使用遙距持久化資料庫。

  4. src/mastra/index.ts 檔案中,將 Agent 加入 Mastra:

    src/mastra/index.ts
    import { Mastra } from '@mastra/core'
    import { LibSQLVector } from '@mastra/libsql'
    import { researchAgent } from './agents/researchAgent'

    const libSqlVector = new LibSQLVector({
    id: 'research-vectors',
    url: 'file:/Users/your-name/guides/research-assistant/vector.db',
    })

    export const mastra = new Mastra({
    agents: { researchAgent },
    vectors: { libSqlVector },
    })

處理文件
處理文件 的直接連結

在以下步驟中,你會擷取研究論文並將它分割成較小的區塊,然後產生嵌入並把區塊儲存在向量資料庫中。

  1. 此步驟會透過 URL 擷取研究論文,將它轉換成文件物件,再分割成較小且易於管理的區塊。分割後,處理速度更快、效率亦更高。

    建立新檔案 src/store.ts 並加入以下內容:

    src/store.ts
    import { MDocument } from '@mastra/rag'

    // Load the paper
    const paperUrl = 'https://arxiv.org/html/1706.03762'
    const response = await fetch(paperUrl)
    const paperText = await response.text()

    // Create document and chunk it
    const doc = MDocument.fromText(paperText)
    const chunks = await doc.chunk({
    strategy: 'recursive',
    maxSize: 512,
    overlap: 50,
    separators: ['\n\n', '\n', ' '],
    })

    console.log('Number of chunks:', chunks.length)

    在終端機執行此檔案:

    npx bun src/store.ts

    你應會得到以下回應:

    Number of chunks: 892
  2. 最後,透過以下步驟為 RAG 準備內容:

    1. 為每個文字區塊產生嵌入
    2. 建立向量儲存庫索引以保存嵌入
    3. 將嵌入及中繼資料(原始文字及來源資訊)儲存在向量資料庫中
    備註

    這些中繼資料非常重要,因為向量儲存庫找到相關配對時,可藉此傳回實際內容。

    Agent 使用向量索引搜尋及檢索相關資訊。

    開啟 src/store.ts 檔案並加入以下內容:

    src/store.ts
    import { MDocument } from '@mastra/rag'
    import { embedMany } from 'ai'
    import { mastra } from './mastra'

    // Load the paper
    const paperUrl = 'https://arxiv.org/html/1706.03762'
    const response = await fetch(paperUrl)
    const paperText = await response.text()

    // Create document and chunk it
    const doc = MDocument.fromText(paperText)
    const chunks = await doc.chunk({
    strategy: 'recursive',
    maxSize: 512,
    overlap: 50,
    separators: ['\n\n', '\n', ' '],
    })

    // Generate embeddings
    const { embeddings } = await embedMany({
    model: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
    values: chunks.map(chunk => chunk.text),
    })

    // Get the vector store instance from Mastra
    const vectorStore = mastra.getVector('libSqlVector')

    // Create an index for paper chunks
    await vectorStore.createIndex({
    indexName: 'papers',
    dimension: 1536,
    })

    // Store embeddings
    await vectorStore.upsert({
    indexName: 'papers',
    vectors: embeddings,
    metadata: chunks.map(chunk => ({
    text: chunk.text,
    source: 'transformer-paper',
    })),
    })

    最後,再次執行指令碼以儲存嵌入:

    npx bun src/store.ts

    如果操作成功,終端機不應顯示任何輸出或錯誤。

測試助手
測試助手 的直接連結

向量資料庫現已包含所有嵌入,你可以使用不同類型的查詢測試研究助手。

建立新檔案 src/ask-agent.ts 並加入不同類型的查詢:

src/ask-agent.ts
import { mastra } from './mastra'
const agent = mastra.getAgent('researchAgent')

// Basic query about concepts
const query1 = 'What problems does sequence modeling face with neural networks?'
const response1 = await agent.generate(query1)
console.log('\nQuery:', query1)
console.log('Response:', response1.text)

執行指令碼:

npx bun src/ask-agent.ts

你應會看到類似以下的輸出:

Query: What problems does sequence modeling face with neural networks?
Response: Sequence modeling with neural networks faces several key challenges:
1. Vanishing and exploding gradients during training, especially with long sequences
2. Difficulty handling long-term dependencies in the input
3. Limited computational efficiency due to sequential processing
4. Challenges in parallelizing computations, resulting in longer training times

嘗試另一條問題:

src/ask-agent.ts
import { mastra } from './mastra'
const agent = mastra.getAgent('researchAgent')

// Query about specific findings
const query2 = 'What improvements were achieved in translation quality?'
const response2 = await agent.generate(query2)
console.log('\nQuery:', query2)
console.log('Response:', response2.text)

輸出:

Query: What improvements were achieved in translation quality?
Response: The model showed significant improvements in translation quality, achieving more than 2.0
BLEU points improvement over previously reported models on the WMT 2014 English-to-German translation
task, while also reducing training costs.

提供應用程式服務
提供應用程式服務 的直接連結

啟動 Mastra 伺服器,透過 API 提供研究助手:

mastra dev

你的研究助手可透過以下位置使用:

http://localhost:4111/api/agents/researchAgent/generate

使用 curl 測試:

curl -X POST http://localhost:4111/api/agents/researchAgent/generate \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "user", "content": "What were the main findings about model parallelization?" }
]
}'

進階 RAG 範例
進階 RAG 範例 的直接連結

瀏覽以下範例,了解更進階的 RAG 技術: