📸 Case Study · Computer Vision · SaaS

GunUpdate — dwa własne modele AI do analizy obrazu produktów sportowo-kolekcjonerskich

Branża sportowo-kolekcjonerska (sport strzelecki, kolekcjonerstwo broni historycznej, ASG, akcesoria sportowe) ma swoją specyfikę: tysiące modeli produktów, setki konfiguracji, wąska wiedza ekspercka. Wybudowaliśmy GunUpdate — platformę SaaS z dwoma własnymi modelami computer vision: pierwszy rozpoznaje produkt i jego części składowe na zdjęciu, drugi rekomenduje kompatybilne akcesoria. To nasz flagowy produkt własny, na którym pokazujemy, co potrafimy.

📅 Styczeń 2026
⏱️ 14 min czytania
🏷️ Computer Vision · SaaS
⚙️ YOLO · CLIP · ViT · własny dataset
2
Własne
modele AI
~85k
Zdjęć
w datasecie
~1.5s
Czas
analizy zdjęcia
SaaS
B2B
multi-tenant

Kontekst — czego brakowało branży

Branża sportowo-kolekcjonerska to specyficzny rynek. Sklep z akcesoriami do sportu strzeleckiego ma w katalogu setki produktów (tłumiki dźwięku do strzelectwa sportowego, kolimatory, lunety, magazynki, kabury, ładownice, futerały, części serwisowe — w pełni legalne w ramach polskich i unijnych przepisów dla osób z odpowiednimi pozwoleniami albo dla rynku ASG/replik). Te produkty mają skomplikowaną kompatybilność. Akcesoria pasują tylko do określonych modeli, montaż wymaga konkretnych standardów (Picatinny, Weaver, dovetail, M-LOK, KeyMod), waga akcesoriów musi być proporcjonalna do platformy, balistyczne tory celownika muszą być spójne z lufą.

Klient końcowy — sportowiec strzelecki, kolekcjoner, strzelec rekreacyjny, gracz ASG — często NIE wie, co dokładnie ma. Robi zdjęcie swojego sprzętu i chce wiedzieć:

Sprzedawca też ma problem: gdy klient przesyła zdjęcie z pytaniem „mam taki sprzęt, co mi polecasz", zatrudniony konsultant musi to rozpoznać manualnie. Doświadczony specjalista — 2-3 minuty. Niedoświadczony — 15 minut researchu lub odsyła do kolegi. Przy 50-100 takich zapytań dziennie, to ogromny koszt obsługi.

„Ja patrzę na zdjęcie i widzę, że to jest replika M4 z handguardem M-LOK, czerwoną kropką typu Vortex Strikefire, magazyn 30-nabojowy, składana kolba. Mój junior salesman patrzy i widzi karabinek. Tygodniami uczę nowych pracowników rozpoznawania modeli. Marzy mi się narzędzie, w które wrzucam zdjęcie i mam pełen rozkład: co to jest, jakie ma akcesoria, jakie polecane uzupełnienia z mojego katalogu." — Właściciel sklepu specjalistycznego, klient pilotażowy GunUpdate

Pozycjonowanie produktu

GunUpdate to nasz produkt własny — nie wdrożenie u klienta, tylko SaaS, który sprzedajemy w modelu subskrypcyjnym sklepom branżowym, klubom sportowym, serwisom kolekcjonerskim. Pozycjonowanie:

⚖️

Compliance — temat poważny i traktowany poważnie

Produkty w branży sportowo-kolekcjonerskiej podlegają specyficznym regulacjom różnym w każdym kraju UE (w Polsce — Ustawa o broni i amunicji + ustawy uzupełniające, w Niemczech — Waffengesetz, etc.). GunUpdate nie omija tych regulacji — wręcz przeciwnie, jest świadomy lokalnego kontekstu i pomaga sklepom oferować produkty zgodnie z prawem. System klasyfikuje produkty jako: dostępne dla każdego, wymagające pozwolenia, wymagające licencji handlowej. Rekomendacje są filtrowane przez deklarowany przez sprzedawcę profil klienta końcowego.

Architektura — dwa modele, jeden pipeline

Core systemu to dwa wytrenowane przez nas modele computer vision oraz warstwa orkiestracji łącząca ich wyjścia z katalogiem produktowym klienta:

M1
Detector & Classifier (DC-Model) Wykrywa produkt na zdjęciu, klasyfikuje typ (karabin sportowy / replika ASG / pistolet sportowy / wiatrówka / akcesorium), identyfikuje konkretny model platformy i wszystkie zamontowane akcesoria z lokalizacją (bounding box).
M2
Compatibility Recommender (CR-Model) Mając rozpoznaną platformę i istniejące akcesoria, rekomenduje kompatybilne uzupełnienia. Bierze pod uwagę: typ montażu, standard rail, kaliber, długość lufy, wagę dotychczasową, gust użytkownika (jeśli ma historię).
O
Orkiestracja (Claude Sonnet 4.6 + katalog klienta) Łączy wyjścia M1 i M2 z katalogiem konkretnego klienta (tenant) i jego polityką cenową. Generuje finalną odpowiedź — listę produktów, opisy, ceny, link do zakupu.
C
Compliance Layer Przed zwróceniem rekomendacji filtruje produkty pod kątem lokalnych regulacji kraju klienta i profilu użytkownika końcowego (klient detaliczny / sport / kolekcja).

Model 1 — Detection & Classification (DC-Model)

Pierwszy z dwóch własnych modeli. Architektura dwustopniowa: szybki detektor lokalizujący obiekty + dokładny klasyfikator do rozpoznawania konkretnego modelu.

Stopień 1 — detektor (YOLOv8)

Wykorzystaliśmy YOLOv8-Medium jako bazę, fine-tunowany na własnym datasecie z 12 klasami obiektów:

YAML · klasy detektora YOLO
# gunupdate_yolo_classes.yaml
names:
  0: platform_long      # karabinek/karabin sportowy, replika ASG długa, wiatrówka
  1: platform_short     # pistolet sportowy, replika ASG krótka, pistolet pneumatyczny
  2: optic_red_dot      # kolimator typu red dot, holosight
  3: optic_scope        # luneta, prismatic
  4: optic_magnifier    # magnifier (powiększacz za kolimatorem)
  5: foregrip           # przedni chwyt
  6: bipod              # dwójnóg
  7: laser_light        # latarka taktyczna, wskaźnik laserowy sportowy
  8: silencer_sport     # tłumik dźwięku (sport, z pozwoleniem)
  9: magazine           # magazynek (różne pojemności i standardy)
  10: stock             # kolba (stała, składana, teleskopowa)
  11: rail_system       # widoczny system montażu Picatinny/M-LOK/KeyMod

Detektor zwraca bounding boxy + confidence + class. Trenowany na ~52 000 zdjęciach, każde ręcznie anotowane (LabelStudio, 3 anotatorów + walidator). Augmentacje: rotacje, zmiany jasności, mosaic mix-up (4 zdjęcia w jedno), random crop.

Python · trening YOLO
from ultralytics import YOLO

model = YOLO('yolov8m.pt')  # base
results = model.train(
    data='gunupdate_dataset.yaml',
    epochs=120,
    imgsz=1024,           # wysoka rozdzielczość — detale akcesoriów
    batch=16,
    optimizer='AdamW',
    lr0=0.001,
    augment=True,
    mosaic=1.0,
    mixup=0.15,
    copy_paste=0.1,
    cls=0.5,              # class loss weight
    box=7.5,              # box loss weight
    device=[0,1,2,3]      # 4× RTX 5090
)

# Walidacja:
# mAP50: 0.91, mAP50-95: 0.72 — bardzo dobry wynik na 12 klasach

Stopień 2 — klasyfikator modelu (Vision Transformer + CLIP)

YOLO mówi nam „to jest platforma długa". Ale klient chce wiedzieć, że to konkretny model w konkretnej konfiguracji. Tu wchodzi drugi model: fine-tunowany Vision Transformer na ~600 klasach produktowych.

Dlaczego ViT, a nie zwykły ResNet? Dwa powody:

  1. Klasyfikacja drobnych różnic — różnica między dwoma podobnymi modelami platformy to często detale na poziomie ułożenia pinów, kształtu osłony. ViT przez self-attention lepiej łapie te subtelności niż konwolucje.
  2. Wykorzystanie CLIP-a — bazą jest CLIP ViT-L/14, który ma pre-trening na 400M par obraz-tekst. Daje nam mocny startowy backbone.
Python · ViT classifier
import torch
from transformers import CLIPVisionModel, CLIPImageProcessor

class GunUpdateClassifier(torch.nn.Module):
    def __init__(self, num_classes=614):
        super().__init__()
        self.backbone = CLIPVisionModel.from_pretrained(
            "openai/clip-vit-large-patch14"
        )
        # Zamrażamy 80% backbone'a, fine-tunujemy tylko ostatnie warstwy
        for param in list(self.backbone.parameters())[:-40]:
            param.requires_grad = False
        
        self.head = torch.nn.Sequential(
            torch.nn.Linear(1024, 512),
            torch.nn.GELU(),
            torch.nn.Dropout(0.2),
            torch.nn.Linear(512, num_classes)
        )
    
    def forward(self, pixel_values):
        outputs = self.backbone(pixel_values=pixel_values)
        pooled = outputs.pooler_output
        return self.head(pooled)

# Dataset: ~33k zdjęć (po wycięciu z YOLO bboxów platform)
# Trening: 80 epoch, AdamW, lr=2e-5, mixed precision bf16
# Wynik: top-1 accuracy 87.3%, top-5 accuracy 96.1%

Dlaczego top-5 a nie top-1? Bo realnie, dla wielu modeli platform sportowo-kolekcjonerskich, nawet człowiek-ekspert nie odróżni dwóch podobnych klonów po jednym zdjęciu. Dlatego naszą metryką sukcesu jest top-5 accuracy: model zwraca 5 najbardziej prawdopodobnych klasyfikacji z procentami, a użytkownik wybiera prawidłową (lub zostawia AI „w niepewności" jeśli żadna nie pasuje). To realistyczny model UX dla branży.

Identyfikacja akcesoriów

Dla każdego akcesorium wykrytego przez YOLO (kolimator, luneta, foregrip, etc.) uruchamiamy mniejsze, specjalizowane klasyfikatory:

M1.2a

Optyka — 120 klas

Klasyfikator kolimatorów i lunet — rozpoznaje markę i model (np. „Vortex Strikefire 2 Red Dot" vs „Aimpoint PRO" vs „Holosun HS510C"). ViT-base + 8k zdjęć treningowych.

M1.2b

Magazynki — 45 klas

Klasyfikator magazynków po standardzie (STANAG, AK, glock-style) i pojemności (10/15/20/30 nabojowy). Często widoczne tylko pod ostrym kątem — augmentacje rotacyjne.

M1.2c

Rail systems — 8 klas

Klasyfikacja widocznego systemu montażu: Picatinny, Weaver, M-LOK, KeyMod, dovetail 11mm, dovetail 3/8", proprietary. Kluczowe dla rekomendacji.

M1.2d

Kolby — 30 klas

Klasyfikator kolb: stałe, składane, teleskopowe, sportowe regulowane. Wpływa na ergonomię i przepisy w niektórych krajach.

Model 2 — Compatibility Recommender (CR-Model)

Drugi z dwóch własnych modeli. To miejsce, gdzie GunUpdate dostaje swoją przewagę konkurencyjną. Bo rozpoznać produkt na zdjęciu — to potrafi (mniej lub bardziej) dziś każdy CLIP. Ale poprawnie zarekomendować, co dokupić, żeby to faktycznie pasowało — to wymaga bardzo specyficznej wiedzy domenowej.

Co to znaczy „kompatybilne"

W tej branży kompatybilność ma wiele wymiarów:

  1. Fizyczna — system montażowy musi się zgadzać (Picatinny rail → tylko montaż Picatinny / M-LOK). Średnice gwintów lufy muszą być zgodne (różne standardy 1/2"-28, 5/8"-24, M14×1).
  2. Wagowa — platforma 3 kg z lekkim handguardem nie pociągnie dwóch kilowych akcesoriów z przodu.
  3. Balistyczna — dla strzelectwa precyzyjnego luneta i kaliber muszą być dobrane do dystansu. Luneta 1-4x nie ma sensu przy lufie 24" do strzelectwa długodystansowego.
  4. Logiczna — nie ma sensu kupować drugiego kolimatora, jeśli jeden już jest. Magnifier ma sens tylko jeśli jest kolimator.
  5. Regulacyjna — niektóre akcesoria w niektórych krajach wymagają osobnych pozwoleń. To filtrowane na warstwie compliance.
  6. Stylistyczna — kolory, wykończenia (czarny / FDE / Cerakote bronze) — drobiazg, ale dla użytkowników się liczy.

Hybryda — embedding-based + reguły

Model CR jest hybrydą:

A
Knowledge Graph kompatybilności Graf w Neo4j — węzły to konkretne produkty (z bazy ~25k SKU w katalogach klientów). Krawędzie: „pasuje fizycznie", „typowo łączone", „kanibalizuje". Twarde reguły zbudowane przez naszego eksperta domenowego.
B
Embedding-based similarity (CLIP) Każdy produkt ma embedding wektorowy (CLIP). Pozwala rekomendować estetycznie pasujące produkty („kupili to, dokupili tamto", podobny styl wykończenia).
C
Collaborative filtering Macierz „co z czym kupowano" zbudowana z anonimizowanych danych transakcyjnych klientów GunUpdate (opt-in). Im więcej tenantów, tym lepiej działa.
D
Re-ranker (cross-encoder) Po zebraniu kandydatów z A+B+C, re-ranker ocenia każdą parę (platforma, kandydat) — zwraca finalny ranking. Trenowany na danych „kliknięcie/zakup po rekomendacji".

Jak działa knowledge graph kompatybilności

Zbudowanie tego grafu zajęło ~4 miesiące. Każdy produkt ma węzeł z atrybutami:

Cypher · schemat KG
// Węzeł produktu
CREATE (p:Product {
  sku: "VRT-STR2-RD",
  name: "Vortex Strikefire II Red Dot",
  category: "optic_red_dot",
  mount_type: ["picatinny_1in_ring"],
  weight_g: 218,
  height_cot: 40,  // height over centerline of tube
  battery_required: true,
  battery_type: "CR2",
  reticle: "4_MOA_dot",
  illumination_levels: 10,
  parallax: "infinity",
  recommended_distance: "0-200m",
  msrp_eur: 199,
  regulatory_class_de: "free",
  regulatory_class_pl: "free",
  regulatory_class_at: "free"
})

// Relacje kompatybilności
MATCH (p:Product {sku: "VRT-STR2-RD"})
MATCH (pl:Platform {has_rail: "picatinny", min_rail_length_cm: 10})
CREATE (p)-[:FITS_ON {confidence: 0.98}]->(pl)

// Relacja kanibalizacji
MATCH (a:Product {category: "optic_red_dot"})
MATCH (b:Product {category: "optic_red_dot"})
WHERE a.sku <> b.sku
CREATE (a)-[:CANNIBALIZES]-(b)

// Relacja synergii
MATCH (rd:Product {sku: "VRT-STR2-RD"})
MATCH (mag:Product {category: "optic_magnifier"})
CREATE (rd)-[:SYNERGIZES_WITH {boost: "long_range_capability"}]->(mag)

Dla rekomendacji uruchamiamy Cypher query, które startuje od rozpoznanej platformy + akcesoriów i przechodzi po krawędziach:

Pipeline rekomendacji

1
Input z DC-Model Klient wrzucił zdjęcie. Wykryto: platforma X (klon AR-15 16"), z optyką Y (red dot), brakuje foregripa, brak magnifiera, magazynek 30-nabojowy STANAG.
2
Query Neo4j na pasujące produkty MATCH platformy → znajdź wszystkie produkty z FITS_ON, gdzie typ montażu się zgadza, waga nie przeciąża, kaliber pasuje. Wynik: ~300 kandydatów z katalogu tenanta.
3
Wykluczenia (kanibalizacja) Wykluczamy produkty, które „kanibalizują" istniejące. Klient ma już red dot — nie polecamy drugiego red dot. Zostaje ~220 kandydatów.
4
Synergie i logiczne uzupełnienia Priorytetyzujemy: foregrip (bo go nie ma, a pasuje), magnifier (synergia z red dot), dwójnóg (typowe dla 16" platformy). Top 40 propozycji.
5
Collaborative filtering boost Wzbogacenie o sygnał „co kupowali inni z podobną konfiguracją". +/- 20% score dla każdego kandydata.
6
Cross-encoder re-rank Top 40 przez cross-encoder (platform_features, candidate_features) → finalny score. Top 10.
7
Filtr compliance Sprawdzenie regulacji per kraj tenanta i profil użytkownika. Zostaje 8 produktów.
8
Generacja opisów (Claude) Claude generuje dla każdego produktu krótki opis „dlaczego pasuje dokładnie do tej konfiguracji", używając wyników z grafu.

Dataset — najtrudniejsza część projektu

Dla całej branży nie istnieje publiczny dataset komputerowo-wizyjny taki, jaki nam był potrzebny. Musieliśmy zbudować własny.

Źródła zdjęć

Łącznie: ~85 000 zdjęć. Po deduplikacji i filtracji: ~71 000 użytecznych do treningu.

Anotacja

Tu nie da się oszukać — anotacja musi być wykonana przez ekspertów. Wynajęliśmy 3 osoby z branżowym doświadczeniem (instruktorzy strzelectwa sportowego, jeden serwisant, jeden kolekcjoner historycznych) na 6-miesięczny projekt anotacji. Każde zdjęcie:

Każde zdjęcie anotowane przez 2 niezależnych anotatorów. Konflikty rozwiązywał trzeci. Inter-annotator agreement: 89% dla klas modeli, 96% dla bounding boxów.

📚

Aspekt etyczny i prawny

Wszystkie zdjęcia użyte do treningu pochodzą z legalnych źródeł, z zachowaniem praw autorskich (zdjęcia własne klientów pilotażowych, zdjęcia producentów za zgodą, ogłoszenia publiczne w ramach fair use w celach researchu). Model NIE jest trenowany do rozpoznawania broni niedostępnej publicznie ani do obchodzenia regulacji. Wręcz przeciwnie — kluczowy element systemu (Compliance Layer) ma pomagać sklepom oferować zgodne z prawem rekomendacje.

Architektura SaaS — multi-tenant od pierwszego dnia

Struktura tenantów

Każdy klient (sklep, klub, serwis) to osobny tenant ze swoim:

API

REST API · endpoint analizy
POST /v1/analyze
Authorization: Bearer {tenant_api_key}
Content-Type: multipart/form-data

{
  "image": [binary],
  "user_profile": {
    "country": "PL",
    "license_class": "sport_shooter",  // optional
    "previous_purchases": ["SKU-1", "SKU-2"]  // optional
  },
  "options": {
    "max_recommendations": 10,
    "include_compatible_only": true,
    "language": "pl"
  }
}

// Response:
{
  "analysis_id": "ana_abc123",
  "processing_time_ms": 1432,
  "detected": {
    "platform": {
      "type": "platform_long",
      "model_candidates": [
        {"id": "ar15-clone-16in-mlok", "confidence": 0.81, "name": "AR-15 clone, 16\" barrel, M-LOK handguard"},
        {"id": "ar15-clone-16in-keymod", "confidence": 0.12, "name": "AR-15 clone, 16\", KeyMod handguard"}
      ]
    },
    "accessories": [
      {"category": "optic_red_dot", "model": "vortex-strikefire-2", "confidence": 0.92},
      {"category": "magazine", "model": "stanag-30rd", "confidence": 0.97}
    ],
    "missing_recommended": ["foregrip", "sling", "bipod"]
  },
  "recommendations": [
    {
      "sku": "MAG-FG-MLOK-BLK",
      "name": "Magpul M-LOK MOE Forward Grip, Black",
      "price_eur": 35.90,
      "compatibility_score": 0.97,
      "reasoning": "Bezpośredni montaż na widocznym handguardzie M-LOK. Lekki (88g), nie wpływa znacząco na balans.",
      "image_url": "...",
      "buy_url": "..."
    },
    // ...
  ],
  "compliance_notes": {
    "country": "PL",
    "all_compliant": true,
    "warnings": []
  }
}

Widget JavaScript dla sklepów

Dla sklepów, które nie chcą integrować się przez API, oferujemy gotowy widget JS do osadzenia:

HTML · integracja widgetu
<!-- W sklepie internetowym, np. na stronie produktu -->
<script src="https://cdn.gunupdate.com/widget/v1.js"></script>
<div id="gunupdate-widget" 
     data-tenant="abc123"
     data-style="card"
     data-color="#d97706"></div>

<script>
  GunUpdate.init({
    onProductRecommended: function(product) {
      // Dodaj do koszyka, śledzenie itp.
      console.log('Polecono:', product.sku);
    }
  });
</script>

Widget renderuje przycisk „📸 Wrzuć zdjęcie swojego sprzętu", po kliknięciu otwiera upload, wysyła do API i wyświetla rekomendacje inline.

Stack i infrastruktura

Stack techniczny

Inference w produkcji

Modele eksportowane do ONNX, serwowane przez Triton Inference Server na 2 maszynach inference z 2× RTX 4090 każda. Średni czas analizy zdjęcia: 1.4-1.6 sekundy (cała ścieżka: upload → YOLO → klasyfikator platformy → klasyfikatory akcesoriów → query KG → re-ranker → compliance → Claude opis → response). Throughput: ~350 req/min per maszyna.

Model biznesowy

GunUpdate jest sprzedawany w trzech planach:

Plan Cena (€/mies) Analiz/mies Dla kogo
Starter 149 500 Mały sklep specjalistyczny, klub sportowy
Pro 449 3 000 Średni sklep z aktywnym ruchem online
Enterprise 1 199+ nielimitowane Duży sklep / sieć, customowy katalog, SLA

Aktualnie (styczeń 2026) mamy 23 płacących tenantów w 5 krajach (PL, DE, AT, CZ, SK) i lej dalej w sprzedaży. Średni MRR rośnie.

Co dalej — roadmap produktowa

Czego nauczyliśmy się przy GunUpdate

1. Domena ekspercka > każda generyczna AI

CLIP wytrenowany na 400M parach obraz-tekst potrafi odpowiedzieć „to wygląda jak karabin sportowy". Ale nie potrafi powiedzieć, czy ten konkretny handguard to M-LOK czy KeyMod. Dla tej wiedzy potrzebny jest dedykowany dataset i dedykowany model. Generyczne AI to budulec, nie produkt.

2. SaaS multi-tenant od dnia 1 ratuje miesiące refaktoringu

Wiele zespołów startuje z mono-tenant prototypem i potem rok refaktoruje na multi-tenant. My zaczęliśmy od architektury multi-tenant od pierwszego dnia. Trochę więcej kodu na początku, ale od pierwszego klienta system był produkcyjny.

3. Compliance jako feature, nie jako blokada

Wiele firm w „regulowanych" branżach unika tych branż jak ognia. My zrobiliśmy odwrotnie — uczyniliśmy z compliance główny feature produktu. Klienci doceniają, że nasze rekomendacje są per-country aware i nie wpędzają ich w problemy.

4. Anotacja przez ekspertów branżowych = przewaga

Outsourcing anotacji do Mechanical Turk dałby nam dataset, w którym 30% etykiet byłoby błędnych. Wynajęcie 3 ekspertów branżowych na 6 miesięcy kosztowało niemało, ale jakość datasetu skoczyła z „użyteczny na demo" do „użyteczny w produkcji". To nie wszędzie się sprawdza, ale w wąskich domenach — bez tego nie da się.

5. Knowledge graph + ML > samo ML dla rekomendacji

Czysty „neural recommender" nauczyłby się powierzchownych korelacji. Knowledge graph daje twarde reguły kompatybilności (te 2 elementy fizycznie się nie połączą), które ML musi szanować. Hybryda twarde reguły + miękkie sygnały dała nam wyniki, których pure ML by nie osiągnął.

Jakie technologie z tego wdrożenia mogą Ci się przydać

GunUpdate to nasz produkt, ale ta sama architektura — YOLO + ViT + Knowledge Graph + Claude jako orkiestrator — działa wszędzie tam, gdzie:

Chcesz computer vision dla swojej branży?

GunUpdate to dowód, że potrafimy budować własne modele AI dla wąskich domen. Buduliśmy go od zera — własny dataset, własne modele, własna infrastruktura SaaS. Tę samą metodologię możemy zastosować u Ciebie.

Porozmawiajmy o Twoim projekcie →