Skip to content

Latest commit

 

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📸 Smart photo catalog

Mikroserwisowa aplikacja chmurowa, która automatycznie analizuje wgrane zdjęcia przy użyciu Azure AI Vision (generowanie opisów, tagów, wykrywanie obiektów, OCR), indeksuje je wektorowo (Azure OpenAI) i udostępnia w nowoczesnej galerii z wyszukiwaniem semantycznym.

Projekt demonstruje w pełni rozproszoną architekturę opartą na asynchronicznej komunikacji (Azure Service Bus) oraz wykorzystaniu wielu języków programowania.

Główne funkcje

  • Inteligentna analiza obrazu - automatyczne generowanie opisów, wyciąganie tagów oraz odczytywanie tekstu ze zdjęć (OCR) za pomocą Azure AI Vision.
  • Asynchroniczne przetwarzanie: - zdjęcia po wgraniu od razu trafiają do galerii ze statusem pending. Analiza dzieje się w tle, zapobiegając blokowaniu interfejsu użytkownika.
  • Wyszukiwanie semantyczne - możliwość wyszukania zdjęć używając naturalnego języka np. "pies na plaży". Tekst z obrazów i opisy są zamieniane na wektory (model text-embedding-3-small), a serwis catalog-cs oblicza podobieństwo kosinusowe, by zwrócić najtrafniejsze wyniki.
  • Reaktywny interfejs (UI) - interfejs napisany w Streamlit oferuje dynamiczne auto-odświeżanie galerii (co 5 sekund), dzięki czemu statusy (pending -> done/failed) zmieniają się na oczach użytkownika.

Przepływ danych

  1. Użytkownik wgrywa plik przez Frontend.
  2. Ingestion API ładuje plik do Blob Storage, zapisuje metadane w bazie i wysyła wiadomość do kolejki.
  3. Frontend natychmiast pokazuje zdjęcie w galerii ze statusem oczekiwania.
  4. Worker odbiera wiadomość, analizuje zdjęcie w zewnętrznych usługach AI i uaktualnia bazę danych o wektory i tagi.
  5. Użytkownik wpisuje frazę w wyszukiwarce. Catalog API zamienia frazę na wektor za pomocą OpenAI, porównuje z wektorami w Cosmos DB i zwraca posortowane wyniki.

Wykorzystane usługi chmurowe

  • Azure Storage Account (Blob) - fizyczne przechowywanie plików .jpg, .png itp.
  • Azure Cosmos DB (NoSQL) - szybka i bez-schematowa baza danych przechowująca metadane zdjęć, tagi oraz embeddingi wektorowe.
  • Azure Service Bus - kolejka komunikatów rozprzęgająca proces wgrywania od procesu analizy AI.
  • Azure AI Vision - usługa kognitywna do ekstrakcji informacji z obrazów.
  • Azure OpenAI - dostawca modelu LLM (text-embedding-3-small) do generowania wielowymiarowych wektorów semantycznych.

Architektura

Architecture diagram

Aplikacja składa się z 4 niezależnych komponentów:

Komponent Język / Framework Rola
frontend Python (Streamlit) Interfejs użytkownika. Obsługuje wgrywanie plików (upload), wyświetla galerię z auto-odświeżaniem i obsługuje wyszukiwarkę.
services/ingestion-js JavaScript (Node.js + Express) Brama wejściowa. Zapisuje fizyczny plik w Azure Blob Storage, tworzy nowy dokument ze statusem pending w bazie Cosmos DB i publikuje zdarzenie (job) na kolejkę Service Bus.
services/worker-py Python Konsument kolejki pracujący w tle. Pobiera zadanie, wywołuje Azure AI Vision, buduje tekstowy profil zdjęcia, zamienia go na embedding przez Azure OpenAI i aktualizuje dokument w Cosmos DB na status done.
services/catalog-cs C# (.NET 8 Minimal API) REST API dla galerii. Udostępnia endpoint /photos (pobranie wszystkich zdjęć) oraz /search (wyszukiwanie wektorowe przy użyciu lokalnego obliczania Cosine Similarity).

Uruchomienie lokalne

Wymagania: Docker, Docker Compose, konto Azure z postawioną infrastrukturą (Cosmos DB, Storage, Service Bus, AI Vision, OpenAI - patrz infra/).

1. Wygeneruj plik .env z danymi dostępowymi

Jeśli masz już wdrożoną infrastrukturę Terraformem, najprościej wyciągnąć dane przez skrypt pomocniczy:

RG=$(cd infra && terraform output -raw resource_group)
./local/gen-env.sh $RG

