In today’s interconnected business landscape, organizations often rely on multiple cloud platforms and SaaS applications to meet their diverse needs. This blog demonstrates how to build a powerful multicloud employee management solution that seamlessly integrates:
- Oracle NetSuite (SaaS application on OCI) for employee data
- Oracle Exadata Database Service on Exascale Infrastructure on Oracle Database @ Azure for data storage
- Azure OpenAI for embeddings and generative AI capabilities
Oracle Exadata Database Service on Exascale Infrastructure brings Oracle’s powerful database capabilities to Azure with shared infrastructure that significantly reduces minimum costs while maintaining all of Exadata’s unique features. This makes it ideal for developers who need high-performance database capabilities with cloud-native integration.
Architecture Overview
Our solution follows this data flow:
- Extract employee data from NetSuite via REST APIs
- Store structured data in Oracle Database 23ai running on Azure
- Generate vector embeddings for each employee record using Azure OpenAI
- Enable similarity search and AI-powered text generation for queries
Prerequisites
Before we begin, ensure you have:
- Oracle Exadata Database Service on Exascale instance on Azure
- Azure OpenAI instance with deployed models
- NetSuite account with REST web services enabled
- Windows VM in the same Virtual Network as Exadata
Step 1: Setting Up Oracle Exadata on Exascale Infrastructure
Oracle Exadata on Exascale provides shared infrastructure that delivers:
- Up to 95% lower minimum infrastructure costs compared to dedicated infrastructure
- All Exadata’s unique capabilities including Smart Scan and storage optimization
- Rapid cloning features for development and testing environments
- Elastic scaling with pay-as-you-go pricing
Create your Exadata instance through the Azure portal, ensuring it’s deployed in your target virtual network for secure connectivity.
Step 2: Configuring Azure OpenAI Services
- Create an Azure OpenAI resource
- Navigate to Azure AI Foundry and deploy the following models:
- text-embedding-3-large for generating vector embeddings
- gpt-35-turbo for generative AI capabilities
- Copy your endpoint URL and API key for later use
Step 3: Setting Up the Development Environment
Create a Windows VM in the same Virtual Network as your Exadata instance and install:
- Python 3.8 or higher
- Visual Studio Code with Python extensions
- Required Python packages
Install Required Python Packages
pip install oracledb
pip install openai
pip install requests
pip install requests_oauthlib
pip install array
Step 4: Connecting to Oracle Database
Establish a connection to your Oracle Database 23ai instance:
import oracledb
# Oracle DB connection parameters
username = "sys"
password = "your_password"
hostname = "your-scan-hostname.oracle.com"
port = 1521
service_name = "your_service_name"
# Create DSN and connect
dsn = f"{hostname}:{port}/{service_name}"
connection = oracledb.connect(
user=username,
password=password,
dsn=dsn,
mode=oracledb.SYSDBA
)
print("Connected to Oracle Database")
Step 5: Setting Up Azure OpenAI Client
Configure your Azure OpenAI client:
import os
from openai import AzureOpenAI
# Initialize Azure OpenAI client
client = AzureOpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-06-01",
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
)
Step 6: Creating the Employee Table
Create a table to store employee data with vector embeddings:
CREATE TABLE EMPLOYEES (
PersonId NUMBER PRIMARY KEY,
FirstName VARCHAR2(100),
LastName VARCHAR2(100),
HireDate DATE,
WorkEmail VARCHAR2(200),
Title VARCHAR2(200),
ExpenseLimit NUMBER,
EMBEDDINGS VECTOR(3072, FLOAT32) -- Vector column for embeddings
);
Step 7: Extracting Data from NetSuite with OAuth Authentication
Configure NetSuite REST API access with proper OAuth 1.0 authentication:
#
#Code truncated for brevity
#
def get_netsuite_employees():
# Set OAuth 1.0 credentials
# API endpoint and query
method = 'POST'
url = f"https://{account}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql"
body = {
"q": "SELECT id, hiredate, firstname, lastname, title, email, entityid, expenselimit FROM Employee"
}
# Generate OAuth parameters
# Create signature base string
# Create signing key and signature
# Build authorization header
}
try:
print("Making request to NetSuite...")
response = requests.post(url, json=body, headers=headers)
print(f"Status Code: {response.status_code}")
if response.status_code == 200:
data = response.json()
print(f"Successfully retrieved {data.get('count', 0)} employee records")
return data
else:
print(f"Error: {response.status_code}")
print(f"Response: {response.text}")
return None
except requests.exceptions.RequestException as e:
print(f"Network Error: {e}")
return None
Step 8: Processing and Storing Employee Data
Extract data from the JSON response and store it in the database with robust error handling:
#
#Code truncated for brevity
#
def process_and_store_employees(json_data):
"""Process NetSuite employee data and store in Oracle Database"""
if not json_data or "items" not in json_data:
print("No employee data to process")
return
cursor = connection.cursor()
count = json_data.get("count", 0)
processed_count = 0
error_count = 0
print(f"Processing {count} employee records...")
for i in range(count):
try:
# Initialize variables with defaults
# Extract employee data with individual error handling
try:
FirstName = json_data["items"][i].get("firstname", "")
except (KeyError, TypeError):
FirstName = ""
#
# Extract remaining employee data fields from the JSON
#
# Insert employee data into database
sql = """
INSERT INTO EMPLOYEES (
PersonId, FirstName, LastName, HireDate,
WorkEmail, Title, ExpenseLimit
) VALUES (:1, :2, :3, :4, :5, :6, :7)
"""
values = (PersonId, FirstName, LastName, HireDate,
WorkEmail, Title, ExpenseLimit)
cursor.execute(sql, values)
# Generate and store embeddings for this employee
generate_and_store_embeddings(cursor, PersonId, FirstName,
LastName, HireDate, WorkEmail,
Title, ExpenseLimit)
except Exception as e:
error_count += 1
print(f"Error processing employee record {i}: {e}")
continue
# Commit all changes
connection.commit()
print(f"Successfully processed {processed_count} employees, {error_count} errors")
# Main execution
if __name__ == "__main__":
# Fetch data from NetSuite
employee_data = get_netsuite_employees()
if employee_data:
# Process and store the data
process_and_store_employees(employee_data)
else:
print("Failed to retrieve employee data from NetSuite")
Step 9: Generating Vector Embeddings
Create vector embeddings for each employee record using Azure OpenAI:
import array
def generate_and_store_embeddings(cursor, PersonId, FirstName, LastName,
HireDate, WorkEmail, Title, ExpenseLimit):
# Create text representation for embedding
embed_text = (f"PersonId: {PersonId}, FirstName: {FirstName}, "
f"LastName: {LastName}, HireDate: {HireDate}, "
f"WorkEmail: {WorkEmail}, Title: {Title}, "
f"ExpenseLimit: {ExpenseLimit}")
try:
# Generate embedding using Azure OpenAI
response = client.embeddings.create(
input=embed_text,
model="text-embedding-3-large"
)
# Convert to array format for Oracle
embedding_vector = array.array("f", response.data[0].embedding)
# Update the employee record with the embedding
sql = """
UPDATE EMPLOYEES
SET EMBEDDINGS = :embedding
WHERE PersonId = :person_id
"""
cursor.execute(sql, {"embedding": embedding_vector, "person_id": PersonId})
except Exception as e:
print(f"Error generating embedding for PersonId {PersonId}: {e}")
Step 10: Verifying the Implementation
Use SQL Developer or similar tools to verify your data:
-- Check employee data
SELECT PersonId, FirstName, LastName, Title FROM EMPLOYEES;
-- Verify embeddings are populated
SELECT PersonId, FirstName, LastName,
CASE WHEN EMBEDDINGS IS NOT NULL THEN 'Has Embedding' ELSE 'No Embedding' END as EmbeddingStatus
FROM EMPLOYEES;
Benefits of This Architecture
For Developers:
- Simplified Infrastructure: Exascale helps eliminate the need to manage dedicated database servers
- Cost Efficiency: Pay only for resources used with up to 95% lower minimum costs
- AI Integration: Seamless integration with Azure OpenAI services
- Rapid Development: Quick cloning features for dev/test environments
For Organizations:
- Multicloud Flexibility: Leverage best-of-breed services across cloud platforms
- Scalability: Elastic infrastructure that can grow with your needs
- Performance: All Exadata capabilities including Smart Scan and optimization
- Security: Enterprise-grade security with Azure networking features
Next Steps
In our next blog post, we’ll build upon this foundation to:
- Implement similarity search using vector embeddings
- Create a user-friendly frontend interface
- Add AI-powered query capabilities for generating emails and reports
- Demonstrate advanced vector search patterns in Oracle Database 23ai
Conclusion
This multicloud solution demonstrates the power of combining Oracle’s database expertise with Azure’s AI capabilities. Oracle Exadata on Exascale provides the perfect foundation for developers who need high-performance database capabilities without the complexity of managing dedicated infrastructure.
For organizations seeking even greater automation, this solution can also be built using Oracle Autonomous Database at Azure, combining self-managing database technology with Azure’s AI capabilities.
The integration of vector embeddings opens up powerful possibilities for AI-driven applications, making employee data more searchable and enabling intelligent automation for HR processes.
By leveraging this architecture, organizations can build sophisticated, AI-powered applications that span multiple cloud platforms while maintaining cost efficiency and performance.
Resources: