| """ |
| OpenRouter Models Display SaaS |
| A Flask application that fetches and displays all OpenRouter AI models with sorting capabilities. |
| """ |
|
|
| from flask import Flask, jsonify, request, Response, render_template |
| import requests |
| from cachetools import TTLCache |
| import json |
| from pathlib import Path |
|
|
| app = Flask(__name__) |
|
|
| |
| models_cache = TTLCache(maxsize=1, ttl=10800) |
|
|
| def fetch_models(): |
| """Fetch models from OpenRouter API with caching.""" |
| if 'models' in models_cache: |
| return models_cache['models'] |
| |
| try: |
| response = requests.get( |
| 'https://openrouter.ai/api/v1/models', |
| timeout=30 |
| ) |
| response.raise_for_status() |
| data = response.json() |
| |
| models = [] |
| for model in data.get('data', []): |
| |
| architecture = [] |
| if model.get('architecture'): |
| if model['architecture'].get('modality'): |
| arch_str = model['architecture']['modality'] |
| if 'text->text' in arch_str: |
| architecture.append('text') |
| if 'image' in arch_str: |
| architecture.append('image') |
| if 'audio' in arch_str: |
| architecture.append('audio') |
| if 'video' in arch_str: |
| architecture.append('video') |
| |
| if not architecture: |
| architecture = ['text'] |
| |
| |
| model_id = model.get('id', '') |
| provider = model_id.split('/')[0] if '/' in model_id else 'Unknown' |
| |
| |
| pricing = model.get('pricing', {}) |
| prompt_price = float(pricing.get('prompt', 0)) * 1000000 |
| completion_price = float(pricing.get('completion', 0)) * 1000000 |
| |
| models.append({ |
| 'id': model_id, |
| 'name': model.get('name', model_id), |
| 'provider': provider, |
| 'architecture': architecture, |
| 'context': model.get('context_length', 0), |
| 'prompt_price': prompt_price, |
| 'completion_price': completion_price, |
| 'description': model.get('description', ''), |
| }) |
| |
| |
| models.sort(key=lambda x: (x['provider'].lower(), x['name'].lower())) |
| |
| models_cache['models'] = models |
| return models |
| except Exception as e: |
| print(f"Error fetching models: {e}") |
| return [] |
|
|
| @app.route('/') |
| def index(): |
| """Main page with sortable HTML table.""" |
| models = fetch_models() |
| providers = set(m['provider'] for m in models) |
| |
| return render_template( |
| 'index.html', |
| models=models, |
| unique_providers=len(providers) |
| ) |
|
|
| @app.route('/api/raw') |
| def api_raw(): |
| """Return raw JSON with indent=4.""" |
| models = fetch_models() |
| return Response( |
| json.dumps(models, indent=4), |
| mimetype='application/json' |
| ) |
|
|
| @app.route('/api/download') |
| def api_download(): |
| """Download JSON file.""" |
| models = fetch_models() |
| json_data = json.dumps(models, indent=4) |
| return Response( |
| json_data, |
| mimetype='application/json', |
| headers={ |
| 'Content-Disposition': 'attachment; filename=openrouter_models.json' |
| } |
| ) |
|
|
| @app.route('/api/models') |
| def api_models(): |
| """Standard JSON API endpoint.""" |
| models = fetch_models() |
| return jsonify(models) |
|
|
| @app.route('/health') |
| def health(): |
| """Health check endpoint.""" |
| return jsonify({'status': 'healthy', 'cached': 'models' in models_cache}) |
|
|
| if __name__ == '__main__': |
| app.run(host='0.0.0.0', port=7860) |