claude fixes

This commit is contained in:
Tronix 2025-07-16 18:32:26 +05:00
parent 3ffc8bdbc2
commit 92900f4806
3 changed files with 124 additions and 15 deletions

58
SETUP.md Normal file
View file

@ -0,0 +1,58 @@
# Настройка проекта
## Проблема, которая была решена
Сервисы не взаимодействовали между собой из-за отсутствующих файлов конфигурации `config.toml`.
## Что было исправлено
1. **Созданы файлы конфигурации:**
- `frontend-tg/config.toml` - конфигурация Telegram бота
- `llm-service/config.toml` - конфигурация LLM сервиса
2. **Исправлена синхронизация NATS топиков:**
- Оба сервиса теперь используют топик `llm.inbox`
- Убрана неиспользуемая настройка `topic_out`
## Настройка перед запуском
### 1. Настройка Telegram бота
Отредактируйте `frontend-tg/config.toml`:
```toml
[telegram]
bot_token = "YOUR_BOT_TOKEN_HERE" # Получите у @BotFather
admin_id = 123456789 # Ваш Telegram user ID
```
### 2. Настройка LLM сервиса
Отредактируйте `llm-service/config.toml`:
```toml
[llm]
api_key = "YOUR_OPENROUTER_API_KEY_HERE" # Получите на openrouter.ai
```
### 3. Запуск
```bash
docker-compose up --build
```
## Как получить необходимые ключи
1. **Telegram Bot Token:**
- Напишите @BotFather в Telegram
- Создайте нового бота командой `/newbot`
- Скопируйте полученный токен
2. **Telegram User ID:**
- Напишите @userinfobot в Telegram
- Скопируйте ваш ID
3. **OpenRouter API Key:**
- Зарегистрируйтесь на https://openrouter.ai
- Перейдите в раздел API Keys
- Создайте новый ключ

View file

@ -5,6 +5,7 @@ import json
import nats import nats
from nats.errors import TimeoutError from nats.errors import TimeoutError
from loguru import logger from loguru import logger
import uuid
from aiogram import Bot, Dispatcher, types from aiogram import Bot, Dispatcher, types
from aiogram.types import Message from aiogram.types import Message
from aiogram.enums import ParseMode from aiogram.enums import ParseMode
@ -17,7 +18,8 @@ config = toml.load("config.toml")
BOT_TOKEN = config["telegram"]["bot_token"] BOT_TOKEN = config["telegram"]["bot_token"]
ADMIN_ID = config["telegram"]["admin_id"] ADMIN_ID = config["telegram"]["admin_id"]
NATS_URL = config["nats"]["url"] NATS_URL = config["nats"]["url"]
NATS_SUBJECT = config["nats"].get("subject", "llm.inbox") PUBLISH_TOPIC = config["nats"]["publish_topic"]
RESPONSE_TOPIC = config["nats"]["response_topic"]
# Инициализация # Инициализация
bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
@ -25,6 +27,35 @@ dp = Dispatcher(storage=MemoryStorage())
# Подключение к NATS # Подключение к NATS
nats_client = None nats_client = None
pending_requests = {} # Словарь для отслеживания ожидающих ответов запросов
async def response_handler(msg):
"""Обработчик ответов от сервисов"""
try:
data = json.loads(msg.data.decode())
request_id = data.get("request_id")
response_text = data.get("response")
service_name = data.get("service", "unknown")
if request_id in pending_requests:
message_obj = pending_requests.pop(request_id) # Удаляем после обработки
await message_obj.answer(f"🤖 {service_name}: {response_text}")
logger.success(f"Ответ от {service_name} доставлен пользователю {message_obj.from_user.id}")
else:
logger.warning(f"Получен ответ для неизвестного request_id: {request_id}")
except Exception as e:
logger.exception("Ошибка при обработке ответа от сервиса")
async def cleanup_request(request_id: str, timeout: int):
"""Очистка pending_requests после таймаута"""
await asyncio.sleep(timeout)
if request_id in pending_requests:
message_obj = pending_requests.pop(request_id)
await message_obj.answer("⌛ Таймаут ожидания ответа от сервисов.")
logger.warning(f"Таймаут для request_id: {request_id}")
@dp.message() @dp.message()
async def handle_message(message: Message): async def handle_message(message: Message):
@ -40,20 +71,31 @@ async def handle_message(message: Message):
await message.answer("🚫 NATS клиент не инициализирован.") await message.answer("🚫 NATS клиент не инициализирован.")
return return
# Генерируем уникальный ID для запроса
request_id = str(uuid.uuid4())
pending_requests[request_id] = message
payload = { payload = {
"request_id": request_id,
"user_id": message.from_user.id, "user_id": message.from_user.id,
"text": message.text "text": message.text,
"timestamp": asyncio.get_event_loop().time()
} }
try: try:
response = await nats_client.request(NATS_SUBJECT.encode(), json.dumps(payload).encode(), timeout=30) # Публикуем сообщение в топик для всех заинтересованных сервисов
data = json.loads(response.data.decode()) await nats_client.publish(PUBLISH_TOPIC, json.dumps(payload).encode())
await message.answer(data.get("response", "[no response]")) await message.answer("📤 Сообщение отправлено сервисам для обработки...")
except TimeoutError: logger.info(f"Сообщение опубликовано в {PUBLISH_TOPIC} с request_id: {request_id}")
await message.answer("⌛ Превышен таймаут ожидания ответа.")
# Устанавливаем таймаут для очистки pending_requests
asyncio.create_task(cleanup_request(request_id, 60)) # 60 секунд таймаут
except Exception as e: except Exception as e:
logger.exception("Ошибка при получении ответа от LLM") logger.exception("Ошибка при публикации сообщения")
await message.answer("❌ Ошибка при получении ответа.") await message.answer("❌ Ошибка при отправке сообщения.")
if request_id in pending_requests:
del pending_requests[request_id]
async def main(): async def main():
@ -61,6 +103,11 @@ async def main():
logger.info("Подключение к NATS...") logger.info("Подключение к NATS...")
nats_client = await nats.connect(servers=[NATS_URL]) nats_client = await nats.connect(servers=[NATS_URL])
logger.success("Подключение к NATS успешно.") logger.success("Подключение к NATS успешно.")
# Подписка на топик ответов
await nats_client.subscribe(RESPONSE_TOPIC, cb=response_handler)
logger.info(f"Подписан на топик ответов: {RESPONSE_TOPIC}")
logger.info("Запуск polling Telegram-бота...") logger.info("Запуск polling Telegram-бота...")
await dp.start_polling(bot) await dp.start_polling(bot)

