Mengelola data gelap tidak terstruktur dengan Gemini dan Knowledge Catalog

1. Pengantar

Lebih dari 80% data perusahaan berada dalam format tidak terstruktur—manual teknik PDF, prosedur operasi standar (SOP), sertifikat kepatuhan, dan skema peralatan yang disimpan di Cloud Storage. Karena katalog tradisional hanya mengindeks skema tabel relasional, dokumen ini tetap menjadi "Data Gelap": tidak terlihat oleh penelusuran Enterprise, tidak terhubung dari tabel inventaris terstruktur, dan tidak terverifikasi untuk kepatuhan terhadap peraturan.

Jika auditor atau agen AI bertanya, "SKU hardware mana yang memerlukan sertifikasi keselamatan UL-153 dan berapa tingkat bahaya termalnya?", katalog yang hanya mengindeks tabel SQL tidak dapat menjawabnya. Fakta-fakta tersebut terkunci di dalam PDF tidak terstruktur di Cloud Storage.

Solusi arsitektur: metadata-as-code multimodal

Dalam codelab ini, Anda akan membangun pipeline Metadata-as-Code end-to-end di Google Cloud yang mengubah manual PDF tidak terstruktur di Cloud Storage menjadi aset Knowledge Catalog yang menerapkan skema menggunakan Gemini Enterprise Agent Platform (Google GenAI SDK, google-genai):

Alur Tata Kelola Data Gelap Tidak Terstruktur

  1. Pendaftaran Fileset (EntryGroup & Entry): Mengelompokkan PDF tidak terstruktur di Cloud Storage ke dalam entri fileset logis yang diatur di Knowledge Catalog.
  2. Ekstraksi Multimodal Gemini (Skema Pydantic): Memanggil Gemini Enterprise Agent Platform pada byte PDF mentah dengan validasi response_schema deterministik.
  3. Pengikatan Aspek Control Plane: Melampirkan payload JSON operasional dan kepatuhan yang divalidasi sebagai instance Aspect yang sangat diketik pada entri katalog.
  4. Penemuan Katalog Terpadu: Membuat kumpulan file PDF tidak terstruktur dan metadata yang diekstrak dapat ditemukan melalui SearchEntriesRequest.

Konsep utama: Primitif bidang kontrol Knowledge Catalog

Bayangkan tim Anda menyimpan ratusan manual produk dalam format PDF di Cloud Storage. Agar file tersebut mudah ditemukan dan diperiksa di Knowledge Catalog, anggaplah lima elemen penyusun seperti mengatur manual kertas di lemari arsip kantor:

  • EntryGroup (Lemari terkunci untuk satu tim): Lemari dengan kunci. Hanya rekan tim yang memiliki izin (roles/dataplex.entryCreator) yang dapat memasukkan folder ke dalamnya. Anda harus mengosongkan setiap folder dari lemari sebelum dapat mengeluarkan lemari itu sendiri.
  • EntryType (Label kategori folder): Label yang memberi tahu orang-orang tentang jenis aset yang diwakili oleh folder—misalnya, "Koleksi Manual PDF", bukan "Tabel Database".
  • Entry (Folder file dengan link penyimpanan): Folder katalog untuk manual PDF Anda. Alih-alih menyimpan salinan kertas yang berat, folder ini menyimpan kartu lokasi yang menunjuk ke bucket Cloud Storage (gs://...) yang tepat tempat file PDF sebenarnya berada.
  • AspectType (Formulir checklist kosong): Formulir kosong yang dapat digunakan kembali dengan kotak yang telah dicetak sebelumnya (misalnya, "Checklist Keselamatan" yang meminta operational_hazard_level sebagai teks dan confidence_score sebagai angka dari 0.0 hingga 1.0). Anda membuat formulir kosong ini satu kali dan menggunakannya kembali di ribuan folder.
  • Aspect (Daftar periksa yang telah diisi dan dilampirkan ke folder): Setelah Gemini Enterprise Agent Platform membaca panduan PDF dan mengisi bagian yang kosong, daftar periksa yang telah diisi tersebut akan disematkan ke folder Entry. Karena setiap checklist memiliki kuncinya sendiri (aspect_keys), tim engineering dan tim hukum dapat melampirkan checklist mereka sendiri ke folder yang sama tanpa menimpa pekerjaan masing-masing.

Kelima resource regional tersebut berada di projects/{project}/locations/{location}/:

Jalur Primitif & Relatif

Peran di Knowledge Catalog

Penghapusan & Aturan IAM

EntryGroup
.../entryGroups/{id}

Penampung logis yang mengelompokkan entri dan mengontrol akses tim (roles/dataplex.entryCreator).

Harus berisi nol resource turunan Entry sebelum dihapus.

EntryType
.../entryTypes/{id}

Definisi kategori untuk class aset (entry.entry_type, seperti kumpulan file PDF tidak terstruktur).

Hapus hanya setelah semua entri yang menggunakan jenis ini dihapus.

Entry (Fileset)
.../entries/{entry_id}

Entri katalog yang menautkan URI Cloud Storage fisik (entry_source.resource) ke nama logis (gcs:{bucket}).

Berada di dalam EntryGroup dan menyimpan data Aspect terlampir.

AspectType
.../aspectTypes/{id}

Template skema yang dapat digunakan kembali yang menentukan record_fields yang diketik (string, enum, double) dan nomor kolom berbasis 1 (index).

Dibuat sekali per region dan dibagikan di seluruh entri.

Aspect
Entry.aspects[key]

Metadata JSON yang divalidasi dan cocok dengan AspectType, dilampirkan ke Entry melalui UpdateEntryRequest.

Diperbarui menggunakan update_mask dan aspect_keys sehingga pipeline terpisah tidak saling menimpa.

Yang akan Anda build

Dengan menggunakan skrip pendamping di codelabs/metadata-as-code-lab, Anda akan menjalankan dan memeriksa pipeline 7 tahap:

  1. schemas.py — Skema Pydantic ganda BaseModel (DarkDataExtractedMetadata dan DocumentGovernanceMetadata) dipasangkan 1:1 dengan template Knowledge Catalog AspectType.
  2. step2_provision.py — Penyediaan cetak biru kustom EntryGroup, EntryType, dan AspectType yang bersifat idempoten.
  3. step3_register_fileset.py — Upload LUM-LIG-DES-8G8J_manual.pdf ke Cloud Storage dan pendaftaran sebagai Fileset Entry yang diatur.
  4. step4_extract_metadata.py — Penemuan model Gemini unggulan yang dinamis dan ekstraksi PDF multimodal menggunakan google-genai.
  5. step5_attach_aspects.py, step6_search_catalog.py, & step7_verify_assertions.py — Lampiran aspek bedah, penelusuran katalog dengan backoff eksponensial, dan pernyataan bidang kontrol end-to-end.

Prasyarat & yang akan Anda butuhkan

  • Project Google Cloud dengan penagihan diaktifkan dan Google Cloud Shell (sudah diinstal dengan gcloud, git, python3, dan pip).
  • Izin IAM untuk mengelola resource Knowledge Catalog (roles/dataplex.admin), menyediakan bucket dan objek Cloud Storage (roles/storage.admin), dan memanggil Gemini Enterprise Agent Platform (roles/aiplatform.user).
  • Browser web seperti Google Chrome.

2. Penyiapan dan persyaratan

Buat clone repositori pendamping di Cloud Shell

Buka Konsol Google Cloud, luncurkan Cloud Shell, dan lakukan checkout jarang codelabs/metadata-as-code-lab, yang mencakup manual teknik PDF contoh (LUM-LIG-DES-8G8J_manual.pdf) dan semua skrip Python:

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

Mengonfigurasi variabel lingkungan

Tetapkan project ID, lokasi bidang kontrol regional, dan bucket Cloud Storage target di 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"

Mengaktifkan API dan menginstal dependensi

Aktifkan API Google Cloud yang diperlukan dan instal dependensi Python (google-genai, google-cloud-dataplex, pydantic, dan pandas) dari 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. Menentukan skema Pydantic dan template aspek

schemas.py menentukan dua kontrak pelengkap yang menyandingkan validasi Pydantic sisi klien dengan template Knowledge Catalog AspectType sisi server:

  1. DarkDataExtractedMetadata: Atribut operasional yang diekstrak dari PDF (judul dokumen, ontologi domain, tingkat bahaya keselamatan, asal penulisan/versi, ringkasan eksekutif, dan skor keyakinan ekstraksi).
  2. DocumentGovernanceMetadata: Kode kepatuhan terhadap peraturan (UL-153, FCC Part 15, CE-LVD, RoHS), pemilik pengelolaan, kebijakan retensi, dan string ID tabel referensi (lakehouse_cross_ref_table) untuk menautkan panduan PDF ke tabel inventaris hilir.

Periksa schemas.py

Pertama, DarkDataExtractedMetadata menggunakan batasan Pydantic Field (ge=0.0, le=1.0, yang berarti lebih besar/lebih kecil dari atau sama dengan, pada confidence_score) untuk membatasi output JSON 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.",
    )

