Merge branch 'main' into gpt-4o

This commit is contained in:
ned
2024-05-14 15:59:00 +02:00
committed by GitHub
8 changed files with 112 additions and 18 deletions

View File

@@ -64,7 +64,7 @@ def main():
if openai_config['enable_functions'] and not functions_available: if openai_config['enable_functions'] and not functions_available:
logging.error(f'ENABLE_FUNCTIONS is set to true, but the model {model} does not support it. ' logging.error(f'ENABLE_FUNCTIONS is set to true, but the model {model} does not support it. '
f'Please set ENABLE_FUNCTIONS to false or use a model that supports it.') 'Please set ENABLE_FUNCTIONS to false or use a model that supports it.')
exit(1) exit(1)
if os.environ.get('MONTHLY_USER_BUDGETS') is not None: if os.environ.get('MONTHLY_USER_BUDGETS') is not None:
logging.warning('The environment variable MONTHLY_USER_BUDGETS is deprecated. ' logging.warning('The environment variable MONTHLY_USER_BUDGETS is deprecated. '

View File

@@ -24,14 +24,13 @@ from plugin_manager import PluginManager
# Models gpt-3.5-turbo-0613 and gpt-3.5-turbo-16k-0613 will be deprecated on June 13, 2024 # Models gpt-3.5-turbo-0613 and gpt-3.5-turbo-16k-0613 will be deprecated on June 13, 2024
GPT_3_MODELS = ("gpt-3.5-turbo", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613") GPT_3_MODELS = ("gpt-3.5-turbo", "gpt-3.5-turbo-0301", "gpt-3.5-turbo-0613")
GPT_3_16K_MODELS = ("gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125") GPT_3_16K_MODELS = ("gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613", "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125")
GPT_4_MODELS = ("gpt-4", "gpt-4-0314", "gpt-4-0613") GPT_4_MODELS = ("gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-turbo-preview")
GPT_4_32K_MODELS = ("gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613") GPT_4_32K_MODELS = ("gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613")
GPT_4_VISION_MODELS = ("gpt-4-vision-preview",) GPT_4_VISION_MODELS = ("gpt-4-vision-preview",)
GPT_4_128K_MODELS = ("gpt-4-1106-preview","gpt-4-0125-preview","gpt-4-turbo-preview") GPT_4_128K_MODELS = ("gpt-4-1106-preview","gpt-4-0125-preview","gpt-4-turbo-preview", "gpt-4-turbo", "gpt-4-turbo-2024-04-09")
GPT_4O_MODELS = ("gpt-4o",) GPT_4O_MODELS = ("gpt-4o",)
GPT_ALL_MODELS = GPT_3_MODELS + GPT_3_16K_MODELS + GPT_4_MODELS + GPT_4_32K_MODELS + GPT_4_VISION_MODELS + GPT_4_128K_MODELS + GPT_4O_MODELS GPT_ALL_MODELS = GPT_3_MODELS + GPT_3_16K_MODELS + GPT_4_MODELS + GPT_4_32K_MODELS + GPT_4_VISION_MODELS + GPT_4_128K_MODELS + GPT_4O_MODELS
def default_max_tokens(model: str) -> int: def default_max_tokens(model: str) -> int:
""" """
Gets the default number of max tokens for the given model. Gets the default number of max tokens for the given model.

View File

@@ -15,6 +15,7 @@ from plugins.deepl import DeeplTranslatePlugin
from plugins.worldtimeapi import WorldTimeApiPlugin from plugins.worldtimeapi import WorldTimeApiPlugin
from plugins.whois_ import WhoisPlugin from plugins.whois_ import WhoisPlugin
from plugins.webshot import WebshotPlugin from plugins.webshot import WebshotPlugin
from plugins.iplocation import IpLocationPlugin
class PluginManager: class PluginManager:
@@ -40,6 +41,7 @@ class PluginManager:
'auto_tts': AutoTextToSpeech, 'auto_tts': AutoTextToSpeech,
'whois': WhoisPlugin, 'whois': WhoisPlugin,
'webshot': WebshotPlugin, 'webshot': WebshotPlugin,
'iplocation': IpLocationPlugin,
} }
self.plugins = [plugin_mapping[plugin]() for plugin in enabled_plugins if plugin in plugin_mapping] self.plugins = [plugin_mapping[plugin]() for plugin in enabled_plugins if plugin in plugin_mapping]
@@ -69,4 +71,4 @@ class PluginManager:
def __get_plugin_by_function_name(self, function_name): def __get_plugin_by_function_name(self, function_name):
return next((plugin for plugin in self.plugins return next((plugin for plugin in self.plugins
if function_name in map(lambda spec: spec.get('name'), plugin.get_spec())), None) if function_name in map(lambda spec: spec.get('name'), plugin.get_spec())), None)

44
bot/plugins/iplocation.py Normal file
View File

@@ -0,0 +1,44 @@
import requests
from typing import Dict
from .plugin import Plugin
class IpLocationPlugin(Plugin):
"""
A plugin to get geolocation and other information for a given IP address
"""
def get_source_name(self) -> str:
return "IP.FM"
def get_spec(self) -> [Dict]:
return [{
"name": "iplocaion",
"description": "Get information for an IP address using the IP.FM API.",
"parameters": {
"type": "object",
"properties": {
"ip": {"type": "string", "description": "IP Address"}
},
"required": ["ip"],
},
}]
async def execute(self, function_name, helper, **kwargs) -> Dict:
ip = kwargs.get('ip')
BASE_URL = "https://api.ip.fm/?ip={}"
url = BASE_URL.format(ip)
try:
response = requests.get(url)
response_data = response.json()
country = response_data.get('data', {}).get('country', "None")
subdivisions = response_data.get('data', {}).get('subdivisions', "None")
city = response_data.get('data', {}).get('city', "None")
location = ', '.join(filter(None, [country, subdivisions, city])) or "None"
asn = response_data.get('data', {}).get('asn', "None")
as_name = response_data.get('data', {}).get('as_name', "None")
as_domain = response_data.get('data', {}).get('as_domain', "None")
return {"Location": location, "ASN": asn, "AS Name": as_name, "AS Domain": as_domain}
except Exception as e:
return {"Error": str(e)}

View File

@@ -58,7 +58,7 @@ class WeatherPlugin(Plugin):
] ]
async def execute(self, function_name, helper, **kwargs) -> Dict: async def execute(self, function_name, helper, **kwargs) -> Dict:
url = f'https://api.open-meteo.com/v1/forecast' \ url = 'https://api.open-meteo.com/v1/forecast' \
f'?latitude={kwargs["latitude"]}' \ f'?latitude={kwargs["latitude"]}' \
f'&longitude={kwargs["longitude"]}' \ f'&longitude={kwargs["longitude"]}' \
f'&temperature_unit={kwargs["unit"]}' f'&temperature_unit={kwargs["unit"]}'

