claude fixes
This commit is contained in:
parent
3ffc8bdbc2
commit
92900f4806
3 changed files with 124 additions and 15 deletions
58
SETUP.md
Normal file
58
SETUP.md
Normal 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
|
||||||
|
- Создайте новый ключ
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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}")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue