УЛЬТРА КРУТОЙ ВАЙБКОД ФИКСЫ И АВТОМОДЕЛЬ ТЕСЛА

This commit is contained in:
huker667 committed 2026-09-15 21:34:10 +03:00
1 parent 5be8fcce19
commit b0541faa3d
8 files changed
+315 -93

No files matched your search

+45 -14
View File
@@ -28,28 +28,35 @@ async def select_provider_callback(callback: CallbackQuery):
buttons = []
i = 0
shown = set()
for model in MODELS.get(provider):
base_model = model.split("*")[0] if "*" in model else model
if base_model in shown:
continue
shown.add(base_model)
i += 1
if f"{provider}*{model}" == user_model:
text = f"{model} ✅"
full_model = f"{provider}*{base_model}"
if full_model == user_model or user_model.startswith(full_model + "*"):
text = f"{base_model} ✅"
else:
text = model
text = base_model
if MODELS[provider][model].get("alias"):
model = MODELS[provider][model].get("alias")
base_model = MODELS[provider][model].get("alias")
if not i % 2:
buttons[len(buttons)-1] +=[
InlineKeyboardButton(
text=text, callback_data=f"set_model%{user_id}%{provider}*{model}"
text=text, callback_data=f"set_model%{user_id}%{provider}*{base_model}"
)
]
else:
buttons.append(
[
InlineKeyboardButton(
text=text, callback_data=f"set_model%{user_id}%{provider}*{model}"
text=text, callback_data=f"set_model%{user_id}%{provider}*{base_model}"
)
]
)
@@ -75,9 +82,12 @@ async def select_provider_callback(callback: CallbackQuery):
@router.callback_query(F.data.startswith("models%"))
async def models_callback(callback: CallbackQuery):
async def models_callback(callback: CallbackQuery, alo=""):
current_user_id = str(callback.from_user.id)
data = callback.data.split("%", 1)
if alo:
data = alo.split("%", 1)
else:
data = callback.data.split("%", 1)
user_id = data[1]
if user_id == current_user_id:
config = get_user_config(user_id)
@@ -86,6 +96,16 @@ async def models_callback(callback: CallbackQuery):
i = 0
if AUTO_MODEL and AUTO_MODELS:
if config["model"] == "all*auto":
buttons.append(
[InlineKeyboardButton(text="✅ автовыбор", callback_data=f"set_model%{user_id}%{DEFAULT_MODEL}")]
)
else:
buttons.append(
[InlineKeyboardButton(text="😱 автовыбор", callback_data=f"set_model%{user_id}%all*auto")]
)
for provider in MODELS:
i += 1
if not i % 2:
@@ -134,12 +154,16 @@ async def set_model_callback(callback: CallbackQuery):
user_id, new_model = data[1], data[2]
provider = data[2].split("*", 1)[0]
amodel = data[2].split("*", 1)[1]
new_model = provider + "*" + amodel
for model in MODELS.get(provider):
nmodel = MODELS[provider][model].get("alias") or None
if nmodel == amodel:
new_model = provider + "*" + model
if amodel == "auto" and provider == "all":
new_model = "all*auto"
else:
new_model = provider + "*" + amodel
for model in MODELS.get(provider, {}):
nmodel = MODELS[provider][model].get("alias") or None
if nmodel == amodel:
new_model = provider + "*" + model
break
if user_id == current_user_id:
current_config = get_user_config(user_id)
@@ -153,7 +177,14 @@ async def set_model_callback(callback: CallbackQuery):
current_config.get("markdown"),
current_config.get("prompts")
)
await callback.message.edit_text(f"выбрана модель: `{new_model}`")
await callback.message.edit_text(
f"выбрана модель: `{new_model}`",
reply_markup=InlineKeyboardMarkup(inline_keyboard=
[
[InlineKeyboardButton(text="⬅️ назад", callback_data=f"models%{user_id}")]
]
)
)
await callback.answer(f"выбрано: {new_model}")
else:
await callback.answer("нет, не трогай")
+9 -1
View File
@@ -34,6 +34,14 @@ BOT_USERNAME = "UzbekGPTTestBot"
# на что бот откликается
BOT_CALLS = ["узбек", "uzbek", f"@{BOT_USERNAME}"]
# включить в настройках автовыбор модели
AUTO_MODEL = True
AUTO_MODELS = [
"ollama*gemma4:31b-cloud*1",
"ollama*gemma4:31b-cloud*2",
"krutoiapi*claude-mythos-5",
]
# дефолт настройки для новых юзеров
DEFAULT_MODEL = "ollama*gemma4:31b-cloud"
DEFAULT_STREAM = "none"
@@ -75,7 +83,7 @@ PROVIDERS = {
"name": "оллама",
"module": "openai",
"url": "http://127.0.0.1:11434/v1",
"key": "da",
"key": ["da", "da2"],
},
"krutoiapi": {
"name": "ваше крутое api",
+39
View File
@@ -269,6 +269,45 @@ def clean_tail_repeats(text: str, max_repeat: int = 10):
return cleaned, removed_count
def get_key(provider, model_full):
prov = PROVIDERS.get(provider, {})
key = prov.get("key", "")
if isinstance(key, list):
parts = model_full.split("*")
if len(parts) >= 3:
try:
idx = int(parts[2]) - 1
except ValueError:
return key[0]
if 0 <= idx < len(key):
return key[idx]
return key[0]
return key
_expanded_auto_models = None
def expand_auto_models():
global _expanded_auto_models
if _expanded_auto_models is not None:
return _expanded_auto_models
result = []
for entry in AUTO_MODELS:
parts = entry.split("*", 2)
provider = parts[0]
model = parts[1]
suffix = parts[2] if len(parts) >= 3 else None
prov_key = PROVIDERS.get(provider, {}).get("key", "")
if isinstance(prov_key, list) and not suffix:
for i in range(len(prov_key)):
result.append(f"{provider}*{model}*{i + 1}")
else:
result.append(entry)
_expanded_auto_models = result
return result
def parse_response(text: str):
if "connection error." in text:
return {
+16 -7
View File
@@ -161,7 +161,8 @@ async def guest_middleware(handler, event, data):
voice = None
model = config["model"].split("*", 1)
model = config["model"].split("*")
is_auto = config["model"] == "all*auto" and AUTO_MODEL and AUTO_MODELS
if VOSK_API != "":
if message.voice:
@@ -169,12 +170,20 @@ async def guest_middleware(handler, event, data):
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 is_auto:
process = {
"text": "wait",
"photo_a": "wait" if replied and replied.photo else None,
"photo": "wait" if message.photo else None,
"stt": "wait" if voice else None,
}
else:
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):
+1 -1
View File
@@ -1,4 +1,4 @@
aiogram==3.29.1
aiogram==3.31.0
python-dotenv==1.2.1
pillow==12.0.0
requests
+161 -70
View File
@@ -1,20 +1,13 @@
import random
import re
import shelve
import time
import ai
from configparser import DEFAULTSECT
from pprint import pprint
from statistics import *
from colors import *
from helpers import *
from config import *
from vars import *
from trust import *
from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError
from aiogram.exceptions import TelegramBadRequest
async def generate(
@@ -25,13 +18,13 @@ async def generate(
user_contexts[user_id] = []
config = get_user_config(user_id)
if "*" in config.get("model", ""):
model = config.get("model").split("*", 2)
else:
print(f"{RED} -- err model - failed to get prov&model in \"{config.get('model','')}\"{RESET}")
model_str = config.get("model", "")
if "*" not in model_str:
print(f"{RED} -- err model - failed to get prov&model in \"{model_str}\"{RESET}")
return "произошла ошибка при парсинге вашей выбранной модели. либо хост бота гандон либо тебе надо сменить модель в настройках!!"
settings = MODELS.get(model[0]).get(model[1])
is_auto = model_str == "all*auto" and AUTO_MODEL and AUTO_MODELS
model = model_str.split("*")
stream_cf = config.get("stream", "none")
system_prompt_name = config.get("prompt", "")
@@ -55,18 +48,12 @@ async def generate(
f"2. конфиг бота настроен неправильно и надо связаться с тем кто его хостит"
return text
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" or stream_cf == "native" and inline_id:
stream = True
else:
stream = False
content = []
if images:
if images and not is_auto:
provider_name = model[0]
model_name = model[1]
settings = MODELS.get(provider_name, {}).get(model_name, {})
if settings.get("vision"):
for image in images:
content += [{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image['data']}"}}]
@@ -101,22 +88,10 @@ async def generate(
messages = [{"role": "system", "content": system_prompt}] + context
else:
model = DEFAULT_MODEL.split("*", 2)
settings = MODELS.get(model[0]).get(model[1])
stream = False
is_auto = True
model = ["all", "auto"]
stream_cf = "none"
content = []
if images:
if settings.get("vision"):
for image in images:
content += [{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image['data']}"}}]
else:
for image in images:
try:
image_text = await image2text(image["data"])
prompt = f"<фото>{image_text}</фото>\n{prompt}"
except Exception as e:
print(f"{RED} -- err photo - {e} : {model}{RESET}")
content += [{"type": "text", "text": prompt}]
messages = [{"role": "system", "content": SYSTEM_PROMPTS[DEFAULT_PROMPT]["text"]+ADD_TO_PROMPT+OLD_MD}] + [
@@ -130,37 +105,112 @@ async def generate(
add_one_to("stats/gens")
try:
provider = PROVIDERS[model[0]]
except Exception:
text = "❌произошла ошибка, возможные проблемы:\n" \
"1. у вас выбрана удалённая модель или провайдер\n" \
"2. конфиг бота настроен неправильно и надо связаться с тем кто его хостит"
return text
if is_auto:
photo_summary = ""
if images:
for image in images:
try:
if process and msg and message:
process[image["process"]] = "make"
await msg.edit_text(make_graph(message, process))
image_text = await image2text(image["data"])
photo_summary += f"<фото>{image_text}</фото>\n"
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} : all*auto{RESET}")
else:
if process and msg and message:
process[image["process"]] = "done"
await msg.edit_text(make_graph(message, process))
if process and msg and message:
process["text"] = "make"
await msg.edit_text(make_graph(message, process))
expanded = expand_auto_models()
expanded = sorted(expanded, key=lambda e: get_trust(e.split("*"))[1], reverse=True)
last_type = ""
for entry in expanded:
if last_type == "da":
break
parts = entry.split("*")
provider_name = parts[0]
model_name = parts[1]
provider = PROVIDERS.get(provider_name)
if not provider:
continue
settings = MODELS.get(provider_name, {}).get(model_name, {})
key = get_key(provider_name, entry)
text = await openai_generate_text(
api=provider,
bot=bot,
model=model[1],
settings=settings,
messages=messages,
stream=stream,
stream_cf=stream_cf,
chat_id=chat_id,
draft_id=chat_id,
message_id=message_id,
inline_id=inline_id
)
auto_content = [{"type": "text", "text": photo_summary + prompt if images and not settings.get("vision") else prompt}]
if images and settings.get("vision"):
for image in images:
auto_content += [{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image['data']}"}}]
auto_messages = [{"role": "system", "content": messages[0]["content"]}, {"role": "user", "content": auto_content}] + messages[2:]
text = await openai_generate_text(
api=provider,
api_key=key,
bot=bot,
model=model_name,
settings=settings,
messages=auto_messages,
stream=False,
stream_cf=stream_cf,
chat_id=chat_id,
draft_id=chat_id,
message_id=message_id,
inline_id=inline_id
)
update_trust(parts, text)
last_type = text["type"]
if text == "":
text = {"type": "error", "text": "все модели в автовыборе вернули ошибку"}
else:
provider_name = model[0]
model_name = model[1]
provider = PROVIDERS.get(provider_name)
if not provider:
return "❌произошла ошибка, возможные проблемы:\n" \
"1. у вас выбрана удалённая модель или провайдер\n" \
"2. конфиг бота настроен неправильно и надо связаться с тем кто его хостит"
settings = MODELS.get(provider_name, {}).get(model_name, {})
key = get_key(provider_name, model_str)
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" or stream_cf == "native" and inline_id:
stream = True
else:
stream = False
if process and msg and message:
process["text"] = "make"
await msg.edit_text(make_graph(message, process))
text = await openai_generate_text(
api=provider,
api_key=key,
bot=bot,
model=model_name,
settings=settings,
messages=messages,
stream=stream,
stream_cf=stream_cf,
chat_id=chat_id,
draft_id=chat_id,
message_id=message_id,
inline_id=inline_id
)
update_trust(model, text)
if user_id:
user_contexts[user_id].append({"role": "assistant", "content": [{"type": "text", "text": text}]})
user_contexts[user_id].append({"role": "assistant", "content": {"type": "text", "text": text["text"]}})
user_contexts[user_id] = user_contexts[user_id][-MAX_CONTEXT:]
return text
return text["text"]
async def image2text(image) -> str:
@@ -178,12 +228,23 @@ async def image2text(image) -> str:
}
]
async for completion in ai.completions(
url=api["url"], api_key=api["key"], model=model[1], messages=messages, stream=False
url=api["url"], api_key=get_key(model[0], IMAGE_MODEL), model=model[1], messages=messages, stream=False
):
pass
return completion["choices"][0]["message"]["content"]
def extract_error(resp):
if isinstance(resp, dict):
err = resp.get("error")
if isinstance(err, dict):
return str(err.get("message") or err)
elif err:
return str(err)
return str(resp.get("message") or "") if "message" in resp else ""
return ""
async def openai_generate_text(
api,
bot,
@@ -195,7 +256,8 @@ async def openai_generate_text(
chat_id=None,
draft_id=None,
message_id=None,
inline_id=None
inline_id=None,
api_key=None
) -> str:
try:
extra_body = {
@@ -206,7 +268,7 @@ async def openai_generate_text(
alo = {
"url": api["url"],
"api_key": api["key"],
"api_key": api_key or api["key"],
"model": model,
"messages": messages,
"stream": stream,
@@ -222,10 +284,17 @@ async def openai_generate_text(
if not draft_id:
draft_id = chat_id
async for chunk in ai.completions(**alo):
# chunk = json.loads(chunk)
try:
content = chunk["choices"][0]["delta"]["content"]
except:
err_text = extract_error(chunk)
if err_text:
error = parse_response(err_text.lower())
print(f"{RED} -- {error['type']} - {err_text}{RESET}")
return {
"type": "error",
"text": error["message"]
}
continue
if content:
message += content
@@ -295,15 +364,37 @@ async def openai_generate_text(
else:
async for completion in ai.completions(**alo):
pass
text = completion["choices"][0]["message"]["content"]
try:
text = completion["choices"][0]["message"]["content"]
except Exception as e:
err_text = extract_error(completion)
if err_text:
error = parse_response(err_text.lower())
print(f"{RED} -- {error['type']} - {err_text}{RESET}")
return {
"type": "error",
"text": error["message"]
}
error = parse_response(str(completion).lower())
print(f"{RED} -- {error['type']} - {completion}{RESET}")
return {
"type": "error",
"text": error["message"]
}
except Exception as e:
error = parse_response(str(e).lower())
print(f"{RED} -- {error['type']} - {e}{RESET}")
return error["message"]
return {
"type": "error",
"text": error["message"]
}
else:
text, s = clean_tail_repeats(text)
if s > 0:
text += f"*... <{s} обрезано>*"
if text == "":
text = "(пустой ответ)"
return text
return {
"type": "da",
"text": text
}
+36
View File
@@ -0,0 +1,36 @@
from vars import models_trust
def trust_key(m: list):
if len(m) >= 3:
return m[0] + '*' + m[1] + '*' + m[2]
return m[0] + '*' + m[1]
def update_trust(m: list, text: dict):
provider_key = m[0]
model_key = trust_key(m)
if provider_key not in models_trust:
set_trust(provider_key, 80.0)
if model_key not in models_trust:
set_trust(model_key, 60.0)
if text['type'] == 'error':
if models_trust[model_key] > 10:
models_trust[model_key] += -0.5
models_trust[provider_key] += -0.08
elif text['type'] == 'net':
if models_trust[model_key] > 10:
models_trust[model_key] += -0.2
models_trust[provider_key] += -0.05
elif text['type'] == 'da':
if models_trust[model_key] < 100:
models_trust[model_key] += 2
models_trust[provider_key] += 0.2
def get_trust(m: list):
return models_trust.get(m[0], 80.0), models_trust.get(trust_key(m), 60.0)
def set_trust(m: str, trust: float):
models_trust[m] = trust
+8
View File
@@ -1,6 +1,14 @@
# таймаут
last_command_time = {}
# от флуда ошибками
last_error_time = {}
# надо удалить но боюсь что придётся фиксить
last_block_time = {}
# для ввода текста msg_input.py
alo_command = {}
# контекст пользователей
user_contexts = {}
# темпбан
temp_benned = {}
# доверие к провейдерам и моделям по ошибкам для автовыбора и значков в выборе моделей
models_trust = {}