Kedua, extracted_aspect_template mencerminkan nama kolom yang sama dan memetakan jenis str dan float Python ke record_fields string dan double Knowledge Catalog. Perhatikan bahwa kontrak protobuf AspectType.MetadataTemplate mewajibkan setiap kolom di record_fields mendeklarasikan bilangan bulat berbasis 1 yang unik dan positif index (1 hingga 7)—menghilangkan atau menduplikasi index akan menyebabkan create_aspect_type gagal dengan 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 ...
        },
    ],
}

Memvalidasi modul skema

Jalankan schemas.py untuk memverifikasi konfigurasi lingkungan Anda dan mengompilasi kedua skema:

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. Menyediakan namespace dan jenis aspek kustom

Sebelum mendaftarkan entri fileset atau melampirkan metadata, step2_provision.py menyediakan tiga resource bidang kontrol di Knowledge Catalog:

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

Penyediaan yang bersifat idempoten di step2_provision.py

Setiap panggilan pembuatan di step2_provision.py membungkus operasi yang berjalan lama (op.result()) dalam blok try / except AlreadyExists sehingga skrip dapat dijalankan kembali dengan aman tanpa gagal pada resource yang ada:

# 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)

Setelah metadata_template=extracted_aspect_template didaftarkan, Knowledge Catalog akan menerapkan skema di batas API—panggilan update_entry() berikutnya yang meneruskan string ke confidence_score (double) akan ditolak.

Jalankan step2_provision.py

Jalankan skrip penyediaan dan konfirmasi bahwa jenis aspek kustom terdaftar di wilayah Anda:

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. Mendaftarkan entri kumpulan file tidak terstruktur

Daripada membuat katalog berantakan dengan jutaan penunjuk file terisolasi, Knowledge Catalog mengelompokkan dokumen terkait di Cloud Storage (gs://YOUR_BUCKET/sop-pdfs/*.pdf) ke dalam Entri Kumpulan File logis—baik melalui pemindaian penemuan otomatis (DataScanServiceClient) atau pendaftaran terprogram langsung (CatalogServiceClient.create_entry).

Cara step3_register_fileset.py memetakan penyimpanan ke katalog

step3_register_fileset.py mengupload LUM-LIG-DES-8G8J_manual.pdf ke gs://${BUCKET_NAME}/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf dan mendaftarkan Entry yang diatur:

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,
)

Perhatikan peran berbeda dari dua kolom URI di Entry:

  • fully_qualified_name=fully_qualified_fileset_uri (f"gcs:{BUCKET_NAME}"): Menggunakan skema FQN kanonis gcs:{bucket_name} yang diperlukan oleh Knowledge Catalog untuk mengorelasikan entri katalog logis dengan bucket Cloud Storage yang mendasarinya.
  • entry_source.resource=VIRTUAL_STORAGE_URI: Menyimpan URI objek gs:// fisik yang diperiksa oleh pekerja ekstraksi hilir.

Jalankan 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. Mengekstrak metadata dokumen dengan Gemini

step4_extract_metadata.py membaca byte PDF mentah dan memanggil Gemini Enterprise Agent Platform (genai_client.models.generate_content) menggunakan dua pola utama:

1. Penemuan model unggulan dinamis

Daripada meng-hardcode string versi model yang tidak stabil, skrip mengkueri genai_client.models.list() dan mengurutkan kandidat aktif menurut (is_ga_channel, semantic_version_tuple) untuk memilih model flash dengan Ketersediaan Umum (GA) terbaru:

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. Ekstraksi multimodal yang dibatasi skema (Part.from_bytes + response_schema)

Meneruskan response_mime_type="application/json" dan response_schema=DarkDataExtractedMetadata (diikuti dengan DocumentGovernanceMetadata) membatasi decoding token langsung ke skema 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)

Jalankan 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. Melampirkan aspek yang divalidasi ke entri katalog

step5_attach_aspects.py mengikat payload JSON yang divalidasi (extracted_metadata.json dan governance_metadata.json) ke entri sop-manuals-fileset-lum8g8j melalui catalog_client.update_entry().

Mutasi aspek bedah di 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],
    )
)

Dengan meneruskan kedua cakupan update_mask={"paths": ["aspects"]} dan aspect_keys=[extracted_aspect_key, governance_aspect_key], mutasi akan dibatasi secara ketat untuk kedua kunci aspek ini—sehingga entry_source dan aspek apa pun yang dimiliki oleh tim lain tidak akan terpengaruh.

Jalankan 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

