Dashboard Part 2 Azure OpenAI
🤖 Part 2 · Topic 2 of 3

Use Azure OpenAI in Foundry Models

This topic covers the Azure OpenAI service in depth — provisioning resources, deploying models, calling the Chat Completions API from Python, generating images with DALL-E, transcribing audio with Whisper, and working with multimodal models that understand both text and images.

🐍 Python — every line explained ⏱️ ~50 min 🔥 Very high exam weight Requires Topic 1 (Part 2)
🔗
Building on Topic 1

This topic uses from Topic 1: token, LLM, prompt, grounding, RAG, model catalog, deployment, dictionary (Python), and messages array. New concepts below are all introduced before code uses them.

Azure OpenAI terms — defined before code

Chat Completion

The primary Azure OpenAI API endpoint. You send a conversation history (a list of messages with roles) and the model generates the next message. This is how GPT-4o works — you give it the conversation so far and it responds as the assistant.

System Message

The first message in the conversation with role: "system". It sets the model's behaviour, persona, and constraints before any user interaction. Example: "You are a friendly customer service agent for Contoso Bank. Only answer questions about banking products."

User Message

A message with role: "user" — what the human said. In a real conversation there are multiple alternating user and assistant messages. This is the input the model responds to.

Assistant Message

A message with role: "assistant" — what the AI previously said. In multi-turn conversations, you include previous assistant responses in the messages array so the model has memory of the conversation history.

Messages Array

The list of all messages in the conversation, sent to the API. Each message is a dictionary with "role" and "content" keys. The model reads the entire array to understand the conversation context before generating the next response.

Completion (legacy)

The older Azure OpenAI API (now deprecated for most models). You send a single text prompt and the model completes it. The exam still references this — but prefer Chat Completions for GPT-3.5-turbo and GPT-4o onwards.

API Version

Azure OpenAI requires you to specify an API version in every call — e.g. "2024-02-01". This ensures your code doesn't break when Azure releases new API versions. Always specify the version explicitly.

Deployment Name vs Model Name

Model name: the actual AI model — e.g. gpt-4o. Deployment name: the name you gave your deployment in Foundry — e.g. "my-gpt4o". In Python code, you always use the deployment name, not the model name, in the model= parameter.

Multimodal

A model that accepts multiple types of input — text AND images. GPT-4o is multimodal: you can include an image in the user message and ask "What is in this image?" The model understands and responds to both.

DALL-E

An Azure OpenAI model that generates images from text descriptions (prompts). You send a text description like "a golden retriever playing in autumn leaves, photorealistic" and it returns a URL to a generated image. Current version in Azure: DALL-E 3.

Whisper

An OpenAI audio model available in Azure. It transcribes speech from audio files into text. Supports 57 languages. Used in Azure OpenAI for high-accuracy transcription beyond what Azure AI Speech offers.

Standard vs Provisioned Deployment

Standard: pay per token (pay-as-you-go). Good for variable traffic. May be subject to throttling at peak times. Provisioned Managed: you reserve a fixed number of tokens per minute (PTU). Guaranteed throughput. Higher upfront cost. Best for predictable production workloads.

Creating an Azure OpenAI resource

Azure OpenAI is a separate resource type from standard Azure AI Services. It requires a separate application and approval process for new customers.

1
Azure Portal — Create Azure OpenAI resource

portal.azure.com → search "Azure OpenAI" → + Create → Fill in: subscription, resource group, region, name, pricing tier (S0). Note: not all regions have all models — choose East US or West Europe for widest availability.

2
Deploy a model

ai.azure.com → your project → Models + endpoints → + Deploy model → Select from catalog (e.g. gpt-4o) → Give deployment a name → Choose deployment type (Standard or Provisioned) → Set token limit → Deploy.

3
Get your endpoint and key

Azure portal → your Azure OpenAI resource → Keys and Endpoint. Endpoint format: https://your-name.openai.azure.com/. This is different from the cognitiveservices.azure.com format used by other AI services.

🎯
Exam Tip — Azure OpenAI Endpoint Is Different

Azure OpenAI endpoints use the domain openai.azure.com, not cognitiveservices.azure.com. The exam shows endpoints and asks which service they belong to.
https://my-resource.openai.azure.com/ → Azure OpenAI
https://my-resource.cognitiveservices.azure.com/ → Other AI services
https://my-resource.search.windows.net → Azure AI Search

How to call GPT-4o from Python

The Chat Completions API is the primary way to interact with GPT models. Before the code, understand the three roles in a conversation:

system
System Role

The instructions that govern how the model behaves. Set once at the start. The model "reads" this before anything else. Defines persona, constraints, and tone. Think of it as the briefing you give the AI before it starts working.

user
User Role

What the human (your application's user) is saying. In a multi-turn conversation there are multiple user messages, alternating with assistant messages. This is the input the model is responding to.

assistant
Assistant Role

What the model has previously said. You include previous assistant responses in the messages array so the model "remembers" the conversation history. Without these, the model has no memory of previous turns.

Single-turn call (one question, one answer)

import os
from openai import AzureOpenAI   # Install: pip install openai

# Create the Azure OpenAI client
# azure_endpoint: your Azure OpenAI resource endpoint (openai.azure.com)
# api_key: your Azure OpenAI key
# api_version: ALWAYS specify — ensures consistent behaviour as Azure updates
client = AzureOpenAI(
    azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT"),
    api_key        = os.environ.get("AZURE_OPENAI_KEY"),
    api_version    = "2024-02-01"
)

# chat.completions.create() sends the conversation to the model
# model=: your DEPLOYMENT NAME (not the model name like "gpt-4o")
# messages=: a list of dictionaries — each one is a message with role and content
response = client.chat.completions.create(
    model    = "my-gpt4o",   # Your deployment name from Foundry
    messages = [
        {
            "role"   : "system",   # System message sets behaviour
            "content": "You are a helpful AI assistant that explains things simply."
        },
        {
            "role"   : "user",     # User message is the question
            "content": "What is the difference between AI and machine learning?"
        }
    ]
)

# Extract the model's response text
# response.choices is a list of possible responses (usually 1)
# [0] gets the first response
# .message.content is the text the model generated
answer = response.choices[0].message.content
print(f"Response: {answer}")

# You can also check token usage (important for cost monitoring)
# response.usage shows how many tokens were used
print(f"Tokens used — Prompt: {response.usage.prompt_tokens}, "
      f"Completion: {response.usage.completion_tokens}, "
      f"Total: {response.usage.total_tokens}")

Multi-turn conversation (chatbot)

For a chatbot, you maintain the conversation history by appending each message to the list before sending. New Python concept: list.append() — adds a new item to the end of a list. Explained in comments.

import os
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT"),
    api_key        = os.environ.get("AZURE_OPENAI_KEY"),
    api_version    = "2024-02-01"
)

# Start with just the system message in the conversation history
# This list grows as the conversation continues
conversation_history = [
    {"role": "system", "content": "You are a helpful banking assistant."}
]

# Simulate a 2-turn conversation
user_inputs = [
    "What is the current interest rate on savings accounts?",
    "How does that compare to a fixed-term deposit?"   # Follow-up question
]

# New concept: for loop over a list (from Part 1 Topic 4)
# "for user_input in user_inputs:" runs once for each item in the list
for user_input in user_inputs:

    # Step 1: Add the user's message to the history
    # list.append() adds a new item to the END of the list
    # So conversation_history grows by one message each iteration
    conversation_history.append({
        "role"   : "user",
        "content": user_input
    })

    # Step 2: Send the ENTIRE conversation history to the model
    # The model reads all previous messages and responds in context
    response = client.chat.completions.create(
        model    = "my-gpt4o",
        messages = conversation_history  # Full history — not just the latest message
    )

    # Step 3: Extract the assistant's reply
    assistant_reply = response.choices[0].message.content
    print(f"User: {user_input}")
    print(f"Assistant: {assistant_reply}\n")

    # Step 4: Add the assistant's reply to the history
    # This is crucial — without this the model loses memory of what it said
    conversation_history.append({
        "role"   : "assistant",
        "content": assistant_reply
    })
🎯
Exam Tip — What Goes in Each Role

The exam shows message arrays with some content removed and asks which role goes where. Remember: system = instructions/persona (written by developer), user = human input (from the end user), assistant = previous AI responses (from earlier in the conversation). System always comes first. User and assistant alternate after that.

Using GPT models to write code

GPT-4o and GPT-3.5-turbo are excellent at generating, explaining, and fixing code. The same Chat Completions API is used — you just craft a code-focused prompt.

import os
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT"),
    api_key        = os.environ.get("AZURE_OPENAI_KEY"),
    api_version    = "2024-02-01"
)

# Code generation — the system prompt tells the model to act as a coding assistant
# The user message asks for code in Python
response = client.chat.completions.create(
    model = "my-gpt4o",
    messages = [
        {
            "role"   : "system",
            "content": "You are an expert Python developer. Provide clean, commented code."
        },
        {
            "role"   : "user",
            "content": "Write a Python function that reads a CSV file and returns a list of dictionaries, "
                       "where each dictionary represents a row with column names as keys."
        }
    ]
)

# The model returns Python code as text inside its response
generated_code = response.choices[0].message.content
print(generated_code)

Generating images from text descriptions

DALL-E 3 in Azure OpenAI generates images from text prompts. The API is different from Chat Completions — you call the images endpoint and get back a URL to the generated image.

DALL-E parameters you need to know

ParameterOptionsWhat it controls
size"1024x1024", "1792x1024", "1024x1792"Image dimensions. Square, landscape, or portrait.
quality"standard", "hd""hd" produces more detailed images with sharper details. Costs more tokens.
style"vivid", "natural""vivid" = hyper-real and dramatic. "natural" = more photographic and realistic.
n1 (DALL-E 3 only supports 1)Number of images to generate. DALL-E 3 always generates 1.
import os
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT"),
    api_key        = os.environ.get("AZURE_OPENAI_KEY"),
    api_version    = "2024-02-01"
)

# images.generate() calls the DALL-E model — different endpoint from chat.completions
# model=: the name of your DALL-E deployment (e.g. "dall-e-3")
# prompt=: text description of the image you want generated
# size=: image dimensions
# quality=: "standard" or "hd" (higher detail)
# n=: number of images (DALL-E 3 only supports n=1)
result = client.images.generate(
    model   = "dall-e-3",         # Your DALL-E deployment name
    prompt  = "A futuristic city skyline at sunset, with flying cars and neon lights, "
              "photorealistic style, ultra-high detail",
    size    = "1792x1024",         # Landscape format
    quality = "hd",               # High definition
    n       = 1                    # DALL-E 3 only generates 1 image at a time
)

# The response contains the URL of the generated image
# result.data is a list (we only have 1 image since n=1)
# .url is the temporary URL where you can download the image
# Note: DALL-E URLs expire after a short time — download and save the image promptly
image_url = result.data[0].url
print(f"Generated image URL: {image_url}")

# result.data[0].revised_prompt contains the prompt DALL-E actually used
# DALL-E 3 may revise your prompt to add safety details
revised = result.data[0].revised_prompt
print(f"Revised prompt: {revised}")
⚠️
DALL-E 3 key facts for the exam

• DALL-E 3 only generates 1 image per request (n=1 always)
• Image URLs are temporary — they expire. Download and store the image immediately.
• DALL-E 3 may revise your prompt slightly — check revised_prompt
• Available sizes: 1024x1024, 1792x1024 (landscape), 1024x1792 (portrait)
• Content filters apply to DALL-E prompts — harmful image requests are blocked

