DEV Community

Cover image for From Web to Vector: Building RAG Pipelines
Lalit Mishra
Lalit Mishra

Posted on

From Web to Vector: Building RAG Pipelines

1. The "Garbage In, Garbage Out" Reality of RAG

In the rush to adopt Generative AI, a dangerous misconception has taken root: that the Large Language Model (LLM) is the magic wand that solves information retrieval. Teams dump thousands of raw PDFs, messy HTML scrapes, and unformatted Confluence pages into a vector database, wire up an embedding model, and expect GPT-4 to act as a perfect oracle.

The reality is a chatbot that confidently hallucinates, retrieves navigation footers instead of technical specs, and costs a fortune in token usage because it’s processing thousands of characters of HTML boilerplate for every query.

Retrieval Augmented Generation (RAG) is not an AI problem; it is a data engineering problem.

The difference between a toy demo and a production RAG system lies almost entirely in the Data Pipeline—specifically, the rigorous transformation of unstructured web content into semantically dense, highly indexable vector representations. If your vector search returns garbage, your LLM will generate garbage. No amount of prompt engineering can fix a context window filled with <div> tags and cookie consent banners.

This article details the architecture of a high-performance Web-to-Vector pipeline, moving beyond basic tutorials to discuss the engineering trade-offs of cleaning, chunking, and embedding strategies that survive in production.

A split-screen meme format


2. The Web-to-Vector Pipeline Architecture

Treating RAG as an ETL (Extract, Transform, Load) workflow allows us to apply standard data engineering rigor to AI systems. The pipeline consists of five distinct stages, each acting as a filter for noise and a multiplier for signal.

  1. Acquisition: Reliable fetching of dynamic and static content.
  2. Distillation: Converting raw DOM trees into "Dense Text" or Markdown.
  3. Fragmentation (Chunking): The strategic breaking of text into semantic units.
  4. Vectorization: Generating embeddings at scale.
  5. Indexing: Storage with metadata strategies for pre-filtering.

A horizontal system architecture diagram titled


3. High-Fidelity Scraping: Beyond requests.get()

The first point of failure is often the acquisition layer. Modern websites are complex Single Page Applications (SPAs) laden with hydration scripts, lazy-loaded content, and anti-bot defenses.

3.1 The DOM is Noise

A raw HTML document is approximately 90% noise relative to an LLM's needs. Classes, IDs, inline styles, script tags, and SVG paths consume embedding dimensions without adding semantic meaning.

  • The Wrong Way: Feeding raw HTML to an embedding model. The model will waste attention mechanisms on <div class="flex-col-8"> rather than the core content.
  • The Right Way: HTML-to-Markdown conversion.

Markdown is the lingua franca of LLMs. It preserves structural hierarchy (headers, lists, tables) which are critical for semantic understanding, while stripping the presentation layer.

Tools of the Trade:

  • Trafilatura: Excellent for extracting the main article body and discarding sidebars/navs. It uses heuristics to identify the "center of gravity" of text density.
  • BeautifulSoup + Custom Heuristics: For specialized sites (e.g., documentation with complex code blocks), you often need to write custom parsers that target specific #content divs and preserve <code> tags while stripping controls.

3.2 Dynamic Content Handling

For production systems, a static HTTP request often fails. You need a headless browser cluster (e.g., Playwright or Puppeteer) to render the DOM.

  • Engineering Tip: Aggressively block resource types. Your scraper does not need to load images, fonts, or stylesheets. Blocking these reduces latency by 60-80% and saves bandwidth costs.

4. Chunking Strategies: The Art of Segmentation

Once you have clean, dense Markdown, you face the most critical decision in the pipeline: Chunking.

How you split your text determines what your retrieval system can find. If you split a question from its answer, no amount of embedding power will reconnect them.

4.1 Fixed-Size vs. Semantic Chunking

Fixed-Size Chunking:
The naive approach. "Split every 500 tokens, with 50 tokens overlap."

  • Pros: Computationally cheap, predictable.
  • Cons: Frequently breaks semantic thoughts. A sentence might be cut in half, destroying its vector representation.

