{"id":368971,"date":"2024-05-21T03:53:25","date_gmt":"2024-05-21T03:53:25","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=368971"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=368971","title":{"rendered":"<span>AutoLove: \u0430\u043f\u0434\u0435\u0439\u0442\u044b \u0434\u0435\u0432\u0443\u0448\u043a\u0435 \u0441 YandexGPT<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/6cf\/a57\/39d\/6cfa5739d317fb166caa43b344d2c0f0.jpg\" width=\"540\" height=\"304\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6cf\/a57\/39d\/6cfa5739d317fb166caa43b344d2c0f0.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>\u0421\u0430\u043b\u044e\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0413\u0440\u0438\u0433\u043e\u0440\u0438\u0439, \u044f \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u043f\u043e \u0441\u043f\u0435\u0446\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c \u0432 AllSee. \u041a\u0430\u043a \u0438\u00a0\u0443\u00a0\u043c\u043d\u043e\u0433\u0438\u0445 \u0438\u0437\u00a0\u043d\u0430\u0441, \u0443\u00a0\u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u043a\u0430, \u0438\u00a0\u0435\u0439\u00a0\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f. \u0421\u0430\u043c \u043f\u043e\u00a0\u0441\u0435\u0431\u0435 \u044f\u00a0\u0447\u0435\u043b\u043e\u0432\u0435\u043a \u0437\u0430\u043d\u044f\u0442\u043e\u0439 \u0438\u00a0\u043c\u043d\u0435 \u0431\u044b\u0432\u0430\u0435\u0442 \u0442\u0440\u0443\u0434\u043d\u043e \u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f \u043e\u0442\u00a0\u0434\u0435\u043b \u0438\u00a0\u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0430\u043f\u0434\u0435\u0439\u0442 \u0434\u0435\u0432\u0443\u0448\u043a\u0435, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0442\u0435\u0440\u043f\u0435\u0442\u044c \u043a\u0430\u043f\u0440\u0438\u0437\u044b \u043f\u043e\u00a0\u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u00ab\u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f\u00bb. \u0412\u00a0\u0441\u0442\u0430\u0442\u044c\u0435 \u044f\u00a0\u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e, \u043a\u0430\u043a YandexGPT \u0438\u00a0Python-Telegram \u00ab\u0443\u0434\u0435\u043b\u044f\u044e\u0442 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435\u00bb \u043c\u043e\u0435\u0439 \u0434\u0435\u0432\u0443\u0448\u043a\u0435.<\/p>\n<h3>\u041a\u0430\u043a\u0438\u0435 \u0432\u0432\u043e\u0434\u043d\u044b\u0435?<\/h3>\n<p>\u0415\u0441\u0442\u044c \u0447\u0430\u0442 \u0432\u00a0Telegram, \u043a\u0443\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0430\u043f\u0434\u0435\u0439\u0442\u044b: \u043f\u043e\u0436\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0431\u0440\u043e\u0433\u043e \u0443\u0442\u0440\u0430, \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0435\u0447\u0435\u0440\u043e\u043c, \u043a\u0430\u043a \u044f\u00a0\u0441\u043a\u0443\u0447\u0430\u044e, \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c, \u043a\u0430\u043a \u0434\u0435\u043b\u0430 \u0438\u00a0\u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u042f\u00a0\u0445\u043e\u0447\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432\u00a0\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u043b\u043e\u0442\u044b. \u0422\u0435\u043a\u0441\u0442\u044b \u0430\u043f\u0434\u0435\u0439\u0442\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u00a0\u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0414\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0430\u043f\u0434\u0435\u0439\u0442\u043e\u0432 \u044f\u00a0\u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/yandexgpt\/\" rel=\"noopener noreferrer nofollow\"><u>YandexGPT API<\/u><\/a>, \u0430\u00a0\u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441\u00a0Telegram\u00a0\u2014 <a href=\"https:\/\/github.com\/alexander-akhmetov\/python-telegram\" rel=\"noopener noreferrer nofollow\"><u>python-telegram<\/u><\/a>.<\/p>\n<h2>Routines (\u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438)<\/h2>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0427\u0442\u0435\u043d\u0438\u0435 YAML \u0438 JSON<\/p>\n<pre><code class=\"python\">def read_yaml(path: str) -> dict:     with open(path, 'r') as stream:         return yaml.safe_load(stream)   def read_json(path: str) -> dict:     with open(path, 'r') as stream:         return json.load(stream)<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u00ab00:00\u00bb \u0432 \u0441\u043f\u0438\u0441\u043a\u0438 datetime.time<\/p>\n<pre><code class=\"python\">def yaml_to_datetime_time(times_str: list) -> list:     return [         datetime.time(             *map(                 int,                 time_str.split(':')             )         )         for time_str         in times_str     ]<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>YandexGPT API<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u0441\u0440\u0430\u0437\u0443 \u043a\u00a0\u043a\u043e\u0434\u0443 \u0434\u043b\u044f\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"python\"> def send_completion_request(           self,           messages: List[dict],           temperature: float = 0.6,           max_tokens: int = 1000,           stream: bool = False,           completion_url: str = \"https:\/\/llm.api.cloud.yandex.net\/foundationModels\/v1\/completion\"   ) -> dict:       # checking if IAM token and catalog id is set       if not self._iam_token or not self._catalog_id:           raise Exception(\"IAM token and catalog id must be set to send completion requests\")       # sending request       headers = {           \"Content-Type\": \"application\/json\",           \"Authorization\": f\"Bearer {self._iam_token}\",           \"x-folder-id\": self._catalog_id       }       data = {           \"modelUri\": f\"gpt:\/\/{self._catalog_id}\/{self.model_type}\/latest\",           \"completionOptions\": {               \"stream\": stream,               \"temperature\": temperature,               \"maxTokens\": str(max_tokens)           },           \"messages\": messages       }       response = requests.post(completion_url, headers=headers, json=data)       # checking response       if response.status_code == 200:           return response.json()       else:           raise Exception(f\"Failed to send completion request. Status code: {response.status_code}\\n{response.text}\") <\/code><\/pre>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 temperature, max_tokens, stream, completion_url \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0442\u044c <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/iam-token\/create-for-sa\" rel=\"noopener noreferrer nofollow\"><u>IAM\u2011\u0442\u043e\u043a\u0435\u043d<\/u><\/a> \u0438 <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/iam-token\/create-for-sa#via-jwt\" rel=\"noopener noreferrer nofollow\"><u>ID \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 Yandex Cloud<\/u><\/a>. <\/p>\n<p>\u042f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e IAM\u2011\u0442\u043e\u043a\u0435\u043d\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f\u00a0\u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c YAML\u2011\u043a\u043e\u043d\u0444\u0438\u0433 \u0441\u00a0\u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 (<a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/authorized-key\/create#console_1\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u0430\u043a\u00a0\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u044e\u0447 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/u><\/a> \u0438 <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/sa\/get-id\" rel=\"noopener noreferrer nofollow\"><u>\u0433\u0434\u0435 \u0432\u0437\u044f\u0442\u044c ID \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430<\/u><\/a><u>)<\/u>:<\/p>\n<pre><code class=\"yaml\">ServiceAccountID: 1111111111111 ServiceAccountKeyID: 11111111111 CatalogID: 11111111<\/code><\/pre>\n<p>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON \u043a\u043b\u044e\u0447 \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u043a\u043b\u0430\u0441\u0441\u0430 ChatGPT.<\/p>\n<p>\u0412\u043e\u0442 \u043a\u0430\u043a\u00a0\u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">class YandexGPT:     available_models = [         'yandexgpt',         'yandexgpt-lite',         'summarization'     ]      def __init__(             self,             model_type: str = 'yandexgpt',             iam_token: str = None,             catalog_id: str = None,             yandex_cloud_config_file_path: str = None,             yandex_gpt_key_file_path: str = None,             iam_url: str = \"https:\/\/iam.api.cloud.yandex.net\/iam\/v1\/tokens\"     ) -> None:         # setting config files         self._yandex_cloud_config_file_path = yandex_cloud_config_file_path         self._yandex_gpt_key_file_path = yandex_gpt_key_file_path         self._iam_url = iam_url         # setting model type         if model_type not in self.available_models:             raise ValueError(f\"Model type must be one of {self.available_models}\")         else:             self.model_type = model_type         # setting IAM token         if not iam_token:             self._set_iam_token()         else:             self._iam_token = iam_token         # setting catalog id         if not catalog_id:             self._set_catalog_id()         else:             self._catalog_id = catalog_id      def _set_iam_token(self) -> None:         # reading yaml config         config = read_yaml(self._yandex_cloud_config_file_path)         # reading json key         key = read_json(self._yandex_gpt_key_file_path)         # generating jwt token         jwt_token = self._generate_jwt_token(             service_account_id=config['ServiceAccountID'],             private_key=key['private_key'],             key_id=config['ServiceAccountKeyID'],             url=self._iam_url         )         # sending request to get IAM token and setting IAM token         self._iam_token = self._swap_jwt_to_iam(             jwt_token=jwt_token,             url=self._iam_url         )      @staticmethod     def _swap_jwt_to_iam(             jwt_token: str,             url: str = \"https:\/\/iam.api.cloud.yandex.net\/iam\/v1\/tokens\"     ) -> str:         # sending request to get IAM token         headers = {             \"Content-Type\": \"application\/json\"         }         data = {             \"jwt\": jwt_token         }         response = requests.post(url, headers=headers, json=data)         # checking response         if response.status_code == 200:             return response.json()['iamToken']         else:             raise Exception(                 f\"Failed to get IAM token. \"                 f\"Status code: {response.status_code}\"                 f\"\\n\"                 f\"{response.text}\"             )      @staticmethod     def _generate_jwt_token(             service_account_id: str,             private_key: str,             key_id: str,             url: str = 'https:\/\/iam.api.cloud.yandex.net\/iam\/v1\/tokens'     ) -> str:         # generating jwt token         now = int(time.time())         payload = {             'aud': url,             'iss': service_account_id,             'iat': now,             'exp': now + 360         }         encoded_token = jwt.encode(             payload,             private_key,             algorithm='PS256',             headers={'kid': key_id}         )         return encoded_token      def _set_catalog_id(self) -> None:         # reading yaml config file         config = read_yaml(self._yandex_cloud_config_file_path)         # setting catalog id from config file         self._catalog_id = config['CatalogID']      def send_completion_request(             self,             messages: List[dict],             temperature: float = 0.6,             max_tokens: int = 1000,             stream: bool = False,             completion_url: str = \"https:\/\/llm.api.cloud.yandex.net\/foundationModels\/v1\/completion\"     ) -> dict:         # checking if IAM token and catalog id is set         if not self._iam_token or not self._catalog_id:             raise Exception(\"IAM token and catalog id must be set to send completion requests\")         # sending request         headers = {             \"Content-Type\": \"application\/json\",             \"Authorization\": f\"Bearer {self._iam_token}\",             \"x-folder-id\": self._catalog_id         }         data = {             \"modelUri\": f\"gpt:\/\/{self._catalog_id}\/{self.model_type}\/latest\",             \"completionOptions\": {                 \"stream\": stream,                 \"temperature\": temperature,                 \"maxTokens\": str(max_tokens)             },             \"messages\": messages         }         response = requests.post(completion_url, headers=headers, json=data)         # checking response         if response.status_code == 200:             return response.json()         else:             raise Exception(f\"Failed to send completion request. Status code: {response.status_code}\\n{response.text}\")<\/code><\/pre>\n<p>\u042f \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433 \u0444\u0430\u0439\u043b\u043e\u0432\u00a0 \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u043c\u043e\u0433 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/div>\n<\/details>\n<h2>Python-Telegram<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u043e\u0442 <a href=\"https:\/\/github.com\/alexander-akhmetov\/python-telegram\/blob\/master\/telegram\/client.py\" rel=\"noopener noreferrer nofollow\"><u>telegram.client.Telegram<\/u><\/a> \u0438 YangexGPT \u043a\u043b\u0430\u0441\u0441. \u041e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u043c\u0435\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0441\u043b\u043e\u0442 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0446\u0435\u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u0443.<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">class AutoChat(Telegram, YandexGPT):     def __init__(             self,             target_username: str = None,             sending_time: List[datetime.time] = None,             chat_system_prompt: List[str] = None,             chat_mode: bool = None,             timezone: pytz.timezone = None,             telegram_config_file_path: str = None,             auto_chat_config_file_path: str = None,             *args,             **kwargs,     ) -> None:         # initializing telegram         # checking if api_id, api_hash, phone, database_encryption_key, files_directory and login in **kwargs         if all(                 key                 in kwargs                 for key                 in [                     'api_id',                     'api_hash',                     'phone',                     'database_encryption_key',                     'files_directory',                     'login'                 ]         ):             Telegram.__init__(                 *args,                 **kwargs,             )         # if there is no then calling custom telegram init method         else:             self._init_telegram(telegram_config_file_path)         # initializing yandex gpt         # checking if iam_token and catalog_id in **kwargs         if all(                 key                 in kwargs                 for key                 in [                     'iam_token',                     'catalog_id'                 ]         ):             YandexGPT.__init__(                 *args,                 **kwargs             )         # if there is no then calling custom yandex gpt init method         else:             self._init_yandex_gpt(                 *args,                 **kwargs             )         # initializing auto chat         # checking if target_username, sending_time, chat_system_prompt, chat_mode, timezone is set         if all([             target_username,             sending_time,             chat_system_prompt,             chat_mode,             timezone         ]):             self._target_user_id = self._get_target_user_id(target_username)             self._sending_time = yaml_to_datetime_time(sending_time)             self._chat_system_prompt = chat_system_prompt             self._chat_mode = chat_mode             self._timezone = timezone         # if there is no then calling custom auto chat init method         else:             self._init_autochat(auto_chat_config_file_path)      def _init_yandex_gpt(             self,             *args,             **kwargs     ) -> None:         # checking if yandex_cloud_config_file_path and yandex_gpt_key_file_path in **kwargs         if not all(                 key                 in kwargs                 for key                 in [                     'yandex_cloud_config_file_path',                     'yandex_gpt_key_file_path'                 ]         ):             raise ValueError(                 \"AutoChat args must contain either\"                 \" 'yandex_cloud_config_file_path' and \"                 \"'yandex_gpt_key_file_path' or \"                 \"'iam_token' and 'catalog_id'\"             )         # if they are than calling custom yandex gpt init method         else:             YandexGPT.__init__(                 self,                 *args,                 **kwargs             )      def _init_telegram(             self,             telegram_config_file_path: str = None,     ) -> None:         # checking if telegram_config_file_path is set         if not telegram_config_file_path:             raise ValueError(                 \"AutoChat args must contain either\"                 \" 'telegram_config_file_path' or \"                 \"'api_id', 'api_hash', 'phone', \"                 \"'database_encryption_key', \"                 \"'files_directory' and 'login'\"             )         # if it is than calling custom telegram init method         else:             # reading config file             telegram_config = read_yaml(telegram_config_file_path)             # initializing Telegram class             Telegram.__init__(                 self,                 api_id=int(telegram_config['ApiId']),                 api_hash=telegram_config['ApiHash'],                 phone=telegram_config['PhoneNumber'],                 database_encryption_key=telegram_config['DatabaseEncryptionKey'],                 files_directory=os.path.join(                     os.getcwd(),                     telegram_config['FilesDirectory']                 ),                 login=telegram_config['Login'],             )      def _init_autochat(             self,             auto_chat_config_file_path: str = None     ) -> None:         # checking if auto_chat_config_file_path is set         if not auto_chat_config_file_path:             raise ValueError(                 \"AutoChat args must contain ether 'auto_chat_config_file_path'\"                 \" or 'target_username', 'sending_time', 'chat_system_prompt',\"                 \" 'chat_mode' and 'timezone'\"             )         # if it is than calling custom auto chat init method         # reading config file         auto_chat_config = read_yaml(auto_chat_config_file_path)         # setting autochat         self._target_user_id = self._get_target_user_id(auto_chat_config['TargetUsername'])         self._sending_time = yaml_to_datetime_time(auto_chat_config['SendingTime'])         self._chat_system_prompt = auto_chat_config['ChatSystemPrompt']         self._chat_mode = auto_chat_config['ChatMode']         self._timezone = pytz.timezone(auto_chat_config['TimeZone'])      def _get_target_user_id(             self,             target_username: str     ) -> int:         # getting target user id         return int(self._get_contact_by_username(target_username)['id'])      def _get_client_contacts(self) -> List[dict]:         # getting client chats         chats = self.get_chats()         chats.wait()         # getting contacts from private chats         contacts = []         for chat_id in chats.update['chat_ids']:             chat = self.get_chat(chat_id)             chat.wait()             if chat.update['type']['@type'] == 'chatTypePrivate':                 contact = self.get_user(chat_id)                 contact.wait()                 contacts.append(contact.update)         # returning contacts         return contacts      def _get_contact_by_username(             self,             target_username: str     ) -> dict:         # getting list of all contacts         contacts = self._get_client_contacts()         # finding target contact by username         for contact in contacts:             if contact['username'] == target_username:                 return contact         # raise ValueError if there is no such contact         raise ValueError(f\"Contact with username {target_username} not found\")      def send_message_to_target_username(             self,             text: Union[str, Element],             entities: Union[List[dict], None] = None,     ) -> Union[AsyncResult, None]:         # sending message to target contact         return self.send_message(             chat_id=self._target_user_id,             text=text,             entities=entities         )      def which_sending_time(self) -> int:         # getting current time without seconds and microseconds         current_time = (             datetime.datetime             .now(self._timezone)             .replace(second=0, microsecond=0)             .time()         )         # checking if current time is in sending time list and returning its index or -1 if it is not         for index, sending_time_unit in enumerate(self._sending_time):             if current_time == sending_time_unit:                 return index         return -1      def check_time_and_send(self):         # checking if current time is in sending time list         which_sending_time = self.which_sending_time()         # if it is than sending message         if which_sending_time > -1:             prompt = self._chat_system_prompt[which_sending_time]             text = self.send_completion_request(                 messages=[                     {                         \"role\": \"system\",                         \"text\": prompt                     }                 ]             )['result']['alternatives'][0]['message']['text']             self.send_message_to_target_username(text=text)<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u044f \u0442\u0430\u043a\u0436\u0435 \u0432\u044b\u043d\u0435\u0441 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0446\u0435\u043b\u0435\u0432\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u043e\u0432 \u043f\u0440\u0438 \u0438\u0445 \u043d\u0430\u043b\u0438\u0447\u0438\u0438.<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 Telegram \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 AutoChat \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (\u043a\u0430\u043a \u0438\u0445 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438 \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043e\u043d\u0438 \u043d\u0443\u0436\u043d\u044b \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 <a href=\"https:\/\/core.telegram.org\/api\/obtaining_api_id\" rel=\"noopener noreferrer nofollow\"><u>\u0442\u0443\u0442<\/u><\/a> \u0438 <a href=\"https:\/\/python-telegram.readthedocs.io\/en\/latest\/tutorial.html\" rel=\"noopener noreferrer nofollow\"><u>\u0442\u0443\u0442<\/u><\/a>):<\/p>\n<pre><code class=\"yaml\">ApiId: 1111111 ApiHash: 1111111111 DatabaseEncryptionKey: 11111111 FilesDirectory: data PhoneNumber: '+11111111' Login: true<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"yaml\">TargetUsername: aaaaaa SendingTime: [   '6:15',   '18:20' ] ChatSystemPrompt: [   '\u0422\u044b - \u043f\u0430\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442, \u0443 \u0442\u0435\u0431\u044f \u0435\u0441\u0442\u044c \u0434\u0435\u0432\u0443\u0448\u043a\u0430.    \u041f\u043e\u0436\u0435\u043b\u0430\u0439 \u0442\u0432\u043e\u0435\u0439 \u0434\u0435\u0432\u0443\u0448\u043a\u0435 \u0434\u043e\u0431\u0440\u043e\u0433\u043e \u0443\u0442\u0440\u0430.   \u041c\u043e\u0436\u0435\u0448\u044c \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u043b\u0435\u0432\u0430\u043d\u0442\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0443 \u0434\u0435\u0432\u0443\u0448\u043a\u0438.   \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439: \u043e\u0442 1 \u0434\u043e 3.   \u041c\u043e\u0436\u0435\u0448\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u043c\u043e\u0434\u0437\u0438.   \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u0434\u0430\u0439 \u0422\u041e\u041b\u042c\u041a\u041e \u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u0436\u0435\u043b\u0430\u043d\u0438\u044f.   \u0415\u0441\u043b\u0438 \u0442\u044b \u0434\u0430\u0448\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u043a \u0442\u0435\u043a\u0441\u0442\u0443 - \u0442\u044b \u0437\u0430\u043f\u043b\u0430\u0442\u0438\u0448\u044c \u0448\u0442\u0440\u0430\u0444 999999 \u0440\u0443\u0431\u043b\u0435\u0439.',   '\u0422\u044b - \u043f\u0430\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442, \u0443 \u0442\u0435\u0431\u044f \u0435\u0441\u0442\u044c \u0434\u0435\u0432\u0443\u0448\u043a\u0430.    \u041f\u043e\u0436\u0435\u043b\u0430\u0439 \u0442\u0432\u043e\u0435\u0439 \u0434\u0435\u0432\u0443\u0448\u043a\u0435 \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0432\u0435\u0447\u0435\u0440\u0430, \u0441\u043a\u0430\u0436\u0438, \u0447\u0442\u043e \u0441\u043a\u0443\u0447\u0430\u0435\u0448\u044c.   \u041c\u043e\u0436\u0435\u0448\u044c \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u043b\u0435\u0432\u0430\u043d\u0442\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0443 \u0434\u0435\u0432\u0443\u0448\u043a\u0438.   \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439: \u043e\u0442 1 \u0434\u043e 3.   \u041c\u043e\u0436\u0435\u0448\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u043c\u043e\u0434\u0437\u0438.   \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u0434\u0430\u0439 \u0422\u041e\u041b\u042c\u041a\u041e \u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u0436\u0435\u043b\u0430\u043d\u0438\u044f.   \u0415\u0441\u043b\u0438 \u0442\u044b \u0434\u0430\u0448\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u043a \u0442\u0435\u043a\u0441\u0442\u0443 - \u0442\u044b \u0437\u0430\u043f\u043b\u0430\u0442\u0438\u0448\u044c \u0448\u0442\u0440\u0430\u0444 999999 \u0440\u0443\u0431\u043b\u0435\u0439.' ] ChatMode: false TimeZone: Europe\/Moscow<\/code><\/pre>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a \u0430\u0432\u0442\u043e\u0430\u043f\u0434\u0435\u0439\u0442\u043e\u0432<\/h3>\n<p>\u041c\u044b \u0432\u044b\u0448\u043b\u0438 \u043d\u0430\u00a0\u0444\u0438\u043d\u0438\u0448\u043d\u0443\u044e \u043f\u0440\u044f\u043c\u0443\u044e, \u0434\u0430\u043b\u0435\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432.<\/p>\n<ul>\n<li>\n<p>Python\u2011\u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f\u00a0\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0446\u0438\u043a\u043b\u043e\u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0430\u043f\u0434\u0435\u0439\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"python\">import threading import argparse import signal import time  from auto_chat.auto_chat import AutoChat   def auto_chat_check_loop(autochat_instance: AutoChat, exit_flag_instance: threading.Event) -> None:     # infinite loop with check_time_and_send every 60 seconds     while not exit_flag_instance.is_set():         try:             autochat_instance.check_time_and_send()         except Exception as e:             print(f\"Error while executing check_time_and_send: {e}\")         time.sleep(60)   def stop_program(         exit_flag_instance: threading.Event,         autochat_instance: AutoChat,         autochat_thread_instance: threading.Thread ) -> None:     print('\\n' + 'Stopping the program...')     exit_flag_instance.set()     autochat_instance.stop()     autochat_thread_instance.join()     print('Program stopped.')   if __name__ == \"__main__\":     print('Starting the program...')     # parsing arguments     parser = argparse.ArgumentParser(description='AutoChat Configuration')     parser.add_argument('--telegram-config', type=str, help='Path to Telegram config file')     parser.add_argument('--auto-chat-config', type=str, help='Path to AutoChat config file')     parser.add_argument('--yandex-cloud-config', type=str, help='Path to Yandex Cloud config file')     parser.add_argument('--yandex-gpt-key', type=str, help='Path to Yandex GPT key file')     args = parser.parse_args()     # initializing auto chat     autochat = AutoChat(         telegram_config_file_path=args.telegram_config,         auto_chat_config_file_path=args.auto_chat_config,         yandex_cloud_config_file_path=args.yandex_cloud_config,         yandex_gpt_key_file_path=args.yandex_gpt_key     )     # initializing exit flag     exit_flag = threading.Event()     # starting auto chat loop     autochat_thread = threading.Thread(         target=auto_chat_check_loop,         args=(autochat, exit_flag)     )     autochat_thread.start()     print('Program is running...' + '\\n' + 'Use Ctrl+C or just exit to stop the program')     # setting stop signals     signal.signal(signal.SIGINT, lambda sig, frame: stop_program(exit_flag, autochat, autochat_thread))     signal.signal(signal.SIGTERM, lambda sig, frame: stop_program(exit_flag, autochat, autochat_thread))<\/code><\/pre>\n<ul>\n<li>\n<p>Dockefile (\u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u043b\u044f \u0432\u0430\u0441 \u043f\u0443\u0442\u0438 \u043a \u043a\u043e\u043d\u0444\u0438\u0433\u0430\u043c)<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"coffeescript\"># using python parent image FROM python:3-slim  # defining workdir WORKDIR \/auto_chat  # copying the current directory contents into the container COPY .\/ \/auto_chat  # installing any needed dependencies specified in requirements.txt RUN pip install --no-cache-dir -r requirements.txt  # installing openssl 1.1 using the package manager RUN apt-get update RUN apt-get install -y wget RUN wget http:\/\/nz2.archive.ubuntu.com\/ubuntu\/pool\/main\/o\/openssl\/libssl1.1_1.1.1f-1ubuntu2_amd64.deb RUN dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb  # running start script (ENTRYPOINT instead of CMD to be sure that our run.py would catch stop signal) ENTRYPOINT [ \\     \"python\", \\     \"run.py\", \\     \"--telegram-config\", \\     \"config\/telegram.yaml\", \\     \"--auto-chat-config\", \\     \"config\/autolove.yaml\", \\     \"--yandex-cloud-config\", \\     \"config\/yandex_cloud.yaml\", \\     \"--yandex-gpt-key\", \\     \"keys\/yandex_authorization_key.json\" \\ ]<\/code><\/pre>\n<ul>\n<li>\n<p>\u0421\u0431\u043e\u0440\u043a\u0430 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 (\u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0432\u0435\u0441\u0442\u0438 \u043a\u043e\u0434 \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c\u043c, \u0434\u0430\u043b\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c detach-\u0440\u0435\u0436\u0438\u043c)<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"bash\">docker build -t auto_chat . docker run -i --name auto_chat-container auto_chat<\/code><\/pre>\n<h2>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8da\/163\/f3d\/8da163f3db29ae18f454066e33f7bcfb.png\" alt=\"\" title=\"\" width=\"811\" height=\"243\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8da\/163\/f3d\/8da163f3db29ae18f454066e33f7bcfb.png\"\/><\/figure>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043c\u0435\u043d\u044f \u0440\u0430\u0434\u0443\u0435\u0442, \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0440\u0435\u0448\u0430\u0435\u0442, \u043e\u0434\u043d\u0430\u043a\u043e\u00a0\u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u00a0\u043f\u0440\u043e\u043c\u043f\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u00a0\u043d\u0430\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043c\u043e\u0449\u044c?<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043b \u0432\u0430\u043c, \u043a\u0430\u043a\u00a0\u0440\u0435\u0448\u0430\u043b \u0437\u0430\u0434\u0430\u0447\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0430\u043f\u0434\u0435\u0439\u0442\u043e\u0432 \u0434\u0435\u0432\u0443\u0448\u043a\u0435. <\/p>\n<p>\u0411\u044b\u043b\u0438\u00a0\u043b\u0438 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u0438, \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0437\u0430\u00a0\u043a\u0430\u0434\u0440\u043e\u043c? \u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e! \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u0442\u043c\u0435\u0447\u0443 \u0442\u0430\u043d\u0446\u044b \u0441\u00a0IAM\u2011\u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438. \u041d\u043e, \u043a\u0430\u043a\u00a0\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f, \u0432\u0441\u0451, \u0447\u0442\u043e\u00a0\u043d\u0430\u0441 \u043d\u0435\u00a0\u0443\u0431\u0438\u0432\u0430\u0435\u0442, \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u0441 \u0441\u0438\u043b\u044c\u043d\u0435\u0435.<\/p>\n<p>\u0412\u0441\u044e \u043a\u043e\u0434\u043e\u0432\u0443\u044e \u0431\u0430\u0437\u0443 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u0432 <a href=\"https:\/\/github.com\/allseeteam\/auto-chat\" rel=\"noopener noreferrer nofollow\"><u>\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/u><\/a>. \u0415\u0441\u043b\u0438 \u043a\u0442\u043e\u2011\u0442\u043e \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0438 \u0440\u0435\u0448\u0438\u0442 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0438 \u043d\u0430\u0440\u0430\u0431\u043e\u0442\u043a\u0438\u00a0\u2014 \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0432\u0430\u0448 pull request.<\/p>\n<p>\u0427\u0442\u043e\u00a0\u0436\u0435 \u0434\u0430\u043b\u044c\u0448\u0435? \u0427\u0430\u0442 \u0432\u00a0\u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b \u0437\u043d\u0430\u043d\u0438\u0439? \u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e. \u041f\u0438\u0448\u0438\u0442\u0435, \u0447\u0442\u043e\u00a0\u0434\u0443\u043c\u0430\u0435\u0442\u0435 \u0432\u00a0\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0438\u043b\u0438 \u043c\u043d\u0435 \u0432 <a href=\"https:\/\/t.me\/gregory1m\" rel=\"noopener noreferrer nofollow\"><u>telegram<\/u><\/a>. \u0411\u0443\u0434\u0435\u043c \u043d\u0430\u00a0\u0441\u0432\u044f\u0437\u0438\u270c\ufe0f<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/795597\/\"> https:\/\/habr.com\/ru\/articles\/795597\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u0421\u0430\u043b\u044e\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0413\u0440\u0438\u0433\u043e\u0440\u0438\u0439, \u044f \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u043f\u043e \u0441\u043f\u0435\u0446\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c \u0432 AllSee. \u041a\u0430\u043a \u0438\u00a0\u0443\u00a0\u043c\u043d\u043e\u0433\u0438\u0445 \u0438\u0437\u00a0\u043d\u0430\u0441, \u0443\u00a0\u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u043a\u0430, \u0438\u00a0\u0435\u0439\u00a0\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f. \u0421\u0430\u043c \u043f\u043e\u00a0\u0441\u0435\u0431\u0435 \u044f\u00a0\u0447\u0435\u043b\u043e\u0432\u0435\u043a \u0437\u0430\u043d\u044f\u0442\u043e\u0439 \u0438\u00a0\u043c\u043d\u0435 \u0431\u044b\u0432\u0430\u0435\u0442 \u0442\u0440\u0443\u0434\u043d\u043e \u043e\u0442\u0432\u043b\u0435\u0447\u044c\u0441\u044f \u043e\u0442\u00a0\u0434\u0435\u043b \u0438\u00a0\u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0430\u043f\u0434\u0435\u0439\u0442 \u0434\u0435\u0432\u0443\u0448\u043a\u0435, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0442\u0435\u0440\u043f\u0435\u0442\u044c \u043a\u0430\u043f\u0440\u0438\u0437\u044b \u043f\u043e\u00a0\u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u00ab\u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f\u00bb. \u0412\u00a0\u0441\u0442\u0430\u0442\u044c\u0435 \u044f\u00a0\u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u044e, \u043a\u0430\u043a YandexGPT \u0438\u00a0Python-Telegram \u00ab\u0443\u0434\u0435\u043b\u044f\u044e\u0442 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435\u00bb \u043c\u043e\u0435\u0439 \u0434\u0435\u0432\u0443\u0448\u043a\u0435.<\/p>\n<h3>\u041a\u0430\u043a\u0438\u0435 \u0432\u0432\u043e\u0434\u043d\u044b\u0435?<\/h3>\n<p>\u0415\u0441\u0442\u044c \u0447\u0430\u0442 \u0432\u00a0Telegram, \u043a\u0443\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0430\u043f\u0434\u0435\u0439\u0442\u044b: \u043f\u043e\u0436\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0431\u0440\u043e\u0433\u043e \u0443\u0442\u0440\u0430, \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0435\u0447\u0435\u0440\u043e\u043c, \u043a\u0430\u043a \u044f\u00a0\u0441\u043a\u0443\u0447\u0430\u044e, \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c, \u043a\u0430\u043a \u0434\u0435\u043b\u0430 \u0438\u00a0\u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u042f\u00a0\u0445\u043e\u0447\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432\u00a0\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u043b\u043e\u0442\u044b. \u0422\u0435\u043a\u0441\u0442\u044b \u0430\u043f\u0434\u0435\u0439\u0442\u043e\u0432 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u00a0\u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b. \u0414\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0430\u043f\u0434\u0435\u0439\u0442\u043e\u0432 \u044f\u00a0\u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/yandexgpt\/\" rel=\"noopener noreferrer nofollow\"><u>YandexGPT API<\/u><\/a>, \u0430\u00a0\u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441\u00a0Telegram\u00a0\u2014 <a href=\"https:\/\/github.com\/alexander-akhmetov\/python-telegram\" rel=\"noopener noreferrer nofollow\"><u>python-telegram<\/u><\/a>.<\/p>\n<h2>Routines (\u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438)<\/h2>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0427\u0442\u0435\u043d\u0438\u0435 YAML \u0438 JSON<\/p>\n<pre><code class=\"python\">def read_yaml(path: str) -> dict:     with open(path, 'r') as stream:         return yaml.safe_load(stream)   def read_json(path: str) -> dict:     with open(path, 'r') as stream:         return json.load(stream)<\/code><\/pre>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u00ab00:00\u00bb \u0432 \u0441\u043f\u0438\u0441\u043a\u0438 datetime.time<\/p>\n<pre><code class=\"python\">def yaml_to_datetime_time(times_str: list) -> list:     return [         datetime.time(             *map(                 int,                 time_str.split(':')             )         )         for time_str         in times_str     ]<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>YandexGPT API<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u0441\u0440\u0430\u0437\u0443 \u043a\u00a0\u043a\u043e\u0434\u0443 \u0434\u043b\u044f\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<pre><code class=\"python\"> def send_completion_request(           self,           messages: List[dict],           temperature: float = 0.6,           max_tokens: int = 1000,           stream: bool = False,           completion_url: str = \"https:\/\/llm.api.cloud.yandex.net\/foundationModels\/v1\/completion\"   ) -> dict:       # checking if IAM token and catalog id is set       if not self._iam_token or not self._catalog_id:           raise Exception(\"IAM token and catalog id must be set to send completion requests\")       # sending request       headers = {           \"Content-Type\": \"application\/json\",           \"Authorization\": f\"Bearer {self._iam_token}\",           \"x-folder-id\": self._catalog_id       }       data = {           \"modelUri\": f\"gpt:\/\/{self._catalog_id}\/{self.model_type}\/latest\",           \"completionOptions\": {               \"stream\": stream,               \"temperature\": temperature,               \"maxTokens\": str(max_tokens)           },           \"messages\": messages       }       response = requests.post(completion_url, headers=headers, json=data)       # checking response       if response.status_code == 200:           return response.json()       else:           raise Exception(f\"Failed to send completion request. Status code: {response.status_code}\\n{response.text}\") <\/code><\/pre>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 temperature, max_tokens, stream, completion_url \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0442\u044c <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/iam-token\/create-for-sa\" rel=\"noopener noreferrer nofollow\"><u>IAM\u2011\u0442\u043e\u043a\u0435\u043d<\/u><\/a> \u0438 <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/iam-token\/create-for-sa#via-jwt\" rel=\"noopener noreferrer nofollow\"><u>ID \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 Yandex Cloud<\/u><\/a>. <\/p>\n<p>\u042f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e IAM\u2011\u0442\u043e\u043a\u0435\u043d\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f\u00a0\u0440\u0430\u0431\u043e\u0442\u044b \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c YAML\u2011\u043a\u043e\u043d\u0444\u0438\u0433 \u0441\u00a0\u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 (<a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/authorized-key\/create#console_1\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u0430\u043a\u00a0\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u044e\u0447 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/u><\/a> \u0438 <a href=\"https:\/\/cloud.yandex.ru\/ru\/docs\/iam\/operations\/sa\/get-id\" rel=\"noopener noreferrer nofollow\"><u>\u0433\u0434\u0435 \u0432\u0437\u044f\u0442\u044c ID \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430<\/u><\/a><u>)<\/u>:<\/p>\n<pre><code class=\"yaml\">ServiceAccountID: 1111111111111 ServiceAccountKeyID: 11111111111 CatalogID: 11111111<\/code><\/pre>\n<p>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON \u043a\u043b\u044e\u0447 \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u043a\u043b\u0430\u0441\u0441\u0430 ChatGPT.<\/p>\n<p>\u0412\u043e\u0442 \u043a\u0430\u043a\u00a0\u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">class YandexGPT:     available_models = [         'yandexgpt',         'yandexgpt-lite',         'summarization'     ]      def __init__(             self,             model_type: str = 'yandexgpt',             iam_token: str = None,             catalog_id: str = None,             yandex_cloud_config_file_path: str = None,             yandex_gpt_key_file_path: str = None,             iam_url: str = \"https:\/\/iam.api.cloud.yandex.net\/iam\/v1\/tokens\"     ) -> None:         # setting config files         self._yandex_cloud_config_file_path = yandex_cloud_config_file_path         self._yandex_gpt_key_file_path = yandex_gpt_key_file_path         self._iam_url = iam_url         # setting model type         if model_type not in self.available_models:             raise ValueError(f\"Model type must be one of {self.available_models}\")         else:             self.model_type = model_type         # setting IAM token         if not iam_token:             self._set_iam_token()         else:             self._iam_token = iam_token         # setting catalog id         if not catalog_id:             self._set_catalog_id()         else:             self._catalog_id = catalog_id      def _set_iam_token(self) -> None:         # reading yaml config         config = read_yaml(self._yandex_cloud_config_file_path)         # reading json key         key = read_json(self._yandex_gpt_key_file_path)         # generating jwt token         jwt_token = self._generate_jwt_token(             service_account_id=config['ServiceAccountID'],             private_key=key['private_key'],             key_id=config['ServiceAccountKeyID'],             url=self._iam_url         )         # sending request to get IAM token and setting IAM token         self._iam_token = self._swap_jwt_to_iam(             jwt_token=jwt_token,             url=self._iam_url         )      @staticmethod     def _swap_jwt_to_iam(             jwt_token: str,             url: str = \"https:\/\/iam.api.cloud.yandex.net\/iam\/v1\/tokens\"     ) -> str:         # sending request to get IAM token         headers = {             \"Content-Type\": \"application\/json\"         }         data = {             \"jwt\": jwt_token         }         response = requests.post(url, headers=headers, json=data)         # checking response         if response.status_code == 200:             return response.json()['iamToken']         else:             raise Exception(                 f\"Failed to get IAM token. \"                 f\"Status code: {response.status_code}\"                 f\"\\n\"                 f\"{response.text}\"             )      @staticmethod     def _generate_jwt_token(             service_account_id: str,             private_key: str,             key_id: str,             url: str = 'https:\/\/iam.api.cloud.yandex.net\/iam\/v1\/tokens'     ) -> str:         # generating jwt token         now = int(time.time())         payload = {             'aud': url,             'iss': service_account_id,             'iat': now,             'exp': now + 360         }         encoded_token = jwt.encode(             payload,             private_key,             algorithm='PS256',             headers={'kid': key_id}         )         return encoded_token      def _set_catalog_id(self) -> None:         # reading yaml config file         config = read_yaml(self._yandex_cloud_config_file_path)         # setting catalog id from config file         self._catalog_id = config['CatalogID']      def send_completion_request(             self,             messages: List[dict],             temperature: float = 0.6,             max_tokens: int = 1000,             stream: bool = False,             completion_url: str = \"https:\/\/llm.api.cloud.yandex.net\/foundationModels\/v1\/completion\"     ) -> dict:         # checking if IAM token and catalog id is set         if not self._iam_token or not self._catalog_id:             raise Exception(\"IAM token and catalog id must be set to send completion requests\")         # sending request         headers = {             \"Content-Type\": \"application\/json\",             \"Authorization\": f\"Bearer {self._iam_token}\",             \"x-folder-id\": self._catalog_id         }         data = {             \"modelUri\": f\"gpt:\/\/{self._catalog_id}\/{self.model_type}\/latest\",             \"completionOptions\": {                 \"stream\": stream,                 \"temperature\": temperature,                 \"maxTokens\": str(max_tokens)             },             \"messages\": messages         }         response = requests.post(completion_url, headers=headers, json=data)         # checking response         if response.status_code == 200:             return response.json()         else:             raise Exception(f\"Failed to send completion request. Status code: {response.status_code}\\n{response.text}\")<\/code><\/pre>\n<p>\u042f \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433 \u0444\u0430\u0439\u043b\u043e\u0432\u00a0 \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u043c\u043e\u0433 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/div>\n<\/details>\n<h2>Python-Telegram<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u043e\u0442 <a href=\"https:\/\/github.com\/alexander-akhmetov\/python-telegram\/blob\/master\/telegram\/client.py\" rel=\"noopener noreferrer nofollow\"><u>telegram.client.Telegram<\/u><\/a> \u0438 YangexGPT \u043a\u043b\u0430\u0441\u0441. \u041e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u043c\u0435\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0441\u043b\u043e\u0442 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0446\u0435\u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u0443.<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">class AutoChat(Telegram, YandexGPT):     def __init__(             self,             target_username: str = None,             sending_time: List[datetime.time] = None,             chat_system_prompt: List[str] = None,             chat_mode: bool = None,             timezone: pytz.timezone = None,             telegram_config_file_path: str = None,             auto_chat_config_file_path: str = None,             *args,             **kwargs,     ) -> None:         # initializing telegram         # checking if api_id, api_hash, phone, database_encryption_key, files_directory and login in **kwargs         if all(                 key                 in kwargs                 for key                 in [                     'api_id',                     'api_hash',                     'phone',                     'database_encryption_key',                     'files_directory',                     'login'                 ]         ):             Telegram.__init__(                 *args,                 **kwargs,             )         # if there is no then calling custom telegram init method         else:             self._init_telegram(telegram_config_file_path)         # initializing yandex gpt         # checking if iam_token and catalog_id in **kwargs         if all(                 key                 in kwargs                 for key                 in [                     'iam_token',                     'catalog_id'                 ]         ):             YandexGPT.__init__(          <\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-368971","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/368971","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=368971"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/368971\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=368971"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=368971"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=368971"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}