Back to templates
AI & Legal

Tax Code Assistant

RAG-powered AI chatbot that answers questions about tax codes using vector search and document parsing.

RAG
Qdrant
Mistral
OpenAI
Legal AI
Vector Search

About this template

Build a sophisticated RAG (Retrieval-Augmented Generation) AI assistant that can answer questions about tax codes. This workflow downloads PDF documents from government websites, extracts and partitions content into chapters and sections, stores them in a Qdrant vector database with Mistral.ai embeddings, and provides an AI chatbot interface with custom search tools. Uses a self-referential tool workflow pattern for efficient document retrieval.

Workflow JSON

{
  "name": "Tax Code Assistant",
  "nodes": [
    {
      "parameters": {
        "content": "## Template by Harshith Vaddiparthy\n\n\n**Learn to Build AI Automations**\nMaster n8n, AI agents, and no-code automation in my comprehensive course.\n→ harshith.com/vibecode\n\n\n**Content Automation Consulting**\nI help businesses automate video creation, social media, blogs, and newsletters.\n→ harshith.com/meet\n\n\n**Connect with me**\n→ linkedin.com/in/harshith-vaddiparthy",
        "height": 310,
        "width": 260,
        "color": 5
      },
      "id": "promo-sticky-note",
      "name": "Sticky Note - Credits",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        -200
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Tax Code Rag Agent\n### Agent for building the RAG agent\n\nThis workflow creates a RAG pipeline for tax code documents:\n1. Downloads PDFs from government websites\n2. Extracts text with proper chapter/section metadata\n3. Stores in Qdrant vector database\n4. Provides AI chat interface with semantic search",
        "height": 244,
        "width": 467
      },
      "id": "d0e45d23-c5f4-40cb-9313-cb5ab2e7bcec",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        160
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Insert\n### Runs the insert chain\n\nThis section handles document ingestion into the vector database with proper chunking and metadata.",
        "height": 180,
        "width": 470,
        "color": 4
      },
      "id": "88b4a9f0-5b9e-4f8f-938f-a74bb2df2f75",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        440
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Download\n### Download the tax code PDF\n\nDownloads the official tax code PDF from the government website.",
        "height": 153,
        "width": 466,
        "color": 4
      },
      "id": "31d1410e-c9fd-44de-8b8e-d5e64e6c2da6",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        660
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Extract\n### Extract the content of the PDF\n\nExtracts text from PDF while preserving structure for proper chapter/section parsing.",
        "height": 135,
        "width": 467,
        "color": 4
      },
      "id": "3e9c1607-8a00-42ea-8e3f-c84ed84fdcdc",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        860
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Partition\n### Partition based on chapter and section\n\nSplits content into meaningful chunks based on legal document structure (chapters and sections).",
        "height": 135,
        "width": 468,
        "color": 4
      },
      "id": "61e4fd17-5f51-40b7-a52d-a4df39c2e0ac",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        1040
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Store\n### Store the documents in the vector database\n\nStores document chunks with metadata in Qdrant for semantic retrieval.",
        "height": 137,
        "width": 468,
        "color": 4
      },
      "id": "3b65ab9e-4ccd-4c7e-9a32-a71113e0eded",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        1220
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Chat\n### Runs the chat chain\n\nProvides the AI chat interface with custom search tools for answering tax questions.",
        "height": 169,
        "width": 467,
        "color": 6
      },
      "id": "e3e16eb2-97b1-4d39-894a-c6201c91b5e2",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        1400
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "3e4aeb9c-63d4-49b7-ab2f-04e3f339bf15",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        1000,
        280
      ],
      "webhookId": "6fe38f8e-f1f8-4c54-952e-81a67f59ad3e",
      "typeVersion": 1.1
    },
    {
      "parameters": {
        "options": {},
        "requestMethod": "POST",
        "path": "tax-code-rag-agent",
        "responseMode": "lastNode"
      },
      "id": "18f76c43-fe1d-4fd5-a1e9-67ca2f5e5d9d",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1000,
        500
      ],
      "webhookId": "8f74a23b-d9ae-4ab9-9fe6-ea24160fa0a5",
      "typeVersion": 2
    },
    {
      "parameters": {
        "url": "https://www.tax.gov/documents/tax-code.pdf",
        "options": {}
      },
      "id": "f5a00e3e-b50f-45f9-97fc-e3ae4f7aabc1",
      "name": "Download PDF",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1380,
        720
      ],
      "typeVersion": 4.2
    },
    {
      "parameters": {
        "operation": "extractFromFile",
        "options": {}
      },
      "id": "e66e7e01-6f7e-487d-87ba-b5eb6f0aaf2d",
      "name": "Extract From PDF",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        1380,
        920
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "jsCode": "const text = $input.first().json.data;\n\nfunction extractChapters(text) {\n  const chapterRegex = /CHAPTER\\s+(\\d+[A-Z]?)\\s*\\n([^\\n]+)/gi;\n  const chapters = [];\n  let match;\n\n  while ((match = chapterRegex.exec(text)) !== null) {\n    chapters.push({\n      chapterNumber: match[1],\n      chapterTitle: match[2].trim(),\n      startIndex: match.index,\n    });\n  }\n\n  for (let i = 0; i < chapters.length; i++) {\n    const startIndex = chapters[i].startIndex;\n    const endIndex =\n      i + 1 < chapters.length ? chapters[i + 1].startIndex : text.length;\n    chapters[i].content = text.substring(startIndex, endIndex).trim();\n  }\n\n  return chapters;\n}\n\nfunction extractSectionsFromChapter(chapter) {\n  const sectionRegex = /SEC\\.\\s*(\\d+)\\.\\s*([^\\n]+)/gi;\n  const sections = [];\n  let match;\n\n  while ((match = sectionRegex.exec(chapter.content)) !== null) {\n    sections.push({\n      chapterNumber: chapter.chapterNumber,\n      chapterTitle: chapter.chapterTitle,\n      sectionNumber: match[1],\n      sectionTitle: match[2].trim(),\n      startIndex: match.index,\n    });\n  }\n\n  for (let i = 0; i < sections.length; i++) {\n    const startIndex = sections[i].startIndex;\n    const endIndex =\n      i + 1 < sections.length\n        ? sections[i + 1].startIndex\n        : chapter.content.length;\n    sections[i].content = chapter.content.substring(startIndex, endIndex).trim();\n    delete sections[i].startIndex;\n  }\n\n  return sections;\n}\n\nconst chapters = extractChapters(text);\nconst allSections = [];\n\nfor (const chapter of chapters) {\n  const sections = extractSectionsFromChapter(chapter);\n  allSections.push(...sections);\n}\n\nreturn allSections.map((section) => ({ json: section }));"
      },
      "id": "d0faa99b-93b9-44ef-bab9-76a2ff00d3ae",
      "name": "Split by chapter and section",
      "type": "n8n-nodes-base.code",
      "position": [
        1380,
        1100
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "mode": "insert",
        "qdrantCollection": {
          "__rl": true,
          "mode": "list",
          "value": "tax_code",
          "cachedResultName": "tax_code"
        },
        "options": {}
      },
      "id": "c5f08c78-22e1-4a3b-9e09-d1014bd05a8b",
      "name": "Insert into Qdrant",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        1380,
        1280
      ],
      "typeVersion": 1,
      "credentials": {
        "qdrantApi": {
          "id": "YOUR_QDRANT_CREDENTIAL_ID",
          "name": "Qdrant"
        }
      }
    },
    {
      "parameters": {
        "model": "mistral-embed"
      },
      "id": "8bf0a72d-c5a1-45ea-a3b6-0c1b6fec7cec",
      "name": "Embeddings Mistral Cloud",
      "type": "@n8n/n8n-nodes-langchain.embeddingsMistralCloud",
      "position": [
        1380,
        1480
      ],
      "typeVersion": 1,
      "credentials": {
        "mistralCloudApi": {
          "id": "YOUR_MISTRAL_CREDENTIAL_ID",
          "name": "Mistral"
        }
      }
    },
    {
      "parameters": {
        "jsonMode": "expressionData",
        "jsonData": "={{ $json.content }}",
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "chapterNumber",
                "value": "={{ $json.chapterNumber }}"
              },
              {
                "name": "chapterTitle",
                "value": "={{ $json.chapterTitle }}"
              },
              {
                "name": "sectionNumber",
                "value": "={{ $json.sectionNumber }}"
              },
              {
                "name": "sectionTitle",
                "value": "={{ $json.sectionTitle }}"
              }
            ]
          }
        }
      },
      "id": "9dc99ca1-d2ab-4d3d-a3ab-cf51915cf3d3",
      "name": "Default Data Loader",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        1500,
        1480
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "chunkSize": 2000,
        "chunkOverlap": 200,
        "options": {}
      },
      "id": "68a4c6a4-efc3-4cee-be0f-5b10f91b5b17",
      "name": "Recursive Character Text Splitter",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        1640,
        1480
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "amount": 1,
        "unit": "seconds"
      },
      "id": "8b1cc8b7-edb9-4f6e-a2c9-e34dc3c5f1f3",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        1580,
        1280
      ],
      "webhookId": "eb6e7155-c9a3-4973-a2cc-b6a3a66dcf2a",
      "typeVersion": 1.1
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $json.body?.route }}",
                    "rightValue": "insert",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputLabel": "Insert"
            },
            {
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $json.body?.route }}",
                    "rightValue": "chat",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputLabel": "Chat"
            },
            {
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $json.body?.route }}",
                    "rightValue": "search",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputLabel": "Search"
            }
          ]
        },
        "options": {}
      },
      "id": "bffacf11-0b52-4b1c-85d6-59b2ff2e0c11",
      "name": "Route",
      "type": "n8n-nodes-base.switch",
      "position": [
        1180,
        500
      ],
      "typeVersion": 3.2
    },
    {
      "parameters": {
        "options": {
          "systemMessage": "You are a tax code expert. Answer questions about tax regulations based on the official tax code documents. Always cite the specific chapter and section when providing information."
        }
      },
      "id": "b49f0b58-bb8f-4c3c-961b-3ab39cbb38cd",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1380,
        1560
      ],
      "typeVersion": 1.7
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "id": "bbf8d19d-b7ba-4e5f-84d9-c5a2dcb66d24",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1260,
        1760
      ],
      "typeVersion": 1.2,
      "credentials": {
        "openAiApi": {
          "id": "YOUR_OPENAI_CREDENTIAL_ID",
          "name": "OpenAI"
        }
      }
    },
    {
      "parameters": {
        "contextWindowLength": 20
      },
      "id": "2dc3e78e-7ed6-4b85-a93f-b0a6e5e0e2bf",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        1380,
        1760
      ],
      "typeVersion": 1.3
    },
    {
      "parameters": {
        "name": "tax_code_search",
        "description": "Search the tax code for relevant sections. Use this to find information about specific tax topics, chapters, or sections.",
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "={{ $workflow.id }}"
        },
        "fields": {
          "values": [
            {
              "name": "route",
              "stringValue": "search"
            }
          ]
        }
      },
      "id": "5d3f14b6-2c91-4e3d-87c3-c45b1b2fe6e7",
      "name": "Tax Code Search Tool",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        1500,
        1760
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "mode": "retrieve",
        "qdrantCollection": {
          "__rl": true,
          "mode": "list",
          "value": "tax_code",
          "cachedResultName": "tax_code"
        },
        "options": {
          "searchFilterJson": "={{ $json.body?.filter ? JSON.stringify($json.body.filter) : '' }}"
        }
      },
      "id": "a8ef9a25-b7a2-46c4-9a4b-bb9c9a1a2d73",
      "name": "Vector Store Search",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        1380,
        1960
      ],
      "typeVersion": 1,
      "credentials": {
        "qdrantApi": {
          "id": "YOUR_QDRANT_CREDENTIAL_ID",
          "name": "Qdrant"
        }
      }
    },
    {
      "parameters": {
        "model": "mistral-embed"
      },
      "id": "e5dcf8ba-8a8e-4f6c-b25f-a54d5ff5af1a",
      "name": "Embeddings Mistral Cloud Search",
      "type": "@n8n/n8n-nodes-langchain.embeddingsMistralCloud",
      "position": [
        1380,
        2160
      ],
      "typeVersion": 1,
      "credentials": {
        "mistralCloudApi": {
          "id": "YOUR_MISTRAL_CREDENTIAL_ID",
          "name": "Mistral"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.body?.query }}"
      },
      "id": "52ffc17d-b1e9-4c1e-8b79-96d32e5adbf7",
      "name": "Vector Store Retriever",
      "type": "@n8n/n8n-nodes-langchain.chainRetrievalQa",
      "position": [
        1380,
        2360
      ],
      "typeVersion": 1.4
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "7e9c8cad-b5c7-48c2-9c8a-f2c6b5d7a8e9",
      "name": "Retriever",
      "type": "@n8n/n8n-nodes-langchain.retrieverVectorStore",
      "position": [
        1620,
        2360
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "id": "9d5f8a3c-e7b2-4c1d-8a9f-b3c7d6e5f4a2",
      "name": "OpenAI Chat Model Search",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1500,
        2560
      ],
      "typeVersion": 1.2,
      "credentials": {
        "openAiApi": {
          "id": "YOUR_OPENAI_CREDENTIAL_ID",
          "name": "OpenAI"
        }
      }
    }
  ],
  "connections": {
    "When chat message received": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Route",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download PDF": {
      "main": [
        [
          {
            "node": "Extract From PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract From PDF": {
      "main": [
        [
          {
            "node": "Split by chapter and section",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split by chapter and section": {
      "main": [
        [
          {
            "node": "Insert into Qdrant",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Mistral Cloud": {
      "ai_embedding": [
        [
          {
            "node": "Insert into Qdrant",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Default Data Loader": {
      "ai_document": [
        [
          {
            "node": "Insert into Qdrant",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Recursive Character Text Splitter": {
      "ai_textSplitter": [
        [
          {
            "node": "Default Data Loader",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "Insert into Qdrant": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Insert into Qdrant",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route": {
      "main": [
        [
          {
            "node": "Download PDF",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Vector Store Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Tax Code Search Tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Vector Store Search": {
      "main": [
        [
          {
            "node": "Vector Store Retriever",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Mistral Cloud Search": {
      "ai_embedding": [
        [
          {
            "node": "Vector Store Search",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Retriever": {
      "ai_retriever": [
        [
          {
            "node": "Vector Store Retriever",
            "type": "ai_retriever",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model Search": {
      "ai_languageModel": [
        [
          {
            "node": "Vector Store Retriever",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 0,
  "updatedAt": "2024-01-23T00:00:00.000Z",
  "versionId": "tax-code-v1"
}

Copy this JSON and import it into n8n via Settings → Import from File/URL → Paste JSON

Free n8n Automation Templates | Production-Ready Workflows | Harshith Vaddiparthy