Skip to content

Commit f679c5f

Browse files
Merge pull request #47 from corticalstack/bugfix/46-model-retirements
fix: replace retiring models and fix the 08-06 agent evaluators (#46)
2 parents 3a0e398 + 99cd423 commit f679c5f

82 files changed

Lines changed: 7237 additions & 3392 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.env.example‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
# Copy this file to .env and replace the placeholder values.
33
# Authentication uses DefaultAzureCredential (RBAC) - gateway keys are the only secrets.
44

5-
CHAT_MODEL=gpt-4.1-mini
5+
CHAT_MODEL=gpt-5.4-mini
66
EMBEDDING_MODEL=text-embedding-3-large
7-
RESEARCH_MODEL=o3-deep-research
7+
RESEARCH_MODEL=deep-research
88
OSS_MODEL=Phi-4
9-
DR_MODEL=o3-deep-research
9+
DR_MODEL=deep-research
1010
# 07-02 model-migration lab: legacy chat model + GPT-5 reasoning model (both on the core account)
1111
GPT4O_MODEL=gpt-4o
1212
GPT5_MODEL=gpt-5-mini

‎.github/workflows/dependency-canary.yml‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ jobs:
5959
- name: SDK model keyword arguments match
6060
run: uv run --frozen python scripts/check_sdk_kwargs.py
6161

62-
# One pytest run per suite: 08-05 and 08-05b both have tests/test_kb.py
63-
# without an __init__.py, which pytest cannot collect in a single run.
62+
# One pytest run per suite. The three suites also pass together in a single run.
6463
- name: Unit tests
6564
run: |
6665
for suite in 08-agents/08-05-contoso-pmo-mcp/tests \

‎.github/workflows/offline-checks.yml‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ jobs:
4545
- name: Every notebook is in the run manifest
4646
run: python3 scripts/run_notebooks.py --check
4747

48-
# One pytest run per suite: 08-05 and 08-05b both have tests/test_kb.py
49-
# without an __init__.py, which pytest cannot collect in a single run.
48+
# One pytest run per suite. The three suites also pass together in a single run.
5049
- name: Unit tests
5150
run: |
5251
for suite in 08-agents/08-05-contoso-pmo-mcp/tests \

‎04-foundry-control-plane/04-03-foundry-api-and-sdks.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ project_client = AIProjectClient(
117117

118118
with project_client.get_openai_client() as openai_client:
119119
response = openai_client.responses.create(
120-
model="gpt-4.1-mini",
120+
model="gpt-5.4-mini",
121121
input="What is the capital of France?",
122122
)
123123
print(response.output_text)
@@ -134,7 +134,7 @@ const project = new AIProjectClient(projectEndpoint, new DefaultAzureCredential(
134134

135135
const openAIClient = await project.getOpenAIClient();
136136
const response = await openAIClient.responses.create({
137-
model: "gpt-4.1-mini",
137+
model: "gpt-5.4-mini",
138138
input: "What is the capital of France?",
139139
});
140140
console.log(response.output_text);
@@ -197,7 +197,7 @@ client = OpenAI(
197197
)
198198

199199
response = client.responses.create(
200-
model="gpt-4.1-mini",
200+
model="gpt-5.4-mini",
201201
input="What is the capital of France?"
202202
)
203203
print(response.output_text)

‎04-foundry-control-plane/04-05-register-and-manage-custom-agents.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def get_weather(city: str) -> str:
180180
return f"The weather in {city} is currently sunny."
181181

182182
agent = create_agent(
183-
model="openai:gpt-4.1-mini",
183+
model="openai:gpt-5.4-mini",
184184
tools=[get_weather],
185185
system_prompt="You are a helpful assistant.",
186186
).with_config({"callbacks": [tracer]})

‎05-foundry-project-pattern-setup/05-01-architecture.md‎

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,16 @@ The shared infrastructure backbone. All team projects route model requests throu
5050

5151
| Model | Foundry Account | Region | SKU | `.env` key | Purpose |
5252
|-------|----------------|--------|-----|------------|---------|
53-
| `gpt-4.1-mini` | `aif-core-{suffix}` | East US 2 | GlobalStandard 30K TPM | `CHAT_MODEL` | General purpose chat |
53+
| `gpt-5.4-mini` | `aif-core-{suffix}` | East US 2 | GlobalStandard 30K TPM | `CHAT_MODEL` | General purpose chat |
5454
| `text-embedding-3-large` | `aif-core-{suffix}` | East US 2 | Standard 50K TPM | `EMBEDDING_MODEL` | Vector embeddings |
55-
| `o3-deep-research` | `aif-research-{suffix}` | Norway East | GlobalStandard 10K TPM | `RESEARCH_MODEL` | Advanced reasoning and deep research |
55+
| `deep-research` (`gpt-5.6-sol`) | `aif-research-{suffix}` | Norway East | GlobalStandard 200K TPM | `RESEARCH_MODEL` | Advanced reasoning and deep research |
5656
| `Phi-4` | `aif-oss-{suffix}` | West US 3 | GlobalStandard 1K TPM | `OSS_MODEL` | Open-weights model from Microsoft |
5757

5858
**APIM routing rules** (evaluated in order - specific URL patterns win over the default):
5959

6060
| Rule | URL pattern | Backend | Auth |
6161
|------|------------|---------|------|
62-
| Research | `/deployments/o3-deep-research/*` | `aif-research-{suffix}` | Managed Identity |
62+
| Research | `/deployments/deep-research/*`, and `/responses` with `"model": "deep-research"` | `aif-research-{suffix}` | Managed Identity |
6363
| OSS | `/deployments/Phi-4/*` | `aif-oss-{suffix}` | Managed Identity |
6464
| Default | all other `/deployments/*` | `aif-core-{suffix}` | Managed Identity |
6565

@@ -88,7 +88,7 @@ Team Alpha has a dedicated Foundry account with no local model deployments - all
8888

8989
Connection: `core-alpha` (`ALPHA_FOUNDRY_CORE_CONNECTION`) → `apim-foundry-{suffix}` (key: `ALPHA_GATEWAY_KEY`)
9090

91-
Model access via connection: `core-alpha/gpt-4.1-mini`
91+
Model access via connection: `core-alpha/gpt-5.4-mini`
9292

9393
---
9494

@@ -141,7 +141,7 @@ Content Understanding requires a **dedicated** AI Services account with local mo
141141
|----------|------|--------|-------------|
142142
| `aif-cu-{suffix}` | Foundry Account (AI Services) | East US 2 | `CU_ACCOUNT_ENDPOINT` |
143143
| `cu-project` | Foundry Project | East US 2 | `CU_FOUNDRY_PROJECT`, `CU_FOUNDRY_PROJECT_ENDPOINT` |
144-
| `gpt-4.1-mini` (local) | Model Deployment on `aif-cu-{suffix}` | East US 2 | used by CU field extraction |
144+
| `gpt-5.4-mini` (local) | Model Deployment on `aif-cu-{suffix}` | East US 2 | used by CU field extraction |
145145
| `text-embedding-3-large` (local) | Model Deployment on `aif-cu-{suffix}` | East US 2 | used by CU embedding |
146146

147147
Connection: `cu-project` → `landing-zone-apim` (`CU_APIM_CONNECTION`) with key `CU_GATEWAY_KEY`
@@ -159,23 +159,25 @@ All model traffic enters through the single APIM gateway (`apim-foundry-{suffix}
159159
APIM evaluates operations in specificity order - an exact literal path beats a wildcard path. The `{deployment-id}` placeholder in a `urlTemplate` is a wildcard; a literal model name in the same position is an exact match and always takes priority.
160160

161161
```
162-
POST /deployments/o3-deep-research/chat/completions
162+
POST /deployments/deep-research/chat/completions
163163
→ exact match: operation "chat-research" → operation policy → openai-research backend
164164
165165
POST /deployments/Phi-4/chat/completions
166166
→ exact match: operation "chat-oss" → operation policy → openai-oss backend
167167
168-
POST /deployments/gpt-4.1-mini/chat/completions
168+
POST /deployments/gpt-5.4-mini/chat/completions
169169
→ wildcard match: operation "chat" → no operation policy → falls through to API-level policy → openai backend
170170
171171
POST /deployments/text-embedding-3-large/embeddings
172172
→ wildcard match: operation "embeddings" → no operation policy → falls through to API-level policy → openai backend
173173
174174
POST /responses
175-
→ exact match: operation "responses" → no operation policy → falls through to API-level policy → openai backend
175+
→ exact match: operation "responses" → operation policy reads "model" from the body
176+
→ "deep-research": openai-research backend
177+
→ anything else: openai backend (set by the API-level policy)
176178
```
177179

178-
Operations that have **no operation-level policy** inherit the **API-level (All operations) policy**, which sets the default backend to `openai` (`aif-core-{suffix}`).
180+
Operations that have **no operation-level policy** inherit the **API-level (All operations) policy**, which sets the default backend to `openai` (`aif-core-{suffix}`). The Responses API carries the model in the request body rather than the URL, so URL matching cannot route it; the `responses` operation policy runs the API-level policy first (`<base />`) and then overrides the backend for `deep-research`.
179181

180182
### Inbound policy per operation
181183

@@ -185,19 +187,19 @@ Operations that have **no operation-level policy** inherit the **API-level (All
185187
| `chat-oss` | Chat Completions (OSS) | Yes | `set-backend-service backend-id="openai-oss"` + managed identity auth |
186188
| `chat` | Chat Completions | No - inherits API-level | API-level: `set-backend-service backend-id="openai"` + managed identity auth + rate limit (100/60s) + default `api-version=2024-10-21` |
187189
| `embeddings` | Embeddings | No - inherits API-level | same as above |
188-
| `responses` | Responses | No - inherits API-level | same as above |
190+
| `responses` | Responses | Yes | API-level policy, then `set-backend-service backend-id="openai-research"` when the body's `model` is `deep-research` |
189191

190192
> **Policy naming note:** every APIM policy resource has the name `policy` - it is not a meaningful identifier. What distinguishes policies is which operation (or API) they are attached to. Operations with no policy of their own fall through to the API-level policy attached to "All operations".
191193
192194
### Operation → backend → Foundry account → model
193195

194196
| APIM operation | Example POST path | Backend ID | Foundry account | Model |
195197
|---|---|---|---|---|
196-
| `chat-research` | `POST /deployments/o3-deep-research/chat/completions` | `openai-research` | `aif-research-{suffix}` (Norway East) | `o3-deep-research` |
198+
| `chat-research` | `POST /deployments/deep-research/chat/completions` | `openai-research` | `aif-research-{suffix}` (Norway East) | `deep-research` (`gpt-5.6-sol`) |
197199
| `chat-oss` | `POST /deployments/Phi-4/chat/completions` | `openai-oss` | `aif-oss-{suffix}` (West US 3) | `Phi-4` |
198-
| `chat` | `POST /deployments/gpt-4.1-mini/chat/completions` | `openai` | `aif-core-{suffix}` (East US 2) | `gpt-4.1-mini` |
200+
| `chat` | `POST /deployments/gpt-5.4-mini/chat/completions` | `openai` | `aif-core-{suffix}` (East US 2) | `gpt-5.4-mini` |
199201
| `embeddings` | `POST /deployments/text-embedding-3-large/embeddings` | `openai` | `aif-core-{suffix}` (East US 2) | `text-embedding-3-large` |
200-
| `responses` | `POST /responses` | `openai` | `aif-core-{suffix}` (East US 2) | as specified by `{connection}/{model}` in request body |
202+
| `responses` | `POST /responses` | `openai`, or `openai-research` for `deep-research` | `aif-core-{suffix}` (East US 2) or `aif-research-{suffix}` (Norway East) | as specified by `model` in the request body |
201203

202204
### Backend resources
203205

@@ -217,17 +219,17 @@ Example - research model request:
217219

218220
```
219221
Client
220-
POST https://apim-foundry-{suffix}.azure-api.net/openai/deployments/o3-deep-research/chat/completions
222+
POST https://apim-foundry-{suffix}.azure-api.net/openai/deployments/deep-research/chat/completions
221223
↓ APIM matches operation "chat-research" (exact URL match beats wildcard)
222224
↓ operation policy: set-backend-service → openai-research
223225
↓ swap api-key header for managed identity Bearer token
224226
↓ prepend backend base URL, keep path suffix unchanged
225-
POST https://aif-research-{suffix}.cognitiveservices.azure.com/openai/deployments/o3-deep-research/chat/completions
226-
↓ Foundry account looks up deployment "o3-deep-research"
227-
→ o3-deep-research model responds
227+
POST https://aif-research-{suffix}.cognitiveservices.azure.com/openai/deployments/deep-research/chat/completions
228+
↓ Foundry account looks up deployment "deep-research"
229+
→ gpt-5.6-sol responds
228230
```
229231

230-
The same mechanics apply to the default backend - for `gpt-4.1-mini` the path `/deployments/gpt-4.1-mini/chat/completions` passes through untouched, with only the host replaced by `aif-core-{suffix}.cognitiveservices.azure.com`.
232+
The same mechanics apply to the default backend - for `gpt-5.4-mini` the path `/deployments/gpt-5.4-mini/chat/completions` passes through untouched, with only the host replaced by `aif-core-{suffix}.cognitiveservices.azure.com`.
231233

232234
### Authentication
233235

@@ -259,7 +261,7 @@ The APIM + hub Foundry account pattern is shared platform infrastructure. Team-l
259261

260262
**1. Quota contention**
261263

262-
The hub's `gpt-4.1-mini` deployment is provisioned at 30K TPM GlobalStandard, shared across all four teams via APIM. There is no mechanism to ring-fence a portion of that quota for a specific workload. Any team workload that places additional calls against core model deployments - for example, the Memory API's per-turn summarisation and fact-extraction calls, or embedding lookups - competes silently with all other inference traffic on the same quota pool. A single team's memory workload can starve the other three teams' APIM-routed requests.
264+
The hub's `gpt-5.4-mini` deployment is provisioned at 30K TPM GlobalStandard, shared across all four teams via APIM. There is no mechanism to ring-fence a portion of that quota for a specific workload. Any team workload that places additional calls against core model deployments - for example, the Memory API's per-turn summarisation and fact-extraction calls, or embedding lookups - competes silently with all other inference traffic on the same quota pool. A single team's memory workload can starve the other three teams' APIM-routed requests.
263265

264266
**2. Hub ownership and blast radius**
265267

@@ -273,7 +275,7 @@ Because the hub RG is excluded from the deny policy, model deployments there are
273275

274276
| Workload | Correct resource group | Correct account | Notes |
275277
|---|---|---|---|
276-
| Standard agents (no memory tools) | `rg-foundry-spoke-alpha-{suffix}` | `aif-spoke-alpha-{suffix}` | Uses `core-alpha/gpt-4.1-mini` via APIM connection |
278+
| Standard agents (no memory tools) | `rg-foundry-spoke-alpha-{suffix}` | `aif-spoke-alpha-{suffix}` | Uses `core-alpha/gpt-5.4-mini` via APIM connection |
277279
| Hosted agents | `rg-foundry-spoke-alpha-{suffix}` | `aif-spoke-alpha-{suffix}` (East US 2) | Uses existing spoke account - East US 2 is supported for hosted agents |
278280
| Foundry IQ (KB + agentic retrieval) | `rg-foundry-multi-{suffix}` | `aif-spoke-multi-{suffix}` (existing) | Adds `iq-project` + `iq-search-{suffix}` to the shared account. No model deployments - deny policy is not violated. `iq` is a capability qualifier, not a team name. Dedicated APIM subscription (`foundry-gateway-iq`) isolates embedding batch quota from team traffic. |
279281
| Custom MCP server (Contoso PMO KB) | `rg-foundry-core-{suffix}` | `aif-core-{suffix}` / `project-admin-{suffix}` (existing) | The agent and its tool catalog entry live on the admin project, which uses the core account's model deployments directly. The Azure Functions MCP server deploys into `rg-foundry-contoso-pmo-mcp`. |
@@ -326,7 +328,7 @@ flowchart TD
326328
327329
subgraph MEM_LOCAL["aif-memory - local deployments"]
328330
MEM_PAD[" "]
329-
MEM_M1["gpt-4.1-mini<br/>(Memory API: summarisation)"]
331+
MEM_M1["gpt-5.4-mini<br/>(Memory API: summarisation)"]
330332
MEM_M2["text-embedding-3-small<br/>(Memory API: indexing)"]
331333
MEM_PAD --> MEM_M1 & MEM_M2
332334
end
@@ -339,7 +341,7 @@ flowchart TD
339341
340342
subgraph CU_LOCAL["aif-cu - local deployments"]
341343
CU_PAD[" "]
342-
CU_M1["gpt-4.1-mini<br/>(CU: field extraction)"]
344+
CU_M1["gpt-5.4-mini<br/>(CU: field extraction)"]
343345
CU_M2["text-embedding-3-large<br/>(CU: embeddings)"]
344346
CU_PAD --> CU_M1 & CU_M2
345347
end
@@ -350,20 +352,20 @@ flowchart TD
350352
APIM["apim-foundry<br/>API Management BasicV2<br/>East US 2"]
351353
352354
subgraph HUB["aif-core, East US 2"]
353-
H1["gpt-4.1-mini"]
355+
H1["gpt-5.4-mini"]
354356
H3["text-embedding-3-large"]
355357
end
356358
357359
subgraph RES["aif-research"]
358-
R1["o3-deep-research<br/>Norway East"]
360+
R1["deep-research (gpt-5.6-sol)<br/>Norway East"]
359361
end
360362
361363
subgraph OSS["aif-oss"]
362364
O1["Phi-4<br/>West US 3"]
363365
end
364366
365367
APIM -->|"Managed Identity - default"| HUB
366-
APIM -->|"Managed Identity - /deployments/o3-deep-research/"| RES
368+
APIM -->|"Managed Identity - deep-research"| RES
367369
APIM -->|"Managed Identity - /deployments/Phi-4/"| OSS
368370
end
369371
@@ -428,9 +430,9 @@ flowchart TD
428430
| Light blue | `aif-core` | Primary core Foundry Account - hosts general-purpose and routing model deployments (East US 2). |
429431
| Light violet | `aif-research` | Research hub Foundry Account - hosts advanced reasoning model deployments (Norway East). |
430432
| Light fuchsia | `aif-oss` | OSS hub Foundry Account - hosts open-weights model deployments (West US 3). |
431-
| Light rose | `aif-memory` | Memory Foundry Account - hosts local `gpt-4.1-mini` (summarisation) and `text-embedding-3-small` (indexing) deployments consumed directly by the Memory API runtime. |
433+
| Light rose | `aif-memory` | Memory Foundry Account - hosts local `gpt-5.4-mini` (summarisation) and `text-embedding-3-small` (indexing) deployments consumed directly by the Memory API runtime. |
432434
| Amber-orange | `rg-foundry-cu` | Content Understanding - dedicated Foundry account (`aif-cu`) with local model deployments for CU field extraction. Intentionally excluded from the deny-model-deployments policy. |
433-
| Light orange | `aif-cu` | Content Understanding Foundry Account - hosts local `gpt-4.1-mini` (field extraction) and `text-embedding-3-large` (embeddings) deployments consumed by CU analyzers. |
435+
| Light orange | `aif-cu` | Content Understanding Foundry Account - hosts local `gpt-5.4-mini` (field extraction) and `text-embedding-3-large` (embeddings) deployments consumed by CU analyzers. |
434436

435437
---
436438

‎05-foundry-project-pattern-setup/05-02-deploy-foundry-core-gateway/05-02-01-deploy-foundry-core-gateway.ipynb‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
"\n",
2525
"| Model | Hub | Purpose |\n",
2626
"|-------|-----|---------|\n",
27-
"| `gpt-4.1-mini` | aif-core | General purpose chat for all teams |\n",
27+
"| `gpt-5.4-mini` | aif-core | General purpose chat for all teams |\n",
2828
"| `text-embedding-3-large` | aif-core | Vector embeddings for search |\n",
29-
"| `o3-deep-research` | aif-research | Advanced reasoning (only available in norwayeast) |\n",
29+
"| `deep-research` (`gpt-5.6-sol`) | aif-research | Advanced reasoning and deep research (norwayeast) |\n",
3030
"| `Phi-4` | aif-oss | Open-weights model from Microsoft (westus3) |\n",
3131
"\n",
3232
"## Naming conventions\n",
@@ -44,7 +44,7 @@
4444
"\n",
4545
"## Multi-region pattern\n",
4646
"\n",
47-
"Some models are only available in specific regions (o3-deep-research → norwayeast, Phi-4 → westus3). Rather than exposing multiple endpoints to consumers, APIM provides a **single gateway URL** and routes requests to the correct regional backend based on the deployment name in the URL path."
47+
"Some models are only available in specific regions (Phi-4 → westus3; o3-deep-research, which `deep-research` replaced, was norwayeast-only). Rather than exposing multiple endpoints to consumers, APIM provides a **single gateway URL** and routes requests to the correct regional backend based on the deployment name in the URL path."
4848
]
4949
},
5050
{

0 commit comments

Comments
 (0)