ai-docs-vector-db-hybrid-scraper
Health Pass
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 10 GitHub stars
Code Fail
- rm -rf — Recursive force deletion command in .github/actions/setup-environment/action.yml
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Retrieval-augmented docs ingestion stack: Firecrawl + Crawl4AI + Qdrant vector search with FastAPI and MCP interfaces for AI engineers.
AI Documentation Vector Database Hybrid Scraper
AI-focused documentation ingestion and retrieval stack that combines Firecrawl and
Crawl4AI powered scraping with a Qdrant vector database. The project exposes both
FastAPI and MCP interfaces, offers mode-aware configuration (solo developer vs
enterprise feature sets), and ships with tooling for embeddings, hybrid search,
retrieval-augmented generation (RAG) workflows, and operational monitoring.
Overview
The system ingests documentation sources, generates dense and sparse embeddings,
stores them in Qdrant, and serves hybrid search and RAG building blocks. It is
built for AI engineers who need reliable documentation ingestion pipelines,
reproducible retrieval quality, and integration points for agents or
applications.
Highlights
- Multi-tier crawling orchestration (
src/services/browser/unified_manager.py)
covering lightweight HTTP, Crawl4AI, browser-use, Playwright, and Firecrawl,
plus a resumable bulk embedder CLI (src/crawl4ai_bulk_embedder.py). - Hybrid retrieval stack leveraging OpenAI and LangChain FastEmbed dense
embeddings plus FastEmbedSparse BM25 signals, reranking, and HyDE augmentation
through the modular Qdrant
service (src/services/vector_db/andsrc/services/hyde/). - Dual interfaces: REST endpoints in FastAPI (
src/api/routers/v1/) and a
FastMCP server (src/unified_mcp_server.py) that registers search, document
management, analytics, and content intelligence tools for Claude Desktop /
Code. - Built-in API hardening with SlowAPI-powered global rate limiting configured
through theSecurityConfigmodel and middleware stack. - Observability built in: OpenTelemetry tracing, structured logging, health
checks, optional Dragonfly cache, and/metricsexposure viaprometheus-fastapi-instrumentator(src/services/observability/). - Developer ergonomics with uv-managed environments, dependency-injector driven
service wiring, Ruff + pytest quality gates, and a unified developer CLI
(scripts/dev.py).
Table of Contents
- Overview
- Highlights
- Architecture
- Core Components
- Quick Start
- Configuration
- Testing & Quality
- Documentation & Resources
- Contributing
- License
Architecture
flowchart LR
subgraph clients["Clients"]
mcp["Claude Desktop / MCP"]
rest["REST / CLI clients"]
end
subgraph mcp_server["FastMCP server"]
registry["Tool registry (register_all_tools)"]
end
subgraph api["FastAPI application"]
router["Mode-aware routers"]
factory["Service factory"]
end
subgraph processing["Processing layer"]
crawl["Unified crawling manager"]
embed["Embedding manager"]
search["Hybrid retrieval"]
end
subgraph data["Storage & caching"]
qdrant[("Qdrant vector DB")]
redis[("Redis / Dragonfly cache")]
storage["Local docs & artifacts"]
end
subgraph observability["Observability"]
metrics["Prometheus exporter"]
health["Health & diagnostics"]
end
mcp --> registry
registry --> processing
rest --> api
api --> processing
processing --> crawl
processing --> embed
processing --> search
crawl --> firecrawl["Firecrawl API"]
crawl --> crawl4ai["Crawl4AI"]
crawl --> browseruse["browser-use / Playwright"]
embed --> openai["OpenAI"]
embed --> fastembed["FastEmbed / optional FlagEmbedding"]
search --> qdrant
processing --> redis
api --> metrics
metrics --> observability
processing --> health
health --> observability
The FastMCP server now registers tool modules directly throughregister_all_tools. Dependencies are resolved once from the sharedApplicationContainer and provided to the tool registrars without an
intermediate services layer, keeping the runtime surface minimal and
maintainable.
The observability surface relies entirely on the OpenTelemetry and Prometheus
stack: FastAPI and MCP emit spans and metrics that flow into the collector,
with Grafana dashboards consuming those native feeds. No bespoke analytics
dashboards or visualization engines ship with the application.
Core Components
Infrastructure Orchestration
ApplicationContainer(src/infrastructure/container.py) is the single source
of truth for wiring clients (OpenAI, Qdrant, Redis, Firecrawl), caches, vector
storage, crawling, embeddings, monitoring, and RAG helpers. Runtime surfaces pull
dependencies from the container usingdependency-injectorproviders rather than
instantiating bespoke managers.src/infrastructure/bootstrap.pyexposesensure_containerandcontainer_sessionhelpers so FastAPI lifespans, the unified MCP server, CLI
utilities, and evaluation scripts share identical lifecycle management without
reimplementing startup/shutdown logic.- Service initialization is coordinated through container lifecycle hooks with
deterministic startup/shutdown ordering, ensuring shared resources (HTTP sessions,
vector stores, MCP sessions, monitoring tasks) are initialised once and cleaned up
safely.
Crawling & Ingestion
- AutomationRouter centralizes tier analysis while UnifiedBrowserManager delegates
multi-tier scraping and tracks quality metrics. - Firecrawl and Crawl4AI adapters plus browser-use / Playwright integrations cover static and dynamic sites.
src/crawl4ai_bulk_embedder.pystreams bulk ingestion, chunking, and embedding into Qdrant with resumable state and progress reporting.docs/users/web-scraping.mdanddocs/users/examples-and-recipes.mdinclude tier selection guidance and code samples.
LangChain splitter matrix & hybrid retrieval glue
The ingestion stack no longer ships bespoke "basic" or "enhanced" chunkers. Every
surface—FastAPI, MCP, CLI—calls the sharedsrc/services/document_chunking.chunk_to_documents helper, which orchestrates a
matrix of LangChain text splitters selected from document metadata:
- Markdown →
MarkdownHeaderTextSplitter+ recursive refinement for heading-aware
segments. - HTML →
HTMLSemanticPreservingSplitter(or header/section splitters when
semantic parsing is disabled) with optional whitespace normalisation. - Code →
RecursiveCharacterTextSplitter.from_languageseeded from inferred file
extensions or crawler metadata. - JSON →
RecursiveJsonSplitterfor structured payloads. - Token aware →
TokenTextSplitter.from_tiktoken_encoderfor strict token
budgets. - Plain text →
RecursiveCharacterTextSplitterusing newline/space fallbacks.
All variants share canonical chunk metadata (chunk_id, chunk_index, inferredkind, provenance fields) so downstream services never rely on bespoke schemas.
See the LangChain text splitter catalogue for implementation details.[^langchain-splitters]
Dense and sparse embeddings are sourced from the LangChain FastEmbed wrappers—FastEmbedEmbeddings for dense vectors and FastEmbedSparse for BM25-compatible
representations—allowing hybrid searches without vendor SDK drift.[^fastembed]VectorStoreService wires both outputs into LangChain's QdrantVectorStore, so
ingestion code and documentation examples share a single integration point.[^langchain-qdrant]
from langchain_community.embeddings import FastEmbedEmbeddings
from langchain_qdrant import FastEmbedSparse, QdrantVectorStore
from src.services.document_chunking import chunk_to_documents, infer_document_kind
from src.config.models import ChunkingConfig
config = ChunkingConfig(chunk_size=1600, chunk_overlap=200)
documents = chunk_to_documents(
raw_text,
metadata,
infer_document_kind(metadata, "text"),
config,
)
store = QdrantVectorStore.from_documents(
documents,
embedding=FastEmbedEmbeddings(model_name="BAAI/bge-small-en-v1.5"),
sparse_embeddings=FastEmbedSparse(model_name="qdrant/bm25"),
url="http://localhost:6333",
collection_name="documentation",
)
Toggle dense-only, sparse-only, or hybrid retrieval before startup withAI_DOCS_EMBEDDING__RETRIEVAL_MODE. Hybrid mode persists both vector modalities
and enables Qdrant's sparse+dense scoring during search.[^qdrant-hybrid]
Vector Search & Retrieval
src/services/vector_db/wraps collection management, hybrid search orchestration, adaptive fusion, and payload indexing.- Dense embeddings via OpenAI or FastEmbed, optional sparse vectors via SPLADE, and reranking hooks are configurable through Pydantic models (
src/config/models.py). - HyDE augmentation and caching live under
src/services/hyde/, enabling query expansion for RAG pipelines. - Search responses return timing, scoring metadata, and diagnostics suitable for observability dashboards.
Caching
- The unified
CacheManager(src/services/cache/manager.py) fronts the Dragonfly cache, hashing keys and enforcing TTL policies across embeddings, search, HyDE, and browser flows. - Specialized helpers such as the HyDE cache depend on
CacheManager, ensuring a single entry point for embeddings, search results, and warm-up flows. - Configure Dragonfly URLs and TTLs via the cache models in
src/config/models.py; the manager automatically wires Prometheus metrics when enabled.
Interfaces & Tooling
- FastAPI routes (
/api/v1/search,/api/v1/documents,/api/v1/collections) expose the core ingestion and retrieval capabilities. - The FastMCP server (
src/unified_mcp_server.py) registers search, document, embedding, scraping, analytics, cache, and content intelligence tool modules (src/mcp_tools/).
MCP tooling now expects dependencies to be supplied explicitly—services resolve
once from the dependency-injector container during startup and are passed into
the toolregister_tools()functions rather than through intermediate
service wrappers. - Developer CLI (
scripts/dev.py) manages services, testing profiles, benchmarks, linting, and type checking. - Example notebooks and scripts under
examples/demonstrate agentic RAG flows and advanced search orchestration.
Observability & Operations
/metricsendpoints are exposed throughprometheus-fastapi-instrumentator, while OpenTelemetry spans capture
embedding, cache, database, and RAG pipeline telemetry; the database
manager emitsdb.query.durationhistograms for each session. All
analytics are powered by these native observability feeds instead of
custom dashboards. Seedocs/observability/embeddings_telemetry.mdanddocs/operators/monitoring.mdfor configuration details.- Health probes for system resources, Qdrant, Redis, RAG configuration, and application metadata are centrally coordinated by the
HealthCheckManager(src/services/observability/health_manager.py), ensuring MCP tools and FastAPI dependencies share the same health state. - A single
GET /healthendpoint on the FastAPI and FastMCP servers reports the aggregated system status; per-service health endpoints have been removed. - Optional Dragonfly cache, PostgreSQL, Prometheus, and Grafana services are provisioned via
docker-compose.ymlprofiles. - Structured logging and SlowAPI-based rate limiting are configured through the middleware manager (
src/services/fastapi/middleware/manager.py) and security helpers (src/services/fastapi/middleware/security.py).
AI Telemetry Quickstart
- Enable OTLP export (set in
.envor deployment secrets):export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <token>" - Run an OpenTelemetry Collector that forwards spans/metrics to your backend:
receivers: otlp: protocols: grpc: http: processors: batch: {} exporters: prometheus: endpoint: "0.0.0.0:9464" otlp: endpoint: "https://observability.example.com:4317" headers: authorization: "Bearer ${OBSERVABILITY_API_TOKEN}" service: pipelines: metrics: receivers: [otlp] processors: [batch] exporters: [prometheus, otlp] traces: receivers: [otlp] processors: [batch] exporters: [otlp] - Scrape
/metricswith Prometheus (the collector exposes the OTLP pipeline
to Prometheus in the example above). Helpful PromQL snippets:sum by (model) (rate(ai_operation_tokens{operation="embedding"}[5m])) sum by (operation) (increase(ai_operation_cost[1h])) histogram_quantile( 0.95, sum by (le) (rate(ai_operation_duration_bucket{operation="embedding"}[5m])) ) - Trace dashboards can group spans with
gen_ai.operation.name,gen_ai.request.model, andgen_ai.usage.*attributes to visualize
synchronous embeds versus asynchronous batch jobs.
Security & Validation
src/security/ml_security.pyprovides the consolidatedMLSecurityValidatorfor URL, query, and filename validation alongside dependency and container scanning hooks.- FastAPI and MCP flows use the shared validator via dependency helpers, ensuring a single source of truth for sanitization and auditing logic.
- Rate limiting defaults (
default_rate_limit,rate_limit_window, optional Redis storage) are controlled throughSecurityConfigand applied via the global SlowAPI limiter.
Run locally
Prerequisites
- Python 3.11 and uv for dependency management.
- A running Qdrant instance (local Docker welcome:
docker compose --profile simple up -d qdrant). - API keys only for providers you enable.
Environment variables
| Variable | Purpose | Example |
|---|---|---|
AI_DOCS_QDRANT__URL |
Points services at your Qdrant instance. | http://localhost:6333 |
AI_DOCS_OPENAI__API_KEY |
Enables OpenAI embeddings and HyDE prompts. | your_openai_api_key_here |
AI_DOCS_BROWSER__FIRECRAWL__API_KEY |
Authenticates Firecrawl API usage. | your_firecrawl_api_key_here |
AI_DOCS_CACHE__DRAGONFLY_URL |
Points distributed caching at Dragonfly. | redis://localhost:6379 |
FASTMCP_TRANSPORT |
Chooses MCP transport (streamable-http or stdio). |
streamable-http |
FASTMCP_HOST / FASTMCP_PORT |
Hostname and port for MCP HTTP transport. | 127.0.0.1 / 8000 |
Store secrets in a .env file or your secrets manager and export them before
running the services.
Clone and install
git clone https://github.com/BjornMelin/ai-docs-vector-db-hybrid-scraper
cd ai-docs-vector-db-hybrid-scraper
uv sync --dev --frozen
The runtime image excludes Crawl4AI's transformer stack, BGE reranking, and the
agent-driven browser stack. The development group already includes browser-use
for adapter contract tests. Install the optional BGE reranker only when enabled:
uv sync --dev --frozen --extra reranking
Set AI_DOCS_RERANKING__ENABLED=true after installing the reranking extra.
For a non-development installation that enables the browser_use provider, useuv sync --frozen --no-dev --extra agentic-browser.
Run the FastAPI application
docker compose --profile simple up -d qdrant
uv run uvicorn src.api.main:app --host 127.0.0.1 --port 8000
Visit http://localhost:8000/docs for interactive OpenAPI docs.
Search API payloads
All search endpoints accept the canonical SearchRequest body. Minimal example:
{
"query": "vector databases",
"limit": 5
}
Responses are emitted as SearchResponse payloads containing canonical SearchRecord entries. Example response payload:
{
"query": "vector databases",
"total_results": 2,
"processing_time_ms": 12.4,
"records": [
{
"id": "doc-1",
"content": "Install Qdrant with Docker...",
"score": 0.91,
"collection": "documentation"
},
{
"id": "doc-2",
"content": "Manage hybrid sparse+dense search pipelines...",
"score": 0.88,
"collection": "documentation"
}
]
}
Run the MCP server
FASTMCP_TRANSPORT=streamable-http FASTMCP_PORT=8001 \
uv run python src/unified_mcp_server.py
The server validates configuration on startup and registers the available MCP tools at http://127.0.0.1:8001/mcp. The checked-in Claude Desktop configuration uses stdio instead:
- Copy
config/claude-mcp-config.example.jsonto your Claude settings directory
and update thecommandfield if you use a virtual environment wrapper. - Replace its
cwdvalue with the absolute repository path. - Add canonical
AI_DOCS_*provider settings only when you enable those providers. - Restart Claude Desktop / Code so it reloads the MCP manifest and tool list.
Bulk ingestion CLI
uv run python -m src.crawl4ai_bulk_embedder --help
Use CSV/JSON/TXT URL lists to scrape, chunk, embed, and upsert into Qdrant with resumable checkpoints.
Docker Compose
- Simple profile (API + Qdrant):
docker compose --profile simple up -d - Enterprise profile (adds Dragonfly, PostgreSQL, Prometheus, and Grafana):
docker compose --profile enterprise up -d
Stop with docker compose down when finished.
Configuration
- Configuration is defined with Pydantic models in
src/config/models.py; explicit constructor values and environment variables override.env, activatedconfig.json, and model defaults in that order. - Typed settings control providers, retrieval, caching, and observability.
- Detailed configuration guidance lives in
docs/developers/setup-and-configuration.mdand operator runbooks underdocs/operators/.
Testing & Quality
# Unit and focused integration tests
uv run python scripts/dev.py test --profile quick
# Full suite with coverage (mirrors CI)
uv run python scripts/dev.py test --profile ci
# Format, lint, and type-check
uv run python scripts/dev.py quality
Performance and benchmark suites are available via uv run python scripts/dev.py benchmark, load tests run through uv run python scripts/dev.py load --host http://localhost:8000, and chaos-focused stress suites live under tests/ with dedicated markers.
Documentation & Resources
- User guides:
docs/users/(quick start, search, scraping recipes, troubleshooting). - Developer deep dives:
docs/developers/(API reference, integration, architecture). - Operator handbook:
docs/operators/(deployment, monitoring, security). - Research notes and experiments:
docs/research/.
Publishable MkDocs output is generated under site/ when running the documentation pipeline.
Contributing
Contributions are welcome. Read the CONTRIBUTING.md guide for
development workflow, coding standards, and review expectations. Please include
tests and documentation updates with feature changes. If this stack accelerates
your RAG pipelines, consider starring the repository so other developers can
discover it.
License
Released under the MIT License.
[^langchain-splitters]: LangChain text splitter reference – https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/
[^fastembed]: FastEmbed dense and sparse configuration guide – https://qdrant.tech/documentation/fastembed/
[^langchain-qdrant]: LangChain Qdrant vector store integration – https://python.langchain.com/docs/integrations/vectorstores/qdrant/
[^qdrant-hybrid]: Qdrant hybrid sparse+dense search overview – https://qdrant.tech/articles/hybrid-search/
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found