Files
gooseek/docs/architecture/MICROSERVICES.md
home f4d945a2b5 feat: localization service and frontend integration
- Add localization-service microservice (locale resolution, translations)
- Add frontend API routes /api/locale and /api/translations/[locale]
- Add LocalizationProvider and localization context
- Integrate localization into layout, EmptyChat, MessageInput components
- Update MICROSERVICES.md architecture docs
- Add localization-service to workspaces

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-20 21:45:44 +03:00

22 KiB
Raw Blame History

Архитектура микросервисов 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) сам подключается к провайдерам. Но тогда дублирование кода и конфигурации. Рекомендуется вынести в общую библиотеку или отдельный сервис.


3.9 Geo Device Service (реализован)

Назначение: Определение геопозиции пользователя, типа устройства, браузера и ОС.

Расположение: apps/geo-device-service/

API:

  • GET /api/context — контекст по IP и заголовкам (User-Agent, Accept-Language)
  • POST /api/context — контекст с дополнительными данными от клиента (screen, timezone, Geolocation API)

Данные:

  • geo — latitude, longitude, city, country, timezone (geoip-lite по IP или из body)
  • device — type (desktop/mobile/tablet), vendor, model
  • browser — name, version (ua-parser-js)
  • os — name, version
  • client — screenWidth, viewportHeight, timezone, language, hardwareConcurrency, deviceMemory, doNotTrack (из POST body)

Запуск: npm run dev:geo или PORT=4002 npm run start -w geo-device-service

Интеграция: Frontend вызывает /api/geo-context (проксирует к сервису), клиент — fetchContextWithClient() из @/lib/geoDevice.


3.10 Localization Service (реализован)

Назначение: Локализация на основе геопозиции. Определяет locale (язык) пользователя по данным из Geo Device Service.

Расположение: apps/localization-service/

Зависимость: Geo Device Service (вызывает /api/context для получения countryCode, client.language, Accept-Language).

API:

  • GET /api/locale — resolve locale по IP/заголовкам (гео через geo-device-service)
  • POST /api/locale — resolve locale с client data (screen, language, geo)
  • GET /api/translations/:locale — переводы для UI
  • GET /api/locales — список поддерживаемых локалей

Данные (LocalizationContext):

  • locale — BCP 47 language code (ru, en, de, ...)
  • source — geo | accept-language | client | fallback

Приоритет определения locale:

  1. client.language (браузер navigator.language)
  2. Accept-Language заголовок
  3. countryCode из геопозиции
  4. fallback: en

Запуск: npm run dev:locale или PORT=4003 npm run start -w localization-service

Конфигурация: GEO_DEVICE_SERVICE_URL — URL geo-device-service (по умолчанию http://localhost:4002)

Интеграция: Frontend вызывает /api/locale, /api/translations/[locale] (проксирует к сервису), клиент — fetchLocaleWithClient(), fetchTranslations() из @/lib/localization.


4. Матрица зависимостей

Сервис От кого получает вызовы Кого вызывает
Gateway Frontend Chat, Storage, Uploads, Search
Localization Frontend Geo Device Service
Geo Device Frontend, Localization
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
│   ├── geo-device-service/   # Геопозиция, устройство, браузер
│   ├── localization-service/ # Локализация (зависит от geo-device)
│   ├── 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) как пилот.