# Content-atom: Implementation Plan > **For Hermes:** roadmap-план по этапам (MVP → V2 → V3). Реализация — по этапам, не все сразу. **Goal:** Атомарный контент-конвейер — атом смысла как источник правды, каналы переупаковывают атомы вместо переписывания статей. **Architecture:** Все стадии работают с `atom_id` вместо `articleIds`. `extract` разбирает статью на типизированные атомы, все 6 слоёв editor-pro привязываются к атому, `atom_versions` переупаковывают атом под каналы, `compositions` собирают выходы, `panel` показывает дашборд смысла. **Tech Stack:** Python (editor-pro, neurogeo), TypeScript (content-pipeline, panel), Qdrant (эмбеддинги), Memgraph/AGE (граф, опционально), FastAPI (панель), Qwen 35B (локальный). --- ## Контекст и предположения ### Что уже есть - **editor-pro** — 6-слойный конвейер (typo → LLM → enrich → GEO → interlink → astro-seo), работает со статьёй. Стек: Python, spaCy, httpx, neo4j (Memgraph), PennyLane (QAOA). Модель: Qwen 35B. - **NeuroGEO** — GEO-скоринг целой статьи, FastAPI на :8009. - **content-pipeline** — TS-оркестратор (`generate → optimize → publish`) + CMS-слой для управления публикациями. Работает с объектом `Article`. - **Qdrant** — эмбеддинги уже используются (qdrant_save.py). - **Memgraph** — для интрелинки. ### Что меняем - Article → atom. Новая стадия `extract` в начале конвейера. - Все стадии привязываются к `atom_id` вместо `articleIds`. - `atom_versions` — переупаковка одного атома под каналы. - `compositions` — сборка выходов (статья/TG/видео). - `panel` — дашборд смысла вместо списка статей. ### Что НЕ тащим сразу - Postgres + pgvector — Qdrant для эмбеддингов, атомы в том, что уже стоит. - Graph (Memgraph/AGE) — только V4, когда атомы отработают. - Адаптеры TG/видео — V3, когда web-канал стабилен. --- ## Дорожная карта ### Этап 1 — MVP: атомы + переупаковка (web-канал) **Цель:** `extract` разбирает статью на атомы, `atom_versions` переупаковывают под web. - **atoms** — типизированные атомы (claim/fact/stat/qa/comparison/hook/cta и др.), body по типам (JSONB). - **atom_versions** — версии под каналы (web_article | telegram | youtube_script | podcast | newsletter | service_card). - **extract** — стадия: статья → типизированные атомы. - **jobs/runs** — задачи пайплайна + стоимость/качество на каждый запуск. - **Qdrant** — эмбеддинги атомов для дедупликации. **KPI:** 4 домена (orabota, ipoteka-ufa, ufa-kvartira, rabota-ufa), один канал (web). ### Этап 2 — связи + композиции (второй канал: Telegram) **Цель:** дедупликация между доменами, сборка выходов. - **atom_relations** — связи (supports/contradicts/expands/example_of/part_of/derived_from). - **compositions** — рецепты сборки (типы, темы, порядок), atom_ids. - **prompts** — промпты как данные (версионирование, A/B). - **Дедупликация** — embedding + atom_relations вместо дублирования статей. **KPI:** 2 канала (web + Telegram), дедup между доменами. ### Этап 3 — медиа + метрики (видео, подкаст, рассылка) **Цель:** сквозная аналитика от смысла до метрики. - **assets** — медиа-активы (image | audio | video | subtitle), транскрипты. - **atom_assets** — привязка атомов к медиа. - **publications** — публикации (URL/channel_id/external_id) + метрики (views/clicks/conversions/revenue). - **Адаптеры** — видео-сценарий, подкаст, рассылка. **KPI:** 4+ канала, сквозная аналитика. ### Этап 4 — граф (Memgraph / Apache AGE) **Цель:** обходы и анализ связей. - Проекция: Atom → Topic → Entity → Project → Asset. - graph_outbox — Postgres → воркер → Memgraph (только id + минимальные атрибуты, тело атома НЕ хранится). - Идемпотентные операции (MERGE по id), ребилд из Postgres за час. - Сборка через обходы графа (топологическая сортировка). **KPI:** граф-проекция, сборка через обходы. ### Этап 5 — панель (дашборд смысла) **Цель:** управление атомами вместо статей. - Дашборд: атомы по доменам, статусы (draft → enriched → edited → approved → published), версии под каналы. - Стоимость на атом + runs — юнит-экономика по домену. - Дедупликация по embedding. - Composition builder — сборка выходов. **KPI:** панель управляет атомами, юнит-экономика по домену. --- ## Схемы данных ### Атомы ```sql CREATE TABLE atoms ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id UUID REFERENCES projects(id) ON DELETE CASCADE, type TEXT NOT NULL, -- claim | fact | stat | quote | definition | instruction | case | comparison | qa | opinion | hook | transition | cta | media_ref status TEXT NOT NULL DEFAULT 'draft', -- draft | enriched | edited | approved | published | archived title TEXT, summary TEXT, body JSONB NOT NULL, -- типизированное тело по типу атома plain_text TEXT, language TEXT DEFAULT 'ru', entities JSONB DEFAULT '[]', topics TEXT[] DEFAULT '{}', intent TEXT, audience TEXT, confidence NUMERIC(3,2), quality_score NUMERIC(4,2), readability NUMERIC(5,2), word_count INT, source_refs JSONB DEFAULT '[]', embedding VECTOR(1024), generator JSONB, cost JSONB, pipeline_stage TEXT, parent_atom_id UUID, lineage_root_id UUID, created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now() ); ``` ### atom_versions ```sql CREATE TABLE atom_versions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), atom_id UUID REFERENCES atoms(id) ON DELETE CASCADE, channel TEXT NOT NULL, -- web_article | telegram | youtube_script | podcast | newsletter | service_card format TEXT NOT NULL, -- markdown | html | plain | srt | ssml | json content TEXT NOT NULL, meta JSONB DEFAULT '{}', quality_score NUMERIC(4,2), created_at TIMESTAMPTZ DEFAULT now(), UNIQUE (atom_id, channel, format) ); ``` ### atom_relations ```sql CREATE TABLE atom_relations ( from_id UUID REFERENCES atoms(id) ON DELETE CASCADE, to_id UUID REFERENCES atoms(id) ON DELETE CASCADE, kind TEXT NOT NULL, -- supports | contradicts | expands | example_of | part_of | refutes | precedes | derived_from weight NUMERIC(3,2) DEFAULT 1.0, meta JSONB DEFAULT '{}', PRIMARY KEY (from_id, to_id, kind) ); ``` ### compositions ```sql CREATE TABLE compositions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_id UUID REFERENCES projects(id) ON DELETE CASCADE, channel TEXT NOT NULL, slug TEXT, title TEXT, status TEXT DEFAULT 'draft', -- draft | building | ready | scheduled | published recipe JSONB NOT NULL, -- правила сборки: типы, темы, порядок atom_ids UUID[] NOT NULL, -- порядок атомов в композиции content TEXT, meta JSONB DEFAULT '{}', scheduled_at TIMESTAMPTZ, published_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT now(), UNIQUE (project_id, channel, slug) ); ``` ### publications ```sql CREATE TABLE publications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), composition_id UUID REFERENCES compositions(id) ON DELETE CASCADE, target TEXT NOT NULL, -- URL, channel_id, video_id external_id TEXT, published_at TIMESTAMPTZ DEFAULT now(), metrics JSONB DEFAULT '{}' -- views, clicks, conversions, revenue ); ``` ### jobs + runs ```sql CREATE TABLE jobs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), kind TEXT NOT NULL, -- generate | edit | adapt | publish | index atom_id UUID REFERENCES atoms(id), composition_id UUID REFERENCES compositions(id), status TEXT DEFAULT 'queued',-- queued | running | done | failed | dead attempts INT DEFAULT 0, max_attempts INT DEFAULT 3, payload JSONB DEFAULT '{}', error TEXT, scheduled_at TIMESTAMPTZ DEFAULT now(), started_at TIMESTAMPTZ, finished_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT now() ); CREATE TABLE runs ( id BIGSERIAL PRIMARY KEY, job_id UUID REFERENCES jobs(id) ON DELETE CASCADE, stage TEXT NOT NULL, model TEXT, prompt_id UUID REFERENCES prompts(id), tokens_in INT, tokens_out INT, seconds NUMERIC, cost_usd NUMERIC DEFAULT 0, quality NUMERIC(4,2), created_at TIMESTAMPTZ DEFAULT now() ); ``` --- ## Интеграция с текущими сервисами ### editor-pro (все 6 слоёв) - Привязать каждый слой к `atom_id` вместо обработки статьи целиком. - `extract` — новая стадия: `python -m editor_pro.main --extract` → атомы. - Все слои работают с кластером атомов, не с одной статьёй. ### neurogeo - GEO-скоринг на кластере атомов, не на статье. - Цитируемость на атоме (fact/stat/claim). ### content-pipeline (TS) - Новый шаг `extract` в `DEFAULT_PIPELINE`. - `atomId` вместо `articleIds`. - `atom_versions` — переупаковка под каналы. ### Qdrant - Эмбеддинги атомов (уже используется). - Дедупликация по embedding + atom_relations. ### Memgraph (V4) - Проекция: Atom → Topic → Entity → Project. - graph_outbox: Postgres → воркер → Memgraph. --- ## Панель (дашборд смысла) **Стек:** FastAPI + SQLite/Postgres + React/Vue (или Astro для единого со стэком). **Разделы:** - Атомы по доменам (orabota, ipoteka-ufa, ufa-kvartira, rabota-ufa). - Статусы атомов (draft → enriched → edited → approved → published). - Версии под каналы (web/TG/видео). - Стоимость на атом + runs — юнит-экономика по домену. - Дедупликация по embedding. - Composition builder — сборка выходов. **KPI:** панель управляет атомами, юнит-экономика по домену. --- ## Правила - Каждая стадия не зависит от предыдущих напрямую — только через атом. - Промпты тянутся из `prompts` по `slug + version`. - Все запуски пишутся в `runs` — воспроизводимость и аналитика. - Идемпотентность через `(atom_id, stage, prompt_id, input_hash)`. - Ошибки → `jobs.error`, ретраи с экспоненциальной задержкой. - После `max_attempts` — статус `dead`, требует ручного вмешательства. --- ## Антипаттерны (из концепции) - Хранить готовый HTML в атоме. - Перезаписывать атом под канал. - Промпты в коде, а не в БД. - Один промпт на все проекты. - Масштабировать на 50 доменов до юнит-экономики. - Граф без ребилда из Postgres. - Публикация без `compositions` (нельзя пересобрать). - Метрики только на уровне сайта, не атома/композиции. --- ## Что даёт такая архитектура | Возможность | Как достигается | |---|---| | Мультиканальность без переписывания | `atom_versions` + `compositions` | | Дедупликация | `embedding` + `atom_relations` | | Полное покрытие темы | граф связей + рецепты сборки | | Сквозная аналитика | `publications.metrics` + `runs` | | Воспроизводимость | `prompts` как данные + `runs` | | Масштабирование на N доменов | `projects` + общий движок | | Избежание footprint | разные шаблоны, ритмы, промпты | | Стоимость и юнит-экономика | `cost` на атом + `runs` | | Защита от обновлений | обновляешь атом → все производные пересобираются | | Продажа частями | композиции и проекты изолированы | --- ## Открытые вопросы 1. **Хранение атомов:** Postgres (как в концепции) или уже есть Postgres? Qdrant только для эмбеддингов. 2. **Панель:** FastAPI + React (отдельно) или Astro (единый стэк)? 3. **V4 граф:** Memgraph или Apache AGE (если Postgres)? 4. **Эмбеддинги:** какая модель (embed-ru, multilingual, локальная)? 5. **Приоритет доменов:** 4 домена (orabota, ipoteka-ufa, ufa-kvartira, rabota-ufa) или начать с одного? --- *Версия 1.0 — roadmap по этапам. Детальные задачи (TDD) — на этапе реализации каждого уровня.*