Spaces:
Paused
Paused
Commit Β·
a68f370
1
Parent(s): 46f30db
Deploy QueryLens (Gradio-SDK launcher: worker :8700 / MCP :8701 / web :7860)
Browse files
README.md
CHANGED
|
@@ -1,16 +1,22 @@
|
|
| 1 |
---
|
| 2 |
-
title: QueryLens V2
|
| 3 |
-
emoji: π
|
| 4 |
-
colorFrom: blue
|
| 5 |
-
colorTo: indigo
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
pinned: false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
|
| 13 |
-
#
|
| 14 |
Multi-Agent System
|
| 15 |
|
| 16 |

|
|
@@ -26,16 +32,16 @@ By leveraging the Model Context Protocol (MCP), local LLMs via Ollama, and intel
|
|
| 26 |
|
| 27 |
## Key Features
|
| 28 |
|
| 29 |
-
- **Multi-Agent Orchestration:** A dynamic routing system featuring specialized agents
|
| 30 |
-
- **Dynamic Database Profiles:** Connect any database by connection string, or upload a `.sqlite`/`.db`/`.csv` file directly from the UI. Profiles are registered, switchable, and deletable at runtime via the `Database` panel or the `/api/schemas` REST surface
|
| 31 |
- **Schema-Aware Generic Agents:** The agent pipeline reads a live introspected schema profile (tables, columns, PK/FK, row counts, sample rows) instead of assuming a fixed schema. The fourteen employee-specific `fast_sql` templates activate only when the employee demo is the active profile; every other database gets generic `schema.list_tables / schema.describe_table / schema.sample_data / sql.build_select` MCP tools and profile-aware prompts, validators, and reducers.
|
| 32 |
-
- **Interactive Charts:** Query results that visualize well (category breakdowns, comparisons, time series) are detected automatically and rendered as ECharts visualizations
|
| 33 |
- **Modern Sepia UI:** A Claude-inspired coffee/sepia interface with serif headings and a warm terracotta accent, wrapping the multi-agent trace panels (Memory / QueryCraft / ResultPresenter), live schema browsing, and charting.
|
| 34 |
-
- **Vision-Language Question Answering:** VQA/OCR extraction from invoices and unstructured documents. Served locally via Ollama (`qwen2-vl:2b`) or
|
| 35 |
- **Three-Level Text-to-SQL Engine:** Translates natural language questions into syntactically valid SQL through a progressive reasoning architecture, with automatic self-correction at each escalation level.
|
| 36 |
- **Semantic Gatekeeping:** A multi-layer validation pipeline filters hallucinated SQL, undefined aliases, missing joins, and incorrect aggregation patterns before any query reaches the database.
|
| 37 |
- **Dynamic VRAM Orchestration:** Custom memory management algorithms automatically load and unload models from GPU VRAM to prevent out-of-memory crashes, enabling concurrent AI workloads on consumer hardware.
|
| 38 |
-
- **Unified MCP Integration:** All external data sources
|
| 39 |
- **Database Agnostic Design:** Architected to interface with PostgreSQL, MySQL, SQLite, MS SQL Server, and Oracle via SQLAlchemy.
|
| 40 |
- **Conversational Interface:** A full Web UI supporting natural language interaction with persistent session context.
|
| 41 |
|
|
@@ -60,7 +66,7 @@ Profiles persist in `chat_store/schema_profiles.json` and survive restarts; uplo
|
|
| 60 |
|
| 61 |
### Chart contract
|
| 62 |
|
| 63 |
-
When a query returns rows that visualize well, the ResultPresenter embeds a chart spec (pie/bar/line, labels + numeric series) that the worker exposes as `{"chart": {...}}` alongside the text `answer`. Selection heuristics: date-like first column + numeric series
|
| 64 |
|
| 65 |
### Working against the demo employee database
|
| 66 |
|
|
@@ -78,15 +84,15 @@ The project employs a decoupled, asynchronous microservices architecture. The We
|
|
| 78 |
|
| 79 |
The MemoryAgent acts as the entry point for all user queries. It performs three functions before any SQL generation occurs: checking whether the current query can be satisfied from historical conversation context, rephrasing ambiguous or under-specified queries based on prior interactions, and routing validated new queries to the appropriate downstream agent. This layer prevents redundant computation and improves response latency for repeated or related questions.
|
| 80 |
|
| 81 |
-
**2. QueryCraftAgent
|
| 82 |
|
| 83 |
The QueryCraftAgent is the core reasoning engine of the system. It implements a progressive escalation architecture that balances inference speed with accuracy:
|
| 84 |
|
| 85 |
-
- **Level 1
|
| 86 |
|
| 87 |
-
- **Level 2
|
| 88 |
|
| 89 |
-
- **Level 3
|
| 90 |
|
| 91 |
**3. ResultPresenterAgent**
|
| 92 |
|
|
@@ -101,7 +107,7 @@ graph TD
|
|
| 101 |
Web -->|Image Upload| Worker["Backend Worker\nPort 8700"]
|
| 102 |
Web -->|Text Query| Worker
|
| 103 |
|
| 104 |
-
subgraph MCP["MCP Tool Server
|
| 105 |
DocScan["document_scanner.process\nTesseract OCR"]
|
| 106 |
FastSQL["fast_sql tools\nSchema-Grounded SQL Generation"]
|
| 107 |
VisionQA["granite_vision.qa\nQwen 3.5 2B Vision"]
|
|
@@ -142,7 +148,7 @@ The system is implemented as a Dockerized microservices architecture, with each
|
|
| 142 |
|
| 143 |
For peak inference performance, the system uses a hybrid offloading strategy. The application logic and MCP servers run inside Docker containers for portability and isolation, while Ollama and all GPU inference are offloaded to the native Windows host and accessed by the containers over the WSL2 host bridge network (`OLLAMA_BASE_URL=http://<wsl2-host-ip>:11434`).
|
| 144 |
|
| 145 |
-
This architecture eliminates the virtualization overhead introduced by Docker Desktop's Linux VM layer. By giving the inference engine direct access to NVIDIA CUDA cores and the full system memory pool
|
| 146 |
|
| 147 |
### Database Health and Startup Reliability
|
| 148 |
|
|
@@ -162,13 +168,13 @@ The Model Context Protocol server runs as a dedicated microservice on port 8701.
|
|
| 162 |
|
| 163 |
## Unified Multimodal Integration via MCP
|
| 164 |
|
| 165 |
-
A defining architectural feature of this system is that OCR and multimodal reasoning are integrated through the same Model Context Protocol used for database access. The Qwen 3.5 2B Vision model is registered as a named MCP tool: `granite_vision.qa`. This internal tool identifier was retained from the original design specification; the underlying engine was subsequently replaced with Qwen 3.5 2B Vision, which demonstrated superior OCR accuracy and a smaller VRAM footprint. Because the tool interface is decoupled from its implementation, this substitution required no changes to the agent orchestration code
|
| 166 |
|
| 167 |
This design delivers three concrete engineering properties:
|
| 168 |
|
| 169 |
**Uniform Protocol:** The orchestrator issues identical-format tool calls regardless of whether the data source is a SQL table or a visual document. There are no special-case code paths for different modalities.
|
| 170 |
|
| 171 |
-
**Modular Replaceability:** The vision model is encapsulated behind its MCP interface. Upgrading to a different vision model
|
| 172 |
|
| 173 |
**Cross-Modal Reasoning Capability:** Because both data sources share the same protocol, the agent can compose multi-step reasoning across modalities. For example, the system can extract a value from a document via the vision tool and immediately verify it against a database record via the SQL tool, within a single agentic workflow.
|
| 174 |
|
|
@@ -276,24 +282,24 @@ GROQ_API_KEY=gsk_xxx
|
|
| 276 |
GROQ_VISION_MODEL=qwen/qwen3.8-27b
|
| 277 |
```
|
| 278 |
|
| 279 |
-
**Local Ollama (optional):** with `USE_HF_CLOUD=0`, the configured Ollama model is used
|
| 280 |
|
| 281 |
### 3. Run Without Docker
|
| 282 |
|
| 283 |
Start each microservice in a separate terminal:
|
| 284 |
|
| 285 |
```bash
|
| 286 |
-
# Terminal 1
|
| 287 |
python -u -m uvicorn "Agent.worker:app" --port 8700
|
| 288 |
|
| 289 |
-
# Terminal 2
|
| 290 |
python -m uvicorn "Agent.mcp_server:app" --port 8701
|
| 291 |
|
| 292 |
-
# Terminal 3
|
| 293 |
python -m uvicorn "web.app:app" --port 8000
|
| 294 |
```
|
| 295 |
|
| 296 |
-
Navigate to `http://localhost:8000` to interact with the system. Use the **Database** panel to connect your own database (connection URL or `.sqlite`/`.csv` upload)
|
| 297 |
|
| 298 |
### 4. Run With Docker
|
| 299 |
|
|
@@ -313,17 +319,17 @@ The database containers include health checks and will be fully initialized befo
|
|
| 313 |
|
| 314 |
The app is fully cloud-based (`USE_HF_CLOUD=1`): Text-to-SQL runs on HF Inference
|
| 315 |
(`Qwen/Qwen2.5-Coder-7B-Instruct`), VQA on Groq (`qwen/qwen3.8-27b`), and the
|
| 316 |
-
built-in `demo_employee` SQLite profile ships with the repo
|
| 317 |
service is needed on Spaces.
|
| 318 |
|
| 319 |
> **Note:** HF Spaces moved the **Docker SDK to a paid tier** (free CPU 2026).
|
| 320 |
-
> Deploy there with the free **Gradio SDK** instead
|
| 321 |
> spawns the same three services the Docker image ran (worker `:8700`,
|
| 322 |
> MCP `:8701`, sepia web UI `:7860`) and mounts a minimal Gradio anchor page at
|
| 323 |
> `/gradio-lp`. The UI at `/` is unchanged.
|
| 324 |
|
| 325 |
-
1. **Create the Space**
|
| 326 |
-
blank template
|
| 327 |
2. **Push the project files** into the Space repo. Easiest on Windows is the
|
| 328 |
bundled helper:
|
| 329 |
```powershell
|
|
@@ -333,29 +339,29 @@ service is needed on Spaces.
|
|
| 333 |
(respecting the exclusions: no `.env`, no `chat_store/`, no 350 MB
|
| 334 |
`dataset_full` dumps, no `__pycache__`), merges the HF frontmatter into the
|
| 335 |
Space `README.md` (keeping the generated `sdk_version`), commits and pushes.
|
| 336 |
-
3. **Add Secrets** (Space settings
|
| 337 |
| Secret | Purpose |
|
| 338 |
|---|---|
|
| 339 |
-
| `HF_API_TOKEN` | HF Inference API
|
| 340 |
| `GROQ_API_KEY` | Groq vision VQA (`qwen/qwen3.8-27b`, free tier) |
|
| 341 |
-
No `DB_CONNECTION_URL` is required
|
| 342 |
Optional: set `DB_CONNECTION_URL` to a hosted Postgres (e.g. Neon) for a real
|
| 343 |
external database.
|
| 344 |
-
4. **Open the Space**
|
| 345 |
The **Database** panel lets you register additional databases (hosted
|
| 346 |
Postgres/MySQL URLs, or uploaded `.sqlite`/`.csv` files) at runtime.
|
| 347 |
|
| 348 |
**Local Docker runs still work** for your own machine: `docker build` +
|
| 349 |
`docker-compose.yml` are unchanged and `start_hf.sh` serves the identical
|
| 350 |
-
stack
|
| 351 |
|
| 352 |
-
Note: free Spaces sleep after inactivity (cold start ~
|
| 353 |
files and chat history are ephemeral unless you enable *Persistent Storage* in
|
| 354 |
the Space settings.
|
| 355 |
|
| 356 |
### Historical deployment journey (reference)
|
| 357 |
|
| 358 |
-
This section documents the **complete deployment journey**
|
| 359 |
|
| 360 |
---
|
| 361 |
|
|
@@ -372,11 +378,11 @@ Before choosing a deployment strategy, it is essential to understand what the fr
|
|
| 372 |
| Public port | 7860 only |
|
| 373 |
| Timeout | Space sleeps after inactivity |
|
| 374 |
|
| 375 |
-
The key challenge: **running a local LLM (e.g. `qwen2.5-coder:1.5b`) via Ollama consumes ~1.
|
| 376 |
|
| 377 |
---
|
| 378 |
|
| 379 |
-
### Phase 1
|
| 380 |
|
| 381 |
#### Theory
|
| 382 |
|
|
@@ -428,13 +434,13 @@ The application code reads `OLLAMA_BASE_URL` and routes all inference calls thro
|
|
| 428 |
|
| 429 |
---
|
| 430 |
|
| 431 |
-
### Phase 2
|
| 432 |
|
| 433 |
#### Theory
|
| 434 |
|
| 435 |
-
The next evolution is to **embed Ollama directly into the Docker image** and pull models at container startup. This makes the deployment fully self-contained
|
| 436 |
|
| 437 |
-
The challenge is that HF Spaces rebuilds the Docker image on every push but does **not cache downloaded model weights** between restarts (storage is ephemeral). This means every **Factory Reboot** triggers a fresh ~
|
| 438 |
|
| 439 |
To prevent HF's health monitor from timing out the Space during this download, model pulling is performed **asynchronously in the background**, allowing the web UI to become responsive immediately while the model fetches in parallel.
|
| 440 |
|
|
@@ -491,11 +497,11 @@ The `&` (ampersand) operator sends the model pull to the background. The `exec`
|
|
| 491 |
|
| 492 |
- **Vision model OOM**: Adding `qwen3.5:2b` alongside `qwen2.5-coder:1.5b` exceeds the 16 GB RAM limit when both are loaded simultaneously.
|
| 493 |
- Model weights are re-downloaded on every Factory Reboot.
|
| 494 |
-
- Ollama version pinning is critical
|
| 495 |
|
| 496 |
---
|
| 497 |
|
| 498 |
-
### Phase 3
|
| 499 |
|
| 500 |
#### Theory
|
| 501 |
|
|
@@ -505,8 +511,8 @@ The final and most robust architecture eliminates the in-container LLM entirely
|
|
| 505 |
|------|----------|-------|------|
|
| 506 |
| Text-to-SQL | HuggingFace Inference API | `Qwen/Qwen2.5-Coder-7B-Instruct` | Free tier |
|
| 507 |
| Vision Q&A | Groq API | `meta-llama/llama-4-scout-17b-16e-instruct` | Free (14,400 req/day) |
|
| 508 |
-
| OCR | Tesseract (in container) |
|
| 509 |
-
| Database | Neon PostgreSQL |
|
| 510 |
|
| 511 |
This eliminates OOM risk entirely, removes the model download cold-start, and makes the container startup under 30 seconds.
|
| 512 |
|
|
@@ -520,7 +526,7 @@ HuggingFace's serverless inference for vision-language models has two limitation
|
|
| 520 |
|
| 521 |
#### Required HuggingFace Space Secrets
|
| 522 |
|
| 523 |
-
Set these in **Space Settings
|
| 524 |
|
| 525 |
```
|
| 526 |
USE_HF_CLOUD = 1
|
|
@@ -538,7 +544,7 @@ DB_CONNECTION_URL = # Neon PostgreSQL connection string
|
|
| 538 |
**Groq API Key:**
|
| 539 |
1. Go to https://console.groq.com
|
| 540 |
2. Sign in with Google / GitHub
|
| 541 |
-
3. Navigate to **API Keys**
|
| 542 |
4. Copy the key
|
| 543 |
|
| 544 |
**Neon PostgreSQL:**
|
|
@@ -600,7 +606,7 @@ pillow>=10.0.0
|
|
| 600 |
|
| 601 |
4. **Factory Reboot** the Space after adding secrets to trigger a clean rebuild with the new environment variables.
|
| 602 |
|
| 603 |
-
5. **Monitor the build logs**
|
| 604 |
```
|
| 605 |
[GRANITE_VQA] Target Model: meta-llama/llama-4-scout-17b-16e-instruct (via Groq Vision)
|
| 606 |
[INFO] CLOUD MODE: Initializing Official HF InferenceClient (Qwen/Qwen2.5-Coder-7B-Instruct)
|
|
@@ -627,7 +633,7 @@ git config core.autocrlf input
|
|
| 627 |
|
| 628 |
This project demonstrates that a self-correcting, multi-modal AI pipeline can be built and deployed entirely on consumer hardware through careful architectural decisions: progressive SQL generation with semantic validation, unified MCP-based tool access across data modalities, dynamic VRAM orchestration to prevent memory exhaustion, and a hybrid containerization strategy that preserves native GPU performance while maintaining deployment portability.
|
| 629 |
|
| 630 |
-
The system was developed iteratively, with each architectural decision
|
| 631 |
|
| 632 |
---
|
| 633 |
-
*Built with
|
|
|
|
| 1 |
---
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
sdk: gradio
|
| 3 |
+
sdk_version: 6.30.0
|
| 4 |
+
python_version: 3.11
|
| 5 |
+
title: QueryLens Text2SQL-DocVQA
|
| 6 |
+
emoji: π€
|
| 7 |
+
colorFrom: amber
|
| 8 |
+
colorTo: orange
|
| 9 |
pinned: false
|
| 10 |
+
- agents
|
| 11 |
+
- mcp
|
| 12 |
+
app_file: app.py
|
| 13 |
+
tags:
|
| 14 |
+
- agents
|
| 15 |
+
- mcp
|
| 16 |
---
|
| 17 |
|
| 18 |
|
| 19 |
+
# Agentic Text2SQL & Document VQA
|
| 20 |
Multi-Agent System
|
| 21 |
|
| 22 |

|
|
|
|
| 32 |
|
| 33 |
## Key Features
|
| 34 |
|
| 35 |
+
- **Multi-Agent Orchestration:** A dynamic routing system featuring specialized agents β MemoryAgent, QueryCraftAgent, and ResultPresenterAgent β each with a clearly defined role in the pipeline.
|
| 36 |
+
- **Dynamic Database Profiles:** Connect any database by connection string, or upload a `.sqlite`/`.db`/`.csv` file directly from the UI. Profiles are registered, switchable, and deletable at runtime via the `Database` panel or the `/api/schemas` REST surface β the built-in employee sample DB ships as one profile (`demo_employee`) among many.
|
| 37 |
- **Schema-Aware Generic Agents:** The agent pipeline reads a live introspected schema profile (tables, columns, PK/FK, row counts, sample rows) instead of assuming a fixed schema. The fourteen employee-specific `fast_sql` templates activate only when the employee demo is the active profile; every other database gets generic `schema.list_tables / schema.describe_table / schema.sample_data / sql.build_select` MCP tools and profile-aware prompts, validators, and reducers.
|
| 38 |
+
- **Interactive Charts:** Query results that visualize well (category breakdowns, comparisons, time series) are detected automatically and rendered as ECharts visualizations β pie, bar, or line β in a sepia-toned palette. Chart specs ride in the query response as a first-class `chart` field; detection is conservative and never corrupts a textual answer.
|
| 39 |
- **Modern Sepia UI:** A Claude-inspired coffee/sepia interface with serif headings and a warm terracotta accent, wrapping the multi-agent trace panels (Memory / QueryCraft / ResultPresenter), live schema browsing, and charting.
|
| 40 |
+
- **Vision-Language Question Answering:** VQA/OCR extraction from invoices and unstructured documents. Served locally via Ollama (`qwen2-vl:2b`) or β in cloud mode β through Groq's `qwen/qwen3.8-27b` vision model (free tier).
|
| 41 |
- **Three-Level Text-to-SQL Engine:** Translates natural language questions into syntactically valid SQL through a progressive reasoning architecture, with automatic self-correction at each escalation level.
|
| 42 |
- **Semantic Gatekeeping:** A multi-layer validation pipeline filters hallucinated SQL, undefined aliases, missing joins, and incorrect aggregation patterns before any query reaches the database.
|
| 43 |
- **Dynamic VRAM Orchestration:** Custom memory management algorithms automatically load and unload models from GPU VRAM to prevent out-of-memory crashes, enabling concurrent AI workloads on consumer hardware.
|
| 44 |
+
- **Unified MCP Integration:** All external data sources β relational databases and vision models alike β are accessed through a single, uniform Model Context Protocol interface.
|
| 45 |
- **Database Agnostic Design:** Architected to interface with PostgreSQL, MySQL, SQLite, MS SQL Server, and Oracle via SQLAlchemy.
|
| 46 |
- **Conversational Interface:** A full Web UI supporting natural language interaction with persistent session context.
|
| 47 |
|
|
|
|
| 66 |
|
| 67 |
### Chart contract
|
| 68 |
|
| 69 |
+
When a query returns rows that visualize well, the ResultPresenter embeds a chart spec (pie/bar/line, labels + numeric series) that the worker exposes as `{"chart": {...}}` alongside the text `answer`. Selection heuristics: date-like first column + numeric series β line; β€8 categories with a single numeric series β pie; otherwise bar. Detection caps at 60 points and never mutates the answer text.
|
| 70 |
|
| 71 |
### Working against the demo employee database
|
| 72 |
|
|
|
|
| 84 |
|
| 85 |
The MemoryAgent acts as the entry point for all user queries. It performs three functions before any SQL generation occurs: checking whether the current query can be satisfied from historical conversation context, rephrasing ambiguous or under-specified queries based on prior interactions, and routing validated new queries to the appropriate downstream agent. This layer prevents redundant computation and improves response latency for repeated or related questions.
|
| 86 |
|
| 87 |
+
**2. QueryCraftAgent β The Three-Level Text-to-SQL Engine**
|
| 88 |
|
| 89 |
The QueryCraftAgent is the core reasoning engine of the system. It implements a progressive escalation architecture that balances inference speed with accuracy:
|
| 90 |
|
| 91 |
+
- **Level 1 β Pure LLM Intelligence:** Zero-shot semantic translation of natural language to SQL using Qwen 2.5 Coder. The generated query passes through a semantic validation pipeline that checks alias correctness, required table joins, aggregation integrity, and department or entity filters before being accepted.
|
| 92 |
|
| 93 |
+
- **Level 2 β LLM with SQL Fixer:** When Level 1 fails validation, the agent enters an autonomous self-correction loop. The SQL Fixer applies a deterministic set of targeted transformations β normalizing aliases, injecting missing to_date filters, repairing phantom column references, and enforcing PostgreSQL-compliant GROUP BY clauses β before re-validating the output.
|
| 94 |
|
| 95 |
+
- **Level 3 β LLM with MCP Schema-Grounded SQL Generation:** The deepest reasoning level, reserved for queries that fail both prior levels. For the built-in employee demo, the agent calls one of fourteen registered `fast_sql` MCP tools, each of which queries the live database schema via SQLAlchemy's inspector to retrieve actual column names and table structures, then programmatically constructs a valid SQL template grounded in the real schema. For any user-registered database, the agent instead grounds itself through the generic `schema.list_tables` / `schema.describe_table` / `schema.sample_data` MCP tools, producing a verified live-schema + sample-data hint that applies to any database. In both cases the template is passed as a verified hint to the LLM, which refines it before the Fixer loop runs. Because the hint is built from the actual schema rather than the LLM's training data, this level eliminates the class of failures caused by hallucinated column names or missing joins.
|
| 96 |
|
| 97 |
**3. ResultPresenterAgent**
|
| 98 |
|
|
|
|
| 107 |
Web -->|Image Upload| Worker["Backend Worker\nPort 8700"]
|
| 108 |
Web -->|Text Query| Worker
|
| 109 |
|
| 110 |
+
subgraph MCP["MCP Tool Server β Port 8701"]
|
| 111 |
DocScan["document_scanner.process\nTesseract OCR"]
|
| 112 |
FastSQL["fast_sql tools\nSchema-Grounded SQL Generation"]
|
| 113 |
VisionQA["granite_vision.qa\nQwen 3.5 2B Vision"]
|
|
|
|
| 148 |
|
| 149 |
For peak inference performance, the system uses a hybrid offloading strategy. The application logic and MCP servers run inside Docker containers for portability and isolation, while Ollama and all GPU inference are offloaded to the native Windows host and accessed by the containers over the WSL2 host bridge network (`OLLAMA_BASE_URL=http://<wsl2-host-ip>:11434`).
|
| 150 |
|
| 151 |
+
This architecture eliminates the virtualization overhead introduced by Docker Desktop's Linux VM layer. By giving the inference engine direct access to NVIDIA CUDA cores and the full system memory pool β rather than a virtualized slice β the 1.5B parameter model achieves response times measured in seconds rather than minutes. The separation also means that GPU memory pressure from Ollama does not compete with the container's allocated memory ceiling.
|
| 152 |
|
| 153 |
### Database Health and Startup Reliability
|
| 154 |
|
|
|
|
| 168 |
|
| 169 |
## Unified Multimodal Integration via MCP
|
| 170 |
|
| 171 |
+
A defining architectural feature of this system is that OCR and multimodal reasoning are integrated through the same Model Context Protocol used for database access. The Qwen 3.5 2B Vision model is registered as a named MCP tool: `granite_vision.qa`. This internal tool identifier was retained from the original design specification; the underlying engine was subsequently replaced with Qwen 3.5 2B Vision, which demonstrated superior OCR accuracy and a smaller VRAM footprint. Because the tool interface is decoupled from its implementation, this substitution required no changes to the agent orchestration code β only the MCP tool registration was updated.
|
| 172 |
|
| 173 |
This design delivers three concrete engineering properties:
|
| 174 |
|
| 175 |
**Uniform Protocol:** The orchestrator issues identical-format tool calls regardless of whether the data source is a SQL table or a visual document. There are no special-case code paths for different modalities.
|
| 176 |
|
| 177 |
+
**Modular Replaceability:** The vision model is encapsulated behind its MCP interface. Upgrading to a different vision model β such as a GPT-4V endpoint β requires updating only the tool registration, not any agent logic.
|
| 178 |
|
| 179 |
**Cross-Modal Reasoning Capability:** Because both data sources share the same protocol, the agent can compose multi-step reasoning across modalities. For example, the system can extract a value from a document via the vision tool and immediately verify it against a database record via the SQL tool, within a single agentic workflow.
|
| 180 |
|
|
|
|
| 282 |
GROQ_VISION_MODEL=qwen/qwen3.8-27b
|
| 283 |
```
|
| 284 |
|
| 285 |
+
**Local Ollama (optional):** with `USE_HF_CLOUD=0`, the configured Ollama model is used β and if it is not installed while `HF_API_TOKEN` is present, the worker **auto-falls back** to HF Inference (`HF_LLM_MODEL`) instead of failing with 404 handshakes.
|
| 286 |
|
| 287 |
### 3. Run Without Docker
|
| 288 |
|
| 289 |
Start each microservice in a separate terminal:
|
| 290 |
|
| 291 |
```bash
|
| 292 |
+
# Terminal 1 β Backend Worker
|
| 293 |
python -u -m uvicorn "Agent.worker:app" --port 8700
|
| 294 |
|
| 295 |
+
# Terminal 2 β MCP Tool Server
|
| 296 |
python -m uvicorn "Agent.mcp_server:app" --port 8701
|
| 297 |
|
| 298 |
+
# Terminal 3 β Web UI
|
| 299 |
python -m uvicorn "web.app:app" --port 8000
|
| 300 |
```
|
| 301 |
|
| 302 |
+
Navigate to `http://localhost:8000` to interact with the system. Use the **Database** panel to connect your own database (connection URL or `.sqlite`/`.csv` upload) β the built-in employee sample is provided as a container-backed profile.
|
| 303 |
|
| 304 |
### 4. Run With Docker
|
| 305 |
|
|
|
|
| 319 |
|
| 320 |
The app is fully cloud-based (`USE_HF_CLOUD=1`): Text-to-SQL runs on HF Inference
|
| 321 |
(`Qwen/Qwen2.5-Coder-7B-Instruct`), VQA on Groq (`qwen/qwen3.8-27b`), and the
|
| 322 |
+
built-in `demo_employee` SQLite profile ships with the repo β no external DB
|
| 323 |
service is needed on Spaces.
|
| 324 |
|
| 325 |
> **Note:** HF Spaces moved the **Docker SDK to a paid tier** (free CPU 2026).
|
| 326 |
+
> Deploy there with the free **Gradio SDK** instead β `app.py` at the repo root
|
| 327 |
> spawns the same three services the Docker image ran (worker `:8700`,
|
| 328 |
> MCP `:8701`, sepia web UI `:7860`) and mounts a minimal Gradio anchor page at
|
| 329 |
> `/gradio-lp`. The UI at `/` is unchanged.
|
| 330 |
|
| 331 |
+
1. **Create the Space** β huggingface.co β *New Space* β SDK: **Gradio** β
|
| 332 |
+
blank template β name it (e.g. `querylens`). Hardware: free CPU basic.
|
| 333 |
2. **Push the project files** into the Space repo. Easiest on Windows is the
|
| 334 |
bundled helper:
|
| 335 |
```powershell
|
|
|
|
| 339 |
(respecting the exclusions: no `.env`, no `chat_store/`, no 350 MB
|
| 340 |
`dataset_full` dumps, no `__pycache__`), merges the HF frontmatter into the
|
| 341 |
Space `README.md` (keeping the generated `sdk_version`), commits and pushes.
|
| 342 |
+
3. **Add Secrets** (Space settings β Variables and Secrets β never commit them):
|
| 343 |
| Secret | Purpose |
|
| 344 |
|---|---|
|
| 345 |
+
| `HF_API_TOKEN` | HF Inference API β Text-to-SQL (`Qwen/Qwen2.5-Coder-7B-Instruct`) |
|
| 346 |
| `GROQ_API_KEY` | Groq vision VQA (`qwen/qwen3.8-27b`, free tier) |
|
| 347 |
+
No `DB_CONNECTION_URL` is required β the worker auto-activates the bundled demo.
|
| 348 |
Optional: set `DB_CONNECTION_URL` to a hosted Postgres (e.g. Neon) for a real
|
| 349 |
external database.
|
| 350 |
+
4. **Open the Space** β the sepia UI loads with the demo profile active.
|
| 351 |
The **Database** panel lets you register additional databases (hosted
|
| 352 |
Postgres/MySQL URLs, or uploaded `.sqlite`/`.csv` files) at runtime.
|
| 353 |
|
| 354 |
**Local Docker runs still work** for your own machine: `docker build` +
|
| 355 |
`docker-compose.yml` are unchanged and `start_hf.sh` serves the identical
|
| 356 |
+
stack β only the Spaces *hosting* path is now the Gradio launcher.
|
| 357 |
|
| 358 |
+
Note: free Spaces sleep after inactivity (cold start ~1β2 min). Uploaded schema
|
| 359 |
files and chat history are ephemeral unless you enable *Persistent Storage* in
|
| 360 |
the Space settings.
|
| 361 |
|
| 362 |
### Historical deployment journey (reference)
|
| 363 |
|
| 364 |
+
This section documents the **complete deployment journey** β from the first proof-of-concept tunnel approach to the final production-ready hybrid architecture. Each phase is explained with commands and rationale so this can serve as a reference for deploying any multi-modal AI application on HuggingFace Spaces.
|
| 365 |
|
| 366 |
---
|
| 367 |
|
|
|
|
| 378 |
| Public port | 7860 only |
|
| 379 |
| Timeout | Space sleeps after inactivity |
|
| 380 |
|
| 381 |
+
The key challenge: **running a local LLM (e.g. `qwen2.5-coder:1.5b`) via Ollama consumes ~1.5β3 GB RAM, leaving limited headroom for vision models and the application stack.** Running a vision-language model such as `qwen3.5:2b` (~3 GB) alongside the text model causes out-of-memory (OOM) failures on the free CPU tier.
|
| 382 |
|
| 383 |
---
|
| 384 |
|
| 385 |
+
### Phase 1 β Cloudflare Tunnel: Bridging Local Resources to the Cloud
|
| 386 |
|
| 387 |
#### Theory
|
| 388 |
|
|
|
|
| 434 |
|
| 435 |
---
|
| 436 |
|
| 437 |
+
### Phase 2 β Self-Contained Docker: Running Ollama Inside the Container
|
| 438 |
|
| 439 |
#### Theory
|
| 440 |
|
| 441 |
+
The next evolution is to **embed Ollama directly into the Docker image** and pull models at container startup. This makes the deployment fully self-contained β no external machine is needed. The HF Space container becomes a complete inference server.
|
| 442 |
|
| 443 |
+
The challenge is that HF Spaces rebuilds the Docker image on every push but does **not cache downloaded model weights** between restarts (storage is ephemeral). This means every **Factory Reboot** triggers a fresh ~1β3 GB model download, causing a cold-start delay of 2β5 minutes.
|
| 444 |
|
| 445 |
To prevent HF's health monitor from timing out the Space during this download, model pulling is performed **asynchronously in the background**, allowing the web UI to become responsive immediately while the model fetches in parallel.
|
| 446 |
|
|
|
|
| 497 |
|
| 498 |
- **Vision model OOM**: Adding `qwen3.5:2b` alongside `qwen2.5-coder:1.5b` exceeds the 16 GB RAM limit when both are loaded simultaneously.
|
| 499 |
- Model weights are re-downloaded on every Factory Reboot.
|
| 500 |
+
- Ollama version pinning is critical β newer models require newer Ollama binaries and pulling the wrong combination causes `412` errors.
|
| 501 |
|
| 502 |
---
|
| 503 |
|
| 504 |
+
### Phase 3 β Hybrid Serverless API (Final Production Architecture)
|
| 505 |
|
| 506 |
#### Theory
|
| 507 |
|
|
|
|
| 511 |
|------|----------|-------|------|
|
| 512 |
| Text-to-SQL | HuggingFace Inference API | `Qwen/Qwen2.5-Coder-7B-Instruct` | Free tier |
|
| 513 |
| Vision Q&A | Groq API | `meta-llama/llama-4-scout-17b-16e-instruct` | Free (14,400 req/day) |
|
| 514 |
+
| OCR | Tesseract (in container) | β | Free |
|
| 515 |
+
| Database | Neon PostgreSQL | β | Free tier |
|
| 516 |
|
| 517 |
This eliminates OOM risk entirely, removes the model download cold-start, and makes the container startup under 30 seconds.
|
| 518 |
|
|
|
|
| 526 |
|
| 527 |
#### Required HuggingFace Space Secrets
|
| 528 |
|
| 529 |
+
Set these in **Space Settings β Variables and Secrets**:
|
| 530 |
|
| 531 |
```
|
| 532 |
USE_HF_CLOUD = 1
|
|
|
|
| 544 |
**Groq API Key:**
|
| 545 |
1. Go to https://console.groq.com
|
| 546 |
2. Sign in with Google / GitHub
|
| 547 |
+
3. Navigate to **API Keys** β **Create API Key**
|
| 548 |
4. Copy the key
|
| 549 |
|
| 550 |
**Neon PostgreSQL:**
|
|
|
|
| 606 |
|
| 607 |
4. **Factory Reboot** the Space after adding secrets to trigger a clean rebuild with the new environment variables.
|
| 608 |
|
| 609 |
+
5. **Monitor the build logs** β a successful startup shows:
|
| 610 |
```
|
| 611 |
[GRANITE_VQA] Target Model: meta-llama/llama-4-scout-17b-16e-instruct (via Groq Vision)
|
| 612 |
[INFO] CLOUD MODE: Initializing Official HF InferenceClient (Qwen/Qwen2.5-Coder-7B-Instruct)
|
|
|
|
| 633 |
|
| 634 |
This project demonstrates that a self-correcting, multi-modal AI pipeline can be built and deployed entirely on consumer hardware through careful architectural decisions: progressive SQL generation with semantic validation, unified MCP-based tool access across data modalities, dynamic VRAM orchestration to prevent memory exhaustion, and a hybrid containerization strategy that preserves native GPU performance while maintaining deployment portability.
|
| 635 |
|
| 636 |
+
The system was developed iteratively, with each architectural decision β from model selection to validation logic to infrastructure design β informed by observed failure modes and measured outcomes rather than theoretical assumptions.
|
| 637 |
|
| 638 |
---
|
| 639 |
+
*Built with β€οΈ for advanced Agentic Data Engineering.*
|