Semantic Chunking:
This approach uses an embedding model to scan the text sentence-by-sentence. It calculates the cosine similarity between sequential sentences. If the similarity drops below a threshold (a "semantic break"), a new chunk is started.

  • Pros: Chunks represent coherent ideas. Retrieval precision increases significantly.
  • Cons: Computationally expensive (requires inference calls).

Recursive / Structural Chunking:
The middle ground for RAG. Since we converted our HTML to Markdown, we can leverage the structure. We split by Header 1 (#), then Header 2 (##), then paragraphs.

  • Benefit: This guarantees that a chunk respects the document's logical hierarchy. A "Configuration" section stays together; it doesn't bleed into "Installation".

A comparative visualization titled


5. The Embedding Layer: Production Considerations

Embedding is the compression of meaning into vectors. In a production pipeline, this is not a "set it and forget it" step.

5.1 Batching and Throughput

Embedding APIs (like OpenAI's text-embedding-3) or local models (like all-MiniLM-L6-v2) have significant latency.

  • Pattern: Implement a Micro-Batching architecture. Don't embed chunks one by one. Accumulate chunks into buffers (e.g., 100 chunks) and send them in a single API call / GPU inference pass. This dramatically reduces network overhead and maximizes GPU utilization.

5.2 Embedding Drift

This is a silent killer in long-running RAG systems. If OpenAI updates their embedding model, or if you switch from v2 to v3, your new vectors will live in a different latent space than your old vectors. Distance calculations between them will be mathematical nonsense.

  • Mitigation: Version your indices. index_v1_openai_ada, index_v2_cohere. Never mix vectors from different models in the same namespace.

6. Vector Storage & Retrieval Optimization

The Vector Database (Pinecone, Weaviate, Chroma) is where the rubber meets the road. However, "Similarity Search" (KNN/ANN) is rarely enough on its own.

6.1 The Power of Metadata Filtering

In high-scale systems, searching the entire vector space is inefficient and noisy.

  • Scenario: A user asks "How do I reset my password?" in the context of "Enterprise Application A".
  • Failure: The vector search retrieves password reset instructions for "Consumer Application B" because the semantic vectors are nearly identical.
  • Fix: Pre-filtering. During the scraping phase, you must extract metadata: product_id, version, category, last_updated.
  • Query: vector_search(query_embedding, filter={product_id: "Ent_App_A"}). This restricts the ANN search to a relevant subset, guaranteeing context awareness.

6.2 Hybrid Search (The "Keyword" Safety Net)

Vectors are great at concepts ("dog" matches "canine"), but terrible at exact matches (SKUs, error codes, acronyms).

  • Solution: Enable Hybrid Search. This combines dense vector search with sparse keyword search (BM25).
  • Why: If a user searches for error code ERR-9921, vector search might return generic error pages. BM25 will find the exact document containing that string. A weighted sum of these scores provides the most robust retrieval.

7. End-to-End Example: The Documentation Crawler

Let's imagine we are building a RAG system for a fast-changing developer documentation site.

  1. Orchestrator: An Airflow DAG triggers nightly.
  2. Scraper: Playwright visits the documentation root. It navigates the sitemap.
  3. Cleaner: BeautifulSoup removes the sidebar, the "Was this helpful?" widgets, and the footer.
  4. Converter: The clean HTML is converted to Markdown. Code blocks are specially tagged to ensure they aren't split mid-function.
  5. Chunker: We use a MarkdownSplitter. We keep headers attached to their child paragraphs so context isn't lost.
  6. Hasher: We generate a hash of the chunk's text content. We check our Vector DB to see if this hash already exists. Deduplication prevents re-indexing unchanged content, saving money and time.
  7. Embedder: New chunks are batched and embedded.
  8. Ingest: Vectors are pushed to Pinecone with metadata: url, title, date_scraped, hash.

8. Conclusion: Engineering Reliability

Building a demo RAG app takes an afternoon. Building a production RAG pipeline takes engineering discipline. The quality of your AI's answers is directly downstream of the quality of your data pipeline.

By focusing on high-fidelity scraping, semantic cleaning, intelligent chunking, and metadata-rich indexing, you move from a stochastic toy to a deterministic system. In the world of LLMs, Data Engineering is the new Prompt Engineering.

Top comments (0)