Spaces:
Sleeping
Sleeping
| ο»Ώ--- | |
| title: Example App Hackathon Gustave Eiffel 2026 | |
| emoji: π€ | |
| colorFrom: blue | |
| colorTo: purple | |
| sdk: gradio | |
| sdk_version: 4.44.1 | |
| python_version: '3.11' | |
| app_file: app.py | |
| pinned: false | |
| license: apache-2.0 | |
| # RAG Chat API Sample Code for Gustave Eiffel Hackathon 2026 | |
| This is a sample code of **Retrieval-Augmented Generation (RAG)** API deployed to Hugging Face Spaces for the Gustave Eiffel Hackathon 2026. The goal of this hackathon is to build an AI assistant for actuarial questions using a document corpus. The core challenge | |
| is to build an assistant that is: | |
| - β Accurate (Juste) β correct answers, no hallucinations | |
| - π² Low cost (Pas cher) β minimize token usage | |
| - π± Sustainable (Sobre) β reduce CO2 impact | |
| π Success = balance all three, not just performance! | |
| This sample code demonstrates how to build a RAG system with FastAPI and Gradio, and deploy it to Hugging Face Spaces. It also includes the necessary configuration and structure to meet the hackathon requirements. It includes: | |
| - `/query` API endpoint to interact with the user or the RAG evaluation system. Note that the output of this endpoint is designed for the RAG evaluation system, which will assess the correctness of the answer from your RAG. The response MUST have all the fields as follow (DO NOT change the response format, otherwise the evaluation framework will not be able to parse the response and evaluate the answer -- you will get 0 for the evaluation if the response is unparseable): | |
| - answer (str): The generated answer from your RAG system | |
| - sources (list): Source documents used for context in the answer generation, each source should have: | |
| - source (str): File name of the source document | |
| - score (float): Relevance score of the source document | |
| - ref_text (str): The exact text span from the source document that is used in the answer generation (can be truncated if too long) | |
| - explanation (str): Explanation of the retrieval and answer logic | |
| - total_token (int): Total token count from the LLM call | |
| - prompt_tokens (int): Prompt token count | |
| - completion_tokens (int): Completion token count | |
| - cached_tokens (int): Cached prompt tokens (when reported by model provider) | |
| - co2_grams (float | None): Estimated CO2 emission in grams (via ecologits) | |
| - energy_kwh (float | None): Estimated energy use in kWh (via ecologits) | |
| - run_time_in_ms (float): Pipeline execution time in milliseconds | |
| - `/health` API endpoint to check if the API is running or not. The return format should be `{"status": "healthy"}` when the API is healthy. | |
| - Gradio UI and configuration to be deployed to Hugging Face Spaces. The UI allows users to chat with the RAG system and ingest new documents. | |
| --- | |
| ## Overview | |
| This application demonstrates how to build a production-ready RAG system within the Hugging Face Spaces. It covers: | |
| | Requirement | Provided Solution | | |
| |---|---| | |
| | LLM API calls | Azure OpenAI (`gpt-5.1` via REST API) | | |
| | Text β Embeddings | Azure OpenAI (`text-embedding-3-small` via REST API) | | |
| | Prompt engineering | Custom prompts for RAG system in /prompts/rag_prompts.txt | | |
| | Vector Store | ChromaDB (persistent in /data folder, runs in-process) | | |
| Hackathon participants can use this code as a starting point and customize any solutions (the LLM calls, embeddings, prompts, and vector store) as they see fit to optimize for accuracy, cost, and sustainability. The provided code is modular and well-documented to facilitate easy modifications. | |
| --- | |
| ## Architecture | |
| ``` | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β Hugging Face Space β | |
| β β | |
| β ββββββββββββ ββββββββββββββββ ββββββββββββββββββ β | |
| β β Gradio β β FastAPI β β ChromaDB β β | |
| β β UI ββββββΆβ /query ββββββΆβ Vector Store β β | |
| β β β β /ingest β β (persistent in β β | |
| β β β β /health β β /data folder) β β | |
| β ββββββββββββ ββββββββ¬ββββββββ ββββββββββββββββββ β | |
| β β β² β | |
| β βΌ β β | |
| β ββββββββββββββββββββ βββββββββββββββββββ β | |
| β β Azure OpenAI β β Azure OpenAI β β | |
| β β GPT-5.1 (LLM) β β text-embedding β β | |
| β β β β -3-small β β | |
| β ββββββββββββββββββββ βββββββββββββββββββ β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| --- | |
| ## Setup & Deployment | |
| ### 1. Register for Hugging Face and Create a Space | |
| If you have not created a Hugging Face Space, follow the instructions in the [Hugging Face Quickstart](README_HF.md) to create an account and set up a new Space and clone the sample code to your local machine. | |
| ### 2. Set Up a Python Virtual Environment | |
| Download and set up a Python virtual environment to manage package dependencies. | |
| To download Python, visit the [official Python website](https://www.python.org/downloads/) and follow the installation instructions for your operating system. Make sure to install Python 3.10 or 3.11. There is no need to install the latest Python version if it is above 3.11, as some dependencies may not be compatible with versions higher than 3.11. | |
| To create a virtual environment, run the following command in your terminal (you can replace `hackathon-eiffel` with any name you prefer for your virtual environment): | |
| ```bash | |
| python -m venv ~/.venv/hackathon-eiffel | |
| # Activate the virtual environment | |
| # macOS / Linux | |
| source ~/.venv/hackathon-eiffel/bin/activate | |
| # Windows (PowerShell) | |
| ~\.venv\hackathon-eiffel\Scripts\Activate.ps1 | |
| # Windows (Command Prompt) | |
| ~\.venv\hackathon-eiffel\Scripts\activate.bat | |
| ``` | |
| Once your virtual environment is activated, go to your project directory to install package dependencies and run the application: | |
| ```bash | |
| # Install dependencies | |
| pip install -r requirements.txt | |
| # Set your Azure API key. Azure API key is a key to call the LLM APIs. The organizers will provide you one at the date of the hackathon. | |
| # macOS / Linux | |
| export AZURE_API_KEY="your_azure_api_key_here" | |
| # Windows (PowerShell) | |
| $env:AZURE_API_KEY = "your_azure_api_key_here" | |
| # Run the application | |
| python app.py | |
| # Server starts at http://localhost:7860 . If you can open http://localhost:7860/health on browser, it means the API is running successfully. | |
| # To make the RAG work, you first need to create embeddings , you can learn about it from README_RAG.md | |
| ``` | |
| > **Tip:** To deactivate the virtual environment when you are done, run `deactivate` (venv) or `conda deactivate` (conda). | |
| --- | |
| ### 3. Install the Hugging Face CLI | |
| To manage binary files in the Hugging Face bucket (for storing large files like ChromaDB vector store, ingested documents, etc.), you need to install the Hugging Face CLI tool: | |
| ```bash | |
| # Install the hf CLI (requires uv) | |
| uv tool install "huggingface_hub[cli]" | |
| # Try to login to Hugging Face with Hugging Face CLI (it needs Write access to the bucket) | |
| export HF_TOKEN="hf_your_token_here" | |
| # or interactively: | |
| hf auth login | |
| ``` | |
| ### 4. Adding Binary Files to the HF Space | |
| Large or binary files (PDFs, pre-built ChromaDB databases, datasets, model weights) have to be stored in a **Hugging Face bucket** and mounted into the Space container. The `hf sync` command keeps your local folder in sync with the bucket. | |
| > **Note:** Git LFS is not supported for Hugging Face Spaces persistent storage. Use the bucket + `hf sync` workflow described here instead. | |
| ### 5. Persist files in the Shared Folder | |
| Each Hugging Face Space has a **persistent storage bucket** that is automatically mounted at `/data` to your project root inside the running container server. This folder is the single shared location where the application reads and writes all persistent files β the ChromaDB vector store, display images, even secrets and any binary assets. | |
| | Path in server | Purpose | | |
| |---|---| | |
| | `/data/chroma_db/` | ChromaDB vector store (survives Space restarts) | | |
| **Default bucket naming convention:** | |
| A Hugging Face Space at | |
| `https://huggingface.co/spaces/<org>/<space-name>` | |
| gets a default /data storage bucket at | |
| `https://huggingface.co/buckets/<org>/<space-name>-storage` | |
| Using this project as an example, the Space URL is: | |
| - Space: `https://huggingface.co/spaces/millimanfrance/Example-App-Hackathon-Gustave-Eiffel-2026` | |
| - Bucket: `https://huggingface.co/buckets/millimanfrance/Example-App-Hackathon-Gustave-Eiffel-2026-storage` | |
| The `hf://` URI for use with the CLI is: | |
| `hf://buckets/millimanfrance/Example-App-Hackathon-Gustave-Eiffel-2026-storage` | |
| Note that by default, the bucket is empty and private when you create the Space. You need to upload files to it (via `hf sync`) before they appear in the Space server at `/data`. | |
| To attach the Hugging Face Storage Bucket to Your Space: | |
| 1. Open your Space on huggingface.co | |
| 2. Go to **"Organization" β Your organization name β "+New" β "Bucket"** | |
| 3. Once the bucket is created. Go to your Hugging Face Space, click **"Settings"**. Scroll down to **"Storage Buckets" β "Mount a bucket"**, select the existing bucket **`<org>/<space-name>-storage`** to mount it to your Space of Month path `/data`. | |
| 4. "Mount bucket" β Hugging Face will mount the bucket at `/data` inside the Space container | |
| To Sync Your Local `./data` with the Space Bucket | |
| Place all persistent files under the `./data` folder of your project. The expected structure may look like this: | |
| ``` | |
| ./data/ | |
| βββ chroma_db/ # Binary files and ChromaDB vector store | |
| β βββ chroma.sqlite3 | |
| ./train_data/ # Hackathon train datasets (will be mounted at /train_data in the project with a bucket from the Hackathon organizer) | |
| βββ Automobile - Train/ | |
| βββ Climatique - Train/ | |
| βββ ... | |
| ``` | |
| **Push local file in ./data to Hugging Face bucket:** | |
| ```bash | |
| # Mirror ./data to the bucket β removes remote files deleted locally | |
| hf sync ./data hf://buckets/<org>/<space-name>-storage --delete | |
| # Sync only a specific sub-folder (e.g., the vector store) | |
| hf sync ./data/chroma_db hf://buckets/<org>/<space-name>-storage/chroma_db | |
| # Sync only specific file types | |
| hf sync ./data hf://buckets/<org>/<space-name>-storage \ | |
| --include "*.pdf" --include "*.sqlite3" | |
| ``` | |
| > **`--delete` flag:** Without it, `hf sync` only uploads new/changed files and never removes anything from the remote. Add `--delete` to make the bucket an exact mirror of your local `./data`. | |
| `hf sync` is **incremental** β it computes checksums and only transfers files that have changed. | |
| **Download the Bucket to another Machine's `./data` folder:** | |
| To pull the latest bucket contents back to a local `./data` folder (e.g., on another team member's machine): | |
| ```bash | |
| hf sync hf://buckets/<org>/<space-name>-storage ./data | |
| ``` | |
| ### 6. Get Hackathon Train Datasets from the Organizer's Bucket | |
| The train datasets for this hackathon are stored in a separate read-only bucket. Sync them to a local `./train_data` folder to save your Hugging Face bucket storage (the train datasets is about 1GB). | |
| ```bash | |
| # Download all training data to local folder train_data/ from the organizer's bucket hf://buckets/millimanfrance/Hackathon2026TrainData | |
| hf sync hf://buckets/millimanfrance/Hackathon2026TrainData ./train_data | |
| ``` | |
| > **Note:** `Hackathon2026TrainData` is a shared read-only bucket. Do not attempt to push to it. | |
| ### 7. Accessing Files in the Space Application | |
| Once the bucket is mounted, files appear under `/data` inside the Space container. The application resolves the data root automatically via a single `DATA_DIR` constant in `app.py`. Here is an example of how to access the ChromaDB vector store and the environment file in your code: | |
| ```python | |
| from pathlib import Path | |
| # /data when running in HF Spaces (bucket mount), ./data for local dev | |
| DATA_DIR = Path("/data") if Path("/data").is_dir() else Path("./data") | |
| CHROMA_PERSIST_DIR = str(DATA_DIR / "chroma_db") | |
| ENV_FILE = str(DATA_DIR / ".env") | |
| ``` | |
| All persistent data β the vector store, sample documents, datasets β lives under `DATA_DIR` so a single `hf sync ./data ...` covers everything. | |
| ## Application Configuration | |
| The application loads model configuration from **`./config.json`** (project root) | |
| **NEVER put real credentials in the config file.** Use environment variables instead. The config file is meant for non-sensitive configuration parameters like model names, API endpoints, and other settings. | |
| ### Step 1 β Configure `./config.json` | |
| Edit `./config.json` to different LLM and embedding models, or to add additional configuration parameters. The provided sample config is designed for Azure OpenAI REST API calls, but you can modify the structure and fields as needed for your implementation. Just make sure to update the code in `app.py` accordingly to read the new config format. The organizers will provide you with the Azure API key at the date of the hackathon, and two LLM models (**gpt-5-mini** & **gpt-5.1**) and embedding models (**text-embedding-3-large** & **text-embedding-3-small**) are available. | |
| ```json | |
| { | |
| "embedding": { | |
| "endpoint_url": "https://hackathon-eiffel-2026-apim.azure-api.net/ai/openai/deployments/text-embedding-3-small/embeddings?api-version=2024-12-01-preview", | |
| "model": "text-embedding-3-small" | |
| }, | |
| "llm": { | |
| "endpoint_url": "https://hackathon-eiffel-2026-apim.azure-api.net/ai/openai/deployments/gpt-5.1/chat/completions?api-version=2024-12-01-preview", | |
| "model": "gpt-5.1", | |
| "max_completion_tokens": 512, | |
| "temperature": 0.7, | |
| "top_p": 0.95 | |
| } | |
| } | |
| ``` | |
| > **Note:** The `endpoint_url` for embeddings ends in `/embeddings` and the one for the LLM ends in `/chat/completions`. Keep those suffixes intact. | |
| ### Step 2 β Set the API Key | |
| The API key **MUST NOT** be stored in `config.json`. Set it as an environment variable: | |
| ```bash | |
| # macOS / Linux | |
| export AZURE_API_KEY="your_azure_api_key_here" | |
| # Windows (PowerShell) | |
| $env:AZURE_API_KEY = "your_azure_api_key_here" | |
| ``` | |
| When deploying to Hugging Face Spaces, add it as a **Space Secret** (Go to your Hugging Face Space, click **Settings β Variables and secrets β New secret β name it `AZURE_API_KEY`**). | |