跳到主要内容

使用 RAG 构建研究论文助手

本指南将介绍如何创建 AI 研究助手,使用检索增强生成(RAG)分析学术论文并回答有关其内容的具体问题。

你将使用 Transformer 原始论文 《Attention Is All You Need》作为示例,并使用本地 libSQL 数据库。

前提条件
前提条件的直接链接

  • 已安装 Node.js v22.13.0 或更高版本
  • 受支持的模型 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 模型,用于理解查询并生成响应
    • 自定义 instructions,用于指导 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. 将嵌入和 metadata(原始文本和来源信息)存储到向量数据库中
    备注

    这些 metadata 至关重要,因为向量存储找到相关匹配项时,可以据此返回实际内容。

    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 技术: