User: оптимзируй код сделай асинхроныке запроч ыи полушче все полнотсью сделай чтоыб бытсрее ра отало import uuid
import time
import logging
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx
import asyncio
import json

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI()

class Message(BaseModel):
    role: str
    content: str

class ChatCompletionRequest(BaseModel):
    model: str
    messages: list[Message]
    max_tokens: int = 16
    temperature: float = 1.0
    top_p: float = 1.0
    n: int = 1
    stream: bool = False
    stop: list = None
    presence_penalty: float = 0.0
    frequency_penalty: float = 0.0
    logit_bias: dict = None

ALLOWED_MODELS = {
    "o1-preview": "https://yuntian-deng-o1.hf.space",
    "o1-mini": "https://yuntian-deng-o1mini.hf.space"
}

COOKIES = {
    "__stripe_mid": "ea43aada-81d9-4008-b199-efe76c14bb3519ac66",
    "__stripe_sid": "1",
    "AMP_569d78c970": "JTdCJTIyZGV2aWNlSWQlMjIlM0ElMjJkYWM1NDM2NS1kNTQ1LTRiMmItYTViZi01MDc2YWQ1NWI5MzklMjIlMkMlMjJ1c2VySWQlMjIlM0ElMjJmMzk4YmFmNS1mNTljLTRiMGMtOTYyNS1mM2ExOGU5NDNhYTclMjIlMkMlMjJzZXNzaW9uSWQlMjIlM0ExNzI5MTA0Nzc1MTk1JTJDJTIyb3B0T3V0JTIyJTNBZmFsc2UlMkMlMjJsYXN0RXZlbnRUaW1lJTIyJTNBMTcyOTEwNDc3NTIwNiUyQyUyMmxhc3RFdmVudElkJTIyJTNBMCU3RA==",
    "AMP_MKTG_569d78c970": "JTdCJTIycmVmZXJyZXIlMjIlM0ElMjJodHRwcyUzQSUyRiUyRnd3dy5nb29nbGUuY29tJTJGJTIyJTJDJTIycmVmZXJyaW5nX2RvbWFpbiUyMiUzQSUyMnd3dy5nb29nbGUuY29tJTIyJTdE",
    "aws-waf-token": "493cff6c-30c3-43ad-8adf-e087238d53be:DQoAjj1fZlYFAAAA:t/stuYnMe87hbVk4xFSuel+1M8VUMHKkduoHnND7MXRnlsIMmr8nCU2cwxmfEmNTB4rBzgUbiDKleYZpPwZovIABIXFItBfSGz05y7VhygB3KU+RORzNlfsUo8fLtvl6AKKSTX2Lwaq4+3kWeWuyaUoAHHi8T/ivaI3RWGelSH9ds6LHSyU4dKCeQsHs4EP61uMrpaqWcn4R6nyqdyHOrXgRJYrd2nltMpeu1q6QINBhWjigvGaXyjwUnLH+W/0iVDWAtQg=",
}

async def ask_question(messages, model):
    logger.info("Starting ask_question with model: %s", model)
    async with httpx.AsyncClient(timeout=99999) as client:
        base_url = ALLOWED_MODELS.get(model)
        if not base_url:
            logger.error("Invalid model: %s", model)
            return "Недопустимая модель."
        logger.info("Selected base_url: %s", base_url)
        
        prompt = "\n".join([f"{msg.role.capitalize()}: {msg.content}" for msg in messages])
        logger.debug("Generated prompt: %s", prompt)
        
        session_hash = str(uuid.uuid4())
        logger.info("Generated session_hash: %s", session_hash)
        
        payload = {
            "fn_index": 5,
            "data": [prompt, 1, 1, 0, [], []],
            "event_data": None,
            "session_hash": session_hash
        }
        logger.debug("Payload for /queue/join: %s", payload)
        
        join_url = f"{base_url}/queue/join?__theme=light"
        logger.info("Sending POST request to %s", join_url)
        try:
            response = await client.post(join_url, json=payload, cookies=COOKIES)
            response.raise_for_status()
            logger.info("Successfully joined the queue.")
        except httpx.HTTPStatusError as e:
            logger.error("HTTP error during /queue/join: %s - %s", e.response.status_code, e.response.text)
            return f"Ошибка при подключении к серверу: {e.response.status_code} - {e.response.text}"
        except Exception as e:
            logger.exception("Unexpected error during /queue/join: %s", str(e))
            return f"Ошибка при подключении к серверу: {str(e)}"
        
        data_url = f"{base_url}/queue/data"
        logger.info("Connecting to SSE at %s", data_url)
        start_time = time.time()
        timeout_seconds = 9999  # Максимальное время ожидания в секундах
        try:
            async with client.stream("GET", data_url, headers={"Accept": "text/event-stream"}, params={"session_hash": session_hash}, cookies=COOKIES) as stream:
                async for line in stream.aiter_lines():
                    current_time = time.time()
                    if current_time - start_time > timeout_seconds:
                        logger.warning("Timeout reached while waiting for response.")
                        return "Превышено время ожидания ответа от сервера."
                    
                    logger.debug("Received line: %s", line)
                    if line.startswith("data: "):
                        data = line[6:]
                        if not data.strip() or data == "[DONE]":
                            logger.debug("Empty or DONE data received, continuing.")
                            continue
                        try:
                            json_data = json.loads(data)
                            msg_type = json_data.get("msg")
                            logger.info("Received msg_type: %s", msg_type)
                            if msg_type == "process_completed":
                                conversation = json_data.get("output", {}).get("data", [])
                                logger.debug("Conversation data: %", conversation)
                                if conversation and isinstance(conversation, list):
                                    for batch in conversation:
                                        if isinstance(batch, list):
                                            for exchange in batch:
                                                if isinstance(exchange, list) and len(exchange) > 1:
                                                    bot_response = exchange[1]
                                                    logger.info("Extracted bot response.")
                                                    return bot_response
                                logger.error("Failed to extract bot response from conversation.")
                                return "Не удалось получить ответ от сервера."
                            elif msg_type in {"process_generating", "estimation", "heartbeat"}:
                                logger.debug("Ignoring msg_type: %s", msg_type)
                                continue
                        except json.JSONDecodeError:
                            logger.error("Failed to decode JSON data: %s", data)
                            continue
        except httpx.HTTPError as e:
            logger.error("HTTP error during SSE stream: %s", str(e))
            return f"Ошибка при получении ответа от сервера: {str(e)}"
        except Exception as e:
            logger.exception("Unexpected error during SSE stream: %s", str(e))
            return f"Ошибка при получении ответа от сервера: {str(e)}"
        
    logger.warning("The process was not completed.")
    return "Процесс не был завершён."

@app.get("/v1/models")
async def get_models():
    logger.info("Received request for /v1/models")
    return {
        "object": "list",
        "data": [
            {"id": "o1-preview", "object": "model"},
            {"id": "o1-mini", "object": "model"}
        ]
    }

@app.post("/v1/chat/completions")
async def chat_completion(request_data: ChatCompletionRequest):
    logger.info("Received POST request to /v1/chat/completions with model: %s", request_data.model)
    if request_data.model not in ALLOWED_MODELS:
        detail = f"Модель '{request_data.model}' не поддерживается. Используйте одну из доступных: {list(ALLOWED_MODELS.keys())}."
        logger.error(detail)
        raise HTTPException(status_code=400, detail=detail)
    logger.debug("Request data: %s", request_data)
    try:
        response_text = await ask_question(request_data.messages, request_data.model)
        logger.info("Generated response: %s", response_text)
    except Exception as e:
        logger.exception("Error during ask_question: %s", str(e))
        raise HTTPException(status_code=500, detail=f"Внутренняя ошибка сервера: {str(e)}")
    return {
        "id": f"chatcmpl-{uuid.uuid4()}",
        "object": "chat.completion",
        "created": int(time.time()),
        "model": request_data.model,
        "choices": [
            {
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": response_text
                },
                "finish_reason": "stop"
            }
        ],
        "usage": {
            "prompt_tokens": 0,
            "completion_tokens": 0,
            "total_tokens": 0
        }
    }

if __name__ == "__main__":
    logger.info("Starting server at http://127.0.0.1:8000")
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
Assistant: Конечно! Я оптимизирую ваш код, сделав его более эффективным и асинхронным. Основные изменения включают:

1. **Переиспользование `httpx.AsyncClient`:** Вместо создания нового клиента для каждого запроса, будем использовать один глобальный клиент, что улучшит производительность за счет повторного использования соединений.
2. **Использование событий `startup` и `shutdown` в FastAPI:** Это позволит корректно инициализировать и закрывать `httpx.AsyncClient`.
3. **Оптимизация обработки SSE (Server-Sent Events):** Улучшим обработку стримов для более быстрого получения ответа.
4. **Удаление избыточных `time` вызовов:** Используем асинхронные подходы для управления временем ожидания.
5. **Улучшение логирования и обработки ошибок:** Сделаем логирование более информативным и корректным.

Вот обновленный код:

```python
import uuid
import asyncio
import logging
from typing import List, Optional, Dict
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx
import json

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI()

# Глобальный клиент HTTPX
client: Optional[httpx.AsyncClient] = None

class Message(BaseModel):
    role: str
    content: str

class ChatCompletionRequest(BaseModel):
    model: str
    messages: List[Message]
    max_tokens: int = 16
    temperature: float = 1.0
    top_p: float = 1.0
    n: int = 1
    stream: bool = False
    stop: Optional[List[str]] = None
    presence_penalty: float = 0.0
    frequency_penalty: float = 0.0
    logit_bias: Optional[Dict[str, float]] = None

ALLOWED_MODELS = {
    "o1-preview": "https://yuntian-deng-o1.hf.space",
    "o1-mini": "https://yuntian-deng-o1mini.hf.space"
}

COOKIES = {
    "__stripe_mid": "ea43aada-81d9-4008-b199-efe76c14bb3519ac66",
    "__stripe_sid": "1",
    "AMP_569d78c970": "JTdCJTIyZGV2aWNlSWQlMjIlM0ElMjJ...",
    "AMP_MKTG_569d78c970": "JTdCJTIycmVmZXJyZXIlMjIlM0ElMjJ...",
    "aws-waf-token": "493cff6c-30c3-43ad-8adf-e087238d53be:DQoAjj1fZlYFAAAA:t/stuYnMe87hbVk4xFSuel..."
}

@app.on_event("startup")
async def startup_event():
    global client
    client = httpx.AsyncClient(timeout=httpx.Timeout(600.0), headers={"Accept": "application/json"})
    logger.info("HTTPX AsyncClient инициализирован.")

@app.on_event("shutdown")
async def shutdown_event():
    global client
    if client:
        await client.aclose()
        logger.info("HTTPX AsyncClient закрыт.")

async def ask_question(messages: List[Message], model: str) -> str:
    logger.info("Начало обработки вопроса с моделью: %s", model)
    
    base_url = ALLOWED_MODELS.get(model)
    if not base_url:
        logger.error("Недопустимая модель: %s", model)
        return "Недопустимая модель."
    logger.info("Используемый URL модели: %s", base_url)
    
    prompt = "\n".join([f"{msg.role.capitalize()}: {msg.content}" for msg in messages])
    logger.debug("Сгенерированный prompt: %s", prompt)
    
    session_hash = str(uuid.uuid4())
    logger.info("Сгенерирован session_hash: %s", session_hash)
    
    payload = {
        "fn_index": 5,
        "data": [prompt, 1, 1, 0, [], []],
        "event_data": None,
        "session_hash": session_hash
    }
    logger.debug("Полезная нагрузка для /queue/join: %s", payload)
    
    join_url = f"{base_url}/queue/join?__theme=light"
    logger.info("Отправка POST запроса на %s", join_url)
    
    try:
        response = await client.post(join_url, json=payload, cookies=COOKIES)
        response.raise_for_status()
        logger.info("Успешно подключено к очереди.")
    except httpx.HTTPStatusError as e:
        logger.error("HTTP ошибка при подключении к /queue/join: %s - %s", e.response.status_code, e.response.text)
        return f"Ошибка при подключении к серверу: {e.response.status_code} - {e.response.text}"
    except Exception as e:
        logger.exception("Неожиданная ошибка при подключении к /queue/join: %s", str(e))
        return f"Ошибка при подключении к серверу: {str(e)}"
    
    data_url = f"{base_url}/queue/data"
    logger.info("Подключение к SSE по URL: %s", data_url)
    
    try:
        async with client.stream("GET", data_url, headers={"Accept": "text/event-stream"}, params={"session_hash": session_hash}, cookies=COOKIES) as stream:
            async for line in stream.aiter_lines():
                if line.startswith("data: "):
                    data = line[6:].strip()
                    if not data or data == "[DONE]":
                        continue
                    try:
                        json_data = json.loads(data)
                        msg_type = json_data.get("msg")
                        logger.info("Получен type сообщения: %s", msg_type)
                        if msg_type == "process_completed":
                            conversation = json_data.get("output", {}).get("data", [])
                            logger.debug("Данные разговора: %s", conversation)
                            if isinstance(conversation, list):
                                for batch in conversation:
                                    if isinstance(batch, list):
                                        for exchange in batch:
                                            if isinstance(exchange, list) and len(exchange) > 1:
                                                bot_response = exchange[1]
                                                logger.info("Извлечен ответ бота.")
                                                return bot_response
                            logger.error("Не удалось извлечь ответ бота из разговора.")
                            return "Не удалось получить ответ от сервера."
                        elif msg_type in {"process_generating", "estimation", "heartbeat"}:
                            logger.debug("Пропуск type сообщения: %s", msg_type)
                            continue
                    except json.JSONDecodeError:
                        logger.error("Ошибка декодирования JSON данных: %s", data)
                        continue
    except httpx.HTTPError as e:
        logger.error("HTTP ошибка при получении SSE стрима: %s", str(e))
        return f"Ошибка при получении ответа от сервера: {str(e)}"
    except Exception as e:
        logger.exception("Неожиданная ошибка при обработке SSE стрима: %s", str(e))
        return f"Ошибка при получении ответа от сервера: {str(e)}"
    
    logger.warning("Процесс не был завершен.")
    return "Процесс не был завершен."

@app.get("/v1/models")
async def get_models():
    logger.info("Получен запрос на /v1/models")
    return {
        "object": "list",
        "data": [
            {"id": "o1-preview", "object": "model"},
            {"id": "o1-mini", "object": "model"}
        ]
    }

@app.post("/v1/chat/completions")
async def chat_completion(request_data: ChatCompletionRequest):
    logger.info("Получен POST запрос на /v1/chat/completions с моделью: %s", request_data.model)
    if request_data.model not in ALLOWED_MODELS:
        detail = f"Модель '{request_data.model}' не поддерживается. Используйте одну из доступных: {list(ALLOWED_MODELS.keys())}."
        logger.error(detail)
        raise HTTPException(status_code=400, detail=detail)
    logger.debug("Данные запроса: %s", request_data)
    try:
        response_text = await ask_question(request_data.messages, request_data.model)
        logger.info("Сгенерированный ответ: %s", response_text)
    except Exception as e:
        logger.exception("Ошибка при выполнении ask_question: %s", str(e))
        raise HTTPException(status_code=500, detail=f"Внутренняя ошибка сервера: {str(e)}")
    return {
        "id": f"chatcmpl-{uuid.uuid4()}",
        "object": "chat.completion",
        "created": int(asyncio.get_event_loop().time()),
        "model": request_data.model,
        "choices": [
            {
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": response_text
                },
                "finish_reason": "stop"
            }
        ],
        "usage": {
            "prompt_tokens": 0,
            "completion_tokens": 0,
            "total_tokens": 0
        }
    }

if __name__ == "__main__":
    logger.info("Запуск сервера на http://127.0.0.1:8000")
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
```

### Подробные изменения и улучшения:

1. **Переиспользование `httpx.AsyncClient`:**
   - **Инициализация клиента:** Добавлены события `startup` и `shutdown` для инициализации и закрытия глобального `httpx.AsyncClient`. Это позволяет переиспользовать соединения и снижает накладные расходы на создание новых клиентов для каждого запроса.
   ```python
   client: Optional[httpx.AsyncClient] = None

   @app.on_event("startup")
   async def startup_event():
       global client
       client = httpx.AsyncClient(timeout=httpx.Timeout(600.0), headers={"Accept": "application/json"})
       logger.info("HTTPX AsyncClient инициализирован.")

   @app.on_event("shutdown")
   async def shutdown_event():
       global client
       if client:
           await client.aclose()
           logger.info("HTTPX AsyncClient закрыт.")
   ```

2. **Оптимизация функции `ask_question`:**
   - **Убран повторяющийся `httpx.AsyncClient`:** Теперь используется глобальный клиент.
   - **Уменьшен `timeout`:** Установлен более разумный таймаут (например, 600 секунд вместо 99999), чтобы предотвратить зависание.
   - **Улучшена обработка SSE:** Упростили логику обработки стрима для быстрого получения ответа.
   - **Исправлены логирующие сообщения:** Исправлены ошибки форматирования и улучшено информирование.
   
3. **Оптимизация модели `ChatCompletionRequest`:**
   - **Использование аннотаций типов:** Добавлены типы для лучшей ясности и проверки.
   ```python
   class ChatCompletionRequest(BaseModel):
       model: str
       messages: List[Message]
       max_tokens: int = 16
       temperature: float = 1.0
       top_p: float = 1.0
       n: int = 1
       stream: bool = False
       stop: Optional[List[str]] = None
       presence_penalty: float = 0.0
       frequency_penalty: float = 0.0
       logit_bias: Optional[Dict[str, float]] = None
   ```

4. **Оптимизация обработчика `/v1/chat/completions`:**
   - **Использование `asyncio.get_event_loop().time()`:** Для получения текущего времени без блокировок.
   - **Улучшено логирование и обработка ошибок.**

5. **Улучшение логирования:**
   - Перевели некоторые сообщения журналирования на русский для единообразия.
   - Убедились, что все сообщения журналирования используют правильный уровень и форматирование.

6. **Улучшение обработки `conversation` данных:**
   - Убедились, что данные разбираются корректно и в случае ошибок возвращается понятное сообщение.
   ```python
   if isinstance(conversation, list):
       for batch in conversation:
           if isinstance(batch, list):
               for exchange in batch:
                   if isinstance(exchange, list) and len(exchange) > 1:
                       bot_response = exchange[1]
                       logger.info("Извлечен ответ бота.")
                       return bot_response
   ```

7. **Использование асинхронных таймингов:** Избегаем использования блокирующих вызовов и используем асинхронные методы для улучшения производительности.

### Дополнительные рекомендации:

- **Мониторинг и балансировка нагрузки:** При увеличении числа пользователей убедитесь, что сервер может выдерживать нагрузку. Рассмотрите использование балансировщиков нагрузки и масштабирование.
- **Кеширование:** Если предполагается повторное использование одних и тех же запросов, можно внедрить механизм кеширования для ускорения ответов.
- **Безопасность:** Убедитесь, что `COOKIES` и другие чувствительные данные хранятся безопасно и не попадают в логи.
- **Тестирование:** Проведите нагрузочное тестирование, чтобы убедиться в стабильности и производительности обновленного кода.

Эти изменения должны значительно повысить производительность и отзывчивость вашего приложения. Если у вас есть дополнительные требования или вопросы, не стесняйтесь обращаться!
User: пому бывает акт тупит INFO:__main__:Начало обработки вопроса с моделью: o1-preview
INFO:__main__:Используемый URL модели: https://yuntian-deng-o1.hf.space
INFO:__main__:Сгенерирован session_hash: bf9a2cfd-a47c-48d1-97a7-67ae3afebda2
INFO:__main__:Отправка POST запроса на https://yuntian-deng-o1.hf.space/queue/join?__theme=light
INFO:httpx:HTTP Request: POST https://yuntian-deng-o1.hf.space/queue/join?__theme=light "HTTP/1.1 200 OK"
INFO:__main__:Успешно подключено к очереди.
INFO:__main__:Подключение к SSE по URL: https://yuntian-deng-o1.hf.space/queue/data
INFO:httpx:HTTP Request: GET https://yuntian-deng-o1.hf.space/queue/data?session_hash=bf9a2cfd-a47c-48d1-97a7-67ae3afebda2 "HTTP/1.1 200 OK"
INFO:__main__:Получен type сообщения: estimation
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: estimation
INFO:__main__:Получен type сообщения: process_starts
Assistant: Здравствуйте!

Похоже, ваш FastAPI-сервис иногда зависает после получения определённых типов сообщений (`estimation`, `heartbeat`, `process_starts`) и не доходит до сообщения `process_completed`. Это приводит к тому, что запросы остаются в ожидании ответа длительное время или вовсе не завершаются. Давайте рассмотрим возможные причины и предложим пути решения этой проблемы.

### Возможные причины зависания

1. **Отсутствие сообщения `process_completed`**: В некоторых случаях внешний сервис может не отправлять это сообщение, что приводит к бесконечному ожиданию.
2. **Длинный или отсутствующий таймаут**: Установленный таймаут в 9999 секунд слишком большой, что позволяет процессу зависнуть на длительное время.
3. **Неправильная обработка сообщений SSE**: Возможно, некоторые типы сообщений не обрабатываются корректно, что мешает завершению процесса.
4. **Проблемы с внешним сервисом**: Внешний сервис, к которому вы подключаетесь, может испытывать проблемы или задержки.

### Предлагаемые решения

1. **Установите разумный таймаут**: Вместо 99999 секунд установите более приемлемый таймаут, например, 60 секунд. Это предотвратит слишком долгое ожидание ответа.
2. **Добавьте обработку дополнительных типов сообщений**: Убедитесь, что все типы сообщений, получаемые от внешнего сервиса, корректно обрабатываются или хотя бы логируются.
3. **Обработайте сообщение `process_starts`**: Добавьте обработку для этого типа сообщений, чтобы понимать, на каком этапе находится процесс.
4. **Используйте `asyncio.wait_for` для управления временем выполнения**: Это позволит более эффективно контролировать время ожидания ответа.
5. **Улучшите логирование**: Добавьте дополнительные точки логирования для лучшего понимания, на каком этапе происходит зависание.

### Обновленный код с применением вышеуказанных рекомендаций

```python
import uuid
import asyncio
import logging
from typing import List, Optional, Dict
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx
import json

# Настройка логирования
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI()

# Глобальный клиент HTTPX
client: Optional[httpx.AsyncClient] = None

class Message(BaseModel):
    role: str
    content: str

class ChatCompletionRequest(BaseModel):
    model: str
    messages: List[Message]
    max_tokens: int = 16
    temperature: float = 1.0
    top_p: float = 1.0
    n: int = 1
    stream: bool = False
    stop: Optional[List[str]] = None
    presence_penalty: float = 0.0
    frequency_penalty: float = 0.0
    logit_bias: Optional[Dict[str, float]] = None

ALLOWED_MODELS = {
    "o1-preview": "https://yuntian-deng-o1.hf.space",
    "o1-mini": "https://yuntian-deng-o1mini.hf.space"
}

COOKIES = {
    "__stripe_mid": "ea43aada-81d9-4008-b199-efe76c14bb3519ac66",
    "__stripe_sid": "1",
    "AMP_569d78c970": "JTdCJTIyZGV2aWNlSWQlMjIlM0ElMjJ...",
    "AMP_MKTG_569d78c970": "JTdCJTIycmVmZXJyZXIlMjIlM0ElMjJ...",
    "aws-waf-token": "493cff6c-30c3-43ad-8adf-e087238d53be:DQoAjj1fZlYFAAAA:t/stuYnMe87hbVk4xFSuel..."
}

@app.on_event("startup")
async def startup_event():
    global client
    client = httpx.AsyncClient(timeout=httpx.Timeout(60.0), headers={"Accept": "application/json"})
    logger.info("HTTPX AsyncClient инициализирован.")

@app.on_event("shutdown")
async def shutdown_event():
    global client
    if client:
        await client.aclose()
        logger.info("HTTPX AsyncClient закрыт.")

async def ask_question(messages: List[Message], model: str) -> str:
    logger.info("Начало обработки вопроса с моделью: %s", model)
    
    base_url = ALLOWED_MODELS.get(model)
    if not base_url:
        logger.error("Недопустимая модель: %s", model)
        return "Недопустимая модель."
    logger.info("Используемый URL модели: %s", base_url)
    
    prompt = "\n".join([f"{msg.role.capitalize()}: {msg.content}" for msg in messages])
    logger.debug("Сгенерированный prompt: %s", prompt)
    
    session_hash = str(uuid.uuid4())
    logger.info("Сгенерирован session_hash: %s", session_hash)
    
    payload = {
        "fn_index": 5,
        "data": [prompt, 1, 1, 0, [], []],
        "event_data": None,
        "session_hash": session_hash
    }
    logger.debug("Полезная нагрузка для /queue/join: %s", payload)
    
    join_url = f"{base_url}/queue/join?__theme=light"
    logger.info("Отправка POST запроса на %s", join_url)
    
    try:
        response = await client.post(join_url, json=payload, cookies=COOKIES)
        response.raise_for_status()
        logger.info("Успешно подключено к очереди.")
    except httpx.HTTPStatusError as e:
        logger.error("HTTP ошибка при подключении к /queue/join: %s - %s", e.response.status_code, e.response.text)
        return f"Ошибка при подключении к серверу: {e.response.status_code} - {e.response.text}"
    except Exception as e:
        logger.exception("Неожиданная ошибка при подключении к /queue/join: %s", str(e))
        return f"Ошибка при подключении к серверу: {str(e)}"
    
    data_url = f"{base_url}/queue/data"
    logger.info("Подключение к SSE по URL: %s", data_url)
    
    async def read_stream():
        try:
            async with client.stream("GET", data_url, headers={"Accept": "text/event-stream"}, params={"session_hash": session_hash}, cookies=COOKIES) as stream:
                async for line in stream.aiter_lines():
                    logger.debug("Получена строка из стрима: %s", line)
                    if line.startswith("data: "):
                        data = line[6:].strip()
                        if not data or data == "[DONE]":
                            continue
                        try:
                            json_data = json.loads(data)
                            msg_type = json_data.get("msg")
                            logger.info("Получен type сообщения: %s", msg_type)
                            if msg_type == "process_completed":
                                conversation = json_data.get("output", {}).get("data", [])
                                logger.debug("Данные разговора: %s", conversation)
                                if isinstance(conversation, list):
                                    for batch in conversation:
                                        if isinstance(batch, list):
                                            for exchange in batch:
                                                if isinstance(exchange, list) and len(exchange) > 1:
                                                    bot_response = exchange[1]
                                                    logger.info("Извлечен ответ бота.")
                                                    return bot_response
                                logger.error("Не удалось извлечь ответ бота из разговора.")
                                return "Не удалось получить ответ от сервера."
                            elif msg_type in {"process_generating", "estimation", "heartbeat", "process_starts"}:
                                logger.debug("Пропуск type сообщения: %s", msg_type)
                                continue
                            else:
                                logger.warning("Неизвестный type сообщения: %s", msg_type)
                        except json.JSONDecodeError:
                            logger.error("Ошибка декодирования JSON данных: %s", data)
                            continue
        except httpx.HTTPError as e:
            logger.error("HTTP ошибка при получении SSE стрима: %s", str(e))
            return f"Ошибка при получении ответа от сервера: {str(e)}"
        except Exception as e:
            logger.exception("Неожиданная ошибка при обработке SSE стрима: %s", str(e))
            return f"Ошибка при получении ответа от сервера: {str(e)}"
    
    try:
        # Установим таймаут на чтение стрима, например, 60 секунд
        response_text = await asyncio.wait_for(read_stream(), timeout=60.0)
        if response_text is None:
            logger.warning("Ответ от сервера не получен в течение 60 секунд.")
            return "Превышено время ожидания ответа от сервера."
        return response_text
    except asyncio.TimeoutError:
        logger.error("Превышено время ожидания ответа от сервера.")
        return "Превышено время ожидания ответа от сервера."
    except Exception as e:
        logger.exception("Ошибка при обработке ответа от сервера: %s", str(e))
        return f"Ошибка при обработке ответа от сервера: {str(e)}"

@app.get("/v1/models")
async def get_models():
    logger.info("Получен запрос на /v1/models")
    return {
        "object": "list",
        "data": [
            {"id": "o1-preview", "object": "model"},
            {"id": "o1-mini", "object": "model"}
        ]
    }

@app.post("/v1/chat/completions")
async def chat_completion(request_data: ChatCompletionRequest):
    logger.info("Получен POST запрос на /v1/chat/completions с моделью: %s", request_data.model)
    if request_data.model not in ALLOWED_MODELS:
        detail = f"Модель '{request_data.model}' не поддерживается. Используйте одну из доступных: {list(ALLOWED_MODELS.keys())}."
        logger.error(detail)
        raise HTTPException(status_code=400, detail=detail)
    logger.debug("Данные запроса: %s", request_data)
    try:
        response_text = await ask_question(request_data.messages, request_data.model)
        if not response_text:
            response_text = "Не удалось получить ответ от сервера."
        logger.info("Сгенерированный ответ: %s", response_text)
    except Exception as e:
        logger.exception("Ошибка при выполнении ask_question: %s", str(e))
        raise HTTPException(status_code=500, detail=f"Внутренняя ошибка сервера: {str(e)}")
    return {
        "id": f"chatcmpl-{uuid.uuid4()}",
        "object": "chat.completion",
        "created": int(asyncio.get_event_loop().time()),
        "model": request_data.model,
        "choices": [
            {
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": response_text
                },
                "finish_reason": "stop"
            }
        ],
        "usage": {
            "prompt_tokens": 0,
            "completion_tokens": 0,
            "total_tokens": 0
        }
    }

if __name__ == "__main__":
    logger.info("Запуск сервера на http://127.0.0.1:8000")
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
```

### Ключевые изменения и улучшения

1. **Управление таймаутом**:
    - **Установлен более разумный таймаут**: Вместо `99999` секунд установлен таймаут `60` секунд с использованием `asyncio.wait_for`. Это предотвращает длительное зависание при отсутствии необходимых сообщений.
    - **Обработка `TimeoutError`**: Если ответ не получен в течение установленного времени, возвращается понятное сообщение об ошибке.

2. **Обработка дополнительных типов сообщений**:
    - **Добавлен `process_starts`**: В условие проверки типов сообщений добавлен `process_starts`, чтобы правильно его обрабатывать (в данном случае пропускать).
    - **Логирование неизвестных типов сообщений**: Добавлено логирование предупреждений для неизвестных типов сообщений, что поможет в будущем при отладке.

3. **Улучшенное логирование**:
    - **Логирование каждой полученной строки из SSE**: Это поможет понять, на каком этапе происходит зависание.
    - **Логирование при извлечении ответа бота**: Позволяет убедиться, что ответ был успешно извлечён.
    - **Логирование ошибок при декодировании JSON**: Помогает выявить проблемы с полученными данными.

4. **Разделение логики чтения стрима**:
    - **Функция `read_stream`**: Вынесена внутренняя логика чтения стрима в отдельную функцию, что делает код более чистым и управляемым.

5. **Проверка на `None` после чтения стрима**:
    - Если функция `read_stream` вернула `None`, это означает, что ответ от сервера не был получен, и в этом случае возвращается соответствующее сообщение об ошибке.

### Дополнительные рекомендации

1. **Проверка поведения внешнего сервиса**:
    - **Свяжитесь с разработчиками**: Убедитесь, что внешний сервис всегда завершает процесс и отправляет сообщение `process_completed`. Если этого не происходит, возможно, это проблема на стороне внешнего сервиса.
    - **Проверьте логи внешнего сервиса**: Возможно, там есть информация о причинах, по которым не отправляется ожидаемое сообщение.

2. **Реализация механизма повторных попыток**:
    - **Повторные запросы**: В случае временных сбоев можно реализовать механизм повторных попыток с экспоненциальной задержкой.
    - **Использование библиотеки `tenacity`**: Эта библиотека позволяет легко реализовать политики повторных попыток.

3. **Мониторинг и алертинг**:
    - **Настройте мониторинг**: Используйте инструменты мониторинга (например, Prometheus, Grafana) для отслеживания состояния вашего приложения.
    - **Настройте алерты**: Уведомляйте себя о резких увеличениях времени ответа или частых ошибках.

4. **Оптимизация запросов и кеширование**:
    - **Кеширование результатов**: Если предполагается, что пользователи будут запрашивать одни и те же данные, рассмотрите возможность кеширования ответов для снижения нагрузки и ускорения ответа.
    - **Оптимизация payload**: Убедитесь, что вы отправляете только необходимые данные, чтобы минимизировать объем передаваемой информации.

5. **Безопасность**:
    - **Хранение конфиденциальных данных**: Убедитесь, что `COOKIES` и другие конфиденциальные данные хранятся безопасно, например, используя переменные окружения или секретные хранилища.
    - **Удаление конфиденциальных данных из логов**: Избегайте логирования чувствительных данных, чтобы предотвратить их утечку.

6. **Тестирование**:
    - **Нагрузочное тестирование**: Проведите нагрузочное тестирование, чтобы понять, как ваше приложение ведет себя при большом количестве запросов.
    - **Тестирование на отказоустойчивость**: Симулируйте сбои во внешнем сервисе, чтобы убедиться, что ваше приложение корректно обрабатывает такие ситуации.

### Заключение

Внедрение этих изменений должно помочь избежать ситуаций, когда ваше приложение зависает в ожидании ответа от внешнего сервиса. Важно тщательно протестировать новое поведение и собрать дополнительную информацию о том, почему внешний сервис не отправляет ожидаемое сообщение `process_completed`, если проблема сохраняется.

Если у вас остались вопросы или потребуются дополнительные уточнения, пожалуйста, дайте знать!
User: а что за особещзняи INFO:__main__:Получен type сообщения: estimation
INFO:__main__:Получен type сообщения: heartbeat
Assistant: Здравствуйте!

Сообщения типа `estimation` и `heartbeat`, которые вы видите в логах, являются частью потока сообщений Server-Sent Events (SSE), получаемых от внешнего сервиса. Давайте разберёмся в их назначении и как с ними работать.

### Что означают `estimation` и `heartbeat`?

1. **`estimation`**:
   - **Назначение**: Это сообщение обычно содержит оценку времени или прогресса обработки вашего запроса на серверной стороне. Например, оно может информировать о том, сколько времени осталось до завершения обработки или насколько далеко продвинулась обработка.
   - **Почему оно важно**: Такие сообщения полезны для информирования клиента о текущем состоянии процесса, особенно если он занимает продолжительное время. Это помогает обеспечить пользователю понимание, что процесс продолжается и не зациклился.

2. **`heartbeat`**:
   - **Назначение**: Это "сердцебиение" или периодические сообщения, отправляемые сервером для поддержания активного соединения и предотвращения разрыва его из-за бездействия.
   - **Почему оно важно**: В некоторых сетевых конфигурациях или промежуточных прокси-серверах соединения, которые остаются без активности определённое время, могут прерываться. Отправка `heartbeat` сообщений помогает избежать таких разрывов, подтверждая, что соединение активно.

### Почему ваш код может "тупеть" после получения этих сообщений?

Исходя из логов, ваш код успешно подключается к очереди и получает несколько сообщений типа `estimation` и `heartbeat`, но затем не получает сообщение `process_completed`, которое сигнализирует о завершении обработки и содержит ответ бота. Это может происходить по нескольким причинам:

1. **Внешний сервис не завершает процесс корректно**:
   - Возможно, внешний сервис сталкивается с ошибкой во время обработки вашего запроса и не отправляет ожидаемое сообщение `process_completed`.
   - Это может быть связано с ограничениями сервиса, такими как длина запроса, формат данных или внутренние ошибки сервера.

2. **Недостаточная обработка типов сообщений в коде**:
   - Ваш текущий код игнорирует сообщения типа `estimation` и `heartbeat`, что обычно корректно. Однако если сервер перестаёт отправлять другие сообщения после этих типов, клиент остаётся в состоянии ожидания.
   
3. **Сетевые проблемы или нестабильное соединение**:
   - Сетевые задержки или нестабильности могут привести к тому, что некоторые сообщения не доходят до вашего клиента.

### Рекомендации по решению проблемы

Чтобы разобраться и устранить причину "зависания" вашего приложения, вы можете предпринять следующие шаги:

1. **Увеличьте детализацию логирования**:
   - Добавьте больше точек логирования для отслеживания всех типов сообщений и стадий обработки.
   - Например, логируйте все сообщения, включая `estimation` и `heartbeat`, чтобы понять, что происходит в каждом шаге.

2. **Убедитесь в корректности запроса**:
   - Проверьте, соответствует ли ваш запрос всем требованиям внешнего сервиса.
   - Убедитесь, что формат сообщений, количество токенов и другие параметры соответствуют ожиданиям сервиса.
   
3. **Проверьте поведение внешнего сервиса**:
   - Попробуйте воспроизвести запрос через инструмент, например, `curl` или Postman, чтобы увидеть, какие сообщения отправляет сервер.
   - Свяжитесь с поддержкой или документацией сервиса, чтобы узнать, каких сообщений ожидать и при каких условиях они отправляются.

4. **Добавьте дополнительные таймауты и обработку ошибок**:
   - Убедитесь, что ваш код корректно обрабатывает случаи, когда сообщение `process_completed` не приходит.
   - Например, можно установить максимальное время ожидания или количество попыток получения ответа.

5. **Обновите логику обработки сообщений**:
   - Возможно, стоит обрабатывать другие типы сообщений, которые также могут сигнализировать о завершении или сбое процесса.
   - Добавьте обработку ошибки, если приходит определённый тип сообщения, указывающий на сбой.

### Пример улучшенного кода с дополнительным логированием и обработкой

Вот пример, как можно улучшить функцию `ask_question`, добавив более подробное логирование и обработку дополнительных сценариев:

```python
import uuid
import asyncio
import logging
from typing import List, Optional, Dict
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx
import json

# Настройка логирования
logging.basicConfig(level=logging.DEBUG)  # Установите уровень DEBUG для подробного логирования
logger = logging.getLogger(__name__)

app = FastAPI()

# Глобальный клиент HTTPX
client: Optional[httpx.AsyncClient] = None

class Message(BaseModel):
    role: str
    content: str

class ChatCompletionRequest(BaseModel):
    model: str
    messages: List[Message]
    max_tokens: int = 16
    temperature: float = 1.0
    top_p: float = 1.0
    n: int = 1
    stream: bool = False
    stop: Optional[List[str]] = None
    presence_penalty: float = 0.0
    frequency_penalty: float = 0.0
    logit_bias: Optional[Dict[str, float]] = None

ALLOWED_MODELS = {
    "o1-preview": "https://yuntian-deng-o1.hf.space",
    "o1-mini": "https://yuntian-deng-o1mini.hf.space"
}

COOKIES = {
    "__stripe_mid": "ea43aada-81d9-4008-b199-efe76c14bb3519ac66",
    "__stripe_sid": "1",
    # Обрезаны для краткости
}

@app.on_event("startup")
async def startup_event():
    global client
    client = httpx.AsyncClient(timeout=httpx.Timeout(60.0), headers={"Accept": "application/json"})
    logger.info("HTTPX AsyncClient инициализирован.")

@app.on_event("shutdown")
async def shutdown_event():
    global client
    if client:
        await client.aclose()
        logger.info("HTTPX AsyncClient закрыт.")

async def ask_question(messages: List[Message], model: str) -> str:
    logger.info("Начало обработки вопроса с моделью: %s", model)
    
    base_url = ALLOWED_MODELS.get(model)
    if not base_url:
        logger.error("Недопустимая модель: %s", model)
        return "Недопустимая модель."
    logger.info("Используемый URL модели: %s", base_url)
    
    prompt = "\n".join([f"{msg.role.capitalize()}: {msg.content}" for msg in messages])
    logger.debug("Сгенерированный prompt: %s", prompt)
    
    session_hash = str(uuid.uuid4())
    logger.info("Сгенерирован session_hash: %s", session_hash)
    
    payload = {
        "fn_index": 5,
        "data": [prompt, 1, 1, 0, [], []],
        "event_data": None,
        "session_hash": session_hash
    }
    logger.debug("Полезная нагрузка для /queue/join: %s", payload)
    
    join_url = f"{base_url}/queue/join?__theme=light"
    logger.info("Отправка POST запроса на %s", join_url)
    
    try:
        response = await client.post(join_url, json=payload, cookies=COOKIES)
        response.raise_for_status()
        logger.info("Успешно подключено к очереди.")
    except httpx.HTTPStatusError as e:
        logger.error("HTTP ошибка при подключении к /queue/join: %s - %s", e.response.status_code, e.response.text)
        return f"Ошибка при подключении к серверу: {e.response.status_code} - {e.response.text}"
    except Exception as e:
        logger.exception("Неожиданная ошибка при подключении к /queue/join: %s", str(e))
        return f"Ошибка при подключении к серверу: {str(e)}"
    
    data_url = f"{base_url}/queue/data"
    logger.info("Подключение к SSE по URL: %s", data_url)
    
    async def read_stream():
        try:
            async with client.stream("GET", data_url, headers={"Accept": "text/event-stream"}, params={"session_hash": session_hash}, cookies=COOKIES) as stream:
                async for line in stream.aiter_lines():
                    logger.debug("Получена строка из стрима: %s", line)
                    if line.startswith("data: "):
                        data = line[6:].strip()
                        if not data or data == "[DONE]":
                            continue
                        try:
                            json_data = json.loads(data)
                            msg_type = json_data.get("msg")
                            logger.info("Получен type сообщения: %s", msg_type)
                            if msg_type == "process_completed":
                                conversation = json_data.get("output", {}).get("data", [])
                                logger.debug("Данные разговора: %s", conversation)
                                if isinstance(conversation, list):
                                    for batch in conversation:
                                        if isinstance(batch, list):
                                            for exchange in batch:
                                                if isinstance(exchange, list) and len(exchange) > 1:
                                                    bot_response = exchange[1]
                                                    logger.info("Извлечен ответ бота.")
                                                    return bot_response
                                logger.error("Не удалось извлечь ответ бота из разговора.")
                                return "Не удалось получить ответ от сервера."
                            elif msg_type in {"process_generating", "estimation", "heartbeat", "process_starts"}:
                                logger.debug("Пропуск type сообщения: %s", msg_type)
                                continue
                            else:
                                logger.warning("Неизвестный type сообщения: %s", msg_type)
                        except json.JSONDecodeError:
                            logger.error("Ошибка декодирования JSON данных: %s", data)
                            continue
        except httpx.HTTPError as e:
            logger.error("HTTP ошибка при получении SSE стрима: %s", str(e))
            return f"Ошибка при получении ответа от сервера: {str(e)}"
        except Exception as e:
            logger.exception("Неожиданная ошибка при обработке SSE стрима: %s", str(e))
            return f"Ошибка при получении ответа от сервера: {str(e)}"
    
    try:
        # Установим таймаут на чтение стрима, например, 60 секунд
        response_text = await asyncio.wait_for(read_stream(), timeout=60.0)
        if response_text is None:
            logger.warning("Ответ от сервера не получен в течение 60 секунд.")
            return "Превышено время ожидания ответа от сервера."
        return response_text
    except asyncio.TimeoutError:
        logger.error("Превышено время ожидания ответа от сервера.")
        return "Превышено время ожидания ответа от сервера."
    except Exception as e:
        logger.exception("Ошибка при обработке ответа от сервера: %s", str(e))
        return f"Ошибка при обработке ответа от сервера: {str(e)}"

@app.get("/v1/models")
async def get_models():
    logger.info("Получен запрос на /v1/models")
    return {
        "object": "list",
        "data": [
            {"id": "o1-preview", "object": "model"},
            {"id": "o1-mini", "object": "model"}
        ]
    }

@app.post("/v1/chat/completions")
async def chat_completion(request_data: ChatCompletionRequest):
    logger.info("Получен POST запрос на /v1/chat/completions с моделью: %s", request_data.model)
    if request_data.model not in ALLOWED_MODELS:
        detail = f"Модель '{request_data.model}' не поддерживается. Используйте одну из доступных: {list(ALLOWED_MODELS.keys())}."
        logger.error(detail)
        raise HTTPException(status_code=400, detail=detail)
    logger.debug("Данные запроса: %s", request_data)
    try:
        response_text = await ask_question(request_data.messages, request_data.model)
        if not response_text:
            response_text = "Не удалось получить ответ от сервера."
        logger.info("Сгенерированный ответ: %s", response_text)
    except Exception as e:
        logger.exception("Ошибка при выполнении ask_question: %s", str(e))
        raise HTTPException(status_code=500, detail=f"Внутренняя ошибка сервера: {str(e)}")
    return {
        "id": f"chatcmpl-{uuid.uuid4()}",
        "object": "chat.completion",
        "created": int(asyncio.get_event_loop().time()),
        "model": request_data.model,
        "choices": [
            {
                "index": 0,
                "message": {
                    "role": "assistant",
                    "content": response_text
                },
                "finish_reason": "stop"
            }
        ],
        "usage": {
            "prompt_tokens": 0,
            "completion_tokens": 0,
            "total_tokens": 0
        }
    }

if __name__ == "__main__":
    logger.info("Запуск сервера на http://127.0.0.1:8000")
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
```

### Что изменилось и как это помогает

1. **Более подробное логирование**:
   - **Уровень `DEBUG`**: Установлен уровень логирования `DEBUG`, чтобы захватывать все внутренние сообщения и поведение приложения.
   - **Логирование всех типов сообщений**: Теперь все получаемые строки из SSE логируются, что поможет понять, какие сообщения приходят и как они обрабатываются.

2. **Обработка таймаута**:
   - **`asyncio.wait_for`**: Установлен таймаут в 60 секунд на ожидание ответа от сервера. Это предотвратит бесконечное ожидание и позволит вернуть ошибку, если сервер не ответит вовремя.

3. **Обработка дополнительных типов сообщений**:
   - **`process_starts`**: Теперь сообщения типа `process_starts` также обрабатываются и пропускаются, предотвращая зацикливание.

4. **Возврат сообщения при отсутствии ответа**:
   - Если ответа от сервера не получено за отведённое время, возвращается сообщение о превышении таймаута.

### Дополнительные рекомендации

1. **Проверьте внешний сервис**:
   - Убедитесь, что внешний сервис (https://yuntian-deng-o1.hf.space) корректно обрабатывает ваши запросы и всегда отправляет сообщение `process_completed` после завершения обработки.
   - Если сервер не отправляет это сообщение, возможно, проблема на стороне сервиса. Свяжитесь с поддержкой или проверьте документацию сервиса.

2. **Тестирование и отладка**:
   - **Используйте инструменты отладки**: Попробуйте воспроизвести запросы с помощью инструментов вроде `curl` или Postman, чтобы увидеть полный поток сообщений.
   - **Локально воспроизведите SSE**: Проверьте, какие сообщения приходят от сервера, и убедитесь, что они соответствуют вашим ожиданиям.

3. **Реализуйте повторные попытки**:
   - При возникновении временных ошибок или таймаутов можно реализовать механизм повторных попыток с экспоненциальной задержкой, чтобы улучшить устойчивость приложения.

4. **Кеширование и оптимизация запросов**:
   - Если ваши запросы часто повторяются, рассмотрите возможность кеширования результатов для снижения нагрузки на внешний сервис и ускорения ответов.

5. **Безопасность**:
   - Убедитесь, что конфиденциальные данные, такие как `COOKIES`, не попадают в публичные логи или репозитории кода.
   - Используйте переменные окружения или секретные хранилища для хранения чувствительных данных.

6. **Мониторинг и алерты**:
   - Настройте мониторинг производительности и состояния вашего приложения. Используйте инструменты вроде Prometheus и Grafana для отслеживания метрик и настройки алертов на сбои или аномалии.

### Заключение

Сообщения типа `estimation` и `heartbeat` являются обычными частями потока SSE, помогающими отслеживать состояние процесса и поддерживать активное соединение. Ваш код правильно игнорирует их, но основная проблема заключается в отсутствии сообщения `process_completed`. Улучшенное логирование и обработка таймаута помогут диагностировать и решить эту проблему. Если внешнему сервису не удаётся завершить процесс корректно, возможно, необходимо обратиться к его разработчикам или документации для получения дополнительной информации.

Если у вас возникнут дополнительные вопросы или потребуется помощь с другими аспектами вашего приложения, не стесняйтесь обращаться!
User: намам ленеькиц хапрос та кдолго овтчеате почеу а кисправить INFO:__main__:Начало обработки вопроса с моделью: o1-preview
INFO:__main__:Используемый URL модели: https://yuntian-deng-o1.hf.space
INFO:__main__:Сгенерирован session_hash: e4f8e353-a2fc-4379-8b20-87dbc411c3db
INFO:__main__:Отправка POST запроса на https://yuntian-deng-o1.hf.space/queue/join?__theme=light
INFO:httpx:HTTP Request: POST https://yuntian-deng-o1.hf.space/queue/join?__theme=light "HTTP/1.1 200 OK"
INFO:__main__:Успешно подключено к очереди.
INFO:__main__:Подключение к SSE по URL: https://yuntian-deng-o1.hf.space/queue/data
INFO:httpx:HTTP Request: GET https://yuntian-deng-o1.hf.space/queue/data?session_hash=e4f8e353-a2fc-4379-8b20-87dbc411c3db "HTTP/1.1 200 OK"
INFO:__main__:Получен type сообщения: estimation
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: estimation
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: estimation
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: estimation
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: heartbeat
INFO:__main__:Получен type сообщения: heartbeat