Verifikasi jalur ganda

  • Jalur 1 (Verifikasi CLI): Periksa entri dengan semua aspek terlampir melalui gcloud:
    gcloud dataplex entries describe sop-manuals-fileset-lum8g8j \
      --entry-group=dark-data-fileset-group \
      --location=$REGION \
      --view=ALL
    
  • Track 2 (Pemeriksaan UI Konsol):
    1. Buka Knowledge Catalog Search Console, telusuri LUM-LIG-DES-8G8J Unstructured SOP & Technical Manual Fileset (sop-manuals-fileset-lum8g8j), lalu pilih entri yang cocok dari hasil.
    2. Di bagian Tag dan aspek opsional, pastikan Dark Data Multimodal Extracted Metadata dan Document Governance & Inventory Cross-Reference Aspect menampilkan tingkat bahaya (MEDIUM), kode kepatuhan (UL-153, FCC Part 15, CE-LVD, RoHS), dan string tabel referensi silang (lakehouse_cross_ref_table) yang diekstrak.

8. Mengkueri data gelap yang diatur dalam katalog

Setelah aspek kustom dilampirkan, manual PDF tidak terstruktur di Cloud Storage dapat ditemukan melalui penelusuran Knowledge Catalog (catalog_client.search_entries()).

Polling search_entries() di step6_search_catalog.py

step6_search_catalog.py melakukan polling search_entries() dengan backoff eksponensial dan membaca kunci aspek yang dikanonikalisasi melalui .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')}")

Jalankan 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

Verifikasi jalur ganda

  • Jalur 1 (Penelusuran CLI): Kueri indeks penelusuran secara langsung melalui gcloud:
    gcloud dataplex entries search "name:sop-manuals-fileset-lum8g8j" --project=$PROJECT_ID
    
  • Track 2 (Penelusuran Bahasa Natural UI Konsol):
    1. Buka Search Console Knowledge Catalog dan telusuri LUM-LIG-DES-8G8J atau UL-153.
    2. Amati cara Knowledge Catalog menampilkan entri kumpulan file PDF Cloud Storage yang diatur dan aspek metadata yang dilampirkan.

9. Memverifikasi pernyataan tata kelola end-to-end

step7_verify_assertions.py menjalankan pernyataan deterministik terhadap respons bidang kontrol Knowledge Catalog langsung untuk memverifikasi bahwa EntryGroup, EntryType, kedua cetak biru kustom AspectType, payload aspek EntryView.ALL terikat (batasan confidence_score dan string lakehouse_cross_ref_table), dan penemuan indeks penelusuran berhasil:

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."

Jalankan 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. Membangun pipeline berbasis peristiwa

Meskipun menjalankan skrip Python secara interaktif di Cloud Shell sangat ideal untuk membuat dan menguji kontrak tata kelola Anda, lingkungan perusahaan menerima ribuan manual teknik PDF baru atau yang direvisi, sertifikat kepatuhan supplier, dan dokumen SOP setiap hari dari ERP, Product Lifecycle Management (PLM), dan portal vendor. Menjalankan skrip batch secara manual dengan cepat akan menciptakan titik buta tata kelola antara upload dokumen dan pengindeksan katalog.

Dalam produksi, tim platform mengoperasikan kode persis yang Anda jalankan di Langkah 4 dan 5 sebagai pipeline berbasis peristiwa tanpa interaksi:

Pipeline Data Gelap Berbasis Peristiwa

  1. Penyerapan Dokumen Berkelanjutan (Cloud Storage → Eventarc): Setiap kali manual PDF baru diupload atau revisi baru menggantikan objek yang ada di Cloud Storage, bucket akan memancarkan CloudEvent google.cloud.storage.object.v1.finalized yang berisi ID bucket, jalur objek, dan nomor generasi objek.
  2. Ekstraksi Multimodal Stateless (Eventarc → Cloud Run → Gemini Enterprise Agent Platform): Eventarc merutekan CloudEvent ke pekerja Cloud Run serverless yang memaketkan schemas.py, step4_extract_metadata.py, dan step5_attach_aspects.py. Pekerja mengalirkan byte PDF ke Gemini Enterprise Agent Platform dengan response_schema yang diterapkan, sehingga menjamin bahwa setiap atribut yang diekstrak sesuai dengan DarkDataExtractedMetadata dan DocumentGovernanceMetadata.
  3. Update Panel Kontrol Bedah (Cloud Run → Knowledge Catalog): Pekerja menyelesaikan Fileset induk Entry dan menjalankan catalog_client.update_entry() dengan update_mask={"paths": ["aspects"]} dan aspect_keys eksplisit. Meskipun puluhan dokumen selesai diproses secara bersamaan, setiap mutasi hanya memperbarui kunci aspek yang ditetapkan.
  4. Karantina Pengelola yang Dibatasi Tingkat Keyakinan: Jika PDF lama yang dipindai menghasilkan ekstraksi confidence_score di bawah nilai minimum operasional Anda (misalnya, < 0.85), worker akan menetapkan governance_status = "PENDING_STEWARD_REVIEW" pada aspek terlampir sehingga pengelola data dapat mengkueri Knowledge Catalog untuk aset dengan tingkat keyakinan rendah yang memerlukan peninjauan manual.

