Spaces:
Running
Running
| import os | |
| import json | |
| from pathlib import Path | |
| import requests | |
| from flask import Flask, request, jsonify, send_from_directory, Response | |
| from openai import OpenAI | |
| BASE_DIR = Path(__file__).resolve().parent | |
| app = Flask(__name__, static_folder=str(BASE_DIR)) | |
| AIHUBMIX_API_KEY = os.environ.get("AIHUBMIX_API_KEY", "sk-I1toL3Pvlk42DKd36d1824Cd683b44Ec834730C17cC39679") | |
| AIHUBMIX_BASE_URL = "https://aihubmix.com/v1" | |
| # النماذج التي اخترناها للمشروع | |
| MODELS = { | |
| "flash_lite": { | |
| "name": "Genisi 4 Flash Lite", | |
| "id": "gpt-4.1-nano-free", | |
| }, | |
| "flash": { | |
| "name": "Genisi 4 Flash", | |
| "id": "gemma-4-26b-a4b-it-free", | |
| }, | |
| "pro": { | |
| "name": "Genisi 4 Pro", | |
| "id": "mimo-v2-flash-free", | |
| }, | |
| } | |
| # API توليد الصور | |
| IMAGE_API_URL = "https://prexzyapis.com/ai/aiappgen" | |
| def get_client(): | |
| if not AIHUBMIX_API_KEY: | |
| raise RuntimeError( | |
| "لم يتم العثور على AIHUBMIX_API_KEY في Environment Variables." | |
| ) | |
| return OpenAI( | |
| api_key=AIHUBMIX_API_KEY, | |
| base_url=AIHUBMIX_BASE_URL, | |
| ) | |
| def index(): | |
| return send_from_directory(BASE_DIR, "index.html") | |
| def models(): | |
| return jsonify({ | |
| "success": True, | |
| "models": MODELS | |
| }) | |
| def chat(): | |
| try: | |
| data = request.get_json(silent=True) or {} | |
| messages = data.get("messages", []) | |
| model_key = data.get("model", "flash") | |
| thinking = bool(data.get("thinking", False)) | |
| if not isinstance(messages, list) or not messages: | |
| return jsonify({ | |
| "success": False, | |
| "error": "messages يجب أن تكون قائمة غير فارغة." | |
| }), 400 | |
| if model_key not in MODELS: | |
| return jsonify({ | |
| "success": False, | |
| "error": "النموذج غير موجود." | |
| }), 400 | |
| model_id = MODELS[model_key]["id"] | |
| # زر التفكير اختياري. | |
| # لا نرسل parameter خاص بالتفكير للنماذج التي قد لا تدعمه. | |
| # بدلاً من ذلك نضيف توجيهاً بسيطاً عند تفعيله. | |
| final_messages = list(messages) | |
| if thinking: | |
| final_messages.insert(0, { | |
| "role": "system", | |
| "content": ( | |
| "عند تفعيل وضع التفكير، حلّل المشكلة داخلياً بعناية " | |
| "وتحقق من خطواتك قبل إعطاء الإجابة النهائية. " | |
| "لا تعرض سلسلة التفكير الداخلية التفصيلية." | |
| ) | |
| }) | |
| client = get_client() | |
| response = client.chat.completions.create( | |
| model=model_id, | |
| messages=final_messages, | |
| max_tokens=16384, | |
| stream=False, | |
| ) | |
| text = "" | |
| if response.choices: | |
| message = response.choices[0].message | |
| text = message.content or "" | |
| return jsonify({ | |
| "success": True, | |
| "model": model_id, | |
| "text": text | |
| }) | |
| except Exception as e: | |
| return jsonify({ | |
| "success": False, | |
| "error": str(e) | |
| }), 500 | |
| def chat_stream(): | |
| try: | |
| data = request.get_json(silent=True) or {} | |
| messages = data.get("messages", []) | |
| model_key = data.get("model", "flash") | |
| thinking = bool(data.get("thinking", False)) | |
| if model_key not in MODELS: | |
| return jsonify({ | |
| "success": False, | |
| "error": "النموذج غير موجود." | |
| }), 400 | |
| if not isinstance(messages, list) or not messages: | |
| return jsonify({ | |
| "success": False, | |
| "error": "messages غير صالحة." | |
| }), 400 | |
| final_messages = list(messages) | |
| if thinking: | |
| final_messages.insert(0, { | |
| "role": "system", | |
| "content": ( | |
| "فكر بعناية داخلياً قبل الإجابة، خصوصاً في الرياضيات " | |
| "والبرمجة والمشاريع المعقدة. لا تعرض سلسلة التفكير الداخلية." | |
| ) | |
| }) | |
| client = get_client() | |
| def generate(): | |
| try: | |
| stream = client.chat.completions.create( | |
| model=MODELS[model_key]["id"], | |
| messages=final_messages, | |
| max_tokens=16384, | |
| stream=True, | |
| ) | |
| for chunk in stream: | |
| if not chunk.choices: | |
| continue | |
| delta = chunk.choices[0].delta | |
| if delta and delta.content: | |
| payload = { | |
| "type": "text", | |
| "text": delta.content | |
| } | |
| yield ( | |
| "data: " | |
| + json.dumps(payload, ensure_ascii=False) | |
| + "\n\n" | |
| ) | |
| yield 'data: {"type":"done"}\n\n' | |
| except Exception as e: | |
| payload = { | |
| "type": "error", | |
| "error": str(e) | |
| } | |
| yield ( | |
| "data: " | |
| + json.dumps(payload, ensure_ascii=False) | |
| + "\n\n" | |
| ) | |
| return Response( | |
| generate(), | |
| mimetype="text/event-stream", | |
| headers={ | |
| "Cache-Control": "no-cache", | |
| "X-Accel-Buffering": "no", | |
| "Connection": "keep-alive", | |
| }, | |
| ) | |
| except Exception as e: | |
| return jsonify({ | |
| "success": False, | |
| "error": str(e) | |
| }), 500 | |
| def image_generation(): | |
| """ | |
| مثال: | |
| /api/image?prompt=a%20beautiful%20city&style=realistic | |
| """ | |
| try: | |
| prompt = request.args.get("prompt", "").strip() | |
| image = request.args.get("image", "") | |
| style = request.args.get("style", "") | |
| if not prompt: | |
| return jsonify({ | |
| "success": False, | |
| "error": "أدخل وصف الصورة." | |
| }), 400 | |
| params = { | |
| "prompt": prompt, | |
| "image": image, | |
| "style": style, | |
| } | |
| response = requests.get( | |
| IMAGE_API_URL, | |
| params=params, | |
| timeout=120, | |
| ) | |
| try: | |
| result = response.json() | |
| except Exception: | |
| return jsonify({ | |
| "success": False, | |
| "error": "الخادم أعاد استجابة غير JSON.", | |
| "raw": response.text | |
| }), response.status_code | |
| return jsonify(result), response.status_code | |
| except requests.RequestException as e: | |
| return jsonify({ | |
| "success": False, | |
| "error": f"Image API error: {str(e)}" | |
| }), 502 | |
| except Exception as e: | |
| return jsonify({ | |
| "success": False, | |
| "error": str(e) | |
| }), 500 | |
| def health(): | |
| return jsonify({ | |
| "status": "ok" | |
| }) | |
| if __name__ == "__main__": | |
| port = int(os.environ.get("PORT", "7860")) | |
| app.run( | |
| host="0.0.0.0", | |
| port=port, | |
| debug=False, | |
| ) |