diff --git a/README.ARCH.md b/README.ARCH.md deleted file mode 100644 index 4453d5b..0000000 --- a/README.ARCH.md +++ /dev/null @@ -1,155 +0,0 @@ -# Архитектура приложения - -Документ описывает модульную архитектуру backend-приложения, связи между модулями и контрактные границы. - -## 1. Диаграмма модулей и взаимосвязей - -```mermaid -flowchart LR - UI["Клиент / Frontend"] --> API["FastAPI (app/main.py)"] - - API --> CHAT["chat модуль"] - API --> RAG["rag модуль"] - API --> AGENT_INTERNAL["internal tools API"] - - CHAT -->|AgentRunner| AGENT["agent модуль"] - AGENT -->|RagRetriever| RAG - AGENT --> DB[(PostgreSQL + pgvector)] - CHAT --> DB - RAG --> DB - - AGENT --> GIGA["GigaChat API"] - RAG --> GIGA - - AGENT_INTERNAL --> AGENT - - APP["ModularApplication\n(app/modules/application.py)"] --> CHAT - APP --> AGENT - APP --> RAG -``` - -### Внутренние слои `agent` - -```mermaid -flowchart TB - ROUTER["Router\n(intent + context)"] --> ORCH["Orchestrator\n(task spec + plan + execution + quality)"] - ORCH --> GRAPHS["Action Graphs\nLangGraph"] - - ORCH --> METRICS["Quality Metrics\n(faithfulness/coverage)"] - METRICS --> DB[(agent_quality_metrics)] -``` - -## 2. Описание модулей - -### Модуль `app/modules/chat` - -- Цель: принять пользовательский запрос, управлять задачей обработки, отдать результат и прогресс. -- Кратко о реализации: - - `ChatModule` публикует HTTP API (`/api/chat/*`, `/api/tasks/*`, `/api/events`). - - `ChatOrchestrator` запускает обработку асинхронной задачи, публикует SSE-события, обрабатывает retry и ошибки. - - `TaskStore`, `DialogSessionStore`, `IdempotencyStore` держат состояние задач/диалогов. -- С кем взаимодействует: - - с `agent` через контракт `AgentRunner`. - - с `rag` для проверки `rag_session_id`. - - с `shared/event_bus` для стриминга прогресса. - - с БД через `ChatRepository` (`dialog_sessions`, `chat_messages`). -- Контракты: - - потребляет `AgentRunner.run(...)` из `app/modules/contracts.py`. - -### Модуль `app/modules/agent` - -- Цель: интеллектуальная обработка запроса, маршрутизация, оркестрация сценария, генерация ответа/changeset. -- Кратко о реализации: - - `GraphAgentRuntime` выполняет pipeline: route -> task spec -> orchestrator -> post-processing. - - Router (`engine/router/*`) выбирает `domain/process` и хранит routing-context. - - Orchestrator (`engine/orchestrator/*`) строит и валидирует plan, исполняет шаги, запускает графовые/функциональные actions. - - Graphs (`engine/graphs/*`) выполняют целевые действия (QA, edits, docs). - - Рассчитывает quality-метрики (`faithfulness`, `coverage`) и сохраняет их в БД. - - Поддерживает внутренний инструмент получения страниц Confluence (`/internal/tools/confluence/fetch`). -- С кем взаимодействует: - - с `rag` через контракт `RagRetriever`. - - с `shared/checkpointer` (LangGraph checkpoints в PostgreSQL). - - с GigaChat (LLM-запросы, промпты). - - с БД через `AgentRepository` (`router_context`, `agent_quality_metrics`). -- Контракты: - - реализует `AgentRunner` (используется `chat`). - - потребляет `RagRetriever` (реализуется `rag`). - -### Модуль `app/modules/rag` - -- Цель: индексация проектных файлов и retrieval релевантного контекста. -- Кратко о реализации: - - API для snapshot/changes индексации и retrieval. - - Индексация хранит чанки, эмбеддинги и состояние job. - - Retrieval ищет релевантные куски в `rag_chunks` (pgvector). -- С кем взаимодействует: - - с `agent` (выдача контекста через `RagRetriever`). - - с БД (`rag_sessions`, `rag_chunks`, `rag_index_jobs`). - - с GigaChat Embeddings. -- Контракты: - - реализует `RagRetriever` и `RagIndexer` из `app/modules/contracts.py`. - -### Модуль `app/modules/shared` - -- Цель: общие инфраструктурные компоненты, переиспользуемые всеми модулями. -- Кратко о реализации: - - `db.py`: engine/session factory. - - `event_bus.py`: pub/sub для SSE. - - `retry_executor.py`: общий retry. - - `checkpointer.py`: PostgresSaver для LangGraph. - - `bootstrap.py`: инициализация схем БД на старте. -- С кем взаимодействует: - - со всеми бизнес-модулями (`chat`, `agent`, `rag`). -- Контракты: - - внутренние инфраструктурные API без отдельного публичного контракта уровня `contracts.py`. - -### Модуль `app/modules/contracts.py` - -- Цель: зафиксировать межмодульные интерфейсы и отделить реализацию от потребителей. -- Кратко о реализации: - - `AgentRunner`, `RagRetriever`, `RagIndexer` определены как `Protocol`. -- С кем взаимодействует: - - используется `chat` (как потребитель `AgentRunner`), `agent` (как потребитель `RagRetriever`), `rag` (как реализация `RagRetriever`/`RagIndexer`). -- Контракты: - - это и есть контрактный слой. - -### Модуль композиции `app/modules/application.py` - -- Цель: централизованный wiring зависимостей. -- Кратко о реализации: - - `ModularApplication` создаёт `EventBus`, `RetryExecutor`, репозитории и модули. - - На `startup()` выполняет bootstrap БД. -- С кем взаимодействует: - - со всеми модулями, но не содержит бизнес-логики. -- Контракты: - - использует `contracts.py` для сборки зависимостей без жёсткого сцепления по реализациям. - -## 3. Ключевые контрактные границы - -- `chat -> agent`: только через `AgentRunner`. -- `agent -> rag`: только через `RagRetriever`. -- `rag`: не зависит от `agent` internals. -- `application.py`: единственная точка связывания реализаций. - -## 4. Схема данных (кратко) - -- `chat`: `dialog_sessions`, `chat_messages`. -- `rag`: `rag_sessions`, `rag_chunks`, `rag_index_jobs`. -- `agent`: - - `router_context` — контекст маршрутизации по диалогу. - - `agent_quality_metrics` — пер-сценарные quality-метрики для отчетности: - - `faithfulness_score`, `coverage_score`, `quality_status`, `metrics_json`, `created_at`. - - `story_records` — карточка Story (статус, владелец, метаданные). - - `story_artifacts` — артефакты по Story (analytics/doc_increment/test_model и версии). - - `story_links` — внешние связи Story (тикеты, документы, URL). - -## 5. Поток обработки запроса - -1. Пользователь отправляет сообщение в `chat`. -2. `chat` создаёт task и вызывает `AgentRunner.run(...)`. -3. `agent/router` выбирает маршрут (domain/process). -4. `agent/orchestrator` строит `TaskSpec` и `ExecutionPlan`. -5. Выполняются шаги плана (function/actions/graph steps). -6. Формируется `answer` или `changeset`. -7. Считаются `faithfulness/coverage`, сохраняются в `agent_quality_metrics`. -8. `chat` возвращает результат и стримит прогресс через SSE. diff --git a/README.md b/README.md index 62b827b..0ea6578 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,109 @@ -# Agent Backend MVP +# Агент для работы с проектной документацией -## Run (Local) +## 1. Общее описание +Приложение представляет собой backend агентного режима для работы с документацией и кодом проекта. +Система решает следующие задачи: +- индексирует локальную копию проекта в `rag_session` и использует ее как основной рабочий контекст пользователя; +- принимает webhook коммитов репозитория в `rag_repo` и фиксирует контекст изменений по `story_id`; +- ускоряет построение `rag_session` за счет переиспользования кэша чанков и эмбеддингов из `rag_repo`; +- обрабатывает пользовательские запросы через `chat`, `agent`, оркестратор и специализированные графы; +- сохраняет quality-метрики, Story-контекст и артефакты сессии в PostgreSQL. + +Ключевая идея архитектуры: +- `rag_session` отвечает за пользовательскую рабочую сессию и всегда остается основным источником retrieval; +- `rag_repo` не участвует напрямую в пользовательском ответе, а служит фоновым источником кэша и контекста коммитов; +- `story_id` связывает изменения аналитика, документацию и последующую работу тестировщика. + +## 2. Архитектура +```mermaid +flowchart LR + User["Пользователь"] + Git["Git репозиторий\n(Gitea / Bitbucket)"] + Chat["Модуль chat"] + Agent["Модуль agent"] + RagSession["Модуль rag_session"] + RagRepo["Модуль rag_repo"] + Shared["Модуль shared"] + DB["PostgreSQL + pgvector"] + Giga["GigaChat API"] + + User --> Chat + Chat --> Agent + Agent --> RagSession + Agent --> Shared + RagSession --> Shared + RagRepo --> Shared + Chat --> DB + Agent --> DB + RagSession --> DB + RagRepo --> DB + RagSession --> Giga + Agent --> Giga + Git --> RagRepo + RagRepo -.кэш и контекст коммитов.-> RagSession +``` + +Кратко по ролям модулей: +- `chat` — внешний API чата, фоновые задачи, SSE события, диалоги. +- `agent` — роутер интентов, оркестратор, графы, tools, генерация ответа и changeset. +- `rag_session` — создание и сопровождение пользовательского RAG индекса по локальным файлам. +- `rag_repo` — прием webhook коммитов, определение `story_id`, фиксация контекста коммита и заполнение repo-cache. +- `shared` — инфраструктурный слой: БД, retry, event bus, GigaChat client, настройки. + +## 3. Типичный флоу +```mermaid +sequenceDiagram + actor User as Пользователь + participant Git as Git репозиторий + participant RagRepo as Модуль rag_repo + participant DB as PostgreSQL + participant RagSession as Модуль rag_session + participant Chat as Модуль chat + participant Agent as Модуль agent + + Note over User,RagSession: Первая рабочая сессия: кэша репозитория еще нет + User->>RagSession: Создание rag_session и загрузка файлов проекта + RagSession->>DB: Проверка cache hit/miss + DB-->>RagSession: Кэш пуст + RagSession->>RagSession: Чанкинг и расчет embeddings без repo-cache + RagSession->>DB: Сохранение rag_chunks и rag_index_jobs + User->>Chat: Отправка запроса в чат + Chat->>Agent: Передача задачи + Agent->>RagSession: Retrieval контекста + RagSession->>DB: Чтение rag_chunks + DB-->>RagSession: Релевантные чанки + RagSession-->>Agent: Контекст + Agent-->>Chat: Ответ / changeset + + Note over User,Git: Пользователь вручную делает commit и push + Git->>RagRepo: Webhook push + RagRepo->>RagRepo: Определение provider, commit_sha, changed_files, story_id + RagRepo->>DB: Запись story_records/story_links/story_artifacts + RagRepo->>DB: Запись rag_blob_cache/rag_chunk_cache/rag_session_chunk_map + + Note over User,RagSession: Вторая рабочая сессия: repo-cache уже существует + User->>RagSession: Создание новой rag_session и загрузка файлов проекта + RagSession->>DB: Проверка cache hit/miss + DB-->>RagSession: Найдены cache hit по части файлов + RagSession->>RagSession: Переиспользование чанков из rag_repo cache + RagSession->>RagSession: Пересчет embeddings только для cache miss файлов + RagSession->>DB: Сохранение rag_chunks, rag_session_chunk_map, rag_index_jobs + User->>Chat: Новый запрос + Chat->>Agent: Передача задачи + Agent->>RagSession: Retrieval по новой сессии + RagSession-->>Agent: Контекст из session-RAG + Agent-->>Chat: Ответ / changeset +``` + +Что важно в этом сценарии: +- первый запуск индексации может быть полностью без кэша; +- после коммита `rag_repo` фиксирует контекст изменений и наполняет cache-таблицы; +- во второй и последующих сессиях `rag_session` использует `cache_hit_files`, чтобы уменьшить объем новых embeddings. + +## 4. Инструкции к запуску + +### Локальный запуск ```bash python3 -m venv .venv source .venv/bin/activate @@ -9,135 +111,51 @@ pip install -r requirements.txt uvicorn app.main:app --reload --port 15000 ``` -## Run (Docker Compose) - -1. Fill env values: - +### Запуск через Docker Compose +1. Создать `.env` на основе примера: ```bash cp .env.example .env ``` -Set `GIGACHAT_TOKEN` in `.env`. - -2. Start: +2. Заполнить как минимум `GIGACHAT_TOKEN`. +3. Запустить сервисы: ```bash -docker compose up --build +docker compose up -d --build ``` -- Public API: `http://localhost:15000/api/*` -- PostgreSQL + pgvector runs in `db` service on `localhost:5432` - -Stop: - +4. Проверить доступность backend: ```bash -docker compose down +curl http://localhost:15000/health ``` -## Public API +Ожидаемый ответ: +```json +{"status":"ok"} +``` -- `POST /api/rag/sessions` -- `POST /api/rag/sessions/{rag_session_id}/changes` -- `GET /api/rag/sessions/{rag_session_id}/jobs/{index_job_id}` -- `GET /api/rag/sessions/{rag_session_id}/jobs/{index_job_id}/events` (SSE progress) -- `POST /api/chat/dialogs` -- `POST /api/chat/messages` -- `GET /api/tasks/{task_id}` -- `GET /api/events?task_id=...` -- `POST /api/index/snapshot` -- `POST /api/index/changes` -- `GET /api/index/jobs/{index_job_id}` -- `GET /api/index/jobs/{index_job_id}/events` (legacy SSE progress) +### Основные адреса +- Backend API: `http://localhost:15000` +- PostgreSQL + pgvector: `localhost:5432` +- Webhook репозитория: `POST /internal/rag-repo/webhook` -RAG indexing SSE events (`/api/rag/sessions/{rag_session_id}/jobs/{index_job_id}/events`): -- `index_status`: `{"index_job_id","status","total_files",...}` -- `index_progress`: `{"index_job_id","current_file_index","total_files","processed_files","current_file_path","current_file_name"}` -- `terminal`: `{"index_job_id","status":"done|error",...}` (final event; stream closes after this event) +### Базовый сценарий проверки +1. Создать `rag_session` через `POST /api/rag/sessions`. +2. Дождаться завершения index-job через `GET /api/rag/sessions/{rag_session_id}/jobs/{index_job_id}`. +3. Создать диалог через `POST /api/chat/dialogs`. +4. Отправить сообщение через `POST /api/chat/messages`. +5. Настроить webhook репозитория на `POST /internal/rag-repo/webhook`. +6. Сделать commit с `story_id` в сообщении, например `FEAT-1 ...`. +7. Проверить заполнение таблиц: + - `story_records`, `story_links`, `story_artifacts` + - `rag_blob_cache`, `rag_chunk_cache`, `rag_session_chunk_map` +8. Во второй сессии индексации проверить поля job-статуса: + - `indexed_files` + - `cache_hit_files` + - `cache_miss_files` -## Session Model - -- `rag_session_id`: identifies indexed project chunks in RAG. -- `dialog_session_id`: identifies one independent dialog context within a `rag_session_id`. -- Multiple dialogs can share one `rag_session_id`. - -Recommended flow: -1. call `POST /api/rag/sessions` after project selection; -2. wait for indexing job completion; -3. call `POST /api/chat/dialogs` with `rag_session_id`; -4. call `POST /api/chat/messages` with `dialog_session_id` + `rag_session_id`. - -`/api/chat/messages` supports explicit routing hint: -- `mode: "auto" | "project_qa" | "project_edits" | "docs_generation" | "qa"` -- Legacy aliases are still accepted: `code_change`, `analytics_review`. - -## Persistence - -Persisted in PostgreSQL: -- `rag_sessions`, `rag_chunks`, `rag_index_jobs` -- `dialog_sessions`, `chat_messages` -- `router_context` (agent routing context per dialog session) -- LangGraph checkpoints via `PostgresSaver` (thread id = `dialog_session_id`) - -Notes: -- RAG vectors are stored in `pgvector` column (`rag_chunks.embedding`). -- Agent context/history is restored after restart for same `dialog_session_id`. - -## Agent Runtime - -- Router + context store (`app/modules/agent/engine/router/*`) -- LangGraph flow execution (`app/modules/agent/engine/graphs/*`) -- Route selection: - - `default/general` -> answer flow - - `project/qa` -> answer flow - - `project/edits` -> conservative changeset flow for non-code file updates (hybrid output: `proposed_content` + `hunks`) - - `docs/generation` -> answer and/or changeset flow -- LLM provider: GigaChat (`chat/completions`) -- Prompts for graph LLM nodes: `app/modules/agent/prompts/*.txt` - - `general_answer.txt` - - `project_answer.txt` - - `project_edits_plan.txt` - - `project_edits_hunks.txt` - - `project_edits_self_check.txt` - - `docs_generation.txt` - - `docs_execution_summary.txt` - -## Modules Structure - -- `app/modules/chat/*`: chat API, tasks, session-scoped orchestration, event streaming. -- `app/modules/agent/*`: intent router, LangGraph flows, confluence integration, changeset validation. -- `app/modules/rag/*`: indexing API/jobs and retrieval service. -- `app/modules/shared/*`: cross-module primitives (event bus, retry, idempotency). -- `app/modules/contracts.py`: fixed inter-module contracts (`AgentRunner`, `RagRetriever`, `RagIndexer`). - -## Module Boundaries - -- `chat` depends on contract `AgentRunner`, but not on concrete `agent` internals. -- `agent` depends on contract `RagRetriever`, but not on `rag` indexing internals. -- `rag` exposes public/internal API and service implementation. -- wiring is centralized in `app/modules/application.py`. - -## Internal API (for integration) - -- `POST /internal/rag/index/snapshot` -- `POST /internal/rag/index/changes` -- `GET /internal/rag/index/jobs/{index_job_id}` -- `POST /internal/rag/retrieve` -- `POST /internal/tools/confluence/fetch` - -## Environment - -- `.env.example` contains full list of parameters. -- `.env` is used by Docker Compose for `db` and `backend`. -- `GIGACHAT_TOKEN`: Basic credentials for OAuth exchange (required for LLM/embeddings). -- `DATABASE_URL`: PostgreSQL DSN, default `postgresql+psycopg://agent:agent@db:5432/agent`. -- `GIGACHAT_AUTH_URL`: default `https://ngw.devices.sberbank.ru:9443/api/v2/oauth`. -- `GIGACHAT_API_URL`: default `https://gigachat.devices.sberbank.ru/api/v1`. -- `GIGACHAT_SCOPE`: default `GIGACHAT_API_PERS`. -- `GIGACHAT_SSL_VERIFY`: `true|false`, default `true`. -- `GIGACHAT_MODEL`: chat model name, default `GigaChat`. -- `GIGACHAT_EMBEDDING_MODEL`: embedding model name, default `Embeddings`. -- `AGENT_PROMPTS_DIR`: optional override path for prompt files. - -Troubleshooting: -- If indexing shows `failed_files > 0` and `indexed_files = 0`, check backend logs for TLS/auth errors to GigaChat. -- In corporate environments with custom TLS chain, set `GIGACHAT_SSL_VERIFY=false` (or install proper CA certs in container). +### Полезные замечания +- Текущая chat-модель: `GigaChat`. +- Основной retrieval всегда идет из `rag_session`. +- `rag_repo` используется как фоновый источник кэша и контекста коммитов. +- Если в webhook не найден `story_id`, commit-контекст Story не будет привязан, но cache-таблицы все равно должны наполняться.