Skip to content

Commit

Permalink
Reply message: prompt construction fixed (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
s-nagaev committed Apr 16, 2024
1 parent 6d23d26 commit ff11e05
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 189 deletions.
8 changes: 8 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.2.3] - 2024-04-17

### Changed

- Reply message logic: prompt construction logic is fixed.
- Now, the provider list contains only providers explicitly marked as `working`


## [0.2.2] - 2024-04-16

### Changed
Expand Down
5 changes: 4 additions & 1 deletion hiroshi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ def provider(self) -> BaseProvider | RetryProvider:
if not self.provider_name:
return default_model.best_provider
if active_provider := ProviderUtils.convert.get(self.provider_name):
return active_provider
if active_provider.working:
return active_provider
else:
return default_model.best_provider
logger.error(f"Unsupported provider selected: {self.provider_name}. Replacing it with the default one.")
return default_model.best_provider

Expand Down
6 changes: 3 additions & 3 deletions hiroshi/services/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@ async def handle_prompt(db: Database, update: Update, context: ContextTypes.DEFA
if prompt.startswith("/ask"):
prompt = prompt.replace("/ask", "", 1).strip()

# Get replied message concatenated to the prompt.
prompt = get_prompt_with_replied_message(update=update, initial_prompt=prompt)

prompt_to_log = prompt.replace("\r", " ").replace("\n", " ")
logger.info(
f"{telegram_user.name} (Telegram ID: {telegram_user.id}) sent a new message in the "
f"{telegram_chat.type.upper()} chat {telegram_chat.id}"
f"{': ' + prompt_to_log if application_settings.log_prompt_data else ''}"
)

# Get replied message concatenated to the prompt.
prompt = get_prompt_with_replied_message(update=update, prompt=prompt)

get_gtp_chat_answer_task = asyncio.ensure_future(get_gtp_chat_answer(chat_id=telegram_chat.id, prompt=prompt))

while not get_gtp_chat_answer_task.done():
Expand Down
7 changes: 6 additions & 1 deletion hiroshi/services/gpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from loguru import logger

from hiroshi.config import gpt_settings
from hiroshi.utils import is_provider_active

MODELS_AND_PROVIDERS: dict[str, tuple[str, str]] = {
"Default": ("gpt_35_long", "Default"),
Expand Down Expand Up @@ -43,4 +44,8 @@ async def get_chat_response(


def retrieve_available_providers() -> list[str]:
return list(MODELS_AND_PROVIDERS.keys())
return [
key
for key in MODELS_AND_PROVIDERS
if is_provider_active(MODELS_AND_PROVIDERS[key]) or "Default" in MODELS_AND_PROVIDERS[key]
]
42 changes: 29 additions & 13 deletions hiroshi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Any, Callable

import httpx
from g4f.Provider import ProviderUtils
from loguru import logger
from telegram import Chat as TelegramChat
from telegram import Message as TelegramMessage
Expand Down Expand Up @@ -36,14 +37,19 @@ def get_telegram_message(update: Update) -> TelegramMessage:
raise ValueError(f"Telegram incoming update does not contain valid message data. Update ID: {update.update_id}")


def get_prompt_with_replied_message(update: Update, prompt: str) -> str:
def get_prompt_with_replied_message(update: Update, initial_prompt: str) -> str:
if not update.message or not update.message.reply_to_message:
return initial_prompt

user = get_telegram_user(update)
if quoted_user := update.message.reply_to_message.from_user:
quoted_user_name = quoted_user.name
else:
quoted_user_name = "user"

quoted_message = update.message.reply_to_message.caption or update.message.reply_to_message.text
prompt = f"> {quoted_message}\n>\n> — *{quoted_user_name}*\n\n" f"{user.username}: {initial_prompt}"

if update.message and update.message.reply_to_message:
prompt = (f'<<{update.message.reply_to_message.caption or update.message.reply_to_message.text}.>> '
f'{user.username} answered: {prompt}')
if update.message.reply_to_message.from_user:
prompt = f' {update.message.reply_to_message.from_user.username} said: ' + prompt
return prompt


Expand Down Expand Up @@ -243,9 +249,11 @@ def log_application_settings() -> None:
logger_info = "<red>DISABLED</red>."

if application_settings.monitoring_url:
logger_info = (f"<blue>ACTIVE</blue>."
f"MONITORING_FREQUENCY_CALL=<blue>{application_settings.monitoring_frequency_call}</blue>."
f"MONITORING_URL=<blue>{application_settings.monitoring_url}</blue>")
logger_info = (
f"<blue>ACTIVE</blue>."
f"MONITORING_FREQUENCY_CALL=<blue>{application_settings.monitoring_frequency_call}</blue>."
f"MONITORING_URL=<blue>{application_settings.monitoring_url}</blue>"
)

messages = (
f"Application is initialized using {storage} storage.",
Expand Down Expand Up @@ -273,14 +281,22 @@ async def run_monitoring(context: ContextTypes.DEFAULT_TYPE) -> None:
if not application_settings.monitoring_url:
return

transport = httpx.AsyncHTTPTransport(retries=application_settings.monitoring_retry_calls,
proxy=application_settings.monitoring_proxy)
transport = httpx.AsyncHTTPTransport(
retries=application_settings.monitoring_retry_calls, proxy=application_settings.monitoring_proxy
)

async with httpx.AsyncClient(transport=transport, proxy=application_settings.monitoring_proxy) as client:
try:
result = await client.get(application_settings.monitoring_url)
except Exception as error:
logger.error(f'Uptime Checker failed with an Exception: {error}')
logger.error(f"Uptime Checker failed with an Exception: {error}")
return
if result.is_error:
logger.error(f'Uptime Checker failed. status_code({result.status_code}) msg: {result.text}')
logger.error(f"Uptime Checker failed. status_code({result.status_code}) msg: {result.text}")


def is_provider_active(model_and_provider_names: tuple[str, str]) -> bool:
_, provider_name = model_and_provider_names
if provider := ProviderUtils.convert.get(provider_name):
return bool(provider.working)
return False
10 changes: 5 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
filters,
)

from hiroshi.config import telegram_settings, application_settings
from hiroshi.config import application_settings, telegram_settings
from hiroshi.services.bot import (
handle_available_providers_options,
handle_prompt,
Expand Down Expand Up @@ -165,11 +165,11 @@ def run(self) -> None:
# )
app.add_error_handler(self.error_handler)
if not app.job_queue:
logger.error('Application job queue was shut down or never started.')
logger.error("Application job queue was shut down or never started.")
else:
app.job_queue.run_repeating(callback=run_monitoring,
interval=application_settings.monitoring_frequency_call,
first=0.0)
app.job_queue.run_repeating(
callback=run_monitoring, interval=application_settings.monitoring_frequency_call, first=0.0
)

app.run_polling()

Expand Down
Loading

0 comments on commit ff11e05

Please sign in to comment.