Transcribing audio to text with OpenAI's Whisper

Whisper is an OpenAI speech-to-text model available in Azure OpenAI. It transcribes audio files into text with high accuracy across 57 languages.

import os
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT"),
    api_key        = os.environ.get("AZURE_OPENAI_KEY"),
    api_version    = "2024-02-01"
)

# New concept: "with open(...) as f:" — opens a file safely
# The "with" statement (from Part 1 Topic 4) ensures the file is closed
# automatically when the block finishes — even if an error occurs
# "rb" means read in binary mode (required for audio files)
with open("meeting_recording.mp3", "rb") as audio_file:

    # audio.transcriptions.create() sends the audio to Whisper for transcription
    # model=: your Whisper deployment name in Foundry
    # file=: the open audio file object
    transcription = client.audio.transcriptions.create(
        model = "whisper",          # Your Whisper deployment name
        file  = audio_file,        # The audio file to transcribe
        language = "en"           # Optional: specify language for better accuracy
    )

# .text contains the full transcription as a single string
print(f"Transcription: {transcription.text}")
🎯
Whisper vs Azure AI Speech — Exam Distinction

Both transcribe speech. Exam scenarios distinguish them:

Use Whisper (Azure OpenAI) when: scenario mentions Azure OpenAI, the solution already uses OpenAI models, highest possible transcription accuracy needed, or the question says "using OpenAI".

Use Azure AI Speech when: scenario mentions real-time streaming transcription, custom speech models (your domain vocabulary), intent recognition, speaker identification, or text-to-speech (Whisper only does speech-to-text).

Sending images to GPT-4o

GPT-4o is multimodal — it can understand images as well as text. You include image data in the user message content and the model analyses and responds to it. This is useful for image description, visual Q&A, document analysis with images, and more.

import os
import base64        # Built-in Python module for encoding binary data as text
from openai import AzureOpenAI

client = AzureOpenAI(
    azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT"),
    api_key        = os.environ.get("AZURE_OPENAI_KEY"),
    api_version    = "2024-02-01"
)

# Method 1: Send image as a URL (the model downloads and reads it)
# Works if the image is publicly accessible on the internet
response_url = client.chat.completions.create(
    model = "my-gpt4o",
    messages = [
        {
            "role": "user",
            "content": [   # Content can be a LIST when combining text + images
                {
                    "type": "text",    # Text part of the message
                    "text": "What items are visible in this image? List them."
                },
                {
                    "type"    : "image_url",  # Image part of the message
                    "image_url": {
                        "url"   : "https://example.com/my-image.jpg",
                        "detail": "high"   # "high" = full resolution analysis
                                                # "low"  = faster, lower cost
                                                # "auto" = model decides
                    }
                }
            ]
        }
    ]
)
print(response_url.choices[0].message.content)


# Method 2: Send image as base64-encoded data (for private/local images)
# base64 converts binary file data into a text string safe for JSON
with open("local_image.jpg", "rb") as img_file:
    # base64.b64encode() encodes the binary image as base64 bytes
    # .decode("utf-8") converts those bytes to a regular text string
    image_data = base64.b64encode(img_file.read()).decode("utf-8")

response_b64 = client.chat.completions.create(
    model = "my-gpt4o",
    messages = [{
        "role": "user",
        "content": [
            {"type": "text", "text": "Describe this image in detail."},
            {
                "type": "image_url",
                "image_url": {
                    # data:image/jpeg;base64, tells the model this is base64 data
                    "url": f"data:image/jpeg;base64,{image_data}"
                }
            }
        ]
    }]
)
print(response_b64.choices[0].message.content)
🎯
Exam Tip — When to use GPT-4o Vision vs Azure AI Vision

GPT-4o Vision — Use when you want the AI to reason about an image and generate a natural language response. "Describe this product photo." "What's wrong with this X-ray?" "Summarise what this chart shows." Rich reasoning, conversational output.

