From 6d9a1247a90965c2a9ba02b09e8442a691788709 Mon Sep 17 00:00:00 2001 From: Sigmun Date: Fri, 31 May 2024 09:35:19 +0000 Subject: [PATCH] Add silent group conversation listening feature --- .env.example | 1 + bot/main.py | 1 + bot/telegram_bot.py | 61 +++++++++++++++++++++++++-------------------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/.env.example b/.env.example index d3d368d0..3736f244 100644 --- a/.env.example +++ b/.env.example @@ -47,6 +47,7 @@ ALLOWED_TELEGRAM_USER_IDS=USER_ID_1,USER_ID_2 # IMAGE_FORMAT=document # VISION_DETAIL="low" # GROUP_TRIGGER_KEYWORD="" +# GROUP_LISTEN_CONVERSATION=false # IGNORE_GROUP_TRANSCRIPTIONS=true # IGNORE_GROUP_VISION=true # TTS_MODEL="tts-1" diff --git a/bot/main.py b/bot/main.py index 8e0118d2..3e9f5aff 100644 --- a/bot/main.py +++ b/bot/main.py @@ -92,6 +92,7 @@ def main(): 'ignore_group_transcriptions': os.environ.get('IGNORE_GROUP_TRANSCRIPTIONS', 'true').lower() == 'true', 'ignore_group_vision': os.environ.get('IGNORE_GROUP_VISION', 'true').lower() == 'true', 'group_trigger_keyword': os.environ.get('GROUP_TRIGGER_KEYWORD', ''), + 'group_listen_conversation': os.environ.get('GROUP_LISTEN_CONVERSATION', False), 'token_price': float(os.environ.get('TOKEN_PRICE', 0.002)), 'image_prices': [float(i) for i in os.environ.get('IMAGE_PRICES', "0.016,0.018,0.02").split(",")], 'vision_token_price': float(os.environ.get('VISION_TOKEN_PRICE', '0.01')), diff --git a/bot/telegram_bot.py b/bot/telegram_bot.py index 4cf9fa4c..bf143546 100644 --- a/bot/telegram_bot.py +++ b/bot/telegram_bot.py @@ -659,7 +659,7 @@ async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): user_id = update.message.from_user.id prompt = message_text(update.message) self.last_message[chat_id] = prompt - + answer = True if is_group_chat(update): trigger_keyword = self.config['group_trigger_keyword'] @@ -676,12 +676,16 @@ async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): logging.info('Message is a reply to the bot, allowing...') else: logging.warning('Message does not start with trigger keyword, ignoring...') - return + if not self.config['group_listen_conversation']: + return + else: + answer = False try: total_tokens = 0 + # logging.info(msg="#### before if stream") - if self.config['stream']: + if self.config['stream'] and answer: await update.effective_message.reply_chat_action( action=constants.ChatAction.TYPING, message_thread_id=get_thread_id(update) @@ -693,7 +697,6 @@ async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): sent_message = None backoff = 0 stream_chunk = 0 - async for content, tokens in stream_response: if is_direct_result(content): return await handle_direct_result(self.config, update, content) @@ -708,7 +711,7 @@ async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): stream_chunk += 1 try: await edit_message_with_retry(context, chat_id, str(sent_message.message_id), - stream_chunks[-2]) + stream_chunks[-2]) except: pass try: @@ -727,7 +730,7 @@ async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): try: if sent_message is not None: await context.bot.delete_message(chat_id=sent_message.chat_id, - message_id=sent_message.message_id) + message_id=sent_message.message_id) sent_message = await update.effective_message.reply_text( message_thread_id=get_thread_id(update), reply_to_message_id=get_reply_to_message_id(self.config, update), @@ -742,7 +745,7 @@ async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): try: use_markdown = tokens != 'not_finished' await edit_message_with_retry(context, chat_id, str(sent_message.message_id), - text=content, markdown=use_markdown) + text=content, markdown=use_markdown) except RetryAfter as e: backoff += 5 @@ -765,38 +768,41 @@ async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): total_tokens = int(tokens) else: + # logging.info(msg="#### before reply") async def _reply(): nonlocal total_tokens response, total_tokens = await self.openai.get_chat_response(chat_id=chat_id, query=prompt) + if answer: + if is_direct_result(response): + return await handle_direct_result(self.config, update, response) - if is_direct_result(response): - return await handle_direct_result(self.config, update, response) - - # Split into chunks of 4096 characters (Telegram's message limit) - chunks = split_into_chunks(response) + # Split into chunks of 4096 characters (Telegram's message limit) + chunks = split_into_chunks(response) - for index, chunk in enumerate(chunks): - try: - await update.effective_message.reply_text( - message_thread_id=get_thread_id(update), - reply_to_message_id=get_reply_to_message_id(self.config, - update) if index == 0 else None, - text=chunk, - parse_mode=constants.ParseMode.MARKDOWN - ) - except Exception: + for index, chunk in enumerate(chunks): try: await update.effective_message.reply_text( message_thread_id=get_thread_id(update), reply_to_message_id=get_reply_to_message_id(self.config, update) if index == 0 else None, - text=chunk + text=chunk, + parse_mode=constants.ParseMode.MARKDOWN ) - except Exception as exception: - raise exception + except Exception: + try: + await update.effective_message.reply_text( + message_thread_id=get_thread_id(update), + reply_to_message_id=get_reply_to_message_id(self.config, + update) if index == 0 else None, + text=chunk + ) + except Exception as exception: + raise exception + else: + logging.info(f"Response would have been {response}") await wrap_with_indicator(update, context, _reply, constants.ChatAction.TYPING) - + # logging.info(msg="#### before add_chat_request_to_usage_tracker") add_chat_request_to_usage_tracker(self.usage, self.config, user_id, total_tokens) except Exception as e: @@ -973,10 +979,11 @@ async def _send_inline_query_response(): # Edit the original message with the generated content await edit_message_with_retry(context, chat_id=None, message_id=inline_message_id, text=text_content, is_inline=True) - + logging.debug("before sendind no stream answer") await wrap_with_indicator(update, context, _send_inline_query_response, constants.ChatAction.TYPING, is_inline=True) + logging.debug("before add_chat_request_to_usage_tracker") add_chat_request_to_usage_tracker(self.usage, self.config, user_id, total_tokens) except Exception as e: