This repository contains a production-grade Apache Beam Bulk ML Inference (RunInference) demonstration that chains remote Gemini foundation models (via Beam's built-in GeminiModelHandler) with local GPU safety moderation using ShieldGemma 2 (google/shieldgemma-2-4b-it) on Google Cloud Dataflow.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BigQuery Source: Google Trends Public Dataset β SELECT * FROM `bigquery-public-data.google_trends.top_terms`
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β beam.combiners.Sample.FixedSizePerKey(10) β Pre-shuffle combiner lifting (top 10 terms per dma_name)
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RunInference Stage 1: Built-in GeminiModelHandler β generate_from_string + JSON response_schema + Flex API
β + with_preprocess_fn / with_postprocess_fn β Emits: {city, terms, summary, image_prompt}
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β (No CoGroupByKey shuffle!)
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RunInference Stage 2: Built-in GeminiModelHandler β generate_image_from_strings_and_images (gemini-2.5-flash-image)
β + with_preprocess_fn / with_postprocess_fn β Emits: {city, summary, image_prompt, image_bytes}
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β (No CoGroupByKey shuffle!)
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RunInference Stage 3: Local ShieldGemma 2 (Vectorized) β ShieldGemma2ForImageClassification (B*P batched forward pass)
β + Right-Fitting GPU Resource Hints + .with_exception_ β Evaluates: dangerous, sexual, violence policies
β handling() (RunInferenceDLQ) β
βββββββββββββββ¬ββββββββββββββββββββββββββββββ¬βββββββββββββ
β β Exceptions (DLQ)
βΌ βΌ
βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
β β
Approved GCS Bucket β β π¨ Quarantine GCS Bucket β β π Quarantine DLQ Path β
β (Passed ShieldGemma 2) β β (Policy Violations) β β (Inference Exceptions) β
βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
This project incorporates architectural recommendations for production ML pipelines on Apache Beam and Cloud Dataflow:
-
Pre-Shuffle Combiner Lifting (
Sample.FixedSizePerKey(10)): Instead of usingGroupByKey()to collect all rows per Designated Market Area (DMA) before slicing top terms, we usebeam.combiners.Sample.FixedSizePerKey(10)so mapper workers aggregate top terms locally before shuffle, reducing network transfer by orders of magnitude on large BigQuery tables. -
Zero-Shuffle Linear Chaining (
with_preprocess_fn/with_postprocess_fn): Standard multi-stage ML pipelines often fork into separate PCollections and join results back usingCoGroupByKey(). This forces high-resolution generated images (hundreds of KB to megabytes each) across the Dataflow shuffle service. By chaining stages sequentially using Beam's.with_preprocess_fn()and.with_postprocess_fn(), element metadata is preserved through composite keys with zero intermediate network shuffle. -
Built-in
GeminiModelHandlerwith Structured Outputs & Flex API: Uses Beam's officialapache_beam.ml.inference.gemini_inference.GeminiModelHandlerwith Vertex AI Structured Outputs (response_schema), guaranteeing strict JSON formatting directly from the model without fragile regex or string parsing. Also supports the Vertex Flex API (use_vertex_flex_api=True) for high-throughput batch workloads. -
Local Vectorized GPU Safety Moderation (
ShieldGemma 2): Runs Google'sgoogle/shieldgemma-2-4b-it(ShieldGemma2ForImageClassification) locally on worker GPUs withlarge_model=TrueandMultiProcessSharedto share loaded model weights across worker threads. Employstorch.bfloat16precision and explicit post-inference memory reclamation (gc.collect()+torch.cuda.empty_cache()) to prevent GPU CUDA OOMs. -
Dataflow Right-Fitting GPU Resource Hints: Decorates the
ShieldGemma 2transform withmin_ram="32GB"andaccelerator="type:nvidia-l4;count:1;install-nvidia-driver"so expensive GPU worker machines are only allocated to the vision safety stage, while CPU-only transforms (BigQuery read, Gemini API calls, GCS sinks) execute on standard CPU workers. -
Native
RunInferenceDead-Letter Queue (RunInferenceDLQ): Employs.with_exception_handling()onRunInferenceto safely catch model inference exceptions (such as corrupted images, transient CUDA faults, or rate limits) into a dedicated DLQ PCollection without failing the overall pipeline. -
Fail-Closed Conditional GCS Routing: If an image violates safety policies or cannot be verified (e.g., missing model token), it is strictly routed to the Quarantine GCS Bucket rather than failing open into production.
ApacheBeam-Dataflow-Local&Remote Inference-Demo/
βββ README.md # Project documentation and architecture guide
βββ LICENSE # Apache 2.0 License
βββ .gitignore # Git ignore rules for Python, Beam, and Jupyter
βββ notebooks/
β βββ beam_bulk_ml_inference_gemini_shieldgemma.ipynb # Production Google Colab notebook
βββ pipeline/ # Modular production script for headless execution
βββ __init__.py
βββ main.py # Main pipeline entrypoint with CLI arguments
βββ requirements.txt # Worker dependencies for Dataflow and local environments
Ensure you have an active GCP project with the following APIs enabled:
- Cloud Dataflow API (
dataflow.googleapis.com) - Vertex AI API (
aiplatform.googleapis.com) - BigQuery API (
bigquery.googleapis.com) - Google Cloud Storage (
storage.googleapis.com)
Create two Google Cloud Storage buckets (or folders within a bucket):
- Primary / Safe Bucket:
gs://<YOUR_BUCKET_NAME>/bulk_inference_demo/safe_output - Quarantine Bucket:
gs://<YOUR_BUCKET_NAME>/bulk_inference_demo/quarantine_output
ShieldGemma 2 is a gated model:
- Visit Hugging Face: google/shieldgemma-2-4b-it and accept the terms of use.
- Generate a Read Token at Hugging Face Settings > Tokens.
- If running in Google Colab, store this token in Colab Secrets (the π icon) as
HF_TOKEN. If running via CLI, set the environment variable:export HF_TOKEN="your_hugging_face_read_token"
The easiest way to explore this pipeline interactively is via Google Colab:
- Open the notebook in Colab.
- Select a GPU runtime (Runtime > Change runtime type > T4 or L4 GPU).
- Set your
PROJECT_ID,GCS_BUCKET,GCS_UNSAFE_BUCKET, andHF_TOKENin Step 2. - Run all cells to execute the pipeline and view the visual safety audit in Step 6.
Run a quick end-to-end smoke test on a small subset of BigQuery Google Trends data (--query_limit=5) locally on your machine:
# Clone the repository
git clone "https://github.com/ashwin-sampathkumar/ApacheBeam-Dataflow-Local&Remote Inference-Demo.git"
cd "ApacheBeam-Dataflow-Local&Remote Inference-Demo"
# Install dependencies
pip install -r pipeline/requirements.txt
# Run locally with DirectRunner
python -m pipeline.main \
--runner=DirectRunner \
--project=YOUR_GCP_PROJECT_ID \
--output_path=gs://YOUR_BUCKET_NAME/safe_output \
--unsafe_output_path=gs://YOUR_BUCKET_NAME/quarantine_output \
--query_limit=5Submit the full distributed bulk ML pipeline to Google Cloud Dataflow with Right-Fitting L4 GPU worker accelerators:
python -m pipeline.main \
--runner=DataflowRunner \
--project=YOUR_GCP_PROJECT_ID \
--region=us-central1 \
--temp_location=gs://YOUR_BUCKET_NAME/temp \
--staging_location=gs://YOUR_BUCKET_NAME/staging \
--output_path=gs://YOUR_BUCKET_NAME/bulk_inference_demo/safe_output \
--unsafe_output_path=gs://YOUR_BUCKET_NAME/bulk_inference_demo/quarantine_output \
--requirements_file=pipeline/requirements.txt \
--machine_type=g2-standard-8 \
--dataflow_service_options="worker_accelerator=type:nvidia-l4;count:1;install-nvidia-driver" \
--experiments=use_runner_v2,enable_recommendation_service \
--job_name="dataflow-gemini-shieldgemma-trends-$(date +%Y%m%d-%H%M%S)"The pipeline evaluates each generated image against three core safety policies:
dangerous: Content encouraging or depicting hazardous, self-harm, or harmful acts.sexual: Sexually explicit imagery.violence: Graphic or severe violence.
Each output JSON record in GCS includes full evaluation metadata:
{
"city": "Austin, TX",
"status": "safe",
"terms": ["Austin City Limits Music Festival", "South by Southwest", "..."],
"summary": "Austin pulses with live indie music, food-truck culture, and tech innovation...",
"image_prompt": "A warm cinematic twilight view over Lady Bird Lake with festival lights in the background...",
"image_source": "gemini-2.5-flash-image",
"image_gcs_uri": "gs://YOUR_BUCKET/safe_output/images/Austin_TX.png",
"safety_check": {
"is_safe": true,
"violated_policies": [],
"policy_scores": {
"dangerous": 0.0012,
"sexual": 0.0004,
"violence": 0.0008
},
"threshold": 0.5,
"evaluation_mode": "shieldgemma-2-bfloat16"
}
}- BigQuery Public Data: The Google Trends public dataset is queried with partition filtering on
week >= DATE_SUB(CURRENT_DATE(), INTERVAL 6 MONTH)to keep bytes scanned minimal. - Vertex AI Gemini Quotas: If running large-scale bulk jobs, consider setting
--use_vertex_flex_apito route requests through the Flex API for lower cost and batch-optimized quotas. - Dataflow GPUs: Right-Fitting ensures GPU charges only accrue for the
RunShieldGemma2SafetyCheckstage onnvidia-l4accelerators (g2-standard-8), while preprocessing and I/O transforms scale on standard CPU instances.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.