Azure AI Vision — Use when you need structured outputs: detect objects, extract text (OCR), identify faces, generate tags, get bounding boxes. Faster, cheaper, more structured. Not conversational.

Azure OpenAI — what the exam specifically tests

⚠️
Top 5 Tested Facts from This Topic

1. model= uses deployment name, not model name — In Python code, model="my-gpt4o-deploy" not model="gpt-4o". The deployment name is what you set when deploying in Foundry.

2. Azure OpenAI endpoint = openai.azure.com — Not cognitiveservices.azure.com. Know all three endpoint patterns.

3. DALL-E 3 always n=1 — It only generates one image per request. Also: URLs expire — you must download and store the image.

4. Content as a list for multimodal — When mixing text and images, the content field in the message dictionary is a list of content objects (text object + image_url object), not a simple string.

5. api_version is always required — Azure OpenAI requires you to specify the API version explicitly. A question may show code missing api_version and ask why it fails.

Test your understanding

5 questions — select an answer to see the explanation immediately.

Topic 2 Quiz — Azure OpenAI 1 / 5

A developer creates an Azure OpenAI deployment named "gpt4-prod" using the gpt-4o model. When calling the API in Python, what should the model= parameter be set to?

💡 Explanation

B is correct. In Azure OpenAI, the model= parameter in Python code takes the deployment name — the name you assigned when deploying the model in Foundry or Azure OpenAI Studio. In this case "gpt4-prod". Not the actual model name ("gpt-4o"), not a prefixed name, not a versioned name. This is a common mistake — people write model="gpt-4o" and get a 404 error because Azure looks for a deployment called "gpt-4o" which doesn't exist.

Scenario: A developer wants to build a multi-turn chatbot that remembers what was said earlier in the conversation. After the first exchange (user asks about savings accounts, assistant responds), the user asks a follow-up: "And what about mortgages?"

What must the developer include in the messages array for the second API call?

💡 Explanation

B is correct. Azure OpenAI models have no persistent memory between API calls. Each call is completely independent. To maintain conversation context, you must include the full conversation history — system message + all previous user messages + all previous assistant responses + the new user message — in every API call. The model reads this array and "sees" the full conversation. Option A is wrong — there is no automatic memory. Option C would lose the context of what was asked before. Option D — there is no "memory" parameter.

A developer generates an image with DALL-E 3 and receives a URL in the response. They plan to display the image on their website 2 days later using that URL. What problem will they encounter?

💡 Explanation

B is correct. DALL-E image URLs are temporary — they expire after a short period (typically a few hours). The correct approach is to download the image immediately after generation and store it in your own Azure Blob Storage (or other permanent storage). The developer should not store just the URL for later use. This is a commonly tested operational fact about DALL-E integration.

Scenario: A company wants to analyse product defect photos uploaded by factory workers. When a worker uploads a photo, the system should generate a natural language description of the defect and suggest a remediation action.

Which Azure service should be used for this image analysis with natural language output?

💡 Explanation

C is correct. The scenario requires both image understanding AND natural language generation — "describe the defect AND suggest remediation." This is exactly GPT-4o's multimodal capability. You send the image and ask a question; GPT-4o reasons about the image and generates a contextual, actionable response. Azure AI Vision (option A) gives you structured data (tags, bounding boxes) not conversational remediation suggestions. Document Intelligence (option B) is for structured document extraction, not general images. DALL-E (option D) generates images — it cannot analyse them.

A developer's Azure OpenAI client code raises an error: "You must provide a model parameter." The code is: client.chat.completions.create(messages=[...]). What is wrong?

💡 Explanation

B is correct. The error message "You must provide a model parameter" is explicit — the model= parameter is missing. The correct call requires specifying the deployment name: client.chat.completions.create(model="your-deployment-name", messages=[...]). Without model=, Azure doesn't know which deployment to route the request to. The error message exactly matches the missing parameter.

Mark this topic as complete