View File

@@ -21,13 +21,13 @@ class WorldTimeApiPlugin(Plugin):
def get_spec(self) -> [Dict]: def get_spec(self) -> [Dict]:
return [{ return [{
"name": "worldtimeapi", "name": "worldtimeapi",
"description": f"Get the current time from a given timezone", "description": "Get the current time from a given timezone",
"parameters": { "parameters": {
"type": "object", "type": "object",
"properties": { "properties": {
"timezone": { "timezone": {
"type": "string", "type": "string",
"description": f"The timezone identifier (e.g: `Europe/Rome`). Infer this from the location." "description": "The timezone identifier (e.g: `Europe/Rome`). Infer this from the location."
f"Use {self.default_timezone} if not specified." f"Use {self.default_timezone} if not specified."
} }
}, },

View File

@@ -84,12 +84,12 @@ class ChatGPTTelegramBot:
""" """
if not await is_allowed(self.config, update, context): if not await is_allowed(self.config, update, context):
logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id}) ' logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id}) '
f'is not allowed to request their usage statistics') 'is not allowed to request their usage statistics')
await self.send_disallowed_message(update, context) await self.send_disallowed_message(update, context)
return return
logging.info(f'User {update.message.from_user.name} (id: {update.message.from_user.id}) ' logging.info(f'User {update.message.from_user.name} (id: {update.message.from_user.id}) '
f'requested their usage statistics') 'requested their usage statistics')
user_id = update.message.from_user.id user_id = update.message.from_user.id
if user_id not in self.usage: if user_id not in self.usage:
@@ -112,7 +112,7 @@ class ChatGPTTelegramBot:
f"*{localized_text('stats_conversation', bot_language)[0]}*:\n" f"*{localized_text('stats_conversation', bot_language)[0]}*:\n"
f"{chat_messages} {localized_text('stats_conversation', bot_language)[1]}\n" f"{chat_messages} {localized_text('stats_conversation', bot_language)[1]}\n"
f"{chat_token_length} {localized_text('stats_conversation', bot_language)[2]}\n" f"{chat_token_length} {localized_text('stats_conversation', bot_language)[2]}\n"
f"----------------------------\n" "----------------------------\n"
) )
# Check if image generation is enabled and, if so, generate the image statistics for today # Check if image generation is enabled and, if so, generate the image statistics for today
@@ -137,7 +137,7 @@ class ChatGPTTelegramBot:
f"{transcribe_minutes_today} {localized_text('stats_transcribe', bot_language)[0]} " f"{transcribe_minutes_today} {localized_text('stats_transcribe', bot_language)[0]} "
f"{transcribe_seconds_today} {localized_text('stats_transcribe', bot_language)[1]}\n" f"{transcribe_seconds_today} {localized_text('stats_transcribe', bot_language)[1]}\n"
f"{localized_text('stats_total', bot_language)}{current_cost['cost_today']:.2f}\n" f"{localized_text('stats_total', bot_language)}{current_cost['cost_today']:.2f}\n"
f"----------------------------\n" "----------------------------\n"
) )
text_month_images = "" text_month_images = ""
@@ -190,14 +190,14 @@ class ChatGPTTelegramBot:
""" """
if not await is_allowed(self.config, update, context): if not await is_allowed(self.config, update, context):
logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id})' logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id})'
f' is not allowed to resend the message') ' is not allowed to resend the message')
await self.send_disallowed_message(update, context) await self.send_disallowed_message(update, context)
return return
chat_id = update.effective_chat.id chat_id = update.effective_chat.id
if chat_id not in self.last_message: if chat_id not in self.last_message:
logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id})' logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id})'
f' does not have anything to resend') ' does not have anything to resend')
await update.effective_message.reply_text( await update.effective_message.reply_text(
message_thread_id=get_thread_id(update), message_thread_id=get_thread_id(update),
text=localized_text('resend_failed', self.config['bot_language']) text=localized_text('resend_failed', self.config['bot_language'])
@@ -218,7 +218,7 @@ class ChatGPTTelegramBot:
""" """
if not await is_allowed(self.config, update, context): if not await is_allowed(self.config, update, context):
logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id}) ' logging.warning(f'User {update.message.from_user.name} (id: {update.message.from_user.id}) '
f'is not allowed to reset the conversation') 'is not allowed to reset the conversation')
await self.send_disallowed_message(update, context) await self.send_disallowed_message(update, context)
return return
@@ -339,7 +339,7 @@ class ChatGPTTelegramBot:
return return
if is_group_chat(update) and self.config['ignore_group_transcriptions']: if is_group_chat(update) and self.config['ignore_group_transcriptions']:
logging.info(f'Transcription coming from group chat, ignoring...') logging.info('Transcription coming from group chat, ignoring...')
return return
chat_id = update.effective_chat.id chat_id = update.effective_chat.id
@@ -463,13 +463,13 @@ class ChatGPTTelegramBot:
if is_group_chat(update): if is_group_chat(update):
if self.config['ignore_group_vision']: if self.config['ignore_group_vision']:
logging.info(f'Vision coming from group chat, ignoring...') logging.info('Vision coming from group chat, ignoring...')
return return
else: else:
trigger_keyword = self.config['group_trigger_keyword'] trigger_keyword = self.config['group_trigger_keyword']
if (prompt is None and trigger_keyword != '') or \ if (prompt is None and trigger_keyword != '') or \
(prompt is not None and not prompt.lower().startswith(trigger_keyword.lower())): (prompt is not None and not prompt.lower().startswith(trigger_keyword.lower())):
logging.info(f'Vision coming from group chat with wrong keyword, ignoring...') logging.info('Vision coming from group chat with wrong keyword, ignoring...')
return return
image = update.message.effective_attachment[-1] image = update.message.effective_attachment[-1]

