фикс я хуй знает много чего я добавил
This commit is contained in:
1 parent
ca0f5bf3de
commit
891131b88e
11 files changed
+830
-557
No files matched your search
@@ -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.
|
||||
@@ -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
|
||||
+12
-100
@@ -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]
|
||||
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)
|
||||
if new_status == "native" or new_status == "edit":
|
||||
set_user_config(
|
||||
|
||||
alo = {
|
||||
data[1]: new_status
|
||||
}
|
||||
|
||||
set_user_setting(
|
||||
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]
|
||||
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"),
|
||||
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(
|
||||
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)
|
||||
|
||||
|
||||
+10
-8
@@ -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}",
|
||||
),
|
||||
|
||||
],
|
||||
|
||||
+35
-9
@@ -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"
|
||||
|
||||
# модель которая умеет принимать картинки очень важно
|
||||
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")
|
||||
+292
-1
@@ -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
|
||||
|
||||
+156
@@ -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
|
||||
@@ -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,12 +161,27 @@ 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:
|
||||
location = 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,16 +224,14 @@ 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)
|
||||
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()
|
||||
|
||||
@@ -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)
|
||||
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:
|
||||
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,6 +348,9 @@ async def guest_middleware(handler, event, data):
|
||||
]
|
||||
)
|
||||
if event.guest_message:
|
||||
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```"))
|
||||
@@ -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:
|
||||
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())
|
||||
|
||||
@@ -2,4 +2,3 @@ aiogram==3.29.1
|
||||
python-dotenv==1.2.1
|
||||
pillow==12.0.0
|
||||
requests
|
||||
openai
|
||||
+103
-250
@@ -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:
|
||||
elif stream_cf == "edit" and chat_id and message_id and settings.get("nostream", False) == False:
|
||||
stream = True
|
||||
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 = {
|
||||
@@ -390,55 +200,98 @@ 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```"
|
||||
|
||||
if counter < 3950:
|
||||
display_text += "▋"
|
||||
|
||||
try:
|
||||
if stream_cf == "native":
|
||||
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="Markdown",
|
||||
)
|
||||
elif stream_cf == "edit":
|
||||
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="Markdown",
|
||||
)
|
||||
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}")
|
||||
|
||||
Reference in new issue
Block a user