-
Notifications
You must be signed in to change notification settings - Fork 0
Implement frontend GUI for LLM backend selection and configuration #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # Core SDLC dependencies | ||
| Flask==3.0.0 | ||
| Werkzeug==3.0.1 | ||
|
|
||
| # Development and testing | ||
| pytest==8.4.1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Launch script for the SDLC Core frontend application. | ||
| """ | ||
|
|
||
| import os | ||
| import sys | ||
|
|
||
| # Add the src directory to the Python path | ||
| sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) | ||
|
|
||
| from src.frontend.app import app | ||
|
|
||
| if __name__ == '__main__': | ||
| print("Starting SDLC Core Frontend...") | ||
| print("Access the application at: http://localhost:5000") | ||
| print("Dashboard: http://localhost:5000/") | ||
| print("Settings: http://localhost:5000/settings") | ||
| print("\nPress Ctrl+C to stop the server") | ||
|
|
||
| app.run(debug=True, host='0.0.0.0', port=5000) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| # Frontend for SDLC Core LLM Infrastructure | ||
|
|
||
| This frontend application provides a web-based GUI for managing LLM backend settings in the SDLC Core system. | ||
|
|
||
| ## Features | ||
|
|
||
| - **Backend Selection**: Choose between different LLM providers (OpenAI, Anthropic, etc.) | ||
| - **Configuration Management**: Set API keys, models, and other backend-specific settings | ||
| - **Visual Interface**: Clean, responsive web interface with real-time updates | ||
| - **Settings Persistence**: Configuration is saved locally and persists across sessions | ||
|
|
||
| ## Installation | ||
|
|
||
| 1. Install dependencies: | ||
| ```bash | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| 2. Run the application: | ||
| ```bash | ||
| python app.py | ||
| ``` | ||
|
|
||
| 3. Open your browser and navigate to `http://localhost:5000` | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Dashboard | ||
| - View the currently active LLM backend | ||
| - See all available backends | ||
| - Quick-switch between backends | ||
|
|
||
| ### Settings Page | ||
| - Configure API keys for each backend | ||
| - Set preferred models | ||
| - Enable/disable specific backends | ||
| - Save and persist configuration changes | ||
|
|
||
| ## Configuration | ||
|
|
||
| The application stores settings in `config/settings.json`. This file is automatically created with default settings on first run. | ||
|
|
||
| Default backends supported: | ||
| - **OpenAI**: GPT models (GPT-3.5, GPT-4, etc.) | ||
Check failureCode scanning / check-spelling Unrecognized Spelling Error
GPT is not a recognized word. (unrecognized-spelling)
Check failureCode scanning / check-spelling Unrecognized Spelling Error
GPT is not a recognized word. (unrecognized-spelling)
Check failureCode scanning / check-spelling Unrecognized Spelling Error
GPT is not a recognized word. (unrecognized-spelling)
|
||
| - **Anthropic**: Claude models | ||
|
|
||
| ## API Endpoints | ||
|
|
||
| - `GET /api/config` - Get current configuration | ||
| - `POST /api/config` - Update configuration | ||
| - `POST /api/backend/select` - Switch active backend | ||
|
|
||
| ## File Structure | ||
|
|
||
| ``` | ||
| frontend/ | ||
| ├── app.py # Main Flask application | ||
| ├── requirements.txt # Python dependencies | ||
| ├── templates/ | ||
| │ ├── index.html # Dashboard page | ||
| │ └── settings.html # Settings configuration page | ||
| └── config/ | ||
| └── settings.json # Persistent configuration (auto-generated) | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,106 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Frontend web application for SDLC_core LLM infrastructure settings. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Provides a GUI interface for selecting and configuring LLM backends. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from flask import Flask, render_template, request, jsonify, redirect, url_for | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import json | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Dict, Any | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| app = Flask(__name__) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Configuration file path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CONFIG_FILE = os.path.join(os.path.dirname(__file__), 'config', 'settings.json') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Default configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEFAULT_CONFIG = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "selected_backend": "openai", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / check-spelling Unrecognized Spelling Error
openai is not a recognized word. (unrecognized-spelling)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "backends": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "openai": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / check-spelling Unrecognized Spelling Error
openai is not a recognized word. (unrecognized-spelling)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "name": "OpenAI", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "description": "OpenAI's GPT models (GPT-3.5, GPT-4, etc.)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / check-spelling Unrecognized Spelling Error
GPT is not a recognized word. (unrecognized-spelling)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "api_key": "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "model": "gpt-3.5-turbo", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / check-spelling Unrecognized Spelling Error
gpt is not a recognized word. (unrecognized-spelling)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "enabled": True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "anthropic": { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "name": "Anthropic", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "description": "Anthropic's Claude models", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "api_key": "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "model": "claude-3-sonnet-20240229", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / check-spelling Unrecognized Spelling Error
claude is not a recognized word. (unrecognized-spelling)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "enabled": True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def load_config() -> Dict[str, Any]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Load configuration from file or return default.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if os.path.exists(CONFIG_FILE): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with open(CONFIG_FILE, 'r') as f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return json.load(f) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Error loading config: {e}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return DEFAULT_CONFIG.copy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def save_config(config: Dict[str, Any]) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Save configuration to file.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| os.makedirs(os.path.dirname(CONFIG_FILE), exist_ok=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with open(CONFIG_FILE, 'w') as f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| json.dump(config, f, indent=2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(f"Error saving config: {e}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @app.route('/') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def index(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Main dashboard.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config = load_config() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return render_template('index.html', config=config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @app.route('/settings') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def settings(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Settings page for backend configuration.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config = load_config() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return render_template('settings.html', config=config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @app.route('/api/config', methods=['GET']) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_config(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """API endpoint to get current configuration.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config = load_config() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return jsonify(config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @app.route('/api/config', methods=['POST']) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def update_config(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """API endpoint to update configuration.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new_config = request.json | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if save_config(new_config): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return jsonify({"success": True, "message": "Configuration updated successfully"}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return jsonify({"success": False, "message": "Failed to save configuration"}), 500 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return jsonify({"success": False, "message": str(e)}), 400 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check warningCode scanning / CodeQL Information exposure through an exception Medium Stack trace information Error loading related location Loading
Copilot AutofixAI 4 months ago To fix the problem, we should avoid returning the raw exception message (
Suggested changeset
1
src/frontend/app.py
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @app.route('/api/backend/select', methods=['POST']) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def select_backend(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """API endpoint to select a backend.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = request.json | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backend = data.get('backend') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config = load_config() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if backend in config['backends']: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config['selected_backend'] = backend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if save_config(config): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return jsonify({"success": True, "message": f"Backend switched to {backend}"}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return jsonify({"success": False, "message": "Invalid backend"}), 400 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return jsonify({"success": False, "message": str(e)}), 400 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check warningCode scanning / CodeQL Information exposure through an exception Medium Stack trace information Error loading related location Loading
Copilot AutofixAI 4 months ago To fix the problem, we should avoid returning the raw exception message to the client. Instead, we should log the exception details on the server (for debugging and auditing purposes) and return a generic error message to the client. This ensures that sensitive information is not exposed to users, while still allowing developers to diagnose issues. The fix should be applied to the exception handler in the
Suggested changeset
1
src/frontend/app.py
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if __name__ == '__main__': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| app.run(debug=True, host='0.0.0.0', port=5000) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check failureCode scanning / CodeQL Flask app is run in debug mode High
A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger.
Copilot AutofixAI 4 months ago To fix this problem, the Flask application should not be run with
Suggested changeset
1
src/frontend/app.py
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Flask==3.0.0 | ||
| Werkzeug==3.0.1 |
Check failure
Code scanning / CodeQL
Flask app is run in debug mode High
Copilot Autofix
AI 4 months ago
To fix the problem, the Flask application should not be run with
debug=Trueunconditionally. The best practice is to enable debug mode only in a development environment, and ensure it is disabled in production. This can be achieved by checking an environment variable (such asFLASK_ENVor a custom variable likeSDLC_ENV) or by defaulting todebug=False. The most robust fix is to read an environment variable (e.g.,SDLC_ENV), and setdebug=Trueonly if it is set to'development'. This change should be made in theif __name__ == '__main__':block inrun_frontend.py. No new imports are needed, asosis already imported.