chore: обновление документации, Docker, UI и поисковых компонентов

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
home
2026-02-20 16:15:05 +03:00
parent b65d24c1e8
commit c839a0c472
21 changed files with 480 additions and 132 deletions

View File

@@ -0,0 +1,348 @@
# Архитектура микросервисов GooSeek
Документ описывает план разбиения монолитного приложения GooSeek на микросервисы.
---
## 1. Текущая архитектура (монолит)
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Next.js Application (monolith) │
├─────────────────────────────────────────────────────────────────────────────┤
│ API Routes │ Agents/Search │ Models/Providers │ Data │
│ /api/chat │ classifier │ OpenAI, Anthropic │ SQLite│
│ /api/search │ researcher │ Ollama, Groq... │ config│
│ /api/images │ widgets │ registry │ uploads│
│ /api/videos │ writer │ │ │
│ /api/uploads │ media (image/video) │ │ │
│ /api/chats │ │ │ │
│ /api/providers │ │ │ │
│ /api/config │ │ │ │
│ /api/suggestions │ │ │ │
│ /api/weather │ │ │ │
│ /api/discover │ │ │ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ External: SearXNG │ Yahoo Finance │ Open-Meteo │ LLM APIs (OpenAI, etc.) │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 2. Предлагаемые микросервисы
### 2.1 Общая схема
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Frontend │────▶│ Gateway │────▶│ Chat │────▶│ Research │
│ (Next.js) │ │ (BFF/API) │ │ Service │ │ Service │
└──────────────┘ └──────────────┘ └──────┬───────┘ └──────┬───────┘
│ │ │ │
│ │ │ │
│ ▼ ▼ ▼
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ Config/Chats │ │ LLM Proxy │ │ Search │
└────────────▶│ Service │ │ Service │ │ Service │
└──────────────┘ └──────────────┘ └──────┬───────┘
│ │ │
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Storage │ │ Providers │ │ Uploads │
│ Service │ │ (external) │ │ Service │
└──────────────┘ └──────────────┘ └──────────────┘
```
---
## 3. Описание сервисов
### 3.1 Frontend (Next.js UI)
**Назначение:** Только UI — страницы, компоненты, клиентский state.
**Содержимое:**
- `src/app/page.tsx`, `layout.tsx`, маршруты страниц
- `src/components/` — все UI компоненты
- `src/lib/hooks/` — клиентские хуки
- `src/lib/actions.ts` — вызовы к Gateway API
**Исключить:** Все API routes (`src/app/api/`), серверная логика агентов, прямые вызовы DB.
**API:** Вызывает только Gateway.
---
### 3.2 Gateway (Backend-for-Frontend / API Gateway)
**Назначение:** Единая точка входа для клиента, роутинг, валидация, агрегация.
**Реализация:** Отдельный Node.js сервис (Fastify/Express) или часть Next.js API routes, которая только проксирует.
**Маршруты:**
- `POST /api/chat` → Chat Service
- `POST /api/search` → Chat Service (API mode)
- `GET/POST /api/chats/*` → Storage Service
- `POST /api/uploads` → Uploads Service
- `GET/POST /api/providers/*` → Config + LLM Proxy
- `GET/POST /api/config/*` → Storage Service (config)
- `POST /api/suggestions` → Chat Service
- `POST /api/images` → Chat/Media Service
- `POST /api/videos` → Chat/Media Service
- `GET /api/weather` → Widgets Service (или inline)
- `POST /api/discover` → Search Service
**Зависимости:** Chat, Storage, Uploads, Search. Не содержит бизнес-логики.
---
### 3.3 Chat Service (Оркестратор)
**Назначение:** Главный оркестратор диалога: классификация, планирование, вызов research и writer.
**Исходники:**
- `src/lib/agents/search/index.ts` — SearchAgent
- `src/lib/agents/search/api.ts` — APISearchAgent
- `src/lib/agents/search/classifier.ts`
- `src/lib/agents/search/widgets/` — executor + виджеты (weather, stock, calc)
- `src/lib/prompts/search/` — classifier, writer, researcher prompts
- `src/lib/session.ts`
**API (внутренние):**
- `POST /classify` — классификация запроса
- `POST /search` — полный пайплайн (classify → research → widgets → write)
- `POST /suggestions` — генерация подсказок
**Вызывает:**
- Research Service — для поиска
- LLM Proxy — для LLM вызовов (classify, write, suggestions)
- Widgets (внешние API: Yahoo Finance, погода) — можно вынести в отдельный сервис
**Поток данных:**
1. Классификация (LLM)
2. Параллельно: Research Service + виджеты
3. Генерация ответа (LLM)
4. Сохранение в Storage (через Gateway или напрямую)
---
### 3.4 Research Service
**Назначение:** Выполнение исследовательского цикла — tools (web, academic, social, scrape, uploads).
**Исходники:**
- `src/lib/agents/search/researcher/` — Researcher, ActionRegistry
- `src/lib/agents/search/researcher/actions/` — webSearch, academicSearch, socialSearch, scrapeURL, uploadsSearch, plan, done
- `src/lib/prompts/search/researcher.ts`
**API:**
- `POST /research` — вход: classification, query, chatHistory, config → выход: searchFindings, findings
**Вызывает:**
- Search Service — SearXNG (web, academic, social)
- Uploads Service — семантический поиск по файлам
- LLM Proxy — для researcher agent (tool calls)
- Внешние URL — scrape
**Важно:** Researcher — это LLM-driven agent с tool calls. LLM решает, какой tool вызвать. Либо LLM живёт в Chat Service и вызывает tools по HTTP, либо Research Service сам держит копию researcher LLM — тогда нужно дублировать LLM-вызовы.
**Рекомендация:** Оставить researcher внутри Chat Service, а в Research Service вынести только **действия** (web search, scrape, uploads search) как отдельные HTTP endpoints. Chat Service вызывает Research Service по каждому tool call. Это уменьшает связанность, но увеличивает сетевые вызовы.
**Альтернатива:** Research как один сервис с LLM — получает query и classification, сам итерирует и возвращает готовые findings. Меньше round-trips, но дублирование LLM-инфраструктуры.
---
### 3.5 Search Service (SearXNG + обёртка)
**Назначение:** Обёртка над SearXNG для веб/академического/медиа поиска.
**Исходники:**
- `src/lib/searxng.ts`
- Вызовы: webSearch, academicSearch, socialSearch, image, video — все идут через `searchSearxng`
**API:**
- `GET /search?q=...&engines=...&categories=...`
- `GET /images?q=...`
- `GET /videos?q=...`
**Внешняя зависимость:** SearXNG (уже отдельный сервис/контейнер).
**Реализация:** Минимальный Node.js/Fastify сервис, который проксирует к SearXNG и добавляет логику (rate limiting, fallback, кэш).
---
### 3.6 Uploads Service
**Назначение:** Загрузка файлов, парсинг (PDF, DOCX, TXT), эмбеддинги, семантический поиск.
**Исходники:**
- `src/lib/uploads/manager.ts` — UploadManager
- `src/lib/uploads/store.ts` — UploadStore (поиск по эмбеддингам)
- `src/lib/utils/splitText.ts`, `computeSimilarity.ts`
- Зависимости: pdf-parse, officeparser
**API:**
- `POST /upload` — multipart, возвращает fileIds
- `POST /search` — query, fileIds → chunks (семантический поиск)
- `GET /files/:id` — метаданные файла
**Вызывает:** LLM Proxy — только для embedding модели (можно вынести в отдельный Embedding Service).
**Хранение:** Файлы на диске/volume, `uploaded_files.json`, `.content.json` с chunks.
---
### 3.7 Storage Service
**Назначение:** Централизованное хранилище: чаты, сообщения, конфигурация.
**Исходники:**
- `src/lib/db/` — schema, migrations, drizzle
- `src/lib/config/` — ConfigManager, modelProviders
**API:**
- `GET/POST/PUT/DELETE /chats`
- `GET/POST/PUT/DELETE /chats/:id`
- `GET/POST/PUT/DELETE /messages`
- `GET/POST /config`
- `GET/POST /config/providers`
**База:** SQLite (или PostgreSQL при масштабировании). config.json можно мигрировать в ту же БД или отдельную таблицу.
---
### 3.8 LLM Proxy Service (опционально)
**Назначение:** Единая точка для вызовов LLM и embedding — OpenAI, Anthropic, Ollama, Groq, Gemini и т.д.
**Исходники:**
- `src/lib/models/` — registry, providers, base LLM/Embedding
**API:**
- `POST /chat` — text generation (streaming)
- `POST /embed` — embedding
- `GET /providers` — список провайдеров и моделей
**Конфигурация:** Берёт из Storage Service (config/providers) или env.
**Альтернатива:** LLM Proxy можно не выделять в отдельный сервис — каждый сервис (Chat, Research, Uploads) сам подключается к провайдерам. Но тогда дублирование кода и конфигурации. Рекомендуется вынести в общую библиотеку или отдельный сервис.
---
## 4. Матрица зависимостей
| Сервис | От кого получает вызовы | Кого вызывает |
|-------------|----------------------------------|----------------------------------|
| Gateway | Frontend | Chat, Storage, Uploads, Search |
| Chat | Gateway | Research, LLM Proxy, Storage |
| Research | Chat | Search, Uploads, LLM Proxy |
| Search | Research, Chat (media) | SearXNG (внешний) |
| Uploads | Gateway, Research | LLM Proxy (embedding) |
| Storage | Gateway, Chat | — |
| LLM Proxy | Chat, Research, Uploads | OpenAI, Anthropic, Ollama... |
---
## 5. Разбиение по репозиториям/папкам
### Вариант A: Монорепо (рекомендуется для старта)
```
gooseek/
├── apps/
│ ├── frontend/ # Next.js UI
│ ├── gateway/ # BFF / API Gateway
│ ├── chat-service/ # SearchAgent, classifier, writer, widgets
│ ├── research-service/ # Researcher, actions
│ ├── search-service/ # SearXNG wrapper
│ ├── uploads-service/ # UploadManager, UploadStore
│ ├── storage-service/ # DB, config
│ └── llm-proxy/ # Models registry, providers
├── packages/
│ ├── shared-types/ # Общие типы, DTO
│ └── shared-utils/ # formatHistory, splitText, computeSimilarity
├── docker-compose.yaml
└── package.json # Turborepo/nx workspace
```
### Вариант B: polyrepo
Отдельные репозитории для каждого сервиса. Больше гибкости в деплое, но сложнее координация изменений.
---
## 6. Порядок миграции (фазы)
### Фаза 1: Выделение Search Service
- Обернуть SearXNG в отдельный сервис
- Chat/Research вызывают его по HTTP вместо прямого импорта `searchSearxng`
- **Риск:** Низкий. SearXNG уже внешний.
### Фаза 2: Выделение Storage Service
- Вынести DB + config в отдельный сервис
- Gateway и Chat переходят на HTTP к Storage
- **Риск:** Средний. Много точек входа в DB.
### Фаза 3: Выделение Uploads Service
- Вынести UploadManager + UploadStore
- Research (uploadsSearch action) и Gateway вызывают Uploads по HTTP
- **Риск:** Средний. Embedding модель — зависимость.
### Фаза 4: Выделение LLM Proxy
- Общая обёртка над провайдерами
- Chat, Research, Uploads вызывают LLM Proxy
- **Риск:** Высокий. Много мест используют LLM напрямую.
### Фаза 5: Выделение Research Service
- Researcher + actions в отдельный сервис
- Chat вызывает Research по одному endpoint «проведи исследование»
- **Риск:** Высокий. Тесная связь с Session, streaming.
### Фаза 6: Gateway + развязка Frontend
- Frontend только UI, все вызовы через Gateway
- Gateway — тонкий роутер без бизнес-логики
- **Риск:** Средний. Рефакторинг API routes.
---
## 7. Ключевые вызовы и риски
1. **Streaming:** Текущий chat stream идёт от SearchAgent до клиента. При разбиении нужно решить: стримить через Gateway (proxy) или от Chat Service напрямую (WebSocket/SSE через Gateway как туннель).
2. **Session/state:** SessionManager — in-memory. При масштабировании Chat Service нужен Redis или аналог для shared state.
3. **Латентность:** Каждый HTTP hop добавляет ~1050ms. Research делает много итераций — если Research в отдельном сервисе, round-trips умножаются.
4. **Embedding в Uploads:** Uploads нужна embedding модель. Варианты: вызывать LLM Proxy, или держать тяжёлую модель (transformers) внутри Uploads.
5. **Конфигурация:** Сейчас config.json на диске. При микросервисах — централизованный config (env, vault, или Storage Service).
---
## 8. Минимальный MVP разбиения
Если цель — не полный microservices, а **модульность и возможность деплоить части отдельно**:
| Сервис | Код | Отдельный процесс |
|---------------|-----------------------------|-------------------|
| **search-api**| `searxng.ts` + route | Да (отдельный порт) |
| **uploads-api**| `uploads/` + route | Да |
| **chat** | Всё остальное (agents, LLM, DB) | Один процесс |
| **frontend** | Next.js UI | Отдельно (static/SSR) |
Так получается 34 контейнера вместо 1, но без глубокой декомпозиции логики.
---
## 9. Следующие шаги
1. Определить: полное разбиение или MVP.
2. Выбрать стек для каждого сервиса (Node.js/Fastify, Next.js API routes, Go и т.д.).
3. Описать контракты API (OpenAPI/JSON Schema) для межсервисного взаимодействия.
4. Настроить docker-compose для локальной разработки.
5. Внедрить общие пакеты (shared-types, shared-utils) в монорепо.
6. Начать с Фазы 1 (Search Service) как пилот.

View File

@@ -1,6 +1,6 @@
# Perplexica Architecture
# GooSeek Architecture
Perplexica is a Next.js application that combines an AI chat experience with search.
GooSeek is a Next.js application that combines an AI chat experience with search.
For a high level flow, see [WORKING.md](WORKING.md). For deeper implementation details, see [CONTRIBUTING.md](../../CONTRIBUTING.md).

View File

@@ -1,6 +1,6 @@
# How Perplexica Works
# How GooSeek Works
This is a high level overview of how Perplexica answers a question.
This is a high level overview of how GooSeek answers a question.
If you want a component level overview, see [README.md](README.md).
@@ -58,7 +58,7 @@ We prompt the model to cite the references it used. The UI then renders those ci
## Search API
If you are integrating Perplexica into another product, you can call `POST /api/search`.
If you are integrating GooSeek into another product, you can call `POST /api/search`.
It returns: