aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhuker667 <huker@tuta.io>2026-08-07 23:03:12 +0300
committerhuker667 <huker@tuta.io>2026-08-07 23:03:12 +0300
commit891131b88e2b1684a453a0b9ab9291b97331809e (patch)
tree240e23daaa5f17c85e8173cf8fe4f29b6074dca7
parentca0f5bf3deed8bbc82a79834a9419233b559ce14 (diff)
downloaduzbekgpt-891131b88e2b1684a453a0b9ab9291b97331809e.tar.gz
uzbekgpt-891131b88e2b1684a453a0b9ab9291b97331809e.tar.bz2
uzbekgpt-891131b88e2b1684a453a0b9ab9291b97331809e.zip
фикс я хуй знает много чего я добавил
-rw-r--r--LICENSE41
-rw-r--r--ai.py104
-rw-r--r--callbacks.py110
-rw-r--r--commands.py18
-rw-r--r--config_def.py46
-rw-r--r--helpers.py293
-rw-r--r--input_msg.py156
-rw-r--r--main.py270
-rw-r--r--requirements.txt1
-rw-r--r--supergenerator.py383
-rw-r--r--vars.py5
11 files changed, 850 insertions, 577 deletions
diff --git a/LICENSE b/LICENSE
index 21189bd..cbff57f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,12 +1,33 @@
-Copyright 2025 Den
+Open Plov License Version 1 (OPLv1)
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted.
+Permission is granted for free use, copying, modification, and
+distribution of this software for non-commercial purposes,
+provided that this license notice is retained.
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
+Any derivative works and modifications must be distributed under
+this same license with open source code.
+
+Closing the source code or distribution under a proprietary
+license is prohibited.
+
+Distribution of compiled (binary) versions of this software
+without publicly available source code from which the software was
+built is prohibited.
+
+Code under this license may only be combined with code under
+licenses that require maintaining open source code.
+
+Combining with code under licenses that permit closing source code
+or unrestricted commercial use is prohibited.
+
+When combining with code under other copyleft licenses, the
+resulting work must comply with the requirements of both licenses.
+
+Project dependencies are not subject to the requirements of this
+license and may be used according to their own terms. This license
+applies only to the original project code and its derivative
+works.
+
+The software is provided "as is", without any warranties. The
+copyright holder is not liable for any damages arising from the
+use of the software.
diff --git a/ai.py b/ai.py
new file mode 100644
index 0000000..dd94cf8
--- /dev/null
+++ b/ai.py
@@ -0,0 +1,104 @@
+import aiohttp
+import asyncio
+import json
+import gconfig
+
+try:
+ from config import *
+except:
+ gconfig.copy_config()
+finally:
+ from config import *
+
+async def make_request(url, headers, payload):
+ async with aiohttp.ClientSession(headers=headers) as session:
+ async with session.post(url, json=payload) as response:
+ if payload.get("stream") == True:
+ async for line in response.content:
+ line = line.decode("utf-8").strip()
+ if line.startswith("data:"):
+ data = line[5:].strip()
+ if data == "DONE":
+ break
+ else:
+ # data = await response.text()
+ yield data
+ else:
+ response_data = b""
+ async for chunk in response.content.iter_chunks():
+ response_data += chunk[0]
+ yield response_data.decode()
+
+async def completions(
+ url,
+ api_key,
+ model,
+ messages,
+ stream=False,
+ max_tokens=MAX_TOKENS,
+ extra=None
+):
+ print(url)
+
+ headers = {
+ "Authorization": f"Bearer {api_key}",
+ "Content-Type": "application/json"
+ }
+
+ payload = {
+ "messages": messages,
+ "model": model,
+ "stream": stream,
+ "max_tokens": max_tokens,
+ }
+
+ if extra:
+ payload = payload | extra
+
+ if stream:
+ async for data in make_request(url+"/chat/completions", headers, payload):
+ try:
+ yield json.loads(data)
+ except:
+ yield data
+ else:
+ async for data in make_request(url+"/chat/completions", headers, payload):
+ try:
+ yield json.loads(data)
+ except:
+ yield data
+
+async def responses(
+ url,
+ api_key,
+ model,
+ input,
+ stream=False,
+ max_tokens=MAX_TOKENS,
+ extra=None
+):
+ headers = {
+ "Authorization": f"Bearer {api_key}",
+ "Content-Type": "application/json"
+ }
+ payload = {
+ "model": model,
+ "input": input,
+ "stream": stream,
+ "max_tokens": max_tokens,
+ }
+ if extra:
+ payload = payload | extra
+
+ if stream:
+ async for data in make_request(url+"/chat/completions", headers, payload):
+ try:
+ yield json.loads(data)
+ except:
+ yield data
+ else:
+ async for data in make_request(url+"/chat/completions", headers, payload):
+ try:
+ yield json.loads(data)
+ except:
+ yield data
diff --git a/callbacks.py b/callbacks.py
index 1304d7e..2182d45 100644
--- a/callbacks.py
+++ b/callbacks.py
@@ -860,114 +860,26 @@ async def settings_callback(callback: CallbackQuery):
await settings_handler(callback)
-@router.callback_query(F.data.startswith("set_stream%"))
-async def set_stream_callback(callback: CallbackQuery):
+@router.callback_query(F.data.startswith("set%"))
+async def set_setting_callback(callback: CallbackQuery):
current_user_id = str(callback.from_user.id)
- data = callback.data.split("%", 2)
- user_id = data[1]
- if user_id != current_user_id:
- await callback.answer("нет, не трогай это не твое")
- return
-
- new_status = callback.data.split("%")[2]
-
- config = get_user_config(user_id)
- if new_status == "native" or new_status == "edit":
- set_user_config(
- user_id,
- config.get("model"),
- new_status,
- config.get("call"),
- config.get("prompt"),
- config.get("notify"),
- config.get("markdown"),
- config.get("prompts"),
- )
- else:
- set_user_config(
- user_id,
- config.get("model"),
- "none",
- config.get("call"),
- config.get("prompt"),
- config.get("notify"),
- config.get("markdown"),
- config.get("prompts"),
- )
- await settings_handler(callback)
-
-
-@router.callback_query(F.data.startswith("set_call%"))
-async def set_call_callback(callback: CallbackQuery):
- current_user_id = str(callback.from_user.id)
- data = callback.data.split("%", 2)
- user_id = data[1]
- if user_id != current_user_id:
- await callback.answer("нет, не трогай это не твое")
- return
-
- new_status = callback.data.split("%")[2]
-
- config = get_user_config(user_id)
- set_user_config(
- user_id,
- config.get("model"),
- config.get("stream"),
- new_status,
- config.get("prompt"),
- config.get("notify"),
- config.get("markdown"),
- config.get("prompts")
- )
- await settings_handler(callback)
-
-
-@router.callback_query(F.data.startswith("set_notify%"))
-async def set_notify_callback(callback: CallbackQuery):
- current_user_id = str(callback.from_user.id)
- data = callback.data.split("%", 2)
- user_id = data[1]
+ data = callback.data.split("%", 3)
+ user_id = data[2]
if user_id != current_user_id:
await callback.answer("нет, не трогай это не твое")
return
- new_status = callback.data.split("%")[2]
+ new_status = callback.data.split("%")[3]
config = get_user_config(user_id)
- set_user_config(
- user_id,
- config.get("model"),
- config.get("stream"),
- config.get("call"),
- config.get("prompt"),
- new_status,
- config.get("markdown"),
- config.get("prompts")
- )
- await settings_handler(callback)
-
-@router.callback_query(F.data.startswith("set_markdown%"))
-async def set_markdown_callback(callback: CallbackQuery):
- current_user_id = str(callback.from_user.id)
- data = callback.data.split("%", 2)
- user_id = data[1]
- if user_id != current_user_id:
- await callback.answer("нет, не трогай это не твое")
- return
-
- new_status = data[2]
-
- config = get_user_config(user_id)
- set_user_config(
+ alo = {
+ data[1]: new_status
+ }
+
+ set_user_setting(
user_id,
- config.get("model"),
- config.get("stream"),
- config.get("call"),
- config.get("prompt"),
- config.get("notify"),
- new_status,
- config.get("prompts")
+ **alo
)
await settings_handler(callback)
diff --git a/commands.py b/commands.py
index 32bac3c..4811b4a 100644
--- a/commands.py
+++ b/commands.py
@@ -27,6 +27,8 @@ from collections import Counter
from colors import *
from config import *
from statistics import *
+from vars import *
+from helpers import *
from supergenerator import *
router = Router()
@@ -69,7 +71,7 @@ async def stats_handler(message: Message):
top_models = models.most_common(5)
top_streams = streams.most_common(2)
- top_prompts = prompts.most_common(5)
+ top_prompts = prompts.most_common(10)
text = [
"✅ *общая статистика*",
@@ -85,8 +87,8 @@ async def stats_handler(message: Message):
*(f"- `{s}`: {c}" for s, c in top_streams),
"👀топ режимов вызова:",
*(f"- `{c}`: {n}" for c, n in calls.most_common()),
- "📝топ 5 промптов:",
- *(f"- `{c}`: {n}" for c, n in prompts.most_common()),
+ "📝топ 10 промптов:",
+ *(f"- `{c}`: {n}" for c, n in top_prompts.most_common()),
]
await message.reply("\n".join(text))
@@ -389,7 +391,7 @@ async def prompt_handler(message: Message):
config = get_user_config(user_id)
system_prompt_name = config["prompt"]
if system_prompt_name in SYSTEM_PROMPTS:
- system_prompt = SYSTEM_PROMPTS[system_prompt_name]
+ system_prompt = SYSTEM_PROMPTS[system_prompt_name]["text"]
else:
await message.reply(
f"🤝 произошла ошибка при отображении промпта `{system_prompt_name}`\n*для фото*: ```prompt\n{IMAGE_PROMPT}```изменить системный промпт узбекгпт пока что нельзя."
@@ -480,21 +482,21 @@ async def settings_handler(event: Union[Message, CallbackQuery]):
[
InlineKeyboardButton(
text=f"стрим: {stream_status}",
- callback_data=f"set_stream%{user_id}%{stream_cb}",
+ callback_data=f"set%stream%{user_id}%{stream_cb}",
),
InlineKeyboardButton(
text=f"отклик: {call_status}",
- callback_data=f"set_call%{user_id}%{call_cb}",
+ callback_data=f"set%call%{user_id}%{call_cb}",
)
],
[
InlineKeyboardButton(
text=f"рассылка: {notify_status}",
- callback_data=f"set_notify%{user_id}%{notify_cb}",
+ callback_data=f"set%notify%{user_id}%{notify_cb}",
),
InlineKeyboardButton(
text=f"маркдаун: {markdown_status}",
- callback_data=f"set_markdown%{user_id}%{markdown_cb}",
+ callback_data=f"set%markdown%{user_id}%{markdown_cb}",
),
],
diff --git a/config_def.py b/config_def.py
index 10e5ec7..4702c57 100644
--- a/config_def.py
+++ b/config_def.py
@@ -4,39 +4,57 @@ from dotenv import load_dotenv
load_dotenv()
-ADMIN_ID = 8243488179
+# айди аккаунта админа для команд /reset /broadcast /clean и так далее
+ADMIN_ID = 8935141038
# поставь "" пустой da если хочешь отключить поддержку голосовых
VOSK_API = "http://127.0.0.1:8080/stt"
+# сколько сообщений хранить в контексте
MAX_CONTEXT = 7
-MAX_PROMPT = 4000
-MAX_TOKENS = 9000
+# максимальное количество символов в промпте +файлы
+MAX_PROMPT = 16000
+# макс токены генерация
+MAX_TOKENS = 4000
+# макс символы (только в режиме стрима работает мне лень фиксить)
+MAX_SYMBOLS = 13400
+# макс количество кастомных промптов
MAX_PROMPTS = 8
+# каждые n (400) символов обновлять стриминг поток
+STREAMING_SPLIT_SYMBOLS = 400
+
+# не важно
BEN_IDS = [-1002147940521, -1001834656942, -1003142512395]
ABEN_IDS = [-1002147940521, -1001834656942, -1003142512395]
REPORN_IDS = [-1002147940521, -1002775610996, -1001834656942, -1003142512395]
+# юз бота без @
BOT_USERNAME = "UzbekGPTTestBot"
+# на что бот откликается
BOT_CALLS = ["узбек", "uzbek", f"@{BOT_USERNAME}"]
+# дефолт настройки для новых юзеров
DEFAULT_MODEL = "ollama*gemma4:31b-cloud"
-IMAGE_MODEL = "ollama*gemma3:27b-cloud"
DEFAULT_STREAM = "none"
DEFAULT_CALL = "da"
DEFAULT_PROMPT = "standart"
DEFAULT_NOTIFY = "da"
-# поставь DEFAULT_MARKDOWN на "" если хочешь спросить пользователя что он хочет при первом соо da.
-DEFAULT_MARKDOWN = "old"
+DEFAULT_MARKDOWN = "old"
+
+# модель которая умеет принимать картинки очень важно
+IMAGE_MODEL = "ollama*gemma3:27b-cloud"
+# я забыл если честно
SHOW_ACC_MSG = True
+# можно отключить некоторые команды
SETTINGS_COMMAND = True
CLEAR_COMMAND = True
PROMPT_COMMAND = True
CONFIG_COMMAND = True
+# /settings -> о боте
ABOUT_BOT = (
"✅ *об узбекгпт* ✅\n"
"- создал @zsh69 (хукер667)\n"
@@ -45,8 +63,10 @@ ABOUT_BOT = (
"- подпешис: t.me/hukerass"
)
-DONATE_LINK = ""
+# /settings -> донат, на самом деле можно вставить любой текст а не ссылку
+DONATE_LINK = "https://t.me/send?start=IVRLB58MrhCp"
+# провайдеры ваши хз
PROVIDERS = {
"ollama": {
"name": "оллама",
@@ -68,14 +88,20 @@ PROVIDERS = {
# },
}
+# какие модели есть и настройки (все настройки ищи в коде)
+# - например тут vision ты указываешь умеет ли эта модель смотреть фото.
+# если нет, то модель в IMAGE_MODEL будет генерить анализ по фото для
+# твоей модели.
+# если да, то модель будет напрямую смотреть фото в messages
MODELS = {
"ollama": {
- "gemma3:27b-cloud": {"n_tok": 7, "e_tok": 15, "vision": True},
- "gemma4:31b-cloud": {"n_tok": 30, "e_tok": 50, "vision": True},
+ "gemma3:27b-cloud": {"vision": False},
+ "gemma4:31b-cloud": {"vision": True},
},
"krutoiapi": {
- "da": {"n_tok": 30, "e_tok": 50, "vision": False},
+ "claude-mythos-5": {"vision": False},
},
}
+# АХУЕТЬ ТОКЕН!!
API_TOKEN = os.getenv("API_TOKEN")
diff --git a/helpers.py b/helpers.py
index 57f8b30..a65890a 100644
--- a/helpers.py
+++ b/helpers.py
@@ -1,11 +1,14 @@
+import re
import time
+import shelve
import requests
from aiogram.methods import AnswerGuestQuery, SendPoll
from aiogram.types import InlineQueryResultArticle, InputTextMessageContent, InputRichMessageContent, InputRichMessage, Message
from aiogram.enums import ChatType
-from supergenerator import *
+from vars import *
+from config import *
def is_blocked(user_id):
@@ -162,3 +165,291 @@ async def mans(message, text):
else:
return await message.reply(text)
+def graph_emoji(status):
+ match status:
+ case "done":
+ return "✅"
+ case "error":
+ return "🚫"
+ case "make":
+ return "💭"
+ case "wait":
+ return "⏳"
+ case _:
+ return "🥺"
+
+
+def make_graph(message, process):
+ text = ""
+ replied = message.reply_to_message or None
+ user_id = message.from_user.id
+ config = get_user_config(user_id)
+ im_model = IMAGE_MODEL.split("*", 1)
+ model = config["model"].split("*", 1)
+ photo_a = process.get("photo_a", None)
+ photo = process.get("photo", None)
+ stt = process.get("stt", None)
+ t = process.get("text", None)
+
+ if photo_a:
+ text += f"{graph_emoji(photo_a)} анализ фото (в ответе)\n"
+ if photo:
+ text += f"{graph_emoji(photo)} анализ фото\n"
+ if stt:
+ text += f"{graph_emoji(stt)} stt (голос -> текст)\n"
+
+ text += f"{graph_emoji(t)} запрос `{model[1]}` (`{model[0]}`)\n"
+
+ if replied and replied.document:
+ text += f"↳ {replied.document.file_size} файл (в ответе)\n"
+ if message.document:
+ text += f"↳ {message.document.file_size} файл\n"
+
+ if replied and replied.photo:
+ text += "↳ фото (в ответе)\n"
+ if message.photo:
+ text += "↳ фото\n"
+
+ if replied and replied.location:
+ text += "↳ геолокация (в ответе)\n"
+ if message.location:
+ text += "↳ геолокация\n"
+
+ if replied and replied.poll:
+ text += "↳ опрос (в ответе)\n"
+ if message.poll:
+ text += "↳ опрос\n"
+
+ if replied and replied.voice:
+ text += "↳ голосовое сообщение (в ответе)\n"
+ if message.voice:
+ text += "↳ голосовое сообщение\n"
+
+ if replied and replied.text:
+ text += f"↳ {len(replied.text)} текст в ответе\n"
+
+ return text
+
+
+def clean_tail_repeats(text: str, max_repeat: int = 10):
+ if not text:
+ return text, 0
+
+ original_length = len(text)
+ cleaned = text
+
+ pattern = rf"(.)\1{{{max_repeat},}}$"
+
+ def limit_repeats(match):
+ char = match.group(1)
+ return char * max_repeat
+
+ cleaned = re.sub(pattern, limit_repeats, cleaned)
+
+ pattern_space = rf"((\S)\s+)\2{{{max_repeat},}}$"
+ cleaned = re.sub(
+ pattern_space,
+ lambda m: (m.group(2) + " ") * min(max_repeat, len(m.group(1))),
+ cleaned,
+ )
+
+ words = cleaned.split()
+ if len(words) >= 2:
+ for i in range(1, min(len(words), 10)):
+ if all(words[-j] == words[-j - 1] for j in range(i)):
+ unique_words = words[: -(i + 1)]
+ cleaned = " ".join(unique_words + [words[-1]])
+ break
+
+ removed_count = original_length - len(cleaned)
+
+ cleaned = re.sub(r" +", " ", cleaned)
+ cleaned = cleaned.strip()
+
+ return cleaned, removed_count
+
+
+def parse_response(text: str):
+ if "connection error." in text:
+ return {
+ "type": "connection",
+ "message": "ошибка подключения к провайдеру. подожди или смени провайдера в настройках узбекгпт.",
+ }
+ elif "model quota exceeded" in text:
+ return {
+ "type": "quota",
+ "message": "лимит токенов закончился. подожди или смени модель.",
+ }
+ elif "tier capacity exceeded." in text:
+ return {"type": "tier", "message": "попробуй ещё раз!"}
+ elif "internal server" in text:
+ return {
+ "type": "int",
+ "message": "произошла ошибка на стороне провайдера. подожди или смени провайдера в настройках узбекгпт.",
+ }
+ elif "(incomplete chunked read)" in text:
+ return {
+ "type": "incomplete",
+ "message": "сервер петух и оборвал соединение. подожди или смени провайдера в настройках узбекгпт.",
+ }
+ elif "provider error" in text:
+ return {
+ "type": "provider",
+ "message": "врат ошибка на стороне провайдера модели. смени провайдера или модель.",
+ }
+ elif "rate limit" in text:
+ return {
+ "type": "quota",
+ "message": "лимит токенов закончился у провайдера врат. подожди или смени модель.",
+ }
+ else:
+ return {
+ "type": "unknown",
+ "message": f"произошла какая-то ошибка при генерации... {text}",
+ }
+
+
+def galockinator(text):
+ for _ in range(random.randint(1, 3)):
+ if random.random() < 0.3:
+ text += "☝️"
+ else:
+ text += "✅"
+
+ return text
+
+
+def remove_think_tags(text):
+ result = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL)
+ result = re.sub(r"<thought>.*?</thought>", "", text, flags=re.DOTALL)
+ return result
+
+
+def get_all_users(only_notify=False):
+ with shelve.open("users") as db:
+ return {k: db[k] for k in db.keys() if not only_notify or db[k].get("notify") == "da"}
+
+
+def get_all_user_ids(only_notify=False):
+ ids = []
+ with shelve.open("users") as db:
+ for user_id in db.keys():
+ if only_notify and db[user_id].get("notify") != "da":
+ continue
+ try:
+ ids.append(int(user_id))
+ except ValueError:
+ pass
+ return ids
+
+
+def set_user_config(
+ user_id,
+ model_name,
+ stream=DEFAULT_STREAM,
+ call=DEFAULT_CALL,
+ prompt=DEFAULT_PROMPT,
+ notify=DEFAULT_NOTIFY,
+ markdown=DEFAULT_MARKDOWN,
+ prompts={},
+):
+ with shelve.open("users") as db:
+ db[str(user_id)] = {
+ "model": model_name,
+ "stream": stream,
+ "call": call,
+ "prompt": prompt,
+ "notify": notify,
+ "markdown": markdown,
+ "prompts": prompts,
+ }
+
+
+
+def set_user_setting(
+ user_id,
+ model=None,
+ stream=None,
+ call=None,
+ prompt=None,
+ notify=None,
+ markdown=None,
+ prompts=None,
+):
+ with shelve.open("users") as db:
+ user_id = str(user_id)
+ if user_id not in db:
+ db[user_id] = {}
+
+ settings = db[user_id]
+
+ if model is not None: settings["model"] = model
+ if stream is not None: settings["stream"] = stream
+ if call is not None: settings["call"] = call
+ if prompt is not None: settings["prompt"] = prompt
+ if notify is not None: settings["notify"] = notify
+ if markdown is not None: settings["markdown"] = markdown
+ if prompts is not None: settings["prompts"] = prompts
+
+ db[user_id] = settings
+
+
+def delete_user_from_db(user_id):
+ with shelve.open("users") as db:
+ if str(user_id) in db:
+ del db[str(user_id)]
+
+
+def reset_user_setting(user_id, key, value):
+ with shelve.open("users") as db:
+ user = db[str(user_id)]
+ user[key] = value
+ db[str(user_id)] = user
+
+
+def ensure_user(
+ user_id,
+ model_name=DEFAULT_MODEL,
+ stream_mode=DEFAULT_STREAM,
+ call_mode=DEFAULT_CALL,
+ prompt_name=DEFAULT_PROMPT,
+ notify_mode=DEFAULT_NOTIFY,
+ markdown=DEFAULT_MARKDOWN,
+ prompts={},
+):
+ with shelve.open("users") as db:
+ key = str(user_id)
+
+ if key not in db:
+ db[key] = {
+ "model": model_name,
+ "stream": stream_mode,
+ "call": call_mode,
+ "prompt": prompt_name,
+ "notify": notify_mode,
+ "markdown": markdown,
+ "prompts": prompts,
+ }
+
+
+def get_user_config(user_id):
+ with shelve.open("users") as db:
+ config = db.get(str(user_id), {})
+ defaults = {
+ "model": DEFAULT_MODEL,
+ "stream": DEFAULT_STREAM,
+ "call": DEFAULT_CALL,
+ "prompt": DEFAULT_PROMPT,
+ "notify": DEFAULT_NOTIFY,
+ "markdown": DEFAULT_MARKDOWN,
+ "prompts": {},
+ }
+ updated = False
+ for key, value in defaults.items():
+ if key not in config:
+ config[key] = value
+ updated = True
+ if updated:
+ db[str(user_id)] = config
+ return config
+
diff --git a/input_msg.py b/input_msg.py
new file mode 100644
index 0000000..9bae20d
--- /dev/null
+++ b/input_msg.py
@@ -0,0 +1,156 @@
+import string
+
+from random import choices
+
+from vars import *
+from config import *
+from helpers import get_user_config, set_user_setting
+
+from aiogram.types import (
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ InlineQueryResultArticle,
+ InputTextMessageContent,
+ Message,
+)
+
+async def da(bot, message, user_id):
+ config = get_user_config(user_id)
+ print(config)
+ if user_id in alo_command:
+ if message.chat.id == alo_command[user_id]["chat_id"]:
+ if alo_command[user_id]["action"] == "p_name":
+ alo_command[user_id]["action"] = "p_prompt"
+ alo_command[user_id]["name"] = message.text[:16]
+ return await bot.edit_message_text(
+ text=f"установи промпт для `{alo_command[user_id]['name']}`:",
+ chat_id=alo_command[user_id]["chat_id"],
+ message_id=alo_command[user_id]["message_id"],
+ reply_markup=InlineKeyboardMarkup(
+ inline_keyboard=[
+ [
+ InlineKeyboardButton(
+ text=f"❌ отменить", callback_data=f"p_cancel%{user_id}"
+ ),
+ ],
+ ]
+ )
+ )
+ elif alo_command[user_id]["action"] == "p_prompt":
+ alo_command[user_id]["action"] = None
+ alo_command[user_id]["prompt"] = message.text
+
+ if len(config["prompts"]) >= MAX_PROMPTS:
+ return await bot.edit_message_text(
+ text=f"невозможно создать новый промпт так как ты превысил лимит промптов da.",
+ chat_id=alo_command[user_id]["chat_id"],
+ message_id=alo_command[user_id]["message_id"],
+ reply_markup=InlineKeyboardMarkup(
+ inline_keyboard=[
+ [
+ InlineKeyboardButton(
+ text=f"ок", callback_data=f"user_prompts%{user_id}"
+ ),
+ ],
+ ]
+ )
+ )
+
+ while 1:
+ alo_command[user_id]["id"] = ''.join(choices(string.ascii_letters, k=10))
+ if alo_command[user_id]["id"] not in config["prompts"]:
+ break
+
+ config["prompts"] = config["prompts"] | {
+ alo_command[user_id]["id"]: {
+ "name": alo_command[user_id]["name"],
+ "text": alo_command[user_id]["prompt"],
+ "filer": False,
+ "public": False
+ }
+ }
+
+ set_user_setting(
+ user_id,
+ prompts=config["prompts"]
+ )
+
+ return await bot.edit_message_text(
+ text=f"промпт `{alo_command[user_id]['name']}` создан!",
+ chat_id=alo_command[user_id]["chat_id"],
+ message_id=alo_command[user_id]["message_id"],
+ reply_markup=InlineKeyboardMarkup(
+ inline_keyboard=[
+ [
+ InlineKeyboardButton(
+ text=f"✅ посмотреть", callback_data=f"vp%{user_id}%{alo_command[user_id]['id']}"
+ ),
+ ],
+ ]
+ )
+ )
+ elif alo_command[user_id]["action"] == "p_e_name":
+ alo_command[user_id]["action"] = None
+ alo_command[user_id]["name"] = message.text[:16]
+
+ config["prompts"] = config["prompts"] | {
+ alo_command[user_id]["prompt_id"]: {
+ "name": alo_command[user_id]["name"],
+ "text": config["prompts"][alo_command[user_id]["prompt_id"]]["text"],
+ "filer": config["prompts"][alo_command[user_id]["prompt_id"]]["filer"],
+ "public": config["prompts"][alo_command[user_id]["prompt_id"]]["public"],
+ }
+ }
+
+ set_user_setting(
+ user_id,
+ prompts = config["prompts"]
+ )
+
+ return await bot.edit_message_text(
+ text=f"имя промпта было изменено на `{alo_command[user_id]['name']}`.",
+ chat_id=alo_command[user_id]["chat_id"],
+ message_id=alo_command[user_id]["message_id"],
+ reply_markup=InlineKeyboardMarkup(
+ inline_keyboard=[
+ [
+ InlineKeyboardButton(
+ text=f"✅ посмотреть", callback_data=f"vp%{user_id}%{alo_command[user_id]['prompt_id']}"
+ ),
+ ],
+ ]
+ )
+ )
+ elif alo_command[user_id]["action"] == "p_e_prompt":
+ alo_command[user_id]["action"] = None
+ alo_command[user_id]["prompt"] = message.text
+
+ config["prompts"] = config["prompts"] | {
+ alo_command[user_id]["prompt_id"]: {
+ "name": config["prompts"][alo_command[user_id]["prompt_id"]]["name"],
+ "text": alo_command[user_id]["prompt"],
+ "filer": config["prompts"][alo_command[user_id]["prompt_id"]]["filer"],
+ "public": config["prompts"][alo_command[user_id]["prompt_id"]]["public"],
+ }
+ }
+
+ set_user_setting(
+ user_id,
+ prompts=config["prompts"]
+ )
+
+ return await bot.edit_message_text(
+ text=f"текст промпта был изменён.",
+ chat_id=alo_command[user_id]["chat_id"],
+ message_id=alo_command[user_id]["message_id"],
+ reply_markup=InlineKeyboardMarkup(
+ inline_keyboard=[
+ [
+ InlineKeyboardButton(
+ text=f"✅ посмотреть", callback_data=f"vp%{user_id}%{alo_command[user_id]['prompt_id']}"
+ ),
+ ],
+ ]
+ )
+ )
+ return None
diff --git a/main.py b/main.py
index 0a3ab08..4c16764 100644
--- a/main.py
+++ b/main.py
@@ -4,9 +4,9 @@ import base64
import io
import sys
import time
-import string
import gconfig
+import input_msg
# from aiogram.methods import SendMessageDraft
from datetime import datetime
@@ -36,6 +36,7 @@ from callbacks import *
from statistics import *
from colors import *
from helpers import *
+from vars import *
from commands import *
from dotenv import load_dotenv
from random import uniform, shuffle, choices
@@ -90,163 +91,9 @@ async def guest_middleware(handler, event, data):
config = get_user_config(user_id)
prompts = SYSTEM_PROMPTS | config["prompts"]
p = prompts[config["prompt"]]
- # внимание внизу самая умная система осторожнеее!!1!1
- if user_id in alo_command:
- if message.chat.id == alo_command[user_id]["chat_id"]:
- if alo_command[user_id]["action"] == "p_name":
- alo_command[user_id]["action"] = "p_prompt"
- alo_command[user_id]["name"] = message.text[:16]
- return await bot.edit_message_text(
- text=f"установи промпт для `{alo_command[user_id]['name']}`:",
- chat_id=alo_command[user_id]["chat_id"],
- message_id=alo_command[user_id]["message_id"],
- reply_markup=InlineKeyboardMarkup(
- inline_keyboard=[
- [
- InlineKeyboardButton(
- text=f"❌ отменить", callback_data=f"p_cancel%{user_id}"
- ),
- ],
- ]
- )
- )
- elif alo_command[user_id]["action"] == "p_prompt":
- alo_command[user_id]["action"] = None
- alo_command[user_id]["prompt"] = message.text
-
- if len(config["prompts"]) >= MAX_PROMPTS:
- return await bot.edit_message_text(
- text=f"невозможно создать новый промпт так как ты превысил лимит промптов da.",
- chat_id=alo_command[user_id]["chat_id"],
- message_id=alo_command[user_id]["message_id"],
- reply_markup=InlineKeyboardMarkup(
- inline_keyboard=[
- [
- InlineKeyboardButton(
- text=f"ок", callback_data=f"user_prompts%{user_id}"
- ),
- ],
- ]
- )
- )
-
- while 1:
- alo_command[user_id]["id"] = ''.join(choices(string.ascii_letters, k=10))
- if alo_command[user_id]["id"] not in config["prompts"]:
- break
-
- config["prompts"] = config["prompts"] | {
- alo_command[user_id]["id"]: {
- "name": alo_command[user_id]["name"],
- "text": alo_command[user_id]["prompt"],
- "filer": False,
- "public": False
- }
- }
-
- set_user_config(
- user_id,
- config.get("model"),
- config.get("stream", True),
- config.get("call"),
- config.get("prompt"),
- config.get("notify"),
- config.get("markdown"),
- config["prompts"]
- )
-
- return await bot.edit_message_text(
- text=f"промпт `{alo_command[user_id]['name']}` создан!",
- chat_id=alo_command[user_id]["chat_id"],
- message_id=alo_command[user_id]["message_id"],
- reply_markup=InlineKeyboardMarkup(
- inline_keyboard=[
- [
- InlineKeyboardButton(
- text=f"✅ посмотреть", callback_data=f"vp%{user_id}%{alo_command[user_id]['id']}"
- ),
- ],
- ]
- )
- )
- elif alo_command[user_id]["action"] == "p_e_name":
- alo_command[user_id]["action"] = None
- alo_command[user_id]["name"] = message.text[:16]
-
-
- config["prompts"] = config["prompts"] | {
- alo_command[user_id]["prompt_id"]: {
- "name": alo_command[user_id]["name"],
- "text": config["prompts"][alo_command[user_id]["prompt_id"]]["text"],
- "filer": config["prompts"][alo_command[user_id]["prompt_id"]]["filer"],
- "public": config["prompts"][alo_command[user_id]["prompt_id"]]["public"],
- }
- }
-
- set_user_config(
- user_id,
- config.get("model"),
- config.get("stream", True),
- config.get("call"),
- config.get("prompt"),
- config.get("notify"),
- config.get("markdown"),
- config["prompts"]
- )
-
- return await bot.edit_message_text(
- text=f"имя промпта было изменено на `{alo_command[user_id]['name']}`.",
- chat_id=alo_command[user_id]["chat_id"],
- message_id=alo_command[user_id]["message_id"],
- reply_markup=InlineKeyboardMarkup(
- inline_keyboard=[
- [
- InlineKeyboardButton(
- text=f"✅ посмотреть", callback_data=f"vp%{user_id}%{alo_command[user_id]['prompt_id']}"
- ),
- ],
- ]
- )
- )
- elif alo_command[user_id]["action"] == "p_e_prompt":
- alo_command[user_id]["action"] = None
- alo_command[user_id]["prompt"] = message.text
-
-
- config["prompts"] = config["prompts"] | {
- alo_command[user_id]["prompt_id"]: {
- "name": config["prompts"][alo_command[user_id]["prompt_id"]]["name"],
- "text": alo_command[user_id]["prompt"],
- "filer": config["prompts"][alo_command[user_id]["prompt_id"]]["filer"],
- "public": config["prompts"][alo_command[user_id]["prompt_id"]]["public"],
- }
- }
- set_user_config(
- user_id,
- config.get("model"),
- config.get("stream", True),
- config.get("call"),
- config.get("prompt"),
- config.get("notify"),
- config.get("markdown"),
- config["prompts"]
- )
-
- return await bot.edit_message_text(
- text=f"текст промпта был изменён.",
- chat_id=alo_command[user_id]["chat_id"],
- message_id=alo_command[user_id]["message_id"],
- reply_markup=InlineKeyboardMarkup(
- inline_keyboard=[
- [
- InlineKeyboardButton(
- text=f"✅ посмотреть", callback_data=f"vp%{user_id}%{alo_command[user_id]['prompt_id']}"
- ),
- ],
- ]
- )
- )
+ if await input_msg.da(bot, message, user_id) != None:
+ return
if p["filer"]:
if event.guest_message:
@@ -294,7 +141,7 @@ async def guest_middleware(handler, event, data):
last_command_time[user_id][1] = True
last_command_time[user_id][2] += [message.message_id]
- await asyncio.sleep(uniform(0,0.5))
+ await asyncio.sleep(uniform(0,0.2))
if event.message:
try:
@@ -314,11 +161,26 @@ async def guest_middleware(handler, event, data):
voice = None
+ model = config["model"].split("*", 1)
+
if VOSK_API != "":
if message.voice:
voice = message.voice
elif replied and replied.voice:
voice = replied.voice
+
+ process = {
+ "text": "wait",
+ "photo_a": "wait" if replied and replied.photo and MODELS[model[0]].get("vision", False) == False else None,
+ "photo": "wait" if message.photo and MODELS[model[0]][model[1]].get("vision", False) == False else None,
+ "stt": "wait" if voice else None,
+ }
+
+ if event.message:
+ if (config["stream"] == "edit") or (config["stream"] == "native" and user_id == message.chat.id):
+ msg = await message.reply(make_graph(message, process))
+ else:
+ gmsg = await g_answer(message, make_graph(message, process))
location = None
if message.location:
@@ -339,7 +201,7 @@ async def guest_middleware(handler, event, data):
try:
brat = await bot.download(voice, destination=buf)
except Exception as e:
- print(f"{YELLOW} -- voice err - {e}{RESET}")
+ print(f"{YELLOW} -- voice download err - {e}{RESET}")
buf.seek(0)
try:
@@ -349,6 +211,12 @@ async def guest_middleware(handler, event, data):
buf.read()
)
except Exception as e:
+ process["stt"] = "error"
+ if event.message and msg:
+ await msg.edit_text(make_graph(message, process))
+ elif event.guest_message and gmsg:
+ await bot.edit_message_text(text=make_graph(message, process), inline_message_id=gmsg.inline_message_id)
+
prompt = f"<голосовое сообщение>ошибка подключения к api stt</голосовое сообщение>{prompt}"
print(f"{RED} -- voice err - {e}{RESET}")
else:
@@ -356,17 +224,15 @@ async def guest_middleware(handler, event, data):
if message.document:
- if message.document.file_size > 4096:
- await mans(message, "слишком много данных не хочу отвечать☝️☝️")
- return
-
file_bytes = io.BytesIO()
-
try:
await bot.download(message.document, destination=file_bytes)
file_bytes.seek(0)
- file_content = file_bytes.read().decode("utf-8", errors="ignore")
+ if message.document.file_size > 9000:
+ file_content = file_bytes.read().decode("utf-8", errors="ignore")[:9000]
+ else:
+ file_content = file_bytes.read().decode("utf-8", errors="ignore")
file_bytes.close()
prompt = f"<файл>{file_content}</файл>{prompt}"
@@ -376,20 +242,20 @@ async def guest_middleware(handler, event, data):
return
except Exception:
- await mans(message, "файл не вошёл ало ошибка❌❌")
+ if msg:
+ await msg.edit_text(message, "файл не вошёл ало ошибка❌❌")
return
if replied and replied.document:
- if replied.document.file_size > 4096:
- await mans(message, "слишком много данных не хочу отвечать☝️☝️")
- return
-
file_bytes = io.BytesIO()
-
try:
await bot.download(replied.document, destination=file_bytes)
file_bytes.seek(0)
- file_content = file_bytes.read().decode("utf-8", errors="ignore")
+ if replied.document.file_size > 9000:
+ file_content = file_bytes.read().decode("utf-8", errors="ignore")[:9000]
+ else:
+ file_content = file_bytes.read().decode("utf-8", errors="ignore")
+ file_bytes.close()
prompt = f"<файл>{file_content}</файл>{prompt}"
except UnicodeDecodeError:
await mans(message, "файл не вошёл❌")
@@ -433,23 +299,30 @@ async def guest_middleware(handler, event, data):
file_bytes = await bot.download(photo)
image_bytes = file_bytes.read()
b64_image = base64.b64encode(image_bytes).decode("utf-8")
- images += [b64_image]
+ images += [{"data": b64_image, "process": "photo_a"}]
except Exception as e:
+ process["photo_a"] = "error"
+ if event.message and msg:
+ await msg.edit_text(make_graph(message, process))
+ elif event.guest_message and gmsg:
+ await bot.edit_message_text(text=make_graph(message, process), inline_message_id=gmsg.inline_message_id)
+
print(f"{RED} -- photo - {e}{RESET}")
if message.photo and IMAGE_MODEL != "":
try:
- if event.message:
- if not msg:
- msg = await message.reply("👀")
photo = message.photo[-1]
file_bytes = await bot.download(photo)
image_bytes = file_bytes.read()
b64_image = base64.b64encode(image_bytes).decode("utf-8")
- images += [b64_image]
+ images += [{"data": b64_image, "process": "photo"}]
except Exception as e:
- print(f"{RED} -- photo - {e}{RESET}")
-
+ process["photo"] = "error"
+ if event.message and msg:
+ await msg.edit_text(make_graph(message, process))
+ elif event.guest_message and gmsg:
+ await bot.edit_message_text(text=make_graph(message, process), inline_message_id=gmsg.inline_message_id)
+ print(f"{RED} -- photo - {e}{RESET}")
prompt = f"{prompt}\n{user_text}"
if replied_text:
prompt = f"<ответ на>{replied_text}</ответ> {prompt}"
@@ -475,7 +348,10 @@ async def guest_middleware(handler, event, data):
]
)
if event.guest_message:
- await g_answer(message, alloh_one_text, reply_markup=reply_markup_url)
+ if gmsg:
+ await bot.edit_message_text(text=alloh_one_text, inline_message_id=gmsg.inline_message_id, reply_markup=reply_markup_url)
+ else:
+ await g_answer(message, alloh_one_text, reply_markup=reply_markup_url)
elif event.message:
await message.reply_rich(InputRichMessage(markdown="# новый крутой стилёк\n*da*\n```\nтестовое сообщение врат\n```"))
await message.answer(alloh_text, reply_markup=reply_markup)
@@ -489,10 +365,12 @@ async def guest_middleware(handler, event, data):
if stream == "edit":
if event.message:
+ im_model = IMAGE_MODEL.split("*", 1)
+ tx_model = config["model"].split("*", 1)
if msg:
message_id = msg.message_id
else:
- msg = await message.reply("💬")
+ msg = await message.reply("💭")
message_id = msg.message_id
elif event.guest_message:
stream = "none"
@@ -517,6 +395,9 @@ async def guest_middleware(handler, event, data):
user_id=user_id,
message_id=message_id,
images=images,
+ msg=msg,
+ process=process,
+ message=message
)
else:
result = await generate(
@@ -526,6 +407,7 @@ async def guest_middleware(handler, event, data):
user_id=user_id,
message_id=None,
images=images,
+ inline_id=gmsg.inline_message_id
)
result = parse_tools(result)
@@ -633,8 +515,23 @@ async def guest_middleware(handler, event, data):
try:
if event.guest_message:
- await g_answer(message, result, user_id=user_id)
+ if len(result) > 4000:
+ result = result[:4000] + "...\n\n__сообщение твой большой и он сокращен__"
+ if gmsg:
+ await bot.edit_message_text(text=result, inline_message_id=gmsg.inline_message_id)
+ else:
+ await g_answer(message, result, user_id=user_id)
elif event.message:
+ if len(result) > 4000:
+ if msg:
+ await msg.delete()
+ file = BufferedInputFile(
+ file=result.encode("utf-8"),
+ filename=result.replace("\n", "").replace(" ", "_")[:5] + ".txt"
+ )
+ return await message.reply_document(
+ document=file
+ )
if msg:
if stream == "native":
await msg.delete()
@@ -653,7 +550,12 @@ async def guest_middleware(handler, event, data):
kwargs["parse_mode"] = None
try:
if event.guest_message:
- await g_answer(message, result)
+ if len(result) > 4000:
+ result = result[:4000] + "...\n\n__сообщение твой большой и он сокращен__"
+ if gmsg:
+ await bot.edit_message_text(text=result, inline_message_id=gmsg.inline_message_id, parse_mode="None")
+ else:
+ await g_answer(message, result, parse_mode="None")
elif event.message:
if msg:
if stream == "native":
@@ -777,6 +679,7 @@ async def chosen_inline_result_handler(chosen_result: ChosenInlineResult):
await bot.edit_message_text(
text=error["message"],
inline_message_id=inline_message_id,
+ parse_mode=None
)
print(f"{RED} -- {error['type']} -- {error['message']}")
return
@@ -823,3 +726,4 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
+
diff --git a/requirements.txt b/requirements.txt
index e652d79..2b3414d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,4 +2,3 @@ aiogram==3.29.1
python-dotenv==1.2.1
pillow==12.0.0
requests
-openai
diff --git a/supergenerator.py b/supergenerator.py
index 1377247..4df694b 100644
--- a/supergenerator.py
+++ b/supergenerator.py
@@ -2,233 +2,24 @@ import random
import re
import shelve
import time
+import ai
+import json
+
from configparser import DEFAULTSECT
from pprint import pprint
-from openai import AsyncOpenAI
-
from statistics import *
from colors import *
+from helpers import *
from config import *
+from vars import *
-last_command_time = {}
-last_error_time = {}
-last_block_time = {}
-alo_command = {}
-user_contexts = {}
-
-
-def get_clients():
- provs = {}
- for provider, settings in PROVIDERS.items():
- if settings.get("module") == "openai":
- provs[provider] = AsyncOpenAI(
- base_url=settings.get("url"), api_key=settings.get("key")
- )
- return provs
-
-
-providers = get_clients()
-
-
-def clean_tail_repeats(text: str, max_repeat: int = 10):
- if not text:
- return text, 0
-
- original_length = len(text)
- cleaned = text
-
- pattern = rf"(.)\1{{{max_repeat},}}$"
-
- def limit_repeats(match):
- char = match.group(1)
- return char * max_repeat
-
- cleaned = re.sub(pattern, limit_repeats, cleaned)
-
- pattern_space = rf"((\S)\s+)\2{{{max_repeat},}}$"
- cleaned = re.sub(
- pattern_space,
- lambda m: (m.group(2) + " ") * min(max_repeat, len(m.group(1))),
- cleaned,
- )
-
- words = cleaned.split()
- if len(words) >= 2:
- for i in range(1, min(len(words), 10)):
- if all(words[-j] == words[-j - 1] for j in range(i)):
- unique_words = words[: -(i + 1)]
- cleaned = " ".join(unique_words + [words[-1]])
- break
-
- removed_count = original_length - len(cleaned)
-
- cleaned = re.sub(r" +", " ", cleaned)
- cleaned = cleaned.strip()
-
- return cleaned, removed_count
-
-
-def parse_response(text: str):
- if "connection error." in text:
- return {
- "type": "connection",
- "message": "ошибка подключения к провайдеру. подожди или смени провайдера в настройках узбекгпт.",
- }
- elif "model quota exceeded" in text:
- return {
- "type": "quota",
- "message": "лимит токенов закончился. подожди или смени модель.",
- }
- elif "tier capacity exceeded." in text:
- return {"type": "tier", "message": "попробуй ещё раз!"}
- elif "internal server" in text:
- return {
- "type": "int",
- "message": "произошла ошибка на стороне провайдера. подожди или смени провайдера в настройках узбекгпт.",
- }
- elif "(incomplete chunked read)" in text:
- return {
- "type": "incomplete",
- "message": "сервер петух и оборвал соединение. подожди или смени провайдера в настройках узбекгпт.",
- }
- elif "provider error" in text:
- return {
- "type": "provider",
- "message": "врат ошибка на стороне провайдера модели. смени провайдера или модель.",
- }
- elif "rate limit" in text:
- return {
- "type": "quota",
- "message": "лимит токенов закончился у провайдера врат. подожди или смени модель.",
- }
- else:
- return {
- "type": "unknown",
- "message": f"произошла какая-то ошибка при генерации... {text}",
- }
-
-
-def galockinator(text):
- for _ in range(random.randint(1, 3)):
- if random.random() < 0.3:
- text += "☝️"
- else:
- text += "✅"
-
- return text
-
-
-def remove_think_tags(text):
- result = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL)
- result = re.sub(r"<thought>.*?</thought>", "", text, flags=re.DOTALL)
- return result
-
-
-def get_all_users(only_notify=False):
- with shelve.open("users") as db:
- return {k: db[k] for k in db.keys() if not only_notify or db[k].get("notify") == "da"}
-
-
-def get_all_user_ids(only_notify=False):
- ids = []
- with shelve.open("users") as db:
- for user_id in db.keys():
- if only_notify and db[user_id].get("notify") != "da":
- continue
- try:
- ids.append(int(user_id))
- except ValueError:
- pass
- return ids
-
-
-def set_user_config(
- user_id,
- model_name,
- stream_mode=DEFAULT_STREAM,
- call_mode=DEFAULT_CALL,
- prompt_name=DEFAULT_PROMPT,
- notify_mode=DEFAULT_NOTIFY,
- markdown=DEFAULT_MARKDOWN,
- prompts={},
-):
- with shelve.open("users") as db:
- db[str(user_id)] = {
- "model": model_name,
- "stream": stream_mode,
- "call": call_mode,
- "prompt": prompt_name,
- "notify": notify_mode,
- "markdown": markdown,
- "prompts": prompts,
- }
-
-
-def delete_user_from_db(user_id):
- with shelve.open("users") as db:
- if str(user_id) in db:
- del db[str(user_id)]
-
-
-def reset_user_setting(user_id, key, value):
- with shelve.open("users") as db:
- user = db[str(user_id)]
- user[key] = value
- db[str(user_id)] = user
-
-
-def ensure_user(
- user_id,
- model_name=DEFAULT_MODEL,
- stream_mode=DEFAULT_STREAM,
- call_mode=DEFAULT_CALL,
- prompt_name=DEFAULT_PROMPT,
- notify_mode=DEFAULT_NOTIFY,
- markdown=DEFAULT_MARKDOWN,
- prompts={},
-):
- with shelve.open("users") as db:
- key = str(user_id)
-
- if key not in db:
- db[key] = {
- "model": model_name,
- "stream": stream_mode,
- "call": call_mode,
- "prompt": prompt_name,
- "notify": notify_mode,
- "markdown": markdown,
- "prompts": prompts,
- }
-
-
-def get_user_config(user_id):
- with shelve.open("users") as db:
- config = db.get(str(user_id), {})
- defaults = {
- "model": DEFAULT_MODEL,
- "stream": DEFAULT_STREAM,
- "call": DEFAULT_CALL,
- "prompt": DEFAULT_PROMPT,
- "notify": DEFAULT_NOTIFY,
- "markdown": DEFAULT_MARKDOWN,
- "prompts": {},
- }
- updated = False
- for key, value in defaults.items():
- if key not in config:
- config[key] = value
- updated = True
- if updated:
- db[str(user_id)] = config
- return config
-
+from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError
async def generate(
- prompt: str, bot=None, user_id=None, chat_id=None, message_id=None, images=None
+ prompt: str, bot=None, user_id=None, chat_id=None, message_id=None, images=None, msg=None, process=None, message=None, inline_id=None
) -> str:
if user_id:
if user_id not in user_contexts:
@@ -265,9 +56,11 @@ async def generate(
f"2. конфиг бота настроен неправильно и надо связаться с тем кто его хостит"
return text
- if stream_cf == "native" and user_id == chat_id and settings.get("nostream") == False:
+ if stream_cf == "native" and user_id == chat_id and settings.get("nostream", False) == False:
+ stream = True
+ elif stream_cf == "edit" and chat_id and message_id and settings.get("nostream", False) == False:
stream = True
- elif stream_cf == "edit" and chat_id and message_id and settings.get("nostream") == False:
+ elif stream_cf == "edit" or stream_cf == "native" and inline_id:
stream = True
else:
stream = False
@@ -281,10 +74,20 @@ async def generate(
else:
for image in images:
try:
- image_text = await image2text(image)
+ if process and msg and message:
+ process[image["process"]] = "make"
+ await msg.edit_text(make_graph(message, process))
+ image_text = await image2text(image["data"])
prompt = f"<фото>{image_text}</фото>\n{prompt}"
except Exception as e:
+ if process and msg and message:
+ process[image["process"]] = "error"
+ await msg.edit_text(make_graph(message, process))
print(f"{RED} -- err photo - {e} : {config.get('model', '')}{RESET}")
+ else:
+ if process and msg and message:
+ process[image["process"]] = "done"
+ await msg.edit_text(make_graph(message, process))
content += [{"type": "text", "text": prompt}]
@@ -322,15 +125,19 @@ async def generate(
add_one_to("stats/gens")
try:
- client = providers[model[0]]
+ provider = PROVIDERS[model[0]]
except Exception:
text = "❌произошла ошибка, возможные проблемы:\n" \
"1. у вас выбрана удалённая модель или провайдер\n" \
"2. конфиг бота настроен неправильно и надо связаться с тем кто его хостит"
return text
-
+
+ if process and msg and message:
+ process["text"] = "make"
+ await msg.edit_text(make_graph(message, process))
+
text = await openai_generate_text(
- oai=client,
+ api=provider,
bot=bot,
model=model[1],
settings=settings,
@@ -340,6 +147,7 @@ async def generate(
chat_id=chat_id,
draft_id=chat_id,
message_id=message_id,
+ inline_id=inline_id
)
if user_id:
@@ -352,8 +160,8 @@ async def generate(
async def image2text(image) -> str:
if IMAGE_MODEL == "":
return ""
- model = IMAGE_MODEL.split("*", 2)
- client = providers[model[0]]
+ model = IMAGE_MODEL.split("*", 1)
+ api = PROVIDERS[model[0]]
text = ""
messages = [
{
@@ -364,24 +172,26 @@ async def image2text(image) -> str:
],
}
]
- response = await client.responses.create(
- model=model[1], input=messages, stream=False
- )
+ async for response in ai.responses(
+ url=api["url"], api_key=api["key"], model=model[1], input=messages, stream=False
+ ):
+ pass
text = response.output_text
return text
async def openai_generate_text(
- oai: AsyncOpenAI,
+ api,
bot,
model,
settings,
messages,
stream,
stream_cf,
- chat_id,
- draft_id,
- message_id,
+ chat_id=None,
+ draft_id=None,
+ message_id=None,
+ inline_id=None
) -> str:
try:
extra_body = {
@@ -389,56 +199,99 @@ async def openai_generate_text(
}
if settings.get("noexb"):
extra_body = None
-
- completion = await oai.chat.completions.create(
- model=model,
- messages=messages,
- stream=stream,
- max_tokens=MAX_TOKENS,
- extra_body=extra_body
- )
+
+ alo = {
+ "url": api["url"],
+ "api_key": api["key"],
+ "model": model,
+ "messages": messages,
+ "stream": stream,
+ "max_tokens": MAX_TOKENS,
+ "extra": extra_body
+ }
+
if stream:
message = ""
+ t_counter = 0
counter = 0
+ counter_2 = 1
if not draft_id:
draft_id = chat_id
- async for event in completion:
- content = event.choices[0].delta.content
+ async for chunk in ai.completions(**alo):
+ # chunk = json.loads(chunk)
+ try:
+ content = chunk["choices"][0]["delta"]["content"]
+ except:
+ continue
if content:
message += content
- counter += 1
- if stream_cf == "native":
- counter_limit = settings.get("n_tok")
- else:
- counter_limit = settings.get("e_tok")
+ counter += len(content)
+ t_counter += 1
- if counter % counter_limit == 0:
+ if counter > MAX_SYMBOLS:
+ break
+
+ if int(counter / STREAMING_SPLIT_SYMBOLS) == counter_2:
+ counter_2 += 1
display_text, s = clean_tail_repeats(message)
if s > 0:
display_text += f"*... <{s} обрезано>*"
if display_text.count("```") % 2 != 0:
display_text += "\n```"
- try:
- if stream_cf == "native":
- await bot.send_message_draft(
- chat_id=chat_id,
- draft_id=draft_id,
- text=display_text,
- parse_mode="Markdown",
- )
- elif stream_cf == "edit":
- await bot.edit_message_text(
- chat_id=chat_id,
- message_id=message_id,
- text=display_text,
- parse_mode="Markdown",
- )
- except Exception as e:
- print(f"{YELLOW} -- {e}{RESET}")
+
+ if counter < 3950:
+ display_text += "▋"
+
+ try:
+ if stream_cf == "native" and chat_id and draft_id:
+ await bot.send_message_draft(
+ chat_id=chat_id,
+ draft_id=draft_id,
+ text=display_text,
+ )
+ elif stream_cf == "edit" and chat_id and message_id:
+ await bot.edit_message_text(
+ chat_id=chat_id,
+ message_id=message_id,
+ text=display_text,
+ )
+ elif stream_cf == "edit" or stream_cf == "native" and inline_id:
+ await bot.edit_message_text(
+ inline_message_id=inline_id,
+ text=display_text,
+ )
+ except TelegramBadRequest as e:
+ if "can't parse entities" in str(e):
+ if stream_cf == "native" and chat_id and draft_id:
+ await bot.send_message_draft(
+ chat_id=chat_id,
+ draft_id=draft_id,
+ text=display_text,
+ parse_mode=None,
+ )
+ elif stream_cf == "edit" and chat_id and message_id:
+ await bot.edit_message_text(
+ chat_id=chat_id,
+ message_id=message_id,
+ text=display_text,
+ parse_mode=None,
+ )
+ elif stream_cf == "edit" or stream_cf == "native" and inline_id:
+ await bot.edit_message_text(
+ inline_message_id=inline_id,
+ text=display_text,
+ parse_mode=None,
+ )
+ else:
+ print(f"{YELLOW} -- {e}{RESET}")
+ except Exception as e:
+ print(f"{YELLOW} -- {e}{RESET}")
text = message
else:
- text = completion.choices[0].message.content
+ async for completion in ai.completions(**alo):
+ pass
+ text = completion["choices"][0]["message"]["content"]
except Exception as e:
error = parse_response(str(e).lower())
print(f"{RED} -- {error['type']} - {e}{RESET}")
diff --git a/vars.py b/vars.py
new file mode 100644
index 0000000..0fcb5e4
--- /dev/null
+++ b/vars.py
@@ -0,0 +1,5 @@
+last_command_time = {}
+last_error_time = {}
+last_block_time = {}
+alo_command = {}
+user_contexts = {}