VietCat commited on
Commit
25d4844
·
1 Parent(s): 4487291
Files changed (3) hide show
  1. Dockerfile +2 -2
  2. app.py +20 -30
  3. rag_core/business.py +39 -14
Dockerfile CHANGED
@@ -16,5 +16,5 @@ RUN pip install --no-cache-dir -r requirements.txt
16
  # Mở port cho FastAPI & Gradio
17
  EXPOSE 7860
18
 
19
- # Khởi chạy app
20
- CMD ["python", "app.py"]
 
16
  # Mở port cho FastAPI & Gradio
17
  EXPOSE 7860
18
 
19
+ # Command khởi chạy FastAPI + Gradio tích hợp
20
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py CHANGED
@@ -1,45 +1,35 @@
1
  import logging
2
- import gradio as gr
3
  from fastapi import FastAPI, Request
4
- from rag_core import business
5
- import threading
6
- import uvicorn
7
 
8
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
 
9
 
10
- # FastAPI dùng cho API nếu cần gọi từ backend hoặc automation
11
- api_app = FastAPI()
12
 
13
- @api_app.post("/ask")
14
  async def ask_api(req: Request):
15
  data = await req.json()
16
- return business.answer_query(data.get("query"))
 
17
 
18
- @api_app.post("/rescan")
19
  async def rescan_api():
20
- return business.rescan_index()
21
-
22
- # Gradio UI
23
- def answer_fn(query):
24
- result = business.answer_query(query)
25
- return result.get("answer", result.get("error", "Lỗi không xác định."))
26
 
27
- def build_index_ui():
28
- business.build_index()
29
- return gr.update(visible=False), gr.update(visible=True), gr.update(visible=True)
 
 
30
 
31
- with gr.Blocks() as iface:
32
- build_btn = gr.Button("🔄 Xây Index", visible=not business.ready)
33
- query_box = gr.Textbox(label="Nhập câu hỏi", visible=business.ready)
34
- output_box = gr.Textbox(label="Trả lời", visible=business.ready)
35
- query_box.submit(fn=answer_fn, inputs=query_box, outputs=output_box)
36
- build_btn.click(fn=build_index_ui, outputs=[build_btn, query_box, output_box])
37
 
38
- # Chạy FastAPI trong thread phụ (nếu cần gọi /ask /rescan qua HTTP)
39
- def start_fastapi():
40
- uvicorn.run(api_app, host="0.0.0.0", port=7861)
41
 
42
- threading.Thread(target=start_fastapi).start()
 
43
 
44
- # 🚀 Gradio chạy app chính (bắt buộc với Hugging Face)
45
- iface.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import logging
 
2
  from fastapi import FastAPI, Request
3
+ import gradio as gr
4
+ from rag_core.business import build_index, answer_query, rescan_index
 
5
 
6
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
7
+ logging.info("🚀 Khởi chạy FastAPI + Gradio tại cổng 7860")
8
 
9
+ app = FastAPI()
 
10
 
11
+ @app.post("/ask")
12
  async def ask_api(req: Request):
13
  data = await req.json()
14
+ query = data.get("query", "")
15
+ return answer_query(query)
16
 
17
+ @app.post("/rescan")
18
  async def rescan_api():
19
+ return rescan_index()
 
 
 
 
 
20
 
21
+ def gradio_ui():
22
+ with gr.Blocks() as ui:
23
+ build_btn = gr.Button("🔄 Xây Index")
24
+ query_box = gr.Textbox(label="Nhập câu hỏi")
25
+ output_box = gr.Textbox(label="Trả lời")
26
 
27
+ build_btn.click(fn=lambda: build_index() or "✅ Đã xây xong Index.", outputs=None)
28
+ query_box.submit(fn=lambda q: answer_query(q)["answer"], inputs=query_box, outputs=output_box)
 
 
 
 
29
 
30
+ return ui
 
 
31
 
32
+ # Mount Gradio vào FastAPI
33
+ app = gr.mount_gradio_app(app, gradio_ui(), path="/")
34
 
35
+ # Run với: uvicorn app:app --host 0.0.0.0 --port 7860
 
