diff --git a/README.md b/README.md index 6819475a..f94d3e83 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@

-The ChatGPT Telegram Bot is a powerful Telegram bot that utilizes the latest GPT models, including GPT3.5, GPT4, GPT4 Turbo, GPT4 Vision, DALLE 3, Groq Mixtral-8x7b/LLaMA2-70b and the official Claude2.1/Claude3 opus/sonnet API. It enables users to engage in efficient conversations and information searches on Telegram. +The ChatGPT Telegram Bot is a powerful Telegram bot that utilizes the latest GPT models, including GPT3.5, GPT4, GPT4 Turbo, GPT4 Vision, DALL·E 3, Groq Mixtral-8x7b/LLaMA2-70b and the official Claude2.1/Claude3 opus/sonnet API. It enables users to engage in efficient conversations and information searches on Telegram. ## ✨ Features -- **Multiple AI Models**: Integrates a variety of AI models including GPT3.5, GPT4, GPT4 Turbo, GPT4 Vision, DALLE 3, and Claude2.1 API. +- **Multiple AI Models**: Integrates a variety of AI models including GPT3.5, GPT4, GPT4 Turbo, GPT4 Vision, DALL·E 3 and Claude2.1 API. - **Powerful Online Search**: Supports online search with DuckDuckGo and Google, providing users with a robust information retrieval tool. - **User-friendly Interface**: Allows flexible model switching within the chat window and supports streaming output for a typewriter-like effect. - **Efficient Message Processing**: Asynchronously processes messages, answers questions in a multi-threaded manner, supports isolated dialogues, and provides unique dialogues for different users. @@ -45,6 +45,7 @@ The ChatGPT Telegram Bot is a powerful Telegram bot that utilizes the latest GPT | CUSTOM_MODELS | Set up a list of custom model name. Connect the model name with a comma (','). | No | | GOOGLE_AI_API_KEY | Google AI offical API key. | No | | GROQ_API_KEY | Groq AI offical API key. | No | +| CHAT_MODE | Introduce multi-user mode, different users' configurations are not shared, the default is that each user has the same configuration, and the CHAT_MODE environment variable is used to control the configuration behavior. When CHAT_MODE is global, all users share the configuration. When CHAT_MODE is multiusers, user configurations are independent of each other. | No | ## Zeabur Remote Deployment (Recommended) diff --git a/bot.py b/bot.py index 024107e5..dcddc0c9 100644 --- a/bot.py +++ b/bot.py @@ -178,6 +178,7 @@ async def getChatGPT(update, context, title, robot, message, chatid, messageid): ) messageid = message.message_id pass_history = config.PASS_HISTORY + image_has_send = 0 try: for data in robot.ask_stream(text, convo_id=str(chatid), pass_history=pass_history): @@ -193,6 +194,10 @@ async def getChatGPT(update, context, title, robot, message, chatid, messageid): tmpresult = claude_replace(tmpresult) if "🌐" in data: tmpresult = data + history = robot.conversation[str(chatid)] + if history[-1]['role'] == "function" and history[-1]['name'] == "generate_image" and not image_has_send: + await context.bot.send_photo(chat_id=chatid, photo=history[-1]['content'], reply_to_message_id=messageid) + image_has_send = 1 modifytime = modifytime + 1 if (modifytime % Frequency_Modification == 0 and lastresult != tmpresult) or "🌐" in data: await context.bot.edit_message_text(chat_id=chatid, message_id=messageid, text=escape(tmpresult), parse_mode='MarkdownV2', disable_web_page_preview=True, read_timeout=time_out, write_timeout=time_out, pool_timeout=time_out, connect_timeout=time_out) @@ -214,64 +219,6 @@ async def getChatGPT(update, context, title, robot, message, chatid, messageid): else: await context.bot.edit_message_text(chat_id=chatid, message_id=messageid, text=escape(tmpresult), parse_mode='MarkdownV2', disable_web_page_preview=True, read_timeout=time_out, write_timeout=time_out, pool_timeout=time_out, connect_timeout=time_out) -@decorators.GroupAuthorization -@decorators.Authorization -async def image(update, context): - if update.edited_message: - message = update.edited_message.text if config.NICK is None else update.edited_message.text[botNicKLength:].strip() if update.edited_message.text[:botNicKLength].lower() == botNick else None - rawtext = update.edited_message.text - chatid = update.edited_message.chat_id - messageid = update.edited_message.message_id - else: - message = update.message.text if config.NICK is None else update.message.text[botNicKLength:].strip() if update.message.text[:botNicKLength].lower() == botNick else None - rawtext = update.message.text - chatid = update.message.chat_id - messageid = update.message.message_id - print("\033[32m", update.effective_user.username, update.effective_user.id, rawtext, "\033[0m") - - if (len(context.args) == 0): - message = ( - f"格式错误哦~,示例:\n\n" - f"`/pic 一只可爱长毛金渐层趴在路由器上`\n\n" - f"👆点击上方命令复制格式\n\n" - ) - await context.bot.send_message(chat_id=chatid, text=escape(message), parse_mode='MarkdownV2', disable_web_page_preview=True) - return - message = ' '.join(context.args) - result = "" - robot = config.dallbot - text = message - message = await context.bot.send_message( - chat_id=chatid, - text="生成中💭", - parse_mode='MarkdownV2', - reply_to_message_id=messageid, - ) - start_messageid = message.message_id - - try: - for data in robot.generate(text): - result = data - await context.bot.delete_message(chat_id=chatid, message_id=start_messageid) - await context.bot.send_photo(chat_id=chatid, photo=result, reply_to_message_id=messageid) - except Exception as e: - print('\033[31m') - print(e) - print('\033[0m') - if "You exceeded your current quota, please check your plan and billing details." in str(e): - print("OpenAI api 已过期!") - result += "OpenAI api 已过期!" - config.API = '' - elif "content_policy_violation" in str(e) or "violates OpenAI's policies" in str(e): - result += "当前 prompt 未能成功生成图片,可能因为版权,政治,色情,暴力,种族歧视等违反 OpenAI 的内容政策😣,换句话试试吧~" - elif "server is busy" in str(e): - result += "服务器繁忙,请稍后再试~" - elif "billing_hard_limit_reached" in str(e): - result += "当前账号余额不足~" - else: - result += f"`{e}`" - await context.bot.edit_message_text(chat_id=chatid, message_id=start_messageid, text=escape(result), parse_mode='MarkdownV2', disable_web_page_preview=True) - import time async def delete_message(update, context, messageid, delay=10): time.sleep(delay) @@ -440,7 +387,6 @@ async def post_init(application: Application) -> None: BotCommand('en2zh', 'translate to Chinese'), BotCommand('zh2en', 'translate to English'), BotCommand('search', 'search Google or duckduckgo'), - BotCommand('pic', 'Generate image'), BotCommand('start', 'Start the bot'), ]) @@ -480,7 +426,6 @@ async def process_update(update): ) application.add_handler(CommandHandler("start", start)) - application.add_handler(CommandHandler("pic", image, block = False)) application.add_handler(CommandHandler("search", lambda update, context: command_bot(update, context, prompt="search: ", has_command="search"))) application.add_handler(CallbackQueryHandler(button_press)) application.add_handler(CommandHandler("reset", reset_chat)) @@ -489,7 +434,7 @@ async def process_update(update): application.add_handler(CommandHandler("info", info)) application.add_handler(InlineQueryHandler(inlinequery)) application.add_handler(MessageHandler(filters.Document.PDF | filters.Document.TXT | filters.Document.DOC, handle_pdf)) - application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, lambda update, context: command_bot(update, context, prompt=None, has_command=False))) + application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, lambda update, context: command_bot(update, context, prompt=None, has_command=False), block = False)) application.add_handler(MessageHandler(filters.CAPTION & filters.PHOTO & ~filters.COMMAND, lambda update, context: command_bot(update, context, prompt=None, has_command=False))) application.add_handler(MessageHandler(~filters.CAPTION & filters.PHOTO & ~filters.COMMAND, handle_photo)) application.add_handler(MessageHandler(filters.COMMAND, unknown)) diff --git a/config.py b/config.py index 953e03cb..2e4aaab8 100644 --- a/config.py +++ b/config.py @@ -6,7 +6,7 @@ from datetime import datetime from ModelMerge.utils import prompt from ModelMerge.utils.scripts import get_encode_image -from ModelMerge.models import chatgpt, claude, groq, claude3, gemini, dalle3 +from ModelMerge.models import chatgpt, claude, groq, claude3, gemini from ModelMerge.models.config import PLUGINS from telegram import InlineKeyboardButton @@ -108,16 +108,15 @@ def update_info_message(user_id = None): f"**WEB_HOOK:** `{WEB_HOOK}`\n\n" ) -ChatGPTbot, translate_bot, dallbot, claudeBot, claude3Bot, groqBot, gemini_Bot = None, None, None, None, None, None, None +ChatGPTbot, translate_bot, claudeBot, claude3Bot, groqBot, gemini_Bot = None, None, None, None, None, None, None def update_ENGINE(data = None, chat_id=None): - global Users, ChatGPTbot, translate_bot, dallbot, claudeBot, claude3Bot, groqBot, gemini_Bot + global Users, ChatGPTbot, translate_bot, claudeBot, claude3Bot, groqBot, gemini_Bot if data: Users.set_config(chat_id, "engine", data) engine = Users.get_config(chat_id, "engine") if API: ChatGPTbot = chatgpt(api_key=f"{API}", engine=engine, system_prompt=systemprompt, temperature=temperature) translate_bot = chatgpt(api_key=f"{API}", engine=engine, system_prompt=systemprompt, temperature=temperature) - dallbot = dalle3(api_key=f"{API}") if CLAUDE_API and "claude-2.1" in engine: claudeBot = claude(api_key=f"{CLAUDE_API}", engine=engine, system_prompt=claude_systemprompt, temperature=temperature) if CLAUDE_API and "claude-3" in engine: @@ -289,11 +288,11 @@ def update_model_buttons(): return buttons def get_plugins_status(item): - return "✅" if PLUGINS[item] else "☑️" + return "✅ " if PLUGINS[item] else "☑️ " PASS_HISTORY = (os.environ.get('PASS_HISTORY', "True") == "False") == False def update_first_buttons_message(): - history = "✅" if PASS_HISTORY else "☑️" + history = "✅ " if PASS_HISTORY else "☑️ " if LANGUAGE == "Simplified Chinese": lang = "zh" @@ -305,18 +304,10 @@ def update_first_buttons_message(): [ InlineKeyboardButton(strings["button_change_model"][lang], callback_data="MODEL"), InlineKeyboardButton(strings['button_language'][lang], callback_data="language"), - InlineKeyboardButton(f"{history} {strings['button_history'][lang]}", callback_data="PASS_HISTORY"), + InlineKeyboardButton(f"{history}{strings['button_history'][lang]}", callback_data="PASS_HISTORY"), ], ] PLUGINS_LIST = list(PLUGINS.keys()) buttons = create_buttons(PLUGINS_LIST, plugins_status=True, lang=lang, button_text=strings) first_buttons.extend(buttons) - # [ - # InlineKeyboardButton(f"{get_plugins_status('SEARCH')}{strings['SEARCH'][lang]}", callback_data='SEARCH'), - # InlineKeyboardButton(f"{get_plugins_status('DATE')}{strings['DATE'][lang]}", callback_data='DATE'), - # ], - # [ - # InlineKeyboardButton(f"{get_plugins_status('URL')}{strings['URL'][lang]}", callback_data='URL'), - # InlineKeyboardButton(f"{get_plugins_status('VERSION')}{strings['VERSION'][lang]}", callback_data='VERSION'), - # ], return first_buttons \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index ad799a1e..930686d0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,6 @@ pytz python-dotenv md2tgmd==0.1.9 fake_useragent -ModelMerge==0.4.2 +ModelMerge==0.4.5 oauth2client==3.0.0 python-telegram-bot[webhooks,rate-limiter]==21.0.1 \ No newline at end of file diff --git a/utils/i18n.py b/utils/i18n.py index 66739254..973c3750 100644 --- a/utils/i18n.py +++ b/utils/i18n.py @@ -47,4 +47,8 @@ "zh": "旅行信息", "en": "Travel info", }, + "IMAGE": { + "zh": "DALL·E 3", + "en": "DALL·E 3", + }, } \ No newline at end of file