Files
content-atom/README.md
T

313 lines
15 KiB
Markdown

# 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) — на этапе реализации каждого уровня.*