ASM_PNS_C/Specyfikacja-procesu-AI.md
majkarol cd292e3198 Inicjalizacja repozytorium: koncepcja platformy AdReactions + specyfikacja AI
Zawartość:
- Koncepcja 0.1 oraz rozszerzona Koncepcja 0.2 (model domenowy, architektura,
  mapowanie cel→metryki→usługi AI, wymienialność modeli, model danych)
- Katalog 15 celów analiz kognitywnych
- Specyfikacja procesu AI + opis procesów źródłowych
- Pytania do koncepcji
- Materiały źródłowe: info.md, n8n.json

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 22:03:32 +02:00

392 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Specyfikacja procesu: analiza uwagi wzrokowej kreacji reklamowych
> Opis **logiki procesu** niezależny od narzędzia orkiestrującego, przeznaczony do
> implementacji jako komponent oprogramowania (np. usługa backendowa / pipeline).
> Definiuje: dane wejściowe, kontrakty zewnętrznych usług AI, kolejność i równoległość
> wywołań, model danych wynikowych oraz logikę prezentacji.
---
## 1. Cel i zakres
System przyjmuje **pojedynczy obraz** (kreację reklamową / grafikę) i zwraca zestaw analiz:
1. **Rozumienie zawartości** — jakie obiekty są na obrazie i gdzie się znajdują.
2. **Predykcja uwagi wzrokowej (saliency)** — gdzie skupi się wzrok odbiorcy; trzy
niezależne modele dla walidacji krzyżowej.
Wynikiem są dane (lista obiektów z ramkami, mapy uwagi) oraz pochodne wizualizacje.
Proces jest **bezstanowy** — jedno wejście (obraz) → jeden komplet wyników.
---
## 2. Architektura logiczna
```
┌────────────────────┐
│ Wejście: obraz │
└─────────┬──────────┘
┌────────────────────┐
│ Preprocessing │ bytes + base64 + mime + (w,h)
└─────────┬──────────┘
┌──────────────┼───────────────┬───────────────┬───────────────┐
▼ (łańcuch A) ▼ (B) ▼ (C) ▼ (D)
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ LLaVA │ │ DeepGaze │ │ UNISAL │ │ ASM │
│ (etykiety)│ │(saliency)│ │(saliency)│ │(2× saliency)
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
▼ │ │ │
┌──────────────┐ │ │ │
│ Grounding │ │ │ │
│ DINO (boxy) │ │ │ │
└────┬─────────┘ │ │ │
│ ▼ ▼ ▼
▼ ┌──────────────────────────────────────┐
┌──────────────┐ │ Agregacja wyników saliency │
│ Wynik: │ └──────────────────┬───────────────────┘
│ detekcja │ ▼
└──────────────┘ ┌──────────────────────────┐
│ Artefakty wyjściowe: │
│ • overlay boxów │
│ • nakładka heatmapy │
│ • porównanie 2×2 │
└──────────────────────────┘
```
**Kluczowe zależności:**
- **Łańcuch A jest sekwencyjny:** Grounding DINO potrzebuje etykiet z LLaVA.
- **Zadania B, C, D oraz cały łańcuch A są względem siebie niezależne** → wykonywane równolegle.
- Punkt agregacji czeka na zakończenie wymaganych zadań przed złożeniem danego artefaktu.
---
## 3. Dane wejściowe i preprocessing
**Wejście:** plik graficzny (PNG lub JPEG).
**Preprocessing** — z jednego uploadu przygotuj reprezentację współdzieloną przez wszystkie usługi:
```
ImageInput {
bytes : binary // oryginalne bajty pliku (do multipart/form-data)
base64 : string // base64 bez prefiksu data: (do osadzania i obliczeń)
mime : "image/png" | "image/jpeg"
width : int
height : int
}
```
- `mime`, `width`, `height` ustal **standardową biblioteką** do obrazów
(np. Pillow / `image-size` / `sharp`).
> Uwaga: pierwotna implementacja parsowała nagłówki ręcznie (PNG: `width@offset16`,
> `height@offset20` jako uint32 BE; JPEG: skan markerów `SOF0 0xC0` / `SOF2 0xC2`).
> W docelowym kodzie użyj gotowej biblioteki — wymiary i tak są potrzebne tylko do
> pozycjonowania ramek i renderowania (sekcja 7).
- `base64` służy do: (a) osadzania oryginału w wizualizacjach, (b) blendu pikselowego.
- `bytes` służy do wszystkich wywołań usług (pole multipart `image` lub `file`).
---
## 4. Wewnętrzny model danych (wyników)
```
DetectionResult {
objects : [ { object_type: string,
bbox_xyxy: [x1, y1, x2, y2], // piksele, układ XYXY
score: float } ] // 0..1
model_id? : string
threshold? : float
}
SaliencyMap {
source : "deepgaze" | "unisal" | "asm_detailed" | "asm_general"
image_base64 : string
mime : string
}
AnalysisResult {
image : ImageInput
detection : DetectionResult
saliency : SaliencyMap[] // 4 pozycje: deepgaze, unisal, asm_detailed, asm_general
}
```
---
## 5. Zewnętrzne usługi AI — kontrakty API
Wszystkie usługi to **HTTP POST** z ciałem `multipart/form-data` zawierającym obraz.
Adresy hostów i token pochodzą z konfiguracji / magazynu sekretów (sekcja 8).
Każde wywołanie powinno mieć skończony **timeout** i być **odporne na błędy** (sekcja 9).
Kształty odpowiedzi oznaczone „(wnioskowane)" odtworzono na podstawie sposobu konsumpcji
danych — przy implementacji potwierdź je z dokumentacją/realnymi odpowiedziami usług.
### 5.1. LLaVA — ekstrakcja typów obiektów
Multimodalny model wizualno-językowy; zwraca listę kategorii obiektów widocznych na obrazie.
```
POST http://{LLAVA_HOST}/llava-api/v1/get-object-types
Headers:
accept: application/json
Authorization: Bearer {TOKEN}
Body (multipart/form-data):
temperature = 0.2 // niska → powtarzalność
top_p = 0.9
image = <plik>
Odpowiedź (wnioskowane):
{ "labels": ["person", "bottle", "logo", ...] }
```
**Transformacja po stronie klienta:** połącz `labels` w jeden ciąg rozdzielony przecinkami
(`"person, bottle, logo"`) — wejście dla Grounding DINO.
### 5.2. Grounding DINO — detekcja obiektów (bounding boxy)
Otwarto-zbiorowa (zero-shot) detekcja sterowana tekstem: dla podanych etykiet zwraca ramki.
```
POST http://{GROUNDING_DINO_HOST}/grounding-dino-api/v1/get-objects-bboxes
Headers:
accept: application/json
Authorization: Bearer {TOKEN}
Body (multipart/form-data):
object_types = "{labels_z_LLaVA}" // np. "person, bottle, logo"
max_objects = 50
base64 = false
image = <plik>
Odpowiedź (wnioskowane):
{
"objects_bboxes": [
{ "object_type": "logo",
"bbox_coords_xyxy": [x1, y1, x2, y2],
"score": 0.87 }
],
"model_id": "...", // opcjonalnie
"threshold": 0.3, // opcjonalnie
"width": 839, // opcjonalnie (fallback wymiarów)
"height": 1190
}
```
### 5.3. DeepGaze — mapa uwagi (saliency)
Predykcja rozkładu uwagi wzrokowej; zwraca heatmapę zakodowaną base64.
```
POST http://{DEEPGAZE_HOST}/v1/predict-heatmap
Headers:
accept: application/json
Authorization: Bearer {TOKEN}
Body (multipart/form-data):
image = <plik>
Odpowiedź (wnioskowane):
{ "heatmap_b64": "<base64>",
"heatmap_mime": "image/png",
"width": 839, "height": 1190,
"model": "deepgaze..." }
```
→ mapuj na `SaliencyMap{ source:"deepgaze", image_base64:heatmap_b64, mime:heatmap_mime }`.
### 5.4. UNISAL — mapa uwagi (saliency, model porównawczy)
```
POST http://{UNISAL_HOST}/unisal/process-image?as_base64=true
Headers:
accept: application/json
X-API-Key: {TOKEN}
Body (multipart/form-data):
file = <plik>
Odpowiedź (wnioskowane):
{ "data": "<base64>", "mimetype": "image/jpeg" }
```
`SaliencyMap{ source:"unisal", image_base64:data, mime:mimetype }`.
### 5.5. ASM (asmModel) — mapy uwagi z warunkowaniem promptem
Model centralny: zwraca **dwie** mapy uwagi (szczegółową i ogólną), warunkowane tekstowym
promptem osadzającym kontekst marketingowy.
```
POST http://{ASM_HOST}/asmModel/process-image
?prompt=Describe the image in the style of a polished marketing ad.
&as_raw_output=false
&max_new_tokens=100
Headers:
accept: application/json
X-API-Key: {TOKEN}
Body (multipart/form-data):
file = <plik>
Odpowiedź (wnioskowane):
{ "image_detailed": "<base64>",
"image_general": "<base64>",
"mimetype": "image/jpeg" }
```
→ dwa wpisy: `SaliencyMap{source:"asm_detailed",...}` oraz `SaliencyMap{source:"asm_general",...}`.
> **Uwaga:** architektura ASM nie wynika z kontraktu — to wewnętrzny mikroserwis.
> `prompt` i `max_new_tokens` sugerują model multimodalny warunkowany językiem.
> Prompt potraktuj jako **parametr konfigurowalny**, nie stałą.
---
## 6. Orkiestracja
Logika sterująca (zastępuje przepływ narzędzia) — uruchom niezależne gałęzie równolegle,
zachowując jedyną zależność LLaVA → Grounding DINO.
```python
async def analyze(image_bytes) -> AnalysisResult:
img = preprocess(image_bytes) # bytes, base64, mime, w, h
async def detection_chain():
labels = await llava_object_types(img.bytes) # 5.1
labels_str = ", ".join(labels)
return await grounding_dino(img.bytes, labels_str) # 5.2
# gałęzie niezależne — równolegle
detection, deepgaze, unisal, asm = await gather(
detection_chain(), # łańcuch A (sekwencyjny wewnątrz)
deepgaze_heatmap(img.bytes), # B
unisal_saliency(img.bytes), # C
asm_saliency(img.bytes, PROMPT), # D
return_exceptions=True, # patrz sekcja 9
)
saliency = [
SaliencyMap("deepgaze", deepgaze.heatmap_b64, deepgaze.heatmap_mime),
SaliencyMap("unisal", unisal.data, unisal.mimetype),
SaliencyMap("asm_detailed", asm.image_detailed, asm.mimetype),
SaliencyMap("asm_general", asm.image_general, asm.mimetype),
]
return AnalysisResult(img, detection, saliency)
```
**Zasady:**
- Cztery gałęzie startują jednocześnie; całkowity czas ≈ czas najwolniejszej gałęzi.
- Punkt agregacji łączy wyniki dopiero, gdy potrzebne gałęzie się zakończą.
- Każdy artefakt wyjściowy zależy od konkretnego podzbioru wyników (sekcja 7) — można je
generować, gdy tylko jego zależności są gotowe.
---
## 7. Warstwa prezentacji (artefakty wyjściowe)
Trzy artefakty. Można je renderować **po stronie klienta** (HTML/Canvas — jak w oryginale)
lub **serwerowo** komponować obrazy (Pillow / sharp / canvas). Poniżej logika niezależna od wyboru.
### 7.1. Wizualizacja detekcji obiektów
**Zależności:** oryginał + `DetectionResult`.
- Dla każdego obiektu narysuj ramkę z `bbox_xyxy`, podpis `"{object_type} {score%}"`.
- Kolor per typ obiektu (paleta cykliczna; ten sam typ = ten sam kolor).
- Pozycje przeliczaj na **procenty** wymiarów obrazu (`x1/width`, `y1/height`, …),
aby skalowały się responsywnie.
- Opcjonalnie: filtry pokazujące/ukrywające typy, legenda, licznik obiektów.
### 7.2. Nakładka pojedynczej mapy uwagi
**Zależności:** oryginał + jedna `SaliencyMap` (np. DeepGaze).
- Heatmapa nałożona na oryginał z **regulowaną przezroczystością** (suwak 0100%).
### 7.3. Porównanie map uwagi (siatka 2×2)
**Zależności:** oryginał + 4 mapy (`deepgaze`, `unisal`, `asm_detailed`, `asm_general`).
- Cztery kafelki, wspólny suwak intensywności, technika „inwersji" (7.4).
### 7.4. Algorytm „inwersji" heatmapy (blend luminancji)
Wspólna logika nakładek. Dla parametru `t ∈ [0,1]` (intensywność / pozycja suwaka):
```
# Z heatmapy licz luminancję (jasność uwagi) 0..1:
lum = (0.299*R + 0.587*G + 0.114*B) / 255
# Blend per kanał (RGB), per piksel:
out = orig * (1 - t) + (lum * 255) * t
```
- `t = 0` → czysty oryginał; `t = 1` → maska uwagi w skali szarości
(biel = wysoka uwaga, czerń = niska) → efekt „reflektora".
- Wymaga zgodności rozdzielczości oryginału i heatmapy (w razie potrzeby przeskaluj heatmapę).
---
## 8. Konfiguracja i sekrety
Wynieś poza kod (zmienne środowiskowe / vault):
| Klucz | Opis |
|---|---|
| `LLAVA_HOST` | host usługi LLaVA |
| `GROUNDING_DINO_HOST` | host usługi Grounding DINO |
| `DEEPGAZE_HOST` | host usługi DeepGaze |
| `UNISAL_HOST` | host usługi UNISAL (w oryginale `1.208.108.242:58951`) |
| `ASM_HOST` | host usługi ASM (w oryginale ten sam host co UNISAL) |
| `TOKEN` | poświadczenie (Bearer dla LLaVA/DINO/DeepGaze; `X-API-Key` dla UNISAL/ASM) |
| `ASM_PROMPT` | prompt warunkujący ASM (domyślnie marketingowy) |
| `MAX_OBJECTS` | limit detekcji (domyślnie 50) |
> Dwa schematy autoryzacji: **`Authorization: Bearer`** (LLaVA, Grounding DINO, DeepGaze)
> vs **`X-API-Key`** (UNISAL, ASM). Zaimplementuj per usługa.
---
## 9. Obsługa błędów i odporność
W oryginale węzły LLaVA, DeepGaze, UNISAL i ASM były ustawione na **kontynuację mimo błędu**
awaria pojedynczego modelu nie przerywała całości. Odtwórz to:
- **Degradacja stopniowa:** błąd jednej gałęzi → pomiń jej artefakt, zwróć pozostałe
(`return_exceptions` / per-task `try/except`). Nie przerywaj całej analizy.
- **Twarda zależność:** jeśli LLaVA zawiedzie, Grounding DINO nie ma etykiet → pomiń detekcję
(lub fallback: pusta lista / domyślne etykiety), reszta map uwagi działa dalej.
- **Timeouty i retry:** skończony timeout na każde wywołanie; ewentualny retry z backoffem
dla błędów przejściowych (5xx / timeout).
- **Walidacja odpowiedzi:** sprawdzaj obecność kluczy (`labels`, `objects_bboxes`,
`heatmap_b64`, `data`, `image_detailed`/`image_general`) przed użyciem.
- **Zgodność wymiarów:** przy blendzie/overlayu pilnuj zgodności rozdzielczości oryginału i map.
---
## 10. Proponowana dekompozycja modułów
| Moduł | Odpowiedzialność |
|---|---|
| `preprocess` | walidacja pliku, base64, mime, wymiary |
| `clients/` | po jednym kliencie na usługę (LLaVA, GroundingDINO, DeepGaze, UNISAL, ASM); auth, timeout, parsowanie odpowiedzi |
| `orchestrator` | równoległe uruchomienie gałęzi, agregacja, obsługa błędów (sekcja 6, 9) |
| `models` | typy danych (sekcja 4) |
| `render/` | generowanie artefaktów (overlay boxów, nakładka heatmapy, siatka 2×2 + blend) |
| `api`/`cli` | punkt wejścia: przyjmij obraz → zwróć `AnalysisResult` + artefakty |
**Sugerowany stack:** dowolny z natywną asynchronicznością i obsługą `multipart` oraz obrazów —
np. Python (FastAPI + `httpx.AsyncClient` + Pillow) lub Node (Fastify/Express + `undici`/`fetch` + `sharp`).
Renderowanie wizualizacji: serwerowo (kompozycja obrazu) albo zwrot danych + szablon kliencki.
---
## 11. Rozszerzenia (roadmapa)
Pierwotny projekt przewidywał dalsze etapy analizy uwagi (jeszcze niezaimplementowane):
- **Mapa cieplna w interwałach czasowych** (np. „30 s, 6 obrazów", „20 s → 0,5 s") —
saliency rozłożona na przedziały czasu.
- **Ścieżki fiksacji (scanpath)** — przewidywana sekwencja ruchów oka.
- **Mapa emocji** — predykcja reakcji emocjonalnej na kreację.
Architektura z sekcji 6 jest na to przygotowana: dokładaj kolejne niezależne gałęzie do
równoległej orkiestracji i nowe artefakty do warstwy prezentacji.
---
*Specyfikacja odtworzona z istniejącego przepływu przetwarzania; kontrakty odpowiedzi oznaczone*
*„wnioskowane" wymagają potwierdzenia z dokumentacją docelowych usług AI.*