CoolFace
Apppublic

kawkabelaloom/app

sourceHugging Faceapache-2.0updated 9mo agoView on Hugging Face
0likes
app.py353 linesDownload Raw Back to root
1"""2🤖 نظام RAG للمستندات - إصدار Gradio لـ HuggingFace3"""4 5import os6import tempfile7import numpy as np8import faiss9import nltk10from pypdf import PdfReader11from sentence_transformers import SentenceTransformer12import gradio as gr13import time14 15# ==================== تهيئة النظام ====================16class FlowRAGSystem:17    def __init__(self):18        self.model = None19        self.index = None20        self.chunks = None21        self.current_file = None22        self.is_ready = False23    24    def initialize(self):25        """تهيئة النظام"""26        try:27            # تحميل موارد NLTK28            try:29                nltk.download('punkt', quiet=True)30                nltk.download('punkt_tab', quiet=True)31            except:32                pass33            34            self.model = SentenceTransformer(35                "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"36            )37            self.is_ready = True38            return True39        except Exception as e:40            return f"❌ خطأ في تحميل النموذج: {str(e)}"41    42    def process_pdf(self, pdf_file):43        """معالجة ملف PDF"""44        try:45            self.current_file = pdf_file.name46            47            # حفظ الملف المؤقت48            with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file:49                tmp_file.write(pdf_file.read())50                pdf_path = tmp_file.name51            52            # قراءة PDF53            reader = PdfReader(pdf_path)54            pages_data = []55            56            for i, page in enumerate(reader.pages):57                text = page.extract_text()58                if text and text.strip():59                    pages_data.append({60                        'page': i + 1,61                        'text': text.strip()62                    })63            64            if not pages_data:65                os.unlink(pdf_path)66                return "❌ لم يتم العثور على نص في الملف"67            68            # تقسيم النص69            self.chunks = []70            for page in pages_data:71                words = page['text'].split()72                73                # تقسيم إلى أجزاء 200 كلمة مع تداخل 4074                chunk_size = 20075                overlap = 4076                77                start = 078                while start < len(words):79                    end = start + chunk_size80                    chunk_words = words[start:end]81                    82                    if chunk_words:83                        self.chunks.append({84                            'text': ' '.join(chunk_words),85                            'page': page['page'],86                            'word_count': len(chunk_words)87                        })88                    89                    start += chunk_size - overlap90            91            # إنشاء embeddings92            if len(self.chunks) > 0:93                chunk_texts = [chunk['text'] for chunk in self.chunks]94                embeddings = self.model.encode(95                    chunk_texts,96                    normalize_embeddings=True,97                    show_progress_bar=False98                )99                100                # بناء الفهرس101                dimension = embeddings.shape[1]102                self.index = faiss.IndexFlatIP(dimension)103                faiss.normalize_L2(embeddings)104                self.index.add(embeddings)105            else:106                os.unlink(pdf_path)107                return "❌ لم يتم إنشاء أي أجزاء نصية"108            109            # تنظيف الملف المؤقت110            os.unlink(pdf_path)111            112            return f"✅ تم معالجة المستند بنجاح!\n📊 {len(pages_data)} صفحة → {len(self.chunks)} جزء نصي"113            114        except Exception as e:115            return f"❌ خطأ في معالجة PDF: {str(e)}"116    117    def search(self, query, top_k=3):118        """بحث في المستند"""119        if not self.is_ready or self.index is None:120            return "❌ يرجى معالجة مستند أولاً"121        122        try:123            query_embedding = self.model.encode([query], normalize_embeddings=True)124            scores, indices = self.index.search(query_embedding, top_k)125            126            results = []127            for i, (score, idx) in enumerate(zip(scores[0], indices[0])):128                if 0 <= idx < len(self.chunks):129                    chunk = self.chunks[idx]130                    131                    # تحديد لون التشابه132                    similarity_score = float(score)133                    if similarity_score >= 0.5:134                        sim_color = "#28a745"  # أخضر135                        sim_text = "ممتاز"136                    elif similarity_score >= 0.3:137                        sim_color = "#ffc107"  # أصفر138                        sim_text = "جيد"139                    else:140                        sim_color = "#dc3545"  # أحمر141                        sim_text = "ضعيف"142                    143                    results.append(f"""144                    <div style="background: #f8f9fa; border-radius: 10px; padding: 1.5rem; 145                    margin: 1rem 0; border-left: 5px solid {sim_color}; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">146                        <h4 style="margin-top: 0;">🏆 النتيجة #{i+1}</h4>147                        <p style="margin-bottom: 0.5rem;">148                            <span style="color: {sim_color}; font-weight: bold;">التشابه: {score*100:.1f}% ({sim_text})</span> | 149                            📖 الصفحة: {chunk['page']} | 150                            🔢 الكلمات: {chunk['word_count']}151                        </p>152                        <hr style="margin: 0.5rem 0;">153                        <p>{chunk['text'][:400]}...</p>154                    </div>155                    """)156            157            if not results:158                return "❌ لم أجد نتائج ذات صلة في المستند"159            160            return f"<h3>🔍 تم العثور على {len(results)} نتيجة:</h3>" + "".join(results)161            162        except Exception as e:163            return f"❌ خطأ في البحث: {str(e)}"164 165# ==================== إنشاء النظام ====================166rag_system = FlowRAGSystem()167init_result = rag_system.initialize()168 169# ==================== واجهة Gradio ====================170with gr.Blocks(title="🤖 نظام RAG الذكي للمستندات", theme=gr.themes.Soft()) as demo:171    172    # العنوان173    gr.Markdown("""174    # 🤖 نظام RAG الذكي للمستندات175    ### بحث دلالي متقدم في ملفات PDF - يدعم العربية والإنجليزية176    """)177    178    # منطقة التنبيهات179    if init_result is not True:180        gr.Warning(f"⚠️ {init_result}")181    else:182        gr.Info("✅ النظام جاهز للاستخدام")183    184    with gr.Row():185        with gr.Column(scale=2):186            # قسم رفع الملف187            with gr.Group():188                gr.Markdown("## 📁 رفع ومعالجة المستند")189                file_input = gr.File(190                    label="اختر ملف PDF",191                    file_types=[".pdf"],192                    type="binary"193                )194                process_btn = gr.Button("🚀 معالجة المستند", variant="primary")195                process_output = gr.Markdown(label="حالة المعالجة")196            197            # قسم البحث198            with gr.Group():199                gr.Markdown("## 💬 اسأل عن المستند")200                question_input = gr.Textbox(201                    label="اكتب سؤالك هنا",202                    placeholder="مثال: ما هي حالة التدفق؟ أو What is flow state?",203                    lines=3204                )205                206                with gr.Row():207                    top_k_slider = gr.Slider(208                        minimum=1, maximum=5, value=3,209                        label="عدد النتائج"210                    )211                    search_btn = gr.Button("🔍 ابحث في المستند", variant="primary")212                213                search_output = gr.HTML(label="نتائج البحث")214        215        with gr.Column(scale=1):216            # الشريط الجانبي217            with gr.Group():218                gr.Markdown("## 💡 أسئلة سريعة")219                220                example_questions = [221                    "ما هي حالة التدفق؟",222                    "What is flow state?",223                    "ما هي عناصر التجربة المثلى؟",224                    "كيف يحقق الإنسان السعادة في العمل؟",225                    "ما هو دور التركيز في التدفق؟"226                ]227                228                for question in example_questions:229                    gr.Button(230                        question,231                        size="sm",232                    ).click(233                        fn=lambda q=question: q,234                        inputs=[],235                        outputs=[question_input]236                    )237            238            with gr.Group():239                gr.Markdown("## 🎯 نصائح البحث")240                gr.Markdown("""241                **لأفضل النتائج:**242                243                • استخدم مصطلحات محددة  244                • جرب اللغتين (عربي/إنجليزي)  245                • اطرح أسئلة واضحة  246                247                **مثال:**  248                ✅ "ما هي خصائص flow state؟"  249                ❌ "اشرح لي"250                """)251            252            with gr.Group():253                gr.Markdown("## 📊 معلومات النظام")254                status_text = gr.Markdown("📄 لم يتم معالجة أي مستند بعد")255                256                # تحديث حالة النظام257                def update_status():258                    if rag_system.current_file:259                        file_info = f"📄 الملف: {rag_system.current_file}"260                        if rag_system.chunks:261                            chunks_info = f" | 📊 الأجزاء: {len(rag_system.chunks)}"262                            if rag_system.index:263                                vectors_info = f" | 🧮 المتجهات: {rag_system.index.ntotal}"264                                return file_info + chunks_info + vectors_info265                            return file_info + chunks_info266                        return file_info267                    return "📄 لم يتم معالجة أي مستند بعد"268                269                status_display = gr.Markdown(update_status())270    271    # نصائح إضافية272    gr.Markdown("---")273    with gr.Row():274        with gr.Column():275            gr.Markdown("### 📚 عن النظام")276            gr.Markdown("""277            **التقنيات المستخدمة:**278            279            • 🤖 **Sentence Transformers** - نماذج embedding متعددة اللغات  280            • ⚡ **FAISS** - بحث سريع في المتجهات  281            • 📄 **PyPDF** - معالجة ملفات PDF  282            • 🌐 **Gradio** - واجهة مستخدم تفاعلية283            """)284        285        with gr.Column():286            gr.Markdown("### 🌍 الدعم اللغوي")287            gr.Markdown("""288            **اللغات المدعومة:**289            290            • العربية - البحث والنتائج  291            • الإنجليزية - البحث والنتائج  292            • الفرنسية، الإسبانية، الألمانية - البحث الأساسي293            294            **المميزات:**  295            ✓ بحث دلالي ذكي  296            ✓ نتائج مرتبة حسب الصلة  297            ✓ دعم ملفات كبيرة298            """)299    300    # تذييل الصفحة301    gr.Markdown("---")302    gr.Markdown("""303    <div style="text-align: center; color: #666;">304        <p>🤖 نظام RAG للمستندات | إصدار HuggingFace Spaces</p>305        <p>تقنية: FAISS + Sentence Transformers + Gradio | يدعم العربية والإنجليزية</p>306    </div>307    """)308    309    # ==================== معالجة الأحداث ====================310    def process_file(file):311        if file is None:312            return "⚠️ يرجى اختيار ملف PDF أولاً"313        314        result = rag_system.process_pdf(file)315        return result316    317    def search_query(question, top_k):318        if not question:319            return "⚠️ يرجى إدخال سؤال"320        321        return rag_system.search(question, int(top_k))322    323    # ربط الأحداث324    process_btn.click(325        fn=process_file,326        inputs=[file_input],327        outputs=[process_output]328    ).then(329        fn=update_status,330        inputs=[],331        outputs=[status_display]332    )333    334    search_btn.click(335        fn=search_query,336        inputs=[question_input, top_k_slider],337        outputs=[search_output]338    )339    340    # معالجة ضغط Enter في حقل السؤال341    question_input.submit(342        fn=search_query,343        inputs=[question_input, top_k_slider],344        outputs=[search_output]345    )346 347# ==================== تشغيل التطبيق ====================348if __name__ == "__main__":349    demo.launch(350        server_name="0.0.0.0",351        server_port=7860,352        share=False353    )