| | import os |
| | import uuid |
| | import gradio as gr |
| | import chromadb |
| | from openai import OpenAI |
| | from chromadb.utils import embedding_functions |
| | from pypdf import PdfReader |
| | from docx import Document |
| |
|
| | |
| | CHROMA_DATA_PATH = "./neural_memory_v2" |
| | chroma_client = chromadb.PersistentClient(path=CHROMA_DATA_PATH) |
| | ef = embedding_functions.DefaultEmbeddingFunction() |
| | collection = chroma_client.get_or_create_collection(name="yousef_vault", embedding_function=ef) |
| |
|
| | |
| | DEFAULT_MODEL = "huihui-ai/Qwen2.5-72B-Instruct-abliterated" |
| |
|
| | |
| | def process_document(file): |
| | if file is None: return "⚠️ لم يتم اختيار ملف." |
| | text = "" |
| | try: |
| | file_ext = os.path.splitext(file.name)[1].lower() |
| | if file_ext == ".pdf": |
| | reader = PdfReader(file.name) |
| | for page in reader.pages: |
| | text += (page.extract_text() or "") + "\n" |
| | elif file_ext == ".docx": |
| | doc = Document(file.name) |
| | text = "\n".join([para.text for para in doc.paragraphs]) |
| | elif file_ext in [".txt", ".md"]: |
| | with open(file.name, "r", encoding="utf-8", errors="ignore") as f: |
| | text = f.read() |
| | |
| | if not text.strip(): |
| | return "❌ تعذر استخراج نص. تأكد أن الملف ليس صوراً فقط." |
| |
|
| | |
| | chunks = [text[i:i+2000] for i in range(0, len(text), 2000)] |
| | ids = [str(uuid.uuid4()) for _ in chunks] |
| | collection.add(documents=chunks, ids=ids) |
| | |
| | return f"✅ تمت الأرشفة: {len(chunks)} شظية معرفية حُقنت في الذاكرة." |
| | except Exception as e: |
| | return f"❌ خطأ في المعالجة: {str(e)}" |
| |
|
| | |
| | def predict(message, history, system_prompt, temperature, custom_model, oauth_token: gr.OAuthToken | None): |
| | |
| | api_key = oauth_token.token if oauth_token else os.getenv("HF_TOKEN") |
| | |
| | if not api_key: |
| | yield "⚠️ يرجى تسجيل الدخول عبر Hugging Face أولاً للوصول إلى رصيدك الشخصي." |
| | return |
| |
|
| | client = OpenAI( |
| | base_url="https://router.huggingface.co/v1", |
| | api_key=api_key |
| | ) |
| | |
| | |
| | active_model = custom_model.strip() if custom_model and custom_model.strip() else DEFAULT_MODEL |
| | |
| | |
| | results = collection.query(query_texts=[message], n_results=10) |
| | context = "\n".join(results['documents'][0]) if results['documents'] else "" |
| | |
| | |
| | messages = [{"role": "system", "content": f"{system_prompt}\n\n[CONTEXT]:\n{context}"}] |
| | |
| | for msg in history: |
| | messages.append({"role": msg['role'], "content": msg['content']}) |
| | |
| | messages.append({"role": "user", "content": message}) |
| |
|
| | try: |
| | response = client.chat.completions.create( |
| | model=active_model, |
| | messages=messages, |
| | temperature=temperature, |
| | stream=True |
| | ) |
| |
|
| | partial_message = "" |
| | for chunk in response: |
| | |
| | if hasattr(chunk, 'choices') and chunk.choices and len(chunk.choices) > 0: |
| | content = chunk.choices[0].delta.content |
| | if content: |
| | partial_message += content |
| | yield partial_message |
| | else: |
| | |
| | continue |
| | |
| | except Exception as e: |
| | if partial_message: |
| | |
| | yield partial_message |
| | else: |
| | yield f"❌ فشل الاتصال بالنموذج ({active_model}): {str(e)}" |
| |
|
| | |
| | with gr.Blocks(fill_height=True, theme=gr.themes.Soft(primary_hue="indigo")) as demo: |
| | with gr.Sidebar(): |
| | gr.Markdown("# 🧬 دهليز يوسف") |
| | gr.LoginButton("Sign in") |
| | |
| | with gr.Accordion("⚙️ الضبط والوعي", open=True): |
| | model_input = gr.Textbox( |
| | label="المحرك المستهدف (Model ID)", |
| | placeholder="اتركه فارغاً للنموذج الأساسي", |
| | value="", |
| | lines=1 |
| | ) |
| | system_input = gr.Textbox( |
| | value="أنت رفيق حكيم يغوص في التيه مع المستخدم. أجب بصدق مستعيناً بالذاكرة.", |
| | label="البرومبت النظامي" |
| | ) |
| | temp_slider = gr.Slider(0.1, 1.5, 0.8, label="درجة التشظي (Temperature)") |
| | |
| | gr.Markdown("---") |
| | gr.Markdown("### 📂 ملقم الذاكرة (PDF, DOCX, TXT)") |
| | file_box = gr.File(label="ارفع مسوداتك هنا", file_types=[".pdf", ".docx", ".txt"]) |
| | status_msg = gr.Markdown("*الذاكرة بانتظار الملفات...*") |
| | |
| | file_box.change(process_document, inputs=file_box, outputs=status_msg) |
| | |
| | clear_btn = gr.Button("🗑 مسح الذاكرة") |
| | def clear_memory(): |
| | all_data = collection.get() |
| | if all_data['ids']: |
| | collection.delete(ids=all_data['ids']) |
| | return "🗑 تم تصفير الذاكرة بالكامل." |
| | clear_btn.click(clear_memory, outputs=status_msg) |
| |
|
| | gr.ChatInterface( |
| | predict, |
| | additional_inputs=[system_input, temp_slider, model_input], |
| | fill_height=True, |
| | type="messages" |
| | ) |
| |
|
| | if __name__ == "__main__": |
| | demo.launch() |