Skip to content

Instantly share code, notes, and snippets.

@STHITAPRAJNAS
Last active June 20, 2025 16:54
Show Gist options
  • Save STHITAPRAJNAS/13d1d2eced4a52c9624f617320e6b3b0 to your computer and use it in GitHub Desktop.
Save STHITAPRAJNAS/13d1d2eced4a52c9624f617320e6b3b0 to your computer and use it in GitHub Desktop.
Address validation flow
<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Intelligent Address Validation Platform</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Chosen Palette: Calm Tech (Background: #F7FAFC, Primary Text: #2D3748, Accent: #4299E1) -->
<!-- Application Structure Plan: A task-oriented SPA featuring three main interactive modules: 1) A visual, clickable funnel diagram to explain the core process. 2) A live demo simulator where users can input an address and see it processed through the funnel, making the system tangible. 3) A tabbed section for a deep dive into the custom models, including a comparison tool. This structure was chosen to transform the static proposal into an engaging, interactive product demonstration, prioritizing user understanding and showcasing value over a linear report format. -->
<!-- Visualization & Content Choices: Report Info -> Funnel Process; Goal -> Explain/Organize; Viz -> Interactive HTML/CSS diagram; Interaction -> Click to expand details; Justification -> More engaging/clear than static text. | Report Info -> Layer 1 Success Rate; Goal -> Inform; Viz -> Chart.js Doughnut Chart; Interaction -> Hover tooltips; Justification -> Quick visual impact. | Report Info -> Entire Funnel Logic; Goal -> Demonstrate/Engage; Viz -> "Live Demo" UI (HTML forms/JS); Interaction -> User input triggers simulated validation flow; Justification -> Makes the abstract process concrete. | Report Info -> Custom Comparison Model; Goal -> Explain/Demonstrate; Viz -> Two-address input form with verdict output (HTML/JS); Interaction -> User input triggers comparison logic; Justification -> Clarifies the value of the advanced feature. -->
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #F7FAFC;
}
.funnel-layer {
transition: all 0.3s ease-in-out;
}
.funnel-layer.active {
transform: scale(1.05);
box-shadow: 0 10px 15px -3px rgba(66, 153, 225, 0.3), 0 4px 6px -2px rgba(66, 153, 225, 0.1);
}
.details-pane {
max-height: 0;
overflow: hidden;
transition: max-height 0.5s ease-in-out;
}
.details-pane.open {
max-height: 500px;
}
.tab-button.active {
border-color: #4299E1;
color: #4299E1;
font-weight: 600;
background-color: #EBF8FF;
}
.arrow-down {
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-top: 20px solid #CBD5E0;
}
.status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.chart-container {
position: relative;
width: 100%;
max-width: 300px;
margin-left: auto;
margin-right: auto;
height: 300px;
max-height: 300px;
}
</style>
</head>
<body class="text-gray-800">
<header class="bg-white shadow-sm sticky top-0 z-50">
<nav class="container mx-auto px-6 py-4 flex justify-between items-center">
<h1 class="text-xl font-bold text-gray-700">Intelligent Address Validation Platform</h1>
<div class="hidden md:flex space-x-6">
<a href="#funnel" class="text-gray-600 hover:text-blue-500 transition-colors">The Funnel</a>
<a href="#demo" class="text-gray-600 hover:text-blue-500 transition-colors">Live Demo</a>
<a href="#models" class="text-gray-600 hover:text-blue-500 transition-colors">Custom Models</a>
</div>
</nav>
</header>
<main class="container mx-auto p-4 md:p-8">
<section id="intro" class="text-center my-12">
<h2 class="text-4xl lg:text-5xl font-bold mb-4 text-gray-700">Transforming Address Data with AI</h2>
<p class="max-w-3xl mx-auto text-lg text-gray-600">
This platform moves beyond simple verification, using a multi-layered AI funnel to correct, complete, and compare addresses. Explore the interactive sections below to see how it works.
</p>
</section>
<section id="funnel" class="my-24">
<h3 class="text-3xl font-bold text-center mb-2">The Intelligent Validation Funnel</h3>
<p class="text-center text-gray-600 mb-12 max-w-2xl mx-auto">An address is passed through progressively sophisticated layers. Click on any layer to see its role in the validation process.</p>
<div class="flex flex-col items-center space-y-4">
<div id="funnel-input" class="text-center bg-white p-4 rounded-lg shadow-md w-full max-w-md">
<h4 class="font-bold">INPUT ADDRESS</h4>
<p class="text-sm text-gray-500">e.g., "1600 pensylvania av" / "rue de la paix 12"</p>
</div>
<div class="arrow-down"></div>
<div class="w-full max-w-2xl">
<div class="funnel-layer cursor-pointer bg-white p-6 rounded-lg shadow-md hover:shadow-xl" data-layer="1">
<div class="flex flex-col md:flex-row justify-between items-center text-center md:text-left">
<div>
<span class="text-xs font-semibold uppercase text-blue-500">Layer 1</span>
<h4 class="text-xl font-bold">Google Address Validation API</h4>
<p class="text-sm text-gray-500">High-speed, low-cost validation for global formats.</p>
</div>
<div class="mt-4 md:mt-0 text-right">
<p class="text-3xl font-bold text-green-500">80-95%</p>
<p class="text-sm text-gray-500">Success Rate</p>
</div>
</div>
</div>
<div id="details-1" class="details-pane bg-gray-100 p-6 rounded-b-lg -mt-2">
<p class="text-gray-700 mb-4">This foundational layer handles the vast majority of requests. It uses Google's authoritative, CASS-certified datasets to instantly validate and standardize addresses from over 240 countries, correcting minor typos and formatting issues according to local postal standards.</p>
<div class="chart-container">
<canvas id="successRateChart"></canvas>
</div>
</div>
</div>
<div class="arrow-down"></div>
<div class="w-full max-w-2xl">
<div class="funnel-layer cursor-pointer bg-white p-6 rounded-lg shadow-md hover:shadow-xl" data-layer="2">
<span class="text-xs font-semibold uppercase text-blue-500">Layer 2</span>
<h4 class="text-xl font-bold">Generative AI (Amazon Bedrock)</h4>
<p class="text-sm text-gray-500">Interprets severe errors and ambiguity.</p>
</div>
<div id="details-2" class="details-pane bg-gray-100 p-6 rounded-b-lg -mt-2">
<p class="text-gray-700">For addresses that are too malformed for the structured API, this layer uses a Large Language Model. It applies "common sense" reasoning to decipher the user's intent, reconstruct plausible addresses from conversational text, and remove extraneous information before re-submitting to Layer 1 for verification.</p>
</div>
</div>
<div class="arrow-down"></div>
<div class="w-full max-w-2xl">
<div class="funnel-layer cursor-pointer bg-white p-6 rounded-lg shadow-md hover:shadow-xl" data-layer="3">
<span class="text-xs font-semibold uppercase text-blue-500">Layer 3</span>
<h4 class="text-xl font-bold">Fine-Tuned Custom Models</h4>
<p class="text-sm text-gray-500">Handles domain-specific logic and comparison.</p>
</div>
<div id="details-3" class="details-pane bg-gray-100 p-6 rounded-b-lg -mt-2">
<p class="text-gray-700">This is our proprietary advantage. Custom models trained on our internal data handle unique business logic, complete partial addresses based on learned patterns, and perform nuanced comparisons to determine if two addresses are a functional match, a conflict, or require review.</p>
</div>
</div>
</div>
</section>
<section id="demo" class="my-24 bg-white p-8 rounded-lg shadow-lg">
<h3 class="text-3xl font-bold text-center mb-8">Live Demo Simulator</h3>
<div class="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-8">
<div>
<label for="address-input" class="block text-sm font-medium text-gray-700 mb-2">Enter an address to validate:</label>
<input type="text" id="address-input" class="w-full p-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500" placeholder="e.g., 10 downing st, londn">
<div class="mt-2 text-xs text-gray-500">
Try: `123 main st, anytown` (Easy), `big apple beside park` (Hard), `Tokyo-to, Chiyoda-ku, Marunouchi 2-7-2` (Int'l)
</div>
<button id="validate-btn" class="mt-4 w-full bg-blue-500 text-white font-bold py-2 px-4 rounded-md hover:bg-blue-600 transition-colors">Validate Address</button>
</div>
<div class="bg-gray-50 p-4 rounded-md border border-gray-200">
<h4 class="font-semibold mb-2 text-center">Validation Process</h4>
<ul id="demo-results" class="space-y-2 text-sm">
<li class="text-gray-400">Awaiting input...</li>
</ul>
</div>
</div>
</section>
<section id="models" class="my-24">
<h3 class="text-3xl font-bold text-center mb-8">Custom Model Capabilities</h3>
<div class="max-w-4xl mx-auto">
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-6" aria-label="Tabs">
<button class="tab-button active py-4 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" data-tab="completion">Address Completion</button>
<button class="tab-button py-4 px-1 border-b-2 font-medium text-sm border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" data-tab="comparison">Address Comparison</button>
</nav>
</div>
<div id="tab-content-completion" class="tab-content py-6">
<p class="text-gray-600 mb-4">This model intelligently infers and fills in missing address components. It's trained on historical data to reconstruct addresses from partial inputs, providing a list of the most probable complete addresses for verification.</p>
</div>
<div id="tab-content-comparison" class="tab-content py-6 hidden">
<p class="text-gray-600 mb-6">The core of our data governance feature. This model provides a nuanced "definitive verdict" when comparing two addresses from different sources.</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 items-start">
<div>
<label for="address-a" class="block text-sm font-medium text-gray-700">Address A (e.g., from CRM)</label>
<input type="text" id="address-a" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" value="123 Main St, Springfield, IL">
</div>
<div>
<label for="address-b" class="block text-sm font-medium text-gray-700">Address B (e.g., from Billing)</label>
<input type="text" id="address-b" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" value="123 Main Street, Suite 4B, Springfield, Illinois, 62704">
</div>
</div>
<button id="compare-btn" class="mt-6 w-full bg-blue-500 text-white font-bold py-2 px-4 rounded-md hover:bg-blue-600 transition-colors">Compare & Get Verdict</button>
<div id="comparison-verdict" class="mt-6 p-4 bg-gray-100 rounded-md text-center hidden">
</div>
</div>
</div>
</section>
</main>
<footer class="bg-white mt-16 border-t">
<div class="container mx-auto py-6 px-6 text-center text-gray-500">
<p>&copy; 2024 Intelligent Address Solutions. All Rights Reserved.</p>
</div>
</footer>
<script>
document.addEventListener('DOMContentLoaded', () => {
const funnelLayers = document.querySelectorAll('.funnel-layer');
funnelLayers.forEach(layer => {
layer.addEventListener('click', () => {
const layerId = layer.dataset.layer;
const detailsPane = document.getElementById(`details-${layerId}`);
const wasActive = layer.classList.contains('active');
funnelLayers.forEach(l => l.classList.remove('active'));
document.querySelectorAll('.details-pane').forEach(p => p.classList.remove('open'));
if (!wasActive) {
layer.classList.add('active');
detailsPane.classList.add('open');
}
});
});
const ctx = document.getElementById('successRateChart').getContext('2d');
new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Layer 1 Success', 'Requires Deeper Validation'],
datasets: [{
data: [85, 15],
backgroundColor: ['#48BB78', '#E2E8F0'],
borderColor: ['#48BB78', '#E2E8F0'],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
},
tooltip: {
callbacks: {
label: function(context) {
return `${context.label}: ${context.raw}%`;
}
}
}
},
cutout: '60%'
}
});
const validateBtn = document.getElementById('validate-btn');
const addressInput = document.getElementById('address-input');
const demoResults = document.getElementById('demo-results');
validateBtn.addEventListener('click', () => {
const address = addressInput.value.trim().toLowerCase();
if (!address) {
demoResults.innerHTML = `<li>Please enter an address.</li>`;
return;
}
demoResults.innerHTML = '';
let step = 1;
function addResult(text, status = 'processing') {
const li = document.createElement('li');
let dotColor = 'bg-yellow-400';
if (status === 'success') dotColor = 'bg-green-500';
if (status === 'fail') dotColor = 'bg-red-500';
li.innerHTML = `<span class="status-dot ${dotColor} mr-2"></span> ${text}`;
li.classList.add('flex', 'items-center', 'text-gray-700');
demoResults.appendChild(li);
}
addResult(`Starting validation for: "${addressInput.value}"`);
setTimeout(() => {
addResult('Attempting Layer 1: Google API...');
setTimeout(() => {
if (address.includes('123 main') || address.includes('chiyoda-ku')) {
addResult('<strong>Success:</strong> Address validated and standardized.', 'success');
let finalAddress = address.includes('chiyoda-ku')
? '2-7-2 Marunouchi, Chiyoda-ku, Tokyo 100-8994, Japan'
: '123 Main St, Anytown, CA 90210, USA';
addResult(`<strong>Formatted Address:</strong> ${finalAddress}`, 'success');
} else {
addResult('Layer 1 Failed: Address too ambiguous.', 'fail');
step = 2;
processLayer2();
}
}, 1500);
}, 1000);
function processLayer2() {
addResult('Attempting Layer 2: Generative AI...');
setTimeout(() => {
if (address.includes('big apple') || address.includes('park')) {
addResult('LLM reconstructed a plausible address...', 'success');
addResult('Re-validating with Layer 1...', 'processing');
setTimeout(() => {
addResult('<strong>Success:</strong> Address validated after reconstruction.', 'success');
addResult('<strong>Formatted Address:</strong> 5th Avenue & E 59th St, New York, NY 10022, USA', 'success');
}, 1500);
} else {
addResult('Layer 2 Failed: Could not interpret.', 'fail');
step = 3;
processLayer3();
}
}, 1500);
}
function processLayer3() {
addResult('Attempting Layer 3: Custom Models...');
setTimeout(() => {
addResult('<strong>Failed:</strong> Address could not be validated.', 'fail');
addResult('Flagging for manual review.', 'fail');
}, 1500);
}
});
const tabButtons = document.querySelectorAll('.tab-button');
const tabContents = document.querySelectorAll('.tab-content');
tabButtons.forEach(button => {
button.addEventListener('click', () => {
tabButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
const tab = button.dataset.tab;
tabContents.forEach(content => {
if (content.id === `tab-content-${tab}`) {
content.classList.remove('hidden');
} else {
content.classList.add('hidden');
}
});
});
});
const compareBtn = document.getElementById('compare-btn');
const addressAInput = document.getElementById('address-a');
const addressBInput = document.getElementById('address-b');
const verdictDiv = document.getElementById('comparison-verdict');
compareBtn.addEventListener('click', () => {
const addrA = addressAInput.value.trim().toLowerCase().replace(/[^a-z0-9]/g, '');
const addrB = addressBInput.value.trim().toLowerCase().replace(/[^a-z0-9]/g, '');
let verdict = '';
let verdictColor = '';
let verdictText = '';
if (addrA === addrB) {
verdict = 'MATCH';
verdictColor = 'bg-green-200 text-green-800';
verdictText = 'The addresses are functionally identical.';
} else if (addrB.includes(addrA)) {
verdict = 'PROBABLE MATCH';
verdictColor = 'bg-yellow-200 text-yellow-800';
verdictText = 'Address B appears to be a more complete version of Address A.';
} else {
verdict = 'CONFLICT';
verdictColor = 'bg-red-200 text-red-800';
verdictText = 'The addresses are fundamentally different.';
}
verdictDiv.innerHTML = `<span class="font-bold">${verdict}</span><p class="text-sm">${verdictText}</p>`;
verdictDiv.className = `mt-6 p-4 rounded-md text-center ${verdictColor}`;
verdictDiv.classList.remove('hidden');
});
});
</script>
</body>
</html>
Design Document: Intelligent Address Validation & Matching Platform
1. Introduction & System Overview
This document outlines the architecture and technical design for the Intelligent Address Validation & Matching Platform. The primary goal of this system is to provide a robust, highly accurate, and cost-effective solution for cleaning, standardizing, completing, and comparing both US and international postal addresses.
The system is architected as a multi-layered "intelligent validation funnel." This design ensures that the most efficient and low-cost tools are used for the majority of requests, while progressively more powerful (and resource-intensive) AI models are reserved for the small subset of highly problematic addresses. This layered approach maximizes both accuracy and return on investment.
Core Components:
Google Address Validation API: The primary tool for high-speed, authoritative validation.
Generative AI (Amazon Bedrock): A reasoning engine for interpreting ambiguous and severely malformed addresses.
Fine-Tuned Custom Models: Proprietary models for handling domain-specific logic, address completion, and nuanced comparison.
Orchestration Logic: A control layer that directs the flow of data through the funnel and manages the feedback loops.
2. The Intelligent Validation Funnel
The core of the system is the validation funnel. An incoming address is processed sequentially through the layers. If a layer returns a high-confidence, verified result, the process concludes. If not, the address is passed to the next layer.
Layer 1: Google Address Validation API
Purpose: To act as the first-pass filter, handling 80-95% of all incoming addresses.
Technology: Google Maps Platform - Address Validation API.
Process:
The raw input address is sent to the Google API endpoint.
The API attempts to match the input against its authoritative postal databases (covering 240+ countries and CASS-certified for the US).
It corrects minor spelling errors, standardizes abbreviations (e.g., "St" to "Street"), and formats the address according to the specific country's postal standards.
Success Condition: The API returns a verdict with validationGranularity of PREMISE or SUB_PREMISE and has no unconfirmed components.
Failure Condition: The API returns a low-confidence result, indicates missing components, or fails to find a match. The original, unmodified address is then passed to Layer 2.
Layer 2: Generative AI Correction
Purpose: To handle addresses with severe errors, ambiguity, or extraneous "junk" data that Layer 1 cannot parse.
Technology: A Large Language Model (LLM) such as Amazon Titan or Anthropic Claude, accessed via Amazon Bedrock.
Process:
The original failed address is embedded in a carefully engineered prompt sent to the LLM.
Prompt Engineering Example: You are an expert in global postal addresses. The following address failed standard validation. Analyze it, correct any spelling mistakes, remove irrelevant information (like "beside the park"), and reconstruct it into a plausible address. Return only the corrected address components in a JSON format. Address to correct: [Original User Input]
The LLM returns a structured JSON object containing its best guess for the address components.
This "corrected guess" is fed back into Layer 1 (Google API) for a second validation attempt. This step is crucial to confirm the LLM's guess against an authoritative source.
Success Condition: The re-submitted address is successfully validated by the Google API in the second pass.
Failure Condition: The reconstructed address still fails validation in Layer 1. The original address is passed to Layer 3.
Layer 3: Fine-Tuned Custom Models
Purpose: To handle domain-specific address patterns, complete partial addresses, and perform nuanced comparisons. This is the system's proprietary logic.
Technology: Custom models fine-tuned on internal business data.
Process (Address Completion):
A partial address that has failed previous layers is sent to the Address Completion model.
This model, trained on (partial_address, complete_address) pairs, generates a ranked list of the most probable complete addresses.
Each probable address from the list is then submitted to Layer 1 for verification until a match is found.
Success/Failure: Dependent on whether any of the generated completions can be validated by the Google API. Addresses that still fail are flagged for manual review, and the outcome is used as new training data to improve the model over time.
Address Validation Funnel Flowchart
graph TD
A[Input Address] --> B{Layer 1: Google API Validation};
B -- Success (80-95%) --> C[Output: Validated Address];
B -- Failure --> D{Layer 2: Generative AI Correction};
D -- Reconstructed Address --> E[Re-submit to Google API];
E -- Success --> C;
E -- Failure --> F{Layer 3: Custom Completion Model};
F -- Generates Probable Addresses --> G[Loop & Re-submit to Google API];
G -- Success --> C;
G -- Failure --> H[Flag for Manual Review];
3. Address Comparison Logic
A key feature of the platform is its ability to act as a definitive arbiter between two different address records. This logic resides within Layer 3.
Purpose: To determine if two addresses are functionally identical, probably a match, or a definite conflict.
Technology: A custom-trained classification model.
Process:
Normalization: Both input addresses (Address A and Address B) are first independently passed through the validation funnel (Layers 1 & 2) to obtain their cleanest, most complete, and standardized forms.
Feature Extraction: The normalized components of both addresses are extracted as features for the model. These include: Street Number, Street Name, Unit/Suite, City, State/Province, Postal Code, and any source tags (e.g., 'CRM', 'Billing').
Model Inference: The feature set is passed to the Address Comparison model.
Verdict Generation: The model outputs a final classification verdict based on its training.
Training Data: The model is trained on pairs of addresses that have been manually labeled with the desired verdict (MATCH, PROBABLE_MATCH, CONFLICT). The model learns the nuanced rules of what constitutes a match within the specific business context. For example, it can learn that an address with a suite number is a PROBABLE_MATCH to one without, rather than a CONFLICT.
Address Comparison Flowchart
graph TD
subgraph Normalize Addresses
InputA[Address A] --> NormA(Run through Validation Funnel);
InputB[Address B] --> NormB(Run through Validation Funnel);
end
NormA --> FeatA[Extract Features from A];
NormB --> FeatB[Extract Features from B];
subgraph Compare & Decide
direction LR
FeatA & FeatB --> C{Custom Comparison Model};
C --> D{Is Street Name/Number Match?};
D -- Yes --> E{Is Unit Info Consistent?};
D -- No --> F[Verdict: CONFLICT];
E -- Yes (or both empty) --> G[Verdict: MATCH];
E -- No (one has unit, other doesn't) --> H[Verdict: PROBABLE_MATCH];
end
H --> FinalVerdict[Output Verdict & Reasoning];
G --> FinalVerdict;
F --> FinalVerdict;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment