Kgshop commited on
Commit
b0d4e88
·
verified ·
1 Parent(s): 32990d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -23
app.py CHANGED
@@ -286,7 +286,9 @@ def generate_chat_response(message, chat_history_from_client):
286
  for p in products:
287
  if p.get('in_stock', True):
288
  price_display = f"{p.get('price', 0):.2f}".replace('.00', '')
289
- product_info_list.append(f"- Название: {p.get('name', 'Без названия')}, Категория: {p.get('category', 'Без категории')}, Цена: {price_display} {CURRENCY_CODE}, Описание: {p.get('description', '')[:100]}..., ID: {p.get('product_id', 'N/A')}")
 
 
290
  product_list_str = "\n".join(product_info_list) if product_info_list else "В данный момент нет товаров в наличии."
291
 
292
  category_list_str = ", ".join(categories) if categories else "Категорий пока нет."
@@ -309,7 +311,7 @@ def generate_chat_response(message, chat_history_from_client):
309
  "Твоя задача - помогать пользователям находить товары, отвечать на вопросы о них, предлагать варианты, а также предоставлять информацию о магазине. "
310
  "Всегда будь вежлив, информативен и стремись решить проблему пользователя. "
311
  "Никогда не выдумывай товары или категории, которых нет в предоставленных списках. "
312
- "Когда ты предлагаешь товар, всегда указывай его название и ID, используя точный формат: [ID_ТОВАРА: <product_id> Название: <product_name>]. Это очень важно для клиента. "
313
  "Если пользователь ищет товар или категорию, предлагай несколько наиболее подходящих вариантов или перечисляй доступные из этой категории.\n\n"
314
  f"Список доступных категорий: {category_list_str}.\n\n"
315
  f"Список доступных товаров в магазине:\n"
@@ -601,19 +603,64 @@ CATALOG_TEMPLATE = '''
601
  #chat-send-button:hover { background-color: #005CBF; }
602
  #chat-send-button:disabled { background-color: #cccccc; cursor: not-allowed; }
603
 
604
- .chat-product-card { background-color: #f0f2f5; border-radius: 12px; padding: 10px; margin-top: 8px; display: flex; align-items: center; gap: 12px; border: 1px solid #e0e0e0; }
605
- .chat-product-card img { width: 50px; height: 50px; object-fit: cover; border-radius: 8px; flex-shrink: 0; }
606
- .chat-product-card-info { flex-grow: 1; }
607
- .chat-product-card-info strong { display: block; font-size: 0.9rem; color: #333; margin-bottom: 2px; }
608
- .chat-product-card-info span { font-size: 0.85rem; color: #0A2A66; font-weight: 500; }
609
- .chat-product-card-actions { display: flex; flex-direction: column; gap: 5px; }
610
- .chat-product-link, .chat-add-to-cart {
611
- display: inline-block; background-color: #E3F2FD; color: #0070D1; padding: 5px 10px; border-radius: 15px;
612
- cursor: pointer; font-size: 0.85rem; text-decoration: none; transition: background-color 0.2s;
613
- font-weight: 500; text-align: center; box-sizing: border-box; width: 100%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
614
  }
615
- .chat-product-link:hover, .chat-add-to-cart:hover { background-color: #BBDEFB; }
616
- .chat-product-card-actions .fa-cart-plus { font-size: 0.9em; }
617
 
618
  </style>
619
  </head>
@@ -1065,14 +1112,18 @@ CATALOG_TEMPLATE = '''
1065
  const messageElement = document.createElement('div');
1066
  messageElement.className = `chat-message ${role}`;
1067
 
 
 
1068
  const productMatchRegex = /\[ID_ТОВАРА:\s*([a-fA-F0-9]+)\s*Название:\s*([^\]]+)\]/g;
1069
  let lastIndex = 0;
1070
  const contentFragment = document.createDocumentFragment();
1071
  let match;
1072
 
1073
  while ((match = productMatchRegex.exec(text)) !== null) {
 
1074
  if (match.index > lastIndex) {
1075
  const textPart = document.createElement('span');
 
1076
  textPart.innerHTML = text.substring(lastIndex, match.index).replace(/\\n/g, '<br>');
1077
  contentFragment.appendChild(textPart);
1078
  }
@@ -1100,14 +1151,16 @@ CATALOG_TEMPLATE = '''
1100
  `;
1101
  contentFragment.appendChild(card);
1102
  } else {
 
1103
  const productName = match[2];
1104
- const notFoundText = document.createElement('strong');
1105
- notFoundText.textContent = ` ${productName} (товар не найден) `;
1106
  contentFragment.appendChild(notFoundText);
1107
  }
1108
  lastIndex = match.index + match[0].length;
1109
  }
1110
 
 
1111
  if (lastIndex < text.length) {
1112
  const textPart = document.createElement('span');
1113
  textPart.innerHTML = text.substring(lastIndex).replace(/\\n/g, '<br>');
@@ -1123,20 +1176,21 @@ CATALOG_TEMPLATE = '''
1123
  localStorage.setItem('evaChatHistory', JSON.stringify(chatHistory));
1124
  }