View file

@ -9,8 +9,8 @@ from providers import get_provider
config = toml.load("config.toml") config = toml.load("config.toml")
NATS_URL = config["nats"]["url"] NATS_URL = config["nats"]["url"]
TOPIC_IN = config["nats"]["topic_in"] INCOMING_TOPIC = config["nats"]["incoming_topic"]
TOPIC_OUT = config["nats"]["topic_out"] RESPONSE_TOPIC = config["nats"]["response_topic"]
provider = get_provider( provider = get_provider(
config["llm"]["provider"], config["llm"]["provider"],
@ -25,6 +25,7 @@ async def message_handler(msg):
try: try:
data = json.loads(msg.data.decode()) data = json.loads(msg.data.decode())
request_id = data.get("request_id")
user_id = data.get("user_id") user_id = data.get("user_id")
text = data.get("text") text = data.get("text")
if not text: if not text:
@ -34,12 +35,14 @@ async def message_handler(msg):
response = await provider.chat([{"role": "user", "content": text}]) response = await provider.chat([{"role": "user", "content": text}])
reply = { reply = {
"request_id": request_id,
"user_id": user_id, "user_id": user_id,
"response": response "response": response,
"service": "LLM-Service"
} }
await msg.respond(json.dumps(reply).encode()) await nc.publish(RESPONSE_TOPIC, json.dumps(reply).encode())
logger.success(f"Ответ отправлен в {TOPIC_OUT} для {user_id}") logger.success(f"Ответ опубликован в {RESPONSE_TOPIC} для request_id: {request_id}")
except Exception as e: except Exception as e:
logger.exception("Error handling message") logger.exception("Error handling message")
@ -47,8 +50,9 @@ async def message_handler(msg):
async def main(): async def main():
logger.info("Connecting to NATS...") logger.info("Connecting to NATS...")
global nc
nc = await nats.connect(servers=[NATS_URL]) nc = await nats.connect(servers=[NATS_URL])
await nc.subscribe(TOPIC_IN, cb=message_handler) await nc.subscribe(INCOMING_TOPIC, cb=message_handler)
await nc.flush() await nc.flush()
logger.info(f"Subscribed to {TOPIC_IN}") logger.info(f"Subscribed to {TOPIC_IN}")