Zarządzanie nieustrukturyzowanymi danymi typu dark data za pomocą Gemini i Knowledge Catalog

1. Wprowadzenie

Ponad 80% danych przedsiębiorstwa jest przechowywanych w formacie nieustrukturyzowanym – są to np. instrukcje obsługi w formacie PDF, standardowe procedury operacyjne, certyfikaty zgodności i schematy urządzeń przechowywane w Cloud Storage. Tradycyjne katalogi indeksują tylko schematy tabel relacyjnych, więc te dokumenty pozostają „ciemnymi danymi”: są niewidoczne dla wyszukiwania dla przedsiębiorstw, odłączone od tabel z danymi o asortymencie i niezweryfikowane pod kątem zgodności z przepisami.

Gdy audytor lub agent AI zada pytanie „Które numery SKU sprzętu wymagają certyfikatu bezpieczeństwa UL-153 i jakie są poziomy zagrożenia termicznego?”, katalog, który indeksuje tylko tabele SQL, nie będzie w stanie na nie odpowiedzieć. Fakty są zamknięte w nieuporządkowanych plikach PDF w Cloud Storage.

Rozwiązanie architektoniczne: metadane multimodalne jako kod

W tym ćwiczeniu utworzysz w Google Cloud kompleksowy potok Metadata-as-Code, który przekształca nieustrukturyzowane instrukcje PDF w Cloud Storage w zasoby Knowledge Catalog z wymuszonym schematem za pomocą Gemini Enterprise Agent Platform (pakiet SDK Google GenAI, google-genai):

Proces zarządzania nieuporządkowanymi danymi typu dark data

  1. Rejestracja zestawu plików (EntryGroup i Entry): grupuje nieustrukturyzowane pliki PDF w Cloud Storage w zarządzane logiczne wpisy zestawu plików w Katalogu wiedzy.
  2. Gemini Multimodal Extraction (Pydantic Schema): wywołuje Gemini Enterprise Agent Platform na surowych bajtach PDF z deterministyczną response_schema weryfikacją.
  3. Powiązanie aspektu płaszczyzny sterowania: dołącza zweryfikowane ładunki JSON dotyczące operacji i zgodności jako silnie typizowane instancje Aspect w pozycji katalogu.
  4. Wykrywanie w ujednoliconym katalogu: umożliwia wykrywanie nieuporządkowanych zestawów plików PDF i wyodrębnionych z nich metadanych za pomocą SearchEntriesRequest.

Kluczowe pojęcia: podstawowe elementy platformy sterującej Knowledge Catalog

