A Django web application that provides an interface for interacting with Large Language Models (LLMs) through API calls while storing conversation metadata for analysis and management.
Live webpage: LLM_Django_app
- Multi-Model Support: Interact with various LLM models including Llama 3.3, Qwen3, and Phi4-reasoning
- Conversation Management: Store, view, and manage conversation history with detailed metadata
- File Upload Support: Upload and process files (.txt, .doc, .json, .csv) as context for conversations
- Configurable Parameters: Adjust model parameters like temperature, top-k, top-p, and max tokens
- User Authentication: Secure user authentication with Django Allauth
- Admin Interface: Django admin panel for managing conversations and metadata
- JSON Viewer: Built-in JSON file viewer and table display functionality
- Responsive Design: Clean, user-friendly interface
main/
├── LLM_Metadata/ # Main application directory
│ ├── migrations/ # Database migrations
│ ├── templatetags/ # Custom template filters
│ ├── admin.py # Django admin configuration
│ ├── apps.py # App configuration
│ ├── forms.py # Django forms
│ ├── models.py # Database models
│ ├── urls.py # URL routing
│ ├── utils.py # API utility functions
│ └── views.py # View functions
├── main/ # Project configuration
│ ├── settings.py # Django settings
│ ├── urls.py # Main URL configuration
│ ├── wsgi.py # WSGI configuration
│ └── asgi.py # ASGI configuration
└── templates/ # HTML templates
┌─────────────────────────────────────────────────────────────────┐
│ User Browser │
│ (HTML/CSS/JavaScript + Bootstrap) │
└────────────────┬────────────────────────────────────────────────┘
│ HTTP/HTTPS
│
┌────────────────▼────────────────────────────────────────────────┐
│ Heroku Platform │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Gunicorn WSGI Server │ │
│ │ (Multiple Workers) │ │
│ └────────────────┬────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────▼────────────────────────────────────────────┐ │
│ │ Django Application │ │
│ │ ┌──────────────────────────────────────────────────────┐ │ │
│ │ │ URL Router (urls.py) │ │ │
│ │ │ / → home │ │ │
│ │ │ /ask/ → ask_question_view │ │ │
│ │ │ /conversation/ → conversation_view │ │ │
│ │ │ /admin/ → Django Admin │ │ │
│ │ │ /accounts/ → Django Allauth │ │ │
│ │ └────────────┬─────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌────────────▼─────────────────────────────────────────┐ │ │
│ │ │ Views (views.py) │ │ │
│ │ │ - Business Logic │ │ │
│ │ │ - Request Handling │ │ │
│ │ │ - Response Generation │ │ │
│ │ └────┬────────────────────────────────┬─────────────────┘ │ │
│ │ │ │ │ │
│ │ ┌────▼──────────┐ ┌─────▼──────────┐ │ │
│ │ │ Forms │ │ Models │ │ │
│ │ │ (forms.py) │ │ (models.py) │ │ │
│ │ │ - Validation │ │ - ORM │ │ │
│ │ │ - Cleaning │ │ - DB Schema │ │ │
│ │ └───────────────┘ └────┬────────────┘ │ │
│ │ │ │ │
│ │ ┌───────────────────────────────────▼──────────────────┐ │ │
│ │ │ Templates (templates/) │ │ │
│ │ │ - HTML rendering with Django template engine │ │ │
│ │ └────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
└───────┬─────────────────────────────────┬──────────────────────────┘
│ │
│ SQL Queries │ HTTP API Calls
│ │
┌───────▼────────────────┐ ┌──────────▼────────────────┐
│ PostgreSQL Database │ │ External LLM API │
│ (Supabase/Heroku) │ │ (Llama, Qwen, etc.) │
│ │ │ │
│ Tables: │ │ Endpoints: │
│ - conversations │ │ - POST /chat │
│ - auth_user │ │ │
│ - django_session │ │ Authentication: │
│ │ │ - Bearer Token │
└────────────────────────┘ └───────────────────────────┘
┌─────────┐
│ User │
└────┬────┘
│ 1. Navigate to /ask/
│
┌────▼────────────────────────────────────────────────────────┐
│ ask_question_view │
│ │
│ GET Request: │
│ ├─ Check session for conversation_id │
│ ├─ Render empty form │
│ └─ Display previous messages (if any) │
│ │
│ POST Request: │
│ ├─ 2. Validate form (QuestionForm) │
│ │ ├─ question text │
│ │ ├─ model selection │
│ │ ├─ parameters (temp, top_k, top_p, max_tokens) │
│ │ └─ optional file upload │
│ │ │
│ ├─ 3. Get/Create conversation_id in session │
│ │ │
│ ├─ 4. Fetch conversation history from database │
│ │ └─ SELECT * FROM conversations │
│ │ WHERE conversation_id = ? │
│ │ ORDER BY timestamp │
│ │ │
│ ├─ 5. Build API payload │
│ │ └─ messages = [ │
│ │ {"role": "user", "content": "prev question"}, │
│ │ {"role": "assistant", "content": "prev answer"}, │
│ │ {"role": "user", "content": "new question"} │
│ │ ] │
│ │ │
│ ├─ 6. Call query_api(messages, model, params) │
│ │ │ │
│ │ ├─ POST request to external LLM API │
│ │ ├─ Include Bearer token authentication │
│ │ ├─ Wait for response │
│ │ └─ Parse response (content, tokens, time) │
│ │ │
│ ├─ 7. Save user question to database │
│ │ └─ INSERT INTO conversations (role='user', ...) │
│ │ │
│ ├─ 8. Save AI response to database │
│ │ └─ INSERT INTO conversations (role='assistant', ...) │
│ │ │
│ └─ 9. Render template with updated conversation │
│ │
└───────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Data Layer │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Conversation Model │ │
│ │ │ │
│ │ Fields: │ │
│ │ ├─ id (PK) │ │
│ │ ├─ conversation_id (UUID, indexed) │ │
│ │ ├─ role ('user' | 'assistant') │ │
│ │ ├─ content (TEXT) │ │
│ │ ├─ username (VARCHAR, indexed) │ │
│ │ ├─ model_name (VARCHAR) │ │
│ │ ├─ token_usage (INT) │ │
│ │ ├─ elapsed_time (FLOAT) │ │
│ │ ├─ timestamp (DATETIME, indexed) │ │
│ │ ├─ temperature (FLOAT) │ │
│ │ ├─ top_k (INT) │ │
│ │ ├─ top_p (FLOAT) │ │
│ │ └─ file_upload (FILE) │ │
│ │ │ │
│ │ Indexes: │ │
│ │ ├─ conversation_id (for fast conversation lookup) │ │
│ │ ├─ username (for user filtering) │ │
│ │ └─ timestamp (for ordering) │ │
│ │ │ │
│ │ Relationships: │ │
│ │ └─ Self-referential via conversation_id │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ Authentication System │
│ (Django Allauth) │
│ │
│ Login Options: │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │Email/Pass │ │Google OAuth │ │GitHub OAuth │ │
│ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └────────────────┼─────────────────┘ │
│ │ │
│ ┌─────────▼──────────┐ │
│ │ Django Session │ │
│ │ ├─ session_key │ │
│ │ ├─ user_id │ │
│ │ └─ expire_date │ │
│ └────────────────────┘ │
│ │ │
│ ┌─────────▼──────────┐ │
│ │ Session Cookies │ │
│ │ (Encrypted) │ │
│ └────────────────────┘ │
│ │ │
│ ┌─────────▼──────────┐ │
│ │ @login_required │ │
│ │ Decorator Check │ │
│ └────────────────────┘ │
│ │ │
│ ┌───────────┴──────────┐ │
│ │ │ │
│ ┌────▼─────┐ ┌─────▼────┐ │
│ │Authorized│ │Redirect │ │
│ │Access │ │to Login │ │
│ └──────────┘ └──────────┘ │
└──────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ File Upload Process │
│ │
│ 1. User selects file │
│ ├─ Supported: .txt, .doc, .json, .csv │
│ └─ Max size: 30MB │
│ │
│ 2. Form validation (clean_file_upload) │
│ ├─ Check file size │
│ ├─ Check file extension │
│ └─ Raise ValidationError if invalid │
│ │
│ 3. File processing in view │
│ ├─ file_upload = form.cleaned_data.get('file_upload') │
│ ├─ file_content = file_upload.read().decode('utf-8') │
│ └─ Append to API messages array │
│ │
│ 4. Storage │
│ ├─ Save to media/file_uploads/ │
│ ├─ Store file reference in database │
│ └─ File path: conversation.file_upload.url │
│ │
│ 5. Send to LLM API │
│ └─ messages.append({ │
│ "role": "user", │
│ "content": f"File context: {file_content}" │
│ }) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Conversation Context System │
│ │
│ Session Storage: │
│ ┌────────────────────────────────┐ │
│ │ request.session │ │
│ │ { │ │
│ │ 'current_conversation_id': │ │
│ │ '550e8400-e29b-41d4-a716' │ │
│ │ } │ │
│ └────────────┬───────────────────┘ │
│ │ │
│ ┌────────────▼───────────────────┐ │
│ │ Database Query │ │
│ │ SELECT * FROM conversations │ │
│ │ WHERE conversation_id = ? │ │
│ │ ORDER BY timestamp ASC │ │
│ └────────────┬───────────────────┘ │
│ │ │
│ ┌────────────▼───────────────────┐ │
│ │ Message History │ │
│ │ [ │ │
│ │ {role: 'user', content: Q1} │ │
│ │ {role: 'assistant', A1} │ │
│ │ {role: 'user', content: Q2} │ │
│ │ {role: 'assistant', A2} │ │
│ │ ] │ │
│ └────────────┬───────────────────┘ │
│ │ │
│ ┌────────────▼───────────────────┐ │
│ │ Build API Payload │ │
│ │ messages = history + new_msg │ │
│ └────────────┬───────────────────┘ │
│ │ │
│ ┌────────────▼───────────────────┐ │
│ │ Send to LLM API │ │
│ │ (Context-aware response) │ │
│ └────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Django Admin Panel │
│ (/admin/) │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ConversationAdmin │ │
│ │ │ │
│ │ List Display: │ │
│ │ ├─ ID │ │
│ │ ├─ Role │ │
│ │ ├─ Content (truncated) │ │
│ │ ├─ Model Name │ │
│ │ ├─ Token Usage │ │
│ │ ├─ Elapsed Time │ │
│ │ ├─ Timestamp │ │
│ │ ├─ Username │ │
│ │ └─ Conversation ID │ │
│ │ │ │
│ │ Filters: │ │
│ │ ├─ Role (User/Assistant) │ │
│ │ ├─ Model Name │ │
│ │ └─ Timestamp (Date hierarchy) │ │
│ │ │ │
│ │ Search: │ │
│ │ ├─ Content │ │
│ │ └─ Username │ │
│ │ │ │
│ │ Actions: │ │
│ │ ├─ View details │ │
│ │ ├─ Edit conversation │ │
│ │ ├─ Delete conversation │ │
│ │ └─ Bulk delete │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Production Stack │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Heroku Dyno │ │
│ │ │ │
│ │ Procfile: │ │
│ │ web: gunicorn main.wsgi:application │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ Gunicorn (WSGI Server) │ │ │
│ │ │ - Multiple worker processes │ │ │
│ │ │ - Handles concurrent requests │ │ │
│ │ └──────────────┬───────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────▼───────────────────────────┐ │ │
│ │ │ Django Application │ │ │
│ │ │ - DEBUG = False │ │ │
│ │ │ - ALLOWED_HOSTS = ['.herokuapp.com'] │ │ │
│ │ └──────────────┬───────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────▼───────────────────────────┐ │ │
│ │ │ WhiteNoise (Static Files) │ │ │
│ │ │ - Serves CSS, JS, images │ │ │
│ │ │ - Compression enabled │ │ │
│ │ │ - Caching headers │ │ │
│ │ └───────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ Environment Variables: │
│ ├─ SECRET_KEY │
│ ├─ DATABASE_URL │
│ ├─ API_URL │
│ ├─ API_KEY │
│ └─ EMAIL_HOST_USER/PASSWORD │
│ │
│ External Services: │
│ ├─ PostgreSQL (Supabase/Heroku) │
│ ├─ LLM API (External provider) │
│ └─ OAuth Providers (Google, GitHub) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Error Handling System │
│ │
│ Form Validation Errors: │
│ ├─ QuestionForm.clean_*() methods │
│ ├─ ValidationError raised │
│ └─ Error displayed in template │
│ │
│ API Call Errors: │
│ ┌────────────────────────────────────────┐ │
│ │ query_api() function │ │
│ │ ├─ Try-except for JSONDecodeError │ │
│ │ ├─ Check HTTP status code │ │
│ │ ├─ Validate response structure │ │
│ │ └─ Return error dict on failure │ │
│ └────────────┬───────────────────────────┘ │
│ │ │
│ ┌────────────▼───────────────────────────┐ │
│ │ View error handling │ │
│ │ ├─ Check 'error' key in response │ │
│ │ ├─ django_messages.error() │ │
│ │ └─ Display user-friendly message │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Database Errors: │
│ ├─ Django ORM handles internally │
│ ├─ Transaction rollback on failure │
│ └─ IntegrityError for constraint violations │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Security Layers │
│ │
│ 1. Transport Security │
│ ├─ HTTPS enforced (Heroku) │
│ └─ TLS 1.2+ encryption │
│ │
│ 2. Input Validation │
│ ├─ Form validation (forms.py) │
│ ├─ File type checking │
│ ├─ File size limits │
│ └─ Parameter range validation │
│ │
│ 3. Authentication │
│ ├─ Django session authentication │
│ ├─ OAuth 2.0 (Google, GitHub) │
│ └─ Password hashing (PBKDF2) │
│ │
│ 4. Authorization │
│ ├─ @login_required decorators │
│ ├─ User-specific data filtering │
│ └─ Admin access control │
│ │
│ 5. CSRF Protection │
│ ├─ Django CSRF middleware │
│ ├─ CSRF tokens in forms │
│ └─ Trusted origins configured │
│ │
│ 6. SQL Injection Prevention │
│ ├─ Django ORM parameterized queries │
│ └─ No raw SQL queries │
│ │
│ 7. XSS Prevention │
│ ├─ Django template auto-escaping │
│ └─ mark_safe() used carefully │
│ │
│ 8. Secrets Management │
│ ├─ Environment variables │
│ ├─ No secrets in code │
│ └─ .gitignore for sensitive files │
└─────────────────────────────────────────────────────────────┘
- Python 3.8+
- Django 4.2+
- PostgreSQL (for production)
- Git
-
Clone the repository
git clone <repository-url> cd django-llm-metadata
-
Create virtual environment
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
-
Environment Variables Create an
env.pyfile or set environment variables:import os os.environ["SECRET_KEY"] = "your-secret-key" os.environ["DEBUG"] = "True" # Set to False in production os.environ["DATABASE_URL"] = "your-database-url" os.environ["API_URL"] = "your-llm-api-endpoint" os.environ["API_KEY"] = "your-api-key" os.environ["EMAIL_HOST_USER"] = "[email protected]" os.environ["EMAIL_HOST_PASSWORD"] = "your-email-password"
-
Database Setup
python manage.py makemigrations python manage.py migrate python manage.py createsuperuser
-
Run the application
python manage.py runserver
The application currently supports these LLM models:
llama3.3:70b-instruct-q8_0- Llama 3.3 70B Instructqwen3:32b-q8_0- Qwen3 32Bphi4-reasoning:14b-plus-fp16- Phi4-reasoning 14B
Additional models can be added by modifying the choices in forms.py.
- Temperature (0-1): Controls randomness in responses
- Top K (0-100): Limits vocabulary selection to top K tokens
- Top P (0-1): Nucleus sampling parameter
- Max Tokens (1-3000): Maximum response length
Supported file types:
.txt- Text files.doc- Document files.json- JSON data files.csv- CSV data files
Maximum file size: 30MB
- Navigate to
/ask/to start a new conversation - Select your preferred model and adjust parameters
- Type your question and submit
- View the AI response and continue the conversation
- Use the file upload field in the question form
- Upload supported file types for additional context
- The file content will be included in the conversation
- Visit
/conversation/to view conversation history - Conversations are grouped by date
- Delete individual conversations using the delete button
- Navigate to
/json-viewer/ - Upload a JSON file to view formatted content
- If the JSON contains tabular data, it will display as a table
Stores all conversation data with the following fields:
role: 'user' or 'assistant'content: Message contentmodel_name: LLM model usedtoken_usage: Number of tokens in responseelapsed_time: API response timetimestamp: Message timestampusername: User who created the messageconversation_id: UUID linking related messagestemperature,top_k,top_p: Model parametersfile_upload: Uploaded file reference
The application uses a custom API utility function (utils.py) to communicate with LLM services. The API expects:
payload = {
"model": model_name,
"messages": conversation_history,
"temperature": temperature,
"max_tokens": max_tokens,
"top_k": top_k,
"top_p": top_p
}The application uses Django Allauth for authentication with support for:
- Email/password authentication
- Google OAuth (configurable)
- GitHub OAuth (configurable)
Access the Django admin at /admin/ to:
- View all conversations
- Filter by role, model, and timestamp
- Search conversation content
- Manage user data
For production deployment:
- Set
DEBUG=False - Configure proper database (PostgreSQL recommended)
- Set up static file serving
- Configure email backend
- Set secure secret key
The application is configured for Heroku deployment with:
dj-database-urlfor database configuration- Static file handling
- CSRF trusted origins for Heroku domains
SECRET_KEY: Django secret keyDEBUG: Debug mode (True/False)DATABASE_URL: Database connection stringAPI_URL: LLM API endpointAPI_KEY: API authentication keyEMAIL_HOST_USER: SMTP email usernameEMAIL_HOST_PASSWORD: SMTP email password
- Add model choice to
forms.pyin theQuestionForm.modelfield - Ensure the API supports the new model
- Test the integration
- Update
clean_file_upload()informs.py - Add new file types to
valid_extensions - Implement file processing logic if needed
The application includes custom template tags:
conversation_filters.py: Get assistant responsescustom_filters.py: Add CSS classes to form fields
-
API Connection Errors
- Verify
API_URLandAPI_KEYare correct - Check network connectivity
- Review API endpoint documentation
- Verify
-
File Upload Issues
- Ensure file size is under 30MB
- Check file extension is supported
- Verify
MEDIA_ROOTis configured
-
Database Errors
- Run migrations:
python manage.py migrate - Check database connection string
- Ensure database server is running
- Run migrations:
Enable Django logging in settings.py for debugging:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': 'INFO',
},
},
}- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
For issues and questions:
- Check the troubleshooting section
- Review Django documentation
- Open an issue on the repository
- Contact the development team ([email protected])
- Initial release
- Multi-model LLM support
- File upload functionality
- Conversation management
- User authentication
- JSON viewer
- Admin interface