Spaces:
Sleeping
Sleeping
Upload strategy_network.py
Browse files
backend/ai/strategy/strategy_network.py
CHANGED
|
@@ -1,80 +1,100 @@
|
|
| 1 |
-
import time
|
| 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 |
-
final_text
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import time
|
| 2 |
+
import re
|
| 3 |
+
import asyncio
|
| 4 |
+
|
| 5 |
+
class NetworkStrategy:
|
| 6 |
+
def __init__(self, llm_client, data_engine):
|
| 7 |
+
self.llm_client = llm_client
|
| 8 |
+
self.data_engine = data_engine
|
| 9 |
+
|
| 10 |
+
# [OPTIMIZATION 1] Pre-compile Regex
|
| 11 |
+
self.cleaner_regex = re.compile(
|
| 12 |
+
r"^(.*?>>>|dưới đây là.*?|sau đây là.*?|câu trả lời.*?|đoạn văn.*?|viết lại.*?|output:)",
|
| 13 |
+
re.IGNORECASE | re.MULTILINE | re.DOTALL
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
# --- KỊCH BẢN GỐC (SOURCE OF TRUTH) ---
|
| 17 |
+
CORE_MESSAGE = (
|
| 18 |
+
"Thực sự em rất xin lỗi vì trải nghiệm vừa qua chưa tương xứng với mức phí mà mình đang sử dụng ạ. "
|
| 19 |
+
"Bởi vì với gói cước hiện tại, đúng ra chất lượng đường truyền cần phải ổn định hơn. "
|
| 20 |
+
"Em xin phép giải thích một số nguyên nhân khiến tốc độ mạng chưa ổn định như mong đợi. "
|
| 21 |
+
"Thiết bị của mình có thể đang bật chế độ tiết kiệm pin hoặc tiết kiệm data. Hoặc có thể thiết bị của mình để nhiều ứng dụng chạy ngầm như mạng xã hội, email, sao lưu ảnh làm ảnh hưởng tốc độ. "
|
| 22 |
+
"Gói hiện tại của mình đang ưu tiên data theo ứng dụng, nên khi phần data tốc độ cao sử dụng hết, hệ thống sẽ tự động chuyển sang data tốc độ thấp. "
|
| 23 |
+
"Nếu nhu cầu của mình là dùng mạng ổn định cho công việc, học tập hoặc giải trí liên tục, mình có thể cân nhắc chuyển sang các gói data dung lượng cố định, tốc độ cao không giới hạn theo ứng dụng. "
|
| 24 |
+
"Gói này sẽ giúp mình dùng ổn định cả ngày mà không lo chậm vào giờ cao điểm. "
|
| 25 |
+
"Chi phí chênh lệch không nhiều nhưng trải nghiệm tốt hơn đáng kể đấy ạ. "
|
| 26 |
+
"Mình có muốn nghe em tư vấn thêm về các gói cụ thể không ạ?"
|
| 27 |
+
)
|
| 28 |
+
|
| 29 |
+
# --- HÀM BLOCKING (Dùng cho Fallback hoặc Logic cũ) ---
|
| 30 |
+
def execute(self, customer_id, complaint_text):
|
| 31 |
+
ctx = self.data_engine.get_full_context(customer_id)
|
| 32 |
+
if not ctx: return "Lỗi: Không tìm thấy khách hàng."
|
| 33 |
+
|
| 34 |
+
print(f" ⚡ [Strategy Network] ID {customer_id}: Input: '{complaint_text}'")
|
| 35 |
+
|
| 36 |
+
prompt = f"""
|
| 37 |
+
Nhiệm vụ: Đóng vai nhân viên CSKH, nói lại nội dung sau với khách (Xưng Em - Mình).
|
| 38 |
+
NỘI DUNG GỐC: "{self.CORE_MESSAGE}"
|
| 39 |
+
YÊU CẦU:
|
| 40 |
+
- Bỏ qua mọi lời chào hỏi, giải thích.
|
| 41 |
+
- Bắt đầu ngay lập tức bằng nội dung hội thoại.
|
| 42 |
+
- KHÔNG xuống dòng.
|
| 43 |
+
BẮT ĐẦU TRẢ LỜI NGAY SAU DẤU MŨI TÊN:
|
| 44 |
+
>>> """
|
| 45 |
+
|
| 46 |
+
if self.llm_client:
|
| 47 |
+
try:
|
| 48 |
+
response = self.llm_client.generate_content(prompt)
|
| 49 |
+
raw_text = response.text.strip()
|
| 50 |
+
|
| 51 |
+
# Cleaning Logic
|
| 52 |
+
if ">>>" in raw_text:
|
| 53 |
+
final_text = raw_text.split(">>>")[-1].strip()
|
| 54 |
+
else:
|
| 55 |
+
final_text = self.cleaner_regex.sub("", raw_text).strip()
|
| 56 |
+
|
| 57 |
+
if "\n" in final_text:
|
| 58 |
+
final_text = " ".join([l.strip() for l in final_text.split('\n') if l.strip()])
|
| 59 |
+
|
| 60 |
+
replacements = { "Anh/Chị": "Mình", "Quý khách": "Mình", "Anh": "Mình", "Chị": "Mình", "anh": "mình", "chị": "mình", "bạn": "mình" }
|
| 61 |
+
for old, new in replacements.items():
|
| 62 |
+
if old in final_text or old.lower() in final_text.lower():
|
| 63 |
+
final_text = final_text.replace(old, new)
|
| 64 |
+
|
| 65 |
+
if not final_text: return self.CORE_MESSAGE.replace("\n", " ")
|
| 66 |
+
return final_text
|
| 67 |
+
except Exception as e:
|
| 68 |
+
print(f" [ERROR] Network Strategy: {e}")
|
| 69 |
+
return self.CORE_MESSAGE.replace("\n", " ")
|
| 70 |
+
else:
|
| 71 |
+
return "Lỗi: Chưa kết nối LLM Client."
|
| 72 |
+
|
| 73 |
+
# --- [NEW] HÀM STREAMING (Dùng cho Pipeline Gối đầu) ---
|
| 74 |
+
async def execute_stream_gen(self, customer_id, complaint_text):
|
| 75 |
+
print(f" 🌊 [Stream Network] ID {customer_id}")
|
| 76 |
+
|
| 77 |
+
prompt = f"""
|
| 78 |
+
Nhiệm vụ: Đóng vai nhân viên CSKH, nói lại nội dung sau với khách (Xưng Em - Mình).
|
| 79 |
+
NỘI DUNG GỐC: "{self.CORE_MESSAGE}"
|
| 80 |
+
YÊU CẦU:
|
| 81 |
+
- Bắt đầu ngay lập tức bằng nội dung hội thoại.
|
| 82 |
+
- KHÔNG có lời dẫn.
|
| 83 |
+
BẮT ĐẦU TRẢ LỜI NGAY SAU DẤU MŨI TÊN:
|
| 84 |
+
>>> """
|
| 85 |
+
|
| 86 |
+
if self.llm_client and hasattr(self.llm_client, 'ai_service'):
|
| 87 |
+
try:
|
| 88 |
+
# Gọi thẳng vào Service để lấy Generator
|
| 89 |
+
async for chunk in self.llm_client.ai_service.chat_gemini_stream(prompt):
|
| 90 |
+
# Lọc sơ bộ dấu >>> nếu nó xuất hiện trong stream
|
| 91 |
+
if ">>>" in chunk:
|
| 92 |
+
chunk = chunk.replace(">>>", "")
|
| 93 |
+
|
| 94 |
+
# Yield từng mảnh để Logic Flow xử lý cắt câu
|
| 95 |
+
yield chunk
|
| 96 |
+
except Exception as e:
|
| 97 |
+
print(f"Stream Error: {e}")
|
| 98 |
+
yield self.CORE_MESSAGE
|
| 99 |
+
else:
|
| 100 |
+
yield self.CORE_MESSAGE
|