Commit
·
0254ce4
1
Parent(s):
68c8519
修正資料庫增強查詢
Browse files- backend/services/enhanced_product_service.py +31 -5
- debug_cat_litter_query.py +275 -0
- test_final_fix.py +193 -0
- test_fixed_keywords.py +164 -0
backend/services/enhanced_product_service.py
CHANGED
@@ -298,11 +298,31 @@ class EnhancedProductService:
|
|
298 |
def _extract_keywords(self, query_text: str) -> List[str]:
|
299 |
"""從查詢文字中提取關鍵字,並擴展相關詞彙"""
|
300 |
# 移除常見的查詢詞彙
|
301 |
-
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋']
|
|
|
|
|
|
|
302 |
|
303 |
# 分割並清理關鍵字
|
304 |
-
words =
|
305 |
-
keywords = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
306 |
|
307 |
# 擴展相關關鍵字
|
308 |
expanded_keywords = []
|
@@ -311,7 +331,7 @@ class EnhancedProductService:
|
|
311 |
|
312 |
# 貓砂相關擴展
|
313 |
if '貓砂' in keyword or '貓' in keyword:
|
314 |
-
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter'])
|
315 |
|
316 |
# 狗糧相關擴展
|
317 |
if '狗糧' in keyword or '狗' in keyword:
|
@@ -321,4 +341,10 @@ class EnhancedProductService:
|
|
321 |
if '寵物' in keyword:
|
322 |
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
323 |
|
324 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
def _extract_keywords(self, query_text: str) -> List[str]:
|
299 |
"""從查詢文字中提取關鍵字,並擴展相關詞彙"""
|
300 |
# 移除常見的查詢詞彙
|
301 |
+
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋', '還有嗎', '還有', '嗎']
|
302 |
+
|
303 |
+
# 清理查詢文字
|
304 |
+
cleaned_text = query_text.replace('?', '').replace('?', '').strip()
|
305 |
|
306 |
# 分割並清理關鍵字
|
307 |
+
words = cleaned_text.split()
|
308 |
+
keywords = []
|
309 |
+
|
310 |
+
for word in words:
|
311 |
+
if word not in stop_words and len(word) > 1:
|
312 |
+
keywords.append(word)
|
313 |
+
|
314 |
+
# 如果沒有有效關鍵字,嘗試從原始文字中提取核心詞彙
|
315 |
+
if not keywords:
|
316 |
+
# 嘗試提取核心商品詞彙
|
317 |
+
core_words = ['貓砂', '狗糧', '寵物', '商品', '產品']
|
318 |
+
for core_word in core_words:
|
319 |
+
if core_word in cleaned_text:
|
320 |
+
keywords.append(core_word)
|
321 |
+
break
|
322 |
+
|
323 |
+
# 如果還是沒有,使用清理後的文字
|
324 |
+
if not keywords:
|
325 |
+
keywords = [cleaned_text]
|
326 |
|
327 |
# 擴展相關關鍵字
|
328 |
expanded_keywords = []
|
|
|
331 |
|
332 |
# 貓砂相關擴展
|
333 |
if '貓砂' in keyword or '貓' in keyword:
|
334 |
+
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter', '貓砂'])
|
335 |
|
336 |
# 狗糧相關擴展
|
337 |
if '狗糧' in keyword or '狗' in keyword:
|
|
|
341 |
if '寵物' in keyword:
|
342 |
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
343 |
|
344 |
+
# 去除重複並返回
|
345 |
+
unique_keywords = list(set(expanded_keywords))
|
346 |
+
|
347 |
+
# 記錄關鍵字提取結果用於調試
|
348 |
+
logger.info(f"關鍵字提取: '{query_text}' → {unique_keywords}")
|
349 |
+
|
350 |
+
return unique_keywords
|
debug_cat_litter_query.py
ADDED
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
緊急調試:貓砂查詢問題
|
3 |
+
"""
|
4 |
+
|
5 |
+
def debug_keyword_expansion():
|
6 |
+
"""調試關鍵字擴展邏輯"""
|
7 |
+
|
8 |
+
def extract_keywords_with_expansion(query_text: str):
|
9 |
+
"""擴展版關鍵字提取"""
|
10 |
+
# 移除常見的查詢詞彙
|
11 |
+
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋', '還有嗎', '?', '?']
|
12 |
+
|
13 |
+
# 分割並清理關鍵字
|
14 |
+
words = query_text.replace('?', '').replace('?', '').split()
|
15 |
+
keywords = [word for word in words if word not in stop_words and len(word) > 1]
|
16 |
+
|
17 |
+
# 擴展相關關鍵字
|
18 |
+
expanded_keywords = []
|
19 |
+
for keyword in keywords:
|
20 |
+
expanded_keywords.append(keyword)
|
21 |
+
|
22 |
+
# 貓砂相關擴展
|
23 |
+
if '貓砂' in keyword or '貓' in keyword:
|
24 |
+
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter'])
|
25 |
+
|
26 |
+
# 狗糧相關擴展
|
27 |
+
if '狗糧' in keyword or '狗' in keyword:
|
28 |
+
expanded_keywords.extend(['犬糧', '犬種', '狗食', 'dog'])
|
29 |
+
|
30 |
+
# 寵物相關擴展
|
31 |
+
if '寵物' in keyword:
|
32 |
+
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
33 |
+
|
34 |
+
return expanded_keywords if expanded_keywords else [query_text.strip()]
|
35 |
+
|
36 |
+
print("🔍 調試關鍵字擴展邏輯")
|
37 |
+
print("=" * 50)
|
38 |
+
|
39 |
+
test_query = "貓砂還有嗎?"
|
40 |
+
print(f"原始查詢: '{test_query}'")
|
41 |
+
|
42 |
+
keywords = extract_keywords_with_expansion(test_query)
|
43 |
+
print(f"擴展關鍵字: {keywords}")
|
44 |
+
|
45 |
+
return keywords
|
46 |
+
|
47 |
+
def debug_product_matching():
|
48 |
+
"""調試商品匹配邏輯"""
|
49 |
+
|
50 |
+
# 實際商品資料
|
51 |
+
products = [
|
52 |
+
{
|
53 |
+
"id": 2,
|
54 |
+
"productCode": "SW-06-01",
|
55 |
+
"productName": "Shovel well豪好鏟 破碎型礦砂",
|
56 |
+
"stock": 50,
|
57 |
+
"category_id": 1
|
58 |
+
},
|
59 |
+
{
|
60 |
+
"id": 3,
|
61 |
+
"productCode": "TL-03",
|
62 |
+
"productName": "美國極冠貓砂 薰衣草12kg",
|
63 |
+
"stock": 48,
|
64 |
+
"category_id": 1
|
65 |
+
}
|
66 |
+
]
|
67 |
+
|
68 |
+
print("\n🛍️ 調試商品匹配邏輯")
|
69 |
+
print("=" * 50)
|
70 |
+
|
71 |
+
keywords = debug_keyword_expansion()
|
72 |
+
|
73 |
+
print(f"\n商品資料:")
|
74 |
+
for product in products:
|
75 |
+
print(f" - {product['productName']}")
|
76 |
+
|
77 |
+
print(f"\n匹配測試:")
|
78 |
+
for keyword in keywords:
|
79 |
+
print(f"\n關鍵字: '{keyword}'")
|
80 |
+
matches = []
|
81 |
+
|
82 |
+
for product in products:
|
83 |
+
product_name_lower = product["productName"].lower()
|
84 |
+
product_code_lower = product["productCode"].lower()
|
85 |
+
keyword_lower = keyword.lower()
|
86 |
+
|
87 |
+
if (keyword_lower in product_name_lower or
|
88 |
+
keyword_lower in product_code_lower):
|
89 |
+
matches.append(product)
|
90 |
+
print(f" ✅ 匹配: {product['productName']}")
|
91 |
+
|
92 |
+
if not matches:
|
93 |
+
print(f" ❌ 無匹配")
|
94 |
+
|
95 |
+
return keywords
|
96 |
+
|
97 |
+
def debug_intent_analysis():
|
98 |
+
"""調試意圖分析邏輯"""
|
99 |
+
|
100 |
+
def analyze_query_intent_debug(message: str):
|
101 |
+
"""調試版意圖分析"""
|
102 |
+
message_lower = message.lower()
|
103 |
+
|
104 |
+
# 商品查詢關鍵字(擴展版)
|
105 |
+
product_keywords = [
|
106 |
+
'推薦', '有沒有', '是否有', '請問有', '商品', '產品', '貨品',
|
107 |
+
'查詢', '搜尋', '找', '庫存', '存貨', '價格', '多少錢',
|
108 |
+
'貓砂', '狗糧', '寵物', '食品', '用品', '貓', '狗', '寵物用品',
|
109 |
+
'cat', 'dog', 'pet', 'litter', 'food', '還有嗎', '還有'
|
110 |
+
]
|
111 |
+
|
112 |
+
# 推薦查詢關鍵字
|
113 |
+
recommendation_keywords = ['推薦', '建議', '介紹', '有什麼', '哪些', '什麼好', '推薦一些']
|
114 |
+
|
115 |
+
# 庫存查詢關鍵字
|
116 |
+
inventory_keywords = ['庫存', '存貨', '剩餘', '還有', '現貨', '有多少', '剩多少', '還有嗎']
|
117 |
+
|
118 |
+
is_product_query = any(keyword in message_lower for keyword in product_keywords)
|
119 |
+
is_recommendation = any(keyword in message_lower for keyword in recommendation_keywords)
|
120 |
+
is_inventory_check = any(keyword in message_lower for keyword in inventory_keywords)
|
121 |
+
|
122 |
+
confidence = 0.5
|
123 |
+
if is_product_query:
|
124 |
+
confidence += 0.3
|
125 |
+
if is_recommendation:
|
126 |
+
confidence += 0.2
|
127 |
+
if is_inventory_check:
|
128 |
+
confidence += 0.2
|
129 |
+
|
130 |
+
return {
|
131 |
+
"is_product_query": is_product_query,
|
132 |
+
"is_recommendation": is_recommendation,
|
133 |
+
"is_inventory_check": is_inventory_check,
|
134 |
+
"confidence": min(confidence, 1.0),
|
135 |
+
"intent": "product_query" if is_product_query else "unknown",
|
136 |
+
"matched_keywords": [kw for kw in product_keywords if kw in message_lower]
|
137 |
+
}
|
138 |
+
|
139 |
+
print("\n🤖 調試意��分析邏輯")
|
140 |
+
print("=" * 50)
|
141 |
+
|
142 |
+
test_query = "貓砂還有嗎?"
|
143 |
+
print(f"查詢: '{test_query}'")
|
144 |
+
|
145 |
+
analysis = analyze_query_intent_debug(test_query)
|
146 |
+
|
147 |
+
print(f"商品查詢: {analysis['is_product_query']}")
|
148 |
+
print(f"推薦查詢: {analysis['is_recommendation']}")
|
149 |
+
print(f"庫存查詢: {analysis['is_inventory_check']}")
|
150 |
+
print(f"信心度: {analysis['confidence']:.2f}")
|
151 |
+
print(f"匹配的關鍵字: {analysis['matched_keywords']}")
|
152 |
+
|
153 |
+
return analysis
|
154 |
+
|
155 |
+
def debug_search_logic():
|
156 |
+
"""調試搜尋邏輯"""
|
157 |
+
|
158 |
+
print("\n🔍 調試搜尋邏輯")
|
159 |
+
print("=" * 50)
|
160 |
+
|
161 |
+
# 模擬 search_products_advanced 邏輯
|
162 |
+
def simulate_search_products_advanced(query_text: str):
|
163 |
+
"""模擬進階商品搜尋"""
|
164 |
+
|
165 |
+
# 1. 提取關鍵字
|
166 |
+
def extract_keywords_with_expansion(query_text: str):
|
167 |
+
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋', '還有嗎', '?', '?']
|
168 |
+
words = query_text.replace('?', '').replace('?', '').split()
|
169 |
+
keywords = [word for word in words if word not in stop_words and len(word) > 1]
|
170 |
+
|
171 |
+
expanded_keywords = []
|
172 |
+
for keyword in keywords:
|
173 |
+
expanded_keywords.append(keyword)
|
174 |
+
|
175 |
+
if '貓砂' in keyword or '貓' in keyword:
|
176 |
+
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter'])
|
177 |
+
|
178 |
+
if '狗糧' in keyword or '狗' in keyword:
|
179 |
+
expanded_keywords.extend(['犬糧', '犬種', '狗食', 'dog'])
|
180 |
+
|
181 |
+
if '寵物' in keyword:
|
182 |
+
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
183 |
+
|
184 |
+
return expanded_keywords if expanded_keywords else [query_text.strip()]
|
185 |
+
|
186 |
+
# 2. 商品資料
|
187 |
+
products = [
|
188 |
+
{
|
189 |
+
"id": 2,
|
190 |
+
"productCode": "SW-06-01",
|
191 |
+
"productName": "Shovel well豪好鏟 破碎型礦砂",
|
192 |
+
"stock": 50,
|
193 |
+
"is_deleted": False
|
194 |
+
},
|
195 |
+
{
|
196 |
+
"id": 3,
|
197 |
+
"productCode": "TL-03",
|
198 |
+
"productName": "美國極冠貓砂 薰衣草12kg",
|
199 |
+
"stock": 48,
|
200 |
+
"is_deleted": False
|
201 |
+
}
|
202 |
+
]
|
203 |
+
|
204 |
+
# 3. 搜尋邏輯
|
205 |
+
keywords = extract_keywords_with_expansion(query_text)
|
206 |
+
print(f"搜尋關鍵字: {keywords}")
|
207 |
+
|
208 |
+
matched_products = []
|
209 |
+
|
210 |
+
for product in products:
|
211 |
+
if product["is_deleted"]:
|
212 |
+
continue
|
213 |
+
|
214 |
+
# 檢查是否有任一關鍵字匹配
|
215 |
+
for keyword in keywords:
|
216 |
+
keyword_lower = keyword.lower()
|
217 |
+
product_name_lower = product["productName"].lower()
|
218 |
+
product_code_lower = product["productCode"].lower()
|
219 |
+
|
220 |
+
if (keyword_lower in product_name_lower or
|
221 |
+
keyword_lower in product_code_lower):
|
222 |
+
matched_products.append(product)
|
223 |
+
print(f" ✅ 匹配: {product['productName']} (關鍵字: {keyword})")
|
224 |
+
break # 找到匹配就跳出
|
225 |
+
|
226 |
+
return {
|
227 |
+
"success": True,
|
228 |
+
"data": matched_products,
|
229 |
+
"count": len(matched_products)
|
230 |
+
}
|
231 |
+
|
232 |
+
test_query = "貓砂還有嗎?"
|
233 |
+
result = simulate_search_products_advanced(test_query)
|
234 |
+
|
235 |
+
print(f"搜尋結果:")
|
236 |
+
print(f" 成功: {result['success']}")
|
237 |
+
print(f" 數量: {result['count']}")
|
238 |
+
|
239 |
+
if result['data']:
|
240 |
+
print(f" 找到的商品:")
|
241 |
+
for product in result['data']:
|
242 |
+
print(f" - {product['productName']} (庫存: {product['stock']})")
|
243 |
+
else:
|
244 |
+
print(f" ❌ 沒有找到商品")
|
245 |
+
|
246 |
+
def main():
|
247 |
+
"""主函數"""
|
248 |
+
print("🚨 緊急調試:貓砂查詢問題")
|
249 |
+
print("=" * 60)
|
250 |
+
|
251 |
+
# 1. 調試意圖分析
|
252 |
+
intent_analysis = debug_intent_analysis()
|
253 |
+
|
254 |
+
# 2. 調試關鍵字擴展和商品匹配
|
255 |
+
debug_product_matching()
|
256 |
+
|
257 |
+
# 3. 調試完整搜尋邏輯
|
258 |
+
debug_search_logic()
|
259 |
+
|
260 |
+
print("\n" + "=" * 60)
|
261 |
+
print("🔍 問題診斷結果:")
|
262 |
+
|
263 |
+
if intent_analysis["confidence"] >= 1.0:
|
264 |
+
print("✅ 意圖識別正常 (信心度 1.00)")
|
265 |
+
else:
|
266 |
+
print("❌ 意圖識別有問題")
|
267 |
+
|
268 |
+
print("\n💡 可能的問題:")
|
269 |
+
print("1. 關鍵字擴展邏輯是否正確執行?")
|
270 |
+
print("2. 資料庫查詢是否有錯誤?")
|
271 |
+
print("3. 商品資料是否正確載入?")
|
272 |
+
print("4. SQL 查詢條件是否正確?")
|
273 |
+
|
274 |
+
if __name__ == "__main__":
|
275 |
+
main()
|
test_final_fix.py
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
測試最終修復版本
|
3 |
+
"""
|
4 |
+
|
5 |
+
def test_final_keyword_extraction():
|
6 |
+
"""測試最終修復的關鍵字提取"""
|
7 |
+
|
8 |
+
def extract_keywords_final(query_text: str):
|
9 |
+
"""最終修復版的關鍵字提取邏輯"""
|
10 |
+
# 移除常見的查詢詞彙
|
11 |
+
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋', '還有嗎', '還有', '嗎']
|
12 |
+
|
13 |
+
# 清理查詢文字
|
14 |
+
cleaned_text = query_text.replace('?', '').replace('?', '').strip()
|
15 |
+
|
16 |
+
# 分割並清理關鍵字
|
17 |
+
words = cleaned_text.split()
|
18 |
+
keywords = []
|
19 |
+
|
20 |
+
for word in words:
|
21 |
+
if word not in stop_words and len(word) > 1:
|
22 |
+
keywords.append(word)
|
23 |
+
|
24 |
+
# 如果沒有有效關鍵字,嘗試從原始文字中提取核心詞彙
|
25 |
+
if not keywords:
|
26 |
+
# 嘗試提取核心商品詞彙
|
27 |
+
core_words = ['貓砂', '狗糧', '寵物', '商品', '產品']
|
28 |
+
for core_word in core_words:
|
29 |
+
if core_word in cleaned_text:
|
30 |
+
keywords.append(core_word)
|
31 |
+
break
|
32 |
+
|
33 |
+
# 如果還是沒有,使用清理後的文字
|
34 |
+
if not keywords:
|
35 |
+
keywords = [cleaned_text]
|
36 |
+
|
37 |
+
# 擴展相關關鍵字
|
38 |
+
expanded_keywords = []
|
39 |
+
for keyword in keywords:
|
40 |
+
expanded_keywords.append(keyword)
|
41 |
+
|
42 |
+
# 貓砂相關擴展
|
43 |
+
if '貓砂' in keyword or '貓' in keyword:
|
44 |
+
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter', '貓砂'])
|
45 |
+
|
46 |
+
# 狗糧相關擴展
|
47 |
+
if '狗糧' in keyword or '狗' in keyword:
|
48 |
+
expanded_keywords.extend(['犬糧', '犬種', '狗食', 'dog'])
|
49 |
+
|
50 |
+
# 寵物相關擴展
|
51 |
+
if '寵物' in keyword:
|
52 |
+
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
53 |
+
|
54 |
+
# 去除重複並返回
|
55 |
+
return list(set(expanded_keywords))
|
56 |
+
|
57 |
+
print("🔧 測試最終修復的關鍵字提取邏輯")
|
58 |
+
print("=" * 50)
|
59 |
+
|
60 |
+
test_cases = [
|
61 |
+
"貓砂還有嗎?",
|
62 |
+
"是否有推薦貓砂?",
|
63 |
+
"有什麼寵物用品?",
|
64 |
+
"查詢狗糧庫存",
|
65 |
+
"美國極冠",
|
66 |
+
"礦砂"
|
67 |
+
]
|
68 |
+
|
69 |
+
for query in test_cases:
|
70 |
+
print(f"\n查詢: '{query}'")
|
71 |
+
keywords = extract_keywords_final(query)
|
72 |
+
print(f"關鍵字: {keywords}")
|
73 |
+
|
74 |
+
# 檢查是否包含預期的關鍵字
|
75 |
+
if query == "貓砂還有嗎?":
|
76 |
+
if '貓砂' in keywords and '礦砂' in keywords:
|
77 |
+
print(" ✅ 包含預期的貓砂相關關鍵字")
|
78 |
+
else:
|
79 |
+
print(" ❌ 缺少預期的關鍵字")
|
80 |
+
|
81 |
+
def test_complete_flow():
|
82 |
+
"""測試完整的查詢流程"""
|
83 |
+
|
84 |
+
def extract_keywords_final(query_text: str):
|
85 |
+
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋', '還有嗎', '還有', '嗎']
|
86 |
+
cleaned_text = query_text.replace('?', '').replace('?', '').strip()
|
87 |
+
words = cleaned_text.split()
|
88 |
+
keywords = [word for word in words if word not in stop_words and len(word) > 1]
|
89 |
+
|
90 |
+
if not keywords:
|
91 |
+
core_words = ['貓砂', '狗糧', '寵物', '商品', '產品']
|
92 |
+
for core_word in core_words:
|
93 |
+
if core_word in cleaned_text:
|
94 |
+
keywords.append(core_word)
|
95 |
+
break
|
96 |
+
if not keywords:
|
97 |
+
keywords = [cleaned_text]
|
98 |
+
|
99 |
+
expanded_keywords = []
|
100 |
+
for keyword in keywords:
|
101 |
+
expanded_keywords.append(keyword)
|
102 |
+
|
103 |
+
if '貓砂' in keyword or '貓' in keyword:
|
104 |
+
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter', '貓砂'])
|
105 |
+
|
106 |
+
if '狗糧' in keyword or '狗' in keyword:
|
107 |
+
expanded_keywords.extend(['犬糧', '犬種', '狗食', 'dog'])
|
108 |
+
|
109 |
+
if '寵物' in keyword:
|
110 |
+
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
111 |
+
|
112 |
+
return list(set(expanded_keywords))
|
113 |
+
|
114 |
+
# 實際商品資料
|
115 |
+
products = [
|
116 |
+
{
|
117 |
+
"id": 2,
|
118 |
+
"productCode": "SW-06-01",
|
119 |
+
"productName": "Shovel well豪好鏟 破碎型礦砂",
|
120 |
+
"stock": 50,
|
121 |
+
"is_deleted": False
|
122 |
+
},
|
123 |
+
{
|
124 |
+
"id": 3,
|
125 |
+
"productCode": "TL-03",
|
126 |
+
"productName": "美國極冠貓砂 薰衣草12kg",
|
127 |
+
"stock": 48,
|
128 |
+
"is_deleted": False
|
129 |
+
}
|
130 |
+
]
|
131 |
+
|
132 |
+
print("\n🛍️ 測試完整查詢流程")
|
133 |
+
print("=" * 50)
|
134 |
+
|
135 |
+
test_query = "貓砂還有嗎?"
|
136 |
+
print(f"用戶查詢: '{test_query}'")
|
137 |
+
|
138 |
+
# 1. 關鍵字提取
|
139 |
+
keywords = extract_keywords_final(test_query)
|
140 |
+
print(f"提取關鍵字: {keywords}")
|
141 |
+
|
142 |
+
# 2. 商品匹配
|
143 |
+
matched_products = []
|
144 |
+
|
145 |
+
for product in products:
|
146 |
+
if product["is_deleted"]:
|
147 |
+
continue
|
148 |
+
|
149 |
+
# 檢查是否有任一關鍵字匹配
|
150 |
+
for keyword in keywords:
|
151 |
+
keyword_lower = keyword.lower()
|
152 |
+
product_name_lower = product["productName"].lower()
|
153 |
+
product_code_lower = product["productCode"].lower()
|
154 |
+
|
155 |
+
if (keyword_lower in product_name_lower or
|
156 |
+
keyword_lower in product_code_lower):
|
157 |
+
if product not in matched_products:
|
158 |
+
matched_products.append(product)
|
159 |
+
print(f" ✅ 匹配: {product['productName']} (關鍵字: {keyword})")
|
160 |
+
break
|
161 |
+
|
162 |
+
# 3. 格式化回應
|
163 |
+
if matched_products:
|
164 |
+
response_text = f"為您推薦 {len(matched_products)} 個商品:\n\n"
|
165 |
+
for i, product in enumerate(matched_products, 1):
|
166 |
+
response_text += f"{i}. {product['productName']}\n"
|
167 |
+
response_text += f" 庫存: {product['stock']} - 庫存正常\n"
|
168 |
+
response_text += f" 商品編號: {product['productCode']}\n\n"
|
169 |
+
|
170 |
+
print(f"\n📝 格式化回應:")
|
171 |
+
print(response_text)
|
172 |
+
print("✅ 應該能找到商品了!")
|
173 |
+
else:
|
174 |
+
print("\n❌ 仍然沒有找到商品")
|
175 |
+
|
176 |
+
def main():
|
177 |
+
"""主函數"""
|
178 |
+
print("🚀 測試最終修復版本")
|
179 |
+
print("=" * 60)
|
180 |
+
|
181 |
+
test_final_keyword_extraction()
|
182 |
+
test_complete_flow()
|
183 |
+
|
184 |
+
print("\n" + "=" * 60)
|
185 |
+
print("✅ 測試完成!")
|
186 |
+
print("\n💡 修復總結:")
|
187 |
+
print("1. 正確處理 '貓砂還有嗎?' → ['貓砂']")
|
188 |
+
print("2. 擴展為相關關鍵字: ['貓砂', '礦砂', ...]")
|
189 |
+
print("3. 能匹配到兩個貓砂商品")
|
190 |
+
print("4. 現在重啟服務應該能正常工作")
|
191 |
+
|
192 |
+
if __name__ == "__main__":
|
193 |
+
main()
|
test_fixed_keywords.py
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
測試修復後的關鍵字提取邏輯
|
3 |
+
"""
|
4 |
+
|
5 |
+
def test_fixed_keyword_extraction():
|
6 |
+
"""測試修復後的關鍵字提取"""
|
7 |
+
|
8 |
+
def extract_keywords_fixed(query_text: str):
|
9 |
+
"""修復後的關鍵字提取邏輯"""
|
10 |
+
# 移除常見的查詢詞彙
|
11 |
+
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋', '還有嗎', '還有', '?', '?']
|
12 |
+
|
13 |
+
# 清理查詢文字
|
14 |
+
cleaned_text = query_text.replace('?', '').replace('?', '').strip()
|
15 |
+
|
16 |
+
# 分割並清理關鍵字
|
17 |
+
words = cleaned_text.split()
|
18 |
+
keywords = [word for word in words if word not in stop_words and len(word) > 1]
|
19 |
+
|
20 |
+
# 如果沒有有效關鍵字,使用原始文字
|
21 |
+
if not keywords:
|
22 |
+
keywords = [cleaned_text]
|
23 |
+
|
24 |
+
# 擴展相關關鍵字
|
25 |
+
expanded_keywords = []
|
26 |
+
for keyword in keywords:
|
27 |
+
expanded_keywords.append(keyword)
|
28 |
+
|
29 |
+
# 貓砂相關擴展
|
30 |
+
if '貓砂' in keyword or '貓' in keyword:
|
31 |
+
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter', '貓砂'])
|
32 |
+
|
33 |
+
# 狗糧相關擴展
|
34 |
+
if '狗糧' in keyword or '狗' in keyword:
|
35 |
+
expanded_keywords.extend(['犬糧', '犬種', '狗食', 'dog'])
|
36 |
+
|
37 |
+
# 寵物相關擴展
|
38 |
+
if '寵物' in keyword:
|
39 |
+
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
40 |
+
|
41 |
+
# 去除重複並返回
|
42 |
+
return list(set(expanded_keywords))
|
43 |
+
|
44 |
+
print("🔧 測試修復後的關鍵字提取邏輯")
|
45 |
+
print("=" * 50)
|
46 |
+
|
47 |
+
test_cases = [
|
48 |
+
"貓砂還有嗎?",
|
49 |
+
"是否有推薦貓砂?",
|
50 |
+
"有什麼寵物用品?",
|
51 |
+
"查詢狗糧庫存",
|
52 |
+
"美國極冠",
|
53 |
+
"礦砂"
|
54 |
+
]
|
55 |
+
|
56 |
+
for query in test_cases:
|
57 |
+
print(f"\n查詢: '{query}'")
|
58 |
+
keywords = extract_keywords_fixed(query)
|
59 |
+
print(f"關鍵字: {keywords}")
|
60 |
+
|
61 |
+
def test_product_matching_fixed():
|
62 |
+
"""測試修復後的商品匹配"""
|
63 |
+
|
64 |
+
def extract_keywords_fixed(query_text: str):
|
65 |
+
stop_words = ['推薦', '有沒有', '是否有', '請問', '想要', '需要', '找', '查詢', '搜尋', '還有嗎', '還有', '?', '?']
|
66 |
+
cleaned_text = query_text.replace('?', '').replace('?', '').strip()
|
67 |
+
words = cleaned_text.split()
|
68 |
+
keywords = [word for word in words if word not in stop_words and len(word) > 1]
|
69 |
+
|
70 |
+
if not keywords:
|
71 |
+
keywords = [cleaned_text]
|
72 |
+
|
73 |
+
expanded_keywords = []
|
74 |
+
for keyword in keywords:
|
75 |
+
expanded_keywords.append(keyword)
|
76 |
+
|
77 |
+
if '貓砂' in keyword or '貓' in keyword:
|
78 |
+
expanded_keywords.extend(['礦砂', '豆腐砂', '水晶砂', '木屑砂', 'litter', '貓砂'])
|
79 |
+
|
80 |
+
if '狗糧' in keyword or '狗' in keyword:
|
81 |
+
expanded_keywords.extend(['犬糧', '犬種', '狗食', 'dog'])
|
82 |
+
|
83 |
+
if '寵物' in keyword:
|
84 |
+
expanded_keywords.extend(['貓', '狗', '犬', 'pet', 'cat'])
|
85 |
+
|
86 |
+
return list(set(expanded_keywords))
|
87 |
+
|
88 |
+
# 實際商品資料
|
89 |
+
products = [
|
90 |
+
{
|
91 |
+
"id": 1,
|
92 |
+
"productCode": "OL1100-1",
|
93 |
+
"productName": "毆力天然犬種300g 室內成犬無榖小顆粒",
|
94 |
+
"stock": 100
|
95 |
+
},
|
96 |
+
{
|
97 |
+
"id": 2,
|
98 |
+
"productCode": "SW-06-01",
|
99 |
+
"productName": "Shovel well豪好鏟 破碎型礦砂",
|
100 |
+
"stock": 50
|
101 |
+
},
|
102 |
+
{
|
103 |
+
"id": 3,
|
104 |
+
"productCode": "TL-03",
|
105 |
+
"productName": "美國極冠貓砂 薰衣草12kg",
|
106 |
+
"stock": 48
|
107 |
+
},
|
108 |
+
{
|
109 |
+
"id": 4,
|
110 |
+
"productCode": "SL11002",
|
111 |
+
"productName": "首領汪 膠原鴨舌 5入彭湃包",
|
112 |
+
"stock": 100
|
113 |
+
}
|
114 |
+
]
|
115 |
+
|
116 |
+
print("\n🛍️ 測試修復後的商品匹配")
|
117 |
+
print("=" * 50)
|
118 |
+
|
119 |
+
test_query = "貓砂還有嗎?"
|
120 |
+
print(f"查詢: '{test_query}'")
|
121 |
+
|
122 |
+
keywords = extract_keywords_fixed(test_query)
|
123 |
+
print(f"提取的關鍵字: {keywords}")
|
124 |
+
|
125 |
+
matched_products = []
|
126 |
+
|
127 |
+
print(f"\n匹配測試:")
|
128 |
+
for keyword in keywords:
|
129 |
+
print(f"\n關鍵字: '{keyword}'")
|
130 |
+
|
131 |
+
for product in products:
|
132 |
+
product_name_lower = product["productName"].lower()
|
133 |
+
product_code_lower = product["productCode"].lower()
|
134 |
+
keyword_lower = keyword.lower()
|
135 |
+
|
136 |
+
if (keyword_lower in product_name_lower or
|
137 |
+
keyword_lower in product_code_lower):
|
138 |
+
if product not in matched_products:
|
139 |
+
matched_products.append(product)
|
140 |
+
print(f" ✅ 匹配: {product['productName']}")
|
141 |
+
|
142 |
+
print(f"\n最終匹配結果:")
|
143 |
+
print(f"找到 {len(matched_products)} 個商品:")
|
144 |
+
for product in matched_products:
|
145 |
+
print(f" - {product['productName']} (庫存: {product['stock']})")
|
146 |
+
|
147 |
+
def main():
|
148 |
+
"""主函數"""
|
149 |
+
print("🚀 測試關鍵字提取修復")
|
150 |
+
print("=" * 60)
|
151 |
+
|
152 |
+
test_fixed_keyword_extraction()
|
153 |
+
test_product_matching_fixed()
|
154 |
+
|
155 |
+
print("\n" + "=" * 60)
|
156 |
+
print("✅ 測試完成!")
|
157 |
+
print("\n💡 修復重點:")
|
158 |
+
print("1. 將 '還有嗎' 和 '?' 加入 stop_words")
|
159 |
+
print("2. 正確分割 '貓砂還有嗎' → ['貓砂']")
|
160 |
+
print("3. 擴展為 ['貓砂', '礦砂', '豆腐砂', ...]")
|
161 |
+
print("4. 應該能匹配到兩個貓砂商品")
|
162 |
+
|
163 |
+
if __name__ == "__main__":
|
164 |
+
main()
|