Обновлены настройки для интеграции с AI-agent сервисом. Изменены переменные окружения в .env, добавлен путь к .env в конфигурации, обновлен GigaChatService для работы через AI-agent. Также исправлены запросы в ScheduleGenerator для корректной загрузки задач. Обновлен docker-compose для подключения к AI-agent сервису.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
GIGACHAT_CLIENT_ID=019966f4-1c5c-7382-9006-b84419fbe5d1
|
||||
GIGACHAT_CLIENT_SECRET=MDE5OTY2ZjQtMWM1Yy03MzgyLTkwMDYtYjg0NDE5ZmJlNWQxOjJjODBmOWE2LWU4YWMtNDE4YS1iOGVkLWE4NTE0YzVkNDAwNw==
|
||||
GIGACHAT_CLIENT_ID=019966f0-5781-76e6-a84f-ec7de158188a
|
||||
GIGACHAT_CLIENT_SECRET=MDE5OTY2ZjAtNTc4MS03NmU2LWE4NGYtZWM3ZGUxNTgxODhhOjI3MDMxZjIxLWY3NWYtNGI4NS05MzM1LTI4ZDYyOWM3MmM0MA==
|
||||
GIGACHAT_AUTH_URL=https://ngw.devices.sberbank.ru:9443/api/v2/oauth
|
||||
GIGACHAT_BASE_URL=https://gigachat.devices.sberbank.ru/api/v1
|
||||
GIGACHAT_MODEL_CHAT=GigaChat-2-Lite
|
||||
@@ -29,3 +29,5 @@ STORAGE_BUCKET=new-planet-images
|
||||
STORAGE_USE_SSL=false
|
||||
STORAGE_REGION=us-east-1
|
||||
|
||||
# Agents
|
||||
AI_AGENT_BASE_URL=http://localhost:8001
|
||||
BIN
new-planet-backend/app/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/__pycache__/config.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/__pycache__/main.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/__pycache__/main.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/api/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/api/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/api/__pycache__/deps.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/api/__pycache__/deps.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/api/v1/__pycache__/ai.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/api/v1/__pycache__/ai.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/api/v1/__pycache__/auth.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/api/v1/__pycache__/auth.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/api/v1/__pycache__/images.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/api/v1/__pycache__/images.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/api/v1/__pycache__/router.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/api/v1/__pycache__/router.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/api/v1/__pycache__/tasks.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/api/v1/__pycache__/tasks.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/core/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/core/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/core/__pycache__/config.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/core/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/core/__pycache__/logging.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/core/__pycache__/logging.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/core/__pycache__/security.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/core/__pycache__/security.cpython-313.pyc
Normal file
Binary file not shown.
@@ -1,5 +1,13 @@
|
||||
from pydantic_settings import BaseSettings
|
||||
from typing import Optional
|
||||
from dotenv import load_dotenv
|
||||
from pathlib import Path
|
||||
|
||||
# Загружаем .env файл перед созданием Settings
|
||||
# Ищем .env в корне проекта (на уровень выше от app/)
|
||||
env_path = Path(__file__).parent.parent.parent / ".env"
|
||||
# override=True гарантирует, что переменные из .env перезапишут существующие
|
||||
load_dotenv(dotenv_path=env_path, override=True)
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
@@ -49,7 +57,14 @@ class Settings(BaseSettings):
|
||||
STORAGE_USE_SSL: bool = False
|
||||
STORAGE_REGION: str = "us-east-1"
|
||||
|
||||
# GigaChat
|
||||
# AI Agent Service (внешний сервис для работы с GigaChat)
|
||||
# URL можно переопределить через переменную окружения AI_AGENT_BASE_URL
|
||||
# Для Docker сети используйте: http://ai-agent:8000 (или имя сервиса из docker-compose)
|
||||
# Для локальной разработки используйте: http://localhost:8000
|
||||
AI_AGENT_BASE_URL: str = "http://ai-agent:8000"
|
||||
AI_AGENT_TIMEOUT: int = 120 # Таймаут в секундах
|
||||
|
||||
# GigaChat (оставлено для обратной совместимости, но используется через AI-agent сервис)
|
||||
GIGACHAT_CLIENT_ID: str = "019966f4-1c5c-7382-9006-b84419fbe5d1"
|
||||
GIGACHAT_CLIENT_SECRET: str = "MDE5OTY2ZjQtMWM1Yy03MzgyLTkwMDYtYjg0NDE5ZmJlNWQxOjJjODBmOWE2LWU4YWMtNDE4YS1iOGVkLWE4NTE0YzVkNDAwNw=="
|
||||
GIGACHAT_AUTH_URL: str = "https://ngw.devices.sberbank.ru:9443/api/v2/oauth"
|
||||
@@ -65,7 +80,9 @@ class Settings(BaseSettings):
|
||||
RATE_LIMIT_PER_MINUTE: int = 60
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
# Путь к .env файлу относительно корня проекта
|
||||
env_file = str(env_path) if env_path.exists() else ".env"
|
||||
env_file_encoding = "utf-8"
|
||||
case_sensitive = True
|
||||
|
||||
|
||||
|
||||
BIN
new-planet-backend/app/crud/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/crud/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/crud/__pycache__/base.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/crud/__pycache__/base.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/crud/__pycache__/schedule.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/crud/__pycache__/schedule.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/crud/__pycache__/task.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/crud/__pycache__/task.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/crud/__pycache__/user.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/crud/__pycache__/user.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/db/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/db/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/db/__pycache__/base.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/db/__pycache__/base.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/db/__pycache__/session.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/db/__pycache__/session.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/models/__pycache__/reward.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/models/__pycache__/reward.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/models/__pycache__/task.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/models/__pycache__/task.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/models/__pycache__/user.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/models/__pycache__/user.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/schemas/__pycache__/ai.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/schemas/__pycache__/ai.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
new-planet-backend/app/schemas/__pycache__/task.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/schemas/__pycache__/task.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/schemas/__pycache__/token.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/schemas/__pycache__/token.cpython-313.pyc
Normal file
Binary file not shown.
BIN
new-planet-backend/app/schemas/__pycache__/user.cpython-313.pyc
Normal file
BIN
new-planet-backend/app/schemas/__pycache__/user.cpython-313.pyc
Normal file
Binary file not shown.
@@ -4,6 +4,7 @@ from app.services.storage_service import storage_service, StorageService
|
||||
from app.services.gigachat_service import gigachat_service, GigaChatService
|
||||
from app.services.chat_service import chat_service, ChatService
|
||||
from app.services.schedule_generator import schedule_generator, ScheduleGenerator
|
||||
from app.services.ai_agent_client import ai_agent_client, AIAgentClient
|
||||
|
||||
__all__ = [
|
||||
"auth_service",
|
||||
@@ -18,5 +19,7 @@ __all__ = [
|
||||
"ChatService",
|
||||
"schedule_generator",
|
||||
"ScheduleGenerator",
|
||||
"ai_agent_client",
|
||||
"AIAgentClient",
|
||||
]
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
117
new-planet-backend/app/services/ai_agent_client.py
Normal file
117
new-planet-backend/app/services/ai_agent_client.py
Normal file
@@ -0,0 +1,117 @@
|
||||
import aiohttp
|
||||
from typing import Optional, List, Dict, Any
|
||||
from app.core.config import settings
|
||||
|
||||
|
||||
class AIAgentClient:
|
||||
"""
|
||||
Клиент для взаимодействия с внешним AI-agent сервисом.
|
||||
|
||||
Сервис должен быть доступен в Docker сети и предоставлять следующие endpoints:
|
||||
- POST /api/v1/chat - для чата с ИИ
|
||||
- POST /api/v1/schedule/generate - для генерации расписаний
|
||||
|
||||
Примечание: Структура API endpoints может отличаться в зависимости от реализации
|
||||
внешнего сервиса. При необходимости измените пути в методах этого класса.
|
||||
"""
|
||||
|
||||
def __init__(self, base_url: Optional[str] = None):
|
||||
self.base_url = base_url or settings.AI_AGENT_BASE_URL
|
||||
if not self.base_url.endswith('/'):
|
||||
self.base_url = self.base_url.rstrip('/')
|
||||
|
||||
async def chat(
|
||||
self,
|
||||
message: str,
|
||||
conversation_id: Optional[str] = None,
|
||||
context: Optional[List[Dict[str, Any]]] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Отправить сообщение в чат через AI-agent сервис.
|
||||
|
||||
Ожидаемый формат ответа от сервиса:
|
||||
{
|
||||
"response": "текст ответа",
|
||||
"conversation_id": "id беседы",
|
||||
"tokens_used": 100,
|
||||
"model": "модель"
|
||||
}
|
||||
или формат GigaChat API (с полем choices).
|
||||
"""
|
||||
url = f"{self.base_url}/api/v1/chat"
|
||||
|
||||
payload = {
|
||||
"message": message,
|
||||
}
|
||||
|
||||
if conversation_id:
|
||||
payload["conversation_id"] = conversation_id
|
||||
|
||||
if context:
|
||||
payload["context"] = context
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(url, json=payload, timeout=aiohttp.ClientTimeout(total=120)) as response:
|
||||
if response.status != 200:
|
||||
error_text = await response.text()
|
||||
raise Exception(
|
||||
f"AI-agent service error: HTTP {response.status} - {error_text}"
|
||||
)
|
||||
|
||||
result = await response.json()
|
||||
return result
|
||||
|
||||
async def generate_schedule(
|
||||
self,
|
||||
child_age: int,
|
||||
preferences: List[str],
|
||||
date: str,
|
||||
description: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Сгенерировать расписание через AI-agent сервис"""
|
||||
url = f"{self.base_url}/api/v1/schedule/generate"
|
||||
|
||||
payload = {
|
||||
"child_age": child_age,
|
||||
"preferences": preferences,
|
||||
"date": date
|
||||
}
|
||||
|
||||
if description:
|
||||
payload["description"] = description
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.post(url, json=payload, timeout=aiohttp.ClientTimeout(total=120)) as response:
|
||||
if response.status != 200:
|
||||
error_text = await response.text()
|
||||
raise Exception(
|
||||
f"AI-agent service error: HTTP {response.status} - {error_text}"
|
||||
)
|
||||
|
||||
result = await response.json()
|
||||
return result
|
||||
|
||||
async def generate_text(
|
||||
self,
|
||||
prompt: str,
|
||||
model: Optional[str] = None
|
||||
) -> str:
|
||||
"""Генерация текста по промпту через AI-agent сервис"""
|
||||
# Для совместимости с текущим интерфейсом используем chat endpoint
|
||||
result = await self.chat(message=prompt)
|
||||
|
||||
# Извлекаем текст ответа
|
||||
# Предполагаем, что ответ имеет структуру ChatResponse
|
||||
response_text = result.get("response", "")
|
||||
if not response_text:
|
||||
# Если структура другая, пытаемся извлечь из choices (как в GigaChat формате)
|
||||
choices = result.get("choices", [])
|
||||
if choices:
|
||||
response_text = choices[0].get("message", {}).get("content", "")
|
||||
|
||||
return response_text
|
||||
|
||||
|
||||
# Создаем экземпляр клиента
|
||||
ai_agent_client = AIAgentClient()
|
||||
|
||||
@@ -7,19 +7,26 @@ import time
|
||||
from urllib.parse import urlencode
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from app.core.config import settings
|
||||
|
||||
load_dotenv()
|
||||
from app.services.ai_agent_client import ai_agent_client
|
||||
|
||||
class GigaChatService:
|
||||
"""
|
||||
Сервис для работы с GigaChat через внешний AI-agent сервис.
|
||||
Все запросы к GigaChat теперь проходят через внешний сервис.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.access_token: Optional[str] = None
|
||||
self.token_expires_at: Optional[float] = None
|
||||
|
||||
async def _get_token(self) -> str:
|
||||
"""Получить OAuth токен"""
|
||||
"""
|
||||
Получить OAuth токен.
|
||||
|
||||
ВНИМАНИЕ: Этот метод больше не используется, так как все запросы
|
||||
к GigaChat теперь проходят через внешний AI-agent сервис.
|
||||
Метод оставлен для возможной обратной совместимости.
|
||||
"""
|
||||
# Проверяем, не истек ли токен (оставляем запас 60 секунд)
|
||||
if self.access_token and self.token_expires_at:
|
||||
if time.time() < (self.token_expires_at - 60):
|
||||
@@ -110,49 +117,59 @@ class GigaChatService:
|
||||
context: Optional[List[Dict[str, Any]]] = None,
|
||||
model: str = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Отправить сообщение в GigaChat"""
|
||||
token = await self._get_token()
|
||||
model = model or settings.GIGACHAT_MODEL_CHAT or "GigaChat"
|
||||
|
||||
messages = context or []
|
||||
messages.append({"role": "user", "content": message})
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": messages,
|
||||
"temperature": 0.7,
|
||||
"max_tokens": 2000
|
||||
}
|
||||
|
||||
# Отключаем проверку SSL (только для разработки!)
|
||||
# Используем ssl=False для полного отключения проверки сертификата
|
||||
connector = aiohttp.TCPConnector(ssl=False)
|
||||
async with aiohttp.ClientSession(connector=connector) as session:
|
||||
async with session.post(
|
||||
f"{settings.GIGACHAT_BASE_URL}/chat/completions",
|
||||
headers=headers,
|
||||
json=payload
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
error_text = await response.text()
|
||||
raise Exception(f"GigaChat API error: {response.status} - {error_text}")
|
||||
|
||||
result = await response.json()
|
||||
"""
|
||||
Отправить сообщение в GigaChat через внешний AI-agent сервис.
|
||||
Сохраняет обратную совместимость с форматом ответа GigaChat API.
|
||||
"""
|
||||
try:
|
||||
# Используем внешний AI-agent сервис
|
||||
result = await ai_agent_client.chat(
|
||||
message=message,
|
||||
conversation_id=None, # Если нужен conversation_id, его нужно передавать отдельно
|
||||
context=context
|
||||
)
|
||||
|
||||
# Преобразуем ответ AI-agent сервиса в формат, совместимый с GigaChat API
|
||||
# Предполагаем, что ai_agent_client возвращает структуру ChatResponse или аналогичную
|
||||
if "response" in result:
|
||||
# Если ответ в формате ChatResponse, преобразуем в формат GigaChat
|
||||
return {
|
||||
"model": result.get("model", model or settings.GIGACHAT_MODEL_CHAT or "GigaChat"),
|
||||
"choices": [{
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": result["response"]
|
||||
},
|
||||
"finish_reason": "stop"
|
||||
}],
|
||||
"usage": {
|
||||
"total_tokens": result.get("tokens_used", 0),
|
||||
"prompt_tokens": 0,
|
||||
"completion_tokens": result.get("tokens_used", 0)
|
||||
}
|
||||
}
|
||||
else:
|
||||
# Если ответ уже в формате GigaChat, возвращаем как есть
|
||||
return result
|
||||
except Exception as e:
|
||||
# Если внешний сервис недоступен, пробрасываем ошибку
|
||||
raise Exception(f"AI-agent service error: {str(e)}")
|
||||
|
||||
async def generate_text(
|
||||
self,
|
||||
prompt: str,
|
||||
model: str = None
|
||||
) -> str:
|
||||
"""Генерация текста по промпту"""
|
||||
result = await self.chat(prompt, model=model)
|
||||
return result.get("choices", [{}])[0].get("message", {}).get("content", "")
|
||||
"""
|
||||
Генерация текста по промпту через внешний AI-agent сервис.
|
||||
"""
|
||||
try:
|
||||
# Используем метод generate_text из ai_agent_client
|
||||
response_text = await ai_agent_client.generate_text(prompt=prompt, model=model)
|
||||
return response_text
|
||||
except Exception as e:
|
||||
# Если произошла ошибка, пробрасываем её
|
||||
raise Exception(f"AI-agent service error: {str(e)}")
|
||||
|
||||
|
||||
gigachat_service = GigaChatService()
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import json
|
||||
from typing import List, Dict, Any, Optional
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import selectinload
|
||||
from app.services.gigachat_service import gigachat_service
|
||||
from app.core.config import settings
|
||||
from app.crud import schedule as crud_schedule, task as crud_task
|
||||
from app.schemas.schedule import ScheduleCreate
|
||||
from app.schemas.task import TaskCreate
|
||||
from app.models.schedule import Schedule
|
||||
from datetime import date
|
||||
|
||||
|
||||
@@ -104,11 +107,17 @@ class ScheduleGenerator:
|
||||
|
||||
await crud_task.create(db, task_create.model_dump())
|
||||
|
||||
await db.refresh(db_schedule)
|
||||
# Загружаем расписание с задачами через selectinload для async корректной работы
|
||||
result = await db.execute(
|
||||
select(Schedule)
|
||||
.where(Schedule.id == db_schedule.id)
|
||||
.options(selectinload(Schedule.tasks))
|
||||
)
|
||||
db_schedule_with_tasks = result.scalar_one()
|
||||
|
||||
return {
|
||||
"schedule_id": db_schedule.id,
|
||||
"title": db_schedule.title,
|
||||
"schedule_id": db_schedule_with_tasks.id,
|
||||
"title": db_schedule_with_tasks.title,
|
||||
"tasks": [
|
||||
{
|
||||
"title": task.title,
|
||||
@@ -117,7 +126,7 @@ class ScheduleGenerator:
|
||||
"category": task.category,
|
||||
"order": task.order
|
||||
}
|
||||
for task in db_schedule.tasks
|
||||
for task in db_schedule_with_tasks.tasks
|
||||
]
|
||||
}
|
||||
except json.JSONDecodeError as e:
|
||||
|
||||
@@ -63,4 +63,8 @@ volumes:
|
||||
networks:
|
||||
new-planet-network:
|
||||
driver: bridge
|
||||
# ВАЖНО: Внешний AI-agent сервис (https://git.bro-js.ru/Glevel/New-planet-ai-agent.git)
|
||||
# должен быть запущен в этой же сети для доступа к GigaChat.
|
||||
# Убедитесь, что сервис ai-agent доступен по имени 'ai-agent' в сети new-planet-network.
|
||||
external: false
|
||||
|
||||
|
||||
@@ -1580,3 +1580,15 @@ redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connec
|
||||
2025-12-18 23:00:15 - root - INFO - Starting up...
|
||||
2025-12-18 23:00:15 - root - INFO - Shutting down...
|
||||
2025-12-18 23:00:15 - root - INFO - Shutting down...
|
||||
2025-12-23 19:00:39 - root - INFO - Starting up...
|
||||
2025-12-23 19:00:39 - root - INFO - Starting up...
|
||||
2025-12-23 19:52:34 - root - INFO - Shutting down...
|
||||
2025-12-23 19:52:34 - root - INFO - Shutting down...
|
||||
2025-12-23 19:52:58 - root - INFO - Starting up...
|
||||
2025-12-23 19:52:58 - root - INFO - Starting up...
|
||||
2025-12-23 19:54:27 - root - INFO - Shutting down...
|
||||
2025-12-23 19:54:27 - root - INFO - Shutting down...
|
||||
2025-12-23 19:54:34 - root - INFO - Starting up...
|
||||
2025-12-23 19:54:34 - root - INFO - Starting up...
|
||||
2025-12-23 20:00:23 - root - INFO - Shutting down...
|
||||
2025-12-23 20:00:23 - root - INFO - Shutting down...
|
||||
|
||||
Reference in New Issue
Block a user