import re from typing import Optional NON_SOLUTION = re.compile( r"(уточнит|приложите скрин|какая ошибка|с какой проблемой" r"|нет обратной связи|запрос завершу|открыть его снова" r"|откройте новый|обратиться в службу поддержки" r"|свяжитесь с технической" r"|напишите нам|позвоните нам)", re.I ) def clean_text(text: str) -> str: text = re.sub(r'\[/?q\].*?\[/q\]', '', text, flags=re.DOTALL | re.IGNORECASE) text = re.sub(r'https?://\S+', '', text) text = re.sub(r'\s+', ' ', text).strip() return text def has_real_solution(messages: list[dict]) -> Optional[str]: support_texts = [] for m in messages: if m["role"] == "support": cleaned = clean_text(m["text"]) if cleaned: support_texts.append(cleaned) if not support_texts: return None combined = "\n".join(support_texts) if len(combined) < 100: return None last = support_texts[-1] if NON_SOLUTION.search(last): return None if last.strip().endswith("?") and len(last) < 150: return None return combined def get_client_dialogue(messages: list[dict]) -> str: texts = [] for m in messages: if m["role"] == "client": cleaned = clean_text(m["text"]) if cleaned: texts.append(cleaned) return "\n".join(texts) def build_chunk(ticket: dict) -> Optional[dict]: msgs = ticket.get("messages") or [] if not msgs: return None description = clean_text(ticket.get("description", "")) solution = has_real_solution(msgs) if not solution: return None client_msgs = get_client_dialogue(msgs) search_parts = [] if description: search_parts.append(description) if client_msgs: search_parts.append(client_msgs) search_text = "\n".join(search_parts).strip() if not search_text: return None full_text = ( f"Категория: {ticket['category']}\n" f"Проблема: {description}\n" f"Решение: {solution}" ) return { "ticket_id": ticket["ticket_id"], "client": ticket["client"], "category": ticket["category"], "search_text": search_text, "full_text": full_text, "tenant_id": None, }