| from flask import Flask, jsonify, request, Response, stream_with_context |
| import requests |
| import os |
| import logging |
| from dotenv import load_dotenv |
|
|
| load_dotenv() |
|
|
| logging.basicConfig(level=logging.INFO) |
|
|
| API_BASE_URL = os.getenv("API_BASE_URL", "") |
| AUTH_KEY = os.getenv("AUTH_KEY", "callme") |
| API_KEYS = os.getenv("API_KEYS") |
|
|
| API_KEY_LIST = API_KEYS.split(",") if API_KEYS else [] |
|
|
| key_index = 0 |
|
|
| app = Flask(__name__) |
|
|
| def getAPI_KEY(): |
| global key_index |
| if not API_KEY_LIST: |
| logging.warning("API_KEYS is not configured.") |
| return "" |
| key = API_KEY_LIST[key_index] |
| key_index = (key_index + 1) % len(API_KEY_LIST) |
| return key |
|
|
| @app.before_request |
| def check_api_key(): |
| key = request.headers.get("Authorization") |
| if key != "Bearer " + AUTH_KEY: |
| return jsonify({"success": False, "message": "Unauthorized: Invalid API key"}), 403 |
|
|
| @app.route("/v1/models", methods=['GET']) |
| def getModels(): |
| api_key = getAPI_KEY() |
| if not api_key: |
| return jsonify({"success": False, "message": "API Key not available"}), 500 |
|
|
| headers = { |
| "Authorization": "Bearer " + api_key, |
| "Content-Type": "application/json" |
| } |
| try: |
| response = requests.get(API_BASE_URL + "/models", headers=headers, timeout=30) |
| response.raise_for_status() |
| response_headers = {'Content-Type': response.headers.get('content-type', 'application/json')} |
| |
| return (response.content, response.status_code, response_headers) |
| except requests.exceptions.RequestException as e: |
| logging.error("Get models error. %s", e) |
| return jsonify({"success": False, "message": f"Failed to fetch models: {e}"}), 500 |
| except Exception as e: |
| logging.error("An unexpected error occurred in getModels: %s", e) |
| return jsonify({"success": False, "message": str(e)}), 500 |
|
|
| @app.route("/v1/chat/completions",methods=['POST']) |
| def chat(): |
| headers = { |
| "Authorization":"Bearer "+getAPI_KEY(), |
| "Content-Type":"application/json" |
| } |
| data = request.get_json() |
| stream_flag = data.get('stream', True) |
|
|
| def generate(): |
| try: |
| with requests.post(API_BASE_URL+"/chat/completions", headers=headers, json=data, stream=stream_flag) as response: |
| response.raise_for_status() |
| for chunk in response.iter_content(chunk_size=1024): |
| yield chunk |
| except requests.exceptions.RequestException as e: |
| logging.error("Request to upstream API failed: %s", e) |
| |
| |
| yield b'{"error": "Upstream API request failed"}' |
| except Exception as e: |
| logging.error("Unexpected error during streaming: %s", e) |
| yield b'{"error": "Internal server error during streaming"}' |
|
|
|
|
| try: |
| |
| if not stream_flag: |
| |
| response = requests.post(API_BASE_URL+"/chat/completions", headers=headers, json=data, stream=False) |
| response.raise_for_status() |
| return Response(response.content, |
| status=response.status_code, |
| content_type=response.headers.get('content-type')) |
| else: |
| |
| |
| |
| initial_response = requests.post(API_BASE_URL+"/chat/completions", headers=headers, json=data, stream=True) |
| initial_response.raise_for_status() |
|
|
| return Response(generate_from_response(initial_response), |
| status=initial_response.status_code, |
| content_type=initial_response.headers.get('content-type')) |
|
|
| except requests.exceptions.RequestException as e: |
| logging.error("Initial upstream API request failed: %s", e) |
| return jsonify({"success": False, "message": f"Upstream API request failed: {e}"}), 500 |
| except Exception as e: |
| logging.error("Error setting up chat completion: %s", e) |
| return jsonify({"success": False, "message": str(e)}), 500 |
|
|
| def generate_from_response(upstream_response): |
| |
| for chunk in upstream_response.iter_content(chunk_size=1024): |
| yield chunk |
|
|
|
|
| if __name__ == '__main__': |
| print("Starting Flask app...") |
| |
| app.run(host='0.0.0.0', port=7860, debug=True) |