первый коммит
This commit is contained in:
98
app/modules/chat/README.md
Normal file
98
app/modules/chat/README.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Модуль chat
|
||||
|
||||
## 1. Функции модуля
|
||||
- Внешний API чата: создание диалога, отправка сообщения, получение статуса задачи.
|
||||
- Асинхронная оркестрация выполнения через `ChatOrchestrator`.
|
||||
- Idempotency и стриминг событий по SSE.
|
||||
|
||||
## 2. Диаграмма классов и взаимосвязей
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ChatModule
|
||||
class ChatOrchestrator
|
||||
class TaskStore
|
||||
class DialogSessionStore
|
||||
class IdempotencyStore
|
||||
class EventBus
|
||||
class AgentRunner
|
||||
|
||||
ChatModule --> ChatOrchestrator
|
||||
ChatModule --> TaskStore
|
||||
ChatModule --> DialogSessionStore
|
||||
ChatModule --> IdempotencyStore
|
||||
ChatModule --> EventBus
|
||||
ChatOrchestrator --> AgentRunner
|
||||
ChatOrchestrator --> TaskStore
|
||||
ChatOrchestrator --> DialogSessionStore
|
||||
ChatOrchestrator --> EventBus
|
||||
```
|
||||
|
||||
## 3. Описание классов
|
||||
- `ChatModule`: фасад модуля и регистрация публичных chat endpoint'ов.
|
||||
Методы: `__init__` — собирает stores/orchestrator; `public_router` — публикует REST и SSE маршруты чата.
|
||||
- `ChatOrchestrator`: выполняет жизненный цикл user-message как фоновой задачи.
|
||||
Методы: `enqueue_message` — создает задачу и запускает обработку; `_process_task` — исполняет runtime и сохраняет результат; `_resolve_sessions` — валидирует и сопоставляет dialog/rag сессии.
|
||||
- `TaskStore`: in-memory store состояний задач.
|
||||
Методы: `create` — создает новую `TaskState`; `get` — возвращает задачу по `task_id`; `save` — обновляет состояние задачи.
|
||||
- `DialogSessionStore`: хранилище dialog-сессий поверх БД.
|
||||
Методы: `create` — создает новую dialog-сессию; `get` — читает dialog-сессию по id.
|
||||
- `IdempotencyStore`: предотвращает дубль задач по идемпотентному ключу.
|
||||
Методы: `get_task_id` — возвращает существующий `task_id` по ключу; `put` — сохраняет ключ и `task_id`.
|
||||
- `EventBus`: асинхронная публикация/подписка событий.
|
||||
Методы: `subscribe` — создает подписку на канал; `unsubscribe` — снимает подписку; `publish` — отправляет событие подписчикам; `as_sse` — сериализует событие в SSE формат.
|
||||
- `AgentRunner` (контракт): интерфейс выполнения агентного запроса из chat-слоя.
|
||||
Методы: `run` — принимает данные задачи и возвращает итог `answer`/`changeset`.
|
||||
|
||||
## 4. Сиквенс-диаграммы API
|
||||
|
||||
### POST /api/chat/dialogs
|
||||
Назначение: создает новый диалог, связанный с существующей `rag_session`, чтобы пользователь мог отправлять сообщения в контексте конкретного индекса.
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Router as ChatModule.APIRouter
|
||||
participant RagSessions as RagSessionStore
|
||||
participant Dialogs as DialogSessionStore
|
||||
|
||||
Router->>RagSessions: get(rag_session_id)
|
||||
RagSessions-->>Router: exists
|
||||
Router->>Dialogs: create(rag_session_id)
|
||||
Dialogs-->>Router: dialog_session
|
||||
```
|
||||
|
||||
### POST /api/chat/messages
|
||||
Назначение: ставит сообщение пользователя в асинхронную обработку и возвращает `task_id` для отслеживания результата.
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Router as ChatModule.APIRouter
|
||||
participant Orchestrator as ChatOrchestrator
|
||||
participant TaskStore as TaskStore
|
||||
|
||||
Router->>Orchestrator: enqueue_message(request, idempotency_key)
|
||||
Orchestrator->>TaskStore: create()/save()
|
||||
Orchestrator-->>Router: task_id,status
|
||||
```
|
||||
|
||||
### GET /api/tasks/{task_id}
|
||||
Назначение: отдает текущее состояние задачи и финальный результат (answer/changeset/error), когда обработка завершена.
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Router as ChatModule.APIRouter
|
||||
participant TaskStore as TaskStore
|
||||
|
||||
Router->>TaskStore: get(task_id)
|
||||
TaskStore-->>Router: task_state
|
||||
```
|
||||
|
||||
### GET /api/events?task_id=...
|
||||
Назначение: открывает SSE-поток с прогрессом выполнения задачи и промежуточными событиями.
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Router as ChatModule.APIRouter
|
||||
participant Events as EventBus
|
||||
|
||||
Router->>Events: subscribe(task_id)
|
||||
loop until disconnect
|
||||
Events-->>Router: SSE event
|
||||
end
|
||||
Router->>Events: unsubscribe(task_id)
|
||||
```
|
||||
Binary file not shown.
Binary file not shown.
@@ -7,7 +7,7 @@ from app.modules.chat.repository import ChatRepository
|
||||
from app.modules.chat.service import ChatOrchestrator
|
||||
from app.modules.chat.task_store import TaskStore
|
||||
from app.modules.contracts import AgentRunner
|
||||
from app.modules.rag.session_store import RagSessionStore
|
||||
from app.modules.rag_session.session_store import RagSessionStore
|
||||
from app.modules.shared.event_bus import EventBus
|
||||
from app.modules.shared.idempotency_store import IdempotencyStore
|
||||
from app.modules.shared.retry_executor import RetryExecutor
|
||||
|
||||
@@ -14,6 +14,13 @@ from app.modules.shared.retry_executor import RetryExecutor
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _truncate_for_log(text: str, max_chars: int = 1200) -> str:
|
||||
value = (text or "").replace("\n", "\\n").strip()
|
||||
if len(value) <= max_chars:
|
||||
return value
|
||||
return value[:max_chars].rstrip() + "...[truncated]"
|
||||
|
||||
|
||||
class ChatOrchestrator:
|
||||
def __init__(
|
||||
self,
|
||||
@@ -78,6 +85,16 @@ class ChatOrchestrator:
|
||||
try:
|
||||
await self._publish_progress(task_id, "task.sessions", "Проверяю сессии диалога и проекта.", progress=10)
|
||||
dialog_session_id, rag_session_id = self._resolve_sessions(request)
|
||||
LOGGER.warning(
|
||||
"incoming chat request: task_id=%s dialog_session_id=%s rag_session_id=%s mode=%s attachments=%s files=%s message=%s",
|
||||
task_id,
|
||||
dialog_session_id,
|
||||
rag_session_id,
|
||||
request.mode.value,
|
||||
len(request.attachments),
|
||||
len(request.files),
|
||||
_truncate_for_log(request.message),
|
||||
)
|
||||
await self._publish_progress(task_id, "task.sessions.done", "Сессии проверены, запускаю агента.", progress=15)
|
||||
loop = asyncio.get_running_loop()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user