import os, uuid, json, zipfile, logging from fastapi import FastAPI, UploadFile, File, Request from fastapi.responses import StreamingResponse, JSONResponse, FileResponse from fastapi.staticfiles import StaticFiles from huggingface_hub import InferenceClient from duckduckgo_search import DDGS import fitz # PyMuPDF from docx import Document app = FastAPI() UPLOAD_DIR = "static/uploads" os.makedirs(UPLOAD_DIR, exist_ok=True) app.mount("/static", StaticFiles(directory="static"), name="static") # التأكد من جلب التوكن HF_TOKEN = os.environ.get("HF_TOKEN") # استخدام العميل مع التوكن مباشرة client = InferenceClient(api_key=HF_TOKEN) def extract_file_content(file_id): filepath = os.path.join(UPLOAD_DIR, file_id) if not os.path.exists(filepath): return "" ext = os.path.splitext(file_id)[1].lower() content = "" try: if ext == ".pdf": doc = fitz.open(filepath) content = "\n".join([page.get_text() for page in doc]) elif ext == ".docx": doc = Document(filepath) content = "\n".join([p.text for p in doc.paragraphs]) elif ext == ".zip": with zipfile.ZipFile(filepath, 'r') as z: names = z.namelist() content = f"ملف ZIP يحتوي على: {', '.join(names)}\n" for name in names[:3]: if name.endswith(('.txt', '.py', '.html', '.json')): with z.open(name) as f: content += f"\n-- {name} --\n{f.read().decode('utf-8')[:1000]}" elif ext in [".txt", ".py", ".js", ".html", ".json"]: with open(filepath, "r", encoding="utf-8") as f: content = f.read() except Exception as e: return f"خطأ قراءة: {str(e)}" return content[:15000] @app.get("/") async def read_index(): path = "index.html" if os.path.exists("index.html") else "static/index.html" return FileResponse(path) @app.post("/api/upload") async def upload_file(file: UploadFile = File(...)): ext = os.path.splitext(file.filename)[1] file_id = f"{uuid.uuid4()}{ext}" filepath = os.path.join(UPLOAD_DIR, file_id) with open(filepath, "wb") as f: f.write(await file.read()) return {"file_id": file_id, "url": f"/static/uploads/{file_id}"} @app.post("/api/chat/stream") async def chat_stream(request: Request): data = await request.json() message = data.get("message", "") file_id = data.get("file_id") if not HF_TOKEN: return JSONResponse({"error": "HF_TOKEN missing in Settings!"}, status_code=500) context = "" if file_id: file_text = extract_file_content(file_id) context += f"\n[محتوى الملف]:\n{file_text}\n" messages = [ {"role": "system", "content": "أنت مساعد ذكي. حلل الملفات وأجب بالعربية."}, {"role": "user", "content": f"{context}\n{message}"} ] async def gen(): try: # تم تحديث الاستدعاء ليكون أكثر استقراراً stream = client.chat.completions.create( model="huihui-ai/Qwen2.5-72B-Instruct-abliterated", messages=messages, stream=True, max_tokens=2048, temperature=0.7 ) for chunk in stream: if chunk.choices[0].delta.content: yield f"data: {json.dumps({'token': chunk.choices[0].delta.content})}\n\n" except Exception as e: # إرسال الخطأ الحقيقي للواجهة لنعرف السبب (مثل توكن خاطئ أو ضغط على السيرفر) error_msg = str(e) yield f"data: {json.dumps({'error': error_msg})}\n\n" return StreamingResponse(gen(), media_type="text/event-stream")