Cara perusahaan menerapkan pola ini dalam produksi

Kasus Penggunaan Enterprise

Cara Kerja Metadata-as-Code dalam Praktiknya

Dampak Bisnis & Operasional

Kesiapan Penarikan Produk & Audit Peraturan Otomatis
(Manufaktur, Hardware, & Energi)

Sistem kepatuhan menggabungkan aspek keamanan PDF tidak terstruktur (compliance_classifications, operational_hazard_level) dengan tabel inventaris SKU terstruktur (lakehouse_cross_ref_table) di BigQuery dan Lakehouse untuk Apache Iceberg.

Saat standar seperti UL-153 atau CE-LVD diperbarui, auditor dapat mengidentifikasi setiap SKU hardware dan lokasi gudang yang terpengaruh dalam hitungan detik, bukan membuka ribuan folder PDF secara manual.

Agen AI yang Berbasis Data & Prapenyaringan RAG
(Asisten Informasi Perusahaan)

Sebelum agen retrieval-augmented generation (RAG) di Gemini Enterprise Agent Platform menjawab pertanyaan teknisi lapangan, agen tersebut memfilter entri Knowledge Catalog menurut governance_status = "VERIFIED_PRODUCTION" dan version_provenance.

Mencegah asisten AI berhalusinasi atau mengutip draf engineering yang tidak digunakan lagi, SOP yang sudah tidak berlaku, atau manual pihak ketiga yang belum diverifikasi.

Pengayaan Serentak Multi-Tim
(Decentralized Data Mesh)

Beberapa pipeline independen memperkaya Fileset yang sama Entry: pekerja rekayasa AI memperbarui dark-data-extracted-metadata, Tim Hukum melampirkan kebijakan retensi melalui document-governance-aspect, dan Tim Keamanan melampirkan aspek sensitivitas DLP.

Karena cakupan UpdateEntryRequest berubah melalui aspect_keys, setiap tim domain men-deploy dan memperbarui pipeline metadatanya secara independen tanpa menimpa data tata kelola tim lain.

Evolusi Skema CI/CD melalui GitOps
(Platform & Data Engineering)

Tim platform menyimpan definisi schemas.py bersama Terraform google_dataplex_aspect_type di Git. Pull request memvalidasi bahwa setiap kolom Pydantic baru memiliki index berbasis 1 yang cocok dalam template AspectType sebelum di-deploy.

Menghilangkan perbedaan skema antara kode ekstraksi aplikasi dan bidang kontrol Knowledge Catalog di seluruh project dev, staging, dan prod.

11. Membersihkan lingkungan Anda

Di Katalog Pengetahuan, penampung induk dan template skema tidak dapat dihapus saat entri turunan masih mereferensikannya. cleanup.py menghapus resource dalam urutan dependensi terbalik yang ketat (Entry → EntryGroup → EntryType → AspectTypes → objek bucket Cloud Storage → file JSON sementara):

# 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()

Jalankan 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.

Hapus direktori repositori yang di-clone

Setelah cleanup.py selesai menghapus resource cloud, kembali ke direktori utama Anda dan hapus folder repositori devrel-demos yang di-clone dari Cloud Shell:

cd ~
rm -rf ~/devrel-demos

12. Selamat!

Anda telah membangun dan memverifikasi pipeline tata kelola Metadata-as-Code end-to-end yang mengubah PDF tidak terstruktur di Cloud Storage menjadi aset Knowledge Catalog yang dapat ditemukan dan sesuai skema menggunakan Gemini Enterprise Agent Platform.

Apa langkah selanjutnya?

  • Otomatiskan dengan Terraform: Kelola resource google_dataplex_aspect_type dan google_dataplex_entry_group secara deklaratif dalam pipeline CI/CD.
  • Men-deploy Eventarc + Cloud Run Worker: Buat step4_extract_metadata.py dan step5_attach_aspects.py dalam container menjadi layanan Cloud Run yang didorong oleh peristiwa.
  • Penggabungan Inventaris Hilir di BigQuery: Ekspor metadata tata kelola yang diekstrak (lakehouse_cross_ref_table) untuk menggabungkan atribut kepatuhan dokumen tidak terstruktur dengan tabel inventaris SKU terstruktur.

Dokumen referensi