1. บทนำ
ข้อมูลขององค์กรกว่า 80% อยู่ในรูปแบบที่ไม่มีโครงสร้าง เช่น คู่มือวิศวกรรม PDF, ขั้นตอนการปฏิบัติงานมาตรฐาน (SOP), ใบรับรองการปฏิบัติตามข้อกำหนด และแผนผังอุปกรณ์ที่จัดเก็บไว้ใน Cloud Storage เนื่องจากแคตตาล็อกแบบเดิมจะจัดทำดัชนีเฉพาะสคีมาตารางเชิงสัมพันธ์ เอกสารเหล่านี้จึงยังคงเป็น "Dark Data" ซึ่งมองไม่เห็นในการค้นหาระดับองค์กร ไม่ได้เชื่อมต่อกับตารางสินค้าคงคลังที่มีโครงสร้าง และไม่ได้รับการยืนยันว่าสอดคล้องกับกฎระเบียบ
เมื่อผู้ตรวจสอบหรือ AI Agent ถามว่า "SKU ของฮาร์ดแวร์ใดบ้างที่ต้องมีการรับรองความปลอดภัย UL-153 และระดับอันตรายจากความร้อนของฮาร์ดแวร์เหล่านั้นคืออะไร" แคตตาล็อกที่จัดทำดัชนีเฉพาะตาราง SQL จะตอบคำถามไม่ได้ ข้อเท็จจริงจะอยู่ในไฟล์ PDF ที่ไม่มีโครงสร้างใน Cloud Storage
โซลูชันด้านสถาปัตยกรรม: ข้อมูลเมตาแบบหลายรูปแบบในรูปแบบโค้ด
ใน Codelab นี้ คุณจะได้สร้างไปป์ไลน์Metadata-as-Code แบบครบวงจรใน Google Cloud ซึ่งจะเปลี่ยนคู่มือ PDF ที่ไม่มีโครงสร้างใน Cloud Storage ให้เป็นชิ้นงาน Knowledge Catalog ที่บังคับใช้สคีมาโดยใช้ Gemini Enterprise Agent Platform (Google GenAI SDK, google-genai)

- การลงทะเบียนชุดไฟล์ (
EntryGroupและEntry): จัดกลุ่ม PDF ที่ไม่มีโครงสร้างใน Cloud Storage เป็นรายการชุดไฟล์เชิงตรรกะที่มีการควบคุมใน Knowledge Catalog - การแยกข้อมูลหลายรูปแบบของ Gemini (สคีมา Pydantic): เรียกใช้แพลตฟอร์ม Agent ของ Gemini Enterprise ในไบต์ PDF ดิบพร้อมการตรวจสอบที่กำหนดได้
response_schema - การเชื่อมโยงแง่มุมของ Control Plane: แนบเพย์โหลด JSON ด้านการปฏิบัติงานและการปฏิบัติตามข้อกำหนดที่ตรวจสอบแล้วเป็นอินสแตนซ์
Aspectที่มีการพิมพ์อย่างเข้มงวดในรายการแคตตาล็อก - การค้นพบแคตตาล็อกแบบรวม: ทำให้ชุดไฟล์ PDF ที่ไม่มีโครงสร้างและข้อมูลเมตาที่ดึงออกมาค้นพบได้ผ่าน
SearchEntriesRequest
แนวคิดหลัก: Primitive ของ Control Plane ของ Knowledge Catalog
ลองนึกภาพว่าทีมของคุณจัดเก็บคู่มือผลิตภัณฑ์ในรูปแบบ PDF หลายร้อยรายการไว้ใน Cloud Storage หากต้องการให้ค้นหาและตรวจสอบไฟล์เหล่านั้นในแคตตาล็อกความรู้ได้ง่าย ให้คิดถึงองค์ประกอบที่ใช้สร้างสรรค์ทั้ง 5 อย่างเหมือนกับการจัดระเบียบคู่มือที่เป็นกระดาษในตู้เก็บเอกสารในสำนักงาน
EntryGroup(ตู้ล็อกสำหรับทีมเดียว): ตู้ที่มีล็อก เฉพาะเพื่อนร่วมทีมที่มีสิทธิ์ (roles/dataplex.entryCreator) เท่านั้นที่จะวางโฟลเดอร์ไว้ข้างในได้ คุณต้องนำทุกโฟลเดอร์ออกจากตู้ก่อนจึงจะนำตู้เองออกได้EntryType(ป้ายกำกับหมวดหมู่โฟลเดอร์): ป้ายกำกับที่บอกให้ผู้ใช้ทราบว่าโฟลเดอร์แสดงถึงชิ้นงานประเภทใด เช่น "คอลเล็กชันคู่มือ PDF" แทนที่จะเป็น "ตารางฐานข้อมูล"Entry(โฟลเดอร์ไฟล์ที่มีลิงก์พื้นที่เก็บข้อมูล): โฟลเดอร์แคตตาล็อกสำหรับคู่มือ PDF โฟลเดอร์จะเก็บการ์ดตำแหน่งที่ชี้ไปยังที่เก็บข้อมูล Cloud Storage (gs://...) ที่มีไฟล์ PDF จริงอยู่ แทนที่จะเก็บสำเนาที่เป็นกระดาษจำนวนมากAspectType(แบบฟอร์มรายการตรวจสอบเปล่า): แบบฟอร์มเปล่าที่นำกลับมาใช้ใหม่ได้พร้อมช่องที่พิมพ์ไว้ล่วงหน้า (เช่น "รายการตรวจสอบความปลอดภัย" ที่ขอoperational_hazard_levelเป็นข้อความและconfidence_scoreเป็นตัวเลขจาก0.0ถึง1.0) คุณสร้างแบบฟอร์มเปล่านี้เพียงครั้งเดียวและนำกลับมาใช้ใหม่ในโฟลเดอร์หลายพันโฟลเดอร์ได้Aspect(รายการตรวจสอบที่กรอกข้อมูลครบถ้วนแล้วซึ่งแนบมากับโฟลเดอร์): หลังจากที่แพลตฟอร์ม Agent ของ Gemini Enterprise อ่านคู่มือ PDF และกรอกข้อมูลในช่องว่างแล้ว ระบบจะคลิปรายการตรวจสอบที่กรอกข้อมูลครบถ้วนแล้วนั้นไว้ในโฟลเดอร์Entryเนื่องจากรายการตรวจสอบแต่ละรายการมีคีย์ของตัวเอง (aspect_keys) ทีมวิศวกรรมและทีมกฎหมายจึงสามารถแนบรายการตรวจสอบของตนเองลงในโฟลเดอร์เดียวกันได้โดยไม่ต้องเขียนทับงานของกันและกัน
แหล่งข้อมูลระดับภูมิภาคทั้ง 5 รายการจะอยู่ใน projects/{project}/locations/{location}/
เส้นทางแบบสัมบูรณ์และแบบสัมพัทธ์ | บทบาทใน Knowledge Catalog | การลบและกฎ IAM |
| คอนเทนเนอร์เชิงตรรกะที่จัดกลุ่มรายการและควบคุมการเข้าถึงของทีม ( | ต้องไม่มี |
| คำจำกัดความหมวดหมู่สำหรับคลาสของชิ้นงาน ( | ลบได้หลังจากนำรายการทั้งหมดที่ใช้ประเภทนี้ออกแล้วเท่านั้น |
| ระเบียนแคตตาล็อกที่ลิงก์ URI ของ Cloud Storage จริง ( | อยู่ใน |
| เทมเพลตสคีมาที่นำกลับมาใช้ใหม่ได้ซึ่งกำหนด | สร้างครั้งเดียวต่อภูมิภาคและแชร์ในรายการต่างๆ |
| ข้อมูลเมตา JSON ที่ผ่านการตรวจสอบซึ่งตรงกับ | อัปเดตโดยใช้ |
สิ่งที่คุณจะสร้าง
การใช้สคริปต์เสริมใน codelabs/metadata-as-code-lab คุณจะเรียกใช้และตรวจสอบไปป์ไลน์ 7 ขั้นตอนได้
schemas.py— สคีมา PydanticBaseModelแบบคู่ (DarkDataExtractedMetadataและDocumentGovernanceMetadata) ที่จับคู่แบบ 1:1 กับเทมเพลต Knowledge CatalogAspectTypestep2_provision.py— การจัดสรรแบบนิจพลของพิมพ์เขียวEntryGroup,EntryTypeและAspectTypestep3_register_fileset.py— อัปโหลดLUM-LIG-DES-8G8J_manual.pdfไปยัง Cloud Storage และลงทะเบียนเป็น Fileset ที่มีการควบคุมEntrystep4_extract_metadata.py- การค้นหาโมเดล Gemini เรือธงแบบไดนามิกและการแยก PDF แบบมัลติโมดัลโดยใช้google-genaistep5_attach_aspects.py,step6_search_catalog.pyและstep7_verify_assertions.py- การแนบแง่มุมการผ่าตัด การค้นหาแคตตาล็อกแบบ Exponential Backoff และการยืนยันระนาบควบคุมแบบครบวงจร
สิ่งที่ต้องดำเนินการก่อนและสิ่งที่คุณต้องมี
- โปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงินและ Google Cloud Shell (ติดตั้ง
gcloud,git,python3และpipไว้ล่วงหน้า) - สิทธิ์ IAM ในการจัดการทรัพยากร Knowledge Catalog (
roles/dataplex.admin) จัดสรร Bucket และออบเจ็กต์ Cloud Storage (roles/storage.admin) และเรียกใช้ Gemini Enterprise Agent Platform (roles/aiplatform.user) - เว็บเบราว์เซอร์ เช่น Google Chrome
2. การตั้งค่าและข้อกำหนด
โคลนที่เก็บคู่ใน Cloud Shell
เปิดคอนโซล Google Cloud เปิดใช้ Cloud Shell และทำการชำระเงินแบบ Sparse ของ codelabs/metadata-as-code-lab ซึ่งรวมถึงคู่มือวิศวกรรม PDF ตัวอย่าง (LUM-LIG-DES-8G8J_manual.pdf) และสคริปต์ 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
กำหนดค่าตัวแปรสภาพแวดล้อม
ตั้งค่ารหัสโปรเจ็กต์ ตำแหน่งของ Control Plane ระดับภูมิภาค และ Bucket Cloud Storage เป้าหมายใน 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"
เปิดใช้ API และติดตั้งการขึ้นต่อกัน
เปิดใช้ API ของ Google Cloud ที่จำเป็นและติดตั้งการอ้างอิง Python (google-genai, google-cloud-dataplex, pydantic และ pandas) จาก 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. กำหนดสคีมา Pydantic และเทมเพลตแง่มุม
schemas.py กำหนดสัญญาเสริม 2 ฉบับที่จับคู่การตรวจสอบ Pydantic ฝั่งไคลเอ็นต์กับเทมเพลตแคตตาล็อกความรู้ AspectTypeฝั่งเซิร์ฟเวอร์ ดังนี้
DarkDataExtractedMetadata: แอตทริบิวต์การปฏิบัติงานที่ดึงมาจาก PDF (ชื่อเอกสาร ออนโทโลยีโดเมน ระดับอันตรายด้านความปลอดภัย แหล่งที่มาของการเขียน/เวอร์ชัน ข้อมูลสรุปสำหรับผู้บริหาร และคะแนนความเชื่อมั่นในการแยกข้อมูล)DocumentGovernanceMetadata: รหัสการปฏิบัติตามกฎระเบียบ (UL-153, FCC Part 15, CE-LVD, RoHS), เจ้าของความรับผิดชอบ, นโยบายการเก็บรักษา และสตริงตัวระบุตารางอ้างอิง (lakehouse_cross_ref_table) สำหรับการลิงก์คู่มือ PDF กับตารางสินค้าคงคลังดาวน์สตรีม
ตรวจสอบ schemas.py
ก่อนอื่น DarkDataExtractedMetadata ใช้ข้อจำกัดของ Pydantic Field (ge=0.0, le=1.0 ซึ่งหมายถึงมากกว่า/น้อยกว่าหรือเท่ากับใน confidence_score) เพื่อจำกัดเอาต์พุต JSON ของแพลตฟอร์ม Gemini Enterprise Agent ดังนี้
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.",
)
ประการที่สอง extracted_aspect_template จะทำซ้ำชื่อฟิลด์ที่แน่นอนเหล่านั้นและแมปประเภท str และ float ของ Python กับ string และ double ของ Knowledge Catalog record_fields โปรดทราบว่าสัญญา Protobuf ของ AspectType.MetadataTemplate กำหนดให้ทุกฟิลด์ใน record_fields ต้องประกาศจำนวนเต็มฐาน 1 ที่ไม่ซ้ำกันและเป็นบวกอย่างเคร่งครัด index (1 ถึง 7) การละเว้นหรือทำซ้ำ index จะทำให้ create_aspect_type ล้มเหลวโดยมี 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 ...
},
],
}
ตรวจสอบโมดูลสคีมา
เรียกใช้ schemas.py เพื่อยืนยันการกำหนดค่าสภาพแวดล้อมและคอมไพล์ทั้ง 2 สคีมา
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. จัดสรรเนมสเปซและประเภทแง่มุมที่กำหนดเอง
ก่อนลงทะเบียนรายการชุดไฟล์หรือแนบข้อมูลเมตา step2_provision.py จะจัดสรรทรัพยากรระนาบควบคุม 3 รายการในแคตตาล็อกความรู้ ดังนี้
EntryGroup:dark-data-fileset-groupEntryType:unstructured-pdf-filesetAspectTypeBlueprint:dark-data-extracted-metadataและdocument-governance-aspect
การจัดสรรที่ไม่มีผลข้างเคียงใน step2_provision.py
การเรียกใช้การสร้างแต่ละครั้งใน step2_provision.py จะห่อหุ้มการดำเนินการที่ใช้เวลานาน (op.result()) ไว้ในบล็อก try / except AlreadyExists เพื่อให้สคริปต์สามารถเรียกใช้ซ้ำได้อย่างปลอดภัยโดยไม่ล้มเหลวกับทรัพยากรที่มีอยู่
# 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)
เมื่อลงทะเบียน metadata_template=extracted_aspect_template แล้ว Knowledge Catalog จะบังคับใช้สคีมาที่ขอบเขต API โดยจะปฏิเสธการเรียกใช้ update_entry() ครั้งต่อๆ ไปที่ส่งสตริงไปยัง confidence_score (double)
เรียกใช้ step2_provision.py
เรียกใช้สคริปต์การจัดสรรและยืนยันว่าได้ลงทะเบียนประเภทแง่มุมที่กำหนดเองในภูมิภาคของคุณแล้ว
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. ลงทะเบียนรายการไฟล์เซ็ตที่ไม่มีโครงสร้าง
แคตตาล็อกความรู้จะจัดกลุ่มเอกสารที่เกี่ยวข้องใน Cloud Storage (gs://YOUR_BUCKET/sop-pdfs/*.pdf) เป็นรายการชุดไฟล์เชิงตรรกะแทนที่จะทำให้แคตตาล็อกรกด้วยตัวชี้ไฟล์ที่แยกกันนับล้านรายการ ไม่ว่าจะผ่านการสแกนการค้นพบอัตโนมัติ (DataScanServiceClient) หรือการลงทะเบียนแบบเป็นโปรแกรมโดยตรง (CatalogServiceClient.create_entry)
วิธีที่ step3_register_fileset.py แมปพื้นที่เก็บข้อมูลกับแคตตาล็อก
step3_register_fileset.pyอัปโหลด LUM-LIG-DES-8G8J_manual.pdf ไปยัง gs://${BUCKET_NAME}/sop-pdfs/LUM-LIG-DES-8G8J_manual.pdf และลงทะเบียน 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,
)
โปรดสังเกตบทบาทที่แตกต่างกันของฟิลด์ URI ทั้ง 2 รายการใน Entry
fully_qualified_name=fully_qualified_fileset_uri(f"gcs:{BUCKET_NAME}"): ใช้รูปแบบgcs:{bucket_name}FQN ที่เป็น Canonical ซึ่ง Knowledge Catalog กำหนดให้ใช้เพื่อเชื่อมโยงรายการแคตตาล็อกเชิงตรรกะกับที่เก็บข้อมูล Cloud Storage ที่อยู่เบื้องหลังentry_source.resource=VIRTUAL_STORAGE_URI: จัดเก็บ URI ของออบเจ็กต์gs://จริงที่ผู้ปฏิบัติงานการแยกข้อมูลดาวน์สตรีมตรวจสอบ
เรียกใช้ 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. แยกข้อมูลเมตาของเอกสารด้วย Gemini
step4_extract_metadata.py จะอ่านไบต์ PDF ดิบและเรียกใช้แพลตฟอร์ม Agent ของ Gemini Enterprise (genai_client.models.generate_content) โดยใช้รูปแบบสำคัญ 2 รูปแบบ ได้แก่
1. การค้นหารุ่นเรือธงแบบไดนามิก
สคริปต์จะค้นหา genai_client.models.list() และจัดเรียงโมเดลที่ใช้งานอยู่ตาม (is_ga_channel, semantic_version_tuple) เพื่อเลือกโมเดล flash ที่พร้อมให้บริการแก่บุคคลทั่วไป (GA) รุ่นล่าสุดแทนที่จะเขียนสตริงเวอร์ชันของโมเดลที่เปราะบางลงในโค้ด
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. การแยกข้อมูลมัลติโมดัลที่จำกัดด้วยสคีมา (Part.from_bytes + response_schema)
การส่ง response_mime_type="application/json" และ response_schema=DarkDataExtractedMetadata (ตามด้วย DocumentGovernanceMetadata) จะจำกัดการถอดรหัสโทเค็นโดยตรงไปยังสคีมา 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)
เรียกใช้ 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. แนบแง่มุมที่ตรวจสอบแล้วกับข้อมูลแคตตาล็อก
step5_attach_aspects.py จะเชื่อมโยงเพย์โหลด JSON ที่ตรวจสอบแล้ว (extracted_metadata.json และ governance_metadata.json) กับรายการ sop-manuals-fileset-lum8g8j ผ่าน catalog_client.update_entry()
การเปลี่ยนแปลงลักษณะการผ่าตัดใน 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],
)
)
การส่งทั้งขอบเขต update_mask={"paths": ["aspects"]} และ aspect_keys=[extracted_aspect_key, governance_aspect_key] จะจำกัดการเปลี่ยนแปลงอย่างเคร่งครัดไว้ที่คีย์ของ 2 ด้านนี้ โดยจะไม่แตะต้อง entry_source และแง่มุมใดๆ ที่เป็นของทีมอื่นๆ
เรียกใช้ 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
การยืนยันแบบ 2 เส้นทาง
- แทร็ก 1 (การยืนยัน CLI): ตรวจสอบรายการที่มีแง่มุมทั้งหมดที่แนบมาผ่าน
gcloud:gcloud dataplex entries describe sop-manuals-fileset-lum8g8j \ --entry-group=dark-data-fileset-group \ --location=$REGION \ --view=ALL - แทร็กที่ 2 (การตรวจสอบ UI ของคอนโซล):
- เปิด Search Console ของแคตตาล็อกความรู้ ค้นหา LUM-LIG-DES-8G8J Unstructured SOP & Technical Manual Fileset (
sop-manuals-fileset-lum8g8j) แล้วเลือกรายการที่ตรงกันจากผลการค้นหา - ในส่วนแท็กและแง่มุมที่ไม่บังคับ ให้ตรวจสอบว่าทั้งข้อมูลเมตาที่แยกจากข้อมูลมืดแบบมัลติโมดัลและแง่มุมการกำกับดูแลเอกสารและการอ้างอิงโยงสินค้าคงคลังแสดงระดับอันตราย (
MEDIUM), รหัสการปฏิบัติตามข้อกำหนด (UL-153, FCC Part 15, CE-LVD, RoHS) และสตริงตารางการอ้างอิงโยง (lakehouse_cross_ref_table)
- เปิด Search Console ของแคตตาล็อกความรู้ ค้นหา LUM-LIG-DES-8G8J Unstructured SOP & Technical Manual Fileset (
8. ค้นหาข้อมูลมืดที่มีการควบคุมในแคตตาล็อก
เมื่อแนบแง่มุมที่กำหนดเองแล้ว คู่มือ PDF ที่ไม่มีโครงสร้างใน Cloud Storage จะค้นพบได้ผ่านการค้นหาในแคตตาล็อกความรู้ (catalog_client.search_entries())
การสำรวจ search_entries() ใน step6_search_catalog.py
step6_search_catalog.py polls search_entries() โดยใช้ Exponential Backoff และอ่านคีย์แง่มุมที่กำหนดหน้า Canonical ผ่าน .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')}")
เรียกใช้ 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
การยืนยันแบบ 2 เส้นทาง
- แทร็ก 1 (การค้นหา CLI): ค้นหาดัชนีการค้นหาโดยตรงผ่าน
gcloudgcloud dataplex entries search "name:sop-manuals-fileset-lum8g8j" --project=$PROJECT_ID - แทร็กที่ 2 (การค้นหาด้วยภาษาธรรมชาติใน UI ของคอนโซล):
- เปิด Search Console ของแคตตาล็อกความรู้ แล้วค้นหา
LUM-LIG-DES-8G8JหรือUL-153 - ดูวิธีที่ Knowledge Catalog แสดงรายการชุดไฟล์ PDF ของ Cloud Storage ที่มีการควบคุมและลักษณะข้อมูลเมตาที่แนบมา
- เปิด Search Console ของแคตตาล็อกความรู้ แล้วค้นหา
9. ยืนยันการยืนยันการกำกับดูแลแบบครบวงจร
step7_verify_assertions.py เรียกใช้การยืนยันที่กำหนดได้กับคำตอบของระนาบควบคุม แคตตาล็อกความรู้ แบบเรียลไทม์เพื่อยืนยันว่า EntryGroup, EntryType, ทั้งพิมพ์เขียวที่กำหนดเอง AspectType, เพย์โหลดของแง่มุมที่เชื่อมโยง EntryView.ALL (ขอบเขต confidence_score และสตริง lakehouse_cross_ref_table) และการค้นพบดัชนีการค้นหาทั้งหมดสำเร็จ:
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."
เรียกใช้ 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. ออกแบบไปป์ไลน์ที่ขับเคลื่อนด้วยเหตุการณ์
แม้ว่าการเรียกใช้สคริปต์ Python แบบอินเทอร์แอกทีฟใน Cloud Shell จะเหมาะสำหรับการสร้างและทดสอบสัญญาการกำกับดูแล แต่สภาพแวดล้อมขององค์กรจะได้รับคู่มือวิศวกรรม PDF ใหม่หรือที่แก้ไขแล้ว ใบรับรองการปฏิบัติตามข้อกำหนดของซัพพลายเออร์ และเอกสาร SOP หลายพันรายการทุกวันจาก ERP, Product Lifecycle Management (PLM) และพอร์ทัลของผู้ให้บริการ การเรียกใช้สคริปต์แบบกลุ่มด้วยตนเองจะสร้างจุดบอดด้านการกำกับดูแลระหว่างการอัปโหลดเอกสารและการจัดทำดัชนีแคตตาล็อกอย่างรวดเร็ว
ในสภาพแวดล้อมการใช้งานจริง ทีมแพลตฟอร์มจะดำเนินการกับโค้ดที่แน่นอนที่คุณรันในขั้นตอนที่ 4 และ 5 เป็นไปป์ไลน์แบบไม่ต้องดำเนินการใดๆ และขับเคลื่อนด้วยเหตุการณ์ ดังนี้

- การนำเข้าเอกสารอย่างต่อเนื่อง (
Cloud Storage→Eventarc): เมื่อใดก็ตามที่มีการอัปโหลดคู่มือ PDF ใหม่หรือการแก้ไขใหม่เขียนทับออบเจ็กต์ที่มีอยู่ใน Cloud Storage Bucket จะปล่อย CloudEventgoogle.cloud.storage.object.v1.finalizedที่มีตัวระบุ Bucket, เส้นทางออบเจ็กต์ และหมายเลขออบเจ็กต์รุ่น - การแยกข้อมูลหลายรูปแบบแบบไม่เก็บสถานะ (
Eventarc→Cloud Run→Gemini Enterprise Agent Platform): Eventarc จะกำหนดเส้นทาง CloudEvent ไปยัง Worker Cloud Run แบบไร้เซิร์ฟเวอร์ที่แพ็กเกจschemas.py,step4_extract_metadata.pyและstep5_attach_aspects.pyWorker จะสตรีมไบต์ PDF ไปยังแพลตฟอร์ม Agent ของ Gemini Enterprise โดยมีresponse_schemaบังคับใช้ ซึ่งรับประกันว่าแอตทริบิวต์ที่แยกออกมาทั้งหมดจะเป็นไปตามDarkDataExtractedMetadataและDocumentGovernanceMetadata - การอัปเดตระนาบควบคุมการผ่าตัด (
Cloud Run→Knowledge Catalog): Worker จะแก้ไข Fileset หลักEntryและเรียกใช้catalog_client.update_entry()ด้วยupdate_mask={"paths": ["aspects"]}และaspect_keysที่ชัดเจน แม้ว่าเอกสารหลายสิบฉบับจะประมวลผลเสร็จพร้อมกัน แต่การเปลี่ยนแปลงแต่ละครั้งจะอัปเดตเฉพาะคีย์แง่มุมที่กำหนดเท่านั้น - การกักกันผู้ดูแลที่มีความน่าเชื่อถือ: หาก PDF เดิมที่สแกนแล้วให้ผลลัพธ์การแยกข้อมูล
confidence_scoreต่ำกว่าเกณฑ์การปฏิบัติงาน (เช่น< 0.85) ผู้ปฏิบัติงานจะตั้งค่าgovernance_status = "PENDING_STEWARD_REVIEW"ในแง่มุมที่แนบมาเพื่อให้ผู้ดูแลข้อมูลสามารถค้นหา Knowledge Catalog สำหรับชิ้นงานที่มีความน่าเชื่อถือต่ำซึ่งต้องมีการตรวจสอบจากเจ้าหน้าที่
วิธีที่องค์กรใช้รูปแบบนี้ในการใช้งานจริง
กรณีการใช้งานระดับองค์กร | วิธีการทำงานของข้อมูลเมตาเป็นโค้ดในทางปฏิบัติ | ผลกระทบทางธุรกิจและการปฏิบัติงาน |
การตรวจสอบด้านกฎระเบียบอัตโนมัติและความพร้อมในการเรียกคืน | ระบบการปฏิบัติตามข้อกำหนดจะรวมด้านความปลอดภัยของ PDF ที่ไม่มีโครงสร้าง ( | เมื่อมีการอัปเดตมาตรฐาน เช่น |
เอเจนต์ AI ที่อิงตามข้อมูลจริงและการกรองล่วงหน้าของ RAG | ก่อนที่ Agent แบบ Retrieval Augmented Generation (RAG) ในแพลตฟอร์ม Agent ของ Gemini Enterprise จะตอบคำถามของวิศวกรภาคสนาม Agent จะกรองรายการแคตตาล็อกความรู้ตาม | ป้องกันไม่ให้ผู้ช่วย AI สร้างข้อมูลที่ไม่ถูกต้องหรืออ้างอิงร่างวิศวกรรมที่เลิกใช้งานแล้ว, SOP ที่หมดอายุ หรือคู่มือของบุคคลที่สามที่ยังไม่ได้รับการยืนยัน |
การเพิ่มคุณค่าแบบพร้อมกันหลายทีม | ไปป์ไลน์อิสระหลายรายการจะเพิ่มคุณค่าให้กับชุดไฟล์เดียวกัน | เนื่องจาก |
การพัฒนาสคีมา CI/CD ผ่าน GitOps | ทีมแพลตฟอร์มจัดเก็บ | ขจัดความคลาดเคลื่อนของสคีมาระหว่างโค้ดการแยกข้อมูลแอปพลิเคชันกับระนาบควบคุมของแคตตาล็อกความรู้ในโปรเจ็กต์ |
11. การล้างข้อมูลในสภาพแวดล้อม
ในแคตตาล็อกความรู้ คุณจะลบคอนเทนเนอร์หลักและเทมเพลตสคีมาไม่ได้ในขณะที่รายการย่อยยังอ้างอิงถึงคอนเทนเนอร์หลักและเทมเพลตสคีมาเหล่านั้น cleanup.py จะลบทรัพยากรตามลำดับการอ้างอิงย้อนกลับที่เข้มงวด (Entry → EntryGroup → EntryType → AspectTypes → ออบเจ็กต์ใน Bucket ของ Cloud Storage → ไฟล์ 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()
เรียกใช้ 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.
นำไดเรกทอรีที่เก็บที่โคลนออก
หลังจาก cleanup.py ลบทรัพยากรในระบบคลาวด์เสร็จแล้ว ให้กลับไปที่ไดเรกทอรีหน้าแรกและนำโฟลเดอร์ที่เก็บ devrel-demos ที่โคลนไว้ออกจาก Cloud Shell โดยใช้คำสั่งต่อไปนี้
cd ~
rm -rf ~/devrel-demos
12. ยินดีด้วย
คุณได้สร้างและยืนยันไปป์ไลน์การกํากับดูแลข้อมูลเมตาเป็นโค้ดแบบครบวงจรที่เปลี่ยน PDF ที่ไม่มีโครงสร้างใน Cloud Storage ให้เป็นชิ้นงานแคตตาล็อกความรู้ที่ค้นพบได้และบังคับใช้สคีมาโดยใช้ Gemini Enterprise Agent Platform
ต้องทำอะไรต่อ
- ทำงานอัตโนมัติด้วย Terraform: จัดการทรัพยากร
google_dataplex_aspect_typeและgoogle_dataplex_entry_groupแบบประกาศในไปป์ไลน์ CI/CD - ติดตั้งใช้งาน Eventarc + Worker ของ Cloud Run: สร้างคอนเทนเนอร์ให้กับ
step4_extract_metadata.pyและstep5_attach_aspects.pyเป็นบริการ Cloud Run ที่ขับเคลื่อนด้วยเหตุการณ์ - การรวมข้อมูลสินค้าคงคลังขั้นปลายใน BigQuery: ส่งออกข้อมูลเมตาด้านการกำกับดูแลที่แยกออกมา (
lakehouse_cross_ref_table) เพื่อรวมแอตทริบิวต์การปฏิบัติตามข้อกำหนดของเอกสารที่ไม่มีโครงสร้างกับตารางสินค้าคงคลัง SKU ที่มีโครงสร้าง