Spaces:
Sleeping
Sleeping
Format lại tên sản phẩm có nhúng link và ảnh thành 2 cột
Browse files
app.py
CHANGED
|
@@ -295,7 +295,61 @@ class ChatService:
|
|
| 295 |
if state.specs_advantages is not None:
|
| 296 |
await ChatService.get_specific_product_from_query(message, state)
|
| 297 |
|
| 298 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 299 |
|
| 300 |
@staticmethod
|
| 301 |
async def get_specific_product_from_query(query, state):
|
|
|
|
| 295 |
if state.specs_advantages is not None:
|
| 296 |
await ChatService.get_specific_product_from_query(message, state)
|
| 297 |
|
| 298 |
+
# Format response with 2-column grid for products
|
| 299 |
+
formatted_response = ChatService.format_product_grid(response)
|
| 300 |
+
|
| 301 |
+
return formatted_response + f"\n\n*Thời gian xử lí: {end - start:.6f}s*"
|
| 302 |
+
|
| 303 |
+
@staticmethod
|
| 304 |
+
def format_product_grid(response_text: str) -> str:
|
| 305 |
+
"""Format product listings into 2-column grid while keeping other content intact"""
|
| 306 |
+
# Pattern to match: * **[Name](url)**\n\n 
|
| 307 |
+
pattern = r'\*\s+\*\*\[(.*?)\]\((.*?)\)\*\*\s*\n\s*!\[(.*?)\]\((.*?)\)'
|
| 308 |
+
|
| 309 |
+
matches = list(re.finditer(pattern, response_text))
|
| 310 |
+
|
| 311 |
+
if not matches:
|
| 312 |
+
# No product listings found, return original
|
| 313 |
+
return response_text
|
| 314 |
+
|
| 315 |
+
# Find boundaries of product section
|
| 316 |
+
first_match_start = matches[0].start()
|
| 317 |
+
last_match_end = matches[-1].end()
|
| 318 |
+
|
| 319 |
+
# Split into: intro + products + rest
|
| 320 |
+
intro_text = response_text[:first_match_start].strip()
|
| 321 |
+
rest_text = response_text[last_match_end:].strip()
|
| 322 |
+
|
| 323 |
+
# Extract all products
|
| 324 |
+
products = []
|
| 325 |
+
for match in matches:
|
| 326 |
+
products.append({
|
| 327 |
+
'name': match.group(1),
|
| 328 |
+
'url': match.group(2),
|
| 329 |
+
'alt': match.group(3),
|
| 330 |
+
'img': match.group(4)
|
| 331 |
+
})
|
| 332 |
+
|
| 333 |
+
# Build 2-column markdown table
|
| 334 |
+
grid_content = "\n\n"
|
| 335 |
+
|
| 336 |
+
for i in range(0, len(products), 2):
|
| 337 |
+
p1 = products[i]
|
| 338 |
+
|
| 339 |
+
if i + 1 < len(products):
|
| 340 |
+
p2 = products[i + 1]
|
| 341 |
+
# Two columns
|
| 342 |
+
grid_content += f"| **[{p1['name']}]({p1['url']})** | **[{p2['name']}]({p2['url']})** |\n"
|
| 343 |
+
grid_content += f"|:---:|:---:|\n"
|
| 344 |
+
grid_content += f"| ![{p1['alt']}]({p1['img']}) | ![{p2['alt']}]({p2['img']}) |\n\n"
|
| 345 |
+
else:
|
| 346 |
+
# Single column for last odd product
|
| 347 |
+
grid_content += f"| **[{p1['name']}]({p1['url']})** |\n"
|
| 348 |
+
grid_content += f"|:---:|\n"
|
| 349 |
+
grid_content += f"| ![{p1['alt']}]({p1['img']}) |\n\n"
|
| 350 |
+
|
| 351 |
+
# Reconstruct full response
|
| 352 |
+
return intro_text + grid_content + rest_text
|
| 353 |
|
| 354 |
@staticmethod
|
| 355 |
async def get_specific_product_from_query(query, state):
|