rag_core/business.py CHANGED
@@ -11,25 +11,50 @@ ready = retriever.index is not None
11
  def build_index():
12
  global ready
13
  logging.info("🔄 Bắt đầu xây FAISS index từ đầu...")
14
- with open("data/raw_law.txt", "r", encoding="utf-8") as f:
15
- text = f.read()
16
- chunks = chunk_legal_text(text)
17
- retriever.build(chunks, get_embedding)
18
- ready = True
 
 
 
 
 
 
 
19
 
20
  def answer_query(query):
 
21
  if not ready:
 
22
  return {"error": "Index chưa sẵn sàng. Vui lòng bấm 'Xây Index' hoặc gọi API rescan."}
23
- docs = retriever.query(query, get_embedding)
24
- prompt = "\n\n".join(docs) + f"\n\nCâu hỏi: {query}\nTrả lời:"
25
- answer = generate_answer(prompt)
26
- return {"answer": answer}
 
 
 
 
 
 
 
27
 
28
  def rescan_index():
 
29
  if not ready:
 
30
  return {"error": "Index chưa sẵn sàng."}
31
- with open("data/raw_law.txt", "r", encoding="utf-8") as f:
32
- text = f.read()
33
- chunks = chunk_legal_text(text)
34
- retriever.rescan_and_append(chunks, get_embedding)
35
- return {"status": "Rescan & update thành công."}
 
 
 
 
 
 
 
 
11
  def build_index():
12
  global ready
13
  logging.info("🔄 Bắt đầu xây FAISS index từ đầu...")
14
+ try:
15
+ with open("data/raw_law.txt", "r", encoding="utf-8") as f:
16
+ text = f.read()
17
+ logging.info("📄 Đọc xong file văn bản luật.")
18
+ chunks = chunk_legal_text(text)
19
+ logging.info(f"🔪 Chunking hoàn tất: {len(chunks)} đoạn.")
20
+ retriever.build(chunks, get_embedding)
21
+ ready = True
22
+ logging.info("✅ Đã xây xong FAISS index.")
23
+ except Exception as e:
24
+ logging.exception(f"❌ Lỗi khi xây index: {e}")
25
+ raise
26
 
27
  def answer_query(query):
28
+ logging.info("💬 Nhận yêu cầu hỏi đáp.")
29
  if not ready:
30
+ logging.warning("⚠️ Index chưa sẵn sàng.")
31
  return {"error": "Index chưa sẵn sàng. Vui lòng bấm 'Xây Index' hoặc gọi API rescan."}
32
+ try:
33
+ logging.info(f"🔍 Truy vấn: {query}")
34
+ docs = retriever.query(query, get_embedding)
35
+ logging.info(f"📚 Top {len(docs)} đoạn liên quan được truy xuất.")
36
+ prompt = "\n\n".join(docs) + f"\n\nCâu hỏi: {query}\nTrả lời:"
37
+ answer = generate_answer(prompt)
38
+ logging.info("✅ Đã nhận được phản hồi từ LLM.")
39
+ return {"answer": answer}
40
+ except Exception as e:
41
+ logging.exception(f"❌ Lỗi khi xử lý truy vấn: {e}")
42
+ return {"error": "Lỗi khi xử lý truy vấn."}
43
 
44
  def rescan_index():
45
+ logging.info("🔄 Thực hiện rescan & bổ sung FAISS index.")
46
  if not ready:
47
+ logging.warning("⚠️ Index chưa sẵn sàng.")
48
  return {"error": "Index chưa sẵn sàng."}
49
+ try:
50
+ with open("data/raw_law.txt", "r", encoding="utf-8") as f:
51
+ text = f.read()
52
+ logging.info("📄 Đọc xong file văn bản luật.")
53
+ chunks = chunk_legal_text(text)
54
+ logging.info(f"🔍 Số chunk sau chunking: {len(chunks)}")
55
+ retriever.rescan_and_append(chunks, get_embedding)
56
+ logging.info("✅ Đã rescan & cập nhật thành công.")
57
+ return {"status": "Rescan & update thành công."}
58
+ except Exception as e:
59
+ logging.exception(f"❌ Lỗi khi rescan index: {e}")
60
+ return {"error": "Lỗi khi rescan index."}