Oracle Cloud Infrastructure (OCI) offers a comprehensive suite of artificial intelligence and machine learning services that go far beyond traditional cloud computing. While many focus on basic compute and networking, the real power of OCI lies in its integrated AI capabilities that can transform how organizations process data, make decisions, and interact with customers. This deep dive explores advanced AI services and machine learning integration patterns that can elevate your cloud applications to the next level.
Understanding OCI’s AI Service Architecture
OCI’s AI services are built on a three-tier architecture that provides both simplicity and power. At the foundation layer, we have OCI Data Science for custom model development, Oracle Machine Learning integrated directly into Autonomous Database, and OCI AI Services for pre-built models. This layered approach allows organizations to choose the right level of customization for their needs.
Pre-built AI Services: Ready-to-Use Intelligence
OCI provides several pre-trained AI services that can be integrated into applications with minimal setup:
OCI Language Service offers advanced natural language processing capabilities including:
- Sentiment analysis with confidence scoring
- Named entity recognition for extracting people, places, and organizations
- Key phrase extraction and text classification
- Language detection supporting over 75 languages
OCI Vision Service provides computer vision capabilities:
- Object detection and classification
- Optical Character Recognition (OCR) with high accuracy
- Image analysis for content moderation
- Document AI for extracting structured data from forms
OCI Speech Service enables voice-powered applications:
- Real-time speech-to-text transcription
- Batch audio file processing
- Support for multiple languages and custom vocabularies
- Speaker diarization for identifying different speakers
Building a Multi-Modal AI Application
Let’s walk through creating an intelligent document processing system that combines multiple OCI AI services. This example demonstrates how to build a solution that can process invoices, extract information, and provide insights.
Step 1: Setting Up the Vision Service for Document Processing
import oci
from oci.ai_vision import AIServiceVisionClient
from oci.ai_vision.models import *
import base64
# Initialize the Vision client
config = oci.config.from_file("~/.oci/config", "DEFAULT")
vision_client = AIServiceVisionClient(config)
def process_invoice_image(image_path, compartment_id):
"""
Process an invoice image using OCI Vision Service
Extract text and analyze document structure
"""
# Read and encode the image
with open(image_path, "rb") as image_file:
image_data = image_file.read()
encoded_image = base64.b64encode(image_data).decode('utf-8')
# Configure document analysis features
features = [
DocumentFeature(
feature_type="TEXT_DETECTION",
max_results=1000
),
DocumentFeature(
feature_type="TABLE_DETECTION",
max_results=50
),
DocumentFeature(
feature_type="KEY_VALUE_DETECTION",
max_results=100
)
]
# Create inline document details
inline_document_details = InlineDocumentDetails(
data=encoded_image,
compartment_id=compartment_id
)
# Create analysis request
analyze_document_details = AnalyzeDocumentDetails(
features=features,
document=inline_document_details
)
# Perform document analysis
response = vision_client.analyze_document(analyze_document_details)
return response.data
def extract_invoice_data(vision_response):
"""
Extract structured data from vision analysis results
"""
extracted_data = {
"invoice_number": None,
"date": None,
"vendor": None,
"total_amount": None,
"line_items": []
}
# Process key-value pairs
if hasattr(vision_response, 'key_value_detection_result'):
key_values = vision_response.key_value_detection_result.pages[0].document_fields
for kv_pair in key_values:
key_text = kv_pair.field_label.text.lower()
value_text = kv_pair.field_value.text if kv_pair.field_value else ""
if "invoice" in key_text and "number" in key_text:
extracted_data["invoice_number"] = value_text
elif "date" in key_text:
extracted_data["date"] = value_text
elif "vendor" in key_text or "supplier" in key_text:
extracted_data["vendor"] = value_text
elif "total" in key_text and ("amount" in key_text or "$" in value_text):
extracted_data["total_amount"] = value_text
# Process table data for line items
if hasattr(vision_response, 'table_detection_result'):
tables = vision_response.table_detection_result.pages[0].tables
for table in tables:
# Extract line items from the first table (assuming it's the items table)
for row in table.rows[1:]: # Skip header row
if len(row.cells) >= 3: # Ensure we have description, quantity, price
line_item = {
"description": row.cells[0].text,
"quantity": row.cells[1].text,
"unit_price": row.cells[2].text
}
extracted_data["line_items"].append(line_item)
return extracted_data
Step 2: Enhancing with Language Service Analysis
Now let’s add sentiment analysis and entity extraction to understand the context better:
from oci.ai_language import AIServiceLanguageClient
from oci.ai_language.models import *
def analyze_invoice_sentiment_and_entities(text_content, compartment_id):
"""
Analyze invoice text for sentiment and extract business entities
"""
# Initialize Language client
language_client = AIServiceLanguageClient(config)
# Configure text analysis features
features = [
"SENTIMENT_ANALYSIS",
"ENTITY_EXTRACTION",
"KEY_PHRASE_EXTRACTION"
]
# Create analysis request
batch_language_translation_details = BatchLanguageTranslationDetails(
documents=[
TextDocument(
key="invoice_analysis",
text=text_content,
language_code="en"
)
]
)
# Perform sentiment analysis
sentiment_details = BatchDetectLanguageSentimentsDetails(
documents=[
TextDocument(
key="invoice_sentiment",
text=text_content,
language_code="en"
)
],
compartment_id=compartment_id
)
sentiment_response = language_client.batch_detect_language_sentiments(
sentiment_details
)
# Perform entity extraction
entity_details = BatchDetectLanguageEntitiesDetails(
documents=[
TextDocument(
key="invoice_entities",
text=text_content,
language_code="en"
)
],
compartment_id=compartment_id
)
entities_response = language_client.batch_detect_language_entities(
entity_details
)
return {
"sentiment": sentiment_response.data,
"entities": entities_response.data
}
def process_extracted_entities(entities_response):
"""
Process and categorize extracted entities
"""
business_entities = {
"organizations": [],
"locations": [],
"money": [],
"dates": [],
"products": []
}
for document in entities_response.documents:
for entity in document.entities:
entity_info = {
"text": entity.text,
"type": entity.type,
"confidence": entity.confidence
}
if entity.type == "ORGANIZATION":
business_entities["organizations"].append(entity_info)
elif entity.type == "LOCATION":
business_entities["locations"].append(entity_info)
elif entity.type == "MONEY":
business_entities["money"].append(entity_info)
elif entity.type in ["DATE", "TIME"]:
business_entities["dates"].append(entity_info)
elif entity.type == "PRODUCT":
business_entities["products"].append(entity_info)
return business_entities
Step 3: Integrating with Oracle Machine Learning for Predictive Analytics
Let’s extend our solution by integrating with Oracle Machine Learning to predict payment delays and vendor risk assessment:
import cx_Oracle
import pandas as pd
from datetime import datetime, timedelta
class InvoiceMLPredictor:
def __init__(self, connection_string):
"""
Initialize ML predictor with Autonomous Database connection
"""
self.connection = cx_Oracle.connect(connection_string)
def create_payment_prediction_model(self):
"""
Create ML model for payment delay prediction using Oracle ML
"""
create_model_sql = """
BEGIN
DBMS_DATA_MINING.DROP_MODEL('PAYMENT_DELAY_MODEL');
EXCEPTION
WHEN OTHERS THEN NULL;
END;
"""
cursor = self.connection.cursor()
cursor.execute(create_model_sql)
# Create training data view
training_view_sql = """
CREATE OR REPLACE VIEW invoice_training_data AS
SELECT
vendor_id,
invoice_amount,
payment_terms,
invoice_date,
due_date,
actual_payment_date,
CASE
WHEN actual_payment_date <= due_date THEN 'ON_TIME'
WHEN actual_payment_date <= due_date + INTERVAL '7' DAY THEN 'SLIGHTLY_LATE'
ELSE 'SIGNIFICANTLY_LATE'
END AS payment_status,
vendor_rating,
historical_late_payments,
invoice_complexity_score
FROM historical_invoices
WHERE actual_payment_date IS NOT NULL
"""
cursor.execute(training_view_sql)
# Create and train the ML model
ml_model_sql = """
BEGIN
DBMS_DATA_MINING.CREATE_MODEL(
model_name => 'PAYMENT_DELAY_MODEL',
mining_function => DBMS_DATA_MINING.CLASSIFICATION,
data_table_name => 'invoice_training_data',
case_id_column_name => 'vendor_id',
target_column_name => 'payment_status',
settings_table_name => null
);
END;
"""
cursor.execute(ml_model_sql)
self.connection.commit()
cursor.close()
def predict_payment_risk(self, invoice_data):
"""
Predict payment delay risk for new invoices
"""
prediction_sql = """
SELECT
PREDICTION(PAYMENT_DELAY_MODEL USING
:vendor_id as vendor_id,
:invoice_amount as invoice_amount,
:payment_terms as payment_terms,
:vendor_rating as vendor_rating,
:historical_late_payments as historical_late_payments,
:invoice_complexity_score as invoice_complexity_score
) as predicted_status,
PREDICTION_PROBABILITY(PAYMENT_DELAY_MODEL, 'SIGNIFICANTLY_LATE' USING
:vendor_id as vendor_id,
:invoice_amount as invoice_amount,
:payment_terms as payment_terms,
:vendor_rating as vendor_rating,
:historical_late_payments as historical_late_payments,
:invoice_complexity_score as invoice_complexity_score
) as risk_probability
FROM dual
"""
cursor = self.connection.cursor()
result = cursor.execute(prediction_sql, invoice_data).fetchone()
cursor.close()
return {
"predicted_status": result[0],
"risk_probability": float(result[1])
}
def calculate_invoice_complexity_score(extracted_data, entities):
"""
Calculate complexity score based on extracted invoice data
"""
complexity_score = 0
# Base complexity from line items
complexity_score += len(extracted_data.get("line_items", [])) * 2
# Add complexity for multiple organizations (subcontractors)
org_count = len([e for e in entities.get("organizations", []) if e["confidence"] > 0.8])
complexity_score += max(0, (org_count - 1) * 5) # Extra orgs add complexity
# Add complexity for multiple locations (shipping/billing different)
loc_count = len([e for e in entities.get("locations", []) if e["confidence"] > 0.8])
complexity_score += max(0, (loc_count - 1) * 3)
# Add complexity for multiple currencies
money_entities = entities.get("money", [])
currencies = set()
for money in money_entities:
# Simple currency detection (could be enhanced)
if "$" in money["text"]:
currencies.add("USD")
elif "€" in money["text"]:
currencies.add("EUR")
elif "£" in money["text"]:
currencies.add("GBP")
complexity_score += max(0, (len(currencies) - 1) * 10)
return min(complexity_score, 100) # Cap at 100
Step 4: Orchestrating the Complete Solution
Now let’s tie everything together with a comprehensive invoice processing pipeline:
class IntelligentInvoiceProcessor:
def __init__(self, compartment_id, db_connection_string):
self.compartment_id = compartment_id
self.ml_predictor = InvoiceMLPredictor(db_connection_string)
async def process_invoice_complete(self, image_path, vendor_id=None):
"""
Complete invoice processing pipeline
"""
print("🔍 Analyzing invoice image...")
# Step 1: Extract data using Vision service
vision_response = process_invoice_image(image_path, self.compartment_id)
extracted_data = extract_invoice_data(vision_response)
print(f"✅ Extracted invoice #{extracted_data.get('invoice_number', 'Unknown')}")
# Step 2: Get full text for language analysis
full_text = self._extract_full_text(vision_response)
# Step 3: Analyze with Language service
language_analysis = analyze_invoice_sentiment_and_entities(
full_text, self.compartment_id
)
entities = process_extracted_entities(language_analysis["entities"])
print(f"🧠 Identified {len(entities['organizations'])} organizations and "
f"{len(entities['products'])} products")
# Step 4: Calculate complexity score
complexity_score = calculate_invoice_complexity_score(extracted_data, entities)
# Step 5: Predict payment risk if we have vendor info
payment_prediction = None
if vendor_id:
prediction_input = {
"vendor_id": vendor_id,
"invoice_amount": self._parse_amount(extracted_data.get("total_amount", "0")),
"payment_terms": 30, # Default, could be extracted
"vendor_rating": self._get_vendor_rating(vendor_id),
"historical_late_payments": self._get_vendor_late_payment_count(vendor_id),
"invoice_complexity_score": complexity_score
}
payment_prediction = self.ml_predictor.predict_payment_risk(prediction_input)
print(f"⚠️ Payment risk: {payment_prediction['predicted_status']} "
f"({payment_prediction['risk_probability']:.2%} probability of significant delay)")
# Step 6: Generate insights and recommendations
insights = self._generate_insights(extracted_data, entities, payment_prediction, complexity_score)
return {
"extracted_data": extracted_data,
"entities": entities,
"language_analysis": language_analysis,
"payment_prediction": payment_prediction,
"complexity_score": complexity_score,
"insights": insights
}
def _extract_full_text(self, vision_response):
"""Extract all text content from vision response"""
text_parts = []
if hasattr(vision_response, 'text_detection_result'):
pages = vision_response.text_detection_result.pages
for page in pages:
for text_line in page.lines:
text_parts.append(text_line.text)
return " ".join(text_parts)
def _parse_amount(self, amount_str):
"""Parse amount string to float"""
import re
if not amount_str:
return 0.0
# Remove currency symbols and commas
clean_amount = re.sub(r'[^\d.]', '', amount_str)
try:
return float(clean_amount)
except ValueError:
return 0.0
def _get_vendor_rating(self, vendor_id):
"""Get vendor rating from database (placeholder)"""
# This would query your vendor management system
return 85.0 # Placeholder
def _get_vendor_late_payment_count(self, vendor_id):
"""Get vendor's historical late payment count (placeholder)"""
# This would query your payment history
return 2 # Placeholder
def _generate_insights(self, extracted_data, entities, payment_prediction, complexity_score):
"""Generate business insights from the analysis"""
insights = []
# Payment risk insights
if payment_prediction:
if payment_prediction["risk_probability"] > 0.7:
insights.append({
"type": "HIGH_RISK",
"message": f"High risk of payment delay ({payment_prediction['risk_probability']:.1%}). "
f"Consider requiring prepayment or additional documentation.",
"priority": "HIGH"
})
elif payment_prediction["risk_probability"] > 0.4:
insights.append({
"type": "MEDIUM_RISK",
"message": f"Moderate payment delay risk. Monitor closely and send early reminders.",
"priority": "MEDIUM"
})
# Complexity insights
if complexity_score > 70:
insights.append({
"type": "COMPLEX_INVOICE",
"message": f"High complexity score ({complexity_score}/100). "
f"Consider additional review before approval.",
"priority": "MEDIUM"
})
# Entity-based insights
if len(entities.get("organizations", [])) > 2:
insights.append({
"type": "MULTIPLE_VENDORS",
"message": f"Multiple organizations detected. Verify primary vendor and "
f"any subcontractor relationships.",
"priority": "MEDIUM"
})
# Amount validation
extracted_amount = self._parse_amount(extracted_data.get("total_amount", "0"))
if extracted_amount > 50000:
insights.append({
"type": "HIGH_VALUE",
"message": f"High-value invoice (${extracted_amount:,.2f}). "
f"Requires executive approval.",
"priority": "HIGH"
})
return insights
Advanced Integration Patterns
Real-time Processing with OCI Streaming
For high-volume invoice processing, integrate with OCI Streaming for real-time processing:
from oci.streaming import StreamClient
from oci.streaming.models import PutMessagesDetails, PutMessagesDetailsEntry
import json
import asyncio
class StreamingInvoiceProcessor:
def __init__(self, stream_client, stream_id):
self.stream_client = stream_client
self.stream_id = stream_id
async def stream_invoice_for_processing(self, invoice_path, metadata=None):
"""Stream invoice processing request"""
# Create processing message
message_data = {
"invoice_path": invoice_path,
"timestamp": datetime.utcnow().isoformat(),
"metadata": metadata or {},
"processing_id": f"inv_{int(datetime.utcnow().timestamp())}"
}
# Stream the message
put_message_details = PutMessagesDetails(
messages=[
PutMessagesDetailsEntry(
key=message_data["processing_id"],
value=json.dumps(message_data).encode('utf-8')
)
]
)
response = self.stream_client.put_messages(
self.stream_id,
put_message_details
)
return response.data
Integration with OCI Functions for Serverless Processing
# This would be deployed as an OCI Function
import io
import json
import logging
from fdk import response
def handler(ctx, data: io.BytesIO = None):
"""
OCI Function for serverless invoice processing
"""
try:
body = json.loads(data.getvalue())
invoice_path = body.get("invoice_path")
if not invoice_path:
raise ValueError("Missing invoice_path")
# Initialize processor
processor = IntelligentInvoiceProcessor(
compartment_id=os.environ["COMPARTMENT_ID"],
db_connection_string=os.environ["DB_CONNECTION_STRING"]
)
# Process invoice
result = await processor.process_invoice_complete(
invoice_path,
body.get("vendor_id")
)
# Return results
return response.Response(
ctx, response_data=json.dumps(result, default=str),
headers={"Content-Type": "application/json"}
)
except Exception as e:
logging.error(f"Invoice processing failed: {str(e)}")
return response.Response(
ctx, response_data=json.dumps({"error": str(e)}),
headers={"Content-Type": "application/json"},
status_code=500
)
Performance Optimization and Best Practices
1. Batch Processing for Efficiency
When processing large volumes of documents, implement batch processing:
class BatchInvoiceProcessor:
def __init__(self, compartment_id, batch_size=10):
self.compartment_id = compartment_id
self.batch_size = batch_size
async def process_batch(self, invoice_paths):
"""Process invoices in optimized batches"""
results = []
for i in range(0, len(invoice_paths), self.batch_size):
batch = invoice_paths[i:i + self.batch_size]
# Process batch concurrently
batch_tasks = [
self._process_single_invoice(path)
for path in batch
]
batch_results = await asyncio.gather(*batch_tasks)
results.extend(batch_results)
# Rate limiting to respect service limits
await asyncio.sleep(1)
return results
2. Caching and Result Storage
Implement caching to avoid reprocessing:
from oci.object_storage import ObjectStorageClient
import hashlib
import pickle
class ProcessingCache:
def __init__(self, bucket_name, namespace):
self.client = ObjectStorageClient(config)
self.bucket_name = bucket_name
self.namespace = namespace
def _get_cache_key(self, file_path):
"""Generate cache key based on file content hash"""
with open(file_path, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
return f"invoice_cache/{file_hash}.pkl"
async def get_cached_result(self, file_path):
"""Retrieve cached processing result"""
try:
cache_key = self._get_cache_key(file_path)
response = self.client.get_object(
self.namespace,
self.bucket_name,
cache_key
)
return pickle.loads(response.data.content)
except Exception:
return None
async def cache_result(self, file_path, result):
"""Store processing result in cache"""
try:
cache_key = self._get_cache_key(file_path)
self.client.put_object(
self.namespace,
self.bucket_name,
cache_key,
pickle.dumps(result)
)
except Exception as e:
logging.warning(f"Failed to cache result: {e}")
Monitoring and Observability
Setting Up Comprehensive Monitoring
from oci.monitoring import MonitoringClient
from oci.monitoring.models import PostMetricDataDetails, MetricDataDetails
class AIProcessingMonitor:
def __init__(self):
self.monitoring_client = MonitoringClient(config)
async def record_processing_metrics(self, compartment_id, processing_time,
confidence_score, complexity_score):
"""Record custom metrics for AI processing"""
metric_data = [
MetricDataDetails(
namespace="custom/invoice_processing",
compartment_id=compartment_id,
name="processing_time_seconds",
dimensions={"service": "ai_invoice_processor"},
datapoints=[{
"timestamp": datetime.utcnow(),
"value": processing_time,
"count": 1
}]
),
MetricDataDetails(
namespace="custom/invoice_processing",
compartment_id=compartment_id,
name="confidence_score",
dimensions={"service": "ai_invoice_processor"},
datapoints=[{
"timestamp": datetime.utcnow(),
"value": confidence_score,
"count": 1
}]
)
]
post_metric_data_details = PostMetricDataDetails(
metric_data=metric_data
)
self.monitoring_client.post_metric_data(
post_metric_data_details
)
Conclusion and Next Steps
This comprehensive exploration of OCI’s AI and machine learning capabilities demonstrates how to build sophisticated, intelligent applications that go beyond traditional cloud computing. The integration of Vision, Language, and Machine Learning services creates powerful solutions for real-world business problems.
Enjoy Reading
Osama