Skrypt zapyta az o connection stringi/klucze i zapisze je do .env w głównym katalogu repo.

Jeśli nie masz skryptu albo wolisz zrobić to ręcznie, skopiuj szablon:

cp .env.example .env

i uzupełnij wartości w .env.

Wartości wyciągniesz komendami:

RG=$(cd infra && terraform output -raw resource_group)

az storage account show-connection-string -g $RG -n $(cd infra && terraform output -raw storage_account) --query connectionString -o tsv

az cosmosdb keys list -g $RG -n $(cd infra && terraform output -raw cosmos_account) --query primaryMasterKey -o tsv

az servicebus namespace authorization-rule keys list -g $RG --namespace-name $(cd infra && terraform output -raw servicebus_namespace) --name RootManageSharedAccessKey --query primaryConnectionString -o tsv

az cognitiveservices account keys list -g $RG -n $(cd infra && terraform output -raw vision_account) --query key1 -o tsv

2. Zbuduj i odpal wszystkie serwisy

docker compose up --build

To zbuduje i uruchomi 4 kontenery: ingestion (:3000), worker, catalog (:8080), frontend (:8501).

3. Sprawdź, że wszystko działa

W przeglądarce wgraj zdjęcie w zakładce Upload, przejdź do Galeria - status powinien przejść z przetwarzanie na gotowe.

4. Zatrzymanie

docker compose down

Żeby zrestartować po zmianie kodu (bez cache):

docker compose up --build --force-recreate

Automatyczne wdrożenie po git push (CI/CD)

Pipeline (.github/workflows/ci-cd.yml) sam buduje obrazy i wdraża je na Azure Container Apps po każdym wypchnięciu na branch main. Żeby to zadziałało, jednorazowo skonfiguruj poniższe.

1. Magazyn na stan Terraform (jeśli jeszcze nie istnieje)

az group create -n rg-tfstate -l germanywestcentral
SA_TF="sttf$RANDOM$RANDOM"
az storage account create -n $SA_TF -g rg-tfstate -l germanywestcentral --sku Standard_LRS
az storage container create -n tfstate --account-name $SA_TF
echo "Nazwa konta: $SA_TF"

2. Service principal dla GitHub Actions

SUB_ID=$(az account show --query id -o tsv)
az ad sp create-for-rbac --name smartphoto-ci --role Contributor --scopes /subscriptions/$SUB_ID --sdk-auth

Zapisz cały wypisany JSON - będzie potrzebny w następnym kroku.

3. Dodaj sekrety w repozytorium GitHub

W repo: Settings -> Secrets and variables -> Actions -> New repository secret. Dodaj:

Nazwa sekretu Wartość
AZURE_CREDENTIALS cały JSON z az ad sp create-for-rbac --sdk-auth
ARM_CLIENT_ID pole clientId z tego JSON-a
ARM_CLIENT_SECRET pole clientSecret z tego JSON-a
ARM_SUBSCRIPTION_ID pole subscriptionId z tego JSON-a
ARM_TENANT_ID pole tenantId z tego JSON-a
TFSTATE_RG rg-tfstate
TFSTATE_STORAGE_ACCOUNT nazwa konta z kroku 1 (np. sttf189423)
TFSTATE_CONTAINER tfstate

4. Wypchnij zmianę i sprawdź pipeline

git add .
git commit -m "Trigger CI/CD"
git push origin main

W zakładce Actions w repo zobaczysz dwa joby:

  1. infra - Terraform stawia/aktualizuje infrastrukturę na Azure,
  2. deploy - buduje 4 obrazy Docker, wypycha je do ACR i aktualizuje Container Apps.

Po zielonym przebiegu każdy kolejny git push na main automatycznie zbuduje i wdroży nową wersję aplikacji - bez żadnej ręcznej interwencji.

5. Adres działającej aplikacji

cd infra
terraform output -raw frontend_url

Czyszczenie zasobów

Aby usunąć całą utworzoną infrastrukturę w Azure:

cd infra
terraform destroy

Potwierdź operację wpisując:

yes

Po zakończeniu można dodatkowo usunąć zasoby utworzone poza Terraformem:

# usunięcie grupy zasobów przechowującej stan Terraform
az group delete -n rg-tfstate --yes --no-wait

# usunięcie Service Principal używanego do wdrożenia
az ad sp delete --id <CLIENT_ID>

Weryfikacja

Sprawdzenie, czy zasoby zostały usunięte:

az resource list --output table

lub dla konkretnej grupy:

az group list --output table

Screeny

Photo upload

Photo gallery 1

Photo gallery 2

Semantic search

About

Distributed photo catalog cloud app

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages