393 lines
16 KiB
Markdown
393 lines
16 KiB
Markdown
|
|
# 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 0–100%).
|
|||
|
|
|
|||
|
|
### 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.*
|