Skip to main content

Overview

GenWealth is a comprehensive demo application for a fictional financial services company that demonstrates how to build trustworthy Gen AI features into existing applications using AlloyDB AI, Vertex AI, Cloud Run, and Cloud Functions. GenWealth Logo

Use Case: Knowledge Worker Assist

GenWealth implements three AI-powered features for investment advisory:

Semantic Search

Improve investment discovery using AlloyDB AI embeddings

Customer Segmentation

Identify prospects for new products with vector similarity

RAG Chatbot

Financial advisor assistant grounded in application data

Architecture

System Components

Database Schema

The GenWealth application uses a simple but powerful relational schema: GenWealth Database Schema Key Tables:
  • investments: Stock/ETF data with AI-generated analysis and embeddings
  • user_profiles: Customer data with bio embeddings for segmentation
  • langchain_vector_store: Document chunks from PDF ingestion
  • conversation_history: Optional chat history for multi-turn conversations

Tech Stack

Database

AlloyDB for PostgreSQL 14+
  • Native pgvector extension
  • Direct Vertex AI integration
  • Embeddings and LLM functions

AI Services

Vertex AI
  • gemini-2.0-flash-001
  • text-embedding-005
  • Agent Builder

Backend

TypeScript/Node.js
  • Express REST API
  • Cloud Run (2nd gen)
  • Cloud Functions (Python 3.11+)

Frontend

Angular 17+
  • Material Design
  • Vertex AI Search widget
  • Real-time chat interface

Supporting Services

  • Document AI: OCR processor for PDF text extraction
  • Cloud Storage: Document and metadata buckets
  • Eventarc: Event-driven pipeline orchestration
  • Pub/Sub: Asynchronous function invocation
  • Secret Manager: Database credentials and API keys
  • LangChain: Text chunking and vector store integration

AlloyDB AI Integration

Native Embeddings Generation

AlloyDB integrates directly with Vertex AI LLMs through the database engine:
-- Generate embeddings during INSERT/UPDATE
INSERT INTO investments (ticker, analysis, analysis_embedding)
VALUES (
  'AAPL',
  'Strong fundamentals with ecosystem lock-in...',
  google_ml.embedding('text-embedding-005', 'Strong fundamentals...')::vector
);
-- Search for stocks that might perform well in high inflation
SELECT ticker, etf, rating, analysis,
  analysis_embedding <=> google_ml.embedding(
    'text-embedding-005', 
    'hedge against high inflation'
  )::vector AS distance
FROM investments
ORDER BY distance
LIMIT 5;
The <=> operator calculates cosine distance. Lower values indicate higher similarity.

Text Generation in SQL

AlloyDB can invoke Gemini directly for text completion:
-- Financial chatbot with context and branding
SELECT llm_prompt, llm_response
FROM llm(
  -- User prompt
  prompt => 'I have $25250 to invest. What do you suggest?',
  
  -- Prompt enrichment
  llm_role => 'You are a financial chatbot named Penny',
  mission => 'Your mission is to assist your clients by providing financial education, account details, and basic information related to budgeting, saving, and different types of investments',
  output_instructions => 'Begin your response with a professional greeting. Greet me by name if you know it. End your response with a signature that includes your name and "GenWealth" company affiliation.',
  
  -- Optional parameters
  enable_history => true,  -- Maintain conversation context
  user_id => 'user123',    -- For history tracking
  model => 'gemini-2.0-flash-001'
);

Document Ingestion Pipeline

The pipeline processes financial documents (prospectuses, 10-Ks, 10-Qs) dropped into Cloud Storage:
1

Upload Trigger

Upload PDF to $PROJECT_ID-docs bucket (named by ticker, e.g., GOOG.pdf)
2

Parallel Processing

Eventarc triggers two parallel branches:
  • RAG Pipeline: Custom processing for AlloyDB vector store
  • Vertex AI Search Pipeline: Automatic indexing with faceted search
3

RAG Pipeline: OCR & Chunking

