deddoggo commited on
Commit
cb8759a
·
1 Parent(s): 8829c2d

change gen model

Browse files
Files changed (2) hide show
  1. app.py +16 -35
  2. rag_pipeline.py +15 -79
app.py CHANGED
@@ -2,66 +2,48 @@
2
  import gradio as gr
3
  import time
4
 
5
- # Đảm bảo import đúng các hàm cần thiết từ rag_pipeline
6
  from rag_pipeline import initialize_components, generate_response
7
 
8
- # --- KHỞI TẠO CÁC THÀNH PHẦN (CHỈ CHẠY 1 LẦN KHI ỨNG DỤNG START) ---
9
  start_time = time.time()
10
  print("Bắt đầu khởi tạo ứng dụng Chatbot Luật Giao thông...")
11
- # Đường dẫn đến file dữ liệu của bạn
12
- DATA_PATH = "data/luat_chi_tiet_output_openai_sdk_final_cleaned.json"
13
- # Hàm này sẽ tải models, dữ liệu, và tạo index.
14
  COMPONENTS = initialize_components(DATA_PATH)
15
  end_time = time.time()
16
  print(f"✅ Ứng dụng đã sẵn sàng! Thời gian khởi tạo: {end_time - start_time:.2f} giây.")
17
  # ----------------------------------------------------
18
 
19
 
 
 
 
 
 
 
 
 
 
20
  # --- GIAO DIỆN GRADIO ---
21
  with gr.Blocks(theme=gr.themes.Soft(), title="Chatbot Luật Giao thông Việt Nam") as demo:
22
  gr.Markdown(
23
  """
24
- # ⚖️ Chatbot Luật Giao thông Việt Nam (Multi-turn)
25
- Hỏi đáp về các quy định, mức phạt trong luật giao thông đường bộ. Chatbot thể hiểu các câu hỏi nối tiếp.
26
  *Lưu ý: Đây là một sản phẩm demo. Thông tin chỉ mang tính chất tham khảo.*
27
  """
28
  )
29
 
30
- # Sử dụng gr.Chatbot để quản lý và hiển thị lịch sử trò chuyện
31
- chatbot = gr.Chatbot(label="Cuộc trò chuyện", height=500)
32
- # Textbox để người dùng nhập câu hỏi
33
  msg = gr.Textbox(label="Nhập câu hỏi của bạn", placeholder="Ví dụ: Vượt đèn đỏ bị phạt bao nhiêu tiền?")
34
- # Nút để xóa cuộc trò chuyện
35
  clear = gr.ClearButton([msg, chatbot])
36
 
37
  def respond(message, chat_history):
38
- """
39
- Hàm xử lý logic cho mỗi lượt chat.
40
- 'message' là tin nhắn mới nhất của người dùng.
41
- 'chat_history' là danh sách các cặp [tin nhắn cũ, trả lời cũ] do Gradio quản lý.
42
- """
43
- print(f"Nhận được câu hỏi: '{message}'")
44
- print(f"Lịch sử trò chuyện hiện tại: {chat_history}")
45
-
46
- # Gọi thẳng hàm generate_response với các tham số cần thiết:
47
- # 1. message: câu hỏi mới
48
- # 2. chat_history: lịch sử trò chuyện
49
- # 3. COMPONENTS: dictionary chứa các model và dữ liệu đã được khởi tạo
50
- bot_message = generate_response(message, chat_history, COMPONENTS)
51
-
52
- # Cập nhật lịch sử để hiển thị trên giao diện
53
  chat_history.append((message, bot_message))
54
-
55
- # Trả về chuỗi rỗng để xóa nội dung trong textbox và lịch sử đã được cập nhật
56
  return "", chat_history
57
 
58
- # Thiết lập sự kiện: khi người dùng 'submit' (nhấn Enter) trong textbox 'msg',
59
- # hàm 'respond' sẽ được gọi.
60
- # - Inputs: nội dung từ 'msg' và 'chatbot' (lịch sử).
61
- # - Outputs: cập nhật lại nội dung cho 'msg' (thành rỗng) và 'chatbot' (lịch sử mới).
62
  msg.submit(respond, [msg, chatbot], [msg, chatbot])
63
 
