From 7ae9b4aff6c27084de54096339fe4b63b6b47397 Mon Sep 17 00:00:00 2001 From: Peter Williams <105436708+pewill-msft@users.noreply.github.com> Date: Wed, 14 Oct 2026 10:46:18 +0000 Subject: [PATCH] update solution hints. Pin Python version --- .../challenges/challenge-01.md | 23 +++++++++++++++---- .../challenges/challenge-02.md | 6 ----- .../challenges/challenge-03.md | 3 --- .../challenges/challenge-04.md | 3 --- .../challenges/challenge-05.md | 7 +++--- .../labautomation/README.md | 3 +++ .../src/agent-workflow/app/.gitignore | 1 + .../src/agent-workflow/app/.python-version | 1 + .../src/agent-workflow/app/agents.py | 8 +++---- .../src/agents/maintenance_scheduler_agent.py | 6 ++--- .../src/agents/parts_ordering_agent.py | 4 ++-- 11 files changed, 36 insertions(+), 29 deletions(-) create mode 100644 03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.gitignore create mode 100644 03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.python-version diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md index ad37a4839..6f4e83fe2 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-01.md @@ -98,14 +98,16 @@ Select the assigned organization, then open the pinned microhack repository. GitHub organization -Microhack repository +Microhack repository You then need to fork the repository before you can create a Codespace. To fork the repository, click the Fork button in the top-right corner of the repository page and follow the prompts: -Create fork +Create fork + Select the organization as owner and use a unique name for the repository name to avoid conflicts with other forks. For example, you can append your lab username to the repository name (e.g., `microhack-labuser-0001`): + Fork name Finally, you should see your forked repository with the unique name you provided and all files and folders from the original repository: @@ -118,13 +120,13 @@ From the repository page, select **Code**, then open the **Codespaces** tab. Sel New Codespace -For Dev container configuration, select **Azure / AI / Predictive Maintenance**, then select **Create codespace**: +For **Dev container configuration**, select **Azure / AI / Predictive Maintenance**, then select **Create codespace**: Select Dev Container Wait for the container setup to finish, then select the **Trust folders & Continue** button and confirm that the repository files are visible in the Explorer and that the integrated terminal opens without errors. -Codespace welcome +Codespace welcome Open a terminal in the Codespace and verify that the required tools are installed: @@ -144,6 +146,8 @@ Sign in to Azure from the Codespace terminal follow the link shown to authentica az login --use-device-code ``` +In the **Select a subscription and tenant** terminal prompt hit enter to use the default Azure subscription + ### 4. Retrieve environment configuration From the repository root, run the setup script with the resource group name provided in your Hackbox under **Resource Group Name**: @@ -186,6 +190,17 @@ az storage blob list \ The expected result is `5` wiki articles, one per machine type. +### 6. Validate the Machine API + +Confirm that the provisioned Machine API in API Management can retrieve the seeded machine data: + +```bash +# Get all machines +curl -fsSL "$APIM_GATEWAY_URL/machine" -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY" -H "Accept: application/json" +``` + +You should receive a JSON response containing the factory machines. You will use this API when building the agents in Challenge 2. + ## 🚀 Go Further Review the [solution architecture](../README.md#architecture) and identify which Azure resource each of the five agents will use in the upcoming challenges. diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md index f2c226a87..f869e817a 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-02.md @@ -2,9 +2,6 @@ **[Home](../README.md)** | [Previous challenge](challenge-01.md) | [Next challenge](challenge-03.md) -> [!TIP] -> Stuck on a step? See the [Challenge 2 walkthrough](../walkthrough/challenge-02/solution-02.md) for exact commands, expected output, and a validation checklist. - ## 🎯 Objective The goals for this challenge are: @@ -145,9 +142,6 @@ Machine and threshold information is typically stored in a central system and ex The Machine API and Maintenance API are already available in API Management and contain endpoints for getting details about a specific machine and thresholds for certain machine types. Try the APIs: ```bash -# Get all machines -curl -fsSL "$APIM_GATEWAY_URL/machine" -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY" -H "Accept: application/json" - # Get a specific machine curl -fsSL "$APIM_GATEWAY_URL/machine/machine-001" -H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY" -H "Accept: application/json" diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md index 3c9c1b25b..5d383b5a1 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-03.md @@ -2,9 +2,6 @@ **[Home](../README.md)** | [Previous challenge](challenge-02.md) | [Next challenge](challenge-04.md) -> [!TIP] -> Stuck on a step? See the [Challenge 3 walkthrough](../walkthrough/challenge-03/solution-03.md) for exact commands, expected output, and a validation checklist. - ## 🎯 Objective The goals for this challenge are: diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md index 9df7afb1c..8ec390c74 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-04.md @@ -2,9 +2,6 @@ **[Home](../README.md)** | [Previous challenge](challenge-03.md) | [Next challenge](challenge-05.md) -> [!TIP] -> Stuck on a step? See the [Challenge 4 walkthrough](../walkthrough/challenge-04/solution-04.md) for exact commands, expected output, and a validation checklist. - ## 🎯 Objective The goals for this challenge are: diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md index e1b3b6b8f..617ed02a9 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/challenges/challenge-05.md @@ -2,9 +2,6 @@ **[Home](../README.md)** | [Previous challenge](challenge-04.md) | [Next: Wrap-up](finish.md) -> [!TIP] -> Stuck on a step? See the [Challenge 5 walkthrough](../walkthrough/challenge-05/solution-05.md) for exact commands, expected output, and a validation checklist. - ## 🎯 Objective The goals for this challenge are: @@ -104,6 +101,10 @@ This challenge uses the **Sequential** pattern — see [Conclusion and Reflectio ### Task 1: Start Aspire +The Python app uses its own virtual environment with Python 3.13, pinned by +`src/agent-workflow/app/.python-version`. This is separate from the workshop's +Python 3.11 environment; `uv` selects the pinned interpreter automatically. + ```bash cd src/agent-workflow aspire run diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md b/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md index 87861e6c5..8adf91e55 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/labautomation/README.md @@ -16,6 +16,9 @@ labautomation/ `-- get-keys.sh # Participant-run script: resolves resource names/keys into a repo-root .env ``` +The generated `.env` uses `AZURE_AI_PROJECT_ENDPOINT` for the Foundry project endpoint +across the agents and workflow. + ## What `main.bicep` provisions - Storage account with a `machine-wiki` blob container (knowledge base articles). diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.gitignore b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.gitignore new file mode 100644 index 000000000..732f7db1a --- /dev/null +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.gitignore @@ -0,0 +1 @@ +!.python-version diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.python-version b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.python-version new file mode 100644 index 000000000..24ee5b1be --- /dev/null +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py index 4118be45c..2c6fc52bb 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agent-workflow/app/agents.py @@ -38,7 +38,7 @@ def extract_work_order_id(text: str) -> str | None: logger.info(f"COSMOS_ENDPOINT set: {bool(os.getenv('COSMOS_ENDPOINT'))}") logger.info(f"COSMOS_DATABASE set: {bool(os.getenv('COSMOS_DATABASE'))}") logger.info( - f"AI_FOUNDRY_PROJECT_ENDPOINT set: {bool(os.getenv('AI_FOUNDRY_PROJECT_ENDPOINT'))}") + f"AZURE_AI_PROJECT_ENDPOINT set: {bool(os.getenv('AZURE_AI_PROJECT_ENDPOINT'))}") # ============================================================================= @@ -141,8 +141,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue) -> Non cosmos_key = os.getenv("COSMOS_KEY") database_name = os.getenv( "COSMOS_DATABASE_NAME") or os.getenv("COSMOS_DATABASE") - project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT") or os.getenv( - "AZURE_AI_PROJECT_ENDPOINT") + project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT") deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4") if not all([cosmos_endpoint, cosmos_key, database_name, project_endpoint]): @@ -305,8 +304,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue) -> Non cosmos_key = os.getenv("COSMOS_KEY") database_name = os.getenv( "COSMOS_DATABASE_NAME") or os.getenv("COSMOS_DATABASE") - project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT") or os.getenv( - "AZURE_AI_PROJECT_ENDPOINT") + project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT") deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4") if not all([cosmos_endpoint, cosmos_key, database_name, project_endpoint]): diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py index 66e1041b2..f38a1bf5a 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/maintenance_scheduler_agent.py @@ -300,11 +300,11 @@ async def main(): print("=== Predictive Maintenance Agent ===\n") - # Load configuration (use AI_FOUNDRY_PROJECT_ENDPOINT for consistency with other challenge scripts) + # Load configuration cosmos_endpoint = os.getenv("COSMOS_ENDPOINT") cosmos_key = os.getenv("COSMOS_KEY") database_name = os.getenv("COSMOS_DATABASE_NAME") - foundry_project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT") + foundry_project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT") deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4") otel_exporter_endpoint = os.getenv( "OTEL_EXPORTER_OTLP_ENDPOINT") @@ -312,7 +312,7 @@ async def main(): # Validate if not all([cosmos_endpoint, cosmos_key, database_name, foundry_project_endpoint]): print("Error: Missing required environment variables.") - print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AI_FOUNDRY_PROJECT_ENDPOINT") + print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AZURE_AI_PROJECT_ENDPOINT") return if otel_exporter_endpoint: diff --git a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py index 10e36cab4..1c2648cb8 100644 --- a/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py +++ b/03-Azure/01-04-AI/08_Predictive_Maintenance/src/agents/parts_ordering_agent.py @@ -283,14 +283,14 @@ async def main(): cosmos_endpoint = os.getenv("COSMOS_ENDPOINT") cosmos_key = os.getenv("COSMOS_KEY") database_name = os.getenv("COSMOS_DATABASE_NAME") - foundry_project_endpoint = os.getenv("AI_FOUNDRY_PROJECT_ENDPOINT") + foundry_project_endpoint = os.getenv("AZURE_AI_PROJECT_ENDPOINT") deployment_name = os.getenv("MODEL_DEPLOYMENT_NAME", "gpt-5.4") otel_exporter_endpoint = os.getenv( "OTEL_EXPORTER_OTLP_ENDPOINT") if not all([cosmos_endpoint, cosmos_key, database_name, foundry_project_endpoint]): print("Error: Missing required environment variables.") - print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AI_FOUNDRY_PROJECT_ENDPOINT") + print("Required: COSMOS_ENDPOINT, COSMOS_KEY, COSMOS_DATABASE_NAME, AZURE_AI_PROJECT_ENDPOINT") return if otel_exporter_endpoint: