# Создание чат-ассистента с ИИ
Помните, как в «Звездном пути» команда корабля могла просто поговорить с компьютером, задавая сложные вопросы и получая вдумчивые ответы? То, что казалось чистой научной фантастикой в 1960-х, теперь можно создать с помощью веб-технологий, которые вы уже знаете.
В этом уроке мы создадим чат-ассистента с искусственным интеллектом, используя HTML, CSS, JavaScript и немного серверной интеграции. Вы узнаете, как навыки, которые вы уже изучаете, могут быть использованы для подключения к мощным ИИ-сервисам, способным понимать контекст и генерировать осмысленные ответы.
Представьте ИИ как доступ к огромной библиотеке, которая не только находит информацию, но и синтезирует её в связные ответы, адаптированные к вашим конкретным вопросам. Вместо того чтобы искать среди тысяч страниц, вы получаете прямые, контекстуальные ответы.
Интеграция осуществляется через знакомые веб-технологии, работающие вместе. HTML создаёт интерфейс чата, CSS отвечает за визуальный дизайн, JavaScript управляет взаимодействием с пользователем, а серверный API связывает всё это с ИИ-сервисами. Это похоже на то, как разные секции оркестра работают вместе, чтобы создать симфонию.
Мы фактически строим мост между естественным человеческим общением и машинной обработкой. Вы изучите как техническую реализацию интеграции ИИ-сервиса, так и шаблоны дизайна, которые делают взаимодействие интуитивным.
К концу этого урока интеграция ИИ будет казаться не загадочным процессом, а ещё одним API, с которым вы можете работать. Вы поймёте основные принципы, которые лежат в основе приложений, таких как ChatGPT и Claude, используя те же принципы веб-разработки, которые вы уже изучаете.
Вот как будет выглядеть ваш готовый проект:

## Понимание ИИ: от загадки к мастерству
Прежде чем погрузиться в код, давайте разберёмся, с чем мы работаем. Если вы уже использовали API, то знаете базовый принцип: отправить запрос, получить ответ.
API ИИ работают по схожей структуре, но вместо того, чтобы извлекать заранее сохранённые данные из базы данных, они генерируют новые ответы на основе шаблонов, изученных из огромного объёма текста. Это похоже на разницу между системой каталогизации библиотеки и знающим библиотекарем, который может синтезировать информацию из множества источников.
### Что такое «генеративный ИИ» на самом деле?
Вспомните, как Розеттский камень позволил учёным понять египетские иероглифы, находя закономерности между известными и неизвестными языками. Модели ИИ работают аналогично — они находят закономерности в огромных объёмах текста, чтобы понять, как работает язык, а затем используют эти закономерности для генерации подходящих ответов на новые вопросы.
**Давайте разберём это на простом сравнении:**
- **Традиционная база данных**: Как запросить свидетельство о рождении — вы каждый раз получаете один и тот же документ.
- **Поисковая система**: Как попросить библиотекаря найти книги о кошках — он покажет вам, что доступно.
- **Генеративный ИИ**: Как спросить знающего друга о кошках — он расскажет вам интересные вещи своими словами, адаптируясь к вашим запросам.
```mermaid
graph LR
A[Your Question] --> B[AI Model]
B --> C[Pattern Recognition]
C --> D[Content Generation]
D --> E[Contextual Response]
F[Training Data
Books, Articles, Web] --> B
```
### Как обучаются модели ИИ (упрощённая версия)
Модели ИИ обучаются на огромных наборах данных, содержащих текст из книг, статей и разговоров. В процессе они выявляют закономерности в:
- Структуре мыслей в письменной коммуникации
- Словах, которые часто встречаются вместе
- Типичном течении разговоров
- Контекстуальных различиях между формальной и неформальной коммуникацией
**Это похоже на то, как археологи расшифровывают древние языки**: они анализируют тысячи примеров, чтобы понять грамматику, словарный запас и культурный контекст, в конечном итоге становясь способными интерпретировать новые тексты, используя изученные шаблоны.
### Почему GitHub Models?
Мы используем GitHub Models по довольно практичной причине — это даёт нам доступ к корпоративному уровню ИИ без необходимости настраивать собственную инфраструктуру ИИ (а это, поверьте, вы не захотите делать прямо сейчас!). Это похоже на использование API погоды вместо попытки предсказать погоду самостоятельно, устанавливая метеостанции повсюду.
Это, по сути, «ИИ как услуга», и самое лучшее? Начать можно бесплатно, так что вы можете экспериментировать, не беспокоясь о больших расходах.
```mermaid
graph LR
A[Frontend Chat UI] --> B[Your Backend API]
B --> C[GitHub Models API]
C --> D[AI Model Processing]
D --> C
C --> B
B --> A
```
Мы будем использовать GitHub Models для нашей серверной интеграции, которая предоставляет доступ к профессиональным возможностям ИИ через удобный интерфейс для разработчиков. [Песочница GitHub Models](https://github.com/marketplace/models/azure-openai/gpt-4o-mini/playground) служит тестовой средой, где вы можете экспериментировать с различными моделями ИИ и понять их возможности перед внедрением в код.

**Почему песочница так полезна:**
- **Пробуйте** различные модели ИИ, такие как GPT-4o-mini, Claude и другие (всё бесплатно!)
- **Тестируйте** свои идеи и запросы перед написанием кода
- **Получайте** готовые фрагменты кода на вашем любимом языке программирования
- **Настраивайте** параметры, такие как уровень креативности и длина ответа, чтобы увидеть, как они влияют на результат
После того как вы немного поиграете, просто нажмите вкладку «Code» и выберите ваш язык программирования, чтобы получить код для реализации.

## Настройка серверной интеграции на Python
Теперь давайте реализуем интеграцию ИИ с использованием Python. Python отлично подходит для приложений с ИИ благодаря простому синтаксису и мощным библиотекам. Мы начнём с кода из песочницы GitHub Models, а затем переработаем его в многоразовую функцию, готовую к использованию в продакшене.
### Понимание базовой реализации
Когда вы возьмёте код на Python из песочницы, он будет выглядеть примерно так. Не переживайте, если сначала это покажется сложным — давайте разберём его по частям:
```python
"""Run this model in Python
> pip install openai
"""
import os
from openai import OpenAI
# To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
# Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
client = OpenAI(
base_url="https://models.github.ai/inference",
api_key=os.environ["GITHUB_TOKEN"],
)
```python
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "",
},
{
"role": "user",
"content": "What is the capital of France?",
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
print(response.choices[0].message.content)
```
**Что происходит в этом коде:**
- **Мы импортируем** необходимые инструменты: `os` для чтения переменных окружения и `OpenAI` для взаимодействия с ИИ
- **Мы настраиваем** клиент OpenAI, чтобы он подключался к серверам GitHub, а не напрямую к OpenAI
- **Мы аутентифицируемся** с помощью специального токена GitHub (об этом чуть позже!)
- **Мы структурируем** наш разговор с различными «ролями» — это как установка сцены для пьесы
- **Мы отправляем** запрос к ИИ с некоторыми параметрами настройки
- **Мы извлекаем** текст ответа из всех полученных данных
### Понимание ролей сообщений: структура разговора с ИИ
Разговоры с ИИ используют определённую структуру с различными «ролями», которые выполняют разные функции:
```python
messages=[
{
"role": "system",
"content": "You are a helpful assistant who explains things simply."
},
{
"role": "user",
"content": "What is machine learning?"
}
]
```
**Представьте, что вы режиссируете пьесу:**
- **Роль системы**: Как сценические указания для актёра — она говорит ИИ, как себя вести, какой иметь характер и как отвечать
- **Роль пользователя**: Реальный вопрос или сообщение от человека, использующего ваше приложение
- **Роль ассистента**: Ответ ИИ (вы его не отправляете, но он появляется в истории разговора)
**Аналогия из реальной жизни**: Представьте, что вы представляете друга кому-то на вечеринке:
- **Сообщение системы**: «Это моя подруга Сара, она врач, которая отлично объясняет медицинские концепции простыми словами»
- **Сообщение пользователя**: «Можете объяснить, как работают вакцины?»
- **Ответ ассистента**: Сара отвечает как дружелюбный врач, а не как юрист или шеф-повар
### Понимание параметров ИИ: настройка поведения ответов
Числовые параметры в вызовах API ИИ управляют тем, как модель генерирует ответы. Эти настройки позволяют вам адаптировать поведение ИИ для различных случаев использования:
#### Температура (0.0 до 2.0): Регулятор креативности
**Что делает**: Управляет тем, насколько креативными или предсказуемыми будут ответы ИИ.
**Представьте, что это уровень импровизации джазового музыканта:**
- **Температура = 0.1**: Играет одну и ту же мелодию каждый раз (очень предсказуемо)
- **Температура = 0.7**: Добавляет несколько интересных вариаций, оставаясь узнаваемым (сбалансированная креативность)
- **Температура = 1.5**: Полная экспериментальная импровизация с неожиданными поворотами (очень непредсказуемо)
```python
# Very predictable responses (good for factual questions)
response = client.chat.completions.create(
messages=[{"role": "user", "content": "What is 2+2?"}],
temperature=0.1 # Will almost always say "4"
)
# Creative responses (good for brainstorming)
response = client.chat.completions.create(
messages=[{"role": "user", "content": "Write a creative story opening"}],
temperature=1.2 # Will generate unique, unexpected stories
)
```
#### Максимальное количество токенов (1 до 4096+): Контроль длины ответа
**Что делает**: Устанавливает ограничение на длину ответа ИИ.
**Представьте токены как примерно эквивалентные словам** (примерно 1 токен = 0.75 слова на английском):
- **max_tokens=50**: Коротко и ясно (как текстовое сообщение)
- **max_tokens=500**: Пара абзацев
- **max_tokens=2000**: Детальное объяснение с примерами
```python
# Short, concise answers
response = client.chat.completions.create(
messages=[{"role": "user", "content": "Explain JavaScript"}],
max_tokens=100 # Forces a brief explanation
)
# Detailed, comprehensive answers
response = client.chat.completions.create(
messages=[{"role": "user", "content": "Explain JavaScript"}],
max_tokens=1500 # Allows for detailed explanations with examples
)
```
#### Top_p (0.0 до 1.0): Параметр фокусировки
**Что делает**: Управляет тем, насколько ИИ сосредоточен на наиболее вероятных ответах.
**Представьте, что у ИИ огромный словарный запас, ранжированный по вероятности каждого слова:**
- **top_p=0.1**: Учитывает только 10% наиболее вероятных слов (очень сосредоточен)
- **top_p=0.9**: Учитывает 90% возможных слов (более креативно)
- **top_p=1.0**: Учитывает всё (максимальное разнообразие)
**Например**: Если вы спросите «Небо обычно...»
- **Низкий top_p**: Почти наверняка скажет «голубое»
- **Высокий top_p**: Может сказать «голубое», «облачное», «обширное», «меняющееся», «красивое» и т. д.
### Объединяем всё: комбинации параметров для различных случаев использования
```python
# For factual, consistent answers (like a documentation bot)
factual_params = {
"temperature": 0.2,
"max_tokens": 300,
"top_p": 0.3
}
# For creative writing assistance
creative_params = {
"temperature": 1.1,
"max_tokens": 1000,
"top_p": 0.9
}
# For conversational, helpful responses (balanced)
conversational_params = {
"temperature": 0.7,
"max_tokens": 500,
"top_p": 0.8
}
```
**Почему эти параметры важны**: Разные приложения требуют разных типов ответов. Бот службы поддержки должен быть последовательным и фактическим (низкая температура), а помощник для творческого письма — воображаемым и разнообразным (высокая температура). Понимание этих параметров даёт вам контроль над личностью и стилем ответа вашего ИИ.
```
**Here's what's happening in this code:**
- **We import** the tools we need: `os` for reading environment variables and `OpenAI` for talking to the AI
- **We set up** the OpenAI client to point to GitHub's AI servers instead of OpenAI directly
- **We authenticate** using a special GitHub token (more on that in a minute!)
- **We structure** our conversation with different "roles" – think of it like setting the scene for a play
- **We send** our request to the AI with some fine-tuning parameters
- **We extract** the actual response text from all the data that comes back
> 🔐 **Security Note**: Never hardcode API keys in your source code! Always use environment variables to store sensitive credentials like your `GITHUB_TOKEN`.
### Creating a Reusable AI Function
Let's refactor this code into a clean, reusable function that we can easily integrate into our web application:
```python
import asyncio
from openai import AsyncOpenAI
# Use AsyncOpenAI for better performance
client = AsyncOpenAI(
base_url="https://models.github.ai/inference",
api_key=os.environ["GITHUB_TOKEN"],
)
async def call_llm_async(prompt: str, system_message: str = "You are a helpful assistant."):
"""
Sends a prompt to the AI model asynchronously and returns the response.
Args:
prompt: The user's question or message
system_message: Instructions that define the AI's behavior and personality
Returns:
str: The AI's response to the prompt
"""
try:
response = await client.chat.completions.create(
messages=[
{
"role": "system",
"content": system_message,
},
{
"role": "user",
"content": prompt,
}
],
model="openai/gpt-4o-mini",
temperature=1,
max_tokens=4096,
top_p=1
)
return response.choices[0].message.content
except Exception as e:
logger.error(f"AI API error: {str(e)}")
return "I'm sorry, I'm having trouble processing your request right now."
# Backward compatibility function for synchronous calls
def call_llm(prompt: str, system_message: str = "You are a helpful assistant."):
"""Synchronous wrapper for async AI calls."""
return asyncio.run(call_llm_async(prompt, system_message))
```
**Понимание этой улучшенной функции:**
- **Принимает** два параметра: запрос пользователя и необязательное сообщение системы
- **Предоставляет** сообщение системы по умолчанию для общего поведения ассистента
- **Использует** правильные подсказки типов Python для лучшей документации кода
- **Возвращает** только содержимое ответа, что делает его удобным для использования в нашем веб-API
- **Сохраняет** те же параметры модели для последовательного поведения ИИ
### Магия системных подсказок: программирование личности ИИ
Если параметры управляют тем, как ИИ думает, то системные подсказки управляют тем, кем ИИ себя считает. Это, честно говоря, одна из самых крутых частей работы с ИИ — вы фактически задаёте ИИ полную личность, уровень экспертизы и стиль общения.
**Представьте системные подсказки как выбор актёров для разных ролей**: Вместо одного универсального ассистента вы можете создать специализированных экспертов для различных ситуаций. Нужен терпеливый учитель? Творческий партнёр для мозгового штурма? Деловой советник без лишних слов? Просто измените системную подсказку!
#### Почему системные подсказки так мощны
Вот что удивительно: модели ИИ обучены на бесчисленных разговорах, где люди принимают разные роли и уровни экспертизы. Когда вы задаёте ИИ определённую роль, это как включение переключателя, активирующего все эти изученные шаблоны.
**Это как методическая актёрская игра для ИИ**: Скажите актёру «вы мудрый старый профессор» и посмотрите, как он автоматически изменит свою осанку, словарный запас и манеры. ИИ делает что-то удивительно похожее с языковыми шаблонами.
#### Создание эффективных системных подсказок: искусство и наука
**Структура отличной системной подсказки:**
1. **Роль/идентичность**: Кто такой ИИ?
2. **Экспертиза**: Что он знает?
3. **Стиль общения**: Как он говорит?
4. **Конкретные инструкции**: На чём он должен сосредоточиться?
```python
# ❌ Vague system prompt
"You are helpful."
# ✅ Detailed, effective system prompt
"You are Dr. Sarah Chen, a senior software engineer with 15 years of experience at major tech companies. You explain programming concepts using real-world analogies and always provide practical examples. You're patient with beginners and enthusiastic about helping them understand complex topics."
```
#### Примеры системных подсказок с контекстом
Давайте посмотрим, как разные системные подсказки создают совершенно разные личности ИИ:
```python
# Example 1: The Patient Teacher
teacher_prompt = """
You are an experienced programming instructor who has taught thousands of students.
You break down complex concepts into simple steps, use analogies from everyday life,
and always check if the student understands before moving on. You're encouraging
and never make students feel bad for not knowing something.
"""
# Example 2: The Creative Collaborator
creative_prompt = """
You are a creative writing partner who loves brainstorming wild ideas. You're
enthusiastic, imaginative, and always build on the user's ideas rather than
replacing them. You ask thought-provoking questions to spark creativity and
offer unexpected perspectives that make stories more interesting.
"""
# Example 3: The Strategic Business Advisor
business_prompt = """
You are a strategic business consultant with an MBA and 20 years of experience
helping startups scale. You think in frameworks, provide structured advice,
and always consider both short-term tactics and long-term strategy. You ask
probing questions to understand the full business context before giving advice.
"""
```
#### Демонстрация системных подсказок в действии
Давайте протестируем один и тот же вопрос с разными системными подсказками, чтобы увидеть драматические различия:
**Вопрос**: «Как мне организовать аутентификацию пользователей в моём веб-приложении?»
```python
# With teacher prompt:
teacher_response = call_llm(
"How do I handle user authentication in my web app?",
teacher_prompt
)
# Typical response: "Great question! Let's break authentication down into simple steps.
# Think of it like a nightclub bouncer checking IDs..."
# With business prompt:
business_response = call_llm(
"How do I handle user authentication in my web app?",
business_prompt
)
# Typical response: "From a strategic perspective, authentication is crucial for user
# trust and regulatory compliance. Let me outline a framework considering security,
# user experience, and scalability..."
```
#### Расширенные техники системных подсказок
**1. Установка контекста**: Дайте ИИ фоновую информацию
```python
system_prompt = """
You are helping a junior developer who just started their first job at a startup.
They know basic HTML/CSS/JavaScript but are new to backend development and databases.
Be encouraging and explain things step-by-step without being condescending.
"""
```
**2. Форматирование вывода**: Укажите ИИ, как структурировать ответы
```python
system_prompt = """
You are a technical mentor. Always structure your responses as:
1. Quick Answer (1-2 sentences)
2. Detailed Explanation
3. Code Example
4. Common Pitfalls to Avoid
5. Next Steps for Learning
"""
```
**3. Установка ограничений**: Определите, чего ИИ не должен делать
```python
system_prompt = """
You are a coding tutor focused on teaching best practices. Never write complete
solutions for the user - instead, guide them with hints and questions so they
learn by doing. Always explain the 'why' behind coding decisions.
"""
```
#### Почему это важно для вашего чат-ассистента
Понимание системных подсказок даёт вам невероятную возможность создавать специализированных ИИ-ассистентов:
- **Бот службы поддержки**: Помощник, терпеливый, знающий политику
- **Учебный наставник**: Подбадривающий, пошаговый, проверяющий понимание
- **Творческий партнёр**: Воображаемый, развивает идеи, задаёт «а что если?»
- **Технический эксперт**: Точный, детальный, ориентированный на безопасность
**Ключевая идея**: Вы не просто вызываете API ИИ — вы создаёте индивидуальную личность ИИ, которая служит вашему конкретному случаю использования. Именно это делает современные приложения с ИИ персонализированными и полезными.
## Создание веб-API с FastAPI: ваш высокопроизводительный центр связи с ИИ
Теперь давайте создадим серверную часть, которая соединяет ваш фронтенд с ИИ-сервисами. Мы будем использовать FastAPI — современный Python-фреймворк, который отлично подходит для создания API для приложений с ИИ.
FastAPI предлагает несколько преимуществ для такого типа проектов: встроенная поддержка асинхронности для обработки конкурентных запросов, автоматическая генерация документации API и отличная производительность. Ваш сервер FastAPI будет действовать как посредник, который принимает запросы от фронтенда, общается с ИИ-сервисами и возвращает отформатированные ответы.
### Почему FastAPI для приложений с ИИ?
Вы можете задаться вопросом: «Разве я не могу просто вызывать ИИ напрямую из моего фронтенд JavaScript?» или «Почему FastAPI вместо Flask или Django?» Отличные вопросы!
**Вот почему FastAPI идеально подходит для нашего проекта:**
- **Асинхронность по умолчанию**: Может обрабатывать несколько запросов к ИИ одновременно, не зависая
- **Автоматическая документация**: Перейдите на `/docs` и получите красивую, интерактивную страницу документации API бесплатно
- **Встроенная валидация**: Обнаруживает ошибки до того, как они вызовут проблемы
- **Молниеносная скорость**: Один из самых быстрых фреймворков на Python
- **Современный Python**: Использует все последние и лучшие функции Python
**Почему нам вообще нужен бэкенд:**
**Безопасность**: Ваш API-ключ для ИИ — это как пароль. Если вы разместите его в JavaScript на фронтенде, любой, кто увидит исходный код вашего сайта, сможет украсть его и использовать ваши кредиты ИИ. Бэкенд защищает конфиденциальные данные.
**Ограничение запросов и контроль**: Бэкенд позволяет контролировать частоту запросов пользователей, реализовывать аутентификацию и добавлять логирование для отслеживания использования.
**Обработка данных**: Возможно, вы захотите сохранять разговоры, фильтровать неподходящий контент или комбинировать несколько сервисов ИИ. Логика для этого находится в бэкенде.
**Архитектура напоминает модель клиент-сервер:**
- **Фронтенд**: Уровень пользовательского интерфейса для взаимодействия
- **Бэкенд API**: Уровень обработки запросов и маршрутизации
- **Сервис ИИ**: Внешние вычисления и генерация ответов
- **Переменные окружения**: Безопасное хранение конфигурации и учетных данных
### Понимание процесса запроса-ответа
Давайте проследим, что происходит, когда пользователь отправляет сообщение:
```mermaid
sequenceDiagram
participant User as 👤 User
participant Frontend as 🌐 Frontend
participant API as 🔧 FastAPI Server
participant AI as 🤖 AI Service
User->>Frontend: Types "Hello AI!"
Frontend->>API: POST /hello {"message": "Hello AI!"}
Note over API: Validates request
Adds system prompt
API->>AI: Sends formatted request
AI->>API: Returns AI response
Note over API: Processes response
Logs conversation
API->>Frontend: {"response": "Hello! How can I help?"}
Frontend->>User: Displays AI message
```
**Понимание каждого шага:**
1. **Взаимодействие с пользователем**: Пользователь вводит текст в интерфейсе чата
2. **Обработка на фронтенде**: JavaScript захватывает ввод и форматирует его в JSON
3. **Валидация API**: FastAPI автоматически проверяет запрос с помощью моделей Pydantic
4. **Интеграция с ИИ**: Бэкенд добавляет контекст (системный запрос) и вызывает сервис ИИ
5. **Обработка ответа**: API получает ответ от ИИ и может модифицировать его при необходимости
6. **Отображение на фронтенде**: JavaScript показывает ответ в интерфейсе чата
### Понимание архитектуры API
```mermaid
sequenceDiagram
participant Frontend
participant FastAPI
participant AI Function
participant GitHub Models
Frontend->>FastAPI: POST /hello {"message": "Hello AI!"}
FastAPI->>AI Function: call_llm(message, system_prompt)
AI Function->>GitHub Models: API request
GitHub Models->>AI Function: AI response
AI Function->>FastAPI: response text
FastAPI->>Frontend: {"response": "Hello! How can I help?"}
```
### Создание приложения FastAPI
Давайте создадим наш API шаг за шагом. Создайте файл `api.py` с следующим кодом FastAPI:
```python
# api.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from llm import call_llm
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Create FastAPI application
app = FastAPI(
title="AI Chat API",
description="A high-performance API for AI-powered chat applications",
version="1.0.0"
)
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Configure appropriately for production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Pydantic models for request/response validation
class ChatMessage(BaseModel):
message: str
class ChatResponse(BaseModel):
response: str
@app.get("/")
async def root():
"""Root endpoint providing API information."""
return {
"message": "Welcome to the AI Chat API",
"docs": "/docs",
"health": "/health"
}
@app.get("/health")
async def health_check():
"""Health check endpoint."""
return {"status": "healthy", "service": "ai-chat-api"}
@app.post("/hello", response_model=ChatResponse)
async def chat_endpoint(chat_message: ChatMessage):
"""Main chat endpoint that processes messages and returns AI responses."""
try:
# Extract and validate message
message = chat_message.message.strip()
if not message:
raise HTTPException(status_code=400, detail="Message cannot be empty")
logger.info(f"Processing message: {message[:50]}...")
# Call AI service (note: call_llm should be made async for better performance)
ai_response = await call_llm_async(message, "You are a helpful and friendly assistant.")
logger.info("AI response generated successfully")
return ChatResponse(response=ai_response)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error processing chat message: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5000, reload=True)
```
**Понимание реализации FastAPI:**
- **Импортирует** FastAPI для современных функций веб-фреймворка и Pydantic для валидации данных
- **Создает** автоматическую документацию API (доступную по адресу `/docs`, когда сервер запущен)
- **Включает** CORS middleware для разрешения запросов с фронтенда из разных источников
- **Определяет** модели Pydantic для автоматической валидации запросов/ответов и документации
- **Использует** асинхронные конечные точки для повышения производительности при одновременных запросах
- **Реализует** правильные коды статуса HTTP и обработку ошибок с помощью HTTPException
- **Включает** структурированное логирование для мониторинга и отладки
- **Предоставляет** конечную точку проверки состояния для мониторинга работы сервиса
**Ключевые преимущества FastAPI по сравнению с традиционными фреймворками:**
- **Автоматическая валидация**: Модели Pydantic обеспечивают целостность данных до их обработки
- **Интерактивная документация**: Перейдите на `/docs` для автоматически сгенерированной, тестируемой документации API
- **Безопасность типов**: Подсказки типов Python предотвращают ошибки во время выполнения и улучшают качество кода
- **Поддержка асинхронности**: Обработка нескольких запросов к ИИ одновременно без блокировки
- **Производительность**: Значительно более быстрая обработка запросов для приложений в реальном времени
### Понимание CORS: охранник безопасности веба
CORS (Cross-Origin Resource Sharing) — это как охранник в здании, который проверяет, разрешено ли посетителям входить. Давайте разберемся, почему это важно и как это влияет на ваше приложение.
#### Что такое CORS и зачем он нужен?
**Проблема**: Представьте, что любой сайт мог бы отправлять запросы на сайт вашего банка от вашего имени без вашего разрешения. Это был бы кошмар безопасности! Браузеры предотвращают это по умолчанию с помощью "Политики одного источника".
**Политика одного источника**: Браузеры разрешают веб-страницам отправлять запросы только на тот же домен, порт и протокол, с которого они были загружены.
**Аналогия из реальной жизни**: Это как охрана в жилом доме – только жители (один источник) могут получить доступ к зданию по умолчанию. Если вы хотите, чтобы друг (другой источник) посетил вас, нужно явно сообщить охране, что это разрешено.
#### CORS в вашей среде разработки
Во время разработки ваш фронтенд и бэкенд работают на разных портах:
- Фронтенд: `http://localhost:3000` (или file://, если открываете HTML напрямую)
- Бэкенд: `http://localhost:5000`
Они считаются "разными источниками", даже если находятся на одном компьютере!
```python
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(__name__)
CORS(app) # This tells browsers: "It's okay for other origins to make requests to this API"
```
**Что делает конфигурация CORS на практике:**
- **Добавляет** специальные HTTP-заголовки к ответам API, которые говорят браузерам: "этот запрос с другого источника разрешен"
- **Обрабатывает** "предварительные" запросы (браузеры иногда проверяют разрешения перед отправкой фактического запроса)
- **Предотвращает** ошибку "запрос заблокирован политикой CORS" в консоли вашего браузера
#### Безопасность CORS: разработка vs производство
```python
# 🚨 Development: Allows ALL origins (convenient but insecure)
CORS(app)
# ✅ Production: Only allow your specific frontend domain
CORS(app, origins=["https://yourdomain.com", "https://www.yourdomain.com"])
# 🔒 Advanced: Different origins for different environments
if app.debug: # Development mode
CORS(app, origins=["http://localhost:3000", "http://127.0.0.1:3000"])
else: # Production mode
CORS(app, origins=["https://yourdomain.com"])
```
**Почему это важно**: В разработке `CORS(app)` — это как оставить дверь открытой — удобно, но небезопасно. В производстве вы хотите точно указать, какие сайты могут взаимодействовать с вашим API.
#### Общие сценарии CORS и решения
| Сценарий | Проблема | Решение |
|----------|---------|----------|
| **Локальная разработка** | Фронтенд не может достичь бэкенда | Добавьте CORSMiddleware в FastAPI |
| **GitHub Pages + Heroku** | Развернутый фронтенд не может достичь API | Добавьте URL GitHub Pages в источники CORS |
| **Собственный домен** | Ошибки CORS в производстве | Обновите источники CORS, чтобы соответствовать вашему домену |
| **Мобильное приложение** | Приложение не может достичь веб-API | Добавьте домен вашего приложения или используйте `*` осторожно |
**Совет**: Вы можете проверить заголовки CORS в инструментах разработчика вашего браузера на вкладке "Сеть". Ищите заголовки, такие как `Access-Control-Allow-Origin` в ответе.
### Обработка ошибок и валидация
Обратите внимание, как наш API включает правильную обработку ошибок:
```python
# Validate that we received a message
if not message:
return jsonify({"error": "Message field is required"}), 400
```
**Основные принципы валидации:**
- **Проверяет** обязательные поля перед обработкой запросов
- **Возвращает** понятные сообщения об ошибках в формате JSON
- **Использует** соответствующие коды статуса HTTP (400 для неверных запросов)
- **Предоставляет** четкую обратную связь, чтобы помочь разработчикам фронтенда устранять проблемы
## Настройка и запуск вашего бэкенда
Теперь, когда у нас есть интеграция с ИИ и сервер FastAPI, давайте запустим все. Процесс настройки включает установку зависимостей Python, конфигурацию переменных окружения и запуск сервера разработки.
### Настройка среды Python
Давайте настроим вашу среду разработки Python. Виртуальные среды похожи на подход к проекту Манхэттен — каждый проект получает свое собственное изолированное пространство с определенными инструментами и зависимостями, предотвращая конфликты между проектами.
```bash
# Navigate to your backend directory
cd backend
# Create a virtual environment (like creating a clean room for your project)
python -m venv venv
# Activate it (Linux/Mac)
source ./venv/bin/activate
# On Windows, use:
# venv\Scripts\activate
# Install the good stuff
pip install openai fastapi uvicorn python-dotenv
```
**Что мы только что сделали:**
- **Создали** собственное пространство Python, где можно устанавливать пакеты, не влияя на другие проекты
- **Активировали** его, чтобы терминал знал, что использовать именно эту среду
- **Установили** необходимые компоненты: OpenAI для магии ИИ, FastAPI для нашего веб-API, Uvicorn для его запуска и python-dotenv для безопасного управления секретами
**Объяснение ключевых зависимостей:**
- **FastAPI**: Современный, быстрый веб-фреймворк с автоматической документацией API
- **Uvicorn**: Молниеносный сервер ASGI, который запускает приложения FastAPI
- **OpenAI**: Официальная библиотека для моделей GitHub и интеграции с API OpenAI
- **python-dotenv**: Безопасная загрузка переменных окружения из файлов .env
### Конфигурация окружения: защита секретов
Прежде чем запустить наш API, нужно поговорить об одном из самых важных уроков веб-разработки: как действительно защитить свои секреты. Переменные окружения — это как защищенный сейф, к которому может получить доступ только ваше приложение.
#### Что такое переменные окружения?
**Представьте переменные окружения как сейф для хранения ценных вещей** — вы кладете туда важные данные, и только вы (и ваше приложение) имеете ключ для их извлечения. Вместо того чтобы записывать конфиденциальную информацию прямо в код (где ее может увидеть кто угодно), вы храните ее безопасно в окружении.
**Вот разница:**
- **Неправильный способ**: Записать пароль на стикере и приклеить его к монитору
- **Правильный способ**: Хранить пароль в защищенном менеджере паролей, к которому имеете доступ только вы
#### Почему переменные окружения важны
```python
# 🚨 NEVER DO THIS - API key visible to everyone
client = OpenAI(
api_key="ghp_1234567890abcdef...", # Anyone can steal this!
base_url="https://models.github.ai/inference"
)
# ✅ DO THIS - API key stored securely
client = OpenAI(
api_key=os.environ["GITHUB_TOKEN"], # Only your app can access this
base_url="https://models.github.ai/inference"
)
```
**Что происходит, если вы жестко прописываете секреты:**
1. **Доступ через систему контроля версий**: Любой, у кого есть доступ к вашему репозиторию, видит ваш API-ключ
2. **Публичные репозитории**: Если вы загружаете код на GitHub, ваш ключ становится видимым для всего интернета
3. **Совместная работа в команде**: Другие разработчики, работающие над вашим проектом, получают доступ к вашему личному API-ключу
4. **Угрозы безопасности**: Если кто-то украдет ваш API-ключ, он сможет использовать ваши кредиты ИИ
#### Настройка файла окружения
Создайте файл `.env` в каталоге вашего бэкенда. Этот файл локально хранит ваши секреты:
```bash
# .env file - This should NEVER be committed to Git
GITHUB_TOKEN=your_github_personal_access_token_here
FASTAPI_DEBUG=True
ENVIRONMENT=development
```
**Понимание файла .env:**
- **Один секрет на строку** в формате `KEY=value`
- **Без пробелов** вокруг знака равенства
- **Без кавычек** вокруг значений (обычно)
- **Комментарии** начинаются с `#`
#### Создание личного токена доступа GitHub
Ваш токен GitHub — это как специальный пароль, который дает вашему приложению разрешение использовать сервисы ИИ GitHub:
**Пошаговое создание токена:**
1. **Перейдите в настройки GitHub** → Настройки разработчика → Личные токены доступа → Токены (классические)
2. **Нажмите "Создать новый токен (классический)"**
3. **Установите срок действия** (30 дней для тестирования, дольше для производства)
4. **Выберите области**: Отметьте "repo" и любые другие необходимые разрешения
5. **Создайте токен** и сразу скопируйте его (вы не сможете увидеть его снова!)
6. **Вставьте в ваш файл .env**
```bash
# Example of what your token looks like (this is fake!)
GITHUB_TOKEN=ghp_1A2B3C4D5E6F7G8H9I0J1K2L3M4N5O6P7Q8R
```
#### Загрузка переменных окружения в Python
```python
import os
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Now you can access them securely
api_key = os.environ.get("GITHUB_TOKEN")
if not api_key:
raise ValueError("GITHUB_TOKEN not found in environment variables!")
client = OpenAI(
api_key=api_key,
base_url="https://models.github.ai/inference"
)
```
**Что делает этот код:**
- **Загружает** ваш файл .env и делает переменные доступными для Python
- **Проверяет**, существует ли необходимый токен (хорошая обработка ошибок!)
- **Вызывает** четкую ошибку, если токен отсутствует
- **Использует** токен безопасно, не раскрывая его в коде
#### Безопасность Git: файл .gitignore
Ваш файл `.gitignore` говорит Git, какие файлы никогда не отслеживать или загружать:
```bash
# .gitignore - Add these lines
.env
*.env
.env.local
.env.production
__pycache__/
venv/
.vscode/
```
**Почему это важно**: Как только вы добавите `.env` в `.gitignore`, Git будет игнорировать ваш файл окружения, предотвращая случайную загрузку ваших секретов на GitHub.
#### Разные окружения, разные секреты
Профессиональные приложения используют разные API-ключи для разных окружений:
```bash
# .env.development
GITHUB_TOKEN=your_development_token
DEBUG=True
# .env.production
GITHUB_TOKEN=your_production_token
DEBUG=False
```
**Почему это важно**: Вы не хотите, чтобы ваши эксперименты в разработке влияли на ваш производственный лимит использования ИИ, и хотите разные уровни безопасности для разных окружений.
### Запуск сервера разработки: оживляем ваш FastAPI
Теперь наступает захватывающий момент — запуск сервера разработки FastAPI и наблюдение за интеграцией ИИ! FastAPI использует Uvicorn, молниеносный сервер ASGI, специально разработанный для асинхронных приложений на Python.
#### Понимание процесса запуска сервера FastAPI
```bash
# Method 1: Direct Python execution (includes auto-reload)
python api.py
# Method 2: Using Uvicorn directly (more control)
uvicorn api:app --host 0.0.0.0 --port 5000 --reload
```
Когда вы выполняете эту команду, вот что происходит за кулисами:
**1. Python загружает ваше приложение FastAPI**:
- Импортирует все необходимые библиотеки (FastAPI, Pydantic, OpenAI и т.д.)
- Загружает переменные окружения из вашего файла `.env`
- Создает экземпляр приложения FastAPI с автоматической документацией
**2. Uvicorn настраивает сервер ASGI**:
- Привязывается к порту 5000 с возможностями асинхронной обработки запросов
- Настраивает маршрутизацию запросов с автоматической валидацией
- Включает горячую перезагрузку для разработки (перезапускается при изменении файлов)
- Генерирует интерактивную документацию API
**3. Сервер начинает слушать**:
- Ваш терминал показывает: `INFO: Uvicorn running on http://0.0.0.0:5000`
- Сервер может обрабатывать несколько одновременных запросов к ИИ
- Ваш API готов с автоматической документацией по адресу `http://localhost:5000/docs`
#### Что вы должны увидеть, когда все работает
```bash
$ python api.py
INFO: Will watch for changes in these directories: ['/your/project/path']
INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
INFO: Started reloader process [12345] using WatchFiles
INFO: Started server process [12346]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
**Понимание вывода FastAPI:**
- **Будет следить за изменениями**: Авто-перезагрузка включена для разработки
- **Uvicorn запущен**: Высокопроизводительный сервер ASGI активен
- **Процесс перезагрузки запущен**: Наблюдатель файлов для автоматических перезапусков
- **Запуск приложения завершен**: Приложение FastAPI успешно инициализировано
- **Интерактивная документация доступна**: Перейдите на `/docs` для автоматической документации API
#### Тестирование вашего FastAPI: несколько мощных подходов
FastAPI предоставляет несколько удобных способов тестирования вашего API, включая автоматическую интерактивную документацию:
**Метод 1: Интерактивная документация API (рекомендуется)**
1. Откройте браузер и перейдите на `http://localhost:5000/docs`
2. Вы увидите Swagger UI со всеми вашими документированными конечными точками
3. Нажмите на `/hello` → "Try it out" → Введите тестовое сообщение → "Execute"
4. Увидьте ответ прямо в браузере с правильным форматированием
**Метод 2: Базовый тест в браузере**
1. Перейдите на `http://localhost:5000` для корневой конечной точки
2. Перейдите на `http://localhost:5000/health`, чтобы проверить состояние сервера
3. Это подтверждает, что ваш сервер FastAPI работает правильно
**Метод 3: Тестирование через командную строку (продвинутый уровень)**
```bash
# Test with curl (if available)
curl -X POST http://localhost:5000/hello \
-H "Content-Type: application/json" \
-d '{"message": "Hello AI!"}'
# Expected response:
# {"response": "Hello! I'm your AI assistant. How can I help you today?"}
```
**Метод 4: Тестовый скрипт на Python**
#### Устранение распространенных проблем при запуске
| Сообщение об ошибке | Что оно означает | Как исправить |
|---------------------|------------------|--------------|
| `ModuleNotFoundError: No module named 'fastapi'` | FastAPI не установлен | Запустите команду `pip install fastapi uvicorn` в виртуальной среде |
| `ModuleNotFoundError: No module named 'uvicorn'` | ASGI сервер не установлен | Запустите команду `pip install uvicorn` в виртуальной среде |
| `KeyError: 'GITHUB_TOKEN'` | Переменная окружения не найдена | Проверьте файл `.env` и вызов `load_dotenv()` |
| `Address already in use` | Порт 5000 занят | Завершите другие процессы, использующие порт 5000, или измените порт |
| `ValidationError` | Данные запроса не соответствуют модели Pydantic | Убедитесь, что формат вашего запроса соответствует ожидаемой схеме |
| `HTTPException 422` | Невозможно обработать сущность | Проверка запроса не удалась, проверьте правильный формат в `/docs` |
| `OpenAI API error` | Ошибка аутентификации сервиса AI | Убедитесь, что ваш токен GitHub верен и имеет необходимые разрешения |
#### Лучшие практики разработки
**Автоматическая перезагрузка**: FastAPI с Uvicorn обеспечивает автоматическую перезагрузку при сохранении изменений в файлах Python. Это позволяет сразу тестировать изменения без необходимости вручную перезапускать сервер.
**Логирование для разработки**: Добавьте логирование, чтобы понимать, что происходит:
**Почему логирование полезно**: Во время разработки вы можете видеть, какие запросы поступают, как отвечает AI и где возникают ошибки. Это значительно ускоряет процесс отладки.
### Настройка для GitHub Codespaces: Удобная облачная разработка
GitHub Codespaces — это как мощный компьютер для разработки в облаке, доступный из любого браузера. Если вы работаете в Codespaces, есть несколько дополнительных шагов, чтобы сделать ваш бэкенд доступным для фронтенда.
#### Понимание сетевых особенностей Codespaces
В локальной среде разработки все работает на одном компьютере:
- Бэкенд: `http://localhost:5000`
- Фронтенд: `http://localhost:3000` (или file://)
В Codespaces ваша среда разработки работает на серверах GitHub, поэтому "localhost" имеет другое значение. GitHub автоматически создает публичные URL для ваших сервисов, но их нужно правильно настроить.
#### Пошаговая настройка Codespaces
**1. Запустите сервер бэкенда**:
Вы увидите знакомое сообщение о запуске FastAPI/Uvicorn, но обратите внимание, что оно работает внутри среды Codespaces.
**2. Настройте видимость порта**:
- Найдите вкладку "Ports" в нижней панели VS Code
- Найдите порт 5000 в списке
- Щелкните правой кнопкой мыши на порт 5000
- Выберите "Port Visibility" → "Public"
**Почему нужно сделать порт публичным?** По умолчанию порты в Codespaces являются приватными (доступны только вам). Сделав порт публичным, вы позволите вашему фронтенду (который работает в браузере) взаимодействовать с бэкендом.
**3. Получите публичный URL**:
После того как порт станет публичным, вы увидите URL, например:
**4. Обновите конфигурацию фронтенда**:
#### Понимание URL Codespaces
URL Codespaces следуют предсказуемому шаблону:
**Разбор структуры:**
- `codespace-name`: Уникальный идентификатор вашего Codespace (обычно включает ваше имя пользователя)
- `port`: Номер порта, на котором работает ваш сервис (5000 для нашего приложения FastAPI)
- `app.github.dev`: Домен GitHub для приложений Codespace
#### Тестирование настройки Codespaces
**1. Протестируйте бэкенд напрямую**:
Откройте ваш публичный URL в новой вкладке браузера. Вы должны увидеть:
**2. Тестирование с помощью инструментов разработчика браузера**:
#### Codespaces vs Локальная разработка
| Аспект | Локальная разработка | GitHub Codespaces |
|--------|-----------------------|-------------------|
| **Время настройки** | Дольше (установка Python, зависимостей) | Мгновенно (преднастроенная среда) |
| **Доступ к URL** | `http://localhost:5000` | `https://xyz-5000.app.github.dev` |
| **Конфигурация порта** | Автоматическая | Ручная (сделать порты публичными) |
| **Сохранение файлов** | Локальный компьютер | Репозиторий GitHub |
| **Совместная работа** | Сложно делиться средой | Легко делиться ссылкой на Codespace |
| **Зависимость от интернета** | Только для вызовов AI API | Требуется для всего |
#### Советы по разработке в Codespaces
**Переменные окружения в Codespaces**:
Ваш файл `.env` работает так же, как и в локальной среде, но вы также можете задавать переменные окружения прямо в Codespace.
**Управление портами**:
- Codespaces автоматически обнаруживает, когда ваше приложение начинает слушать порт
- Вы можете одновременно перенаправлять несколько портов (полезно, если позже добавите базу данных)
- Порты остаются доступными, пока ваш Codespace работает
**Рабочий процесс разработки**:
1. Внесите изменения в код в VS Code
2. FastAPI автоматически перезагружается (благодаря режиму перезагрузки Uvicorn)
3. Тестируйте изменения сразу через публичный URL
4. Коммитите и отправляйте изменения, когда будете готовы
> 💡 **Полезный совет**: Сохраните закладку на URL вашего бэкенда в Codespace во время разработки. Поскольку имена Codespace стабильны, URL не изменится, пока вы используете тот же Codespace.
## Создание интерфейса чата: где человек встречается с AI
Теперь мы создадим пользовательский интерфейс – ту часть, которая определяет, как люди взаимодействуют с вашим AI-ассистентом. Как дизайн интерфейса оригинального iPhone, мы сосредоточимся на том, чтобы сделать сложные технологии интуитивно понятными и удобными в использовании.
### Понимание современной архитектуры фронтенда
Наш интерфейс чата будет представлять собой так называемое "Одностраничное приложение" (SPA). Вместо старомодного подхода, где каждый клик загружает новую страницу, наше приложение будет обновляться плавно и мгновенно:
**Старые сайты**: Как чтение физической книги – вы переворачиваете страницы
**Наше приложение чата**: Как использование телефона – все плавно обновляется и работает без задержек
### Три столпа фронтенд-разработки
Каждое фронтенд-приложение – от простых сайтов до сложных приложений, таких как Discord или Slack – строится на трех основных технологиях. Они являются основой всего, что вы видите и с чем взаимодействуете в интернете:
**HTML (Структура)**: Это ваш фундамент
- Определяет, какие элементы существуют (кнопки, текстовые поля, контейнеры)
- Придает смысл содержимому (это заголовок, это форма и т.д.)
- Создает базовую структуру, на которой все остальное строится
**CSS (Презентация)**: Это ваш дизайнер интерьера
- Делает все красивым (цвета, шрифты, макеты)
- Учитывает разные размеры экрана (телефон, ноутбук, планшет)
- Создает плавные анимации и визуальную обратную связь
**JavaScript (Поведение)**: Это ваш мозг
- Реагирует на действия пользователей (клики, ввод текста, прокрутка)
- Общается с бэкендом и обновляет страницу
- Делает все интерактивным и динамичным
**Представьте это как архитектурный дизайн:**
- **HTML**: Структурный чертеж (определение пространств и связей)
- **CSS**: Эстетический и дизайнерский аспект (визуальный стиль и пользовательский опыт)
- **JavaScript**: Механические системы (функциональность и интерактивность)
### Почему важна современная архитектура JavaScript
Наше приложение для чата будет использовать современные шаблоны JavaScript, которые вы встретите в профессиональных приложениях. Понимание этих концепций поможет вам развиваться как разработчику:
**Архитектура на основе классов**: Мы организуем наш код в классы, что похоже на создание чертежей для объектов
**Async/Await**: Современный способ обработки операций, которые занимают время (например, вызовы API)
**Программирование, основанное на событиях**: Наше приложение реагирует на действия пользователя (клики, нажатия клавиш), а не работает в цикле
**Манипуляция DOM**: Динамическое обновление содержимого веб-страницы на основе взаимодействий пользователя и ответов API
### Настройка структуры проекта
Создайте директорию фронтенда с такой организованной структурой:
**Понимание архитектуры:**
- **Разделение** обязанностей между структурой (HTML), поведением (JavaScript) и презентацией (CSS)
- **Поддержание** простой структуры файлов, которая легко навигабельна и модифицируема
- **Следование** лучшим практикам веб-разработки для организации и удобства поддержки
### Создание HTML-основы: семантическая структура для доступности
Начнем с HTML-структуры. Современная веб-разработка подчеркивает важность "семантического HTML" – использования элементов, которые четко описывают свое назначение, а не только внешний вид. Это делает ваше приложение доступным для экранных читалок, поисковых систем и других инструментов.
**Почему семантический HTML важен**: Представьте, что вы описываете ваше приложение чата кому-то по телефону. Вы бы сказали: "Есть заголовок с названием, основная область, где появляются сообщения, и форма внизу для ввода сообщений". Семантический HTML использует элементы, которые соответствуют этому естественному описанию.
Создайте файл `index.html` с продуманной структурой разметки:
**Понимание каждого HTML-элемента и его назначения**:
#### Структура документа
- **``**: Указывает браузеру, что это современный HTML5
- **``**: Указывает язык страницы для экранных читалок и инструментов перевода
- **``**: Обеспечивает правильное кодирование символов для международного текста
- **``**: Делает страницу адаптивной для мобильных устройств, контролируя масштабирование
#### Семантические элементы
- **``**: Четко обозначает верхнюю часть с заголовком и описанием
- **``**: Обозначает основную область контента (где происходят разговоры)
- **`