feat: multi-user awareness in chat, per-user /talk prompt, thinking tokens for /talk
This commit is contained in:
parent
acb7421cc0
commit
89a14f2ebf
1 changed files with 29 additions and 4 deletions
|
|
@ -41,6 +41,8 @@ SUMMARY_LINE_CHAR_LIMIT = 220
|
||||||
HISTORY_LINE_CHAR_LIMIT = 450
|
HISTORY_LINE_CHAR_LIMIT = 450
|
||||||
RETRY_MIN_MAX_TOKENS = 512
|
RETRY_MIN_MAX_TOKENS = 512
|
||||||
RETRY_MAX_MAX_TOKENS = 1_024
|
RETRY_MAX_MAX_TOKENS = 1_024
|
||||||
|
TALK_MAX_TOKENS = 1536
|
||||||
|
TALK_THINKING_BUDGET = 1024
|
||||||
|
|
||||||
REPLY_RULES = {
|
REPLY_RULES = {
|
||||||
"mention": {"cooldown": 25, "min_user_messages": 1},
|
"mention": {"cooldown": 25, "min_user_messages": 1},
|
||||||
|
|
@ -128,10 +130,21 @@ BOT_STYLE_PROMPT = (
|
||||||
|
|
||||||
SYSTEM_PROMPT = (
|
SYSTEM_PROMPT = (
|
||||||
f"{BOT_STYLE_PROMPT}\n\n"
|
f"{BOT_STYLE_PROMPT}\n\n"
|
||||||
"Ты отвечаешь как живой участник одного Telegram-чата. "
|
"Ты отвечаешь как живой участник Telegram-чата с несколькими разными людьми. "
|
||||||
|
"Сообщения в истории записаны в формате «Имя: текст» — каждое имя это отдельный человек, не путай их. "
|
||||||
|
"Отвечай тому, кто написал последним, учитывай контекст именно его сообщений. "
|
||||||
"Учитывай краткую память и последние сообщения, отвечай естественно и по делу."
|
"Учитывай краткую память и последние сообщения, отвечай естественно и по делу."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
TALK_SYSTEM_PROMPT = (
|
||||||
|
f"{BOT_STYLE_PROMPT}\n\n"
|
||||||
|
"Ты ведёшь личный разговор тет-а-тет с одним конкретным человеком через /talk. "
|
||||||
|
"Помни всё, что он говорил раньше — ты видишь историю этого разговора и должен её учитывать. "
|
||||||
|
"Замечай если человек продолжает старую тему или переходит к новой. "
|
||||||
|
"Отвечай КОРОТКО: 1–3 предложения максимум. "
|
||||||
|
"Только если тебя прямо попросили объяснить, развернуть или написать подробно — тогда можно больше."
|
||||||
|
)
|
||||||
|
|
||||||
AUTOREPLY_SYSTEM_PROMPT = (
|
AUTOREPLY_SYSTEM_PROMPT = (
|
||||||
f"{BOT_STYLE_PROMPT}\n\n"
|
f"{BOT_STYLE_PROMPT}\n\n"
|
||||||
"Ты иногда сам коротко и уместно влезаешь в разговор в Telegram-чате. "
|
"Ты иногда сам коротко и уместно влезаешь в разговор в Telegram-чате. "
|
||||||
|
|
@ -533,6 +546,7 @@ async def _call_single_model(
|
||||||
temperature: float,
|
temperature: float,
|
||||||
top_p: float,
|
top_p: float,
|
||||||
disable_thinking: bool,
|
disable_thinking: bool,
|
||||||
|
reasoning_budget: int = 0,
|
||||||
) -> str:
|
) -> str:
|
||||||
url = f"{api_url.rstrip('/')}/v1/chat/completions"
|
url = f"{api_url.rstrip('/')}/v1/chat/completions"
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
@ -551,6 +565,8 @@ async def _call_single_model(
|
||||||
"reasoning_format": "none",
|
"reasoning_format": "none",
|
||||||
"chat_template_kwargs": {"enable_thinking": False, "thinking": False},
|
"chat_template_kwargs": {"enable_thinking": False, "thinking": False},
|
||||||
})
|
})
|
||||||
|
elif reasoning_budget > 0:
|
||||||
|
payload["reasoning_budget"] = reasoning_budget
|
||||||
timeout = aiohttp.ClientTimeout(total=120)
|
timeout = aiohttp.ClientTimeout(total=120)
|
||||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||||
async with session.post(url, json=payload, headers=headers) as resp:
|
async with session.post(url, json=payload, headers=headers) as resp:
|
||||||
|
|
@ -582,7 +598,7 @@ async def _call_single_model(
|
||||||
messages,
|
messages,
|
||||||
api_url=api_url, api_key=api_key, model=model,
|
api_url=api_url, api_key=api_key, model=model,
|
||||||
max_tokens=retry_max_tokens, temperature=temperature, top_p=top_p,
|
max_tokens=retry_max_tokens, temperature=temperature, top_p=top_p,
|
||||||
disable_thinking=True,
|
disable_thinking=True, reasoning_budget=0,
|
||||||
)
|
)
|
||||||
return cleaned_content
|
return cleaned_content
|
||||||
|
|
||||||
|
|
@ -594,6 +610,7 @@ async def _call_llm(
|
||||||
temperature: float,
|
temperature: float,
|
||||||
top_p: float,
|
top_p: float,
|
||||||
disable_thinking: bool | None = None,
|
disable_thinking: bool | None = None,
|
||||||
|
reasoning_budget: int = 0,
|
||||||
) -> str:
|
) -> str:
|
||||||
disable_thinking = FORCE_DISABLE_THINKING if disable_thinking is None else disable_thinking
|
disable_thinking = FORCE_DISABLE_THINKING if disable_thinking is None else disable_thinking
|
||||||
|
|
||||||
|
|
@ -606,6 +623,7 @@ async def _call_llm(
|
||||||
temperature=temperature,
|
temperature=temperature,
|
||||||
top_p=top_p,
|
top_p=top_p,
|
||||||
disable_thinking=disable_thinking,
|
disable_thinking=disable_thinking,
|
||||||
|
reasoning_budget=reasoning_budget,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Если основная модель не смогла ответить — пробуем fallback
|
# Если основная модель не смогла ответить — пробуем fallback
|
||||||
|
|
@ -622,6 +640,7 @@ async def _call_llm(
|
||||||
temperature=temperature,
|
temperature=temperature,
|
||||||
top_p=top_p,
|
top_p=top_p,
|
||||||
disable_thinking=disable_thinking,
|
disable_thinking=disable_thinking,
|
||||||
|
reasoning_budget=reasoning_budget,
|
||||||
)
|
)
|
||||||
if fallback_result:
|
if fallback_result:
|
||||||
return f"{fallback_result}\n\n<i>🤖 {fallback_model}</i>"
|
return f"{fallback_result}\n\n<i>🤖 {fallback_model}</i>"
|
||||||
|
|
@ -696,6 +715,8 @@ async def _generate_response(
|
||||||
max_tokens: int,
|
max_tokens: int,
|
||||||
temperature: float,
|
temperature: float,
|
||||||
top_p: float,
|
top_p: float,
|
||||||
|
disable_thinking: bool | None = None,
|
||||||
|
reasoning_budget: int = 0,
|
||||||
) -> str:
|
) -> str:
|
||||||
await _maybe_refresh_summary(chat_id, user_id=user_id)
|
await _maybe_refresh_summary(chat_id, user_id=user_id)
|
||||||
if current_content is None:
|
if current_content is None:
|
||||||
|
|
@ -721,6 +742,8 @@ async def _generate_response(
|
||||||
max_tokens=max_tokens,
|
max_tokens=max_tokens,
|
||||||
temperature=temperature,
|
temperature=temperature,
|
||||||
top_p=top_p,
|
top_p=top_p,
|
||||||
|
disable_thinking=disable_thinking,
|
||||||
|
reasoning_budget=reasoning_budget,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1040,11 +1063,13 @@ async def handle_talk(message: Message) -> None:
|
||||||
await message.bot.send_chat_action(chat_id=chat_id, action="typing")
|
await message.bot.send_chat_action(chat_id=chat_id, action="typing")
|
||||||
response = await _generate_response(
|
response = await _generate_response(
|
||||||
chat_id,
|
chat_id,
|
||||||
system_prompt=SYSTEM_PROMPT,
|
system_prompt=TALK_SYSTEM_PROMPT,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
max_tokens=768,
|
max_tokens=TALK_MAX_TOKENS,
|
||||||
temperature=0.7,
|
temperature=0.7,
|
||||||
top_p=0.95,
|
top_p=0.95,
|
||||||
|
disable_thinking=False,
|
||||||
|
reasoning_budget=TALK_THINKING_BUDGET,
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Talk command generation failed")
|
logger.exception("Talk command generation failed")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue