Исправь все символы на текст # bot.py
import json
import os
from datetime import datetime
from nlp_module import NLPModule
from bs4 import BeautifulSoup 
from PyQt6.QtCore import Qt, QUrl 

class MLBotHandler:
    def __init__(self, history_manager, browser_instance=None):
        self.history_manager = history_manager
        self.faq_knowledge_file = "knowledge/faq_knowledge.json"
        self.learned_knowledge_file = "knowledge/learned_knowledge.json"
        self.query_log_file = "knowledge/user_queries.json"
        self.nlp_module = NLPModule()
        self._ensure_files()
        self.faq_knowledge = self._load_faq_knowledge()
        self.learned_knowledge = self._load_learned_knowledge()
        
        self.browser_instance = browser_instance 
        self.chat_widget_instance = None 
        
        self.user_name = "Š’Ń‹"
        self.bot_name = "Š�ŠŗŃ€ŠµŠæŠŗŠ°"

        self._current_search_query = None
        self._current_search_callback = None 
        
        # Š�Š¾Ń�Ń‚Š¾Ń¸Š½ŠøŠµ Ń€ŠµŠ¶ŠøŠ¼Š° Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸
        self._training_mode = False
        self._training_topic = None
        self._found_facts_for_training = [] 

    def set_chat_widget(self, chat_widget):
        self.chat_widget_instance = chat_widget
        self.chat_widget_instance.train_bot_signal.connect(self.start_training_mode)
        self.chat_widget_instance.user_name = self.user_name
        self.chat_widget_instance.bot_name = self.bot_name

    def _add_message_to_chat(self, text, sender="bot"):
        if self.chat_widget_instance:
            self.chat_widget_instance.add_message(text, sender=sender)
        else:
            print(f"{self.bot_name} (Š² Ń‡Š°Ń‚): {text}")

    def _ensure_files(self):
        os.makedirs("knowledge", exist_ok=True)
        for file_path in [self.faq_knowledge_file, self.learned_knowledge_file, self.query_log_file]:
            if not os.path.exists(file_path):
                with open(file_path, 'w', encoding='utf-8') as f:
                    if "user_queries.json" in file_path:
                         json.dump([], f, indent=2) 
                    else:
                         json.dump({}, f, indent=2)

    def _load_faq_knowledge(self):
        try:
            with open(self.faq_knowledge_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
                return data if isinstance(data, dict) else {}
        except (FileNotFoundError, json.JSONDecodeError):
            return {}

    def _load_learned_knowledge(self):
        try:
            with open(self.learned_knowledge_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
                return data if isinstance(data, dict) else {}
        except (FileNotFoundError, json.JSONDecodeError):
            return {}

    def _save_learned_knowledge(self):
        with open(self.learned_knowledge_file, 'w', encoding='utf-8') as f:
            json.dump(self.learned_knowledge, f, indent=2, ensure_ascii=False)

    def _log_query(self, query):
        with open(self.query_log_file, 'r+', encoding='utf-8') as f:
            try:
                data = json.load(f)
            except (json.JSONDecodeError, FileNotFoundError):
                data = [] 
            
            if not isinstance(data, list):
                data = []

            data.append({"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "query": query})
            
            f.seek(0)
            f.truncate(0) 
            json.dump(data, f, indent=2, ensure_ascii=False)


    def start_training_mode(self):
        """Š’ŠŗŠ»ŃˇŃ‡Š°ŠµŃ‚ Ń€ŠµŠ¶ŠøŠ¼ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸, Š±Š¾Ń‚ Š¶Š´ŠµŃ‚ Ń‚ŠµŠ¼Ń� Š´Š»Ń¸ ŠøŠ·Ń�Ń‡ŠµŠ½ŠøŃ¸."""
        if self._training_mode:
            self._add_message_to_chat(f"ŠÆ Ń�Š¶Šµ Š½Š°Ń…Š¾Š¶Ń�Ń�Ń� Š² Ń€ŠµŠ¶ŠøŠ¼Šµ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸. Š�Š¾Š¶Š°Š»Ń�Š¹Ń�Ń‚Š°, Š²Š²ŠµŠ´ŠøŃ‚Šµ Ń‚ŠµŠ¼Ń� ŠøŠ»Šø Š¾Ń‚Š²ŠµŃ‚Ń�Ń‚Šµ Š½Š° Š¼Š¾Š¹ ŠæŃ€ŠµŠ´Ń‹Š´Ń�Ń‰ŠøŠ¹ Š²Š¾ŠæŃ€Š¾Ń�.", sender="bot")
            return
            
        self._training_mode = True
        self._training_topic = None
        self._found_facts_for_training = []
        self._add_message_to_chat(f"Š�Ń€ŠøŠ²ŠµŃ‚, {self.user_name}! ŠÆ Š² Ń€ŠµŠ¶ŠøŠ¼Šµ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸. Š¯Š°ŠæŠøŃ�ŠøŃ‚Šµ, ŠæŠ¾Š¶Š°Š»Ń�Š¹Ń�Ń‚Š°, Ń‚ŠµŠ¼Ń�, ŠŗŠ¾Ń‚Š¾Ń€Ń�Ńˇ Š²Ń‹ Ń…Š¾Ń‚ŠøŃ‚Šµ, Ń‡Ń‚Š¾Š±Ń‹ Ń¸ ŠøŠ·Ń�Ń‡ŠøŠ». Š¯Š°ŠæŃ€ŠøŠ¼ŠµŃ€: 'Š�Š»Š¾Š½ Š�Š°Ń�Šŗ' ŠøŠ»Šø 'Š�Š²Š°Š½Ń‚Š¾Š²Š°Ń¸ Ń„ŠøŠ·ŠøŠŗŠ°'.", sender="bot")

    def get_response(self, message, callback=None):
        self._log_query(message)
        
        corrected_message = self.nlp_module.spell_check(message) if hasattr(self.nlp_module, 'spell_check') else message
        
        if self._training_mode:
            self._handle_training_mode_response(corrected_message, callback)
            return

        nlp_info = self.nlp_module.analyze_text(corrected_message)

        faq_answer = self._find_faq_answer(corrected_message, nlp_info)
        if faq_answer:
            response = faq_answer
        else:
            learned_answer = self._find_in_learned_knowledge(corrected_message, nlp_info)
            if learned_answer:
                response = learned_answer
            else:
                if self.browser_instance:
                    self._add_message_to_chat(f"ŠÆ Š½Šµ Š½Š°Ń�ŠµŠ» ŠæŃ€Ń¸Š¼Š¾Š³Š¾ Š¾Ń‚Š²ŠµŃ‚Š° Š² Ń�Š²Š¾ŠµŠ¹ Š±Š°Š·Šµ. <b>{self.bot_name}</b> ŠøŃ‰ŠµŃ‚ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃˇ ŠæŠ¾ Š·Š°ŠæŃ€Š¾Ń�Ń� '<b>{corrected_message}</b>' Š² ŠøŠ½Ń‚ŠµŃ€Š½ŠµŃ‚Šµ...", sender="bot")
                    self._current_search_query = corrected_message
                    self._current_search_callback = callback
                    self.browser_instance.search_web_for_bot(corrected_message, self._search_web_callback)
                    return 
                else:
                    response = self._compose_nlp_summary_response(corrected_message, nlp_info)

        if callback:
            callback(response)

    def _handle_training_mode_response(self, message, callback):
        if self._training_topic is None: # Š•Ń�Š»Šø Š¶Š´ŠµŠ¼ Ń‚ŠµŠ¼Ń�
            self._training_topic = message.strip()
            if not self._training_topic:
                self._add_message_to_chat("Š�Š¾Š¶Š°Š»Ń�Š¹Ń�Ń‚Š°, Š²Š²ŠµŠ´ŠøŃ‚Šµ Ń‚ŠµŠ¼Ń� Š´Š»Ń¸ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸.", sender="bot")
                if callback: callback("Š˛Š¶ŠøŠ´Š°Ńˇ Ń‚ŠµŠ¼Ń�...")
                return

            self._add_message_to_chat(f"Š˛Ń‚Š»ŠøŃ‡Š½Š¾! <b>{self.bot_name}</b> Š½Š°Ń‡ŠøŠ½Š°ŠµŃ‚ ŠøŠ·Ń�Ń‡ŠµŠ½ŠøŠµ Ń‚ŠµŠ¼Ń‹ '<b>{self._training_topic}</b>'. Š­Ń‚Š¾ Š¼Š¾Š¶ŠµŃ‚ Š·Š°Š½Ń¸Ń‚Ń� Š½ŠµŠ¼Š½Š¾Š³Š¾ Š²Ń€ŠµŠ¼ŠµŠ½Šø...", sender="bot")
            if self.browser_instance:
                self.browser_instance.search_web_for_bot(self._training_topic, self._search_web_for_training_callback)
            else:
                self._add_message_to_chat("Š¯Šµ Š¼Š¾Š³Ń� Š½Š°Ń‡Š°Ń‚Ń� Š¾Š±Ń�Ń‡ŠµŠ½ŠøŠµ: Š±Ń€Š°Ń�Š·ŠµŃ€ Š½ŠµŠ´Š¾Ń�Ń‚Ń�ŠæŠµŠ½.", sender="bot")
                self._reset_training_mode() # Š’Ń‹Ń…Š¾Š´ŠøŠ¼ ŠøŠ· Ń€ŠµŠ¶ŠøŠ¼Š°, ŠµŃ�Š»Šø Š½ŠµŃ‚ Š±Ń€Š°Ń�Š·ŠµŃ€Š°
            if callback:
                callback("Š�Ń‰Ń� ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃˇ...") 
            return
        else: # Š•Ń�Š»Šø Š¶Š´ŠµŠ¼ ŠæŠ¾Š´Ń‚Š²ŠµŃ€Š¶Š´ŠµŠ½ŠøŠµ (Š´Š°/Š½ŠµŃ‚)
            message_lower = message.lower()
            if "Š´Š°" in message_lower or "yes" in message_lower:
                self._save_found_facts()
                response = f"<b>Š¤Š°ŠŗŃ‚Ń‹ Ń�Š¾Ń…Ń€Š°Š½ŠµŠ½Ń‹!</b> {self.bot_name} Š·Š°ŠŗŠ¾Š½Ń‡ŠøŠ» Š¾Š±Ń�Ń‡ŠµŠ½ŠøŠµ ŠæŠ¾ Ń¨Ń‚Š¾Š¹ Ń‚ŠµŠ¼Šµ."
            elif "Š½ŠµŃ‚" in message_lower or "no" in message_lower:
                response = f"Š�Š¾Š½Ń¸Ń‚Š½Š¾. {self.bot_name} Š½Šµ Š±Ń�Š´ŠµŃ‚ Ń�Š¾Ń…Ń€Š°Š½Ń¸Ń‚Ń� Ń¨Ń‚Šø Ń„Š°ŠŗŃ‚Ń‹. Š˛Š±Ń�Ń‡ŠµŠ½ŠøŠµ ŠæŠ¾ Ń¨Ń‚Š¾Š¹ Ń‚ŠµŠ¼Šµ Š·Š°Š²ŠµŃ€Ń�ŠµŠ½Š¾."
            else:
                response = "Š�Š¾Š¶Š°Š»Ń�Š¹Ń�Ń‚Š°, Š¾Ń‚Š²ŠµŃ‚Ń�Ń‚Šµ '<b>Š´Š°</b>', Ń‡Ń‚Š¾Š±Ń‹ Ń�Š¾Ń…Ń€Š°Š½ŠøŃ‚Ń� Š½Š°Š¹Š´ŠµŠ½Š½Ń‹Šµ Ń„Š°ŠŗŃ‚Ń‹, ŠøŠ»Šø '<b>Š½ŠµŃ‚</b>', Ń‡Ń‚Š¾Š±Ń‹ Š¾Ń‚Š¼ŠµŠ½ŠøŃ‚Ń�."
            
            self._reset_training_mode() # Š’Ń‹Ń…Š¾Š´ŠøŠ¼ ŠøŠ· Ń€ŠµŠ¶ŠøŠ¼Š° Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸ ŠæŠ¾Ń�Š»Šµ Š¾Ń‚Š²ŠµŃ‚Š°
            
            if callback:
                callback(response)
            return

    def _reset_training_mode(self):
        """Š�Š±Ń€Š°Ń�Ń‹Š²Š°ŠµŃ‚ Š²Ń�Šµ Ń„Š»Š°Š³Šø Šø ŠæŠµŃ€ŠµŠ¼ŠµŠ½Š½Ń‹Šµ, Ń�Š²Ń¸Š·Š°Š½Š½Ń‹Šµ Ń� Ń€ŠµŠ¶ŠøŠ¼Š¾Š¼ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸."""
        self._training_mode = False
        self._training_topic = None
        self._found_facts_for_training = []

    def _search_web_callback(self, html_content, error_message):
        """Callback Š´Š»Ń¸ Š¾Š±Ń‹Ń‡Š½Š¾Š³Š¾ Š²ŠµŠ±-ŠæŠ¾ŠøŃ�ŠŗŠ°."""
        if self._current_search_callback:
            if error_message:
                self._add_message_to_chat(f"Š¯Šµ Ń�Š´Š°Š»Š¾Ń�Ń� ŠæŠ¾Š»Ń�Ń‡ŠøŃ‚Ń� ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃˇ: {error_message}", sender="bot")
                self._current_search_callback(f"Š�Ń€Š¾ŠøŠ·Š¾Ń�Š»Š° Š¾Ń�ŠøŠ±ŠŗŠ° ŠæŃ€Šø ŠæŠ¾ŠøŃ�ŠŗŠµ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø.")
            elif html_content:
                current_url = self.browser_instance.tabs.currentWidget().browser.url().toString()
                if current_url and current_url != "about:blank":
                    display_url = f"<a href='{current_url}'>{current_url}</a>"
                    self._add_message_to_chat(f"<b>{self.bot_name}</b> Š½Š°Ń�ŠµŠ» Ń�Ń‚Ń€Š°Š½ŠøŃ†Ń� ŠæŠ¾ Š²Š°Ń�ŠµŠ¼Ń� Š·Š°ŠæŃ€Š¾Ń�Ń�: {display_url}. Š�Š¾Š³Ń� Š»Šø Ń¸ Ń‡Ń‚Š¾-Ń‚Š¾ ŠŗŠ¾Š½ŠŗŃ€ŠµŃ‚Š½Š¾Šµ Š½Š°Š¹Ń‚Šø Š½Š° Š½ŠµŠ¹?", sender="bot")
                    self._current_search_callback("Š�Š¾ŠøŃ�Šŗ Š·Š°Š²ŠµŃ€Ń�ŠµŠ½. Š§Ń‚Š¾-Ń‚Š¾ ŠµŃ‰Ń‘?")
                else:
                    self._add_message_to_chat(f"<b>{self.bot_name}</b> Š·Š°Š²ŠµŃ€Ń�ŠøŠ» ŠæŠ¾ŠøŃ�Šŗ, Š½Š¾ Š½Šµ Š¼Š¾Š³Ń� Ń�ŠŗŠ°Š·Š°Ń‚Ń� Š½Š° ŠŗŠ¾Š½ŠŗŃ€ŠµŃ‚Š½Ń�Ńˇ Ń�Ń‚Ń€Š°Š½ŠøŃ†Ń�.", sender="bot")
                    self._current_search_callback("Š¯ŠøŃ‡ŠµŠ³Š¾ Š½Šµ Š½Š°Š¹Š´ŠµŠ½Š¾.")
            else:
                self._add_message_to_chat(f"<b>{self.bot_name}</b> Š½Šµ Š´Š°Š» Ń€ŠµŠ·Ń�Š»Ń�Ń‚Š°Ń‚Š¾Š².", sender="bot")
                self._current_search_callback("Š¯ŠøŃ‡ŠµŠ³Š¾ Š½Šµ Š½Š°Š¹Š´ŠµŠ½Š¾.")
        self._current_search_query = None
        self._current_search_callback = None


    def _search_web_for_training_callback(self, html_content, error_message):
        """
        Callback-Ń„Ń�Š½ŠŗŃ†ŠøŃ¸ Š´Š»Ń¸ Š¾Š±Ń€Š°Š±Š¾Ń‚ŠŗŠø Ń€ŠµŠ·Ń�Š»Ń�Ń‚Š°Ń‚Š¾Š² Š²ŠµŠ±-ŠæŠ¾ŠøŃ�ŠŗŠ° Š² Ń€ŠµŠ¶ŠøŠ¼Šµ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸.
        """
        topic = self._training_topic
        
        if error_message:
            self._add_message_to_chat(f"Š¯Šµ Ń�Š´Š°Š»Š¾Ń�Ń� ŠæŠ¾Š»Ń�Ń‡ŠøŃ‚Ń� ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃˇ Š´Š»Ń¸ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸ ŠæŠ¾ Ń‚ŠµŠ¼Šµ '<b>{topic}</b>': {error_message}", sender="bot")
            self._reset_training_mode()
            return

        if html_content:
            self._add_message_to_chat(f"<b>{self.bot_name}</b> Š°Š½Š°Š»ŠøŠ·ŠøŃ€Ń�ŠµŃ‚ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃˇ ŠæŠ¾ '<b>{topic}</b>'...", sender="bot")
            try:
                soup = BeautifulSoup(html_content, 'html.parser')
                
                # Š�Š¾ŠæŃ€Š¾Š±Ń�ŠµŠ¼ ŠøŠ·Š²Š»ŠµŃ‡Ń� Š¾Ń�Š½Š¾Š²Š½Š¾Š¹ Ń‚ŠµŠŗŃ�Ń‚ ŠøŠ· Š°Š±Š·Š°Ń†ŠµŠ², Š·Š°Š³Š¾Š»Š¾Š²ŠŗŠ¾Š² Šø Ń¨Š»ŠµŠ¼ŠµŠ½Ń‚Š¾Š² Ń�ŠæŠøŃ�ŠŗŠ°
                paragraphs = soup.find_all(['p', 'h1', 'h2', 'h3', 'li'])
                full_text = " ".join([p.get_text().strip() for p in paragraphs if p.get_text().strip()])
                
                if full_text:
                    nlp_result = self.nlp_module.analyze_text(full_text)
                    
                    suggested_facts = []
                    
                    if nlp_result['summary'] and nlp_result['summary'].lower() != topic.lower():
                        suggested_facts.append(nlp_result['summary'])
                    
                    doc = self.nlp_module.nlp(full_text) 
                    sentences = [sent.text.strip() for sent in doc.sents]
                    
                    topic_keywords = {kw.lower() for kw, _ in self.nlp_module.analyze_text(topic)['keywords']}
                    
                    for sent in sentences:
                        # Š¤ŠøŠ»Ń�Ń‚Ń€Ń�ŠµŠ¼ ŠæŃ€ŠµŠ´Š»Š¾Š¶ŠµŠ½ŠøŃ¸: Š´Š¾Ń�Ń‚Š°Ń‚Š¾Ń‡Š½Š¾ Š´Š»ŠøŠ½Š½Ń‹Šµ, Ń�Š¾Š´ŠµŃ€Š¶Š°Ń‚ ŠŗŠ»ŃˇŃ‡ŠµŠ²Ń‹Šµ Ń�Š»Š¾Š²Š°, Šø ŠµŃ‰Ń‘ Š½Šµ Š´Š¾Š±Š°Š²Š»ŠµŠ½Ń‹
                        if len(sent) > 50 and any(kw in sent.lower() for kw in topic_keywords) and sent not in suggested_facts:
                            if len(suggested_facts) < 5: 
                                suggested_facts.append(sent)
                    
                    self._found_facts_for_training = suggested_facts 
                    
                    if suggested_facts:
                        display_facts = "<br>".join([f"ā€“ {fact}" for fact in suggested_facts])
                        self._add_message_to_chat(f"<b>{self.bot_name}</b> Š½Š°Ń�ŠµŠ» Ń�Š»ŠµŠ´Ń�ŃˇŃ‰Ń�Ńˇ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃˇ ŠæŠ¾ Ń‚ŠµŠ¼Šµ '<b>{topic}</b>':<br>{display_facts}<br><br>Š�Š¾Ń‚ŠøŃ‚Šµ, Ń‡Ń‚Š¾Š±Ń‹ Ń¸ Š·Š°ŠæŠ¾Š¼Š½ŠøŠ» Ń¨Ń‚Š¾? Š˛Ń‚Š²ŠµŃ‚Ń�Ń‚Šµ '<b>Š´Š°</b>' ŠøŠ»Šø '<b>Š½ŠµŃ‚</b>'.", sender="bot")
                    else:
                        self._add_message_to_chat(f"<b>{self.bot_name}</b> Š½Š°Ń�ŠµŠ» Ń�Ń‚Ń€Š°Š½ŠøŃ†Ń� ŠæŠ¾ '<b>{topic}</b>', Š½Š¾ Š½Šµ Ń�Š¼Š¾Š³ ŠøŠ·Š²Š»ŠµŃ‡Ń� ŠæŠ¾Š»ŠµŠ·Š½Ń�Ńˇ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃˇ Š´Š»Ń¸ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸.", sender="bot")
                        self._reset_training_mode()
                else:
                    self._add_message_to_chat(f"<b>{self.bot_name}</b> Š½Š°Ń�ŠµŠ» Ń�Ń‚Ń€Š°Š½ŠøŃ†Ń� ŠæŠ¾ '<b>{topic}</b>', Š½Š¾ Š½Šµ Ń�Š¼Š¾Š³ ŠæŠ¾Š»Ń�Ń‡ŠøŃ‚Ń� Ń‚ŠµŠŗŃ�Ń‚Š¾Š²Š¾Šµ Ń�Š¾Š´ŠµŃ€Š¶ŠøŠ¼Š¾Šµ.", sender="bot")
                    self._reset_training_mode()
                    
            except Exception as e:
                self._add_message_to_chat(f"Š˛Ń�ŠøŠ±ŠŗŠ° ŠæŃ€Šø Š¾Š±Ń€Š°Š±Š¾Ń‚ŠŗŠµ Š½Š°Š¹Š´ŠµŠ½Š½Š¾Š¹ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š´Š»Ń¸ '<b>{topic}</b>': {e}", sender="bot")
                print(f"Š�Š°Ń€Ń�ŠøŠ½Š³/NLP Š¾Ń�ŠøŠ±ŠŗŠ° Š² Ń€ŠµŠ¶ŠøŠ¼Šµ Š¾Š±Ń�Ń‡ŠµŠ½ŠøŃ¸: {e}")
                self._reset_training_mode()
    
    def _save_found_facts(self):
        """Š�Š¾Ń…Ń€Š°Š½Ń¸ŠµŃ‚ Š½Š°Š¹Š´ŠµŠ½Š½Ń‹Šµ Ń„Š°ŠŗŃ‚Ń‹ Š² learned_knowledge.json."""
        if not self._found_facts_for_training or not self._training_topic:
            return

        topic_key = self._training_topic.lower()
        
        self.learned_knowledge[topic_key] = {
            'summary': self._found_facts_for_training[0] if self._found_facts_for_training else "",
            'facts': self._found_facts_for_training
        }

        self._save_learned_knowledge()
        self._add_message_to_chat(f"Š�Š½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃ¸ ŠæŠ¾ Ń‚ŠµŠ¼Šµ '<b>{self._training_topic}</b>' Ń�Š¾Ń…Ń€Š°Š½ŠµŠ½Š° Š² Š±Š°Š·Šµ {self.bot_name}.", sender="bot")

    def _find_faq_answer(self, message, nlp_info):
        """
        Š�Ń‰ŠµŃ‚ ŠæŃ€Ń¸Š¼Š¾Š¹ Š¾Ń‚Š²ŠµŃ‚ Š² FAQ Š±Š°Š·Šµ Š·Š½Š°Š½ŠøŠ¹.
        """
        message_lower = message.lower()

        if message_lower in self.faq_knowledge:
            return self.faq_knowledge[message_lower]
        
        faq_synonyms = {
            "ŠŗŃ�Ń€Ń� Š´Š¾Š»Š»Š°Ń€Š°": ["ŠŗŃ�Ń€Ń� Š´Š¾Š»Š»Š°Ń€Š°", "Ń�ŠŗŠ¾Š»Ń�ŠŗŠ¾ Ń�Ń‚Š¾ŠøŃ‚ Š´Š¾Š»Š»Š°Ń€", "Š´Š¾Š»Š»Š°Ń€ ŠŗŃ�Ń€Ń�", "ŠŗŃ�Ń€Ń� usd"],
            "ŠŗŃ�Ń€Ń� ŠµŠ²Ń€Š¾": ["ŠŗŃ�Ń€Ń� ŠµŠ²Ń€Š¾", "Ń�ŠŗŠ¾Š»Ń�ŠŗŠ¾ Ń�Ń‚Š¾ŠøŃ‚ ŠµŠ²Ń€Š¾", "ŠµŠ²Ń€Š¾ ŠŗŃ�Ń€Ń�", "ŠŗŃ�Ń€Ń� eur"],
            "Ń�ŠŗŠ¾Š»Ń�ŠŗŠ¾ Ń�Ń‚Š¾ŠøŃ‚ Š±ŠøŃ‚ŠŗŠ¾ŠøŠ½": ["Ń�ŠŗŠ¾Š»Ń�ŠŗŠ¾ Ń�Ń‚Š¾ŠøŃ‚ Š±ŠøŃ‚ŠŗŠ¾ŠøŠ½", "Ń†ŠµŠ½Š° Š±ŠøŃ‚ŠŗŠ¾ŠøŠ½Š°", "Š±ŠøŃ‚ŠŗŠ¾ŠøŠ½ ŠŗŃ�Ń€Ń�", "btc ŠŗŃ�Ń€Ń�"],
            "ŠæŃ€ŠøŠ²ŠµŃ‚": ["ŠæŃ€ŠøŠ²ŠµŃ‚", "ŠæŃ€ŠøŠ²ŠµŃ‚Ń�Ń‚Š²ŠøŠµ", "Š·Š´Ń€Š°Š²Ń�Ń‚Š²Ń�Š¹Ń‚Šµ", "Š´Š¾Š±Ń€Ń‹Š¹ Š´ŠµŠ½Ń�", "Š´Š¾Š±Ń€Ń‹Š¹ Š²ŠµŃ‡ŠµŃ€", "Ń…Š°Š¹"],
            "ŠŗŠ°Šŗ Š´ŠµŠ»Š°": ["ŠŗŠ°Šŗ Š´ŠµŠ»Š°", "ŠŗŠ°Šŗ Ń‚Ń‹", "ŠŗŠ°Šŗ Ń� Ń‚ŠµŠ±Ń¸ Š´ŠµŠ»Š°", "Ń‡Ń‚Š¾ Š½Š¾Š²Š¾Š³Š¾"],
            "ŠŗŃ‚Š¾ Ń‚Ń‹": ["ŠŗŃ‚Š¾ Ń‚Ń‹", "Ń‡Ń‚Š¾ Ń‚Ń‹", "Š½Š°Š·Š¾Š²Šø Ń�ŠµŠ±Ń¸", "ŠŗŠ°Šŗ Ń‚ŠµŠ±Ń¸ Š·Š¾Š²Ń�Ń‚"],
            "Š¾Š±Ń�Ń‡ŠøŃ‚Ń�": ["ŠŗŠ°Šŗ Š¾Š±Ń�Ń‡Š°Ń‚Ń�", "Š¾Š±Ń�Ń‡ŠøŃ‚Ń� Š±Š¾Ń‚Š°", "Š½Š°Ń�Ń‡ŠøŃ�Ń�"] 
        }
        for official_q, variants in faq_synonyms.items():
            if any(v in message_lower for v in variants):
                if official_q in self.faq_knowledge:
                    return self.faq_knowledge[official_q]

        keywords_lower = {kw.lower() for kw, _ in nlp_info['keywords']}
        entities_lower = {ent_text.lower() for ent_text, _ in nlp_info['entities']}
        
        for q_key, answer in self.faq_knowledge.items():
            q_key_nlp_info = self.nlp_module.analyze_text(q_key)
            q_key_keywords = {kw.lower() for kw, _ in q_key_nlp_info['keywords']}
            q_key_entities = {ent_text.lower() for ent_text, _ in q_key_nlp_info['entities']}

            if keywords_lower.intersection(q_key_keywords) or entities_lower.intersection(q_key_entities):
                return answer 
        
        return None

    def _find_in_learned_knowledge(self, message, nlp_info):
        """
        Š�Ń‰ŠµŃ‚ Š¾Ń‚Š²ŠµŃ‚ Š² Š±Š°Š·Šµ 'ŠøŠ·Ń�Ń‡ŠµŠ½Š½Ń‹Ń…' Š·Š½Š°Š½ŠøŠ¹.
        """
        message_lower = message.lower()
        keywords = {kw.lower() for kw, _ in nlp_info['keywords']}
        entities = {ent_text.lower() for ent_text, _ in nlp_info['entities']}

        # 1. Š�Š¾ŠøŃ�Šŗ ŠæŠ¾ Ń‚Š¾Ń‡Š½Š¾Š¹ Ń‚ŠµŠ¼Šµ ŠøŠ»Šø Ń�Ń…Š¾Š¶ŠµŠ¹
        for topic_key, topic_data in self.learned_knowledge.items():
            if message_lower == topic_key:
                return topic_data.get('summary', topic_data.get('facts', [])[0] if topic_data.get('facts') else None)
            
            topic_words = set(topic_key.lower().split())
            if keywords.intersection(topic_words) or entities.intersection(topic_words):
                return topic_data.get('summary', topic_data.get('facts', [])[0] if topic_data.get('facts') else None)

        # 2. Š�Š¾ŠøŃ�Šŗ ŠæŠ¾ Ń„Š°ŠŗŃ‚Š°Š¼ Š²Š½Ń�Ń‚Ń€Šø Ń‚ŠµŠ¼
        for topic_key, topic_data in self.learned_knowledge.items():
            if 'facts' in topic_data and isinstance(topic_data['facts'], list):
                for fact in topic_data['facts']:
                    fact_lower = fact.lower()
                    if message_lower in fact_lower:
                        return fact
                    
                    fact_nlp_info = self.nlp_module.analyze_text(fact)
                    fact_keywords = {kw.lower() for kw, _ in fact_nlp_info['keywords']}
                    if keywords.intersection(fact_keywords):
                        return fact
        return None

    def _compose_nlp_summary_response(self, message, nlp_info):
        """
        Š¤Š¾Ń€Š¼ŠøŃ€Ń�ŠµŃ‚ Š¾Ń‚Š²ŠµŃ‚ Š½Š° Š¾Ń�Š½Š¾Š²Šµ Ń€ŠµŠ·Ń�Š»Ń�Ń‚Š°Ń‚Š¾Š² NLP-Š°Š½Š°Š»ŠøŠ·Š°, ŠµŃ�Š»Šø ŠæŃ€Ń¸Š¼Š¾Š³Š¾ Š¾Ń‚Š²ŠµŃ‚Š° Š½Šµ Š½Š°Š¹Š´ŠµŠ½Š¾.
        """
        keywords_str = ', '.join([f"<b>{kw}</b>" for kw, _ in nlp_info['keywords']]) if nlp_info['keywords'] else 'Š½ŠµŃ‚'
        entities_str = ', '.join([f"<b>{text}</b> ({label})" for text, label in nlp_info['entities']]) or 'Š½ŠµŃ‚'
        
        response_parts = []
        
        if nlp_info['intent'] != 'Š¾Š±Ń‰ŠøŠ¹':
            response_parts.append(f"Š�Š¾Ń…Š¾Š¶Šµ, Š²Ń‹ Ń…Š¾Ń‚ŠøŃ‚Šµ Ń�Š·Š½Š°Ń‚Ń� Š¾ <b>{nlp_info['intent']}</b>.")
        
        if nlp_info['summary'] and nlp_info['summary'].lower() != message.lower():
            response_parts.append(f"Š˛Ń�Š½Š¾Š²Š½Š°Ń¸ ŠøŠ´ŠµŃ¸: <i>{nlp_info['summary']}</i>")
        elif nlp_info['summary']:
             response_parts.append(f"Š’Š°Ń� Š·Š°ŠæŃ€Š¾Ń�: <i>{nlp_info['summary']}</i>")
        
        if keywords_str != 'Š½ŠµŃ‚':
            response_parts.append(f"Š�Š»ŃˇŃ‡ŠµŠ²Ń‹Šµ Ń�Š»Š¾Š²Š°: {keywords_str}.")
        
        if entities_str != 'Š½ŠµŃ‚':
            response_parts.append(f"Š�Ń�Ń‰Š½Š¾Ń�Ń‚Šø: {entities_str}.")
        
        if not response_parts:
            return f"<b>{self.bot_name}</b> ŠæŠ¾Š»Ń�Ń‡ŠøŠ» Š²Š°Ń� Š·Š°ŠæŃ€Š¾Ń�, Š½Š¾ Š½Šµ Ń�Š¼Š¾Š³ Š½Š°Š¹Ń‚Šø ŠŗŠ¾Š½ŠŗŃ€ŠµŃ‚Š½Š¾Š¹ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŠø Š² Š¼Š¾ŠµŠ¹ Š±Š°Š·Šµ ŠøŠ»Šø Š¾ŠæŃ€ŠµŠ´ŠµŠ»ŠøŃ‚Ń� Ń‚ŠµŠ¼Ń�. Š�Š¾Š¶ŠµŃ‚Šµ ŠæŠµŃ€ŠµŃ„Ń€Š°Š·ŠøŃ€Š¾Š²Š°Ń‚Ń�?"
            
        return "<br>".join(response_parts)