Skip to content

Commit

Permalink
Merge branch 'main' into gpt-4o
Browse files Browse the repository at this point in the history
  • Loading branch information
n3d1117 authored May 14, 2024
2 parents 54c4afc + 9a1b5cb commit e1f5988
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 18 deletions.
2 changes: 1 addition & 1 deletion bot/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def main():

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. '
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)
if os.environ.get('MONTHLY_USER_BUDGETS') is not None:
logging.warning('The environment variable MONTHLY_USER_BUDGETS is deprecated. '
Expand Down
5 changes: 2 additions & 3 deletions bot/openai_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@
# 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_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_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_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:
"""
Gets the default number of max tokens for the given model.
Expand Down
4 changes: 3 additions & 1 deletion bot/plugin_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from plugins.worldtimeapi import WorldTimeApiPlugin
from plugins.whois_ import WhoisPlugin
from plugins.webshot import WebshotPlugin
from plugins.iplocation import IpLocationPlugin


class PluginManager:
Expand All @@ -40,6 +41,7 @@ def __init__(self, config):
'auto_tts': AutoTextToSpeech,
'whois': WhoisPlugin,
'webshot': WebshotPlugin,
'iplocation': IpLocationPlugin,
}
self.plugins = [plugin_mapping[plugin]() for plugin in enabled_plugins if plugin in plugin_mapping]

Expand Down Expand Up @@ -69,4 +71,4 @@ def get_plugin_source_name(self, function_name) -> str:

def __get_plugin_by_function_name(self, function_name):
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 changes: 44 additions & 0 deletions bot/plugins/iplocation.py
Original file line number Diff line number Diff line change
@@ -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)}
2 changes: 1 addition & 1 deletion bot/plugins/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def get_spec(self) -> [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'&longitude={kwargs["longitude"]}' \
f'&temperature_unit={kwargs["unit"]}'
Expand Down
4 changes: 2 additions & 2 deletions bot/plugins/worldtimeapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ def get_source_name(self) -> str:
def get_spec(self) -> [Dict]:
return [{
"name": "worldtimeapi",
"description": f"Get the current time from a given timezone",
"description": "Get the current time from a given timezone",
"parameters": {
"type": "object",
"properties": {
"timezone": {
"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."
}
},
Expand Down
20 changes: 10 additions & 10 deletions bot/telegram_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ async def stats(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
if not await is_allowed(self.config, update, context):
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)
return

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
if user_id not in self.usage:
Expand All @@ -112,7 +112,7 @@ async def stats(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
f"*{localized_text('stats_conversation', bot_language)[0]}*:\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"----------------------------\n"
"----------------------------\n"
)

# Check if image generation is enabled and, if so, generate the image statistics for today
Expand All @@ -137,7 +137,7 @@ async def stats(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
f"{transcribe_minutes_today} {localized_text('stats_transcribe', bot_language)[0]} "
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"----------------------------\n"
"----------------------------\n"
)

text_month_images = ""
Expand Down Expand Up @@ -190,14 +190,14 @@ async def resend(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
if not await is_allowed(self.config, update, context):
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)
return

chat_id = update.effective_chat.id
if chat_id not in self.last_message:
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(
message_thread_id=get_thread_id(update),
text=localized_text('resend_failed', self.config['bot_language'])
Expand All @@ -218,7 +218,7 @@ async def reset(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
if not await is_allowed(self.config, update, context):
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)
return

Expand Down Expand Up @@ -339,7 +339,7 @@ async def transcribe(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
return

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

chat_id = update.effective_chat.id
Expand Down Expand Up @@ -463,13 +463,13 @@ async def vision(self, update: Update, context: ContextTypes.DEFAULT_TYPE):

if is_group_chat(update):
if self.config['ignore_group_vision']:
logging.info(f'Vision coming from group chat, ignoring...')
logging.info('Vision coming from group chat, ignoring...')
return
else:
trigger_keyword = self.config['group_trigger_keyword']
if (prompt is None and trigger_keyword != '') or \
(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

image = update.message.effective_attachment[-1]
Expand Down
49 changes: 49 additions & 0 deletions translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,55 @@
"loading":"Lataa...",
"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": {
"help_description": "Menampilkan pesan bantuan",
"reset_description": "Merestart percakapan. Opsional memasukkan instruksi tingkat tinggi (misalnya /reset Anda adalah asisten yang membantu)",
Expand Down

0 comments on commit e1f5988

Please sign in to comment.