mirror of
https://github.com/MuRuLOSE/limoka.git
synced 2026-06-16 14:34:17 +02:00
Added and updated repositories 2026-03-03 01:27:55
This commit is contained in:
@@ -13,7 +13,7 @@ class DBMod(loader.Module):
|
|||||||
"close_btn": "❌ Close",
|
"close_btn": "❌ Close",
|
||||||
"back_btn": "⬅ Back",
|
"back_btn": "⬅ Back",
|
||||||
"del_btn": "🗑 Delete",
|
"del_btn": "🗑 Delete",
|
||||||
"del_all_btn": "💣 Delete all",
|
"del_all_btn": "❌ Delete all",
|
||||||
"not_found": "🔍 Key {key} not found",
|
"not_found": "🔍 Key {key} not found",
|
||||||
"invalid_key": "⚠ Invalid key",
|
"invalid_key": "⚠ Invalid key",
|
||||||
"page": "📄 Page {current}/{total}",
|
"page": "📄 Page {current}/{total}",
|
||||||
@@ -34,7 +34,7 @@ class DBMod(loader.Module):
|
|||||||
"close_btn": "❌ Закрыть",
|
"close_btn": "❌ Закрыть",
|
||||||
"back_btn": "⬅ Назад",
|
"back_btn": "⬅ Назад",
|
||||||
"del_btn": "🗑 Удалить",
|
"del_btn": "🗑 Удалить",
|
||||||
"del_all_btn": "💣 Удалить все",
|
"del_all_btn": "❌ Удалить все",
|
||||||
"not_found": "🔍 Ключ {key} не найден",
|
"not_found": "🔍 Ключ {key} не найден",
|
||||||
"invalid_key": "⚠ Некорректный ключ",
|
"invalid_key": "⚠ Некорректный ключ",
|
||||||
"page": "📄 Страница {current}/{total}",
|
"page": "📄 Страница {current}/{total}",
|
||||||
@@ -240,6 +240,7 @@ class DBMod(loader.Module):
|
|||||||
{
|
{
|
||||||
"text": self.strings["del_all_btn"],
|
"text": self.strings["del_all_btn"],
|
||||||
"callback": self.confirm_delete_all,
|
"callback": self.confirm_delete_all,
|
||||||
|
"style": "danger",
|
||||||
"args": [key_path],
|
"args": [key_path],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -290,6 +291,7 @@ class DBMod(loader.Module):
|
|||||||
{
|
{
|
||||||
"text": self.strings["back_btn"],
|
"text": self.strings["back_btn"],
|
||||||
"callback": self.navigate_db,
|
"callback": self.navigate_db,
|
||||||
|
"style": "primary",
|
||||||
"args": [key_path[:-1], parent_page],
|
"args": [key_path[:-1], parent_page],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -329,6 +331,7 @@ class DBMod(loader.Module):
|
|||||||
{
|
{
|
||||||
"text": self.strings["del_all_btn"],
|
"text": self.strings["del_all_btn"],
|
||||||
"callback": self.confirm_delete_all,
|
"callback": self.confirm_delete_all,
|
||||||
|
"style": "danger",
|
||||||
"args": [key_path],
|
"args": [key_path],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -344,13 +347,16 @@ class DBMod(loader.Module):
|
|||||||
{
|
{
|
||||||
"text": self.strings["del_btn"],
|
"text": self.strings["del_btn"],
|
||||||
"callback": self.delete_key,
|
"callback": self.delete_key,
|
||||||
|
"styles": "danger",
|
||||||
"args": [key_path],
|
"args": [key_path],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"text": self.strings["back_btn"],
|
"text": self.strings["back_btn"],
|
||||||
|
"style": "primary",
|
||||||
"callback": self.navigate_db,
|
"callback": self.navigate_db,
|
||||||
|
"style": "primary",
|
||||||
"args": [key_path[:-1], parent_page],
|
"args": [key_path[:-1], parent_page],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -363,6 +369,7 @@ class DBMod(loader.Module):
|
|||||||
{
|
{
|
||||||
"text": self.strings["del_btn"],
|
"text": self.strings["del_btn"],
|
||||||
"callback": self.delete_key,
|
"callback": self.delete_key,
|
||||||
|
"style": "danger",
|
||||||
"args": [key_path],
|
"args": [key_path],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -370,6 +377,7 @@ class DBMod(loader.Module):
|
|||||||
{
|
{
|
||||||
"text": self.strings["back_btn"],
|
"text": self.strings["back_btn"],
|
||||||
"callback": self.navigate_db,
|
"callback": self.navigate_db,
|
||||||
|
"style": "primary",
|
||||||
"args": [key_path[:-1], parent_page],
|
"args": [key_path[:-1], parent_page],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -11,26 +11,54 @@
|
|||||||
# Description: Взаимодействие с Cocoon от HikkaHost
|
# Description: Взаимодействие с Cocoon от HikkaHost
|
||||||
# meta developer: @FAmods & @vsecoder_m
|
# meta developer: @FAmods & @vsecoder_m
|
||||||
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/cocoon.png?raw=true
|
# meta banner: https://github.com/FajoX1/FAmods/blob/main/assets/banners/cocoon.png?raw=true
|
||||||
# requires: openai httpx aiohttp
|
# requires: openai httpx aiohttp bs4 markdown
|
||||||
# ---------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import re
|
||||||
import html
|
import html
|
||||||
|
import uuid
|
||||||
import httpx
|
import httpx
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
import markdown
|
||||||
|
|
||||||
from openai import AsyncOpenAI
|
from openai import AsyncOpenAI
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from bs4 import BeautifulSoup, NavigableString
|
||||||
from datetime import datetime, timezone, timedelta
|
from datetime import datetime, timezone, timedelta
|
||||||
|
|
||||||
|
from telethon.tl.types import User
|
||||||
from telethon.errors import MessageNotModifiedError
|
from telethon.errors import MessageNotModifiedError
|
||||||
|
|
||||||
|
from aiogram.exceptions import TelegramBadRequest
|
||||||
|
|
||||||
from .. import loader, utils
|
from .. import loader, utils
|
||||||
|
from ..inline.types import InlineCall
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
TG_ALLOWED = {
|
||||||
|
"b",
|
||||||
|
"strong",
|
||||||
|
"i",
|
||||||
|
"em",
|
||||||
|
"u",
|
||||||
|
"ins",
|
||||||
|
"s",
|
||||||
|
"strike",
|
||||||
|
"del",
|
||||||
|
"a",
|
||||||
|
"code",
|
||||||
|
"pre",
|
||||||
|
"blockquote",
|
||||||
|
"emoji",
|
||||||
|
"tg-emoji",
|
||||||
|
}
|
||||||
|
TAG_MAP = {"strong": "b", "em": "i", "del": "s", "strike": "s", "ins": "u"}
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Usage:
|
class Usage:
|
||||||
spent_nano: int
|
spent_nano: int
|
||||||
@@ -110,6 +138,92 @@ def _percent_remaining(spent: int, total: int) -> float:
|
|||||||
return (remaining / total) * 100.0
|
return (remaining / total) * 100.0
|
||||||
|
|
||||||
|
|
||||||
|
def md_to_tg_html(text: str) -> str:
|
||||||
|
if not text:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
raw_html = markdown.markdown(text, extensions=["fenced_code", "tables", "nl2br"])
|
||||||
|
soup = BeautifulSoup(raw_html, "html.parser")
|
||||||
|
|
||||||
|
def stringify(node, lang=None):
|
||||||
|
res = ""
|
||||||
|
|
||||||
|
for child in node.children:
|
||||||
|
if isinstance(child, NavigableString):
|
||||||
|
res += html.escape(str(child))
|
||||||
|
|
||||||
|
elif child.name:
|
||||||
|
tag_name = child.name
|
||||||
|
|
||||||
|
if tag_name in ["h1", "h2", "h3", "h4", "h5", "h6"]:
|
||||||
|
content = stringify(child)
|
||||||
|
res += f"<b>{content}</b>\n\n"
|
||||||
|
elif tag_name == "p":
|
||||||
|
res += stringify(child) + "\n\n"
|
||||||
|
elif tag_name == "br":
|
||||||
|
res += "\n"
|
||||||
|
elif tag_name == "li":
|
||||||
|
res += f"• {stringify(child)}\n"
|
||||||
|
elif tag_name in ["ul", "ol"]:
|
||||||
|
res += stringify(child) + "\n"
|
||||||
|
elif tag_name == "tr":
|
||||||
|
res += "| " + stringify(child) + "\n"
|
||||||
|
elif tag_name in ["td", "th"]:
|
||||||
|
res += stringify(child) + " | "
|
||||||
|
|
||||||
|
else:
|
||||||
|
target_tag = TAG_MAP.get(tag_name, tag_name)
|
||||||
|
|
||||||
|
if target_tag in TG_ALLOWED:
|
||||||
|
inner_html = stringify(child)
|
||||||
|
|
||||||
|
if not inner_html.strip() and target_tag not in ["code", "pre"]:
|
||||||
|
res += inner_html
|
||||||
|
continue
|
||||||
|
|
||||||
|
if target_tag == "a":
|
||||||
|
href = child.get("href", "")
|
||||||
|
if href:
|
||||||
|
res += f'<a href="{html.escape(href)}">{inner_html}</a>'
|
||||||
|
else:
|
||||||
|
res += inner_html
|
||||||
|
elif target_tag == "code":
|
||||||
|
cls = child.get("class", [])
|
||||||
|
if cls and cls[0].startswith("language-"):
|
||||||
|
res += f'<code class="{cls[0]}">{inner_html}</code>'
|
||||||
|
else:
|
||||||
|
res += f"<code>{inner_html}</code>"
|
||||||
|
elif target_tag == "pre":
|
||||||
|
res += f"<pre>{inner_html}</pre>"
|
||||||
|
else:
|
||||||
|
res += f"<{target_tag}>{inner_html}</{target_tag}>"
|
||||||
|
else:
|
||||||
|
res += stringify(child)
|
||||||
|
return res
|
||||||
|
|
||||||
|
final_text = stringify(soup)
|
||||||
|
|
||||||
|
final_text = re.sub(r"\n{3,}", "\n\n", final_text)
|
||||||
|
return final_text.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def repair_html_tags(html_chunk: str) -> str:
|
||||||
|
if not html_chunk:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
newline_placeholder = f"MARKER_{uuid.uuid4().hex}"
|
||||||
|
|
||||||
|
protected_html = html_chunk.replace("\n", newline_placeholder)
|
||||||
|
|
||||||
|
soup = BeautifulSoup(protected_html, "html.parser")
|
||||||
|
|
||||||
|
repaired_html = soup.decode_contents(formatter=None)
|
||||||
|
|
||||||
|
final_html = repaired_html.replace(newline_placeholder, "\n")
|
||||||
|
|
||||||
|
return final_html
|
||||||
|
|
||||||
|
|
||||||
@loader.tds
|
@loader.tds
|
||||||
class Cocoon(loader.Module):
|
class Cocoon(loader.Module):
|
||||||
"""Взаимодействие с Cocoon от HikkaHost"""
|
"""Взаимодействие с Cocoon от HikkaHost"""
|
||||||
@@ -126,24 +240,25 @@ class Cocoon(loader.Module):
|
|||||||
"<b><emoji document_id=5456307331644037599>❌</emoji>Неверный токен или у вас нет подписки <emoji document_id=5188377234380954537>🌘</emoji> HikkaHost.</b>\n\n"
|
"<b><emoji document_id=5456307331644037599>❌</emoji>Неверный токен или у вас нет подписки <emoji document_id=5188377234380954537>🌘</emoji> HikkaHost.</b>\n\n"
|
||||||
"<emoji document_id=5456672880605565619>🌘</emoji> Получить токен: @hikkahost_bot → <emoji document_id=5208521532942358129>🥚</emoji> Cocoon</b>"
|
"<emoji document_id=5456672880605565619>🌘</emoji> Получить токен: @hikkahost_bot → <emoji document_id=5208521532942358129>🥚</emoji> Cocoon</b>"
|
||||||
),
|
),
|
||||||
"sending_request_to_cocoon": "<emoji document_id=5197252827247841976>🐣</emoji> <b>Обрабатываю запрос в Cocoon...</b>",
|
"sending_request_to_cocoon": "<tg-emoji emoji-id=5197252827247841976>🐣</tg-emoji> <b>Обрабатываю запрос в Cocoon...</b>",
|
||||||
"thinking": (
|
"thinking": (
|
||||||
"<emoji document_id=5197252827247841976>🐣</emoji> <b>Думаю...</b>\n\n"
|
"<tg-emoji emoji-id=5197252827247841976>🐣</tg-emoji> <b>Думаю...</b>\n\n"
|
||||||
"<blockquote>{thoughts}…</blockquote>"
|
"<blockquote>{thoughts}…</blockquote>"
|
||||||
),
|
),
|
||||||
"answer": (
|
"answer": (
|
||||||
"<emoji document_id=5456217626957091223>🌘</emoji> <b>Вопрос:</b> {question}\n\n"
|
"<tg-emoji emoji-id=5456217626957091223>🌘</tg-emoji> <b>Вопрос:</b> {question}\n\n"
|
||||||
"<emoji document_id=5197252827247841976>🐣</emoji> <b>Размышления:</b>\n"
|
"<tg-emoji emoji-id=5197252827247841976>🐣</tg-emoji> <b>Размышления:</b>\n"
|
||||||
"<blockquote expandable>{thoughts}</blockquote>\n\n"
|
"<blockquote expandable>{thoughts}</blockquote>\n\n"
|
||||||
"<emoji document_id=5208521532942358129>🥚</emoji> {answer}\n\n"
|
"<tg-emoji emoji-id=5208521532942358129>🥚</tg-emoji> {answer}\n\n"
|
||||||
"<emoji document_id=5458567764341985638>🚀</emoji> <b>Модель</b>: <code>{model}</code>"
|
"<tg-emoji emoji-id=5458567764341985638>🚀</tg-emoji> <b>Модель</b>: <code>{model}</code>"
|
||||||
),
|
),
|
||||||
"usage": (
|
"usage": (
|
||||||
"<b><emoji document_id=5208521532942358129>🥚</emoji> Cocoon API\n\n"
|
"<b><tg-emoji emoji-id=5208521532942358129>🥚</tg-emoji> Cocoon API\n\n"
|
||||||
"<emoji document_id=5458805877328875335>💡</emoji> Использовано:\n"
|
"<tg-emoji emoji-id=5458805877328875335>💡</tg-emoji> Использовано:\n"
|
||||||
"</b><i>• {current}/{total} ({percent}% осталось)</i><b>\n\n"
|
"</b><i>• {current}/{total} ({percent}% осталось)</i><b>\n\n"
|
||||||
"<emoji document_id=5456591761558245861>⏳</emoji> Лимит сбросится через {days} день(-ей).</b>"
|
"<tg-emoji emoji-id=5456591761558245861>⏳</tg-emoji> Лимит сбросится через {days} день(-ей).</b>"
|
||||||
),
|
),
|
||||||
|
"again_kb": "🔄 Сгенерировать ещё раз",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -163,6 +278,9 @@ class Cocoon(loader.Module):
|
|||||||
"role",
|
"role",
|
||||||
"user",
|
"user",
|
||||||
lambda: "Роль user-сообщения (обычно user).",
|
lambda: "Роль user-сообщения (обычно user).",
|
||||||
|
validator=loader.validators.Choice(
|
||||||
|
["system", "developer", "user", "assistant", "tool"]
|
||||||
|
),
|
||||||
),
|
),
|
||||||
loader.ConfigValue(
|
loader.ConfigValue(
|
||||||
"system_prompt",
|
"system_prompt",
|
||||||
@@ -201,12 +319,13 @@ class Cocoon(loader.Module):
|
|||||||
):
|
):
|
||||||
self._rebuild_openai_client()
|
self._rebuild_openai_client()
|
||||||
|
|
||||||
async def _answer(self, message, text):
|
async def _answer(self, message, text, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
if len(text) > 4096:
|
if len(text) > 4096:
|
||||||
text = text[:4090] + "..."
|
text = text[:4090] + "..."
|
||||||
return await utils.answer(message, text)
|
|
||||||
except MessageNotModifiedError:
|
return await utils.answer(message, repair_html_tags(text), *args, **kwargs)
|
||||||
|
except (MessageNotModifiedError, TelegramBadRequest):
|
||||||
return message
|
return message
|
||||||
|
|
||||||
async def _fetch_usage(self) -> Optional[Usage]:
|
async def _fetch_usage(self) -> Optional[Usage]:
|
||||||
@@ -245,6 +364,9 @@ class Cocoon(loader.Module):
|
|||||||
updated_at=(_safe_int(data.get("updated_at"), 0) or None),
|
updated_at=(_safe_int(data.get("updated_at"), 0) or None),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _regenerate(self, call: InlineCall, arg1, arg2):
|
||||||
|
await self.cocoon(arg1, inline_message=arg2)
|
||||||
|
|
||||||
@loader.command()
|
@loader.command()
|
||||||
async def ccusage(self, message):
|
async def ccusage(self, message):
|
||||||
"""Статистика использования Cocoon"""
|
"""Статистика использования Cocoon"""
|
||||||
@@ -280,8 +402,8 @@ class Cocoon(loader.Module):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@loader.command()
|
@loader.command()
|
||||||
async def cocoon(self, message):
|
async def cocoon(self, message, inline_message=None):
|
||||||
"""Задать вопрос к ИИ"""
|
"""Задать вопрос к ИИ (поддерживает ответ на сообщение)"""
|
||||||
|
|
||||||
q = utils.get_args_raw(message)
|
q = utils.get_args_raw(message)
|
||||||
if not q:
|
if not q:
|
||||||
@@ -299,26 +421,72 @@ class Cocoon(loader.Module):
|
|||||||
if not usage:
|
if not usage:
|
||||||
return await utils.answer(message, self.strings["invalid_token_or_no_sub"])
|
return await utils.answer(message, self.strings["invalid_token_or_no_sub"])
|
||||||
|
|
||||||
message = await utils.answer(message, self.strings["sending_request_to_cocoon"])
|
user_message = message
|
||||||
|
|
||||||
|
if not inline_message:
|
||||||
|
message = await self.inline.form(
|
||||||
|
text="...",
|
||||||
|
message=message,
|
||||||
|
force_me=False,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
message = inline_message
|
||||||
|
|
||||||
|
await utils.answer(message, self.strings["sending_request_to_cocoon"])
|
||||||
|
|
||||||
self._ensure_client()
|
self._ensure_client()
|
||||||
|
|
||||||
client = AsyncOpenAI(api_key=self.config["token"], base_url=self.api_url)
|
|
||||||
|
|
||||||
system_prompt = (self.config.get("system_prompt") or "").strip()
|
system_prompt = (self.config.get("system_prompt") or "").strip()
|
||||||
|
|
||||||
messages = []
|
messages = []
|
||||||
if system_prompt:
|
if system_prompt:
|
||||||
messages.append({"role": "system", "content": system_prompt})
|
messages.append({"role": "system", "content": system_prompt})
|
||||||
messages.append({"role": self.config["role"] or "user", "content": q})
|
|
||||||
|
if user_message.reply_to:
|
||||||
|
reply = await user_message.get_reply_message()
|
||||||
|
|
||||||
|
entity_id = None
|
||||||
|
|
||||||
|
if hasattr(reply, "from_id") and reply.from_id:
|
||||||
|
if hasattr(reply.from_id, "user_id") and reply.from_id.user_id:
|
||||||
|
entity_id = reply.from_id.user_id
|
||||||
|
elif hasattr(reply.from_id, "channel_id") and reply.from_id.channel_id:
|
||||||
|
entity_id = reply.from_id.channel_id
|
||||||
|
|
||||||
|
if entity_id is None:
|
||||||
|
if hasattr(reply.peer_id, "user_id") and reply.peer_id.user_id:
|
||||||
|
entity_id = reply.peer_id.user_id
|
||||||
|
else:
|
||||||
|
entity_id = reply.peer_id.channel_id
|
||||||
|
|
||||||
|
entity = await self.client.get_entity(entity_id)
|
||||||
|
|
||||||
|
date = reply.date.strftime("%H:%M %d.%m.%Y UTC")
|
||||||
|
|
||||||
|
messages.append(
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": (
|
||||||
|
(
|
||||||
|
f"{entity.first_name} {entity.last_name or ''} (user id: {entity.id}) "
|
||||||
|
if isinstance(entity, User)
|
||||||
|
else f"Channel {entity.title} (channel id: {entity.id}) "
|
||||||
|
)
|
||||||
|
+ f"msg id: {reply.id}, date: {date}: "
|
||||||
|
+ reply.message
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
messages.append({"role": self.config.get("role", "user"), "content": q})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = await client.chat.completions.create(
|
response = await self._openai.chat.completions.create(
|
||||||
messages=messages,
|
messages=messages,
|
||||||
stream=True,
|
stream=True,
|
||||||
max_tokens=self.config.get("max_tokens", 3900),
|
max_tokens=self.config.get("max_tokens", 3900),
|
||||||
model=self.config.get("model", "Qwen/Qwen3-32B"),
|
model=self.config.get("model", "Qwen/Qwen3-32B"),
|
||||||
temperature=self.config.get("temperature", 0.2)
|
temperature=self.config.get("temperature", 0.2),
|
||||||
)
|
)
|
||||||
|
|
||||||
response_text = ""
|
response_text = ""
|
||||||
@@ -328,60 +496,57 @@ class Cocoon(loader.Module):
|
|||||||
if chunk.choices and chunk.choices[0].delta.content:
|
if chunk.choices and chunk.choices[0].delta.content:
|
||||||
chunk_buffer += chunk.choices[0].delta.content
|
chunk_buffer += chunk.choices[0].delta.content
|
||||||
|
|
||||||
if len(chunk_buffer) >= 150:
|
if len(chunk_buffer) >= 100:
|
||||||
response_text += chunk_buffer
|
response_text += chunk_buffer
|
||||||
chunk_buffer = ""
|
chunk_buffer = ""
|
||||||
|
|
||||||
thoughts = (
|
thoughts = response_text.split("</think>", 1)[0].replace(
|
||||||
response_text.replace("<think>", "")
|
"<think>", ""
|
||||||
.replace("</think>", "")
|
|
||||||
.strip()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if "</think>" in response_text:
|
if "</think>" in response_text:
|
||||||
after_think = response_text.split("</think>", 1)[-1].strip()
|
after_think = response_text.split("</think>", 1)[1].strip()
|
||||||
await self._answer(
|
await self._answer(
|
||||||
message,
|
message,
|
||||||
self.strings["answer"].format(
|
self.strings["answer"].format(
|
||||||
thoughts=thoughts[:300],
|
thoughts=thoughts[:500],
|
||||||
question=q,
|
question=q,
|
||||||
answer=_escape_text(after_think) + "…",
|
answer=md_to_tg_html(_escape_text(after_think) + "…"),
|
||||||
model=self.config["model"],
|
model=self.config["model"],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
thinking_text = (
|
|
||||||
response_text.replace("<think>", "")
|
|
||||||
.replace("</think>", "")
|
|
||||||
.strip()
|
|
||||||
)
|
|
||||||
await self._answer(
|
await self._answer(
|
||||||
message,
|
message,
|
||||||
self.strings["thinking"].format(
|
self.strings["thinking"].format(
|
||||||
thoughts=_escape_text(thinking_text)
|
thoughts=md_to_tg_html(_escape_text(thoughts) + "…")
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(0.2)
|
||||||
|
|
||||||
if chunk_buffer:
|
if chunk_buffer:
|
||||||
response_text += chunk_buffer
|
response_text += chunk_buffer
|
||||||
|
|
||||||
if "</think>" in response_text:
|
responses_data = response_text.split("</think>", 1)
|
||||||
after_think = response_text.split("</think>", 1)[-1].strip()
|
thoughts = responses_data[0].strip().replace("<think>", "")
|
||||||
else:
|
after_think = responses_data[1].strip()
|
||||||
after_think = (
|
|
||||||
response_text.replace("<think>", "").replace("</think>", "").strip()
|
|
||||||
)
|
|
||||||
|
|
||||||
await self._answer(
|
await self._answer(
|
||||||
message,
|
message,
|
||||||
self.strings["answer"].format(
|
self.strings["answer"].format(
|
||||||
thoughts=thoughts,
|
|
||||||
question=q,
|
question=q,
|
||||||
answer=_escape_text(after_think),
|
thoughts=md_to_tg_html(_escape_text(thoughts[:500])),
|
||||||
|
answer=md_to_tg_html(_escape_text(after_think)),
|
||||||
model=self.config["model"],
|
model=self.config["model"],
|
||||||
),
|
),
|
||||||
|
reply_markup=[
|
||||||
|
{
|
||||||
|
"text": self.strings["again_kb"],
|
||||||
|
"callback": self._regenerate,
|
||||||
|
"args": [user_message, message],
|
||||||
|
}
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
except httpx.RemoteProtocolError:
|
except httpx.RemoteProtocolError:
|
||||||
|
|||||||
@@ -44,3 +44,4 @@ spotify4ik
|
|||||||
picme
|
picme
|
||||||
hetsu
|
hetsu
|
||||||
ptichki
|
ptichki
|
||||||
|
cocoon
|
||||||
|
|||||||
Reference in New Issue
Block a user