Merge branch 'main' into vision-support

This commit is contained in:
gilcu3
2023-11-18 17:55:53 +01:00
8 changed files with 348 additions and 49 deletions

View File

@@ -20,10 +20,12 @@ ALLOWED_TELEGRAM_USER_IDS=USER_ID_1,USER_ID_2
# VISION_TOKEN_PRICE=0.01 # VISION_TOKEN_PRICE=0.01
# ENABLE_QUOTING=true # ENABLE_QUOTING=true
# ENABLE_IMAGE_GENERATION=true # ENABLE_IMAGE_GENERATION=true
# ENABLE_TTS_GENERATION=true
# ENABLE_TRANSCRIPTION=true # ENABLE_TRANSCRIPTION=true
# ENABLE_VISION=true # ENABLE_VISION=true
# PROXY=http://localhost:8080 # PROXY=http://localhost:8080
# OPENAI_MODEL=gpt-3.5-turbo # OPENAI_MODEL=gpt-3.5-turbo
# OPENAI_BASE_URL=https://example.com/v1/
# ASSISTANT_PROMPT="You are a helpful assistant." # ASSISTANT_PROMPT="You are a helpful assistant."
# SHOW_USAGE=false # SHOW_USAGE=false
# STREAM=true # STREAM=true
@@ -38,9 +40,15 @@ ALLOWED_TELEGRAM_USER_IDS=USER_ID_1,USER_ID_2
# TEMPERATURE=1.0 # TEMPERATURE=1.0
# PRESENCE_PENALTY=0.0 # PRESENCE_PENALTY=0.0
# FREQUENCY_PENALTY=0.0 # FREQUENCY_PENALTY=0.0
# IMAGE_SIZE=512x512 # IMAGE_MODEL=dall-e-3
# IMAGE_QUALITY=hd
# IMAGE_STYLE=natural
# IMAGE_SIZE=1024x1024
# IMAGE_FORMAT=document
# VISION_DETAIL="low" # VISION_DETAIL="low"
# GROUP_TRIGGER_KEYWORD="" # GROUP_TRIGGER_KEYWORD=""
# IGNORE_GROUP_TRANSCRIPTIONS=true # IGNORE_GROUP_TRANSCRIPTIONS=true
# IGNORE_GROUP_VISION=true # IGNORE_GROUP_VISION=true
# TTS_MODEL="tts-1"
# TTS_VOICE="alloy"
# BOT_LANGUAGE=en # BOT_LANGUAGE=en

View File

