File size: 6,268 Bytes
7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 ee1ea3a 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 8a3b8db 0cbefb6 7d1d5af 0cbefb6 8a3b8db 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 7d1d5af 0cbefb6 8a3b8db ee1ea3a 7d1d5af 0cbefb6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | 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
# --- 1. إعداد الذاكرة السيبرانية (ChromaDB) ---
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"
# --- 2. دالة استخراج النصوص (يدعم PDF, DOCX, TXT) ---
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)}"
# --- 3. دالة الحوار (RAG) مع معالجة أخطاء الـ Stream ---
def predict(message, history, system_prompt, temperature, custom_model, oauth_token: gr.OAuthToken | None):
# استخدام توكن المستخدم المسجل (OAuth) لخصم الرصيد الشخصي
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:
# حماية ضد خطأ list index out of range
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)}"
# --- 4. بناء الواجهة (بسيطة، داكنة، ومتجاوبة) ---
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() |