Spaces:
Sleeping
Sleeping
| # FastAPI + Streamlit + Groq Project Setup Rules | |
| ## Project Structure | |
| ``` | |
| . | |
| βββ app/ | |
| β βββ __init__.py | |
| β βββ main.py # FastAPI application | |
| β βββ models/ | |
| β β βββ __init__.py | |
| β β βββ base.py # Pydantic models | |
| β βββ services/ | |
| β β βββ __init__.py | |
| β β βββ llm.py # LLM integration | |
| β βββ utils/ | |
| β βββ __init__.py | |
| β βββ helpers.py # Utility functions | |
| βββ frontend/ | |
| β βββ __init__.py | |
| β βββ app.py # Streamlit application | |
| βββ data/ # Data storage | |
| βββ tests/ | |
| β βββ __init__.py | |
| β βββ test_api.py | |
| β βββ test_services.py | |
| βββ .env # Environment variables | |
| βββ .gitignore | |
| βββ README.md | |
| βββ requirements.txt | |
| βββ run.py # Application entry point | |
| ``` | |
| ## Required Dependencies | |
| ```python | |
| # requirements.txt | |
| fastapi>=0.100.0 | |
| uvicorn>=0.22.0 | |
| pydantic>=2.0.0 | |
| streamlit>=1.25.0 | |
| requests>=2.31.0 | |
| python-multipart>=0.0.6 | |
| python-dotenv>=1.0.0 | |
| groq>=0.4.0 | |
| pytest>=7.4.0 | |
| httpx>=0.24.0 # For testing | |
| ``` | |
| ## Environment Variables | |
| ```bash | |
| # .env | |
| GROQ_API_KEY=your-api-key | |
| ENVIRONMENT=development | |
| CORS_ORIGINS=["http://localhost:8501"] | |
| ``` | |
| ## Best Practices | |
| ### FastAPI Setup | |
| ```python | |
| # app/main.py | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from dotenv import load_dotenv | |
| import os | |
| # Load environment variables | |
| load_dotenv() | |
| app = FastAPI( | |
| title="Your App Name", | |
| description="Your app description", | |
| version="1.0.0" | |
| ) | |
| # CORS setup | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=json.loads(os.getenv("CORS_ORIGINS", '["http://localhost:8501"]')), | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Error handling | |
| @app.exception_handler(HTTPException) | |
| async def http_exception_handler(request, exc): | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content={"detail": exc.detail}, | |
| ) | |
| ``` | |
| ### Pydantic Models | |
| ```python | |
| # app/models/base.py | |
| from pydantic import BaseModel, Field | |
| from typing import Optional, List | |
| from datetime import datetime | |
| from uuid import UUID, uuid4 | |
| class BaseModelWithTimestamp(BaseModel): | |
| id: UUID = Field(default_factory=uuid4) | |
| created_at: datetime = Field(default_factory=datetime.utcnow) | |
| updated_at: datetime = Field(default_factory=datetime.utcnow) | |
| def model_dump(self, *args, **kwargs): | |
| data = super().model_dump(*args, **kwargs) | |
| # Convert UUID and datetime to string | |
| data['id'] = str(data['id']) | |
| data['created_at'] = data['created_at'].isoformat() | |
| data['updated_at'] = data['updated_at'].isoformat() | |
| return data | |
| ``` | |
| ### Streamlit Setup | |
| ```python | |
| # frontend/app.py | |
| import streamlit as st | |
| import requests | |
| from typing import Dict, List | |
| import os | |
| from dotenv import load_dotenv | |
| # Load environment variables | |
| load_dotenv() | |
| # Page config | |
| st.set_page_config( | |
| page_title="Your App Name", | |
| page_icon="π", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # API client setup | |
| class APIClient: | |
| def __init__(self): | |
| self.base_url = os.getenv("API_URL", "http://localhost:8000") | |
| def _handle_response(self, response): | |
| if response.ok: | |
| return response.json() | |
| st.error(f"Error: {response.status_code} - {response.text}") | |
| return None | |
| def get(self, endpoint: str): | |
| try: | |
| response = requests.get(f"{self.base_url}{endpoint}") | |
| return self._handle_response(response) | |
| except Exception as e: | |
| st.error(f"API Error: {str(e)}") | |
| return None | |
| api = APIClient() | |
| ``` | |
| ### LLM Integration | |
| ```python | |
| # app/services/llm.py | |
| from groq import Groq | |
| from dotenv import load_dotenv | |
| import os | |
| import json | |
| from typing import List, Dict, Any | |
| load_dotenv() | |
| class LLMService: | |
| def __init__(self): | |
| api_key = os.getenv("GROQ_API_KEY") | |
| if not api_key: | |
| raise ValueError("GROQ_API_KEY not set") | |
| self.client = Groq(api_key=api_key) | |
| def _handle_response(self, response_text: str) -> Dict[str, Any]: | |
| try: | |
| return json.loads(response_text) | |
| except json.JSONDecodeError as e: | |
| print(f"Error parsing LLM response: {e}") | |
| return None | |
| ``` | |
| ### Data Storage | |
| ```python | |
| # app/utils/storage.py | |
| import json | |
| from pathlib import Path | |
| from typing import Dict, Any | |
| from fastapi import HTTPException | |
| class JSONStorage: | |
| def __init__(self, file_path: str): | |
| self.file_path = Path(file_path) | |
| self.file_path.parent.mkdir(exist_ok=True) | |
| def read(self) -> Dict[str, Any]: | |
| try: | |
| if not self.file_path.exists(): | |
| return {} | |
| with open(self.file_path, 'r') as f: | |
| return json.load(f) | |
| except json.JSONDecodeError: | |
| return {} | |
| def write(self, data: Dict[str, Any]): | |
| temp_file = self.file_path.with_suffix('.tmp') | |
| try: | |
| with open(temp_file, 'w') as f: | |
| json.dump(data, f, indent=2) | |
| temp_file.replace(self.file_path) | |
| except Exception as e: | |
| if temp_file.exists(): | |
| temp_file.unlink() | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| ``` | |
| ## Common Issues & Solutions | |
| 1. **Environment Variables** | |
| - Always use python-dotenv | |
| - Check variables at startup | |
| - Provide clear error messages | |
| 2. **JSON Handling** | |
| - Always use try-except for JSON operations | |
| - Implement atomic writes | |
| - Validate data before saving | |
| 3. **API Errors** | |
| - Implement proper error handling | |
| - Use appropriate HTTP status codes | |
| - Return meaningful error messages | |
| 4. **LLM Integration** | |
| - Handle malformed responses | |
| - Implement fallback mechanisms | |
| - Cache expensive operations | |
| 5. **Frontend** | |
| - Show loading states | |
| - Handle API errors gracefully | |
| - Validate input before submission | |
| 6. **Testing** | |
| - Write tests for API endpoints | |
| - Mock external services | |
| - Test error conditions | |
| ## Security Considerations | |
| 1. **Environment Variables** | |
| - Never commit .env files | |
| - Use secure secrets management in production | |
| 2. **API Security** | |
| - Implement rate limiting | |
| - Add authentication when needed | |
| - Validate all inputs | |
| 3. **CORS** | |
| - Restrict origins in production | |
| - Only allow necessary methods | |
| - Handle credentials properly | |
| 4. **Data Storage** | |
| - Implement backup mechanisms | |
| - Use atomic operations | |
| - Validate data integrity | |