Spaces:
Sleeping
Sleeping
viktor-hirenko commited on
Commit Β·
5fd4bb2
1
Parent(s): 40e5eae
feat: migrate from Ollama to Hugging Face Inference API
Browse files- Replace Ollama with HF Inference API in llm_handler.py
- Update config.py with HF model settings
- Remove ollama dependencies, add huggingface_hub
- Create app.py as HF Spaces entry point
- Add HF token validation in main.py
- Create README_HF.md with HF Spaces YAML frontmatter
- Add comprehensive documentation:
- DEPLOYMENT_GUIDE.md: Step-by-step deployment instructions
- ENV_SETUP.md: Environment variables documentation
- MIGRATION_SUMMARY.md: Complete migration overview
- test_hf_integration.py: Integration test suite
Ready for deployment to Hugging Face Spaces with free, permanent hosting.
- DEPLOYMENT_GUIDE.md +309 -0
- ENV_SETUP.md +193 -0
- MIGRATION_SUMMARY.md +185 -0
- README_HF.md +173 -0
- app.py +91 -0
- config.py +5 -4
- llm_handler.py +47 -69
- main.py +12 -1
- requirements.txt +2 -3
- test_hf_integration.py +185 -0
DEPLOYMENT_GUIDE.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Hugging Face Spaces Deployment Guide
|
| 2 |
+
|
| 3 |
+
This guide walks you through deploying the RAG system to Hugging Face Spaces for free, permanent hosting.
|
| 4 |
+
|
| 5 |
+
## Prerequisites
|
| 6 |
+
|
| 7 |
+
- Hugging Face account ([sign up here](https://huggingface.co/join))
|
| 8 |
+
- Git installed on your local machine
|
| 9 |
+
- Code migrated to use HF Inference API (already done β
)
|
| 10 |
+
|
| 11 |
+
## Step 1: Test Locally (Recommended)
|
| 12 |
+
|
| 13 |
+
Before deploying, test the application with HF Inference API locally:
|
| 14 |
+
|
| 15 |
+
### 1.1 Get Your HF Token
|
| 16 |
+
|
| 17 |
+
1. Go to [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
|
| 18 |
+
2. Click "New token"
|
| 19 |
+
3. Name it (e.g., "RAG System")
|
| 20 |
+
4. Select `read` permissions
|
| 21 |
+
5. Click "Generate"
|
| 22 |
+
6. Copy the token (starts with `hf_`)
|
| 23 |
+
|
| 24 |
+
### 1.2 Set Environment Variable
|
| 25 |
+
|
| 26 |
+
```bash
|
| 27 |
+
# Linux/Mac
|
| 28 |
+
export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 29 |
+
|
| 30 |
+
# Windows (PowerShell)
|
| 31 |
+
$env:HF_TOKEN="hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
### 1.3 Install Dependencies
|
| 35 |
+
|
| 36 |
+
```bash
|
| 37 |
+
cd /Users/v.hirenko/Desktop/DevHubVault/my-ai-projects/rag-python-rag
|
| 38 |
+
source venv/bin/activate # or venv\Scripts\activate on Windows
|
| 39 |
+
pip install -r requirements.txt
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
### 1.4 Run Tests
|
| 43 |
+
|
| 44 |
+
```bash
|
| 45 |
+
python test_hf_integration.py
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
If all tests pass, proceed to deployment!
|
| 49 |
+
|
| 50 |
+
### 1.5 Test the Application
|
| 51 |
+
|
| 52 |
+
```bash
|
| 53 |
+
python app.py
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
Open http://localhost:7860 and test with a few questions.
|
| 57 |
+
|
| 58 |
+
## Step 2: Create Hugging Face Space
|
| 59 |
+
|
| 60 |
+
### 2.1 Create New Space
|
| 61 |
+
|
| 62 |
+
1. Go to [https://huggingface.co/new-space](https://huggingface.co/new-space)
|
| 63 |
+
2. Fill in the details:
|
| 64 |
+
- **Owner**: Your username (e.g., `monsara`)
|
| 65 |
+
- **Space name**: `rag-python-rag`
|
| 66 |
+
- **License**: MIT
|
| 67 |
+
- **Select the Space SDK**: Gradio
|
| 68 |
+
- **Space hardware**: CPU basic (free)
|
| 69 |
+
- **Space visibility**: Public (or Private if you prefer)
|
| 70 |
+
3. Click "Create Space"
|
| 71 |
+
|
| 72 |
+
### 2.2 Note Your Space URL
|
| 73 |
+
|
| 74 |
+
Your Space will be available at:
|
| 75 |
+
```
|
| 76 |
+
https://huggingface.co/spaces/YOUR_USERNAME/rag-python-rag
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
## Step 3: Configure Space Secrets
|
| 80 |
+
|
| 81 |
+
### 3.1 Add HF_TOKEN Secret
|
| 82 |
+
|
| 83 |
+
1. Go to your Space page
|
| 84 |
+
2. Click on "Settings" (gear icon)
|
| 85 |
+
3. Scroll down to "Repository secrets"
|
| 86 |
+
4. Click "Add a secret"
|
| 87 |
+
5. Fill in:
|
| 88 |
+
- **Name**: `HF_TOKEN`
|
| 89 |
+
- **Value**: Your HF token from Step 1.1
|
| 90 |
+
6. Click "Add"
|
| 91 |
+
|
| 92 |
+
β οΈ **Important**: The Space will NOT work without this secret!
|
| 93 |
+
|
| 94 |
+
## Step 4: Push Code to Space
|
| 95 |
+
|
| 96 |
+
You have two options:
|
| 97 |
+
|
| 98 |
+
### Option A: Direct Git Push (Recommended)
|
| 99 |
+
|
| 100 |
+
```bash
|
| 101 |
+
cd /Users/v.hirenko/Desktop/DevHubVault/my-ai-projects/rag-python-rag
|
| 102 |
+
|
| 103 |
+
# Add HF Space as remote
|
| 104 |
+
git remote add hf https://huggingface.co/spaces/YOUR_USERNAME/rag-python-rag
|
| 105 |
+
# Replace YOUR_USERNAME with your actual HF username
|
| 106 |
+
|
| 107 |
+
# Push to HF Space
|
| 108 |
+
git push hf main
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
If prompted for credentials:
|
| 112 |
+
- **Username**: Your HF username
|
| 113 |
+
- **Password**: Your HF token (the same one you created)
|
| 114 |
+
|
| 115 |
+
### Option B: Link GitHub Repository
|
| 116 |
+
|
| 117 |
+
1. In your Space Settings
|
| 118 |
+
2. Find "Linked repositories"
|
| 119 |
+
3. Click "Link a GitHub repository"
|
| 120 |
+
4. Select `monsara/rag-python-rag`
|
| 121 |
+
5. The Space will automatically sync with your GitHub repo
|
| 122 |
+
|
| 123 |
+
## Step 5: Verify Deployment
|
| 124 |
+
|
| 125 |
+
### 5.1 Check Build Logs
|
| 126 |
+
|
| 127 |
+
1. Go to your Space page
|
| 128 |
+
2. Click on "Logs" tab
|
| 129 |
+
3. Watch the build process
|
| 130 |
+
4. Look for:
|
| 131 |
+
```
|
| 132 |
+
β
HF_TOKEN validated successfully
|
| 133 |
+
β
RAG pipeline setup complete!
|
| 134 |
+
Running on local URL: http://0.0.0.0:7860
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
### 5.2 Test the Space
|
| 138 |
+
|
| 139 |
+
1. Once "Running" status appears
|
| 140 |
+
2. Click on the Space URL
|
| 141 |
+
3. Try example questions
|
| 142 |
+
4. Verify answers are generated correctly
|
| 143 |
+
|
| 144 |
+
## Step 6: Update README (Optional)
|
| 145 |
+
|
| 146 |
+
Replace the Space README with the HF-specific one:
|
| 147 |
+
|
| 148 |
+
```bash
|
| 149 |
+
cd /Users/v.hirenko/Desktop/DevHubVault/my-ai-projects/rag-python-rag
|
| 150 |
+
|
| 151 |
+
# Backup current README
|
| 152 |
+
mv README.md README_LOCAL.md
|
| 153 |
+
|
| 154 |
+
# Use HF README
|
| 155 |
+
cp README_HF.md README.md
|
| 156 |
+
|
| 157 |
+
# Commit and push
|
| 158 |
+
git add README.md
|
| 159 |
+
git commit -m "Update README for HF Spaces"
|
| 160 |
+
git push hf main
|
| 161 |
+
```
|
| 162 |
+
|
| 163 |
+
## Troubleshooting
|
| 164 |
+
|
| 165 |
+
### Issue: "HF_TOKEN not found"
|
| 166 |
+
|
| 167 |
+
**Solution**: Make sure you added `HF_TOKEN` to Space secrets (Step 3.1)
|
| 168 |
+
|
| 169 |
+
### Issue: "Model not found" or "Rate limit exceeded"
|
| 170 |
+
|
| 171 |
+
**Solution**:
|
| 172 |
+
- Check if you're using the correct model name in `config.py`
|
| 173 |
+
- Free tier has rate limits (~1000 requests/hour)
|
| 174 |
+
- Consider upgrading to HF Pro ($9/month)
|
| 175 |
+
|
| 176 |
+
### Issue: "Build failed"
|
| 177 |
+
|
| 178 |
+
**Solution**:
|
| 179 |
+
1. Check the build logs for specific errors
|
| 180 |
+
2. Verify `requirements.txt` has all dependencies
|
| 181 |
+
3. Make sure Python version is compatible (3.9+)
|
| 182 |
+
|
| 183 |
+
### Issue: "Application crashes on startup"
|
| 184 |
+
|
| 185 |
+
**Solution**:
|
| 186 |
+
1. Check if `app.py` is set as the entry point in Space settings
|
| 187 |
+
2. Verify all imports are correct
|
| 188 |
+
3. Check logs for Python errors
|
| 189 |
+
|
| 190 |
+
### Issue: Slow responses
|
| 191 |
+
|
| 192 |
+
**Solution**:
|
| 193 |
+
- Free tier uses shared infrastructure
|
| 194 |
+
- Upgrade to better hardware (paid)
|
| 195 |
+
- Or optimize chunk size and retrieval count
|
| 196 |
+
|
| 197 |
+
## Monitoring
|
| 198 |
+
|
| 199 |
+
### View Logs
|
| 200 |
+
|
| 201 |
+
```bash
|
| 202 |
+
# Real-time logs
|
| 203 |
+
# Go to Space page β Logs tab
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
+
### Check Usage
|
| 207 |
+
|
| 208 |
+
1. Go to your HF profile
|
| 209 |
+
2. Click on "Usage & billing"
|
| 210 |
+
3. View API usage statistics
|
| 211 |
+
|
| 212 |
+
## Updating the Space
|
| 213 |
+
|
| 214 |
+
### Update Code
|
| 215 |
+
|
| 216 |
+
```bash
|
| 217 |
+
cd /Users/v.hirenko/Desktop/DevHubVault/my-ai-projects/rag-python-rag
|
| 218 |
+
|
| 219 |
+
# Make your changes
|
| 220 |
+
git add .
|
| 221 |
+
git commit -m "Your update message"
|
| 222 |
+
git push hf main
|
| 223 |
+
```
|
| 224 |
+
|
| 225 |
+
The Space will automatically rebuild.
|
| 226 |
+
|
| 227 |
+
### Update Dependencies
|
| 228 |
+
|
| 229 |
+
Edit `requirements.txt`, then:
|
| 230 |
+
|
| 231 |
+
```bash
|
| 232 |
+
git add requirements.txt
|
| 233 |
+
git commit -m "Update dependencies"
|
| 234 |
+
git push hf main
|
| 235 |
+
```
|
| 236 |
+
|
| 237 |
+
### Update Configuration
|
| 238 |
+
|
| 239 |
+
Edit `config.py`, then push changes as above.
|
| 240 |
+
|
| 241 |
+
## Cost Considerations
|
| 242 |
+
|
| 243 |
+
### Free Tier (Current Setup)
|
| 244 |
+
|
| 245 |
+
- β
**Cost**: $0/month
|
| 246 |
+
- β
**Hosting**: Unlimited
|
| 247 |
+
- β οΈ **Rate limits**: ~1000 requests/hour
|
| 248 |
+
- β οΈ **Performance**: Shared CPU
|
| 249 |
+
- β οΈ **Tokens**: 1024 max per response
|
| 250 |
+
|
| 251 |
+
### Upgrade Options
|
| 252 |
+
|
| 253 |
+
**HF Pro ($9/month)**:
|
| 254 |
+
- Higher rate limits
|
| 255 |
+
- Faster inference
|
| 256 |
+
- Priority support
|
| 257 |
+
- Better hardware options
|
| 258 |
+
|
| 259 |
+
**Dedicated Hardware**:
|
| 260 |
+
- CPU Upgrade: $0.03/hour (~$22/month)
|
| 261 |
+
- GPU T4: $0.60/hour (~$432/month)
|
| 262 |
+
- GPU A10G: $1.05/hour (~$756/month)
|
| 263 |
+
|
| 264 |
+
## Security Best Practices
|
| 265 |
+
|
| 266 |
+
1. **Never commit HF_TOKEN** to Git
|
| 267 |
+
2. **Use Space secrets** for all sensitive data
|
| 268 |
+
3. **Rotate tokens** periodically
|
| 269 |
+
4. **Monitor usage** for unexpected spikes
|
| 270 |
+
5. **Set rate limits** in your application
|
| 271 |
+
|
| 272 |
+
## Next Steps
|
| 273 |
+
|
| 274 |
+
After successful deployment:
|
| 275 |
+
|
| 276 |
+
1. β
Test thoroughly with various questions
|
| 277 |
+
2. β
Share the Space URL with users
|
| 278 |
+
3. β
Monitor logs for errors
|
| 279 |
+
4. β
Gather user feedback
|
| 280 |
+
5. β
Iterate and improve
|
| 281 |
+
|
| 282 |
+
## Support
|
| 283 |
+
|
| 284 |
+
If you need help:
|
| 285 |
+
|
| 286 |
+
1. Check [HF Spaces documentation](https://huggingface.co/docs/hub/spaces)
|
| 287 |
+
2. Visit [HF Community forums](https://discuss.huggingface.co/)
|
| 288 |
+
3. Open an issue on [GitHub](https://github.com/monsara/rag-python-rag/issues)
|
| 289 |
+
|
| 290 |
+
---
|
| 291 |
+
|
| 292 |
+
## Quick Reference
|
| 293 |
+
|
| 294 |
+
**Space URL**: `https://huggingface.co/spaces/YOUR_USERNAME/rag-python-rag`
|
| 295 |
+
|
| 296 |
+
**Settings**: `https://huggingface.co/spaces/YOUR_USERNAME/rag-python-rag/settings`
|
| 297 |
+
|
| 298 |
+
**Logs**: `https://huggingface.co/spaces/YOUR_USERNAME/rag-python-rag/logs`
|
| 299 |
+
|
| 300 |
+
**Push command**:
|
| 301 |
+
```bash
|
| 302 |
+
git push hf main
|
| 303 |
+
```
|
| 304 |
+
|
| 305 |
+
**Update secret**: Space Settings β Repository secrets β Edit
|
| 306 |
+
|
| 307 |
+
---
|
| 308 |
+
|
| 309 |
+
Good luck with your deployment! π
|
ENV_SETUP.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Environment Variables Setup
|
| 2 |
+
|
| 3 |
+
This document describes the environment variables needed to run the RAG system.
|
| 4 |
+
|
| 5 |
+
## Required Variables
|
| 6 |
+
|
| 7 |
+
### HF_TOKEN (Required)
|
| 8 |
+
|
| 9 |
+
Your Hugging Face API token for accessing the Inference API.
|
| 10 |
+
|
| 11 |
+
**How to get it:**
|
| 12 |
+
1. Go to [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
|
| 13 |
+
2. Click "New token"
|
| 14 |
+
3. Give it a name (e.g., "RAG System")
|
| 15 |
+
4. Select `read` permissions
|
| 16 |
+
5. Click "Generate"
|
| 17 |
+
6. Copy the token (starts with `hf_`)
|
| 18 |
+
|
| 19 |
+
**Set it:**
|
| 20 |
+
|
| 21 |
+
```bash
|
| 22 |
+
# Linux/Mac
|
| 23 |
+
export HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 24 |
+
|
| 25 |
+
# Windows (PowerShell)
|
| 26 |
+
$env:HF_TOKEN="hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
| 27 |
+
|
| 28 |
+
# Windows (CMD)
|
| 29 |
+
set HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
**For Hugging Face Spaces:**
|
| 33 |
+
- Go to Space Settings β Repository secrets
|
| 34 |
+
- Add secret: Name=`HF_TOKEN`, Value=your token
|
| 35 |
+
|
| 36 |
+
## Optional Variables
|
| 37 |
+
|
| 38 |
+
### HF_MODEL
|
| 39 |
+
|
| 40 |
+
The Hugging Face model to use for text generation.
|
| 41 |
+
|
| 42 |
+
**Default:** `meta-llama/Llama-3.2-3B-Instruct`
|
| 43 |
+
|
| 44 |
+
**Other options:**
|
| 45 |
+
- `mistralai/Mistral-7B-Instruct-v0.2`
|
| 46 |
+
- `meta-llama/Meta-Llama-3-8B-Instruct`
|
| 47 |
+
|
| 48 |
+
```bash
|
| 49 |
+
export HF_MODEL=meta-llama/Llama-3.2-3B-Instruct
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
### EMBEDDING_MODEL
|
| 53 |
+
|
| 54 |
+
The sentence transformer model for embeddings (runs locally).
|
| 55 |
+
|
| 56 |
+
**Default:** `all-MiniLM-L6-v2`
|
| 57 |
+
|
| 58 |
+
```bash
|
| 59 |
+
export EMBEDDING_MODEL=all-MiniLM-L6-v2
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
### CHROMA_PERSIST_DIR
|
| 63 |
+
|
| 64 |
+
Directory for ChromaDB vector database storage.
|
| 65 |
+
|
| 66 |
+
**Default:** `./chroma_db`
|
| 67 |
+
|
| 68 |
+
```bash
|
| 69 |
+
export CHROMA_PERSIST_DIR=./chroma_db
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
### DOCUMENTS_DIR
|
| 73 |
+
|
| 74 |
+
Directory containing source documents.
|
| 75 |
+
|
| 76 |
+
**Default:** `./documents`
|
| 77 |
+
|
| 78 |
+
```bash
|
| 79 |
+
export DOCUMENTS_DIR=./documents
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
### PROCESSED_DOCS_DIR
|
| 83 |
+
|
| 84 |
+
Directory for processed markdown documents.
|
| 85 |
+
|
| 86 |
+
**Default:** `./processed_docs`
|
| 87 |
+
|
| 88 |
+
```bash
|
| 89 |
+
export PROCESSED_DOCS_DIR=./processed_docs
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
### DEFAULT_N_RESULTS
|
| 93 |
+
|
| 94 |
+
Number of context chunks to retrieve for each query.
|
| 95 |
+
|
| 96 |
+
**Default:** `5`
|
| 97 |
+
|
| 98 |
+
```bash
|
| 99 |
+
export DEFAULT_N_RESULTS=5
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
### SIMILARITY_THRESHOLD
|
| 103 |
+
|
| 104 |
+
Minimum similarity score for retrieved chunks.
|
| 105 |
+
|
| 106 |
+
**Default:** `0.5`
|
| 107 |
+
|
| 108 |
+
```bash
|
| 109 |
+
export SIMILARITY_THRESHOLD=0.5
|
| 110 |
+
```
|
| 111 |
+
|
| 112 |
+
### CHUNK_SIZE
|
| 113 |
+
|
| 114 |
+
Size of text chunks for processing.
|
| 115 |
+
|
| 116 |
+
**Default:** `1000`
|
| 117 |
+
|
| 118 |
+
```bash
|
| 119 |
+
export CHUNK_SIZE=1000
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
### CHUNK_OVERLAP
|
| 123 |
+
|
| 124 |
+
Overlap between consecutive chunks.
|
| 125 |
+
|
| 126 |
+
**Default:** `200`
|
| 127 |
+
|
| 128 |
+
```bash
|
| 129 |
+
export CHUNK_OVERLAP=200
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
### GRADIO_SHARE
|
| 133 |
+
|
| 134 |
+
Whether to create a public Gradio share link.
|
| 135 |
+
|
| 136 |
+
**Default:** `False` (set to `True` for 72-hour public link)
|
| 137 |
+
|
| 138 |
+
```bash
|
| 139 |
+
export GRADIO_SHARE=True
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
### GRADIO_SERVER_PORT
|
| 143 |
+
|
| 144 |
+
Port for the Gradio server.
|
| 145 |
+
|
| 146 |
+
**Default:** `7860`
|
| 147 |
+
|
| 148 |
+
```bash
|
| 149 |
+
export GRADIO_SERVER_PORT=7860
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
## Complete Example
|
| 153 |
+
|
| 154 |
+
Create a `.env` file in the project root:
|
| 155 |
+
|
| 156 |
+
```bash
|
| 157 |
+
# Required
|
| 158 |
+
HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
| 159 |
+
|
| 160 |
+
# Optional (uncomment to override defaults)
|
| 161 |
+
# HF_MODEL=meta-llama/Llama-3.2-3B-Instruct
|
| 162 |
+
# EMBEDDING_MODEL=all-MiniLM-L6-v2
|
| 163 |
+
# CHROMA_PERSIST_DIR=./chroma_db
|
| 164 |
+
# DOCUMENTS_DIR=./documents
|
| 165 |
+
# PROCESSED_DOCS_DIR=./processed_docs
|
| 166 |
+
# DEFAULT_N_RESULTS=5
|
| 167 |
+
# SIMILARITY_THRESHOLD=0.5
|
| 168 |
+
# CHUNK_SIZE=1000
|
| 169 |
+
# CHUNK_OVERLAP=200
|
| 170 |
+
# GRADIO_SHARE=False
|
| 171 |
+
# GRADIO_SERVER_PORT=7860
|
| 172 |
+
```
|
| 173 |
+
|
| 174 |
+
Then load it before running:
|
| 175 |
+
|
| 176 |
+
```bash
|
| 177 |
+
# Using python-dotenv (recommended)
|
| 178 |
+
pip install python-dotenv
|
| 179 |
+
# Add to your script: from dotenv import load_dotenv; load_dotenv()
|
| 180 |
+
|
| 181 |
+
# Or manually source it
|
| 182 |
+
source .env # Linux/Mac
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
## Verification
|
| 186 |
+
|
| 187 |
+
To verify your environment is set up correctly:
|
| 188 |
+
|
| 189 |
+
```bash
|
| 190 |
+
python -c "import os; print('HF_TOKEN:', 'SET' if os.getenv('HF_TOKEN') else 'NOT SET')"
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
Should output: `HF_TOKEN: SET`
|
MIGRATION_SUMMARY.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Migration Summary: Ollama β Hugging Face Spaces
|
| 2 |
+
|
| 3 |
+
## Overview
|
| 4 |
+
|
| 5 |
+
Successfully migrated the RAG system from local Ollama to Hugging Face Inference API for free, permanent cloud hosting.
|
| 6 |
+
|
| 7 |
+
## Changes Made
|
| 8 |
+
|
| 9 |
+
### 1. Core Files Modified
|
| 10 |
+
|
| 11 |
+
#### `llm_handler.py` β
|
| 12 |
+
- **Before**: Used `ollama` library for local LLM inference
|
| 13 |
+
- **After**: Uses `huggingface_hub.InferenceClient` for cloud inference
|
| 14 |
+
- **Key changes**:
|
| 15 |
+
- Replaced `ollama.Client` with `InferenceClient`
|
| 16 |
+
- Updated streaming logic for HF API
|
| 17 |
+
- Added token authentication
|
| 18 |
+
- Changed model to `meta-llama/Llama-3.2-3B-Instruct`
|
| 19 |
+
|
| 20 |
+
#### `config.py` β
|
| 21 |
+
- **Removed**:
|
| 22 |
+
```python
|
| 23 |
+
OLLAMA_MODEL = "llama3.2"
|
| 24 |
+
OLLAMA_BASE_URL = "http://localhost:11434"
|
| 25 |
+
```
|
| 26 |
+
- **Added**:
|
| 27 |
+
```python
|
| 28 |
+
HF_MODEL = "meta-llama/Llama-3.2-3B-Instruct"
|
| 29 |
+
HF_TOKEN = os.getenv("HF_TOKEN", "")
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
#### `requirements.txt` β
|
| 33 |
+
- **Removed**:
|
| 34 |
+
- `ollama==0.4.4`
|
| 35 |
+
- `langchain-ollama==0.2.2`
|
| 36 |
+
- **Added**:
|
| 37 |
+
- `huggingface_hub==0.20.3`
|
| 38 |
+
|
| 39 |
+
#### `main.py` β
|
| 40 |
+
- Added HF token validation on startup
|
| 41 |
+
- Updated error messages
|
| 42 |
+
- Removed Ollama-specific checks
|
| 43 |
+
|
| 44 |
+
### 2. New Files Created
|
| 45 |
+
|
| 46 |
+
#### `app.py` β
|
| 47 |
+
- Entry point for Hugging Face Spaces
|
| 48 |
+
- Validates HF_TOKEN from environment/secrets
|
| 49 |
+
- Provides clear setup instructions if token missing
|
| 50 |
+
- Launches Gradio interface with HF-specific settings
|
| 51 |
+
|
| 52 |
+
#### `README_HF.md` β
|
| 53 |
+
- Hugging Face Spaces README with YAML frontmatter
|
| 54 |
+
- Setup instructions for HF Spaces
|
| 55 |
+
- Usage examples
|
| 56 |
+
- Architecture diagram
|
| 57 |
+
- Rate limits and limitations
|
| 58 |
+
- Links to documentation
|
| 59 |
+
|
| 60 |
+
#### `ENV_SETUP.md` β
|
| 61 |
+
- Complete environment variables documentation
|
| 62 |
+
- Step-by-step token setup guide
|
| 63 |
+
- Examples for different platforms
|
| 64 |
+
- Verification commands
|
| 65 |
+
|
| 66 |
+
#### `test_hf_integration.py` β
|
| 67 |
+
- Comprehensive test suite
|
| 68 |
+
- Tests HF token, imports, API connection
|
| 69 |
+
- Tests LLM handler and vector store
|
| 70 |
+
- Provides clear pass/fail results
|
| 71 |
+
|
| 72 |
+
#### `DEPLOYMENT_GUIDE.md` β
|
| 73 |
+
- Step-by-step deployment instructions
|
| 74 |
+
- Local testing guide
|
| 75 |
+
- HF Spaces setup process
|
| 76 |
+
- Troubleshooting section
|
| 77 |
+
- Cost considerations
|
| 78 |
+
- Security best practices
|
| 79 |
+
|
| 80 |
+
### 3. Files Unchanged
|
| 81 |
+
|
| 82 |
+
- `document_converter.py` β
(no changes needed)
|
| 83 |
+
- `text_splitter.py` β
(no changes needed)
|
| 84 |
+
- `vector_store.py` β
(no changes needed)
|
| 85 |
+
- `README.md` β
(kept for local development)
|
| 86 |
+
- All documentation files β
|
| 87 |
+
|
| 88 |
+
## Architecture Comparison
|
| 89 |
+
|
| 90 |
+
### Before (Ollama)
|
| 91 |
+
```
|
| 92 |
+
User β Gradio β Vector Store β Ollama (Local) β Response
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
### After (HF Spaces)
|
| 96 |
+
```
|
| 97 |
+
User β Gradio β Vector Store β HF Inference API (Cloud) β Response
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
## Key Differences
|
| 101 |
+
|
| 102 |
+
| Aspect | Ollama (Before) | HF Spaces (After) |
|
| 103 |
+
|--------|----------------|-------------------|
|
| 104 |
+
| **Hosting** | Local only | Cloud (free) |
|
| 105 |
+
| **LLM** | llama3.2 (local) | Llama-3.2-3B-Instruct (cloud) |
|
| 106 |
+
| **Setup** | Install Ollama + model | Just HF token |
|
| 107 |
+
| **Cost** | Free (local compute) | Free (with rate limits) |
|
| 108 |
+
| **Availability** | Only when PC on | 24/7 |
|
| 109 |
+
| **Rate Limits** | None | ~1000 req/hour |
|
| 110 |
+
| **Scalability** | Limited by hardware | Managed by HF |
|
| 111 |
+
|
| 112 |
+
## Testing Checklist
|
| 113 |
+
|
| 114 |
+
Before deploying to HF Spaces, run:
|
| 115 |
+
|
| 116 |
+
```bash
|
| 117 |
+
# 1. Set HF token
|
| 118 |
+
export HF_TOKEN=hf_your_token_here
|
| 119 |
+
|
| 120 |
+
# 2. Install dependencies
|
| 121 |
+
pip install -r requirements.txt
|
| 122 |
+
|
| 123 |
+
# 3. Run tests
|
| 124 |
+
python test_hf_integration.py
|
| 125 |
+
|
| 126 |
+
# 4. Test locally
|
| 127 |
+
python app.py
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
## Deployment Steps
|
| 131 |
+
|
| 132 |
+
1. β
**Get HF Token**: https://huggingface.co/settings/tokens
|
| 133 |
+
2. β
**Test Locally**: Run `python test_hf_integration.py`
|
| 134 |
+
3. β³ **Create Space**: https://huggingface.co/new-space
|
| 135 |
+
4. β³ **Add Secret**: Space Settings β Repository secrets β `HF_TOKEN`
|
| 136 |
+
5. β³ **Push Code**: `git push hf main`
|
| 137 |
+
6. β³ **Verify**: Check Space URL and test
|
| 138 |
+
|
| 139 |
+
## Next Steps
|
| 140 |
+
|
| 141 |
+
### Immediate
|
| 142 |
+
1. Get Hugging Face token
|
| 143 |
+
2. Run local tests
|
| 144 |
+
3. Create HF Space
|
| 145 |
+
4. Deploy and verify
|
| 146 |
+
|
| 147 |
+
### Future Enhancements
|
| 148 |
+
- [ ] Add file upload functionality
|
| 149 |
+
- [ ] Support multiple documents
|
| 150 |
+
- [ ] Add conversation history
|
| 151 |
+
- [ ] Custom model selection
|
| 152 |
+
- [ ] Advanced filtering
|
| 153 |
+
- [ ] Export conversations
|
| 154 |
+
|
| 155 |
+
## Resources
|
| 156 |
+
|
| 157 |
+
- **HF Spaces Docs**: https://huggingface.co/docs/hub/spaces
|
| 158 |
+
- **HF Inference API**: https://huggingface.co/docs/api-inference/
|
| 159 |
+
- **Get Token**: https://huggingface.co/settings/tokens
|
| 160 |
+
- **Pricing**: https://huggingface.co/pricing
|
| 161 |
+
|
| 162 |
+
## Rollback Plan
|
| 163 |
+
|
| 164 |
+
If you need to revert to Ollama:
|
| 165 |
+
|
| 166 |
+
```bash
|
| 167 |
+
# Checkout previous commit
|
| 168 |
+
git log --oneline # Find commit before migration
|
| 169 |
+
git checkout <commit-hash>
|
| 170 |
+
|
| 171 |
+
# Or restore specific files
|
| 172 |
+
git checkout HEAD~1 llm_handler.py config.py requirements.txt
|
| 173 |
+
```
|
| 174 |
+
|
| 175 |
+
## Support
|
| 176 |
+
|
| 177 |
+
- **Documentation**: See `DEPLOYMENT_GUIDE.md`
|
| 178 |
+
- **Issues**: https://github.com/monsara/rag-python-rag/issues
|
| 179 |
+
- **HF Community**: https://discuss.huggingface.co/
|
| 180 |
+
|
| 181 |
+
---
|
| 182 |
+
|
| 183 |
+
**Migration completed**: β
All code changes done
|
| 184 |
+
**Ready to deploy**: β³ Awaiting HF Space creation and token setup
|
| 185 |
+
**Status**: Ready for testing and deployment
|
README_HF.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: RAG Python System
|
| 3 |
+
emoji: π€
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 4.44.1
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# RAG Python System π€
|
| 14 |
+
|
| 15 |
+
A local-first Retrieval-Augmented Generation (RAG) system that enables intelligent question-answering over your documents using Hugging Face Inference API, ChromaDB, and Gradio.
|
| 16 |
+
|
| 17 |
+
## Features
|
| 18 |
+
|
| 19 |
+
- π **Document Processing**: Converts PDF, DOCX, and TXT files to searchable format
|
| 20 |
+
- π **Semantic Search**: Uses sentence transformers for accurate context retrieval
|
| 21 |
+
- π€ **AI-Powered Answers**: Leverages Llama 3.2 3B via Hugging Face Inference API
|
| 22 |
+
- π¬ **Interactive UI**: Clean Gradio interface for easy interaction
|
| 23 |
+
- π― **Source Citations**: Provides references to source documents
|
| 24 |
+
|
| 25 |
+
## How It Works
|
| 26 |
+
|
| 27 |
+
1. **Document Ingestion**: Upload or use pre-loaded documents (currently includes "Think Python" guide)
|
| 28 |
+
2. **Semantic Chunking**: Documents are split into meaningful chunks
|
| 29 |
+
3. **Vector Embeddings**: Text chunks are converted to embeddings using `all-MiniLM-L6-v2`
|
| 30 |
+
4. **Context Retrieval**: Relevant chunks are retrieved based on your question
|
| 31 |
+
5. **Answer Generation**: Llama 3.2 generates answers using the retrieved context
|
| 32 |
+
|
| 33 |
+
## Setup Instructions
|
| 34 |
+
|
| 35 |
+
### For Hugging Face Spaces Deployment
|
| 36 |
+
|
| 37 |
+
1. **Fork or Duplicate this Space**
|
| 38 |
+
- Click the three dots menu β "Duplicate Space"
|
| 39 |
+
|
| 40 |
+
2. **Get Your Hugging Face Token**
|
| 41 |
+
- Go to [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)
|
| 42 |
+
- Create a new token with `read` permissions
|
| 43 |
+
- Copy the token (starts with `hf_`)
|
| 44 |
+
|
| 45 |
+
3. **Add Token to Space Secrets**
|
| 46 |
+
- Go to your Space Settings
|
| 47 |
+
- Navigate to "Repository secrets"
|
| 48 |
+
- Add a new secret:
|
| 49 |
+
- **Name**: `HF_TOKEN`
|
| 50 |
+
- **Value**: Your token from step 2
|
| 51 |
+
- Click "Add"
|
| 52 |
+
|
| 53 |
+
4. **Restart the Space**
|
| 54 |
+
- The Space will automatically rebuild and start
|
| 55 |
+
|
| 56 |
+
### For Local Development
|
| 57 |
+
|
| 58 |
+
1. **Clone the Repository**
|
| 59 |
+
```bash
|
| 60 |
+
git clone https://github.com/monsara/rag-python-rag.git
|
| 61 |
+
cd rag-python-rag
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
2. **Create Virtual Environment**
|
| 65 |
+
```bash
|
| 66 |
+
python -m venv venv
|
| 67 |
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
3. **Install Dependencies**
|
| 71 |
+
```bash
|
| 72 |
+
pip install -r requirements.txt
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
4. **Set Environment Variable**
|
| 76 |
+
```bash
|
| 77 |
+
export HF_TOKEN=hf_your_token_here
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
5. **Run the Application**
|
| 81 |
+
```bash
|
| 82 |
+
python app.py
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
6. **Access the Interface**
|
| 86 |
+
- Open your browser to `http://localhost:7860`
|
| 87 |
+
|
| 88 |
+
## Usage Examples
|
| 89 |
+
|
| 90 |
+
Try asking questions like:
|
| 91 |
+
|
| 92 |
+
- "How do if-else statements work in Python?"
|
| 93 |
+
- "What are the different types of loops in Python?"
|
| 94 |
+
- "How do you handle errors in Python?"
|
| 95 |
+
- "Explain Python functions with examples"
|
| 96 |
+
- "What is object-oriented programming in Python?"
|
| 97 |
+
|
| 98 |
+
## Architecture
|
| 99 |
+
|
| 100 |
+
```
|
| 101 |
+
User Query β Gradio UI β Vector Store (ChromaDB) β Context Retrieval
|
| 102 |
+
β
|
| 103 |
+
HF Inference API
|
| 104 |
+
β
|
| 105 |
+
Llama 3.2 3B
|
| 106 |
+
β
|
| 107 |
+
Formatted Response
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
## Tech Stack
|
| 111 |
+
|
| 112 |
+
- **Frontend**: Gradio 4.44.1
|
| 113 |
+
- **LLM**: Llama 3.2 3B Instruct (via Hugging Face Inference API)
|
| 114 |
+
- **Embeddings**: all-MiniLM-L6-v2 (Sentence Transformers)
|
| 115 |
+
- **Vector DB**: ChromaDB
|
| 116 |
+
- **Document Processing**: PyMuPDF, python-docx
|
| 117 |
+
- **Text Splitting**: LangChain Text Splitters
|
| 118 |
+
|
| 119 |
+
## Rate Limits
|
| 120 |
+
|
| 121 |
+
**Free Tier (Hugging Face Inference API):**
|
| 122 |
+
- ~1000 requests/hour
|
| 123 |
+
- 1024 max tokens per response
|
| 124 |
+
- Shared infrastructure
|
| 125 |
+
|
| 126 |
+
**For Production:**
|
| 127 |
+
Consider upgrading to [Hugging Face Pro](https://huggingface.co/pricing) ($9/month) for:
|
| 128 |
+
- Higher rate limits
|
| 129 |
+
- Faster inference
|
| 130 |
+
- Priority support
|
| 131 |
+
|
| 132 |
+
## Limitations
|
| 133 |
+
|
| 134 |
+
- Currently uses a single pre-loaded document ("Think Python")
|
| 135 |
+
- Free tier has rate limits
|
| 136 |
+
- Response quality depends on context relevance
|
| 137 |
+
- Max 1024 tokens per response
|
| 138 |
+
|
| 139 |
+
## Roadmap
|
| 140 |
+
|
| 141 |
+
- [ ] File upload functionality
|
| 142 |
+
- [ ] Multiple document support
|
| 143 |
+
- [ ] Conversation history
|
| 144 |
+
- [ ] Custom model selection
|
| 145 |
+
- [ ] Advanced filtering options
|
| 146 |
+
- [ ] Export conversation feature
|
| 147 |
+
|
| 148 |
+
## Contributing
|
| 149 |
+
|
| 150 |
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
| 151 |
+
|
| 152 |
+
## License
|
| 153 |
+
|
| 154 |
+
MIT License - see LICENSE file for details
|
| 155 |
+
|
| 156 |
+
## Links
|
| 157 |
+
|
| 158 |
+
- **GitHub Repository**: [monsara/rag-python-rag](https://github.com/monsara/rag-python-rag)
|
| 159 |
+
- **Documentation**: See [README.md](README.md) for detailed technical documentation
|
| 160 |
+
- **Hugging Face**: [Get your API token](https://huggingface.co/settings/tokens)
|
| 161 |
+
|
| 162 |
+
## Support
|
| 163 |
+
|
| 164 |
+
If you encounter issues:
|
| 165 |
+
|
| 166 |
+
1. Check that `HF_TOKEN` is set correctly in Space secrets
|
| 167 |
+
2. Verify your token has `read` permissions
|
| 168 |
+
3. Check the Space logs for error messages
|
| 169 |
+
4. Open an issue on GitHub
|
| 170 |
+
|
| 171 |
+
---
|
| 172 |
+
|
| 173 |
+
Built with β€οΈ using Hugging Face, Gradio, and ChromaDB
|
app.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Hugging Face Spaces Entry Point
|
| 3 |
+
This file is the main entry point for running the RAG system on HF Spaces
|
| 4 |
+
"""
|
| 5 |
+
import os
|
| 6 |
+
import sys
|
| 7 |
+
import logging
|
| 8 |
+
|
| 9 |
+
# Configure logging
|
| 10 |
+
logging.basicConfig(
|
| 11 |
+
level=logging.INFO,
|
| 12 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
| 13 |
+
)
|
| 14 |
+
logger = logging.getLogger(__name__)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def validate_hf_token():
|
| 18 |
+
"""
|
| 19 |
+
Validate that HF_TOKEN is set
|
| 20 |
+
|
| 21 |
+
Returns:
|
| 22 |
+
True if token is valid, False otherwise
|
| 23 |
+
"""
|
| 24 |
+
token = os.getenv("HF_TOKEN", "")
|
| 25 |
+
|
| 26 |
+
if not token:
|
| 27 |
+
logger.error(
|
| 28 |
+
"β HF_TOKEN not found! Please set it in Space Settings β Repository secrets"
|
| 29 |
+
)
|
| 30 |
+
return False
|
| 31 |
+
|
| 32 |
+
if not token.startswith("hf_"):
|
| 33 |
+
logger.error(
|
| 34 |
+
"β Invalid HF_TOKEN format. Token should start with 'hf_'"
|
| 35 |
+
)
|
| 36 |
+
return False
|
| 37 |
+
|
| 38 |
+
logger.info("β
HF_TOKEN validated successfully")
|
| 39 |
+
return True
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def main():
|
| 43 |
+
"""
|
| 44 |
+
Main entry point for Hugging Face Spaces
|
| 45 |
+
"""
|
| 46 |
+
logger.info("π Starting RAG System on Hugging Face Spaces...")
|
| 47 |
+
|
| 48 |
+
# Validate HF token
|
| 49 |
+
if not validate_hf_token():
|
| 50 |
+
logger.error(
|
| 51 |
+
"\n" + "="*60 + "\n"
|
| 52 |
+
"SETUP REQUIRED:\n"
|
| 53 |
+
"1. Go to your Space Settings\n"
|
| 54 |
+
"2. Navigate to 'Repository secrets'\n"
|
| 55 |
+
"3. Add a new secret:\n"
|
| 56 |
+
" - Name: HF_TOKEN\n"
|
| 57 |
+
" - Value: Your Hugging Face token from https://huggingface.co/settings/tokens\n"
|
| 58 |
+
"4. Restart the Space\n"
|
| 59 |
+
+ "="*60
|
| 60 |
+
)
|
| 61 |
+
sys.exit(1)
|
| 62 |
+
|
| 63 |
+
# Import main application after token validation
|
| 64 |
+
from main import rag_system, create_gradio_interface
|
| 65 |
+
|
| 66 |
+
# Setup the pipeline
|
| 67 |
+
logger.info("Setting up RAG pipeline...")
|
| 68 |
+
success = rag_system.setup_pipeline(force_rebuild=False)
|
| 69 |
+
|
| 70 |
+
if not success:
|
| 71 |
+
logger.error("Failed to setup RAG pipeline. Please check the logs.")
|
| 72 |
+
sys.exit(1)
|
| 73 |
+
|
| 74 |
+
# Create and launch Gradio interface
|
| 75 |
+
logger.info("Creating Gradio interface...")
|
| 76 |
+
interface = create_gradio_interface()
|
| 77 |
+
|
| 78 |
+
logger.info("Launching web interface on Hugging Face Spaces...")
|
| 79 |
+
|
| 80 |
+
# Launch without share (not needed on HF Spaces)
|
| 81 |
+
# HF Spaces automatically provides the public URL
|
| 82 |
+
interface.queue().launch(
|
| 83 |
+
share=False, # No need for share on HF Spaces
|
| 84 |
+
server_name="0.0.0.0",
|
| 85 |
+
server_port=7860,
|
| 86 |
+
show_error=True,
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
if __name__ == "__main__":
|
| 91 |
+
main()
|
config.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
| 2 |
Configuration file for RAG System
|
| 3 |
Contains all settings and parameters for the document processing pipeline
|
| 4 |
"""
|
|
|
|
| 5 |
from pathlib import Path
|
| 6 |
from typing import List
|
| 7 |
|
|
@@ -35,9 +36,9 @@ EMBEDDING_DIMENSION = 384
|
|
| 35 |
CHROMA_COLLECTION_NAME = "document_embeddings"
|
| 36 |
CHROMA_DISTANCE_METRIC = "cosine"
|
| 37 |
|
| 38 |
-
# LLM Configuration
|
| 39 |
-
|
| 40 |
-
|
| 41 |
|
| 42 |
# Retrieval Configuration
|
| 43 |
DEFAULT_N_RESULTS = 5
|
|
@@ -65,7 +66,7 @@ GRADIO_CONFIG = {
|
|
| 65 |
"What is object-oriented programming in Python?",
|
| 66 |
],
|
| 67 |
"theme": "default",
|
| 68 |
-
"share":
|
| 69 |
}
|
| 70 |
|
| 71 |
# Test Document URL (Think Python book)
|
|
|
|
| 2 |
Configuration file for RAG System
|
| 3 |
Contains all settings and parameters for the document processing pipeline
|
| 4 |
"""
|
| 5 |
+
import os
|
| 6 |
from pathlib import Path
|
| 7 |
from typing import List
|
| 8 |
|
|
|
|
| 36 |
CHROMA_COLLECTION_NAME = "document_embeddings"
|
| 37 |
CHROMA_DISTANCE_METRIC = "cosine"
|
| 38 |
|
| 39 |
+
# LLM Configuration - Hugging Face Inference API
|
| 40 |
+
HF_MODEL = "meta-llama/Llama-3.2-3B-Instruct"
|
| 41 |
+
HF_TOKEN = os.getenv("HF_TOKEN", "")
|
| 42 |
|
| 43 |
# Retrieval Configuration
|
| 44 |
DEFAULT_N_RESULTS = 5
|
|
|
|
| 66 |
"What is object-oriented programming in Python?",
|
| 67 |
],
|
| 68 |
"theme": "default",
|
| 69 |
+
"share": True, # Creates public link for 72 hours # Set to True to create a public link
|
| 70 |
}
|
| 71 |
|
| 72 |
# Test Document URL (Think Python book)
|
llm_handler.py
CHANGED
|
@@ -1,14 +1,15 @@
|
|
| 1 |
"""
|
| 2 |
LLM Handler Module
|
| 3 |
-
Manages interaction with
|
| 4 |
"""
|
| 5 |
-
import
|
| 6 |
from typing import Generator, Dict, List
|
| 7 |
import logging
|
|
|
|
| 8 |
|
| 9 |
from config import (
|
| 10 |
-
|
| 11 |
-
|
| 12 |
SYSTEM_PROMPT,
|
| 13 |
PROMPT_TEMPLATE,
|
| 14 |
)
|
|
@@ -20,56 +21,28 @@ logger = logging.getLogger(__name__)
|
|
| 20 |
|
| 21 |
class LLMHandler:
|
| 22 |
"""
|
| 23 |
-
Handles LLM interactions using
|
| 24 |
"""
|
| 25 |
|
| 26 |
-
def __init__(self, model: str =
|
| 27 |
"""
|
| 28 |
Initialize the LLM handler
|
| 29 |
|
| 30 |
Args:
|
| 31 |
-
model: Name of the
|
|
|
|
| 32 |
"""
|
| 33 |
self.model = model
|
| 34 |
-
self.
|
| 35 |
-
logger.info(f"Initialized LLM handler with model: {model}")
|
| 36 |
-
|
| 37 |
-
# Verify model is available
|
| 38 |
-
try:
|
| 39 |
-
self.verify_model()
|
| 40 |
-
except Exception as e:
|
| 41 |
-
logger.error(f"Failed to verify model: {e}")
|
| 42 |
-
raise
|
| 43 |
-
|
| 44 |
-
def verify_model(self) -> bool:
|
| 45 |
-
"""
|
| 46 |
-
Verify that the model is available in Ollama
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
models = self.client.list()
|
| 53 |
-
available_models = [m.model for m in models.models]
|
| 54 |
-
|
| 55 |
-
# Check if model name matches any available model
|
| 56 |
-
model_available = any(
|
| 57 |
-
self.model in model_name
|
| 58 |
-
for model_name in available_models
|
| 59 |
)
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
return True
|
| 64 |
-
else:
|
| 65 |
-
logger.error(
|
| 66 |
-
f"Model {self.model} not found. "
|
| 67 |
-
f"Available models: {available_models}"
|
| 68 |
-
)
|
| 69 |
-
return False
|
| 70 |
-
except Exception as e:
|
| 71 |
-
logger.error(f"Error verifying model: {e}")
|
| 72 |
-
raise
|
| 73 |
|
| 74 |
def generate_answer(
|
| 75 |
self,
|
|
@@ -88,24 +61,30 @@ class LLMHandler:
|
|
| 88 |
Returns:
|
| 89 |
Generated answer
|
| 90 |
"""
|
| 91 |
-
# Format the prompt
|
| 92 |
-
|
| 93 |
-
context=context,
|
| 94 |
-
question=question
|
| 95 |
-
)
|
| 96 |
|
| 97 |
try:
|
| 98 |
-
response = self.client.generate(
|
| 99 |
-
model=self.model,
|
| 100 |
-
prompt=prompt,
|
| 101 |
-
system=SYSTEM_PROMPT,
|
| 102 |
-
stream=stream,
|
| 103 |
-
)
|
| 104 |
-
|
| 105 |
if not stream:
|
| 106 |
-
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
except Exception as e:
|
| 111 |
logger.error(f"Error generating answer: {e}")
|
|
@@ -126,23 +105,22 @@ class LLMHandler:
|
|
| 126 |
Yields:
|
| 127 |
Generated text tokens
|
| 128 |
"""
|
| 129 |
-
# Format the prompt
|
| 130 |
-
|
| 131 |
-
context=context,
|
| 132 |
-
question=question
|
| 133 |
-
)
|
| 134 |
|
| 135 |
try:
|
| 136 |
-
stream = self.client.
|
|
|
|
| 137 |
model=self.model,
|
| 138 |
-
|
| 139 |
-
|
|
|
|
| 140 |
stream=True,
|
|
|
|
| 141 |
)
|
| 142 |
|
| 143 |
-
for
|
| 144 |
-
|
| 145 |
-
yield chunk['response']
|
| 146 |
|
| 147 |
except Exception as e:
|
| 148 |
logger.error(f"Error streaming answer: {e}")
|
|
|
|
| 1 |
"""
|
| 2 |
LLM Handler Module
|
| 3 |
+
Manages interaction with Hugging Face Inference API for answer generation
|
| 4 |
"""
|
| 5 |
+
import os
|
| 6 |
from typing import Generator, Dict, List
|
| 7 |
import logging
|
| 8 |
+
from huggingface_hub import InferenceClient
|
| 9 |
|
| 10 |
from config import (
|
| 11 |
+
HF_MODEL,
|
| 12 |
+
HF_TOKEN,
|
| 13 |
SYSTEM_PROMPT,
|
| 14 |
PROMPT_TEMPLATE,
|
| 15 |
)
|
|
|
|
| 21 |
|
| 22 |
class LLMHandler:
|
| 23 |
"""
|
| 24 |
+
Handles LLM interactions using Hugging Face Inference API
|
| 25 |
"""
|
| 26 |
|
| 27 |
+
def __init__(self, model: str = HF_MODEL, token: str = None):
|
| 28 |
"""
|
| 29 |
Initialize the LLM handler
|
| 30 |
|
| 31 |
Args:
|
| 32 |
+
model: Name of the Hugging Face model to use
|
| 33 |
+
token: HF API token (if not provided, will use HF_TOKEN from config)
|
| 34 |
"""
|
| 35 |
self.model = model
|
| 36 |
+
self.token = token or HF_TOKEN
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
+
if not self.token:
|
| 39 |
+
raise ValueError(
|
| 40 |
+
"Hugging Face token not found. Please set HF_TOKEN environment variable "
|
| 41 |
+
"or pass it to the constructor."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
)
|
| 43 |
+
|
| 44 |
+
self.client = InferenceClient(token=self.token)
|
| 45 |
+
logger.info(f"Initialized LLM handler with model: {model}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
def generate_answer(
|
| 48 |
self,
|
|
|
|
| 61 |
Returns:
|
| 62 |
Generated answer
|
| 63 |
"""
|
| 64 |
+
# Format the prompt with system prompt, context, and question
|
| 65 |
+
full_prompt = f"{SYSTEM_PROMPT}\n\n{PROMPT_TEMPLATE.format(context=context, question=question)}"
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
if not stream:
|
| 69 |
+
response = self.client.text_generation(
|
| 70 |
+
prompt=full_prompt,
|
| 71 |
+
model=self.model,
|
| 72 |
+
max_new_tokens=1024,
|
| 73 |
+
temperature=0.7,
|
| 74 |
+
top_p=0.95,
|
| 75 |
+
stream=False,
|
| 76 |
+
)
|
| 77 |
return response
|
| 78 |
+
else:
|
| 79 |
+
# Return generator for streaming
|
| 80 |
+
return self.client.text_generation(
|
| 81 |
+
prompt=full_prompt,
|
| 82 |
+
model=self.model,
|
| 83 |
+
max_new_tokens=1024,
|
| 84 |
+
temperature=0.7,
|
| 85 |
+
top_p=0.95,
|
| 86 |
+
stream=True,
|
| 87 |
+
)
|
| 88 |
|
| 89 |
except Exception as e:
|
| 90 |
logger.error(f"Error generating answer: {e}")
|
|
|
|
| 105 |
Yields:
|
| 106 |
Generated text tokens
|
| 107 |
"""
|
| 108 |
+
# Format the prompt with system prompt, context, and question
|
| 109 |
+
full_prompt = f"{SYSTEM_PROMPT}\n\n{PROMPT_TEMPLATE.format(context=context, question=question)}"
|
|
|
|
|
|
|
|
|
|
| 110 |
|
| 111 |
try:
|
| 112 |
+
stream = self.client.text_generation(
|
| 113 |
+
prompt=full_prompt,
|
| 114 |
model=self.model,
|
| 115 |
+
max_new_tokens=1024,
|
| 116 |
+
temperature=0.7,
|
| 117 |
+
top_p=0.95,
|
| 118 |
stream=True,
|
| 119 |
+
details=False,
|
| 120 |
)
|
| 121 |
|
| 122 |
+
for token in stream:
|
| 123 |
+
yield token
|
|
|
|
| 124 |
|
| 125 |
except Exception as e:
|
| 126 |
logger.error(f"Error streaming answer: {e}")
|
main.py
CHANGED
|
@@ -2,11 +2,12 @@
|
|
| 2 |
Main RAG Application
|
| 3 |
Combines all components and provides a Gradio web interface
|
| 4 |
"""
|
|
|
|
| 5 |
import gradio as gr
|
| 6 |
import logging
|
| 7 |
from typing import Generator
|
| 8 |
|
| 9 |
-
from config import GRADIO_CONFIG, DEFAULT_N_RESULTS
|
| 10 |
from document_converter import download_test_document, convert_all_documents
|
| 11 |
from text_splitter import process_all_documents
|
| 12 |
from vector_store import VectorStore, retrieve_context
|
|
@@ -183,6 +184,16 @@ def main():
|
|
| 183 |
"""
|
| 184 |
logger.info("π Starting RAG System...")
|
| 185 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
# Setup the pipeline
|
| 187 |
logger.info("Setting up RAG pipeline...")
|
| 188 |
success = rag_system.setup_pipeline(force_rebuild=False)
|
|
|
|
| 2 |
Main RAG Application
|
| 3 |
Combines all components and provides a Gradio web interface
|
| 4 |
"""
|
| 5 |
+
import os
|
| 6 |
import gradio as gr
|
| 7 |
import logging
|
| 8 |
from typing import Generator
|
| 9 |
|
| 10 |
+
from config import GRADIO_CONFIG, DEFAULT_N_RESULTS, HF_TOKEN
|
| 11 |
from document_converter import download_test_document, convert_all_documents
|
| 12 |
from text_splitter import process_all_documents
|
| 13 |
from vector_store import VectorStore, retrieve_context
|
|
|
|
| 184 |
"""
|
| 185 |
logger.info("π Starting RAG System...")
|
| 186 |
|
| 187 |
+
# Validate HF token
|
| 188 |
+
if not HF_TOKEN:
|
| 189 |
+
logger.warning(
|
| 190 |
+
"β οΈ HF_TOKEN not set. Please set the HF_TOKEN environment variable.\n"
|
| 191 |
+
"Get your token from: https://huggingface.co/settings/tokens"
|
| 192 |
+
)
|
| 193 |
+
logger.info("Continuing without HF token validation (may fail during LLM calls)...")
|
| 194 |
+
else:
|
| 195 |
+
logger.info("β
HF_TOKEN found")
|
| 196 |
+
|
| 197 |
# Setup the pipeline
|
| 198 |
logger.info("Setting up RAG pipeline...")
|
| 199 |
success = rag_system.setup_pipeline(force_rebuild=False)
|
requirements.txt
CHANGED
|
@@ -12,9 +12,8 @@ langchain-text-splitters==0.3.2
|
|
| 12 |
# Vector Database
|
| 13 |
chromadb==0.5.23
|
| 14 |
|
| 15 |
-
# LLM Integration
|
| 16 |
-
|
| 17 |
-
langchain-ollama==0.2.2
|
| 18 |
|
| 19 |
# Web Interface (max version for Python 3.9)
|
| 20 |
gradio==4.44.1
|
|
|
|
| 12 |
# Vector Database
|
| 13 |
chromadb==0.5.23
|
| 14 |
|
| 15 |
+
# LLM Integration - Hugging Face
|
| 16 |
+
huggingface_hub==0.20.3
|
|
|
|
| 17 |
|
| 18 |
# Web Interface (max version for Python 3.9)
|
| 19 |
gradio==4.44.1
|
test_hf_integration.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Test script for Hugging Face Inference API integration
|
| 3 |
+
Run this to verify the setup before deploying to HF Spaces
|
| 4 |
+
"""
|
| 5 |
+
import os
|
| 6 |
+
import sys
|
| 7 |
+
import logging
|
| 8 |
+
|
| 9 |
+
# Configure logging
|
| 10 |
+
logging.basicConfig(
|
| 11 |
+
level=logging.INFO,
|
| 12 |
+
format='%(asctime)s - %(levelname)s - %(message)s'
|
| 13 |
+
)
|
| 14 |
+
logger = logging.getLogger(__name__)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def test_hf_token():
|
| 18 |
+
"""Test if HF_TOKEN is set"""
|
| 19 |
+
logger.info("Testing HF_TOKEN...")
|
| 20 |
+
token = os.getenv("HF_TOKEN", "")
|
| 21 |
+
|
| 22 |
+
if not token:
|
| 23 |
+
logger.error("β HF_TOKEN not found!")
|
| 24 |
+
logger.info("Please set it: export HF_TOKEN=hf_your_token_here")
|
| 25 |
+
return False
|
| 26 |
+
|
| 27 |
+
if not token.startswith("hf_"):
|
| 28 |
+
logger.error("β Invalid HF_TOKEN format (should start with 'hf_')")
|
| 29 |
+
return False
|
| 30 |
+
|
| 31 |
+
logger.info(f"β
HF_TOKEN found: {token[:10]}...")
|
| 32 |
+
return True
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def test_imports():
|
| 36 |
+
"""Test if all required packages are installed"""
|
| 37 |
+
logger.info("\nTesting imports...")
|
| 38 |
+
|
| 39 |
+
required_packages = [
|
| 40 |
+
("huggingface_hub", "Hugging Face Hub"),
|
| 41 |
+
("gradio", "Gradio"),
|
| 42 |
+
("chromadb", "ChromaDB"),
|
| 43 |
+
("sentence_transformers", "Sentence Transformers"),
|
| 44 |
+
("langchain_text_splitters", "LangChain Text Splitters"),
|
| 45 |
+
]
|
| 46 |
+
|
| 47 |
+
all_ok = True
|
| 48 |
+
for package, name in required_packages:
|
| 49 |
+
try:
|
| 50 |
+
__import__(package)
|
| 51 |
+
logger.info(f"β
{name} installed")
|
| 52 |
+
except ImportError:
|
| 53 |
+
logger.error(f"β {name} not installed")
|
| 54 |
+
all_ok = False
|
| 55 |
+
|
| 56 |
+
return all_ok
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def test_hf_api():
|
| 60 |
+
"""Test Hugging Face Inference API connection"""
|
| 61 |
+
logger.info("\nTesting HF Inference API...")
|
| 62 |
+
|
| 63 |
+
try:
|
| 64 |
+
from huggingface_hub import InferenceClient
|
| 65 |
+
from config import HF_TOKEN, HF_MODEL
|
| 66 |
+
|
| 67 |
+
if not HF_TOKEN:
|
| 68 |
+
logger.error("β Cannot test API without HF_TOKEN")
|
| 69 |
+
return False
|
| 70 |
+
|
| 71 |
+
client = InferenceClient(token=HF_TOKEN)
|
| 72 |
+
|
| 73 |
+
# Test with a simple prompt
|
| 74 |
+
logger.info(f"Testing model: {HF_MODEL}")
|
| 75 |
+
logger.info("Sending test request...")
|
| 76 |
+
|
| 77 |
+
response = client.text_generation(
|
| 78 |
+
prompt="Say 'Hello, World!' and nothing else.",
|
| 79 |
+
model=HF_MODEL,
|
| 80 |
+
max_new_tokens=20,
|
| 81 |
+
temperature=0.1,
|
| 82 |
+
)
|
| 83 |
+
|
| 84 |
+
logger.info(f"β
API Response: {response}")
|
| 85 |
+
return True
|
| 86 |
+
|
| 87 |
+
except Exception as e:
|
| 88 |
+
logger.error(f"β API Test failed: {e}")
|
| 89 |
+
return False
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def test_llm_handler():
|
| 93 |
+
"""Test the LLM handler module"""
|
| 94 |
+
logger.info("\nTesting LLM Handler...")
|
| 95 |
+
|
| 96 |
+
try:
|
| 97 |
+
from llm_handler import LLMHandler
|
| 98 |
+
|
| 99 |
+
llm = LLMHandler()
|
| 100 |
+
logger.info("β
LLM Handler initialized")
|
| 101 |
+
|
| 102 |
+
# Test answer generation
|
| 103 |
+
logger.info("Testing answer generation...")
|
| 104 |
+
test_question = "What is 2+2?"
|
| 105 |
+
test_context = "Basic arithmetic: 2+2 equals 4."
|
| 106 |
+
|
| 107 |
+
answer = llm.generate_answer(test_question, test_context, stream=False)
|
| 108 |
+
logger.info(f"β
Generated answer: {answer[:100]}...")
|
| 109 |
+
|
| 110 |
+
return True
|
| 111 |
+
|
| 112 |
+
except Exception as e:
|
| 113 |
+
logger.error(f"β LLM Handler test failed: {e}")
|
| 114 |
+
return False
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def test_vector_store():
|
| 118 |
+
"""Test vector store initialization"""
|
| 119 |
+
logger.info("\nTesting Vector Store...")
|
| 120 |
+
|
| 121 |
+
try:
|
| 122 |
+
from vector_store import VectorStore
|
| 123 |
+
|
| 124 |
+
vs = VectorStore()
|
| 125 |
+
logger.info("β
Vector Store initialized")
|
| 126 |
+
|
| 127 |
+
stats = vs.get_collection_stats()
|
| 128 |
+
logger.info(f"β
Collection stats: {stats}")
|
| 129 |
+
|
| 130 |
+
return True
|
| 131 |
+
|
| 132 |
+
except Exception as e:
|
| 133 |
+
logger.error(f"β Vector Store test failed: {e}")
|
| 134 |
+
return False
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def main():
|
| 138 |
+
"""Run all tests"""
|
| 139 |
+
logger.info("="*60)
|
| 140 |
+
logger.info("RAG System - Hugging Face Integration Tests")
|
| 141 |
+
logger.info("="*60)
|
| 142 |
+
|
| 143 |
+
tests = [
|
| 144 |
+
("HF Token", test_hf_token),
|
| 145 |
+
("Package Imports", test_imports),
|
| 146 |
+
("HF API Connection", test_hf_api),
|
| 147 |
+
("LLM Handler", test_llm_handler),
|
| 148 |
+
("Vector Store", test_vector_store),
|
| 149 |
+
]
|
| 150 |
+
|
| 151 |
+
results = {}
|
| 152 |
+
for test_name, test_func in tests:
|
| 153 |
+
try:
|
| 154 |
+
results[test_name] = test_func()
|
| 155 |
+
except Exception as e:
|
| 156 |
+
logger.error(f"β {test_name} crashed: {e}")
|
| 157 |
+
results[test_name] = False
|
| 158 |
+
|
| 159 |
+
# Summary
|
| 160 |
+
logger.info("\n" + "="*60)
|
| 161 |
+
logger.info("Test Summary")
|
| 162 |
+
logger.info("="*60)
|
| 163 |
+
|
| 164 |
+
for test_name, passed in results.items():
|
| 165 |
+
status = "β
PASS" if passed else "β FAIL"
|
| 166 |
+
logger.info(f"{status} - {test_name}")
|
| 167 |
+
|
| 168 |
+
all_passed = all(results.values())
|
| 169 |
+
|
| 170 |
+
logger.info("="*60)
|
| 171 |
+
if all_passed:
|
| 172 |
+
logger.info("π All tests passed! Ready to deploy to HF Spaces.")
|
| 173 |
+
logger.info("\nNext steps:")
|
| 174 |
+
logger.info("1. Create a new Space at https://huggingface.co/new-space")
|
| 175 |
+
logger.info("2. Choose 'Gradio' as SDK")
|
| 176 |
+
logger.info("3. Add HF_TOKEN to Space secrets")
|
| 177 |
+
logger.info("4. Push code to the Space repository")
|
| 178 |
+
return 0
|
| 179 |
+
else:
|
| 180 |
+
logger.error("β Some tests failed. Please fix the issues before deploying.")
|
| 181 |
+
return 1
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
if __name__ == "__main__":
|
| 185 |
+
sys.exit(main())
|