n8n Workflow
Expert

AI-Powered Stock Document Q&A with OpenAI and Qdrant

Build a RAG (Retrieval-Augmented Generation) system to answer questions about financial documents. Ingest PDFs from Google Drive, create embeddings with OpenAI, store in Qdrant, and query via a webhook API.

Overview

Automates the creation of an AI-powered Q&A system that ingests stock reports from Google Drive and answers user queries about them through a simple API endpoint using OpenAI and Qdrant.

🧠 Description & Use Case

This workflow builds a complete Retrieval-Augmented Generation (RAG) system for querying documents. It consists of two main parts:

  1. Data Ingestion: Processing a source document (a PDF from Google Drive), converting it into searchable vector embeddings, and storing it in a Qdrant vector database.
  2. Question Answering: Exposing a webhook API that allows users to ask natural language questions and receive AI-generated answers based on the ingested document's content.

🔄 How It Works:

Part 1: Data Ingestion (Manual Trigger)

This part of the workflow is executed manually to load a document into the knowledge base.

  1. Trigger: The workflow begins when you manually click 'Execute Workflow'.
  2. Fetch Document: The Google Drive node downloads a specified PDF file (e.g., a company's financial report).
  3. Process & Chunk: The binary data from the PDF is passed to the Binary to Document loader. This loader utilizes the Recursive Character Text Splitter to break the document's text into smaller, overlapping chunks, which is optimal for AI processing.
  4. Embed & Store: The Qdrant Vector Store node orchestrates the final step. It takes the text chunks and uses the Embeddings OpenAI node to convert each chunk into a numerical vector (an embedding). These embeddings are then stored (upserted) into a specified collection in your Qdrant database, making the document's knowledge semantically searchable.

Part 2: Question & Answering (Webhook API)

This part is always active, listening for user questions.

  1. API Endpoint: The Webhook node acts as an API endpoint, waiting for a POST request. The request should contain the user's question (input) and the name of the company/collection to query (company).
  2. Retrieve Relevant Context: When a question is received, the Retrieval QA Chain is triggered. It uses a Vector Store Retriever to search the specified Qdrant collection for the text chunks that are most semantically similar to the user's question.
  3. Generate Answer: The retrieved chunks (the context) and the original question are sent to the OpenAI Chat Model (e.g., GPT-4). The large language model analyzes the context and formulates a coherent, human-like answer to the question.
  4. Send Response: The Respond to Webhook node sends the final, AI-generated answer back to the user who made the API request.

✅ Real-World Use Cases:

  • Financial Analysis: Quickly ask questions about specific figures, statements, or risk factors mentioned in lengthy 10-K filings or earnings reports.
  • Internal Knowledge Base: Create a Q&A bot for your company's internal documentation, HR policies, or technical manuals.
  • Customer Support Automation: Build a chatbot that can answer customer questions by referencing product user guides or FAQs.
  • Research Assistant: Ingest complex research papers or legal documents and query them for specific information, summaries, or cross-references without reading the entire text.

Instructions

Basic steps

  1. Download workflow JSON
  2. Import into n8n
  3. Configure node parameters as needed
  4. Test and enable the workflow

💡 Tips

After importing, verify all connectors and credentials match your environment.

Preview

Workflow Visualization

17 nodes
100%
Embeddings OpenAI1@n8n/langchain.embeddingsOpenAiOn new manual Chat Message@n8n/langchain.manualChatTriggerSticky Note1stickyNoteRetrieval QA Chain@n8n/langchain.chainRetrievalQaRespond to WebhookrespondToWebhookVector Store Retriever@n8n/langchain.retrieverVectorStoreWebhook1webhookWhen clicking "Execute Workflow"manualTriggerGoogle DrivegoogleDriveBinary to Document@n8n/langchain.documentBinaryInputLoaderRecursive Character Text Splitter@n8n/langchain.textSplitterRecursiveCharacterTextSplitterEmbeddings OpenAI@n8n/langchain.embeddingsOpenAiSticky NotestickyNoteQdrant Vector Store@n8n/langchain.vectorStoreQdrantQdrant Vector Store1@n8n/langchain.vectorStoreQdrantOpenAI Chat Model@n8n/langchain.lmChatOpenAiSticky Note2stickyNote

Nodes

1

Embeddings OpenAI1

@n8n/langchain.embeddingsOpenAi

v1
2

On new manual Chat Message

禁用

@n8n/langchain.manualChatTrigger

v1
3

Sticky Note1

stickyNote

v1
4

Retrieval QA Chain

@n8n/langchain.chainRetrievalQa

v1
5

Respond to Webhook

respondToWebhook

v1
6

Vector Store Retriever

@n8n/langchain.retrieverVectorStore

v1
7

Webhook1

webhook

v1.1
8

When clicking "Execute Workflow"

manualTrigger

v1
9

Google Drive

googleDrive

v3
10

Binary to Document

@n8n/langchain.documentBinaryInputLoader

v1
11

Recursive Character Text Splitter

@n8n/langchain.textSplitterRecursiveCharacterTextSplitter

v1
12

Embeddings OpenAI

@n8n/langchain.embeddingsOpenAi

v1
13

Sticky Note

stickyNote

v1
14

Qdrant Vector Store

@n8n/langchain.vectorStoreQdrant

v1
15

Qdrant Vector Store1

@n8n/langchain.vectorStoreQdrant

v1
16

OpenAI Chat Model

@n8n/langchain.lmChatOpenAi

v1
17

Sticky Note2

stickyNote

v1

Statistics

Total nodes:17
Disabled nodes:1
Node types:13
Connections:12
View full JSON structure
{
  "nodes": [
    {
      "id": "ec3b86be-4113-4fd5-8365-02adb67693e9",
      "name": "Embeddings OpenAI1",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        1960,
        720
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "fOF5kro9BJ6KMQ7n",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "42fd8020-3861-4d0f-a7a2-70e2c35f0bed",
      "name": "On new manual Chat Message",
      "type": "@n8n/n8n-nodes-langchain.manualChatTrigger",
      "disabled": true,
      "position": [
        1620,
        240
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "a9b48d04-691e-4537-90f8-d7a4aa6153af",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1560,
        120
      ],
      "parameters": {
        "color": 6,
        "width": 903.0896125323785,
        "height": 733.5099670584011,
        "content": "## Step 2: Setup the Q&A \n### The incoming message from the webhook is queried from the Supabase Vector Store. The response is provided in the response webhook. "
      },
      "typeVersion": 1
    },
    {
      "id": "472b4800-745a-4337-9545-163247f7e9ae",
      "name": "Retrieval QA Chain",
      "type": "@n8n/n8n-nodes-langchain.chainRetrievalQa",
      "position": [
        1880,
        240
      ],
      "parameters": {
        "query": "={{ $json.body.input }}"
      },
      "typeVersion": 1
    },
    {
      "id": "e58bd82d-abc6-44ed-8e93-ec5436126d66",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2280,
        240
      ],
      "parameters": {
        "options": {},
        "respondWith": "text",
        "responseBody": "={{ $json.response.text }}"
      },
      "typeVersion": 1
    },
    {
      "id": "04bbf01e-8269-47c7-897d-4ea94a1bd1c0",
      "name": "Vector Store Retriever",
      "type": "@n8n/n8n-nodes-langchain.retrieverVectorStore",
      "position": [
        2020,
        440
      ],
      "parameters": {
        "topK": 5
      },
      "typeVersion": 1
    },
    {
      "id": "feee6d68-2e0d-4d40-897e-c1d833a13bf2",
      "name": "Webhook1",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1620,
        420
      ],
      "webhookId": "679f4afb-189e-4f04-9dc0-439eec2ec5f1",
      "parameters": {
        "path": "19f5499a-3083-4783-93a0-e8ed76a9f742",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 1.1
    },
    {
      "id": "1b8d251f-7069-4d7d-b6d6-4bfa683d4ad1",
      "name": "When clicking \"Execute Workflow\"",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        280,
        260
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "b746a7a4-ed94-4332-bf7b-65aadcf54130",
      "name": "Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        580,
        260
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "list",
          "value": "1LZezppYrWpMStr4qJXtoIX-Dwzvgehll",
          "cachedResultUrl": "https://drive.google.com/file/d/1LZezppYrWpMStr4qJXtoIX-Dwzvgehll/view?usp=drivesdk",
          "cachedResultName": "crowdstrike.pdf"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "1tsDIpjUaKbXy0be",
          "name": "Google Drive account"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "83a7d470-f934-436d-ba3f-1ae7c776f5a5",
      "name": "Binary to Document",
      "type": "@n8n/n8n-nodes-langchain.documentBinaryInputLoader",
      "position": [
        860,
        480
      ],
      "parameters": {
        "loader": "pdfLoader",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "b52b4a90-99a1-49cc-a6f0-7551d6754496",
      "name": "Recursive Character Text Splitter",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        860,
        640
      ],
      "parameters": {
        "options": {},
        "chunkSize": 3000,
        "chunkOverlap": 200
      },
      "typeVersion": 1
    },
    {
      "id": "b525e130-2029-4f55-a603-1fdc05a19c17",
      "name": "Embeddings OpenAI",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        1160,
        480
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "fOF5kro9BJ6KMQ7n",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5358c53f-55f9-431d-8956-c6bae7ad25bc",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        540,
        120
      ],
      "parameters": {
        "color": 6,
        "width": 772.0680602743597,
        "height": 732.3675002130781,
        "content": "## Step 1: Upserting the PDF\n### Fetch file from Google Drive, split it into chunks and insert into Supabase index\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fb91e2da-0eeb-47a5-aa49-65bf56986857",
      "name": "Qdrant Vector Store",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        940,
        260
      ],
      "parameters": {
        "mode": "insert",
        "options": {},
        "qdrantCollection": {
          "__rl": true,
          "mode": "id",
          "value": "=crowd"
        }
      },
      "credentials": {
        "qdrantApi": {
          "id": "U5CpjAgFeXziP3I1",
          "name": "QdrantApi account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "89e14837-d1fc-4b1e-9ebc-7cf3e7fd9a70",
      "name": "Qdrant Vector Store1",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        1980,
        600
      ],
      "parameters": {
        "qdrantCollection": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.body.company }}"
        }
      },
      "credentials": {
        "qdrantApi": {
          "id": "U5CpjAgFeXziP3I1",
          "name": "QdrantApi account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c619245b-5ea0-4354-974d-21ec6b8efa93",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1880,
        460
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "fOF5kro9BJ6KMQ7n",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e4aa780d-8069-4308-a61f-82ed876af71a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        120
      ],
      "parameters": {
        "color": 6,
        "width": 710.9124489067698,
        "height": 726.4452519516944,
        "content": "## Start here: Step-by Step Youtube Tutorial :star:\n\n[![Building an AI Crew to Analyze Financial Data with CrewAI and n8n](https://img.youtube.com/vi/pMvizUx5n1g/sddefault.jpg)](https://www.youtube.com/watch?v=pMvizUx5n1g)\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Webhook1": {
      "main": [
        [
          {
            "node": "Retrieval QA Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive": {
      "main": [
        [
          {
            "node": "Qdrant Vector Store",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Retrieval QA Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Binary to Document": {
      "ai_document": [
        [
          {
            "node": "Qdrant Vector Store",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI1": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store1",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Retrieval QA Chain": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Qdrant Vector Store1": {
      "ai_vectorStore": [
        [
          {
            "node": "Vector Store Retriever",
            "type": "ai_vectorStore",
            "index": 0
          }
        ]
      ]
    },
    "Vector Store Retriever": {
      "ai_retriever": [
        [
          {
            "node": "Retrieval QA Chain",
            "type": "ai_retriever",
            "index": 0
          }
        ]
      ]
    },
    "On new manual Chat Message": {
      "main": [
        [
          {
            "node": "Retrieval QA Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \"Execute Workflow\"": {
      "main": [
        [
          {
            "node": "Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recursive Character Text Splitter": {
      "ai_textSplitter": [
        [
          {
            "node": "Binary to Document",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    }
  }
}

Actions

Share
Categories:
Tags:
manualtriggerwebhookstickynotegoogledriverespondtowebhook

Technical Specs

Complexity:
Expert
Node Count:
17 nodes
Published:11 months ago
Updated:about 1 month ago

Compatibility

Platform:
N8N Cloud & Self-hosted
Min Version:
N8N v1.0.0+
Supports cloud and self-hosted deployment

License

This workflow template follows MIT license, you can freely use, modify and distribute.

Please comply with relevant third-party service terms when using.

Related Workflows