View File

@@ -293,6 +293,55 @@
"loading":"Lataa...", "loading":"Lataa...",
"function_unavailable_in_inline_mode": "Tämä toiminto ei ole käytettävissä sisäisessä tilassa" "function_unavailable_in_inline_mode": "Tämä toiminto ei ole käytettävissä sisäisessä tilassa"
}, },
"he": {
"help_description": "הצג הודעת עזרה",
"reset_description": "אתחל את השיחה. ניתן להעביר הוראות ברמה גבוהה (למשל, /reset אתה עוזר מועיל)",
"image_description": "צור תמונה מהפרומפט (למשל, /image חתול)",
"tts_description": "צור דיבור מטקסט (למשל, /tts הבית שלי)",
"stats_description": "קבל את סטטיסטיקות השימוש הנוכחיות שלך",
"resend_description": "שלח מחדש את ההודעה האחרונה",
"chat_description": "שוחח עם הבוט!",
"disallowed": "מצטערים, אינך מורשה להשתמש בבוט זה. תוכל לבדוק את הקוד המקור ב https://github.com/n3d1117/chatgpt-telegram-bot",
"budget_limit": "מצטערים, הגעת למגבלת השימוש שלך.",
"help_text": ["אני בוט של ChatGPT, דבר איתי!", "שלח לי הודעה קולית או קובץ ואני אתרגם אותו בשבילך", "קוד פתוח ב https://github.com/n3d1117/chatgpt-telegram-bot"],
"stats_conversation": ["שיחה נוכחית", "הודעות צ'אט בהיסטוריה", "אסימוני צ'אט בהיסטוריה"],
"usage_today": "שימוש היום",
"usage_month": "שימוש החודש",
"stats_tokens": "אסימונים",
"stats_images": "תמונות שנוצרו",
"stats_vision": "אסימוני תמונה שפורשו",
"stats_tts": "תווים שהומרו לדיבור",
"stats_transcribe": ["דקות ו", "שניות שהוקלטו"],
"stats_total": "💰 לסך כל של $",
"stats_budget": "התקציב הנותר שלך",
"monthly": " לחודש זה",
"daily": " להיום",
"all-time": "",
"stats_openai": "החשבון שלך ב-OpenAI חויב החודש ב-$",
"resend_failed": "אין לך מה לשלוח מחדש",
"reset_done": "בוצע!",
"image_no_prompt": "נא לספק פרומפט! (למשל, /image חתול)",
"image_fail": "נכשל ביצירת התמונה",
"vision_fail": "נכשל בפרשנות התמונה",
"tts_no_prompt": "נא לספק טקסט! (למשל, /tts הבית שלי)",
"tts_fail": "נכשל ביצירת הדיבור",
"media_download_fail": ["נכשל בהורדת קובץ השמע", "ודא שהקובץ אינו גדול מדי. (מקסימום 20MB)"],
"media_type_fail": "סוג קובץ לא נתמך",
"transcript": "תמליל",
"answer": "תשובה",
"transcribe_fail": "נכשל בתרגום הטקסט",
"chat_fail": "נכשל בקבלת תגובה",
"prompt": "פרומפט",
"completion": "השלמה",
"openai_rate_limit": "חריגה מהגבלת השימוש של OpenAI",
"openai_invalid": "בקשה לא חוקית של OpenAI",
"error": "אירעה שגיאה",
"try_again": "נא לנסות שוב מאוחר יותר",
"answer_with_chatgpt": "ענה באמצעות ChatGPT",
"ask_chatgpt": "שאל את ChatGPT",
"loading": "טוען...",
"function_unavailable_in_inline_mode": "הפונקציה לא זמינה במצב inline"
}
"id": { "id": {
"help_description": "Menampilkan pesan bantuan", "help_description": "Menampilkan pesan bantuan",
"reset_description": "Merestart percakapan. Opsional memasukkan instruksi tingkat tinggi (misalnya /reset Anda adalah asisten yang membantu)", "reset_description": "Merestart percakapan. Opsional memasukkan instruksi tingkat tinggi (misalnya /reset Anda adalah asisten yang membantu)",