1125
 
 
1126
  messageElement.querySelectorAll('.chat-product-link').forEach(link => {
1127
  link.addEventListener('click', (e) => {
1128
- e.preventDefault();
1129
  const id = e.currentTarget.dataset.productId;
1130
- closeModal('chatModal');
1131
- openModalById(id);
1132
  });
1133
  });
1134
  messageElement.querySelectorAll('.chat-add-to-cart').forEach(link => {
1135
  link.addEventListener('click', (e) => {
1136
- e.preventDefault();
1137
  const id = e.currentTarget.dataset.productId;
1138
- closeModal('chatModal');
1139
- openQuantityModalById(id);
1140
  });
1141
  });
1142
  }
@@ -1819,6 +1873,7 @@ def catalog():
1819
 
1820
  products_in_stock = [p for p in all_products_raw if p.get('in_stock', True)]
1821
 
 
1822
  products_sorted_for_js = sorted(products_in_stock, key=lambda p: (not p.get('is_top', False), p.get('name', '').lower()))
1823
 
1824
  products_by_category = {cat: [] for cat in all_cat_names}
@@ -1834,7 +1889,7 @@ def catalog():
1834
  CATALOG_TEMPLATE,
1835
  products_by_category=products_by_category,
1836
  ordered_categories=ordered_categories,
1837
- products_json=json.dumps(products_sorted_for_js),
1838
  repo_id=REPO_ID,
1839
  store_address=STORE_ADDRESS,
1840
  currency_code=CURRENCY_CODE
 
286
  for p in products:
287
  if p.get('in_stock', True):
288
  price_display = f"{p.get('price', 0):.2f}".replace('.00', '')
289
+ # AI is instructed to output in format: [ID_ТОВАРА: <product_id> Название: <product_name>]
290
+ # We add a placeholder here for the AI to pick up on it.
291
+ product_info_list.append(f"- [ID_ТОВАРА: {p.get('product_id', 'N/A')} Название: {p.get('name', 'Без названия')}], Категория: {p.get('category', 'Без категории')}, Цена: {price_display} {CURRENCY_CODE}, Описание: {p.get('description', '')[:100]}...")
292
  product_list_str = "\n".join(product_info_list) if product_info_list else "В данный момент нет товаров в наличии."
293
 
294
  category_list_str = ", ".join(categories) if categories else "Категорий пока нет."
 
311
  "Твоя задача - помогать пользователям находить товары, отвечать на вопросы о них, предлагать варианты, а также предоставлять информацию о магазине. "
312
  "Всегда будь вежлив, информативен и стремись решить проблему пользователя. "
313
  "Никогда не выдумывай товары или категории, которых нет в предоставленных списках. "
314
+ "Когда ты предлагаешь товар, всегда указывай его название и ID, используя *точный формат*: [ID_ТОВАРА: <product_id> Название: <product_name>]. Это *очень важно* для клиента. "
315
  "Если пользователь ищет товар или категорию, предлагай несколько наиболее подходящих вариантов или перечисляй доступные из этой категории.\n\n"
316
  f"Список доступных категорий: {category_list_str}.\n\n"
317
  f"Список доступных товаров в магазине:\n"
 
603
  #chat-send-button:hover { background-color: #005CBF; }
604
  #chat-send-button:disabled { background-color: #cccccc; cursor: not-allowed; }
605
 