64
- # Thêm một vài ví dụ để người dùng dễ bắt đầu
65
  gr.Examples(
66
  examples=[
67
  "Phương tiện giao thông đường bộ gồm những loại nào?",
@@ -72,6 +54,5 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Chatbot Luật Giao thông Việt
72
  inputs=msg
73
  )
74
 
75
- # Chạy ứng dụng
76
  if __name__ == "__main__":
77
- demo.launch()
 
2
  import gradio as gr
3
  import time
4
 
 
5
  from rag_pipeline import initialize_components, generate_response
6
 
7
+ # --- KHỞI TẠO CÁC THÀNH PHẦN (CHỈ CHẠY 1 LẦN) ---
8
  start_time = time.time()
9
  print("Bắt đầu khởi tạo ứng dụng Chatbot Luật Giao thông...")
10
+ DATA_PATH = "data/luat_chi_tiet_output_openai_sdk_final_cleaned.json"
 
 
11
  COMPONENTS = initialize_components(DATA_PATH)
12
  end_time = time.time()
13
  print(f"✅ Ứng dụng đã sẵn sàng! Thời gian khởi tạo: {end_time - start_time:.2f} giây.")
14
  # ----------------------------------------------------
15
 
16
 
17
+ def chat_interface(query, history):
18
+ """
19
+ Hàm xử lý logic cho giao diện chat của Gradio.
20
+ """
21
+ print(f"Nhận được câu hỏi từ người dùng: '{query}'")
22
+ # Gọi hàm generate_response với query và các thành phần đã được khởi tạo
23
+ response = generate_response(query, COMPONENTS)
24
+ return response
25
+
26
  # --- GIAO DIỆN GRADIO ---
27
  with gr.Blocks(theme=gr.themes.Soft(), title="Chatbot Luật Giao thông Việt Nam") as demo:
28
  gr.Markdown(
29
  """
30
+ # ⚖️ Chatbot Luật Giao thông Việt Nam
31
+ Hỏi đáp về các quy định, mức phạt trong luật giao thông đường bộ dựa trên sở dữ liệu được cung cấp.
32
  *Lưu ý: Đây là một sản phẩm demo. Thông tin chỉ mang tính chất tham khảo.*
33
  """
34
  )
35
 
36
+ chatbot = gr.Chatbot(label="Chatbot", height=500)
 
 
37
  msg = gr.Textbox(label="Nhập câu hỏi của bạn", placeholder="Ví dụ: Vượt đèn đỏ bị phạt bao nhiêu tiền?")
 
38
  clear = gr.ClearButton([msg, chatbot])
39
 
40
  def respond(message, chat_history):
41
+ bot_message = chat_interface(message, chat_history)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  chat_history.append((message, bot_message))
 
 
43
  return "", chat_history
44
 
 
 
 
 
45
  msg.submit(respond, [msg, chatbot], [msg, chatbot])
46
 
 
47
  gr.Examples(
48
  examples=[
49
  "Phương tiện giao thông đường bộ gồm những loại nào?",
 
54
  inputs=msg
55
  )
56
 
 
57
  if __name__ == "__main__":
58
+ demo.launch()
rag_pipeline.py CHANGED
@@ -79,89 +79,28 @@ def initialize_components(data_path):
79
  "bm25_model": bm25_model
80
  }
81
 
82
- def format_history(chat_history):
83
- """Định dạng lịch sử trò chuyện thành một chuỗi dễ đọc cho LLM."""
84
- if not chat_history:
85
- return ""
86
- formatted = []
87
- for user_turn, bot_turn in chat_history:
88
- formatted.append(f"Người dùng: {user_turn}")
89
- formatted.append(f"Bot: {bot_turn}")
90
- return "\n".join(formatted)
91
-
92
- def create_standalone_question(question, chat_history, components):
93
  """
94
- Sử dụng LLM để tạo một câu hỏi độc lập dựa trên câu hỏi mới lịch sử trò chuyện.
95
  """
96
- llm_model = components["llm_model"]
97
- tokenizer = components["tokenizer"]
98
-
99
- # Định dạng lịch sử trò chuyện
100
- history_str = format_history(chat_history)
101
-
102
- # Nếu không có lịch sử, câu hỏi đã là độc lập
103
- if not history_str:
104
- return question
105
-
106
- prompt = f"""Dựa vào lịch sử trò chuyện dưới đây và câu hỏi theo sau, hãy tạo ra một câu hỏi độc lập, đầy đủ ngữ nghĩa.
107
- Câu hỏi mới này phải có thể hiểu được mà không cần đọc lại lịch sử.
108
- Chỉ trả về câu hỏi đã được viết lại, không thêm bất kỳ lời giải thích nào.
109
-
110
- ### Lịch sử trò chuyện:
111
- {history_str}
112
-
113
- ### Câu hỏi theo sau:
114
- {question}
115
-
116
- ### Câu hỏi độc lập:
117
- """
118
-
119
- inputs = tokenizer(prompt, return_tensors="pt").to("cuda" if torch.cuda.is_available() else "cpu")
120
-
121
- # Generate với max_new_tokens nhỏ vì chỉ cần tạo lại câu hỏi
122
- output_ids = llm_model.generate(
123
- **inputs,
124
- max_new_tokens=100,
125
- temperature=0.1,
126
- do_sample=True,
127
- pad_token_id=tokenizer.eos_token_id
128
- )
129
-
130
- input_length = inputs.input_ids.shape[1]
131
- generated_ids = output_ids[0][input_length:]
132
- standalone_question = tokenizer.decode(generated_ids, skip_special_tokens=True).strip()
133
-
134
- print(f"--- Câu hỏi gốc: '{question}'")
135
- print(f"--- Câu hỏi độc lập được tạo: '{standalone_question}'")
136
-
137
- return standalone_question
138
-
139
-
140
- def generate_response(query, chat_history, components): # Thêm chat_history
141
- """
142
- Tạo câu trả lời cho một query, có xem xét đến lịch sử trò chuyện.
143
- """
144
- print("--- Bắt đầu quy trình RAG (Multi-turn) cho query mới ---")
145
 
146
  # Unpack các thành phần
147
  llm_model = components["llm_model"]
148
  tokenizer = components["tokenizer"]
149
-
150
- # 1. [MỚI] Tạo câu hỏi độc lập từ lịch sử
151
- standalone_query = create_standalone_question(query, chat_history, components)
152
 
153
- # 2. Truy xuất ngữ cảnh bằng câu hỏi độc lập
154
  retrieved_results = search_relevant_laws(
155
- query_text=standalone_query, # Sử dụng câu hỏi đã được cô đọng
156
  embedding_model=components["embedding_model"],
157
  faiss_index=components["faiss_index"],
158
  chunks_data=components["chunks_data"],
159
  bm25_model=components["bm25_model"],
160
- k=3,
161
  initial_k_multiplier=18
162
  )
163
 
164
- # 3. Định dạng Context (giữ nguyên)
165
  if not retrieved_results:
166
  context = "Không tìm thấy thông tin luật liên quan trong cơ sở dữ liệu."
167
  else:
@@ -173,23 +112,20 @@ def generate_response(query, chat_history, components): # Thêm chat_history
173
  context_parts.append(f"{header}\n{text}")
174
  context = "\n\n---\n\n".join(context_parts)
175
 
176
- # 4. Xây dựng Prompt cuối cùng (có thêm lịch sử)
177
- history_str = format_history(chat_history)
178
- prompt = f"""Bạn một trợ am hiểu luật giao thông Việt Nam. Dựa vào lịch sử trò chuyện và các thông tin luật được cung cấp dưới đây, hãy trả lời câu hỏi của người dùng một cách tự nhiênchính xác.
179
-
180
- ### Lịch sử trò chuyện:
181
- {history_str}
182
 
183
- ### Thông tin luật liên quan (dùng để trả lời câu hỏi mới nhất):
184
  {context}
185
 
186
- ### Câu hỏi mới nhất của người dùng:
187
  {query}
188
 
189
- ### Trả lời của bạn:
190
- """
191
 
192
- print("--- Bắt đầu tạo câu trả lời cuối cùng từ LLM ---")
193
  inputs = tokenizer(prompt, return_tensors="pt").to("cuda" if torch.cuda.is_available() else "cpu")
194
 
195
  generation_config = dict(
 
79
  "bm25_model": bm25_model
80
  }
81
 
82
+ def generate_response(query, components):
 
 
 
 
 
 
 
 
 
 
83
  """
84
+ Tạo câu trả lời cho một query bằng cách sử dụng các thành phần đã được khởi tạo.
85
  """
86
+ print("--- Bắt đầu quy trình RAG cho query mới ---")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  # Unpack các thành phần
89
  llm_model = components["llm_model"]
90
  tokenizer = components["tokenizer"]
 
 
 
91
 
92
+ # 1. Truy xuất ngữ cảnh
93
  retrieved_results = search_relevant_laws(
94
+ query_text=query,
95
  embedding_model=components["embedding_model"],
96
  faiss_index=components["faiss_index"],
97
  chunks_data=components["chunks_data"],
98
  bm25_model=components["bm25_model"],
99
+ k=5,
100
  initial_k_multiplier=18
101
  )
102
 
103
+ # 2. Định dạng Context
104
  if not retrieved_results:
105
  context = "Không tìm thấy thông tin luật liên quan trong cơ sở dữ liệu."
106
  else:
 
112
  context_parts.append(f"{header}\n{text}")
113
  context = "\n\n---\n\n".join(context_parts)
114
 
115
+ # 3. Xây dựng Prompt tạo câu trả lời
116
+ prompt = f"""Dưới đây là một số thông tin trích dẫn từ văn bản luật giao thông đường bộ Việt Nam.
117
+ Hãy SỬ DỤNG CÁC THÔNG TIN NÀY để trả lời câu hỏi một cách chính xácđầy đủ.
118
+ Nếu câu hỏi đưa ra nhiều đáp án thì chọn 1 đáp án đúng nhất.
 
 
119
 
120
+ ### Thông tin luật:
121
  {context}
122
 
123
+ ### Câu hỏi:
124
  {query}
125
 
126
+ ### Trả lời:"""
 
127
 
128
+ print("--- Bắt đầu tạo câu trả lời từ LLM ---")
129
  inputs = tokenizer(prompt, return_tensors="pt").to("cuda" if torch.cuda.is_available() else "cpu")
130
 
131
  generation_config = dict(