Wyobraź sobie, że Twój zespół przechowuje setki instrukcji obsługi produktów w formacie PDF w Cloud Storage. Aby ułatwić znajdowanie tych plików i sprawdzanie ich w Knowledge Catalog, pomyśl o 5 elementach składowych jak o porządkowaniu papierowych instrukcji w szafie biurowej:

  • EntryGroup (Zamykana szafka dla jednego zespołu): szafka z zamkiem. Tylko członkowie zespołu z uprawnieniami (roles/dataplex.entryCreator) mogą umieszczać w nim foldery. Zanim usuniesz szafę, musisz opróżnić wszystkie foldery.
  • EntryType (Etykieta kategorii folderu): etykieta, która informuje użytkowników, jaki rodzaj komponentu reprezentuje folder, np. „Kolekcja instrukcji w formacie PDF” zamiast „Tabela bazy danych”.
  • Entry (Folder z linkiem do pamięci): folder katalogu z instrukcjami w formacie PDF. Zamiast ciężkich papierowych kopii folder zawiera kartę lokalizacji wskazującą dokładny zasobnik Cloud Storage (gs://...), w którym znajdują się prawdziwe pliki PDF.
  • AspectType (Pusty formularz listy kontrolnej): pusty formularz wielokrotnego użytku z wstępnie wydrukowanymi polami (np. „Lista kontrolna bezpieczeństwa” z prośbą o podanie operational_hazard_level w formie tekstu i confidence_score w formie liczby z zakresu od 0.0 do 1.0). Ten pusty formularz tworzysz raz i używasz go w tysiącach folderów.
  • Aspect (Wypełniona lista kontrolna dołączona do folderu): po tym, jak Gemini Enterprise Agent Platform odczyta instrukcję w formacie PDF i wypełni puste pola, wypełniona lista kontrolna zostanie przypięta do folderu Entry. Każda lista kontrolna ma własny klucz (aspect_keys), więc zespół inżynierów i zespół prawny mogą dołączyć własne listy kontrolne do tego samego folderu bez zastępowania pracy innych osób.

Wszystkie 5 zasobów regionalnych znajduje się w domenie projects/{project}/locations/{location}/:

Ścieżka podstawowa i względna

Rola w Knowledge Catalog

Reguła usuwania i reguła uprawnień

EntryGroup
.../entryGroups/{id}

Kontener logiczny, który grupuje wpisy i kontroluje dostęp zespołu (roles/dataplex.entryCreator).

Przed usunięciem nie może zawierać żadnych zasobów podrzędnych Entry.

EntryType
.../entryTypes/{id}

Definicja kategorii dla klasy zasobów (entry.entry_type, np. nieustrukturyzowane zestawy plików PDF).

Usuń go dopiero po usunięciu wszystkich wpisów korzystających z tego typu.

Entry (Zbiór plików)
.../entries/{entry_id}

Rekord katalogu łączący fizyczny identyfikator URI Cloud Storage (entry_source.resource) z nazwą logiczną (gcs:{bucket}).

Znajduje się w EntryGroup i zawiera powiązane rekordy Aspect.

AspectType
.../aspectTypes/{id}

Szablon schematu wielokrotnego użytku definiujący typowane record_fields (string, enum, double) i numery pól oparte na 1 (index).

Utworzone raz na region i udostępniane w ramach wszystkich zgłoszeń.

Aspect
Entry.aspects[key]

Zweryfikowane metadane JSON pasujące do AspectType, dołączone do Entry za pomocą UpdateEntryRequest.

Aktualizacje są przeprowadzane za pomocą funkcji update_mask i aspect_keys, dzięki czemu oddzielne potoki nie zastępują się nawzajem.

Co utworzysz

Za pomocą skryptów towarzyszących w codelabs/metadata-as-code-lab uruchomisz i sprawdzisz 7-etapowy potok:

  1. schemas.py – 2 schematy Pydantic BaseModel (DarkDataExtractedMetadata i DocumentGovernanceMetadata) sparowane 1:1 z szablonami AspectType Knowledge Catalog.
  2. step2_provision.py – idempotentne udostępnianie niestandardowych planów EntryGroup, EntryType i AspectType.
  3. step3_register_fileset.py – przesłanie LUM-LIG-DES-8G8J_manual.pdf do Cloud Storage i zarejestrowanie go jako zarządzanego zbioru plików Entry.
  4. step4_extract_metadata.py – dynamiczne wykrywanie flagowego modelu Gemini i multimodalne wyodrębnianie danych z plików PDF za pomocą google-genai.
  5. step5_attach_aspects.py, step6_search_catalog.py i step7_verify_assertions.py – przyłącze aspektu chirurgicznego, wyszukiwanie w katalogu z wzrastającym czasem do ponowienia i potwierdzenia w platformie sterującej typu end-to-end.

Wymagania wstępne i potrzebne elementy

  • Projekt Google Cloud z włączonym rozliczeniem i Google Cloud Shell (z wstępnie zainstalowanymi narzędziami gcloud, git, python3 i pip).
  • Uprawnienia IAM do zarządzania zasobami Knowledge Catalog (roles/dataplex.admin), udostępniania zasobników i obiektów Cloud Storage (roles/storage.admin) oraz wywoływania Gemini Enterprise Agent Platform (roles/aiplatform.user).
  • przeglądarka internetowa, np. Google Chrome;

2. Konfiguracja i wymagania

Klonowanie repozytorium towarzyszącego w Cloud Shell

Otwórz konsolę Google Cloud, uruchom Cloud Shell i wykonaj rzadkie wyewidencjonowanie codelabs/metadata-as-code-lab, które obejmuje przykładowy podręcznik inżynierski w formacie PDF (LUM-LIG-DES-8G8J_manual.pdf) i wszystkie skrypty w Pythonie:

git clone --branch main --depth 1 --filter=blob:none --sparse \
  https://github.com/GoogleCloudPlatform/devrel-demos.git
cd devrel-demos
git sparse-checkout set codelabs/metadata-as-code-lab
cd codelabs/metadata-as-code-lab
ls -la

Konfigurowanie zmiennych środowiskowych

Ustaw identyfikator projektu, lokalizację regionalnej platformy sterującej i docelowy zasobnik Cloud Storage w Cloud Shell:

export PROJECT_ID="${PROJECT_ID:-$(gcloud config get-value project)}"
gcloud config set project $PROJECT_ID

export REGION="us-central1"
export BUCKET_NAME="${PROJECT_ID}-dark-data-manuals"
export GEMINI_LOCATION="global"

echo "Configured Project ID        : $PROJECT_ID"
echo "Knowledge Catalog Region     : $REGION"
echo "Gemini Endpoint Location     : $GEMINI_LOCATION"
echo "Target Cloud Storage Bucket  : $BUCKET_NAME"

Włączanie interfejsów API i instalowanie zależności

Włącz wymagane interfejsy Google Cloud API i zainstaluj zależności Pythona (google-genai, google-cloud-dataplex, pydantic i pandas) z requirements.txt:

gcloud services enable \
  dataplex.googleapis.com \
  storage.googleapis.com \
  aiplatform.googleapis.com \
  --quiet
python3 -m pip install --upgrade --quiet --user --break-system-packages -r requirements.txt

3. Definiowanie schematów Pydantic i szablonów aspektów

schemas.py definiuje 2 uzupełniające się kontrakty, które łączą walidację Pydantic po stronie klienta z szablonami Knowledge Catalog po stronie serwera:AspectType

  1. DarkDataExtractedMetadata: atrybuty operacyjne wyodrębnione z pliku PDF (tytuł dokumentu, ontologia domeny, poziom zagrożenia, pochodzenie autora lub wersji, podsumowanie i poziom ufności wyodrębniania).
  2. DocumentGovernanceMetadata: kody zgodności z przepisami (UL-153, FCC Part 15, CE-LVD, RoHS), właściciel zarządzania produktem, zasady przechowywania i ciąg znaków identyfikatora tabeli referencyjnej (lakehouse_cross_ref_table) do łączenia instrukcji w formacie PDF z tabelami danych o produktach.

Sprawdź schemas.py

Po pierwsze, DarkDataExtractedMetadata używa ograniczeń Field Pydantic (ge=0.0, le=1.0, czyli większe/mniejsze lub równe, na confidence_score), aby ograniczyć dane wyjściowe JSON platformy Gemini Enterprise Agent Platform:

class DarkDataExtractedMetadata(BaseModel):
    document_title: str = Field(
        description="Official document title or product model name extracted from the PDF manual."
    )
    # ... domain_ontology, operational_hazard_level, author_provenance ...
    version_provenance: str = Field(
        description="Document version, revision code, or publication standard identifier."
    )
    # ... document_summary ...
    confidence_score: float = Field(
        ge=0.0,
        le=1.0,
        description="AI extraction confidence metric between 0.0 and 1.0.",
    )

Po drugie, extracted_aspect_template odzwierciedla te same nazwy pól i mapuje typy str i float w Pythonie na typy string i double record_fields w Knowledge Catalog. Pamiętaj, że kontrakt protobuf AspectType.MetadataTemplate wymaga, aby każde pole w record_fields deklarowało unikalną, ściśle dodatnią liczbę całkowitą zaczynającą się od 1 index (od 1 do 7). Pominięcie lub zduplikowanie index spowoduje, że create_aspect_type zakończy się niepowodzeniem z błędem 400 INVALID_ARGUMENT:

extracted_aspect_template = {
    "name": "DarkDataExtractedMetadata",
    "type": "record",
    "record_fields": [
        {
            "name": "document_title",
            "type": "string",
            "index": 1,
            "annotations": {"description": "Official document title or product model name."},
        },
        # ... fields 2 through 6 (string) ...
        {
            "name": "confidence_score",
            "type": "double",
            "index": 7,
            # ... annotations ...
        },
    ],
}

Weryfikacja modułu schematu

Uruchom schemas.py, aby sprawdzić konfigurację środowiska i skompilować oba schematy:

python3 schemas.py
Configured Project ID         : your-project-id
Knowledge Catalog Region      : us-central1
Gemini Endpoint Location      : global
Governed Fileset Storage URI  :
  gs://your-project-id-dark-data-manuals/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf
Target Fileset Entry ID       : sop-manuals-fileset-lum8g8j
✓ Defined DarkDataExtractedMetadata and DocumentGovernanceMetadata
  Pydantic schemas.
✓ Prepared Knowledge Catalog AspectType metadata templates.

4. Tworzenie przestrzeni nazw i niestandardowych typów aspektów

Przed zarejestrowaniem wpisów zbioru plików lub dołączeniem metadanych usługa step2_provision.py udostępnia 3 zasoby platformy sterującej w Knowledge Catalog:

  • EntryGroup: dark-data-fileset-group
  • EntryType: unstructured-pdf-fileset
  • AspectType Plany: dark-data-extracted-metadata i document-governance-aspect

Idempotentna obsługa administracyjna w usłudze step2_provision.py

Każde wywołanie tworzenia w step2_provision.py otacza długo trwającą operację (op.result()) blokiem try / except AlreadyExists, dzięki czemu skrypt można bezpiecznie uruchamiać ponownie bez niepowodzenia w przypadku istniejących zasobów:

# Provision AspectType 1: dark-data-extracted-metadata
try:
    at1_op = catalog_client.create_aspect_type(
        parent=parent_location,
        aspect_type_id=EXTRACTED_ASPECT_TYPE_ID,
        aspect_type=AspectType(
            name=extracted_aspect_type_name,
            display_name="Dark Data Multimodal Extracted Metadata",
            # ... description ...
            metadata_template=extracted_aspect_template,
        ),
    )
    if hasattr(at1_op, "result"):
        at1_op.result()
    print(f"Created AspectType: {extracted_aspect_type_name}")
except AlreadyExists:
    print(f"AspectType already exists; retrieving live resource: {extracted_aspect_type_name}")

live_extracted_aspect_type = catalog_client.get_aspect_type(name=extracted_aspect_type_name)

Po zarejestrowaniu metadata_template=extracted_aspect_template Knowledge Catalog wymusza schemat na granicy interfejsu API – każde kolejne wywołanie update_entry(), które przekazuje ciąg znaków do confidence_score (double), jest odrzucane.

Uruchom step2_provision.py

Uruchom skrypt udostępniania i sprawdź, czy niestandardowe typy aspektów są zarejestrowane w Twoim regionie:

python3 step2_provision.py
gcloud dataplex aspect-types list --location=$REGION
Created EntryGroup:
  projects/your-project-id/locations/us-central1/entryGroups/
  dark-data-fileset-group
Created EntryType :
  projects/your-project-id/locations/us-central1/entryTypes/
  unstructured-pdf-fileset
Created AspectType:
  projects/your-project-id/locations/us-central1/aspectTypes/
  dark-data-extracted-metadata
Created AspectType:
  projects/your-project-id/locations/us-central1/aspectTypes/
  document-governance-aspect
✓ All Knowledge Catalog namespaces and AspectType blueprints are active.

5. Rejestrowanie wpisów nieuporządkowanego zbioru plików

Zamiast zaśmiecać katalog milionami odseparowanych wskaźników plików, Knowledge Catalog grupuje powiązane dokumenty w Cloud Storage (gs://YOUR_BUCKET/sop-pdfs/*.pdf) w logiczne wpisy zestawu plików – za pomocą automatycznych skanów wykrywania (DataScanServiceClient) lub bezpośredniej rejestracji programowej (CatalogServiceClient.create_entry).

Jak step3_register_fileset.py mapuje pamięć masową na katalog

step3_register_fileset.py przesyła LUM-LIG-DES-8G8J_manual.pdf do gs://${BUCKET_NAME}/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf i rejestruje zarządzane Entry:

fully_qualified_fileset_uri = f"gcs:{BUCKET_NAME}"
fileset_entry_spec = Entry(
    name=fileset_entry_name,
    entry_type=entry_type_resource_name,
    fully_qualified_name=fully_qualified_fileset_uri,
    entry_source=EntrySource(
        resource=VIRTUAL_STORAGE_URI,
        system="Cloud Storage",
        platform="Google Cloud",
        display_name="LUM-LIG-DES-8G8J Unstructured SOP & Technical Manual Fileset",
        # ... description ...
        location=REGION,
    ),
)

create_entry_op = catalog_client.create_entry(
    parent=entry_group_resource_name,
    entry_id=FILESET_ENTRY_ID,
    entry=fileset_entry_spec,
)

Zwróć uwagę na różne role 2 pól identyfikatora URI na stronie Entry:

  • fully_qualified_name=fully_qualified_fileset_uri (f"gcs:{BUCKET_NAME}"): używa kanonicznego schematu gcs:{bucket_name} pełnej i jednoznacznej nazwy wymaganej przez Knowledge Catalog do powiązania logicznego wpisu katalogu z bazowym zasobnikiem Cloud Storage.
  • entry_source.resource=VIRTUAL_STORAGE_URI: przechowuje fizyczny identyfikator URI obiektu gs:// sprawdzany przez podrzędne procesy wyodrębniania.

Uruchom step3_register_fileset.py

python3 step3_register_fileset.py
Created Cloud Storage bucket:
  gs://your-project-id-dark-data-manuals in us-central1
Uploaded unstructured PDF manual to:
  gs://your-project-id-dark-data-manuals/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf
Registered governed Fileset Entry:
  projects/your-project-id/locations/us-central1/entryGroups/
  dark-data-fileset-group/entries/sop-manuals-fileset-lum8g8j
  -> Fully Qualified Name : gcs:your-project-id-dark-data-manuals
  -> Physical Resource URI:
  gs://your-project-id-dark-data-manuals/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf
  -> Source System        : Cloud Storage

6. Wyodrębnianie metadanych dokumentu za pomocą Gemini

step4_extract_metadata.py odczytuje surowe bajty pliku PDF i wywołuje Gemini Enterprise Agent Platform (genai_client.models.generate_content) za pomocą 2 kluczowych wzorców:

1. Dynamiczne wykrywanie flagowego modelu

Zamiast na stałe kodować niepewne ciągi znaków wersji modelu, skrypt wysyła zapytanie do genai_client.models.list() i sortuje aktywne kandydatury według (is_ga_channel, semantic_version_tuple), aby wybrać najnowszy model flash ogólnodostępny:

genai_client = genai.Client(
    vertexai=True,
    project=PROJECT_ID,
    location=GEMINI_LOCATION,
)

for model_obj in genai_client.models.list():
    raw_id = (model_obj.name or "").split("/")[-1]
    # Filter to flagship Gemini Flash models (version >= 3.0) and prioritize GA over preview
    ...
    discovered_candidates.append((is_ga_channel, ver_tuple, raw_id))

discovered_candidates.sort(key=lambda item: (item[0], item[1]), reverse=True)

2. Wielomodalne wyodrębnianie z ograniczeniami schematu (Part.from_bytes + response_schema)

Przekazanie response_mime_type="application/json" i response_schema=DarkDataExtractedMetadata (po którym następuje DocumentGovernanceMetadata) ogranicza dekodowanie tokena bezpośrednio do schematu JSON Pydantic:

with open(LOCAL_PDF_PATH, "rb") as pdf_file:
    raw_pdf_bytes = pdf_file.read()

extraction_response = genai_client.models.generate_content(
    model=candidate_model,
    contents=[
        types.Part.from_bytes(data=raw_pdf_bytes, mime_type="application/pdf"),
        extraction_prompt,
    ],
    config=types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=DarkDataExtractedMetadata,
        temperature=0.1,
    ),
)

extracted_dark_data = json.loads(extraction_response.text)
validated_extraction = DarkDataExtractedMetadata(**extracted_dark_data)

Uruchom step4_extract_metadata.py

python3 step4_extract_metadata.py
Dynamically discovered active GA model currency :
  gemini-3.8-flash (version (3, 8))
Loaded unstructured PDF manual at: LUM-LIG-DES-8G8J_manual.pdf
Read unstructured PDF document (1184 bytes).
  Executing multimodal extraction with gemini-3.8-flash...
✓ Multimodal extraction completed using model: gemini-3.8-flash
✓ Governance classification completed using model: gemini-3.8-flash

--- Extracted Multimodal Operational Metadata ---
Extracted Attribute    Multimodal Value
document_title    LUM-LIG-DES-8G8J Contemporary Linen Desk Lamp
domain_ontology    Electrical Hardware & Lighting Systems
operational_hazard_level    MEDIUM
author_provenance    Global Hardware Safety & Lighting Systems Engin
version_provenance    Rev 4.2
document_summary    This document outlines standard operating proce
confidence_score    0.99

--- Extracted Governance & Inventory Cross-Reference Metadata ---
Governance Attribute    Classification Value
compliance_classifications    UL-153 Portable Luminaires, FCC Part 15, CE-LVD
stewardship_owner    Global Hardware Safety & Lighting Systems Engin
retention_policy    10-Year Active Product Lifecycle Archival
lakehouse_cross_ref_table    lakehouse.your-project-id.retail_hardware
governance_status    VERIFIED_PRODUCTION

7. Dołączanie zweryfikowanych aspektów do wpisów w katalogu

step5_attach_aspects.py wiąże zweryfikowane ładunki JSON (extracted_metadata.json i governance_metadata.json) z wpisem sop-manuals-fileset-lum8g8j za pomocą catalog_client.update_entry().

Zmiana aspektu chirurgicznego w step5_attach_aspects.py

extracted_aspect_key = f"{PROJECT_ID}.{REGION}.{EXTRACTED_ASPECT_TYPE_ID}"
governance_aspect_key = f"{PROJECT_ID}.{REGION}.{GOVERNANCE_ASPECT_TYPE_ID}"

updated_entry_payload = Entry(
    name=fileset_entry_name,
    entry_type=entry_type_resource_name,
    fully_qualified_name=fully_qualified_fileset_uri,
    aspects={
        extracted_aspect_key: Aspect(
            aspect_type=extracted_aspect_type_name,
            data=extracted_data,
        ),
        governance_aspect_key: Aspect(
            aspect_type=governance_aspect_type_name,
            data=governance_data,
        ),
    },
)

update_op = catalog_client.update_entry(
    request=dataplex_v1.UpdateEntryRequest(
        entry=updated_entry_payload,
        update_mask={"paths": ["aspects"]},
        aspect_keys=[extracted_aspect_key, governance_aspect_key],
    )
)

Przekazanie obu zakresów update_mask={"paths": ["aspects"]} i aspect_keys=[extracted_aspect_key, governance_aspect_key] ogranicza modyfikację wyłącznie do tych 2 kluczy aspektów, pozostawiając entry_source i wszystkie aspekty należące do innych zespołów bez zmian.

Uruchom step5_attach_aspects.py

python3 step5_attach_aspects.py
Successfully bound 2 Aspect(s) to Entry:
  projects/your-project-id/locations/us-central1/entryGroups/
  dark-data-fileset-group/entries/sop-manuals-fileset-lum8g8j

=== Live Attached Aspect: document-governance-aspect ===
Catalog Field    Authoritative Stored Value
compliance_classifications    UL-153 Portable Luminaires, FCC Part 15, CE-LVD
stewardship_owner    Global Hardware Safety & Lighting Systems Engin
retention_policy    10-Year Active Product Lifecycle Archival
lakehouse_cross_ref_table    lakehouse.your-project-id.retail_hardware
governance_status    VERIFIED_PRODUCTION

=== Live Attached Aspect: dark-data-extracted-metadata ===
Catalog Field    Authoritative Stored Value
document_title    LUM-LIG-DES-8G8J Contemporary Linen Desk Lamp
domain_ontology    Electrical Hardware & Lighting Systems
operational_hazard_level    MEDIUM
author_provenance    Global Hardware Safety & Lighting Systems Engin
version_provenance    Rev 4.2
document_summary    This document outlines standard operating proce
confidence_score    0.99

Weryfikacja dwutorowa

  • Ścieżka 1 (weryfikacja za pomocą interfejsu wiersza poleceń): sprawdź wpis ze wszystkimi dołączonymi aspektami za pomocą gcloud:
    gcloud dataplex entries describe sop-manuals-fileset-lum8g8j \
      --entry-group=dark-data-fileset-group \
      --location=$REGION \
      --view=ALL
    
  • Ścieżka 2 (sprawdzanie interfejsu Konsoli):
    1. Otwórz Knowledge Catalog Search Console, wyszukaj LUM-LIG-DES-8G8J Unstructured SOP & Technical Manual Fileset (sop-manuals-fileset-lum8g8j) i wybierz pasujący wpis z wyników.
    2. W sekcji Opcjonalne tagi i aspekty sprawdź, czy w przypadku tagów Dark Data Multimodal Extracted Metadata i Document Governance & Inventory Cross-Reference Aspect wyświetla się wyodrębniony poziom zagrożenia (MEDIUM), kody zgodności (UL-153, FCC Part 15, CE-LVD, RoHS) i ciąg tabeli odniesień (lakehouse_cross_ref_table).

8. Wysyłanie zapytań o zarządzane dane niejawne w katalogu

Po dołączeniu aspektów niestandardowych nieustrukturyzowane instrukcje PDF w Cloud Storage stają się wykrywalne w wyszukiwarce Knowledge Catalog (catalog_client.search_entries()).

Ankieta search_entries() za step6_search_catalog.py

step6_search_catalog.py wysyła zapytania do search_entries() ze wzrastającym czasem do ponowienia i odczytuje kanoniczne klucze aspektów za pomocą .endswith():

search_query = f"entrygroup={entry_group_resource_name} name:{FILESET_ENTRY_ID}"

while elapsed_seconds < max_wait_seconds:
    catalog_search_results = list(
        catalog_client.search_entries(
            request=dataplex_v1.SearchEntriesRequest(
                name=parent_location,
                query=search_query,
            )
        )
    )
    if catalog_search_results:
        break
    backoff_seconds = min(5 * (2 ** attempt), 30)
    time.sleep(backoff_seconds)
    ...

for k, asp in detailed_entry.aspects.items():
    if k.endswith(f".{REGION}.{EXTRACTED_ASPECT_TYPE_ID}"):
        print(f"    Domain Ontology     : {asp.data.get('domain_ontology')}")
        print(f"    Hazard Level        : {asp.data.get('operational_hazard_level')}")
    elif k.endswith(f".{REGION}.{GOVERNANCE_ASPECT_TYPE_ID}"):
        print(f"    Compliance Codes    : {asp.data.get('compliance_classifications')}")
        print(f"    Lakehouse Join Table: {asp.data.get('lakehouse_cross_ref_table')}")

Uruchom step6_search_catalog.py

python3 step6_search_catalog.py
Executing Knowledge Catalog search query:
  'entrygroup=projects/your-project-id/locations/us-central1/entryGroups/
  dark-data-fileset-group name:sop-manuals-fileset-lum8g8j'...

✓ Discovered 1 governed asset(s) in Knowledge Catalog:

[1] Entry Resource Name :
    projects/your-project-id/locations/us-central1/entryGroups/
    dark-data-fileset-group/entries/sop-manuals-fileset-lum8g8j
    Fully Qualified Name: gcs:your-project-id-dark-data-manuals
    Entry Type :
    projects/your-project-id/locations/us-central1/entryTypes/
    unstructured-pdf-fileset
    Physical Storage URI:
    gs://your-project-id-dark-data-manuals/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf
    Domain Ontology     : Electrical Hardware & Lighting Systems
    Hazard Level        : MEDIUM
    Compliance Codes    : UL-153 Portable Luminaires, FCC Part 15, CE-LVD, RoHS
    Lakehouse Join Table:
    lakehouse.your-project-id.retail_hardware.luminaire_sku_inventory_iceberg

Weryfikacja dwutorowa

  • Ścieżka 1 (wyszukiwanie w interfejsie wiersza poleceń): wysyłaj zapytania do indeksu wyszukiwania bezpośrednio za pomocą gcloud:
    gcloud dataplex entries search "name:sop-manuals-fileset-lum8g8j" --project=$PROJECT_ID
    
  • Ścieżka 2 (wyszukiwanie w języku naturalnym w interfejsie konsoli):
    1. Otwórz Search Console Knowledge Catalog i wyszukaj LUM-LIG-DES-8G8J lub UL-153.
    2. Zobacz, jak Knowledge Catalog wyświetla zarządzany wpis zbioru plików PDF Cloud Storage i jego dołączone aspekty metadanych.

9. Weryfikowanie asercji dotyczących zarządzania kompleksowego

step7_verify_assertions.py wykonuje deterministyczne asercje na podstawie odpowiedzi z płaszczyzny sterowania Knowledge Catalog, aby sprawdzić, czy EntryGroup, EntryType, oba niestandardowe schematy AspectType, powiązane ładunki aspektów EntryView.ALL (confidence_score zakresy i lakehouse_cross_ref_table ciągi znaków) oraz wykrywanie indeksu wyszukiwania działają prawidłowo:

verify_eg = catalog_client.get_entry_group(name=entry_group_resource_name)
assert verify_eg.name == entry_group_resource_name, "EntryGroup resource name mismatch."

verify_entry = catalog_client.get_entry(
    request=dataplex_v1.GetEntryRequest(
        name=fileset_entry_name,
        view=dataplex_v1.EntryView.ALL,
    )
)
bound_extracted = next(
    (
        asp for k, asp in verify_entry.aspects.items()
        if k.endswith(f".{REGION}.{EXTRACTED_ASPECT_TYPE_ID}")
    ),
    None,
)
bound_governance = next(
    (
        asp for k, asp in verify_entry.aspects.items()
        if k.endswith(f".{REGION}.{GOVERNANCE_ASPECT_TYPE_ID}")
    ),
    None,
)

assert bound_extracted is not None, f"Aspect '{EXTRACTED_ASPECT_TYPE_ID}' not found on live Entry."
assert bound_governance is not None, (
    f"Aspect '{GOVERNANCE_ASPECT_TYPE_ID}' not found on live Entry."
)
assert (
    bound_extracted.data.get("document_title") == expected_extraction["document_title"]
), "Extracted title mismatch."
assert (
    0.0 <= float(bound_extracted.data.get("confidence_score", -1.0)) <= 1.0
), "Invalid confidence score in catalog."
assert (
    "lakehouse" in str(bound_governance.data.get("lakehouse_cross_ref_table", "")).lower()
), "Missing Lakehouse cross-reference."
...
assert len(search_results) >= 1, "Expected at least 1 search result in Knowledge Catalog."

Uruchom step7_verify_assertions.py

python3 step7_verify_assertions.py && echo "Verification exit code: $?"
Running substantive end-to-end verification assertions...
✓ All 5 substantive verification assertions passed
  against live Google Cloud control plane state!
Verification exit code: 0

10. Projektowanie potoku opartego na zdarzeniach

Interaktywne uruchamianie skryptów w Pythonie w Cloud Shell jest idealne do tworzenia i testowania umów dotyczących zarządzania, ale w środowiskach przedsiębiorstw codziennie pojawiają się tysiące nowych lub zmienionych instrukcji technicznych w formacie PDF, certyfikatów zgodności dostawców i dokumentów SOP z systemów ERP, PLM i portali dostawców. Ręczne uruchamianie skryptów wsadowych szybko tworzy luki w nadzorze między przesyłaniem dokumentów a indeksowaniem katalogu.

W środowisku produkcyjnym zespoły platformy wdrażają kod, który został uruchomiony w krokach 4 i 5, jako bezobsługowy potok oparty na zdarzeniach:

Potok danych opartej na zdarzeniach

  1. Ciągłe wczytywanie dokumentów (Cloud Storage → Eventarc): gdy nowy podręcznik w formacie PDF zostanie przesłany lub nowa wersja zastąpi istniejący obiekt w Cloud Storage, zasobnik wyemituje google.cloud.storage.object.v1.finalized CloudEvent zawierający identyfikator zasobnika, ścieżkę obiektu i numer generacji obiektu.
  2. Stateless Multimodal Extraction (Eventarc → Cloud Run → Gemini Enterprise Agent Platform): Eventarc kieruje CloudEvent do bezserwerowego procesu Cloud Run, który zawiera schemas.py, step4_extract_metadata.py i step5_attach_aspects.py. Proces roboczy przesyła strumieniowo bajty PDF do platformy agentowej Gemini Enterprise z response_schema, co gwarantuje, że każdy wyodrębniony atrybut jest zgodny z DarkDataExtractedMetadata i DocumentGovernanceMetadata.
  3. Aktualizacja platformy sterującej operacji (Cloud Run → Knowledge Catalog): proces roboczy rozwiązuje nadrzędny zestaw plików Entry i wykonuje catalog_client.update_entry() z update_mask={"paths": ["aspects"]} i jawnym aspect_keys. Nawet jeśli dziesiątki dokumentów zakończą przetwarzanie w tym samym czasie, każda modyfikacja zaktualizuje tylko wyznaczone klucze aspektów.
  4. Kwarantanna nadzorowana na podstawie poziomu ufności: jeśli zeskanowany starszy plik PDF wygeneruje wyodrębnianie confidence_score poniżej progu operacyjnego (np. < 0.85), pracownik ustawi wartość governance_status = "PENDING_STEWARD_REVIEW" w powiązanym aspekcie, aby administratorzy danych mogli wysyłać zapytania do Knowledge Catalog dotyczące zasobów o niskim poziomie ufności, które wymagają sprawdzenia przez człowieka.

Jak przedsiębiorstwa stosują ten wzorzec w środowisku produkcyjnym

Przypadek użycia w firmie

Jak w praktyce działa podejście Metadane jako kod

Wpływ na działalność i operacje

Automatyczne audyty zgodności z przepisami i gotowość do wycofania
(produkcja, sprzęt i energetyka)

Systemy zgodności łączą nieustrukturyzowane aspekty bezpieczeństwa plików PDF (compliance_classifications, operational_hazard_level) z ustrukturyzowanymi tabelami asortymentu SKU (lakehouse_cross_ref_table) w BigQuery i Lakehouse for Apache Iceberg.

Gdy standard, np. UL-153 lub CE-LVD, zostanie zaktualizowany, audytorzy w ciągu kilku sekund zidentyfikują wszystkie jednostki SKU sprzętu i lokalizacje magazynów, których dotyczy zmiana, zamiast ręcznie otwierać tysiące folderów PDF.

Agenty AI oparte na wiedzy i wstępne filtrowanie RAG
(asystenci wiedzy dla firm)

Zanim agent generowania wspomaganego wyszukiwaniem (RAG) na Gemini Enterprise Agent Platform odpowie na pytanie inżyniera terenowego, filtruje wpisy Knowledge Catalog według governance_status = "VERIFIED_PRODUCTION" i version_provenance.

Zapobiega halucynacjom asystentów AI i cytowaniu przez nich wycofanych projektów technicznych, nieaktualnych standardowych procedur operacyjnych lub niezweryfikowanych instrukcji obsługi innych firm.

Wzbogacanie danych przez wiele zespołów jednocześnie
(zdecentralizowana siatka danych)

Wiele niezależnych potoków wzbogaca ten sam zbiór plików Entry: instancja robocza inżynierii AI aktualizuje dark-data-extracted-metadata, dział prawny dołącza zasady przechowywania za pomocą document-governance-aspect, a dział ds. bezpieczeństwa dołącza aspekty związane z ochroną danych (DLP).

Ponieważ UpdateEntryRequest ogranicza zmiany za pomocą aspect_keys, każdy zespół ds. domeny wdraża i aktualizuje swój potok metadanych niezależnie od innych zespołów, nie zastępując ich danych dotyczących zarządzania.

Ewolucja schematu CI/CD za pomocą GitOps
(Platform & Data Engineering)

Zespoły platformowe przechowują definicje schemas.py wraz z definicjami Terraform google_dataplex_aspect_type w Git. Żądania scalenia sprawdzają, czy każde nowe pole Pydantic ma pasujący indeks index w szablonie AspectType przed wdrożeniem.

Eliminuje dryf schematu między kodem wyodrębniania aplikacji a platformą sterującą Knowledge Catalog w projektach dev, staging i prod.

11. Czyszczenie środowiska

W Knowledge Catalog nie można usuwać kontenerów nadrzędnych i szablonów schematów, jeśli wpisy podrzędne nadal się do nich odwołują. cleanup.py usuwa zasoby w ścisłej odwrotnej kolejności zależności (Entry → EntryGroup → EntryType → AspectTypes → obiekty zasobnika Cloud Storage → tymczasowe pliki JSON):

# 1. Delete Fileset Entry first
catalog_client.delete_entry(name=target_entry_path)

# 2. Delete EntryGroup container
del_eg_op = catalog_client.delete_entry_group(name=target_eg_path)
if hasattr(del_eg_op, "result"):
    del_eg_op.result()

# 3. Delete EntryType and Custom AspectTypes
del_et_op = catalog_client.delete_entry_type(name=target_et_path)
if hasattr(del_et_op, "result"):
    del_et_op.result()
for aspect_id_val in (EXTRACTED_ASPECT_TYPE_ID, GOVERNANCE_ASPECT_TYPE_ID):
    target_at_path = f"{active_parent}/aspectTypes/{aspect_id_val}"
    del_at_op = catalog_client.delete_aspect_type(name=target_at_path)
    if hasattr(del_at_op, "result"):
        del_at_op.result()

Uruchom cleanup.py

python3 cleanup.py
Starting reverse-dependency resource cleanup in Knowledge Catalog...
Deleted Fileset Entry:
  projects/your-project-id/locations/us-central1/entryGroups/
  dark-data-fileset-group/entries/sop-manuals-fileset-lum8g8j
Deleted EntryGroup   :
  projects/your-project-id/locations/us-central1/entryGroups/
  dark-data-fileset-group
Deleted EntryType    :
  projects/your-project-id/locations/us-central1/entryTypes/
  unstructured-pdf-fileset
Deleted AspectType   :
  projects/your-project-id/locations/us-central1/aspectTypes/
  dark-data-extracted-metadata
Deleted AspectType   :
  projects/your-project-id/locations/us-central1/aspectTypes/
  document-governance-aspect
Deleted Cloud Storage object :
  gs://your-project-id-dark-data-manuals/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf
Deleted Cloud Storage bucket : gs://your-project-id-dark-data-manuals
Removed local temporary file : extracted_metadata.json
Removed local temporary file : governance_metadata.json
✓ Standalone teardown complete. Environment cleanly reset.

Usuwanie sklonowanego katalogu repozytorium

Gdy cleanup.py zakończy usuwanie zasobów w chmurze, wróć do katalogu głównego i usuń sklonowany folder repozytorium devrel-demos z Cloud Shell:

cd ~
rm -rf ~/devrel-demos

12. Gratulacje!

Masz utworzoną i zweryfikowaną kompleksową ścieżkę zarządzania metadanymi jako kodem, która przekształca nieustrukturyzowane pliki PDF w Cloud Storage w wykrywalne zasoby Knowledge Catalog z wymuszonym schematem za pomocą Gemini Enterprise Agent Platform.

Co dalej?

  • Automatyzacja za pomocą Terraform: deklaratywne zarządzanie zasobami google_dataplex_aspect_type i google_dataplex_entry_group w potokach CI/CD.
  • Wdrażanie Eventarc i procesów roboczych Cloud Run: skonteneryzuj step4_extract_metadata.py i step5_attach_aspects.py w usłudze Cloud Run opartej na zdarzeniach.
  • Łączenie zasobów podrzędnych w BigQuery: eksportuj wyodrębnione metadane dotyczące zarządzania (lakehouse_cross_ref_table), aby połączyć atrybuty zgodności nieuporządkowanych dokumentów z uporządkowanymi tabelami zasobów SKU.

Dokumentacja