smart-bot-factory 0.2.4__tar.gz → 0.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of smart-bot-factory might be problematic. Click here for more details.
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/PKG-INFO +1 -1
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/best-valera.py +248 -239
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/pyproject.toml +1 -1
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/bot_builder.py +65 -4
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/handlers/handlers.py +14 -1
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/supabase/client.py +3 -12
- smart_bot_factory-0.2.6/smart_bot_factory/utils/__init__.py +10 -0
- smart_bot_factory-0.2.6/smart_bot_factory/utils/user_prompt_loader.py +56 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/uv.lock +1 -1
- smart_bot_factory-0.2.4/smart_bot_factory/utils/__init__.py +0 -9
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.claude/settings.local.json +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.env.example +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.github/ISSUE_TEMPLATE//342/234/250-/320/267/320/260/320/277/321/200/320/276/321/201-/321/204/321/203/320/275/320/272/321/206/320/270/320/270.md" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.github/ISSUE_TEMPLATE//360/237/220/233-/320/261/320/260/320/263-/321/200/320/265/320/277/320/276/321/200/321/202.md" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.github/workflows/ci.yml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.github/workflows/publish-private.yml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.github/workflows/publish.yml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.gitignore +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/.python-version +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/CLIENTS_USAGE.md +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/Dockerfile +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/LICENSE +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/README.md +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/1sales_context.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/final_instructions.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/tests/quick_scenarios.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/welcome_files/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/welcome_files//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/prompts/final_instructions.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/tests/quick_scenarios.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/welcome_files/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/welcome_files//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/configs/valera/cats//320/224/320/276/320/263/320/276/320/262/320/276/321/200.pdf" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/configs/valera/cats//320/272/320/276/320/275/320/270.jpg" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/configs/valera/cats//320/272/320/276/321/202.jpg" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/configs/valera/cats//320/273/320/265/321/201.jpg" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/configs/valera/tests/fixes_elina.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/configs/valera/welcome_file//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/create_tag.sh +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/docker-compose.yml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/env.example +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/requirements.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/save_backup.sh +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/save_fixes.sh +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/__init__.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/__init__.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_logic.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_manager.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_migration.sql +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_tester.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/timeout_checker.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/analytics/analytics_manager.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/cli.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/config.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/1sales_context.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/2product_info.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/3objection_handling.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/final_instructions.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/help_message.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/prompts/welcome_message.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064229.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064335.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/reports/test_20250924_064638.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/tests/quick_scenarios.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/tests/realistic_scenarios.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/tests/scenario_examples.yaml +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/welcome_file/welcome_file_msg.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/configs/growthmed-october-24/welcome_file//320/247/320/265/320/272 /320/273/320/270/321/201/321/202 /320/277/320/276 152/320/244/320/227 /320/270 323/320/244/320/227 /320/264/320/273/321/217 /320/274/320/265/320/264/320/270/321/206/320/270/320/275/321/213.pdf" +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/bot_utils.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/conversation_manager.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/decorators.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/message_sender.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/router.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/router_manager.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/states.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/telegram_router.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/__init__.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/bot_testing.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/event/__init__.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/integrations/openai_client.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/integrations/supabase_client.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/message/__init__.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/router/__init__.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/setup_checker.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/supabase/__init__.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/table/database_structure.sql +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/table/schema.sql +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/utils/debug_routing.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/utils/prompt_loader.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/utm_link_generator.py +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/system_prompt_example.txt +0 -0
- {smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/valera.py +0 -0
|
@@ -1,239 +1,248 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import logging
|
|
3
|
-
|
|
4
|
-
from smart_bot_factory.router import EventRouter, TelegramRouter
|
|
5
|
-
from smart_bot_factory.message import send_message_by_human, send_message_to_users_by_stage, send_message
|
|
6
|
-
from smart_bot_factory.supabase import SupabaseClient
|
|
7
|
-
from smart_bot_factory.creation import BotBuilder
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
# =============================================================================
|
|
12
|
-
# СОЗДАНИЕ РОУТЕРОВ
|
|
13
|
-
# =============================================================================
|
|
14
|
-
|
|
15
|
-
# Роутер для событий (бизнес-логика)
|
|
16
|
-
event_router = EventRouter("best-valera_events")
|
|
17
|
-
|
|
18
|
-
# Роутер для Telegram (команды и сообщения)
|
|
19
|
-
telegram_router_1 = TelegramRouter("best-valera_telegram")
|
|
20
|
-
telegram_router_2 = TelegramRouter("best-valera_telegram_2")
|
|
21
|
-
|
|
22
|
-
supabase_client = SupabaseClient("best-valera")
|
|
23
|
-
|
|
24
|
-
# =============================================================================
|
|
25
|
-
# ИНИЦИАЛИЗАЦИЯ BOT BUILDER (нужен для декоратора on_start)
|
|
26
|
-
# =============================================================================
|
|
27
|
-
|
|
28
|
-
bot_builder = BotBuilder("best-valera")
|
|
29
|
-
|
|
30
|
-
# =============================================================================
|
|
31
|
-
# TELEGRAM ОБРАБОТЧИКИ (используем прямой aiogram API)
|
|
32
|
-
# =============================================================================
|
|
33
|
-
|
|
34
|
-
from aiogram import F
|
|
35
|
-
from aiogram.filters import Command
|
|
36
|
-
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
|
37
|
-
from aiogram.fsm.context import FSMContext
|
|
38
|
-
|
|
39
|
-
# =============================================================================
|
|
40
|
-
# ОБРАБОТЧИК on_start (вызывается после стандартного /start)
|
|
41
|
-
# =============================================================================
|
|
42
|
-
|
|
43
|
-
@bot_builder.on_start
|
|
44
|
-
async def custom_start_handler(user_id: int, session_id: str, message: Message, state: FSMContext):
|
|
45
|
-
"""
|
|
46
|
-
Вызывается после стандартной логики /start
|
|
47
|
-
Здесь можно отправить дополнительные сообщения, кнопки и т.д.
|
|
48
|
-
"""
|
|
49
|
-
# Пример: отправляем сообщение с кнопками
|
|
50
|
-
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
|
51
|
-
[InlineKeyboardButton(text="📖 Каталог", callback_data="catalog")],
|
|
52
|
-
[InlineKeyboardButton(text="💰 Цены", callback_data="prices")],
|
|
53
|
-
[InlineKeyboardButton(text="📞 Связаться", callback_data="contact")]
|
|
54
|
-
])
|
|
55
|
-
|
|
56
|
-
await message.answer(
|
|
57
|
-
"🎯 Что вас интересует?",
|
|
58
|
-
reply_markup=keyboard
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
# =============================================================================
|
|
62
|
-
# ХУКИ ДЛЯ КАСТОМИЗАЦИИ ОБРАБОТКИ СООБЩЕНИЙ
|
|
63
|
-
# =============================================================================
|
|
64
|
-
|
|
65
|
-
# ХУК 1: Валидация сообщений
|
|
66
|
-
@bot_builder.validate_message
|
|
67
|
-
async def validate_service_names(message, supabase_client):
|
|
68
|
-
"""Проверяем корректность названий услуг"""
|
|
69
|
-
# Пример: блокируем неправильные названия
|
|
70
|
-
incorrect_names = ["массаш", "педекюр", "макияш"]
|
|
71
|
-
|
|
72
|
-
if message.text:
|
|
73
|
-
for incorrect in incorrect_names:
|
|
74
|
-
if incorrect in message.text.lower():
|
|
75
|
-
await message.answer(
|
|
76
|
-
f"❗ Возможно, вы имели в виду другую услугу?\n"
|
|
77
|
-
f"Пожалуйста, уточните название"
|
|
78
|
-
)
|
|
79
|
-
return False # Прерываем обработку AI
|
|
80
|
-
|
|
81
|
-
return True # Продолжаем обработку
|
|
82
|
-
|
|
83
|
-
# ХУК 2: Обогащение промпта
|
|
84
|
-
@bot_builder.enrich_prompt
|
|
85
|
-
async def add_client_info_to_prompt(system_prompt, user_id, session_id, supabase_client):
|
|
86
|
-
"""Добавляем информацию о клиенте в промпт"""
|
|
87
|
-
try:
|
|
88
|
-
session = await supabase_client.get_active_session(user_id)
|
|
89
|
-
|
|
90
|
-
if session and session.get('metadata'):
|
|
91
|
-
phone = session['metadata'].get('phone')
|
|
92
|
-
name = session['metadata'].get('confirmed_name') or session['metadata'].get('telegram_name')
|
|
93
|
-
|
|
94
|
-
if phone:
|
|
95
|
-
client_info = f"\n\nИНФОРМАЦИЯ О КЛИЕНТЕ:\n- Телефон: {phone}"
|
|
96
|
-
if name:
|
|
97
|
-
client_info += f"\n- Имя: {name}"
|
|
98
|
-
client_info += "\n\n⚠️ ВАЖНО: При создании записи используй ЭТОТ телефон и имя!"
|
|
99
|
-
|
|
100
|
-
return system_prompt + client_info
|
|
101
|
-
except Exception as e:
|
|
102
|
-
logger.error(f"Ошибка обогащения промпта: {e}")
|
|
103
|
-
|
|
104
|
-
return system_prompt
|
|
105
|
-
|
|
106
|
-
# ХУК 3: Обогащение контекста (например, данные из внешнего API)
|
|
107
|
-
@bot_builder.enrich_context
|
|
108
|
-
async def add_external_api_data(messages, user_id, session_id):
|
|
109
|
-
"""Добавляем данные из внешних систем"""
|
|
110
|
-
# Пример: можно добавить расписание из YClients, данные из CRM и т.д.
|
|
111
|
-
# messages.append({
|
|
112
|
-
# "role": "system",
|
|
113
|
-
# "content": "Реальное доступное время: ..."
|
|
114
|
-
# })
|
|
115
|
-
return messages
|
|
116
|
-
|
|
117
|
-
# ХУК 4:
|
|
118
|
-
@bot_builder.
|
|
119
|
-
async def
|
|
120
|
-
"""
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
await
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
await
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from smart_bot_factory.router import EventRouter, TelegramRouter
|
|
5
|
+
from smart_bot_factory.message import send_message_by_human, send_message_to_users_by_stage, send_message
|
|
6
|
+
from smart_bot_factory.supabase import SupabaseClient
|
|
7
|
+
from smart_bot_factory.creation import BotBuilder
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
# =============================================================================
|
|
12
|
+
# СОЗДАНИЕ РОУТЕРОВ
|
|
13
|
+
# =============================================================================
|
|
14
|
+
|
|
15
|
+
# Роутер для событий (бизнес-логика)
|
|
16
|
+
event_router = EventRouter("best-valera_events")
|
|
17
|
+
|
|
18
|
+
# Роутер для Telegram (команды и сообщения)
|
|
19
|
+
telegram_router_1 = TelegramRouter("best-valera_telegram")
|
|
20
|
+
telegram_router_2 = TelegramRouter("best-valera_telegram_2")
|
|
21
|
+
|
|
22
|
+
supabase_client = SupabaseClient("best-valera")
|
|
23
|
+
|
|
24
|
+
# =============================================================================
|
|
25
|
+
# ИНИЦИАЛИЗАЦИЯ BOT BUILDER (нужен для декоратора on_start)
|
|
26
|
+
# =============================================================================
|
|
27
|
+
|
|
28
|
+
bot_builder = BotBuilder("best-valera")
|
|
29
|
+
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# TELEGRAM ОБРАБОТЧИКИ (используем прямой aiogram API)
|
|
32
|
+
# =============================================================================
|
|
33
|
+
|
|
34
|
+
from aiogram import F
|
|
35
|
+
from aiogram.filters import Command
|
|
36
|
+
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
|
37
|
+
from aiogram.fsm.context import FSMContext
|
|
38
|
+
|
|
39
|
+
# =============================================================================
|
|
40
|
+
# ОБРАБОТЧИК on_start (вызывается после стандартного /start)
|
|
41
|
+
# =============================================================================
|
|
42
|
+
|
|
43
|
+
@bot_builder.on_start
|
|
44
|
+
async def custom_start_handler(user_id: int, session_id: str, message: Message, state: FSMContext):
|
|
45
|
+
"""
|
|
46
|
+
Вызывается после стандартной логики /start
|
|
47
|
+
Здесь можно отправить дополнительные сообщения, кнопки и т.д.
|
|
48
|
+
"""
|
|
49
|
+
# Пример: отправляем сообщение с кнопками
|
|
50
|
+
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
|
51
|
+
[InlineKeyboardButton(text="📖 Каталог", callback_data="catalog")],
|
|
52
|
+
[InlineKeyboardButton(text="💰 Цены", callback_data="prices")],
|
|
53
|
+
[InlineKeyboardButton(text="📞 Связаться", callback_data="contact")]
|
|
54
|
+
])
|
|
55
|
+
|
|
56
|
+
await message.answer(
|
|
57
|
+
"🎯 Что вас интересует?",
|
|
58
|
+
reply_markup=keyboard
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# =============================================================================
|
|
62
|
+
# ХУКИ ДЛЯ КАСТОМИЗАЦИИ ОБРАБОТКИ СООБЩЕНИЙ
|
|
63
|
+
# =============================================================================
|
|
64
|
+
|
|
65
|
+
# ХУК 1: Валидация сообщений
|
|
66
|
+
@bot_builder.validate_message
|
|
67
|
+
async def validate_service_names(message, supabase_client):
|
|
68
|
+
"""Проверяем корректность названий услуг"""
|
|
69
|
+
# Пример: блокируем неправильные названия
|
|
70
|
+
incorrect_names = ["массаш", "педекюр", "макияш"]
|
|
71
|
+
|
|
72
|
+
if message.text:
|
|
73
|
+
for incorrect in incorrect_names:
|
|
74
|
+
if incorrect in message.text.lower():
|
|
75
|
+
await message.answer(
|
|
76
|
+
f"❗ Возможно, вы имели в виду другую услугу?\n"
|
|
77
|
+
f"Пожалуйста, уточните название"
|
|
78
|
+
)
|
|
79
|
+
return False # Прерываем обработку AI
|
|
80
|
+
|
|
81
|
+
return True # Продолжаем обработку
|
|
82
|
+
|
|
83
|
+
# ХУК 2: Обогащение промпта
|
|
84
|
+
@bot_builder.enrich_prompt
|
|
85
|
+
async def add_client_info_to_prompt(system_prompt, user_id, session_id, supabase_client):
|
|
86
|
+
"""Добавляем информацию о клиенте в промпт"""
|
|
87
|
+
try:
|
|
88
|
+
session = await supabase_client.get_active_session(user_id)
|
|
89
|
+
|
|
90
|
+
if session and session.get('metadata'):
|
|
91
|
+
phone = session['metadata'].get('phone')
|
|
92
|
+
name = session['metadata'].get('confirmed_name') or session['metadata'].get('telegram_name')
|
|
93
|
+
|
|
94
|
+
if phone:
|
|
95
|
+
client_info = f"\n\nИНФОРМАЦИЯ О КЛИЕНТЕ:\n- Телефон: {phone}"
|
|
96
|
+
if name:
|
|
97
|
+
client_info += f"\n- Имя: {name}"
|
|
98
|
+
client_info += "\n\n⚠️ ВАЖНО: При создании записи используй ЭТОТ телефон и имя!"
|
|
99
|
+
|
|
100
|
+
return system_prompt + client_info
|
|
101
|
+
except Exception as e:
|
|
102
|
+
logger.error(f"Ошибка обогащения промпта: {e}")
|
|
103
|
+
|
|
104
|
+
return system_prompt
|
|
105
|
+
|
|
106
|
+
# ХУК 3: Обогащение контекста (например, данные из внешнего API)
|
|
107
|
+
@bot_builder.enrich_context
|
|
108
|
+
async def add_external_api_data(messages, user_id, session_id):
|
|
109
|
+
"""Добавляем данные из внешних систем"""
|
|
110
|
+
# Пример: можно добавить расписание из YClients, данные из CRM и т.д.
|
|
111
|
+
# messages.append({
|
|
112
|
+
# "role": "system",
|
|
113
|
+
# "content": "Реальное доступное время: ..."
|
|
114
|
+
# })
|
|
115
|
+
return messages
|
|
116
|
+
|
|
117
|
+
# ХУК 4: Обработка ответа AI
|
|
118
|
+
@bot_builder.process_response
|
|
119
|
+
async def add_promo_to_price_response(response_text, ai_metadata, user_id):
|
|
120
|
+
"""Добавляем промо-код к ответам о ценах"""
|
|
121
|
+
if "цен" in response_text.lower() or "стоимост" in response_text.lower():
|
|
122
|
+
response_text += "\n\n🎁 Промокод FIRST10 для скидки 10% на первый визит!"
|
|
123
|
+
|
|
124
|
+
return response_text, ai_metadata
|
|
125
|
+
|
|
126
|
+
# ХУК 5: Фильтр отправки
|
|
127
|
+
@bot_builder.filter_send
|
|
128
|
+
async def allow_all_messages(user_id, response_text):
|
|
129
|
+
"""Разрешаем все сообщения (можно добавить блокировку по условию)"""
|
|
130
|
+
# Пример: блокировка во время обработки
|
|
131
|
+
# if is_processing(user_id):
|
|
132
|
+
# return False
|
|
133
|
+
return True
|
|
134
|
+
|
|
135
|
+
@telegram_router_1.router.message(Command("price", "цена"))
|
|
136
|
+
async def handle_price_command(message: Message, state: FSMContext):
|
|
137
|
+
"""Обработчик команды /price"""
|
|
138
|
+
await message.answer(
|
|
139
|
+
"💰 Наши цены:\n\n"
|
|
140
|
+
"📦 Базовый пакет - 1000₽\n"
|
|
141
|
+
"📦 Стандартный - 2000₽\n"
|
|
142
|
+
"📦 Премиум - 5000₽"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
@telegram_router_2.router.message(F.text & (F.text.lower().contains("цена") | F.text.lower().contains("стоимость")))
|
|
146
|
+
async def handle_price_question(message: Message, state: FSMContext):
|
|
147
|
+
"""Обработчик вопросов о цене"""
|
|
148
|
+
await message.answer("💡 Напишите /price чтобы увидеть актуальные цены")
|
|
149
|
+
|
|
150
|
+
# Обработчики callback'ов от кнопок в on_start
|
|
151
|
+
@telegram_router_1.router.callback_query(F.data == "catalog")
|
|
152
|
+
async def handle_catalog(callback: CallbackQuery, state: FSMContext):
|
|
153
|
+
"""Обработка кнопки Каталог"""
|
|
154
|
+
await callback.answer()
|
|
155
|
+
|
|
156
|
+
# Пример: используем send_message с файлами
|
|
157
|
+
await send_message(
|
|
158
|
+
message=callback.message,
|
|
159
|
+
text="📖 Вот наш каталог товаров:\n\n1. Товар 1\n2. Товар 2\n3. Товар 3",
|
|
160
|
+
supabase_client=supabase_client,
|
|
161
|
+
files_list=[], # Можно добавить файлы: ["catalog.pdf"]
|
|
162
|
+
parse_mode="Markdown"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
@telegram_router_1.router.callback_query(F.data == "prices")
|
|
166
|
+
async def handle_prices(callback: CallbackQuery, state: FSMContext):
|
|
167
|
+
"""Обработка кнопки Цены"""
|
|
168
|
+
await callback.answer()
|
|
169
|
+
await callback.message.answer("💰 Наши цены:\n\n📦 Базовый - 1000₽\n📦 Премиум - 5000₽")
|
|
170
|
+
|
|
171
|
+
@telegram_router_1.router.callback_query(F.data == "contact")
|
|
172
|
+
async def handle_contact(callback: CallbackQuery, state: FSMContext):
|
|
173
|
+
"""Обработка кнопки Связаться"""
|
|
174
|
+
await callback.answer()
|
|
175
|
+
await callback.message.answer("📞 Свяжитесь с нами:\n\nТелефон: +7 (999) 123-45-67\nEmail: info@example.com")
|
|
176
|
+
|
|
177
|
+
# =============================================================================
|
|
178
|
+
# ОБРАБОТЧИКИ СОБЫТИЙ (бизнес-логика)
|
|
179
|
+
# =============================================================================
|
|
180
|
+
|
|
181
|
+
@event_router.event_handler("example_event")
|
|
182
|
+
async def handle_example_event(user_id: int, event_data: str):
|
|
183
|
+
"""Пример обработчика события"""
|
|
184
|
+
await send_message_by_human(
|
|
185
|
+
user_id=user_id,
|
|
186
|
+
message_text=f"✅ Событие обработано! Данные: {event_data}"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
"status": "success",
|
|
191
|
+
"message": "Событие обработано"
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
# =============================================================================
|
|
195
|
+
# ВРЕМЕННЫЕ ЗАДАЧИ ДЛЯ ОДНОГО ПОЛЬЗОВАТЕЛЯ
|
|
196
|
+
# =============================================================================
|
|
197
|
+
|
|
198
|
+
@event_router.schedule_task("send_reminder", delay="1h")
|
|
199
|
+
async def send_user_reminder(user_id: int, reminder_text: str):
|
|
200
|
+
"""Отправляет напоминание пользователю"""
|
|
201
|
+
await send_message_by_human(
|
|
202
|
+
user_id=user_id,
|
|
203
|
+
message_text=f"🔔 Напоминание: {reminder_text}"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
"status": "reminder_sent",
|
|
208
|
+
"message": f"Напоминание отправлено пользователю {user_id}"
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
# =============================================================================
|
|
212
|
+
# ГЛОБАЛЬНЫЕ ОБРАБОТЧИКИ (для всех пользователей)
|
|
213
|
+
# =============================================================================
|
|
214
|
+
|
|
215
|
+
@event_router.global_handler("mass_notification", delay="1h", notify=True)
|
|
216
|
+
async def send_global_announcement(announcement_text: str):
|
|
217
|
+
"""Отправляет анонс всем пользователям бота"""
|
|
218
|
+
|
|
219
|
+
await send_message_to_users_by_stage(
|
|
220
|
+
stage="introduction",
|
|
221
|
+
message_text=announcement_text,
|
|
222
|
+
bot_id="best-valera"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
# =============================================================================
|
|
226
|
+
# ОСНОВНАЯ ФУНКЦИЯ
|
|
227
|
+
# =============================================================================
|
|
228
|
+
|
|
229
|
+
async def main():
|
|
230
|
+
"""Основная функция запуска бота"""
|
|
231
|
+
try:
|
|
232
|
+
# bot_builder уже создан выше (для декоратора @bot_builder.on_start)
|
|
233
|
+
|
|
234
|
+
# Регистрируем роутеры ПЕРЕД сборкой (можно по одному или несколько сразу)
|
|
235
|
+
bot_builder.register_routers(event_router) # Роутеры событий
|
|
236
|
+
bot_builder.register_telegram_routers(telegram_router_1, telegram_router_2) # Telegram роутеры
|
|
237
|
+
|
|
238
|
+
await bot_builder.build()
|
|
239
|
+
|
|
240
|
+
# Запускаем бота
|
|
241
|
+
await bot_builder.start()
|
|
242
|
+
|
|
243
|
+
except Exception as e:
|
|
244
|
+
print(f"❌ Ошибка запуска бота: {e}")
|
|
245
|
+
raise
|
|
246
|
+
|
|
247
|
+
if __name__ == "__main__":
|
|
248
|
+
asyncio.run(main())
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/bot_builder.py
RENAMED
|
@@ -52,8 +52,12 @@ class BotBuilder:
|
|
|
52
52
|
self._message_validators: List = [] # Валидация ДО обработки
|
|
53
53
|
self._prompt_enrichers: List = [] # Обогащение системного промпта
|
|
54
54
|
self._context_enrichers: List = [] # Обогащение контекста для AI
|
|
55
|
+
self._response_processors: List = [] # Обработка ответа AI
|
|
55
56
|
self._send_filters: List = [] # Фильтры перед отправкой пользователю
|
|
56
57
|
|
|
58
|
+
# Кастомный PromptLoader
|
|
59
|
+
self._custom_prompt_loader = None
|
|
60
|
+
|
|
57
61
|
# Флаги инициализации
|
|
58
62
|
self._initialized = False
|
|
59
63
|
|
|
@@ -174,10 +178,16 @@ class BotBuilder:
|
|
|
174
178
|
else:
|
|
175
179
|
logger.info(f"✅ Router Manager уже был создан ранее")
|
|
176
180
|
|
|
177
|
-
# Prompt Loader
|
|
178
|
-
self.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
+
# Prompt Loader (используем кастомный если установлен)
|
|
182
|
+
if self._custom_prompt_loader:
|
|
183
|
+
self.prompt_loader = self._custom_prompt_loader
|
|
184
|
+
logger.info(f"✅ Используется кастомный Prompt Loader: {type(self.prompt_loader).__name__}")
|
|
185
|
+
else:
|
|
186
|
+
self.prompt_loader = PromptLoader(
|
|
187
|
+
prompts_dir=self.config.PROMT_FILES_DIR
|
|
188
|
+
)
|
|
189
|
+
logger.info(f"✅ Используется стандартный Prompt Loader")
|
|
190
|
+
|
|
181
191
|
await self.prompt_loader.validate_prompts()
|
|
182
192
|
logger.info(f"✅ Prompt Loader инициализирован")
|
|
183
193
|
|
|
@@ -364,6 +374,34 @@ class BotBuilder:
|
|
|
364
374
|
"""Получает список обработчиков on_start"""
|
|
365
375
|
return self._start_handlers.copy()
|
|
366
376
|
|
|
377
|
+
def set_prompt_loader(self, prompt_loader):
|
|
378
|
+
"""
|
|
379
|
+
Устанавливает кастомный PromptLoader
|
|
380
|
+
|
|
381
|
+
Должен быть вызван ДО build()
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
prompt_loader: Экземпляр PromptLoader или его наследника (например UserPromptLoader)
|
|
385
|
+
|
|
386
|
+
Example:
|
|
387
|
+
from smart_bot_factory.utils import UserPromptLoader
|
|
388
|
+
|
|
389
|
+
# Использовать UserPromptLoader с автопоиском prompts_dir
|
|
390
|
+
custom_loader = UserPromptLoader("my-bot")
|
|
391
|
+
bot_builder.set_prompt_loader(custom_loader)
|
|
392
|
+
|
|
393
|
+
# Или кастомный наследник
|
|
394
|
+
class MyPromptLoader(UserPromptLoader):
|
|
395
|
+
def __init__(self, bot_id):
|
|
396
|
+
super().__init__(bot_id)
|
|
397
|
+
self.extra_file = self.prompts_dir / 'extra.txt'
|
|
398
|
+
|
|
399
|
+
my_loader = MyPromptLoader("my-bot")
|
|
400
|
+
bot_builder.set_prompt_loader(my_loader)
|
|
401
|
+
"""
|
|
402
|
+
self._custom_prompt_loader = prompt_loader
|
|
403
|
+
logger.info(f"✅ Установлен кастомный PromptLoader: {type(prompt_loader).__name__}")
|
|
404
|
+
|
|
367
405
|
# ========== ХУКИ ДЛЯ КАСТОМИЗАЦИИ ОБРАБОТКИ СООБЩЕНИЙ ==========
|
|
368
406
|
|
|
369
407
|
def validate_message(self, handler):
|
|
@@ -437,6 +475,28 @@ class BotBuilder:
|
|
|
437
475
|
logger.info(f"✅ Зарегистрирован обогатитель контекста: {handler.__name__}")
|
|
438
476
|
return handler
|
|
439
477
|
|
|
478
|
+
def process_response(self, handler):
|
|
479
|
+
"""
|
|
480
|
+
Регистрирует обработчик ответа AI (ПОСЛЕ получения ответа)
|
|
481
|
+
|
|
482
|
+
Args:
|
|
483
|
+
handler: async def(response_text: str, ai_metadata: dict, user_id: int) -> tuple[str, dict]
|
|
484
|
+
|
|
485
|
+
Example:
|
|
486
|
+
@bot_builder.process_response
|
|
487
|
+
async def modify_response(response_text, ai_metadata, user_id):
|
|
488
|
+
# Модифицируем ответ
|
|
489
|
+
if "цена" in response_text.lower():
|
|
490
|
+
response_text += "\\n\\n💰 Актуальные цены на сайте"
|
|
491
|
+
return response_text, ai_metadata
|
|
492
|
+
"""
|
|
493
|
+
if not callable(handler):
|
|
494
|
+
raise TypeError(f"Обработчик должен быть callable, получен {type(handler)}")
|
|
495
|
+
|
|
496
|
+
self._response_processors.append(handler)
|
|
497
|
+
logger.info(f"✅ Зарегистрирован обработчик ответа: {handler.__name__}")
|
|
498
|
+
return handler
|
|
499
|
+
|
|
440
500
|
def filter_send(self, handler):
|
|
441
501
|
"""
|
|
442
502
|
Регистрирует фильтр отправки (может блокировать отправку пользователю)
|
|
@@ -466,6 +526,7 @@ class BotBuilder:
|
|
|
466
526
|
'validators': self._message_validators.copy(),
|
|
467
527
|
'prompt_enrichers': self._prompt_enrichers.copy(),
|
|
468
528
|
'context_enrichers': self._context_enrichers.copy(),
|
|
529
|
+
'response_processors': self._response_processors.copy(),
|
|
469
530
|
'send_filters': self._send_filters.copy()
|
|
470
531
|
}
|
|
471
532
|
|
|
@@ -624,6 +624,19 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
|
|
|
624
624
|
|
|
625
625
|
logger.info(f"✅ Финальный текст для отправки: {len(response_text)} символов")
|
|
626
626
|
|
|
627
|
+
# ============ ХУК 4: ОБРАБОТКА ОТВЕТА ============
|
|
628
|
+
response_processors = message_hooks.get('response_processors', [])
|
|
629
|
+
for processor in response_processors:
|
|
630
|
+
try:
|
|
631
|
+
response_text, ai_metadata = await processor(
|
|
632
|
+
response_text,
|
|
633
|
+
ai_metadata,
|
|
634
|
+
message.from_user.id
|
|
635
|
+
)
|
|
636
|
+
logger.info(f"✅ Ответ обработан '{processor.__name__}'")
|
|
637
|
+
except Exception as e:
|
|
638
|
+
logger.error(f"❌ Ошибка в обработчике ответа '{processor.__name__}': {e}")
|
|
639
|
+
|
|
627
640
|
# Обновляем этап сессии и качество лида
|
|
628
641
|
if ai_metadata:
|
|
629
642
|
logger.info("🔍 Анализ метаданных от ИИ:")
|
|
@@ -732,7 +745,7 @@ async def process_user_message(message: Message, state: FSMContext, session_id:
|
|
|
732
745
|
|
|
733
746
|
logger.info(f"📱 Отправляем пользователю: {len(final_response)} символов")
|
|
734
747
|
|
|
735
|
-
# ============ ХУК
|
|
748
|
+
# ============ ХУК 5: ФИЛЬТРЫ ОТПРАВКИ ============
|
|
736
749
|
send_filters = message_hooks.get('send_filters', [])
|
|
737
750
|
for filter_func in send_filters:
|
|
738
751
|
try:
|
|
@@ -32,10 +32,10 @@ class SupabaseClient:
|
|
|
32
32
|
# Автоматически загружаем настройки из .env
|
|
33
33
|
self._load_env_config()
|
|
34
34
|
|
|
35
|
-
# Инициализируем клиент
|
|
36
|
-
self.client
|
|
35
|
+
# Инициализируем клиент СИНХРОННО прямо в __init__
|
|
36
|
+
self.client = create_client(self.url, self.key)
|
|
37
37
|
|
|
38
|
-
logger.info(f"
|
|
38
|
+
logger.info(f"✅ SupabaseClient инициализирован для bot_id: {self.bot_id}")
|
|
39
39
|
|
|
40
40
|
def _load_env_config(self):
|
|
41
41
|
"""Загружает конфигурацию из .env файла"""
|
|
@@ -80,15 +80,6 @@ class SupabaseClient:
|
|
|
80
80
|
logger.error(f" Искали в: {bot_env_path}")
|
|
81
81
|
return None
|
|
82
82
|
|
|
83
|
-
async def initialize(self):
|
|
84
|
-
"""Инициализация клиента Supabase"""
|
|
85
|
-
try:
|
|
86
|
-
self.client = create_client(self.url, self.key)
|
|
87
|
-
logger.info(f"✅ Supabase client инициализирован{f' для bot_id: {self.bot_id}' if self.bot_id else ''}")
|
|
88
|
-
except Exception as e:
|
|
89
|
-
logger.error(f"❌ Ошибка инициализации Supabase client: {e}")
|
|
90
|
-
raise
|
|
91
|
-
|
|
92
83
|
# =============================================================================
|
|
93
84
|
# МЕТОДЫ ДЛЯ РАБОТЫ С ПОЛЬЗОВАТЕЛЯМИ
|
|
94
85
|
# =============================================================================
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UserPromptLoader - упрощенный PromptLoader для пользователей библиотеки
|
|
3
|
+
с автоматическим поиском prompts_dir от корня проекта
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from .prompt_loader import PromptLoader
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class UserPromptLoader(PromptLoader):
|
|
14
|
+
"""
|
|
15
|
+
PromptLoader для пользователей библиотеки с автоматическим поиском prompts_dir
|
|
16
|
+
|
|
17
|
+
Автоматически находит папку prompts для указанного бота от корня проекта
|
|
18
|
+
Наследуется от базового PromptLoader - все методы доступны
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, bot_id: str, prompts_subdir: str = "prompts"):
|
|
22
|
+
"""
|
|
23
|
+
Инициализация загрузчика промптов с автоматическим поиском
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
bot_id: Идентификатор бота
|
|
27
|
+
prompts_subdir: Подпапка с промптами (по умолчанию "prompts")
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
# Автоматически найдет bots/my-bot/prompts
|
|
31
|
+
loader = UserPromptLoader("my-bot")
|
|
32
|
+
|
|
33
|
+
# Или кастомную подпапку
|
|
34
|
+
loader = UserPromptLoader("my-bot", "custom_prompts")
|
|
35
|
+
|
|
36
|
+
# Наследование для кастомизации
|
|
37
|
+
class MyLoader(UserPromptLoader):
|
|
38
|
+
def __init__(self, bot_id):
|
|
39
|
+
super().__init__(bot_id)
|
|
40
|
+
# Добавить свою логику
|
|
41
|
+
self.extra_file = self.prompts_dir / 'extra.txt'
|
|
42
|
+
"""
|
|
43
|
+
from project_root_finder import root
|
|
44
|
+
|
|
45
|
+
# Автоматически определяем путь к промптам
|
|
46
|
+
prompts_dir = root / "bots" / bot_id / prompts_subdir
|
|
47
|
+
|
|
48
|
+
if not prompts_dir.exists():
|
|
49
|
+
logger.warning(f"⚠️ Папка промптов не найдена: {prompts_dir}")
|
|
50
|
+
logger.warning(f" Создайте папку или проверьте bot_id")
|
|
51
|
+
|
|
52
|
+
# Вызываем базовую инициализацию
|
|
53
|
+
super().__init__(str(prompts_dir))
|
|
54
|
+
|
|
55
|
+
logger.info(f"✅ UserPromptLoader создан для bot_id '{bot_id}': {prompts_dir}")
|
|
56
|
+
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Utils модули smart_bot_factory
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from ..integrations.supabase_client import SupabaseClient
|
|
6
|
-
from ..utils.prompt_loader import PromptLoader
|
|
7
|
-
from ..utils.debug_routing import setup_debug_handlers
|
|
8
|
-
|
|
9
|
-
__all__ = ['SupabaseClient', 'PromptLoader', 'setup_debug_handlers']
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/1sales_context.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/2product_info.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/3objection_handling.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/final_instructions.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/help_message.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/prompts/welcome_message.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/tests/quick_scenarios.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/tests/realistic_scenarios.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/best-valera/tests/scenario_examples.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/prompts/3objection_handling.txt
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/prompts/final_instructions.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/tests/realistic_scenarios.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/tests/scenario_examples.yaml
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/bots/valera/welcome_files/welcome_file_msg.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_manager.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/admin_migration.sql
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/admin/timeout_checker.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/analytics/analytics_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/conversation_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/message_sender.py
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/router_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/core/telegram_router.py
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/creation/bot_testing.py
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/integrations/openai_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/table/database_structure.sql
RENAMED
|
File without changes
|
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/utils/debug_routing.py
RENAMED
|
File without changes
|
{smart_bot_factory-0.2.4 → smart_bot_factory-0.2.6}/smart_bot_factory/utils/prompt_loader.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|