import os import logging import re import io from PIL import Image import gradio as gr # ✅ تعطيل SSR قبل استيراد Gradio os.environ["GRADIO_SSR_MODE"] = "False" os.environ["GRADIO_NODE_DISABLED"] = "True" logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) logger.info("بدء تشغيل DermaScan AI...") try: from rag import build_default_vectorstore from agent import ( build_agent, set_session_storage, set_current_thread_id, set_api_client, ) from api_client import DermaScanAPIClient logger.info("✅ تم استيراد جميع الوحدات بنجاح") except Exception as e: logger.error(f"❌ فشل استيراد الوحدات: {e}", exc_info=True) raise MODEL_NAME = "llama-3.1-8b-instant" TEMPERATURE = 0.25 TOP_K = 3 EXTERNAL_API_URL = "https://omarelrayes-api.hf.space" SESSIONS = {} agent = None api_client = None def get_session(thread_id: str) -> dict: if thread_id not in SESSIONS: SESSIONS[thread_id] = { "role": "patient", "last_analysis": None, "current_image": None, "_image_blobs": {}, "_session_image_names": [], "_turn_count": 0 } return SESSIONS[thread_id] def initialize_system(): global agent, api_client try: logger.info("بدء تهيئة النظام...") groq_key = os.environ.get("GROQ_API_KEY") if not groq_key: logger.warning("GROQ_API_KEY not set") else: logger.info("GROQ_API_KEY found") api_client = DermaScanAPIClient(EXTERNAL_API_URL) set_api_client(api_client) if api_client.health_check(): logger.info("External API is healthy") vectorstore = build_default_vectorstore() retriever = vectorstore.as_retriever(search_kwargs={"k": TOP_K}) if vectorstore else None if retriever is None: logger.warning("Vectorstore not available") agent = build_agent(retriever, model_name=MODEL_NAME, temperature=TEMPERATURE) logger.info("✅ Agent built successfully") logger.info("تم تهيئة النظام بنجاح!") except Exception as e: logger.error(f"فشل التهيئة: {e}", exc_info=True) raise initialize_system() def chat_with_agent(message: str, history: list) -> str: if agent is None: return "System not initialized yet." session = get_session("default") set_session_storage(SESSIONS) set_current_thread_id("default") try: last_analysis = session.get("last_analysis") analysis_ctx = f"\n\n[Analysis: {last_analysis.get('label', 'N/A')}]" if last_analysis else "" full_prompt = message + analysis_ctx config = {"configurable": {"thread_id": "default"}, "recursion_limit": 14} final_text = "" for event in agent.stream( {"messages": [("user", full_prompt)]}, config=config, stream_mode="values" ): last_msg = event["messages"][-1] if last_msg.type == "ai" and last_msg.content: final_text = last_msg.content cleaned_text = re.sub(r'\[ANALYSIS_RESULT:\{.*?\}\]', '', final_text).strip() session["_turn_count"] = session.get("_turn_count", 0) + 1 return cleaned_text if cleaned_text else "No response." except Exception as e: logger.error(f"Chat error: {e}") return f"Error: {str(e)}" def analyze_image(image, thread_id: str = "default") -> str: if api_client is None: return "API client not initialized" try: api_client.set_role(thread_id, "patient") session = get_session(thread_id) session["current_image"] = image result = api_client.upload_and_analyze_image(image, thread_id) if not result.get('ok'): return f"Error: {result.get('error', 'Unknown error')}" session["last_analysis"] = { "label": result.get("label"), "confidence_pct": result.get("confidence_pct"), "infection_pct": result.get("infection_pct") } return ( f"تم التحليل بنجاح!\n\n" f"التصنيف: {result.get('label')}\n" f"نسبة الثقة: {result.get('confidence_pct')}%\n" f"المساحة المصابة: {result.get('infection_pct')}%" ) except Exception as e: logger.error(f"Image analysis error: {e}") return f"Error: {str(e)}" logger.info("جاري بناء واجهة Gradio...") with gr.Blocks(title="DermaScan AI") as demo: gr.Markdown("# 🏥 DermaScan AI - مساعد أمراض الجلدية") with gr.Tab("📤 رفع الصورة"): image_input = gr.Image(type="pil", label="ارفع صورة الجلد") analyze_btn = gr.Button("🔍 تحليل الصورة", variant="primary") analysis_output = gr.Textbox(label="نتيجة التحليل", lines=6) analyze_btn.click(fn=analyze_image, inputs=[image_input], outputs=[analysis_output]) with gr.Tab("💬 الدردشة"): chatbot = gr.Chatbot(label="المحادثة", height=400) msg_input = gr.Textbox(label="رسالتك", placeholder="اسأل عن حالتك الجلدية...", lines=2) send_btn = gr.Button("🚀 إرسال", variant="primary") clear_btn = gr.Button("🗑️ مسح") def user_message(user_msg, history): return "", history + [[user_msg, None]] def bot_response(history): if not history: return history user_msg = history[-1][0] response = chat_with_agent(user_msg, history[:-1]) history[-1][1] = response return history send_btn.click(user_message, [msg_input, chatbot], [msg_input, chatbot]).then( bot_response, chatbot, chatbot ) msg_input.submit(user_message, [msg_input, chatbot], [msg_input, chatbot]).then( bot_response, chatbot, chatbot ) clear_btn.click(lambda: None, None, chatbot) with gr.Tab("📚 API Info"): gr.Markdown("## API شغالة! استخدم Gradio Client للاتصال.") logger.info("✅ تم بناء واجهة Gradio") logger.info("🎉 DermaScan AI جاهز!") # ✅ الحل الحقيقي: ssr_mode=False في launch() demo.launch( server_name="0.0.0.0", server_port=7860, ssr_mode=False, # ← ده اللي هيمنع Node.js SSR share=False )