Files
gitrusprusandCursor 3f9dc6643b Add reusable LLM parser profiles with multi-event extract.
Support kind=llm profiles (instruction/schema), optional multi-event posts via #eN URLs, and recover stale running/queued parse jobs after worker crashes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 20:22:38 +03:00

4.6 KiB

Contracts — общие схемы

Каталог contracts/ — shared truth для формы данных и маршрутизации между ЦА и ЦП.

Правило платформы: сначала contracts, потом реализация в CA/CP/UI.


Модули

Файл Назначение
jobs.py Контракт задания. Payload задания в Redis
ingest.py Контракт результата. Событие и пакет ingest
sources.py Контракт настроек парсера. Схемы source_config по source_type
queues.py Контракт доставки задания нужному воркеру. source_type → family → Redis key
heuristic_profile.py Статичные правила extract_mode=profile
llm_profile.py Reusable LLM instruction/schema + required_fields + multi_event

ЦА при admin CRUD валидирует конфиг через parse_source_config.
ЦП адаптеры должны отдавать dict, совместимые с IngestEventItem.

На практике CA дублирует часть DTO в app/schemas.py для FastAPI; при изменении формы сверяйте оба места и UI.


JobPayload (jobs.py)

class JobPayload(BaseModel):
    job_id: int
    source_type: str
    source_config: dict = {}

Уходит в Redis как JSON. Семейство очереди выбирается по source_type, не по содержимому config.


Ingest (ingest.py)

Ключевые поля IngestEventItem:

Поле Обязательность Заметка
source_url да Стабильный URL; дедуп в ЦА
source_type да (часто default) Должен соответствовать адаптеру
raw_text / title / description нет Текст события
latitude / longitude нет Без них точка на карту не создаётся
event_date, locality, region, topic нет Фильтры карты и ПИ
tags, metadata нет Расширения

Пакет: { job_id?, events: [...] }.
Listener добавляет флаг listener: true на стороне CA API (см. internal schemas).


Source config (sources.py)

source_type Модель Главные поля
telegram TelegramSourceConfig channel, limit, extract_mode (heuristic|llm|profile), heuristic_profile, extract_schema, instruction, required_fields (llm gate)
crawl4ai Crawl4AISourceConfig urls, extract_mode, extract_schema, domain_profile
viina ViinaSourceConfig urls / texts, input_mode

Реестр: CONFIG_MODELS + parse_source_config(source_type, raw).

Профили в БД ЦА (ParserProfile):

kind Хранилище Flatten в Redis
heuristic heuristic_profile (contracts/heuristic_profile.py) extract_mode=profile
llm llm_profile (contracts/llm_profile.py: instruction, extract_schema, required_fields, multi_event) extract_mode=llm (+ #eN URLs if multi)

required_fields — обязательные поля; пустой список = без фильтра (для llm остаётся только is_event). Канал + профиль живут в ЦА; CP получает только плоский source_config.


Очереди (queues.py)

SOURCE_FAMILY = {
  "telegram": "telegram",  # cp:jobs:telegram
  "crawl4ai": "web",       # cp:jobs:web
  "viina": "nlp",          # cp:jobs:nlp
}
  • queue_key_for_source(source_type) — куда enqueue из ЦА.
  • Legacy-ключ cp:jobs ещё может дренироваться telegram-воркерами (совместимость).

При добавлении нового source_type обязательно:

  1. схема в sources.py;
  2. запись в SOURCE_FAMILY;
  3. адаптер + registry + (при необходимости) новый Docker-сервис;
  4. поля формы в ParsersView.vue.

Чеклист: .cursor/skills/add-parser-adapter/.