File size: 8,102 Bytes
8cf4b8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
import gradio as gr
import os
from datetime import datetime
from retriever import retriever, reload_retriever
from generator import answer_query
from langchain_community.document_loaders import PyPDFLoader, TextLoader, CSVLoader, UnstructuredWordDocumentLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS

# Hàm xử lý upload tài liệu và làm mới FAISS
def process_document(file):
    file_path = file.name

    # Chọn loader theo đuôi file
    if file_path.endswith(".pdf"):
        loader = PyPDFLoader(file_path)
    elif file_path.endswith(".csv"):
        loader = CSVLoader(file_path)
    elif file_path.endswith(".txt"):
        loader = TextLoader(file_path)
    elif file_path.endswith(".docx") or file_path.endswith(".doc"):
        loader = UnstructuredWordDocumentLoader(file_path)
    else:
        return "Định dạng file không hỗ trợ!"

    # Load tài liệu
    documents = loader.load()

    # Cắt chunk văn bản
    splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
    docs = splitter.split_documents(documents)

    if not docs:
        return "Không trích xuất được nội dung từ file tải lên."

    # Tạo FAISS mới 
    embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
    db = FAISS.from_documents(docs, embeddings)

    db.save_local("vectorstore")
    reload_retriever()

    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    return f"Đã xử lý và thêm {len(docs)} đoạn tài liệu vào VectorStore lúc {timestamp}"

# Hàm xử lý tìm kiếm
def query_function(question, model_choice, temperature, include_sources):
    answer, sources = answer_query(question, model=model_choice, temperature=temperature)
    
    if include_sources and sources:
        sources_text = "\n\n**Nguồn tài liệu:**\n"
        for i, doc in enumerate(sources):
            sources_text += f"{i+1}. {doc.page_content}\n"
            if hasattr(doc, 'metadata') and doc.metadata:
                sources_text += f"   - Nguồn: {doc.metadata.get('source', 'Unknown')}\n"
                sources_text += f"   - Trang: {doc.metadata.get('page', 'N/A')}\n"
        result = answer + sources_text
    else:
        result = answer
    result = result.encode('utf-8', errors='ignore').decode('utf-8')
    return result

def clear_inputs():
    return "", []

# Giao diện Gradio
with gr.Blocks(theme=gr.themes.Soft()) as demo:
    with gr.Row():
        with gr.Column(scale=3):
            gr.Markdown(
                """

                # 🔎 RAGFlow Enterprise Search

                ### Công cụ tìm kiếm thông minh dựa trên RAG (Retrieval-Augmented Generation)



                Hệ thống giúp truy xuất và trả lời câu hỏi từ tài liệu nội bộ doanh nghiệp.

                """
            )
    
    with gr.Tabs():
        # Tab tìm kiếm
        with gr.TabItem("Tìm kiếm 🔍"):
            with gr.Row():
                with gr.Column(scale=3):
                    question = gr.Textbox(
                        label="Nhập câu hỏi của bạn:",
                        placeholder="Ví dụ: Quy trình xin nghỉ phép nội bộ là gì?",
                        lines=2
                    )
                with gr.Column(scale=1):
                    model_choice = gr.Dropdown(
                        label="Mô hình AI",
                        choices=["Gemini Pro", "GPT-3.5", "GPT-4", "Claude"],
                        value="Gemini Pro"
                    )
                    temperature = gr.Slider(
                        label="Temperature",
                        minimum=0.0,
                        maximum=1.0,
                        value=0.2,
                        step=0.1
                    )
                    include_sources = gr.Checkbox(
                        label="Hiển thị nguồn tài liệu",
                        value=True
                    )
            
            search_button = gr.Button("🔍 Tìm kiếm", variant="primary")
            clear_button = gr.Button("🗑️ Xóa")
            output = gr.Textbox(
                label="Kết quả tìm kiếm:",
                lines=15,
                interactive=False
            )
            
            search_button.click(
                query_function,
                inputs=[question, model_choice, temperature, include_sources],
                outputs=output
            )
            question.submit(
                query_function,
                inputs=[question, model_choice, temperature, include_sources],
                outputs=output
            )
            clear_button.click(clear_inputs, outputs=[question, output])

        # Tab quản lý tài liệu
        with gr.TabItem("📚 Quản lý tài liệu"):
            with gr.Row():
                with gr.Column():
                    upload_file = gr.File(
                        label="Tải lên tài liệu mới (PDF, Word, CSV, TXT)",
                        file_types=[".pdf", ".docx", ".doc", ".csv", ".txt"]
                    )
                    upload_button = gr.Button("📤 Tải lên và xử lý", variant="primary")
                
                with gr.Column():
                    upload_status = gr.Textbox(
                        label="📄 Trạng thái:",
                        lines=3,
                        interactive=False
                    )
            
            gr.Markdown("### 📊 Danh sách tài liệu đã xử lý")
            upload_button.click(
                process_document,
                inputs=upload_file,
                outputs=upload_status
            )

        # Tab cài đặt (optional)
        with gr.TabItem("⚙️ Cài đặt hệ thống"):
            gr.Markdown("### ⚙️ Cấu hình Vector Store & Embedding")
            with gr.Row():
                with gr.Column():
                    vector_store = gr.Dropdown(
                        label="Vector Store",
                        choices=["FAISS", "Pinecone", "Milvus"],
                        value="FAISS"
                    )
                    embedding_model = gr.Dropdown(
                        label="Embedding Model",
                        choices=["Sentence-Transformers", "OpenAI Embeddings", "Cohere Embeddings"],
                        value="Sentence-Transformers"
                    )
                with gr.Column():
                    chunk_size = gr.Slider(
                        label="Chunk size (độ dài văn bản mỗi đoạn)",
                        minimum=100,
                        maximum=1000,
                        value=500,
                        step=50
                    )
                    chunk_overlap = gr.Slider(
                        label="Chunk overlap (chồng lấp giữa các đoạn)",
                        minimum=0,
                        maximum=200,
                        value=50,
                        step=10
                    )
            
            save_settings = gr.Button("💾 Lưu cài đặt", variant="primary")
            settings_status = gr.Textbox(
                label="🗂️ Trạng thái:",
                interactive=False
            )

            def save_system_settings(vector_store, embedding_model, chunk_size, chunk_overlap):
                return f"✅ Đã lưu: VectorStore={vector_store}, Embedding={embedding_model}, ChunkSize={chunk_size}, Overlap={chunk_size}"

            save_settings.click(
                save_system_settings,
                inputs=[vector_store, embedding_model, chunk_size, chunk_overlap],
                outputs=settings_status
            )


demo.launch()