606
+ /* New styles for chat product cards */
607
+ .chat-product-card {
608
+ background-color: #f0f2f5;
609
+ border-radius: 12px;
610
+ padding: 10px;
611
+ margin-top: 8px; /* Give some space after text, if any */
612
+ display: flex;
613
+ align-items: center;
614
+ gap: 12px;
615
+ border: 1px solid #e0e0e0;
616
+ }
617
+ .chat-product-card img {
618
+ width: 50px;
619
+ height: 50px;
620
+ object-fit: cover;
621
+ border-radius: 8px;
622
+ flex-shrink: 0;
623
+ }
624
+ .chat-product-card-info {
625
+ flex-grow: 1;
626
+ }
627
+ .chat-product-card-info strong {
628
+ display: block;
629
+ font-size: 0.9rem;
630
+ color: #333;
631
+ margin-bottom: 2px;
632
+ }
633
+ .chat-product-card-info span {
634
+ font-size: 0.85rem;
635
+ color: #0A2A66;
636
+ font-weight: 500;
637
+ }
638
+ .chat-product-card-actions {
639
+ display: flex;
640
+ flex-direction: column;
641
+ gap: 5px;
642
+ }
643
+ .chat-product-link, .chat-add-to-cart {
644
+ display: inline-block;
645
+ background-color: #E3F2FD;
646
+ color: #0070D1;
647
+ padding: 5px 10px;
648
+ border-radius: 15px;
649
+ cursor: pointer;
650
+ font-size: 0.85rem;
651
+ text-decoration: none;
652
+ transition: background-color 0.2s;
653
+ font-weight: 500;
654
+ text-align: center;
655
+ box-sizing: border-box;
656
+ width: 100%; /* Make buttons take full width of their container */
657
+ }
658
+ .chat-product-link:hover, .chat-add-to-cart:hover {
659
+ background-color: #BBDEFB;
660
+ }
661
+ .chat-product-card-actions .fa-cart-plus {
662
+ font-size: 0.9em; /* Adjust icon size slightly */
663
  }
 
 
664
 
665
  </style>
666
  </head>
 
1112
  const messageElement = document.createElement('div');
1113
  messageElement.className = `chat-message ${role}`;
1114
 
1115
+ // Regex to find the product pattern: [ID_ТОВАРА: <product_id> Название: <product_name>]
1116
+ // This regex is slightly different from the original prompt to match the AI's output exactly
1117
  const productMatchRegex = /\[ID_ТОВАРА:\s*([a-fA-F0-9]+)\s*Название:\s*([^\]]+)\]/g;
1118
  let lastIndex = 0;
1119
  const contentFragment = document.createDocumentFragment();
1120
  let match;
1121
 
1122
  while ((match = productMatchRegex.exec(text)) !== null) {
1123
+ // Add any preceding text
1124
  if (match.index > lastIndex) {
1125
  const textPart = document.createElement('span');
1126
+ // Replace newlines for proper rendering
1127
  textPart.innerHTML = text.substring(lastIndex, match.index).replace(/\\n/g, '<br>');
1128
  contentFragment.appendChild(textPart);
1129
  }
 
1151
  `;
1152
  contentFragment.appendChild(card);
1153
  } else {
1154
+ // If product not found in allProducts, display it as plain text with a note
1155
  const productName = match[2];
1156
+ const notFoundText = document.createElement('span');
1157
+ notFoundText.innerHTML = `[ID_ТОВАРА: ${productId} Название: ${productName}] (товар не найден) `;
1158
  contentFragment.appendChild(notFoundText);
1159
  }
1160
  lastIndex = match.index + match[0].length;
1161
  }
1162
 
1163
+ // Add any remaining text after the last product card
1164
  if (lastIndex < text.length) {
1165
  const textPart = document.createElement('span');
1166
  textPart.innerHTML = text.substring(lastIndex).replace(/\\n/g, '<br>');
 
1176
  localStorage.setItem('evaChatHistory', JSON.stringify(chatHistory));
1177
  }
1178
 
1179
+ // Attach event listeners to dynamically created links/buttons
1180
  messageElement.querySelectorAll('.chat-product-link').forEach(link => {
1181
  link.addEventListener('click', (e) => {
1182
+ e.preventDefault(); // Prevent default link behavior
1183
  const id = e.currentTarget.dataset.productId;
1184
+ closeModal('chatModal'); // Close chat modal
1185
+ openModalById(id); // Open product detail modal
1186
  });
1187
  });
1188
  messageElement.querySelectorAll('.chat-add-to-cart').forEach(link => {
1189
  link.addEventListener('click', (e) => {
1190
+ e.preventDefault(); // Prevent default link behavior
1191
  const id = e.currentTarget.dataset.productId;
1192
+ closeModal('chatModal'); // Close chat modal
1193
+ openQuantityModalById(id); // Open quantity modal for adding to cart
1194
  });
1195
  });
1196
  }
 
1873
 
1874
  products_in_stock = [p for p in all_products_raw if p.get('in_stock', True)]
1875
 
1876
+ # Sort products for consistent display and indexing
1877
  products_sorted_for_js = sorted(products_in_stock, key=lambda p: (not p.get('is_top', False), p.get('name', '').lower()))
1878
 
1879
  products_by_category = {cat: [] for cat in all_cat_names}
 
1889
  CATALOG_TEMPLATE,
1890
  products_by_category=products_by_category,
1891
  ordered_categories=ordered_categories,
1892
+ products_json=json.dumps(products_sorted_for_js), # Pass sorted products to JS
1893
  repo_id=REPO_ID,
1894
  store_address=STORE_ADDRESS,
1895
  currency_code=CURRENCY_CODE