process-pdf function:
  • Extracts text with Document AI OCR
  • Chunks text with LangChain
  • Generates embeddings with text-embedding-005
  • Writes to langchain_vector_store table
4

RAG Pipeline: Analysis

analyze-prospectus function:
  • Retrieves document chunks from AlloyDB
  • Generates company overview with Gemini
  • Creates investment analysis and rating
  • Saves to investments table with embeddings
5

Search Pipeline: Metadata & Indexing

  • write-metadata function creates JSONL for faceted search
  • update-search-index function triggers re-indexing
  • Vertex AI Search makes document queryable

Pipeline Performance

  • Processing time: 1-10+ minutes depending on PDF size
  • Parallel documents: Up to 5 by default (quota-dependent)
  • File limits: Tested up to 15MB, 200 pages
  • Method: Batch processing via Document AI
import functions_framework
from google.cloud import documentai
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_google_alloydb_pg import AlloyDBVectorStore

@functions_framework.cloud_event
def process_pdf(cloud_event):
    # Extract text with Document AI
    document = documentai_client.process_document(
        request={"name": processor_name, "raw_document": raw_document}
    )
    text = document.text
    
    # Chunk with LangChain
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000, chunk_overlap=100
    )
    chunks = text_splitter.split_text(text)
    
    # Store in AlloyDB with embeddings
    vector_store = AlloyDBVectorStore(
        engine=alloydb_engine,
        embedding_service=VertexAIEmbeddings(
            model_name="text-embedding-005"
        )
    )
    vector_store.add_texts(chunks, metadatas=[{"ticker": ticker}])

Middle Tier API

The Express/TypeScript backend provides REST endpoints:
import express from 'express';
import { Database } from './Database';

const app: express.Application = express();
const db = new Database();

// Semantic search for investments
app.get('/api/investments/search', async (req, res) => {
  const { query } = req.query;
  
  const sql = `
    SELECT ticker, etf, rating, analysis,
      analysis_embedding <=> google_ml.embedding(
        'text-embedding-005', $1
      )::vector AS distance
    FROM investments
    ORDER BY distance
    LIMIT 10
  `;
  
  const results = await db.query(sql, [query]);
  res.json(results);
});

// Customer segmentation
app.post('/api/customers/segment', async (req, res) => {
  const { persona, riskProfile, ageMin, ageMax } = req.body;
  
  const sql = `
    SELECT first_name, last_name, email, age, risk_profile,
      bio_embedding <=> google_ml.embedding(
        'text-embedding-005', $1
      )::vector AS distance
    FROM user_profiles
    WHERE risk_profile = $2
      AND age BETWEEN $3 AND $4
    ORDER BY distance
    LIMIT 50
  `;
  
  const results = await db.query(sql, [persona, riskProfile, ageMin, ageMax]);
  res.json(results);
});

// RAG chatbot
app.post('/api/chat', async (req, res) => {
  const { prompt, userId } = req.body;
  
  const sql = `SELECT llm_prompt, llm_response FROM llm(
    prompt => $1,
    llm_role => 'You are a financial chatbot named Penny',
    mission => 'Assist clients with financial education and advice',
    output_instructions => 'Be professional and cite sources',
    enable_history => true,
    user_id => $2
  )`;
  
  const result = await db.query(sql, [prompt, userId]);
  res.json(result[0]);
});

Frontend Features

Investment Search Interface

  • Semantic search bar: Natural language queries against investment data
  • Faceted filters: Risk profile, asset type, sector
  • Results display: Cards with analysis, rating, and similarity score
  • PDF viewer: Inline prospectus viewing with Vertex AI Search widget

Customer Segmentation Tool

  • Persona builder: Describe ideal customer in natural language
  • Filter controls: Risk profile, age range, investment goals
  • Match scoring: Similarity distance visualization
  • Export options: CSV download for marketing campaigns

Financial Advisor Chatbot

  • Conversational UI: Multi-turn chat with context preservation
  • Grounding visualization: Shows retrieved documents used for responses
  • Citation links: References to source prospectuses and data
  • History: Persistent conversation across sessions

Deployment

Prerequisites

  • Google Cloud project with billing enabled
  • Cloud Shell or local terminal with gcloud CLI
  • Public IP address for AlloyDB connection (during setup)

Installation Steps

1

Clone Repository

cd ~
git clone https://github.com/GoogleCloudPlatform/generative-ai.git
cd generative-ai/gemini/sample-apps/genwealth/
2

Configure Environment

Edit env.sh with your settings:
export REGION="us-central1"
export ZONE="us-central1-a"
export LOCAL_IPV4="X.X.X.X"  # Your public IP from ipv4.icanhazip.com
3

Run Installation Script

./install.sh
The script provisions:
  • AlloyDB cluster (zonal) with pgvector extension
  • Cloud Run service for Express API
  • Cloud Functions for document processing
  • GCS buckets for documents and metadata
  • Vertex AI Search app and datastore
  • Networking (VPC, PSC endpoints)
  • IAM roles and service accounts
Duration: ~30-35 minutes
4

Configure Vertex AI Search

When prompted, retrieve the configId:
  1. Navigate to Vertex AI Search in console
  2. Accept terms and activate API
  3. Click Apps → search-prospectus → Integration
  4. Copy configId UUID (e.g., 4205ae6a-434e-695e-aee4-58f500bd9000)
  5. Paste into installation prompt
5

Set Allowed Domain

After deployment completes:
  1. Copy the Cloud Run service URL
  2. In Vertex AI Search Integration settings, add domain without https:// or trailing slash
  3. Save configuration
6

Access Application

Open the Cloud Run URL in your browser to explore the demo

Post-Installation

Set AlloyDB password (if prompted during install):
source ./env.sh
gcloud secrets versions access latest --secret="alloydb-password"

Troubleshooting

Re-run bucket IAM binding:
source ./env.sh
gcloud storage buckets add-iam-policy-binding gs://${PROJECT_ID}-docs \
  --member=allUsers --role=roles/storage.objectViewer
Ensure:
  1. Domain added to allowed list in Vertex AI Search Integration
  2. API terms accepted and activated
  3. No trailing slash in domain configuration
Check:
  • Document AI quota limits
  • Cloud Function logs for errors: gcloud functions logs read process-pdf
  • File size (max 15MB recommended)

Demo Walkthroughs

Customization & Extension

Using Non-Vertex Models

See alternate-configs/non-vertex-models.md for using open-source models.

AlloyDB Omni Configuration

For on-premises deployment: alternate-configs/alloydb-omni.md

Custom Document Types

Modify analyze-prospectus function to handle different financial documents:
  • Earnings reports
  • Research papers
  • Analyst ratings
  • Market commentary

Cleanup

Deleting the project permanently destroys all resources. Ensure you have backups of any data you need.
# Set your project ID
PROJECT_ID='your-project-id'
gcloud projects delete ${PROJECT_ID}
Alternatively, delete individual resources:
source ./env.sh

# Delete Cloud Run service
gcloud run services delete genwealth-ui --region=${REGION}

# Delete AlloyDB cluster
gcloud alloydb clusters delete genwealth-cluster --region=${REGION}

# Delete Cloud Functions
gcloud functions delete process-pdf --region=${REGION}
gcloud functions delete analyze-prospectus --region=${REGION}

# Delete Cloud Storage buckets
gcloud storage rm -r gs://${PROJECT_ID}-docs
gcloud storage rm -r gs://${PROJECT_ID}-docs-metadata

Key Takeaways

Database-Native AI

AlloyDB’s direct Vertex AI integration eliminates external API calls for embeddings and LLM inference

Hybrid Search

Combine semantic similarity with structured filters for precise results

Event-Driven Pipelines

Eventarc + Cloud Functions enable scalable, parallel document processing

Production Patterns

Secret Manager, IAM, VPC, and PSC provide enterprise-grade security

Next Steps

Build docs developers (and LLMs) love