фикс я хуй знает много чего я добавил
This commit is contained in:
1 parent
ca0f5bf3de
commit
891131b88e
11 files changed
+850
-577
No files matched your search
+118
-265
@@ -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 = {
|
||||
@@ -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}")
|
||||
|
||||
Reference in new issue
Block a user