vanhai123 commited on
Commit
8cf4b8e
·
verified ·
1 Parent(s): dc72a26

Upload 6 files

Browse files
Files changed (6) hide show
  1. README.md +0 -13
  2. app.py +199 -0
  3. generator.py +45 -0
  4. ingest.py +21 -0
  5. requirements.txt +9 -0
  6. retriever.py +21 -0
README.md CHANGED
@@ -1,13 +0,0 @@
1
- ---
2
- title: Ragflow Enterprise Search App
3
- emoji: 🚀
4
- colorFrom: red
5
- colorTo: purple
6
- sdk: gradio
7
- sdk_version: 5.27.0
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- ---
12
-
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from datetime import datetime
4
+ from retriever import retriever, reload_retriever
5
+ from generator import answer_query
6
+ from langchain_community.document_loaders import PyPDFLoader, TextLoader, CSVLoader, UnstructuredWordDocumentLoader
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain_community.embeddings import HuggingFaceEmbeddings
9
+ from langchain_community.vectorstores import FAISS
10
+
11
+ # Hàm xử lý upload tài liệu và làm mới FAISS
12
+ def process_document(file):
13
+ file_path = file.name
14
+
15
+ # Chọn loader theo đuôi file
16
+ if file_path.endswith(".pdf"):
17
+ loader = PyPDFLoader(file_path)
18
+ elif file_path.endswith(".csv"):
19
+ loader = CSVLoader(file_path)
20
+ elif file_path.endswith(".txt"):
21
+ loader = TextLoader(file_path)
22
+ elif file_path.endswith(".docx") or file_path.endswith(".doc"):
23
+ loader = UnstructuredWordDocumentLoader(file_path)
24
+ else:
25
+ return "Định dạng file không hỗ trợ!"
26
+
27
+ # Load tài liệu
28
+ documents = loader.load()
29
+
30
+ # Cắt chunk văn bản
31
+ splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
32
+ docs = splitter.split_documents(documents)
33
+
34
+ if not docs:
35
+ return "Không trích xuất được nội dung từ file tải lên."
36
+
37
+ # Tạo FAISS mới
38
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
39
+ db = FAISS.from_documents(docs, embeddings)
40
+
41
+ db.save_local("vectorstore")
42
+ reload_retriever()
43
+
44
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
45
+ return f"Đã xử lý và thêm {len(docs)} đoạn tài liệu vào VectorStore lúc {timestamp}"
46
+
47
+ # Hàm xử lý tìm kiếm
48
+ def query_function(question, model_choice, temperature, include_sources):
49
+ answer, sources = answer_query(question, model=model_choice, temperature=temperature)
50
+
51
+ if include_sources and sources:
52
+ sources_text = "\n\n**Nguồn tài liệu:**\n"
53
+ for i, doc in enumerate(sources):
54
+ sources_text += f"{i+1}. {doc.page_content}\n"
55
+ if hasattr(doc, 'metadata') and doc.metadata:
56
+ sources_text += f" - Nguồn: {doc.metadata.get('source', 'Unknown')}\n"
57
+ sources_text += f" - Trang: {doc.metadata.get('page', 'N/A')}\n"
58
+ result = answer + sources_text
59
+ else:
60
+ result = answer
61
+ result = result.encode('utf-8', errors='ignore').decode('utf-8')
62
+ return result
63
+
64
+ def clear_inputs():
65
+ return "", []
66
+
67
+ # Giao diện Gradio
68
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
69
+ with gr.Row():
70
+ with gr.Column(scale=3):
71
+ gr.Markdown(
72
+ """
73
+ # 🔎 RAGFlow Enterprise Search
74
+ ### Công cụ tìm kiếm thông minh dựa trên RAG (Retrieval-Augmented Generation)
75
+
76
+ 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.
77
+ """
78
+ )
79
+
80
+ with gr.Tabs():
81
+ # Tab tìm kiếm
82
+ with gr.TabItem("Tìm kiếm 🔍"):
83
+ with gr.Row():
84
+ with gr.Column(scale=3):
85
+ question = gr.Textbox(
86
+ label="Nhập câu hỏi của bạn:",
87
+ placeholder="Ví dụ: Quy trình xin nghỉ phép nội bộ là gì?",
88
+ lines=2
89
+ )
90
+ with gr.Column(scale=1):
91
+ model_choice = gr.Dropdown(
92
+ label="Mô hình AI",
93
+ choices=["Gemini Pro", "GPT-3.5", "GPT-4", "Claude"],
94
+ value="Gemini Pro"
95
+ )
96
+ temperature = gr.Slider(
97
+ label="Temperature",
98
+ minimum=0.0,
99
+ maximum=1.0,
100
+ value=0.2,
101
+ step=0.1
102
+ )
103
+ include_sources = gr.Checkbox(
104
+ label="Hiển thị nguồn tài liệu",
105
+ value=True
106
+ )
107
+
108
+ search_button = gr.Button("🔍 Tìm kiếm", variant="primary")
109
+ clear_button = gr.Button("🗑️ Xóa")
110
+ output = gr.Textbox(
111
+ label="Kết quả tìm kiếm:",
112
+ lines=15,
113
+ interactive=False
114
+ )
115
+
116
+ search_button.click(
117
+ query_function,
118
+ inputs=[question, model_choice, temperature, include_sources],
119
+ outputs=output
120
+ )
121
+ question.submit(
122
+ query_function,
123
+ inputs=[question, model_choice, temperature, include_sources],
124
+ outputs=output
125
+ )
126
+ clear_button.click(clear_inputs, outputs=[question, output])
127
+
128
+ # Tab quản lý tài liệu
129
+ with gr.TabItem("📚 Quản lý tài liệu"):
130
+ with gr.Row():
131
+ with gr.Column():
132
+ upload_file = gr.File(
133
+ label="Tải lên tài liệu mới (PDF, Word, CSV, TXT)",
134
+ file_types=[".pdf", ".docx", ".doc", ".csv", ".txt"]
135
+ )
136
+ upload_button = gr.Button("📤 Tải lên và xử lý", variant="primary")
137
+
138
+ with gr.Column():
139
+ upload_status = gr.Textbox(
140
+ label="📄 Trạng thái:",
141
+ lines=3,
142
+ interactive=False
143
+ )
144
+
145
+ gr.Markdown("### 📊 Danh sách tài liệu đã xử lý")
146
+ upload_button.click(
147
+ process_document,
148
+ inputs=upload_file,
149
+ outputs=upload_status
150
+ )
151
+
152
+ # Tab cài đặt (optional)
153
+ with gr.TabItem("⚙️ Cài đặt hệ thống"):
154
+ gr.Markdown("### ⚙️ Cấu hình Vector Store & Embedding")
155
+ with gr.Row():
156
+ with gr.Column():
157
+ vector_store = gr.Dropdown(
158
+ label="Vector Store",
159
+ choices=["FAISS", "Pinecone", "Milvus"],
160
+ value="FAISS"
161
+ )
162
+ embedding_model = gr.Dropdown(
163
+ label="Embedding Model",
164
+ choices=["Sentence-Transformers", "OpenAI Embeddings", "Cohere Embeddings"],
165
+ value="Sentence-Transformers"
166
+ )
167
+ with gr.Column():
168
+ chunk_size = gr.Slider(
169
+ label="Chunk size (độ dài văn bản mỗi đoạn)",
170
+ minimum=100,
171
+ maximum=1000,
172
+ value=500,
173
+ step=50
174
+ )
175
+ chunk_overlap = gr.Slider(
176
+ label="Chunk overlap (chồng lấp giữa các đoạn)",
177
+ minimum=0,
178
+ maximum=200,
179
+ value=50,
180
+ step=10
181
+ )
182
+
183
+ save_settings = gr.Button("💾 Lưu cài đặt", variant="primary")
184
+ settings_status = gr.Textbox(
185
+ label="🗂️ Trạng thái:",
186
+ interactive=False
187
+ )
188
+
189
+ def save_system_settings(vector_store, embedding_model, chunk_size, chunk_overlap):
190
+ return f"✅ Đã lưu: VectorStore={vector_store}, Embedding={embedding_model}, ChunkSize={chunk_size}, Overlap={chunk_size}"
191
+
192
+ save_settings.click(
193
+ save_system_settings,
194
+ inputs=[vector_store, embedding_model, chunk_size, chunk_overlap],
195
+ outputs=settings_status
196
+ )
197
+
198
+
199
+ demo.launch()
generator.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from retriever import retrieve_docs
3
+
4
+ API_KEY = "AIzaSyClqQssVMjt02qKrGKnghYAK9RkGf0lkS4"
5
+
6
+ def answer_query(query, model="Gemini Pro", temperature=0.2):
7
+ docs = retrieve_docs(query)
8
+ context = "\n\n".join([doc.page_content for doc in docs])
9
+ prompt = f"""Dựa trên các tài liệu sau, hãy trả lời ngắn gọn, chính xác:
10
+
11
+ {context}
12
+
13
+ Câu hỏi: {query}
14
+ Trả lời:"""
15
+
16
+ # Gửi request tới Gemini
17
+ url = f"https://generativelanguage.googleapis.com/v1/models/gemini-1.5-pro:generateContent?key={API_KEY}"
18
+
19
+ headers = {
20
+ "Content-Type": "application/json",
21
+ }
22
+
23
+ payload = {
24
+ "contents": [
25
+ {
26
+ "parts": [
27
+ {"text": prompt}
28
+ ]
29
+ }
30
+ ],
31
+ "generationConfig": {
32
+ "temperature": temperature
33
+ }
34
+ }
35
+
36
+ response = requests.post(url, headers=headers, json=payload)
37
+ data = response.json()
38
+
39
+ try:
40
+ answer = data['candidates'][0]['content']['parts'][0]['text']
41
+ except Exception as e:
42
+ print("🔴 Response từ Gemini:", data)
43
+ answer = "Lỗi khi gọi Gemini API: " + str(e)
44
+
45
+ return answer, docs
ingest.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datasets import load_dataset
2
+ from langchain.docstore.document import Document
3
+ from langchain.vectorstores import FAISS
4
+ from langchain.embeddings import HuggingFaceEmbeddings
5
+
6
+ # Load dataset
7
+ dataset = load_dataset("facebook/kilt_tasks", "fever", split="train[:10%]")
8
+
9
+ # Convert to documents
10
+ documents = []
11
+ for item in dataset:
12
+ text = item['input']
13
+ documents.append(Document(page_content=text, metadata={"id": item['id']}))
14
+
15
+ # Embed documents
16
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
17
+ db = FAISS.from_documents(documents, embeddings)
18
+
19
+ # Save FAISS index
20
+ db.save_local("vectorstore")
21
+ print("✅ Saved vectorstore!")
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ langchain
2
+ faiss-cpu
3
+ sentence-transformers
4
+ gradio
5
+ fastapi
6
+ uvicorn
7
+ huggingface_hub
8
+ datasets
9
+ google-generativeai
retriever.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from langchain_community.vectorstores import FAISS
3
+ from langchain_community.embeddings import HuggingFaceEmbeddings
4
+
5
+ # Hàm khởi tạo retriever
6
+ def load_retriever():
7
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
8
+ retriever = FAISS.load_local("vectorstore", embeddings, allow_dangerous_deserialization=True).as_retriever(search_kwargs={"k": 5})
9
+ return retriever
10
+
11
+ # Lần đầu load retriever
12
+ retriever = load_retriever()
13
+
14
+ # Hàm reload retriever khi thêm tài liệu
15
+ def reload_retriever():
16
+ global retriever
17
+ retriever = load_retriever()
18
+
19
+ # Hàm retrieve_docs để lấy tài liệu
20
+ def retrieve_docs(query):
21
+ return retriever.get_relevant_documents(query)