Beginner AI-900

AI-900: Generative AI Workloads on Azure

Generative AI models, Microsoft Foundry, Azure OpenAI, the model catalog and responsible generative AI.

Target Certification: AI-900 Microsoft Azure AI Fundamentals
Exam Module: 20–25% of the exam (highest-weighted module)
Objectives: Identify features of Generative AI solutions; identify Generative AI services and capabilities in Microsoft Azure
Level: Beginner to Intermediate


Table of Contents

  1. Introduction to Generative AI
  2. Generative AI Models
  3. Key Concepts of Generative AI
  4. Generative AI Use Cases
  5. Responsible AI for Generative AI
  6. Microsoft Foundry
  7. Azure OpenAI Service
  8. Model Catalog
  9. Practical Implementation with Python
  10. Generative AI Solution Architecture
  11. Exam Tips and Common Pitfalls
  12. Practical Exercises
  13. Summary and Key Points
  14. Glossary

1. Introduction to Generative AI

1.1 What is Generative AI?

Generative AI is a type of artificial intelligence capable of creating new content — text, code, images, audio, video — from a natural language description (a “prompt”). It doesn’t merely classify or predict: it generates.

The fundamental difference from other AI types:

AI TypeWhat it doesExample
Classical Machine LearningPredicts a value or classifies”Will this customer churn?” → Yes/No
Computer VisionAnalyzes existing images”What is in this photo?”
Traditional NLPAnalyzes existing text”Is this review positive?”
Generative AICreates new content”Write a welcome email for this customer”

1.2 The Foundation Model Revolution

Modern Generative AI is enabled by Foundation Models — models trained on massive amounts of data (gigabytes to terabytes), with billions of parameters, capable of adapting to many tasks without being retrained from scratch.

flowchart TD
    DATA["🌐 Internet Data\n(billions of texts, images, code)"] --> PRETRAIN["🔧 Pre-training\n(expensive, months)"]
    PRETRAIN --> FOUNDATION["🧠 Foundation Model\n(GPT-4, DALL-E, Phi...)\nGeneralist, versatile"]
    
    FOUNDATION --> |"Prompt Engineering\n(fast, no training cost)"| TASK1["Text Generation\n(emails, articles...)"]
    FOUNDATION --> |"Fine-tuning\n(hours/data)"| TASK2["Specialized Task\n(domain vocabulary)"]
    FOUNDATION --> |"RAG\n(connected to data)"| TASK3["Q&A on your data\n(internal documentation)"]
    FOUNDATION --> TASK4["Image Generation\nCode, Audio, Video"]

1.3 Positioning in the AI-900 Exam

Generative AI is the most heavily weighted section of the AI-900 (20-25%). Priority topics:

TopicWeightWhat to know
Concepts (token, context, RAG, hallucination)Very HighPrecise definitions
Foundation Models vs LLMsHighDifferences and use cases
Use CasesHighIdentify the right use case
Microsoft FoundryHighRole and features
Azure OpenAI ServiceHighAvailable models, differences from OpenAI.com
Responsible AI for Generative AIMediumRisks and mitigations
Model CatalogMediumTypes of available models

2. Generative AI Models

2.1 Foundation Models

Definition: Large models trained on massive data (internet, books, code…). Generalist, versatile, capable of performing many tasks.

Characteristics:

  • Trained on internet-scale data (gigabytes to terabytes)
  • Billions of parameters
  • General-purpose
  • Very expensive to train (reserved for large organizations)

Examples: GPT-5, GPT-4, DALL-E 3, Phi-3, Llama 3, Claude

2.2 Large Language Models (LLMs)

Definition: A specific type of foundation model designed to understand and generate human language.

LLM Capabilities:

  • Generate new text (articles, emails, descriptions…)
  • Summarize long blocks of text
  • Translate between languages
  • Answer questions (Q&A)
  • Generate code for developers

How they work:

flowchart LR
    PROMPT["📝 Prompt\n(user input)"] --> TOKENIZE["🔢 Tokenization\n(text → tokens)"]
    TOKENIZE --> LLM["🧠 LLM\n(billions of parameters)"]
    LLM --> PREDICT["📊 Next token\nprediction"]
    PREDICT --> |"Repeat until end"| OUTPUT["📝 Output\n(generated text)"]

Fundamental mechanism: An LLM predicts the most probable next token in a sequence. It repeats this process token by token until the response is complete. This is not “understanding” in the human sense — it is sophisticated statistical prediction.

2.3 Multimodal Models

Definition: Models capable of processing and generating multiple types of data simultaneously (text + images, text + audio…).

ModelSupported InputsSupported Outputs
GPT-4oText + Images + AudioText + Audio
DALL-E 3TextImages
GPT-4 VisionText + ImagesText
WhisperAudioText
Phi-3-VisionText + ImagesText

How models process images:

  1. The image is divided into small regions (patches)
  2. Each patch is converted into a numeric representation
  3. These representations are treated as image tokens
  4. The model can then reason about visual content

2.4 Model Type Comparison

flowchart TD
    FM["Foundation Models\nLarge, generalist\nTrained on internet-scale data"]
    
    FM --> LLM["Large Language Models\nSpecialized in language\nGPT-4, GPT-4o, Phi-3"]
    FM --> IMG["Image Generation Models\nSpecialized in images\nDALL-E 3, Stable Diffusion"]
    FM --> MULTI["Multimodal Models\nText + Image + Audio\nGPT-4o, GPT-4V"]
    FM --> EMBED["Embedding Models\nText → vector conversion\ntext-embedding-3-small"]
    FM --> SMALL["Small Language Models\nCompact, efficient\nPhi-3-mini, Phi-3.5"]
TypeSpecialtySizeUse Case
LLM (large)Text, complex reasoning100B+ parametersAdvanced chatbots, complex analysis
SLM (small)Text, targeted tasks3B-13B parametersEdge, mobile, reduced cost
Image GenerationCreating imagesVariableMarketing, design
EmbeddingVector representationCompactSemantic search, RAG
MultimodalText + images + audioVery largeUniversal assistants

3. Key Concepts of Generative AI

3.1 Token

Definition: The smallest element that a Generative AI model can process. A token can represent a full word, part of a word, or even a single character.

Tokenization examples:

"Summarize the following text" → [summarize] [the] [following] [text]

"Climate change" → [Climate] [change]
(common words are often single tokens)

"AI" → [AI]  (single token as it's very frequent in training data)

Why it matters:

  • Models are billed by number of tokens (input + output)
  • Long or rare words → more tokens → higher cost
  • The model’s token limit = limit on the length of processable text

Tokens for images:

  • The image is split into patches
  • Each patch → numeric representation → treated as a token
  • Larger images = more tokens = higher cost

3.2 Context Window

Definition: The maximum number of tokens a model can process at once. It is the model’s “short-term memory.”

flowchart LR
    subgraph "Context Window (e.g.: 1M tokens)"
        SYSTEM["System instructions\n(200 tokens)"]
        HISTORY["Conversation history\n(5000 tokens)"]
        INPUT["User input\n(300 tokens)"]
        OUTPUT["Generated response\n(400 tokens)"]
    end

Context windows for popular models (Azure OpenAI):

ModelContext WindowText equivalent
GPT-4.11,000,000+ tokens~750,000 words (~750 books)
GPT-4o128,000 tokens~96,000 words (~3 books)
GPT-3.5 Turbo16,385 tokens~12,000 words
GPT-4 Turbo128,000 tokens~96,000 words

What consumes the context window:

  1. The system prompt (model instructions)
  2. Conversation history
  3. RAG context (retrieved documents)
  4. User prompt
  5. Generated response

Important for the exam: When the context window is full, the model can no longer process additional tokens. Very long conversations may “forget” earlier messages.

3.3 Prompt and Prompt Engineering

Definition: A prompt is the textual instruction you give the model. Prompt engineering is the art of formulating prompts to get the best results.

Prompt types:

TypeDescriptionExample
Zero-shotInstruction only, no example”Translate this text to Spanish:“
One-shotInstruction + 1 example”Translate ‘hello’ → ‘hola’, now translate ‘world’:“
Few-shotInstruction + multiple examples2-5 examples to guide the model
Chain-of-ThoughtAsk the model to “think” step by step”Solve this problem step by step:”

Prompt Engineering Best Practices:

# Prompt engineering example with Azure OpenAI
from openai import AzureOpenAI
import os

client = AzureOpenAI(
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    api_key=os.environ["AZURE_OPENAI_API_KEY"],
    api_version="2024-02-01"
)

# ❌ BAD prompt: too vague
bad_prompt = "Tell me about Azure"
# Result: Generic and overly long response

# ✅ GOOD prompt: specific, clear constraints
good_prompt = """
You are a technical assistant expert in Azure.
Explain Azure Blob Storage for a beginner developer.
Constraints:
- Maximum 3 paragraphs
- Use a simple analogy to explain
- Include 2 concrete use cases
- Professional but accessible tone
"""

# ✅ EXCELLENT prompt with few-shot
few_shot_prompt = """
You convert product descriptions into marketing copy.

Example 1:
Technical description: "512GB NVMe PCIe 4.0 SSD"
Marketing copy: "Lightning fast! This ultra-fast SSD loads your games in 2 seconds and boosts your daily productivity."

Example 2:
Technical description: "27-inch IPS 144Hz display"
Marketing copy: "Total immersion! Dive into crystal-clear images with ultra-smooth motion for an unmatched visual experience."

Now convert this description:
Technical description: "Wireless headset with active noise cancellation, 40-hour battery"
Marketing copy:"""

# API call
response = client.chat.completions.create(
    model="gpt-4",  # Azure deployment name
    messages=[
        {"role": "system", "content": "You are an expert in digital marketing."},
        {"role": "user", "content": few_shot_prompt}
    ],
    max_tokens=150,
    temperature=0.7
)

print(response.choices[0].message.content)

3.4 Temperature

Definition: Parameter controlling the randomness of generated responses. Value between 0 and 2.

flowchart LR
    subgraph "Temperature Values"
        T0["🧊 Temperature = 0\nDeterministic\nAlways the same response\n→ Facts, code, translations"]
        T1["🌡️ Temperature = 1\nBalanced\nVaried but coherent response\n→ General use cases"]
        T2["🔥 Temperature = 2\nVery random\nCreative but sometimes incoherent\n→ Creative brainstorming"]
    end
TemperatureBehaviorIdeal Use Case
0.0Deterministic, always the sameCode, translation, facts
0.1 - 0.4Low randomnessSummaries, classification
0.5 - 0.8BalancedChatbots, general Q&A
0.9 - 1.2CreativeMarketing, writing
1.5 - 2.0Very creative/unpredictableExtreme brainstorming
# Comparing temperatures
def compare_temperatures(prompt: str) -> dict:
    """Generates responses with different temperatures for comparison."""
    temperatures = [0.0, 0.5, 1.0, 1.5]
    results = {}
    
    for temp in temperatures:
        response = client.chat.completions.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
            temperature=temp,
            max_tokens=100,
            seed=42  # For reproducibility (ignored if temp > 0)
        )
        results[f"temp={temp}"] = response.choices[0].message.content
    
    return results

# Test with a creative prompt
prompt = "Give me an original name for an AI startup"
results = compare_temperatures(prompt)

for config, response_text in results.items():
    print(f"\n[{config}]: {response_text}")

3.5 Embedding

Definition: Representation of text (or an image) as a high-dimensional numeric vector. Semantically similar texts have vectors close to each other.

flowchart LR
    TEXT1["'The cat sleeps'"] --> EMBED["Embedding Model\n(text-embedding-3-small)"]
    TEXT2["'The feline slumbers'"] --> EMBED
    TEXT3["'The car drives'"] --> EMBED
    
    EMBED --> VEC1["[0.23, -0.45, 0.67, ...]"]
    EMBED --> VEC2["[0.25, -0.43, 0.65, ...]"]
    EMBED --> VEC3["[-0.89, 0.12, -0.34, ...]"]
    
    VEC1 -->|"Similar!"| SIM["Cosine similarity ≈ 0.97"]
    VEC2 --> SIM
    VEC3 -->|"Different"| DIF["Cosine similarity ≈ 0.12"]

Use cases for embeddings:

  • Semantic search: Find similar documents by meaning, not just keywords
  • RAG (Retrieval-Augmented Generation): Retrieve relevant documents
  • Clustering: Group similar texts
  • Recommendation: “If you liked X, you’ll like Y”
  • Plagiarism detection: Texts that are too similar
# Embeddings example with Azure OpenAI
import numpy as np

def compute_similarity(text1: str, text2: str) -> float:
    """
    Computes cosine similarity between two texts via embeddings.
    
    Returns:
        Score between -1 (opposites) and 1 (identical)
    """
    # Generate embeddings
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=[text1, text2]
    )
    
    vector1 = np.array(response.data[0].embedding)
    vector2 = np.array(response.data[1].embedding)
    
    # Cosine similarity
    similarity = np.dot(vector1, vector2) / (
        np.linalg.norm(vector1) * np.linalg.norm(vector2)
    )
    
    return float(similarity)

# Similarity tests
pairs = [
    ("The cat sleeps on the couch", "The feline dozes on the sofa"),
    ("Azure is a cloud service", "Microsoft offers a cloud platform"),
    ("I love pizza", "The weather is cloudy"),
    ("Artificial intelligence", "Machine learning")
]

print("=== Semantic Similarities ===\n")
for text1, text2 in pairs:
    sim = compute_similarity(text1, text2)
    bar = "█" * int(sim * 20)
    print(f"  '{text1[:40]}...'")
    print(f"  '{text2[:40]}...'")
    print(f"  Similarity: {sim:.2f}  {bar}")
    print()

3.6 Deterministic vs Non-Deterministic Outputs

TypeDefinitionTemperatureExample
DeterministicSame input → same output always0”2+2=” → “4” (always)
Non-deterministicSame input → varied outputs> 0”Write a joke” → different response each time

Note: LLMs are fundamentally non-deterministic (even with temperature=0, slight variations may exist depending on the infrastructure). The seed parameter can help with reproducibility.

3.7 Hallucination

Definition: Phenomenon where an LLM generates factually incorrect information with apparent confidence. The model “invents” facts, quotes, sources that don’t exist.

Why it happens:

  • LLMs don’t verify facts — they predict the most probable text
  • The model was trained to appear confident, even when uncertain
  • Knowledge cutoff date: the model doesn’t know about recent events

Hallucination examples:

Question: "What is the latest book by [fictional author]?"
LLM: "Their latest book is 'Journey to the Stars' published in 2023."
Reality: The author doesn't exist!

Question: "What is the population of [fictional city]?"
LLM: "The population is 3.4 million according to the 2020 census."
Reality: The city doesn't exist!

Mitigation strategies:

# Hallucination mitigation with RAG
# Instead of asking the model to "know", we provide the facts

# ❌ PROBLEMATIC: Asking for facts without context
response_without_rag = client.chat.completions.create(
    model="gpt-4",
    messages=[{
        "role": "user",
        "content": "What is the subscription price of Azure DevOps for 10 users?"
    }]
)
# High risk of hallucination on prices!

# ✅ BETTER: Provide context (RAG)
official_context = """
Azure DevOps Pricing (official source August 2024):
- Basic Plan: $6 USD/user/month (first 5 users free)
- Basic + Test Plans: $52 USD/user/month
- Azure Artifacts: $2 USD/GiB/month (2 GiB free)
"""

response_with_rag = client.chat.completions.create(
    model="gpt-4",
    messages=[
        {
            "role": "system",
            "content": f"""Answer only based on the provided context. 
If the information is not in the context, say so clearly.
Never invent or extrapolate numbers.

Official context:
{official_context}"""
        },
        {
            "role": "user",
            "content": "What is the subscription price of Azure DevOps for 10 users?"
        }
    ]
)

3.8 RAG — Retrieval-Augmented Generation

Definition: Technique that augments an LLM’s responses with data retrieved in real time from an external knowledge base. This reduces hallucinations and allows the model to respond on recent or private data.

flowchart TB
    USER["👤 User question\n'What is the vacation policy?'"] --> EMBED_Q["Embedding\nof the question"]
    
    EMBED_Q --> SEARCH["🔍 Vector search\n(Azure AI Search)"]
    
    DOCS["📚 Knowledge base\n(HR policies, manuals...)"] --> EMBED_D["Embedding\nof documents (indexed)"]
    EMBED_D --> VECTDB["🗄️ Vector database\n(Azure AI Search Index)"]
    VECTDB --> SEARCH
    
    SEARCH --> RELEVANT["📄 Relevant documents\n(Top-K chunks)"]
    
    RELEVANT --> LLM["🧠 LLM (GPT-4)\nPrompt = Question + Retrieved Context"]
    USER --> LLM
    
    LLM --> ANSWER["💬 Precise response\nbased on real policies"]

Advantages of RAG:

  • Responses based on up-to-date and reliable data
  • Significant reduction in hallucinations
  • Can cite its sources
  • No need to fine-tune the model (cost-effective)
  • Private data is never in the model

RAG use cases:

  • Support chatbot using internal documentation
  • Legal assistant based on contracts
  • Q&A on HR policies
  • Technical support using previous tickets
# Simplified RAG architecture with Azure
from azure.search.documents import SearchClient
from azure.search.documents.models import VectorizedQuery
from azure.core.credentials import AzureKeyCredential
import os

class RAGAssistant:
    """Q&A assistant with RAG using Azure AI Search + Azure OpenAI."""
    
    def __init__(self):
        # Azure OpenAI client
        self.openai_client = AzureOpenAI(
            azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
            api_key=os.environ["AZURE_OPENAI_API_KEY"],
            api_version="2024-02-01"
        )
        
        # Azure AI Search client
        self.search_client = SearchClient(
            endpoint=os.environ["AZURE_SEARCH_ENDPOINT"],
            index_name="knowledge-base",
            credential=AzureKeyCredential(os.environ["AZURE_SEARCH_KEY"])
        )
        
        self.embedding_model = "text-embedding-3-small"
        self.chat_model = "gpt-4"
    
    def _generate_embedding(self, text: str) -> list[float]:
        """Generates an embedding for a given text."""
        response = self.openai_client.embeddings.create(
            model=self.embedding_model,
            input=text
        )
        return response.data[0].embedding
    
    def _search_documents(self, question: str, top_k: int = 3) -> list[dict]:
        """Retrieves relevant documents via vector search."""
        question_vector = self._generate_embedding(question)
        
        # Vector search (semantic)
        query_vector = VectorizedQuery(
            vector=question_vector,
            k_nearest_neighbors=top_k,
            fields="content_vector"  # Vector field in the index
        )
        
        results = self.search_client.search(
            search_text=None,  # Pure vector search
            vector_queries=[query_vector],
            select=["title", "content", "source_url"],
            top=top_k
        )
        
        return [
            {
                "title": r["title"],
                "content": r["content"],
                "source": r.get("source_url", "Internal")
            }
            for r in results
        ]
    
    def answer(self, question: str) -> dict:
        """
        Answers a question using RAG.
        
        Returns:
            dict with response, sources used, and tokens consumed
        """
        # 1. Retrieve relevant documents
        documents = self._search_documents(question, top_k=3)
        
        if not documents:
            return {
                "response": "I could not find relevant information in the knowledge base.",
                "sources": [],
                "tokens": 0
            }
        
        # 2. Build context
        context = "\n\n".join([
            f"Source [{i+1}] - {doc['title']}:\n{doc['content'][:500]}"
            for i, doc in enumerate(documents)
        ])
        
        # 3. Generate response with context
        system_prompt = f"""You are an expert assistant. 
Answer questions based ONLY on the context below.
If the answer is not in the context, clearly state "I cannot find this information in my knowledge base."
Always cite your sources with [1], [2], [3].

CONTEXT:
{context}"""
        
        response = self.openai_client.chat.completions.create(
            model=self.chat_model,
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": question}
            ],
            temperature=0.1,  # Low temperature for factual responses
            max_tokens=500
        )
        
        return {
            "response": response.choices[0].message.content,
            "sources": [{"title": d["title"], "url": d["source"]} for d in documents],
            "tokens_input": response.usage.prompt_tokens,
            "tokens_output": response.usage.completion_tokens,
            "tokens_total": response.usage.total_tokens
        }

# Usage
assistant = RAGAssistant()

questions = [
    "What is the company's remote work policy?",
    "How do I submit a travel expense reimbursement?",
    "What are the benefits of the health plan?"
]

for question in questions:
    print(f"\n❓ {question}")
    result = assistant.answer(question)
    print(f"💬 {result['response']}")
    print(f"📚 Sources: {[s['title'] for s in result['sources']]}")
    print(f"🔢 Tokens: {result['tokens_total']}")

3.9 Fine-tuning vs Prompt Engineering

ApproachDescriptionWhen to useCost
Prompt EngineeringOptimize instructions to the modelGeneral use cases, flexibilityLow (no training)
Few-shotProvide examples in the promptTasks with a specific formatLow (additional tokens)
RAGConnect to a knowledge basePrivate or recent dataMedium (search infrastructure)
Fine-tuningRetrain on your dataVery specific behavior, domain vocabularyHigh (data + compute)

Decision rule: Always try Prompt Engineering first. If insufficient, test Few-shot. If insufficient with private data, use RAG. If the behavior itself must change, consider Fine-tuning.


4. Generative AI Use Cases

4.1 Use Case Overview

mindmap
  root((Generative AI\nUse Cases))
    Content Creation
      Blog articles
      Marketing emails
      Product descriptions
      Technical documentation
    Summarization
      Meeting notes
      Article summaries
      Report synthesis
      Executive summaries
    Interactive Assistance
      Customer service chatbots
      IT help desk
      Virtual tutors
      Internal assistants
    Content Transformation
      Translation
      Tone change
      Simplification
      FAQ from documents
    Code Generation
      Autocomplete
      Function generation
      Debug and explanations
      Unit tests
    Image Generation
      Visual marketing
      Concept art
      Product mockups
      Illustrations

4.2 Use Cases and Services Table

Use CaseDescriptionAzure ServiceTypical Model
Text generationArticles, emails, descriptionsAzure OpenAIGPT-4, GPT-4o
SummarizationCondensing long contentAzure OpenAIGPT-4
ChatbotConversational assistantsAzure OpenAI + Bot FrameworkGPT-4o
Document Q&AAnswering from your doc baseAzure OpenAI + AI SearchGPT-4 + RAG
Code generationWrite/debug codeAzure OpenAIGPT-4
Translation/ParaphraseTransform tone, languageAzure OpenAIGPT-4
Image generationCreate visuals from textAzure OpenAI DALL-EDALL-E 3
Document analysisExtract insights from PDFsAzure OpenAI + Document IntelligenceGPT-4V

4.3 Example: Marketing Content Application

# Marketing content generation application
import os
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    api_key=os.environ["AZURE_OPENAI_API_KEY"],
    api_version="2024-02-01"
)

class MarketingContentGenerator:
    """Generates different types of marketing content with GPT-4."""
    
    TONES = {
        "professional": "Formal, professional, credible tone",
        "friendly": "Warm, accessible, conversational tone",
        "urgent": "Tone creating urgency, strong call to action",
        "premium": "Luxurious, exclusive, sophisticated tone"
    }
    
    def generate_product_description(self, 
                                     product_name: str,
                                     features: list[str],
                                     tone: str = "professional",
                                     length: str = "short") -> str:
        """Generates a product description."""
        lengths = {
            "short": "2-3 sentences maximum",
            "medium": "1 paragraph (5-7 sentences)",
            "long": "2-3 detailed paragraphs"
        }
        
        prompt = f"""Generate a product description for: {product_name}

Features:
{chr(10).join(f'• {f}' for f in features)}

Constraints:
- Tone: {self.TONES.get(tone, self.TONES['professional'])}
- Length: {lengths.get(length, lengths['short'])}
- Highlight customer benefits (not just technical specs)
- No excessive technical jargon
- End with a subtle call to action"""
        
        response = client.chat.completions.create(
            model="gpt-4",
            messages=[
                {"role": "system", "content": "You are an expert in e-commerce copywriting."},
                {"role": "user", "content": prompt}
            ],
            temperature=0.7,
            max_tokens=300
        )
        
        return response.choices[0].message.content
    
    def generate_marketing_email(self,
                                  subject: str,
                                  audience: str,
                                  objective: str) -> dict:
        """Generates a complete marketing email."""
        prompt = f"""Create a complete marketing email:
Subject: {subject}
Target audience: {audience}
Objective: {objective}

Required JSON format:
{{
    "subject_line": "...",
    "hook": "...",
    "email_body": "...",
    "call_to_action": "...",
    "postscript": "..."
}}"""
        
        response = client.chat.completions.create(
            model="gpt-4",
            messages=[
                {"role": "system", "content": "You are an expert in B2C email marketing."},
                {"role": "user", "content": prompt}
            ],
            temperature=0.8,
            max_tokens=600,
            response_format={"type": "json_object"}
        )
        
        import json
        return json.loads(response.choices[0].message.content)
    
    def generate_marketing_image(self, description: str, style: str = "photo") -> str:
        """
        Generates a marketing image with DALL-E 3.
        
        Returns:
            URL of the generated image
        """
        styles = {
            "photo": "professional commercial photography, high resolution",
            "illustration": "modern vector illustration, vivid colors",
            "minimalist": "minimalist design, white background, clean"
        }
        
        image_prompt = f"{description}, {styles.get(style, styles['photo'])}"
        
        response = client.images.generate(
            model="dall-e-3",
            prompt=image_prompt,
            size="1024x1024",
            quality="standard",
            n=1
        )
        
        return response.data[0].url

# Usage example
generator = MarketingContentGenerator()

# Product description
desc = generator.generate_product_description(
    product_name="Premium XH-900 Audio Headset",
    features=[
        "Advanced active noise cancellation",
        "40-hour battery life",
        "Bluetooth 5.2 connectivity",
        "HD integrated microphone",
        "Foldable, lightweight 250g"
    ],
    tone="premium",
    length="medium"
)
print("=== Product Description ===")
print(desc)

# Marketing email
email = generator.generate_marketing_email(
    subject="XH-900 headset launch",
    audience="Professionals 25-45 working from home",
    objective="Drive direct sales, launch offer -20%"
)
print("\n=== Marketing Email ===")
for key, value in email.items():
    print(f"\n[{key.upper()}]\n{value}")

5. Responsible AI for Generative AI

5.1 Risks Specific to Generative AI

flowchart TD
    RISKS["⚠️ Generative AI Risks"] --> H["🤔 Hallucinations\nand Misinformation\n\nInvented facts with confidence"]
    RISKS --> B["⚖️ Bias\n\nDiscriminatory or\nstereotyped output"]
    RISKS --> T["🚫 Toxic Content\n\nOffensive, hateful,\nviolent language"]
    RISKS --> D["🔓 Data Leakage\n\nConfidential information\nrevealed"]
    
    H --> H_MIT["Mitigation:\n• RAG with reliable data\n• Clear prompts\n• Human review"]
    B --> B_MIT["Mitigation:\n• Monitor outputs\n• Apply safeguards\n• Regular evaluation"]
    T --> T_MIT["Mitigation:\n• Azure Content Safety\n• Content filters\n• Restrictive system prompts"]
    D --> D_MIT["Mitigation:\n• No sensitive data\n  in prompts\n• Encryption\n• RBAC on endpoints"]

5.2 Azure Content Safety

Azure AI Content Safety is a service that analyzes and filters content generated by or submitted to AI models.

# Azure AI Content Safety - Content filtering
from azure.ai.contentsafety import ContentSafetyClient
from azure.ai.contentsafety.models import AnalyzeTextOptions, TextCategory
from azure.core.credentials import AzureKeyCredential
import os

cs_client = ContentSafetyClient(
    endpoint=os.environ["CONTENT_SAFETY_ENDPOINT"],
    credential=AzureKeyCredential(os.environ["CONTENT_SAFETY_KEY"])
)

def analyze_content_safety(text: str) -> dict:
    """
    Analyzes text for content safety issues.
    
    Categories: Hate, SelfHarm, Sexual, Violence
    Levels: Safe (0), Low (2), Medium (4), High (6)
    """
    options = AnalyzeTextOptions(
        text=text,
        categories=[
            TextCategory.HATE,
            TextCategory.SELF_HARM,
            TextCategory.SEXUAL,
            TextCategory.VIOLENCE
        ],
        output_type="FourSeverityLevels"
    )
    
    response = cs_client.analyze_text(options)
    
    results = {}
    for analysis in response.categories_analysis:
        severity = analysis.severity
        if severity is None:
            severity = 0
        
        results[analysis.category] = {
            "severity": severity,
            "level": ["Safe", "Low", "Medium", "High"][min(severity // 2, 3)],
            "block": severity >= 4  # Block if Medium or High
        }
    
    return {
        "text": text[:100],
        "categories": results,
        "action": "BLOCK" if any(r["block"] for r in results.values()) else "ALLOW"
    }

# Test
test_texts = [
    "Hello, how can I help you today?",
    "Let me explain how Azure AI works.",
]

for text in test_texts:
    result = analyze_content_safety(text)
    print(f"Text: '{result['text']}'")
    print(f"Action: {result['action']}")
    for cat, info in result['categories'].items():
        print(f"  {cat}: {info['level']} (severity={info['severity']})")
    print()

5.3 Responsible AI Principles for Generative AI

PrincipleSpecific application to Generative AIConcrete measure
FairnessAvoid biased outputs (recruitment, credit…)Test on diverse demographic groups
ReliabilityReduce hallucinationsRAG, output validation
PrivacyNot revealing personal dataDon’t include PII in prompts
InclusivenessContent accessible to allMultilingual support, inclusive tone
TransparencyIndicate content is AI-generatedWatermarking, disclaimers
AccountabilityHuman review for important decisionsHuman-in-the-loop for critical content

6. Microsoft Foundry

6.1 What is Microsoft Foundry?

Microsoft Foundry is Azure’s unified platform for developing, deploying, and managing Generative AI applications. It is the recommended entry point for working with generative AI models on Azure.

Exam note: Microsoft Foundry is a development and management platform, not an AI model itself. Models (GPT-4, DALL-E…) are accessible VIA Microsoft Foundry.

flowchart TD
    FOUNDRY["🏭 Microsoft Foundry\n(Unified Platform)"] --> CATALOG["📦 Model Catalog\n(172+ models)"]
    FOUNDRY --> PLAYGROUND["🎮 Playgrounds\n(Chat, Image, Audio)"]
    FOUNDRY --> DEPLOY["🚀 Deployment\n(Managed Endpoints)"]
    FOUNDRY --> MONITOR["📊 Monitoring\n(Usage, Performance)"]
    FOUNDRY --> FINETUNE["🔧 Fine-tuning\n(Customize models)"]
    FOUNDRY --> AGENTS["🤖 AI Agents\n(Autonomous agents)"]
    FOUNDRY --> SECURITY["🔒 Security\n(RBAC, Networking, Key Vault)"]
    
    CATALOG --> OPENAI["OpenAI Models\n(GPT-4, DALL-E...)"]
    CATALOG --> MICROSOFT["Microsoft Models\n(Phi-3, Florence...)"]
    CATALOG --> THIRDPARTY["Third-party Models\n(Llama, Claude, Mistral...)"]

6.2 Key Features of Microsoft Foundry

FeatureDescriptionBenefit
Model CatalogLibrary of 172+ AI modelsFind and deploy easily
PlaygroundsInteractive testing environmentsTest without code
DeploymentDeploy models with managed endpointsAutomatic scalability
MonitoringTrack usage and performanceCost optimization
Fine-tuningCustomize existing modelsAdapted to your data
AI AgentsAutonomous multi-step agentsComplex automation
SecurityRBAC, VNet, Key Vault integratedEnterprise compliance
Multi-cloudAccessible via Azure Portal and Foundry PortalFlexibility

6.3 Available Playgrounds

flowchart LR
    PLAYGROUND["Microsoft Foundry Playgrounds"] --> CHAT["Chat Playground\n• Test LLMs\n• Adjust system prompt\n• Modify temperature\n• See tokens used"]
    PLAYGROUND --> IMAGE["Image Playground\n• Test DALL-E\n• Generate images\n• See effective prompts"]
    PLAYGROUND --> AUDIO["Audio Playground\n• Test audio models\n• Speech-to-Text\n• Text-to-Speech"]

6.4 Accessing Foundry via SDK

# Using Microsoft Foundry via Azure OpenAI SDK
# (Microsoft Foundry exposes models via Azure OpenAI-compatible endpoints)
from openai import AzureOpenAI
import os

# The Foundry endpoint is compatible with the Azure OpenAI SDK
foundry_client = AzureOpenAI(
    azure_endpoint=os.environ["AZURE_FOUNDRY_ENDPOINT"],
    api_key=os.environ["AZURE_FOUNDRY_API_KEY"],
    api_version="2024-05-01-preview"
)

# Use a model deployed in Foundry
response = foundry_client.chat.completions.create(
    model="gpt-4-1",  # Deployment name in Foundry
    messages=[
        {
            "role": "system",
            "content": "You are a technical expert in Azure."
        },
        {
            "role": "user",
            "content": "What are the advantages of Microsoft Foundry?"
        }
    ],
    max_tokens=500,
    temperature=0.5
)

# Get the response
print(response.choices[0].message.content)
print(f"\nTokens used: {response.usage.total_tokens}")
print(f"Estimated cost: {response.usage.total_tokens * 0.00001:.5f}$")

7. Azure OpenAI Service

7.1 Azure OpenAI vs OpenAI.com

Fundamental difference: Azure OpenAI Service is an enterprise version of OpenAI, hosted in Azure with all Azure security and compliance guarantees.

AspectOpenAI.comAzure OpenAI Service
HostingOpenAI infrastructureMicrosoft Azure
AuthenticationOpenAI API keyAzure RBAC + Azure AD
SecurityStandardAzure-grade (VNET, Private Endpoints)
ComplianceBasicSOC 2, ISO 27001, HIPAA, GDPR
SLANone guaranteed99.9% (Azure SLA)
DataMay be used for trainingNOT used for training
AccessOpenAI accountAzure subscription
SupportOpenAIMicrosoft Azure Support
Azure IntegrationNoFull (Key Vault, Monitor, AI Search…)

7.2 Models Available in Azure OpenAI

mindmap
  root((Azure OpenAI\nModels))
    GPT Text Generation
      GPT-5
      GPT-4o
      GPT-4.1
      GPT-4 Turbo
      GPT-3.5 Turbo
      GPT-4o mini
    Reasoning
      o1
      o1-mini
      o3
      o3-mini
    Embeddings
      text-embedding-3-large
      text-embedding-3-small
      text-embedding-ada-002
    Images
      DALL-E 3
      DALL-E 2
    Audio
      Whisper
      TTS tts-1
      TTS tts-1-hd
    Multimodal
      GPT-4 Vision
      GPT-4o

7.3 Complete Implementation with Azure OpenAI

# Full Azure OpenAI client
from openai import AzureOpenAI
import os
import json
import base64
from pathlib import Path

class AzureOpenAIClient:
    """Complete client for Azure OpenAI Service."""
    
    def __init__(self):
        self.client = AzureOpenAI(
            azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
            api_key=os.environ["AZURE_OPENAI_API_KEY"],
            api_version="2024-02-01"
        )
        
        self.chat_model = os.environ.get("AZURE_OPENAI_CHAT_MODEL", "gpt-4")
        self.embedding_model = os.environ.get("AZURE_OPENAI_EMBED_MODEL", "text-embedding-3-small")
        self.image_model = os.environ.get("AZURE_OPENAI_IMAGE_MODEL", "dall-e-3")
    
    def chat(self, 
             messages: list[dict],
             temperature: float = 0.7,
             max_tokens: int = 1000,
             json_mode: bool = False) -> dict:
        """
        Sends messages to the chat model.
        
        Args:
            messages: List of messages [{role, content}]
            temperature: Creativity (0=deterministic, 2=very creative)
            max_tokens: Output token limit
            json_mode: If True, forces response as valid JSON
        
        Returns:
            dict with response and metadata
        """
        kwargs = {
            "model": self.chat_model,
            "messages": messages,
            "temperature": temperature,
            "max_tokens": max_tokens
        }
        
        if json_mode:
            kwargs["response_format"] = {"type": "json_object"}
        
        response = self.client.chat.completions.create(**kwargs)
        
        return {
            "content": response.choices[0].message.content,
            "role": response.choices[0].message.role,
            "finish_reason": response.choices[0].finish_reason,
            "tokens": {
                "input": response.usage.prompt_tokens,
                "output": response.usage.completion_tokens,
                "total": response.usage.total_tokens
            },
            "model": response.model
        }
    
    def analyze_image(self, 
                       question: str, 
                       image_path: str = None,
                       image_url: str = None) -> str:
        """
        Analyzes an image with GPT-4 Vision.
        
        Args:
            question: Question about the image
            image_path: Local image path
            image_url: Public image URL
        """
        # Prepare the image
        if image_path:
            with open(image_path, "rb") as f:
                image_data = base64.b64encode(f.read()).decode("utf-8")
            
            ext = Path(image_path).suffix.lower()
            mime_types = {".jpg": "image/jpeg", ".png": "image/png"}
            mime = mime_types.get(ext, "image/jpeg")
            
            image_content = {
                "type": "image_url",
                "image_url": {"url": f"data:{mime};base64,{image_data}"}
            }
        elif image_url:
            image_content = {
                "type": "image_url",
                "image_url": {"url": image_url}
            }
        else:
            raise ValueError("Provide image_path or image_url")
        
        response = self.client.chat.completions.create(
            model=self.chat_model,
            messages=[{
                "role": "user",
                "content": [
                    {"type": "text", "text": question},
                    image_content
                ]
            }],
            max_tokens=500
        )
        
        return response.choices[0].message.content
    
    def generate_image(self, 
                        description: str,
                        size: str = "1024x1024",
                        quality: str = "standard") -> str:
        """
        Generates an image with DALL-E 3.
        
        Returns:
            URL of the generated image (valid 1h)
        """
        response = self.client.images.generate(
            model=self.image_model,
            prompt=description,
            size=size,      # "1024x1024", "1792x1024", "1024x1792"
            quality=quality,  # "standard" or "hd"
            n=1,
            style="vivid"     # "vivid" (default) or "natural"
        )
        
        return response.data[0].url
    
    def summarize_document(self, 
                             text: str, 
                             target_length: int = 200) -> str:
        """Summarizes a long document."""
        return self.chat(
            messages=[
                {
                    "role": "system",
                    "content": f"Summarize the following text in approximately {target_length} words. "
                               "Keep the essential information. "
                               "Use bullet points if appropriate."
                },
                {"role": "user", "content": text}
            ],
            temperature=0.3  # Low temp for factual summaries
        )["content"]
    
    def generate_code(self, 
                       description: str, 
                       language: str = "python") -> str:
        """Generates code from a description."""
        return self.chat(
            messages=[
                {
                    "role": "system",
                    "content": f"You are an expert {language} developer. "
                               "Generate clean, commented, production-ready code. "
                               "Include docstrings and error handling."
                },
                {
                    "role": "user",
                    "content": f"Write {language} code for: {description}"
                }
            ],
            temperature=0.2  # Precise code = low temperature
        )["content"]
    
    def translate(self, text: str, target_language: str) -> str:
        """Translates a text to the target language."""
        return self.chat(
            messages=[{
                "role": "user",
                "content": f"Translate the following text to {target_language}. "
                           "Preserve the tone, style, and formatting:\n\n{text}"
            }],
            temperature=0.3
        )["content"]

# === Demonstrations ===
ai_client = AzureOpenAIClient()

# 1. Simple chat
print("=== Simple Chat ===")
response = ai_client.chat(
    messages=[
        {"role": "system", "content": "You are an Azure AI expert."},
        {"role": "user", "content": "Explain Azure OpenAI Service in 3 key points."}
    ]
)
print(f"Response: {response['content']}")
print(f"Tokens: {response['tokens']['total']}")

# 2. Summary
print("\n=== Summary ===")
long_text = """
Azure Machine Learning is a cloud platform that enables data scientists
and ML engineers to create, deploy, and manage machine learning models.
It provides tools for the entire ML lifecycle, from data preparation
to model monitoring in production. Features include AutoML for
automating algorithm selection, Designer for creating pipelines visually,
and the Python SDK for custom workflows. It integrates with Azure DevOps for
CI/CD pipelines and Azure Monitor for observability.
"""
summary = ai_client.summarize_document(long_text, target_length=50)
print(f"Summary: {summary}")

# 3. Code generation
print("\n=== Code Generation ===")
code = ai_client.generate_code(
    description="A function that computes the TF-IDF score for a list of documents",
    language="python"
)
print(code[:500] + "...")

8. Model Catalog

8.1 Overview

The Model Catalog in Microsoft Foundry is a centralized marketplace for discovering, evaluating, and deploying generative AI models. More than 172 models are available.

flowchart TD
    CATALOG["🗂️ Model Catalog\n(172+ models)"] --> OPENAI_MODELS["OpenAI\n• GPT-5 series\n• GPT-4.x series\n• DALL-E 3\n• Whisper\n• Embeddings"]
    CATALOG --> MS_MODELS["Microsoft\n• Phi-3 (small)\n• Phi-3.5 (vision)\n• Florence\n• BioMedLM"]
    CATALOG --> THIRD_PARTY["Third-party\n• Meta Llama 3\n• Anthropic Claude\n• Mistral\n• DeepSeek\n• Cohere"]

8.2 Model Types in the Catalog

CategoryModelsUse Cases
Large LLMsGPT-4, GPT-5, Claude 3Complex reasoning, advanced chatbots
SLMs (small)Phi-3-mini, Phi-3.5Edge, mobile, reduced cost
Reasoningo1, o3, DeepSeek-R1Math, code, complex logic
MultimodalGPT-4o, GPT-4V, Phi-3-VisionText + images simultaneously
Embeddingstext-embedding-3-large, smallSemantic search, RAG
ImagesDALL-E 3, Stable DiffusionImage generation
AudioWhisper, TTSTranscription, text-to-speech
CodeGPT-4, Phi-3 (code)Code generation, debugging

8.3 Choosing the Right Model

# Model selection guide
def recommend_model(use_case: str, 
                    budget: str = "medium",
                    precision_required: str = "high") -> dict:
    """
    Recommends an Azure OpenAI model based on use case.
    
    Args:
        use_case: Type of task
        budget: "low", "medium", "high"
        precision_required: "low", "medium", "high"
    
    Returns:
        Recommendation with justification
    """
    recommendations = {
        "support_chatbot": {
            "low": {"model": "gpt-4o-mini", "reason": "Fast, economical for simple Q&A"},
            "medium": {"model": "gpt-4o", "reason": "Good cost/performance balance"},
            "high": {"model": "gpt-4", "reason": "Best contextual understanding"}
        },
        "code_generation": {
            "low": {"model": "gpt-4o-mini", "reason": "Sufficient for simple code"},
            "medium": {"model": "gpt-4", "reason": "Good for complex code"},
            "high": {"model": "o1", "reason": "Superior reasoning for algorithms"}
        },
        "image_generation": {
            "low": {"model": "dall-e-2", "reason": "Less expensive, sufficient quality"},
            "medium": {"model": "dall-e-3", "reason": "High quality, good value"},
            "high": {"model": "dall-e-3-hd", "reason": "Maximum quality"}
        },
        "semantic_search": {
            "low": {"model": "text-embedding-ada-002", "reason": "Economical for embeddings"},
            "medium": {"model": "text-embedding-3-small", "reason": "Better quality/price"},
            "high": {"model": "text-embedding-3-large", "reason": "Best precision"}
        },
        "transcription": {
            "low": {"model": "whisper", "reason": "Only available option"},
            "medium": {"model": "whisper", "reason": "Only available option"},
            "high": {"model": "whisper", "reason": "Only available option"}
        },
        "complex_reasoning": {
            "low": {"model": "gpt-4o", "reason": "Acceptable compromise"},
            "medium": {"model": "o1-mini", "reason": "Good reasoning, cheaper than o1"},
            "high": {"model": "o3", "reason": "Most advanced reasoning"}
        }
    }
    
    if use_case not in recommendations:
        return {"model": "gpt-4o", "reason": "Default versatile model"}
    
    return recommendations[use_case].get(budget, recommendations[use_case]["medium"])

# Tests
use_cases = [
    ("support_chatbot", "medium"),
    ("code_generation", "high"),
    ("image_generation", "medium"),
    ("complex_reasoning", "high"),
    ("semantic_search", "low")
]

print("=== Model Recommendations ===\n")
for case, budget in use_cases:
    reco = recommend_model(case, budget)
    print(f"Use case: {case} (budget: {budget})")
    print(f"  → Model: {reco['model']}")
    print(f"  → Reason: {reco['reason']}")
    print()

9. Practical Implementation with Python

9.1 Complete Conversational Assistant

# Conversational assistant with memory, RAG, and safety
from dataclasses import dataclass, field
from datetime import datetime
import os
from openai import AzureOpenAI

@dataclass
class Message:
    """Represents a message in the conversation."""
    role: str  # "system", "user", "assistant"
    content: str
    timestamp: str = field(default_factory=lambda: datetime.now().isoformat())

class ConversationalAssistant:
    """
    Conversational assistant with:
    - Conversation memory (history)
    - Configurable system prompt
    - Token management (automatic truncation)
    - Conversation logging
    """
    
    MAX_HISTORY_TOKENS = 4000  # Max tokens for history
    
    def __init__(self, system_prompt: str, model: str = "gpt-4o"):
        self.client = AzureOpenAI(
            azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
            api_key=os.environ["AZURE_OPENAI_API_KEY"],
            api_version="2024-02-01"
        )
        self.model = model
        self.system_prompt = system_prompt
        self.history: list[Message] = []
        self.total_tokens_used = 0
    
    def _build_messages(self) -> list[dict]:
        """
        Builds the message list for the API.
        Truncates history if too long.
        """
        messages = [{"role": "system", "content": self.system_prompt}]
        
        # Estimate tokens (approximation: ~4 chars per token)
        estimated_tokens = len(self.system_prompt) // 4
        
        # Add history starting from most recent messages
        for msg in reversed(self.history):
            msg_tokens = len(msg.content) // 4
            if estimated_tokens + msg_tokens > self.MAX_HISTORY_TOKENS:
                break
            estimated_tokens += msg_tokens
            messages.insert(1, {"role": msg.role, "content": msg.content})
        
        return messages
    
    def send_message(self, 
                      user_text: str,
                      temperature: float = 0.7) -> str:
        """
        Sends a message to the assistant and returns the response.
        
        Args:
            user_text: User message
            temperature: Response creativity
        
        Returns:
            Assistant's response
        """
        # Add user message to history
        self.history.append(Message(role="user", content=user_text))
        
        # Build messages for API
        messages = self._build_messages()
        
        # API call
        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            temperature=temperature,
            max_tokens=1000
        )
        
        response_text = response.choices[0].message.content
        self.total_tokens_used += response.usage.total_tokens
        
        # Add response to history
        self.history.append(Message(role="assistant", content=response_text))
        
        return response_text
    
    def clear_history(self) -> None:
        """Clears the conversation history (new session)."""
        self.history = []
    
    def get_conversation_summary(self) -> str:
        """Generates a summary of the current conversation."""
        if len(self.history) < 2:
            return "No conversation to summarize."
        
        history_text = "\n".join([
            f"{msg.role.upper()}: {msg.content[:200]}"
            for msg in self.history
        ])
        
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "user", 
                 "content": f"Summarize this conversation in 3 points:\n{history_text}"}
            ],
            temperature=0.3,
            max_tokens=200
        )
        
        return response.choices[0].message.content

# Demonstration of an Azure technical support assistant
assistant = ConversationalAssistant(
    system_prompt="""You are a technical support assistant specialized in Azure AI.
You help developers understand and use Azure AI services.
Your responses are:
- Accurate and technical
- Accompanied by code examples when relevant
- In English
- Limited to 3-4 paragraphs maximum per response
If a question falls outside your Azure AI domain, indicate it politely.""",
    model="gpt-4o"
)

# Simulating a conversation
conversation = [
    "What is the difference between Azure OpenAI and OpenAI.com?",
    "When should I use RAG rather than fine-tuning?",
    "Can you give me a Python code example for using RAG with Azure AI Search?"
]

print("=== Conversational Assistant Demonstration ===\n")
for question in conversation:
    print(f"👤 User: {question}")
    response = assistant.send_message(question)
    print(f"🤖 Assistant: {response[:300]}...")
    print(f"   [Tokens used: {assistant.total_tokens_used}]")
    print()

print("=== Conversation Summary ===")
print(assistant.get_conversation_summary())

10. Generative AI Solution Architecture

10.1 Reference Architecture

flowchart TB
    USER["👤 Users"] --> FE["Frontend\n(React, Teams, Mobile)"]
    FE --> APIM["Azure API Management\n(Rate limiting, Auth)"]
    
    APIM --> FUNC["Azure Functions\n(Orchestration)"]
    
    FUNC --> FOUNDRY["Microsoft Foundry\n(Azure OpenAI / Models)"]
    FUNC --> SEARCH["Azure AI Search\n(RAG - Vector search)"]
    FUNC --> CONTENT["Azure AI Content Safety\n(Content filtering)"]
    
    SEARCH --> STORAGE["Azure Blob Storage\n(Source documents)"]
    SEARCH --> INDEX["Vector Index\n(Embeddings)"]
    
    FOUNDRY --> GPT4["GPT-4\n(Response generation)"]
    FOUNDRY --> EMBED["text-embedding-3-small\n(Embeddings)"]
    FOUNDRY --> DALLE["DALL-E 3\n(Images)"]
    
    subgraph "Security and Monitoring"
        KV["Azure Key Vault\n(Secrets)"]
        MONITOR["Azure Monitor\n(Metrics, Logs)"]
        AAD["Azure Active Directory\n(Auth)"]
    end
    
    FUNC -.-> KV
    FOUNDRY -.-> MONITOR
    APIM -.-> AAD

10.2 Deployment Pattern with Cost Management

# Cost management with token counting
from dataclasses import dataclass

@dataclass
class TokenCost:
    """Calculates cost based on tokens used."""
    
    # Approximate Azure OpenAI prices (USD/1000 tokens)
    MODEL_PRICES = {
        "gpt-4": {"input": 0.03, "output": 0.06},
        "gpt-4o": {"input": 0.005, "output": 0.015},
        "gpt-4o-mini": {"input": 0.00015, "output": 0.0006},
        "gpt-3.5-turbo": {"input": 0.0005, "output": 0.0015},
        "text-embedding-3-small": {"input": 0.00002, "output": 0},
        "text-embedding-3-large": {"input": 0.00013, "output": 0},
        "dall-e-3-standard": {"input": 0.04, "output": 0},  # per image
        "dall-e-3-hd": {"input": 0.08, "output": 0}  # per HD image
    }
    
    def calculate_cost(self, 
                        model: str, 
                        input_tokens: int, 
                        output_tokens: int) -> dict:
        """
        Calculates the cost of an API call.
        
        Returns:
            dict with input, output, and total cost
        """
        if model not in self.MODEL_PRICES:
            return {"error": f"Unknown model '{model}'"}
        
        prices = self.MODEL_PRICES[model]
        input_cost = (input_tokens / 1000) * prices["input"]
        output_cost = (output_tokens / 1000) * prices["output"]
        
        return {
            "model": model,
            "input_tokens": input_tokens,
            "output_tokens": output_tokens,
            "input_cost_usd": round(input_cost, 6),
            "output_cost_usd": round(output_cost, 6),
            "total_cost_usd": round(input_cost + output_cost, 6),
            "total_cost_cad": round((input_cost + output_cost) * 1.36, 6)
        }
    
    def estimate_monthly_budget(self,
                                 model: str,
                                 tokens_per_call: int,
                                 calls_per_day: int) -> dict:
        """Estimates monthly budget for a given workload."""
        monthly_calls = calls_per_day * 30
        input_tokens_per_call = tokens_per_call * 0.6  # 60% input
        output_tokens_per_call = tokens_per_call * 0.4  # 40% output
        
        cost_per_call = self.calculate_cost(
            model,
            int(input_tokens_per_call),
            int(output_tokens_per_call)
        )
        
        return {
            "monthly_calls": monthly_calls,
            "cost_per_call_usd": cost_per_call["total_cost_usd"],
            "monthly_cost_usd": round(cost_per_call["total_cost_usd"] * monthly_calls, 2),
            "monthly_cost_cad": round(cost_per_call["total_cost_usd"] * monthly_calls * 1.36, 2)
        }

# Cost comparison
calculator = TokenCost()

print("=== Model comparison (1000 input tokens + 500 output) ===\n")
models = ["gpt-4", "gpt-4o", "gpt-4o-mini", "gpt-3.5-turbo"]

for model in models:
    cost = calculator.calculate_cost(model, 1000, 500)
    print(f"{model:20}: ${cost['total_cost_usd']:.5f}/call  (~${cost['total_cost_usd']*1000:.3f}/1000 calls)")

print("\n=== Monthly budget estimate (100 calls/day, 1500 tokens/call) ===\n")
for model in models:
    budget = calculator.estimate_monthly_budget(model, 1500, 100)
    print(f"{model:20}: ${budget['monthly_cost_usd']:.2f}/month USD  (~${budget['monthly_cost_cad']:.2f} CAD)")

11. Exam Tips and Common Pitfalls

11.1 Critical Distinctions

Common confusionClarification
Foundry = AI modelNo! Foundry = development platform. Models are in the Model Catalog
Azure OpenAI = OpenAI.comNo! Azure OpenAI is hosted in Azure with enterprise security
Temperature = 0 → 100% identicalAlmost, but slight variations remain possible (not 100% guaranteed)
RAG = Fine-tuningNo! RAG connects to external data. Fine-tuning modifies model weights
Hallucination = errorIt is a fundamental characteristic of LLMs, not a bug
Context Window = permanent memoryIt is temporary memory, cleared between sessions
Tokens = wordsA token can be part of a word, a word, or punctuation

11.2 Quick Associations for the Exam

"Create new content" → Generative AI (Azure OpenAI)
"Billions of parameters" → Foundation Model
"Understands text + images" → Multimodal model
"Predicts the next token" → LLM (basic mechanism)
"False but confident information" → Hallucination
"Connect to internal data without retraining" → RAG
"Conversation memory" → Context Window
"Deeply change model behavior" → Fine-tuning
"Playground, Model Catalog, deployment" → Microsoft Foundry
"Enterprise, Azure RBAC, VNET" → Azure OpenAI Service
"Response randomness" → Temperature
"Vectorial text representation" → Embedding
"Semantic search, RAG" → Embedding + Azure AI Search
"Offensive, hateful content" → Azure AI Content Safety

11.3 Final Checklist

✅ I understand the difference between Foundation Model, LLM, and multimodal model
✅ I know what a token is and how billing works
✅ I understand the context window and its limits
✅ I know when to use Prompt Engineering vs RAG vs Fine-tuning
✅ I can explain hallucination and its mitigations
✅ I know the role of Microsoft Foundry (platform, not a model)
✅ I know the difference between Azure OpenAI vs OpenAI.com
✅ I know which model for which use case (GPT, DALL-E, Embeddings, Whisper)
✅ I know the 6 Responsible AI risks for Generative AI
✅ I know what Azure AI Content Safety does

12. Practical Exercises

12.1 Scenario: Internal Support Chatbot

Objective: Build a Q&A assistant using RAG on internal documentation.

Proposed architecture:

  1. Azure AI Document Intelligence → Extract text from PDFs
  2. Azure OpenAI (text-embedding-3-small) → Embeddings of chunks
  3. Azure AI Search → Vector index
  4. Azure OpenAI (GPT-4o) → Response generation

Steps:

1. Index the documentation:
   for doc in documents:
       text = extract_pdf_text(doc)  # Document Intelligence
       chunks = split_into_chunks(text, size=500)
       for chunk in chunks:
           embedding = generate_embedding(chunk)  # text-embedding-3-small
           index_in_search(chunk, embedding)  # Azure AI Search

2. Answer questions:
   def answer(question):
       vec_question = generate_embedding(question)
       relevant_docs = vector_search(vec_question, top_k=3)
       context = "\n".join(relevant_docs)
       response = gpt4o.chat(system=f"Context: {context}", user=question)
       return response

12.2 Sample Exam Questions

Q1: An LLM generates “The President of France in 2024 is Jacques Chirac.” What concept does this illustrate?

A: Hallucination – the model generates a factually incorrect response with confidence.

Q2: What is the fundamental difference between RAG and Fine-tuning?

A: RAG retrieves external information at inference time (without modifying the model). Fine-tuning retrains the model on new data (modifies its weights).

Q3: Is Microsoft Foundry an AI model?

A: No! Microsoft Foundry is a development and management platform. Models (GPT-4, DALL-E…) are accessible VIA Foundry.

Q4: What temperature should you choose for generating Python code?

A: Temperature close to 0 (0.1-0.2) for deterministic and precise responses.


13. Summary and Key Points

13.1 Fundamental Concepts

mindmap
  root((Generative AI\nKey Concepts))
    Models
      Foundation Models (generalist)
      LLMs (language)
      Multimodal (text + images)
      Embeddings (vectors)
    Concepts
      Token (smallest unit)
      Context Window (max memory)
      Temperature (randomness)
      Hallucination (errors)
    Techniques
      Prompt Engineering (instructions)
      RAG (external data)
      Fine-tuning (retraining)
      Few-shot (examples)
    Azure Services
      Microsoft Foundry (platform)
      Azure OpenAI Service (models)
      Model Catalog (marketplace)
      Content Safety (filtering)

13.2 Final Synthesis Table

ConceptOne-line definitionExample
Generative AICreates new content from a promptGPT-4 writes an article
Foundation ModelLarge generalist model trained on the internetGPT-4, DALL-E
LLMFoundation model specialized in languageGPT-4, GPT-4o
TokenSmallest unit processable by the model1 word ≈ 1-2 tokens
Context WindowMax token limit in one interactionGPT-4.1 = 1M tokens
TemperatureRandomness parameter (0=deterministic, 2=creative)0 for code, 1 for emails
HallucinationGenerating false information with confidenceCiting a non-existent source
RAGAugment the LLM with retrieved external dataQ&A on your documentation
EmbeddingVector representation of textSemantic similarity
Fine-tuningRetrain the model on your dataAdapt the company’s tone
Microsoft FoundryAzure unified platform for Generative AIDeploy, test, monitor
Azure OpenAIOpenAI with Azure enterprise securityGPT-4 with RBAC, VNet

14. Glossary

TermDefinition
Azure AI Content SafetyAzure service filtering offensive/harmful content
Azure OpenAI ServiceAzure service providing access to OpenAI models with enterprise security
Chain-of-ThoughtPrompting technique asking the model to reason step by step
Context WindowMaximum number of tokens an LLM can process at once
DALL-EOpenAI image generation model from text descriptions
DeterministicResponse that will always be identical for the same input (temperature=0)
EmbeddingNumeric vector representation of text or an image
Few-shotPrompting technique providing multiple examples to the model
Fine-tuningRetraining a pre-trained model on specific data
Foundation ModelLarge generalist model trained on internet-scale data
Generative AIAI capable of creating new content (text, images, code…)
GPTGenerative Pre-trained Transformer – OpenAI LLM model
HallucinationLLM generating incorrect facts with false confidence
LLMLarge Language Model – foundation model specialized in language
Microsoft FoundryAzure unified platform for developing/deploying Generative AI solutions
Model CatalogLibrary of 172+ AI models in Microsoft Foundry
MultimodalModel processing multiple data types (text + images + audio)
Non-deterministicResponse that may vary for the same input (temperature > 0)
One-shotPrompting technique with a single provided example
PromptTextual instruction given to a Generative AI model
Prompt EngineeringArt of optimizing instructions to get better results
RAGRetrieval-Augmented Generation – augmenting LLMs with external data
SLMSmall Language Model – compact and efficient model (Phi-3)
TemperatureParameter controlling response randomness (0-2)
TokenSmallest unit processable by a model (word, sub-word, character)
Zero-shotPrompting technique with no provided examples

Additional resources:


Document prepared for the AI-900 Azure AI Fundamentals certification – Generative AI Workloads on Azure


Search Terms

ai-900 · generative · ai · workloads · azure · services · artificial · intelligence · model · models · exam · foundry · openai · microsoft · architecture · available · cases · catalog · concepts · content · engineering · foundation · practical · prompt

Interested in this course?

Contact us to book it or get a custom training plan for your team.