@@ -30,12 +30,15 @@ A [Telegram bot](https://core.telegram.org/bots/api) that integrates with OpenAI
- [x] GPT-4 support - [x] GPT-4 support
- If you have access to the GPT-4 API, simply change the `OPENAI_MODEL` parameter to `gpt-4` - If you have access to the GPT-4 API, simply change the `OPENAI_MODEL` parameter to `gpt-4`
- [x] Localized bot language - [x] Localized bot language
- Available languages :gb: :de: :ru: :tr: :it: :finland: :es: :indonesia: :netherlands: :cn: :taiwan: :vietnam: :iran: :brazil: :ukraine: :malaysia: - Available languages :gb: :de: :ru: :tr: :it: :finland: :es: :indonesia: :netherlands: :cn: :taiwan: :vietnam: :iran: :brazil: :ukraine: :malaysia: :uzbekistan:
- [x] Improved inline queries support for group and private chats - by [@bugfloyd](https://github.com/bugfloyd) - [x] Improved inline queries support for group and private chats - by [@bugfloyd](https://github.com/bugfloyd)
- To use this feature, enable inline queries for your bot in BotFather via the `/setinline` [command](https://core.telegram.org/bots/inline) - To use this feature, enable inline queries for your bot in BotFather via the `/setinline` [command](https://core.telegram.org/bots/inline)
- [x] (NEW!) Support *new models* [announced on June 13, 2023](https://openai.com/blog/function-calling-and-other-api-updates) - [x] Support *new models* [announced on June 13, 2023](https://openai.com/blog/function-calling-and-other-api-updates)
- [x] (NEW!) Support *functions* (plugins) to extend the bot's functionality with 3rd party services - [x] Support *functions* (plugins) to extend the bot's functionality with 3rd party services
- Weather, Spotify, Web search, text-to-speech and more. See [here](#available-plugins) for a list of available plugins - Weather, Spotify, Web search, text-to-speech and more. See [here](#available-plugins) for a list of available plugins
- [x] Support unofficial OpenAI-compatible APIs - by [@kristaller486](https://github.com/kristaller486)
- [x] (NEW!) Support GPT-4 Turbo and DALL·E 3 [announced on November 6, 2023](https://openai.com/blog/new-models-and-developer-products-announced-at-devday) - by [@AlexHTW](https://github.com/AlexHTW)
- [x] (NEW!) Text-to-speech support [announced on November 6, 2023](https://platform.openai.com/docs/guides/text-to-speech) - by [@gilcu3](https://github.com/gilcu3)
## Additional features - help needed! ## Additional features - help needed!
If you'd like to help, check out the [issues](https://github.com/n3d1117/chatgpt-telegram-bot/issues) section and contribute! If you'd like to help, check out the [issues](https://github.com/n3d1117/chatgpt-telegram-bot/issues) section and contribute!
@@ -77,35 +80,43 @@ The following parameters are optional and can be set in the `.env` file:
Check out the [Budget Manual](https://github.com/n3d1117/chatgpt-telegram-bot/discussions/184) for possible budget configurations. Check out the [Budget Manual](https://github.com/n3d1117/chatgpt-telegram-bot/discussions/184) for possible budget configurations.
#### Additional optional configuration options #### Additional optional configuration options
| Parameter | Description | Default value | | Parameter | Description | Default value |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------| |------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------|
| `ENABLE_QUOTING` | Whether to enable message quoting in private chats | `true` | | `ENABLE_QUOTING` | Whether to enable message quoting in private chats | `true` |
| `ENABLE_IMAGE_GENERATION` | Whether to enable image generation via the `/image` command | `true` | | `ENABLE_IMAGE_GENERATION` | Whether to enable image generation via the `/image` command | `true` |
| `ENABLE_TRANSCRIPTION` | Whether to enable transcriptions of audio and video messages | `true` | | `ENABLE_TRANSCRIPTION` | Whether to enable transcriptions of audio and video messages | `true` |
| `ENABLE_TTS_GENERATION` | Whether to enable text to speech generation via the `/tts` | `true` |
| `ENABLE_VISION` | Whether to enable vision capabilities in supported models | `true` | | `ENABLE_VISION` | Whether to enable vision capabilities in supported models | `true` |
| `PROXY` | Proxy to be used for OpenAI and Telegram bot (e.g. `http://localhost:8080`) | - | | `PROXY` | Proxy to be used for OpenAI and Telegram bot (e.g. `http://localhost:8080`) | - |
| `OPENAI_MODEL` | The OpenAI model to use for generating responses. You can find all available models [here](https://platform.openai.com/docs/models/) | `gpt-3.5-turbo` | | `OPENAI_MODEL` | The OpenAI model to use for generating responses. You can find all available models [here](https://platform.openai.com/docs/models/) | `gpt-3.5-turbo` |
| `ASSISTANT_PROMPT` | A system message that sets the tone and controls the behavior of the assistant | `You are a helpful assistant.` | | `OPENAI_BASE_URL` | Endpoint URL for unofficial OpenAI-compatible APIs (e.g., LocalAI or text-generation-webui) | Default OpenAI API URL |
| `SHOW_USAGE` | Whether to show OpenAI token usage information after each response | `false` | | `ASSISTANT_PROMPT` | A system message that sets the tone and controls the behavior of the assistant | `You are a helpful assistant.` |
| `STREAM` | Whether to stream responses. **Note**: incompatible, if enabled, with `N_CHOICES` higher than 1 | `true` | | `SHOW_USAGE` | Whether to show OpenAI token usage information after each response | `false` |
| `MAX_TOKENS` | Upper bound on how many tokens the ChatGPT API will return | `1200` for GPT-3, `2400` for GPT-4 | | `STREAM` | Whether to stream responses. **Note**: incompatible, if enabled, with `N_CHOICES` higher than 1 | `true` |
| `MAX_TOKENS` | Upper bound on how many tokens the ChatGPT API will return | `1200` for GPT-3, `2400` for GPT-4 |
| `VISION_MAX_TOKENS` | Upper bound on how many tokens vision models will return | `300` for gpt-4-vision-preview | | `VISION_MAX_TOKENS` | Upper bound on how many tokens vision models will return | `300` for gpt-4-vision-preview |
| `MAX_HISTORY_SIZE` | Max number of messages to keep in memory, after which the conversation will be summarised to avoid excessive token usage | `15` | | `MAX_HISTORY_SIZE` | Max number of messages to keep in memory, after which the conversation will be summarised to avoid excessive token usage | `15` |
| `MAX_CONVERSATION_AGE_MINUTES` | Maximum number of minutes a conversation should live since the last message, after which the conversation will be reset | `180` | | `MAX_CONVERSATION_AGE_MINUTES` | Maximum number of minutes a conversation should live since the last message, after which the conversation will be reset | `180` |
| `VOICE_REPLY_WITH_TRANSCRIPT_ONLY` | Whether to answer to voice messages with the transcript only or with a ChatGPT response of the transcript | `false` | | `VOICE_REPLY_WITH_TRANSCRIPT_ONLY` | Whether to answer to voice messages with the transcript only or with a ChatGPT response of the transcript | `false` |
| `VOICE_REPLY_PROMPTS` | A semicolon separated list of phrases (i.e. `Hi bot;Hello chat`). If the transcript starts with any of them, it will be treated as a prompt even if `VOICE_REPLY_WITH_TRANSCRIPT_ONLY` is set to `true` | - | | `VOICE_REPLY_PROMPTS` | A semicolon separated list of phrases (i.e. `Hi bot;Hello chat`). If the transcript starts with any of them, it will be treated as a prompt even if `VOICE_REPLY_WITH_TRANSCRIPT_ONLY` is set to `true` | - |
| `VISION_PROMPT` | A phrase (i.e. `What is in this image`). The vision models use it as prompt to interpret a given image. If there is caption in the image sent to the bot, that supersedes this parameter | `What is in this image` | | `VISION_PROMPT` | A phrase (i.e. `What is in this image`). The vision models use it as prompt to interpret a given image. If there is caption in the image sent to the bot, that supersedes this parameter | `What is in this image` |
| `N_CHOICES` | Number of answers to generate for each input message. **Note**: setting this to a number higher than 1 will not work properly if `STREAM` is enabled | `1` | | `N_CHOICES` | Number of answers to generate for each input message. **Note**: setting this to a number higher than 1 will not work properly if `STREAM` is enabled | `1` |
| `TEMPERATURE` | Number between 0 and 2. Higher values will make the output more random | `1.0` | | `TEMPERATURE` | Number between 0 and 2. Higher values will make the output more random | `1.0` |
| `PRESENCE_PENALTY` | Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far | `0.0` | | `PRESENCE_PENALTY` | Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far | `0.0` |
| `FREQUENCY_PENALTY` | Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far | `0.0` | | `FREQUENCY_PENALTY` | Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far | `0.0` |
| `IMAGE_SIZE` | The DALL·E generated image size. Allowed values: `256x256`, `512x512` or `1024x1024` | `512x512` | | `IMAGE_FORMAT` | The Telegram image receive mode. Allowed values: `document` or `photo` | `photo` |
| `IMAGE_MODEL` | The DALL·E model to be used. Available models: `dall-e-2` and `dall-e-3`, find current available models [here](https://platform.openai.com/docs/models/dall-e) | `dall-e-2` |
| `IMAGE_QUALITY` | Quality of DALL·E images, only available for `dall-e-3`-model. Possible options: `standard` or `hd`, beware of [pricing differences](https://openai.com/pricing#image-models). | `standard` |
| `IMAGE_STYLE` | Style for DALL·E image generation, only available for `dall-e-3`-model. Possible options: `vivid` or `natural`. Check availbe styles [here](https://platform.openai.com/docs/api-reference/images/create). | `vivid` |
| `IMAGE_SIZE` | The DALL·E generated image size. Must be `256x256`, `512x512`, or `1024x1024` for dall-e-2. Must be `1024x1024` for dall-e-3 models. | `512x512` |
| `VISION_DETAIL` | The detail parameter for vision models, explained [Vision Guide](https://platform.openai.com/docs/guides/vision). Allowed values: `low` or `high` | `low` | | `VISION_DETAIL` | The detail parameter for vision models, explained [Vision Guide](https://platform.openai.com/docs/guides/vision). Allowed values: `low` or `high` | `low` |
| `GROUP_TRIGGER_KEYWORD` | If set, the bot in group chats will only respond to messages that start with this keyword | - | | `GROUP_TRIGGER_KEYWORD` | If set, the bot in group chats will only respond to messages that start with this keyword | - |
| `IGNORE_GROUP_TRANSCRIPTIONS` | If set to true, the bot will not process transcriptions in group chats | `true` | | `IGNORE_GROUP_TRANSCRIPTIONS` | If set to true, the bot will not process transcriptions in group chats | `true` |
| `IGNORE_GROUP_VISION` | If set to true, the bot will not process vision queries in group chats | `true` | | `IGNORE_GROUP_VISION` | If set to true, the bot will not process vision queries in group chats | `true` |
| `BOT_LANGUAGE` | Language of general bot messages. Currently available: `en`, `de`, `ru`, `tr`, `it`, `fi`, `es`, `id`, `nl`, `zh-cn`, `zh-tw`, `vi`, `fa`, `pt-br`, `uk`, `ms`. [Contribute with additional translations](https://github.com/n3d1117/chatgpt-telegram-bot/discussions/219) | `en` | | `BOT_LANGUAGE` | Language of general bot messages. Currently available: `en`, `de`, `ru`, `tr`, `it`, `fi`, `es`, `id`, `nl`, `zh-cn`, `zh-tw`, `vi`, `fa`, `pt-br`, `uk`, `ms`, `uz`. [Contribute with additional translations](https://github.com/n3d1117/chatgpt-telegram-bot/discussions/219) | `en` |
| `WHISPER_PROMPT` | To improve the accuracy of Whisper's transcription service, especially for specific names or terms, you can set up a custom message. [Speech to text - Prompting](https://platform.openai.com/docs/guides/speech-to-text/prompting) | `-` | | `WHISPER_PROMPT` | To improve the accuracy of Whisper's transcription service, especially for specific names or terms, you can set up a custom message. [Speech to text - Prompting](https://platform.openai.com/docs/guides/speech-to-text/prompting) | `-` |
| `TTS_VOICE` | The Text to Speech voice to use. Allowed values: `alloy`, `echo`, `fable`, `onyx`, `nova`, or `shimmer` | `alloy` |
| `TTS_MODEL` | The Text to Speech model to use. Allowed values: `tts-1` or `tts-1-hd` | `tts-1` |
Check out the [official API reference](https://platform.openai.com/docs/api-reference/chat) for more details. Check out the [official API reference](https://platform.openai.com/docs/api-reference/chat) for more details.

View File

@@ -41,6 +41,9 @@ def main():
'max_tokens': int(os.environ.get('MAX_TOKENS', max_tokens_default)), 'max_tokens': int(os.environ.get('MAX_TOKENS', max_tokens_default)),
'n_choices': int(os.environ.get('N_CHOICES', 1)), 'n_choices': int(os.environ.get('N_CHOICES', 1)),
'temperature': float(os.environ.get('TEMPERATURE', 1.0)), 'temperature': float(os.environ.get('TEMPERATURE', 1.0)),
'image_model': os.environ.get('IMAGE_MODEL', 'dall-e-2'),
'image_quality': os.environ.get('IMAGE_QUALITY', 'standard'),
'image_style': os.environ.get('IMAGE_STYLE', 'vivid'),
'image_size': os.environ.get('IMAGE_SIZE', '512x512'), 'image_size': os.environ.get('IMAGE_SIZE', '512x512'),
'model': model, 'model': model,
'enable_functions': os.environ.get('ENABLE_FUNCTIONS', str(functions_available)).lower() == 'true', 'enable_functions': os.environ.get('ENABLE_FUNCTIONS', str(functions_available)).lower() == 'true',
@@ -53,6 +56,8 @@ def main():
'vision_prompt': os.environ.get('VISION_PROMPT', 'What is in this image'), 'vision_prompt': os.environ.get('VISION_PROMPT', 'What is in this image'),
'vision_detail': os.environ.get('VISION_DETAIL', 'low'), 'vision_detail': os.environ.get('VISION_DETAIL', 'low'),
'vision_max_tokens': int(os.environ.get('VISION_MAX_TOKENS', '300')), 'vision_max_tokens': int(os.environ.get('VISION_MAX_TOKENS', '300')),
'tts_model': os.environ.get('TTS_MODEL', 'tts-1'),
'tts_voice': os.environ.get('TTS_VOICE', 'alloy'),
} }
if openai_config['enable_functions'] and not functions_available: if openai_config['enable_functions'] and not functions_available:
@@ -74,6 +79,7 @@ def main():
'enable_image_generation': os.environ.get('ENABLE_IMAGE_GENERATION', 'true').lower() == 'true', 'enable_image_generation': os.environ.get('ENABLE_IMAGE_GENERATION', 'true').lower() == 'true',
'enable_transcription': os.environ.get('ENABLE_TRANSCRIPTION', 'true').lower() == 'true', 'enable_transcription': os.environ.get('ENABLE_TRANSCRIPTION', 'true').lower() == 'true',
'enable_vision': os.environ.get('ENABLE_VISION', 'true').lower() == 'true', 'enable_vision': os.environ.get('ENABLE_VISION', 'true').lower() == 'true',
'enable_tts_generation': os.environ.get('ENABLE_TTS_GENERATION', 'true').lower() == 'true',
'budget_period': os.environ.get('BUDGET_PERIOD', 'monthly').lower(), 'budget_period': os.environ.get('BUDGET_PERIOD', 'monthly').lower(),
'user_budgets': os.environ.get('USER_BUDGETS', os.environ.get('MONTHLY_USER_BUDGETS', '*')), 'user_budgets': os.environ.get('USER_BUDGETS', os.environ.get('MONTHLY_USER_BUDGETS', '*')),
'guest_budget': float(os.environ.get('GUEST_BUDGET', os.environ.get('MONTHLY_GUEST_BUDGET', '100.0'))), 'guest_budget': float(os.environ.get('GUEST_BUDGET', os.environ.get('MONTHLY_GUEST_BUDGET', '100.0'))),
@@ -87,6 +93,9 @@ def main():
'token_price': float(os.environ.get('TOKEN_PRICE', 0.002)), '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(",")], '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')), 'vision_token_price': float(os.environ.get('VISION_TOKEN_PRICE', '0.01')),
'image_receive_mode': os.environ.get('IMAGE_FORMAT', "photo"),
'tts_model': os.environ.get('TTS_MODEL', 'tts-1'),
'tts_prices': [float(i) for i in os.environ.get('TTS_PRICES', "0.015,0.030").split(",")],
'transcription_price': float(os.environ.get('TRANSCRIPTION_PRICE', 0.006)), 'transcription_price': float(os.environ.get('TRANSCRIPTION_PRICE', 0.006)),
'bot_language': os.environ.get('BOT_LANGUAGE', 'en'), 'bot_language': os.environ.get('BOT_LANGUAGE', 'en'),
} }

View File

@@ -10,6 +10,7 @@ import openai
import requests import requests
import json import json
import httpx import httpx
import io
from datetime import date from datetime import date
from calendar import monthrange from calendar import monthrange
from PIL import Image from PIL import Image
@@ -21,11 +22,12 @@ from plugin_manager import PluginManager
# Models can be found here: https://platform.openai.com/docs/models/overview # Models can be found here: https://platform.openai.com/docs/models/overview
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_16K_MODELS = ("gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613", "gpt-3.5-turbo-1106")
GPT_4_MODELS = ("gpt-4", "gpt-4-0314", "gpt-4-0613") GPT_4_MODELS = ("gpt-4", "gpt-4-0314", "gpt-4-0613")
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_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-4-1106-preview",)
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
def default_max_tokens(model: str) -> int: def default_max_tokens(model: str) -> int:
@@ -39,12 +41,16 @@ def default_max_tokens(model: str) -> int:
return base return base
elif model in GPT_4_MODELS: elif model in GPT_4_MODELS:
return base * 2 return base * 2
elif model in GPT_3_16K_MODELS: elif model in GPT_3_16K_MODELS:
if model == "gpt-3.5-turbo-1106":
return 4096
return base * 4 return base * 4
elif model in GPT_4_32K_MODELS: elif model in GPT_4_32K_MODELS:
return base * 8 return base * 8
elif model in GPT_4_VISION_MODELS: elif model in GPT_4_VISION_MODELS:
return 4096 return 4096
elif model in GPT_4_128K_MODELS:
return 4096
def are_functions_available(model: str) -> bool: def are_functions_available(model: str) -> bool:
@@ -55,7 +61,7 @@ def are_functions_available(model: str) -> bool:
if model in ("gpt-3.5-turbo-0301", "gpt-4-0314", "gpt-4-32k-0314"): if model in ("gpt-3.5-turbo-0301", "gpt-4-0314", "gpt-4-32k-0314"):
return False return False
# Stable models will be updated to support functions on June 27, 2023 # Stable models will be updated to support functions on June 27, 2023
if model in ("gpt-3.5-turbo", "gpt-4", "gpt-4-32k"): if model in ("gpt-3.5-turbo", "gpt-3.5-turbo-1106", "gpt-4", "gpt-4-32k","gpt-4-1106-preview"):
return datetime.date.today() > datetime.date(2023, 6, 27) return datetime.date.today() > datetime.date(2023, 6, 27)
if model == 'gpt-4-vision-preview': if model == 'gpt-4-vision-preview':
return False return False
@@ -326,6 +332,9 @@ class OpenAIHelper:
response = await self.client.images.generate( response = await self.client.images.generate(
prompt=prompt, prompt=prompt,
n=1, n=1,
model=self.config['image_model'],
quality=self.config['image_quality'],
style=self.config['image_style'],
size=self.config['image_size'] size=self.config['image_size']
) )
@@ -340,6 +349,28 @@ class OpenAIHelper:
except Exception as e: except Exception as e:
raise Exception(f"⚠️ _{localized_text('error', bot_language)}._ ⚠️\n{str(e)}") from e raise Exception(f"⚠️ _{localized_text('error', bot_language)}._ ⚠️\n{str(e)}") from e
async def generate_speech(self, text: str) -> tuple[any, int]:
"""
Generates an audio from the given text using TTS model.
:param prompt: The text to send to the model
:return: The audio in bytes and the text size
"""
bot_language = self.config['bot_language']
try:
response = await self.client.audio.speech.create(
model=self.config['tts_model'],
voice=self.config['tts_voice'],
input=text,
response_format='opus'
)
temp_file = io.BytesIO()
temp_file.write(response.read())
temp_file.seek(0)
return temp_file, len(text)
except Exception as e:
raise Exception(f"⚠️ _{localized_text('error', bot_language)}._ ⚠️\n{str(e)}") from e
async def transcribe(self, filename): async def transcribe(self, filename):
""" """
Transcribes the audio file using the Whisper model. Transcribes the audio file using the Whisper model.
@@ -372,7 +403,7 @@ class OpenAIHelper:
message = {'role':'user', 'content':[{'type':'text', 'text':prompt}, {'type':'image_url', \ message = {'role':'user', 'content':[{'type':'text', 'text':prompt}, {'type':'image_url', \
'image_url': {'url':f'data:image/jpeg;base64,{image}', 'detail':self.config['vision_detail'] } }]} 'image_url': {'url':f'data:image/jpeg;base64,{image}', 'detail':self.config['vision_detail'] } }]}
common_args = { common_args = {
'model': self.config['model'], 'model': 'gpt-4-vision-preview', # the only one that currently makes sense here
'messages': self.conversations[chat_id] + [message], 'messages': self.conversations[chat_id] + [message],
'temperature': self.config['temperature'], 'temperature': self.config['temperature'],
'n': 1, # several choices is not implemented yet 'n': 1, # several choices is not implemented yet
@@ -451,7 +482,7 @@ class OpenAIHelper:
messages=messages, messages=messages,
temperature=0.4 temperature=0.4
) )
return response.choices[0]['message']['content'] return response.choices[0].message.content
def __max_model_tokens(self): def __max_model_tokens(self):
base = 4096 base = 4096
@@ -465,6 +496,8 @@ class OpenAIHelper:
return base * 8 return base * 8
if self.config['model'] in GPT_4_VISION_MODELS: if self.config['model'] in GPT_4_VISION_MODELS:
return base * 31 return base * 31
if self.config['model'] in GPT_4_128K_MODELS:
return base * 31
raise NotImplementedError( raise NotImplementedError(
f"Max tokens for model {self.config['model']} is not implemented yet." f"Max tokens for model {self.config['model']} is not implemented yet."
) )
@@ -485,7 +518,7 @@ class OpenAIHelper:
if model in GPT_3_MODELS + GPT_3_16K_MODELS: if model in GPT_3_MODELS + GPT_3_16K_MODELS:
tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n
tokens_per_name = -1 # if there's a name, the role is omitted tokens_per_name = -1 # if there's a name, the role is omitted
elif model in GPT_4_MODELS + GPT_4_32K_MODELS + GPT_4_VISION_MODELS: elif model in GPT_4_MODELS + GPT_4_32K_MODELS + GPT_4_VISION_MODELS + GPT_4_128K_MODELS:
tokens_per_message = 3 tokens_per_message = 3
tokens_per_name = 1 tokens_per_name = 1
else: else:
@@ -507,9 +540,9 @@ class OpenAIHelper:
:return: the number of tokens required :return: the number of tokens required
""" """
image = Image.open(fileobj) image = Image.open(fileobj)
model = self.config['model'] model = 'gpt-4-vision-preview' # fixed for now
if model not in GPT_4_VISION_MODELS: if model not in GPT_4_VISION_MODELS:
raise NotImplementedError(f"""num_tokens_from_messages() is not implemented for model {model}.""") raise NotImplementedError(f"""count_tokens_vision() is not implemented for model {model}.""")
w, h = image.size w, h = image.size
if w > h: w, h = h, w if w > h: w, h = h, w

View File

@@ -48,6 +48,9 @@ class ChatGPTTelegramBot:
if self.config.get('enable_image_generation', False): if self.config.get('enable_image_generation', False):
self.commands.append(BotCommand(command='image', description=localized_text('image_description', bot_language))) self.commands.append(BotCommand(command='image', description=localized_text('image_description', bot_language)))
if self.config.get('enable_tts_generation', False):
self.commands.append(BotCommand(command='tts', description=localized_text('tts_description', bot_language)))
self.group_commands = [BotCommand( self.group_commands = [BotCommand(
command='chat', description=localized_text('chat_description', bot_language) command='chat', description=localized_text('chat_description', bot_language)
)] + self.commands )] + self.commands
@@ -97,6 +100,7 @@ class ChatGPTTelegramBot:
(transcribe_minutes_today, transcribe_seconds_today, transcribe_minutes_month, (transcribe_minutes_today, transcribe_seconds_today, transcribe_minutes_month,
transcribe_seconds_month) = self.usage[user_id].get_current_transcription_duration() transcribe_seconds_month) = self.usage[user_id].get_current_transcription_duration()
vision_today, vision_month = self.usage[user_id].get_current_vision_tokens() vision_today, vision_month = self.usage[user_id].get_current_vision_tokens()
characters_today, characters_month = self.usage[user_id].get_current_tts_usage()
current_cost = self.usage[user_id].get_current_cost() current_cost = self.usage[user_id].get_current_cost()
chat_id = update.effective_chat.id chat_id = update.effective_chat.id
@@ -119,12 +123,17 @@ class ChatGPTTelegramBot:
text_today_vision = "" text_today_vision = ""
if self.config.get('enable_vision', False): if self.config.get('enable_vision', False):
text_today_vision = f"{vision_today} {localized_text('stats_vision', bot_language)}\n" text_today_vision = f"{vision_today} {localized_text('stats_vision', bot_language)}\n"
text_today_tts = ""
if self.config.get('enable_tts_generation', False):
text_today_tts = f"{characters_today} {localized_text('stats_tts', bot_language)}\n"
text_today = ( text_today = (
f"*{localized_text('usage_today', bot_language)}:*\n" f"*{localized_text('usage_today', bot_language)}:*\n"
f"{tokens_today} {localized_text('stats_tokens', bot_language)}\n" f"{tokens_today} {localized_text('stats_tokens', bot_language)}\n"
f"{text_today_images}" # Include the image statistics for today if applicable f"{text_today_images}" # Include the image statistics for today if applicable
f"{text_today_vision}" f"{text_today_vision}"
f"{text_today_tts}"
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"
@@ -138,6 +147,10 @@ class ChatGPTTelegramBot:
text_month_vision = "" text_month_vision = ""
if self.config.get('enable_vision', False): if self.config.get('enable_vision', False):
text_month_vision = f"{vision_month} {localized_text('stats_vision', bot_language)}\n" text_month_vision = f"{vision_month} {localized_text('stats_vision', bot_language)}\n"
text_month_tts = ""
if self.config.get('enable_tts_generation', False):
text_month_tts = f"{characters_month} {localized_text('stats_tts', bot_language)}\n"
# Check if image generation is enabled and, if so, generate the image statistics for the month # Check if image generation is enabled and, if so, generate the image statistics for the month
text_month = ( text_month = (
@@ -145,6 +158,7 @@ class ChatGPTTelegramBot:
f"{tokens_month} {localized_text('stats_tokens', bot_language)}\n" f"{tokens_month} {localized_text('stats_tokens', bot_language)}\n"
f"{text_month_images}" # Include the image statistics for the month if applicable f"{text_month_images}" # Include the image statistics for the month if applicable
f"{text_month_vision}" f"{text_month_vision}"
f"{text_month_tts}"
f"{transcribe_minutes_month} {localized_text('stats_transcribe', bot_language)[0]} " f"{transcribe_minutes_month} {localized_text('stats_transcribe', bot_language)[0]} "
f"{transcribe_seconds_month} {localized_text('stats_transcribe', bot_language)[1]}\n" f"{transcribe_seconds_month} {localized_text('stats_transcribe', bot_language)[1]}\n"
f"{localized_text('stats_total', bot_language)}{current_cost['cost_month']:.2f}" f"{localized_text('stats_total', bot_language)}{current_cost['cost_month']:.2f}"
@@ -241,10 +255,18 @@ class ChatGPTTelegramBot:
async def _generate(): async def _generate():
try: try:
image_url, image_size = await self.openai.generate_image(prompt=image_query) image_url, image_size = await self.openai.generate_image(prompt=image_query)
await update.effective_message.reply_photo( if self.config['image_receive_mode'] == 'photo':
reply_to_message_id=get_reply_to_message_id(self.config, update), await update.effective_message.reply_photo(
photo=image_url reply_to_message_id=get_reply_to_message_id(self.config, update),
) photo=image_url
)
elif self.config['image_receive_mode'] == 'document':
await update.effective_message.reply_document(
reply_to_message_id=get_reply_to_message_id(self.config, update),
document=image_url
)
else:
raise Exception(f"env variable IMAGE_RECEIVE_MODE has invalid value {self.config['image_receive_mode']}")
# add image request to users usage tracker # add image request to users usage tracker
user_id = update.message.from_user.id user_id = update.message.from_user.id
self.usage[user_id].add_image_request(image_size, self.config['image_prices']) self.usage[user_id].add_image_request(image_size, self.config['image_prices'])
@@ -263,6 +285,52 @@ class ChatGPTTelegramBot:
await wrap_with_indicator(update, context, _generate, constants.ChatAction.UPLOAD_PHOTO) await wrap_with_indicator(update, context, _generate, constants.ChatAction.UPLOAD_PHOTO)
async def tts(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
Generates an speech for the given input using TTS APIs
"""
if not self.config['enable_tts_generation'] \
or not await self.check_allowed_and_within_budget(update, context):
return
tts_query = message_text(update.message)
if tts_query == '':
await update.effective_message.reply_text(
message_thread_id=get_thread_id(update),
text=localized_text('tts_no_prompt', self.config['bot_language'])
)
return
logging.info(f'New speech generation request received from user {update.message.from_user.name} '
f'(id: {update.message.from_user.id})')
async def _generate():
try:
speech_file, text_length = await self.openai.generate_speech(text=tts_query)
await update.effective_message.reply_voice(
reply_to_message_id=get_reply_to_message_id(self.config, update),
voice=speech_file
)
speech_file.close()
# add image request to users usage tracker
user_id = update.message.from_user.id
self.usage[user_id].add_tts_request(text_length, self.config['tts_model'], self.config['tts_prices'])
# add guest chat request to guest usage tracker
if str(user_id) not in self.config['allowed_user_ids'].split(',') and 'guests' in self.usage:
self.usage["guests"].add_tts_request(text_length, self.config['tts_model'], self.config['tts_prices'])
except Exception as e:
logging.exception(e)
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),
text=f"{localized_text('tts_fail', self.config['bot_language'])}: {str(e)}",
parse_mode=constants.ParseMode.MARKDOWN
)
await wrap_with_indicator(update, context, _generate, constants.ChatAction.UPLOAD_VOICE)
async def transcribe(self, update: Update, context: ContextTypes.DEFAULT_TYPE): async def transcribe(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
""" """
Transcribe audio messages. Transcribe audio messages.
@@ -909,6 +977,7 @@ class ChatGPTTelegramBot:
application.add_handler(CommandHandler('reset', self.reset)) application.add_handler(CommandHandler('reset', self.reset))
application.add_handler(CommandHandler('help', self.help)) application.add_handler(CommandHandler('help', self.help))
application.add_handler(CommandHandler('image', self.image)) application.add_handler(CommandHandler('image', self.image))
application.add_handler(CommandHandler('tts', self.tts))
application.add_handler(CommandHandler('start', self.help)) application.add_handler(CommandHandler('start', self.help))
application.add_handler(CommandHandler('stats', self.stats)) application.add_handler(CommandHandler('stats', self.stats))
application.add_handler(CommandHandler('resend', self.resend)) application.add_handler(CommandHandler('resend', self.resend))

View File

@@ -56,8 +56,10 @@ class UsageTracker:
if os.path.isfile(self.user_file): if os.path.isfile(self.user_file):
with open(self.user_file, "r") as file: with open(self.user_file, "r") as file:
self.usage = json.load(file) self.usage = json.load(file)
if 'vision_tokens' not in self.usage['usage_history']: if 'vision_tokens' not in self.usage['usage_history']:
self.usage['usage_history']['vision_tokens'] = {} self.usage['usage_history']['vision_tokens'] = {}
if 'tts_characters' not in self.usage['usage_history']:
self.usage['usage_history']['tts_characters'] = {}
else: else:
# ensure directory exists # ensure directory exists
pathlib.Path(logs_dir).mkdir(exist_ok=True) pathlib.Path(logs_dir).mkdir(exist_ok=True)
@@ -65,7 +67,7 @@ class UsageTracker:
self.usage = { self.usage = {
"user_name": user_name, "user_name": user_name,
"current_cost": {"day": 0.0, "month": 0.0, "all_time": 0.0, "last_update": str(date.today())}, "current_cost": {"day": 0.0, "month": 0.0, "all_time": 0.0, "last_update": str(date.today())},
"usage_history": {"chat_tokens": {}, "transcription_seconds": {}, "number_images": {}, "vision_tokens":{}} "usage_history": {"chat_tokens": {}, "transcription_seconds": {}, "number_images": {}, "tts_characters": {}, "vision_tokens":{}}
} }
# token usage functions: # token usage functions:
@@ -194,6 +196,57 @@ class UsageTracker:
tokens_month += tokens tokens_month += tokens
return tokens_day, tokens_month return tokens_day, tokens_month
# tts usage functions:
def add_tts_request(self, text_length, tts_model, tts_prices):
tts_models = ['tts-1', 'tts-1-hd']
price = tts_prices[tts_models.index(tts_model)]
today = date.today()
tts_price = round(text_length * price / 1000, 2)
self.add_current_costs(tts_price)
if 'tts_characters' not in self.usage['usage_history']:
self.usage['usage_history']['tts_characters'] = {}
if tts_model not in self.usage['usage_history']['tts_characters']:
self.usage['usage_history']['tts_characters'][tts_model] = {}
# update usage_history
if str(today) in self.usage["usage_history"]["tts_characters"][tts_model]:
# add requested text length to existing date
self.usage["usage_history"]["tts_characters"][tts_model][str(today)] += text_length
else:
# create new entry for current date
self.usage["usage_history"]["tts_characters"][tts_model][str(today)] = text_length
# write updated token usage to user file
with open(self.user_file, "w") as outfile:
json.dump(self.usage, outfile)
def get_current_tts_usage(self):
"""Get length of speech generated for today and this month.
:return: total amount of characters converted to speech per day and per month
"""
tts_models = ['tts-1', 'tts-1-hd']
today = date.today()
characters_day = 0
for tts_model in tts_models:
if tts_model in self.usage["usage_history"]["tts_characters"] and \
str(today) in self.usage["usage_history"]["tts_characters"][tts_model]:
characters_day += self.usage["usage_history"]["tts_characters"][tts_model][str(today)]
month = str(today)[:7] # year-month as string
characters_month = 0
for tts_model in tts_models:
if tts_model in self.usage["usage_history"]["tts_characters"]:
for today, characters in self.usage["usage_history"]["tts_characters"][tts_model].items():
if today.startswith(month):
characters_month += characters
return int(characters_day), int(characters_month)
# transcription usage functions: # transcription usage functions:
def add_transcription_seconds(self, seconds, minute_price=0.006): def add_transcription_seconds(self, seconds, minute_price=0.006):
@@ -279,14 +332,15 @@ class UsageTracker:
cost_all_time = self.usage["current_cost"].get("all_time", self.initialize_all_time_cost()) cost_all_time = self.usage["current_cost"].get("all_time", self.initialize_all_time_cost())
return {"cost_today": cost_day, "cost_month": cost_month, "cost_all_time": cost_all_time} return {"cost_today": cost_day, "cost_month": cost_month, "cost_all_time": cost_all_time}
def initialize_all_time_cost(self, tokens_price=0.002, image_prices="0.016,0.018,0.02", minute_price=0.006, vision_token_price=0.01): def initialize_all_time_cost(self, tokens_price=0.002, image_prices="0.016,0.018,0.02", minute_price=0.006, vision_token_price=0.01, tts_prices='0.015,0.030'):
"""Get total USD amount of all requests in history """Get total USD amount of all requests in history
:param tokens_price: price per 1000 tokens, defaults to 0.002 :param tokens_price: price per 1000 tokens, defaults to 0.002
:param image_prices: prices for images of sizes ["256x256", "512x512", "1024x1024"], :param image_prices: prices for images of sizes ["256x256", "512x512", "1024x1024"],
defaults to [0.016, 0.018, 0.02] defaults to [0.016, 0.018, 0.02]
:param minute_price: price per minute transcription, defaults to 0.006 :param minute_price: price per minute transcription, defaults to 0.006
:param vision_token_price: price per 1k vision token interpretation, defaults to 0.01 :param vision_token_price: price per 1K vision token interpretation, defaults to 0.01
:param tts_prices: price per 1K characters tts per model ['tts-1', 'tts-1-hd'], defaults to [0.015, 0.030]
:return: total cost of all requests :return: total cost of all requests
""" """
total_tokens = sum(self.usage['usage_history']['chat_tokens'].values()) total_tokens = sum(self.usage['usage_history']['chat_tokens'].values())
@@ -302,5 +356,9 @@ class UsageTracker:
total_vision_tokens = sum(self.usage['usage_history']['vision_tokens'].values()) total_vision_tokens = sum(self.usage['usage_history']['vision_tokens'].values())
vision_cost = round(total_vision_tokens * vision_token_price / 1000, 2) vision_cost = round(total_vision_tokens * vision_token_price / 1000, 2)
all_time_cost = token_cost + transcription_cost + image_cost + vision_cost total_characters = [sum(tts_model.values()) for tts_model in self.usage['usage_history']['tts_characters'].values()]
tts_prices_list = [float(x) for x in tts_prices.split(',')]
tts_cost = round(sum([count * price / 1000 for count, price in zip(total_characters, tts_prices_list)]), 2)
all_time_cost = token_cost + transcription_cost + image_cost + vision_cost + tts_cost
return all_time_cost return all_time_cost

View File

@@ -1,7 +1,7 @@
python-dotenv~=1.0.0 python-dotenv~=1.0.0
pydub~=0.25.1 pydub~=0.25.1
tiktoken==0.5.1 tiktoken==0.5.1
openai==1.1.1 openai==1.3.3
python-telegram-bot==20.3 python-telegram-bot==20.3
requests~=2.31.0 requests~=2.31.0
tenacity==8.2.2 tenacity==8.2.2
@@ -11,4 +11,4 @@ spotipy~=2.23.0
pytube~=15.0.0 pytube~=15.0.0
gtts~=2.3.2 gtts~=2.3.2
whois~=0.9.27 whois~=0.9.27
Pillow~=10.1.0 Pillow~=10.1.0

View File

@@ -3,6 +3,7 @@
"help_description":"Show help message", "help_description":"Show help message",
"reset_description":"Reset the conversation. Optionally pass high-level instructions (e.g. /reset You are a helpful assistant)", "reset_description":"Reset the conversation. Optionally pass high-level instructions (e.g. /reset You are a helpful assistant)",
"image_description":"Generate image from prompt (e.g. /image cat)", "image_description":"Generate image from prompt (e.g. /image cat)",
"tts_description":"Generate speech from text (e.g. /tts my house)",
"stats_description":"Get your current usage statistics", "stats_description":"Get your current usage statistics",
"resend_description":"Resend the latest message", "resend_description":"Resend the latest message",
"chat_description":"Chat with the bot!", "chat_description":"Chat with the bot!",
@@ -15,6 +16,7 @@
"stats_tokens":"tokens", "stats_tokens":"tokens",
"stats_images":"images generated", "stats_images":"images generated",
"stats_vision":"image tokens interpreted", "stats_vision":"image tokens interpreted",
"stats_tts":"characters converted to speech",
"stats_transcribe":["minutes and", "seconds transcribed"], "stats_transcribe":["minutes and", "seconds transcribed"],
"stats_total":"💰 For a total amount of $", "stats_total":"💰 For a total amount of $",
"stats_budget":"Your remaining budget", "stats_budget":"Your remaining budget",
@@ -27,6 +29,8 @@
"image_no_prompt":"Please provide a prompt! (e.g. /image cat)", "image_no_prompt":"Please provide a prompt! (e.g. /image cat)",
"image_fail":"Failed to generate image", "image_fail":"Failed to generate image",
"vision_fail":"Failed to interpret image", "vision_fail":"Failed to interpret image",
"tts_no_prompt":"Please provide text! (e.g. /tts my house)",
"tts_fail":"Failed to generate speech",
"media_download_fail":["Failed to download audio file", "Make sure the file is not too large. (max 20MB)"], "media_download_fail":["Failed to download audio file", "Make sure the file is not too large. (max 20MB)"],
"media_type_fail":"Unsupported file type", "media_type_fail":"Unsupported file type",
"transcript":"Transcript", "transcript":"Transcript",
@@ -48,6 +52,7 @@
"help_description":"Muestra el mensaje de ayuda", "help_description":"Muestra el mensaje de ayuda",
"reset_description":"Reinicia la conversación. Opcionalmente, pasa instrucciones de alto nivel (por ejemplo, /reset Eres un asistente útil)", "reset_description":"Reinicia la conversación. Opcionalmente, pasa instrucciones de alto nivel (por ejemplo, /reset Eres un asistente útil)",
"image_description":"Genera una imagen a partir de una sugerencia (por ejemplo, /image gato)", "image_description":"Genera una imagen a partir de una sugerencia (por ejemplo, /image gato)",
"tts_description":"Genera voz a partir de texto (por ejemplo, /tts mi casa)",
"stats_description":"Obtén tus estadísticas de uso actuales", "stats_description":"Obtén tus estadísticas de uso actuales",
"resend_description":"Reenvía el último mensaje", "resend_description":"Reenvía el último mensaje",
"chat_description":"¡Chatea con el bot!", "chat_description":"¡Chatea con el bot!",
@@ -59,6 +64,7 @@
"usage_month":"Uso este mes", "usage_month":"Uso este mes",
"stats_tokens":"tokens de chat usados", "stats_tokens":"tokens de chat usados",
"stats_images":"imágenes generadas", "stats_images":"imágenes generadas",
"stats_tts":"caracteres convertidos a voz",
"stats_transcribe":["minutos y", "segundos transcritos"], "stats_transcribe":["minutos y", "segundos transcritos"],
"stats_total":"💰 Por un monto total de $", "stats_total":"💰 Por un monto total de $",
"stats_budget":"Tu presupuesto restante", "stats_budget":"Tu presupuesto restante",
@@ -70,6 +76,8 @@
"reset_done":"¡Listo!", "reset_done":"¡Listo!",
"image_no_prompt":"¡Por favor proporciona una sugerencia! (por ejemplo, /image gato)", "image_no_prompt":"¡Por favor proporciona una sugerencia! (por ejemplo, /image gato)",
"image_fail":"No se pudo generar la imagen", "image_fail":"No se pudo generar la imagen",
"tts_no_prompt":"¡Por favor proporciona texto! (por ejemplo, /tts mi casa)",
"tts_fail":"No se pudo generar la voz",
"media_download_fail":["No se pudo descargar el archivo de audio", "Asegúrate de que el archivo no sea demasiado grande. (máx. 20MB)"], "media_download_fail":["No se pudo descargar el archivo de audio", "Asegúrate de que el archivo no sea demasiado grande. (máx. 20MB)"],
"media_type_fail":"Tipo de archivo no compatible", "media_type_fail":"Tipo de archivo no compatible",
"transcript":"Transcripción", "transcript":"Transcripción",
@@ -91,6 +99,7 @@
"help_description": "Mostra a mensagem de ajuda", "help_description": "Mostra a mensagem de ajuda",
"reset_description": "Redefine a conversa. Opcionalmente, passe instruções de alto nível (por exemplo, /reset Você é um assistente útil)", "reset_description": "Redefine a conversa. Opcionalmente, passe instruções de alto nível (por exemplo, /reset Você é um assistente útil)",
"image_description": "Gera uma imagem a partir do prompt (por exemplo, /image gato)", "image_description": "Gera uma imagem a partir do prompt (por exemplo, /image gato)",
"tts_description": "Gera fala a partir do texto (por exemplo, /tts minha casa)",
"stats_description": "Obtenha suas estatísticas de uso atuais", "stats_description": "Obtenha suas estatísticas de uso atuais",
"resend_description": "Reenvia a última mensagem", "resend_description": "Reenvia a última mensagem",
"chat_description": "Converse com o bot!", "chat_description": "Converse com o bot!",
@@ -102,6 +111,7 @@
"usage_month": "Uso este mês", "usage_month": "Uso este mês",
"stats_tokens": "tokens de chat usados", "stats_tokens": "tokens de chat usados",
"stats_images": "imagens geradas", "stats_images": "imagens geradas",
"stats_tts": "caracteres convertidos em fala",
"stats_transcribe": ["minutos e", "segundos transcritos"], "stats_transcribe": ["minutos e", "segundos transcritos"],
"stats_total": "💰 Para um valor total de $", "stats_total": "💰 Para um valor total de $",
"stats_budget": "Seu orçamento restante", "stats_budget": "Seu orçamento restante",
@@ -113,6 +123,8 @@
"reset_done": "Feito!", "reset_done": "Feito!",
"image_no_prompt": "Por favor, forneça um prompt! (por exemplo, /image gato)", "image_no_prompt": "Por favor, forneça um prompt! (por exemplo, /image gato)",
"image_fail": "Falha ao gerar imagem", "image_fail": "Falha ao gerar imagem",
"tts_no_prompt": "Por favor, forneça texto! (por exemplo, /tts minha casa)",
"tts_fail": "Falha ao gerar fala",
"media_download_fail": ["Falha ao baixar arquivo de áudio", "Certifique-se de que o arquivo não seja muito grande. (máx. 20 MB)"], "media_download_fail": ["Falha ao baixar arquivo de áudio", "Certifique-se de que o arquivo não seja muito grande. (máx. 20 MB)"],
"media_type_fail": "Tipo de arquivo não suportado", "media_type_fail": "Tipo de arquivo não suportado",
"transcript": "Transcrição", "transcript": "Transcrição",
@@ -134,6 +146,7 @@
"help_description":"Zeige die Hilfenachricht", "help_description":"Zeige die Hilfenachricht",
"reset_description":"Setze die Konversation zurück. Optionale Eingabe einer grundlegenden Anweisung (z.B. /reset Du bist ein hilfreicher Assistent)", "reset_description":"Setze die Konversation zurück. Optionale Eingabe einer grundlegenden Anweisung (z.B. /reset Du bist ein hilfreicher Assistent)",
"image_description":"Erzeuge ein Bild aus einer Aufforderung (z.B. /image Katze)", "image_description":"Erzeuge ein Bild aus einer Aufforderung (z.B. /image Katze)",
"tts_description":"Erzeuge Sprache aus Text (z.B. /tts mein Haus)",
"stats_description":"Zeige aktuelle Benutzungstatistiken", "stats_description":"Zeige aktuelle Benutzungstatistiken",
"resend_description":"Wiederhole das Senden der letzten Nachricht", "resend_description":"Wiederhole das Senden der letzten Nachricht",
"chat_description":"Schreibe mit dem Bot!", "chat_description":"Schreibe mit dem Bot!",
@@ -145,6 +158,7 @@
"usage_month":"Nutzung diesen Monat", "usage_month":"Nutzung diesen Monat",
"stats_tokens":"Chat Tokens verwendet", "stats_tokens":"Chat Tokens verwendet",
"stats_images":"Bilder generiert", "stats_images":"Bilder generiert",
"stats_tts":"Zeichen in Sprache umgewandelt",
"stats_transcribe":["Minuten und", "Sekunden abgeschrieben"], "stats_transcribe":["Minuten und", "Sekunden abgeschrieben"],
"stats_total":"💰 Für einem Gesamtbetrag von $", "stats_total":"💰 Für einem Gesamtbetrag von $",
"stats_budget":"Dein verbliebenes Budget", "stats_budget":"Dein verbliebenes Budget",
@@ -156,6 +170,8 @@
"reset_done":"Fertig!", "reset_done":"Fertig!",
"image_no_prompt":"Bitte füge eine Aufforderung hinzu (z.B. /image Katze)", "image_no_prompt":"Bitte füge eine Aufforderung hinzu (z.B. /image Katze)",
"image_fail":"Fehler beim Generieren eines Bildes", "image_fail":"Fehler beim Generieren eines Bildes",
"tts_no_prompt":"Bitte füge Text hinzu! (z.B. /tts mein Haus)",
"tts_fail":"Fehler beim Generieren von Sprache",
"media_download_fail":["Fehler beim Herunterladen der Audiodatei", "Die Datei könnte zu groß sein. (max 20MB)"], "media_download_fail":["Fehler beim Herunterladen der Audiodatei", "Die Datei könnte zu groß sein. (max 20MB)"],
"media_type_fail":"Dateityp nicht unterstützt", "media_type_fail":"Dateityp nicht unterstützt",
"transcript":"Abschrift", "transcript":"Abschrift",
@@ -177,6 +193,7 @@
"help_description":"Näytä ohjeet", "help_description":"Näytä ohjeet",
"reset_description":"Nollaa keskustelu. Voit myös antaa korkean tason ohjeita (esim. /reset Olet avulias avustaja)", "reset_description":"Nollaa keskustelu. Voit myös antaa korkean tason ohjeita (esim. /reset Olet avulias avustaja)",
"image_description":"Luo kuva tekstistä (esim. /image kissa)", "image_description":"Luo kuva tekstistä (esim. /image kissa)",
"tts_description":"Muuta teksti puheeksi (esim. /tts taloni)",
"stats_description":"Hae tämän hetken käyttötilastot", "stats_description":"Hae tämän hetken käyttötilastot",
"resend_description":"Lähetä viimeisin viesti uudestaan", "resend_description":"Lähetä viimeisin viesti uudestaan",
"chat_description":"Keskustele botin kanssa!", "chat_description":"Keskustele botin kanssa!",
@@ -188,6 +205,7 @@
"usage_month":"Käyttö tässä kuussa", "usage_month":"Käyttö tässä kuussa",
"stats_tokens":"viestipolettia käytetty", "stats_tokens":"viestipolettia käytetty",
"stats_images":"kuvaa luotu", "stats_images":"kuvaa luotu",
"stats_tts":"merkkiä muutettu puheeksi",
"stats_transcribe":["minuuttia ja", "sekuntia litteroitu"], "stats_transcribe":["minuuttia ja", "sekuntia litteroitu"],
"stats_total":"💰 Yhteensä $", "stats_total":"💰 Yhteensä $",
"stats_budget":"Jäljellä oleva budjettisi", "stats_budget":"Jäljellä oleva budjettisi",
@@ -199,6 +217,8 @@
"reset_done":"Valmis!", "reset_done":"Valmis!",
"image_no_prompt":"Ole hyvä ja anna ohjeet! (esim. /image kissa)", "image_no_prompt":"Ole hyvä ja anna ohjeet! (esim. /image kissa)",
"image_fail":"Kuvan luonti epäonnistui", "image_fail":"Kuvan luonti epäonnistui",
"tts_no_prompt":"Ole hyvä ja anna teksti! (esim. /tts taloni)",
"tts_fail":"Puheen luonti epäonnistui",
"media_download_fail":["Äänitiedoston lataus epäonnistui", "Varmista että se ei ole liian iso. (enintään 20MB)"], "media_download_fail":["Äänitiedoston lataus epäonnistui", "Varmista että se ei ole liian iso. (enintään 20MB)"],
"media_type_fail":"Tiedostomuoto ei tuettu", "media_type_fail":"Tiedostomuoto ei tuettu",
"transcript":"Litteroitu teksti", "transcript":"Litteroitu teksti",
@@ -220,6 +240,7 @@
"help_description":"Показать справочное сообщение", "help_description":"Показать справочное сообщение",
"reset_description":"Перезагрузить разговор. По желанию передай общие инструкции (например, /reset ты полезный помощник)", "reset_description":"Перезагрузить разговор. По желанию передай общие инструкции (например, /reset ты полезный помощник)",
"image_description":"Создать изображение по запросу (например, /image кошка)", "image_description":"Создать изображение по запросу (например, /image кошка)",
"tts_description":"Создать речь из текста (например, /tts мой дом)",
"stats_description":"Получить статистику использования", "stats_description":"Получить статистику использования",
"resend_description":"Повторная отправка последнего сообщения", "resend_description":"Повторная отправка последнего сообщения",
"chat_description":"Общайся с ботом!", "chat_description":"Общайся с ботом!",
@@ -231,6 +252,7 @@
"usage_month":"Использование в этом месяце", "usage_month":"Использование в этом месяце",
"stats_tokens":"токенов чата использовано", "stats_tokens":"токенов чата использовано",
"stats_images":"изображений создано", "stats_images":"изображений создано",
"stats_tts":"символов преобразовано в речь",
"stats_transcribe":["минут(ы) и", "секунд(ы) расшифровки"], "stats_transcribe":["минут(ы) и", "секунд(ы) расшифровки"],
"stats_total":"💰 На общую сумму $", "stats_total":"💰 На общую сумму $",
"stats_budget":"Остаточный бюджет", "stats_budget":"Остаточный бюджет",
@@ -242,6 +264,8 @@
"reset_done":"Готово!", "reset_done":"Готово!",
"image_no_prompt":"Пожалуйста, подайте запрос! (например, /image кошка)", "image_no_prompt":"Пожалуйста, подайте запрос! (например, /image кошка)",
"image_fail":"Не удалось создать изображение", "image_fail":"Не удалось создать изображение",
"tts_no_prompt":"Пожалуйста, подайте текст! (например, /tts мой дом)",
"tts_fail":"Не удалось создать речь",
"media_download_fail":["Не удалось загрузить аудиофайл", "Проверьте, чтобы файл не был слишком большим. (не более 20 МБ)"], "media_download_fail":["Не удалось загрузить аудиофайл", "Проверьте, чтобы файл не был слишком большим. (не более 20 МБ)"],
"media_type_fail":"Неподдержанный тип файла", "media_type_fail":"Неподдержанный тип файла",
"transcript":"Расшифровка", "transcript":"Расшифровка",
@@ -263,6 +287,7 @@
"help_description":"Yardım mesajını göster", "help_description":"Yardım mesajını göster",
"reset_description":"Konuşmayı sıfırla. İsteğe bağlı olarak botun nasıl davranacağını belirleyin (Örneğin: /reset Sen yardımcı bir asistansın)", "reset_description":"Konuşmayı sıfırla. İsteğe bağlı olarak botun nasıl davranacağını belirleyin (Örneğin: /reset Sen yardımcı bir asistansın)",
"image_description":"Verilen komuta göre görüntü üret (Örneğin /image kedi)", "image_description":"Verilen komuta göre görüntü üret (Örneğin /image kedi)",
"tts_description":"Verilen metni seslendir (Örneğin /tts evim)",
"stats_description":"Mevcut kullanım istatistiklerinizi alın", "stats_description":"Mevcut kullanım istatistiklerinizi alın",
"resend_description":"En son mesajı yeniden gönder", "resend_description":"En son mesajı yeniden gönder",
"chat_description":"Bot ile sohbet edin!", "chat_description":"Bot ile sohbet edin!",
@@ -274,6 +299,7 @@
"usage_month":"Bu ayki kullanım", "usage_month":"Bu ayki kullanım",
"stats_tokens":"sohbet token'i kullanıldı", "stats_tokens":"sohbet token'i kullanıldı",
"stats_images":"görüntüler oluşturuldu", "stats_images":"görüntüler oluşturuldu",
"stats_tts":"seslendirilen karakterler",
"stats_transcribe":["dakika", "saniye sesten yazıya çeviri yapıldı"], "stats_transcribe":["dakika", "saniye sesten yazıya çeviri yapıldı"],
"stats_total":"💰 Bu kullanımların toplam maliyeti $", "stats_total":"💰 Bu kullanımların toplam maliyeti $",
"stats_budget":"Kalan bütçeniz", "stats_budget":"Kalan bütçeniz",
@@ -285,6 +311,8 @@
"reset_done":"Tamamlandı!", "reset_done":"Tamamlandı!",
"image_no_prompt":"Lütfen komut giriniz (Örneğin /image kedi)", "image_no_prompt":"Lütfen komut giriniz (Örneğin /image kedi)",
"image_fail":"Görüntü oluşturulamadı", "image_fail":"Görüntü oluşturulamadı",
"tts_no_prompt":"Lütfen metin giriniz (Örneğin /tts evim)",
"tts_fail":"Seslendirme oluşturulamadı",
"media_download_fail":["Ses dosyası indirilemedi", "Dosyanın çok büyük olmadığından emin olun. (maksimum 20MB)"], "media_download_fail":["Ses dosyası indirilemedi", "Dosyanın çok büyük olmadığından emin olun. (maksimum 20MB)"],
"media_type_fail":"Desteklenmeyen dosya türü", "media_type_fail":"Desteklenmeyen dosya türü",
"transcript":"Yazıya çevirilmiş hali", "transcript":"Yazıya çevirilmiş hali",
@@ -306,6 +334,7 @@
"help_description":"Mostra il messaggio di aiuto", "help_description":"Mostra il messaggio di aiuto",
"reset_description":"Resetta la conversazione. Puoi anche specificare ulteriori istruzioni (ad esempio, /reset Sei un assistente utile).", "reset_description":"Resetta la conversazione. Puoi anche specificare ulteriori istruzioni (ad esempio, /reset Sei un assistente utile).",
"image_description":"Genera immagine da un testo (ad es. /image gatto)", "image_description":"Genera immagine da un testo (ad es. /image gatto)",
"tts_description":"Genera audio da un testo (ad es. /tts la mia casa)",
"stats_description":"Mostra le statistiche di utilizzo", "stats_description":"Mostra le statistiche di utilizzo",
"resend_description":"Reinvia l'ultimo messaggio", "resend_description":"Reinvia l'ultimo messaggio",
"chat_description":"Chatta con il bot!", "chat_description":"Chatta con il bot!",
@@ -317,6 +346,7 @@
"usage_month":"Utilizzo questo mese", "usage_month":"Utilizzo questo mese",
"stats_tokens":"token utilizzati", "stats_tokens":"token utilizzati",
"stats_images":"immagini generate", "stats_images":"immagini generate",
"stats_tts":"caratteri convertiti in audio",
"stats_transcribe":["minuti", "secondi trascritti"], "stats_transcribe":["minuti", "secondi trascritti"],
"stats_total":"💰 Per un totale di $", "stats_total":"💰 Per un totale di $",
"stats_budget":"Budget rimanente", "stats_budget":"Budget rimanente",
@@ -328,6 +358,8 @@
"reset_done":"Fatto!", "reset_done":"Fatto!",
"image_no_prompt":"Inserisci un testo (ad es. /image gatto)", "image_no_prompt":"Inserisci un testo (ad es. /image gatto)",
"image_fail":"Impossibile generare l'immagine", "image_fail":"Impossibile generare l'immagine",
"tts_no_prompt":"Inserisci un testo (ad es. /tts la mia casa)",
"tts_fail":"Impossibile generare l'audio",
"media_download_fail":["Impossibile processare il file audio", "Assicurati che il file non sia troppo pesante (massimo 20MB)"], "media_download_fail":["Impossibile processare il file audio", "Assicurati che il file non sia troppo pesante (massimo 20MB)"],
"media_type_fail":"Tipo di file non supportato", "media_type_fail":"Tipo di file non supportato",
"transcript":"Trascrizione", "transcript":"Trascrizione",
@@ -349,6 +381,7 @@
"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)",
"image_description": "Menghasilkan gambar dari input prompt (misalnya /image kucing)", "image_description": "Menghasilkan gambar dari input prompt (misalnya /image kucing)",
"tts_description": "Menghasilkan suara dari teks (misalnya /tts rumah saya)",
"stats_description": "Mendapatkan statistik penggunaan saat ini", "stats_description": "Mendapatkan statistik penggunaan saat ini",
"resend_description": "Mengirim kembali pesan terakhir", "resend_description": "Mengirim kembali pesan terakhir",
"chat_description": "Berkonversasi dengan bot!", "chat_description": "Berkonversasi dengan bot!",
@@ -360,6 +393,7 @@
"usage_month": "Penggunaan bulan ini", "usage_month": "Penggunaan bulan ini",
"stats_tokens": "token obrolan yang digunakan", "stats_tokens": "token obrolan yang digunakan",
"stats_images": "gambar yang dihasilkan", "stats_images": "gambar yang dihasilkan",
"stats_tts": "karakter dikonversi ke suara",
"stats_transcribe": ["menit dan", "detik ditranskripsi"], "stats_transcribe": ["menit dan", "detik ditranskripsi"],
"stats_total": "💰 Untuk total sebesar $", "stats_total": "💰 Untuk total sebesar $",
"stats_budget": "Sisa anggaran Anda", "stats_budget": "Sisa anggaran Anda",
@@ -371,6 +405,8 @@
"reset_done": "Selesai!", "reset_done": "Selesai!",
"image_no_prompt": "Harap berikan prompt! (misalnya /image kucing)", "image_no_prompt": "Harap berikan prompt! (misalnya /image kucing)",
"image_fail": "Gagal menghasilkan gambar", "image_fail": "Gagal menghasilkan gambar",
"tts_no_prompt": "Harap berikan teks! (misalnya /tts rumah saya)",
"tts_fail": "Gagal menghasilkan suara",
"media_download_fail": ["Gagal mengunduh file audio", "Pastikan file tidak terlalu besar. (maksimal 20MB)"], "media_download_fail": ["Gagal mengunduh file audio", "Pastikan file tidak terlalu besar. (maksimal 20MB)"],
"media_type_fail": "Tipe file tidak didukung", "media_type_fail": "Tipe file tidak didukung",
"transcript": "Transkrip", "transcript": "Transkrip",
@@ -392,6 +428,7 @@
"help_description":"Toon uitleg", "help_description":"Toon uitleg",
"reset_description":"Herstart het gesprek. Voeg eventueel instructies toe (bijv. /reset Je bent een behulpzame assistent)", "reset_description":"Herstart het gesprek. Voeg eventueel instructies toe (bijv. /reset Je bent een behulpzame assistent)",
"image_description":"Genereer een afbeelding van een prompt (bijv. /image kat)", "image_description":"Genereer een afbeelding van een prompt (bijv. /image kat)",
"tts_description":"Genereer spraak van tekst (bijv. /tts mijn huis)",
"stats_description":"Bekijk je huidige gebruiksstatistieken", "stats_description":"Bekijk je huidige gebruiksstatistieken",
"resend_description":"Verstuur het laatste bericht opnieuw", "resend_description":"Verstuur het laatste bericht opnieuw",
"chat_description":"Chat met de bot!", "chat_description":"Chat met de bot!",
@@ -403,6 +440,7 @@
"usage_month":"Gebruik deze maand", "usage_month":"Gebruik deze maand",
"stats_tokens":"chat tokens gebruikt", "stats_tokens":"chat tokens gebruikt",
"stats_images":"afbeeldingen gegenereerd", "stats_images":"afbeeldingen gegenereerd",
"stats_tts":"karakters omgezet naar spraak",
"stats_transcribe":["minuten en", "seconden audio naar tekst omgezet"], "stats_transcribe":["minuten en", "seconden audio naar tekst omgezet"],
"stats_total":"💰 Voor een totaal van $", "stats_total":"💰 Voor een totaal van $",
"stats_budget":"Je resterende budget", "stats_budget":"Je resterende budget",
@@ -414,6 +452,8 @@
"reset_done":"Klaar!", "reset_done":"Klaar!",
"image_no_prompt":"Geef a.u.b. een prompt! (bijv. /image kat)", "image_no_prompt":"Geef a.u.b. een prompt! (bijv. /image kat)",
"image_fail":"Afbeelding genereren mislukt", "image_fail":"Afbeelding genereren mislukt",
"tts_no_prompt":"Geef a.u.b. tekst! (bijv. /tts mijn huis)",
"tts_fail":"Spraak genereren mislukt",
"media_download_fail":["Audio bestand downloaden mislukt", "Check of het niet te groot is. (max 20MB)"], "media_download_fail":["Audio bestand downloaden mislukt", "Check of het niet te groot is. (max 20MB)"],
"media_type_fail":"Niet ondersteund bestandsformaat", "media_type_fail":"Niet ondersteund bestandsformaat",
"transcript":"Uitgeschreven tekst", "transcript":"Uitgeschreven tekst",
@@ -435,6 +475,7 @@
"help_description":"显示帮助信息", "help_description":"显示帮助信息",
"reset_description":"重置对话。可以选择传递高级指令(例如/reset 你是一个有用的助手)", "reset_description":"重置对话。可以选择传递高级指令(例如/reset 你是一个有用的助手)",
"image_description":"根据提示生成图像(例如/image 猫)", "image_description":"根据提示生成图像(例如/image 猫)",
"tts_description":"将文本转换为语音(例如/tts 我的房子)",
"stats_description":"获取您当前的使用统计", "stats_description":"获取您当前的使用统计",
"resend_description":"重新发送最近的消息", "resend_description":"重新发送最近的消息",
"chat_description":"与机器人聊天!", "chat_description":"与机器人聊天!",
@@ -446,6 +487,7 @@
"usage_month":"本月使用情况", "usage_month":"本月使用情况",
"stats_tokens":"使用的token", "stats_tokens":"使用的token",
"stats_images":"生成图像的数量", "stats_images":"生成图像的数量",
"stats_tts":"转换为语音的字符",
"stats_transcribe":["分钟", "秒转录时长"], "stats_transcribe":["分钟", "秒转录时长"],
"stats_total":"💰 总计金额 $", "stats_total":"💰 总计金额 $",
"stats_budget":"您的剩余预算", "stats_budget":"您的剩余预算",
@@ -457,6 +499,8 @@
"reset_done":"完成!", "reset_done":"完成!",
"image_no_prompt":"请提供提示!(例如/image 猫)", "image_no_prompt":"请提供提示!(例如/image 猫)",
"image_fail":"生成图像失败", "image_fail":"生成图像失败",
"tts_no_prompt":"请提供文本!(例如/tts 我的房子)",
"tts_fail":"生成语音失败",
"media_download_fail":["下载音频文件失败", "请确保文件不要太大最大20MB"], "media_download_fail":["下载音频文件失败", "请确保文件不要太大最大20MB"],
"media_type_fail":"不支持的文件类型", "media_type_fail":"不支持的文件类型",
"transcript":"转录", "transcript":"转录",
@@ -478,6 +522,7 @@
"help_description":"顯示幫助訊息", "help_description":"顯示幫助訊息",
"reset_description":"重設對話。可以選擇傳遞進階指令(例如 /reset 你是一個樂於助人的助手)", "reset_description":"重設對話。可以選擇傳遞進階指令(例如 /reset 你是一個樂於助人的助手)",
"image_description":"根據提示生成圖片(例如 /image 貓)", "image_description":"根據提示生成圖片(例如 /image 貓)",
"tts_description":"將文字轉換為語音(例如 /tts 我的房子)",
"stats_description":"取得當前使用統計", "stats_description":"取得當前使用統計",
"resend_description":"重新傳送最後一則訊息", "resend_description":"重新傳送最後一則訊息",
"chat_description":"與機器人聊天!", "chat_description":"與機器人聊天!",
@@ -489,6 +534,7 @@
"usage_month":"本月用量", "usage_month":"本月用量",
"stats_tokens":"Token 已使用", "stats_tokens":"Token 已使用",
"stats_images":"圖片已生成", "stats_images":"圖片已生成",
"stats_tts":"轉換為語音的字元",
"stats_transcribe":["分", "秒已轉錄"], "stats_transcribe":["分", "秒已轉錄"],
"stats_total":"💰 總計金額 $", "stats_total":"💰 總計金額 $",
"stats_budget":"剩餘預算", "stats_budget":"剩餘預算",
@@ -500,6 +546,8 @@
"reset_done":"重設完成!", "reset_done":"重設完成!",
"image_no_prompt":"請輸入提示!(例如 /image 貓)", "image_no_prompt":"請輸入提示!(例如 /image 貓)",
"image_fail":"圖片生成失敗", "image_fail":"圖片生成失敗",
"tts_no_prompt":"請輸入文字!(例如 /tts 我的房子)",
"tts_fail":"語音生成失敗",
"media_download_fail":["下載音訊檔案失敗", "請確保檔案大小不超過 20MB"], "media_download_fail":["下載音訊檔案失敗", "請確保檔案大小不超過 20MB"],
"media_type_fail":"不支援的檔案類型", "media_type_fail":"不支援的檔案類型",
"transcript":"轉錄", "transcript":"轉錄",
@@ -521,6 +569,7 @@
"help_description":"Hiển thị trợ giúp", "help_description":"Hiển thị trợ giúp",
"reset_description":"Đặt lại cuộc trò chuyện. Tùy ý chuyển hướng dẫn cấp cao (ví dụ: /reset Bạn là một trợ lý hữu ích)", "reset_description":"Đặt lại cuộc trò chuyện. Tùy ý chuyển hướng dẫn cấp cao (ví dụ: /reset Bạn là một trợ lý hữu ích)",
"image_description":"Tạo hình ảnh từ câu lệnh (ví dụ: /image cat)", "image_description":"Tạo hình ảnh từ câu lệnh (ví dụ: /image cat)",
"tts_description":"Tạo giọng nói từ văn bản (ví dụ: /tts nhà của tôi)",
"stats_description":"Nhận số liệu thống kê sử dụng hiện tại của bạn", "stats_description":"Nhận số liệu thống kê sử dụng hiện tại của bạn",
"resend_description":"Gửi lại tin nhắn mới nhất", "resend_description":"Gửi lại tin nhắn mới nhất",
"chat_description":"Trò chuyện với bot!", "chat_description":"Trò chuyện với bot!",
@@ -532,6 +581,7 @@
"usage_month":"Sử dụng trong tháng này", "usage_month":"Sử dụng trong tháng này",
"stats_tokens":"mã thông báo trò chuyện được sử dụng", "stats_tokens":"mã thông báo trò chuyện được sử dụng",
"stats_images":"hình ảnh tạo ra", "stats_images":"hình ảnh tạo ra",
"stats_tts":"ký tự được chuyển đổi thành giọng nói",
"stats_transcribe":["phút và", "giây"], "stats_transcribe":["phút và", "giây"],
"stats_total":"💰 Với tổng số tiền $", "stats_total":"💰 Với tổng số tiền $",
"stats_budget":"Ngân sách còn lại của bạn", "stats_budget":"Ngân sách còn lại của bạn",
@@ -543,6 +593,8 @@
"reset_done":"Xong!", "reset_done":"Xong!",
"image_no_prompt":"Vui lòng cung cấp lời nhắc! (ví dụ: /image con mèo", "image_no_prompt":"Vui lòng cung cấp lời nhắc! (ví dụ: /image con mèo",
"image_fail":"Không thể tạo hình ảnh", "image_fail":"Không thể tạo hình ảnh",
"tts_no_prompt":"Vui lòng cung cấp văn bản! (ví dụ: /tts nhà của tôi)",
"tts_fail":"Không thể tạo giọng nói",
"media_download_fail":["Không thể tải xuống tệp âm thanh", "Đảm bảo tệp không quá lớn. (tối đa 20 MB)"], "media_download_fail":["Không thể tải xuống tệp âm thanh", "Đảm bảo tệp không quá lớn. (tối đa 20 MB)"],
"media_type_fail":"Loại tập tin không được hỗ trợ", "media_type_fail":"Loại tập tin không được hỗ trợ",
"transcript":"Dịch", "transcript":"Dịch",
@@ -564,6 +616,7 @@
"help_description":"نمایش پیغام راهنما", "help_description":"نمایش پیغام راهنما",
"reset_description":"مکالمه را تنظیم مجدد کنید. به صورت اختیاری می‌توانید دستورالعمل های سطح بالا را ارسال کنید (به عنوان مثال /reset تو یک دستیار مفید هستی)", "reset_description":"مکالمه را تنظیم مجدد کنید. به صورت اختیاری می‌توانید دستورالعمل های سطح بالا را ارسال کنید (به عنوان مثال /reset تو یک دستیار مفید هستی)",
"image_description":"ایجاد تصویر بر اساس فرمان (به عنوان مثال /image گربه)", "image_description":"ایجاد تصویر بر اساس فرمان (به عنوان مثال /image گربه)",
"tts_description":"تبدیل متن به صدا (به عنوان مثال /tts خانه من)",
"stats_description":"آمار استفاده فعلی خود را دریافت کنید", "stats_description":"آمار استفاده فعلی خود را دریافت کنید",
"resend_description":"آخرین پیام را دوباره ارسال کنید", "resend_description":"آخرین پیام را دوباره ارسال کنید",
"chat_description":"چت با ربات!", "chat_description":"چت با ربات!",
@@ -575,6 +628,7 @@
"usage_month":"استفاده این ماه", "usage_month":"استفاده این ماه",
"stats_tokens":"توکن چت استفاده شده است", "stats_tokens":"توکن چت استفاده شده است",
"stats_images":"تصویر تولید شده است", "stats_images":"تصویر تولید شده است",
"stats_tts":"کاراکترهای تبدیل شده به صدا",
"stats_transcribe":["دقیقه و", "ثانیه رونویسی شده است"], "stats_transcribe":["دقیقه و", "ثانیه رونویسی شده است"],
"stats_total":"💰 مقدار کل مصرف: $", "stats_total":"💰 مقدار کل مصرف: $",
"stats_budget":"بودجه باقی‌مانده شما", "stats_budget":"بودجه باقی‌مانده شما",
@@ -586,6 +640,8 @@
"reset_done":"انجام شد!", "reset_done":"انجام شد!",
"image_no_prompt":"لطفا یک فرمان ارائه دهید! (به عنوان مثال /image گربه)", "image_no_prompt":"لطفا یک فرمان ارائه دهید! (به عنوان مثال /image گربه)",
"image_fail":"در تولید تصویر خطایی رخ داد", "image_fail":"در تولید تصویر خطایی رخ داد",
"tts_no_prompt":"لطفا متنی را وارد کنید! (به عنوان مثال /tts خانه من)",
"tts_fail":"در تولید صدا خطایی رخ داد",
"media_download_fail":["فایل صوتی دانلود نشد", "دقت کنید که فایل خیلی بزرگ نباشد. (حداکثر 20 مگابایت)"], "media_download_fail":["فایل صوتی دانلود نشد", "دقت کنید که فایل خیلی بزرگ نباشد. (حداکثر 20 مگابایت)"],
"media_type_fail":"نوع فایل پشتیبانی نمی‌شود", "media_type_fail":"نوع فایل پشتیبانی نمی‌شود",
"transcript":"رونوشت", "transcript":"رونوشت",
@@ -607,6 +663,7 @@
"help_description":"Показати повідомлення допомоги", "help_description":"Показати повідомлення допомоги",
"reset_description":"Скинути розмову. Опціонально передайте високорівневі інструкції (наприклад, /reset Ви корисний помічник)", "reset_description":"Скинути розмову. Опціонально передайте високорівневі інструкції (наприклад, /reset Ви корисний помічник)",
"image_description":"Створити зображення за вашим запитом (наприклад, /image кіт)", "image_description":"Створити зображення за вашим запитом (наприклад, /image кіт)",
"tts_description":"Створити голос з тексту (наприклад, /tts мій будинок)",
"stats_description":"Отримати вашу поточну статистику використання", "stats_description":"Отримати вашу поточну статистику використання",
"resend_description":"Повторно відправити останнє повідомлення", "resend_description":"Повторно відправити останнє повідомлення",
"chat_description":"Розмовляйте з ботом!", "chat_description":"Розмовляйте з ботом!",
@@ -618,6 +675,7 @@
"usage_month":"Використання цього місяця", "usage_month":"Використання цього місяця",
"stats_tokens":"використано токенів чату", "stats_tokens":"використано токенів чату",
"stats_images":"згенеровано зображень", "stats_images":"згенеровано зображень",
"stats_tts":"символів перетворено на голос",
"stats_transcribe":["хвилин і", "секунд транскрибовано"], "stats_transcribe":["хвилин і", "секунд транскрибовано"],
"stats_total":"💰 Загальна сума $", "stats_total":"💰 Загальна сума $",
"stats_budget":"Ваш залишок бюджету", "stats_budget":"Ваш залишок бюджету",
@@ -629,6 +687,8 @@
"reset_done":"Готово!", "reset_done":"Готово!",
"image_no_prompt":"Будь ласка, надайте свій запит! (наприклад, /image кіт)", "image_no_prompt":"Будь ласка, надайте свій запит! (наприклад, /image кіт)",
"image_fail":"Не вдалося створити зображення", "image_fail":"Не вдалося створити зображення",
"tts_no_prompt":"Будь ласка, надайте текст! (наприклад, /tts мій будинок)",
"tts_fail":"Не вдалося створити голос",
"media_download_fail":["Не вдалося завантажити аудіофайл", "Переконайтеся, що файл не занадто великий. (максимум 20 МБ)"], "media_download_fail":["Не вдалося завантажити аудіофайл", "Переконайтеся, що файл не занадто великий. (максимум 20 МБ)"],
"media_type_fail":"Непідтримуваний тип файлу", "media_type_fail":"Непідтримуваний тип файлу",
"transcript":"Транскрипт", "transcript":"Транскрипт",
@@ -650,6 +710,7 @@
"help_description":"Lihat Mesej Bantuan", "help_description":"Lihat Mesej Bantuan",
"reset_description":"Tetapkan semula perbualan. Secara pilihan, hantar arahan peringkat tinggi (cth. /reset Anda adalah pembantu yang membantu)", "reset_description":"Tetapkan semula perbualan. Secara pilihan, hantar arahan peringkat tinggi (cth. /reset Anda adalah pembantu yang membantu)",
"image_description":"Jana imej daripada gesaan (cth. /image cat)", "image_description":"Jana imej daripada gesaan (cth. /image cat)",
"tts_description":"Tukar teks kepada suara (cth. /tts rumah saya)",
"stats_description":"Dapatkan statistik penggunaan semasa anda", "stats_description":"Dapatkan statistik penggunaan semasa anda",
"resend_description":"Hantar semula mesej terkini", "resend_description":"Hantar semula mesej terkini",
"chat_description":"Sembang dengan bot!", "chat_description":"Sembang dengan bot!",
@@ -661,6 +722,7 @@
"usage_month":"Penggunaan bulan ini", "usage_month":"Penggunaan bulan ini",
"stats_tokens":"Token", "stats_tokens":"Token",
"stats_images":"Penghasilan", "stats_images":"Penghasilan",
"stats_tts":"Aksara yang ditukar kepada suara",
"stats_transcribe":["Minit dan", "Penterjemah yang kedua"], "stats_transcribe":["Minit dan", "Penterjemah yang kedua"],
"stats_total":"Jumlah semua 💰 dalam $", "stats_total":"Jumlah semua 💰 dalam $",
"stats_budget":"Baki yang tersisa", "stats_budget":"Baki yang tersisa",
@@ -672,6 +734,8 @@
"reset_done":"Selesai!", "reset_done":"Selesai!",
"image_no_prompt":"Sila berikan gesaan! (cth. /image cat)", "image_no_prompt":"Sila berikan gesaan! (cth. /image cat)",
"image_fail":"Gagal menjana imej", "image_fail":"Gagal menjana imej",
"tts_no_prompt":"Sila berikan teks! (cth. /tts rumah saya)",
"tts_fail":"Gagal menjana suara",
"media_download_fail":["Gagal memuat turun fail audio", "Pastikan fail tidak terlalu besar. (maks 20MB)"], "media_download_fail":["Gagal memuat turun fail audio", "Pastikan fail tidak terlalu besar. (maks 20MB)"],
"media_type_fail":"Jenis fail tidak disokong", "media_type_fail":"Jenis fail tidak disokong",
"transcript":"Transkrip", "transcript":"Transkrip",
@@ -688,5 +752,52 @@
"ask_chatgpt":"Tanya ChatGPT", "ask_chatgpt":"Tanya ChatGPT",
"loading":"Memuatkan...", "loading":"Memuatkan...",
"function_unavailable_in_inline_mode": "Fungsi ini tidak tersedia dalam mod sebaris" "function_unavailable_in_inline_mode": "Fungsi ini tidak tersedia dalam mod sebaris"
},
"uz": {
"help_description": "Yordam xabarini ko'rsatish",
"reset_description": "Suhbatni qayta boshlang. Agar xohlasangiz, umumiy ko'rsatmalar bering (masalan, /reset siz foydali yordamchisiz)",
"image_description": "Tasvirni so'rov bo'yicha yaratish (masalan, /image mushuk)",
"tts_description": "Matnni ovozga aylantirish (masalan, /tts uyim)",
"stats_description": "Hozirgi foydalanilgan statistikani olish",
"resend_description": "Oxirgi xabarni qayta yuborish",
"chat_description": "Bot bilan suxbat!",
"disallowed": "Kechirasiz, sizga bu botdan foydalanish taqiqlangan. Siz manba kodini tekshirishingiz mumkin https://github.com/n3d1117/chatgpt-telegram-bot",
"budget_limit": "Kechirasiz, siz foydalanish chegarasiga yetdingiz.",
"help_text": ["Men ChatGPT botman, men bilan gaplashing!", "Menga ovozli xabar yoki fayl yuboring, men uni siz uchun transkripsiya qilaman", "Ochiq manba: https://github.com/n3d1117/chatgpt-telegram-bot"],
"stats_conversation": ["Hozirgi suhbat", "tarixdagi chat xabarlari", "tarixdagi suhbat tokenlari"],
"usage_today": "Bugungi foydalanish",
"usage_month": "Bu oydagi foydalanish",
"stats_tokens": "tokenlar",
"stats_images": "yaratilgan tasvirlar",
"stats_tts": "ovozga aylangan belgilar",
"stats_transcribe": ["minutlar va", "soniyalar transkripsiya qilingan"],
"stats_total": "💰 Jami miqdor $",
"stats_budget": "Qolgan budjetingiz",
"monthly": " bu oy uchun",
"daily": " bugun uchun",
"all-time": "",
"stats_openai": "Shu oyda OpenAI hisobingizdan to'lov amalga oshirildi $",
"resend_failed": "Sizda qayta yuborish uchun hech narsa yo'q",
"reset_done": "Bajarildi!",
"image_no_prompt": "Iltimos, so'rov yozing! (masalan, /image mushuk)",
"image_fail": "Tasvir yaratish amalga oshmadi",
"tts_no_prompt": "Iltimos, matn kiriting! (masalan, /tts uyim)",
"tts_fail": "Ovoz yaratish amalga oshmadi",
"media_download_fail": ["Audio faylni yuklab olish amalga oshmadi", "Fayl hajmi katta emasligiga ishonch hosil qiling. (max 20MB)"],
"media_type_fail": "Qo'llab-quvvatlanmaydigan fayl turi",
"transcript": "Transkript",
"answer": "Javob",
"transcribe_fail": "Matnni transkripsiya qilib bo'lmadi",
"chat_fail": "Javob olish amalga oshmadi",
"prompt": "so'rov",
"completion": "yakunlash",
"openai_rate_limit": "OpenAI ta'rif chegarasidan oshib ketdi",
"openai_invalid": "OpenAI So'rov noto'g'ri",
"error": "Xatolik yuz berdi",
"try_again": "Birozdan keyin qayta urinib ko'ring",
"answer_with_chatgpt": "ChatGPT bilan javob berish",
"ask_chatgpt": "ChatGPTdan so'rash",
"loading": "Yuklanmoqda...",
"function_unavailable_in_inline_mode": "Bu funksiya inline rejimida mavjud emas"
} }
} }