Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gpt4-vision feature. #395

Open
wants to merge 24 commits into
base: http-version
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a8c1e21
Update Dockerfile
karfly Jun 20, 2023
28e7426
Fix HTTPX problem
karfly Jun 20, 2023
533e670
Added GPT-3.5 16K chat functionality (#306)
maccagnit Jun 20, 2023
e42798c
fixed grammar and spelling (#301)
Light2Dark Jun 20, 2023
8df5e2d
fix argument of type 'float' is not iterable (#211)
TanNhatCMS Jun 20, 2023
a4bd06a
Allow channels (#312)
Fl0p Jun 20, 2023
1847b9c
Update Dockerfile for faster build
karfly Jun 20, 2023
006bc45
Merge branch 'main' of github.com:karfly/chatgpt_telegram_bot
karfly Jun 20, 2023
c9db7dc
❤️ Update top donations
karfly Jun 20, 2023
c77501c
Remove deprecated "use_chatgpt_api" parameter
karfly Jul 18, 2023
0c09f1a
Add OpenAI API Base to config
karfly Aug 1, 2023
8f5a020
Increase OpenAI timeout
karfly Aug 28, 2023
c538993
❤️ Update top donations
karfly Aug 28, 2023
200ba31
create .dockerignore (#344)
realies Aug 28, 2023
bd6c686
❤️ Update top donations
karfly Aug 29, 2023
f87b54d
❤️ Update top donations
karfly Sep 7, 2023
acd4cab
Make the DALLe image size configurable (#365)
alfaridi Sep 13, 2023
d495f7d
Update README.md
karfly Sep 14, 2023
3d281de
♥️ Update top donations
karfly Sep 18, 2023
bab5938
Merge branch 'main' of github.com:karfly/chatgpt_telegram_bot
karfly Sep 18, 2023
ce0c348
Store Voice temp files in memory and don't convert them
ohld Nov 2, 2023
977ffb5
Fix openai version
karfly Nov 7, 2023
d212a02
Add dependencies and update configurations.
lvmax1998 Nov 14, 2023
bd7bcf4
Add gpr4-vision feature to bot
lvmax1998 Nov 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mongodb

21 changes: 6 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
FROM python:3.8-slim
FROM python:3.8-slim-bookworm

ENV PYTHONFAULTHANDLER=1
ENV PYTHONUNBUFFERED=1
ENV PYTHONHASHSEED=random
ENV PYTHONDONTWRITEBYTECODE 1
ENV PIP_NO_CACHE_DIR=off
ENV PIP_DISABLE_PIP_VERSION_CHECK=on
ENV PIP_DEFAULT_TIMEOUT=100
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && pip3 install -U pip && pip3 install -U wheel && pip3 install -U setuptools==59.5.0
COPY ./requirements.txt /tmp/requirements.txt
RUN pip3 install -r /tmp/requirements.txt && rm -r /tmp/requirements.txt

RUN apt-get update
RUN apt-get install -y python3 python3-pip python-dev build-essential python3-venv ffmpeg

RUN mkdir -p /code
ADD . /code
COPY . /code
WORKDIR /code

RUN pip3 install -r requirements.txt
CMD ["bash"]

CMD ["bash"]
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ You can deploy your own bot, or use mine: [@chatgpt_karfly_bot](https://t.me/cha
- [ЮMoney](https://yoomoney.ru)
- and [many-many other](https://core.telegram.org/bots/payments#supported-payment-providers)

If you want to add payments to your bot and create profitable business – write me on Telegram ([@karfly](https://t.me/karfly)).
If you want to add payments to your bot and create profitable business – write me on Telegram ([@karfly](https://t.me/karfly)) or Email ([email protected]).

## News
- *21 Apr 2023*:
Expand All @@ -60,7 +60,8 @@ If you want to add payments to your bot and create profitable business – write
- *15 Mar 2023*: Added message streaming. Now you don't have to wait until the whole message is ready, it's streamed to Telegram part-by-part (watch demo)
- *9 Mar 2023*: Now you can easily create your own Chat Modes by editing `config/chat_modes.yml`
- *8 Mar 2023*: Added voice message recognition with [OpenAI Whisper API](https://openai.com/blog/introducing-chatgpt-and-whisper-apis). Record a voice message and ChatGPT will answer you!
- *2 Mar 2023*: Added support of [ChatGPT API](https://platform.openai.com/docs/guides/chat/introduction). It's enabled by default and can be disabled with `use_chatgpt_api` option in config. Don't forget to **rebuild** you docker image (`--build`).
- *2 Mar 2023*: Added support of [ChatGPT API](https://platform.openai.com/docs/guides/chat/introduction).
- *1 Aug 2023*: Added OpenAI API Base to config (useful while using OpenAI-compatible API like [LocalAI](https://github.com/go-skynet/LocalAI))

## Bot commands
- `/retry` – Regenerate last bot answer
Expand Down Expand Up @@ -89,19 +90,31 @@ If you want to add payments to your bot and create profitable business – write
## ❤️ Top donations
You can be in this list: <a href="https://github.com/karfly/chatgpt_telegram_bot/blob/main/static/donate/donate.md#%EF%B8%8F-donate" alt="Donate shield"><img src="https://img.shields.io/badge/-Donate-red?logo=undertale" /></a>

1. [LilRocco](https://t.me/LilRocco). Donation: **11000$** (!!!)

1. [Mr V](https://t.me/mr_v_v_v). Donation **250$**

1. [unexpectedsunday](https://t.me/unexpectedsunday). Donation: **150$**

1. [Sem](https://t.me/sembrestels). Donation: **100$**

2. [Ryo](https://t.me/ryokihara). Donation: **80$**
1. [Miksolo](https://t.me/Miksolo). Donation: **81$**

3. [Ilias Ism](https://twitter.com/illyism). Donation: **69$**
*Message:* Thank you. Using this docker container every day! Actually created the same project but its good to see that this one is being supported often. Will continue using it! Good architecture choices made in the code 💪!

1. [Ryo](https://t.me/ryokihara). Donation: **80$**

1. [Ilias Ism](https://twitter.com/illyism). Donation: **69$**

*Message:* I wanted to thank you for your amazing code! It helped me start my own Telegram ChatGPT bot and add a bunch of cool features. I really appreciate your hard work on this project. For anyone interested in trying my bot, feel free to check it out here: [magicbuddy.chat](https://magicbuddy.chat) 🤖 Thanks again! 😊

4. [Sebastian](https://t.me/dell1503). Donation: **55$**
1. [Sebastian](https://t.me/dell1503). Donation: **55$**

1. [Alexander Zimin](https://t.me/azimin). Donation: **50$**

5. [Alexander Zimin](https://t.me/azimin). Donation: **50$**
1. [Kbaji20](https://t.me/Kbaji20). Donation: **30$**

6. [Hans Blinken](https://t.me/hblink). Donation: **10$**
1. [Hans Blinken](https://t.me/hblink). Donation: **10$**

## References
1. [*Build ChatGPT from GPT-3*](https://learnprompting.org/docs/applied_prompting/build_chatgpt)
58 changes: 27 additions & 31 deletions bot/bot.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import os
import io
import logging
import asyncio
import traceback
import html
import json
import tempfile
import pydub
from pathlib import Path
from datetime import datetime
import openai

Expand All @@ -33,7 +30,7 @@
import config
import database
import openai_utils

from vision_handle import VISION_CONVERSATION_HANDLER,VISION_FILTER

# setup
db = database.Database()
Expand Down Expand Up @@ -94,7 +91,7 @@ async def register_user_if_not_exists(update: Update, context: CallbackContext,

# back compatibility for n_used_tokens field
n_used_tokens = db.get_user_attribute(user.id, "n_used_tokens")
if isinstance(n_used_tokens, int): # old format
if isinstance(n_used_tokens, int) or isinstance(n_used_tokens, float): # old format
new_n_used_tokens = {
"gpt-3.5-turbo": {
"n_input_tokens": 0,
Expand Down Expand Up @@ -342,25 +339,15 @@ async def voice_message_handle(update: Update, context: CallbackContext):
db.set_user_attribute(user_id, "last_interaction", datetime.now())

voice = update.message.voice
with tempfile.TemporaryDirectory() as tmp_dir:
tmp_dir = Path(tmp_dir)
voice_ogg_path = tmp_dir / "voice.ogg"

# download
voice_file = await context.bot.get_file(voice.file_id)
await voice_file.download_to_drive(voice_ogg_path)

# convert to mp3
voice_mp3_path = tmp_dir / "voice.mp3"
pydub.AudioSegment.from_file(voice_ogg_path).export(voice_mp3_path, format="mp3")
voice_file = await context.bot.get_file(voice.file_id)

# transcribe
with open(voice_mp3_path, "rb") as f:
transcribed_text = await openai_utils.transcribe_audio(f)

if transcribed_text is None:
transcribed_text = ""
# store file in memory, not on disk
buf = io.BytesIO()
await voice_file.download_to_memory(buf)
buf.name = "voice.oga" # file extension is required
buf.seek(0) # move cursor to the beginning of the buffer

transcribed_text = await openai_utils.transcribe_audio(buf)
text = f"🎤: <i>{transcribed_text}</i>"
await update.message.reply_text(text, parse_mode=ParseMode.HTML)

Expand All @@ -382,8 +369,8 @@ async def generate_image_handle(update: Update, context: CallbackContext, messag
message = message or update.message.text

try:
image_urls = await openai_utils.generate_images(message, n_images=config.return_n_generated_images)
except openai.error.InvalidRequestError as e:
image_urls = await openai_utils.generate_images(message, n_images=config.return_n_generated_images, size=config.image_size)
except openai.OpenAIError as e:
if str(e).startswith("Your request was rejected as a result of our safety system"):
text = "🥲 Your request <b>doesn't comply</b> with OpenAI's usage policies.\nWhat did you write there, huh?"
await update.message.reply_text(text, parse_mode=ParseMode.HTML)
Expand Down Expand Up @@ -534,9 +521,9 @@ def get_settings_menu(user_id: int):
title = "✅ " + title

buttons.append(
InlineKeyboardButton(title, callback_data=f"set_settings|{model_key}")
[InlineKeyboardButton(title, callback_data=f"set_settings|{model_key}")]
)
reply_markup = InlineKeyboardMarkup([buttons])
reply_markup = InlineKeyboardMarkup(buttons)

return text, reply_markup

Expand Down Expand Up @@ -657,14 +644,17 @@ async def post_init(application: Application):
BotCommand("/balance", "Show balance"),
BotCommand("/settings", "Show settings"),
BotCommand("/help", "Show help message"),
BotCommand("/vision", "Use GPT-4 to understand images"),
])

def run_bot() -> None:
application = (
ApplicationBuilder()
Application.builder()
.token(config.telegram_token)
.concurrent_updates(True)
.rate_limiter(AIORateLimiter(max_retries=5))
.http_version("1.1")
.get_updates_http_version("1.1")
.post_init(post_init)
.build()
)
Expand All @@ -673,8 +663,12 @@ def run_bot() -> None:
user_filter = filters.ALL
if len(config.allowed_telegram_usernames) > 0:
usernames = [x for x in config.allowed_telegram_usernames if isinstance(x, str)]
user_ids = [x for x in config.allowed_telegram_usernames if isinstance(x, int)]
user_filter = filters.User(username=usernames) | filters.User(user_id=user_ids)
any_ids = [x for x in config.allowed_telegram_usernames if isinstance(x, int)]
user_ids = [x for x in any_ids if x > 0]
group_ids = [x for x in any_ids if x < 0]
user_filter = filters.User(username=usernames) | filters.User(user_id=user_ids) | filters.Chat(chat_id=group_ids)

user_filter = user_filter & ~VISION_FILTER

application.add_handler(CommandHandler("start", start_handle, filters=user_filter))
application.add_handler(CommandHandler("help", help_handle, filters=user_filter))
Expand All @@ -696,11 +690,13 @@ def run_bot() -> None:

application.add_handler(CommandHandler("balance", show_balance_handle, filters=user_filter))

application.add_handler(VISION_CONVERSATION_HANDLER)

application.add_error_handler(error_handle)

# start the bot
application.run_polling()


if __name__ == "__main__":
run_bot()
run_bot()
3 changes: 2 additions & 1 deletion bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
# config parameters
telegram_token = config_yaml["telegram_token"]
openai_api_key = config_yaml["openai_api_key"]
use_chatgpt_api = config_yaml.get("use_chatgpt_api", True)
openai_api_base = config_yaml.get("openai_api_base", None)
allowed_telegram_usernames = config_yaml["allowed_telegram_usernames"]
new_dialog_timeout = config_yaml["new_dialog_timeout"]
enable_message_streaming = config_yaml.get("enable_message_streaming", True)
return_n_generated_images = config_yaml.get("return_n_generated_images", 1)
image_size = config_yaml.get("image_size", "512x512")
n_chat_modes_per_page = config_yaml.get("n_chat_modes_per_page", 5)
mongodb_uri = f"mongodb://mongo:{config_env['MONGODB_PORT']}"

Expand Down
Loading