From 1b3c3f10b06326cf7d55de38c4db16dc6efb83d8 Mon Sep 17 00:00:00 2001 From: "microsoft-github-operations[bot]" <55726097+microsoft-github-operations[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:55:51 +0000 Subject: [PATCH 001/180] Initial commit --- .gitignore | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..8a30d258 --- /dev/null +++ b/.gitignore @@ -0,0 +1,398 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml From 6e39261ccdab8eabd95d7720284fea379bf74777 Mon Sep 17 00:00:00 2001 From: Microsoft Open Source Date: Wed, 23 Oct 2024 08:55:54 -0700 Subject: [PATCH 002/180] CODE_OF_CONDUCT.md committed --- CODE_OF_CONDUCT.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..f9ba8cf6 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,9 @@ +# Microsoft Open Source Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). + +Resources: + +- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) +- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns From 8e1a10367c86be4ccaacf8085948ee6581ab30b1 Mon Sep 17 00:00:00 2001 From: Microsoft Open Source Date: Wed, 23 Oct 2024 08:55:55 -0700 Subject: [PATCH 003/180] LICENSE committed --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..9e841e7a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE From 72aa0288a5f99bcb7cc106bd4d582cd38edfe581 Mon Sep 17 00:00:00 2001 From: Microsoft Open Source Date: Wed, 23 Oct 2024 08:55:55 -0700 Subject: [PATCH 004/180] SECURITY.md committed --- SECURITY.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..b3c89efc --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). + + From 5b63df4476cc9feb1fb74ff39f35cb5b18a0e72b Mon Sep 17 00:00:00 2001 From: Microsoft Open Source Date: Wed, 23 Oct 2024 08:55:56 -0700 Subject: [PATCH 005/180] SUPPORT.md committed --- SUPPORT.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 SUPPORT.md diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 00000000..291d4d43 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,25 @@ +# TODO: The maintainer of this repo has not yet edited this file + +**REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? + +- **No CSS support:** Fill out this template with information about how to file issues and get help. +- **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. +- **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. + +*Then remove this first heading from this SUPPORT.MD file before publishing your repo.* + +# Support + +## How to file issues and get help + +This project uses GitHub Issues to track bugs and feature requests. Please search the existing +issues before filing new issues to avoid duplicates. For new issues, file your bug or +feature request as a new Issue. + +For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE +FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER +CHANNEL. WHERE WILL YOU HELP PEOPLE?**. + +## Microsoft Support Policy + +Support for this **PROJECT or PRODUCT** is limited to the resources listed above. From a8e2a556180c63ad89fb220a196ef19cc03381bd Mon Sep 17 00:00:00 2001 From: Microsoft Open Source Date: Wed, 23 Oct 2024 08:55:57 -0700 Subject: [PATCH 006/180] README.md committed --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..5cd7cecf --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# Project + +> This repo has been populated by an initial template to help get you started. Please +> make sure to update the content to build a great experience for community-building. + +As the maintainer of this project, please make a few updates: + +- Improving this README.MD file to provide a great experience +- Updating SUPPORT.MD with content about this project's support experience +- Understanding the security reporting process in SECURITY.MD +- Remove this section from the README + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +## Trademarks + +This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft +trademarks or logos is subject to and must follow +[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). +Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. +Any use of third-party trademarks or logos are subject to those third-party's policies. From 866f0dc86657082b542bf5aafe8e8b0fa3e7ab3a Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 30 Oct 2024 15:09:36 -0700 Subject: [PATCH 007/180] filling out docs --- README.md | 67 ++++++++++++++++----- quickstart.md | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+), 15 deletions(-) create mode 100644 quickstart.md diff --git a/README.md b/README.md index 5cd7cecf..c6ee024a 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,61 @@ -# Project +# Azure AI Agent Service -> This repo has been populated by an initial template to help get you started. Please -> make sure to update the content to build a great experience for community-building. +Build fast, secure enterprise AI Agents to automate any business workflow -As the maintainer of this project, please make a few updates: +Azure AI Agent Service is a fully-managed service designed to empower developers to securely build, deploy, and scale high-quality, and extensible AI agents. Leveraging an extensive ecosystem of models, tools and capabilities from OpenAI, Microsoft, and third-party providers, Azure AI Agent Service enables building agents for a wide range of generative AI use cases. -- Improving this README.MD file to provide a great experience -- Updating SUPPORT.MD with content about this project's support experience -- Understanding the security reporting process in SECURITY.MD -- Remove this section from the README +## Highlights -## Contributing +**Enterprise grade security**: Ensure data privacy and compliance with secure data handling and no public egress. Azure AI Agent Service provides features like bring your own storage and private networking, platform-managed storage, and built-in content filters and XPIA mitigation. These capabilities help organizations protect their sensitive data while meeting regulatory requirements, ensuring that AI agents operate within a secure and compliant environment. Key features include: + +- Bring your own Azure Storage Account +- Bring your own VNET (coming soon) +- Keyless setup and authentication +- No public egress +- Built-in conversation state management +- On-behalf-of authentication support for agents (coming soon) +- Monitor agent performance with OpenTelemetry-based tracing (coming soon) +- Build responsibly with content filters and XPIA (Cross Prompt Injection Attack) mitigation + +**Rapid development and automation**: Quickly build enterprise-grade AI agents with a user-friendly interface and comprehensive toolset, including pre-built tools for advanced data analysis and RAG. Azure AI Agent Service also supports seamless integration with enterprise applications through Azure Logic Apps, OpenAPI 3.0 specified tools, and Azure Functions for real-time data processing and workflow automation. This enables developers to accelerate time-to-market while enhancing operational efficiency with intelligent automation. Key features include: + +* Create a wide range of automated workflows with Azure Logic Apps’ 1400+built-in connectors​ + +* Build standardized custom tools with OpenAPI 3.0 specifications​ with managed identity support + +* Implement stateless or stateful code-based actions with Azure Functions​ (coming soon) + +* Perform advanced data analysis, write code, and create rich data visualization with Code Interpreter​ + +* Wire-compatible with Azure OpenAI Assistants API + +**Extensive data connections**: Ground your AI agents with relevant, secure enterprise knowledge from a variety of data sources. Azure AI Agent Service offers seamless integration with Microsoft Bing, Microsoft SharePoint, Microsoft Fabric, Azure AI Search, and third-party APIs. This extensive connectivity enables AI agents to access and process data from multiple sources, providing accurate and comprehensive responses to user queries. New data sources include: -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. +- Microsoft Bing +- Microsoft SharePoint (coming soon) +- Local Files +- Microsoft Fabric (coming soon) +- Azure Blob Storage (coming soon) +- Third-party APIs (Booking.com, TripAdvisor) (coming soon) -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. +**Flexible model selection**: Leverage the best model for the job, whether it's GPT-4o, Llama 3, or other specialized models from OpenAI, Meta, and Azure AI. Azure AI Agent Service supports a variety of models, allowing developers to optimize AI agent performance for specific use cases. This flexibility ensures that developers can choose the most suitable model to meet their business needs and achieve the desired outcomes. Key features include: + +* Support for various models from the Azure AI model catalog including OpenAI, Meta, and more​ +* Full parity with Azure OpenAI Service regional availability + +> [!IMPORTANT] +> The Azure AI Agent Service is currently in Private Preview. This early stage of development means the product is actively evolving, with significant updates and improvements expected. Users should anticipate changes as we work towards refining features, enhancing functionality, and expanding capabilities. We welcome feedback and contributions during this phase to help shape the future of the product. + +## Get started + +QuickStart (link) + +## Get help + +* GitHub Issues (Preferred) +* For other communications, please contact azureaiagents-preview@microsoft.com + +## Contributing This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or diff --git a/quickstart.md b/quickstart.md new file mode 100644 index 00000000..88b0858d --- /dev/null +++ b/quickstart.md @@ -0,0 +1,162 @@ +# AI Agents Quick Start + +This QuickStart demonstrates how to quickly set up your first agent with Azure AI Agent Service. + +## Complete Azure prerequisites + +1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. + +1. Make sure both developers and end users have the following permissions: + + * `Microsoft.MachineLearningServices/workspaces/agents/read` + * `Microsoft.MachineLearningServices/workspaces/agents/action` + * `Microsoft.MachineLearningServices/workspaces/agents/delete` + + If you want to create custom permissions, make sure they have: + + `agents/*/read` + + `agents/*/action` + + `agents/*/delete` + +## Setup your Azure AI Hub and Agent project + +To set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground): + +1. Create an Azure AI Hub to set up your app environment and network HOBO resources + +1. Create an Azure AI project under your Hub to provides an endpoint for your app to call, and set up proxy app services to access to resources in your tenant. + +1. Connect an Azure OpenAI resource or an Azure AI resource + +Follow these steps to set up your hub and project: + +1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). + +1. Register a provider + + ```console + az provider register –namespace {my_resource_namespace} + + [--accept-terms] + + [--consent-to-permissions] + + [--management-group-id] + + [--wait] + ``` + +1. To authenticate to your Azure subscription from the Azure CLI, use the following command: + + ```console + az login + ``` +2. Create a resource group: + + ```console + az group create --name {my_resource_group} --location westus2 + ``` + + + +Create an Azure OpenAI resource: + +Note: Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions (see the models guide) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. + + + +az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus2 + + + + Alternatively, you can create an AI Services resource: + + + + az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus2 --kind OpenAI --sku s0 + + + +Save the id that gets output, you’ll need it later. It will look similar to: https://eastus.api.cognitive.microsoft.com/ + +ai_services_resource_id: /subscriptions/1234-5678-abcd-9fc6-62780b3d3e05/resourceGroups/my-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource + + + +Create a Bing grounding resource + +az cognitiveservices account create \ + + --name bing-grounding-resource \ + + --resource-group \ + + --kind Bing.Grounding \ + + --sku G1 \ + + --location Global \ + + --yes + + +Create an Azure AI Hub. +Note: the following command auto creates a storage account, AML workspace and Key Vault + +az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} + + + +OR + + + +Optional: If you want to connect an existing storage account and/or key vault you can specify them here: + +az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} --location {hub-region} --storage-account {my_storage_account_id} --key-vault {my_key_vault_id} + + + + + +Connect your Hub to your Azure AI resource or Azure OpenAI resource. Replace the resource group and hub name with your resource and hub name. + +Save the following in a file named connection.yml + +If using an AI Services resource, use the following and replace ai_services_resource_id with the fully qualified ID from earlier. + + + +name: myazai_connection + +type: azure_ai_services + +endpoint: https://eastus.api.cognitive.microsoft.com/ + +ai_services_resource_id: /subscriptions/12345678-abcd-1234-9fc6-62780b3d3e05/resourceGroups/my-ai-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource + +If using an Azure OpenAI resource, create the following connection.yml file: + +name: {my_connection_name} + +type: azure_open_ai + +azure_endpoint: https://eastus.api.cognitive.microsoft.com/ + + + +Then run the following command: + +az ml connection create --file connection.yml --resource-group {my_resource_group} --workspace-name {my_hub_name} + +Create a Project. + +Run the following command to find your ARM Template: + +az ml workspace show -n {my_hub_name} --resource-group {my_resource_group} --query id + +Now run this command to create your project + +az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} \ No newline at end of file From a7198a51db9144f702ae79fdfd50c7a11f6d2ffe Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 30 Oct 2024 15:38:16 -0700 Subject: [PATCH 008/180] quickstart --- quickstart.md | 260 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 189 insertions(+), 71 deletions(-) diff --git a/quickstart.md b/quickstart.md index 88b0858d..cfec2030 100644 --- a/quickstart.md +++ b/quickstart.md @@ -32,9 +32,9 @@ To set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-stu Follow these steps to set up your hub and project: -1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). +1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). If you have the CLI already installed, make sure it's updated to the latest version. -1. Register a provider +1. Register a provider. ```console az provider register –namespace {my_resource_namespace} @@ -61,102 +61,220 @@ Follow these steps to set up your hub and project: -Create an Azure OpenAI resource: +1. Create an Azure OpenAI resource: -Note: Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions (see the models guide) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. - - - -az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus2 - - - - Alternatively, you can create an AI Services resource: - - - - az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus2 --kind OpenAI --sku s0 + > [!NOTE] + > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. + ``` + az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus2 + ``` -Save the id that gets output, you’ll need it later. It will look similar to: https://eastus.api.cognitive.microsoft.com/ - -ai_services_resource_id: /subscriptions/1234-5678-abcd-9fc6-62780b3d3e05/resourceGroups/my-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource - + Alternatively, you can create an AI Services resource: + + ```console + az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus2 --kind OpenAI --sku s0 + ``` -Create a Bing grounding resource - -az cognitiveservices account create \ - - --name bing-grounding-resource \ - - --resource-group \ - - --kind Bing.Grounding \ - - --sku G1 \ + Save the id that gets output, you’ll need it later. It will look similar to: `https://eastus.api.cognitive.microsoft.com/ai_services_resource_id: /subscriptions/1234-5678-abcd-9fc6-62780b3d3e05/resourceGroups/my-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource` - --location Global \ - - --yes +1. Create a Bing grounding resource. + ```console + az cognitiveservices account create \ + + --name bing-grounding-resource \ + + --resource-group \ + + --kind Bing.Grounding \ + + --sku G1 \ + + --location Global \ + + --yes + ``` -Create an Azure AI Hub. -Note: the following command auto creates a storage account, AML workspace and Key Vault - -az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} - - +1. Create an Azure AI Hub. -OR + > [!NOTE] the following command auto creates a storage account, AML workspace and Key Vault. - + ```console + az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} + ``` -Optional: If you want to connect an existing storage account and/or key vault you can specify them here: + OR -az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} --location {hub-region} --storage-account {my_storage_account_id} --key-vault {my_key_vault_id} + Optional: If you want to connect an existing storage account and/or key vault you can specify them here: + ```console + az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} --location {hub-region} --storage-account {my_storage_account_id} --key-vault {my_key_vault_id} + ``` +1. Connect your Hub to your Azure AI resource or Azure OpenAI resource. Replace the resource group and hub name with your resource and hub name. - + 1. Save the following in a file named `connection.yml`. -Connect your Hub to your Azure AI resource or Azure OpenAI resource. Replace the resource group and hub name with your resource and hub name. + 1. If using an AI Services resource, use the following and replace ai_services_resource_id with the fully qualified ID from earlier. -Save the following in a file named connection.yml - -If using an AI Services resource, use the following and replace ai_services_resource_id with the fully qualified ID from earlier. + ```yml + name: myazai_connection + type: azure_ai_services + endpoint: https://eastus.api.cognitive.microsoft.com/ + ai_services_resource_id: /subscriptions/12345678-abcd-1234-9fc6-62780b3d3e05/resourceGroups/my-ai-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource + ``` + 1. If using an Azure OpenAI resource, create the following `connection.yml` file: + ```yml + name: {my_connection_name} + type: azure_open_ai + azure_endpoint: https://eastus.api.cognitive.microsoft.com/ + ``` -name: myazai_connection +1. Then run the following command: -type: azure_ai_services - -endpoint: https://eastus.api.cognitive.microsoft.com/ - -ai_services_resource_id: /subscriptions/12345678-abcd-1234-9fc6-62780b3d3e05/resourceGroups/my-ai-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource - -If using an Azure OpenAI resource, create the following connection.yml file: - -name: {my_connection_name} - -type: azure_open_ai - -azure_endpoint: https://eastus.api.cognitive.microsoft.com/ + ```console + az ml connection create --file connection.yml --resource-group {my_resource_group} --workspace-name {my_hub_name} + ``` - +1. Create a Project. -Then run the following command: + 1. Run the following command to find your ARM Template: -az ml connection create --file connection.yml --resource-group {my_resource_group} --workspace-name {my_hub_name} + ```console + az ml workspace show -n {my_hub_name} --resource-group {my_resource_group} --query id + ``` -Create a Project. + 1. Now run this command to create your project -Run the following command to find your ARM Template: + ```console + az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} + ``` -az ml workspace show -n {my_hub_name} --resource-group {my_resource_group} --query id +## Configure and run your first agent -Now run this command to create your project -az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} \ No newline at end of file +| Component | Description | +|---|---| +| Agent | Custom AI that uses AI models in conjunction with tools. | +| Tool | Tools help extend an agent’s ability to reliably and accurately respond during conversation. Such as connecting to user-defined knowledge bases to ground the model, or enabling web search to provide current information. | +| Thread | A conversation session between an agent and a user. Threads store Messages and automatically handle truncation to fit content into a model’s context. | +| Message | A message created by an agent or a user. Messages can include text, images, and other files. Messages are stored as a list on the Thread. | +| Run | Activation of an agent to begin running based on the contents of Thread. The agent uses its configuration and Thread’s Messages to perform tasks by calling models and tools. As part of a Run, the agent appends Messages to the Thread. +| Run Step | A detailed list of steps the agent took as part of a Run. An agent can call tools or create Messages during its run. Examining Run Steps allows you to understand how the agent is getting to its results. | + +Use the following code to create an agent and send a message to it. This agent will have the code interpreter tool to enable your agent to perform advanced data analysis in a sandboxed environment and Bing search tool to real-time, web data grounding. + +## Python SDK + +> [!NOTE] +> You can find [C# code below](#c). + +Run the following command to install the python package. + +```console +python -m pip install azure-ai-projects azure-identity +``` + +Use the following code to create and run an agent. + +```python +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import Agent, MessageDeltaChunk, MessageDeltaTextContent, RunStep, ThreadMessage, ThreadRun +from azure.ai.projects.models import AgentEventHandler +from azure.ai.projects.operations import AgentsOperations +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import CodeInterpreterTool, bing_grounding, ToolSet +from typing import Any + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +# When using CodeInterpreterTool with ToolSet in agent creation, the tool call events are handled inside the create_stream +# method and functions gets automatically called by default. +class MyEventHandler(AgentEventHandler): + + def on_message_delta(self, delta: "MessageDeltaChunk") -> None: + for content_part in delta.delta.content: + if isinstance(content_part, MessageDeltaTextContent): + text_value = content_part.text.value if content_part.text else "No text" + print(f"Text delta received: {text_value}") + + def on_thread_message(self, message: "ThreadMessage") -> None: + print(f"ThreadMessage created. ID: {message.id}, Status: {message.status}") + + def on_thread_run(self, run: "ThreadRun") -> None: + print(f"ThreadRun status: {run.status}") + + if run.status == "failed": + print(f"Run failed. Error: {run.last_error}") + + def on_run_step(self, step: "RunStep") -> None: + print(f"RunStep type: {step.type}, Status: {step.status}") + + def on_error(self, data: str) -> None: + print(f"An error occurred. Data: {data}") + + def on_done(self) -> None: + print("Stream completed.") + + def on_unhandled_event(self, event_type: str, event_data: Any) -> None: + print(f"Unhandled Event Type: {event_type}, Data: {event_data}") + +# create a connection to the grounding with bing search resource +connection_name = "bing_grounding_connection" +target = "GROUNDING_WITH_BING_SEARCH_API" +wps_connection = WorkspaceConnection( + name=connection_name, + type="custom", + target=target, + credentials=ApiKeyConfiguration(key="API_KEY"), +) +ml_client.connections.create_or_update(workspace_connection=wps_connection) + +with project_client: + # Create Grounding with Bing Search tool with resources + bing_grounding_tool = bing_grounding(connection_id=[connection id of Grounding with Bing Search resource]) + code_interpreter = CodeInterpreterTool() + toolset = ToolSet() + toolset.add(code_interpreter) + toolset.add(bing_grounding_tool) + + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset + ) + print(f"Created agent, ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Write code to calculate compound interest.", + ) + print(f"Created message, message ID {message.id}") + + with project_client.agents.create_stream( + thread_id=thread.id, assistant_id=agent.id, event_handler=MyEventHandler() + ) as stream: + stream.until_done() + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") +``` + +## C# \ No newline at end of file From 71afe551911256ce6cfbe6b48d3b8d1a55b2d37e Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 30 Oct 2024 15:39:59 -0700 Subject: [PATCH 009/180] c# code --- quickstart.md | 103 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index cfec2030..e4dce255 100644 --- a/quickstart.md +++ b/quickstart.md @@ -277,4 +277,105 @@ with project_client: print(f"Messages: {messages}") ``` -## C# \ No newline at end of file +## C# + +Use the following package in your C# project + +```console +dotnet add package Azure.AI.Project --prerelease +``` + +Then use the following sample code to create an agent. + +```csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Identity; +using NUnit.Framework; + +namespace Azure.AI.Projects.Tests +{ + public partial class Sample_Agent_Basics + { + [Test] + public async Task BasicExample() + { + #region Snippet:OverviewCreateClient + var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); + AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); + #endregion + + // Step 1: Create an agent with a model, agent name, and instructions to help it respond + Response agentResponse = await client.CreateAgentAsync( + model: "gpt-4-1106-preview", + name: "Math Tutor", + instructions: "You are a personal math tutor. Write and run code to answer math questions.", + tools: new List { new CodeInterpreterToolDefinition() } + ); + Agent agent = agentResponse.Value; + + // The agent should now be listed + Response> agentListResponse = await client.GetAgentsAsync(); + + // Step 2: Create a thread, which will be used to store messages during conversation + Response threadResponse = await client.CreateThreadAsync(); + AgentThread thread = threadResponse.Value; + + // Step 3: Add a message to a thread, starting a conversation with the agent + Response messageResponse = await client.CreateMessageAsync( + thread.Id, + MessageRole.User, + "I need to solve the equation `3x + 11 = 14`. Can you help me?" + ); + ThreadMessage message = messageResponse.Value; + + // The message is now correlated with thread + // Sending a List messages will retrieve the message just added + Response> messagesListResponse = await client.GetMessagesAsync(thread.Id); + Assert.That(messagesListResponse.Value.Data[0].Id == message.Id); + + // Step 4: Run the agent, which will activate the assistant to begin running based on the contents of the thread + Response runResponse = await client.CreateRunAsync( + thread.Id, + agent.Id, + additionalInstructions: "Please address the user as Jane Doe. The user has a premium account." + ); + ThreadRun run = runResponse.Value; + + // Wait for the agent to finish running before retrieving the response + do + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); + } + while (runResponse.Value.Status == RunStatus.Queued || runResponse.Value.Status == RunStatus.InProgress); + #endregion + + #region Snippet:OverviewListUpdatedMessages + Response> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id); + IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + + // Note: messages iterate from newest to oldest, with the messages[0] being the most recent + foreach (ThreadMessage threadMessage in messages) + { + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($" Date: Wed, 30 Oct 2024 17:44:12 -0700 Subject: [PATCH 010/180] additional file updates --- media/llama-deployment-2.png | Bin 0 -> 173284 bytes media/llama-deployment.png | Bin 0 -> 246671 bytes quickstart.md | 9 +- samples/llama-3.md | 31 +++ samples/tools/bing-search.md | 154 +++++++++++++++ samples/tools/code-interpreter.md | 149 ++++++++++++++ samples/tools/file-search.md | 184 +++++++++++++++++ samples/tools/function-calling.md | 275 ++++++++++++++++++++++++++ samples/tools/openapi-30-functions.md | 191 ++++++++++++++++++ 9 files changed, 987 insertions(+), 6 deletions(-) create mode 100644 media/llama-deployment-2.png create mode 100644 media/llama-deployment.png create mode 100644 samples/llama-3.md create mode 100644 samples/tools/bing-search.md create mode 100644 samples/tools/code-interpreter.md create mode 100644 samples/tools/file-search.md create mode 100644 samples/tools/function-calling.md create mode 100644 samples/tools/openapi-30-functions.md diff --git a/media/llama-deployment-2.png b/media/llama-deployment-2.png new file mode 100644 index 0000000000000000000000000000000000000000..5503d43f9214563ab79366859f12114769a59d65 GIT binary patch literal 173284 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

iA1d&K$|D`%EE6c#V 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
c#EX#mDlkmg*(Rmj_n*9Ci_Ye&6>R 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

}55E>AnWtZBm)miETKQ89j*PO2E{`@~L4()c__ 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

{sv>sQz04N9wMw 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�J_IWk)iwWuXynIAobi=M1;!zZVwAj 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 R*>}K~q^O)o)mMYS{|7xdh3NnQ literal 0 HcmV?d00001 diff --git a/quickstart.md b/quickstart.md index e4dce255..7c863698 100644 --- a/quickstart.md +++ b/quickstart.md @@ -251,7 +251,7 @@ with project_client: toolset.add(bing_grounding_tool) agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset + model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent", toolset=toolset ) print(f"Created agent, ID: {agent.id}") @@ -266,7 +266,7 @@ with project_client: print(f"Created message, message ID {message.id}") with project_client.agents.create_stream( - thread_id=thread.id, assistant_id=agent.id, event_handler=MyEventHandler() + thread_id=thread.id, agent_id=agent.id, event_handler=MyEventHandler() ) as stream: stream.until_done() @@ -336,7 +336,7 @@ namespace Azure.AI.Projects.Tests Response> messagesListResponse = await client.GetMessagesAsync(thread.Id); Assert.That(messagesListResponse.Value.Data[0].Id == message.Id); - // Step 4: Run the agent, which will activate the assistant to begin running based on the contents of the thread + // Step 4: Run the agent, which will activate the agent to begin running based on the contents of the thread Response runResponse = await client.CreateRunAsync( thread.Id, agent.Id, @@ -351,9 +351,7 @@ namespace Azure.AI.Projects.Tests runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); } while (runResponse.Value.Status == RunStatus.Queued || runResponse.Value.Status == RunStatus.InProgress); - #endregion - #region Snippet:OverviewListUpdatedMessages Response> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id); IReadOnlyList messages = afterRunMessagesResponse.Value.Data; @@ -374,7 +372,6 @@ namespace Azure.AI.Projects.Tests Console.WriteLine(); } } - #endregion } } } diff --git a/samples/llama-3.md b/samples/llama-3.md new file mode 100644 index 00000000..e6aa4eca --- /dev/null +++ b/samples/llama-3.md @@ -0,0 +1,31 @@ +# Use Llama models with Agents + +You can now create agents using Llama 3 in Azure AI Agents Service. To get started: +1. Go to ai.azure.com and select **Model catalog** in the left navigation menu, and scroll down to **Meta-Llama-3-70B-Instruct**. You can also use this link. + +1. Select **Deploy**. + +1. In the Deployment options screen that appears, select Serverless API with Azure AI Content Safety. + + ![An image of the llama model project selection screen](../media/llama-deployment.png) + +1. Select your project and click **Subscribe and deploy**. + + ![An image of the llama model deployment screen](../media/llama-deployment-2.png) + +1. Add the Serverless connection to your hub / project. The deployment name you choose will be the one you reference in your code. + +1. When calling agent creation API, set the `models` parameter to your deployment name. For example: + + + ```python + agent = project_client.agents.create_agent( model="llama-3", name="my-agent", instructions="You are a helpful agent" ) + ``` + + ```csharp + Response agentResponse = await client.CreateAgentAsync( + model: "llama-3", + name: "Math Tutor", + instructions: "You are a helpful agent", + ); + ``` \ No newline at end of file diff --git a/samples/tools/bing-search.md b/samples/tools/bing-search.md new file mode 100644 index 00000000..38689a98 --- /dev/null +++ b/samples/tools/bing-search.md @@ -0,0 +1,154 @@ +# Grounding with Bing Search + +Grounding with Bing Search allows your Azure Agents to incorporate real-time public web data when generating responses. To start with, you need to create a Grounding with Bing Search resource, then connect this resource to your Azure Agents. When a user sends a query, Azure Agents will decide if Grounding with Bing Search should be leveraged or not. If so, it will leverage Bing to search over public web data and return relevant chunks. Lastly, Azure Agents will use returned chunks to generate a response. + +Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Bing + +Please note that developers and end users don’t have access to raw chunks returned by Grounding with Bing Search. Grounding with Bing Search is a free service during private preview. + +## Setup + +Create a Bing Search resource. If you don’t have one, you can use the Azure CLI or Azure portal to create one: + +```console +az cognitiveservices account create \ + + --name bing-grounding-resource \ + --resource-group \ + --kind Bing.Grounding \ + --sku G1 \ + --location Global \ + --yes +``` + +## Example + +> [!NOTE] +> You can find [C# code below](#c). + +### Python + +```python +import os + +from azure.ai.projects.models import bing_grounding, ToolSet +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential + +from azure.ai.ml.entities import WorkspaceConnection +from azure.ai.ml.entities import UsernamePasswordConfiguration, ApiKeyConfiguration + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + + + +# Customer needs to create a connection to the Grounding with Bing Search resource + +connection_name = "bing_grounding_connection" + + + +target = “GROUNDING_WITH_BING_SEARCH_API” + +wps_connection = WorkspaceConnection( + name=connection_name, + type="custom", + target=target, + credentials=ApiKeyConfiguration(key="API_KEY"), + ) + ml_client.connections.create_or_update(workspace_connection=wps_connection) + +with project_client: + + # Create Grounding with Bing Search tool with resources + bing_grounding_tool = bing_grounding(connection_id=[connection id of Grounding with Bing Search resource]) + + # Create agent with SharePoint tool and process agent run + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-agent", + instructions="Hello, you are helpful agent and can search information from uploaded files", + tools=bing_grounding_tool.definitions, + tool_resources= bing_grounding_tool.resources, + ) + print(f"Created agent, agent ID: {agent.id}") + + # Create thread for communication + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + # Create message to thread + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" + ) + print(f"Created message, ID: {message.id}") + + # Create and process agent run in thread with tools + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") + + if run.status == “complete”: + +print(f"Run complete: {run.id}") + + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") +``` + +## C# + +```csharp +using System; +using Azure.Identity; +using Azure.AI.Projects; +using Azure.AI.Projects.Models; +using Azure.AI.ML.Entities; + +class Program +{ + static void Main(string[] args) + { + // Ensure the environment variable is set + string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); + if (string.IsNullOrEmpty(connectionString)) + { + Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); + return; + } + + // Create an Azure AI Client from a connection string + var credential = new DefaultAzureCredential(); + var projectClient = AIProjectClient.FromConnectionString(credential, connectionString); + + // Create a connection to the Grounding with Bing Search resource + string connectionName = "bing_grounding_connection"; + string target = "GROUNDING_WITH_BING_SEARCH_API"; + + var wpsConnection = new WorkspaceConnection + { + Name = connectionName, + Type = "custom", + Target = target + }; + + // Additional code to use the projectClient and wpsConnection can be added here + } +} +``` \ No newline at end of file diff --git a/samples/tools/code-interpreter.md b/samples/tools/code-interpreter.md new file mode 100644 index 00000000..93f216bd --- /dev/null +++ b/samples/tools/code-interpreter.md @@ -0,0 +1,149 @@ +# Code interpreter + +Code Interpreter allows the Agent to write and run Python code in a sandboxed execution environment. With Code Interpreter enabled, your Agent can run code iteratively to solve more challenging code, math, and data analysis problems. + +## Supported file types + +|File format|MIME Type| +|---|---| +|.c| text/x-c | +|.cpp|text/x-c++ | +|.csv|application/csv| +|.docx|application/vnd.openxmlformats-officedocument.wordprocessingml.document| +|.html|text/html| +|.java|text/x-java| +|.json|application/json| +|.md|text/markdown| +|.pdf|application/pdf| +|.php|text/x-php| +|.pptx|application/vnd.openxmlformats-officedocument.presentationml.presentation| +|.py|text/x-python| +|.py|text/x-script.python| +|.rb|text/x-ruby| +|.tex|text/x-tex| +|.txt|text/plain| +|.css|text/css| +|.jpeg|image/jpeg| +|.jpg|image/jpeg| +|.js|text/javascript| +|.gif|image/gif| +|.png|image/png| +|.tar|application/x-tar| +|.ts|application/typescript| +|.xlsx|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet| +|.xml|application/xml or "text/xml"| +|.zip|application/zip| + +## Example + +Use the following examples to use Code interpreter with file attachment. + +> [!NOTE] +> You can find [C# code below](#c). + +### Python + +```python +from openai import AzureOpenAI + +client = AzureOpenAI( + api_key=os.getenv("AZURE_OPENAI_API_KEY"), + api_version="2024-05-01-preview", + azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") + ) + +# Upload a file with an "assistants" purpose +file = client.files.create( + file=open("speech.py", "rb"), + purpose='assistants' +) + +# Create an assistant using the file ID +assistant = client.beta.assistants.create( + instructions="You are an AI assistant that can write code to help answer math questions.", + model="gpt-4-1106-preview", + tools=[{"type": "code_interpreter"}], + tool_resources={"code interpreter":{"file_ids":[file.id]}} +) + +client = AzureOpenAI( + api_key=os.getenv("AZURE_OPENAI_API_KEY"), + api_version="2024-05-01-preview", + azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") + ) + +thread = client.beta.threads.create( + messages=[ + { + "role": "user", + "content": "I need to solve the equation `3x + 11 = 14`. Can you help me?", + "file_ids": ["file.id"] # file id will look like: "assistant-R9uhPxvRKGH3m0x5zBOhMjd2" + } + ] +) +``` + +## C# + +```csharp +using System; +using System.IO; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; + +class Program +{ + private static readonly string apiKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"); + private static readonly string apiVersion = "2024-05-01-preview"; + private static readonly string azureEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"); + + static async Task Main(string[] args) + { + var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); + + // Upload a file with an "assistants" purpose + var fileContent = new StreamContent(File.OpenRead("speech.py")); + var fileRequest = new MultipartFormDataContent(); + fileRequest.Add(fileContent, "file", "speech.py"); + fileRequest.Add(new StringContent("assistants"), "purpose"); + + var fileResponse = await client.PostAsync($"{azureEndpoint}/v1/files?api-version={apiVersion}", fileRequest); + var fileResponseBody = await fileResponse.Content.ReadAsStringAsync(); + var fileId = JObject.Parse(fileResponseBody)["id"].ToString(); + + // Create an assistant using the file ID + var assistantRequest = new + { + instructions = "You are an AI assistant that can write code to help answer math questions.", + model = "gpt-4-1106-preview", + tools = new[] { new { type = "code_interpreter" } }, + tool_resources = new { code_interpreter = new { file_ids = new[] { fileId } } } + }; + + var assistantResponse = await client.PostAsJsonAsync($"{azureEndpoint}/v1/assistants?api-version={apiVersion}", assistantRequest); + var assistantResponseBody = await assistantResponse.Content.ReadAsStringAsync(); + var assistantId = JObject.Parse(assistantResponseBody)["id"].ToString(); + + // Create a thread with the assistant + var threadRequest = new + { + messages = new[] + { + new + { + role = "user", + content = "I need to solve the equation `3x + 11 = 14`. Can you help me?", + file_ids = new[] { fileId } + } + } + }; + + var threadResponse = await client.PostAsJsonAsync($"{azureEndpoint}/v1/threads?api-version={apiVersion}", threadRequest); + var threadResponseBody = await threadResponse.Content.ReadAsStringAsync(); + Console.WriteLine(threadResponseBody); + } +} +``` \ No newline at end of file diff --git a/samples/tools/file-search.md b/samples/tools/file-search.md new file mode 100644 index 00000000..e38d51a8 --- /dev/null +++ b/samples/tools/file-search.md @@ -0,0 +1,184 @@ +# File Search + +File Search augments the Agent with knowledge from outside its model, such as proprietary product information or documents provided by your users. OpenAI automatically parses and chunks your documents, creates and stores the embeddings, and use both vector and keyword search to retrieve relevant content to answer user queries. + +## Setup + +To access your files, the file search tool uses the vector store object. Upload your files and create a vector store to contain them. Once the vector store is created, you should poll its status until all files are out of the in_progress state to ensure that all content has finished processing. The SDK provides helpers for uploading and polling. + +## Example + +> [!NOTE] +> You can find [C# code below](#c). + +### Python + +```python +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models._patch import FileSearchTool +from azure.identity import DefaultAzureCredential + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + + +with project_client: + + openai_file = project_client.agents.upload_file_and_poll(file_path="product_info_1.md", purpose="assistants") + print(f"Uploaded file, file ID: {openai_file.id}") + + openai_vectorstore = project_client.agents.create_vector_store_and_poll(file_ids=[openai_file.id], name="my_vectorstore") + print(f"Created vector store, vector store ID: {openai_vectorstore.id}") + + # Create file search tool with resources + file_search = FileSearchTool(vector_store_ids=[openai_vectorstore.id]) + + # Create agent with file search tool and process the agent run + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-agent", + instructions="Hello, you are helpful agent and can search information from uploaded files", + tools=file_search.definitions, + tool_resources=file_search.resources, + ) + print(f"Created agent, agent ID: {agent.id}") + + # Create thread for communication + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + # Create message to thread + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" + ) + print(f"Created message, ID: {message.id}") + + # Create and process agent run in thread with tools + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") + + # Delete the file when done + project_client.agents.delete_vector_store(openai_vectorstore.id) + print("Deleted vector store") + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") +``` + + +### C# + +```csharp +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Azure.Identity; +using NUnit.Framework; + +namespace Azure.AI.Projects.Tests +{ + public partial class Sample_Agent_FileSearch + { + [Test] + public async Task FilesSearchExample() + { + var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); + AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); + + #region Snippet:UploadAgentFilesToUse + // Upload a file and wait for it to be processed + File.WriteAllText( + path: "sample_file_for_upload.txt", + contents: "The word 'apple' uses the code 442345, while the word 'banana' uses the code 673457."); + Response uploadAgentFileResponse = await client.UploadFileAsync( + filePath: "sample_file_for_upload.txt", + purpose: AgentFilePurpose.Agents); + + AgentFile uploadedAgentFile = uploadAgentFileResponse.Value; + #endregion + + #region Snippet:CreateVectorStore + // Create a vector store with the file and wait for it to be processed. + // If you do not specify a vector store, create_message will create a vector store with a default expiration policy of seven days after they were last active + VectorStore vectorStore = await client.CreateVectorStoreAsync( + fileIds: new List { uploadedAgentFile.Id }, + name: "my_vector_store"); + #endregion + + #region Snippet:CreateAgentWithFiles + FileSearchToolResource fileSearchToolResource = new FileSearchToolResource(); + fileSearchToolResource.VectorStoreIds.Add(vectorStore.Id); + + // Create an agent with toolResources and process the agent run + Response agentResponse = await client.CreateAgentAsync( + model: "gpt-4-1106-preview", + name: "SDK Test Agent - Retrieval", + instructions: "You are a helpful agent that can help fetch data from files you know about.", + tools: new List { new FileSearchToolDefinition() }, + toolResources: new ToolResources() { FileSearch = fileSearchToolResource }); + Agent agent = agentResponse.Value; + #endregion + + // Create thread for communication + Response threadResponse = await client.CreateThreadAsync(); + AgentThread thread = threadResponse.Value; + + // Create message to thread + Response messageResponse = await client.CreateMessageAsync( + thread.Id, + MessageRole.User, + "Can you give me the documented codes for 'banana' and 'orange'?"); + ThreadMessage message = messageResponse.Value; + + // Run the agent + Response runResponse = await client.CreateRunAsync(thread, agent); + + do + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); + } + while (runResponse.Value.Status == RunStatus.Queued + || runResponse.Value.Status == RunStatus.InProgress); + + Response> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id); + IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + + // Note: messages iterate from newest to oldest, with the messages[0] being the most recent + foreach (ThreadMessage threadMessage in messages) + { + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($""); + } + Console.WriteLine(); + } + } + } + } +} +``` \ No newline at end of file diff --git a/samples/tools/function-calling.md b/samples/tools/function-calling.md new file mode 100644 index 00000000..07ed0b8a --- /dev/null +++ b/samples/tools/function-calling.md @@ -0,0 +1,275 @@ +# Function Calling + +Azure AI Agents Service supports function calling, which allows you to describe the structure of functions to an Agent and then return the functions that need to be called along with their arguments. + +## Example + +> [!NOTE] +> You can find [C# code below](#c). + +```python +import os, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import FunctionTool, SubmitToolOutputsAction, RequiredFunctionToolCall +from user_functions import user_functions + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +# Initialize function tool with user functions +functions = FunctionTool(functions=user_functions) + +with project_client: + # Create an agent and run user's request with function calls + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-agent", + instructions="You are a helpful agent", + tools=functions.definitions, + ) + print(f"Created agent, ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Hello, send an email with the datetime and weather information in New York?", + ) + print(f"Created message, ID: {message.id}") + + run = project_client.agents.create_run(thread_id=thread.id, agent_id=agent.id) + print(f"Created run, ID: {run.id}") + + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) + run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + if run.status == "requires_action" and isinstance(run.required_action, SubmitToolOutputsAction): + tool_calls = run.required_action.submit_tool_outputs.tool_calls + if not tool_calls: + print("No tool calls provided - cancelling run") + project_client.agents.cancel_run(thread_id=thread.id, run_id=run.id) + break + + tool_outputs = [] + for tool_call in tool_calls: + if isinstance(tool_call, RequiredFunctionToolCall): + try: + output = functions.execute(tool_call) + tool_outputs.append( + { + "tool_call_id": tool_call.id, + "output": output, + } + ) + except Exception as e: + print(f"Error executing tool_call {tool_call.id}: {e}") + + print(f"Tool outputs: {tool_outputs}") + if tool_outputs: + project_client.agents.submit_tool_outputs_to_run( + thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs + ) + + print(f"Current run status: {run.status}") + + print(f"Run completed with status: {run.status}") + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") +``` + +## C# + +```csharp +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Azure.Identity; +using NUnit.Framework; + +namespace Azure.AI.Projects.Tests +{ + public partial class Sample_Agent_Functions + { + [Test] + public async Task FunctionCallingExample() + { + var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); + AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); + + #region Snippet:FunctionsDefineFunctionTools + // Example of a function that defines no parameters + string GetUserFavoriteCity() => "Seattle, WA"; + FunctionToolDefinition getUserFavoriteCityTool = new("getUserFavoriteCity", "Gets the user's favorite city."); + + // Example of a function with a single required parameter + string GetCityNickname(string location) => location switch + { + "Seattle, WA" => "The Emerald City", + _ => throw new NotImplementedException(), + }; + FunctionToolDefinition getCityNicknameTool = new( + name: "getCityNickname", + description: "Gets the nickname of a city, e.g. 'LA' for 'Los Angeles, CA'.", + parameters: BinaryData.FromObjectAsJson( + new + { + Type = "object", + Properties = new + { + Location = new + { + Type = "string", + Description = "The city and state, e.g. San Francisco, CA", + }, + }, + Required = new[] { "location" }, + }, + new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); + + // Example of a function with one required and one optional, enum parameter + string GetWeatherAtLocation(string location, string temperatureUnit = "f") => location switch + { + "Seattle, WA" => temperatureUnit == "f" ? "70f" : "21c", + _ => throw new NotImplementedException() + }; + FunctionToolDefinition getCurrentWeatherAtLocationTool = new( + name: "getCurrentWeatherAtLocation", + description: "Gets the current weather at a provided location.", + parameters: BinaryData.FromObjectAsJson( + new + { + Type = "object", + Properties = new + { + Location = new + { + Type = "string", + Description = "The city and state, e.g. San Francisco, CA", + }, + Unit = new + { + Type = "string", + Enum = new[] { "c", "f" }, + }, + }, + Required = new[] { "location" }, + }, + new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); + #endregion + + #region Snippet:FunctionsHandleFunctionCalls + ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall) + { + if (toolCall is RequiredFunctionToolCall functionToolCall) + { + if (functionToolCall.Name == getUserFavoriteCityTool.Name) + { + return new ToolOutput(toolCall, GetUserFavoriteCity()); + } + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + if (functionToolCall.Name == getCityNicknameTool.Name) + { + string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString(); + return new ToolOutput(toolCall, GetCityNickname(locationArgument)); + } + if (functionToolCall.Name == getCurrentWeatherAtLocationTool.Name) + { + string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString(); + if (argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unitElement)) + { + string unitArgument = unitElement.GetString(); + return new ToolOutput(toolCall, GetWeatherAtLocation(locationArgument, unitArgument)); + } + return new ToolOutput(toolCall, GetWeatherAtLocation(locationArgument)); + } + } + return null; + } + #endregion + + #region Snippet:FunctionsCreateAgentWithFunctionTools + // note: parallel function calling is only supported with newer models like gpt-4-1106-preview + Response agentResponse = await client.CreateAgentAsync( + model: "gpt-4-1106-preview", + name: "SDK Test Agent - Functions", + instructions: "You are a weather bot. Use the provided functions to help answer questions. " + + "Customize your responses to the user's preferences as much as possible and use friendly " + + "nicknames for cities whenever possible.", + tools: new List { getUserFavoriteCityTool, getCityNicknameTool, getCurrentWeatherAtLocationTool } + ); + Agent agent = agentResponse.Value; + #endregion + + Response threadResponse = await client.CreateThreadAsync(); + AgentThread thread = threadResponse.Value; + + Response messageResponse = await client.CreateMessageAsync( + thread.Id, + MessageRole.User, + "What's the weather like in my favorite city?"); + ThreadMessage message = messageResponse.Value; + + Response runResponse = await client.CreateRunAsync(thread, agent); + + #region Snippet:FunctionsHandlePollingWithRequiredAction + do + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); + + if (runResponse.Value.Status == RunStatus.RequiresAction + && runResponse.Value.RequiredAction is SubmitToolOutputsAction submitToolOutputsAction) + { + List toolOutputs = new(); + foreach (RequiredToolCall toolCall in submitToolOutputsAction.ToolCalls) + { + toolOutputs.Add(GetResolvedToolOutput(toolCall)); + } + runResponse = await client.SubmitToolOutputsToRunAsync(runResponse.Value, toolOutputs); + } + } + while (runResponse.Value.Status == RunStatus.Queued + || runResponse.Value.Status == RunStatus.InProgress); + #endregion + + Response> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id); + IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + + // Note: messages iterate from newest to oldest, with the messages[0] being the most recent + foreach (ThreadMessage threadMessage in messages) + { + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($""); + } + Console.WriteLine(); + } + } + } + } +} +``` \ No newline at end of file diff --git a/samples/tools/openapi-30-functions.md b/samples/tools/openapi-30-functions.md new file mode 100644 index 00000000..fe08908a --- /dev/null +++ b/samples/tools/openapi-30-functions.md @@ -0,0 +1,191 @@ +# Use OpenAPI 3.0 Specified Tools + +The Custom Tools feature allows developers to describe custom tools in the Agent API using an [OpenAPI schema](https://www.openapis.org/), enabling the model to intelligently call these functions based on user input. You can use any API spec that is written according to the OpenAPI 3.0 schema. + +## Setup + +First you need a tool defined using the OpenAPI Schema, for example: + +```yml +openapi: 3.0.1  +info:  +  title: Weather Service API  +  description: This is a sample API for retrieving weather information.  +  version: 1.0.0  +servers:  +  - url: https://api.example.com/weather  +    description: Main API Server  +paths:  +  /current:  +    get:  +      summary: Get current weather  +      operationId: getCurrentWeather  +... +``` + +## Example + +> [!NOTE] +> You can find [C# code below](#c). + +```python +import os, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import openapi, SubmitToolOutputsAction, RequiredFunctionToolCall + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +with project_client: + # Create an agent and run user's request with function calls + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-agent", + instructions="You are a helpful agent", + tools=[{ + "type": "openapi", + "openapi": { + "name": "mytool", + "description": "My tool", + "spec": { + "openapi": "3.0.0", + + } + }, + "auth": { + "type": "anonymous | managed_identity | connection" + } + }] + ) + print(f"Created agent, ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Hello, send an email with the datetime and weather information in New York?", + ) + print(f"Created message, ID: {message.id}") + + run = project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Created run, ID: {run.id}") + + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) + run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + if run.status == "requires_action" and isinstance(run.required_action, SubmitToolOutputsAction): + tool_calls = run.required_action.submit_tool_outputs.tool_calls + if not tool_calls: + print("No tool calls provided - cancelling run") + project_client.agents.cancel_run(thread_id=thread.id, run_id=run.id) + break + + tool_outputs = [] + for tool_call in tool_calls: + if isinstance(tool_call, RequiredFunctionToolCall): + try: + tool_outputs.append({ + "tool_call_id": tool_call.id, + }) + except Exception as e: + print(f"Error executing tool_call {tool_call.id}: {e}") + + print(f"Tool outputs: {tool_outputs}") + if tool_outputs: + project_client.agents.submit_tool_outputs_to_run( + thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs + ) + + print(f"Current run status: {run.status}") + + print(f"Run completed with status: {run.status}") + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") +``` + + +## C# + + +```csharp +using System; +using System.Threading.Tasks; +using Azure.Identity; +using Azure.AI.Projects; +using Azure.AI.Projects.Models; + +class Program +{ + static async Task Main(string[] args) + { + // Ensure the environment variable is set + string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); + if (string.IsNullOrEmpty(connectionString)) + { + Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); + return; + } + + // Create an Azure AI Client from a connection string + var credential = new DefaultAzureCredential(); + var projectClient = new AIProjectClient(connectionString, credential); + + // Create an agent and run user's request with function calls + var agent = await projectClient.Agents.CreateAgentAsync(new CreateAgentOptions + { + Model = "gpt-4-1106-preview", + Name = "my-agent", + Instructions = "You are a helpful agent", + Tools = new[] + { + new Tool + { + Type = "openapi", + OpenApi = new OpenApiTool + { + Name = "mytool", + Description = "My tool", + Spec = new OpenApiSpec + { + OpenApi = "3.0.0", + // + } + } + } + } + }); + + // Use the agent as needed + // ... + } +} +``` + + + +Authentication can be either anonymous (no authentication) or “managed_identity” + +"auth": { "type": "managed_identity", "security_scheme": { "audience": "https://cognitiveservices.azure.com/" }} + + or “connection” + +"auth": { "type": "connection", "security_scheme": { "connection_id": "1234-56789" }} + +anonymous is not authentication, managed_identity is authenticating with various Azure Services using RBAC, connection is using 3rd party APIs with API keys and Custom Keys Connections in azure AI studio. + +Note: Connection authentication requires an enterprise setup. \ No newline at end of file From 417c4413e31f27b82dc0299124d63667a9421efb Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 30 Oct 2024 17:56:49 -0700 Subject: [PATCH 011/180] moving rbac --- README.md | 2 +- quickstart.md | 14 +------------- rbac.md | 13 +++++++++++++ 3 files changed, 15 insertions(+), 14 deletions(-) create mode 100644 rbac.md diff --git a/README.md b/README.md index c6ee024a..66899d2e 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Azure AI Agent Service is a fully-managed service designed to empower developers ## Get started -QuickStart (link) +See the QuickStart to [get started](./quickstart.md). ## Get help diff --git a/quickstart.md b/quickstart.md index 7c863698..992408d9 100644 --- a/quickstart.md +++ b/quickstart.md @@ -6,19 +6,7 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A 1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. -1. Make sure both developers and end users have the following permissions: - - * `Microsoft.MachineLearningServices/workspaces/agents/read` - * `Microsoft.MachineLearningServices/workspaces/agents/action` - * `Microsoft.MachineLearningServices/workspaces/agents/delete` - - If you want to create custom permissions, make sure they have: - - `agents/*/read` - - `agents/*/action` - - `agents/*/delete` +1. check the [RBAC roles](./rbac.md). ## Setup your Azure AI Hub and Agent project diff --git a/rbac.md b/rbac.md new file mode 100644 index 00000000..0b756aa1 --- /dev/null +++ b/rbac.md @@ -0,0 +1,13 @@ +# RBAC roles + +Make sure both developers and end users have the following permissions: + +* `Microsoft.MachineLearningServices/workspaces/agents/read ` +* `Microsoft.MachineLearningServices/workspaces/agents/action ` +* `Microsoft.MachineLearningServices/workspaces/agents/delete ` + +If you want to create custom permissions, make sure they have: + +* `agents/*/read` +* `agents/*/action` +* `agents/*/delete` \ No newline at end of file From 1348f855e1e3074e4447b94fff7f346a9af81506 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 09:36:47 -0700 Subject: [PATCH 012/180] formatting overview and adding sample links --- README.md | 19 +++++++++++-------- samples/tools/bing-search.md | 6 +++++- samples/tools/code-interpreter.md | 6 +++++- samples/tools/file-search.md | 6 +++++- samples/tools/function-calling.md | 6 +++++- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 66899d2e..1075cda3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ -# Azure AI Agent Service +# 🤖 Azure AI Agent Service 🤖 + + | [**Get started**](./quickstart.md) | [**Samples**](./samples/) | Build fast, secure enterprise AI Agents to automate any business workflow +## ❓What is the Azure AI Agent Service? Azure AI Agent Service is a fully-managed service designed to empower developers to securely build, deploy, and scale high-quality, and extensible AI agents. Leveraging an extensive ecosystem of models, tools and capabilities from OpenAI, Microsoft, and third-party providers, Azure AI Agent Service enables building agents for a wide range of generative AI use cases. -## Highlights +## 💥 Highlights -**Enterprise grade security**: Ensure data privacy and compliance with secure data handling and no public egress. Azure AI Agent Service provides features like bring your own storage and private networking, platform-managed storage, and built-in content filters and XPIA mitigation. These capabilities help organizations protect their sensitive data while meeting regulatory requirements, ensuring that AI agents operate within a secure and compliant environment. Key features include: +✅ **Enterprise grade security**: Ensure data privacy and compliance with secure data handling and no public egress. Azure AI Agent Service provides features like bring your own storage and private networking, platform-managed storage, and built-in content filters and XPIA mitigation. These capabilities help organizations protect their sensitive data while meeting regulatory requirements, ensuring that AI agents operate within a secure and compliant environment. Key features include: - Bring your own Azure Storage Account - Bring your own VNET (coming soon) @@ -17,7 +20,7 @@ Azure AI Agent Service is a fully-managed service designed to empower developers - Monitor agent performance with OpenTelemetry-based tracing (coming soon) - Build responsibly with content filters and XPIA (Cross Prompt Injection Attack) mitigation -**Rapid development and automation**: Quickly build enterprise-grade AI agents with a user-friendly interface and comprehensive toolset, including pre-built tools for advanced data analysis and RAG. Azure AI Agent Service also supports seamless integration with enterprise applications through Azure Logic Apps, OpenAPI 3.0 specified tools, and Azure Functions for real-time data processing and workflow automation. This enables developers to accelerate time-to-market while enhancing operational efficiency with intelligent automation. Key features include: +✅ **Rapid development and automation**: Quickly build enterprise-grade AI agents with a user-friendly interface and comprehensive toolset, including pre-built tools for advanced data analysis and RAG. Azure AI Agent Service also supports seamless integration with enterprise applications through Azure Logic Apps, OpenAPI 3.0 specified tools, and Azure Functions for real-time data processing and workflow automation. This enables developers to accelerate time-to-market while enhancing operational efficiency with intelligent automation. Key features include: * Create a wide range of automated workflows with Azure Logic Apps’ 1400+built-in connectors​ @@ -29,7 +32,7 @@ Azure AI Agent Service is a fully-managed service designed to empower developers * Wire-compatible with Azure OpenAI Assistants API -**Extensive data connections**: Ground your AI agents with relevant, secure enterprise knowledge from a variety of data sources. Azure AI Agent Service offers seamless integration with Microsoft Bing, Microsoft SharePoint, Microsoft Fabric, Azure AI Search, and third-party APIs. This extensive connectivity enables AI agents to access and process data from multiple sources, providing accurate and comprehensive responses to user queries. New data sources include: +✅ **Extensive data connections**: Ground your AI agents with relevant, secure enterprise knowledge from a variety of data sources. Azure AI Agent Service offers seamless integration with Microsoft Bing, Microsoft SharePoint, Microsoft Fabric, Azure AI Search, and third-party APIs. This extensive connectivity enables AI agents to access and process data from multiple sources, providing accurate and comprehensive responses to user queries. New data sources include: - Microsoft Bing - Microsoft SharePoint (coming soon) @@ -38,7 +41,7 @@ Azure AI Agent Service is a fully-managed service designed to empower developers - Azure Blob Storage (coming soon) - Third-party APIs (Booking.com, TripAdvisor) (coming soon) -**Flexible model selection**: Leverage the best model for the job, whether it's GPT-4o, Llama 3, or other specialized models from OpenAI, Meta, and Azure AI. Azure AI Agent Service supports a variety of models, allowing developers to optimize AI agent performance for specific use cases. This flexibility ensures that developers can choose the most suitable model to meet their business needs and achieve the desired outcomes. Key features include: +✅ **Flexible model selection**: Leverage the best model for the job, whether it's GPT-4o, Llama 3, or other specialized models from OpenAI, Meta, and Azure AI. Azure AI Agent Service supports a variety of models, allowing developers to optimize AI agent performance for specific use cases. This flexibility ensures that developers can choose the most suitable model to meet their business needs and achieve the desired outcomes. Key features include: * Support for various models from the Azure AI model catalog including OpenAI, Meta, and more​ * Full parity with Azure OpenAI Service regional availability @@ -46,11 +49,11 @@ Azure AI Agent Service is a fully-managed service designed to empower developers > [!IMPORTANT] > The Azure AI Agent Service is currently in Private Preview. This early stage of development means the product is actively evolving, with significant updates and improvements expected. Users should anticipate changes as we work towards refining features, enhancing functionality, and expanding capabilities. We welcome feedback and contributions during this phase to help shape the future of the product. -## Get started +## 🚀 Get started See the QuickStart to [get started](./quickstart.md). -## Get help +## ❓Get help * GitHub Issues (Preferred) * For other communications, please contact azureaiagents-preview@microsoft.com diff --git a/samples/tools/bing-search.md b/samples/tools/bing-search.md index 38689a98..6a426df4 100644 --- a/samples/tools/bing-search.md +++ b/samples/tools/bing-search.md @@ -151,4 +151,8 @@ class Program // Additional code to use the projectClient and wpsConnection can be added here } } -``` \ No newline at end of file +``` + +## Samples + +* [Assistant function calling with Bing Search](https://github.com/Azure-Samples/azureai-samples/tree/main/scenarios/Assistants/function_calling) \ No newline at end of file diff --git a/samples/tools/code-interpreter.md b/samples/tools/code-interpreter.md index 93f216bd..ba03ffa5 100644 --- a/samples/tools/code-interpreter.md +++ b/samples/tools/code-interpreter.md @@ -146,4 +146,8 @@ class Program Console.WriteLine(threadResponseBody); } } -``` \ No newline at end of file +``` + +# Samples + +* [Math tutor](https://github.com/openai/openai-cookbook/blob/main/examples/data/oai_docs/tool-code-interpreter.txt) \ No newline at end of file diff --git a/samples/tools/file-search.md b/samples/tools/file-search.md index e38d51a8..5ad542fa 100644 --- a/samples/tools/file-search.md +++ b/samples/tools/file-search.md @@ -181,4 +181,8 @@ namespace Azure.AI.Projects.Tests } } } -``` \ No newline at end of file +``` + +## Samples + +* [Python Quart app](https://github.com/Azure-Samples/azureai-assistant-tool/tree/main/samples/FileSearch) \ No newline at end of file diff --git a/samples/tools/function-calling.md b/samples/tools/function-calling.md index 07ed0b8a..af998fbe 100644 --- a/samples/tools/function-calling.md +++ b/samples/tools/function-calling.md @@ -272,4 +272,8 @@ namespace Azure.AI.Projects.Tests } } } -``` \ No newline at end of file +``` + +# Samples + +Get the latest stock price using function calling with Yfinance ([shown in Personal Finance Assistant](https://github.com/Azure-Samples/azureai-samples/blob/main/scenarios/Assistants/api-in-a-box/personal_finance/assistant-personal_finance.ipynb)) From c82d608686fa5a2870994879ed9ae342bf338b15 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:39:02 -0700 Subject: [PATCH 013/180] Update README.md updated data source names --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1075cda3..57e04784 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,11 @@ Azure AI Agent Service is a fully-managed service designed to empower developers ✅ **Extensive data connections**: Ground your AI agents with relevant, secure enterprise knowledge from a variety of data sources. Azure AI Agent Service offers seamless integration with Microsoft Bing, Microsoft SharePoint, Microsoft Fabric, Azure AI Search, and third-party APIs. This extensive connectivity enables AI agents to access and process data from multiple sources, providing accurate and comprehensive responses to user queries. New data sources include: -- Microsoft Bing -- Microsoft SharePoint (coming soon) +- Grounding with Bing Search +- SharePoint (coming soon) - Local Files - Microsoft Fabric (coming soon) - Azure Blob Storage (coming soon) -- Third-party APIs (Booking.com, TripAdvisor) (coming soon) ✅ **Flexible model selection**: Leverage the best model for the job, whether it's GPT-4o, Llama 3, or other specialized models from OpenAI, Meta, and Azure AI. Azure AI Agent Service supports a variety of models, allowing developers to optimize AI agent performance for specific use cases. This flexibility ensures that developers can choose the most suitable model to meet their business needs and achieve the desired outcomes. Key features include: From 47b0c1a2ca783eca902de2a017848f9778612709 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 11:03:49 -0700 Subject: [PATCH 014/180] removing link --- samples/tools/bing-search.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/samples/tools/bing-search.md b/samples/tools/bing-search.md index 6a426df4..31e9c396 100644 --- a/samples/tools/bing-search.md +++ b/samples/tools/bing-search.md @@ -152,7 +152,3 @@ class Program } } ``` - -## Samples - -* [Assistant function calling with Bing Search](https://github.com/Azure-Samples/azureai-samples/tree/main/scenarios/Assistants/function_calling) \ No newline at end of file From cc72e2244178b61751a58497ad862d9abdda45c8 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 12:42:45 -0700 Subject: [PATCH 015/180] reorganizing files --- quickstart.md | 15 ++ samples/bing-search/bing-search.md | 34 ++++ samples/bing-search/csharp-sample.cs | 36 ++++ samples/bing-search/python-sample.py | 81 +++++++++ .../csharp-sample.cs} | 95 +---------- samples/code-interpreter/python-sample.py | 37 +++++ samples/code-interpreter/readme.md | 49 ++++++ samples/{tools => file-search}/file-search.md | 0 .../function-calling.md | 0 .../openapi-30-functions.md | 0 samples/tools/bing-search.md | 154 ------------------ 11 files changed, 253 insertions(+), 248 deletions(-) create mode 100644 samples/bing-search/bing-search.md create mode 100644 samples/bing-search/csharp-sample.cs create mode 100644 samples/bing-search/python-sample.py rename samples/{tools/code-interpreter.md => code-interpreter/csharp-sample.cs} (50%) create mode 100644 samples/code-interpreter/python-sample.py create mode 100644 samples/code-interpreter/readme.md rename samples/{tools => file-search}/file-search.md (100%) rename samples/{tools => function-calling}/function-calling.md (100%) rename samples/{tools => openapi}/openapi-30-functions.md (100%) delete mode 100644 samples/tools/bing-search.md diff --git a/quickstart.md b/quickstart.md index 992408d9..c7e6c332 100644 --- a/quickstart.md +++ b/quickstart.md @@ -143,6 +143,21 @@ Follow these steps to set up your hub and project: az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} ``` +## Install the SDK package + +Depending on your programming language of choice install the SDK using the following steps: + +### Python + +1. Download the [Python .whl file](./packages/azure_ai_project-1.0.0b1-py3-none-any.whl) to your project directory. +1. Install the SDK with `pip install azure_ai_project-1.0.0b1-py3-none-any.whl --user --force-reinstall` + >[!NOTE] + > We recommend creating a virtual environment with [venv](https://docs.python.org/3/library/venv.html). + +### C# + +TBD + ## Configure and run your first agent diff --git a/samples/bing-search/bing-search.md b/samples/bing-search/bing-search.md new file mode 100644 index 00000000..0ffece50 --- /dev/null +++ b/samples/bing-search/bing-search.md @@ -0,0 +1,34 @@ +# Grounding with Bing Search + +Grounding with Bing Search allows your Azure Agents to incorporate real-time public web data when generating responses. To start with, you need to create a Grounding with Bing Search resource, then connect this resource to your Azure Agents. When a user sends a query, Azure Agents will decide if Grounding with Bing Search should be leveraged or not. If so, it will leverage Bing to search over public web data and return relevant chunks. Lastly, Azure Agents will use returned chunks to generate a response. + +Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Bing + +Please note that developers and end users don’t have access to raw chunks returned by Grounding with Bing Search. Grounding with Bing Search is a free service during private preview. + +## Setup + +1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). + +1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI or Azure portal to create one: + + ```console + az cognitiveservices account create \ + + --name bing-grounding-resource \ + --resource-group \ + --kind Bing.Grounding \ + --sku G1 \ + --location Global \ + --yes + ``` + +## Examples + +Run the code samples below and view the output. + +>[!NOTE] +> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. + +* [Python](./python-sample.py) +* [C#](./csharp-sample.cs) \ No newline at end of file diff --git a/samples/bing-search/csharp-sample.cs b/samples/bing-search/csharp-sample.cs new file mode 100644 index 00000000..c894fd5b --- /dev/null +++ b/samples/bing-search/csharp-sample.cs @@ -0,0 +1,36 @@ +using System; +using Azure.Identity; +using Azure.AI.Projects; +using Azure.AI.Projects.Models; +using Azure.AI.ML.Entities; + +class Program +{ + static void Main(string[] args) + { + // Ensure the environment variable is set + string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); + if (string.IsNullOrEmpty(connectionString)) + { + Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); + return; + } + + // Create an Azure AI Client from a connection string + var credential = new DefaultAzureCredential(); + var projectClient = AIProjectClient.FromConnectionString(credential, connectionString); + + // Create a connection to the Grounding with Bing Search resource + string connectionName = "bing_grounding_connection"; + string target = "GROUNDING_WITH_BING_SEARCH_API"; + + var wpsConnection = new WorkspaceConnection + { + Name = connectionName, + Type = "custom", + Target = target + }; + + // Additional code to use the projectClient and wpsConnection can be added here + } +} \ No newline at end of file diff --git a/samples/bing-search/python-sample.py b/samples/bing-search/python-sample.py new file mode 100644 index 00000000..022c4932 --- /dev/null +++ b/samples/bing-search/python-sample.py @@ -0,0 +1,81 @@ +import os + +from azure.ai.projects.models import bing_grounding, ToolSet +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential + +from azure.ai.ml.entities import WorkspaceConnection +from azure.ai.ml.entities import UsernamePasswordConfiguration, ApiKeyConfiguration + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + + + +# Customer needs to create a connection to the Grounding with Bing Search resource + +connection_name = "bing_grounding_connection" + + + +target = “GROUNDING_WITH_BING_SEARCH_API” + +wps_connection = WorkspaceConnection( + name=connection_name, + type="custom", + target=target, + credentials=ApiKeyConfiguration(key="API_KEY"), + ) + ml_client.connections.create_or_update(workspace_connection=wps_connection) + +with project_client: + + # Create Grounding with Bing Search tool with resources + bing_grounding_tool = bing_grounding(connection_id=[connection id of Grounding with Bing Search resource]) + + # Create agent with SharePoint tool and process agent run + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-agent", + instructions="Hello, you are helpful agent and can search information from uploaded files", + tools=bing_grounding_tool.definitions, + tool_resources= bing_grounding_tool.resources, + ) + print(f"Created agent, agent ID: {agent.id}") + + # Create thread for communication + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + # Create message to thread + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" + ) + print(f"Created message, ID: {message.id}") + + # Create and process agent run in thread with tools + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") + + if run.status == “complete”: + +print(f"Run complete: {run.id}") + + +# Delete the agent when done +project_client.agents.delete_agent(agent.id) +print("Deleted agent") + +# Fetch and log all messages +messages = project_client.agents.list_messages(thread_id=thread.id) +print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/tools/code-interpreter.md b/samples/code-interpreter/csharp-sample.cs similarity index 50% rename from samples/tools/code-interpreter.md rename to samples/code-interpreter/csharp-sample.cs index ba03ffa5..e98cd7cb 100644 --- a/samples/tools/code-interpreter.md +++ b/samples/code-interpreter/csharp-sample.cs @@ -1,91 +1,3 @@ -# Code interpreter - -Code Interpreter allows the Agent to write and run Python code in a sandboxed execution environment. With Code Interpreter enabled, your Agent can run code iteratively to solve more challenging code, math, and data analysis problems. - -## Supported file types - -|File format|MIME Type| -|---|---| -|.c| text/x-c | -|.cpp|text/x-c++ | -|.csv|application/csv| -|.docx|application/vnd.openxmlformats-officedocument.wordprocessingml.document| -|.html|text/html| -|.java|text/x-java| -|.json|application/json| -|.md|text/markdown| -|.pdf|application/pdf| -|.php|text/x-php| -|.pptx|application/vnd.openxmlformats-officedocument.presentationml.presentation| -|.py|text/x-python| -|.py|text/x-script.python| -|.rb|text/x-ruby| -|.tex|text/x-tex| -|.txt|text/plain| -|.css|text/css| -|.jpeg|image/jpeg| -|.jpg|image/jpeg| -|.js|text/javascript| -|.gif|image/gif| -|.png|image/png| -|.tar|application/x-tar| -|.ts|application/typescript| -|.xlsx|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet| -|.xml|application/xml or "text/xml"| -|.zip|application/zip| - -## Example - -Use the following examples to use Code interpreter with file attachment. - -> [!NOTE] -> You can find [C# code below](#c). - -### Python - -```python -from openai import AzureOpenAI - -client = AzureOpenAI( - api_key=os.getenv("AZURE_OPENAI_API_KEY"), - api_version="2024-05-01-preview", - azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") - ) - -# Upload a file with an "assistants" purpose -file = client.files.create( - file=open("speech.py", "rb"), - purpose='assistants' -) - -# Create an assistant using the file ID -assistant = client.beta.assistants.create( - instructions="You are an AI assistant that can write code to help answer math questions.", - model="gpt-4-1106-preview", - tools=[{"type": "code_interpreter"}], - tool_resources={"code interpreter":{"file_ids":[file.id]}} -) - -client = AzureOpenAI( - api_key=os.getenv("AZURE_OPENAI_API_KEY"), - api_version="2024-05-01-preview", - azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") - ) - -thread = client.beta.threads.create( - messages=[ - { - "role": "user", - "content": "I need to solve the equation `3x + 11 = 14`. Can you help me?", - "file_ids": ["file.id"] # file id will look like: "assistant-R9uhPxvRKGH3m0x5zBOhMjd2" - } - ] -) -``` - -## C# - -```csharp using System; using System.IO; using System.Net.Http; @@ -145,9 +57,4 @@ static async Task Main(string[] args) var threadResponseBody = await threadResponse.Content.ReadAsStringAsync(); Console.WriteLine(threadResponseBody); } -} -``` - -# Samples - -* [Math tutor](https://github.com/openai/openai-cookbook/blob/main/examples/data/oai_docs/tool-code-interpreter.txt) \ No newline at end of file +} \ No newline at end of file diff --git a/samples/code-interpreter/python-sample.py b/samples/code-interpreter/python-sample.py new file mode 100644 index 00000000..0000a89d --- /dev/null +++ b/samples/code-interpreter/python-sample.py @@ -0,0 +1,37 @@ +from openai import AzureOpenAI + +client = AzureOpenAI( + api_key=os.getenv("AZURE_OPENAI_API_KEY"), + api_version="2024-05-01-preview", + azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") + ) + +# Upload a file with an "assistants" purpose +file = client.files.create( + file=open("speech.py", "rb"), + purpose='assistants' +) + +# Create an assistant using the file ID +assistant = client.beta.assistants.create( + instructions="You are an AI assistant that can write code to help answer math questions.", + model="gpt-4-1106-preview", + tools=[{"type": "code_interpreter"}], + tool_resources={"code interpreter":{"file_ids":[file.id]}} +) + +client = AzureOpenAI( + api_key=os.getenv("AZURE_OPENAI_API_KEY"), + api_version="2024-05-01-preview", + azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") + ) + +thread = client.beta.threads.create( + messages=[ + { + "role": "user", + "content": "I need to solve the equation `3x + 11 = 14`. Can you help me?", + "file_ids": ["file.id"] # file id will look like: "assistant-R9uhPxvRKGH3m0x5zBOhMjd2" + } + ] +) \ No newline at end of file diff --git a/samples/code-interpreter/readme.md b/samples/code-interpreter/readme.md new file mode 100644 index 00000000..7ca0d2af --- /dev/null +++ b/samples/code-interpreter/readme.md @@ -0,0 +1,49 @@ +# Code interpreter + +Code Interpreter allows the Agent to write and run Python code in a sandboxed execution environment. With Code Interpreter enabled, your Agent can run code iteratively to solve more challenging code, math, and data analysis problems. + +## Supported file types + +|File format|MIME Type| +|---|---| +|.c| text/x-c | +|.cpp|text/x-c++ | +|.csv|application/csv| +|.docx|application/vnd.openxmlformats-officedocument.wordprocessingml.document| +|.html|text/html| +|.java|text/x-java| +|.json|application/json| +|.md|text/markdown| +|.pdf|application/pdf| +|.php|text/x-php| +|.pptx|application/vnd.openxmlformats-officedocument.presentationml.presentation| +|.py|text/x-python| +|.py|text/x-script.python| +|.rb|text/x-ruby| +|.tex|text/x-tex| +|.txt|text/plain| +|.css|text/css| +|.jpeg|image/jpeg| +|.jpg|image/jpeg| +|.js|text/javascript| +|.gif|image/gif| +|.png|image/png| +|.tar|application/x-tar| +|.ts|application/typescript| +|.xlsx|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet| +|.xml|application/xml or "text/xml"| +|.zip|application/zip| + +## Examples + +Run the code samples below and view the output. + +>[!NOTE] +> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. + +* [Python](./python-sample.py) +* [C#](./csharp-sample.cs) + +# Additional samples + +* [Math tutor](https://github.com/openai/openai-cookbook/blob/main/examples/data/oai_docs/tool-code-interpreter.txt) \ No newline at end of file diff --git a/samples/tools/file-search.md b/samples/file-search/file-search.md similarity index 100% rename from samples/tools/file-search.md rename to samples/file-search/file-search.md diff --git a/samples/tools/function-calling.md b/samples/function-calling/function-calling.md similarity index 100% rename from samples/tools/function-calling.md rename to samples/function-calling/function-calling.md diff --git a/samples/tools/openapi-30-functions.md b/samples/openapi/openapi-30-functions.md similarity index 100% rename from samples/tools/openapi-30-functions.md rename to samples/openapi/openapi-30-functions.md diff --git a/samples/tools/bing-search.md b/samples/tools/bing-search.md deleted file mode 100644 index 31e9c396..00000000 --- a/samples/tools/bing-search.md +++ /dev/null @@ -1,154 +0,0 @@ -# Grounding with Bing Search - -Grounding with Bing Search allows your Azure Agents to incorporate real-time public web data when generating responses. To start with, you need to create a Grounding with Bing Search resource, then connect this resource to your Azure Agents. When a user sends a query, Azure Agents will decide if Grounding with Bing Search should be leveraged or not. If so, it will leverage Bing to search over public web data and return relevant chunks. Lastly, Azure Agents will use returned chunks to generate a response. - -Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Bing - -Please note that developers and end users don’t have access to raw chunks returned by Grounding with Bing Search. Grounding with Bing Search is a free service during private preview. - -## Setup - -Create a Bing Search resource. If you don’t have one, you can use the Azure CLI or Azure portal to create one: - -```console -az cognitiveservices account create \ - - --name bing-grounding-resource \ - --resource-group \ - --kind Bing.Grounding \ - --sku G1 \ - --location Global \ - --yes -``` - -## Example - -> [!NOTE] -> You can find [C# code below](#c). - -### Python - -```python -import os - -from azure.ai.projects.models import bing_grounding, ToolSet -from azure.ai.projects import AIProjectClient -from azure.identity import DefaultAzureCredential - -from azure.ai.ml.entities import WorkspaceConnection -from azure.ai.ml.entities import UsernamePasswordConfiguration, ApiKeyConfiguration - - -# Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# Customer needs to login to Azure subscription via Azure CLI and set the environment variables - -project_client = AIProjectClient.from_connection_string( - credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] -) - - - -# Customer needs to create a connection to the Grounding with Bing Search resource - -connection_name = "bing_grounding_connection" - - - -target = “GROUNDING_WITH_BING_SEARCH_API” - -wps_connection = WorkspaceConnection( - name=connection_name, - type="custom", - target=target, - credentials=ApiKeyConfiguration(key="API_KEY"), - ) - ml_client.connections.create_or_update(workspace_connection=wps_connection) - -with project_client: - - # Create Grounding with Bing Search tool with resources - bing_grounding_tool = bing_grounding(connection_id=[connection id of Grounding with Bing Search resource]) - - # Create agent with SharePoint tool and process agent run - agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", - name="my-agent", - instructions="Hello, you are helpful agent and can search information from uploaded files", - tools=bing_grounding_tool.definitions, - tool_resources= bing_grounding_tool.resources, - ) - print(f"Created agent, agent ID: {agent.id}") - - # Create thread for communication - thread = project_client.agents.create_thread() - print(f"Created thread, ID: {thread.id}") - - # Create message to thread - message = project_client.agents.create_message( - thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" - ) - print(f"Created message, ID: {message.id}") - - # Create and process agent run in thread with tools - run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Run finished with status: {run.status}") - - if run.status == "failed": - # Check if you got "Rate limit is exceeded.", then you want to get more quota - print(f"Run failed: {run.last_error}") - - if run.status == “complete”: - -print(f"Run complete: {run.id}") - - - # Delete the agent when done - project_client.agents.delete_agent(agent.id) - print("Deleted agent") - - # Fetch and log all messages - messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") -``` - -## C# - -```csharp -using System; -using Azure.Identity; -using Azure.AI.Projects; -using Azure.AI.Projects.Models; -using Azure.AI.ML.Entities; - -class Program -{ - static void Main(string[] args) - { - // Ensure the environment variable is set - string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); - if (string.IsNullOrEmpty(connectionString)) - { - Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); - return; - } - - // Create an Azure AI Client from a connection string - var credential = new DefaultAzureCredential(); - var projectClient = AIProjectClient.FromConnectionString(credential, connectionString); - - // Create a connection to the Grounding with Bing Search resource - string connectionName = "bing_grounding_connection"; - string target = "GROUNDING_WITH_BING_SEARCH_API"; - - var wpsConnection = new WorkspaceConnection - { - Name = connectionName, - Type = "custom", - Target = target - }; - - // Additional code to use the projectClient and wpsConnection can be added here - } -} -``` From e5c83888bb45c900495803117ef183fea65921f3 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 12:43:42 -0700 Subject: [PATCH 016/180] file rename --- samples/bing-search/{bing-search.md => readme-bing-search.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename samples/bing-search/{bing-search.md => readme-bing-search.md} (100%) diff --git a/samples/bing-search/bing-search.md b/samples/bing-search/readme-bing-search.md similarity index 100% rename from samples/bing-search/bing-search.md rename to samples/bing-search/readme-bing-search.md From 188bfb64a46e78dbd1b8f528b3bc658e7b73b425 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 13:43:05 -0700 Subject: [PATCH 017/180] new files --- .../{readme-bing-search.md => readme.md} | 5 +- samples/code-interpreter/readme.md | 32 +- .../{file-search.md => csharp-sample.cs} | 94 +- samples/file-search/python-sample.py | 65 + samples/file-search/readme.md | 19 + .../{function-calling.md => csharp-sample.cs} | 105 +- samples/function-calling/python-sample.py | 83 ++ samples/function-calling/readme.md | 22 + samples/openapi/csharp-sample.cs | 51 + samples/openapi/function-example.json | 1239 +++++++++++++++++ ...enapi-30-functions.md => python-sample.py} | 106 +- samples/openapi/readme.md | 42 + 12 files changed, 1545 insertions(+), 318 deletions(-) rename samples/bing-search/{readme-bing-search.md => readme.md} (81%) rename samples/file-search/{file-search.md => csharp-sample.cs} (54%) create mode 100644 samples/file-search/python-sample.py create mode 100644 samples/file-search/readme.md rename samples/function-calling/{function-calling.md => csharp-sample.cs} (68%) create mode 100644 samples/function-calling/python-sample.py create mode 100644 samples/function-calling/readme.md create mode 100644 samples/openapi/csharp-sample.cs create mode 100644 samples/openapi/function-example.json rename samples/openapi/{openapi-30-functions.md => python-sample.py} (51%) create mode 100644 samples/openapi/readme.md diff --git a/samples/bing-search/readme-bing-search.md b/samples/bing-search/readme.md similarity index 81% rename from samples/bing-search/readme-bing-search.md rename to samples/bing-search/readme.md index 0ffece50..5ef4cada 100644 --- a/samples/bing-search/readme-bing-search.md +++ b/samples/bing-search/readme.md @@ -8,9 +8,12 @@ Please note that developers and end users don’t have access to raw chunks retu ## Setup +> [!IMPORTANT] +> Grounding with Bing Search has a separate Terms of Use agreement you need to agree to in order to move forward. Please use this form[pending link] to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. + 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). -1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI or Azure portal to create one: +1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI or Azure portal to create one[pending Bing update]: ```console az cognitiveservices account create \ diff --git a/samples/code-interpreter/readme.md b/samples/code-interpreter/readme.md index 7ca0d2af..73652fd1 100644 --- a/samples/code-interpreter/readme.md +++ b/samples/code-interpreter/readme.md @@ -2,6 +2,22 @@ Code Interpreter allows the Agent to write and run Python code in a sandboxed execution environment. With Code Interpreter enabled, your Agent can run code iteratively to solve more challenging code, math, and data analysis problems. + +## Examples + +Run the code samples below and view the output. + +>[!NOTE] +> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. + +* [Python](./python-sample.py) +* [C#](./csharp-sample.cs) + +# Additional samples + +* [Math tutor](https://github.com/openai/openai-cookbook/blob/main/examples/data/oai_docs/tool-code-interpreter.txt) + + ## Supported file types |File format|MIME Type| @@ -32,18 +48,4 @@ Code Interpreter allows the Agent to write and run Python code in a sandboxed ex |.ts|application/typescript| |.xlsx|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet| |.xml|application/xml or "text/xml"| -|.zip|application/zip| - -## Examples - -Run the code samples below and view the output. - ->[!NOTE] -> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. - -* [Python](./python-sample.py) -* [C#](./csharp-sample.cs) - -# Additional samples - -* [Math tutor](https://github.com/openai/openai-cookbook/blob/main/examples/data/oai_docs/tool-code-interpreter.txt) \ No newline at end of file +|.zip|application/zip| \ No newline at end of file diff --git a/samples/file-search/file-search.md b/samples/file-search/csharp-sample.cs similarity index 54% rename from samples/file-search/file-search.md rename to samples/file-search/csharp-sample.cs index 5ad542fa..851e9a6d 100644 --- a/samples/file-search/file-search.md +++ b/samples/file-search/csharp-sample.cs @@ -1,90 +1,3 @@ -# File Search - -File Search augments the Agent with knowledge from outside its model, such as proprietary product information or documents provided by your users. OpenAI automatically parses and chunks your documents, creates and stores the embeddings, and use both vector and keyword search to retrieve relevant content to answer user queries. - -## Setup - -To access your files, the file search tool uses the vector store object. Upload your files and create a vector store to contain them. Once the vector store is created, you should poll its status until all files are out of the in_progress state to ensure that all content has finished processing. The SDK provides helpers for uploading and polling. - -## Example - -> [!NOTE] -> You can find [C# code below](#c). - -### Python - -```python -import os -from azure.ai.projects import AIProjectClient -from azure.ai.projects.models._patch import FileSearchTool -from azure.identity import DefaultAzureCredential - - -# Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# Customer needs to login to Azure subscription via Azure CLI and set the environment variables - -project_client = AIProjectClient.from_connection_string( - credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] -) - - -with project_client: - - openai_file = project_client.agents.upload_file_and_poll(file_path="product_info_1.md", purpose="assistants") - print(f"Uploaded file, file ID: {openai_file.id}") - - openai_vectorstore = project_client.agents.create_vector_store_and_poll(file_ids=[openai_file.id], name="my_vectorstore") - print(f"Created vector store, vector store ID: {openai_vectorstore.id}") - - # Create file search tool with resources - file_search = FileSearchTool(vector_store_ids=[openai_vectorstore.id]) - - # Create agent with file search tool and process the agent run - agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", - name="my-agent", - instructions="Hello, you are helpful agent and can search information from uploaded files", - tools=file_search.definitions, - tool_resources=file_search.resources, - ) - print(f"Created agent, agent ID: {agent.id}") - - # Create thread for communication - thread = project_client.agents.create_thread() - print(f"Created thread, ID: {thread.id}") - - # Create message to thread - message = project_client.agents.create_message( - thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" - ) - print(f"Created message, ID: {message.id}") - - # Create and process agent run in thread with tools - run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Run finished with status: {run.status}") - - if run.status == "failed": - # Check if you got "Rate limit is exceeded.", then you want to get more quota - print(f"Run failed: {run.last_error}") - - # Delete the file when done - project_client.agents.delete_vector_store(openai_vectorstore.id) - print("Deleted vector store") - - # Delete the agent when done - project_client.agents.delete_agent(agent.id) - print("Deleted agent") - - # Fetch and log all messages - messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") -``` - - -### C# - -```csharp using System; using System.Collections.Generic; using System.IO; @@ -180,9 +93,4 @@ public async Task FilesSearchExample() } } } -} -``` - -## Samples - -* [Python Quart app](https://github.com/Azure-Samples/azureai-assistant-tool/tree/main/samples/FileSearch) \ No newline at end of file +} \ No newline at end of file diff --git a/samples/file-search/python-sample.py b/samples/file-search/python-sample.py new file mode 100644 index 00000000..c982b40b --- /dev/null +++ b/samples/file-search/python-sample.py @@ -0,0 +1,65 @@ +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models._patch import FileSearchTool +from azure.identity import DefaultAzureCredential + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + + +with project_client: + + openai_file = project_client.agents.upload_file_and_poll(file_path="product_info_1.md", purpose="assistants") + print(f"Uploaded file, file ID: {openai_file.id}") + + openai_vectorstore = project_client.agents.create_vector_store_and_poll(file_ids=[openai_file.id], name="my_vectorstore") + print(f"Created vector store, vector store ID: {openai_vectorstore.id}") + + # Create file search tool with resources + file_search = FileSearchTool(vector_store_ids=[openai_vectorstore.id]) + + # Create agent with file search tool and process the agent run + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-agent", + instructions="Hello, you are helpful agent and can search information from uploaded files", + tools=file_search.definitions, + tool_resources=file_search.resources, + ) + print(f"Created agent, agent ID: {agent.id}") + + # Create thread for communication + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + # Create message to thread + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" + ) + print(f"Created message, ID: {message.id}") + + # Create and process agent run in thread with tools + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") + + # Delete the file when done + project_client.agents.delete_vector_store(openai_vectorstore.id) + print("Deleted vector store") + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md new file mode 100644 index 00000000..69ad2961 --- /dev/null +++ b/samples/file-search/readme.md @@ -0,0 +1,19 @@ +# File Search + +File Search augments the Agent with knowledge from outside its model, such as proprietary product information or documents provided by your users. OpenAI automatically parses and chunks your documents, creates and stores the embeddings, and use both vector and keyword search to retrieve relevant content to answer user queries. + +To access your files, the file search tool uses the vector store object. Upload your files and create a vector store to contain them. Once the vector store is created, you should poll its status until all files are out of the in_progress state to ensure that all content has finished processing. The SDK provides helpers for uploading and polling. + +## Examples + +Run the code samples below and view the output. + +>[!NOTE] +> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. + +* [Python](./python-sample.py) +* [C#](./csharp-sample.cs) + +## Additional samples + +* [Python Quart app](https://github.com/Azure-Samples/azureai-assistant-tool/tree/main/samples/FileSearch) \ No newline at end of file diff --git a/samples/function-calling/function-calling.md b/samples/function-calling/csharp-sample.cs similarity index 68% rename from samples/function-calling/function-calling.md rename to samples/function-calling/csharp-sample.cs index af998fbe..fe4ad03b 100644 --- a/samples/function-calling/function-calling.md +++ b/samples/function-calling/csharp-sample.cs @@ -1,101 +1,3 @@ -# Function Calling - -Azure AI Agents Service supports function calling, which allows you to describe the structure of functions to an Agent and then return the functions that need to be called along with their arguments. - -## Example - -> [!NOTE] -> You can find [C# code below](#c). - -```python -import os, time -from azure.ai.projects import AIProjectClient -from azure.identity import DefaultAzureCredential -from azure.ai.projects.models import FunctionTool, SubmitToolOutputsAction, RequiredFunctionToolCall -from user_functions import user_functions - - -# Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# Customer needs to login to Azure subscription via Azure CLI and set the environment variables - -project_client = AIProjectClient.from_connection_string( - credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] -) - -# Initialize function tool with user functions -functions = FunctionTool(functions=user_functions) - -with project_client: - # Create an agent and run user's request with function calls - agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", - name="my-agent", - instructions="You are a helpful agent", - tools=functions.definitions, - ) - print(f"Created agent, ID: {agent.id}") - - thread = project_client.agents.create_thread() - print(f"Created thread, ID: {thread.id}") - - message = project_client.agents.create_message( - thread_id=thread.id, - role="user", - content="Hello, send an email with the datetime and weather information in New York?", - ) - print(f"Created message, ID: {message.id}") - - run = project_client.agents.create_run(thread_id=thread.id, agent_id=agent.id) - print(f"Created run, ID: {run.id}") - - while run.status in ["queued", "in_progress", "requires_action"]: - time.sleep(1) - run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) - - if run.status == "requires_action" and isinstance(run.required_action, SubmitToolOutputsAction): - tool_calls = run.required_action.submit_tool_outputs.tool_calls - if not tool_calls: - print("No tool calls provided - cancelling run") - project_client.agents.cancel_run(thread_id=thread.id, run_id=run.id) - break - - tool_outputs = [] - for tool_call in tool_calls: - if isinstance(tool_call, RequiredFunctionToolCall): - try: - output = functions.execute(tool_call) - tool_outputs.append( - { - "tool_call_id": tool_call.id, - "output": output, - } - ) - except Exception as e: - print(f"Error executing tool_call {tool_call.id}: {e}") - - print(f"Tool outputs: {tool_outputs}") - if tool_outputs: - project_client.agents.submit_tool_outputs_to_run( - thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs - ) - - print(f"Current run status: {run.status}") - - print(f"Run completed with status: {run.status}") - - # Delete the agent when done - project_client.agents.delete_agent(agent.id) - print("Deleted agent") - - # Fetch and log all messages - messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") -``` - -## C# - -```csharp using System; using System.Collections.Generic; using System.Text.Json; @@ -271,9 +173,4 @@ ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall) } } } -} -``` - -# Samples - -Get the latest stock price using function calling with Yfinance ([shown in Personal Finance Assistant](https://github.com/Azure-Samples/azureai-samples/blob/main/scenarios/Assistants/api-in-a-box/personal_finance/assistant-personal_finance.ipynb)) +} \ No newline at end of file diff --git a/samples/function-calling/python-sample.py b/samples/function-calling/python-sample.py new file mode 100644 index 00000000..30c5d0a2 --- /dev/null +++ b/samples/function-calling/python-sample.py @@ -0,0 +1,83 @@ +import os, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import FunctionTool, SubmitToolOutputsAction, RequiredFunctionToolCall +from user_functions import user_functions + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +# Initialize function tool with user functions +functions = FunctionTool(functions=user_functions) + +with project_client: + # Create an agent and run user's request with function calls + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-agent", + instructions="You are a helpful agent", + tools=functions.definitions, + ) + print(f"Created agent, ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Hello, send an email with the datetime and weather information in New York?", + ) + print(f"Created message, ID: {message.id}") + + run = project_client.agents.create_run(thread_id=thread.id, agent_id=agent.id) + print(f"Created run, ID: {run.id}") + + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) + run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + if run.status == "requires_action" and isinstance(run.required_action, SubmitToolOutputsAction): + tool_calls = run.required_action.submit_tool_outputs.tool_calls + if not tool_calls: + print("No tool calls provided - cancelling run") + project_client.agents.cancel_run(thread_id=thread.id, run_id=run.id) + break + + tool_outputs = [] + for tool_call in tool_calls: + if isinstance(tool_call, RequiredFunctionToolCall): + try: + output = functions.execute(tool_call) + tool_outputs.append( + { + "tool_call_id": tool_call.id, + "output": output, + } + ) + except Exception as e: + print(f"Error executing tool_call {tool_call.id}: {e}") + + print(f"Tool outputs: {tool_outputs}") + if tool_outputs: + project_client.agents.submit_tool_outputs_to_run( + thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs + ) + + print(f"Current run status: {run.status}") + + print(f"Run completed with status: {run.status}") + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/function-calling/readme.md b/samples/function-calling/readme.md new file mode 100644 index 00000000..f29b6d2c --- /dev/null +++ b/samples/function-calling/readme.md @@ -0,0 +1,22 @@ +# Function Calling + +Azure AI Agents Service supports function calling, which allows you to describe the structure of functions to an Agent and then return the functions that need to be called along with their arguments. + +## Setup + + + +## Examples + +Run the code samples below and view the output. + +>[!NOTE] +> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. + +* [Python](./python-sample.py) +* [C#](./csharp-sample.cs) + + +# Additional samples + +Get the latest stock price using function calling with Yfinance ([shown in Personal Finance Assistant](https://github.com/Azure-Samples/azureai-samples/blob/main/scenarios/Assistants/api-in-a-box/personal_finance/assistant-personal_finance.ipynb)) diff --git a/samples/openapi/csharp-sample.cs b/samples/openapi/csharp-sample.cs new file mode 100644 index 00000000..aa099d39 --- /dev/null +++ b/samples/openapi/csharp-sample.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading.Tasks; +using Azure.Identity; +using Azure.AI.Projects; +using Azure.AI.Projects.Models; + +class Program +{ + static async Task Main(string[] args) + { + // Ensure the environment variable is set + string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); + if (string.IsNullOrEmpty(connectionString)) + { + Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); + return; + } + + // Create an Azure AI Client from a connection string + var credential = new DefaultAzureCredential(); + var projectClient = new AIProjectClient(connectionString, credential); + + // Create an agent and run user's request with function calls + var agent = await projectClient.Agents.CreateAgentAsync(new CreateAgentOptions + { + Model = "gpt-4-1106-preview", + Name = "my-agent", + Instructions = "You are a helpful agent", + Tools = new[] + { + new Tool + { + Type = "openapi", + OpenApi = new OpenApiTool + { + Name = "mytool", + Description = "My tool", + Spec = new OpenApiSpec + { + OpenApi = "3.0.0", + // + } + } + } + } + }); + + // Use the agent as needed + // ... + } +} \ No newline at end of file diff --git a/samples/openapi/function-example.json b/samples/openapi/function-example.json new file mode 100644 index 00000000..0ac5aa72 --- /dev/null +++ b/samples/openapi/function-example.json @@ -0,0 +1,1239 @@ +{ + "openapi": "3.0.2", + "servers": [ + { + "url": "/v3" + } + ], + "info": { + "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)", + "version": "1.0.20-SNAPSHOT", + "title": "Swagger Petstore - OpenAPI 3.0", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + }, + { + "name": "user", + "description": "Operations about user" + } + ], + "paths": { + "/pet": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "Add a new pet to the store", + "operationId": "addPet", + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "requestBody": { + "description": "Create a new pet in the store", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePet", + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "requestBody": { + "description": "Update an existent pet in the store", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": false, + "explode": true, + "schema": { + "type": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "default": "available" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": false, + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + }, + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "name", + "in": "query", + "description": "Name of pet that needs to be updated", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "Status of pet that needs to be updated", + "schema": { + "type": "string" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "parameters": [ + { + "name": "api_key", + "in": "header", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "additionalMetadata", + "in": "query", + "description": "Additional Metadata", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "requestBody": { + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "x-swagger-router-controller": "OrderController", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "Place a new order in the store", + "operationId": "placeOrder", + "x-swagger-router-controller": "OrderController", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "x-swagger-router-controller": "OrderController", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.", + "operationId": "getOrderById", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of order that needs to be fetched", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "x-swagger-router-controller": "OrderController", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "responses": { + "default": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + }, + "description": "Created user object" + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "Creates list of users with given input array", + "x-swagger-router-controller": "UserController", + "operationId": "createUsersWithListInput", + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "default": { + "description": "successful operation" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "headers": { + "X-Rate-Limit": { + "description": "calls per hour allowed by the user", + "schema": { + "type": "integer", + "format": "int32" + } + }, + "X-Expires-After": { + "description": "date in UTC when token expires", + "schema": { + "type": "string", + "format": "date-time" + } + } + }, + "content": { + "application/xml": { + "schema": { + "type": "string" + } + }, + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Update user", + "x-swagger-router-controller": "UserController", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that needs to be updated", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + }, + "requestBody": { + "description": "Update an existent user in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + }, + "components": { + "schemas": { + "Order": { + "x-swagger-router-model": "io.swagger.petstore.model.Order", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "petId": { + "type": "integer", + "format": "int64", + "example": 198772 + }, + "quantity": { + "type": "integer", + "format": "int32", + "example": 7 + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "enum": [ + "placed", + "approved", + "delivered" + ], + "example": "approved" + }, + "complete": { + "type": "boolean" + } + }, + "xml": { + "name": "order" + }, + "type": "object" + }, + "Customer": { + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 100000 + }, + "username": { + "type": "string", + "example": "fehguy" + }, + "address": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Address" + }, + "xml": { + "wrapped": true, + "name": "addresses" + } + } + }, + "xml": { + "name": "customer" + }, + "type": "object" + }, + "Address": { + "properties": { + "street": { + "type": "string", + "example": "437 Lytton" + }, + "city": { + "type": "string", + "example": "Palo Alto" + }, + "state": { + "type": "string", + "example": "CA" + }, + "zip": { + "type": "string", + "example": 94301 + } + }, + "xml": { + "name": "address" + }, + "type": "object" + }, + "Category": { + "x-swagger-router-model": "io.swagger.petstore.model.Category", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + }, + "type": "object" + }, + "User": { + "x-swagger-router-model": "io.swagger.petstore.model.User", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "username": { + "type": "string", + "example": "theUser" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "lastName": { + "type": "string", + "example": "James" + }, + "email": { + "type": "string", + "example": "john@email.com" + }, + "password": { + "type": "string", + "example": 12345 + }, + "phone": { + "type": "string", + "example": 12345 + }, + "userStatus": { + "type": "integer", + "format": "int32", + "example": 1, + "description": "User Status" + } + }, + "xml": { + "name": "user" + }, + "type": "object" + }, + "Tag": { + "x-swagger-router-model": "io.swagger.petstore.model.Tag", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + }, + "type": "object" + }, + "Pet": { + "x-swagger-router-model": "io.swagger.petstore.model.Pet", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Tag", + "xml": { + "name": "tag" + } + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "pet" + }, + "type": "object" + }, + "ApiResponse": { + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "xml": { + "name": "##default" + }, + "type": "object" + } + }, + "requestBodies": { + "Pet": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "description": "Pet object that needs to be added to the store" + }, + "UserArray": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "description": "List of user object" + } + }, + "securitySchemes": { + "petstore_auth": { + "type": "oauth2", + "flows": { + "implicit": { + "authorizationUrl": "https://petstore.swagger.io/oauth/authorize", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + } + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + } + } + } \ No newline at end of file diff --git a/samples/openapi/openapi-30-functions.md b/samples/openapi/python-sample.py similarity index 51% rename from samples/openapi/openapi-30-functions.md rename to samples/openapi/python-sample.py index fe08908a..d1d272d8 100644 --- a/samples/openapi/openapi-30-functions.md +++ b/samples/openapi/python-sample.py @@ -1,34 +1,3 @@ -# Use OpenAPI 3.0 Specified Tools - -The Custom Tools feature allows developers to describe custom tools in the Agent API using an [OpenAPI schema](https://www.openapis.org/), enabling the model to intelligently call these functions based on user input. You can use any API spec that is written according to the OpenAPI 3.0 schema. - -## Setup - -First you need a tool defined using the OpenAPI Schema, for example: - -```yml -openapi: 3.0.1  -info:  -  title: Weather Service API  -  description: This is a sample API for retrieving weather information.  -  version: 1.0.0  -servers:  -  - url: https://api.example.com/weather  -    description: Main API Server  -paths:  -  /current:  -    get:  -      summary: Get current weather  -      operationId: getCurrentWeather  -... -``` - -## Example - -> [!NOTE] -> You can find [C# code below](#c). - -```python import os, time from azure.ai.projects import AIProjectClient from azure.identity import DefaultAzureCredential @@ -115,77 +84,4 @@ # Fetch and log all messages messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") -``` - - -## C# - - -```csharp -using System; -using System.Threading.Tasks; -using Azure.Identity; -using Azure.AI.Projects; -using Azure.AI.Projects.Models; - -class Program -{ - static async Task Main(string[] args) - { - // Ensure the environment variable is set - string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); - if (string.IsNullOrEmpty(connectionString)) - { - Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); - return; - } - - // Create an Azure AI Client from a connection string - var credential = new DefaultAzureCredential(); - var projectClient = new AIProjectClient(connectionString, credential); - - // Create an agent and run user's request with function calls - var agent = await projectClient.Agents.CreateAgentAsync(new CreateAgentOptions - { - Model = "gpt-4-1106-preview", - Name = "my-agent", - Instructions = "You are a helpful agent", - Tools = new[] - { - new Tool - { - Type = "openapi", - OpenApi = new OpenApiTool - { - Name = "mytool", - Description = "My tool", - Spec = new OpenApiSpec - { - OpenApi = "3.0.0", - // - } - } - } - } - }); - - // Use the agent as needed - // ... - } -} -``` - - - -Authentication can be either anonymous (no authentication) or “managed_identity” - -"auth": { "type": "managed_identity", "security_scheme": { "audience": "https://cognitiveservices.azure.com/" }} - - or “connection” - -"auth": { "type": "connection", "security_scheme": { "connection_id": "1234-56789" }} - -anonymous is not authentication, managed_identity is authenticating with various Azure Services using RBAC, connection is using 3rd party APIs with API keys and Custom Keys Connections in azure AI studio. - -Note: Connection authentication requires an enterprise setup. \ No newline at end of file + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/openapi/readme.md b/samples/openapi/readme.md new file mode 100644 index 00000000..917110f8 --- /dev/null +++ b/samples/openapi/readme.md @@ -0,0 +1,42 @@ +# Use OpenAPI 3.0 Specified Tools + +The Custom Tools feature allows developers to describe custom tools in the Agent API using an [OpenAPI schema](https://www.openapis.org/), enabling the model to intelligently call these functions based on user input. You can use any API spec that is written according to the OpenAPI 3.0 schema. + +## Setup + +You need a function defined using the OpenAPI Schema. See the [example function](./function-example.json) for details. It will look something like this: + +```yml +openapi: 3.0.1  +info:  +  title: Weather Service API  +  description: This is a sample API for retrieving weather information.  +  version: 1.0.0  +servers:  +  - url: https://api.example.com/weather  +    description: Main API Server  +paths:  +  /current:  +    get:  +      summary: Get current weather  +      operationId: getCurrentWeather  +... +``` + + +Authentication can be either `anonymous` (no authentication) or `managed_identity`: + +`"auth": { "type": "managed_identity", "security_scheme": { "audience": "https://cognitiveservices.azure.com/" }}` + +`Anonymous` is not authentication, `managed_identity` is authenticating with various Azure Services using RBAC. + +## Examples + +Run the code samples below and view the output. + +>[!NOTE] +> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. + +* [Python](./python-sample.py) +* [C#](./csharp-sample.cs) + From 035189934004f3b86f20453ea03ac0ea9d6a101d Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 15:10:46 -0700 Subject: [PATCH 018/180] updating quickstart --- quickstart.md | 207 +++++++++++++++++--------------------------------- 1 file changed, 69 insertions(+), 138 deletions(-) diff --git a/quickstart.md b/quickstart.md index c7e6c332..aaa11b4c 100644 --- a/quickstart.md +++ b/quickstart.md @@ -68,24 +68,6 @@ Follow these steps to set up your hub and project: Save the id that gets output, you’ll need it later. It will look similar to: `https://eastus.api.cognitive.microsoft.com/ai_services_resource_id: /subscriptions/1234-5678-abcd-9fc6-62780b3d3e05/resourceGroups/my-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource` -1. Create a Bing grounding resource. - - ```console - az cognitiveservices account create \ - - --name bing-grounding-resource \ - - --resource-group \ - - --kind Bing.Grounding \ - - --sku G1 \ - - --location Global \ - - --yes - ``` - 1. Create an Azure AI Hub. > [!NOTE] the following command auto creates a storage account, AML workspace and Key Vault. @@ -186,14 +168,12 @@ python -m pip install azure-ai-projects azure-identity Use the following code to create and run an agent. ```python -import os -from azure.ai.projects import AIProjectClient -from azure.ai.projects.models import Agent, MessageDeltaChunk, MessageDeltaTextContent, RunStep, ThreadMessage, ThreadRun -from azure.ai.projects.models import AgentEventHandler -from azure.ai.projects.operations import AgentsOperations -from azure.identity import DefaultAzureCredential -from azure.ai.projects.models import CodeInterpreterTool, bing_grounding, ToolSet -from typing import Any +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import CodeInterpreterTool +from azure.ai.projects.models import FilePurpose +from azure.identity import DefaultAzureCredential +from pathlib import Path # Create an Azure AI Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" @@ -203,81 +183,70 @@ project_client = AIProjectClient.from_connection_string( credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] ) -# When using CodeInterpreterTool with ToolSet in agent creation, the tool call events are handled inside the create_stream -# method and functions gets automatically called by default. -class MyEventHandler(AgentEventHandler): - - def on_message_delta(self, delta: "MessageDeltaChunk") -> None: - for content_part in delta.delta.content: - if isinstance(content_part, MessageDeltaTextContent): - text_value = content_part.text.value if content_part.text else "No text" - print(f"Text delta received: {text_value}") - - def on_thread_message(self, message: "ThreadMessage") -> None: - print(f"ThreadMessage created. ID: {message.id}, Status: {message.status}") - - def on_thread_run(self, run: "ThreadRun") -> None: - print(f"ThreadRun status: {run.status}") - - if run.status == "failed": - print(f"Run failed. Error: {run.last_error}") - - def on_run_step(self, step: "RunStep") -> None: - print(f"RunStep type: {step.type}, Status: {step.status}") - - def on_error(self, data: str) -> None: - print(f"An error occurred. Data: {data}") - - def on_done(self) -> None: - print("Stream completed.") - - def on_unhandled_event(self, event_type: str, event_data: Any) -> None: - print(f"Unhandled Event Type: {event_type}, Data: {event_data}") +with project_client: -# create a connection to the grounding with bing search resource -connection_name = "bing_grounding_connection" -target = "GROUNDING_WITH_BING_SEARCH_API" -wps_connection = WorkspaceConnection( - name=connection_name, - type="custom", - target=target, - credentials=ApiKeyConfiguration(key="API_KEY"), -) -ml_client.connections.create_or_update(workspace_connection=wps_connection) + # upload a file and wait for it to be processed + file = project_client.agents.upload_file_and_poll( + file_path="nifty_500_quarterly_results.csv", purpose=FilePurpose.AGENTS + ) + print(f"Uploaded file, file ID: {file.id}") -with project_client: - # Create Grounding with Bing Search tool with resources - bing_grounding_tool = bing_grounding(connection_id=[connection id of Grounding with Bing Search resource]) - code_interpreter = CodeInterpreterTool() - toolset = ToolSet() - toolset.add(code_interpreter) - toolset.add(bing_grounding_tool) + code_interpreter = CodeInterpreterTool(file_ids=[file.id]) + # notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent", toolset=toolset + model="gpt-4-1106-preview", + name="my-agent", + instructions="You are helpful agent", + tools=code_interpreter.definitions, + tool_resources=code_interpreter.resources, ) - print(f"Created agent, ID: {agent.id}") + print(f"Created agent, agent ID: {agent.id}") thread = project_client.agents.create_thread() - print(f"Created thread, thread ID {thread.id}") + print(f"Created thread, thread ID: {thread.id}") + # create a message message = project_client.agents.create_message( thread_id=thread.id, role="user", - content="Write code to calculate compound interest.", + content="Could you please create bar chart in TRANSPORTATION sector for the operating profit from the uploaded csv file and provide file to me?", ) - print(f"Created message, message ID {message.id}") + print(f"Created message, message ID: {message.id}") - with project_client.agents.create_stream( - thread_id=thread.id, agent_id=agent.id, event_handler=MyEventHandler() - ) as stream: - stream.until_done() + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") - project_client.agents.delete_agent(agent.id) - print("Deleted agent") + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") + + project_client.agents.delete_file(file.id) + print("Deleted file") - messages = project_client.agents.list_messages(thread_id=thread.id) + messages = project_client.agents.get_messages(thread_id=thread.id) print(f"Messages: {messages}") + + last_msg = messages.get_last_text_message_by_sender("assistant") + if last_msg: + print(f"Last Message: {last_msg.text.value}") + + for image_content in messages.image_contents: + print(f"Image File ID: {image_content.image_file.file_id}") + file_name = f"{image_content.image_file.file_id}_image_file.png" + project_client.agents.save_file(file_id=image_content.image_file.file_id, file_name=file_name) + print(f"Saved image file to: {Path.cwd() / file_name}") + + for file_path_annotation in messages.file_path_annotations: + print(f"File Paths:") + print(f"Type: {file_path_annotation.type}") + print(f"Text: {file_path_annotation.text}") + print(f"File ID: {file_path_annotation.file_path.file_id}") + print(f"Start Index: {file_path_annotation.start_index}") + print(f"End Index: {file_path_annotation.end_index}") + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") ``` ## C# @@ -294,85 +263,47 @@ Then use the following sample code to create an agent. using System; using System.Collections.Generic; using System.Threading.Tasks; -using Azure.Core; using Azure.Identity; using NUnit.Framework; namespace Azure.AI.Projects.Tests { - public partial class Sample_Agent_Basics + public class Sample_Agent_Streaming { - [Test] - public async Task BasicExample() + public async Task Streaming() { - #region Snippet:OverviewCreateClient var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); - #endregion - // Step 1: Create an agent with a model, agent name, and instructions to help it respond Response agentResponse = await client.CreateAgentAsync( model: "gpt-4-1106-preview", - name: "Math Tutor", - instructions: "You are a personal math tutor. Write and run code to answer math questions.", - tools: new List { new CodeInterpreterToolDefinition() } - ); + name: "My Friendly Test Agent", + instructions: "You politely help with math questions. Use the code interpreter tool when asked to visualize numbers.", + tools: new List { new CodeInterpreterToolDefinition() }); Agent agent = agentResponse.Value; - // The agent should now be listed - Response> agentListResponse = await client.GetAgentsAsync(); - - // Step 2: Create a thread, which will be used to store messages during conversation Response threadResponse = await client.CreateThreadAsync(); AgentThread thread = threadResponse.Value; - // Step 3: Add a message to a thread, starting a conversation with the agent Response messageResponse = await client.CreateMessageAsync( thread.Id, MessageRole.User, - "I need to solve the equation `3x + 11 = 14`. Can you help me?" - ); + "Hi, Agent! Draw a graph for a line with a slope of 4 and y-intercept of 9."); ThreadMessage message = messageResponse.Value; - // The message is now correlated with thread - // Sending a List messages will retrieve the message just added - Response> messagesListResponse = await client.GetMessagesAsync(thread.Id); - Assert.That(messagesListResponse.Value.Data[0].Id == message.Id); - - // Step 4: Run the agent, which will activate the agent to begin running based on the contents of the thread - Response runResponse = await client.CreateRunAsync( - thread.Id, - agent.Id, - additionalInstructions: "Please address the user as Jane Doe. The user has a premium account." - ); - ThreadRun run = runResponse.Value; - - // Wait for the agent to finish running before retrieving the response - do - { - await Task.Delay(TimeSpan.FromMilliseconds(500)); - runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); - } - while (runResponse.Value.Status == RunStatus.Queued || runResponse.Value.Status == RunStatus.InProgress); - - Response> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id); - IReadOnlyList messages = afterRunMessagesResponse.Value.Data; - - // Note: messages iterate from newest to oldest, with the messages[0] being the most recent - foreach (ThreadMessage threadMessage in messages) + await foreach (StreamingUpdate streamingUpdate in client.CreateRunStreamingAsync(thread.Id, agent.Id)) { - Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); - foreach (MessageContent contentItem in threadMessage.ContentItems) + if (streamingUpdate.UpdateKind == StreamingUpdateReason.RunCreated) { - if (contentItem is MessageTextContent textItem) - { - Console.Write(textItem.Text); - } - else if (contentItem is MessageImageFileContent imageFileItem) + Console.WriteLine($"--- Run started! ---"); + } + else if (streamingUpdate is MessageContentUpdate contentUpdate) + { + Console.Write(contentUpdate.Text); + if (contentUpdate.ImageFileId is not null) { - Console.Write($" Date: Thu, 31 Oct 2024 15:11:33 -0700 Subject: [PATCH 019/180] updating description --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index aaa11b4c..2af9faf1 100644 --- a/quickstart.md +++ b/quickstart.md @@ -152,7 +152,7 @@ TBD | Run | Activation of an agent to begin running based on the contents of Thread. The agent uses its configuration and Thread’s Messages to perform tasks by calling models and tools. As part of a Run, the agent appends Messages to the Thread. | Run Step | A detailed list of steps the agent took as part of a Run. An agent can call tools or create Messages during its run. Examining Run Steps allows you to understand how the agent is getting to its results. | -Use the following code to create an agent and send a message to it. This agent will have the code interpreter tool to enable your agent to perform advanced data analysis in a sandboxed environment and Bing search tool to real-time, web data grounding. +Use the following code to create an agent and send a message to it. This agent will have the code interpreter tool to enable your agent to perform advanced data analysis in a sandboxed environment. ## Python SDK From d6c6832108d2a28997106dede84a29d370d435cc Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 15:16:24 -0700 Subject: [PATCH 020/180] updating sample --- quickstart.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/quickstart.md b/quickstart.md index 2af9faf1..8c4fb2eb 100644 --- a/quickstart.md +++ b/quickstart.md @@ -185,19 +185,13 @@ project_client = AIProjectClient.from_connection_string( with project_client: - # upload a file and wait for it to be processed - file = project_client.agents.upload_file_and_poll( - file_path="nifty_500_quarterly_results.csv", purpose=FilePurpose.AGENTS - ) - print(f"Uploaded file, file ID: {file.id}") - code_interpreter = CodeInterpreterTool(file_ids=[file.id]) # notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment agent = project_client.agents.create_agent( model="gpt-4-1106-preview", name="my-agent", - instructions="You are helpful agent", + instructions="You are a helpful agent", tools=code_interpreter.definitions, tool_resources=code_interpreter.resources, ) @@ -210,7 +204,7 @@ with project_client: message = project_client.agents.create_message( thread_id=thread.id, role="user", - content="Could you please create bar chart in TRANSPORTATION sector for the operating profit from the uploaded csv file and provide file to me?", + content="Hi, Agent! Draw a graph for a line with a slope of 4 and y-intercept of 9.", ) print(f"Created message, message ID: {message.id}") @@ -221,9 +215,6 @@ with project_client: # Check if you got "Rate limit is exceeded.", then you want to get more quota print(f"Run failed: {run.last_error}") - project_client.agents.delete_file(file.id) - print("Deleted file") - messages = project_client.agents.get_messages(thread_id=thread.id) print(f"Messages: {messages}") From 1492813fe1e4a7ecc2aba44bc54d40e27397236e Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 31 Oct 2024 15:25:33 -0700 Subject: [PATCH 021/180] adding whl file --- .../azure_ai_project-1.0.0b1-py3-none-any.whl | Bin 0 -> 143723 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/azure_ai_project-1.0.0b1-py3-none-any.whl diff --git a/packages/azure_ai_project-1.0.0b1-py3-none-any.whl b/packages/azure_ai_project-1.0.0b1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..64c7a6e595ed615cf49360aa23d9f0119bc84bb2 GIT binary patch literal 143723 zcmZ^~Q?M{Ru(i2u+qP}nwr$(CZQHhOzT38K?>*nCshYoL>P&K%&Q)qv=jo)Ef;2D) z3IG5A1ORHbnkHx=72^yb000pP007Q^tA<{#PNwvRmh=uz_Ex6GF7*2PmUfmd`ucPZ zp0&z5)>{k+{_OAm9GmGTGk$o1JShlV&8^V3m@!B(M7g%MaU^n5SbuNa+Kt(E3+0zL ze17=uNp*r+rLw&|Ayi*UWNQh&>lYhptF9$iWCJpD2XfL)yJ~??$25@zwUY;BwuTmu z0_TZw6_0q|y3#Cos5mh~K??-isPe{K;o>8d5aj@yFuZZs_9=i9n*gb#7RK;voSWi{ z7IK8k774KpQ+3@89NrnjWzey#jW=vwAo57M0Y(xvkupXSu+ z`Aa6;FDD*Q7R%Qgu=2Yv`3FNl`USwo;rvcwHfIlIVfk-eT4p&uGpCl1=nDUj3Q+!2 z!JNa8(kA$S3cvyY!2VxVU~FS)YUlDlBEZnK-{N@e75D=#cggV1|S9r0Ck5F|bF6xlVyTofQhR0vuZ#-cpl(*W{> zq^x{I0ZGIrz^}8raTBov$O`pI2syzjL-^)TkRaknHyH(;gn`LBvNF%WI#438o&W?D zqL1O3BHve1j)3 zCY@qmdLoU&TjpZxAoHWB-Bn*lebc=>1DGX`%T^R$&PyxQ{CWC5lVCo@az&ZHvZR3*j!Zx(^Y% z2m~9Jn9@|ymk?J;l%F-tXj$8e!M4M32X|`>1oO|eG+>o8+E6}LdU4QKCMpqPVFZfm zJWe1FEvK-1g0?KKJqpb$X?udov`5kvjjDxHfs{))e0#_Cz9=R7<2x43G|UrxBS);o zAaQrYbg{0dn^@;r5h`#sfnm72E4P+9El+HZ@X7u=F#(5-prEW>fzsY_O|(auQ-Mt? zQ#W{3@(3bTDDi=~>>N_$Dgx*JQ~gARR3lzce=}_Q1Yi9uBpb#jQ5pe4n~DxAm?9>k zVtXiLZak~z!R#nVDJsr+>atG;ggRx*D6NanDSl$*1L6V?FdvwVUoR5muytP*@yrE0 zEc&zQ5+g3(O2Mg8KpX?^-&5vlntMm=Xl@Y3!7}M#vxPFc-ot6OO4X*coJFYDfm)Fc zvCI(tN}!UuD}=_P_rlMLH?#Ct4ghol+1W?ww$TmAbXRujnN#X)x7WRc!+H z>2UxA^=On@Cds8-HIV+e+5PA7%Y1XP|BRep7Anvy44j|{pHt;fj?_?Mi$N76Gs+Si z=89p#(lVId4HbR05UE!~qJ4Ml1Z%zIa2;0c598j}cU+7FPIJyAN8a-By}FSh{FW*C zXYNnof@|D3&@AAEXoT~r7vudlDu+Y8o-MpejjHcdyqUL@S-Hh74jQe7O)G&kl22oF zy|Z%F=~sSHa%Z&y=ieb+{l9wW>V!UBk6lfF5!Ajp#X{a;xz-$ZUz6uRGHe@XKVT{+ zmxtKM9jCa&Hd^Q^zW(K~1rZ=2y@bOI%joi&k~d5m)nb<9oO!0a`tH1@A2_O4jrgPY zHP_1~N}L_%`A%v38$tMYFV2QD!_Hg%E@=2V*ih52i@|jU3-|K4CtLeSHYNkb!DvZ? z_F#qZ=-|K~_2>}wf6-+5=lMItwK~37D?68}UbSv<$kZ1s*TkK_F>C^=6qtPDcY?-p zNR4r)mSq33aGFCD}Xzr%QDX*nIIAm5i+#xzYdtWUd1-%-7Q9v)>v71x)tG{|dIhT~m@ z^Gw&%SJP)ObQ3lXTpxotxrCscaB@U{{Nrs)6pUDhU8zeh!dvUKUB*Av3NJtc?$A#2 zo@PHtZq~hZkGIeP$@z`rA0fF(c4*ECRm)m>9pNt)y^QdTTJ`Cql58kP?6&pA*h%H( z<-L>M$FfDyCYp4*36c(;j?t*(4alnp4iWo-w^1-ebgNGT4@=nKiQkbC{-GfDt3f?D z!+xHZ(*`xcLKwEiarl>ieAAm{$1jtRA3r~p*75p{FFP0Md9R$Y6>}P_^`ExZsSm+W z-~?(iU8Nk@a~Ee!J9A4yf(Ncy=%0bMw^7GVR%QiUGIrqKp2w)13Nym%8F%Mx{HPW} zFW1UTAE%y7ST2Ul@aGgQgdg*;2Im>$6Js5qykF7DCN17Y^4fPIQt}ka5uGL9lZDnOIm0&sc*>=MD-{@l-bXb2;8eS^aJ5 zHTa0>vtI`S3n(gfM#wOXy9-w8XEXFWNl5EK2sB=jn8RL3E>bGM+p;{0+NwY;&im;r z1zR2bk*RCDpEy6a?jer$L>LD<^s|BL%iguk^ot7awk4NHca!HaSn^FVTj^gyE?%#F zvVC!*Nk+kg2dilnaCoEv@Ks2E1_83VkC$Ywl5nJ4vdgRKr60~*h^*e3*u$%w==-bn zBuAv@L#!+YZXDPPmhN+4FQ*~FZo-1R1@Vd&gW;*q68z_gyC^H__X!4wX(^_1r9Lv- zVFA%mK7Y{vZzSMQ1_99q1pv55{0|QQcOHG z{s#?+NUy+b7*2sQu}j7_XC#(@hPfzWTxgxsL}E*FyoO)5+$-soTXf(BpHQCk@`k@$ zC3u4+MtJ1QO7%YZbMknA|Ehm5TQVuylE|rHi!EU8JV-*3q-C#~5RxqE9s%fo1gJB>VppqSc1BT`Y_NJ>~*;5&@4 z4C1`zH1sk*&vZeQsv*^Jq#Z1ni-y=mIJ&PQBckNf%$`Une`&*@4wS8bZj(|U|(lp0H0Vi_cWJVZ*R zS?kIwN!R&Hhn;>5f3ZY(?bJC}qTDEkm2QBW=>xRCn~$5Y`l^6fXe>|#EH|iQsqj@u zJPkKVj~jIfw?LlOzzg00bik1K6{jGEMWUJ@oUNL(M!(m>l$m$g>Ktr!;1S>sJ4<9w zY1@Q#&3WJ$UIcZbc3R{O*bjD|8H8d^BeCP)_YNQ-2reXLW4DXNcr%=G6&7WJVqG(-n;Nzt9)b1tY5{TgsuFn_x_pqQ zTEB!w5WslOxnjg&aeOLg(9OH?d+*rS!nf9$@-17WP3whguyse}DbvkAdOsNbOqdjr zosw0jkMH*vJ)d%Hbar+IP%eK3384_rGkKc_gJQQ!R->41n2uIN537pK$F%vdp!Osw zO(eEk)I)ge-ul96O3DZ5WPl5WB4OY~k4`=)PvArxgE_vpXkf5x*&!$3$6%7ix$%@?Hf<`Bf$tov})0)J3 zbMY{*e{QF@5l&JY{HIDHEG1nxd@0-KI@f0YHugMrwR<-R-lUK9RMfO-e)Uk3uy~e+ zMRtLW8^+%H0Kunv^yG%I!^XJ|ZOj#v6Gg(ff;n=Fjr)wf{EVZqCy92jwfUftR-rmf zj|At@@j(>-H;$Hg9zml6*@#EBfK@8_{kF&F;=7i025UJ0QmoFYPPjEF}2Y*GITcmFE8KlT00+&CGP2- z{4o?#wU(q0S=r_zR}XP`e>Je1*XmM}c0$z(5jar{0s(>nyxiB_w(Gmk13!Tf-f+3P zqLv+&4rJ!#<=y@_^TzPDw$VH{@S03_P0T^_TUA^8=ccxNJ!Z1y`8SNCtuoWknr*u` z|9F3U{}%ZmZaiB%YoDH?(_+z)-BRc;t18uKdFt6!b6Y)C$*wgO8LXBYve z(|i)^n}z;*H`AasCW;p2v$k%%6?5~4qb~dBo5K8GN`ISAKdrsH8L=Oox^I6q%smrr zws6EXS5~rUo737quq-GVllySA4P-^-pjtrLR&*nZBROl^=ephdMXhJH^{$CwVzBB z2mL`-X8q_BwjOIH{0ZYcG}k6*<@i_LITs#S?-5{jPSw9j6|N%MGx_Jp_8d^?S02Pa z-n4gZ4DJEU(9o*1Kh3mJMu@3(_Ku_0I4)2$GkzS$#`I-2){=+i`3>(0BciJ)0(Kn2 zB;DE+0^-_eosJaS5T|FO!?JfkG>vQde@K3Q!|nThKhkDVtVz#$e(?Gpy>iM-+fFUH z3d1bbP%NQf&x(&uN*gDNDY0<}(}DT}V%jgL&PJ8~K!KVoo?P|JY*pjs5Z5R7milve zz%`;`12EAU#vu8KVv>`$VE?Su;>9l}BM{!7lS%a(Rh|s8SScHXmsXG5Jl7viLvH>O z2bCp57cHK9r~>;60+?pkBJJj?n3X69wos>~UO(T#U%%?%@|X&x1^N&%3|LHgIOW%i z@%w!oAD^G@`Zzea-s6wNBhcZVphnTqIke5NuSqK4v93T^)|>&pk8HgG`=vqMCg?WZ zmT>qyo$}hzx0v@+Uy|Fm%4X3&7%3L7YEI<~sGm`AR|LYdYvxvWTrlN+LB<&KR0e2S zOgBowvL1zV!o3EzY<2MtO)Tq@el%KvQl83!OD!wH_Ke4~iNH%o3?oc~jZrmWw}HHP z?6DUmejuVdWj3p3qg42?~ z3hPHYXypwN3(%2J@B`nEIFi(N#QJUZV%F^|LxZ4jN4~4HisAH6-obEKdFV{vQ2vw_ zaRyGBOv7Q-YK5y^$pSthFA`$2txsb6F zi5crTs9yJQN%;VZiDMJBtgy?C1r36eUTT3+R68wFj|;M<(u$FCIci~UB}0u2p}=E- zo>g&5G30z1nP6ZalnT|qy~!HR*teuf6&Z~%7v5|-cZ%y_skFqP4^xV%?~?9Cf!TB7j} zD+Gw6XJEqYJD6|jgs6$Kt!UXqlNv74hD9wZ8A1>GR-n29-A4)|gI0p*3xV<=1a* zNcNs2uLCr&?_L{+m(8wbPjFDYOz{$Y9sBUsEieq--MA?a6v^VWrm#*00YPd2=E1^E zPto)vp$P`ZCA0AI$@_t0+l{VnkfQ%t4oI1zYOK%*2M5P)=}!QKg2US1T%_zfs76}s zTlJMmaXVXr&7$B(oH85U$qE=yQ_7UZd{NDUTgbGaV^k4iW!cczCX2k3ni zWGLg96vYIw?;q@+E@l?JgR(PDv$YU16tZ|P{CH-U6{JV6r1*lVQLO7TBpY=fXVHaU!{k^R z5Dxh!SOIF}>*^76C>yhE!P+rL;;F$^Y+=a)7LJI51a!ye;7RFA;LLUo{WaSzPF1QQ zZvqw{;5TZ06behH9V%dNZLX!n}59}-Om+sHoERbabM<;fN^AS@P!dB%` zNh(5@+ornJ89Jq+YOn8*LE#5S%L^MLzV&wVn5ct%I6>({c)&5IIM7K74=Q7~b{Ev? zo<_UXbYokeWxFXs+tvJgK&@yW+#1{y5{c4c^QP+pa<9IHu`WKnaB4|4Z=OY6yJ=F zh_kVuzVCN0=YHAgHTYRI-np@=fJS{yo_xm&N`TKm%=J;{^oGSPa>#D(l zYI9||yjnOZ%Y`)o7RlgDVA_F~~l-iw+rnHZ%VS!8=11I54JZ>6smMjB>!lNfe>7!x5}XqXzor3*{*8j_>y#-KQ_o<*^u~%$R$!xVhc>Rb4gF5!Wj&BQ ztVePmfV(R}!4wcR82nePer}<%f(obn!iKTV6ynW`gbOZ4Giy{!PfHA1V(vRA>2u=F zk}8w6FPd5vG4peLUoJ=d1wzB|fcKtw3IXBlaSV}LZWpZp$z?4e<`{|Db@U` zQF5z96?2m8{E|))BXkgek^2EkZ=XE*-45=HRt2LIk`XyS`q_jCWP*L#pE_oYBRB|Q zD>kMZOqt-6n16VI_Gy=bW5e$V`R15j#z}pLVzyEIL(;P!jP!UKh6FoHdFrW~dOeK% zHqP83yQYUV3XMZOA`Klnzn2C{dZ1Cjry~E6=6et(-BtSJjs-F(U`KukhnviVxEtyL z34MHOs`50M^u8IBW5Bne|K)1Jgz(;|{xc-Hh&pO`*{H+~jh3c`I|_c|USL!Kxu$cY zCw^topy#VRe`;LZG?^~t;meF&H@Eo)-7+_3S+pQn_wCDQ*lVH(_KDho6^6~CG8in| znG7{ujeTW|_+01Fmw1>&9>QZ%pQI%COf2u zg`VO8WqW6&BK`OJdEBke-^1(W_7Bm4M4m?M2jzOM@6#82Wt(>r%Y?aVPKaqoj!bYC zd7>joc?7}6drrHV^xhg0jCJvEf#4@)g_{4CUuq91uAah>(xGiVaEO_4-+(K=Lj5tH zgca^XKm};L46*PZu}1?C!RHzdbK97%zcy*ur&73`8M0%BfMgaRH1K3}7FQ@G!0o$h zPhHwpka9)-zo;^q?+X0$VG4^K7nw->n8PhW2-LZ85e~r4Ol;yDGRvrkPZre&FKQKo zisI@@t-WV$J)jlzd4$@DK9{xHCNaHSLWEtw+%jw}k+RjN+i~S^pTmw(axC7rNU``x ztKG(tg&LYCw_TwS1z5q>d4I17R?Sfjx%6WfAyZR6BhagEs(V zWGLtSjp7zW#4@9q5$v%Prbx(W0*L@Q2LZx|$d|!8uFq!x{L4s1k{N6F7|B*=W0$uD zDIv!L;M%(&@!xCkVlEB^DLV6AR`edc3Bn2_p!X?%$OH=d&@2cg4`hG(_xJUj{bj{p zdM=gSpbB~X-2{}IWC3uc6qry3fX``bgX1?_C#IN843c(a;h?0H zeygwpX8>Cq(dpue0?!MCC2mX*kfB%k#}zB6_0d$?Zp`Z{*|?8$NhF>SIKfC4kbtuC zd|(XW$;27Ez%XKAmTwXD@^#4k3-2hkN6=&+pyB9HCg#|&Ya@gBo^wZg$UHY4_;*wa zXy2lMcB(Yglo4NFcy)3S}C!Z47rhT9w< z-wtIx_$~U;?65R$jTJjAGnG#L9piCF);yPFFfLM(WwsI5?8f9yDf`l>XmIixW|N|4 zVRJ={HWO4;A7h($-P?M|M${t`01l5preSLv^S&gB0S5etnN8;W#{cRrVd(&5M?-3K zHwG=c;3rj{kP`2$#0W-M*zY?P-(@D4I}5)XmLPbZrGV}i8W{!jHVAran!6!fWO88v z_Cjr7aB!Ky0iur1bQOZ@R_3 zl`@+T$`U~IHK-HWOgXVs^u3v08l2xN=>obBSg;L=hW-2=n0=GdRwIGB>G0fHE+3mI z{Pq>GcgNQ-qf%e1OB$;<^LLg74|5*o(?c)rt{Fjq0A3j$G6Utpwb*x4A#O06xev1H zL=;dkF7~Yec+2Se%cyKw|NWGqYz(SPA3J?eiD$jM3huEowgUXcx(!%XE=TII%~8+u z+pG2H*NVj#6hoIDlA@B%iMf4D38X9_o5oseflR~+aRbGV>ri$r0WiTwG|k3!v;hcd zP#ZAz z4?CKH`C0#rQaTw%%!}sPW|1BFHWxlz=_1g(VsJ>~zAH!bMRgjjd_{F2i@t4s>Z(!GBUqa} zJfMn?K}#8vm2f+U$I=YEF{k@B!Tqd&h`FJ(U`83!B`7eQQg-VW^SvF-w{n`GIxs}0 z0DQmusz7d+8#tUx2!86@RfcmPvk-Z4WpDfo;C~_Yf=^B!CP|>fkqv z+%x>i6g+0d+&|=^i^B}B7GEUM#8Dy4m^*@Bq%IC*nGu^6isVtLxTc4GJabY4u1`)I zfKhL(qTY72|15p7A&It_A;xx|oVJ9=Y&~^}|4EO9f-IWywVZ|jQx#rtxhc%xB#0$) z$IDxy3;Ti!LMK#U`D-G7e#`1^C;m(<`n6X8`fM1K*9m~Z02Tll0SD}{bbG-gq60K> zkC1g?A-a}v{zpZhuBnJogU>Z{Gl=`f2o!~VIvB_46EU!VCMZPQ@P$BV`7l>Xh>uMp z{_h{ECWc`}0YM5O6A`5ee5bsk9QDf!h{i4)*BT_q7Zhl~YP5guN) zkWCu;mDe{Tvdt77`F_PlBgd$So5|RMyvDz)Dzap7|87zJc)I8Ms-lWI z%B@!-<%{)G^Nu5DJ;NyE>&I_1;g#7L#mPUz_+3urV9*ZlW4q*GjYHiGX(N?9{XDI@ zq*+Pc-UP=X;mmE4vLka$PHJz{OTzxt;gHi&hc~!RNs_OGn$2yu1Ak4u>G;HmggJFqALj4$mz}X}XYYuLj zQfS~}Hky&FD-qv~nS#$7j{d~Fjc(?q#rQP@@fs+YPG(abx zjy3J1R4V&Cf?XcA!?-B-*FwG(-FpWPS2jzYYB4gh1-Xbc3fUd=ZCsVm<%LATMnPpU z=la2uy6FYb>-J_EpQBVmPN8)SRh;Uw97F$1Nx=?Dp{DP{E(&khnWIL}S0gm6V6w{y zgZae(tBo}rIhaKxh-|sA#L^6e(#HkoLcd*Q$VVADv=Nt4&7?*!6!?#1E#EImmWp7| zDG({ez+x}3K8j-}$V)j#523*5w0ykq}2Pks6qzB@# z;guuOG%a>=#%%?x&m<{|)YQIO8gGE-ua|hScOSVB%vB3@N-t`oqPwZZIZs)fC{8u4 zdF3?M0Ji&)Yf2!o69{TUqeKazcAi4bA{Q;}2&4Q$G2{{MRPH^_ACZB+kYzP<7%))? z!Po|&k`iof{uW^P5S3IqFC~an^+{;XOFP{JM3*n4Hrq6Z?6D?P{E5@Ovbv&=j z;u5?f%(_^Ef|+O@u}HFP(Fo$ApexMjktJdZ4m3__D)eoXBu-B2O%aHp39%6{tN_g! zZ% z#qqG9+sJaOjD_%L1o%0iX5gG7CKU85=op6JRKRKWvWR#tiWp+lNNf0FRPwytzLY`K zQ%UO!$`!3fHa|vD|ABIJ?W^rO_o1lk zRK~re-GUyinRM#fBPGwmrE<$uykq>z=A9+2&|Vq^{ddy_xGLfgOW)OX^C7P*_Oj4u z0l%WINH8n?ih_H(va#o5y)2Ftv3OK~t3Bs_EYNPbT3OcPruK)a{cL*1tm?l{cm4PN zF@)v_puZ_X|3hUE9z1lY8?%f>ma|jvzF>z#_lW{7=t;_m{LTlSJeZR#jsHlJRd-;~ z@%xPO0+|{v)R(Pa^x;P8HgbQgI2;KfmL#>29+*R||7v~<%x^3WQ$vd@Lp6h*S9ug; zGA}AA@qtP3j(Ysddq*s z?QJlZ(Jt-lF7^AP<26;Tyu3Dst3-{J!sn+q)z#5D;$=%PPAhWyCh8u7P_F zyf`i-*@wvs;2szQMG%s(!JA5p)_{@iiv`Vph;gKTj9vYba7EYFh%_MIn$E@eYz7J5 zlz1pn_@qV6@j+Nz-_mlZEoX2?BUbE8;=JP{6$r?fs^WmuG4IEwBCYXhIUH15b?~?C zloN=7>rij6oIQ+E+6S)6yVuI`rkxv(u)B?r;5*KHExXhhNrK-g^djAd7>!XN&=M9R z+@qfu`v;06RUdx-JUC9!Y$A3QB&xcEXos$g8{K_QNVnAPN!-7&#sgw8yiPJO#t7NL z)?CLEy2)%$QARA})YS4B8@EU*>MFbPW=Li%)fB#(auBaSP&(wl5QZgtEO2T94xWAI z9tq--{&`aqHrlITew{dk5R7SS0T^jXvbAma(AlY$HpF}5(OCkl8S8HEVjmx+BH-;< zBm)ZB2g&FSzR;~jUpIXODa>PMq%xZEf*O&5MN7_?L;${~8GB|({R+Z)p1)Of(#?pM zo%c%(cucFWS=QLUq0I`+VGerTE!vs&QWd8i@CG+A<2S7~gZ2mdjAB!#Cvpg_iVBmF-Z1l?MqJ8T`E`pBc-92l-D6x_9rMJ|)_x?DgY@sAAd&}fh4^v-s@FS- z1yOq^wnr-V?Lc-N-|YIy5HTqLvEIWafe2olivohl#-CQ) z3X2Fhxlj+eoozo352IV^VmaOlVQ695 z1uPBrqx)-AGU7*eld!#3pXMokk&j`27fd?oEzp!GgQ~lu;}lA*S}i&EvsDJ$b62`c z4A)_;H1@h|*&FYKPCobqHQxwyE1GYN7Rg|%l6Yh};In;Uk+`&3H}S0ZI`g7ZqXOb* z8}aUy>^lL!0yF3Zi{IyGJ*jDB4aKRCVQ<3F%004umakZnK0LGc_>_@G+9>7ME}cj0 zPrip^r}ZhoqgnCug#vKLnG1X>LBe0OxRdkeVK%-VA~uUN2#?;rYs)EkvntbS-`N;8*T{XSs0N$mdp3|Us>CN z6iR6LVkuMa7{Hva4u>Ox!Ihx&{w>}W0}PHQM%&-;uc146dfn9eqyg_;YkDq;jKWH@ z-d{*{nE|GhB@^6zx^tJlw#s+=?}=V@-uA-xyWn;gTS(0Nq^4z`2;ALnmaWN2iNR z$!XU;0!s$CKYWW6bS`+I&JZ$1_18IzHW@4!6X4K`Bc~3{bVU>3&QQ6Gwdf&AVQD>5 zhI`a#{2yzW*VVg4D*(NRZVyb8=DSo~x-;p6Sk#ySH9~)Kb=fpL{`R6}N-?&Zuw*WL0(c}Tk11rBA}cT5_t>on9wc7JgT zgt&ut5y5#;MH>%@tmq?EUzO<%Uf)QK^*wJQg-l55{dI=bG!IRfW^u9Ky<8k|>iM12 zjS&|_;)ev_<$TfV?^lWp-q+V^Jr?H5iIe1WR2OlrdU4t3}HHuvdtlgiE7(C>uE{__DRUs(m?a&R{)E!BYg-Rxv+T zVe8=QYQWc32W%_8*Ol;%r9)qJS|4-e4L2v4jNP{A^AgWOYL_)%m)V8Ps4dR4@)!Nr zZH(rLXKk&V!GB+o3L_D(qV0eDFdy~%(Q()?WcM-qm}T`c#59F!;~HslYXi=Sk+pCC z0NFvgn(bJyaH%y679o$P4GXUg_WOZJAy)6Y&M|EV3K=q!6EvYM_MLdlgKzSuALh1F*c zxwplB>iJp>p%AMFa>)J(O^Oxq0PAXh6Zk8nDJWTdG;{^Hg-nb3Nvz4liyfM}uq%PY zLWBKEJLOClskUGo=23ZyhDK%Rl%i4p*qJs$eX6F0D}joZ56u^efcnUrlT|7ZuOXmJ zzdK2wFmmpwG3#D})+=mQ+xhiel^>c}qgG&XW!~Px2{laFiwS3?#jeeCe*MvRdaCp8 zZ|1h1eVESi+8bz2N;ONBg0e)LtHAeFo+Wdsb;aD`W4Fqh>Ajp2ur?&5gy#WMA8Ucs z>2dd_*vN`tsqORl%TNDfjflVhHz+wi5jx=|a2L#q-8Z5BA;d?#HWhxNUO{Y^FCsFP zJ+9LtE_%F;9J6h=3%y2x!-WJQ`WH0M%7Lp_;zN4{mU^ zmU~mLflybwUzKw|C58dd-|({bjRXC?!lKkX__ojW^WujJ#M8r4q3%yeB4EcDCb$sW z)nDawjM@Lz#U^GLW_kArN4?cRzB^t-ZIIM;TXbncA^QeDqOe^YxObJ+m5bRT|J1`AywSbKV8dn zI)}*zoOuA6{LI|*wh@V#Qt&|T+8TePnbN$G0Oms z0cLqgR79wqeGwd6zdmQ)s0|W?Yp!g{!7z7Ljgh!!)=m;kx8M>wFP`}Fn1rQD&kYb( zui3>kN;VK<>lXJ4;It~!ptLcQ!E3b@fk9;q(-l)QY&n)#|s6ISEr#Eo7oxZ4GiPAXw+F!jvxn~j#TQcJ2 zAc<=k;-)I-+yueR;0$}X%+5V4-x1Fir)#C0tWdfT5s8Nn6g!VGlxUdyh2SeXD?BV( z0G6(v+P4aG1X;AG@sQ)w95(K9ON~{LJ1uU97!cryXG(~?e_xu6%*Y)+D<-WaYV=T^ z|4sjY+O&#u)ijw}dg;0$0RTQI0RaB<)%-8kDhERsV~hXk(9+uZ&r^fsPrvXNSk9NT z<9sYa$rmwcf6A-dZYVjRR)qE4gN=OK<9(qE)!V(|_%7B6I^ zQ-nH?_%UROhR`UGP07rNG5-ksy38o9Kl0r$@8&qH*)xaIZ=lyIqKdK=fL?zAMU7lh zapC9>*5WeJkVxP6}&CPy;*d5dKs_G~Vic>h)t<>b+L?oXP?a$RqOP z)M!%8AfJZl)#Oq?#elGjS%&Mn99lGLA3YfrN_eUQW;oJPi61bH!CDV8nprMWhk($z zS{LPwXv(te6y9?CW-bz-K2oA%&NDF-ro2Qt36l~03u{=LpxoFgPW0{bWtezwZ9i;k zU-ky6g8tP_}G7X4VsS_}9?HICDYX$kRZf6y1 z@zHDZzLnLE3;-E?-~0(%6Rknc!#wM0ksd zZE_$ZQB#YXdu*2s@4#Af6k}~n2kzd*L2Q_IQkBGIfJDJk#(2j6q(M2;O)L}?N8^}9 zjZx!Z@noE|D&xODUNnR#2ppa79!>1k3KQO19NnK89CQkbd;$pb?#UME{aD0zU!bk& z-9Q6-X>Ih0s7mCaD3$)e9z|qv^MGC@cE7Igkdj9iLs=}fxMC80PSn-1j009l!(Ka3 z%8P9`Fvh>#hgkflsW^W{GZ+wHw;yA;)sE5x%?Quj;Ep@T7Qm7&LJo5RN`rB zZyZ?AoOigF0PdiGws}hL?SS9K0_!OzOFS;tG&b-!_uFnx?%&V#_aV*nWLlEAIsNp% z%piJj*pbdFhKhlsA**)VdMQb)`c4PtJi!Sn?wriA%(i6hVS+~&hl=qx>2CSzmTNcv z;0nJoPnJk~_{` zdIH7nSx1oIxJ6Cg@8qdV(w!v#tDk-;2s6=Db?0H2hbIBhHs9S?^<_g;f? z;_Rm1S3*Olcu>e_9>}Z){%Uk|7C&Zd9d`hKnO(cUd4L=bEV(}Qdj8YR_fa43gSfiz5Lkxq-A}2$=^lhEmCv9%Y76>|vC<%#6d>QKLH+nFqNsl)G|+ zDa0!dSmpnTdZU$jlp9CAF*BMfn3o$ytqrH-<;DNE=_BJ1H<)r4q09re%mX;XDfOPH zjsF=Z480$k{*t9V_Lt)R@DGyykKNkozHaeQIIpA756SaF*lHugJtapI5C!exX@PMG+AqWPg>zZVwAe=;ms%Nv#!$8QT2 zUu`pjKsW4y0xrNb@vX<%spDnKW)*j7YY^a#ZyzYUQhVnydzOvQ)Db&vm*(mrSLh!*%oS{hx79Z6Mlt{cNg z`m?n5r*AI&Nu$3g5wY{wsg+QL7#?{PLRH%EMj|mT;jgI%Q&z^R{JUf*cHMVL;u=?q zpi@_;9}p@f%6PfVESs_RJrEaTTZ_YvhB@PCCFxZKjk!f=O^Hcbzu>`aVJOO%j#y zOr7ua2C0D(TY)J)DY`xWsuCmUgyTUqS2ux7MLxsNRgxE47g>^9)CYPtQwbnlDr~C{ zZ4$F=u8)octZEhm|Cyb5J=qp3mh)wxu%x@SDZfa6qvDz`vR=8M0{W{v^EC)b=32ay zV!+O_TRpVRt})GT6Gqn@a>S{#5R%GQi?5RE)69^D*I#~#$b1O6#2d|RduU?~SoB$) z88AbIC+Vy_sD$}0=p4Lr0~RyVX>LP()*`<%&&VsCv>v_HL(L8ykrX;4q;C*Ww=2k_ zqNIwP@v5CfcS=wEExJ0GeY+bfl*yHiI5^tvio5z*4(jT{N1eE z5_$|(y#@PoB~il0UnX0alvo)9jV0Qi@24GhpU!T_W%9)eyUDG9mZgdgZN@$jIqofzH&qm+X>EbKV=dcOBa7rp$1WR_TGr6vvV4C9H1_9?-ySX;YjN@1JPap|X#i8%0_ z06nFP4FAF&LiVHd)+<93!0#T7w{>?j>S~|J5uNP9>B3(!Zlp6>>rK%6;H~m2Oi2ne z7&_!oXx~@qy2q-I>xBsm)2Dpuizz$-K7aI9rCjk0#4Cg%sOboA-e3}bkA}qfB3k2e ztwTT)>u%2B6+jFT@SR3-dYifl<||E&@-S?oMTHx5!b(rSTjC=v^UQ=eG@>Q^){6J3 zN{WXe_|Kf~N`Qx$Xb9nk{nIEZUt4$V_SE~gyyU-txO|*sSkWy>wk@k-6I5-v<;|pc8g^SuT6dASlFCWU z+nEKV;uU}YTjAE) zX5hHy&!jzGM6UN201L=_i%w0|_hS`eucUs@47sXiIyx**J(_7Mo2Mqs=&ub~g#v9= z&0LlHh6}}2zMkpf$w8$@qI^@)oCv(%^GUb5ChPnamOw-gn!09cZvBX9Dw-@CZbUTI zw1_7mnYyKGCaj1u)OnSLi7G7W)DzikbWaCLWd=YT1UwYGIshbMk6bm(l)R|c+6jp~ zU`a+=@(B+$){vIYadQn?FBpPM(pr;L(sLte2;1zx%n9f~&}D1KTz2)7ra?P4RX#xh zU<#H@+VY5KFW%|1P8+Z)Vir!Gg-BD_T*3bfDL~f0lm}v7PV)==H=`admglp)z8c{C z0`&7`0}pF_NMkp^{yZux1XpJ;O1(j#LaATHx?Da=@tR>#K6^_9rK*xmZ>O zG@MbjX$b>J?fyNRH24H-T$Hm}d5wLXl*Kg1uGPEN9H-~yyNtTU)KZiUV9luDoGi>- z%UAVP3Vk@w0ib1bFqK)SMjIAqh|wg@RwI72d`g? z;}e8-`0~|@!vlDHc=Yten`ehd-;3{{>d`R}^C3_%z&$;tHYK#fgVzY}<-y6*AK>Ty zcZV+yPyaeVSkDhnj}Y?n;}fwjUhSWp9zK2ZV*f3#OojSU%bH95ZwM7=*9^mDxMy{`s>Nz_dlG9AC6xg9EfN8FZaJcpjyWOh&qWS8BOuy4+r=ZTiu8Mo}L~aA7Ou<9v_{a zz|R46_vBR9{_*hj!9eVv9KHsGsgEbe&S(Uy{7R$a>}bozE2K^@Fc(9MY5A)6 z$!`RFo&jGQ@YnrfCBIG5T0J~o;3`aK^5>fZnV>HJx~b%k!(;j7WxBv-fe?}d@j7@G!gA^`77>!jJKr)91e*GX3_5c474Ql4WzT^ZSGb`z5@Y;Y2_^Ic2>>KTLq= z%Vja$<40KKkFR0X?|BnCf_-g(RC0zeKl#mM2HUeZNv}<(Gn^5g6JT@`ny#eDZkh!4 zib)E)r?}1@!q!zTvO>)B0(Xu@RxW1Qa5&_O*!KA3;Co=`fC3HAd;!~iuS))-2bjQy zN@Mij2)F;JH%fPY{%m;m*-xMKzr{86|G3YL!%;fVaMQ;92{%8iBPkg;OMp8FaHue+ zRn4=I3V@xZbKHKpb`4W8o59?J$a9_ZZaynh5V{&s78BgsLAIHf)e7W?3O4?02kzko zJaU>HFqkT9Kq8?%9t9yl?;Qv+NYp(L9>n>o$zY7|D`V8Rq3*)+1tfU{4~xaJ!LeG- zridL?CAosT(o<+N?N3R96Sx}sSjx;bK}HlMV5pA;G`z#(00S)IP7(@A@`;e6tm|-} zxr|Ln)Sgq2VU;AFIWud106W_7g$|`NUW#UeNB_RN36dG z%$$DrhX|?Xj5xHG*Li_*+9Z<=(!lub;j3|4k8x!7xMOjivs34nxCT|l4EEgs_k)|o zEJXpm6!X<$MdSkHT#?l3j&9gEb&9wV^~&xJLq7q!1&Q`M=!ZD2rdb8sSoIeBy1+9I z%pf$))VZ#c^4D;N#TPx~zW(^xbb^N=T)tk1<)T1G7o;H)Ko(!L^a;)(!1CRrxk6Vo(^w1su2u_q@pI{HtZfunvk7V_djnVEWm7K||{=0rhDo zd26OlD;yz@7xd%R0%out{Bt}?4T#TSkDryrLp&x`q)7mAf|LgEGDb`Fa)L)R#%>JU zcsXl;&cptPRbd8X?G_X*9w;G4sSG9(Ry3-t20W!GjNoirKY>gJaw>Ug#~=|25`)B< z1}U*oGA8SuU=+@0<>W0Zs*qP`Du{HCbukyqf;3Y=?NAXR$c6A~h0JFTy$7LXxnNbpzvWrrs%aME z%dCK>lbR0&=jC)YCc$dW(clV1G!U3~)yccYSiO~^;9oAsxlGP_awB#;)P9v zHN@_QL$jms0a{Pr!CJy&wW;g~Kz#gjWJGuHkhiGLy6eJ&BMXh(>Sx0m&d^OS`M0D$ zdJMlvuIYE0)$+UrPxGnZB?JorRq8+@z%&KQ)XuK@K)fL4c?nci zGh0PY;+5H-k+wR=ou3?)8jO!ebr_(LA0sB7e49$uu0*j=AmySvTLI8SYT z#i4_(Z@xffHlI=zbG^sTHZ84$-FJ4?SbvkhIg>f9Tc`1;1iV%=67B2s9TJ0_&in10 z--uuK-sbhHTvqkolRhsDPnWIHmP%aw{xdEK;6&r+`As%GW|H1S!HtE?*;9=cFGU+z zxF*|Ah0sZ=sg_nws@Ns&zZuG~)C-;*RRwR7AHngEwsU+fahjHs_W9G}B^%nc8Z_@% z-twlv{G`Lt7*A2-v7|4CLUK_=)q-V)DSjd3g3(=UcFogMc>x;$=P5p@Y{ug_oXpPn8Z`8N)| zZ@>QSPe1j48YU7`>@KQi>4JaURB2J;aKkSAHd_to)fjgD$pEF3rPMX~rXR}!uOxP0 zw8*4E@1FYtfCvjHi!qYNkt8eEokl@3P)lzOK$suuQUZyosSk7j6sBh9mK86zifU!pu#0j9V z|LTxRFVg1fW1N6l4qP0LK7dCpXF{P}uVBN!8M;$}<-NI}s(V7M3wdVH_>K}Nkev11 zi5rdiMqq4K$UI%(Z1vvuY0H0$ydPnog)@x$lWk{so9QF{j5U29-^`uHvFu(oX0^b4 zy~ipE*4}96No01$s0D)wy_wI(1*)N&^m2gLDHr+89&RrKQPlLsnw6(i2aam2O`1m8 z6#$a5X?husHkRO4xDbC2im2hk`t>56xMR!j6cX-;My&$WcW{0>fs zRdxvrDXYdBi5{26q3LS~PBo)imo4^^+eCZ@h2T$ehhJe>+)1(u^E-1oqZ|AllbbaU zFY_B%cent_Kx>xc6_`}{&_VW*(va}^dX8X7M^rBtxSKL0*G2({VCw4GhSqq=qh!52 z$8knRuuIk{Y(`+dp+Ny&df(p38V>W=unwsL2!-_(%#p>DD}VR9x7R4a>|*hlcuBHL zI%Nww5a1S7xyY&}cXWE~Sdx6BnV@VcvPCK7#}2XX9ppDVd6Ug+SE2$^dP~ZfTuG_! z$h9kbp=q?f>?NPpc%DWWsd!tI*Op*G)|*6ApR(dmUAD8(G))HL?LbM#RFD)9c5|fK zeQVG&lSBahhoiS=sMP4ub$40JR?r09G{mk#g07s%N>&d(t$n1)3Pg5lqYeaGA|``| zZs(b500_?|;NN$tEBh~VWPwrgtygYl8&dGkQo3y6lWQF`%#aEh={mhc6(|FWpn3ui%T zJ-*`lS+*Ffjf&SS;43f2LqP&BDcmVMF=ldPXh6r6Yh~(2HcBXd@wE%v`{F$e5w$bl zr}#K0%LqU)C8_N{)0$Rvuj@SEbz+bA+W+*e{8r^sT&D%!2s_f=fZk1@VKf|}u5iEQ z3fx0lkMU6&EpG(vmbl~cc9ZY#{LQ_N5&S-%&1gJ{A2&JhtKi~JD}wXZ>pWx73bXoJ z|B&1=FD^jJ=bep3hz z;R?3a9a@~Y$*9CG2ESEa1)x;>X?VDCMcARfH5tYe?VdvJQmo zVW!LZ!ZnbczC*DE3#FHtG(ak)G(TJM4LLdi%+Apw0~Qz&an@MI&iEM)$tHVucR?yT z-}VIue!kjHuVH^AQ9*ed@}II5uKgy^SZJeXRu~S6<5C-z*jB4y16g0`Er#OhvZ{dn z%vN+cnSxv=9wNm)WRnx}iBcfuHC@@#RUyjs4*@?@PU|t)a&2nqGw?$uM+*H3w<`ik1?!?hrbzIb^dFUki4DE+%f5>r$Zo(=l}hs;!{{ZWAi} zRN1JJ$N#FW!5ON(HQWB?dq<178tJkpv4&zJo=&8aNlK3Ra|wrw@vxHiDMJv%o}h_} zTUA%9SM`u9)guGXE6utt)7I_VUGa{!Fu-i->XTmSBhZjEExo>XsC_q}sp;Rj;H3e# zk~Eb%#%ZD-2&c}* z#&$?&yX4U{(%wvG%Krx4-!}EL(Y0OKf~=O=ze0)-_NK;HDV7~FlnljlOGhp7vcPFj zO|_gf=nKXi>U@P=O<{uxjom`e6t4=ZUK(MWF9F*|N=4J>C~qu;qI2zrO&zfdBgI15 zm|-Ou=9V~5Tz!2t=8NkceNeMdPGH=vDax(Pf{P#hD#QEjtN%m za=4uq$)?MbrK2=ybx{+iD@tcKz@sOy1Z`dN#v-+%W((+g(jQoY^_mqxnY9FLjqRP2dvM!qJ*q zQFk=#y;{B2Pz1}jTYj;pc;6ernDFv{>wVpNx9bnxAqH@PK;`aJqxF6>o08ffthxy) zhqX4PQm?8f^yC*Fy(zCWw-{b;cm*A)&vfP2<*MV089IU#>h6#Y=;@>^Rp_>GiT2U< zEn{MYFeBB)HMF;mAR;|ch@Dei3+M=1KeL7e1xPxn^7&CV=2sX}5g^&1d2DOAT%e(o zysfQA8s6D37y+mA{g}|#eln1qRSq%Ts%LzfU#xh@)unKB+))jEl}+CA>75M{tpVWM z=3*t_;5?gh0Y_B)G1KQldECL$d2t0qhQg-}EP5M5j98(_+HU1+WehO<^0Fh+otLnd zkJ>coTnMm~`h}3oQHd4~cfny$s3XYnJ-TF_vqQcEAj>{7vyg67F=g#>6!Eb_0|TUg zb96DYXbcD98YW;ns5(#;2w{0V13V31TA+hY&+1kmZALJ| zjDb{Zep-_gYk_3IK~hM)Y^VWB43mglpgvBAI?6fQbG%rKJLq|prEfP{T!9J3Gn?!L z+m@u~bd`kxB$gO$BGz3IE<)qcvIak!96NWm2m_-%j&$$H!rZOx`>b&e`^XBFtc+Cv zY1C4o?-ScWk#9G`jSBFpm0ff5Ng(ITy5TTd!r?nDI!tBQsj%|e3(PrXXB;V~858D` zxqAkl5e}$OKXYw9t-z%tv}^2?5>N+nPq6$1pW~>2xYp(~}J3ZS4xk1$;YEKEuho2zf=DdCEIk({nb|w;}5F z8k1eCIsF4m`^y z>Y41lWwPgtKmuHTJj;s9=E|Ctfq+#3Phn!j*TU9tCG+&AyZkp^c@X92%ei0pCIUBJ zE)EYQzX-^^D9mWtZ~U?_4s>I%`7m@9_pn}|Oj8wpVHEJIOoobqE%OE?)8U(=!>7m3 z4*E8LWs$>rZfWedd-M&Rpl71nKP!bviwFtTye@Zs|JCCsfU04ERyBC<2|!78G1+p`TIdtpRt4Yr<*)@tpZldpXJJWLmcCjoxxEX^O>+m{oky_t#h7i2 zPULRXOSClld>Qa@zMIS~y37kivMxSvBRoO$Jf2?AzchbAkYv^-f#&JE~kW6Wx*2 zeAO47Qb>8?$Isx)1Nq8;H>TB%5ZazLu_H z-fdK<1hP%M$L^v~BsWs+Sc=JR_09%Bq5qA%cIzqlHUk?vw&$+LwY45ypP>Arqv^oA z-2!4$vu_l= znOi+Ddm-_q?fVemGjJwUefpdGGvNoX%<^IxsPtvOtj=S2nyBvtN6q)Vbg6vO9w^Zo znkZD|BNpMt_Q%>O<;~VQz%43BGYEXyA0+H!${=+7P4s z_xe_ymN8M#8D#C5!*RQ)Xza7#IwGg;wz*Lp*%{dJq`7GlWex7xCflDPyH>r6?LoRH z1DoX?^WPjdw^05XnFAINO@4PA8-gS&Dv1#UG3XbEx(&A{}21+_5`@mdBmo?bb zAujd$sxW$PC8FsyjLxfEw8e9@KXLzR)A@k})q$(iT^{`8_V)Jf?#_z)$4~~k&>DCa z(<42KtToU?yFqkT`_s<*)F&8mim$%mh+F7VXvjUYxb7cKi(jZ#B+u9!OF$Bi)4lf? zP4YgDqR@Q}ZhsyqZ-FWLMk5=S*LU#s5k^hxxPs&QAlbfr^ZHas?LE5&q?g7;f{w)a zXehp0vf!c&O*NVO7PgVGX2zjRU)26*vBpIC<}qv9V8zkp3`js@#McnY5OI|z+IO*l zpb_jy&1iw^qe$}ku8Poa1#DRNv9ZAQ3k&z}WnT0~Hu%xwGqZrZc&GZb+;DDyfNEu9 zf=(BU_a+G3xDAJOLn%uKZKyCDYMo6<{@EsuIDRZK2E7o}&$~9k1V3Y|lKR?F z+BqGX9~<-xJG5ng?D!K_%Nwktad=c1zvq5w50L&odb@$CM+-s-$NU0FVa+YV=gV=j zwjn4NO9<1&kVz$IQ;9^N=Xy~Ov|eLC_U8;Yj@!H@?rDq>Ztrj!r8*RTOgL1ss{s9} zummOR>}ynP16shAI?7wa?D!IPzXu4#qC@-sQd3)NjiG8({5mo~jcK6PX^b<jHZZI?wZq+B-1LdieZGGP#(YggK9#aaDF8$QK?%*6$ zs29*9WT!rm5y3G;aWXo)bp(#EraB=y-bpAV#~TSwH@}vm@gjyhB^jveq=${NN4jBNW5NF8M~e{Z&V61a@06Eczqg!{v##AqS#C5iHgY^F=-_o42-r+SZX+v zhN-KsaaG%x_3P0Iu_tC*O-Q!~#s)4H>hlX+E$|cDrrU-3HCT6S#qZ_SaZi23&wDzE zbPSVB6y*%b*mknCRv#ti*j`;Oxnb0oXies!h^UafDb$KNU!re;bUWJ>7%dOw4@^5` zOA`@!0)4gJE_PpFQOw|KCdCaFb?!&#cysc?4J3*mJF+3PWnvquj0UQf2}Ti$9sekC z#fco=DnqCqL}U{!z237tvnG~Nxoj58rbWx#MIts3=b{xaUf6Omq;K7t4ogz^_*tN; z#*>zHjb6Xa7h_6one?%fXwA{p04@m)xwRC3F=nQ>ARSO6__g0RFYe3>5XUx?4|FSB z(ZUE$4CzI-mqfhWBl0bBi<^mmAy1q_6Aj>drwyxV8gB1~`q*NYu1xJB`NYj6;1Z0X z%>h8_tyUk12N3M-m;hDzNIAg3GeiI2i@TN4c%!s2J3yD6EM+$UGQ3aGkV>U1L6Zf# z_EWax9OH(y#rZox09$n2knv-)2Pf0fD6sON;;|!+{yuuL8}+-ImdqYdX@r;Iao!Qy z-+1&NF_4pNFeaI+M)%a0j=Q%9;)r67a?G77yIjuF$|Z)6mNk12KL}&~pTtF-P8wFq z$%#GyFIBn;ZeTlxs_S?)J`zdlAH_j=ST<&yzOC6Pp{NtdS?rX~r;kyRP&I`V8x`=B zQW!HV7nm1(gk0g{UUc3Ny|3<6X10r@p++~cE|F9y^)l{ws7uA53)iW4|C_;!Zhg9^6Kaj1PAWyM($;X}dR%MhqMjdE zU5*+-0yeUzL55R@mO_EV{P;|KX8jDrXUg)cD&EJ0YiMUa*|GHALILWE&#c6aFZGOi zOrxSQkKF#Yy2HB6LGafwiLL+m1)bW5ynggMFYaQBwxGuyKHC%64a>Rh56XVq(ful> znuOCD#+|Au116(oIj0zmgN8ikg%B&Z=xn&R{F^< zui60Pu9@%|sGfoC|%X?Cy0KP5^g1N49uX)-}cSl#zqY zn;p^SSv=M5SrZv)?MzVAQp`;zRQhrC4p&ZWdUoWs35P&+>vzmRTriSS(Xmb}u%%3d ze5+Ks1~}|&Ml20`u&EdkNF}?rK+>5AH@1v)1ewTU?iSF0!SeC5hzD{$x~jLY9YgZV zB1g@R4^NiOfVEodsHd+;in7io5q^Xfb~upGW=l@BuNR%azA!0sIx~q@Ddv!@j=v=U z=@?gYROrtwS~!rZt5UoqZSQ)pxDI^KTd%a1Xf(40NYvf<+KARb)9NA5*$CPKm1cv?+SMh+a zl<}?{jZv+{4U|-b(n_Mgi<4d2KyyR_IJLoeVVLjb!-tACT1A_w6H%)rZ?IPf525iz zW4(z{JZT#3!>Jac@O<;ma}90XZY-{6Z7>`t3BzxM`$XuUz){0wBrqv#!~YdUgK=G< z(5FJws7+!y$+@QwA&)qy`kAP&bk+x~jKOuahIsuZVHPLH%k;0?>Y#pq3fEkErtykM8*#$}slopSyVoaWMY?`Gd_tYJsSyyn4INf;O zDU!1Gx}?ljPsWjTf^yV#8(HauM!Zp7p2Gt4!uPf2o7-jnBAZNUkGZ}p(z>iwkXJV) zZKAw8&a5J>T@|Uh38<}002TrG{Hj2ld5GZh+`2h#s0Dm0ENF_Y^vzR$SjcJ0hG>y9 zYR`xmgA2MKdx4-(wpB(k{wW@=Z~bh!ZG}yB`fqjnY=w#syn0i0B9vr-i);?;_7&=c zbVkkVDqT=!C&!Lo^wgo{B30>7q?Eu>kZ~)xO5bH7VHyqauEz*@LG$KzQ$BCGH$+t8 z!$a=8N9@TI;o!Q=31`bJS;|M{^ab#);yx|C%M=HUr>!lxlrF#ee;QRI{@$Bza4R1pl z@m?M5tH1L85)!1fKHH;T0Na1PJXfioZJa4OdSCIpc1?%N!?xyP%n}?v)~$QjfuB0` z?jEaCcgs5Smnui`KGo@wbx~73A6dK!&zq8Qp>~E-pz+pXAlZ(Sq8BJY%?)aw_8x4q z&Vejf(6XiIOl9QdxGHQrPHZt!(jxpKotTUjvPl3XtBS=<*11WmbRUj0BB12NB=S5s zIsa|zRqjSHmiY2PhTru7j1=^+_YTuS?mZt9z9=m+#8rfe*#rijBI5wcNx8y|A0!<2Z#~`T;-Q z(N;nhe%d3uzqha@_a`ZCwa8fb3FNF_j7ey`(z>Tc1{*hjYCNGvakvVMT>kytnYCL zta8f)C#y__wrLmsy(B*g-@r`MuteS=FUJdW$SJR~a0Hsy#=Gov1Mr)Tg% zd4ocIz%V>$m?BjGtnM~8X9$99RW>zMA*i;Sx*-Y2W^zNy(s62gn~1#20&g~UpujRn zq;6S4D42YqfiZ1&zWP$#X0+U_ZYxc$l_EKmZi^HtC-D5MFWIv}&N>IL?`^&?xsiJu zJGz?sSVv7|I^Js=xFoG7d2Xv+^-7_d%GrG{v0Sb`!+`%g_LE2WWSne14Yu@hKl31E zCmln#XeCGXMRI7J?JKSF6uibSoPC@kKv2TKIC? zk%BspW?l}yaIoAGv5_(dqb-L^pA+thxbT)ks~}+j4qqQroOgM--k7`J$OuyHdtdn2 z#r7k2AdN>Zer2E==A;Qdc1Lj3>}8av&p3H|(T*ZS*D=vBGY6Pg!G^q`|3 zHS8S4)IH3~Qj@CWx4srzdQOwJ{ES&ElveuDd;p2y4g5$3j@u zW+a8HBGJR@hE8WNYcy#p>63IoXd|mf(A{A(A78_dvq3N@_-Z~4GKg3}IDL}>1HW3J&}JHaLtHuDa_*;YkuQL~ zS}!(Vph|!H0T<}jV$?k@(D10f^-6^i`alv`bkqK)S^W|>iR^b^>^SXy|3WJ`WVl!@`Q`u zXY}R^eiL-Z1|GrMYdaZY{2%+FTLn816{}C%<+89*n_mdSRt63`a(IW$E-Vh=f{xpq z5Xx?!;AiqTTj3CK6muqWduOq!&+#|ZyS2n{Y~PvMkkU+Qvkj?xck{5?kQHM-uMf_P zi-wLzfw}mp43$`Aiz>tXseIEdDd1i?bzW>9S<>ay?Ti|*#o^n6QRf@pF@GcsSqbJv z)0?ETteB=1olr0N2Eyag{dS@RjvQw)V0)Ppl#9{Ew9a{C{e%Vl z?z*hrVlrkK<$;|@P2&X@?T-pOIMzaTb3k4b6dMD)QLj2@6iZR~*ILVo%CB;iQ z2El3U1?G`JyJvuqv=Dvre>CegbyW48={qkDCH0CY`j6jVPsEh&=F zSci|KduHdC!Ud@0dyX|#=xCE{u#LV07X1!1bxMbJDnNGse7IBjZhWRqwC=RM3#SHY zz==OyN~gn|Pw4yn*fjZ>m0!nr#b}auno|jxtbB#e`ygi%!?4^MqTrl7a!v`I8rFtX zuYu#`fQzMUd!Kx2l5$M?Bt$@*;uIrHV(QE*a$K3R z0~?Y7Ci`58i@Z_+*rbLcXeVx7A8BplM1${z;fhiNuvvnvu0)9&Euwo|MH+Kudv5K713D(a zL-Je6oJQBDYV^5!N2518^Lhu}j=UBz<$Fu3ZRrZ_RWNqOkGWu6{7n@C=(7%`$}Df^6Hkg^&Nt9ls#t!5lAX1q3WsgE46 zd$9~JR!BUo=H~K?(pBFcIkjTt$$xl}7gIPP_B@u$vljFvwMLP1(BL!{R($3|83_vx zo+i~DrB`IeW^o9rA9PxFsI4>cMX;sZ@E*gV^60_BK~r4SFUL39PFBN$06O8LlVWxw zc;48MT4*avaH!)GAcngP@csT!mfdh89JMIEu= zNF7f9)>epvZY?cXegy@my3RQKdaL)v=!`>gHA2=!WpWL|0Y}pG;-q>l?sG}K9?&Bl z8l9&r45bNYw}s5nLk{OIbMzO5gMvD^%w{ZW`+IKdu$d(nA2t=g%mF8n!tgPOiN-?4 z9inIuj0X0by#Fa{dJpNB!c4eHvVvLvZKw?7%ZpgTm&lcBa$4ma49H45qnD*Od&N{D zTVpOpIrz1BczgG7C|=UktjeY8+%yALTgl{O3=Xwp4DDOJy~boo_?7LT0O=ad+Mo91 zpPqs`x z9?kHR{!MhIQMxc3OM8ea8)CQeS=OtPpQg88-i>z7;NQ>nzo+zf*ZTX@@Y|oJzx&&_ zqn*#rz8%q{vu}6xH)AG33IN!}@@71ie&c%3k0tvYy@b^WqsxIf$%R*W)b+*AH@<3J z`b1h5%Y08tN&_wr7fFBA(QJA4O}e z^a9uOekYp7HyMUphts81EZB>Iy%KEi3Zr1X%`dWsi_ly*VNEG>B>b?V0<-$_s{9d*)% zO?`*)0ST&-J2prEad&=f^62;!dyuh_NosOkih5Nv>5YT44(2pa4znnfEel229vQ69 zV2PP^+&u<^H0wRaBp{{+Nj4a>+6_+ocnMEyDR2;m{q`wJI5jLIa_*wjNU+c+KBb+HJ;rC6xgUEUS1uhYv*=u!e5nl7PB z6z4B}m*%q|M6@&qizaTw5P}|Aw4}6fc=0rXYUDCW&W8CRZ}T~f!LnGSlec5pv0ld% zM`F(s1Utc{O)WuGTBl@4UG2K)P2g04W_J>xrkCn0>=$l$Kl5*Gw;u0D1WLedCW&3w4o3(QqzDjG-H8b@k zuBA$l)(xqmNijGeY;T1O7c4Vi!Mlt65*tzaYXy@;cHZPU;eZURL3=9IV&#s4p7gzt z5%GW!r1Gcx6+qRrPKqD5A3Bo9_UT`(p`y!2978n-EztwyKs9;chYV03jt{Ws4U}iV z@3k(&Aw;cpHgB2ZIm%Oq9yWC$($aV=kDme5mf_sPKLSN6i34HGix0DDD(%fjp$^7< z5MiyRi!v}wERaYv#5jI73BX|hxZX&-Bgo^X3ABm`(xd!hHD;dI&i~c0n{hO7V_}`G z4aPf$sdQwjet&%fw0rqU;mzyV?6o0aCC;%Ba8R)A*pPPA@0PSp(J2dAjOHLUDH^22 z0GPf(9hzTj8VsAnu;9uQR`B;)V{IoCJD!m>n#u@6&x!VWD6;h%# zWOOzm=B* zV&tic#kVvKXb>*P2$qshkMQqV7^YM?vbnpxmGx{O{*b>M668D>`TF7bmdbPqtmSm>92C zeiPd~5kK-eauc1+hCxW%_CR~rCZR!XispR6CN0tGCPf?Vo^)dw?4I|(;cwRE4GqI+ z)>sE}o6Uwzdbum`Ukv$c0?A{EJ9{N#5XwSX(t3L1cFzjWVaL^aIP`B7nC%Y=2fH3Coz>Kr6w>A8Ugoq9Xg5CrS#79C<}&_?j>%r>93 zVct2*#y>vTN}*_iE~YDTvCZ&e6qTWIwJPgfq$*{SS{L}}l*sMo6x5iq;HYDPC08D! z=%z|e7%UR%d6pHV2(IRsHwP~bfnb?6YPCs+Vn}A&br9TCH3U!|d6wl`Z>dbo+w??I z%|q#zO#fXx*l4Nd0;EZasDLc{T{$hzDwGh{hD;vBLZ4epSdl^Gco^5f$cAGwB){@B z3UZrNTVcE1jKYNf?aouCk>D@ph^%rL`M3q)E4MneZJJz-baQ%Q*v{c4Yvzhl(ZecO z)o#yCZdz^s9B%n$d6T9wy~sAu`>wxCAR#rY$pws}Qq~maZ;6Kkj!o{d0PCuaEM3ys z4AySS>;nhDwMRfEB3G|C0cJj*;|y8XDag>4HHQEt-KyUnJBzUuRa5E_yt0%O5iu?{N-~-^LvF(<$z8`AtF9qK z$s33U5B)P7uJaY`5_o$yD=+g2W2jPo0!ed%%NV1<=-CSNF5ju~ZJNC1ZA+Bna)ci+ z!h0zwijdNWnEB;lc|^k$UVc$;pV6T3{)fG#J3ET}LASq@%5+Nb$=m>z%X}g897iC& z;h^L`P@X5bgT6U^{`>VDNHefEv{nEQ+3{fum(td_4$V;h6MT@z} z0;4WKp18*P0~4I5m(XRSUR=|BiWy$j{^{c=7Ue9Ttp1G`x4mJxp_n>`AJ#y5S>QIg zEOK-^g|qP$Z0WEf>REbKS;Lvh-}*tiLp%gQfsJmqV4qu zdMypFvUCb)cl0;b+0cF>*1_Sr9;#ge|HTHUAELW!I_upKY2-L{4Xy4zIgUi|#|!QE zMwzA}zCCutuUE0_Wj*KY9ICEZv^EN?F7;JZ#5NE~8zU#1Er4-*pouO#>j+FM7TFa7 zTN_VsWT^g`+jqH^9?(vUW)n4+Pc0B)J>P9HYf}-PVp65*Ov`cFnu@8{!!{<5%oR3U zloPeeG00iEJeOBAnrZ8~O~&%A@6)P2@gp+QFxl_ziBVjw&Ay9o2jU%0wYg|CRui_p z#5-06DzHia{Y)AnSN&wxaL;HOi;jCkljE78Lh$V_;9?_1^lM}BR+|{eiA8}#Kh#t6 z8Tb7zHha=I3q>w-3*75S&!X;a?G{?InYcv8Cn0n9RU60r_@!Wcxy2i^8;L8t@n$mi zyj7&IK}HolCaP^~D!|TrkJ~#wlrihNy&DScfx+W%*#xXl4$^%c0#rcxHmj;14Fnjv zsjah0a*_#kUDxBsr-gwHq}}eM3izZo{0H<8o?$6S+hUX9UzCgG4EH0CtBS~NA&nZ; zKBZyD;JH$6x14{;_fJm}9*P&S-fVPJb+fSd}g;?4|3 z>*5G4JtPXPnf&yvPdm`yI++vu`DC|2yS^V#q|MkB+Zq=O+A}OmIUUHcJJ*pv?iz!7 zoRTa(mIrxl0GQ6tr>VHv6*p=_9mT_1=r{yBTxSOb+snd@IBI{CKg*!y_2{haRfP^K zk#`X}V$JQPG+v8!-i&Tv>yY(vsC$&-c1r{gC@*HLfX$4I9Zs*s5XPECgyhep9R@=K z8$CXQP0#$?d2$v|t*N*L)wZn^YDGgl^ViJi$u6J}L}|8ibB5PUwuMqKyV~+lfoQiI z-R>^io;c-d&S4)m9SX~;Q6cAaJQf+*GA40vpWer$#JNxK!w{>Dopg)5vs+twH>=y; z=%m%R!Ax7=+2H%FIeC3GiFwCuYY(H)Oi)bTeFU2=yDwA7vO`&H<4xK)zne`u$VqNB zu0cfi+Gs(B?gjw(&}npKbbv$DQ)TE=fIS2hP1z?&|*UI<+H@gw7Yk@L7`3l@eM z;^uoC!vkdFVEgLw>VBFQ?sX%Dl^osPol)cio(Bwnhcjalww}0wl?AvTS~88|CS|Ej zc`_i8l>X0J1=rlmNv-p&chRn!(LSn*d1O)WGvgK>p<%HJ;qxkwy+3Fi=?CVGPmCwPq34Bj>g+${n zy1+UttR#Ydzu&fX_+8LXTh*dYw0CX9{h?B>yKCW>C0*~%e%`%u-usy3(ri2lP*D~; zXyn*P%Q#v{mH|eGp7XvrzfY#mO7`|e=Q519f?j$9b}=(H7;tjSknir~@dUcqOg9Q! zc&XUQ)hV!q#k4+Oxa=!kq4Y@PYTqgY78xKWHXwyCt?zj2v(7J?nL>)z%10 zcH!+ZTzkWKpE<4_7Gr0*j*Q!f&vV^2L^}I%MA&jUGP~d~p1E`>(HEtG@vUrzO^tG00LS#%EQW{{8 z8-K65SQZ>3fHtkvh-Kp8lZONG@G<^rs%7?&Ks>y_Fof{k>H??JK;XQBqc?>n9P>Ts zA$<*^tp(LJquZkiSQyX3<%}872KH**t||MWvb|VIx!a9D4$%VXVU@{Kj5gR=E*2%n z(;!dvIKC#FWZlrL6&z5PLcHl%kFIiHyZzRVmmDe?tQ<0NwT9(*w#R#83k!Il{U;wj z9B?SLuhU20kU@s+R?w;7N+Q<;ZGed{kc_=kaIitMH5xl_Y&&^l+qP}nwryK)Y}>YN z+jesD)nBLf-lzUub#7*==Hj{NndxVB_w-st2*qeBoCGP+js6PY8u4P3jNJ$l==4zN z!hK|KtRjgP%0og@d0Pa8X8F_VTW8U;8L}Y&IALVKcdwP&pdqzh{(}7*LYs9N%jTB| z!64}Xq;ozAgP1Mw5Ylj(`iQLJ1-y9Riz1kidV0m8wRK)#7hJTs$1?+)Z0?LDCPu!@j>>pV461>E6qvdmtP=i( zA32l4vKxbFYK$@nqiY(h>yaND7Nd3*%;pn=-3G>54oX7k$pG4Kq*X0mHh<)Pyx^nL zB@13!JTU!n6dKKNnDZ>p(`UD$`d8Uj6%+4=d_o6cA(f#RDHy^M_PU$Sij~+@R6blo z?%{G;Ogt9f9&k*wpXWGwj<2lbE=o6$CvpEccY45iAnUY`O+J<^BZjA>?V+NhgBb5h zm5}%p8H51(nUq<}ylx?x2zj(_4+~0O$itn~@!1dsntgZUU)N7@wl-O<-m(qwiTSd2!{}UD6VWh zYQ&^-jTgOZ=6!9obBUHG%a(XBO^)Ll+*2I=QGQh=l1u(|%cN%Yu}~z%RB#Qba?j5& z7Z&252m>2Lw4bxfOeFG%);O~r<~kDKVaEK|DFPNm)r>z-1hA_-KK(G!%?OPd>h6I- z2xW6^yj9jd;6x7;?e89pDB1BU4XUEws{wr%ziJVv*25dlMIT&x!?EGzMR8riy4H47 zF!RhcT`X?72k9KZr+eH#=aMeO@%6Tulslx3BKCYM(&(v#Rd-6z&Ro7*4u@aTxQ4s5 znZ7ZQTBB;oy@fA`cbsz{0+(U9!x_g91E%|t-LFbsYxSySF8a)_>$zl`a1{sA&{jCR}jEFa_(fb&y>xU6Owjm@8(DPGSkXoDz3uukK zM)87*HCQ#)KILLeWsQkq>ma3RI)6NrwHs!Zxt0{{l9K}y-7md*!j(sc8%=EJScsUY zXgz9Fa$nT1ZEi=LIydrgrdi}9TIiJ%}ZtUftWCuGO^ja)S=XZ4dq-uX)0*=eu;p8 zd-khhMan3fzC2fh)896-l=QiL2-0~3v0il}1r|u5%O28S9u0}5oUo=tm`CjrD|C{h zz7I<9d^2KZ5S=N&Y2o;<{e8D97u=mOoaT(=hTZ0I5*DVJdIno5N&(jM0T9g+S+<58 zkw=YipC;(qK!5^$3rG>eNVTUk+|`*>V-I5~vP=iD96E?VWmOg>ll_I?DGK%#tZN7S z)VhXBPwjRan_tv^Lcm^dZHe;rT^n|2ntA&&Z`n8GCj2NtBMIr7;p>q~#Q~%|ScG>s)C7{M>^v zJ{tK?1L@N$t0H8LNRc3D$6tpI1moNlqG!uWgv4Bb=a-D!7nvUxAIJAbN!_-ps6d@} zG$ihT7n<`?AFDbQ{kEOJ!UxN0Wxf;NLye{h8Z_v6O;;N6UKa;YX6)cwrAMZRB=e;7XkLYUlbgHOCFhjDM0JW6NX?$jDQdZZHymhUQ=rG4>$`~vUcTj@_ zr;B*IftB2DPtH#F=?vM1rnGMaq6*#obdJpp6A8L6yYF{)j#Blgh9@=5^|&o2s6J{; zr4w;fv#gZFiJ%y&N*WqQiS=nB*1+;L!CywA}&?-U_Z%VDv%?Q8kou$ zCOSVLI`BPGiZJny9jbRP;&QhTm^nP^!_kB@pleuW;3tZm&)}m}&m0t8JfAR(b-$Um ztTv+bu|yCicR7NxI;Eg zMm<{f5GRvWCimok%B@-kbD{5^&S~uab>j9PFJlfW-F*3Hy#L||{g0Hh-0C#%G7tbj zGdKVM*8i0w)Wz7w$kyRM+o&XMyFmxj1wQJFKN|_#`UVKdk$1{7tFIo)%n2&;PfhBd zN(zkn^*QXv4G{^M%O>n;e)k~i8!jGRnO5&nCilV^=;ms#IYtFQ` zarW(a28Na;EI}DqD04em5+j(eJZJ_c36sb_U|&A9O`6yd##T`-?^jc}@t~~nHE=2} zHcRfyN?;sEav5D?D$F7AAZ|=z0wv>(KOm$#im%J>fz0$*ic$?UgmC?rbs-9ka$%%) zXv^$09YcX`3Q8*Ikh~~Q&BC+Iq~0BQHF`WlT{#xu^DRz39P%U>mwWlmCLC+*ngO9Jg9jYftnkfBlJ@y>h#-PW41&KWj-+do*- zVf}7QKGN3u?ddW+3j5Mrffc2$%ATph00VD~aI|~mGwN6aDMI%BQe=FxNnGUUvEah> zhWmW`5DWeR!4(BX*%5$>-%#c9JvBtvC+G%RWU)x`t-$T(5@t`(E5-#~$k6p88POhbD2SwGuqn(J)x3E=1CtRJ?z@52Vy)(yhkJ zc@D^(yq&wnFm@gDvBE7w1vCmaDvB&)M4YU+g?EgP;yAFLM}2|v=ZFJZR1_k&&PS5- zdB(;7h4NFLxHc1}kL50g-kcDTsvqlTAtqPqU#fG7F3^7;T+ZDr%~tZfY?ky5v8RstE646r zbie<}VREg&)riq#%l-uYpVz@!*pA}r_Zr;%IyUV8S>H^X^3UP-De|~^yWGOr0>hyE# zPNM1#r$jz7fM`7Y=DrH8)r=ac%jQ&5t(sb1UCx>lW*x-d$|-U&o;KYsrZl%cP9oP% zzMXhFy9`3#RIC?^H>V@l{u{F};;+|up8_8Ik9q#XDva@eGn1V=&40YVk)q12G}X8a zwSw5hq`0!!1g!#u9jqK3GvgvK!2h&-(_anz#$T(S|Nc(!|8JkvH@BtL)it*ST04S=T3rnZ6*kj%%n;h7|x{-oWdozwfN+mOJtSXT%QU$Xbs1v zb>wV3^xHW>Zj=Ydw(}!RkMDi+P2(M-+SBzl6kj%}(Ld@tap%F5e%?q7~hp3EERwD`aMOi9R;K`2zo+J8t)kDhUJu0MPM!itzr|9XGTxH@0#5&xWI0 z+HSDidisBZ3w+6S)E-r$*Y>3WgNUbqX?Ns}(ZOiv(;-?rrU*wDUX}{KY`BU>AU@e8 z=s%%F9(LWh!FA);iMcgvAbYTX-MuxS8NE;Wh+Qci79CbJkruc~ZQrRuk)&Wg8`BUk zX&Di)iz^!VA;(M6w;76ujrQE88Ap&5jv|tV>oDG5-w#`d9%j^e-2hkrgALqro;e2E~Zcfkg!@S71j;5=aD1$qo6P~^l zu`WciYgXx5{y++=paTBedfPJN%0z8uilyv-Yu;x3{fXhPyTVgv1X&BDtRytYLv6Sf z20I~R319f}sh*`!)b62t7>Iw09TXNI>eyWXe=JhxF3bNbkOj-eCkRuAIRGW?uC}H2 zikx%QPa~XbxruJeV>LGLso5F}NiVjM8pQma0mpe$OH92vLd*`29-=2hvW1vJ(zd(H z;Q;J@407hLI@UykNORtKnny~bZ=llXGS9+z8zBe zWOfBqWIVxM-l|x4$lgx9AAUph6Q-4ega6xLdjya!kIY~)ClNsy%g}C|0`0@@Of>?B zLf*zV3k(B(=A5pQ^3sYE!5PHXTP9sN@o&t`Zt22SLC-P|G#~U7RFl44WPP#b7GP<} z1!(*Su$$+|7k4~=&+eWniKTKAIvqaj%4~!Wa$)cgeA-IW>^6EKFDzAxUNM+T>~@H{d)f*k^Qs#< z)}&j-;(16{hg8>8hSG6kx3kFy&ciF)Uxo9Jb#=y)wApLSu;ppEkG_)0?ujMVgaz1M zvpoCI3~e$qOuSzl8ZoV+;d2n>Bw`ud^HDb1TYt90Au*2ZyI42x0CNGlM2hSiIukJ|M!J~~ArSg! zHy4cN1e`obLjcdOINwjjpIw?5;3XvE1gQydBa1!{6kx-9b20n;##IqZ0v6dpu_23K zq=kbJj)S=2S8c$zH<5YtxE#GI%n!^H`YG4TX!{TIaWj=eZ7B3KIE=JfWGG~ji-I}O zFP+Cchg=W$;TUAW27J=o@9Wc;zo;k-+CtJj=S(__Xl4pK+jW$(unQioz^GGpteCEQ zh{uBOg8F#PJkV7V@d1T6{8LBaIEZM6rl*){;4{lmN==LlQC=TX8ZJ3b>N4;5E=La{ zSb8jM9bSep+YrFm;HF7GGj--%$U=fj%~ycq@z;B^`nSGFd0461OK)Cr*^$6qK>IU|O4zLDv*VHD~8-&x(09 z&;^zNl;_?`4i@cZGoOg{`xl2UZ!E#&jdFP{IZqm;K&`jYsOiFXiy;{S(%D{$0tnSd zEjY@|`}80<#x&;AiYaChW^;@L5{2N=nR-Dj(eo9tS$iMB`sB^*`G&xeuie|7W4-W{ zL?S0Qj{f;HV?*R-ojV&55e9f_Syf1S4o=A1z`lwBy zvE{QvstY%SSnt1kYbmb=3I{a{I&@Emu4kCbrBlK(mY-xA*8aD#)>r2wKryq6#VZ-o z3!;JQ@`75Wiwz|roq>ZXZ#`)vp`S47Bk5llgV$`pTo-BR%?n)OLv6?so{5uf4uqAp z&(O7D>3PQeBI+iY#r*6Yg&*<{(Eo%FXx*TYCZNAjDHiKNY;8=;O`RS7U%KNe zRqbCCf$R+z_hXmOvq)n=asg&VcMOz{RXDspDYgJKz(F46MD3U&9$lE_G4QemBSS{r~0AZST@-bQ6dQ(=mv4)R#}(=EqJ3$ zgTkm40Z-EaBS8iW#as?cny>wtGD6NoDi;QVl19?sv8MgN5%dyv75HZ57dcO+dJh)` zOHKhxRTxltPr%7tMLBQb2q_Q&WKJ}AU+c`m){4{bWtpO&WV4c-skAgsf<$4V)<8X2 zNnU4ImQ>{3OR{12&zR6(RHlv_-$-HM8};bhAacaIlG^pPiP6`iUd{p5BvaAezlLHB zjArN==GrG)S9pO{bs^W3b)|~vqe2c{0RsJ)Ya|NVO64fwenh^dTOZw8&V1b9;QsFX z`Rg(j>w=%&1%0@LjE^^$SS2lwF3Xt1z=Lw%CH8qwrdm!)6D`uy1JP8gI;O{EMV*9}CJ@=uInnK7g#IpNKA(rw@aRCZ2_(S(~T(hNiVfoSeBBwyb_> zV)Kop2IN7?hQb;cW&s{oK2rd0V$1^K+4ZbW%QvkHOg(x#IZtB_%36KgS#KrSF47lO zD>+b2#SaWT8_2AHqiAj@Fa~ADxHbpMsCyitzV~qyo~jrBrxh|5bq!Q!%@(P_@jU7g+T9oJ-}QW;*$Z*6}K~agBXn z#AI)XaWKkTJ4#?G8f_1jwij>vt4R{&rkxjzfT$!fKcx-aJ{0{~@2X<3bwsv`cI@zuoqWbDbg2qGQa2 zP6HcDOCG=O6wt`qP~;MkVj1p+Vzmc%&>ZD>UGLrWlq`f)o(9@610F~WJKIIodhM82 z8C@g`vx+rWH3R6R#gwS#FlA98Cdk9_sNc!d`bjO#sRw>x7grK_{*k>}rx0)OWFXu0 znqpVU?Q<{oiOa@5Md9`PfmMfyC)A3~6JYVRTCnwq)cWxq*QbT-=ey^(cXGz#(v0TH z*nMH5)6Bxy?4bCsK9>|+8@nv{93f7kn}sdZ%Oz7}59m}^5RD_%P*YbD^WPpGILjdz zA6E%YLkp%RXZTYil&Yd#N+p+G47?@z+@CL5c$Hl6z;_N#?Dw|>j4f1!1j)aj#goF) z@r3#xCWNog{Uc%f@8#ivBK09S^xJEa2-i@WxrNEKPPk=Z^Mq1L+bb>G+s~JMao1i~ zTRfk9&ytoosVc6vI5{K?@5l>Z#M%WTx5W&&eI*uN+s_3Zq;Q@#(xP#U>BY?)U8~v! zp+12j*B}*~Lk3=&?6?z%O%{*B{kU+vx`%f^s|JWTZ80ed)$e1^I9%1{XSX4jqNQeZ zZC|5TCwG;&;_d-E%QT|yQ5>^i)n&Qi7{>?9*69E9={;!_; zziSa4ups*C>ivMLeAqoN$0L>X0`k1t@z-yFow}e&U+bXykBc=?=wM0p^C!(0Sr!a=A{?@OLJ z#h(awT6sH;m^DTH0{Nh5VO)FCDTwTXltm2enKE~nA6V=|x<>UmCY(+CRvAVbxMD59 zb;{;2ZeJDzuV7``B5R0qu$4-E3WXVYlFb`4`?Tz8NRIqeLq(f)uSip35*Td~6#C`D z7p5QX6G?YT!%3qV(_vf`w^(ed8ts}1G>`MJ$v2`25D|*+LstGI?W8VgVUV?}rW2?` zS=6TtXw20UnX&;txr61kZ{tOESzJUzeCD$xt+HdWN3S3T0rYYIbT{{0HM5Re>9y32 zoOleO`VmoNdDq3vunt8rRPM$jTJ@nJkWi6S)4wAXsf-l|N(p?p778JFAl388|3#IP zW1Y@>4^t>I5+~aY8-L>)@-tTP{u6i9fQRhEN;IQz%MpgL6-y+hoV?76 z1QqYKSlz<7ms;JrW7bzasy%`4@$T>$G=QW4?CZe8D`@a7&}AcPh`5Gr|8V=V5BUbC zPxPaOH&(Z)w+KuYidCxWy(V!Nz&f}=xJ&i1&Obf&&>Aa%9&9b=Qkp`C)B78~oSf(? zU`KyXMey%er9@}IqO-ZP*z{wN<+N`Y7gXDGp`cg~I@`B=C_TK>;8P2Q z&_N2&_=LGT?k(@G8))e>V_$%O5dgQQpAWnDp#e2xC0`$dFEjv?pm~j=SU)pDs{{!N*_lU zv~q{eJ$8%=!g6R%K6dSrY{yCX1T)`fzqzb7k~cZG4^HinT+2b93FN;)z=rcdw$Oe^ zK;+Cr%yDJxk^+>Ii+m~yU7Dw{mL2UCJ9xB5g3yKa>|T00*gN$xp9;9;2%9lklb;%e z0QHGGJn>uB3~ZsqbCuhj$xTR>-!i>8IDq6V zFx8SdB^#Jp0FNG|3`j~|4Lb}h&VfTSJb?*uG)o6tLd)^OlQ zVg@KVF%#%d!iJ+3(ASIT1Sly7C^-vArAje_^x~O2fR4mMFS2vde5VU)*xy5cEIXKX zEh!~QYD({~P45}Ck76Q8h=2-$9h9ie$`s5!tF-knV3y-3`Fstw+x_NU8)gIKEWTRUotvUTR1Vsp`hGZRCGxxNz@A!xtc%ZS&wsQw4ZTexP z)bU5=9Bo2;!B2eSy|`)UOZuaAuBXf#>O3PrkqH6(=VVJeFJrp4nvqMGtZ52wc6APd z;eEWcmt$NimrSOOc*sc95QNvD{QSkCXBQoh5Gn*d7)5@el)Rr00F zCQRe55Pj}qaci_x;!teGycv6_EGzBi_K9z<8*9Fa(lYffW`&K#Bc?(sbG_RS!h5u@ za@8++H|nHHhwQJ%oQx$P%JRF7afY$lZnWV?_H`DM`r|%>M1sJvjO#wF?QGRJ()iWg zobRy4Mp-?k$A^;i(M(fCuY=-xrID@)g)-5NZZxi<#Omm5%$%#^qhJjn>m>3+Gurc% zysFpQP*%Zx+D^af9EN8XB=)btAz+KWv@(?>)KjoqmQtbio^c8dc_zk|{?Wd^EL z`=Yc({T9AUK$BUm;CG=p^3>W5ag)@1+D9rc7 zJviT^)30jHyqs=x+`d?@*xqh+oCZI9FS9kQ9~f3UiMf8zwD^OkpBU-IoLf%|yzh$F z&eql~HAVmOsM>5&66CGs*n8$5hA8}_$e3EWuu*hVkSeJc%|2dhHeV_$unokR%Nw!H zj_RCf`Va895j#%*xFkxoP-}_bSRH+d%%hadgA*6Of}GM#_6tEW-O=~ICI3->>j^@X zW}n@^$$tkB007GW4I$Xt8ULR!&hdZN0i-SeQ(VUS#0xpB$1=#B=*R7^C(f6~TGx_* z5TT5=ZqkX4JCy#s;jDM*67Oh~`?ulM>28}-=onYnXrAI-8VTp_@@J?co6TC-#jf2P zc=8bYy3y&d>`#_!N)|+h6r`#)xM3oADDKuDWsJVuMxg_Fep_S?2 z2wK2K4A05}JaS;Re*nzvrwVW@?CYfS#4-d-W^uuE6DDpXcF)d#UIfj?3Y#w$MQ8{# z^)Vl7QGmtfVjD=<(ac#_BeG32^pUwNx2*$b<4wJvN@a)LIj%YEQ*UlMaX75|fs&pL z7WVGf;?1GDj5h@J$1cnSbB@%n%%JsaKcVoG_x3)%+BLQ+RqU1%5<|N?$^sodIL%65^iio=aoAqV0 zuy)jKHy>2y;V`7;ogpUS1!=Z;ITw>VI(*~2NzP*e9Wt!jBFZ(juodh3cDi66yv8-- z1NdJd{eO-Doi1K>qW}N^kSYiO&HtZc@Lxybw?J^^ZE1TTmazK*_Rb5B3A28k*i^l~ z)>jF5mEBR^F|q=O)?V&vS4uIOlvK|y9FNI!`Ap;C`yni3k|54Nk>H^o3omCZALS)1 zA~H-#^s`Hq<4r48omGa`VW6=YT{D12)}s!wG`S86PJ6NL~y~^;y7*z)w{y zgDE9^NDSBic6J>2?Y`TIM(8Q#BZ*CmpC*j_EhvRZ1~o949vpuliS7m`>$p~Wxv9kV zLI^*LU}pSj<#cUgr{cn=STc&HsuD^@*qqv>f_hdV=?3~o4P($mJ1!1v84UOmH9vYm-)=L&-%o$1%k$5|3 zbbo^!s-WBJXN6e(lW-q23HkWuRx?cm>F&yQR>#Wo!7~u%%^OO~q4T_=%|_7oY>4`|KV5GvbYW zR54!-hBGV}Ff3cffW@PzA=-%8j^Rl3(v1Bd+upN(Hzm10Hy<0hJ+OBC!2Yqtqn%tU zFW-{rpm@S`QwaCjC(v4m-g=5aW;#*FWw~y*)EES=n9^H=Q<9<31Z_rK=tnz}NnA4A zz8nF`@Wgj!`(Q|?W=UWLVlt{dxaSDysQ6qVKZ9mq+JS(iiJ?U#{`g1)xf;Dw!q@|} z)cBbmRQUXyOm8 z@L}uOLHzTm&49(A(u8Wj-sW*^2$7_%CSF8~P{?Mq%SFA2YItfj-`gM|S1f`QldQlN zgUtcIvRDIF9XhHKu9Wr29x?sBju#Z+3wN8q9#De5$i-uX!8-}H;YtfbjVLoJcGSzE z0ahzEj87%d$dDJ|XsEsb=>1)?)g55y;uzL`27oYaA>Bg-7bOlOOIBFN5Y5(jLve2R z_{HYZq13{ey~r7)^-(F$>4nWk-hjK&RAXH6 zdJPo6D9EWzw2Mo_j`)a$@@Fto&c7fOEbyF*Wmg5%ufTAVV-Ca*sY@q?*+gKUCTK-^ z0>Yr|lKcFOIK{#2W8?7Z6mwRP=w6&5jp> zrM|o;z6ZX(-baSt4A(hIM?SD1an@J~PEbKbI>AId4{7<$b48Otd3NP|0;zd96ac_G z7u81Q*7W#zUVM6e>|NCG`^F%lJ<{Q$$tCb}rf8>mlq!DA0AD84xB%Do%DqoJrg7W} zroAhUWJ~#3#`|ysmqX^-Rl|m3xXGn$^ByK^$pfpp{tzictYDFM0D8fKudv=6CN3i0 zbVo!d*dz$4x+XYpvA+tvkM*KAd~%>Lnu0vSVtYEFLi;YecDodOpnrRPy+QV5bE5t1 zePV<4_eP)rXyWZ@rdey*nu4SQ>q!UB1$ltsvw!L#&`i_J%+2a41xyUYPa*Khrd%pp z!UU$f_9#Rv)oU0Q!&NDmtFV=;Se0s2C|M(yj2l1wkhMtf7AOhY|B=oXojPF4;?ZRv zh0pE$`*;gas2X990rh4~Bco5r3B;5i4`AIo2c zzSxCo6mhL?517C~op93Y9N9+aX5RKfosrdNqJH|o0&w2eFRDcnem?^3#%8lUM6#DP zjR(y4k7grmHe|Z)L}5fz(gbe-u6I?wqbH9IKCj-L_Y3Iahz_6}%K)1OSG#^hxyTKA z09E=UHRgVw5IW8huS#fHUG3%gSITWAQXlhs#6lTU=~8G&{8B_qnBxYka{g6ji+B>9 zx4E#llMevNE%}C2ZXXGmU&jcb?^iVfS`Sk{K3Mcj$QlKqpj=+))mS1S&}O!><%v=p2-}k4Y4L$-S(N7W&jR5;9{qHU zl?&TP`lCtVTwR-ti_!vbxCzzF1u zlp|D?)-PuG(zW^;GM?`FFrRhGiErs^vThg#pM6q5Sbb>3~|VZvxV)#QIP zG9wzBD1{a>lvB*l<>$B)#x#u+;~^yMME^>}g0$OQ&5RH`cch!6%TQ}*A^xQDn;H$N z1mUUE$1yPA2j=i;It9@AQ~z~86?+Z(X+J9q!;8?Ijg9%F z7bT*S&&piYW1Vd^h+_?-KEx#zB`04Yo)M!^dUq)jo2P`pP!>NSbKCeZn)im)L+exm zi@B%8*ZxwcIotR!bFvG@vE`n#uv>qomoh`#n@i&72E`}5Ao2VisS+6(fVl*06gjE@t!OjPMhM^fS zql5<&_Ulb{`VbJFSKQ890Jag;o)Vr3bKvc3#Eav=cOtDWPY!mX_h zZ%i(Kz)xd4w}D`W0Cx|GkRh#Ifhmg&6TFUflCUSoB;L{HI5)q>XuZ3Lu`*^C zmNgcOShITV6k*A>Ocn$PCLlE2Y5?UGumWfQNE8Ron2bi6LftOIag#PBq$bwtdhaq= zGfQoge-*5iwVoyLf0ky2&lcdEeDs)H_2X0j6^2avVnGDVYZ_aZef;wC>b%Bx#J+_KL4dn4OEootaly1~kEg zif&$n!n=GlW#hr95FWRvOsr|Yz1y{EZ~<^D*eEq;!<22>)rPh}T1L#Vy7lkFDP}#l zaw-a}AI>>np!W3)!$Ra{T#4fyRZkHb!0cfTtlAye@4QBZ?!5lI9TotE&Mns0szx#s zmM_Jp4uzrFms}4@jAb{#EAloN?>xe66cYd*2Lj+b1;D38cISlhB%UQ@#`_g0E7Qsa z*NKOxz^_`AmY9E#2*mH z#rK&R$wsTi;9D@t@c~8Z+SP(Srfgb+C78-4{WmiNI#=Fo1NJ(;6 z{-I3++l-i-EEG;tLOU~_q~kelHzJe)P9|Uo@Zrerrt^GU-?JtI9l@y~i5ij_>|YkF zP9}7q%N95b{V1lLu!_xmaD@j#5MyMsM&xofF(SM`xM)D*Uhk22&e8l{N{^GG@8|kF z-QK~eMrB2l_;^<87Bvs;m0F$79Z~)ES9Jz-&5e{~O*5Gl#`cj2k->5a?s~sc9Tdu% zNBM9zNe|V_$bc4?elOF$v704le^>zZwERY3VV2cK$PgVwN_7;HkhB7%jM`5H&M?7tL{%9QR^CaN%m|1It^?(?V_<~ZjMsiN!Pp5ibqR-Z) z9628WP#5JEWFa=n9K3D-@r<5-!yz!>?G}hZQG-r$<70tie_r43?-i9TcU_;{U(tQ2AVwByDbImU|4mL7=HR@Kjyt1><6D+r z%_~5-3NsY}r}ES(17ZyNsKoa=KET;Mc5~6W#viXLs!Ko&p`HHQxJKJZ1$s?_RZ?C) zyMcMztiyPKt=$2jyOZfzOf(E_6@w-BAZ)~kVS*4X`zY51S8#~RZ>@vonu2^@%h^2) zq^8?&P&F3p*a6@71dF>S$`kC}k*&VTu@gDixGym%F4>Q?ev2CK_Snz#oSV#BZ$>mB zg%1_EavzB_ehJUdfforunPLLTuoWAe;aWQJ7T-IEi>RLxI{D`ViamtiwT6cFV^9e3 zK1%EXD6F)GmQ#IAiM6ZOWLVxY%8|UsQm_m24I(bV&2jhS+ABZW+CmQ)zYkJ;@fJ-8 zg##hbIW6Rq&%+%8rYFq~_#_nH3#u`HNEq>yUz_`{$hdONg4~i>#-$Nxc@w@c!c`Na zcmZ3Ik578wKt2<~-zo@y{ZIx@)c5_cnBr3|e**5n)BRa{9$>P+(Gc^wkA`O4d9jn= zGuZLwTJohS4G1LhX%I~Ez{aQI05a6{5n%WW&Dmb!U!ao8fE;tH!xo_$PYX8m13oL+|$_Dp)ZjKti) zBt$MJ7_(x{qN$4x^5$NZ-q!SDm^j*NOzIoBnUuPNT5Eb~S_?Gh4d}}Xe3Fy~*=79+ zK6!<;^ULgoKaz@k6;5J5sa2?hGG{;YSWU}Exlh(OR+D;$U|5W+X??>{NX#aS*O8*8 zyQ2*3WdnD7c(_H50M*q7EF3sqKf-(!`|@$m_;S<#_yXGjW(*uz6_cL%wj&yODg&e} z1~@3Un#8s)w^{wwb#w%Ewu7v+#a`{us3)4JR#bSYR&WavtFNVs z(vj;NisuRYYzPk$hbT-Ce3L&L5*{_V?31#?;>}4_ll6uI0gG;`&1sE&7Xm6yYbR(mNmEZ8qqT0d-_ zuWPHFU0N(BGykc>bgCaas8nBB&$g^$U$AhxZj@=k1ihGUtM+bRGAnq_qRh2n)_-&Q zosJf&yxNmxTXHtfmaA61T~c%`cam_YkDc8Lcjm2oy2Z_a)4Nv*2T}72^kO_y^`flV zttRv}|7(>8@;|yg6 z&#s!DXSjC+{S_S;&#)H`&oB;;XSnuWUJE^gTw8hTi|Jak5~TIplQ8O^jL1zP`0)|k zAu6ZEY2y%D=89e9Q$x3>gs5wzW6v?aj$_xox(;f9I)n*IhNIAKGPlr12R@-w{HDJe-D!w(U5L>P}tv&(wwla$au?pld^ z5WfkBfg1caaD3#Yesg^I;Y`lzt93(M{jYJoR>b0y43dO@zY2uahT6o=wBlB7Md8|G zrO*#LJfKmFR}_e2*>JU(yEiL>Qr_Ph)0eWn+_?g_&X7f*G3uWr$lB&m)Oc+5i6V9u z6a?j90w8XbzTBm#L2YKIf}~lxdhLgEnzi5r)RtxIp9R0I7JSA(pKjs3v5A`;Exuu< zcqBbUJh6_aN}KZ;I|{g37wCT?12@z%IC)_E1F)eTs7CAXT_H5{eDv_hMjkbADid~D zu-7&gI#7nz$7{SjL2L}!C`EI-KVh34C{HM@)(WnZcrN8lW82%R@4=r-8$`XyaGfdo zuw%%&2DoX*QAwuCEs$)mR4p0?XRT|Lji;q<^BaHPCJ&kQU>cVve`$P3)V)-iX4mID z3Dgy4D`gv}_EDjPG78|C?6A2ck!Ytlsm~jWx4i3%zqpZXg;eG-?*SXLyROg|E_b?C z4elERu)Y0LUhmM@OB0lZQ^Zj-1w4!`N{;JMqa=N*4FG>OXU09xFv#Wo_*^^jW#IXt z7SrYYbG%7bJVT#1Qj6YhY_6+Lr%A?^bW|@*HMcb!P%kuuh$5*ZN-KW`{(NnZd?Zsq z&aN}Bu!1`xiF!Daj5CNWKjvfd%-E2d{x$ik&)e`>o9oVa#-R#Ro+M_TUiEM^Kw-U= zoRNApC8A8H30xVOEml}$eb1WMoLE4kj%i|^R;2%=|2ytkOAa(oUD^%qhg?dZ>pe>j z>7pVgQ%Ry1yq^Uf;>XL-KK5Q})bnhqP4+9LO9Z`}L$3#xyE|G8Xjl^ZTA?Ih1b4SG z+!QP_)rdSnce2{%Dmltk*E<@OJjx_c$))N`JneD>HiCj$5ykE9rg*yKQb?1w?d)Y% zqiu-i6ak}^;f3ba*kxY?J4CM}MNFbxfF7E(_S2(FzF3}I(?rif{=D>X(uL?nJWv`m z&{z?P`1q~W0?;QCJ9|5EiW0L7!s(yOj?F}_l>U=K7%sl`<6)POMhOSKglLK;_n9JPKF| zwYY2s3X_Ewa7!@@;c~aWi~FZi)a=YS`(}-zx3x3bgx#jKd`Ye6=~5d}lF+AseZHDp zn6=1BzxQ;3JmBS(=$3YO1+#L7_c@Tep**dHWsCUzTn zY}zrpzcvjdh84l-pgM*(K8iMT^um=@x|E@93Bk&teFyZ|T|3M-9NHcaZ0p6G=23dM zkvQjJ$c)gJqo_aopEeY?M$S{!_%b!oVO}Z@cvn{EX5)g{eqbV<3{U-Q*s^E~c0)x4 z#svs^i-M$8avEp%754>><~~#htci(qC^OEo)4C-`C4KF1FD5X!nO&{dh29&`m^HZ; zu68?l&0^O`tP_ucYT-g1>x(5n%^h=4s6vNs#*-yb_FdTipzq0rAmAd?)lc-$ZM9`%4UvedsBn4#_;BU7xmb9uaOfv-Kf3hljZquyPTSg5nm9m{X~&^v{AG*cNyUe&1~*q$zW*fcCgY z#BP_2pmKpZLjh_^@l+7G>hb@9G&!wIA_o*!k}o=WRy`mgIO9>~7*l;#fMn6xrg4v1 z!Ei9sOa&4GeM2Mr2LJV_gM_(zst4%+BW@3K|BH5J;R=SIs zIxPPS()c2Ti_%INas!J zB80j>CefEGKaR(e4N*_o0Y?Zb=q#&-KI>S33OYF+SS`0wnhzMw$+~*soYU{^F?eVm z7`*DLqUs-zUdX0KUiE(NDkp5vLahb8)K5lvC246J&Rsq2a*zI`aIO{=@_0$P^2VOg zbSy>07I%MUD|g(o-`^>_XxCpPXs2Gb55jfO9EED9Ql8w71g{$*ZkDIsr!uLfD8b2! z&ewJEk#KCB5NC>>F$F;~peVU*1~@=9T~Ffc$i7imS`}MUNv50nUtE(4IWgsAi#!2J z6NZI}>~1bIXf$Q4MW_Bvq;Ktr@U=dGPMW={BgdKXy2O&$#gAs{uBQZuLlOJ$%77br z{8%N8-KOwwCDc`d-4u)oo=QtGJ%-^fkwo7;^$%dU3CbZBo0dt~Do6}#sbuS<>>wC< zCvPxUz}cjsgFCEYwROH~x3u|x82hL2OrkAn7>$kYIB#sTW81cE+jcs(ZQHhO zcWm2#_TJ}w|99@rMa`P4R^8N7ct(ve*O>W#I1PF-)|sPeQZN^OTS=sqY21kmVKBao zX7nG7>f$KX5wAN?Q-bZaSxug5^cS3!&%L6V#w(*=d{Q~AE3ob#W4tH=7c2WleIHL_>UQF49B21R|ew2qx+;diCx6+~T2gqa6$>rai%*$b%P(Pk-VZ+zY za4_HeM?}&wGcn8M!tLFn`$c1j9+nw|=!8Q~tk@0VkdaE`%6YFF8ZI(;m_dS1!=jDj zt`I+q&zpsr8~YnGuEC0?>CA0A;gDS`Vxz^_$>NYL#vbV5Di8RwDue34 zsKj&{EAV4UD||4i50IvBakB||QKXBd6|&H*x&L26k4@)yI8xH@I;@#m=V9E}^sw+S zjA2yMc^K%Na`6jH(r(-zHg9C`!tob6#Ps`5%VC(4F>tZ*n5-1)#y`43I+bmxi%0(> z^Q2-E9>q}(sg7+0NI35DlEnCu9M?sEDb^dL0&P;kjRQbqL_0Rw8rw`$?%>kH+r#Uj zo<=YJnc8MgN5P3Bi50}R`aO{lITN^2OV1HY6|hYN;F&W6*!5+KXcvJdl_pJ6m&K~_ z1bqD!|E@!b6b7o=5^9{pH>L z6@2~5K-{6_U#!6-=N>;W)KWL!7zAbLVO3Gb$`{OJ36%?y*N(X$wK%RxGM#c<8v-&x zB>pH|N{zI&NM+>*7)TZ^>1>#+yt1BM3PD>R?=V)m0BR}M*o5E2XFy0mA_OoeW5?`l zDvQ~3-@&rER+F;#Kx}A`NUkPJ4B5ab1QaVE7T$`2Y11F|>WraES) zVscKs(vJVC>kU{Ol8mb;*4F30*uj+x^P&|-X#ObHm3OLAQK^Ux={lxqP_{aDJ_x{w z4tpg&WuYDwn6;E;M8W8ld;}fdx@09-;7L!_dcrqP`49ZlA%wdM;(}xDZn73xx$Y89 z4BSHWM0M(Dvte%8;2^j_wQQ{d>eyNR9KLGVckSug#EeLBd8ylv#4){KGaSL>oL;pb zj&8U}`~MmLamoBYr>r$=LA?1pirD>J_B0fJ%ar!H&AKqF%XPcD`PSk25}F6|5kqJC z)>m;)ClZYcD%EU{25bfnUGxBi&Y7{|N@YB8@k#Bcjw(Mts(dhPk2>T_e(@oEQheKG6VFQAN&xuM5+iJmK|*vf!&u9BsLX2RlHah8PJO*c#~5jd@@ zt@9LauivC-tO!!~`e;mc-g;KNRaz4U87`=OQdPO4&Ft$!^QeQSv?|9Q!e^<-OfL9%D9y3*pEqC>_4|=>3bJkPCMc^@_$gIg@ zW9l+I6i(t@9)?Ptp#FB2y)NUeOY$f^k3zh^(a+wZZ)H&!kWt*jVHMm1^9=3kZQsK0 z5%)LXwTG>jg;W6jR=l;w0T#f(*^BWWP06O>9w7J963f=OB$)>ayhJ{ zLgc*|Pr!3Ibap%hF3I*xl_Gi&WyDi~Lwvtl_mu65R)(ligIFIsXtSw|IVtV5Obv%e zTpLtSO$4}>EB=B2=_N)&O7dg16<3uFf5qJth~Is{#Mrb>b(#cfLjKcvdiR5=cl z??EhdGs~QN9S?Y{i5{iw`x+ILn`a%yRAC`YKjLr5qAGEq8=~oY{c%KX$c!y{y@NTD z8R^f0G3WY2*)bg*H?hY5m3QZA($-)Maa6}wpv;0S{Y;0FVJ_29UHT4{x;MXglZxRJ zoOwfu+&SkgDdXlz`cle+>{W7Kx3rsh*Ku!BThpy|H0(JNwFd0Hs+C^^>H&##z=3e; zf>ct4mQ0-Hdb$1XV^>c#;TJlz^$6;Dxn|iDXtYUMu%^an(=gv|v?=MpR6#w_9$?^& zEqxO(2lm)cEQ&rGS^z5n@8|?9if;G6(AQ1;FD+MY&z1&q2CJMWc^Gk#oT7qsyVnho zEsXsgfhrBW_fwS-k@a1sdyyR&abih5N4?sljYC(JTD3t-8ZWt`L-?}XvU_nFy3r(R zaMfDs3hNA6V#nXjK@4uz)W)8{%`w*s5&y&Vp-U({d0|1V-ECC-wNXgycy)dt?v9ne z=e6LpiPg4@S`^d?0XhkXUW+0aHj6|jtoqi%j@>1~F=w1<+uv|IWerM-M;o*pDeDH! zwlSAzzS;5Kh-9T-(F${?rZ81cSfeTYd}M`tv#)h*9w-}_VzrtopNd?wSDE(PsuQa0 zh~+&*VR>Soikw;(pvwyXcJ@#ifID{_FFEg-T>fB^u=S>`o28R_=W_K%>6#j=AK@wJ zA}H%mhu_fYUU5lX-)9gMWWnPDrHDtDHn)Ps94xBzGV}X_MLj6oAQbP!rEKu=BQ>5$ z4+$(B*ZEPF1r=lNcMu?L7Dp}T=bv~8f3gc$a_NSQgHMuicvQ$W6bf#u=a6+#bFJC9 z@vrs1o_)^W&Qm3@J5_N9_EU1oKFv@dRI#*T{aShu!&b?We2o@aA^RHgM|z)V{~k2G z^mYrU@%7U~ZJMWIp4#qpWt@CskVGjICCyISf;SQ-Le6>Y7Nd(?=6#BbTn9M^;KWdW za~V6hR*MA46CGl3mY6-jzbWd++aiX1_VnL5&UOp`Ejvma#wJ6s%0dr|sDrI6-T~JF zeBF?Bb&YOE&B7A+Zjvft=Ru@`R&O zS~K&yZm^?;^kv|Xv`V}pnHczlIRI}Gl~ZTC-YBiaXxv`xkFeD)l%++`t_*t$J)wLD1Y$@$pU~leB~x=XbJs(}JHe-Y~_ytOw7D$O?I)jaJjb zyf`@fRIT!Na&M`=s>fg0&R2OkAkNZcoFB{5nX{tq_+cHgC-W#A=LRSe?o~PRalDXF zE>u^MBC)+ZSf-&Lw5FXXIR$^?1VqV|G{J6~hv><`V579D+!$yt>R6)}T(1u06Y$J^ zPv1zyKexj?<&HP-=+tef5lZ*uFCXX zYrRzt*gDH5?_Jda0ff0Q=spc-mD_Np-~-|!7$26P>8gD}?r95ky;Hz>G46m8` z0=2-%%!Jt9bpZ$Q@iHc4ITrqZA~Hi}d`hYE2`qv5g#SM{ZRmeEE#bCHkCCTBwS#mH z(sX`55-;;M@Q;t(FyhD0_PQI1XK6g&fevlmW>1J_?Qlw|zFL+hBJXWt>_e^5bS_)i6Ya7B5A9Mj{K;aUlcNvUkiVgeZF^k0qnq_P zewYaOr-&!hliq961K}oY_?=$D=Jz5R=k@eoQ?d&(-eHi{qM?KZhF{qS zo|-PQ15B@O?4X=w9!Dg@PsgYK8!7f(5jH*LR^y_c6S)0P$lD`=ft?IMY3i=d5(flq{2C4Etrb-N0Lk9S6$_$(NFIpI=4W(7>*k~ovG|Q@!5n~R}>NXK4yUb3O;SH_ZoPjMjbAU(z7=q4;_9> z@c&JH<;!G(VKjjowggR&>N}+p2W!8l&r4N6KOnm(llg-G3q>j<|!uOH9M*hzlAh`#vMn-n+j{52=H~2WPLdb zA+|~-@L+8^b=9|Yu-DG{)YV&bjpi}mBO);;8 z`6-lzBktxsySh8oRIFhZ7mH_^Ch?&<`@-Q0bXT763Jjfe(?}0bzRCNT8@*YL6>J`D zv6{7JPph&5wf)oHXh^CmQI=M+T}rx%PhIT-P0=7{k~b;f+AHt~x`F*Xf0QcwdNgk~ ziK1;o>`qzu~EQ73id zU?Xjff9%TS!v8poE%U{G`cNbUL0r-6+n)nsEtl>}0_K%S#1ao3WfxQFzeL0;e_yr; zXT_)lzMew}Tu3Rx7?q7hVw7IcVoJ2+TVVPruu)~T6GE%Ykj^Cg}+oiTGy{&}_eMt69jx=hTVHIJW9Z7?Hou zcTJz$O7`Aq*! zFdR@7_jd_^QQm`%)PF}e(L?=R|DpL=`?0}6T-X|plZ72g;i>W~;2hhur&Kbo9C||A zn`Tg`14DoSKA66I6gfs>U73PS^;f(zcSXe5MY*26o2(YW7_(Zr^$gx<2MNbSGLfIqO) z)NBnu$$fLwNKw_r39%VR@i!DKiV1v8RV69r7@jPX^Mx;x%Qlh2#X5gBm@wgdTv%gH z_C88wW)t8VadP2 z@(2A4$PKR5qdpeIX7`JvsRI23F6?(v?RH#e{iZfW)%hosc zDuP}3M`(EHVqkqmiqytrCG26=R+ODntdqwHSTA+p6o;f!>-9|m>$L=(~Sn$*Ts^$lS=Xt)yX z##mXwdp*K(XKNk5-d?QAtnXqWa`eYzKYWl?4o6Dabd0zVdU8;3M-I-Y<$4JyjQ@G~ekT2v@9V#AL1dmub;Iv6;nl-4| zVJhmmCmzZti>l)qyC-t5(;dxaw=z)s@)`dEJ>-Q+!>{X`u~xfKb#OvIn6B4Sv@^wu zmCLwl@hT%ej6l32Veg8{{;_P{(ms|R<8%%gF9$7A)sO6|plrC%gh6Y@CRcK6MxB+? zB3T)%VWFP_0h01<@-Jh`IzXlA-ga`4arBA9m=Z0mE+54RD)CEdRZFdvu$XDc*s#@l z*o>uj(Q#?PbVg0^*7%Tzpnfu=mp+bAV+JK=^5XrB?B8hte*5P)1ajPeQ}UYwO>osG z6fa+i+8JXB+)`~ZA>9lfIY#ha|5FWCc|)$iUyy+fCGbC?U{(-eh;2gfJ^C2W=?A1^tZ-7Jm7I5|;W!9=|6r$*q_jpVQ$KZgA;-poWG z*M-Af^+0ljdjyPu3sSj#XDQbd!$N4;j{}*&o#?s3m~IWK!Y9ZaF(>@n>N~hk=|mzZ zS38)S-7E+s&4tsm8l~w68wo)BK(Y zh-DW1G8H;=Ly-uFB!cTU^Y+1sR@txg!*gF&1#uw21yT4t{-DFiPOXZ%Z%l((uk&=D zrGJr|J04FX5jMf4)u`-MB)wRWbZeY8R;#>4SLfK+cOikGf#R{CCCug_^PBT}Qvos~OUQL}zVreK;XyjYt zXUS^V(u9AV(q1ZDd1(s%A@tG&O_F*VabbKnjvv1kEO#^Us~APm%r_jc#(mEd?~bk0nY zKTb@VL+4KF@Shc-%2-v>BjPXX!L}PEkvEEO{1egd&Wt>h>d;8}i>~kXz*?TW^=U+aU;t%+H|T7n zGQj7kNP(_YrRzF7ws|g=t`w&JGn0RbMO~0x8s7N4El|x^KPgxlO-21biE)o|vY<4> zB6GYu)38*Ar?bcz)`k3gtw_)|D0l#(z*u-gIn#ql1`n!*o}ZcP*B_>z3 z_^#!Mo!HszvI_;DnlxlH!4#o-gZ%`CerewdvIkhEpI~Mhx{Xxr>KK2S;69%h;A|9q zIX$#sIgy>kPG~$){^_-Fk)Y-SogJac+dQ-=#L(F0%^!!?OQyWSc0l2_SXOc< zgM$|J__)Y`hrTHWve@kU*ii9e)@e0w3_;q(tX}Z`1}B}^7$+LfF{?pwODd*ur3Mgb zUPp1_sQhlNJSt)x z(Qq@<@B28=&kOsVCYflHy21MT4gY8n{y-;d&?ZiJ1nYj7i5=F?ODUux_*^Zn=|X+o z7eKh5PkcUHyW9`-O)EgoxE;|5U#VVe(w8pGIc2~OYIqos1gk=;)~5HrwJ+=R)jAxb>4Hqk30jp4IqDF=k+*#gVxro#&QjA3fJpscNoBEbpvI?aftqgzbfyb8L_v9LS8u<7)w zBTXuw8ZEUh;z7|b%DSEj`-7;*KP2>aUUpl_tfRZmvA}NpMw}Y@4z+C<2T)6P7~lFY zcEA*s^7XZ35d-cpi1V1{{f5utWl#~ZmrSi`!EY&u^T2?k`Z9z$BCBQz3I!xfm{EOl zdnQUM1Q*&hI;M(4REn~Sj}Arl(*bDknuaoifCWCt3Jn7|70M|Fm%xZ4Zo$tYCd}bC z9KepGoI@G>As&lw?Q7r^p4FG$z3Ah>QB2WM4CTDWRXnPp*fV%t%n>q}b(LlRa)lJ+ z>$YrW?d|wD;Gi2l*M_7{JL+9Wsfi6TM((A!cbklWT?$#zu>t&9sXg;~sIN+2JTuC= zaSFuO+)kyf2dtq;Q-57Q=h1&*8B*e)7P<*&Ms39me29dZn!6!r28l=Vg?hIkNcXcg zs7D>Tr|}x6Ay+r$QhWW{AUtdw+Ongzr%2OK!vbbnkAAg3R}UY_`0d||J)C7m_zP!L zWkG-2om>WEP72w&S3}xub>aBYw3uL;^R!=ZYmD44^_f>2=Z%yJm2BymP^*rp$CzBn zo$fASNUMKb;U7nubYDBt6q8fxra0NoZqpB2+zZbl@K7`kz7@Ufv$z>@K|Gv?PXtx$3{-M9NvIl%W z5Wd{!!gw~12i#KV5*;3pDe&0a3672}^%*60XQ=%VTStyLSZp2qtC%x0Wub#^Fk@k^MEd+B}(6_VH$T z-4fyMMPPm}5Vs6|Qzg5$SH5y&mIZ)GZ>}qFQdPZnhj;G2=)3XC*}8kZX8dZwJ;Yxq zQT`ZhQ?oOUYhXR2szKdZ$ffqu1aoO92+_(4La3b~nQvFG&JgNavpgC*?^uvLLR7<2 z&q-#*O~1cej1V-q<3hOGlwq2mSU9OqO`iI7whF5i`0tFY)d%uZq!AbQ0|~of+#}C z*a)7Vd3KUexhYqVy<#@=)ljxu4g>mCPw(8sw8<@D^jYf(NoZJ$l*`V3sGy8|(GOiS zgdMuTn$1)q;MRXph!o;PopuI3`DCZCkw;~Cn`hf$%6Ci_tF?oPCbxEO;zQL!Akz*b zS=+>FB2X7W;Eo$kA!w37m+8-$qz*(Q#CqY59C)`Q89{hn-NnKxuLfErP5D$!oH4Vg z75^j~bu8eieF?s-wDb%OaSVQ2Y-2ewGj*@<)#TQm$Of9^^ELtger2lqT9nnD%*ZgM zRMx2gBD*T7dzx(wYdV_;DlB=Pcx>fBEiT>>m#xm&GPPGA)dgyBzGTF&eRhc+cS52 z5jA2RT{x;YxZQ%zPbJ;g%~tpp=hkI$XD6%#AdJT0-vIo^CaW3>hB|k>1_V_1 z?&EV@Tgf^;jkGzRPrGqT!Gq_bhOy|QbF{J1!0DY57Zpab`~2>8PBHM-JuWH;Xx!t< z^;@lrG9WmjMfEeW1qv<5Ng8Vka7;}Ra!ZnJl3wMshH|1CCySkJID^F!5|^<~e*4Po zI!XTxj_Ci62ltfOUHf!K)@*28`QHom3;wgtxvXY}vbjB!Ms(Iw+2fPTpk9BIw=tx| zbJ;Z;w{t8Il#3ONG7|R|#41gb4!+YjUzu=4Xf7VuHj>@ED3P`!wu)oDp0UJtCtjhX z!u0U!AU^T5Y)7e{v8&hu1!~-FinXNfVP>9J@|*gz;lX!){`*}Dh+B$A&s`(yx10ts zA1RVL;g&NR0evOqR(i6EEXvencd-Md@!ojv54<@*>$uonlQ?+K*g3vMCLSE5{S&9G3p2l zjiU)s(wmPOe&Pg#T-G@ZMQX{ps`lHulk&}_Nx1xjDwG9#_f$0VKswWrx{8YDY*fbD z#e$WyNpcUNqo&F3zNFr6fM-kk-KoPvyl8s1pY!ee|MI^;$^Nlbf9m8^B>8bmhy(_r z`2WZM;{SN2asOCfu*L5{rhfCa+KVyTC7$+eZ)*eXXgA|=wxwM$ainQqFax3u7V22) z50;29XST0wd&&tZ;!unyqVJ1&okWrFhRO}#WiqkyUIb|#S&$OOh+Zl{>^Xd;+rYT&zv(QYO5+j+??ms<`->2T0q8G4|lQG{l zF{7&Q2q$4!#QzNY!kgZw9*0_Kpxl4l{KM~r2~_v_^_3h`gK!jKkWLD@&)y7KRe?^l zL;`$s$(lf&Rfi81vciQa*f0ktqFMVaKRJWuNKT?FWd3NHsiPw@X8f3Ww3H*vv|m4E zzz`}>-nE~=!zqDwBik(|G6IgkGWB+0%|!X;*NOdA)WSE&^Dc+>G7@SRZT+w|hCPQj z?ENGO;`^{hJ_vKlJhR7yO_X0cbJK!!gC^3)CHXxr8hqvr)r-#>)`zgbjt(}Z?9XZ* z&*$#ttl$gh_#DbhX+UFs3uULH7PWQ_xCHBiD@8r-v%^IzFh_2e#e7l{del3kpH~D;o|cCQ5#O*s5t|$Vp4R>L zPuB(xLW13J=m0nMGj9nQUS8suv2L#V-ds&2^PxoA!J#nEcs~2mnk-#xPxq(E3oIP+ zI6t?UeCJk?%+DAl)O|WS0b1(FXwb49Z%-AXhasnSmtG>@fNgWioeMZS#NYS^hLmG* zjS~g@HgpH{{*Q}!ryTsZD^>DMMK75P0u&&+nBXHJpPt|(q<{@%Iqt^md22~JRr|=( z>YG>n8a~lm5#3vm#1jyUulO|zi$+Ra$^NSl;LJWXPfVk)(59i^Azd@{gDdzLNh9AIzVw}=!hdqj9eL7`uNQ+yh+_Q6ac&9RRH&E@!fUbt3Nk)`IKnV7VTfsb zEiy0?7xM4l7tWw?6%%NO)L?}|tc8?JO2rv%Tu!;UjD@~(NqPJ%$4c_5p{@RH-rJu+ zPpLJDw>adGc`CT%vK70AQ3V332m?`a&GUV_b)2)4mHo6Ptt1tSzcw6pKtBx$rOFL{ z=EAI204+H$aDF&@kxf7Pg)&^kH)nHg2vcCsa6k;6l;2XK*fWZz;(5fOij3k`g|s{o zP6;*2Q@GD~gtxHA?IKwlr{>asO>ULOZqf7HkkxU#?9S^#8h+f8V(o_TzRng}wdth8j>T z3W`)Tm;kR-b!R8z>XOu}^)UYr(z*zoOaoF>AryE!{( zo*h6mZmNY|Fby?2pQ)3_66emU=LF3$qQ(cH5R3Q;jLq4jqs~_s$Z1o>9Ov&l7Uj{% zV-AfM0qPS)ih@)wx5Cj@7;!_<$abE-=_@0B_6z9-vifAJ>Q>S&o!Pga&=Cl3f67&;3G#G z#!VV)TBm*}v7A9qkj3RI=n|)PO%ef*BsFmBr4Dp5|3jm$02BO1AQoKUVIUrOI`A6^X^p~u zf~zMD+$;+(oR`ZCm+F{U$aq3vWvEYoYhbE-Yew>36%((2JQ8$?D`ueI_H>&?F_UQh zjT1X`G#+cQZgtRC)7{{dkEPrG1g9&&5@0}Z61e`J4-((k9`qeZBk%f0_Sl%(Bu$vy zTCDh$8L`1`c@Q?;U8M*3eezpHWH$E5hK=|KI_q#Q8xv+GEu*Ho+4e3F59E~SaXK(k z9FqTNXrKxM)cR)7Fy%qr!*ZK&|7uld);V<1Ow_`oWT#DV2R*D)0|S~Xh=+9N6<$DR zXTwNgos`rv3ng7=nF${vi0s?wM`|_Mp|KT-P!`ORf10e%7{tQDF%wSxRS`jX`%SxG zmG>O7OGZ&pJ4!sB>yvIqT?*eydKUY}Q0eB?V5xby+;FtQ@C)nSsHH21`zhzb6LwCn ztS=oQNhwk)5D9E={4q)a8S?VR>-EdhPZ-+<{5^PLDA#8>{YuTXk$^hb^!na0xrCQSsK(Hj=G)Y#Ub%&(V=3-b;|*IosM zde@ogi=>c!(j+n7lK`N&#f4f2!)p5%Ide3WZ`#}=U}OF@jB37J{6V5mKPmh>G*Xjr zXD}$77MbtPZ5G-0Vclp&M-Zt)P-Hax++72zML?@9RZx=Ff8>!BQO6ny&zg9(u2(6-tG4FR`ya=&_nf$&u$5`ZS9 z%InLh{M>4#wYQZy;l8_uNi9Iz#GD=7%7SU1e0DxDkv*E_fzFyujX_zZ`p|&B#necY zc&4q@_1Y*nZ=;G``z$xQR-sWzV`saa63RU3T(kP(TWr_=H1NA=qs$^=0evO5C*2Z8 zLN7(ffO5lok=+X1EA6wr?NgoR_`rLbERPR{(oJ z)mBxTrZ8_XL4r)X1r{m+s{&{D89a}jm6F+GRFm&mzHJqx9`EoW#*rfS1bqqP$NCfl z5m5O?sDUYd$t<%6b?{f(Kt4o;>EN8(Y-0mr9%70w9{kEidh&3TC6RD-H*J`+hE-#2|{Wdbqn z{Ow-s?iD);GVBXE89|sToJPN!VOcx&2eWKK_5`V-W8l9(?CBqi^mqcvH&`NF9mL5% zMN4001WVmow?oqDQ8caJK*DQeR*9h3Wijsp2VK8qiMv)iDTAy8GN9`4xZjVfoKk-! z2;$MoVx#G8}SY76|0<*!fs8hm1yLIXgG6HhWY%I*VHkeXV#>lzUp)hDb!U$UN9 z{V6hmhBL4G{hh(};VOdRTD*LeEnT$DCaJdUjn(0xOp0O=sbJCd4$g|isLR^yAn^RX z?f#H^eXc8bmntcA;dF)1oOM(H(<9n{feJURBjd~MUfA$tx{{}e^I-H>rUnPA6p%e> z!)}kq9K{)=Ju4|Bp0lS1siQ>?5H7CwN9`Fz(C#hEkHj*1OCPsK)yfkJI^fB4?YB_c z;osfp7g64$=}K|;SU!0}fQa|em>?4dZ~j7}VW!OJBAVL#Y}-^S$1@bjmLDzludK)-WpMTvaZN_&#R_m`xOvf#c=CFvga98{=GnI=^C zplI**3YqbPFwzk_ZWu$PUq^#`NW$@lmgR3tepRLw7r~s3NOw{ z_tdE3Bu5qNZjRaVITWl8Ix|W{dojiQb&wpX`KT^Frsc@&5eh`$O=@ z(C^s+th`_sBPU2%gJ2E_1)X~r@Ben1ZnuQ=Ca3zT{EHi@k4UmVfUHesg*X;)03ccR z9t&o-kX2b?%Q=Na2FO81k%Jk)_lLqv76uCEhR`z3O0yuxMg|&C41z2nv`KqM6yG^2#SK~b%!PZQS`!bEN!GV zxsDY0F~2p*xt+rO^d&fgLm@(7q9TRo)R_dxPBA4!6qjCsbUk&QyKO025p)2cqTm>@ zwBMT5XC3;BK%2SXDSJxh4oN3;$84@T-?$C@h=cUU`iWyndMKnAqfilq*wXAWJdt`4 zfy!?}Oz^|dQ7k0Mup|3oCx2_BVIt)^-#`vx%ruw+M7&1_1z-!XBoUxjWxe7+kLhYX z1LV(7o_hwgqtw|b?R*4a8Dwc0-oT~kijs8_KF`nbGErGj6q(URLI4+0gQgb5clkq| zoQE=sQ&=wBwf7-g3#=EdO1j%@Qk-!dMU%zalIYwe0uH`C=9DK-@IE0)j3b>p>%wZXVk2@MWm6H>c(Pi z5F(q`|^f4_VUM07*dgUH&#Q6?2kdLI0741FjRZjBpD zd0e}A`a86P;z=3j!FpW8ls^ zFnO#NS;#Ic)*M(!bg8`1K#Ogd6#d=*vtQAZ_lcp1y1P;p0k%5;~ad!ztMl~vF8C7Zh!?T>k z$C~LOm8#;I?Ku{+5VPxZYyz&o%G>3GR6Yck)i%t9c(b#-4Y2VZUEqI1G+^Z^IcnmP z)iA`62Zq$KRhytkJgX-{jF9<4IqnC!J^pFQOX?-+@bu54(<1_%i;o`m|N6Jd)#7rm zfi+xu*r*6P5mjv-T;EZl&`w8q2<--i|CzZh!hP=bYMfZUGs=CBx!&yENAD8|W zpHv(S;nH!E8se^ok|s5CN#XQhm50B!mMRZ#!s=pGUF*}pXujG#gwh=qI;X~w-yBDC zF$*)@+GzjO49KcZGs>dx0!ZZXjTQ%Q*umCzD>;~N)iNWBAm!2kk0Ot*c0pH zE6Wt#XOJyq4f?>puVg}yQXj%Sid&N4zl1TypldW8s@ zilgc*DICB$g7t(XJ8F(N1q)AzW>%F7OGDfKb?Z`g$B~^?))0tsocZ3%4PwpNob}n{ zo-W|TV#!C*7@u4<)JUO>fB&HCh&DJt45n%Wr4%*d;K5KR%?~Q)`5w?_o}q<{ zn5P{kRWK=rV9T7ROA49+6NBbRow%r`^9K1CuHUQh9UNh=|BHc4J+gub3qNWN4EZ4R zcph2WaRN}|9a}ydD3?M6f)Rg#kdy;mar4F?mDS(h-}@nGE$zVTQ-;WA=HyH`!y$@F zlAad72`5C#&x_cGQtTGHYuiz5(PUQ2x_0@egHr!x@>frILYNn)rT45i@wCi2pVzf? zrI9(2@P$<0;`+w~N5QSkLqUnpwNFh_B2g6^)W%U?(OXeqL#UQy;~>bQ>!`5RJFMZ@ zE-a7chLrJzBA)Dy6*V(Nze_*nkwQ-=pg56pT!!x-*z{N9p z52gY&Ywa$?B0&y9N_Y;3M-^9lHv5$vIWLN#b_Wc=%f0=-LxLO+UxN-E58pm0(|-ei z=oKgmarWgup|ceT{!7dA-EP%0)D5dY#_vvT)gNQ@H>kbI38SMbFjgrn!A*B!_E*`8 z>mWRU^P_wMuX4)vguO<~h>&N|8CHJ_d@HEXGrRIKrb@7e3uw(a{2B46kHap*_*ONh z@Krk0HkX%eyxI1f2;jOoDB9JoO%Ry;JfSH^Ir7sYMZUosncyo|5qCO7xzGaNX48^t z^{s7#R1jEpLqxE@t*RaoV5?!ljMC+QUj>_A?89u=Y1vn$Lj}pd0pDDJOZzFza@h0HduoK+QLj)$$^0R z&Z5UiiF2y!{~Yz6NRUkB;f})y(a_2o@YiQvz`J-~hHUJXI)EvMXYizqQMBcOnsnI> zshlpmcnN?U9C{&G@aepFtnj?dUf6rut3KXH;NnQ%#OIaTq@z;;)yJPZsZBjX9YUOW z$#JRFF;A{YOzexS!~ogger{0TtOu zU8BCof{Y~KwcTN4q_!eCmb_0fn+JiQ?%=geXiHJu30l}JP(37 zCT5GhE8o`z(QvjX*d@+H;%qqU{taG|##8OmS&Br%XUXJTOTgt+SO-1b8!&aTfxVW& zIB}BrCUG@-yR_guV^7W+EHtQT8PS3E53PMfFiZYI&LA25$*6ayDdM-P_`~hr7ogPk z0AKo%D6+!Ika8g@u|$CS==4nR-?zidu@P6@nVF=q>lwc7t3!bqMManC8WBLaXYx|a z*Z;%VImY%Db?d&i?RM9;?Oofp?SI|w+T68m+qP}nc6;_Y_vR+=my^4)vXYtgX=P=O zjQNZ)o?oF!j_1Cz{59iKkp97Cs*;@EvKuzK&^>~5#33JMLv?qUrM2|Bv#bojsv>n~ zo1rLBzVr^7tpex;nvFkim}2oY2q#D30M*J{IGTOKM>tx(6rlF+RrK*)(cJ6R7Xve3 z_}(rLu2@~Bdmg+F&V=N-RAzeEv^c{bVJg5?iGY@p`}M$8KLZih1s=B%?Bx3R_Ka;S z%{DZOzvg!Hfp_iwO}^#n+1DPg@!>@OV>b(NyUTxfi$(M5lWL1U>SVy<|M&6j?c~P~ zXjuR)T`6(q=c1I8j-jxBJC~<;DM=KNi+2evNmLh&a_|8;0>|Lc(Th1Mh)9MLL?4gT zU1{ldrEjx7cuufbv;z(5UQMURyv#F>^xV;ze^E2bp?N6&d) zVr(1|W4$hBa#b;a??V(8*=QkZ1RrwQ{hIQ!q;yeBpTt;t^48SWz;FHK#KtgxCALbF z;eD}Y$JgAPT!q4gwVr2?iK)G)>$&>*V*>3~_%t9WZf~L@)e@lPuj%IcDDSk-f@CnW z*>t;q^v&+Zg4Z@6@biO!>NaqD||Ldp#0G@g+mYvqvir z>qO19Li_?fwqtq?K0C`}P~VI8h`%dA7r{&AeYpyRa`-I64Cshmkh^n5wpKf~@Umsg z*h)`Z3;u!~;q2u15`~Y*ak`r1h-}2m9=2Ya&jE(CAAP|}tkaVpGp=0c$(sGRNsCjU zO()HR>03z`rFU`u>_^YlT$jO5i#~pHaTNdT9rlbWoB(y&+rIAcjK19FbVavm(R~}w zvVNtC*Y$Xj`=&td!S@=hTxi4ogf?{XFG|k-?moF~g4Ml{{-PFCocjlM4%FsNDasMutsjrS zZr!o9xCADUF7Z2q?FF|t@2B5}Ep6{^!c08>0{DGGe@M7-Zd-d7Qkv}_T)3(+Hpc99 zpX)sAxQ&oMOzccVc`(V6$U_56lkHne9qQv;-S~3(sW&hH15sSpjbTPBxno`~ZePSD znX4mAD?~Ogn}k6I>R^NRFz0-w^$&5+IFXbcQnMnoejMWXaYX@pwv+<9=j~2+?r58{ zFWnp@pHZZI7Olt=Q+9d7@AHjk^tIYWio36h((usMrcCX&dHoh!a)sk)tU0F!@g&Ox zODJc{OtXOg(1JG@Apx>8+5G0FP!DotdlWM79!k{titCC+Ho{u17DWDe&{=m<}{S4wT?RaMn8tWK1!oZ^-Jud)gpDMlVEOSsm3 zqNA9FD)}cZPp$g zsSM}vCTDI#M7HPgX18(JJQd1@9V?8FjY>_)J^5c*l$3I``D0DN&o`pNbyrYSUK$CE zSq|hL=tYS5?KFtyB#m3!$?bH&6ej4)AE_8O3(VNCd48X` zcwX?3wb!PUlu9DH*8QgK`&Ey0JH(KLD|bS10GKm^Uu*?31*Db`G5;W}_tWn*yykCp z{4@Wq`(7!4TP?xDIf{TE0;J;&n5Vuf{9@iIgEhRVO%jh@h^ud0vP!JzK0rOT5p0Voi%OrI~d(- zrXyL`=~Ud!vcgigEUmYHt;jCExh?Mmj^AwQ#g2ORpthu7^2y6QZceMNxaK|Tb&fDV zekS=WB8(u655PX~ZkLtscO`D~0Cu*=C`iM*NS^fY$|7PKK~$inlTsSiv&wPu8pq-J za`1syH-FZEoRoh~aN?9OL8pFJhb))L)EmwOFLrmzF`h#Tq>m?Vh)mrDWw_Eu;00^p z>hNtWLlv4xegm^b)v&5nNEkF(a$XF|8bIiQQkmrk`J9z8Pzv4c^QBU}nyZngelCAl zQTz%-gO#YhOrJNcVfn>$6!BMfHt3K9vo@`D zPP||~0}cm$;Ph4ssCzx{YmIXqtc?;UOAp&(_dq__S_ztg4yP8b?8G6AMayNrS=A6n z{c9QRm!^&1#{AK!HdA>sNmX|HWEs~@X?tGMa^peE`cWYS@i~ta=(DsBa@Fd2*ouQy zZB8OM^Z(T_pRy$Ppp1YXNCwxx}YD7rHUoIxCTkFJ8Q}^R}NNsS&>`tzmb(5o}S0kJH;t6v3C_+?`=) zcdj=NTFaYi1M~D{z>~o)u>X-1Q_16|`0!?Dz_9)`%9KPeVHK~8p!1f|cl~C@SOd?; zWqYbN62VJ0Z~(|k-80|(GuaxmmpnBYPd4J%2*K6~{Xi_68p;DSfJ?ajdOIA-!QXi| z2lh->CL9!=>?p1a$}B>UfG&y1;l^_(>Z%O+Mx91v>@7I0n{ev3JA)MWuI?o=;3;Ae zGQa+Np0*-{QNfRMTwye^KWoZ;BA$%iz zW9ExWSnK0Km$%;((yrjsM$?sdzAMy~vVlhDmR-(>Kr=F8YciSDM$>t#bsq7m=`Jd& z+VWNo_hQ!_P(po9Fs$V#!`_Pd%%HovF-KP;!(YmL_QyeQaG+C8N9sh`lAE4wM?W)`vw4!8OD``=Cy46Bbw_Hm0&Fd>B4 z7Bx(1-;XH=tl>Kc3;IEQQCvQ5A3lLHw{7Z;T*!3G{)%hcU#F4WC6bfaqPo z1!n1GmpdBjp0hWK%a{G+hDpo+fd`b}Y4x11FSCggRn9wRnSC(2~Ky$==G;*oDE?-o(`AKfzR5iuN0vD8Bzl!-6jQ2}9&Fp&&lD z+?F$~Zm5H2_z0223Z(1HOBk+bOI0r`HwsCVPMn1r2B3?z#~++{@MFK;mIUgQR9qYU zRw}lp1n3!jjX3-^a-N$pt~8fF{urqrv3;ndD7hGw{4>w^1*;l){I@FRH+vj6Ibh_7 zLvQPRnD8Qj1HVRNM@5I(b@y`N7{I(!Pj~Vx3y~$_i`zy_UW~5!wUQ^Y5=pw%7LnOk?PdSI^ z>bw|Tw`#!w;0UNo+#g(Q3)bv~o6P?C@c60!KKXjr&)DI&KoGrN+t$-#e8o-Q?rsdG zMpWL&!G`6z!5vj}1zjs07gjUIT7Ovmxtf5kce*5JP+x}y8``P&+<_XC4W$`PeII)B z9f{TH8C63sztK5-BLXM}|7G(&#Xzk3eoS|%X!hOLg*E&3O{F4u*LK`rYCsx!66%dg zuWb%~V{6@H-C~Sf$zNOg*p|5oe>P`$vuZdBrbV0$KRvqaA98_o_g3db6|hJ41_|$?;f0_v%(Er$j6P1V=qHnRg@42X7!2KjqnXD?OJc zPC<8b87B$>JeI)IiTEFGtd>}X+YVx&?|kuC*M^X!Y`HZrW5^la{b(0|O|-}teipOX zDEfKIQC>=yVEl!EFF_%gYJ$k$c5;dYNSc?4w&NX|tdH$r*3{FFH9gJVn>Ec{@ePo0 zE_eK;$3x_CpUAr{A&^3_M}=#+i9%+$@6``{uusJkw%gMmPaJUCz79{}!&6L8C@ALv z^+osF|GBXqt57{7wPkKswbsRpg{>9fMup|L&S*-jn!RsGqzAe#LUZzUapLFy$FaE4 zP!6YsJq5h|-EamY^!Yaytj;^FgHWsWA#gA^*t*2rIU8BFX{=HET6o zteK3Qye=WdDc*M_Sj$-ARMwd@{z=A$&QNAUrZr~(tFHWG{6yl0J}S->bB-IPU?f!wI7$K>DUWi1*OOBjO7*s<(-H|8_%dEk3!Go zRq2lOQU#xGo3w$QmskYeJ?z@8C0m)_772`PAN4tyE9DRPf{ZNLWixqxmvNg8r>oN6Vnm~9aK-8hUtZz4CKi<Ek1xPbYy>Vh z$MSrpajo&Zye0Im^-0D(`#sz{G+|iHpMTBc&mM6eBelML(Lu z5|1KixhR0FAtwyhlvxOuZUl}zr$h-HI!ha>wLuxSexeCXCbRH_CnAB-#P}=9Q^Ta& zz;O{YfuxQoPTWH%UpSuC|FID^D!!DrY_TrJsH_RhiAsD}$LPUf<5#qZYGHg34ef<# z{N&o-!gnpbq=a)iB!vQ6t>X_NPjSNT_ZLu=^%te-x>TIqSD*msGa-q?9b{E1N`@U| zLpE_~iWDSub15mkrb+xeS>|D5g@glLE|%0?mN6$es5agkS&_D6|6Be&>FNM% z8vIBwUONqstN=kz*Sx*UBb?4T3Fz8XQK{Ngw3SzhmT}5y-sd_w|(mLiUv2p)fy2*!E|I`$#f<)>JK>U;&?!jsocqDjqLCc+nWQc z*%TA#LGJ9N#@eA=T9!s9CJjBwX$q#*8hMPuS3uf`8LZ-x0LUpQo^-+7G>73`Z!Rv9 z+G-B>rH(D}Y4Nk}lriq)`K&ouoMAmo4qWUs*op>9Ak+475-wU0&2+V`7od%uxK5M- zm~~L$?q-8cIfBPcaSZ<~8k0S%OfkIpbPbZce5wRtyBkasyt6vIDc`kb6MZmmY{g%P zSn0luaMO+QJ}=b$Vx!1*4I+P?Dej0vJ=^|bL;4f`j(sTz2)vC=O2W#)2u>s;Hcs|h zBRkq*wHn-8m2%UP2dQKCt_!@P+e`*1>waw`^l;ie*~go^YW&={m^#c5OcoENSU-rY z?S;-f{Jc&&-7Y;H4e9@9KGC2Eze|Y%1SF{r1oZ2F%O_0jTy35I8*ZqhZNDK=?@MU# zEi&-nfI@`)tV4hRG6_nz5boxJ8!lyr2|A0mRNtB>LDyla{f~;>t-6HCPIZ3Gbut8; zu&UzzwBmYkUY_r3pXd=rnK|TFb>u9l>Wm+WaQgCzWQ# zX`s6Axzng8o*~md2A5vKdd2hAt`I|S1vii7JpckzOS8xKzahU_^Po`&6o>ez4crS) z>4>e7VA|l@YT_k}@=Qm9q+~s)J|^|nD>fUM_&7p40@REiI!+A=&)9{-~t4qvJGjDq$YKpzRW6^b9|LN zya$x~Z4zKs`fGxY3xYiqYEc9G_wJ_5vP(OL$N}=Iqy71{9$d6!Nq~a4huC z4Y^9L@n4=h7ax0zFXUScVAPTTN)MI63cl8IV1(q2?OW$p0CPJ0%`OEgD`Y@WtQdkG zp08DjD&avK?qhr6oQn%#(98B!;fh$G^+C~qDJw%lYnF*~l8DRuP{!*4G9%JhxT?yn zEP{+Bg^JI0-0e4a#%tb+GnTj>TU5dy8Ed$CG~9EpWboMKZ`4nZGPQT)R)rX}q?SD6 zrq{4(H9icPS?b;UUQ!l+@mNBFQ7b|MjQFTsOime&&bSSEaeE$o?q2@s1>W!PG5!z% z)*n<4bfS*a!CQt*n`h<1m+-F#a?MR|BMvKt*PNfH9S*`(S^g2w4o`#`?yTt^xGVe2 zJ69t|ftub|Lzdc#C;=8WY($l=LrC(-Fiy}Cw0A=`If>U>P;O`}?vq@zh;}2;-||E3 ziomd)peZCIcijWKVaA_iTJ}n*ZLRIh?_ZbC~XM-mO}$OJ48 z8s0=yVVQ>BkI@h&QXI3ICxNg{K$miKyRCgd4qf`5;rDkCc9}ZUSl1fxd8m%uUMvHk>KBCdE#Y?!FWr8 zM zbzeDdZ)V3Y&ULZ5G-*gaoLGgT-5zrXZdF8#dwa#IcTsJN0ts?ch`1ofQKEY01j!o= zVX=NA#{vt}@gPQnFjFnU4=hAPwOJQK+OAlKY>|iAy`Om2WfR$&2Su ze7mgsAD7-?zn+i#F-t^WAkByWTvS4Gip)TOB51+EqiV24;q3J(4o0WdM78taM1A;1 zBH+;QhoG^|Ms;bezYu`Y%Th{1jmI4HDy~#$ui(0U`Ra%A&v9fOV;pOjT9B(3@bCh-*Cy~q8fN}bif5gR(-utMk&Wawb)bT{<;yeGPCL+g3Bvcv zbj|ois#}U~k7P!KpE5wNLRek%+guS8k*x~^&Fy+^DV#yw7b}R>pu zp_z6XQU4Lrr0c{h*9pZA1AufA9~UJKbuCa$iP06U>A<5Fa!Z5o^w#mL4VrO(&U;UB zViNa}=5t&drl(4rA3D?7W4-n$E=%2GQs{$YTD{`a%25mrQ8O$AOCBq6E1jf)-=0y) z=TM3Pt+)rA`5_^YiP(bRk9`BUaY70<1U_`NZtaO@gtN-(E~dfe0Ui$gm4XU-oU)7` z{+YC@3C&tCeB#+f+8Gt-JePEaM&ya95$x)wmexs0)F{@++Q)`+F#tX#JeeS4HL@9I z85+ZP$_Ya|L;fmNtl_R(%pZnPg4rPb*XDh=ab$wp(q@NbfyYsfUcZ=k)A}%t8@rv% zvfte}-_9_IshK*A3^9HAtE_;@-h+O-?Y`0%+aT&=wZrp>T+`v zWmyoI0b4&8Sl~em5Z^hFHrWRNDg?i=avEm!O8(=`p>@p#DohQBYGl~4&8q)bDSZ%+ z1GPGtC#YT}Y6c4EfnHprD;>-x3H5M&&`d*cc`{Y(@%TYgXI?D93*vgTq#;W@ZR_*Z z3{6-78#&g2-PzCmKOV0GqQ|gl-Pn-ob0bqIa57533Z70JGFARKh6XyvH>;6GL>YRD zr-%TYnN;}%=>ehXSwwTmtJDx@W+X@xBzTNDBLSvNeYBU2R{Jlomigbiu>H|X()M_TxG{U>uPRAqys5xD+EQf%p}&k5jo^zKyqxJYo1OvG z;8P@L82)mB8$<`Yq*f`yCi1&}0UN?bo8pC7e_is&sYv>2y2_>n_{sABTJuJ)$jDkJ zRA&sMNi(isK`c2;uFb2wueA!?U#m>&+RgK7wKBQonk#f!$FP~OgiIMChJPXov0c)o zXgmtnl!2^^o|>Yv2|j^y#{bb0&QaF5^v5-cfm5oJ)hh+YA_Fx)mP{YD4Sgb2ZTcm= z5NdXhIHc^vo7(I%|4|hL23bs1-ftCcMSVHLoWu9~dAzjz7N$e0v7q<3bG^tiQ}Ztt zH|H$tZQ@;@t#|2NUoMPLV zkM}rse!z2lKw(052)075iJj5knbYIX{eb(MON=>{+d_e>lsD{WjtR+4-5|9kl^mzy zfs1Kpe^ob^S4gWOmeYnVtF>1sB|=g+oC~6sYg30%>LKNtK{sQN^I3-&Q6Eqjrnhke{n3JxjU#Y~&XEbbPKE^}j z-e3fk_UFNi`U3%|RlPO#lB|f;9#iW-6X|4~g5{#d=xi0Ij<-$k{{+R6>sI{2K}){S z36A(s)15jDQ)v z!X>0a$-HU;b$%pr0m}h%Zc>mruoi7BGbVhgIXgxB_mDekiKeT2>N0pnNE~P9&66!6 zwjR9+RDe>~9~teK1-IXPiJo+g&{spV?(|ZL!a_ze$i@?_p5BcutOez+__ow1@vd(Z z)YRZZoN}lHRJGH}Y7okiO6SRN8ozAH^fGHLc`jBxRq-J)t(Wa$Dhoqapt+wA3R{&A zILEnE4=vQ!C9}KFzmn%;1yQ4ZOU*7Th5Fz`E6`bSBVUO>Di{5A*s`D|Q2@oAy&5oc zH%KCMv^kho@3_bk4!w5u@?a@S7_M*#?YV6wHLpG=rSE{_Iq$0HhACgM(~4xvu3Ak2 z528Z}q;5wnrOS7=c-~#E0I@ao?@e3b6|KYUdFRuiH2@T!LBT>+ULUR$qUUZa0t zH$n#)zX&KyU^GyWux(NWjkWGm^)qfLn*+FuJt2;&isDu{(I)LW;9oknbfr+UQ(Vl+ z5!G(+wYHenW;sD9cGsfQUu>1La&|4`E`;Z2)}a16b;jT6`=-LemTJ|RaF zWcKuY7`YK8&vmsYL#&e6)YUrN zE^ak;l!TLExv&UnIJ!T4bzP~!3KR)RcW!7_K;xalZU_naw9agD5%bdTqL{PgwRQh~iyt44c~E`wWJ%lfwe z0nWpt1k=Nv`L^k(vL3S-K}+bxR2xhJc3=uXXc4 zor=`v63;$l%8~MKWI_Ky(w)Jc8AOyZD^|)kU7wn%G6GEq2^{kK;KlJzOp9TMn8ruq zY=&|4%XpA*Gq`lY1!JRZ$jhPpR2xIy{o8nD*GDb9L`fHbh}qw(5nbdS;Rz{()#yO{ zIFA)?#gfU-4x~{wJ(jjx{3zf!*9xR~>Dq#C>}9Mlj4p&GDZy6H9x3qL={?P<<&V5b^&eGyR|P)qm?uKGx27Bk{ZLzh4Dh3=RSd5eKF8 zHtI&8bn#@Q^fKwBe=A(9-cmwDr$Nk4q+PFF6C|`oZteJ{Y2KKtzdQmFEg?wvPcD+s z{JU6a2!Gc0bJ2IRNU*OPX%oYbJ}OQ|bA1>4-z`a6CUn zI_Rp}l?^^k^y!ryH1#(O+u=1c^%MDVgzfUWYHEvSD~msRmF<;f7xW!v88!p!y*Ia( z6Xd47Rgss?r7%EXW^LUoK;GZaV$TOY?&|85YdIPX?S_0e_vg(P4Ys~HRrh?+UF8`N zC0+E__lRUN8R{38#{X=Q=<8*-K)gA?c3?(m9IKqJ8_t;QZ+L;)sMeoNJ9f~gCfK}N z$z(p?)qB2G+k&S~>)HJ0lQ;HPdfF||ZI`!h{F#}*4*;%y>0MOnTU5K9MSku;pU12p z{5ysN3zwnz2x0nNA1#DEy4~L?_WD0>`!#;tQ@-W99}AV=3alC2`Ugp@18ZqmK5gKI zHh)(D+M_#-H=-;=v3AfjT5Lznl@2^|YwjGTb()dc6Z!v4Y3EMfYW$M>ex_giKgwy; z|M?@nbnGX6-MZ=Px(&&F9P1n6UL2!*Q|awoRlL;xYaVzxd;Ye)BlJpTXmaeR2)OmQ zzzjOaMdhklrDW#@dJ*$VM}}CZwdV@d!u$7GTDJGiQ_}(7?I$>Yr@Kc4^lyL3%gJqH z@bD_2<5hN!JJ}$jrMe3?pnrlEhCfPxA~g~J0u5blH0Ol4WU|*>ke{_QZq0rdV| z+co+nHQdWxwaymuD5IY8CYr2bm4O83^@)I<3FC1!gp&OX^JZ3k-hrq{e^{6VPSX{R zPyRa&04yWwEBa9{Y;D)$I3xCrZ@(MdX{JIBm)}cy^YB9!Qe*A%jcVV5IDrol+D;cRKn1vL2g-i1)M<32+2n9Dss><`d8&%c*t5Wrv0Et zRBZ>&88JAA9+-3YI6u=7Ln)ALcxIWfWF%aYBc=k$z#15B2p8t(jMBhmn7Rq--a?jJB6 z0LK#~?mL17&HTrwLIWt^sq#oCNUgwA&{!_*s#>G(Oz+otEiMnSO_lkYd+qQ(>g*51 zG|9KOYq0w<3IbrR7u(-YU-vG)7Sa*57i3b9W;ot%96mu<8WQK*WMH>tqIoo9X=_Qf z_6E}E3`FJdl2Zw9jk`V{%8zCp`;@+!CkZTfqvFy&Y!xFV7E<>k9CelIw(r^)_~eJi zsHul<;v2k>A}%frzo|CnMeKQLP2d3?iDvuw1{>wvr)9%k@QG0mbnD`(%;I<0`XXUg zyl+Lc;(a&AQv^G~FO7r0y}@v=H2-4zSw$zXWG;)OUCSnLQJ+{-z}~JKgTQP888!dE zaYg=7sx3nxktTiH2p<~l{bEe`s+5}OIuL_Gx=mVH=~RDwP=ak3ySb$sA*sVeB3eob zy_1!r;>&BpD_fe^b5nTEH|`A#uEvrIg^Ql@mX2Z@%Zt+u-RCFupDFA}xfuUYg(1kF z3?xYoMtZ2ECpTCQya8xjG(fiy^BS9t1$h6p>(_pl1cXS0^ntPrIOZm{%afDMYL0SG?fwybvrxOz0muzifxK<0!E7XK!_wzB8V5 z+@kcv9Pnfa98GK2WiXas%ddWc6s#b^Vj#<&y3Cq7>YnwVIC28Gf2HAx^bfH+ zlAqymVb-%v{phdL+(4CCUcYa7_(#s^?eA4XOQ1aMBhE1p;GBS`S)%lMe%@QQ5#ld2 zh%Mm9AqtRQS7ww-(J6vqUDr6$A#Oi|ZP)|QBop@>ggp+ZXLi`QZcbJ|Lt+1}2~Ra~ zDk7Z`XOi^&^WLTVIyOPfKa!@>%1(`wBXRdspa|~6$~NjR!W+Z*F#;urN^#O5`xz3y zOr}2ah)Kf4bqi9UqS$99usZNd;ayBR+dt$IpJp{%2_^sqp*qYAI?j>GeT+!RRQBNq zDe5mLAr403OiMaVMl4!=1X9WuSCSHho}X&m&!fYFA@=ax{{_$26-60;BO%kD4%rzD z))MD3us*~!1vX!(A9DybS2!jX!Py1`U?!C;j}($3wuh4}OevE6H4Cj6!*J`2a>|N* zSJG+{yqUC5UvA@n{;6rx=C$`_oXv1`rVD8z>Ulr8gIF&1Se>3$T_ zi~STJ{CMtHj8*Iqy9OrPw=j#+ZGyNO3KpzqWY%dUVCRfM4=23mx7o3{`Zp~{fLDM+ zV*a6NU}sC4Yy4m)_;E}u$2u<)Eob+VxaHU$q8%8l@Bw$$@29J(g6snRoq-9U5b=T@ zE+Sk){;01T&j?m^%RQ?2*S!CRO=`q;f`9kb{sn!9H$9(*e{VIt9%2RQ^zx&4{I(@Z zhwl0fP!5x8Vk&nc4+{iz`Oz(Q1DB^f8vifLM?y-ecsC{k+r=}jK(+A+%?>k8Od^g=N& z0&%ZLM=+nr_-vf$HuejQ#F zEX@{z>OPP~3IVEs?Sb_KLWH$EJDinBk>rL~!#-3eO^u^8_#r`XT8O9Cr4e+PZhzYwr!d*E~2^xEIjRX)5py>i%F zWeQjr&^omR_d0;J?4lmi6Et%-^!0Gj9$2`O^Bz_}S7j7(DH7KYlix>LX|(Nz&^-{* zvy0;n3N-AbVy?MU>iQ%qk9nWvJPePQkGr2OH87lsMm%U^|7h@r{-(_o!ZUb~+7p50 zpD{lhbrSUp1=bm#$>AjPW74tm4g5Od?L+XpzXWt=9=#oG6gPbcf8r|u>ycphav5@K z{um$Nu(zOn6P22wVD|--N5nD*hHK#`dv`B zSVb3d0iBn-z0AS@jP%qt8@bltr)AFxm*0#InxbslKDLTIAt!W*ZnOyvFJ)BSHqy!cUKAXfJQm}Jp=?_J-EbN|NZLNN;r@55)7(x<^3vbA zbd6_(;Fon6X<+J9N!F1Gdw8q_=UCZ9wE2gUS z8KK@qZl+l)_b&c7WRH8GPyQ?ve8FExQJ34f$+nxn(%p9xMb*Zf9^x=Rem`YBdX~?) zB+`A(-ePaZV7O<`5q;9B-(6yF71NL|`|fcB@4oc%x0Yr|6C4z^Sg8R|Tyt_P?9=pV z`uN#Kwh=OucNVcEQQ1Z_NW=A>F$Hk4MN9N^Pn| z0EYWZ!5x+$raW*s+Kx8AMiV1Q;<_DE5!m&b# zJ)jerFR(%rq_Bkckse$ke5PrrK23#C+d6PL~xSOJ66Un+7elHH`LgpD0OpEyy%k*-;gpRcinTDi%}AN zZ0JG{A%u`$f)>O0D-cV`EN4T=I0QO%CraWGE74;Sn7{HDDv~jF7KNj;v~(ohsWzJ8z2c zdS}@U4tWO=K0s{9-Ka0M7eCD@|rbu z@0P!z2^>>BiwYEH9~eHjWy?4Ugo@bH%HVt~4 zMTk2ovYaf&+b!tjxjjaJXfg2u?CtvvL9>wg?zfrzFB2T-(a+Z3k8N&_A8?l@Ps~uY zPnxN7q;5cPxEOQEJ>f(ehX93MPysq5769+vqr}HS>I$dIoaaSo!7(0hAqul#UcJw< zT*!fQ%&lY0tiwa_XG=Z}C~^S0q{1f`-^^6Y{_u5X)!)qKU#EaqKbfBNJNks*lhgiw z`1C>GIBii~IZQo-M`d?)cL3kn-h-cb%P4r36AUww3Scr$1(mq|jCOo5?kdK~63~0- z(b?Va@D~32PUt4)>YF#;p_8DEzr2-?`bYM=wX9~St4#K~~A zaVYh&q{VL!&{C+*SI2yPh7yi(a_~kAjdLB$)yKCS_FO6{gg=<8xu+mpFCo#!B^mUg z6qhQ25SkQ4mJ=)|5T#7HKF2a3fulrafQEkdZMSYV{Cd)Bc4h4n&Dr0o6HZOE^ zQh^w*b3AKSg#I0zEa`zD*qIvDHDJJE?FY9^&vsBUxdJ>ovVS)G zt9ERs!g}g6dtotU>=JeAnZT=SpnxsWQZntKNe(Ua%8wB$J><`1U*?EA!WQ|SdtF&B zZ^F|WoO+t=*hoEDi+2lElZ(8ot>R)>dC@@o+CsS^iiiN#;K-x7dGz6FMKh2Ynl$>@ z@35Zl*2>gnmoW%Tg$@Q`Z-)n665CphnCQnLh_poeab)d*-(iJMYF_zCVgdiLK9&g=;r6+Zba_>^5-Dr#V^s z_H*%BfJ?UVM#z^!wvd^fmbjKP6jJUIfLWXP#DRsH1zsCI$nPe#1Ns6vZFnXAog#UA zLF|sf7FtD7*T7dne5LG0<;EOoK(~O z6H4uZxdMO=4AX#fR8JuJB9wN{DP+wVc^e)kaS%-40}((sg>3y)@>fa^p(UUteq&12 zoCsG9XF;gyn5K0pQq_6rv}RMghLdvbWiF={+qh?ZW|uqx2KY@=amLb~^Czw&rec&9 zL8@2QV>RPj$PCaU>2(}XS}&h3>Wl3za1>%ak;|+5h2`Cl%%LGT*`*#M7VQ@y35yv_ z$W@WEhZEY$Wy=2jt!@<`N@6GjqYa->(nBB{)iL(Ri;rfSX6a_Sod@2$QX@C6IO;f* z8Tg+OuXM2HfAaJ9ogU=)T=SFA0Alsx__mE&->a${6%Dr6toRKXJ^}2v4KbrXN3S$5 zFM@=(hV`3n%%%{&;v^=VewL|#YQ}w+9Xods;i<#+C5PZ|V3P)9AI)^##9XGD<6~O0 zkvcio1=Z=&KUIt$d0KNLM)0%&i7@uwu}Q&;GT^_Pdmjqih8SD%?pzCct1^~-`lJqi zy<1pK69tb#N1H^2A8B|e1YD+#f*c(UOK48u4X!Op?qq5>#mU9-du1AzOTvpUWQ<00 zv?vYB_S64~N>I+~qeuVb-U;`w0rsLCcx;eDFika-ii4j%GSgC{o$wXg)BISx@tsqt zc44hh&2@^w5VAoF6v3{1hVb1$kZ1Ennt9?!DHMwH5G^s8A}F4uQmQpG4Vc9$)CwsS z5D;m!bX-LVt$mBlzzy>VEcZ-(9 zeUX3DSDo4Be<>^MV*UD2^%Aw^av`=B>9(|HSB?~?v_bKnb+sD~K-^rg_V+1kH8-^u zHigC6GgUk|oFK8(+vYN3yOdTOc!j7hiB-QBvVr2PcW%{5@-SYWMp@o5Bwfn&JLf~9 z|Di_JhY##$F?eOYYfkAbD~N~SHOvQjQ{nYVrQR5^kFD67#@R<^6Jl{?`>xQn@=+l)W=le znN1rY&?FR>TyNWiDH3Bis*b<>2XSq9F-*Q#xGljWeS88Spv~*#PKvI5Nqn)oaRbeS zuvTE?xH&$Ypq!2&j)s%9K2P%^qY`RX^PpceyRx9GvV8F1d<+mH^bT=zno9ODok+B3 zdB{vF32g_8b{P$b5}SCyVvA3tvjh$s%H28Mym!+OE6O;*S)J6PKK%2~Wr{w`K-F0# z^gTIFlLj&0hvI`@P3w;p-?NX96>@V^g8QhKX1cj+IntoaWwc@4rG>k=ReuzY zHsB;%s8)DQQxqy5k36L@!wdsysT)=8Bj_18s+BB)A5J5A?BWwt8l8WQmm`EMc-)rv zTt68QPr^ak%q3Mi1RhNe=bnK?JSHM3=8$Nkpr1h80cT~{JjhR2_2`0}^)u~3V~T3| zz3!!_{dt?&Ms9en-nL)X?7H!XR*nXWNoEu9cDSrvg%Wh>xX}B)=CB#i;1ArHxcND| zd|?pMYOQvJI_)<hTpT_khEmgU_XIazD;8zt6qE0qUYc8#uv)o zLB+2$1hf00u8zT6T|Lwd^gW39ZaIht&C6k@ zP9u4cp>)>9h{Oq_wMY>e2;3URE&1w>Q)+~_ZPPM08&id zEXg^El|nMjUhH?_yp&XjMI1@J8Vegn5V~iuKn)ugyl`nNx9xxuR|l_pS>&SzeDLjLW}-Rwfm-F84JseQ{ONV)mvj9i&hk-Sg<>iU#yd5b z4=tP2*}J-K3$n6ttm18ZSAV1*0XSo%A#UvId7NjpQ_to4kZ@vGt76w-+G!f?8lVJy zJ7;usIDkXPwcMw-fEp zahO`#@@9@Vk>Od;dw>OARO{kXq78)FhARq``18`PD^RiTjl}(H%H3a?lZVv)9xmaX z)$!@ZHm>}T3*ZKT(*sCY$Or)%R3;9_oY!sJ05V11ISfgY`YHu5=roz-rsK*@-xqBQ z8+}fjk5=;@T>$7p=#>;F#;!{$?k!&C??4#3#-{;6Q4V|Iwc~AjDfNaiSwCUx+cF5l zr&W$-$D<=qYz_t=4!u_Njr}6=%&d1`-S2gAQGqzV;2_ANijT2ZRToAw*94iW&v+XI@ z$kFq*-k7x-BjHKilZ57WqK zSBX2`HE{kEO<7hYJ5$Qg!n zFN5u|+)qLRPa{GwjDq=Yd9Xm7;IZ-l61=Jsly4+pseNM$uL=$ufLP{tQsHRdLfU_L zEu0n_RK@Anh(1oHXMV|%y<9!L@nto(6aM>YniHAJtE z;kZ)9$C2iSiLf{M+Xf+PwoW{XEN-9s=N|6oxPp*+x1><)kkBsK9JOTzc7x1E8a19C zyK!YK4L@fm&g>qi6b+wgmB?g!jtTjhRphdlsWnfMhi#(xfo@laJ6b*_+A0q9G8u{Z zg^u~fNrDce_b>{fX()5U2>Wprm(cC~Iyy(4WI3~g>2&@n+F2RFq}iqnF)Tk*6FPQf z#eiL2ZAI}IkI~dly`i$sWo6h1)i4G}a-X4n&$mg==R+Ym$|LIRi~T6V3#ujOm=?G{ zr)HXxCZ!fKX6u&?W?E(jZZX{>DQdW8Vg)4wL#^Lc*|6P@d3UGUq>58&nMzP|aB{d{ zMQ>jEuo`+lJ1uS~&L-364#MKB&3$1Eafl*^RMW4*IYj(LD{r{kG_{Sem!z;^OAeKe z%Qee!;S52olQcDL!_$;Bg89+ZGs3M`F=J@us4hiYT_s~!iEA$oI(nS$e4BB6hB$g5 zvsgKu21W;A7)u?lc2SDK9?5bDGgTagjthT3#YyOuY@5FaxpBXf5`mNEfc3JtlM)vQ znev0orsEsR=#=hJV~XsadNP%FnUBe14U;-RO?Od ztgxD%noxAnOk)z+k$hNI-((i*Cm&q|^a`GSn;7GtSlwEbGir+6CSQ31J!m*<{cQ)o zE;YiSFLd(2Em8Erfsm7XE*E1+iztd}txr~9ajgTU(uVWpBJ-tol;km$96gAt7ZzD3 zzH=CzoD7hP1pDRE8140E$MqkJkd)td{g0z+Ih#Re$yw$`(6^jXBe&%F29x;FRha2% z#;$YaB?GHbboZ>b5xmb*&%_BoC4W3f77A-yK9@Y?xi7oAez~cu+X3pBB^I^ABqK`* zaKkit5r-9zFuc>*UrWj7QzJD0V_$b%7?Ok1caj5?9bb< zjfIs*5<10Y#Y5sY?e?jh;q#-(8!4#<&nq0Oh^IJbMXs<%6=p_@Yc z7g{1|xR5@SEZN3-T{5YRyX>qe6DE|lL@Dwxhy4!A=q#|#{yFHr)2#QHdW=k#>&AwW$ayaZ* zq(OXf18b#ES|%p^zWB7miQHUFd|`>%n4GH1FyI?Ja4+J-8K#MwUq;dJaW& zC|t*uR-&ow++CoxbbLAtQf;1A33Myl9BD&Y!*WASu^Kpj(d8NSGweH>fJ zi3i_|jk`Hl{*T<7OSf6DJkON(lRvFw|kpDA{lLt{A6iu2UJ zk0;tbo>=?Hw=izBPmejW4~!v}1{~>b%BJmv-wt{RrBKNMzI1TF51#HZ1A(R@@d0r@ zzFWw%%|R)BT5dOt`WHI+FM8?!K)N)YB zigMM|ZGF>ymtQyK%B-XO-2CVW$Xn5Qc|*NVtmnF+It%B^Nm(9alUWv)Y9Ny-^~YMBc!S#l z!k}-#&De=c7512^KW^r2n;sKXJk{ z@rMrHZr|+cRzxDA%!PjY{99$=?I|mb6%=1~`>K$_zWVAVED5NIf+1vWW9!qh-gj{2 z;g{EWx4M&ms2}hsoO~!--$SolL|=Ra39ziOWo+p7txO!!S$qBtH-Y3mIyN6b_QeBC z)Qb~wCPHU99IbG&-y!Q}K_EMJetA4d#s36oS0DwmCPmZK6i)(>7aeOsNTAQ2AQ7>O z6eL{YDqR#TdFE`M)&wC?ks7FP^51dkE3CZ1Ax3%?nIl-lBt=&UG983K@2V7FK7qk0 z8EM9;4z8@4z!I5t#0WecQfT(D%Cd@eMUD6=Owq9GNCp-gHo_C-U^@SC*pE3l6KuaZ z*#lpEDfy!1G(Qc~^Z+V3hc7Hg;}$(dz((@Th2oM6$vGD;>ts<&ie1{DIhSN#6W`SS z)PB?>ofs?C30UwCX>AGNgqTMpmG?Ek)qg7a(;`$nP&)L99%EjCJj9wS2kHOC(9xsxr_FFlu>By($A@BZ5&L{ZvLL= z_Rp5c2Q39H?{)ToxKIloOQ_zXvQS6401zr)NcT&n_>F1(TPh43@b z<`CStE{82rbveWcn>2)wpbEme#{JW2e||RAuLk(3N=}3iE*Edy90{efQb!*X16fPL z7Zo`HJ+F)!Uk+mpf0wsFZ+N+%3!KB=u5uxr06ox?7ux0U9~A*Ft~z-yVzB2b-*tdH zaYd!UreL_P>rKD3OcXI*TJ9ye1-fR0W63z!Uwzl{+kJJ} z6}$ODezF%b-=X%e$y80+_GsU&eI}^4WY8E=^Yr8aG(eo8;k;HsS|MD(rWBcc8`WJLf_XhvWSM?LQs&S|0>w3PfJ!COo z*}v#3n~}hLZGTDE_S<5$ZzwA2a&=d%_q`#ycJoYy;5&EaUA=F37H4D!^iigxY54#V zp2@n?%~e`H%-gcsQwW3@oPRN3csYc3f{#VZ=XD5#^xlAov?dybPdBYQiLY*MV<)sp8RZw zQn5@1AI0x3Ony|WMQTVk;lKrZC!;Qb*<#x}C6BjvUHi%1Htoklux`cs^kZ(0_&Him z6~)2dHRbIsbmaea5~!$_C*B(%;~niA02@BER>snh#FQ;TK9a=ZRs5Swm<$zzd zdr*(fg9-Kd8FC|LLorXJMCkwY=Qz0h(7M#wMjoZ*NL%Q4v~)= zoQte!952s^cNkc5;qYad6uXjU1>voMDN=SGdW}+Pa`S7z0Lwn5071kRpFn!nOgt=k z{9Vos1Te^IvtPqyMTyR+$Y^uB-xksIlnR)LRlrZJiM4?xawg1vd+?^(`0(b*<6R5` zgG866E=JK4RGKH+e0SUVihP?t<=rwe%hm`C&QkkC8S}+S9C$6I7B^n|D4Ka3NorP- zJ>}2`R`a3cmyoNmW8?Q^q&80no5pS2PduPH);=IV~H} zfC3c}y7T111kh_aor4x=!Z(Iw^vt-MRp3`frhXz*8F49 ztwbG(G&f^VpT)%U0exk`v_n0%ws)$0rcBl z=YfL#a4-bc_}1)Q-Q^qk<2(G6RT2b!?&lny|E{g+MWjTVF|e=NmLD}Cb~w%M$fN6G zrGMhF8zLula1!MG2kgU?jMu+KdKy>HTsi8K?G%L(^D7)ea78Z(5a)6Xp)4MhRPMquyYgNZ&zYL+=+w4Ln8u7!mrIn7~3r;Woy#(Mr4F znUNDbX{K07A}aZ6qgdlZH_zbYG{GtZmaSX@Q5LGZ=z1HTObltwWLL7;x3aW=2S>jB z))XA&7YJ0fDmEKdn1+=nz`wY>MjwbOicdQncywtRP865a++0_&GmFy*;euV5{`EOf z=!5hD;VDW?!6S5GzRE6uFYb1ma)nIqG+=$EFdioOSW=G(GRJc?dW_H82R4ajhV1mT z3s7;AIRre6F;MSD8Z*YBV~pVt&_v~v z;4_<=Ar8u($(RWiBF-~nW+J#*sfeqvVv1hRTESzXuVostA?E<~onFiQWvVS*&Z6MX z0gn`zvESiBzWzh@zPSHK2K+8Bn>LfB31Jy|*X8JdNpIH`Kg*{~xmQN(wyPVGyj0|$ zkEOw|oEe~{4Egzf#UcS&TewmRkcqbWJxK3kVyf^p- zWc2#|*T404i0NPgL2KzHgJoJAee3}%bvf~Fw%~U_k+KnT=fa*}f0Si%o6i?mlhxt? zPb`%(`Gmu6`iI+NEKax^xEe@bn@d4{H8aHdFcY6y`Vl%gH);04EE+? zn>`tcX~C%`6)ruHeKz&^baCyG05zmbA1)2~?U8`=$(ag5Lxy`K2u-Qemv}+Rc8>(2 zBYjHPxb!9?LhaLRiEUw~II%#giK0@D3kjr}1zE^RZwxspoH1fTaZ?DI9Nf=I+d~a>w+H2Nac_BV3)c_XD zCqym0lHfvo;6Na@ekx^qesNjk&FW71?eky%2yp$W0TCBphn!zu1DY;S`UQ-@zvb`7 z1XSnMKf3LxDS!CBTs3uD-*n&Q*G;+d4}1x?MnM*UK`~5EAW-QZHkXABe9nPNPaqm8 zgvdD>>5IP&97gVCWX~-w?*t@~S$LV3%a;1taY@L)8H<-uNTT}p`9;R&;@;e4+wSdX zBw+e>{1GP!ehQTzxV%q&@^~m*dQ8)TYK?oI%_|YpMW;kv$k1kpC(?% zJ^*q4?G-h9`S&%7J-4D;0{hOeM<#n5nR&C7v)2oA;?JFrn}|^d<$VGHNF{fnW?2d+p^1D8tDD5+wa~GSfaughu3S(t-5c+XPhfy3Y6l(@cw7 zdTe;hL_8!HCmYUoP)}p=o6S2RY@gqG$%}8f;Z)+@WfEy*M71l z*kT1=_;@}MMgKAFu^=6eNmICLaL$M30R;^yJdYDIHuY`WpLz^h9V%kb!Qy)O6e0!! z-Xmeq+L8neY{?^)iiQ!%IRNjs z&Zgu;65yE$O>=V-VUDtN^jfNsB$gUUq}Zyx9OqDLHT$eg*3cDg#bgTMc4N$;*zUJH z1yCPtf995Kdt;Jp+0JezabCNZ8Bu8?OZcYxOyMW(tFztH33g2q%q+aK%_W~Aq&kAv$ZyW#Fm!;bRPXZDzyqcog zc!DeC+N1H6hvQtuSc>JC)ge>B?+L%0Zjbcc;rnIn(WDGk?t%8@L1>y;=W(qIlO{bB zIVFynf-os>#Y1Hy?8*Bvrz8vpf*w6DVK_*7PEI&;)T43KH^rvQd&&h%!$U_>CUnSl z`8{G?MjICSmPf>}cp27eb+@nHpPAe>oS?|hGe;*S0sxrg>~Irvq+pPkHbh+f2`ymC zLp2iSIjHSH4$x~P^wd+7+sA}5Cg;^X#?@B0=*x#h2J~cvpsn|mcSatzCzM&xru@gw zGRra$H8t-bH5P1*SYTbjVXQ<}c)qjbgnXBODCCx-gpwqq z@fni%pR02YN$4}lt|lk=;dmaO=4Z&J_on+{eRZQF$Gex|_81hWp@S!2Sd8LezGfaP zc3L|+fuDl+mTAmjg2P2uY=59BeK(qqWbmcnWmnfPH?>Gu;R=p8S9W0=gUGaw(flD% z@>#1Iwr4%INr0;End|@)BzZFTjPCx1?2huqFPu~{;RSXgCz+Q2L?761XW6$oa6`ti+d``(BHs>L`G2@(#0Dy?r&V|Q?e1mKj%^6oFba`d}ba@hH|2x21rnL=#%k) zs0Fg*uG^jec>Ll8C|xfS*_ItS3enytMvaNwA`70L5o4H@`e7rrQZU7$vHB$-f6P`g z&m4-kqsuXV_-Fq5pfO#%WhDZvY|6X zl;-$tXPQzhy=SxT-BoD5Q3)bfI&nkNG0_UWoPm)>m@&woBkS5pCQ-)jQ!{8tEpwg6C2Hk8~@}A%aYAM8y2u z_*k;5^%RyUx$<6NvDIO1v&?!7nN@PJB!N}zTAH-VTXSbJ<7Vr%u&T~UmQ_K8y&|nx z!Lj98f!BUvmbWw{S-JSQz3)3`HC~sx9?U;k5qAt0X0AV>yekl!a1B_-zUQvV)42n- ztjlu6`vmU--Y^plV>bbljmPFBcVJ56i_S`t_@mv6!RIU%Ppv(k+ck+xTAP&i>f|i$ z$gI=Zg2Y!RyPwWbU3|q^iWgCFF6-a7DS7L3ibYsI65F?CZL-<#swW} zl(|FsTY||R#UflewJJVt?qAX{Af@tlA$AlB1JHj@R$KdEIL6VM!vY>nk2D_yQ{)Gw zltqFlRR(9u_9)%-F(d$}Hxy1kT7XbMrHKyOB9ep#)t*74!VRniI&!}La_nXoRimco zF%etV`;ee5^2ox2hW=j7OSRQS1sxR$IW`0idJ>_G+@?t%bPrkB%mk;C7_`&S#~1sP z+Q%!+lB~cpZ?afHgTdh#59SkM2|avq(ksL%(2>A@^#jfzpySOZ_o!vGh9s7YnS=Ux z;5%sSaK0x{kk-Y7PdOr7_?X~S>}K{Kc?j9*+ok~$>5J|uu$5W!!YVJAXE&@cMkM9? znx8;68Wk>J*B3AZ`mX0Zvb?HGYD)AcgrElCSZ;veyJhidRTS%D?Ho-ued5t1te`if zN6BGpxZ7{@>Lum@L^C7{q4Snpv=`=Aef)Y4gZZZl5Y9-)zG)?#aofU3gf9$?FLabI zd^q=5OnSpnM&ofxUNZ#GuGTkmsiSkLu!GxB-?mUyIor)`XhAvFiQmVVaaPrmV_z1Z ziq*cO#M5%7&%H{VhU26HamR63ivM z8iPDEg3MQU)|imxA%6UesdA7S^h3VPXx~tpg&8hi1dg>(~;-C>Jjc0hI zA&RWsjj-@!Hx8RX6AN`dj6+8v{`u0S7y3))LqrEL0O3ySyqyJ;^D|^+l4v^$6;R2R(TpG>}lB3i(}*) zRKo8$JoMFFPRT+`l}%SU^!C*AjJZqqSOj`D%I7ZKGvXv06|D8yJN<;aW9V z3I*1<=b7)ny}UgC)3?jlZ@)c%ck#ntJvLy?hw8$6NjZ4&+BB^)e0@gZ0q%MhQM?rj zNRK$Iy-Yc1IIe&^Xxps~=h(|l*B<=JMVu`wh7c8$p(okzYPtB1zkRQVuY!6sNxAoMi*RIhKFlEYKWVpea{P z-PSkVclmWwu97W|ThVWMLmg8rk8-YzO*YB`$!}8X8Grk6rmF!xG@vKk?DMiP+SpHe z5OTIGE%3qWHR5T=9b(w~kOTOUrK1tZT{u7*@AD1DNOS<&APVbkbnE=B5 zQ`UOGFUdv1ZXi8A*m33O5Za)(2#GH2pn?LnFUB8F7wWWg>RD}?wZQGD`pf|md|J#MPDi~F);!!D z4|5j=4Z-54FeLC1B9?@(&T93Ihow$|0N>IdNI!ShIv?@lC_eXXS8U(pT^>ES-@~D$ zyjCzY9N&taTFoP?T4yj`hZrbtN-e9;9V4}Uvnu3vy#*2@2VFQoC7QIEld$EpE8>MH zO!}0j_*iZ>NWAQN7KvGlYK`#ZB+|iou<~bdca~+&9lE=63ynZ+H-O7Ng8C(0dz=i} z`XK)Wm?&_RGx3LSy6bzM&UOvws_gE$(T&ew;l(=_j$jFI>Zhd=Fx3pijD}CM^a_f& zpG&r%UhKi{O60kF|NN(SuV2_xx@2qv-+oh`ltV4mr+cj6v-^~eT!sLGeG;}y&p8IoMk@^d7$9inhpw@ z?S_F9CpZa{yYI;xsrVWL7Ki$tkCeWz{PGCwZVDxHf)sr79o>^}icNuSF1x(j_lrI) zHDk}>{Gwg+5tOsigK|mzyt|L;5-D2DCP)hc=0QoXsZ+7W#~ZE#0X&FdfC&JE>D0h< z!rJ|6RkZERJ`%ww2fdamC=cKvWi9EMi}vA+kCdc(n_V2OTg>e;wXa+*U zPcsMXfC|vz%T$TvOti$y9!$I^3v2d?^CgXZjW>2<7GNh7VD&vaOQA&jJC~PpC-Hbf zH(v4YG%G%VzJe!5I8BR$ucn#s(V02Bs^JJW;+(AjMAIt@z&`)+B7-r>EE}=jdHDKZ zPRkKCgwyga{hZb>@c&empVV!CitB9)P;J*hQ_>5KbHR!|O!Jj!l3t&CSh|A17Uc;C z;35H!qXZ}fZCw|ey1GTDiiizDjcOZwN$OyeDG5Y#`0vRKR#wYhQ{Mubq@fMJT-Dnh zo~08;rzhgGdm#z{dSk;FI82x_h*?gy|yNYmfP9<_Y~y$^&hhL#r;3Bi+7io zO)H$kNJ`LG2H&u2kyk|m2Ef5@JBDglR>{)(1i!~*IBf_hw_6EwI3Wv*Tg zONc{IqLPfx(O8WlQpCj;Zo*L{uBZ)l^4;+VV9$cG)hwfs}{HBDsO1{g^UQ_n_ab2EK@ z#c%W;gBXC362gBhXB+xM+t77g!~QO4LuZe>J+)D|DZR&leoDolME1D#p6(tli{tOl zTIGa-EVUHj#C%ielq=7Z^NmbQx6Wuw3*vFYD@vK-0hGE~7Y#X}6%}(tBfGriUSe6J z_ywxJ*OvlD0$r2h0h;<_A(=3o_sxEdyC`PJev@5Yp$K$!wOC}B4~t&xiq;mCQ6a+D z1H>NO3b1bMMI2sv)X}{I>)O_>3f9ANFt9YKR#C^7umkuUttz_7@Mwfca)Lgv)G+*I zgM~6=KT!!AXuxhxIzuq6fJ)4n-8A)9lY!uBs3qOv*TBSJL)zSW4)s~FAK0*mwH9z2 zgfPj;LQth7f!F({f!{Z9rkna2sgMPZFj`Q;LAfP_ApCh%)g5!Tz=95Vb<;D_wU%b_ zLzxSy0%!vXy(?raKVgn#a}#@Y{^Lc0G4WV7F-4*zt8vJsd2BX^9ZR4aYXqB0OPqvR z5%(p?QDuRa7OqA@X0FO?ZH#-U@E$04Ax5h9hh)C|c!new&i zjkr)M=`w-$h2<{sH!j9qT~+(d=IRQWx@yX?g(bti{s7*J-T9{_ZwicK+12lhs^unC z{0;cbcGrpTQ(S5LE?M=C2G@kgn|9AC#QsDYJKo&rlfME;Zz=S|n4dY;QU?uQl!1e%Tfe!LZ#ljz#El;>6M0}opjY(oG zAg!rM(^e+PycL#4vdDcbt9AWRFr6)cO(}RlKaTK7F9>0&Mz;QeBoJHVTCVQuas{M} zFWU_YSt8^O7JyVqsxN7flraJCyl9cW>_V)ku2e~_8jaL+3}FepY?IdnbdEw@d%i0v z!vVp@Ofugag|Jz(zhbp4)zBmL$>njD+Q(U=(`WJ}qo=bykmAbk#naYx0bIR=o`^j(%e+JhB9RFF!3+MyVUXY#FR&Al=7HKL6bnA>KlXJC0#Fi{5|*KYVqIf2OB?0{p@S2%2l z8^?m!JB13Lk`hk6kgzIbK@UhB(F# zvo$Wbu~9h3>)!JGq%LfOBWtTnj>cy(6w~YYPs+3Yls}+yqocm{jww$*%s9D_&aGO? zvD|Kl7#q#39o&GYZx0#lqABJkFea*}Oli_ftYYOi6lxy%mUS+A?hmpP`XW%6iOzhy zGfi?moakVq;pZ2&qg&!02~fju=;vt7BjeIBAwELL%xGhxg3vJ3JrabbY0(3vX25$S z5FHa^GuJ*T)Myy6yV=hW z284dQ+b}3o?S$hY^%~xktYR73qH^FN*218j(2%91;p>F5-9;>0K|m+82x_)Kj^17a z)gsL#xahG7Y6^vAoN^Fj+K+mWGnLuSG1v)Cn2Z(IXoffmne65WzbPX8r%J-Jw+)2aLE$OT)KPPWS5Hx=U_ilxb8&HE|Kv z6Gugf_9#qR%b3#A6XBY!KWGCbh~N5FdPO*^fnS2s_jj1^;v^$amL_yZ?{Qaddb}%} zWQ?KE^8fBp6ztX^nciu4;0w=2A@oEWXI5NM! zH89X2pJP%Q-MJB-!m@JTQ<({f?e0#P;0~kow+is0iD7|yu_DKHo%i>a?J_2g?ss*CKP}rLZ&r6#S87JzC?9~=b8VGIvnyy=@KBX;ft*?f z$#TrN@YB4o2w=o5Pn#@oAQ#}e6WenJeI8!Je=bx@eXsRZX!z(`fPp&BxOCVJgz<%V z)?myS1phl|bxDmvkYkagDuc9-fZoKU)T)lswx=s^+0dW8o|F92GuIx0=DI< zsoVMnxOINrl&iia*zLzJ!kzhmWf;}f<10{A4*dkApbnFdG2H=RQ_p2yCKA8Z+z)?Q zt&2|zbdtZ&M&c~OnLO;^hTorGu%lqEL%TLyzTm1G5rz=9NKL@f6f;u~g*ppxA@!gA zu|N)DTPB?LVfP``M`vR}O<+>?$yO#^=S&|P+9ZAygx5I7V?kvGNWI>0BJAm$$b{NC zxGv=06FU~i>1@YhI8(~;Q*akc+8@sWtbqXT(R zjcQQxJr!SQ?&^=K*p+aS;6_?Z!Pek=jqXz+v)pjQO@o@dN)#i60R5@heANz>VOEx5 z@3XY>XFcO#+st_vAOYUA@9L{7@nti)m#x z;+u%5#(RjpDzVo_rF{^F1POV}dlmpP(n>eP(K>yPEbiLk?x7Dud|Xu+T^-{WqKs(xm-I5CP@c?fot85WW{pFsoK}VPU|(y(WsOw!<*w!wJ}p} z^<+;w0LUqiULW-H5jye_^6Pa6o*s{ZCvV4Bo@YOzLVWCFO&;dOFEoID7ze!g35QMQr|H~s z+Z;|`{vj_n=t9UBFJ<xvW*Kun(z>{d?`< zyf(&V`EnlT4R;V@9rmD`%CY9x-T8I*Y3R}aO843&UTZzBvBnjOmnIyx&4zO$7D5dS zf`T8ZoCUu}`@EFqr1dhF)YX-4STf(5LW%439;vD826y)U&?US}6`~d41oB_usDW@{RU{Mn4%;%E-5Lm)w)kRm@_g(J-SPo4hV+J{79-<|Nc&r6WQrTrl3j9 z$Rh6|J0pp9o!C~rG#)0EMqLKXAKm&>NfY{k~f++0?XQ}&-Yy&SovvY9nW$V zXel5+-$-woHKnN87Q`mESfdzA4NLnZFwVMJQ;aCtAlZM>SZQYeX>~$yI^x`b|5QZ=x_|XR*VfkhNQS`G2cLbJT?-wc1 zu%#zSG^}YjNH$##snG^>bU}o{`#DJ>gqK+q`Aj&|I8lW2ngq&qgb{XZ3~7XAHExP- z-&DeNf#O&k4ur{%tM^EBAg|o-N=!I+f66!t{QtUG<%08&hv&zfzb}&G6x8{}>J z=u4fyt%@Bh#!_P7{d&Jr+566ayodzX$FE^p^udD15AXiv+qZ{E9*UW;v5qTyIE$Wz zk0&a8*mTj)7Ty#r2{E(l^+X%-=pj2W{;q0jumr#J$k@B)0 z-zVx+tno3NzjLxjo|4tGp|>P4Fsom*U*Rj*&3+S}M-Hk=3J&zNdZydW&iHuY`hA?x zp#O=lW53_kuvhIdTOp6Hft>J@#sRyL_G&JXb3kpyVY{Tf;uc;=CYHoTK4BR9GjsSy zv7H;V>Hj6b{O#wH-bB}h>;T*wd(Z*)@P3_-<<;sA%O9N6f3-(Ydf^d;X}qJugxyn+ zXhD-8;I?hswt3sOZQHhO+qP}nw(aiQn)}Z_%x=U+%+sl?=ZZL)kyZJbT1(O>xpnN_ zSkkcfi&=p(d5EHad>MO|WT*4zs%Ogxun9CYDU70-Xd~ILV=m3YtJ~kV<}dhUxD6Y6 z;@y8iLp-&Jt+#}<*hC?_;D?`#t>2Tl=OuRFwX<%DJAO0Q@wN^|*BvW_zLyHb~=ZsGMA%t0?3i2mjpvBz!S- zH{5-g?Kuco9?M&T5j3I;EATyxftiH2a>=<-*6`uPu)~&VkBK)Oigq^@tp7ZjY z;Q2T4{yb$gSeN(@zz(mq#$6cfjoIf+tKMHkcaSW-P^xLhgmOeDUNOhyV;%Zby<~$lA{s+LD7sy(ij7#FVq)9AM)uPcxQ$noi-?NID`7G>lW~z}WkvaB#A&w%PF_o-{ADITiv7*=7ZQjmrE7x7T z+isaVs3vf?xc2wp?RFP?Q@vaItdc9Q)cj>(oX(g$VmDCU@E3Rb$zz>kB&oVOlG}WI z;0aY$i8w3WoUkdi=#Zt7fk@g-Fwm?jBcvy_4S1CS$KnRBK;CmmDHy(9TJ{sPc{OiM zRDnVtQ%nQa(&KZLUW228i*%H?%Fv`3$ngj4eDYvTHo~CC-p-)kK;@?G)Gb2^M#o+# zo*c;st5q-pWRuOjP> z!A<5{NBwK8&)Ic$6P2gyY+J*n1>|1a(7VB87|&@sOo`@YBr`rA>xHd6e}WPoY`dW= zKc&%-!PH(2^&V`(n|cMi&3`F<Q9KI?N%+2%oSCy5*F5ID5bA=Wxna zjB@a^&USCNpWDM0H~{SQp#C~>g*IMyT(AO!q7pPJ2;CDnC%hEMXxg{-5032|M!a)G z?1JT*ffccD4YBLRSqH!GD)c(*`hxDSmhj7znM9fV2+=EJ z*hKdv3M)5FL|4=$(G0NFD`A+Y>OGrvBRj3S_w@Q?qQjRa(^|}t0Rx9kC5JxgEnDXy z8W>Rk`^;&!)+3@km+ym5Zs{xbL}tR*Hu1f*vZ&ECs@wQWrk@UIN)G1$wT*?-YL__7ioo&yr@^RW* z;;E{Nq>E|KOkw2rJ?8^UrHV$@@z_t{R0^%fE}z>W_BYvkwuviZF|uOy>;rZVZsv)R zJKRWD<*-2zF__0H73>tiQ#o&iG%j_l?cM=qDA}Z+K6>$^av#hRvd2yWHjmHXeyz1e zmqf*9G@z=J>qG@m?p>YD6Ou<*?JK;@#o2wwnEmoYgISC0#Ur<@F00f0@=`$m-vIr( zfU*yZqQ0TBrcCrzt&k1dg@Pxaq={RA65@ZTXmI=jJvV)K%>&^xTrvbm6(b2H|B(Ww z-Y2Ab9qYaNl-;acV`duYcubluNG=;(suCO)?2s(CCq@ZnH(pC6bJR@w?}t6iUR7uG zq348P)>)-O50wD64EJ(x64neQyLeXF4t^pw!{bR>b}_kSA4p7f!?3?+H()I3^Tw>Y(;%o3?uq+FZJc$EZF4 z6$4_uIoWwbVMd9>G#aGb*@_#-38KV8{+)Zu)J0x%87KVX1Z!UMCWzN47oXnrPnPc*|hx8WEM zRJlthewRuzuyEQBh`k_NJY1H}Jpvy%!kOsr@O1&mZgFw}u_A&?>@oK7Twu|W4;^Xn zk|ec@YufT!aRyi#Fj>I%Dnsae-WG+-sq%4&Jp7FRLT2=yL`k(k3jg+07*P5-Rd=O( zjW+p@gbf+|J$+1SlgIF`OtAPKs9|AceAxj3PV}(2t{7@8t;!DpOarum`@^l{G#Ftz z6MppQ^cqR~L6s$k0L6>zY zOqq=YO>ZO`PcUb5ti58@2QUmCU%RUBB9XEt85k}sP$+~-EKF9zSY%pTHw)VrYk7@~ zlw*Kxc2P?bpFgV-KZ~iyg(vcRXSKU0^e$1@+=&iRA%m2yzcPj=sTj$rP$hVH9$XLB zT5AOBcJR@`?yl#W?3jBo8OX*O8;FO}DJcCF2odK{OMI0FT@T~EZ%W`Xj6Qe%gbhfq zJ)Z$MLNXaYJAnwIbU+w=h(`W6jQ}8+yy7tcWTjZb0ScLzr2-jGRvGmJ1gA!v6cE>X zA(+2^p1SbD;3%o%XNWSuG6$QMP5zO{$6V}H>OmeHa1b!GBv>SE7A@mgbu%fot&P4y3UCM5gO#=wL>HGI?kxI@ocz%pAxY=$=m^S zgR3hzkzqpkfPcizv7$i6%YpP(;FEZ1;7D@@q_ zA2g#@cCuvhEHtRzT&|w%Mm3Mo5dJav;VFUv0MiS~8!IL^EQqS6%zfmtgfR^3^wqTR z*20jWp@kz|_xypnN5>O?B^zLMa*q3=KnTFW)2N9jJNlc`{n|A_0!CDgYj{yM3JeTA z=GPuKgkM!O0$ljKOH3B7gU*Yzd$6m zae{u#Y&l$4zx(^YySaE_b$d8{Q1G&3KAYv77!dGCffP*?j6VU3FPRtscqkKk2K_it z%K8`@ZemIb)*~G0&c>V2B{8u2T%%_}NP;iJH*M&C+>rnRy)UeyHaYbp`$3LoZ=b@j zZx1!V9(%qbTHh)Vvt=Im#John+~p|Wt!3o(c&ywCW%2B+l{aDdO#$EcZ%VE1qhJ(Z z`hu{~zFqjye$%-g*yK;Gl+pTrLUD-A@wsVM@|=s-3mo*T`T0R>gG*&}^=zik&#&PK z&5A{+Z10Ce59T)DTvm(Aa-GPG>*>Y_D3Pk0%$)@3R*AHsz&U?oo~WmL2Z$h6Jtd-_ zx+5b}KLIHemy27tRgh|Rkp2K9qfdZ@2R^uoC>~~#7`Z~f5KT9Ev3=z~O$2=SPbqu> zK-ZfvUIXH02|N4$c87Uzm|wa(^KTl!@bnA-K3pv9?=}*c#M~#=uFS&CX4l)Ed#{yR zh$O#)NNe}weQ1kFLJ&O@(654|pmb-bIAnx3o0P9Q7;WNbIKb9Tc2oXo;vkk;CK~yS zT`&CfJQi&%xPZK@`MG9mJd9h1oPnh4(h6VjJp^*+f)dCrqa(QCGxZo>gS%^Gspgo5 zp08wWzM)b;C?t#$T{J1Y3^OO2?8NOrdP=!4W4P9EV#U#Zx2LAs0!c|E`B`o^PXeP*xZ5P!Z;2Z96~Q&A5^N#^ZOP69v)s0 zn2*P=CKQ<9&*4bkjDnPn7Yb}H3Q0NEIzi1n{@LAtT9E7wsOco*yxO+8^T&u*IKNGu zr_kq~>`Z3i>^R2TKAo(vcK*e_!5tXLX|vNxWoU8vMMD;&Oep4pVCw1&GtAVfo=m>I zi6n}%>!{E)!R#VZ=Y*&!!Dvv3ghTpW5f+2)Ab5Ge7Qj5$Y|b+D9UBx9vm(M2o57+p zp3eUs5don&P`=~jN{}O|SpM<;cUSgR{Tp>h{(Sx{uWAKHbUQQ_k3MZ#%RV%!TU)fn z`bnFGNFWQqd8^G%E_SuW221^z&&N@Y%9+5lVGyTvh)5Y*{$I~6NVe6Eaqr(`SP(mB z4f6e|LS2_Au}oy+WAWNPX`iTk5VIa>;Z?1qWG@&2z)e{2WTC+fOUPdz@ex-rX@xy6 z^@vF(O-hM}<lKC&5$Z=Qb2&GbXLnddsR-9vB`KmYT&uu{QaDP)uxv7zj+o zilStMjj_e}`CNm)c+S3P2e~2LKCxNw!}TiF6OweR8+RYsbnp&)llS{`VZ?2kUhx?> zRF(T0jxBe9L4ft1{>j`VhUvRzHaF0{BJD#FtBfkbwPXaST|W~$@I^ka+t*_insqTy zjs|zD1sNIyPrzwitRQ9}V)|SmexT1LYN7we`K&jzlGYpy`PUv4#?knV9hII^S;d_H zdA32WuH{y7wYt8)Qy*-NPB-L!{$R_9dWXRy9`qMQs8p0K&#^*zM@5x>5D8?e;>(Sy zG3nfu_7N#cKQD+_Y>%@{&mUmDtKuVn(SwD)!2r2r9-j{isYPzwpJWsrX zpwdV>K$DoL*_ak|K?$HGXT<(9G=Z(yfo@BNxk|R(i?bpmTekH{EFm6gCAXU6ck9%) znK&4X2TZc&Y>5pexT?@+Gf8r=?Kh3h@7JkoSP`;@`$ArhhC{b?;#t{mapMh`3(>r+ zrV&V3^;Cys=Sd%5Ju`#tG(a?GMAEXqiZuZ1|zOkV<_ zjbN*kp!iLL7Dn*t7Ao4@MMe<*phH=w_=D8lm`1x6p`;}4>(Mg?^O0GCOXL+tLpUQ= z#)uCe^=H0($GiIJFl=+Aj2W1}F2}oF?|BAcQX+PNY^Dr}Y#D9iy$G&JZqf}@ONnq@ zJbK?nW?Zrn+}t|ix@sUr_2f3f7qF7%@zQF2XJyu&--B~4zG8n0Qumc?jzG;ZLSa`j zs$oyw;wsLHM`8}%R@vl_qDohoH?bp4gy*E*JAgWqO~T=$&(iFF!(sCDmDWLgS3_!#`-AQ5o6SYtFX z<4%Z5I6;v)rpm{78nV5Mzpr>JZj3A8{@Wy)rbr7ro^7^zJU1pPL@*-R~)s$NC)*Ti^H z^zdt`ZU~2Qt#GivIP!@}ENFjp_8DC7zVaCL;3E@!vkCZWV`@$At?g8Bx^johqs3!K zH==dYpMW4J18?odA5>KJls|#q35$TPWBrdev=JNv>eo=4){a!Tyg={-4w>P>guP#$ zI=kyDNISs%q>u1~$diZo9(7}94Gqbg2Ws_$sA}2zM8fz;Qj&;jo`{1Cgq-X-LBorc zPnsL9;}v+3o-t8>fQq$Sqw^K-mdIX4-@*AK^Iwn2hoNi+LkQB)ieLT1dEBfDw_(wu z8beY)+j*Hf4_OY|)>UC(<;VQG`Oa1Al-^eoKW?^-1`a|>3k&qLTAKr@9LmI-Rz^xj zZylw?=pmscVmn3IrGa8H0tHB!fTe(&Htrot8@tO-dP7^o_(a!ax7LmpGZX&00~dF{ z^cTX+`237o&dsVZ(T%*HSBV?Ai=2l}D-(y@Qp-AkOH7t3*XmkpwtD&eoaRpF4Mx@m z(-Fho^9=Fxgxty`k^4H3H=ERk(c?R)oahWj74b@-9+R-wf2MPwYnev#Bs@mAvN0f^ z0Xd4K%7A?U?!hghQ}CVk-bM*n1F zZJ<({X8f8Bn4J2KC@N<5Rjxr8Uvs+*>HF?Q=`MbWOR(r!Fq2HJ<`DIqieIu%Rnoub z+2bnIq9E(2$lZ2};CVaLC-K#{)%a}0lfA}ZO=UtH(GkgDk?40f2x?g{YcM8jatIE8 z(em8?WbAi|({?d=^&x0jr(I>c+4Y{KFB3EZaYXW{s zK4?{(YBcX(K(XiT2G(w&6Y8tOKlLO*tPIUpmH2G9bMNnM73r`8-|y38#AA?6T-(~I zfH1KVYzfdx3zlINyVW425h)ho(I51vmJxI24GFL8?b^(HtQlWU_zyCyA?~Z5?d2SE zEN=QPT;OEktanzzvt)uB$vG`W%9GyQ>PQezk1{~;*CgGW#Rb&Tz}w!mUzUAAhe&6c zh35p3FuD0wa)f}88B^kCig=qr2k26J)wW!O3);17QO~hv-FJTuQjpu&REKM%2jTG0-E+gJWl(JfqH4++4d zAo~AOv>|2ZuvCk7rw)vgt>-&JUFVM~No`B*CEQ07E;F5w zBLg(IrK&#UamwxbgIsKG!2Tko7#OjGO_D8LoslsI%Vk+}7XmcX3YudDw$V=G0qX+r zx}e{IS&D-Jx|W>a?#;gRZ6WPh_?N^|Pa-0%hCO;gPGGCH4fBK3^qBQsa2Ti{)zz@6 zaAork^Uh*huxzySGr@x@Rk9y8MKTXF>GH+rEQ5~dh89|n!019!%^CjfXeg}nZL%%f zqqp2f!`7P}_Obo~3bjr67Mb3WdXU2C85uWY_KBJ_a{)jrsau2%2ON=wso5H%KZcBW z)gHD*2Ti#woM2FRCwo0PML+y{E%CvhXG(A=iWMe1-F%9QdUf@5TKNdsOViO!%vz$C zw@*usO}=e;^rCGHz~9t9I=2?P9)Vm z?zeLk-k{Uysz%&^8+kBSw1~&1l)_L>&UU7&xo7%VF1Wni8XoBVK!NP2@g&#xYL{p? zkH5XTW>a{i6EOeGS|3@+QGY0YyREh3!_ot7SlXZ$jj>(P^rZ)-0?s8yQSIK9AsPJA z3ci=2v6{K)BA^3^p6PiZ0r5)Btn!CGrpivCjkh(JV8G#GPi02twP{}SE$C)sX~ z9#^$RIZLYn++zOWOb^0u`d7VAl)Xh7S}``8i38rH`)qX)>! zb#&=vkP1Vss$!Ov9{}?_X~Kv-3sgf_$QEs$@oTY6Dr{yT6_dSsHaB;*Kzmz%)A*b7 zKIpnyH4p)kjv*6%M%mH3sNpb6_yh~1)Q84iu7Po-mJJKzM{u$k!-0>H6~|NlNn%tA z`Ge_5fIoXsw@d6BY3A5jcQfTW_PKg!lb~SRYw(+t#;!o=TD{+2bw##O-7&~adw71r z?4u{E%s*ru`Im3(E)_=WL!*e)=nKGbH$QQqqiMq5Ub2l4Mza&x<*z3D)!pSt{)uhA z@0nm9bYwS%Vl}ZA8vTk1{~?ykcA{b;zUln->$AFcuc6b)PpN|aPukK^P|^MKP1QXD zUk*NgOk3Fd*49xQH(+)*)LwS)&%yKiwKaJ8(otUzFJSup{{7eSOBF5wyk4L8)1iBt ztdF1lqanHfP>@>K7`<+G_g@3I{2U0}-#css;E;B= ze$j~8*|;V4AQSjs_T5MC7Uer( zbMspc&zg}~k4o#oKNHQgBV0MQ$9L!NBOe2|*Uo;Zw?`UGSnmS4oqYsrQ%Yv=I^etk z&&eE{a51>@b4b&0zWj8#F9|GTdfW|8a``cS3{kfN!u#0*Fj-kob{5&0zviMycD03yzuDxbiB8@tZ zZV|52<#ufp7ttd^^ApuuB;DNNYfr`=nPK-w#q0ctLgha2W?;xS_%q>-4Dbd+B)j~m z$oOSUvZ}t^rEKmGM@vg6l5-xsRbF*A4Z2 zZ@S1WrcJM0zT3;beOJH2q<$Uz8sv28v!wLS{}AlY`9}e`d%xxG_5S7@TblG{J>ybn z_$}R`!B5Gb(IT2zacyVu`#%a8q#hR3i|fAh?VGwFKJYHP(_SW+G`0_^>iH5%Uy|-B zS+fLZXst84u23|tHYZOhDttB~BWlu!q{*~Y6gvBU5sMKxoV`9X!hqg4BS>wch8GvH zIXk`i1w*YJH>x16NuuPK&fkv#Aqd9RVu5*`?+?^9Uf#wdM_072JgJ;`Q#f%Zv13eQ zMj1y9(}X|&cg(JP>P}Vef zE#j+-QiX z+XZ~7DEt7M%PM7XuE+^jULvAAwr0TE$LOXT@E7NV=!1mbX=!Z~0IoZFIh+4C4DcJg z(r9?G9BB;xe$3bdRcybpwjrWh5CvoIj%2QXi^t4CY2|~-1HVG+5s|z%hPc~@(#3Vf@^tch*FmGxQZ?KW1Kn8nLTM|N)I>x3&HzxjA=If5T(X~gSt69Eq z%e&jdF1OezzPQ;U)u%iP-oq7cq$`KRM#R;=(*k(<80WUx`M3fu+buO4B2yYtO$Xd4 z2|NsM2TlcZAg@{YNI}pJg$sgqaOY--P-l>Rm=b~>uo=^`Bkki|Scgkj3moz(u-1@2AAe4@DZYFU(yP|E=8xgHf*d?BuhloQ>8eLXVARMP;3 z$7ftY$YA2iTqyTMCTo@?K8=y0>S)xC?uL0}(N)J}9(aW@o0T1wBfi3pF{eQwxrB!#QJu0mc%87$6+( z;;YWjKCe^Ll|WDefCLo18PWA32rsqO)p~qXSMamf3vYqP%Ngzs+>av~NTFj&?Cw0F zc_Lpo?0)v62gA^|bBo8P?{n|o-Occ+uUy%@qPsUbhd42LoOeAAD5D25Kz(9O435b3 zFkrJCcihPou0)7Y=ep8h=^x~FG=b{U*(~Yd;}W;QPd|r6KOXzqkO{mbddOqY6f-nX zzl5U^$RP%Y+rbG(Q!Mv*xuuPY8|@MHwju=igz{783+DR^^mEzpaT7Wi?9!NV6xQyz@qg#S+J@HndwsssqVoLw$Hp?=tFT{k^nk_Z-3Gl7 zKMJ@fDrJfH-b8~kunmrsski+~5-|GBBLm*K(3IV)v0a{T*x|f&KXV}xpHM=X#k(10 zF19G3ih8|&jS{DQ5g%Y2p`P5{X{C!A+&@t@@wRrqaLDfdI&mmyNP3y|t!TermF8GrO%}glE`Zg1@avS4Z+>4uIAm|IW{KS*zmI_aWtK z!727D1tMR-X|QZ1aU7d39uSTe(gf{<*{7B`j#11%AS7!%mO-AIJGFx`=6KGJC3r=; z(}f`yP~BLD2jkkYhl(1;k0tQfE4XVo8ofN@kg_FN;;bXn`}w?lJZl4_W6tk60MUp% z`@7pGoGbS$oSbB`a#6^0&;vo{;kM_|D^Ph0oP;RQYRDn;Jse~=f#5M^e@I5>3ZBYU zT?L5X4TB1k@Wk=!a*Ffqwf8Y+R+b1=9_euY+0Pn33Vv%|P3@US);_%3#jKsU=L?*J zX4-nFNL%Wf&A;#EaOvI#IPGsKXW)=&f>{*1q3`Sfkkh2tkf&ezIgZL_1bPxf3QC1P zax|W$kb7hw%=5lw7uq*yEW|YqPCBU<=YPsSm~;p)))UA3e$s+}1b^RUN|DF%_VHXH zy^&`b@y2|QJ5lop=BMgsPZFwT=hwmUdvW;N`wdz-S%!mc(v2M*F#=;`M-=)NZ%ia{ zGVO8pH&M&yb4GZZqiFewT<9MFfCN8Qe~3(&7n)$byYO_ThqrysRx0Rziu0S+@whAu za~BMKj3xB3O6o`wg)u$2p&(as^OCdY>vsy^GKjANBVWj!Q-_k#tQ<~biUS7uDxj#q zhRcwfS76?Rz)Xr#(nYA(n@S(YKbgiK7T{irbvfHzpovokm#js#>K;=vS!!Ar`=r*R zMqc;h?)}IgC#Q=yl-T_?EJR;r6x{`$tZlu*`5o;MQ0vp;(cMqmkOm827zB`+GU)qr zMbBR`5OM=0dDUZogt49rjlA1rlD`VIPI5F@>`ldj3%*FgP7r$Duiat&(B-#Av79pv^k%LfYwxcAVz;MwC#jpih@f zjIr2d@3{JD@9~28IAEN85dD1OK4xZ_{^`jv>#X%RRySbIGPMSNsiN;ng?j5j`)2*0 zM2}=d32--*dr)49VgTZTNeS^Jj#lhi12|Yhz2B6U{_I5A=aq!=ST$l=i~+fBNOQFy zuBgxIPwN`6!9cB^j#~aAJFL+*?-G+-UQ74UNG}!m7||)--X^bl zQ#p>AsJ+HJ^rSs6rk!b-+fcIvz@cO~^$Pj{%M_yxr>4FSF>+Bm|REHS8 z8$~LU0tLkQ?gi!qrlI}e20?TRnJ`ka3Z$_le#^Ov3Rv@5VDzM}rG^5-(e|j(@($b` zU|Tr31gO!9GA4}>ZWz#a)Iq)vS$|t~8B?JqEL&3&m!#)N z@_7yaevZQ?&wc@506~vUJHE!8)c5z)zrr7|S^dDJbqstp)lW&ACu#DN4A5cmtDZG9 zk8j7!xi;q7pp#fFH?amt+w^TH40pugJdM~DSL$`eQ^SI!B3VWQd-c1#IgC*2Y~s;- zqA_RGTr+7ID70{^MJ*xjZx|qj{xC=U@PHec3Wl-UpnP@R8eZ z(&_e>o6*@8Dc^6kj=THmX{TV58?x=e$x(Xr?ahAUk%Q;n&)u4vP}EsB(l!yb>xz29 zV7F?jRpSDLmrb95>OZ2Jn49$hoCe9A1aS}kxMuiKu8-h>UH?moc#lV)sLw?6gf1*t zpp6!$pB_?E;F%0&A2Q_XvgDRfY#FM13R7BB$`V&r%Jj^d+xDX9a}Hp&n!j8*you|w zc2LAs(L2ip=AZj5qhS-@qW13P*jYoS4Tjb&`3h7nx9|$CXXqzWK&b!h5Z6iQCUujw zfxMeQD{67N8`$m)dKa9AqMrlO$ty-}M>!yg4q^N>m5Zs{&2|^(rlFXJ)nOZlJoMU& zo>UqyzQJA9uESe&b*N848HyE;7{gy((teFIjiXh!qxVgWQF~vOQd1Z=OOTXogtDdi z8bF#rQlYGuN#%=?;V&8C31-Hc^?9OpCX|I#&;;sxL&Rc8{I%#2V|o ziL6j1XEj^M{$?uSa24v1+9r?+ddvw~SO1J|D9GZG^R#WF1z`EiKcP)eIXta8;C4QZUV!Vo0O3&$xZC%GkKZY|>bPb#du7 z-LNGVX(jeEQbRiJ-kSAbx5ebK9*q)djDz|tzedT#4-*8i!h+Bc3uwWU1xF*Z9XfCD zAok2b4V_GTlsyJD;?D^$xcU@jEMj<;fVQbmLI;o4 zMC5wEa;>>jdar8&I;`ssvAsaERN>^3;HYYd;Cw)@d)-<7=5n$Vx&D?~CN=0e2wl4a zO9>NDsnKk)SFKVEQWMTVHG)hu)*47Jtu^)}r|eQ}6{LE;CaBh0;3iUGh}5qgh&P;wKU`a(l%TSXY#{{? zR8cn>q)Lj>Cq)f6a?mi9B^iMUHkd*iO2vhAXMEk^aGkyAUOtf)PK2tqLP*Nt1E2a>6M1=D2e)y zZsUK`vmgPhWltA5;LmRy_!t5IxM{f?0MPbB$L`oBiIA;3k!Z96&+Asm3=de)`#{~; zN5BY6g9#IBxVO`fcLK^N7qet@2BI-wz)^}KkjTwd{hVOFFv&(G z`cg*$rJvlWO2q(U-@W-msyJ&I(GbqFHiqjI@TX~7p=Ce9U2#Fw)rj!>4k49c*DZH0 z6Y0t#c4azdaN?-qX-_SU{|%88{X}OXuhM$8wdi6Awz)a_1ANd!W@R+?3gmF0U=v!| zPqIpl6%?J9CT61FUCvQ{SMg{D{ox%!G)b|mFRXYLdl9b;4bknx?0z(FQ-H*M99`s+i{MO+ zS$dRmX?~PobPMP^xF6#XpdiMmLjgRZ+&LBu@8@*b)<5jV;^6mebL)31pJ04`jIx&n z^JDw_w*S$~?9w-G0JQ{SPhl@W!5m05Xt5_PH3Uf{Su(69%9%Uqha4LrT~CUf-A#$0 zm+gLZDURjB5?#TG(%h#Jk^VaH)bH>x?Y>`l3LHlMPjk^0)o_1DTqUy~cfO8dnN=kE z2oE0}G0)o;_dgoNv#>&vxSh{ZZ)zj?BJ!UZkF4i~lm0u7>(QIWGl((LF!56N2cs{o zKB_aG9Og@`31&Dl0e#7NsgC*VWTH=HvS_4aOL!|&VPG#9m>R|NN@#;1IdrMQpR(W~ z0Th^$7?|lCl0;|`Gj{N}miS=leN9FV)R)3mke};u%p1cX;&6KytSev=HK@CP;m@ss zV{jmXjJs&Xd9>4J572lyQO?_a>)S^0XJ)X@Xvw0(a390@r5y8UTid@1ABc3_UkU7( zX*F-w{-*mY3D`n++;&!*UXgoX9oGLSpKd^e7MmFHvPfYe@8>-FPJe%_oN5Tk z8*zJ3QJAl|JvC$LBQCA38WYV}>4QQRisGH1SV-x@-r>XI86y1q$<`dN@w67^Ij*}u z22TTU;g2CQ0Hh*2Cni}vm57>5aJJmUL&+(1mX@OCFBGh}CM$Yta&>}!jIeA&PCI-* zDqs|>dH{8aALZx1k!Vh=F`-krIHM8rkY){BunT0hl)eto6_R>de<#Q)X+2%Qf40tv z&M&|N=);uI(L5R~M8s&mz8;QGDu{P9XO+}51q(rpEA#bazr;}9PGsMm(z~IT^bO_S z^E?LI^cW{&X*c@PCWBCc$Ay$5zjhW|0(cxX?z^URHFfUpn@G$AsHmJEtX;pEtMtAb zASyuBa zL9Jj8T#BlDyfR9P)GSf0>FomV)A53%K%g(T68IESKNWn3U}Fzjg6h~!=T zr0J@4OGVX5&6a;i1rbgks72@D<)3PV*FKe*oC#eRX`jodw%@7ywSf?nNgg^UJK#i$ z?CPduh>TL$dFrS&=yvl98*nKNoLReQsoEBB>CE1vK`%01ZYGwiqC(d-D+p$XuA*)g zE^1*L^fpCL+^x7U#`j*9I#oX+ijAESGh=QFU+W%)fP$w$xoK{4oW#v z01Tj{H6Ndr&4Rxqh1#B+!n))NCWEa$6)?a+!UUz`NR^!;Eh+dAK|t4VDap**@P(kN ztRM&lQO)3O1Flc!O70U#p)8#s3muyd4+M1idAc}0c0{5pXVGvFM&Qx*W!_*Dc<~Um zzAK%}iU%gYllaqmMj~b@*kXJd(6Ev?aQqM@S{5Klaf_)fqdAX+HlI$*wSR;*&qGy=^;h-fH*HD%|S!%f5e5zos3)pLR-OrABoAi+y}6b#*C;FDVsqH?kR8ML0Vd9WpwbK}uY)gU3QgQcW!Ub2kwV}D z)yO*}fOyKQ#x*7&tXwUttYoqIs0Ucm1{H?CZex}y;7DToVik3OxnI?wBNXEwuelrl zrE2a##Fd#B2h#Bb2|tw22Q`xBk)ROwThuLh@Wsc3%S9kUZ7-CMDRU4fVni#C1e=^s z0@&7wrJ(YZw%I+$_s1UWwFVkwry&;?$CMl{8@!*g&8~P}=a2vwXkjP9+@s7|RO1PA zt+MeI6=}rAC6kD$-PtVR6x>=rQ_H@7-JkMpj_x%T_XLxiyqsmu2j95mRGbniNo;s+ z5qU6YaW+6Tw(+S>-454m6aoAY{w|VXR+j>FvV^`;Mgp_0To9jM^&q2YF{yf1hBqB^*{RKu zf7j#~7Y^BtzDxF#@r5$v&0}~4-*Wps;*{)|bW`WdQ>mQo;2$&Drc$1R`wBtwDW1?w zR-4|Za#k~im{Hu-3T0xWosVVmJW1Bea^AejGR2u@Z>kizlE(^VzLb9<{H^k3q6@DS zgkMY6A>7#ZCU2n~!zjNFU~{m$cJ;5p_na=na1Au@XeRdRcKvB6D|>Z^!3?aGt-90D zf3~hO5vuUl|A`?HHB7k}Vt*@*55@IxE~b2o`!ZpWt>#o^O$WM+-cxc}a zb;@DJj1!}k(b{NzwB822mG`?pRqA!TB~ylUfOdnvt;~)3F*!x=)Ae^l)lB&ncjt?? z!IApR%5X#WHkr?w+>EB!8-)iFZTb&PMMS4Ty&*! z-Zb<;ez8NO%y3!n1##t%PYqtlx@T$`oJQ_uJh?e}Lg@ujs_1$a;$Mx|7+!wN1*Sq1 z;VQmpbIgTX+QOQcS&btIdC``uSAdq$!YpVI^q|%Wbf=KQs*u5Jj?S!oKgPv5d?_me zzXy`I#T`em^-`Dis;UT^ck3ZD?4N=4`?SdR)$7O(nd@9$jyD6$W-)O+j8NW@mL!FB zrqmNpUQSGYMqk6P=C^kV{`#3%AA+?@;ECPX)W+8Jtp7AaD~B=pf8#NQCj-)%6;Drd2yJFkkWz1E6h&yYKxv$C!}E%59@CJSl6=T8UzjdU zmZ!?o6z-rD>TH0waNo7CMI>-jcaz_Y3Ejn&5YSg-$w`{RSWF6ZOm;Z_+VfIEE15*X zT$Z7ZLscH1Kte*-hJHEFg-udCk5qWH6_vWK8{h!*|b`@I#w4}_ep3!iDMkHz2w94!qDz$CA@D#GL>Do5B0so*EGx-2gF-=#z`SNtM>6G0Wv>T9nhG?9k))lv#Wc6l)lK#QeCq#55r83ymxkQ* zZ|xno)jyz zlD9}bO0|-UdC{6%Cv6}(q@GD&qowSm1ib@7%M(THe!~Zp3NB(9)jiS~OH_xFUV13i zXlG&v@Rlr!K}}f6rMmz{@@L!gLMGv!V`UmLL|Weyp1*0?%oAqnwI-V5*KUSQnW%Zy z_gcE4W0-pio6E+I5ib_NkjIeZp2!&i1@cv`6U;uV0BLVm8rqR8J*1Hd#UumnF!Q&iaUaWy4Oh z6t0)Iwi;_yx07to+PmZ3|qRYB=HdYD)MT(U!hcA`#IF2G1f|DL&U!f3>{}lEYXVK+)HwKhz%CEs>}+a){pptEFtJr5`(UC}=XX%> zkeh3%a^iL6N?^igvK<*QX`qjbFOhM@cchMfS_id69tcDZ`ou~s>4)QS$-0273N>Nx zUt)6+Vnv3~R0|;3 zd;*M~@E=|?Q$-fql#+&${L1C3`dlWftEG{}rdp_zc{;-pd!V4TzJQTh(tx_{6}WJ( z#AKsT#xiLEX9nGFe#HY+>j`4Xl`GJ(kW&p0o3XwRBx~b8XV4i~p?&pSGAkdZ-7ztT7L;xU8EV*GvGuX}fK+ zQ&mFN+`6ggWzphs@u{HpxykNHAg-iUX#jb)9Chw=K#CxeaONm~fqNrs_UzvR_5qOj zlfR~>$W_)4eUDVIZqwmf6#5C?4OsDNYD6e)w|b^Lv;<}o$OP&7tCJgj2K-s4K$t5cjH=d zQBU0y`#cxo^{m+>+^2<|WzdPy-+Y3}PR@hwc9ZMV1Nf}q`}@yt&BW_;=USi|o?`<( z*&!PZq)bFN{pkjya_@QJCu3*t>m# zPf;qlwB5!J!q>4Fq_70dv_p-!29swj_q*R<69TRwypd+YnmHF_x9f!o*3V(gSiXp$ zf-U%Q;yE2W$FkKu)WJn5Ic?r4ssM);7cmT5S>mcH#STw7IBT*D z?DZ2D)3Px6NBZ)iEKjWJ=X;eVPc7{mC0UO&{;20F{C1>MM1ogP4I zCK#ybKn)?`=}tl7_DK4Av5O907Q-!ZBe~!7pl3OvP;7uXyc*-AB|?kHH2}+kSS3(a z0cDC$Wp(9F)niAl1WvL`W3;TXSRNG$3k82Yy?+b&7~$lUwX&!WKBlpVtI*o*rtMT- zcZrN}5k)~DT+24KH&m0EEN7+hp$dkUDyu3uIv(oi52`>%6>q5vsnXEORuJ~j>?CW& zd3lPL+{!FS$Y#&ehm6pHg~S>3#ZhK8PgzkV7pzc*I`%a{x(hLpPC-J>GwfZU^adlf z1+CJxDA{G_@96w|y*xg<+NtYAB&&)8DW=B4$*4TDZ)E87u`PXmp~|^PX<4IA9fzc# z*MrT(@6ggonc6(|&<}88eyv+v1)qL0oq-IiNhWJ*K?ucOk^~J5SmJ|C0S5vXyQfS0 zn5G<(GOfyTl(la%K}6%I{ibfB<1`N_An3K!VGpF93P53Gft!Eih5c%CSqjB9e4)bu zZeZtY=$1L9LqAaxDHSmh+a6)H%r9eQA~GUFbM+j;)F6DSscTFy!n{u6dGUq|i}j42UM>HuiNEM_Tm ztC2*&n|c zW8|%nXrZPHmJMOv|?j05YN+Hrdl_w2B>uo(GSU4pwP=Gq4SmmLk@PeMH~f}f8g+LrQz*;*|(sDx(Vvs zKsefy7m0F`unNJuOsoJCj)+98YYGs=!mkPC2Qv`fR3n-}MrX5t-X>?QhYJJ~nF z#@5!@X!|eLHk+HX(ee>5dwfl1#Egk8xiK?l+Qf!zGH?C=H#cVfjaU7jOKK-%3h+6Q zK*WO@#Df5ww0BZ3%Jf_;-Se_TS9E>!Y75ni@dmBuukAmkLoGB^X$1aRP1~?_ufc0S zC{b@_nTaN0cnrRH>jHu*ikQ-UnN3@Cu1ziq$VIcyp!+wPDw!Y3Q&SOY z8woRn`M23I;1 zpunXJ1S)YTNWJv^r%Y4-I^qhUAq(G%noOreQ2WbC&Nb zf$^sv;14}?arJU9gHZaAKiNNqGBcU!j4a01kN=>a@{x&+YMs+a0p-5A%buNnul!=J z8|wI%8>W+!Ng_Ad2@M0zuKf9JsCzjo)i_uy?}?yjZxggAU5%~mUH@Jbrid!65A zqBvmof6~=HudgRV;5R+3KLP1Ady{fsziCb6J_2FMecs%b!|mUpUc`_XbcDlGI2sgK!>NT7lxG^y18HV5=jCNchNpP&ds|Wm+7sWGKWs0!!&NZvuhGO;;ccSLwZE`{46|d*ECU;+g)V^%*@wi{ z5aV0{hac9&4TAZAo(+v+%>#VF*8cZkur25~0>Sr{Iy~$tJ3Oj19+*Td z+A^dKXJ5F>C_ZFp*p%S#89Kfl8<9-!3Kuo_#%axbXg)FW^cHWS7>N`+q3l}ClZl6qMZoDDb^}-D zk9B+!UxvEVecx!aeS0-WiEWS}29-`ciAWeVV%=t1Pdnl@vFJ4$=pnDPqF3;^-CP~L9KEFHqN{JBHB5HH zfG%MdXn7xcf~;Qm{0EAr;ryYXD*o?MH6Fd=j5=gv3zzE49R4M9%2=dvFy19t`M}Fh zrVxceB@hSCwMUK(^{fyv#EYSjvw`on2T}+>CIL`-xdDD5_W6j}1kN2i9%{SyWOJw1 zW^+M%xUI3dU08I-gb3)pnxrGg1toQFnvVfRBC`yrVGg*sE7n)Bb(6fPT|Gq$DyMhaUua4A*EXFINBC{fMF%VTD}T1xy@z$ptvclQ+5DM zZ1)+Etbyyaj^nb>Cn-!5^MiUgCx5&xoXw*whsJMcT9VvsdBZyylOTb&%^2fECqmbh zZ30oYcDeyvy!uaSXnZ%-)z33uetg{eyQ4YGGKmRsS*>q1%T%>;T74_sR+Q?()z=@x zy`E1W&;B}@^|>$X?rl_JxzhF*QWN7L1AfAU5xM|`D_-BJNj_3=XqR%m$XjrG|NF!7 zjI6?FlSqkS}MMv!C_-m7QO_S-=`wwZGvJ{+N3VqL54?v zCzL!K6&N@6e-oLOW;*tufL|iRrxMBRD?gYFi!EE>xyivN}dP6XsM@4W;e3vHcR6The$2EykLOYJ`zn(z#@4%6Zk{vHu}5 z^e+F0$c)`9{gFf=jC*9?2gnZe`&5u7DHy8^7%xmr0v!Y)xMZZTP9ZCK!U}D(5Q?P< zF)OkwqQSuNEs-e+PihZ<^9@-F%@(nY8tDr+QfvtHRk_LdFO#{VJU9Wn z4M@2R5Bu9N9Jvu@g6;?;fGJKG^MwL70u0%oNHbOQL-Z-P!O0lOy{a^k;0i{ba3=jO ztFP}Jn4}U=3FHZ>_-0#ihta^WWol7s^i>6lUTTVU&2G0Mq40lcj2g@B@(2ybs~Bt) z)P@z46NW3D_m6CerP4t6qkX0tH>}37VGhxE$!V~iY^;!FohmnNE>FTDjP~;?h!S= zw6Qyh&8{P}t3lj0!4&y0yuOwc^d1?vEs+T~^VT;NDn9{I5~5&j&@7 z#ie3De3>mP$>SBtCL37X_NXGZnjOUE;ON$Et?>=y5>3f5nb?@UYeiYE zSnX-94aR2I=o4-8kK0CXYscf@rir5QB#L$!jjZW^${N#f8fBYIqiGba^0t-X|2-5e zvi^V0Tm;Z4e+0(oI>R)x4lyvh=1NB!nxSc-57uZ2*C*6!NbM$VEww(&L07SBJ5k3C zLND3;T}4$u08u#^uwRK;-rT4ecSvG{{b?noxOPrxd5Wf0_O0NMHWH>8nR5(->QBq4 zKwO+hw@$*LJXdgesAO|2OI$o}#=mGfOJRi+5Ge<_Tg@tfie~hDUR5%KEB({2;H6gW zCi?~#7d-07!x0BQdOwEu-?GPn_c+|&g$ij~>qunwC^9hU@;EdceBTjNBD($xE@($V zq4K8m9X&iw4Xks`j(9zu`?4;f30=AhOPYOXGw)lmpPB{#+@R7EPL2aaSTKmCd< ze4V*vLfZeb)Wo6e&xwLB>=AYcv%efp$RqsbNzlD<^#asaY;WFnIzruXyz*M6w{UTQ zFP1#O2{vd}Gm0CpqZ6v=6e(%jdv_yyPZRP@GAaR}-J)T}#kHb8BjVt94_E;0#PlDj zD0!{u+nv=b{#DLlzRZSo|MUU+V;{}er^J&}?D1BDLP+fPIiG@aqm`Jw9W|5uRN5qH zM99n2X@R^qBf-9h1v&WX;i4pYFxskYTV6boI4S$94p%9q{u{xUxSP^O?#87IT-McQ zul+tFaosKGP6G_~`rvXOu|x@f;K2K!GPLk|P4kHoCcu^ogPr(7yu$(WM3b3Q#OZv3fSAgBziB`7 z6fKT`Hr?wEZfdnGir+$MvUp|HlF|z6Ba9rkgPgXu>w9;$@Rt093e+l~{sI0_bTdxJ6UPSdWEEE)iSpEn``pFPi%i3U|C@{SW0;<9fUa(Y@?RN!st~gVIgUtP>&g*t1+{zNK~ZZ1 z2qdpEj#_gdg~Hqj{;ve2b@LwyNLJV<^FI=hjPQ@)F&wqKM#ta;?(=`)iQ)~5P5Ec> zUB|tTqT-7|OqM3r^neD-rQwd?&9A4kF4S^4-GB~9P8KRw3MuyLTbw-C5CG4Ge^hK! z*wTDj45JROMImmz28b0(cvKRL;By8)Zuwo5`K))}GYVkBLkYe0Af6a~DCtW2CrISQ z8~#32)PkL=GF`gqrWNvTWJ&`h;{isZvh?dx>ALTDK$D6Sp|XVMeiA`60&ppU&?+*g z@-NH}<`?su`CUEVf6y%O&t%ui4Z)99fmCF+-@&xd<3ra-aW)htsHPy~8V%+TW)myhpO%{3=PYT!SmBtanmoAW-h-#S53Q^p6 zPW$uH+MiPvYkK>S)(A51Cq+mTxLn8LNBMS_O`y8*spU-ID>Rt_ivsW}S(c|e47iCT zQp`pIW4IiBV;GD?X-_JJ5S}SrCb7Tig_tES8{sxeOVnofWn7RffI~u35>7=@ue^Tl zGyFPF(!=`t=1G-OA9B3Fj`r~yn>@bqDf+TVNhPt)k-Je$e&EvjdMe4a_UW2(!B7=} zuSfA>OT%gHb)tHv(!BJqO~b!Q)^O&bdL@g%LEuKQPH{p6E?}~WX;p84YJ>T zA49cE0vEa(VLBhCu^x9 zJ|D=qmX&}6zU0Ev0*YyDPhZ%nxi@!aFK>gF+{_3r-%xa7KVi+0$J|(1bX)4@5^n*( z^*rXI*g6jbc?Q3wQ;_lQvCF~#K#%k z(*)y2z^LVZkbAjeK(~Q?SFt*j{WNKVAL@*B#5ga9JJKC)d2Vw>VXx}#>B6Kp1FY3D zhkO^&;Z=cwx<4;N8{0BLgsOZA$`i?NQL9uB=+FU#xpGDi8nW>+Tx}yQ3M+e1k95Yk zVqP+>nAS{cq`P)L8tdQ+`2r5tbxI8S-8lRatS|NMKx%(7I@j7$dXEW*2Z7f<@zdYdZx08TZEjI2rXO6Ze6eL?}cQ zVW7AYtYsWTEh^yRbwes(YDE(&AYfa829Sq?QX>H52}Qb!Y~`G$m?^l`ZO#Uo4yVv! z*K`z>hE_AfBid@Bo98~XWu$075rnYuX-i{o7xtiK(3*HKeuL9bko2pM)Ty57ose5m zU|cQ_C{2sI*>^Y+p+>WQ>Rm8zFN|1%10=M#W?gcQ!X56((yWlThNgeG?{zaike7ND zEYh==%G<~d&qftS(3R^(J*X7~X|^JQniV1|&Jy+{hwW~#tVGz>R$1)N(|GG74Y9gZ ztfFm;s;O#o*aZsn;vM~Sz!P2y^(Z!BVI)!;e$bD`PFHCsD#>{#~8rJJyj` zco(r})=wyY+3e|TA#4oo$@JCv?q+8Adx~6C#xf}J1CiMMeJ$F zn2#Hm12(ys<_T8q^Q1LSaL#hNp-EEZ?q~duMUCy(q88;$g)jIUx`(?vzCY=bwPa97*n(J^UFFr4}U{utgVV%@r1l3ZJ925%`FHj{ywlH*`@MD<BbZsVg%CFbkWTwGj^t<&m8EDfigMgn*uc!S>UNEc z1}TB*|2nu@rV%i_)z~U9O;Lqyv}okSv~1=LlH|-AtH31AuB;wF`*$}1YHj+A0-Xz$ z7ZGH`32pwG;}@&2WQAPlFwh)G#=?hj#+jcCF7i^SSekobtn~-s()@RLpt&+|w17k7 zK9`wy`hDAiq(q$$jBt-KUakbAqCUqV(Up5}18t`SqR`E13(M2(tg)!4s_Duo_ypo4 z>b@#fcQif6hYkv(!L8m7b@PNDKM>UgPLLMyQ}Z@YG7=k!4aGz(ha)l)AM}V0sk+Bf z2E~q=xx;c(>HS%BWK2^4R3R_C7!{jm_U5@Q>%L2AP2|@?m;CvVgqz2{gVU@=9$lfo z*3~VzYM38349-PZgEW-=6eBLvYBs)Fan^sC*baAHD2UZ3oAZiVq&uvk)jGd?UNQ|C zf`~*!(mq&|bw1r@(e|Of=1T%imv{->Du6Emg`pd6n8ZuA!8iM4*bHw5Z-a04&A1-K zrN`8-TQvFHKJ?xbvh1qq{&nV5FjE*~9^mR5(ea00x^+Z#O|8QxJGKpSWIML$DaJHo zn%85R-|nlPre<8Z=<5u^vg2;e6_k`*+hH5K-2V`8Hr-MbPcwODxL+*kQ`-Mk7au-e z2McGD1$L6UN5X-UN1;|6c9M@phcV1=4>b*BXbf+H0ul(p>cK{5l9!nk^(>yoa9!f- zy}*j0$UN1{1|w>9$*iY8xQu@LAnNTsYpA355?AM(bqqx$qv2wrnI1KW%hJSkCAg^I zv@l#>#gshjMmbIqAv1rFKgZpT6Tw$YY>bLgHK`#oM%7$wuphjZXkWdFYqF_}cx+j= zpXNNN@{`#+o0hx1&D=X^?)_?O z=-TCbYPn|w$^LX^swp{1U>qO!T8FX1z_W%;SBAf4H)O7c?Nh;xQL!;od&17LOx7R2 z#AD=LGSbNYe1LJzs8lmKZ}oT;mY^r;nVFlAd%KZzwUGEVgUE;3W%?(0uKVs@qfN3& zHpw>0CfOwWC~l3!edT9uUkR~t(_#S=4Tk6uH?x&1TRgA5UMGl}baQ(06MB3{)`%TC zcZLu;7n_&63uIJ;I$I-6o2XRDe_c1BkW<(>?Brr_E~oIlP{>(3B?_+X8!U$o+Cu2^ zTF|bh4|k5nK%E7&pFn2NJCV@r^w&+W+|EH96;qYu0r^5+A3f2Z%7?K%w@%I3MyKkQMHWTr^$> z_LaH&>cKHUk*@8Ubnb04|0Nfh;RQVe%2!81K102(&A+^h+(LYndN8T43}?a)kunXO#3aN+}@%iq6oK1<#rrea7G@W8owk69SiyxJO@@9$Z12<*92gVYQTOIza|=X<;G*>*%Y8BW&Q#ENyIc} zo-j+G?~8H7JjQR4KyPoo$(HjkOKUmc;nOap~J-!_d-<$R$zcF-p{O|?u5SWG5h=rWnoiJo@ zU~o0<01W$;^LMASyE=*j3)N=AR$1Bu(XicmyVE6m~(NaW?GUPI(^ zF+&Lg)An#ru2iK^@q%$8D+F4xY5V^fSJr4T6A} zo-X(06l?-XQlKyr#B`I=4+4ufYE%mW5`=~^GfRbcp?Q}B2*=9&{zEsR4u3b58-+tr#?Z#23Z(MS+axWO2<95akhZ4d`xY6Y{6ejXEg79 zDW{`uG&Aj=FkkW6Zs-#SnfCbeyz2!24U@X6d6|*SO5`Q-5PLow{vy9hiQbmgYvzLb z5v6pk4h=ZLUT3vUmXd7Y1zoIhzlIRWQSWqVy1NS%Tx_^^ncvhdGYIESeN*MLcKoDktd6No(S)- zje1{yH-dt)n`e?ZrB86UyS%TiN~=ImBFbu4t`>qUs~@b4EiYd+rQ#BLA|cjM9~*># zq!m#d6>L`68+#+4Wozt>e337+*^agUq4|<*4?fhQd*-kI@%!t0>C6t{O*0l`M5zyb zoIs4^%`x`o+~mTrRD4Ue@)q;rfX{i%YGH8^Ow!BRRE$UBuUEC`s7GVX3^z1OkpCd+ z3kg%Uu_wJJJHw$tDD6Pg-v}~_q{BAcMbv+eA6q-I6+2PS|J;iwe`qY3IvQ0G7pU$# zL(!(ERNQI_p|52g7g1NYWzOo-v3|JrzSDW2yn1}EU#K4hqo~#haZ0ea6jYUNbzTR0 zX{ivlf#zYywj?kwc?K|P(|2OlYxm~av09h>?N*y!ciV6^FE*^Y;hXh1l{Qc576$2v z4$&ByTQ{O_@wl{p6xf7=gzFgy9T6AVf}F^~}T%WKw!~(c>1<_;dQYjhGh7{0BT< z^Em3uLuR|C^QLztINaAsqj(Zacjatiwu+^bUbDCh6>A%KKBn$=Au|dFe!vT9#){6) z@qk|Mx{GW58>kFm^{ZUZ6~{Z@S_l2el#;d%TC;}L=5BN#6pNwB1r)4PEtx@7c!hQe zE6wUJlrWsIb8JSLvTxIzQK(iC7kq;O224O~@2jYZI-e z;>HWB6z|8Q_jiBYJ0t|n3qaBHM9G-_3=wE+hW zU+~Iss5u8{k$)Qt_5_A4t?#sAu9?Wxb)nyjxRGlA(ov(?{RSxEeBndYa*Nwlnm{87fh+{ahS<;a&2#*XVX9^x~(6bGU9gBA*SBu3xCOMwBlUR484{mSyy`` zGJn&UPoDy7Sw54ls&J&|4DO>+&D1I3=iXG;*~6gid-v?^fQGJ6x6>2E!@}BN>HK_Z z(rUP`uTAAC8GZ75H^-?yJ#?4r&GCdrEx0B5-pEg}&Aaix`Q^8GwKhcKjFU&wW$BJ+ z^2!-wh0*R`lccNl9Z_n^#(o07cUqG<<$s3CN|+-JK<_KfiAJEd4PrObMxd-DZ5K3~)P_!M949X#lvo@uTl+u|=>$~1xn4N^dFV3&CUe|-_qPqt3*1EZGY9(I?^eO6~6 zfRwAT`EgWhCz7T~cAgM^+RaUAD|<9`wy)Y(^Xp1e4P13RQ2T72 z_H&n}I5DiZOJi-gEw9a`W>0PTtwWyx+gn4wIW`O*?LPda=;8B-;L_mKJwiGb{5%;U z9XXv588D6h+g9*f#QK>-&X8_w@*0upIXt+`(VRApm$aG>K;a(_1ESw~K;%@bG%C~T zj#XU`I3O}}WDqd9)1C-ij)l^p6EHa&#gu_$l!yx#Qsj}36)_q;KpLj7t`dG!EYHY2 z%259m7lY=%8Lu#lZPodtYE-3T{q;mcczK2c68gg$BTLc;M^QGzX2`DX5M3c5n;JjY zhf$^*L++cV>vmn*VkNJPL86a;|4*YMlsq*}sd@MzGg1Hmr6@pv-vVIxyQ#>O-q4cX z!O7mr)Yygo|7&hUumArf)HoluC+?P8{QyfTS0?^3@iM1R?`oIo;K<9=-Mxt^|7}{C zR7n|$Mws0w!sN47Jx%)eyAvA#GN?dg`~mxe!8pl-r4u{W571*cX_zMF!51wg)1U2d zkSEUl)URbNbd|^Z{XjJwsSDRn$?MwKDeUcfF4-#yKfFblMm*z!>ID+HF&VAr~3Sz zSU7(V_qW6O(OXkw&m6e5p;;%9A!@PjZ!B@1m@-lZ|KL+%kF-6HVvhYFjZ7*h3~|K# zx$47<;{0`fpL&SKl40OJb2}EZUh9^_=|F_$DeU`-40T!5J^@8Mxr&u@BET9|hkfVb z-nU&QuAv{u{1Tp7zDJrs_STWJt`CJaE+8l;V-s-6iiw{1#g2UFC{_Z=FCV9QkR#%d|H+XbzMOk`&?!3H9BMq!zHO~UETkpyNDzVUA@B!?)O&wggBuy6H*)!JNQZLt zJ4ut269p< z-hVblSlx zljz0yfwcuVOTlQvn?G=FK}Fys7YgG9w>hW$^Ibm{DDTdESc)C#^kmHZlNeLp2+8vy z>dkiee-9*p_)Lil3^U@zzGG&~2y6njD7%3Wp%6Q{rnLGQ zIcrF*{kEF_Mi7w!j>N@@5r|;+OdoKx!G0Fxo&g zWyWFp5Y1rh3|FnSM|rVlj}KyyC^lvYwvoUlQw)pTGG84f`DRZj@-;^-s6;ds<<$eq zKP8a&qm3;5l@2K%(*6dRW<{#CTWXoJ5~<4z!FF#@Cc*XW?VOkQsF?Pq2){Dfvd69J z7)vFL&F!rk2vfc+(W=F&XdhPg)6k3LNq)=s?|u6;eOkkx^zRPue%$wZJ}MCB_s%GWnDJqcCCr7oy?D8I9$m~!%d-HvX@?Ol zc_{(*Cj$6zjDO7I>l$gl=wuwKo3tVDu*f-Z2xPeg<-pqbCO+mJ^FjHMXS{Eg<6P?! zHrh$eSi-A5xuH_8?M(h^k5@S>4QcxoeEOtSp^%nmL`2p{T2SG?ia5atCEG<fUY#_jJs*&%|w~zsowLH@{e?# z;FHO+4Dz|$pic~z88>RKlV|mWsW6t6w5)I*FG}nJNKG-2kzmszCA(R0Hf0ia(%gB% zAEC)u)KM_Z{IVH|BL-||2IJmeQ1w(7Y7*-WF!KMu?TO~Vf zEG_u~PheabfzM99CiN?2jt&#%J!ONhTlfqZokpjs=bev^*`!Q-M}*B%o$E%H-mtbx zm|?RgF;xc4Jt<=Qx`DkuhDTn!YcvdfFq`W@F^Xf~HuAkq>5i-Y)cihm4Pcfm^=>Bz z79m^sr>|tfQ`Md?x&(9e1oQNQHTnMiFqFhCHk<62ABWp6&yw6fY^+ zj9X79$+mspIj}b=M1yq7YLkIIv=E`ifeOgb>qvlT)P}+**X~9#`>m?b;st>kOP%lI zab50DUE7i}BO2P0z)IX(>_~0dP>=lF;d_|3D_$OpEJo772)MDmrcx!=YdWXC^j%G! zXOuMsFU_mOG?N2Cx*nMWweQAhfEMV*83aCf6iLRt8&Ap zT1OodpjRKW5%fYmni#{{FkoB(4YDwW1K}x{U}t%)J%Ien9RGlw$zHp7PN*eyHEm{(!L-#j!V(Bsn9I$Cl(GA=xx5OEr?9~QZRBK zk@e3YY3peXs1_E|;n-5xZ)t2ewW*X;=|31#)9-6Y`ptF6+uWLlf8DI*_K;D7Q<+Lt zuG~7$uu5p$SOwPqCBgwKgZyi@#I!13LEjAMT|tLNsbLE(uA_xl$YfwWGX*<40W;~4 zYc8ftrb{;{0Dp(j&4h$PP0+25iysP7Yc+!F2locj?$Y&cjS+^DCdqSCC6*GhE0OnE z#_m4#C{>upmhN<=y$x<;rv~B!vKluiZdypwQs{&vcf)dmLN10^tcb&;k!pAg#kuZ+ zi4}|d4uv&a>{~03O?Z(61%4~q#}3}binV?eW;xL<1Y559%JB8}OS+>tt0%m#`Av6# zb6L&qIB(qTgjTZs^HIF$U&c&&>hwlYjt(IXgEhcmu5`He z>5V4Nn;oF6Bk!>6naVTLcg`36##+2%+awXNVAZ6OVD+0qeZVCL41B{csQ3bjecb1K zaaf077Jd-<8)rHpG=|sm3imnBY`G()55@@Y#g+ATH`PdCsXAIJ`-Q+Haj}rU#&^;z zbVy(v0&05W#zLx8O;CjPhuopFF?GME7Vq!;4;et{uwM4Du19?p0gZYq$3EV8y%lI3 z6lnL-i(1;ShmICRWJ8k!99pGb6i8wgX!#u?2DrQEz-m41vba>_(&l{jTTSmK7JxLI zInSI@H81GG(aKGd;zFSg6{i79>GhaaY~EV&1?_hGRx=Ca<0Smo*6PN<_PLQf^}&i# zIhj6K*5D7Bkr*WOxG%?f+zyp}@0e|PYvq_04*Bv_-P$W;1QF<;4A}^j2Mmc8l?t1e zIF{yD^GC``KP%*ilmm+6=-8N^-!S9bbs&{#&uigKa`hm^hheO_rLLx6V$%qP z&Sf=sAt1j#Jc-SccgqgFTGqb#so?@qaG(C6d*Tp$tdKr9yP5Itp(Is z6BOtvRs68#9MAnBoxOehqRMY>DUSTPIx(ZQuJr(>jd?Q(#~x7tEp2R)E;@9ilc!{D zR7Gc#efkLBm_!jt4At^Ufr7h-@2sbYpJ_x?yPj9!cR0MAAWmS#-A7m2w|`sjb;At` zroW{F%i711f#5>}*pw}Z@-FEh0%tURwk__tYjYJ=@<))3kV8lW4yFU&n|N|q7%QI} zLCU$PECQRE7->T?{JDbZi1C5{MdTsbmbh5j!ctVD?!`on$DnI!BCY@CoCKi5@--#| z3{5jI5)#)yPL{>sB-4w2j6&kIc+Pw^JA`G5IM2PhR{A3W|LpWJT@CQ`@{3(JP&J^6F3@1A^ScUjX8SkbDVDaMuCL@S<%F(YG ze+&7?_Q3K4Pe~ghNu{S|5keW&GS1=%oGT6J8L}pHUMLL`gS#Ne&%&T$VX_wiH;2e2 zSzl(tqM8eT*ZQh@`k5AVxmU{Qpb`Lh{_yu$sux!bwhvaTfl{uNOg-v{sK4X!#Qj&~ zAP>uYGo(@vio`dZ>YsJ?cj|Y1Fx1e@5n&=IvSg66Y+-E7!3Qb)ZCacM7ksCH@D6hn zZ=uB!WY#@9Bm`XyO%m>LCEhz0@QA*~+h5`O)U|ss(!Z2{#KB(}iWxt{r~)cOUz(|P7mijeXTn4o zTxoAnXiUXYrgYeuSfI`JhPg5Zvq){EgF|kBaW5&TJAL5nF@h)`Eg{g=+}jgjtYMWJ z0OR};(JY?BdvJwl9?#)@Qmu!I-GxDBF|jz!KEjINz9B?Cn&3r31oGe|c6FyC-rh1#iEN@&7|?FN-t&7wqO zqaT%m4}0y|O1EWGOJ`$c6?Wt!+?enz6{-BJ4A%+P;+7VpfEog)M=b>X#b-@(%u<9e zC(q9q7w^@@iU`(>U8v%$jaOO67*7$5R?l%;8b1vFa1oYE%H0cP5c?CSzKGCpqrg&N zY+u2z;a*WY-@wYvoKxjlCKg2<4%j0Bu6i6+CDxOWk$x;LkBmMYwCuBFWzhln0kpx_ z?$t$77XDP9h%0ZopH|~3TLahnH&&^059b0N7#b+-ss31+^}z6Zo<=(|uJGoQQ5%Gi zvBV#ojCskVf6jwVsydQi#UEoAb=IO@`bBZ`59#|@5fN&k>baFN`Vt@au;IytQRYW^ z?XYSQ=fz->ch*gu>Wk3ewBoxPpX-TJYk`^oR4qzX$7Ob%_f2N^-4DN$Fm^2dv zbBE7XRi#dwmpdLNw7GSfTJG@mNJG9UA>Cj{>DESDJPS~pC4zd@qQ#<@bDk+f{l>J_ zz#_O})pS*Fq@o}7%l+0rPu-!5EOYvg$QX<*SVk&Lu59hTw`tc*4Q ze{>JlH<+zakQIV+;)oSg)P7^8_%K8&m z4n#ySj#2xckz5%vgy!oy7a$&><55fR8(G$vxoM~Mjg3;2=$t=+QXhX^#dcQQ0zSu{ z=J+l-@wI24G~`ow3uNH0-^)1hrI~rHzIkeM;G>zMn9=pZAC2IKGV%e_hg(qbpeR)q zhExN+j_7hOz#_>U6U|EhF{_f{$X!NB`&s~!0O!lyx4<#_LwvVd&T0cDW?NV|^Wwc^ zHgXb>$vBilcL+Y+#83P^pHsmzv3@mDp#TpCA^8C!r2@afjUSY#y7J+9Idf3@-i9bE z!k=ln*Qhi0XwqPbWnZSxGJz>(^U{`qm{x2D{8Unn@|E&LX9x!cAwgxW~YQLfO$Ygw@rF5J>Dy6G=J| zW<$|kd)ks&_PDKvjc1*v0;;~}TrSpU+lLL?r>0E3-eM47ODHppd{1PiMusT0$fGof zqK1{LMUg@ri#Nt~^cbTPXHY!J_${V;lh!et_K1+r<#oGR-r46!rHX%U~O&70uENRxI=N5V8z|tf?JW|1b5d`N(&Ts zDK5o=yA~<#E=39yD^QBVOYeK`_9gnm3;Z~{h2j0nYGvKz1H*+e8P(53y*>B z_~+j4uL#C9wF(ZpvEd`Lk$#JFVR&$H#k0;OS)c2o)lO_?>x0>{3cX@STgfr+Jt`cIcNI%8 zWx!nt%9S(o0~7EQpFJ44G1S&lwzJvbmS^~ZGjeHbZkOTLp#|WZdXZe`{t@r#vK2f| zuy;o*LV*h!>oE)W5-;KghQRi{pQcPv_{L;&eMotBi#-|c*IIiDnv8U&o2rw-0&U3& z68*JB3fnI_l0z-{%L?vh#dr3MO{<^fh^HbS$6eNd<9dx<^?CBu34Luloc3G6$RJ2R zZGwQIh97Ph2;U6s8U4IanxK*!bXqK6{LbnbJ69qOT(Tpk=VWYAeIQCaV7kT&I5dc7 z7_+D*{vzC6#p@Mp1|d$$HA%Qg@}ZHdx*|cHpN#qtxX+tPwnB(B5gWjJy zRJw+nw$&UW=+5*odk=F3EAZqtFB-kSACRt(H{`CQPKZw)X$Z$wWLvCa&6(#;nJ1Gw zAeL&?131^Le~QzPcJu=6UW>Pn!1<*kTr?wmKRW8wxNS2dH(PgiAxj?Jh}(amR-%BK z49~O(dO$EeFSv*aArR_pG$f?#9)sCJBcG|Op$?>4{vtDuww);pDKbtLv*fEx)Af?D zV+}7Fp=NpMh}q6w{1_+jljci5K5#dEVF2Dt?*>GPVhBxP>{i~H2g6mz#p@|N@iOO+V>!-X&T^TYK6 zPS`;YXZ~!b>SjQYrI6NL7&tF?rNqQ;7fr!94IWgCUBsEZrHy#1pH>>}>mVK!t$t{2 z>C7TPu7z}<6R3Y(4evKoNpvY(PA+z646Q_HXTl)aP=kr_{g9hbvxu-%CYQ0~K1Bb9 zBt!E$Vv!?Pp%$RrSjYZE$SvRQ$=i1@T5WUJDd?}C7I1AUUQx+vD~~=IdbNOijOn;^ zQHc6sqdgk0!j54G)`Ju5xb!*#mGau*#TvPiZr9V4l0Iq>$Y0A$<}yAlX{_)0JD&h= z-`kUwxf9*g)1%&v!)IU4ww|t!SZbZ`MnCoNrUAxm;h)J};*Cb5DikTQ%286Rno`EP zSZz)@@KUU}o%@tF(Z<+!x!jx-usHE^0O>99)`9eW+r5n$gvmIYE@p-*Z-!n?Shftk za^~kyWuou1fF^vD2ph;B^geeGim)bheTy8_X{Jarwdo~G9Mo0IZ$`GBAl0Sc?g}#F zr`{vuAt0Tn+42yim+-tWtbYQyt_^WeJ39Pvj|0;VwM}T z*pLoQCv&7`)ufB4xll-{y+)nz^0ebO9!$Z$?MNZW0V(nIsd3GWf6N zLjqb_8Vyto@%x3%ZFxn~Lvr4VJZBd@5kt({o|Gt4(WS76)ugmmD=o$%yu?Os`X;C& zT=ID^tmA7XA7i?CCtP+bkIH+max;(5!Przjg$pk#S#<;b6|sb+3udp0i43}f$LtKQ zHrvxb%V@OvfR#-q=>5;XlW+~@2+`%m7E_K|O^oc+@n)>akFUvR`Nj!xuNe-?4)xrg zL(1~J<}dpm_2%LC$!n)br?~#j}I_TCXA+ z7PANL({noKsXZ!*YDJBd7A!fMm4|z|nojj62B31&au~{s^iP*vpKW6bSJpQJ(uWlq zoHmW!xf^ zPhvP`HJodDShBE#{^cyy24+{ZWQ;(aY*YqjxZ)nNLM|OLmS@Aa>CdrX2P3jVS3*SH zj~s&@y((GPe1F1K_tKW1M;;cJTcAp?7fXS|9+O(RFE_#wn;Eodh!8uFQk>P0#;MNj zi>Sh#DNv|(Zz;yGYK1h!Se_>zOUE&+=FiqbMVNF=(;kS&ePUjdL`|yGJW;P4V38Ps z#o8bvl}Z;Z!|ocwcaAHc)C$fp@r!iwTV=!;K4iVn(lCk zop5<8AyCqxXVtuN?uI?73D=~RKl}3hplEpN(-CdfJT2Hk05miMLtvCX1-da9*oK5d z_a4wEo+{@PZ`{NsQEN-eN_y{V=ViQ9Xnj8J4?zz?;|c&`SmXBdM#8O)uPsVTOSoui zz|<{scnB0WaVF`KOhLC|4Nlgs(vm^KlOWoashMB198o|CJl#_hcDBY)E@rI_WCp#m zmt{}wi3{5c zyuRD0{rGDrA4(0HygWq?M}c8G9l8|t&3j4=n~ggspX*o7e$yQ4=@nwMG;y4u$D;7} z`JyuXZEn@CxLi>Cz(Q*9@$Ush2t9eiyHj$ahu+!#1qYSuBmC@s#2eo<|om6E04N5GK!(1l0_9 zz0=WoyK42olK!Bx!WGdWWK_$KBE~0+XH9`USwpt4HHGhLsGyazKP?$>#Ou?u#;i6X zO8f+_%pjo55M~1B8IE`du}s;4!rw;C!Tj7eJ~rDoN%7yp{*Zm z+-}s0PnFrJd>Z1D)bbf2Yo_}G5?lMjyL~zoU%@Fy@e)sm_lV~4Ymp>F$eFU#ZVsP) z_M7|5;|H>u;=M>%}xqt&Hl^UbR@!hMO}r^4KMug4}+A|5Ep&Zq;vMdcrpy|Fw)wHHs};y={&4;cD

U} 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 Mn9s-n9T)-s10D8gdH?_b literal 0 HcmV?d00001 From cf2e338aac46e5956dbef79120c269d459cfc7ec Mon Sep 17 00:00:00 2001 From: e-straight Date: Fri, 1 Nov 2024 13:50:10 -0400 Subject: [PATCH 022/180] updated python sample --- quickstart.md | 113 +++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 43 deletions(-) diff --git a/quickstart.md b/quickstart.md index 8c4fb2eb..6257b8af 100644 --- a/quickstart.md +++ b/quickstart.md @@ -168,75 +168,102 @@ python -m pip install azure-ai-projects azure-identity Use the following code to create and run an agent. ```python +#First install the azure-ai-project sdk using the whl file provided in the repo +# %pip install --force-reinstall azure_ai_project-1.0.0b1-py3-none-any.whl + +#Install the azure-identity SDK +# %pip install azure-identity import os -from azure.ai.projects import AIProjectClient -from azure.ai.projects.models import CodeInterpreterTool -from azure.ai.projects.models import FilePurpose +from azure.ai.project import * +from azure.ai.project.models import * from azure.identity import DefaultAzureCredential -from pathlib import Path +from typing import Any # Create an Azure AI Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" # Customer needs to login to Azure subscription via Azure CLI and set the environment variables +os.environ['PROJECT_CONNECTION_STRING'] = "eastus2euap.api.azureml.ms;47f1c914-e299-4953-a99d-3e34644cfe1c;rg-agent-test-westus2;proj-eastus2euap-brefmanyqpzrq" project_client = AIProjectClient.from_connection_string( credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] ) with project_client: + #Set up the Event Handler Class. This class handles all of the various action for the Agent. + class MyEventHandler(AgentEventHandler): + def on_message_delta(self, delta: "MessageDeltaChunk") -> None: + for content_part in delta.delta.content: + if isinstance(content_part, MessageDeltaTextContent): + text_value = content_part.text.value if content_part.text else "No text" + print(f"Text delta received: {text_value}") + + def on_thread_message(self, message: "ThreadMessage") -> None: + print(f"ThreadMessage created. ID: {message.id}, Status: {message.status}") + + def on_thread_run(self, run: "ThreadRun") -> None: + print(f"ThreadRun status: {run.status}") + if run.status == "failed": + print(f"Run failed. Error: {run.last_error}") + + def on_run_step(self, step: "RunStep") -> None: + print(f"RunStep type: {step.type}, Status: {step.status}") + + def on_error(self, data: str) -> None: + print(f"An error occurred. Data: {data}") - code_interpreter = CodeInterpreterTool(file_ids=[file.id]) + def on_done(self) -> None: + print("Stream completed.") + + def on_unhandled_event(self, event_type: str, event_data: Any) -> None: + print(f"Unhandled Event Type: {event_type}, Data: {event_data}") + + #Upload the file to be used in the Agent scenario + file = project_client.agents.upload_file_and_poll( + file_path="nifty_500_quarterly_results.csv", purpose=FilePurpose.AGENTS + ) + print(f"Uploaded file, file ID: {file.id}") + + #Create the CodeInterpreterTool and add it to the toolset + code_interpreter = CodeInterpreterTool() + code_interpreter.file_ids = [file.id] + toolset = ToolSet() + toolset.add(code_interpreter) # notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", - name="my-agent", - instructions="You are a helpful agent", - tools=code_interpreter.definitions, - tool_resources=code_interpreter.resources, + model="gpt-4-1106-preview", + name="my-agent", + instructions="you are a helpful agent", + toolset=toolset ) - print(f"Created agent, agent ID: {agent.id}") + print(f"Created agent, ID: {agent.id}") - thread = project_client.agents.create_thread() - print(f"Created thread, thread ID: {thread.id}") + #Create an agentic thread + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID {thread.id}") - # create a message - message = project_client.agents.create_message( + #Send a message to the agent + message = project_client.agents.create_message( thread_id=thread.id, role="user", - content="Hi, Agent! Draw a graph for a line with a slope of 4 and y-intercept of 9.", - ) - print(f"Created message, message ID: {message.id}") + content="Write code to calculate compound interest.", + ) - run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Run finished with status: {run.status}") + print(f"Created message, message ID {message.id}") - if run.status == "failed": - # Check if you got "Rate limit is exceeded.", then you want to get more quota - print(f"Run failed: {run.last_error}") + #Create and run the agent stream + with project_client.agents.create_stream( + thread_id=thread.id, assistant_id=agent.id, event_handler=MyEventHandler() + ) as stream: + stream.until_done() - messages = project_client.agents.get_messages(thread_id=thread.id) + #Display the messages and output from the agent + messages = project_client.agents.list_messages(thread_id=thread.id) print(f"Messages: {messages}") + print(f"Content: {messages.data[0].content[0].text.value}") - last_msg = messages.get_last_text_message_by_sender("assistant") - if last_msg: - print(f"Last Message: {last_msg.text.value}") - - for image_content in messages.image_contents: - print(f"Image File ID: {image_content.image_file.file_id}") - file_name = f"{image_content.image_file.file_id}_image_file.png" - project_client.agents.save_file(file_id=image_content.image_file.file_id, file_name=file_name) - print(f"Saved image file to: {Path.cwd() / file_name}") - - for file_path_annotation in messages.file_path_annotations: - print(f"File Paths:") - print(f"Type: {file_path_annotation.type}") - print(f"Text: {file_path_annotation.text}") - print(f"File ID: {file_path_annotation.file_path.file_id}") - print(f"Start Index: {file_path_annotation.start_index}") - print(f"End Index: {file_path_annotation.end_index}") - - project_client.agents.delete_agent(agent.id) + #Delete the agent when finished + project_client.agents.delete_agent(agent.id) print("Deleted agent") ``` From be67e959c0d8469eb65a8fdafa538d849ed883b7 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 1 Nov 2024 10:56:24 -0700 Subject: [PATCH 023/180] data file --- data/nifty_500_quarterly_results.csv | 502 +++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 data/nifty_500_quarterly_results.csv diff --git a/data/nifty_500_quarterly_results.csv b/data/nifty_500_quarterly_results.csv new file mode 100644 index 00000000..e02068e0 --- /dev/null +++ b/data/nifty_500_quarterly_results.csv @@ -0,0 +1,502 @@ +name,NSE_code,BSE_code,sector,industry,revenue,operating_expenses,operating_profit,operating_profit_margin,depreciation,interest,profit_before_tax,tax,net_profit,EPS,profit_TTM,EPS_TTM +3M India Ltd.,3MINDIA,523395,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,"1,057",847.4,192.1,18.48%,12.9,0.7,195.9,49.8,146.1,129.7,535.9,475.7 +ACC Ltd.,ACC,500410,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"4,644.8","3,885.4",549.3,12.39%,212.8,28.9,517.7,131.5,387.9,20.7,"1,202.7",64 +AIA Engineering Ltd.,AIAENG,532683,GENERAL INDUSTRIALS,OTHER INDUSTRIAL GOODS,"1,357.1",912.7,382.1,29.51%,24.5,7.4,412.5,88.4,323.1,34.3,"1,216.1",128.9 +APL Apollo Tubes Ltd.,APLAPOLLO,533758,METALS & MINING,IRON & STEEL PRODUCTS,"4,65","4,305.4",325,7.02%,41.3,26.6,276.7,73.8,202.9,7.3,767.5,27.7 +Au Small Finance Bank Ltd.,AUBANK,540611,BANKING AND FINANCE,BANKS,"2,956.5","1,026.7",647.7,25.59%,0,"1,282.1",533.4,131.5,401.8,6,"1,606.2",24 +Adani Ports & Special Economic Zone Ltd.,ADANIPORTS,532921,TRANSPORTATION,MARINE PORT & SERVICES,"6,951.9","2,982.4","3,664",55.13%,974.5,520.1,"2,474.9",759,"1,747.8",8.1,"6,337",29.3 +Adani Energy Solutions Ltd.,ADANIENSOL,ASM,UTILITIES,ELECTRIC UTILITIES,"3,766.5","2,169.3","1,504.6",40.95%,432.1,640.8,369.9,84.9,275.9,2.5,"1,315.1",11.8 +Aditya Birla Fashion and Retail Ltd.,ABFRL,535755,RETAILING,DEPARTMENT STORES,"3,272.2","2,903.6",322.9,10.01%,388.8,208.4,-228.6,-28.2,-179.2,-1.9,-491.7,-5.2 +Aegis Logistics Ltd.,AEGISCHEM,500003,OIL & GAS,OIL MARKETING & DISTRIBUTION,"1,279.3","1,026.5",208.3,16.87%,34.1,26.6,192,42,127,3.6,509,14.5 +Ajanta Pharma Ltd.,AJANTPHARM,532331,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,049.8",737.8,290.7,28.26%,33.7,2.3,275.9,80.6,195.3,15.5,660.2,52.3 +Alembic Pharmaceuticals Ltd.,APLLTD,533573,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,605.1","1,386.7",208.2,13.06%,67.6,15.7,135.1,-1.9,136.6,7,531.7,27 +Alkem Laboratories Ltd.,ALKEM,539523,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"3,503.4","2,693.4",746.7,21.71%,73.9,30.3,648,33.1,620.5,51.9,"1,432.9",119.9 +Amara Raja Energy & Mobility Ltd.,ARE&M,500008,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"2,988.6","2,556.9",402.5,13.60%,115.7,6.2,309.8,83.5,226.3,13.2,779.8,45.7 +Ambuja Cements Ltd.,AMBUJACEM,500425,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"7,9","6,122.1","1,301.8",17.54%,380.9,61.2,"1,335.7",352.5,793,4,"2,777.9",14 +Apollo Hospitals Enterprise Ltd.,APOLLOHOSP,508869,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,"4,869.1","4,219.4",627.5,12.95%,163.4,111.3,376.9,130.2,232.9,16.2,697.5,48.5 +Apollo Tyres Ltd.,APOLLOTYRE,500877,AUTOMOBILES & AUTO COMPONENTS,AUTO TYRES & RUBBER PRODUCTS,"6,304.9","5,119.8","1,159.8",18.47%,360.3,132.8,679.9,205.8,474.3,7.5,"1,590.7",25 +Ashok Leyland Ltd.,ASHOKLEY,500477,AUTOMOBILES & AUTO COMPONENTS,COMMERCIAL VEHICLES,"11,463","9,558.6","1,870.4",16.37%,226.6,715.1,924.4,358,526,1.8,"2,141.5",7.3 +Asian Paints Ltd.,ASIANPAINT,500820,DIVERSIFIED CONSUMER SERVICES,FURNITURE-FURNISHING-PAINTS,"8,643.8","6,762.3","1,716.2",20.24%,208.7,50.9,"1,621.8",418.6,"1,205.4",12.6,"5,062.6",52.8 +Astral Ltd.,ASTRAL,532830,GENERAL INDUSTRIALS,PLASTIC PRODUCTS,"1,376.4","1,142.9",220.1,16.15%,48.7,8,176.8,45.1,131.2,4.9,549.7,20.4 +Atul Ltd.,ATUL,500027,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,"1,215.8","1,038.5",155.2,13.00%,54,1.9,121.5,32.5,90.3,30.6,392.3,132.9 +Aurobindo Pharma Ltd.,AUROPHARMA,524804,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"7,406.4","5,846","1,373.4",19.02%,417.5,68.2,"1,074.7",323.7,757.2,12.8,"2,325.5",39.7 +Avanti Feeds Ltd.,AVANTIFEED,512573,FOOD BEVERAGES & TOBACCO,OTHER FOOD PRODUCTS,"1,312","1,184.5",94,7.35%,14.3,0.2,113,30.5,74.2,5.5,336.4,24.7 +Avenue Supermarts Ltd.,DMART,540376,RETAILING,DEPARTMENT STORES,"12,661.3","11,619.4","1,005",7.96%,174.4,15.6,851.9,228.6,623.6,9.6,"2,332.1",35.8 +Axis Bank Ltd.,AXISBANK,532215,BANKING AND FINANCE,BANKS,"33,122.2","9,207.3","9,166",33.43%,0,"14,749","8,313.8","2,096.1","6,204.1",20.1,"13,121",42.6 +Bajaj Auto Ltd.,BAJAJ-AUTO,532977,AUTOMOBILES & AUTO COMPONENTS,2/3 WHEELERS,"11,206.8","8,708.1","2,130.1",19.65%,91.8,6.5,"2,400.4",564,"2,02",71.4,"6,841.6",241.8 +Bajaj Finance Ltd.,BAJFINANCE,500034,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"13,381.8","2,851.5","9,449.7",70.63%,158.5,"4,537.1","4,757.6","1,207","3,550.8",58.7,"13,118.5",216.7 +Bajaj Finserv Ltd.,BAJAJFINSV,532978,DIVERSIFIED,HOLDING COMPANIES,"26,022.7","14,992.2","9,949.9",38.24%,208.8,"4,449.1","5,292","1,536.5","1,929",12.1,"7,422.6",46.6 +Bajaj Holdings & Investment Ltd.,BAJAJHLDNG,500490,DIVERSIFIED,HOLDING COMPANIES,240.1,33.5,191.2,85.08%,8.4,0.2,197.9,73.9,"1,491.2",134,"5,545.1",498.3 +Balkrishna Industries Ltd.,BALKRISIND,502355,AUTOMOBILES & AUTO COMPONENTS,AUTO TYRES & RUBBER PRODUCTS,"2,360.3","1,720.5",532.7,23.64%,160.4,23.9,455.5,108.1,347.4,18,"1,047.5",54.2 +Balrampur Chini Mills Ltd.,BALRAMCHIN,500038,FOOD BEVERAGES & TOBACCO,SUGAR,"1,649","1,374.6",164.9,10.71%,41.2,17.2,215.9,56.6,166.3,8.2,540.5,26.8 +Bank of Baroda,BANKBARODA,532134,BANKING AND FINANCE,BANKS,"35,766","8,430.4","9,807.9",33.52%,0,"17,527.7","6,022.8","1,679.7","4,458.4",8.5,"18,602.9",35.9 +Bank of India,BANKINDIA,532149,BANKING AND FINANCE,BANKS,"16,779.4","3,704.9","3,818.8",25.35%,0,"9,255.7","2,977.4","1,488.6","1,498.5",3.6,"5,388.7",13.1 +Bata India Ltd.,BATAINDIA,500043,RETAILING,FOOTWEAR,834.6,637.5,181.7,22.18%,81.7,28.4,46.1,12.1,34,2.6,289.7,22.5 +Berger Paints (India) Ltd.,BERGEPAINT,509480,DIVERSIFIED CONSUMER SERVICES,FURNITURE-FURNISHING-PAINTS,"2,782.6","2,293.7",473.6,17.12%,82.9,21.1,385,96.7,291.6,2.5,"1,032.6",8.9 +Bharat Electronics Ltd.,BEL,500049,GENERAL INDUSTRIALS,DEFENCE,"4,146.1","2,994.9","1,014.2",25.30%,108.3,1.5,"1,041.5",260.7,789.4,1.1,"3,323",4.5 +Bharat Forge Ltd.,BHARATFORG,500493,GENERAL INDUSTRIALS,OTHER INDUSTRIAL PRODUCTS,"3,826.7","3,152.8",621.4,16.47%,211.3,124.3,336.1,121.8,227.2,4.9,783.7,16.8 +Bharat Heavy Electricals Ltd.,BHEL,500103,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"5,305.4","5,513",-387.7,-7.56%,59.9,180.4,-447.9,-197.9,-238.1,-0.7,71.3,0.2 +Bharat Petroleum Corporation Ltd.,BPCL,500547,OIL & GAS,REFINERIES/PETRO-PRODUCTS,"103,72","90,103.9","12,940.5",12.56%,"1,605.3",973.2,"10,755.7","2,812.2","8,243.5",38.7,"27,505.3",129.2 +Bharti Airtel Ltd.,BHARTIARTL,532454,TELECOM SERVICES,TELECOM SERVICES,"37,374.2","17,530.1","19,513.7",52.68%,"9,734.3","5,185.8","3,353.7","1,846.5","1,340.7",2.4,"7,547",13.2 +Indus Towers Ltd.,INDUSTOWER,534816,TELECOM SERVICES,OTHER TELECOM SERVICES,"7,229.7","3,498.8","3,633.7",50.95%,"1,525.6",458.6,"1,746.7",452,"1,294.7",4.8,"3,333.5",12.4 +Biocon Ltd.,BIOCON,532523,PHARMACEUTICALS & BIOTECHNOLOGY,BIOTECHNOLOGY,"3,620.2","2,720.7",741.6,21.42%,389.3,247.7,238.5,41.6,125.6,1.1,498.4,4.2 +Birla Corporation Ltd.,BIRLACORPN,500335,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"2,313.2","1,997",288.9,12.64%,143.5,95.4,77.1,18.8,58.4,7.6,153.1,19.9 +Blue Dart Express Ltd.,BLUEDART,526612,TRANSPORTATION,TRANSPORTATION - LOGISTICS,"1,329.7","1,101.8",222.7,16.82%,110.6,19.5,97.9,24.8,73.1,30.8,292.4,123.2 +Blue Star Ltd.,BLUESTARCO,500067,CONSUMER DURABLES,CONSUMER ELECTRONICS,"1,903.4","1,767.7",122.7,6.49%,23,17.6,95,24.3,70.7,3.6,437.7,21.3 +Bombay Burmah Trading Corporation Ltd.,BBTC,501425,FOOD BEVERAGES & TOBACCO,TEA & COFFEE,"4,643.5","3,664.7",859.2,18.99%,74.7,154.6,697.1,212.6,122,17.5,"-1,499.5",-214.8 +Bosch Ltd.,BOSCHLTD,500530,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"4,284.3","3,638.8",491.3,11.90%,101.3,12.2,"1,317",318.1,999.8,339,"2,126.9",721 +Brigade Enterprises Ltd.,BRIGADE,532929,REALTY,REALTY,"1,407.9","1,041.8",324.8,23.77%,75.7,110,180.3,67.8,133.5,5.8,298.2,12.9 +Britannia Industries Ltd.,BRITANNIA,500825,FMCG,PACKAGED FOODS,"4,485.2","3,560.5",872.4,19.68%,71.7,53.4,799.7,212.1,587.6,24.4,"2,536.2",105.3 +CCL Products India Ltd.,CCL,519600,FOOD BEVERAGES & TOBACCO,TEA & COFFEE,608.3,497.7,109.9,18.09%,22.6,18.4,69.7,8.8,60.9,4.6,279.9,21 +Crisil Ltd.,CRISIL,500092,BANKING AND FINANCE,OTHER FINANCIAL SERVICES,771.8,544.2,191.7,26.05%,26.5,0.8,200.3,48.3,152,20.8,606.3,82.9 +Zydus Lifesciences Ltd.,ZYDUSLIFE,532321,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"4,422.8","3,222.7","1,146.1",26.23%,184.2,8.7,"1,007.2",226.4,800.7,7.9,"2,807.1",27.7 +Can Fin Homes Ltd.,CANFINHOME,511196,BANKING AND FINANCE,HOUSING FINANCE,871,49.7,749.2,86.01%,2.8,548.4,198,39.9,158.1,11.9,658.8,49.5 +Canara Bank,CANBK,532483,BANKING AND FINANCE,BANKS,"33,891.2","8,250.3","7,706.6",28.24%,0,"17,934.3","5,098","1,420.6","3,86",20.9,"13,968.4",77 +Carborundum Universal Ltd.,CARBORUNIV,513375,GENERAL INDUSTRIALS,OTHER INDUSTRIAL PRODUCTS,"1,166",978.8,167.5,14.61%,45.9,4.9,136.4,43.7,101.9,5.4,461.3,24.3 +Castrol India Ltd.,CASTROLIND,500870,OIL & GAS,OIL MARKETING & DISTRIBUTION,"1,203.2",914.4,268.6,22.70%,22.9,2.4,263.5,69.1,194.4,2,815.5,8.2 +Ceat Ltd.,CEATLTD,500878,AUTOMOBILES & AUTO COMPONENTS,AUTO TYRES & RUBBER PRODUCTS,"3,063.8","2,597.2",456.1,14.94%,124.5,71.7,270.4,68.3,208,51.4,521.7,129 +Central Bank of India,CENTRALBK,532885,BANKING AND FINANCE,BANKS,"8,438.5","2,565.4","1,535.4",20.81%,0,"4,337.7",567.2,-41.5,622,0.7,"2,181.4",2.5 +Century Plyboards (India) Ltd.,CENTURYPLY,532548,FOREST MATERIALS,FOREST PRODUCTS,"1,011.4",852.5,144.3,14.47%,23.4,6.1,129.4,32.2,96.9,4.4,380.7,17.1 +Cera Sanitaryware Ltd.,CERA,532443,DIVERSIFIED CONSUMER SERVICES,FURNITURE-FURNISHING-PAINTS,476.2,387.2,76.5,16.49%,8.9,1.4,77.2,19.8,56.9,43.8,232.4,178.7 +Chambal Fertilisers & Chemicals Ltd.,CHAMBLFERT,500085,FERTILIZERS,FERTILIZERS,"5,467.3","4,770.5",615,11.42%,78.4,45.8,572.6,200.2,381,9.2,"1,137.7",27.3 +Cholamandalam Investment & Finance Company Ltd.,CHOLAFIN,511243,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"4,695.2",987.6,"3,235.1",69.99%,38.5,"2,204.2","1,065",288.8,772.9,9.4,"3,022.8",36.7 +Cipla Ltd.,CIPLA,500087,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"6,854.5","4,944.4","1,733.8",25.96%,290,25.8,"1,594.2",438.4,"1,130.9",14,"3,449.1",42.7 +City Union Bank Ltd.,CUB,532210,BANKING AND FINANCE,BANKS,"1,486.1",333.9,386.6,29.65%,0,765.6,330.6,50,280.6,3.8,943.8,12.7 +Coal India Ltd.,COALINDIA,533278,METALS & MINING,COAL,"34,760.3","24,639.4","8,137",24.83%,"1,178.2",182.5,"8,760.2","2,036.5","6,799.8",11,"28,059.6",45.5 +Colgate-Palmolive (India) Ltd.,COLPAL,500830,FMCG,PERSONAL PRODUCTS,"1,492.1",989,482.1,32.77%,44.3,1.1,457.8,117.8,340.1,12.5,"1,173.2",43.1 +Container Corporation of India Ltd.,CONCOR,531344,COMMERCIAL SERVICES & SUPPLIES,WAREHOUSING AND LOGISTICS,"2,299.8","1,648.4",546.5,24.90%,153.1,16.5,481.8,119,367.4,6,"1,186.2",19.5 +Coromandel International Ltd.,COROMANDEL,506395,FERTILIZERS,FERTILIZERS,"7,032.9","5,929.4","1,058.7",15.15%,54,46.2,"1,003.3",245,756.9,25.7,"2,024.2",68.8 +Crompton Greaves Consumer Electricals Ltd.,CROMPTON,539876,CONSUMER DURABLES,HOUSEHOLD APPLIANCES,"1,797.2","1,607.8",174.5,9.79%,32.1,21.5,135.8,34.9,97.2,1.5,432,6.7 +Cummins India Ltd.,CUMMINSIND,500480,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,"2,011.3","1,575.4",346.2,18.02%,38.3,6.8,390.9,99.6,329.1,11.9,"1,445.5",52.1 +Cyient Ltd.,CYIENT,532175,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"1,792","1,452.7",325.8,18.32%,65.8,27,240.3,56.7,178.3,16.3,665.6,60.1 +DCM Shriram Ltd.,DCMSHRIRAM,523367,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,"2,73","2,593.9",114.1,4.21%,74,14.7,47.5,15.2,32.2,2.1,617.6,39.4 +DLF Ltd.,DLF,532868,REALTY,REALTY,"1,476.4",885.3,462.4,34.31%,37,90.2,464,112.2,622.8,2.5,"2,239",9 +Dabur India Ltd.,DABUR,500096,FMCG,PERSONAL PRODUCTS,"3,320.2","2,543",660.9,20.63%,98.3,28.1,650.8,144.3,515,2.9,"1,755.7",9.9 +Delta Corp Ltd.,DELTACORP,532848,COMMERCIAL SERVICES & SUPPLIES,MISC. COMMERCIAL SERVICES,282.6,170.5,100.1,36.99%,16.9,2.7,92.4,23,69.4,2.6,273.3,10.2 +Divi's Laboratories Ltd.,DIVISLAB,532488,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,995","1,43",479,25.09%,95,1,469,121,348,13.1,"1,331.8",50.3 +Dr. Lal Pathlabs Ltd.,LALPATHLAB,539524,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE SERVICES,619.4,423.5,177.8,29.57%,35.9,7.8,152.2,41.5,109.3,13.2,301.4,36.1 +Dr. Reddy's Laboratories Ltd.,DRREDDY,500124,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"7,217.6","4,888.8","2,008.3",29.09%,375.5,35.3,"1,912.5",434.5,"1,482.2",89.1,"5,091.2",305.2 +EID Parry (India) Ltd.,EIDPARRY,500125,FOOD BEVERAGES & TOBACCO,OTHER FOOD PRODUCTS,"9,210.3","8,002","1,057.5",11.67%,101.2,74.2,"1,032.8",246.8,452.3,25.5,991,55.8 +Eicher Motors Ltd.,EICHERMOT,505200,AUTOMOBILES & AUTO COMPONENTS,2/3 WHEELERS,"4,388.3","3,027.4","1,087.2",26.42%,142.5,12.7,"1,205.7",291.1,"1,016.2",37.1,"3,581",130.8 +Emami Ltd.,EMAMILTD,531162,FMCG,PERSONAL PRODUCTS,876,631.2,233.7,27.02%,46.1,2.2,196.4,15.8,178.5,4.1,697.8,16 +Endurance Technologies Ltd.,ENDURANCE,540153,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"2,560.5","2,226.7",318.3,12.51%,118.4,9.8,205.6,51.1,154.6,11,562.8,40 +Engineers India Ltd.,ENGINERSIN,532178,COMMERCIAL SERVICES & SUPPLIES,CONSULTING SERVICES,833.6,691.3,98.5,12.47%,8.3,0.4,133.6,32.2,127.5,2.3,472.7,8.4 +Escorts Kubota Ltd.,ESCORTS,500495,AUTOMOBILES & AUTO COMPONENTS,COMMERCIAL VEHICLES,"2,154.4","1,798.6",260.7,12.66%,40.8,3.1,311.9,79.7,223.3,20.6,910.5,82.4 +Exide Industries Ltd.,EXIDEIND,500086,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"4,408.9","3,872.4",499.1,11.42%,141.5,29.7,365.3,95.2,269.4,3.2,872.7,10.3 +Federal Bank Ltd.,FEDERALBNK,500469,BANKING AND FINANCE,BANKS,"6,548.2","1,603.8","1,400.3",24.18%,0,"3,544.1","1,342.7",342.6,994.1,4.3,"3,671.4",15.6 +Finolex Cables Ltd.,FINCABLES,500144,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,"1,229.3","1,041.3",146.1,12.30%,10.8,0.4,176.7,52.3,154.2,10.1,643.9,42.1 +Finolex Industries Ltd.,FINPIPE,500940,GENERAL INDUSTRIALS,PLASTIC PRODUCTS,944.5,780.2,103,11.66%,27.4,12.5,124.5,35.4,98,1.6,459.3,7.4 +Firstsource Solutions Ltd.,FSL,532809,SOFTWARE & SERVICES,BPO/KPO,"1,556.9","1,311.2",228.8,14.86%,65.4,26.1,154.3,27.8,126.5,1.9,551.7,7.9 +GAIL (India) Ltd.,GAIL,532155,UTILITIES,UTILITIES,"33,191","29,405.5","3,580.2",10.85%,837.3,199.6,"2,748.7",696.3,"2,444.1",3.7,"5,283.8",8 +GlaxoSmithKline Pharmaceuticals Ltd.,GLAXO,500660,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,985.2,667.5,289.5,30.25%,18.1,0.4,299.2,81.7,217.5,12.8,647.8,38.2 +Glenmark Pharmaceuticals Ltd.,GLENMARK,532296,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"3,209.1","2,745.1",462.3,14.41%,141.5,121.5,-124.4,55.9,-81.9,-2.9,-196.3,-7 +Godrej Consumer Products Ltd.,GODREJCP,532424,FMCG,PERSONAL PRODUCTS,"3,667.9","2,897.8",704.2,19.55%,60.9,77.3,619.4,186.6,432.8,4.2,"1,750.1",17.1 +Godrej Industries Ltd.,GODREJIND,500164,DIVERSIFIED,DIVERSIFIED,"4,256.9","3,672.1",265.5,6.74%,89.3,333.1,162.4,75.9,87.3,2.6,880,26.1 +Godrej Properties Ltd.,GODREJPROP,533150,REALTY,REALTY,605.1,404.7,-61.7,-17.98%,7.4,48,145.1,38.8,66.8,2.4,662.6,23.8 +Granules India Ltd.,GRANULES,532482,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,191",976.5,213,17.90%,52.5,26,136,33.9,102.1,4.2,393.9,16.3 +Great Eastern Shipping Company Ltd.,GESHIP,500620,TRANSPORTATION,SHIPPING,"1,461.5",585.6,643.4,52.35%,186.7,77.1,611.9,17.3,594.7,41.6,"2,520.1",176.5 +Gujarat Alkalies & Chemicals Ltd.,GUJALKALI,530001,CHEMICALS & PETROCHEMICALS,COMMODITY CHEMICALS,"1,042.3",926.1,45.2,4.65%,95.2,10.8,10.2,-0.1,-18.4,-2.5,82.7,11.3 +Gujarat Gas Ltd.,GUJGASLTD,539336,UTILITIES,UTILITIES,"4,019.3","3,494.5",496.6,12.44%,117.9,7.8,399.1,102.9,296.2,4.3,"1,254.3",18.2 +Gujarat Narmada Valley Fertilizers & Chemicals Ltd.,GNFC,500670,FERTILIZERS,FERTILIZERS,"2,232","1,911",169,8.12%,78,1,242,64,182,11.7,932,60.1 +Gujarat Pipavav Port Ltd.,GPPL,533248,TRANSPORTATION,MARINE PORT & SERVICES,270.4,102,150.6,59.64%,28.8,2.2,141.1,53.4,92.3,1.9,341.8,7.1 +Gujarat State Fertilizer & Chemicals Ltd.,GSFC,500690,FERTILIZERS,FERTILIZERS,"3,313.2","2,881.4",237.3,7.61%,45.7,1.6,387,78.1,308.9,7.8,"1,056.2",26.5 +Gujarat State Petronet Ltd.,GSPL,532702,UTILITIES,UTILITIES,"4,455.9","3,497.2",913.7,20.72%,165,14.5,779.2,198.7,454.6,8.1,"1,522",27 +HCL Technologies Ltd.,HCLTECH,532281,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"27,037","20,743","5,929",22.23%,"1,01",156,"5,128","1,295","3,832",14.2,"15,445",56.9 +HDFC Bank Ltd.,HDFCBANK,500180,BANKING AND FINANCE,BANKS,"107,566.6","42,037.6","24,279.1",32.36%,0,"41,249.9","20,967.4","3,655","16,811.4",22.2,"54,474.6",71.8 +Havells India Ltd.,HAVELLS,517354,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,"3,952.8","3,527",373.4,9.57%,81.2,9.3,335.3,86.2,249.1,4,"1,177.7",18.8 +Hero MotoCorp Ltd.,HEROMOTOCO,500182,AUTOMOBILES & AUTO COMPONENTS,2/3 WHEELERS,"9,741.2","8,173.5","1,359.5",14.26%,187.1,25,"1,355.6",353.1,"1,006.3",50.3,"3,247.6",162.5 +HFCL Ltd.,HFCL,500183,TELECOMMUNICATIONS EQUIPMENT,TELECOM CABLES,"1,128.7",978.9,132.6,11.93%,21.4,34.8,93.5,24,69.4,0.5,305.5,2.1 +Hindalco Industries Ltd.,HINDALCO,500440,METALS & MINING,ALUMINIUM AND ALUMINIUM PRODUCTS,"54,632","48,557","5,612",10.36%,"1,843","1,034","3,231","1,035","2,196",9.9,"8,423",37.9 +Hindustan Copper Ltd.,HINDCOPPER,513599,METALS & MINING,COPPER,392.6,260.2,121.2,31.77%,45.6,4.1,82.6,21.9,60.7,0.6,320.5,3.3 +Hindustan Petroleum Corporation Ltd.,HINDPETRO,500104,OIL & GAS,REFINERIES/PETRO-PRODUCTS,"96,093.4","87,512","8,24",8.61%,"1,247.3",590,"6,744.1","1,616","5,827",41.1,"16,645",117.3 +Hindustan Unilever Ltd.,HINDUNILVR,500696,FMCG,PERSONAL PRODUCTS,"15,806","11,826","3,797",24.30%,297,88,"3,59",931,"2,656",11.3,"10,284",43.8 +Hindustan Zinc Ltd.,HINDZINC,500188,METALS & MINING,ZINC,"7,014","3,652","3,139",46.22%,825,232,"2,305",576,"1,729",4.1,"8,432",20 +Housing and Urban Development Corporation Ltd.,HUDCO,540530,BANKING AND FINANCE,HOUSING FINANCE,"1,880.8",82.7,"1,809.6",97.04%,2.4,"1,216.8",606.4,154.7,451.6,2.3,"1,790.7",8.9 +ITC Ltd.,ITC,500875,FOOD BEVERAGES & TOBACCO,CIGARETTES-TOBACCO PRODUCTS,"18,439.3","11,320.2","6,454.2",36.31%,453,9.9,"6,656.2","1,700.3","4,898.1",3.9,"20,185.1",16.2 +ICICI Bank Ltd.,ICICIBANK,532174,BANKING AND FINANCE,BANKS,"57,292.3","23,911","15,473.2",39.74%,0,"17,908","14,824.2","3,808.8","11,805.6",15.6,"41,086.8",58.7 +ICICI Prudential Life Insurance Company Ltd.,ICICIPRULI,540133,BANKING AND FINANCE,LIFE INSURANCE,"17,958.1","17,612.3",-229.6,-1.32%,0,0,340.2,32.5,243.9,1.7,906.9,6.3 +IDBI Bank Ltd.,IDBI,500116,BANKING AND FINANCE,BANKS,"7,063.7","1,922.3","2,175.3",36.02%,0,"2,966.1","2,396.9","1,003.7","1,385.4",1.3,"4,776.3",4.4 +IDFC First Bank Ltd.,IDFCFIRSTB,539437,BANKING AND FINANCE,BANKS,"8,765.8","3,849","1,511.2",20.54%,0,"3,405.6",982.8,236,746.9,1.1,"2,911.1",4.3 +IDFC Ltd.,IDFC,532659,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),36.7,6,30.6,83.56%,0,0,30.6,6.6,223.5,1.4,"4,147.1",25.9 +IRB Infrastructure Developers Ltd.,IRB,532947,CEMENT AND CONSTRUCTION,ROADS & HIGHWAYS,"1,874.5",950.4,794.6,45.54%,232.7,434.6,256.9,85.8,95.7,0.2,501,0.8 +ITI Ltd.,ITI,523610,TELECOMMUNICATIONS EQUIPMENT,TELECOM EQUIPMENT,256.1,299.3,-52.8,-21.42%,13.3,69.3,-125.8,0,-126,-1.3,-388.4,-4 +Vodafone Idea Ltd.,IDEA,532822,TELECOM SERVICES,TELECOM SERVICES,"10,750.8","6,433.5","4,282.8",39.97%,"5,667.3","6,569","-7,919",817.7,"-8,737.9",-1.8,"-30,986.8",-6.4 +India Cements Ltd.,INDIACEM,530005,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"1,272.4","1,26",4.4,0.35%,55,60.4,-103,-17.4,-80.1,-2.6,-261.1,-8.4 +Indiabulls Housing Finance Ltd.,IBULHSGFIN,535789,BANKING AND FINANCE,HOUSING FINANCE,"2,242.3",190.6,"1,779.2",79.88%,22.9,"1,349.8",421.6,123.6,298,6.5,"1,146",24.3 +Indian Bank,INDIANB,532814,BANKING AND FINANCE,BANKS,"15,929.4","3,599.1","4,327.7",31.44%,0,"8,002.6","2,776.7",768.6,"2,068.5",16.6,"6,893.3",55.3 +Indian Hotels Company Ltd.,INDHOTEL,500850,HOTELS RESTAURANTS & TOURISM,HOTELS,"1,480.9","1,078.4",354.8,24.75%,111.2,59,232.2,72.3,166.9,1.2,"1,100.3",7.7 +Indian Oil Corporation Ltd.,IOC,530965,OIL & GAS,OIL MARKETING & DISTRIBUTION,"179,752.1","156,013.1","23,328.4",13.01%,"3,609.6","2,135","18,090.2","4,699.7","13,114.3",9.5,"38,614.3",27.3 +Indian Overseas Bank,IOB,532388,BANKING AND FINANCE,BANKS,"6,941.5","1,785.1","1,679.8",28.84%,0,"3,476.6",635.5,8.3,627.2,0.3,"2,341.9",1.2 +Indraprastha Gas Ltd.,IGL,532514,UTILITIES,UTILITIES,"3,520.2","2,801.6",656.9,18.99%,102.2,2.5,613.9,151.4,552.7,7.9,"1,806.2",25.8 +IndusInd Bank Ltd.,INDUSINDBK,532187,BANKING AND FINANCE,BANKS,"13,529.7","3,449.9","3,908.7",34.75%,0,"6,171.1","2,934.9",732.9,"2,202.2",28.4,"8,333.7",107.2 +Info Edge (India) Ltd.,NAUKRI,532777,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,792,421.2,204.7,32.70%,25.9,8.2,382.8,68.7,205.1,15.9,-25.6,-2 +InterGlobe Aviation Ltd.,INDIGO,539448,TRANSPORTATION,AIRLINES,"15,502.9","12,743.6","2,200.3",14.72%,"1,549","1,021.3",189.1,0.2,188.9,4.9,"5,621.3",145.7 +Ipca Laboratories Ltd.,IPCALAB,524494,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"2,072.5","1,712.7",321.3,15.80%,90.3,44.1,225.4,87.9,145.1,5.7,492.2,19.4 +J B Chemicals & Pharmaceuticals Ltd.,JBCHEPHARM,506943,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,889.4,638.2,243.5,27.62%,32.2,10.4,208.7,58.1,150.6,9.7,486.6,31.4 +JK Cement Ltd.,JKCEMENT,532644,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"2,782.1","2,285.8",467,16.96%,137.1,115,244.2,65.7,178.1,23.1,444,57.5 +JK Lakshmi Cement Ltd.,JKLAKSHMI,500380,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"1,588.5","1,357.3",217.3,13.80%,56.6,33.6,141,45.1,92.7,7.9,357.6,30.4 +JM Financial Ltd.,JMFINANCIL,523405,DIVERSIFIED,HOLDING COMPANIES,"1,214",407.9,662.6,55.34%,13.2,388.1,277.9,72.4,194.9,2,608.1,6.4 +JSW Energy Ltd.,JSWENERGY,533148,UTILITIES,ELECTRIC UTILITIES,"3,387.4","1,379","1,880.4",57.69%,408.7,513.7,"1,085.9",235.1,850.2,5.2,"1,591.7",9.7 +JSW Steel Ltd.,JSWSTEEL,500228,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"44,821","36,698","7,886",17.69%,"2,019","2,084","4,609","1,812","2,76",11.4,"9,252",38.1 +Jindal Stainless Ltd.,JSL,532508,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"9,829","8,566.5","1,230.6",12.56%,221.9,155.6,985.7,229.1,774.3,9.4,"2,600.2",31.6 +Jindal Steel & Power Ltd.,JINDALSTEL,532286,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"12,282","9,964.5","2,285.7",18.66%,603.7,329.4,"1,384.5",-5.8,"1,387.8",13.8,"4,056",40.4 +Jubilant Foodworks Ltd.,JUBLFOOD,533155,HOTELS RESTAURANTS & TOURISM,RESTAURANTS,"1,375.7","1,091.4",277.2,20.25%,141.9,56.8,85.5,23.3,97.2,1.5,235,3.6 +Just Dial Ltd.,JUSTDIAL,535648,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,318.5,211.8,48.8,18.71%,12.2,2.4,92.1,20.3,71.8,8.4,314.1,36.9 +Jyothy Labs Ltd.,JYOTHYLAB,532926,FMCG,PERSONAL PRODUCTS,745.6,597,135.4,18.48%,12.3,1.2,135.1,31.1,104.2,2.8,326.9,8.9 +KRBL Ltd.,KRBL,530813,FMCG,PACKAGED FOODS,"1,246.5","1,018.9",194.5,16.03%,19.9,0.8,206.8,53.6,153.3,6.5,671.4,29.3 +Kajaria Ceramics Ltd.,KAJARIACER,500233,DIVERSIFIED CONSUMER SERVICES,FURNITURE-FURNISHING-PAINTS,"1,129.9",941.9,179.7,16.02%,36.1,4.3,147.7,36.6,108,6.8,397.8,25 +Kalpataru Projects International Ltd.,KPIL,522287,UTILITIES,ELECTRIC UTILITIES,"4,53","4,148",370,8.19%,113,137,132,42,89,5.5,478,29.9 +Kansai Nerolac Paints Ltd.,KANSAINER,500165,DIVERSIFIED CONSUMER SERVICES,FURNITURE-FURNISHING-PAINTS,"1,978.6","1,683.3",273.2,13.97%,47.4,7.6,240.3,64.8,177.2,2.2,"1,118.8",13.8 +Karur Vysya Bank Ltd.,KARURVYSYA,590003,BANKING AND FINANCE,BANKS,"2,336",616.4,637.9,31.94%,0,"1,081.7",511.5,133.1,378.4,4.7,"1,364.2",17 +KEC International Ltd.,KEC,532714,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"4,514.9","4,224.7",274.3,6.10%,46.5,177.8,65.8,9.9,55.8,2.2,187.9,7.3 +Kotak Mahindra Bank Ltd.,KOTAKBANK,500247,BANKING AND FINANCE,BANKS,"21,559.5","9,681","6,343",46.24%,0,"5,535.5","5,888.3","1,465.5","4,461",22.4,"17,172.7",86.4 +L&T Finance Holdings Ltd.,L&TFH,533519,DIVERSIFIED,HOLDING COMPANIES,"3,482.1",935.3,"1,882.4",58.57%,28.3,"1,324.9",797.4,203.2,595.1,2.4,"2,080.8",8.4 +L&T Technology Services Ltd.,LTTS,540115,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"2,427.7","1,910.9",475.6,19.93%,68.1,12.6,436.1,120.2,315.4,29.8,"1,239.7",117.5 +LIC Housing Finance Ltd.,LICHSGFIN,500253,BANKING AND FINANCE,HOUSING FINANCE,"6,765.9",250.6,"6,095.7",90.10%,13.2,"4,599.9","1,483",291.2,"1,193.5",21.7,"4,164.5",75.7 +Lakshmi Machine Works Ltd.,LAXMIMACH,500252,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,"1,355.5","1,184.5",136,10.30%,23.6,0,147.4,32.3,115.1,107.8,416,389.5 +Laurus Labs Ltd.,LAURUSLABS,540222,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,226.2","1,036.6",187.9,15.34%,93.4,42.4,53.9,14.6,37,0.7,367.8,6.8 +Lupin Ltd.,LUPIN,500257,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"5,079","4,120.8",917.8,18.21%,247.8,80.6,629.7,134.3,489.5,10.8,"1,331.2",29.2 +MMTC Ltd.,MMTC,513377,COMMERCIAL SERVICES & SUPPLIES,COMMODITY TRADING & DISTRIBUTION,-167.2,-180.1,-30.4,14.42%,0.8,1.1,12.1,1.5,52,0.3,174.1,1.2 +MRF Ltd.,MRF,500290,AUTOMOBILES & AUTO COMPONENTS,AUTO TYRES & RUBBER PRODUCTS,"6,287.8","5,060.2","1,156.9",18.61%,351.5,85.5,790.6,203.9,586.7,1383.3,"1,690.9",3988 +Mahanagar Gas Ltd.,MGL,539957,UTILITIES,UTILITIES,"1,772.7","1,250.1",478.9,27.70%,65.8,2.5,454.3,115.8,338.5,34.3,"1,147.8",116.2 +Mahindra & Mahindra Financial Services Ltd.,M&MFIN,532720,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"3,863.5","1,077.5","2,109.3",55.03%,67.1,"1,703.4",369.1,96,281.1,2.3,"1,982.5",16 +Mahindra & Mahindra Ltd.,M&M,500520,AUTOMOBILES & AUTO COMPONENTS,CARS & UTILITY VEHICLES,"35,027.2","28,705.9","5,729.6",16.64%,"1,138.6","1,835.2","3,347.5","1,083.7","2,347.8",21.1,"11,169.4",100.2 +Mahindra Holidays & Resorts India Ltd.,MHRIL,533088,HOTELS RESTAURANTS & TOURISM,HOTELS,672.2,519.3,136,20.76%,83.8,33.3,35.8,14,21.3,1.1,66,3.3 +Manappuram Finance Ltd.,MANAPPURAM,531213,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"2,174",555.6,"1,481.3",68.68%,62.5,689.4,746.7,186.1,558.4,6.6,"1,859.8",22 +Mangalore Refinery And Petrochemicals Ltd.,MRPL,500109,OIL & GAS,REFINERIES/PETRO-PRODUCTS,"22,904.7","20,705.6","2,138.2",9.36%,296,311.2,"1,592",546.2,"1,051.7",6,"3,784.9",21.6 +Marico Ltd.,MARICO,531642,FMCG,PERSONAL PRODUCTS,"2,514","1,979",497,20.07%,39,20,476,116,353,2.7,"1,41",10.9 +Maruti Suzuki India Ltd.,MARUTI,532500,AUTOMOBILES & AUTO COMPONENTS,CARS & UTILITY VEHICLES,"37,902.1","32,282.5","4,790.3",12.92%,794.4,35.1,"4,790.1","1,083.8","3,764.3",124.6,"11,351.8",375.9 +Max Financial Services Ltd.,MFSL,500271,BANKING AND FINANCE,LIFE INSURANCE,"10,189.1","10,024.6",143.9,1.42%,0.8,9.4,158.2,-12.1,147.9,4.3,506.4,14.7 +UNO Minda Ltd.,UNOMINDA,532539,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"3,630.2","3,219.8",401.6,11.09%,125.4,27.2,257.9,73.3,225,3.9,742.4,13 +Motilal Oswal Financial Services Ltd.,MOTILALOFS,532892,BANKING AND FINANCE,OTHER FINANCIAL SERVICES,"1,650.7",724.1,904.5,55.18%,17.3,241.1,657.6,124.2,531.2,35.9,"1,449.3",97.8 +MphasiS Ltd.,MPHASIS,526299,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"3,325.5","2,680.9",595.6,18.18%,89,34,521.7,129.7,391.9,20.8,"1,605.6",85.1 +Muthoot Finance Ltd.,MUTHOOTFIN,533398,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"3,631.9",723.4,"2,801.6",77.69%,22.2,"1,335","1,470.2",374.9,"1,059.6",26.4,"3,982.9",99.2 +Natco Pharma Ltd.,NATCOPHARM,524816,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,060.8",573.4,458,44.41%,43.6,4.2,439.6,70.6,369,20.6,"1,127.4",63 +NBCC (India) Ltd.,NBCC,534309,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,"2,129.1","1,957.7",95.5,4.65%,1.3,0,104.6,22.9,79.6,0.4,332.2,1.8 +NCC Ltd.,NCC,500294,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,"4,746.4","4,415.9",303.7,6.44%,53.2,153.5,123.8,38.8,77.3,1.2,599.4,9.5 +NHPC Ltd.,NHPC,533098,UTILITIES,ELECTRIC UTILITIES,"3,113.8","1,173.9","1,757.4",59.95%,294.9,104.8,"1,618.3",-75,"1,545.8",1.5,"3,897.8",3.9 +Coforge Ltd.,COFORGE,532541,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"2,285.1","1,935.3",340.9,14.98%,77.2,31.9,240.7,52.8,187.9,29.6,696.2,113.2 +NLC India Ltd.,NLCINDIA,513683,UTILITIES,ELECTRIC UTILITIES,"3,234","2,143",834.6,28.03%,455.1,213.9,"1,700.6",614.7,"1,084.7",7.8,"1,912.3",13.8 +NTPC Ltd.,NTPC,532555,UTILITIES,ELECTRIC UTILITIES,"45,384.6","32,303.2","12,680.2",28.19%,"4,037.7","2,920.5","6,342.9","2,019.7","4,614.6",4.8,"19,125.2",19.7 +Narayana Hrudayalaya Ltd.,NH,539551,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,"1,323.6",997.1,308.1,23.61%,55.3,22.9,248.4,21.7,226.6,11.2,737.5,36.1 +National Aluminium Company Ltd.,NATIONALUM,532234,METALS & MINING,ALUMINIUM AND ALUMINIUM PRODUCTS,"3,112","2,646.9",396.5,13.03%,186.2,4,275,68.7,187.3,1,"1,272.4",6.9 +Navin Fluorine International Ltd.,NAVINFLUOR,532504,CHEMICALS & PETROCHEMICALS,COMMODITY CHEMICALS,494.9,373.4,98.3,20.84%,24.2,20,77.2,16.6,60.6,12.2,365,73.7 +Oberoi Realty Ltd.,OBEROIRLTY,533273,REALTY,REALTY,"1,243.8",579.2,638.2,52.42%,11.3,56.5,596.8,142.1,456.8,12.6,"1,961.3",53.9 +Oil And Natural Gas Corporation Ltd.,ONGC,500312,OIL & GAS,EXPLORATION & PRODUCTION,"149,388.5","118,618.4","28,255.3",19.24%,"6,698.1","2,603.3","21,564.9","5,633.6","13,734.1",10.9,"43,072.5",34.2 +Oil India Ltd.,OIL,533106,OIL & GAS,EXPLORATION & PRODUCTION,"9,200.1","5,293.3","3,523.2",39.96%,499,278.9,762,67.6,420.7,3.9,"5,874.5",54.2 +Oracle Financial Services Software Ltd.,OFSS,532466,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"1,509.6",886.4,558.1,38.64%,19,8,596.2,178.8,417.4,48.2,"1,835.1",211.9 +PI Industries Ltd.,PIIND,523642,CHEMICALS & PETROCHEMICALS,AGROCHEMICALS,"2,163.8","1,565.5",551.4,26.05%,80.3,7.8,510.2,31.7,480.5,31.7,"1,495.8",98.4 +PNB Housing Finance Ltd.,PNBHOUSING,540173,BANKING AND FINANCE,HOUSING FINANCE,"1,779.4",158.8,"1,574.1",88.54%,11.3,"1,057.3",507.1,124.1,383,14.8,"1,278.7",49.3 +PNC Infratech Ltd.,PNCINFRA,539150,CEMENT AND CONSTRUCTION,ROADS & HIGHWAYS,"1,932.4","1,511.6",399.8,20.92%,40.9,161.3,218.6,70.7,147.9,5.8,614.3,23.9 +PVR INOX Ltd.,PVRINOX,532689,RETAILING,SPECIALTY RETAIL,"2,023.7","1,293.1",706.8,35.34%,308.6,200.3,221.7,55.5,166.3,17,-232.5,-23.7 +Page Industries Ltd.,PAGEIND,532827,TEXTILES APPARELS & ACCESSORIES,OTHER APPARELS & ACCESSORIES,"1,126.8",891.6,233.5,20.76%,24.6,11.2,199.4,49.1,150.3,134.7,510.7,457.9 +Persistent Systems Ltd.,PERSISTENT,533179,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"2,449","2,006.5",405.2,16.80%,74.4,12.3,355.8,92.5,263.3,35,981.5,127.6 +Petronet LNG Ltd.,PETRONET,532522,OIL & GAS,OIL MARKETING & DISTRIBUTION,"12,686.2","11,317.9","1,214.7",9.69%,194.8,74.7,"1,098.8",283.9,855.7,5.7,"3,490.3",23.3 +Pfizer Ltd.,PFIZER,500680,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,611.3,392.6,182.6,31.75%,15.4,2.7,200.5,51.6,149,32.6,522.8,114.3 +Phoenix Mills Ltd.,PHOENIXLTD,503100,REALTY,REALTY,906.6,361.2,506,57.82%,65.9,96.5,375.2,71.4,252.6,14.2,923.6,51.7 +Pidilite Industries Ltd.,PIDILITIND,500331,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,"3,107.6","2,396.3",679.7,22.10%,75.2,13.1,623,163.1,450.1,8.8,"1,505.5",29.6 +Power Finance Corporation Ltd.,PFC,532810,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"22,403.7",315.4,"22,941.9",102.46%,12.7,"14,313.1","8,628.8","2,000.6","4,833.1",14.7,"17,946.4",54.4 +Power Grid Corporation of India Ltd.,POWERGRID,532898,UTILITIES,ELECTRIC UTILITIES,"11,530.4","1,358.7","9,908.4",87.94%,"3,277","2,341.3","4,393.4",573.7,"3,781.4",4.1,"15,344.4",16.5 +Prestige Estates Projects Ltd.,PRESTIGE,ASM,REALTY,REALTY,"3,256","1,643.9",592.5,26.49%,174.1,263.9,"1,174.1",256.4,850.9,21.2,"1,714",42.8 +Prism Johnson Ltd.,PRSMJOHNSN,500338,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"1,846","1,745.4",92.4,5.03%,95.2,43.5,210,30.4,182.7,3.6,154.2,3.1 +Procter & Gamble Hygiene & Healthcare Ltd.,PGHH,500459,FMCG,PERSONAL PRODUCTS,"1,154.1",853.5,284.9,25.03%,14.3,1.9,284.5,73.8,210.7,64.9,734.4,226.3 +Punjab National Bank,PNB,532461,BANKING AND FINANCE,BANKS,"29,857","6,798.1","6,239.1",23.23%,0,"16,819.8","2,778.3","1,013.8","1,990.2",1.8,"5,904.8",5.4 +Quess Corp Ltd.,QUESS,539978,SOFTWARE & SERVICES,BPO/KPO,"4,763.5","4,584.8",163.6,3.44%,69.7,28.1,79.3,8.3,71.9,4.8,240.9,16.2 +RBL Bank Ltd.,RBLBANK,540065,BANKING AND FINANCE,BANKS,"3,720.6","1,422.6",765.4,25.45%,0,"1,532.6",125,-206.1,331.1,5.5,"1,173.9",19.5 +Radico Khaitan Ltd.,RADICO,532497,FOOD BEVERAGES & TOBACCO,BREWERIES & DISTILLERIES,925.7,803.8,121.2,13.10%,26.1,12.5,83.3,21.4,64.8,4.8,237,17.7 +Rain Industries Ltd.,RAIN,500339,CHEMICALS & PETROCHEMICALS,PETROCHEMICALS,"4,208.9","3,794.3",366,8.80%,192.5,241.7,-19.5,46.2,-90.2,-2.7,270.4,8 +Rajesh Exports Ltd.,RAJESHEXPO,531500,TEXTILES APPARELS & ACCESSORIES,GEMS & JEWELLERY,"38,079.4","38,015.8",50.1,0.13%,10.7,0,53,7.7,45.3,1.5,"1,142.2",38.7 +Rallis India Ltd.,RALLIS,500355,CHEMICALS & PETROCHEMICALS,AGROCHEMICALS,837,699,133,15.99%,26,3,110,28,82,4.2,98.4,5.2 +Rashtriya Chemicals & Fertilizers Ltd.,RCF,524230,FERTILIZERS,FERTILIZERS,"4,222.1","4,049.3",105.9,2.55%,56.1,44,72.8,21.1,51,0.9,523.6,9.5 +Redington Ltd.,REDINGTON,532805,COMMERCIAL SERVICES & SUPPLIES,COMMODITY TRADING & DISTRIBUTION,"22,296.6","21,738.7",481.4,2.17%,43.7,105.8,408.3,96.7,303.5,3.9,"1,242",15.9 +Relaxo Footwears Ltd.,RELAXO,530517,RETAILING,FOOTWEAR,725.9,623.8,91.5,12.79%,36.9,4.7,60.4,16.2,44.2,1.8,193.9,7.8 +Reliance Industries Ltd.,RELIANCE,500325,OIL & GAS,REFINERIES/PETRO-PRODUCTS,"238,797","193,988","40,968",17.44%,"12,585","5,731","26,493","6,673","17,394",25.7,"68,496",101.2 +REC Ltd.,RECLTD,532955,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"11,701.3",275.1,"12,180.5",104.21%,6.1,"7,349.8","4,837.6","1,047.7","3,789.9",14.4,"12,738.6",48.4 +SJVN Ltd.,SJVN,533206,UTILITIES,ELECTRIC UTILITIES,951.6,172.2,706.2,80.40%,101.9,124.2,567.7,129.2,439.6,1.1,"1,016",2.6 +SKF India Ltd.,SKFINDIA,500472,GENERAL INDUSTRIALS,OTHER INDUSTRIAL GOODS,"1,145.5","1,003.7",121.5,10.80%,19.3,0.5,122,31.7,90,18.2,484,97.9 +SRF Ltd.,SRF,503806,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,"3,206.5","2,551.2",626.2,19.71%,161.2,79.3,414.8,114,300.8,10.2,"1,733.4",58.5 +Sanofi India Ltd.,SANOFI,500674,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,726.4,506.1,208.5,29.17%,9.9,0.3,210.1,57.9,152.1,66.1,596.3,259.3 +Schaeffler India Ltd.,SCHAEFFLER,505790,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,879.2","1,506.3",342,18.50%,55.6,1.6,315.7,80.7,235,15,922.6,59 +Shree Cements Ltd.,SHREECEM,500387,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"4,932.1","3,914.1",886,18.46%,411.7,67,539.2,92.6,446.6,123.8,"1,826.8",506.3 +Shriram Finance Ltd.,SHRIRAMFIN,511218,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"8,893","1,409.4","6,334.3",71.30%,141.4,"3,798","2,404.2",614.9,"1,786.1",47.6,"6,575.4",175.2 +Siemens Ltd.,SIEMENS,500550,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"5,953.2","5,107.5",700.2,12.06%,78.6,4.9,762.2,190.5,571.3,16.1,"1,960.9",55.1 +Sobha Ltd.,SOBHA,532784,REALTY,REALTY,773.6,665.8,75.4,10.18%,19.3,63.9,24.7,9.7,14.9,1.6,107.4,11.3 +Solar Industries India Ltd.,SOLARINDS,532725,GENERAL INDUSTRIALS,OTHER INDUSTRIAL PRODUCTS,"1,355.2","1,011.3",336.1,24.95%,33.7,24.9,285.3,75.5,200.1,22.1,808.2,89.3 +Sonata Software Ltd.,SONATSOFTW,532221,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"1,935.8","1,715.2",197.3,10.32%,33.3,20.7,166.5,42.3,124.2,9,475.7,34.3 +State Bank of India,SBIN,500112,BANKING AND FINANCE,BANKS,"144,256.1","58,597.6","22,703.3",21.14%,0,"62,955.2","21,935.7","5,552.5","17,196.2",18,"69,304.1",77.7 +Steel Authority of India (SAIL) Ltd.,SAIL,500113,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"29,858.2","25,836.7","3,875.4",13.04%,"1,326.6",605.2,"1,674.7",464.2,"1,305.6",3.2,"3,219.5",7.8 +Sun Pharma Advanced Research Company Ltd.,SPARC,532872,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,29.7,112.7,-91.5,-431.87%,3.2,0.3,-86.4,0,-86.4,-2.7,-253.6,-7.8 +Sun Pharmaceutical Industries Ltd.,SUNPHARMA,524715,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"12,486","9,013","3,179.4",26.08%,632.8,49.3,"2,790.9",390.1,"2,375.5",9.9,"8,548.5",35.6 +Sun TV Network Ltd.,SUNTV,532733,MEDIA,BROADCASTING & CABLE TV,"1,160.2",320.6,727.8,69.42%,218.8,1.7,619.1,154.4,464.7,11.8,"1,861.8",47.2 +Sundram Fasteners Ltd.,SUNDRMFAST,500403,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,429.1","1,191.1",230.7,16.23%,54.5,7.4,176.2,43.1,131.9,6.3,502.9,23.9 +Sunteck Realty Ltd.,SUNTECK,512179,REALTY,REALTY,36.2,39.1,-14.1,-56.70%,2.2,15.8,-20.9,-6.4,-13.9,-1,-46.5,-3.3 +Supreme Industries Ltd.,SUPREMEIND,509930,GENERAL INDUSTRIALS,PLASTIC PRODUCTS,"2,321.4","1,952.5",356.2,15.43%,71.9,1.6,295.4,76.3,243.2,19.1,"1,028.2",80.9 +Suzlon Energy Ltd.,SUZLON,ASM,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"1,428.7","1,196.4",225,15.83%,51.2,43.7,102.4,0.1,102.3,0.1,561.4,0.4 +Syngene International Ltd.,SYNGENE,539268,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,931.7,656,254.1,27.92%,104.6,13,150.7,34.2,116.5,2.9,498.3,12.4 +TTK Prestige Ltd.,TTKPRESTIG,517506,CONSUMER DURABLES,HOUSEWARE,747.2,648.6,80.8,11.08%,15.9,3.1,79.5,20.5,59.3,4.3,224.3,16.2 +TV18 Broadcast Ltd.,TV18BRDCST,532800,MEDIA,BROADCASTING & CABLE TV,"1,989","1,992.2",-198.1,-11.04%,50.1,33.8,-87.1,-6.5,-28.9,-0.2,92.2,0.5 +TVS Motor Company Ltd.,TVSMOTOR,532343,AUTOMOBILES & AUTO COMPONENTS,2/3 WHEELERS,"9,983.8","8,576.9","1,355.9",13.65%,237.1,483.3,686.4,259.8,386.3,8.1,"1,457.6",30.7 +Tata Consultancy Services Ltd.,TCS,532540,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"60,698","43,946","15,746",26.38%,"1,263",159,"15,33","3,95","11,342",31,"44,654",122 +Tata Elxsi Ltd.,TATAELXSI,500408,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,912.8,618.2,263.5,29.89%,25,5.8,263.9,63.8,200,32.1,785.1,126.1 +Tata Consumer Products Ltd.,TATACONSUM,500800,FMCG,PACKAGED FOODS,"3,823.6","3,196.7",537.1,14.38%,93.9,27.6,490.9,131.7,338.2,3.6,"1,275.2",13.7 +Tata Motors Limited (DVR),TATAMTRDVR,570001,AUTOMOBILES & AUTO COMPONENTS,COMMERCIAL VEHICLES,,,,,,,,,,,, +Tata Motors Ltd.,TATAMOTORS,500570,AUTOMOBILES & AUTO COMPONENTS,COMMERCIAL VEHICLES,"106,759","91,361.3","13,766.9",13.10%,"6,636.4","2,651.7","5,985.9","2,202.8","3,764",9.8,"15,332.3",40 +Tata Power Company Ltd.,TATAPOWER,500400,UTILITIES,ELECTRIC UTILITIES,"16,029.5","12,647","3,091",19.64%,925.9,"1,181.8",979.2,213.3,875.5,2.7,"3,570.8",11.2 +Tata Steel Ltd.,TATASTEEL,500470,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"55,910.2","51,414.1","4,267.8",7.66%,"2,479.8","1,959.4","-6,842.1",-228,"-6,196.2",-5.1,"-6,081.3",-5 +Tech Mahindra Ltd.,TECHM,532755,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"13,128.1","11,941.1",922.8,7.17%,465.7,97.5,623.8,110,493.9,5.6,"3,600.7",40.9 +The Ramco Cements Ltd.,RAMCOCEM,500260,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"2,352.1","1,935",405.6,17.33%,162.8,116.5,137.8,37,72,3.1,348.9,14.8 +Thermax Ltd.,THERMAX,500411,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"2,368.3","2,097.8",204.6,8.89%,33,19.8,217.7,58.9,157.7,14,498.8,44.3 +Timken India Ltd.,TIMKEN,522113,GENERAL INDUSTRIALS,OTHER INDUSTRIAL PRODUCTS,692.1,546.5,135.5,19.87%,21.1,0.9,123.6,30.6,93,12.4,358.3,47.6 +Titan Company Ltd.,TITAN,500114,TEXTILES APPARELS & ACCESSORIES,GEMS & JEWELLERY,"12,653","11,118","1,411",11.26%,144,140,"1,251",336,915,10.3,"3,302",37.1 +Torrent Pharmaceuticals Ltd.,TORNTPHARM,500420,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"2,686","1,835",825,31.02%,201,91,559,173,386,11.4,"1,334",39.4 +Torrent Power Ltd.,TORNTPOWER,532779,UTILITIES,ELECTRIC UTILITIES,"7,069.1","5,739.5","1,221.4",17.55%,341.7,247.2,740.7,198.1,525.9,10.9,"2,176.8",45.3 +Trent Ltd.,TRENT,500251,RETAILING,DEPARTMENT STORES,"3,062.5","2,525.8",456.6,15.31%,152.2,95.5,288.9,86.3,234.7,6.6,629.4,17.7 +Trident Ltd.,TRIDENT,521064,TEXTILES APPARELS & ACCESSORIES,TEXTILES,"1,812","1,557.3",240.3,13.37%,89.4,35,130.4,40.1,90.7,0.2,458.1,0.9 +UPL Ltd.,UPL,512070,CHEMICALS & PETROCHEMICALS,AGROCHEMICALS,"10,275","8,807","1,325",13.03%,657,871,-185,-96,-189,-2.5,"1,856",24.7 +UltraTech Cement Ltd.,ULTRACEMCO,532538,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"16,179.3","13,461.2","2,550.9",15.93%,797.8,233.9,"1,686.2",409.4,"1,281.5",44.5,"5,694.1",197.2 +Union Bank of India,UNIONBANK,532477,BANKING AND FINANCE,BANKS,"28,952.5","6,189.3","7,265",29.38%,0,"15,498.2","5,492.3","1,944","3,571.8",5.1,"11,918.9",16.1 +United Breweries Ltd.,UBL,532478,FOOD BEVERAGES & TOBACCO,BREWERIES & DISTILLERIES,"1,902.1","1,705.8",184.3,9.75%,50.9,1.4,144,36.9,107.3,4.1,251.3,9.5 +United Spirits Ltd.,MCDOWELL-N,532432,FOOD BEVERAGES & TOBACCO,BREWERIES & DISTILLERIES,"6,776.6","6,269.8",466.7,6.93%,65.3,26.2,446,106.3,339.3,4.8,"1,133",15.6 +V-Guard Industries Ltd.,VGUARD,532953,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,"1,147.9","1,041.3",92.5,8.16%,19.8,9.3,77.5,18.6,59,1.4,215.2,5 +Vardhman Textiles Ltd.,VTL,502986,TEXTILES APPARELS & ACCESSORIES,TEXTILES,"2,487","2,192.1",205.4,8.57%,103.7,22,169.2,41.7,134.3,4.7,531.9,18.7 +Varun Beverages Ltd.,VBL,540180,FOOD BEVERAGES & TOBACCO,NON-ALCOHOLIC BEVERAGES,"3,889","2,988.4",882.1,22.79%,170.8,62.5,667.3,152.9,501.1,3.9,"1,998.7",15.4 +Vinati Organics Ltd.,VINATIORGA,524200,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,464.4,337.3,110.8,24.73%,13.7,0.3,113,28.9,84.2,8.2,408.2,39.7 +Voltas Ltd.,VOLTAS,500575,CONSUMER DURABLES,CONSUMER ELECTRONICS,"2,363.7","2,222.5",70.3,3.06%,11.7,11.4,118.1,49.3,36.7,1.1,199.5,6 +ZF Commercial Vehicle Control Systems India Ltd.,ZFCVINDIA,533023,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,015.8",846.2,145.5,14.67%,27.1,1.3,141.2,35.5,105.7,55.7,392,206.7 +Welspun Corp Ltd.,WELCORP,ASM,METALS & MINING,IRON & STEEL PRODUCTS,"4,161.4","3,659.9",399.5,9.84%,85.7,75,340.8,79,384.7,14.7,809.2,30.9 +Welspun Living Ltd.,WELSPUNLIV,514162,TEXTILES APPARELS & ACCESSORIES,TEXTILES,"2,542.4","2,151.1",358,14.27%,98.5,33.8,258.9,58.7,196.7,2,526.1,5.4 +Whirlpool of India Ltd.,WHIRLPOOL,500238,CONSUMER DURABLES,CONSUMER ELECTRONICS,"1,555.5","1,448.4",73.2,4.81%,49.2,5.6,52.3,14.1,36.6,2.9,198.8,15.7 +Wipro Ltd.,WIPRO,507685,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"23,255.7","18,543.2","3,972.7",17.64%,897,303.3,"3,512.2",841.9,"2,646.3",5.1,"11,643.8",22.3 +Zee Entertainment Enterprises Ltd.,ZEEL,505537,MEDIA,BROADCASTING & CABLE TV,"2,509.6","2,105",332.8,13.65%,77.2,23.4,184.2,54.4,123,1.3,-102.2,-1.1 +eClerx Services Ltd.,ECLERX,532927,SOFTWARE & SERVICES,BPO/KPO,735.9,517,204.7,28.37%,30.3,6.1,182.4,46.3,136,28.2,506,105 +Sterlite Technologies Ltd.,STLTECH,532374,TELECOMMUNICATIONS EQUIPMENT,TELECOM CABLES,"1,497","1,281",213,14.26%,85,95,36,12,34,0.9,203,5.1 +HEG Ltd.,HEG,509631,GENERAL INDUSTRIALS,OTHER INDUSTRIAL GOODS,642.2,512.3,101.9,16.58%,38.5,8.5,82.9,21.7,96,24.9,439.5,113.9 +SBI Life Insurance Company Ltd.,SBILIFE,540719,BANKING AND FINANCE,LIFE INSURANCE,"28,816.2","28,183.8",609.9,2.12%,0,0,621.5,43.9,380.2,3.8,"1,842.2",18.4 +General Insurance Corporation of India,GICRE,540755,BANKING AND FINANCE,GENERAL INSURANCE,"13,465.9","11,574","1,464.6",11.20%,0,0,"1,855.4",243.7,"1,689",15.2,"6,628",37.8 +Tube Investments of India Ltd.,TIINDIA,540762,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"2,005.4","1,718.2",251.4,12.76%,34.6,7.7,244.8,63.4,181.4,9.4,717.5,37.1 +Honeywell Automation India Ltd.,HONAUT,517174,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,"1,144.3",965.9,138.3,12.52%,13.8,0.7,163.9,42,121.9,137.8,443.4,503.9 +Indian Energy Exchange Ltd.,IEX,540750,BANKING AND FINANCE,EXCHANGE,133,16.6,92,84.73%,5.1,0.7,110.6,27.9,86.5,1,327.8,3.7 +ICICI Lombard General Insurance Company Ltd.,ICICIGI,540716,BANKING AND FINANCE,GENERAL INSURANCE,"5,271.1","4,612.4",743.5,14.16%,0,0,763.6,186.4,577.3,11.8,"1,757.1",35.8 +Aster DM Healthcare Ltd.,ASTERDM,540975,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,"3,325.2","2,939.4",377.3,11.38%,227.2,101.9,2.1,10.2,-30.8,-0.6,284.3,5.7 +Central Depository Services (India) Ltd.,CDSL,CDSL,OTHERS,INVESTMENT COMPANIES,230.1,77.9,129.4,62.40%,6.5,0,145.6,35.8,108.9,10.4,320.2,30.6 +Graphite India Ltd.,GRAPHITE,509488,GENERAL INDUSTRIALS,OTHER INDUSTRIAL GOODS,884,823,-30,-3.78%,19,4,992,190,804,41.1,856,43.9 +Grasim Industries Ltd.,GRASIM,500300,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"30,505.3","25,995.9","4,224.8",13.98%,"1,245.2",397.8,"2,866.4",837.7,"1,163.8",17.7,"6,624.9",100.6 +KNR Constructions Ltd.,KNRCON,532942,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,"1,043.8",806.9,231.6,22.30%,39.2,20.6,177.1,34.6,147.4,5.2,537.5,19.1 +Aditya Birla Capital Ltd.,ABCAPITAL,540691,DIVERSIFIED,HOLDING COMPANIES,"7,730.4","4,550.1","2,821.9",36.55%,48,"1,827",956.8,284.1,705,2.7,"5,231.9",20.1 +Dixon Technologies (India) Ltd.,DIXON,540699,CONSUMER DURABLES,CONSUMER ELECTRONICS,"4,943.9","4,744.3",198.9,4.02%,36.4,17.1,146.1,35.2,107.3,19,308.7,51.8 +Cholamandalam Financial Holdings Ltd.,CHOLAHLDNG,504973,DIVERSIFIED,HOLDING COMPANIES,"6,372.2","2,495.1","3,404.8",54.05%,52.1,"2,209.4","1,215.8",324.6,420.9,22.4,"1,532.3",81.6 +Cochin Shipyard Ltd.,COCHINSHIP,540678,TRANSPORTATION,MARINE PORT & SERVICES,"1,100.4",820.5,191.2,18.90%,18.9,9.6,251.4,69.9,181.5,13.8,429.9,32.7 +Bharat Dynamics Ltd.,BDL,541143,GENERAL INDUSTRIALS,DEFENCE,694.1,481.8,134,21.77%,17.4,0.8,194.1,47,147.1,8,425.4,23.2 +Lux Industries Ltd.,LUXIND,539542,TEXTILES APPARELS & ACCESSORIES,OTHER APPARELS & ACCESSORIES,643.6,584.2,55,8.61%,5.9,5.4,48,12.1,37.1,12.3,103.1,32.9 +Zensar Technologies Ltd.,ZENSARTECH,504067,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"1,277.1","1,009.9",230.9,18.61%,36.6,5.7,224.9,51,173.9,7.7,525.8,23.2 +PCBL Ltd.,PCBL,506590,CHEMICALS & PETROCHEMICALS,CARBON BLACK,"1,489.4","1,248.6",238.1,16.02%,48.2,21,171.6,48.8,122.6,3.2,431.6,11.4 +Zydus Wellness Ltd.,ZYDUSWELL,531335,FMCG,PACKAGED FOODS,444,423.1,16.8,3.82%,5.8,6.5,8.6,2.7,5.9,0.9,281.2,44.2 +Linde India Ltd.,LINDEINDIA,523457,GENERAL INDUSTRIALS,INDUSTRIAL GASES,729.9,537.7,173.6,24.41%,49.7,1.2,141.3,34.6,108.7,12.8,417.9,49 +FDC Ltd.,FDC,531599,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,513.6,409.9,76.4,15.71%,9.9,1.1,92.7,22.9,69.8,4.2,251.2,15.4 +The New India Assurance Company Ltd.,NIACL,540769,BANKING AND FINANCE,GENERAL INSURANCE,"10,571","10,773.4",-246.5,-2.33%,0,0,-242,-46.7,-176.1,-1.1,947,5.7 +Sundaram Finance Ltd.,SUNDARMFIN,590071,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"1,710.6",322.5,"1,332.1",77.98%,43.6,820.3,470.6,142.8,365.4,33.2,"1,506.7",135.6 +TeamLease Services Ltd.,TEAMLEASE,539658,COMMERCIAL SERVICES & SUPPLIES,MISC. COMMERCIAL SERVICES,"2,285.6","2,240.8",31.8,1.40%,12.9,2.5,29.4,1.8,27.3,16.3,106.6,63.5 +Galaxy Surfactants Ltd.,GALAXYSURF,540935,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,985.8,858.2,124.9,12.70%,24.7,5.4,97.5,20.1,77.4,21.8,349.3,98.5 +Bandhan Bank Ltd.,BANDHANBNK,541153,BANKING AND FINANCE,BANKS,"5,032.2","1,400.2","1,583.4",35.25%,0,"2,048.6",947.2,226.1,721.2,4.5,"2,541.1",15.8 +ICICI Securities Ltd.,ISEC,541179,BANKING AND FINANCE,CAPITAL MARKETS,"1,249",433.5,810.2,64.87%,25.8,215.1,569.4,145.7,423.6,13.1,"1,238.1",38.3 +V-Mart Retail Ltd.,VMART,534976,RETAILING,DEPARTMENT STORES,551.4,548.8,0.7,0.12%,53.2,35.9,-86.4,-22.3,-64.1,-32.4,-103.1,-52.1 +Nippon Life India Asset Management Ltd.,NAM-INDIA,540767,BANKING AND FINANCE,ASSET MANAGEMENT COS.,475.4,156.1,241.4,60.73%,7.2,1.7,310.4,66.1,244.4,3.9,883.3,14.1 +Grindwell Norton Ltd.,GRINDWELL,506076,GENERAL INDUSTRIALS,OTHER INDUSTRIAL PRODUCTS,690,536,131.4,19.69%,16.9,1.8,135.3,33.1,101.9,9.2,378.3,34.2 +HDFC Life Insurance Company Ltd.,HDFCLIFE,540777,BANKING AND FINANCE,LIFE INSURANCE,"23,276.6","23,659.3",-508.1,-2.20%,0,0,-373.1,-657.5,378.2,1.8,"1,472.8",6.9 +Elgi Equipments Ltd.,ELGIEQUIP,522074,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,817.8,663.4,142.7,17.71%,18.7,6.6,129.2,38.8,91.3,2.9,401.9,12.7 +Hindustan Aeronautics Ltd.,HAL,541154,GENERAL INDUSTRIALS,DEFENCE,"6,105.1","4,108.1","1,527.6",27.11%,349.6,0.3,"1,647",414.8,"1,236.7",18.5,"6,037.3",90.3 +BSE Ltd.,BSE,BSE,BANKING AND FINANCE,EXCHANGE,367,172.8,189.2,52.26%,22.7,8.5,163,63.6,120.5,8.8,706,52.1 +Rites Ltd.,RITES,541556,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,608.8,444.5,137.8,23.67%,14.1,1.4,148.8,40.1,101.2,4.2,488.1,20.3 +Fortis Healthcare Ltd.,FORTIS,532843,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,"1,783.5","1,439.8",330.2,18.65%,84.1,31.8,231.4,48.8,173.7,2.3,547.6,7.3 +Varroc Engineering Ltd.,VARROC,541578,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,893.5","1,692.6",194.3,10.30%,84.9,50.3,65.9,18.2,54.2,3.5,146.5,9.6 +Adani Green Energy Ltd.,ADANIGREEN,ASM,UTILITIES,ELECTRIC UTILITIES,"2,589",521,"1,699",76.53%,474,"1,165",413,119,372,2.2,"1,305",8.2 +VIP Industries Ltd.,VIPIND,507880,TEXTILES APPARELS & ACCESSORIES,OTHER APPARELS & ACCESSORIES,548.7,493.2,52.9,9.68%,23.8,12.4,19.3,6,13.3,0.9,110.9,7.8 +CreditAccess Grameen Ltd.,CREDITACC,541770,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"1,247.6",248.8,902.3,72.36%,12.3,423.9,466.8,119.7,347,21.8,"1,204.2",75.7 +CESC Ltd.,CESC,500084,UTILITIES,ELECTRIC UTILITIES,"4,414","3,706",646,14.84%,303,305,461,98,348,2.6,"1,447",10.9 +Jamna Auto Industries Ltd.,JAMNAAUTO,520051,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,608.7,528.2,79.1,13.03%,10.9,0.8,68.7,18.6,50.1,2.4,189.3,4.7 +Suprajit Engineering Ltd.,SUPRAJIT,532509,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,727.6,639.1,69.8,9.85%,25.7,13.6,49.2,14.5,34.8,2.5,146.9,10.6 +JK Paper Ltd.,JKPAPER,532162,COMMERCIAL SERVICES & SUPPLIES,PAPER & PAPER PRODUCTS,"1,708.8","1,242.8",407.3,24.68%,83.5,42,340.6,34.9,302.4,17.9,"1,220.6",72.1 +Bank of Maharashtra,MAHABANK,532525,BANKING AND FINANCE,BANKS,"5,735.5","1,179.4","1,920.5",37.90%,0,"2,635.7",935.7,16,919.8,1.3,"3,420.8",4.8 +Aavas Financiers Ltd.,AAVAS,541988,BANKING AND FINANCE,HOUSING FINANCE,497.6,123.5,367.8,74.03%,7.6,203.6,157.4,35.7,121.7,15.4,465.4,58.8 +HDFC Asset Management Company Ltd.,HDFCAMC,541729,BANKING AND FINANCE,ASSET MANAGEMENT COS.,765.4,162,481.1,74.81%,13,2.3,588.1,151.6,436.5,20.4,"1,659.3",77.7 +KEI Industries Ltd.,KEI,517569,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,"1,954.2","1,742.7",203.9,10.47%,15.6,7.5,188.4,48.2,140.2,15.5,528.3,58.5 +Orient Electric Ltd.,ORIENTELEC,541301,CONSUMER DURABLES,CONSUMER ELECTRONICS,570.3,546.2,20.7,3.65%,14.2,5.2,23.4,4.9,18.4,0.9,95.3,4.5 +Deepak Nitrite Ltd.,DEEPAKNTR,506401,CHEMICALS & PETROCHEMICALS,COMMODITY CHEMICALS,"1,795.1","1,475.8",302.3,17.00%,39.4,2.7,277.2,72.1,205.1,15,797.9,58.5 +Fine Organic Industries Ltd.,FINEORG,541557,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,557.6,409.4,131.1,24.25%,14.4,0.7,133.1,28.9,103.4,33.7,458.8,149.6 +LTIMindtree Ltd.,LTIM,540005,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"9,048.6","7,274.1","1,631.3",18.32%,208.2,47,"1,519.3",357,"1,161.8",39.3,"4,427.5",149.6 +Dalmia Bharat Ltd.,DALBHARAT,542216,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"3,234","2,56",589,18.70%,401,101,172,48,118,6.3,"1,041",54.8 +Godfrey Phillips India Ltd.,GODFRYPHLP,500163,FOOD BEVERAGES & TOBACCO,CIGARETTES-TOBACCO PRODUCTS,"1,412.5","1,151",223.6,16.27%,36.5,6.6,218.5,55.5,202.1,38.9,802.9,154.4 +Vaibhav Global Ltd.,VAIBHAVGBL,532156,TEXTILES APPARELS & ACCESSORIES,OTHER APPARELS & ACCESSORIES,708.4,641.5,63.5,9.01%,22.6,2.9,41.4,12.4,29.4,1.8,121.3,7.3 +Abbott India Ltd.,ABBOTINDIA,500488,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,549.7","1,113.3",380.9,25.49%,17.8,3.1,415.4,102.5,312.9,147.3,"1,081.4",508.9 +Adani Total Gas Ltd.,ATGL,ASM,UTILITIES,UTILITIES,"1,104.8",815.7,279.9,25.55%,37.6,27.3,224.2,57.2,172.7,1.6,571,5.2 +Nestle India Ltd.,NESTLEIND,500790,FMCG,PACKAGED FOODS,"5,070.1","3,811.9","1,224.9",24.32%,111.2,31.4,"1,222",313.9,908.1,94.2,"2,971.1",308.2 +Bayer Cropscience Ltd.,BAYERCROP,506285,CHEMICALS & PETROCHEMICALS,AGROCHEMICALS,"1,633.3","1,312.3",304.9,18.85%,11.6,3.7,305.7,82.8,222.9,49.6,844.4,188.1 +Amber Enterprises India Ltd.,AMBER,540902,CONSUMER DURABLES,CONSUMER ELECTRONICS,939.8,867.5,59.6,6.43%,45.2,36.6,-9.5,-3.8,-6.9,-2.1,156.8,46.5 +Rail Vikas Nigam Ltd.,RVNL,542649,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,"5,210.3","4,616",298.3,6.07%,6.2,132.7,455.4,85.2,394.3,1.9,"1,478.8",7.1 +Metropolis Healthcare Ltd.,METROPOLIS,542650,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE SERVICES,309.7,233.7,74.8,24.25%,22.2,5.7,48.1,12.5,35.5,6.9,133.4,26 +Polycab India Ltd.,POLYCAB,542652,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,"4,253","3,608.8",608.9,14.44%,60.3,26.8,557.2,127.4,425.6,28.4,"1,607.2",107.1 +Multi Commodity Exchange of India Ltd.,MCX,534091,BANKING AND FINANCE,EXCHANGE,184,193.8,-28.7,-17.38%,6.6,0.1,-16.4,1.6,-19.1,-3.7,44.8,8.8 +IIFL Finance Ltd.,IIFL,532636,BANKING AND FINANCE,OTHER FINANCIAL SERVICES,"2,533.7",788.3,"1,600.8",64.66%,43.3,932.1,683.5,158,474.3,12.4,"1,690.7",44.4 +Ratnamani Metals & Tubes Ltd.,RATNAMANI,520111,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"1,141.9",886.3,244.9,21.65%,23.6,10.8,221.1,56.8,163.9,23.4,622.6,88.8 +RHI Magnesita India Ltd.,RHIM,534076,GENERAL INDUSTRIALS,OTHER INDUSTRIAL GOODS,989.7,839,147.9,14.98%,44.2,8.5,97.9,26.3,71.3,3.5,-502.2,-24.3 +Birlasoft Ltd.,BSOFT,532400,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"1,325.4","1,102.7",207.1,15.81%,21.5,5.7,195.5,50.4,145.1,5.2,378.4,13.7 +EIH Ltd.,EIHOTEL,500840,HOTELS RESTAURANTS & TOURISM,HOTELS,552.5,387.6,142.9,26.94%,33.2,5.6,126.1,36.2,93.1,1.5,424.1,6.8 +Affle (India) Ltd.,AFFLE,542752,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,441.2,344.1,87.2,20.22%,18.4,5.5,73.2,6.4,66.8,5,264.3,19.8 +Westlife Foodworld Ltd.,WESTLIFE,505533,HOTELS RESTAURANTS & TOURISM,RESTAURANTS,618,516.5,98.2,15.98%,43.9,27.4,30.2,7.8,22.4,1.4,107.7,6.9 +IndiaMART InterMESH Ltd.,INDIAMART,542726,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,329.3,214.7,80,27.15%,8,2.3,104.3,23.9,69.4,11.4,321.1,53.6 +Infosys Ltd.,INFY,500209,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"39,626","29,554","9,44",24.21%,"1,166",138,"8,768","2,553","6,212",15,"24,871",60.1 +Sterling and Wilson Renewable Energy Ltd.,SWSOLAR,542760,COMMERCIAL SERVICES & SUPPLIES,CONSULTING SERVICES,776.7,758,1.5,0.19%,4.3,64.3,-50,4.6,-54.2,-2.9,-668.4,-35.2 +ABB India Ltd.,ABB,500002,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"2,846","2,330.7",438.5,15.84%,30.3,0.9,484.2,122.2,362.9,17.1,"1,208.7",57 +Poly Medicure Ltd.,POLYMED,531768,HEALTHCARE EQUIPMENT & SUPPLIES,HEALTHCARE SUPPLIES,351.4,253.1,84.2,24.97%,16,2.2,80.9,18.8,62.2,6.5,233.7,24.4 +GMM Pfaudler Ltd.,GMMPFAUDLR,505255,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,946,795.5,142,15.15%,32.2,21.5,96.8,26.5,71.1,15.8,183.2,40.8 +Gujarat Fluorochemicals Ltd.,FLUOROCHEM,542812,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,960.3,783.7,163.1,17.23%,67.5,34.2,74.8,22.1,52.7,4.8,915.2,83.3 +360 One Wam Ltd.,360ONE,542772,BANKING AND FINANCE,OTHER FINANCIAL SERVICES,617.1,235.6,317.8,57.31%,13.7,139.9,226.8,40.8,186,5.2,696.8,19.5 +Tata Communications Ltd.,TATACOMM,500483,TELECOM SERVICES,OTHER TELECOM SERVICES,"4,897.9","3,857.1","1,015.5",20.84%,605.1,137.4,298.3,77.9,220.7,7.7,"1,322.3",46.4 +Alkyl Amines Chemicals Ltd.,ALKYLAMINE,506767,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,354.5,303.9,48.3,13.71%,12.5,1.7,36.4,9.2,27.2,5.3,171.3,33.5 +CSB Bank Ltd.,CSBBANK,542867,BANKING AND FINANCE,BANKS,835.8,317.5,174.6,25.41%,0,343.6,178,44.8,133.2,7.7,577.7,33.3 +Indian Railway Catering & Tourism Corporation Ltd.,IRCTC,542830,DIVERSIFIED CONSUMER SERVICES,TRAVEL SUPPORT SERVICES,"1,042.4",628.8,366.6,36.83%,14,4.4,395.2,100.5,294.7,3.7,"1,061.2",13.3 +Sumitomo Chemical India Ltd.,SUMICHEM,542920,CHEMICALS & PETROCHEMICALS,AGROCHEMICALS,928,715.5,187.9,20.80%,15.8,1.2,195.5,52,143.4,2.9,367.7,7.4 +Century Textiles & Industries Ltd.,CENTURYTEX,500040,COMMERCIAL SERVICES & SUPPLIES,PAPER & PAPER PRODUCTS,"1,114.9","1,069.2",33.8,3.07%,59.2,17,-30.5,-3.3,-30.4,-2.8,117.7,10.5 +SBI Cards and Payment Services Ltd.,SBICARD,543066,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"4,221.4","2,018.8","1,327",32.47%,46.8,604.9,809.4,206.4,603,6.4,"2,302.2",24.3 +Hitachi Energy India Ltd.,POWERINDIA,543187,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"1,228.2","1,162.6",65.3,5.32%,22.5,10.7,32.4,7.6,24.7,5.8,82.5,19.5 +Suven Pharmaceuticals Ltd.,SUVENPHAR,543064,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,250.9,133.1,98,42.40%,11.9,0.5,105.4,25.8,79.6,3.1,431.8,17 +Tata Chemicals Ltd.,TATACHEM,500770,CHEMICALS & PETROCHEMICALS,COMMODITY CHEMICALS,"4,083","3,179",819,20.49%,234,145,627,120,428,16.8,"2,06",80.8 +Aarti Drugs Ltd.,AARTIDRUGS,524348,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,642.2,565.1,76.4,11.92%,12.6,8.2,56.3,16.7,39.6,4.3,180.2,19.6 +Gujarat Ambuja Exports Ltd.,GAEL,524226,FMCG,EDIBLE OILS,"1,157.7","1,012.2",103.3,9.26%,30.5,5.9,109.1,26.3,82.8,3.6,305.1,13.3 +Polyplex Corporation Ltd.,POLYPLEX,524051,COMMERCIAL SERVICES & SUPPLIES,CONTAINERS & PACKAGING,"1,595.7","1,451.5",120.6,7.67%,75.1,9.9,59.1,10.9,27.9,8.9,71.1,22.6 +Chalet Hotels Ltd.,CHALET,542399,HOTELS RESTAURANTS & TOURISM,HOTELS,318.2,188.6,126,40.04%,35,50.1,44.5,8,36.4,1.8,266.7,13 +Adani Enterprises Ltd.,ADANIENT,512599,COMMERCIAL SERVICES & SUPPLIES,COMMODITY TRADING & DISTRIBUTION,"23,066","20,087.2","2,430.1",10.79%,757,"1,342.8",791,397.8,227.8,2,"2,444.3",21.4 +YES Bank Ltd.,YESBANK,532648,BANKING AND FINANCE,BANKS,"7,980.6","2,377.1",810,12.06%,0,"4,793.6",304.4,75.7,228.6,0.1,836.6,0.3 +EPL Ltd.,EPL,500135,COMMERCIAL SERVICES & SUPPLIES,CONTAINERS & PACKAGING,"1,011.2",820.6,181,18.07%,83.6,30.6,76.4,25.4,50.5,1.6,251.9,7.9 +Network18 Media & Investments Ltd.,NETWORK18,532798,MEDIA,BROADCASTING & CABLE TV,"2,052.2","2,083.8",-218.3,-11.70%,56.8,66.2,-154.5,-6.5,-61,-0.6,-144.2,-1.4 +CIE Automotive India Ltd.,CIEINDIA,532756,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"2,299.4","1,934",345.4,15.15%,78.3,31,256.1,69.1,375.4,9.9,298.4,7.9 +Vedanta Ltd.,VEDL,500295,METALS & MINING,ALUMINIUM AND ALUMINIUM PRODUCTS,"39,585","27,466","11,479",29.47%,"2,642","2,523","8,177","9,092","-1,783",-4.8,"5,202",14 +Rossari Biotech Ltd.,ROSSARI,543213,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,484.8,419.9,63.6,13.15%,15.1,5,44.8,11.9,32.9,6,116.8,21.2 +KPIT Technologies Ltd.,KPITTECH,542651,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,"1,208.6",959.2,239.9,20.01%,48.1,13.6,187.7,46.3,140.9,5.2,486.9,18 +Intellect Design Arena Ltd.,INTELLECT,538835,SOFTWARE & SERVICES,IT SOFTWARE PRODUCTS,631.7,497.2,121.9,19.69%,33.7,0.8,96.5,25.7,70.4,5.2,316.6,23.2 +Balaji Amines Ltd.,BALAMINES,530999,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,387.3,326.8,53.8,14.13%,10.8,1.8,48,11.6,34.7,10.7,197.3,60.9 +UTI Asset Management Company Ltd.,UTIAMC,543238,BANKING AND FINANCE,ASSET MANAGEMENT COS.,405.6,172.5,231.5,57.30%,10.4,2.8,219.8,37,182.8,14.4,562.9,44.3 +Mazagon Dock Shipbuilders Ltd.,MAZDOCK,543237,TRANSPORTATION,SHIPPING,"2,079.2","1,651.1",176.6,9.66%,20.2,1.3,406.6,102.8,332.9,16.5,"1,327.6",65.8 +Computer Age Management Services Ltd.,CAMS,543232,BANKING AND FINANCE,CAPITAL MARKETS,284.7,153,122.1,44.39%,17.4,2,112.4,28.6,84.5,17.2,309.2,62.9 +Happiest Minds Technologies Ltd.,HAPPSTMNDS,543227,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,428.8,324,82.6,20.32%,14.6,11.2,79.1,20.7,58.5,3.9,232,15.6 +Triveni Turbine Ltd.,TRITURBINE,533655,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,402.3,313.4,74.3,19.17%,5.1,0.6,83.2,19,64.2,2,233.1,7.3 +Angel One Ltd.,ANGELONE,ASM,BANKING AND FINANCE,CAPITAL MARKETS,"1,049.3",602.6,443.4,42.31%,11.2,26.4,407.2,102.7,304.5,36.3,"1,020.2",121.7 +Tanla Platforms Ltd.,TANLA,532790,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,"1,014.9",811.8,196.8,19.51%,22.6,1.8,178.7,36.2,142.5,10.6,514.7,38.3 +Max Healthcare Institute Ltd.,MAXHEALTH,543220,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,"1,408.6",975.8,387.4,28.42%,57.9,8.5,366.4,89.7,276.7,2.9,990.1,10.2 +Asahi India Glass Ltd.,ASAHIINDIA,515030,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,122.6",934,185.6,16.58%,43,34.4,111.3,30.2,86.9,3.6,343.5,14.1 +Prince Pipes & Fittings Ltd.,PRINCEPIPE,542907,GENERAL INDUSTRIALS,PLASTIC PRODUCTS,660.4,562.3,94.2,14.35%,22.5,0.7,92.8,22.2,70.6,5.2,219.8,19.9 +Route Mobile Ltd.,ROUTE,543228,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,"1,018.3",886.5,128.1,12.63%,21.4,6.5,103.8,15.5,88.8,14.2,365.3,58.3 +KPR Mill Ltd.,KPRMILL,532889,TEXTILES APPARELS & ACCESSORIES,TEXTILES,"1,533","1,212.9",298,19.72%,46,18.1,256,54.2,201.8,5.9,788.8,23.1 +Infibeam Avenues Ltd.,INFIBEAM,539807,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,792.6,719.7,70.2,8.89%,17.1,0.5,55.2,14.7,41,0.1,142.2,0.5 +Restaurant Brands Asia Ltd.,RBA,543248,HOTELS RESTAURANTS & TOURISM,RESTAURANTS,628.2,568.7,56.2,9.00%,78.6,31.5,-50.7,0,-46,-0.9,-220.3,-4.5 +Larsen & Toubro Ltd.,LT,500510,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,"52,157","45,392.1","5,632",11.04%,909.9,864,"4,991.1","1,135.5","3,222.6",22.9,"12,255.3",89.2 +Gland Pharma Ltd.,GLAND,543245,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,426.6","1,049.3",324.1,23.60%,81.3,6,289.9,95.8,194.1,11.8,698.8,42.4 +Macrotech Developers Ltd.,LODHA,543287,REALTY,REALTY,"1,755.1","1,333.5",416.1,23.78%,29.3,123.1,269.2,62.4,201.9,2.1,"1,529.2",15.9 +Poonawalla Fincorp Ltd.,POONAWALLA,524000,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),745.3,178.9,531.7,71.98%,14.7,215.5,"1,124.6",270,860.2,11.2,"1,466.4",19.1 +The Fertilisers and Chemicals Travancore Ltd.,FACT,590024,FERTILIZERS,FERTILIZERS,"1,713.6","1,530.8",132.4,7.96%,5.3,61.2,105.2,0,105.2,1.6,508.4,7.9 +Home First Finance Company India Ltd.,HOMEFIRST,543259,BANKING AND FINANCE,HOUSING FINANCE,278,53.7,211.6,77.43%,2.8,117,96.4,22.1,74.3,8.4,266.2,30.2 +CG Power and Industrial Solutions Ltd.,CGPOWER,500093,GENERAL INDUSTRIALS,HEAVY ELECTRICAL EQUIPMENT,"2,019","1,692.9",308.6,15.42%,22.9,0.4,329.9,86.2,242.3,1.6,"1,1",7.2 +Laxmi Organic Industries Ltd.,LXCHEM,543277,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,660.5,613.3,38.9,5.97%,27.5,2.1,17.5,6.8,10.7,0.4,100.6,3.8 +Anupam Rasayan India Ltd.,ANURAS,543275,CHEMICALS & PETROCHEMICALS,AGROCHEMICALS,395.6,284.7,107.5,27.41%,19.8,20.4,70.7,22,40.7,3.8,178.9,16.6 +Kalyan Jewellers India Ltd.,KALYANKJIL,ASM,TEXTILES APPARELS & ACCESSORIES,GEMS & JEWELLERY,"4,427.7","4,100.9",313.7,7.11%,66.9,81.7,178.1,43.3,135.2,1.3,497.9,4.8 +Jubilant Pharmova Ltd.,JUBLPHARMA,530019,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,690.2","1,438.5",241.8,14.39%,96.6,66.1,89,35.9,62.5,3.9,-44.6,-2.8 +Indigo Paints Ltd.,INDIGOPNTS,543258,DIVERSIFIED CONSUMER SERVICES,FURNITURE-FURNISHING-PAINTS,273.4,228.7,41.8,15.45%,10,0.5,34.3,8.2,26.1,5.5,132.4,27.8 +Indian Railway Finance Corporation Ltd.,IRFC,543257,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"6,767.5",33.5,"6,732.4",99.50%,2.1,"5,181.5","1,549.9",0,"1,549.9",1.2,"6,067.6",4.6 +Mastek Ltd.,MASTEK,523704,SOFTWARE & SERVICES,IT CONSULTING & SOFTWARE,770.4,642.5,123,16.07%,20.9,12.6,90.3,25,62.8,20.5,269.7,88 +Equitas Small Finance Bank Ltd.,EQUITASBNK,543243,BANKING AND FINANCE,BANKS,"1,540.4",616.8,330.2,24.30%,0,593.4,267,68.9,198.1,1.8,749.5,6.7 +Tata Teleservices (Maharashtra) Ltd.,TTML,532371,TELECOM SERVICES,TELECOM SERVICES,288.6,159.3,127.5,44.45%,36.3,403.2,-310.2,0,-310.2,-1.6,"-1,168.3",-6 +Praj Industries Ltd.,PRAJIND,522205,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,893.3,798.4,84,9.52%,9.1,1,84.8,22.4,62.4,3.4,271.4,14.8 +Nazara Technologies Ltd.,NAZARA,543280,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,309.5,269.4,26.7,8.98%,15.1,2.7,21.2,-1.3,19.8,3,60,9.1 +Jubilant Ingrevia Ltd.,JUBLINGREA,543271,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,"1,028.5",902.3,117.7,11.54%,33.9,12.5,79.8,22.4,57.5,3.6,258.9,16.4 +Sona BLW Precision Forgings Ltd.,SONACOMS,543300,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,796.9,567.5,223.3,28.24%,53.4,6,164.1,40.1,123.8,2.1,462.8,7.9 +Chemplast Sanmar Ltd.,CHEMPLASTS,543336,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,"1,025",941.8,46,4.65%,35.3,38.6,9.2,-16.8,26.1,1.6,35.3,2.2 +Aptus Value Housing Finance India Ltd.,APTUS,543335,BANKING AND FINANCE,HOUSING FINANCE,344.5,50.6,277.5,83.18%,2.6,96.1,189.6,41.5,148,3,551.1,11.1 +Clean Science & Technology Ltd.,CLEAN,543318,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,187.1,106.3,74.8,41.32%,11.1,0.3,69.5,17.3,52.2,4.9,275.5,25.9 +Medplus Health Services Ltd.,MEDPLUS,543427,HEALTHCARE EQUIPMENT & SUPPLIES,HEALTHCARE SUPPLIES,"1,419","1,323.5",85.1,6.04%,55.5,23.5,16.4,1.9,14.6,1.2,58.3,4.9 +Nuvoco Vistas Corporation Ltd.,NUVOCO,543334,CEMENT AND CONSTRUCTION,CEMENT & CEMENT PRODUCTS,"2,578.9","2,243",329.9,12.82%,225.6,139.9,-29.6,-31.1,1.5,0,141.8,4 +Star Health and Allied Insurance Company Ltd.,STARHEALTH,543412,BANKING AND FINANCE,GENERAL INSURANCE,"3,463.2","3,295.8",165.7,4.79%,0,0,167.1,41.8,125.3,2.1,725.4,12.4 +Go Fashion (India) Ltd.,GOCOLORS,543401,TEXTILES APPARELS & ACCESSORIES,OTHER APPARELS & ACCESSORIES,192.8,132.2,56.6,29.98%,25.8,8.9,25.8,5.7,20,3.7,85.4,15.8 +PB Fintech Ltd.,POLICYBZR,543390,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,909.1,900.7,-89.1,-10.98%,22.3,7.2,-21.1,-0.3,-20.2,-0.5,-127.9,-2.8 +FSN E-Commerce Ventures Ltd.,NYKAA,543384,SOFTWARE & SERVICES,INTERNET & CATALOGUE RETAIL,"1,515.6","1,426.4",80.6,5.35%,54.6,21.3,13.3,4,5.8,0,19.8,0.1 +Krishna Institute of Medical Sciences Ltd.,KIMS,543308,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,655.4,475.2,177.3,27.17%,32.6,8.9,138.6,37.3,92,11.5,342.1,42.7 +Zomato Ltd.,ZOMATO,543320,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,"3,06","2,895",-47,-1.65%,128,16,21,-15,36,0,-496.8,-0.6 +Brightcom Group Ltd.,BCG,532368,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,"1,690.5","1,172.3",518,30.65%,72.3,0.1,445.8,124.3,321.5,1.6,"1,415.2",7 +Shyam Metalics and Energy Ltd.,SHYAMMETL,543299,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"2,978.9","2,633.6",307.1,10.44%,176.5,35.4,133.4,-348.6,484.1,18.9,"1,049.9",41.2 +G R Infraprojects Ltd.,GRINFRA,543317,CEMENT AND CONSTRUCTION,ROADS & HIGHWAYS,"1,909.2","1,415.7",467.1,24.81%,61.7,144.6,287.1,69.9,217.2,22.5,"1,240.3",128.3 +RattanIndia Enterprises Ltd.,RTNINDIA,534597,UTILITIES,ELECTRIC UTILITIES,"1,618.1","1,392.8",1.5,0.11%,4.3,28.8,142.2,1.7,140.9,1,147.6,1.1 +Borosil Renewables Ltd.,BORORENEW,502219,CONSUMER DURABLES,HOUSEWARE,406.3,369.2,32.5,8.09%,31,9.6,28.9,-1.1,25.1,1.9,32.1,2.5 +HLE Glascoat Ltd.,HLEGLAS,522215,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,227.8,198,26.5,11.79%,6.1,5.8,16.1,5.3,10,1.6,54.4,8 +Tata Investment Corporation Ltd.,TATAINVEST,501301,DIVERSIFIED,HOLDING COMPANIES,125,10.1,113.8,91.88%,0.2,4.7,110.1,-1.3,124.4,24.6,326.1,64.4 +Sapphire Foods India Ltd.,SAPPHIRE,543397,HOTELS RESTAURANTS & TOURISM,RESTAURANTS,650.1,527.5,115.1,17.91%,76.8,24.5,21.4,6.2,15.3,2.4,208.5,32.7 +Devyani International Ltd.,DEVYANI,543330,HOTELS RESTAURANTS & TOURISM,RESTAURANTS,826,665,154.4,18.84%,86.3,41.7,19,-16.8,33.4,0.3,177.5,1.5 +Vijaya Diagnostic Centre Ltd.,VIJAYA,543350,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE SERVICES,145.6,81.5,57.4,41.31%,13.7,5.9,44.6,11,33.3,3.3,103.4,10.1 +C.E. Info Systems Ltd.,MAPMYINDIA,543425,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,99.3,50.1,41,44.98%,3.7,0.7,44.7,11.1,33,6.1,122.9,22.7 +Latent View Analytics Ltd.,LATENTVIEW,543398,SOFTWARE & SERVICES,DATA PROCESSING SERVICES,172.7,124.9,30.8,19.78%,2.3,0.8,44.7,10.6,34,1.7,153.6,7.5 +Metro Brands Ltd.,METROBRAND,543426,RETAILING,FOOTWEAR,571.9,400.3,155.4,27.96%,57.2,19.7,94.7,27.5,66.7,2.5,340,12.5 +Easy Trip Planners Ltd.,EASEMYTRIP,543272,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,144.6,76.9,64.8,45.71%,1,2,64.7,17.7,47.2,0.3,146,0.8 +Shree Renuka Sugars Ltd.,RENUKA,532670,FOOD BEVERAGES & TOBACCO,SUGAR,"2,564.7","2,491",63.7,2.49%,64.1,216.8,-207.2,-1.6,-204.9,-1,-286,-1.3 +One97 Communications Ltd.,PAYTM,543396,SOFTWARE & SERVICES,INTERNET SOFTWARE & SERVICES,"2,662.5","2,749.6",-231,-9.17%,180.1,7,-279.9,12.7,-290.5,-5,"-1,207.9",-19 +MTAR Technologies Ltd.,MTARTECH,543270,GENERAL INDUSTRIALS,DEFENCE,167.7,130.7,36.1,21.64%,5.8,5.5,25.7,5.2,20.5,6.7,103.3,33.6 +Capri Global Capital Ltd.,CGCL,531595,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),557.4,229.3,304.8,54.70%,23.1,195.8,86,20.8,65.2,3.2,231.2,11.2 +GMR Airports Infrastructure Ltd.,GMRINFRA,ASM,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,"2,185","1,336.8",726.7,35.22%,373,695.8,-252,54.9,-91,-0.1,-370.9,-0.6 +Triveni Engineering & Industries Ltd.,TRIVENI,532356,FOOD BEVERAGES & TOBACCO,SUGAR,"1,629.7","1,554.5",62.9,3.89%,25.8,10.2,39.3,10.1,29.1,1.3,434.3,19.8 +Delhivery Ltd.,DELHIVERY,543529,TRANSPORTATION,TRANSPORTATION - LOGISTICS,"2,043","1,957.3",-15.6,-0.80%,171.2,19.6,-105.2,-2.1,-102.9,-1.4,-546.7,-7.5 +Life Insurance Corporation of India,LICI,543526,BANKING AND FINANCE,LIFE INSURANCE,"202,394.9","193,612.5","8,445",4.18%,0,0,"8,696.5","1,083.9","8,030.3",12.7,"37,204.8",58.8 +Campus Activewear Ltd.,CAMPUS,543523,RETAILING,FOOTWEAR,259.1,234.2,24.5,9.46%,18.1,6.5,0.4,0.1,0.3,0,103.1,3.4 +Motherson Sumi Wiring India Ltd.,MSUMI,543498,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"2,110.2","1,856.5",248.1,11.79%,36.4,7.4,210,54.1,155.9,0.3,523.6,1.2 +Olectra Greentech Ltd.,OLECTRA,532439,AUTOMOBILES & AUTO COMPONENTS,COMMERCIAL VEHICLES,310.3,266.6,40.5,13.20%,8.8,9.7,25.2,8,18.6,2.2,78.5,9.6 +Patanjali Foods Ltd.,PATANJALI,500368,FMCG,EDIBLE OILS,"7,845.8","7,426.6",395.3,5.05%,60.1,24,335.1,80.5,254.5,7,875.2,24.2 +Raymond Ltd.,RAYMOND,500330,TEXTILES APPARELS & ACCESSORIES,TEXTILES,"2,320.7","1,938.8",314.6,13.96%,65.4,89.3,204.2,50.7,159.8,24,"1,514.2",227.5 +Swan Energy Ltd.,SWANENERGY,503310,REALTY,REALTY,"1,230.1",966.3,257,21.01%,27.1,58.3,178.4,12.8,84.6,6.7,308.4,11.7 +Samvardhana Motherson International Ltd.,MOTHERSON,517334,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"23,639.2","21,585","1,888.8",8.05%,867.4,487.9,449.5,229.2,201.6,0.3,"1,910.3",2.8 +Vedant Fashions Ltd.,MANYAVAR,543463,RETAILING,SPECIALTY RETAIL,233.4,125.5,92.8,42.51%,32.5,10.7,64.8,16.1,48.7,2,399.9,16.5 +Adani Wilmar Ltd.,AWL,543458,FMCG,EDIBLE OILS,"12,331.2","12,123.5",143.7,1.17%,95.7,220.2,-161.8,-31.5,-130.7,-1,130.1,1 +Mahindra Lifespace Developers Ltd.,MAHLIFE,532313,REALTY,REALTY,25.7,52.7,-34.9,-196.45%,3.1,0.2,-30.3,-10.8,-18.9,-1.2,10.5,0.7 +Tejas Networks Ltd.,TEJASNET,540595,TELECOM SERVICES,OTHER TELECOM SERVICES,413.9,383,13,3.28%,41.7,7,-17.7,-5.1,-12.6,-0.7,-61.3,-3.5 +Aether Industries Ltd.,AETHER,543534,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,178.3,118.2,46,28.00%,9.7,1.6,48.7,12.1,36.7,2.8,139.1,10.5 +JBM Auto Ltd.,JBMA,ASM,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,238.8","1,091.3",139.7,11.35%,41.2,47.9,58.3,11.3,44.2,3.7,136.8,11.6 +Deepak Fertilisers & Petrochemicals Corporation Ltd.,DEEPAKFERT,500645,CHEMICALS & PETROCHEMICALS,COMMODITY CHEMICALS,"2,443.2","2,138.1",286.1,11.80%,81.2,107.1,116.8,53.3,60.1,4.8,674.5,53.4 +Sharda Cropchem Ltd.,SHARDACROP,538666,CHEMICALS & PETROCHEMICALS,AGROCHEMICALS,604.3,559.6,21.2,3.65%,74,4.6,-33.8,-6.3,-27.6,-3.1,191,21.2 +Shoppers Stop Ltd.,SHOPERSTOP,532638,RETAILING,DEPARTMENT STORES,"1,049.7",878.2,160.9,15.49%,108.2,54.9,3.5,0.8,2.7,0.2,94.2,8.6 +BEML Ltd.,BEML,500048,AUTOMOBILES & AUTO COMPONENTS,COMMERCIAL VEHICLES,924,855.3,61.5,6.70%,15.8,10.8,42.2,-9.6,51.8,12.4,200.8,48.2 +Lemon Tree Hotels Ltd.,LEMONTREE,541233,HOTELS RESTAURANTS & TOURISM,HOTELS,230.1,125.3,101.9,44.84%,22.6,47.3,34.8,8.6,22.6,0.3,130.1,1.6 +Rainbow Childrens Medicare Ltd.,RAINBOW,543524,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,340.5,215.1,117.6,35.34%,26.8,13.3,85.2,22.1,62.9,6.2,215.4,21.2 +UCO Bank,UCOBANK,532505,BANKING AND FINANCE,BANKS,"5,865.6","1,581.5",981.9,18.81%,0,"3,302.3",639.8,238.1,403.5,0.3,"1,84",1.5 +Piramal Pharma Ltd.,PPLPHARMA,543635,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"1,960.6","1,645.7",265.6,13.90%,184.5,109.9,20.4,34.5,5,0,-133.6,-1 +KSB Ltd.,KSB,500249,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,572.2,493.4,70.3,12.47%,12.3,2,64.5,17.1,50.1,14.4,209.7,60.3 +Data Patterns (India) Ltd.,DATAPATTNS,543428,GENERAL INDUSTRIALS,DEFENCE,119.2,67.5,40.8,37.63%,3.1,2.3,46.3,12.5,33.8,6,148.3,26.5 +Global Health Ltd.,MEDANTA,543654,DIVERSIFIED CONSUMER SERVICES,HEALTHCARE FACILITIES,864.7,631.1,212.9,25.22%,42.9,20.1,170.6,45.4,125.2,4.7,408.9,15.2 +Aarti Industries Ltd.,AARTIIND,524208,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,"1,454","1,221.2",232.8,16.01%,93,58.2,81.6,-9.1,90.7,2.5,446.2,12.3 +BLS International Services Ltd.,BLS,540073,DIVERSIFIED CONSUMER SERVICES,TRAVEL SUPPORT SERVICES,416.4,321,86.7,21.27%,7.3,1,87.2,5.2,78.7,1.9,267.6,6.5 +Archean Chemical Industries Ltd.,ACI,543657,CHEMICALS & PETROCHEMICALS,COMMODITY CHEMICALS,301.7,195,95.5,32.86%,17.5,1.9,87.3,21.3,66,5.4,394.4,32.1 +Adani Power Ltd.,ADANIPOWER,ASM,UTILITIES,ELECTRIC UTILITIES,"14,935.7","7,819.2","5,171.4",39.81%,"1,004.5",888.4,"5,223.6","-1,370.6","6,594.2",16.5,"20,604.8",53.4 +Craftsman Automation Ltd.,CRAFTSMAN,543276,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,183.8",941.6,237.5,20.14%,66.8,41.6,133.8,29.6,94.5,44.1,298.3,141.2 +NMDC Ltd.,NMDC,526371,METALS & MINING,MINING,"4,335","2,823.6","1,190.4",29.66%,88.8,18.6,"1,404.1",379,"1,026.2",3.5,"5,862.2",20 +Epigral Ltd.,EPIGRAL,543332,CHEMICALS & PETROCHEMICALS,SPECIALTY CHEMICALS,479.1,370.2,107.9,22.57%,31.5,21.3,56.1,17.9,38,9.1,223.4,53.8 +Apar Industries Ltd.,APARINDS,532259,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,"3,944.7","3,576.2",349.8,8.91%,28.2,103.1,237.3,62.9,173.9,45.4,783.9,204.8 +Bikaji Foods International Ltd.,BIKAJI,543653,FMCG,PACKAGED FOODS,614.7,521,87.7,14.41%,15.6,2.9,75.2,15.4,61.2,2.5,173.6,6.9 +Five-Star Business Finance Ltd.,FIVESTAR,543663,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),522.4,133.2,375,72.28%,5.7,105.9,267,67.6,199.4,6.8,703,24.1 +Ingersoll-Rand (India) Ltd.,INGERRAND,500210,GENERAL INDUSTRIALS,INDUSTRIAL MACHINERY,282.8,210.7,65.7,23.76%,4.6,0.6,67,17.2,49.7,15.8,218.5,69.2 +KFIN Technologies Ltd.,KFINTECH,543720,BANKING AND FINANCE,OTHER FINANCIAL SERVICES,215.3,115.3,93.7,44.82%,12.6,3.2,84.2,22.3,61.4,3.6,215.1,12.6 +Piramal Enterprises Ltd.,PEL,500302,BANKING AND FINANCE,FINANCE (INCLUDING NBFCS),"2,205.2","1,320.1","1,117.9",50.97%,38.3,"1,038.9",-11.8,10.7,48.2,2,"3,906.5",173.9 +NMDC Steel Ltd.,NSLNISP,543768,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,290.3,349.6,-72.2,-26.04%,74.5,40.8,-174.7,-43.6,-131.1,-0.5,, +Eris Lifesciences Ltd.,ERIS,540596,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,508.8,324.2,181.1,35.85%,42.1,16.3,126.2,3.9,123.4,9.1,385.6,28.3 +Mankind Pharma Ltd.,MANKIND,543904,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,"2,768.1","2,025.5",682.6,25.21%,96.5,8.6,637.5,129.8,501,12.5,"1,564.8",39.1 +Kaynes Technology India Ltd.,KAYNES,ASM,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,369.8,312.1,48.8,13.52%,6.5,11.8,39.4,7.1,32.3,5.5,143.2,24.6 +Safari Industries (India) Ltd.,SAFARI,523025,TEXTILES APPARELS & ACCESSORIES,OTHER APPARELS & ACCESSORIES,372.9,306.6,63.5,17.15%,12.2,2.2,51.9,12.1,39.8,16.7,162.3,68.2 +Saregama India Ltd.,SAREGAMA,532163,MEDIA,MOVIES & ENTERTAINMENT,185.6,111.5,60.9,35.32%,8.2,0.2,65.6,17.6,48.1,2.5,193.4,10 +Syrma SGS Technology Ltd.,SYRMA,543573,CONSUMER DURABLES,OTHER ELECTRICAL EQUIPMENT/PRODUCTS,720.6,662.7,49,6.88%,11.6,8,37,6.4,28.3,1.6,132.4,7.5 +Jindal Saw Ltd.,JINDALSAW,ASM,GENERAL INDUSTRIALS,OTHER INDUSTRIAL PRODUCTS,"5,488.9","4,662",804.2,14.71%,142.5,188.7,495.6,139.6,375.7,11.8,"1,135.8",35.5 +Godawari Power & Ispat Ltd.,GPIL,532734,METALS & MINING,IRON & STEEL/INTERM.PRODUCTS,"1,314.2",929.6,361.4,28.00%,34.8,10.2,339.6,86.1,256.9,20.6,785.5,63 +Gillette India Ltd.,GILLETTE,507815,FMCG,PERSONAL PRODUCTS,676.2,530.8,136.7,20.48%,20.1,0.1,125.2,32.5,92.7,28.4,361.6,111 +Symphony Ltd.,SYMPHONY,517385,CONSUMER DURABLES,CONSUMER ELECTRONICS,286,234,41,14.91%,7,2,43,8,35,5.1,114,16.5 +Glenmark Life Sciences Ltd.,GLS,543322,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,600.7,428.3,167.1,28.06%,13.1,0.4,158.9,40.2,118.7,9.7,505.5,41.3 +Usha Martin Ltd.,USHAMART,517146,METALS & MINING,IRON & STEEL PRODUCTS,806,640.4,144.3,18.39%,18,6.4,141.2,35,109.5,3.6,399.4,13.1 +Ircon International Ltd.,IRCON,541956,CEMENT AND CONSTRUCTION,CONSTRUCTION & ENGINEERING,"3,136.3","2,771.2",215.7,7.22%,27.1,36.9,301.2,77.6,250.7,2.7,884.6,9.4 +Ujjivan Small Finance Bank Ltd.,UJJIVANSFB,542904,BANKING AND FINANCE,BANKS,"1,579.8",528.6,483.4,34.75%,0,567.8,436.4,108.7,327.7,1.7,"1,254.5",6.4 +Procter & Gamble Health Ltd.,PGHL,500126,PHARMACEUTICALS & BIOTECHNOLOGY,PHARMACEUTICALS,311,216.3,88.7,29.08%,6.5,0.2,88,22.5,65.6,39.5,231.4,139.4 +Allcargo Logistics Ltd.,ALLCARGO,532749,TRANSPORTATION,TRANSPORTATION - LOGISTICS,"3,336.3","3,188.8",118,3.57%,106.7,36.7,14.2,1.3,21.8,0.9,361.9,14.7 +Sheela Foam Ltd.,SFL,540203,DIVERSIFIED CONSUMER SERVICES,FURNITURE-FURNISHING-PAINTS,637.6,547,66.2,10.80%,21.9,8.6,60.2,15.6,44,4.5,192.4,17.7 +Alok Industries Ltd.,ALOKINDS,521070,TEXTILES APPARELS & ACCESSORIES,TEXTILES,"1,369.3","1,323.1",35.9,2.64%,78.6,142.2,-174.6,0,-174.8,-0.3,-948.4,-1.9 +Minda Corporation Ltd.,MINDACORP,538962,AUTOMOBILES & AUTO COMPONENTS,AUTO PARTS & EQUIPMENT,"1,197.9","1,064.5",131.3,10.98%,41.4,14.9,77,18.7,58.8,2.5,278.2,11.6 +Concord Biotech Ltd.,CONCORDBIO,543960,PHARMACEUTICALS & BIOTECHNOLOGY,BIOTECHNOLOGY,270.5,143.2,119.2,45.43%,13.3,0.8,113.2,28.7,81,7.7,, \ No newline at end of file From d5b880de7645acfd54f83ce56fe04784f890e9ae Mon Sep 17 00:00:00 2001 From: e-straight <142330569+e-straight@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:01:29 -0400 Subject: [PATCH 024/180] Update quickstart.md Added the file download step --- quickstart.md | 1 + 1 file changed, 1 insertion(+) diff --git a/quickstart.md b/quickstart.md index 6257b8af..605734c1 100644 --- a/quickstart.md +++ b/quickstart.md @@ -168,6 +168,7 @@ python -m pip install azure-ai-projects azure-identity Use the following code to create and run an agent. ```python +#Make sure to download nifty_500_quarterly_results.csv from the data file before starting #First install the azure-ai-project sdk using the whl file provided in the repo # %pip install --force-reinstall azure_ai_project-1.0.0b1-py3-none-any.whl From eb0ab045a7f9e0390bf561f14d57e066c7494084 Mon Sep 17 00:00:00 2001 From: aahill Date: Fri, 1 Nov 2024 11:02:39 -0700 Subject: [PATCH 025/180] Update quickstart.md --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 605734c1..f9eb29dd 100644 --- a/quickstart.md +++ b/quickstart.md @@ -168,7 +168,7 @@ python -m pip install azure-ai-projects azure-identity Use the following code to create and run an agent. ```python -#Make sure to download nifty_500_quarterly_results.csv from the data file before starting +#Make sure to download nifty_500_quarterly_results.csv from the `data` folder before starting #First install the azure-ai-project sdk using the whl file provided in the repo # %pip install --force-reinstall azure_ai_project-1.0.0b1-py3-none-any.whl From 08d0b60586895bc18417aeccd6e017f626faf686 Mon Sep 17 00:00:00 2001 From: e-straight <142330569+e-straight@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:10:05 -0400 Subject: [PATCH 026/180] Update quickstart.md deleted line --- quickstart.md | 1 - 1 file changed, 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index f9eb29dd..c4584266 100644 --- a/quickstart.md +++ b/quickstart.md @@ -183,7 +183,6 @@ from typing import Any # Create an Azure AI Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" # Customer needs to login to Azure subscription via Azure CLI and set the environment variables -os.environ['PROJECT_CONNECTION_STRING'] = "eastus2euap.api.azureml.ms;47f1c914-e299-4953-a99d-3e34644cfe1c;rg-agent-test-westus2;proj-eastus2euap-brefmanyqpzrq" project_client = AIProjectClient.from_connection_string( credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] From 71933284c57aeef25e695db51ed2124e061dd078 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 1 Nov 2024 11:54:24 -0700 Subject: [PATCH 027/180] Bing form link --- samples/bing-search/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 5ef4cada..8a1c13f6 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -9,7 +9,7 @@ Please note that developers and end users don’t have access to raw chunks retu ## Setup > [!IMPORTANT] -> Grounding with Bing Search has a separate Terms of Use agreement you need to agree to in order to move forward. Please use this form[pending link] to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. +> Grounding with Bing Search has a separate Terms of Use agreement you need to agree to in order to move forward. Please [use this form](https://forms.office.com/r/2j3Sgu8S9K) to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). From d558f2506903b399ea4e8c7b2d3386884a0d6cff Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Fri, 1 Nov 2024 15:03:11 -0400 Subject: [PATCH 028/180] hub and project created --- main.bicep | 84 +++++++++++++ modules/ai-hub.bicep | 74 ++++++++++++ modules/ai-project.bicep | 42 +++++++ modules/dependent-resources.bicep | 190 ++++++++++++++++++++++++++++++ 4 files changed, 390 insertions(+) create mode 100644 main.bicep create mode 100644 modules/ai-hub.bicep create mode 100644 modules/ai-project.bicep create mode 100644 modules/dependent-resources.bicep diff --git a/main.bicep b/main.bicep new file mode 100644 index 00000000..2236ebd4 --- /dev/null +++ b/main.bicep @@ -0,0 +1,84 @@ +// Execute this main file to depoy Azure AI studio resources in the basic security configuraiton + +// Parameters +@minLength(2) +@maxLength(12) +@description('Name for the AI resource and used to derive name of dependent resources.') +param aiHubName string = 'demo' + +@description('Friendly name for your Azure AI resource') +param aiHubFriendlyName string = 'Demo AI resource' + +@description('Description of your Azure AI resource dispayed in AI studio') +param aiHubDescription string = 'This is an example AI resource for use in Azure AI Studio.' + +param aiProjectName string = 'project-demo' + +@description('Friendly name for your Azure AI resource') +param aiProjectFriendlyName string = 'Demo AI Project resource' + +@description('Description of your Azure AI resource dispayed in AI studio') +param aiProjectDescription string = 'This is an example AI Project resource for use in Azure AI Studio.' + +@description('Azure region used for the deployment of all resources.') +param location string = resourceGroup().location + +@description('Set of tags to apply to all resources.') +param tags object = {} + +// Variables +var name = toLower('${aiHubName}') +var projectName = toLower('${aiProjectName}') + +// Create a short, unique suffix, that will be unique to each resource group +var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) + +// Dependent resources for the Azure Machine Learning workspace +module aiDependencies 'modules/dependent-resources.bicep' = { + name: 'dependencies-${name}-${uniqueSuffix}-deployment' + params: { + location: location + storageName: 'st${name}${uniqueSuffix}' + keyvaultName: 'kv-${name}-${uniqueSuffix}' + applicationInsightsName: 'appi-${name}-${uniqueSuffix}' + containerRegistryName: 'cr${name}${uniqueSuffix}' + aiServicesName: 'ais${name}${uniqueSuffix}' + tags: tags + } +} + +module aiHub 'modules/ai-hub.bicep' = { + name: 'ai-${name}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiHubName: 'aih-${name}-${uniqueSuffix}' + aiHubFriendlyName: aiHubFriendlyName + aiHubDescription: aiHubDescription + location: location + tags: tags + + // dependent resources + aiServicesId: aiDependencies.outputs.aiservicesID + aiServicesTarget: aiDependencies.outputs.aiservicesTarget + applicationInsightsId: aiDependencies.outputs.applicationInsightsId + containerRegistryId: aiDependencies.outputs.containerRegistryId + keyVaultId: aiDependencies.outputs.keyvaultId + storageAccountId: aiDependencies.outputs.storageId + } +} + +module aiProject 'modules/ai-project.bicep' = { + name: 'ai-${projectName}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiProjectName: 'aip-${projectName}-${uniqueSuffix}' + aiProjectFriendlyName: aiProjectFriendlyName + aiProjectDescription: aiProjectDescription + location: location + tags: tags + + // dependent resources + aiHubId: aiHub.outputs.aiHubID + } +} + diff --git a/modules/ai-hub.bicep b/modules/ai-hub.bicep new file mode 100644 index 00000000..24f8ec6b --- /dev/null +++ b/modules/ai-hub.bicep @@ -0,0 +1,74 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI hub name') +param aiHubName string + +@description('AI hub display name') +param aiHubFriendlyName string = aiHubName + +@description('AI hub description') +param aiHubDescription string + +@description('Resource ID of the application insights resource for storing diagnostics logs') +param applicationInsightsId string + +@description('Resource ID of the container registry resource for storing docker images') +param containerRegistryId string + +@description('Resource ID of the key vault resource for storing connection strings') +param keyVaultId string + +@description('Resource ID of the storage account resource for storing experimentation outputs') +param storageAccountId string + +@description('Resource ID of the AI Services resource') +param aiServicesId string + +@description('Resource ID of the AI Services endpoint') +param aiServicesTarget string + +resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { + name: aiHubName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiHubFriendlyName + description: aiHubDescription + + // dependent resources + keyVault: keyVaultId + storageAccount: storageAccountId + applicationInsights: applicationInsightsId + containerRegistry: containerRegistryId + } + kind: 'hub' + + resource aiServicesConnection 'connections@2024-01-01-preview' = { + name: '${aiHubName}-connection-AzureOpenAI' + properties: { + category: 'AzureOpenAI' + target: aiServicesTarget + authType: 'ApiKey' + isSharedToAll: true + credentials: { + key: '${listKeys(aiServicesId, '2021-10-01').key1}' + } + metadata: { + ApiType: 'Azure' + ResourceId: aiServicesId + } + } + } +} + +output aiHubID string = aiHub.id diff --git a/modules/ai-project.bicep b/modules/ai-project.bicep new file mode 100644 index 00000000..764ca201 --- /dev/null +++ b/modules/ai-project.bicep @@ -0,0 +1,42 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI Project name') +param aiProjectName string + +@description('AI Project display name') +param aiProjectFriendlyName string = aiProjectName + +@description('AI Project description') +param aiProjectDescription string + +@description('Resource ID of the AI Hub resource') +param aiHubId string + + + +resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { + name: aiProjectName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiProjectFriendlyName + description: aiProjectDescription + + // dependent resources + hubResourceId: aiHubId + + } + kind: 'project' +} + +output aiProjectID string = aiProject.id diff --git a/modules/dependent-resources.bicep b/modules/dependent-resources.bicep new file mode 100644 index 00000000..70216192 --- /dev/null +++ b/modules/dependent-resources.bicep @@ -0,0 +1,190 @@ +// Creates Azure dependent resources for Azure AI studio + +@description('Azure region of the deployment') +param location string = resourceGroup().location + +@description('Tags to add to the resources') +param tags object = {} + +@description('AI services name') +param aiServicesName string + +@description('Application Insights resource name') +param applicationInsightsName string + +@description('Container registry name') +param containerRegistryName string + +@description('The name of the Key Vault') +param keyvaultName string + +var containerRegistryNameCleaned = replace(containerRegistryName, '-', '') + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { + name: applicationInsightsName + location: location + tags: tags + kind: 'web' + properties: { + Application_Type: 'web' + DisableIpMasking: false + DisableLocalAuth: false + Flow_Type: 'Bluefield' + ForceCustomerStorageForProfiler: false + ImmediatePurgeDataOn30Days: true + IngestionMode: 'ApplicationInsights' + publicNetworkAccessForIngestion: 'Enabled' + publicNetworkAccessForQuery: 'Disabled' + Request_Source: 'rest' + } +} + +resource containerRegistry 'Microsoft.ContainerRegistry/registries@2021-09-01' = { + name: containerRegistryNameCleaned + location: location + tags: tags + sku: { + name: 'Premium' + } + properties: { + adminUserEnabled: true + dataEndpointEnabled: false + networkRuleBypassOptions: 'AzureServices' + networkRuleSet: { + defaultAction: 'Deny' + } + policies: { + quarantinePolicy: { + status: 'enabled' + } + retentionPolicy: { + status: 'enabled' + days: 7 + } + trustPolicy: { + status: 'disabled' + type: 'Notary' + } + } + publicNetworkAccess: 'Disabled' + zoneRedundancy: 'Disabled' + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyvaultName + location: location + tags: tags + properties: { + createMode: 'default' + enabledForDeployment: false + enabledForDiskEncryption: false + enabledForTemplateDeployment: false + enableSoftDelete: true + enableRbacAuthorization: true + enablePurgeProtection: true + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + sku: { + family: 'A' + name: 'standard' + } + softDeleteRetentionInDays: 7 + tenantId: subscription().tenantId + } +} + +@description('Name of the storage account') +param storageName string + +@allowed([ + 'Standard_LRS' + 'Standard_ZRS' + 'Standard_GRS' + 'Standard_GZRS' + 'Standard_RAGRS' + 'Standard_RAGZRS' + 'Premium_LRS' + 'Premium_ZRS' +]) + +@description('Storage SKU') +param storageSkuName string = 'Standard_LRS' + +var storageNameCleaned = replace(storageName, '-', '') + +resource aiServices 'Microsoft.CognitiveServices/accounts@2021-10-01' = { + name: aiServicesName + location: location + sku: { + name: 'S0' + } + kind: 'AIServices' // or 'OpenAI' + identity: { + type: 'SystemAssigned' + } + properties: { + apiProperties: { + statisticsEnabled: false + } + } +} + +resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = { + name: storageNameCleaned + location: location + tags: tags + sku: { + name: storageSkuName + } + kind: 'StorageV2' + properties: { + accessTier: 'Hot' + allowBlobPublicAccess: false + allowCrossTenantReplication: false + allowSharedKeyAccess: true + encryption: { + keySource: 'Microsoft.Storage' + requireInfrastructureEncryption: false + services: { + blob: { + enabled: true + keyType: 'Account' + } + file: { + enabled: true + keyType: 'Account' + } + queue: { + enabled: true + keyType: 'Service' + } + table: { + enabled: true + keyType: 'Service' + } + } + } + isHnsEnabled: false + isNfsV3Enabled: false + keyPolicy: { + keyExpirationPeriodInDays: 7 + } + largeFileSharesState: 'Disabled' + minimumTlsVersion: 'TLS1_2' + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + supportsHttpsTrafficOnly: true + } +} + +output aiservicesID string = aiServices.id +output aiservicesTarget string = aiServices.properties.endpoint +output storageId string = storage.id +output keyvaultId string = keyVault.id +output containerRegistryId string = containerRegistry.id +output applicationInsightsId string = applicationInsights.id From 0da0df5a8723323f44278d2bfc423370f4c5ddd4 Mon Sep 17 00:00:00 2001 From: e-straight Date: Sun, 3 Nov 2024 11:18:54 -0500 Subject: [PATCH 029/180] Python sdk example update --- quickstart.md | 121 ++++++++++++++++++++++---------------------------- 1 file changed, 53 insertions(+), 68 deletions(-) diff --git a/quickstart.md b/quickstart.md index c4584266..4fde8b77 100644 --- a/quickstart.md +++ b/quickstart.md @@ -189,81 +189,66 @@ project_client = AIProjectClient.from_connection_string( ) with project_client: - #Set up the Event Handler Class. This class handles all of the various action for the Agent. - class MyEventHandler(AgentEventHandler): - def on_message_delta(self, delta: "MessageDeltaChunk") -> None: - for content_part in delta.delta.content: - if isinstance(content_part, MessageDeltaTextContent): - text_value = content_part.text.value if content_part.text else "No text" - print(f"Text delta received: {text_value}") - - def on_thread_message(self, message: "ThreadMessage") -> None: - print(f"ThreadMessage created. ID: {message.id}, Status: {message.status}") - - def on_thread_run(self, run: "ThreadRun") -> None: - print(f"ThreadRun status: {run.status}") - if run.status == "failed": - print(f"Run failed. Error: {run.last_error}") - - def on_run_step(self, step: "RunStep") -> None: - print(f"RunStep type: {step.type}, Status: {step.status}") - - def on_error(self, data: str) -> None: - print(f"An error occurred. Data: {data}") - - def on_done(self) -> None: - print("Stream completed.") - - def on_unhandled_event(self, event_type: str, event_data: Any) -> None: - print(f"Unhandled Event Type: {event_type}, Data: {event_data}") - - #Upload the file to be used in the Agent scenario - file = project_client.agents.upload_file_and_poll( - file_path="nifty_500_quarterly_results.csv", purpose=FilePurpose.AGENTS - ) - print(f"Uploaded file, file ID: {file.id}") - - #Create the CodeInterpreterTool and add it to the toolset + # Create an instance of the CodeInterpreterTool code_interpreter = CodeInterpreterTool() - code_interpreter.file_ids = [file.id] - toolset = ToolSet() - toolset.add(code_interpreter) - - # notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment + + # The CodeInterpeterTool needs to be included in creation of the agent agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", - name="my-agent", - instructions="you are a helpful agent", - toolset=toolset + model="gpt-4-1106-preview", + name="my-assistant", + instructions="You are helpful assistant", + tools=code_interpreter.definitions, + tool_resources=code_interpreter.resources, ) - print(f"Created agent, ID: {agent.id}") - - #Create an agentic thread - thread = project_client.agents.create_thread() - print(f"Created thread, thread ID {thread.id}") - - #Send a message to the agent - message = project_client.agents.create_message( + print(f"Created agent, agent ID: {agent.id}") + + # Create a thread + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + # Create a message + message = project_client.agents.create_message( thread_id=thread.id, role="user", - content="Write code to calculate compound interest.", - ) - - print(f"Created message, message ID {message.id}") - - #Create and run the agent stream - with project_client.agents.create_stream( - thread_id=thread.id, assistant_id=agent.id, event_handler=MyEventHandler() - ) as stream: - stream.until_done() + content="Could you please create a bar chart for the operating profit using the following data and provide the file to me? Company A: $1.2 million, Company B: $2.5 million, Company C: $3.0 million, Company D: $1.8 million", + ) + print(f"Created message, message ID: {message.id}") + + # Run the agent + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") - #Display the messages and output from the agent - messages = project_client.agents.list_messages(thread_id=thread.id) + # Get messages from the thread + messages = project_client.agents.get_messages(thread_id=thread.id) print(f"Messages: {messages}") - print(f"Content: {messages.data[0].content[0].text.value}") - - #Delete the agent when finished - project_client.agents.delete_agent(agent.id) + + # Get the last message from the sender + last_msg = messages.get_last_text_message_by_sender("assistant") + if last_msg: + print(f"Last Message: {last_msg.text.value}") + + # Generate an image file for the bar chart + for image_content in messages.image_contents: + print(f"Image File ID: {image_content.image_file.file_id}") + file_name = f"{image_content.image_file.file_id}_image_file.png" + project_client.agents.save_file(file_id=image_content.image_file.file_id, file_name=file_name) + print(f"Saved image file to: {Path.cwd() / file_name}") + + # Print the file path(s) from the messages + for file_path_annotation in messages.file_path_annotations: + print(f"File Paths:") + print(f"Type: {file_path_annotation.type}") + print(f"Text: {file_path_annotation.text}") + print(f"File ID: {file_path_annotation.file_path.file_id}") + print(f"Start Index: {file_path_annotation.start_index}") + print(f"End Index: {file_path_annotation.end_index}") + + # Delete the agent once done + project_client.agents.delete_agent(agent.id) print("Deleted agent") ``` From 2ff31575c1a600db67e686a9d72c06c6981730cb Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Sun, 3 Nov 2024 11:57:24 -0500 Subject: [PATCH 030/180] arm template with hub, project, and aoai resource created --- modules/ai-hub.bicep | 6 ++---- modules/dependent-resources.bicep | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/ai-hub.bicep b/modules/ai-hub.bicep index 24f8ec6b..057b726c 100644 --- a/modules/ai-hub.bicep +++ b/modules/ai-hub.bicep @@ -58,11 +58,8 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' properties: { category: 'AzureOpenAI' target: aiServicesTarget - authType: 'ApiKey' + authType: 'AAD' isSharedToAll: true - credentials: { - key: '${listKeys(aiServicesId, '2021-10-01').key1}' - } metadata: { ApiType: 'Azure' ResourceId: aiServicesId @@ -71,4 +68,5 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' } } + output aiHubID string = aiHub.id diff --git a/modules/dependent-resources.bicep b/modules/dependent-resources.bicep index 70216192..ef50dd5b 100644 --- a/modules/dependent-resources.bicep +++ b/modules/dependent-resources.bicep @@ -115,7 +115,7 @@ param storageSkuName string = 'Standard_LRS' var storageNameCleaned = replace(storageName, '-', '') -resource aiServices 'Microsoft.CognitiveServices/accounts@2021-10-01' = { +resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' = { name: aiServicesName location: location sku: { @@ -129,6 +129,7 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2021-10-01' = { apiProperties: { statisticsEnabled: false } + publicNetworkAccess: 'Enabled' } } From 8976d2619f3275d68ea5bdc79ee4f510d747bd56 Mon Sep 17 00:00:00 2001 From: e-straight Date: Sun, 3 Nov 2024 17:40:44 -0500 Subject: [PATCH 031/180] Updated whl, CI python sample --- .../azure_ai_project-1.0.0b1-py3-none-any.whl | Bin 143723 -> 0 bytes samples/code-interpreter/python-sample.py | 147 +++++++++++++----- 2 files changed, 110 insertions(+), 37 deletions(-) delete mode 100644 packages/azure_ai_project-1.0.0b1-py3-none-any.whl diff --git a/packages/azure_ai_project-1.0.0b1-py3-none-any.whl b/packages/azure_ai_project-1.0.0b1-py3-none-any.whl deleted file mode 100644 index 64c7a6e595ed615cf49360aa23d9f0119bc84bb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143723 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

U} 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 Mn9s-n9T)-s10D8gdH?_b diff --git a/samples/code-interpreter/python-sample.py b/samples/code-interpreter/python-sample.py index 0000a89d..90cd6f41 100644 --- a/samples/code-interpreter/python-sample.py +++ b/samples/code-interpreter/python-sample.py @@ -1,37 +1,110 @@ -from openai import AzureOpenAI - -client = AzureOpenAI( - api_key=os.getenv("AZURE_OPENAI_API_KEY"), - api_version="2024-05-01-preview", - azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") - ) - -# Upload a file with an "assistants" purpose -file = client.files.create( - file=open("speech.py", "rb"), - purpose='assistants' -) - -# Create an assistant using the file ID -assistant = client.beta.assistants.create( - instructions="You are an AI assistant that can write code to help answer math questions.", - model="gpt-4-1106-preview", - tools=[{"type": "code_interpreter"}], - tool_resources={"code interpreter":{"file_ids":[file.id]}} -) - -client = AzureOpenAI( - api_key=os.getenv("AZURE_OPENAI_API_KEY"), - api_version="2024-05-01-preview", - azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") - ) - -thread = client.beta.threads.create( - messages=[ - { - "role": "user", - "content": "I need to solve the equation `3x + 11 = 14`. Can you help me?", - "file_ids": ["file.id"] # file id will look like: "assistant-R9uhPxvRKGH3m0x5zBOhMjd2" - } - ] -) \ No newline at end of file +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: python-sample.py + +DESCRIPTION: + This sample demonstrates how to use agent operations with code interpreter from + the Azure Agents service using a synchronous client. + +USAGE: + python python-sample.py + + Before running the sample: + + pip install azure-ai-projects azure-identity + + Set this environment variables with your own values: + PROJECT_CONNECTION_STRING - the Azure AI Project connection string, as found in your AI Studio Project. +""" + +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import CodeInterpreterTool +from azure.ai.projects.models import FilePurpose +from azure.identity import DefaultAzureCredential +from pathlib import Path + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +with project_client: + + # upload a file and wait for it to be processed + file = project_client.agents.upload_file_and_poll( + file_path="../../data/nifty_500_quarterly_results.csv", purpose=FilePurpose.AGENTS + ) + print(f"Uploaded file, file ID: {file.id}") + + # instantiate the CodeInterpreterTool with the necessary files + code_interpreter = CodeInterpreterTool(file_ids=[file.id]) + + # notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-assistant", + instructions="You are helpful assistant", + tools=code_interpreter.definitions, + tool_resources=code_interpreter.resources, + ) + print(f"Created agent, agent ID: {agent.id}") + + # create a thread + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + # create a message + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Could you please create bar chart in the TRANSPORTATION sector for the operating profit from the uploaded csv file and provide file to me?", + ) + print(f"Created message, message ID: {message.id}") + + # create and execute a run + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") + + # delete the original file from the agent to free up space (note: this does not delete your version of the file) + project_client.agents.delete_file(file.id) + print("Deleted file") + + # print the messages from the agent + messages = project_client.agents.get_messages(thread_id=thread.id) + print(f"Messages: {messages}") + + # get the most recent message from the assistant + last_msg = messages.get_last_text_message_by_sender("assistant") + if last_msg: + print(f"Last Message: {last_msg.text.value}") + + # save the newly created file + for image_content in messages.image_contents: + print(f"Image File ID: {image_content.image_file.file_id}") + file_name = f"{image_content.image_file.file_id}_image_file.png" + project_client.agents.save_file(file_id=image_content.image_file.file_id, file_name=file_name) + print(f"Saved image file to: {Path.cwd() / file_name}") + + # iterates through file_path_annotations in messages and prints details for each annotation + for file_path_annotation in messages.file_path_annotations: + print(f"File Paths:") + print(f"Type: {file_path_annotation.type}") + print(f"Text: {file_path_annotation.text}") + print(f"File ID: {file_path_annotation.file_path.file_id}") + print(f"Start Index: {file_path_annotation.start_index}") + print(f"End Index: {file_path_annotation.end_index}") + + # delete the agent once done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") \ No newline at end of file From 74f35db7dad31eddb91c7f4674bf0399974f579b Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Sun, 3 Nov 2024 20:06:43 -0500 Subject: [PATCH 032/180] Update quickstart.md I believe correct command is (removing s) python -m pip install azure-ai-project azure-identity --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index c4584266..f62da2dd 100644 --- a/quickstart.md +++ b/quickstart.md @@ -162,7 +162,7 @@ Use the following code to create an agent and send a message to it. This agent w Run the following command to install the python package. ```console -python -m pip install azure-ai-projects azure-identity +python -m pip install azure-ai-project azure-identity ``` Use the following code to create and run an agent. From 69f46aad7877c176e7be0a0a277f642c45f5de4c Mon Sep 17 00:00:00 2001 From: e-straight <142330569+e-straight@users.noreply.github.com> Date: Mon, 4 Nov 2024 10:37:10 -0500 Subject: [PATCH 033/180] Update quickstart.md Fixed the create AI Services vs OpenAI resource commands --- quickstart.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quickstart.md b/quickstart.md index 25d94144..7d4da73f 100644 --- a/quickstart.md +++ b/quickstart.md @@ -54,15 +54,15 @@ Follow these steps to set up your hub and project: > [!NOTE] > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. - ``` - az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus2 + ```console + az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus2 --kind OpenAI --sku s0 ``` Alternatively, you can create an AI Services resource: ```console - az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus2 --kind OpenAI --sku s0 + az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus2 ``` From b5a24d35451a2560356f422bfe083075fa9b69a4 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 4 Nov 2024 10:51:34 -0500 Subject: [PATCH 034/180] aoai connection to hub working --- main.bicep | 11 +++++++---- modules/ai-hub.bicep | 17 +++++++++-------- modules/dependent-resources.bicep | 23 ++++++++++++++++++++--- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/main.bicep b/main.bicep index 2236ebd4..48e6900c 100644 --- a/main.bicep +++ b/main.bicep @@ -4,7 +4,7 @@ @minLength(2) @maxLength(12) @description('Name for the AI resource and used to derive name of dependent resources.') -param aiHubName string = 'demo' +param aiHubName string = 'hub-demo' @description('Friendly name for your Azure AI resource') param aiHubFriendlyName string = 'Demo AI resource' @@ -31,7 +31,10 @@ var name = toLower('${aiHubName}') var projectName = toLower('${aiProjectName}') // Create a short, unique suffix, that will be unique to each resource group -var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) +// var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) +param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') +var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) + // Dependent resources for the Azure Machine Learning workspace module aiDependencies 'modules/dependent-resources.bicep' = { @@ -51,7 +54,7 @@ module aiHub 'modules/ai-hub.bicep' = { name: 'ai-${name}-${uniqueSuffix}-deployment' params: { // workspace organization - aiHubName: 'aih-${name}-${uniqueSuffix}' + aiHubName: 'ai-${name}-${uniqueSuffix}' aiHubFriendlyName: aiHubFriendlyName aiHubDescription: aiHubDescription location: location @@ -71,7 +74,7 @@ module aiProject 'modules/ai-project.bicep' = { name: 'ai-${projectName}-${uniqueSuffix}-deployment' params: { // workspace organization - aiProjectName: 'aip-${projectName}-${uniqueSuffix}' + aiProjectName: 'ai-${projectName}-${uniqueSuffix}' aiProjectFriendlyName: aiProjectFriendlyName aiProjectDescription: aiProjectDescription location: location diff --git a/modules/ai-hub.bicep b/modules/ai-hub.bicep index 057b726c..acddd4ee 100644 --- a/modules/ai-hub.bicep +++ b/modules/ai-hub.bicep @@ -33,7 +33,7 @@ param aiServicesId string @description('Resource ID of the AI Services endpoint') param aiServicesTarget string -resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { +resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { name: aiHubName location: location tags: tags @@ -53,16 +53,17 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' } kind: 'hub' - resource aiServicesConnection 'connections@2024-01-01-preview' = { - name: '${aiHubName}-connection-AzureOpenAI' + resource aiServicesConnection 'connections@2024-07-01-preview' = { + name: '${aiHubName}-connection-AIServices' properties: { - category: 'AzureOpenAI' + category: 'OpenAI' target: aiServicesTarget - authType: 'AAD' + // useWorkspaceManagedIdentity: true + peRequirement: 'Required' + authType: 'ApiKey' isSharedToAll: true - metadata: { - ApiType: 'Azure' - ResourceId: aiServicesId + credentials: { + key: '${listKeys(aiServicesId, '2021-10-01').key1}' } } } diff --git a/modules/dependent-resources.bicep b/modules/dependent-resources.bicep index ef50dd5b..900f3c35 100644 --- a/modules/dependent-resources.bicep +++ b/modules/dependent-resources.bicep @@ -39,7 +39,7 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { } } -resource containerRegistry 'Microsoft.ContainerRegistry/registries@2021-09-01' = { +resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' = { name: containerRegistryNameCleaned location: location tags: tags @@ -115,7 +115,7 @@ param storageSkuName string = 'Standard_LRS' var storageNameCleaned = replace(storageName, '-', '') -resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' = { +resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { name: aiServicesName location: location sku: { @@ -132,8 +132,25 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' = { publicNetworkAccess: 'Enabled' } } +/* +resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { + parent: aiServices + name: 'gpt-4o-mini' + sku : { + capacity: 1 + name: 'Standard' + } + properties: { + model:{ + name: 'gpt-4o-mini' + format: 'OpenAI' + // version: '2024-07-18' + } + } +} +*/ -resource storage 'Microsoft.Storage/storageAccounts@2022-09-01' = { +resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { name: storageNameCleaned location: location tags: tags From fe05d17e884322a4927b4aa47108449b52208fb1 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 09:38:37 -0800 Subject: [PATCH 035/180] Update readme.md --- samples/bing-search/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 8a1c13f6..9bdd076c 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -9,7 +9,7 @@ Please note that developers and end users don’t have access to raw chunks retu ## Setup > [!IMPORTANT] -> Grounding with Bing Search has a separate Terms of Use agreement you need to agree to in order to move forward. Please [use this form](https://forms.office.com/r/2j3Sgu8S9K) to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. +> Grounding with Bing Search has a separate [Terms of Use agreement](https://www.microsoft.com/en-us/bing/apis/grounding-legal-preview) you need to agree to in order to move forward. Please [use this form](https://forms.office.com/r/2j3Sgu8S9K) to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). @@ -34,4 +34,4 @@ Run the code samples below and view the output. > Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) -* [C#](./csharp-sample.cs) \ No newline at end of file +* [C#](./csharp-sample.cs) From 913fcc9b6a6dca5a9d7384fe97201a5db1a3790e Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 09:50:43 -0800 Subject: [PATCH 036/180] Update readme.md --- samples/bing-search/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 9bdd076c..693667cc 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -13,7 +13,7 @@ Please note that developers and end users don’t have access to raw chunks retu 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). -1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI or Azure portal to create one[pending Bing update]: +1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI to create one[pending Bing update]: ```console az cognitiveservices account create \ From dadb1fbf87a7805d31eab0029539ed4cfd887be9 Mon Sep 17 00:00:00 2001 From: e-straight Date: Mon, 4 Nov 2024 13:08:16 -0500 Subject: [PATCH 037/180] added file for file search --- data/product_info_1.md | 215 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 data/product_info_1.md diff --git a/data/product_info_1.md b/data/product_info_1.md new file mode 100644 index 00000000..bfe299f2 --- /dev/null +++ b/data/product_info_1.md @@ -0,0 +1,215 @@ +# Information about product item_number: 1 +TrailMaster X4 Tent, price $250, + +## Brand +OutdoorLiving + +## Category +Tents + +## Features +- Polyester material for durability +- Spacious interior to accommodate multiple people +- Easy setup with included instructions +- Water-resistant construction to withstand light rain +- Mesh panels for ventilation and insect protection +- Rainfly included for added weather protection +- Multiple doors for convenient entry and exit +- Interior pockets for organizing small items +- Reflective guy lines for improved visibility at night +- Freestanding design for easy setup and relocation +- Carry bag included for convenient storage and transportation + +## Technical Specs +**Best Use**: Camping +**Capacity**: 4-person +**Season Rating**: 3-season +**Setup**: Freestanding +**Material**: Polyester +**Waterproof**: Yes +**Floor Area**: 80 square feet +**Peak Height**: 6 feet +**Number of Doors**: 2 +**Color**: Green +**Rainfly**: Included +**Rainfly Waterproof Rating**: 2000mm +**Tent Poles**: Aluminum +**Pole Diameter**: 9mm +**Ventilation**: Mesh panels and adjustable vents +**Interior Pockets**: Yes (4 pockets) +**Gear Loft**: Included +**Footprint**: Sold separately +**Guy Lines**: Reflective +**Stakes**: Aluminum +**Carry Bag**: Included +**Dimensions**: 10ft x 8ft x 6ft (length x width x peak height) +**Packed Size**: 24 inches x 8 inches +**Weight**: 12 lbs + +## TrailMaster X4 Tent User Guide + +### Introduction + +Thank you for choosing the TrailMaster X4 Tent. This user guide provides instructions on how to set up, use, and maintain your tent effectively. Please read this guide thoroughly before using the tent. + +### Package Contents + +Ensure that the package includes the following components: + +- TrailMaster X4 Tent body +- Tent poles +- Rainfly (if applicable) +- Stakes and guy lines +- Carry bag +- User Guide + +If any components are missing or damaged, please contact our customer support immediately. + +### Tent Setup + +#### Step 1: Selecting a Suitable Location + +- Find a level and clear area for pitching the tent. +- Remove any sharp objects or debris that could damage the tent floor. + +#### Step 2: Unpacking and Organizing Components + +- Lay out all the tent components on the ground. +- Familiarize yourself with each part, including the tent body, poles, rainfly, stakes, and guy lines. + +#### Step 3: Assembling the Tent Poles + +- Connect the tent poles according to their designated color codes or numbering. +- Slide the connected poles through the pole sleeves or attach them to the tent body clips. + +#### Step 4: Setting up the Tent Body + +- Begin at one end and raise the tent body by pushing up the poles. +- Ensure that the tent body is evenly stretched and centered. +- Secure the tent body to the ground using stakes and guy lines as needed. + +#### Step 5: Attaching the Rainfly (if applicable) + +- If your tent includes a rainfly, spread it over the tent body. +- Attach the rainfly to the tent corners and secure it with the provided buckles or clips. +- Adjust the tension of the rainfly to ensure proper airflow and weather protection. + +#### Step 6: Securing the Tent + +- Stake down the tent corners and guy out the guy lines for additional stability. +- Adjust the tension of the guy lines to provide optimal stability and wind resistance. + +### Tent Takedown and Storage + +#### Step 1: Removing Stakes and Guy Lines + +- Remove all stakes from the ground. +- Untie or disconnect the guy lines from the tent and store them separately. + +#### Step 2: Taking Down the Tent Body + +- Start by collapsing the tent poles carefully. +- Remove the poles from the pole sleeves or clips. +- Collapse the tent body and fold it neatly. + +#### Step 3: Disassembling the Tent Poles + +- Disconnect and separate the individual pole sections. +- Store the poles in their designated bag or sleeve. + +#### Step 4: Packing the Tent + +- Fold the tent body tightly and place it in the carry bag. +- Ensure that the rainfly and any other components are also packed securely. + +### Tent Care and Maintenance + +- Clean the tent regularly with mild soap and water. +- Avoid using harsh chemicals or abrasive cleaners. +- Allow the tent to dry completely before storing it. +- Store the tent in a cool, dry place away from direct sunlight. + +## Cautions +1. **Avoid Uneven or Rocky Surfaces**: Do not place the tent on uneven or rocky surfaces. +2. **Stay Clear of Hazardous Areas**: Avoid setting up the tent near hazardous areas. +3. **No Open Flames or Heat Sources**: Do not use open flames, candles, or any other flammable heat sources near the tent. +4. **Avoid Overloading**: Do not exceed the maximum weight capacity or overload the tent with excessive gear or equipment. +5. **Don't Leave Unattended**: Do not leave the tent unattended while open or occupied. +6. **Avoid Sharp Objects**: Keep sharp objects away from the tent to prevent damage to the fabric or punctures. +7. **Avoid Using Harsh Chemicals**: Do not use harsh chemicals or abrasive cleaners on the tent, as they may damage the material. +8. **Don't Store Wet**: Do not store the tent when it is wet or damp, as it can lead to mold, mildew, or fabric deterioration. +9. **Avoid Direct Sunlight**: Avoid prolonged exposure of the tent to direct sunlight, as it can cause fading or weakening of the fabric. +10. **Don't Neglect Maintenance**: Regularly clean and maintain the tent according to the provided instructions to ensure its longevity and performance. + +## Warranty Information +Thank you for purchasing the TrailMaster X4 Tent. We are confident in the quality and durability of our product. This warranty provides coverage for any manufacturing defects or issues that may arise during normal use of the tent. Please read the terms and conditions of the warranty below: + +1. **Warranty Coverage**: The TrailMaster X4 Tent is covered by a **2-year limited warranty** from the date of purchase. This warranty covers manufacturing defects in materials and workmanship. + +2. **What is Covered**: + - Seam or fabric tears that occur under normal use and are not a result of misuse or abuse. + - Issues with the tent poles, zippers, buckles, or other hardware components that affect the functionality of the tent. + - Problems with the rainfly or other included accessories that impact the performance of the tent. + +3. **What is Not Covered**: + - Damage caused by misuse, abuse, or improper care of the tent. + - Normal wear and tear or cosmetic damage that does not affect the functionality of the tent. + - Damage caused by extreme weather conditions, natural disasters, or acts of nature. + - Any modifications or alterations made to the tent by the user. + +4. **Claim Process**: + - In the event of a warranty claim, please contact our customer support (contact details provided in the user guide) to initiate the process. + - Provide proof of purchase, including the date and place of purchase, along with a detailed description and supporting evidence of the issue. + +5. **Resolution Options**: + - Upon receipt of the warranty claim, our customer support team will assess the issue and determine the appropriate resolution. + - Options may include repair, replacement of the defective parts, or, if necessary, replacement of the entire tent. + +6. **Limitations and Exclusions**: + - Our warranty is non-transferable and applies only to the original purchaser of the TrailMaster X4 Tent. + - The warranty does not cover any incidental or consequential damages resulting from the use or inability to use the tent. + - Any unauthorized repairs or alterations void the warranty. + +### Contact Information + +If you have any questions or need further assistance, please contact our customer support: + +- Customer Support Phone: +1-800-123-4567 +- Customer Support Email: support@example.com + +## Return Policy +- **If Membership status "None ":** Returns are accepted within 30 days of purchase, provided the tent is unused, undamaged and in its original packaging. Customer is responsible for the cost of return shipping. Once the returned item is received, a refund will be issued for the cost of the item minus a 10% restocking fee. If the item was damaged during shipping or if there is a defect, the customer should contact customer service within 7 days of receiving the item. +- **If Membership status "Gold":** Returns are accepted within 60 days of purchase, provided the tent is unused, undamaged and in its original packaging. Free return shipping is provided. Once the returned item is received, a full refund will be issued. If the item was damaged during shipping or if there is a defect, the customer should contact customer service within 7 days of receiving the item. +- **If Membership status "Platinum":** Returns are accepted within 90 days of purchase, provided the tent is unused, undamaged and in its original packaging. Free return shipping is provided, and a full refund will be issued. If the item was damaged during shipping or if there is a defect, the customer should contact customer service within 7 days of receiving the item. + +## Reviews +1) **Rating:** 5 + **Review:** I am extremely happy with my TrailMaster X4 Tent! It's spacious, easy to set up, and kept me dry during a storm. The UV protection is a great addition too. Highly recommend it to anyone who loves camping! + +2) **Rating:** 3 + **Review:** I bought the TrailMaster X4 Tent, and while it's waterproof and has a spacious interior, I found it a bit difficult to set up. It's a decent tent, but I wish it were easier to assemble. + +3) **Rating:** 5 + **Review:** The TrailMaster X4 Tent is a fantastic investment for any serious camper. The easy setup and spacious interior make it perfect for extended trips, and the waterproof design kept us dry in heavy rain. + +4) **Rating:** 4 + **Review:** I like the TrailMaster X4 Tent, but I wish it came in more colors. It's comfortable and has many useful features, but the green color just isn't my favorite. Overall, it's a good tent. + +5) **Rating:** 5 + **Review:** This tent is perfect for my family camping trips. The spacious interior and convenient storage pocket make it easy to stay organized. It's also super easy to set up, making it a great addition to our gear. + +## FAQ +1) Can the TrailMaster X4 Tent be used in winter conditions? + The TrailMaster X4 Tent is designed for 3-season use and may not be suitable for extreme winter conditions with heavy snow and freezing temperatures. + +2) How many people can comfortably sleep in the TrailMaster X4 Tent? + The TrailMaster X4 Tent can comfortably accommodate up to 4 people with room for their gear. + +3) Is there a warranty on the TrailMaster X4 Tent? + Yes, the TrailMaster X4 Tent comes with a 2-year limited warranty against manufacturing defects. + +4) Are there any additional accessories included with the TrailMaster X4 Tent? + The TrailMaster X4 Tent includes a rainfly, tent stakes, guy lines, and a carry bag for easy transport. + +5) Can the TrailMaster X4 Tent be easily carried during hikes? + Yes, the TrailMaster X4 Tent weighs just 12lbs, and when packed in its carry bag, it can be comfortably carried during hikes. From b6c25426368f5d47286328e79b446ae33b41f33a Mon Sep 17 00:00:00 2001 From: e-straight Date: Mon, 4 Nov 2024 13:14:08 -0500 Subject: [PATCH 038/180] updated quickstart guide --- quickstart.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/quickstart.md b/quickstart.md index 7d4da73f..6518254a 100644 --- a/quickstart.md +++ b/quickstart.md @@ -55,14 +55,14 @@ Follow these steps to set up your hub and project: > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. ```console - az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus2 --kind OpenAI --sku s0 + az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus --kind OpenAI --sku s0 ``` Alternatively, you can create an AI Services resource: ```console - az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus2 + az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus ``` @@ -113,7 +113,7 @@ Follow these steps to set up your hub and project: 1. Create a Project. - 1. Run the following command to find your ARM Template: + 1. Run the following command to find your ARM ID: ```console az ml workspace show -n {my_hub_name} --resource-group {my_resource_group} --query id @@ -131,8 +131,8 @@ Depending on your programming language of choice install the SDK using the follo ### Python -1. Download the [Python .whl file](./packages/azure_ai_project-1.0.0b1-py3-none-any.whl) to your project directory. -1. Install the SDK with `pip install azure_ai_project-1.0.0b1-py3-none-any.whl --user --force-reinstall` +1. Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. +1. Install the SDK with `pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall` >[!NOTE] > We recommend creating a virtual environment with [venv](https://docs.python.org/3/library/venv.html). @@ -175,8 +175,8 @@ Use the following code to create and run an agent. #Install the azure-identity SDK # %pip install azure-identity import os -from azure.ai.project import * -from azure.ai.project.models import * +from azure.ai.projects import * +from azure.ai.projects.models import * from azure.identity import DefaultAzureCredential from typing import Any From 800dd2e2d05b655b6352dd2525918b401bfcca00 Mon Sep 17 00:00:00 2001 From: e-straight Date: Mon, 4 Nov 2024 13:37:24 -0500 Subject: [PATCH 039/180] Got rid of C# and edited some commands --- quickstart.md | 90 ++++----------------------------------------------- 1 file changed, 7 insertions(+), 83 deletions(-) diff --git a/quickstart.md b/quickstart.md index 6518254a..c4834ac4 100644 --- a/quickstart.md +++ b/quickstart.md @@ -125,21 +125,6 @@ Follow these steps to set up your hub and project: az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} ``` -## Install the SDK package - -Depending on your programming language of choice install the SDK using the following steps: - -### Python - -1. Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. -1. Install the SDK with `pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall` - >[!NOTE] - > We recommend creating a virtual environment with [venv](https://docs.python.org/3/library/venv.html). - -### C# - -TBD - ## Configure and run your first agent @@ -159,21 +144,18 @@ Use the following code to create an agent and send a message to it. This agent w > [!NOTE] > You can find [C# code below](#c). -Run the following command to install the python package. +Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. + +Run the following commands to install the python packages. ```console -python -m pip install azure-ai-project azure-identity +pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall azure-identity +pip install azure-identity ``` Use the following code to create and run an agent. ```python -#Make sure to download nifty_500_quarterly_results.csv from the `data` folder before starting -#First install the azure-ai-project sdk using the whl file provided in the repo -# %pip install --force-reinstall azure_ai_project-1.0.0b1-py3-none-any.whl - -#Install the azure-identity SDK -# %pip install azure-identity import os from azure.ai.projects import * from azure.ai.projects.models import * @@ -182,6 +164,7 @@ from typing import Any # Create an Azure AI Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" +# HostName can be found by navigating to your discovery_url and removing the leading "https://" and trailing "/discovery" # Customer needs to login to Azure subscription via Azure CLI and set the environment variables project_client = AIProjectClient.from_connection_string( @@ -253,63 +236,4 @@ with project_client: ``` ## C# - -Use the following package in your C# project - -```console -dotnet add package Azure.AI.Project --prerelease -``` - -Then use the following sample code to create an agent. - -```csharp -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Azure.Identity; -using NUnit.Framework; - -namespace Azure.AI.Projects.Tests -{ - public class Sample_Agent_Streaming - { - public async Task Streaming() - { - var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); - AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); - - Response agentResponse = await client.CreateAgentAsync( - model: "gpt-4-1106-preview", - name: "My Friendly Test Agent", - instructions: "You politely help with math questions. Use the code interpreter tool when asked to visualize numbers.", - tools: new List { new CodeInterpreterToolDefinition() }); - Agent agent = agentResponse.Value; - - Response threadResponse = await client.CreateThreadAsync(); - AgentThread thread = threadResponse.Value; - - Response messageResponse = await client.CreateMessageAsync( - thread.Id, - MessageRole.User, - "Hi, Agent! Draw a graph for a line with a slope of 4 and y-intercept of 9."); - ThreadMessage message = messageResponse.Value; - - await foreach (StreamingUpdate streamingUpdate in client.CreateRunStreamingAsync(thread.Id, agent.Id)) - { - if (streamingUpdate.UpdateKind == StreamingUpdateReason.RunCreated) - { - Console.WriteLine($"--- Run started! ---"); - } - else if (streamingUpdate is MessageContentUpdate contentUpdate) - { - Console.Write(contentUpdate.Text); - if (contentUpdate.ImageFileId is not null) - { - Console.WriteLine($"[Image content file ID: {contentUpdate.ImageFileId}"); - } - } - } - } - } -} -``` +C# support coming soon! \ No newline at end of file From 76e79120f94827645a7af53d64db834cb752cf57 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 4 Nov 2024 10:43:48 -0800 Subject: [PATCH 040/180] file updates --- .../{python-sample.py => bing-python.py} | 0 samples/bing-search/csharp-sample.cs | 36 ---- samples/code-interpreter/csharp-sample.cs | 60 ------ ...on-sample.py => python-code-inerpreter.py} | 0 samples/file-search/csharp-sample.cs | 96 ---------- ...python-sample.py => python-file-search.py} | 0 samples/function-calling/csharp-sample.cs | 176 ------------------ ...n-sample.py => python-function-calling.py} | 0 samples/openapi/csharp-sample.cs | 51 ----- .../{python-sample.py => python-openapi.py} | 0 10 files changed, 419 deletions(-) rename samples/bing-search/{python-sample.py => bing-python.py} (100%) delete mode 100644 samples/bing-search/csharp-sample.cs delete mode 100644 samples/code-interpreter/csharp-sample.cs rename samples/code-interpreter/{python-sample.py => python-code-inerpreter.py} (100%) delete mode 100644 samples/file-search/csharp-sample.cs rename samples/file-search/{python-sample.py => python-file-search.py} (100%) delete mode 100644 samples/function-calling/csharp-sample.cs rename samples/function-calling/{python-sample.py => python-function-calling.py} (100%) delete mode 100644 samples/openapi/csharp-sample.cs rename samples/openapi/{python-sample.py => python-openapi.py} (100%) diff --git a/samples/bing-search/python-sample.py b/samples/bing-search/bing-python.py similarity index 100% rename from samples/bing-search/python-sample.py rename to samples/bing-search/bing-python.py diff --git a/samples/bing-search/csharp-sample.cs b/samples/bing-search/csharp-sample.cs deleted file mode 100644 index c894fd5b..00000000 --- a/samples/bing-search/csharp-sample.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using Azure.Identity; -using Azure.AI.Projects; -using Azure.AI.Projects.Models; -using Azure.AI.ML.Entities; - -class Program -{ - static void Main(string[] args) - { - // Ensure the environment variable is set - string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); - if (string.IsNullOrEmpty(connectionString)) - { - Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); - return; - } - - // Create an Azure AI Client from a connection string - var credential = new DefaultAzureCredential(); - var projectClient = AIProjectClient.FromConnectionString(credential, connectionString); - - // Create a connection to the Grounding with Bing Search resource - string connectionName = "bing_grounding_connection"; - string target = "GROUNDING_WITH_BING_SEARCH_API"; - - var wpsConnection = new WorkspaceConnection - { - Name = connectionName, - Type = "custom", - Target = target - }; - - // Additional code to use the projectClient and wpsConnection can be added here - } -} \ No newline at end of file diff --git a/samples/code-interpreter/csharp-sample.cs b/samples/code-interpreter/csharp-sample.cs deleted file mode 100644 index e98cd7cb..00000000 --- a/samples/code-interpreter/csharp-sample.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.IO; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; - -class Program -{ - private static readonly string apiKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"); - private static readonly string apiVersion = "2024-05-01-preview"; - private static readonly string azureEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"); - - static async Task Main(string[] args) - { - var client = new HttpClient(); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); - - // Upload a file with an "assistants" purpose - var fileContent = new StreamContent(File.OpenRead("speech.py")); - var fileRequest = new MultipartFormDataContent(); - fileRequest.Add(fileContent, "file", "speech.py"); - fileRequest.Add(new StringContent("assistants"), "purpose"); - - var fileResponse = await client.PostAsync($"{azureEndpoint}/v1/files?api-version={apiVersion}", fileRequest); - var fileResponseBody = await fileResponse.Content.ReadAsStringAsync(); - var fileId = JObject.Parse(fileResponseBody)["id"].ToString(); - - // Create an assistant using the file ID - var assistantRequest = new - { - instructions = "You are an AI assistant that can write code to help answer math questions.", - model = "gpt-4-1106-preview", - tools = new[] { new { type = "code_interpreter" } }, - tool_resources = new { code_interpreter = new { file_ids = new[] { fileId } } } - }; - - var assistantResponse = await client.PostAsJsonAsync($"{azureEndpoint}/v1/assistants?api-version={apiVersion}", assistantRequest); - var assistantResponseBody = await assistantResponse.Content.ReadAsStringAsync(); - var assistantId = JObject.Parse(assistantResponseBody)["id"].ToString(); - - // Create a thread with the assistant - var threadRequest = new - { - messages = new[] - { - new - { - role = "user", - content = "I need to solve the equation `3x + 11 = 14`. Can you help me?", - file_ids = new[] { fileId } - } - } - }; - - var threadResponse = await client.PostAsJsonAsync($"{azureEndpoint}/v1/threads?api-version={apiVersion}", threadRequest); - var threadResponseBody = await threadResponse.Content.ReadAsStringAsync(); - Console.WriteLine(threadResponseBody); - } -} \ No newline at end of file diff --git a/samples/code-interpreter/python-sample.py b/samples/code-interpreter/python-code-inerpreter.py similarity index 100% rename from samples/code-interpreter/python-sample.py rename to samples/code-interpreter/python-code-inerpreter.py diff --git a/samples/file-search/csharp-sample.cs b/samples/file-search/csharp-sample.cs deleted file mode 100644 index 851e9a6d..00000000 --- a/samples/file-search/csharp-sample.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Azure.Identity; -using NUnit.Framework; - -namespace Azure.AI.Projects.Tests -{ - public partial class Sample_Agent_FileSearch - { - [Test] - public async Task FilesSearchExample() - { - var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); - AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); - - #region Snippet:UploadAgentFilesToUse - // Upload a file and wait for it to be processed - File.WriteAllText( - path: "sample_file_for_upload.txt", - contents: "The word 'apple' uses the code 442345, while the word 'banana' uses the code 673457."); - Response uploadAgentFileResponse = await client.UploadFileAsync( - filePath: "sample_file_for_upload.txt", - purpose: AgentFilePurpose.Agents); - - AgentFile uploadedAgentFile = uploadAgentFileResponse.Value; - #endregion - - #region Snippet:CreateVectorStore - // Create a vector store with the file and wait for it to be processed. - // If you do not specify a vector store, create_message will create a vector store with a default expiration policy of seven days after they were last active - VectorStore vectorStore = await client.CreateVectorStoreAsync( - fileIds: new List { uploadedAgentFile.Id }, - name: "my_vector_store"); - #endregion - - #region Snippet:CreateAgentWithFiles - FileSearchToolResource fileSearchToolResource = new FileSearchToolResource(); - fileSearchToolResource.VectorStoreIds.Add(vectorStore.Id); - - // Create an agent with toolResources and process the agent run - Response agentResponse = await client.CreateAgentAsync( - model: "gpt-4-1106-preview", - name: "SDK Test Agent - Retrieval", - instructions: "You are a helpful agent that can help fetch data from files you know about.", - tools: new List { new FileSearchToolDefinition() }, - toolResources: new ToolResources() { FileSearch = fileSearchToolResource }); - Agent agent = agentResponse.Value; - #endregion - - // Create thread for communication - Response threadResponse = await client.CreateThreadAsync(); - AgentThread thread = threadResponse.Value; - - // Create message to thread - Response messageResponse = await client.CreateMessageAsync( - thread.Id, - MessageRole.User, - "Can you give me the documented codes for 'banana' and 'orange'?"); - ThreadMessage message = messageResponse.Value; - - // Run the agent - Response runResponse = await client.CreateRunAsync(thread, agent); - - do - { - await Task.Delay(TimeSpan.FromMilliseconds(500)); - runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); - } - while (runResponse.Value.Status == RunStatus.Queued - || runResponse.Value.Status == RunStatus.InProgress); - - Response> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id); - IReadOnlyList messages = afterRunMessagesResponse.Value.Data; - - // Note: messages iterate from newest to oldest, with the messages[0] being the most recent - foreach (ThreadMessage threadMessage in messages) - { - Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); - foreach (MessageContent contentItem in threadMessage.ContentItems) - { - if (contentItem is MessageTextContent textItem) - { - Console.Write(textItem.Text); - } - else if (contentItem is MessageImageFileContent imageFileItem) - { - Console.Write($""); - } - Console.WriteLine(); - } - } - } - } -} \ No newline at end of file diff --git a/samples/file-search/python-sample.py b/samples/file-search/python-file-search.py similarity index 100% rename from samples/file-search/python-sample.py rename to samples/file-search/python-file-search.py diff --git a/samples/function-calling/csharp-sample.cs b/samples/function-calling/csharp-sample.cs deleted file mode 100644 index fe4ad03b..00000000 --- a/samples/function-calling/csharp-sample.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text.Json; -using System.Threading.Tasks; -using Azure.Identity; -using NUnit.Framework; - -namespace Azure.AI.Projects.Tests -{ - public partial class Sample_Agent_Functions - { - [Test] - public async Task FunctionCallingExample() - { - var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); - AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); - - #region Snippet:FunctionsDefineFunctionTools - // Example of a function that defines no parameters - string GetUserFavoriteCity() => "Seattle, WA"; - FunctionToolDefinition getUserFavoriteCityTool = new("getUserFavoriteCity", "Gets the user's favorite city."); - - // Example of a function with a single required parameter - string GetCityNickname(string location) => location switch - { - "Seattle, WA" => "The Emerald City", - _ => throw new NotImplementedException(), - }; - FunctionToolDefinition getCityNicknameTool = new( - name: "getCityNickname", - description: "Gets the nickname of a city, e.g. 'LA' for 'Los Angeles, CA'.", - parameters: BinaryData.FromObjectAsJson( - new - { - Type = "object", - Properties = new - { - Location = new - { - Type = "string", - Description = "The city and state, e.g. San Francisco, CA", - }, - }, - Required = new[] { "location" }, - }, - new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); - - // Example of a function with one required and one optional, enum parameter - string GetWeatherAtLocation(string location, string temperatureUnit = "f") => location switch - { - "Seattle, WA" => temperatureUnit == "f" ? "70f" : "21c", - _ => throw new NotImplementedException() - }; - FunctionToolDefinition getCurrentWeatherAtLocationTool = new( - name: "getCurrentWeatherAtLocation", - description: "Gets the current weather at a provided location.", - parameters: BinaryData.FromObjectAsJson( - new - { - Type = "object", - Properties = new - { - Location = new - { - Type = "string", - Description = "The city and state, e.g. San Francisco, CA", - }, - Unit = new - { - Type = "string", - Enum = new[] { "c", "f" }, - }, - }, - Required = new[] { "location" }, - }, - new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); - #endregion - - #region Snippet:FunctionsHandleFunctionCalls - ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall) - { - if (toolCall is RequiredFunctionToolCall functionToolCall) - { - if (functionToolCall.Name == getUserFavoriteCityTool.Name) - { - return new ToolOutput(toolCall, GetUserFavoriteCity()); - } - using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); - if (functionToolCall.Name == getCityNicknameTool.Name) - { - string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString(); - return new ToolOutput(toolCall, GetCityNickname(locationArgument)); - } - if (functionToolCall.Name == getCurrentWeatherAtLocationTool.Name) - { - string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString(); - if (argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unitElement)) - { - string unitArgument = unitElement.GetString(); - return new ToolOutput(toolCall, GetWeatherAtLocation(locationArgument, unitArgument)); - } - return new ToolOutput(toolCall, GetWeatherAtLocation(locationArgument)); - } - } - return null; - } - #endregion - - #region Snippet:FunctionsCreateAgentWithFunctionTools - // note: parallel function calling is only supported with newer models like gpt-4-1106-preview - Response agentResponse = await client.CreateAgentAsync( - model: "gpt-4-1106-preview", - name: "SDK Test Agent - Functions", - instructions: "You are a weather bot. Use the provided functions to help answer questions. " - + "Customize your responses to the user's preferences as much as possible and use friendly " - + "nicknames for cities whenever possible.", - tools: new List { getUserFavoriteCityTool, getCityNicknameTool, getCurrentWeatherAtLocationTool } - ); - Agent agent = agentResponse.Value; - #endregion - - Response threadResponse = await client.CreateThreadAsync(); - AgentThread thread = threadResponse.Value; - - Response messageResponse = await client.CreateMessageAsync( - thread.Id, - MessageRole.User, - "What's the weather like in my favorite city?"); - ThreadMessage message = messageResponse.Value; - - Response runResponse = await client.CreateRunAsync(thread, agent); - - #region Snippet:FunctionsHandlePollingWithRequiredAction - do - { - await Task.Delay(TimeSpan.FromMilliseconds(500)); - runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); - - if (runResponse.Value.Status == RunStatus.RequiresAction - && runResponse.Value.RequiredAction is SubmitToolOutputsAction submitToolOutputsAction) - { - List toolOutputs = new(); - foreach (RequiredToolCall toolCall in submitToolOutputsAction.ToolCalls) - { - toolOutputs.Add(GetResolvedToolOutput(toolCall)); - } - runResponse = await client.SubmitToolOutputsToRunAsync(runResponse.Value, toolOutputs); - } - } - while (runResponse.Value.Status == RunStatus.Queued - || runResponse.Value.Status == RunStatus.InProgress); - #endregion - - Response> afterRunMessagesResponse = await client.GetMessagesAsync(thread.Id); - IReadOnlyList messages = afterRunMessagesResponse.Value.Data; - - // Note: messages iterate from newest to oldest, with the messages[0] being the most recent - foreach (ThreadMessage threadMessage in messages) - { - Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); - foreach (MessageContent contentItem in threadMessage.ContentItems) - { - if (contentItem is MessageTextContent textItem) - { - Console.Write(textItem.Text); - } - else if (contentItem is MessageImageFileContent imageFileItem) - { - Console.Write($""); - } - Console.WriteLine(); - } - } - } - } -} \ No newline at end of file diff --git a/samples/function-calling/python-sample.py b/samples/function-calling/python-function-calling.py similarity index 100% rename from samples/function-calling/python-sample.py rename to samples/function-calling/python-function-calling.py diff --git a/samples/openapi/csharp-sample.cs b/samples/openapi/csharp-sample.cs deleted file mode 100644 index aa099d39..00000000 --- a/samples/openapi/csharp-sample.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Threading.Tasks; -using Azure.Identity; -using Azure.AI.Projects; -using Azure.AI.Projects.Models; - -class Program -{ - static async Task Main(string[] args) - { - // Ensure the environment variable is set - string connectionString = Environment.GetEnvironmentVariable("PROJECT_CONNECTION_STRING"); - if (string.IsNullOrEmpty(connectionString)) - { - Console.WriteLine("Please set the PROJECT_CONNECTION_STRING environment variable."); - return; - } - - // Create an Azure AI Client from a connection string - var credential = new DefaultAzureCredential(); - var projectClient = new AIProjectClient(connectionString, credential); - - // Create an agent and run user's request with function calls - var agent = await projectClient.Agents.CreateAgentAsync(new CreateAgentOptions - { - Model = "gpt-4-1106-preview", - Name = "my-agent", - Instructions = "You are a helpful agent", - Tools = new[] - { - new Tool - { - Type = "openapi", - OpenApi = new OpenApiTool - { - Name = "mytool", - Description = "My tool", - Spec = new OpenApiSpec - { - OpenApi = "3.0.0", - // - } - } - } - } - }); - - // Use the agent as needed - // ... - } -} \ No newline at end of file diff --git a/samples/openapi/python-sample.py b/samples/openapi/python-openapi.py similarity index 100% rename from samples/openapi/python-sample.py rename to samples/openapi/python-openapi.py From 8e753203cd5a2e19cdec5bf4ff4ff862e3cb17de Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 4 Nov 2024 10:44:50 -0800 Subject: [PATCH 041/180] adding whl --- .../azure_ai_projects-1.0.0b1-py3-none-any.whl | Bin 0 -> 153467 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/azure_ai_projects-1.0.0b1-py3-none-any.whl diff --git a/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl b/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..06dffa63c4af553f115f5d1d93b492acf2c0eb40 GIT binary patch literal 153467 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%0D4q)o$0q=ep2Zx9H_ZM-^cI~K9u&<3PgPIuS%E!- zDwx-}&+=*v8Fjg#!7j_56t_e2^K-;EB|_P|D^5gV;trh_lhzV7x-ZTBV)#FMTK@~* zSb7(hLBjw5SIhvwfBBpLTL#O)(8bu|e=Azr+y7;6kbN2Ee*I7RvbLR%B&Z$y5cqWB zns`CZ?dD5b5k&Ktk&PdTBe~+84(LC6ccVz9mO|+!$F>Ix)Os?d|AZ{pxB0RwkC25f>+QMjyI#2i_Nns?g!DxxBrpH2$qw!}X zVo*4-qv@5)heCYKO@@iVh5V`+fW=m51=aq$48@QVKU@OkAvft0L1|tj-ZLKYMTFgP z>?o@$IpWysPa(q6#u(N&ePF0&m$Eg|bO7c%kUQ_5b$mK7gZ>?yMyW)`!`^Y^r-)5h zToLA%#PUZ5f1MF=NG(w>i+LngbEHSp0?MjR1yy^PoALu$fNf?1%}phC`DhNR4Ten0 z0AJ%>PhS46GUG1BoA>}QI+fgD!krjT-B|;!eKpndArp+p5WO&blI@BkQ|-Ail2a~= zrh--uLxE?H)MMkS3dUq?_#6A9>debR5tX`Bil5n+r|mJ?;vj8$K>J6d9+^=}BNbh@ zpR@AAs*@M=45la{PH)irM!2ki&4O4Yb17#Rk>{6CQ zGUg$3ccRaLankL59%nWqRQ?f*eR3G<3vq{`YyyXRqjSx}2qzZXmxIY%x6k*TL?YS{ zxtJgyACb8)MQ>QxG);&4(aCD1{^^na9u$xb$i8Bh*?xDvRDyWTO5Q^RZ@g^Fvawlp zRYtUl2V42uy(co1s;wMbB9?r+2_=oGeWD2IVLUmhP5`b1qrr69bZvXNw++ryo^h;S zjqy3kLVbz2)V0ayTILY17hLVxp;r4OP!0*Uv;8EpOe~25loE$B!J|HCmP!^F32+bq z9SVVwi9|xzO9y$niKv#jFOd(l&5N%b&0480=S*NUS7(G%6E&BRWwi6YNYdaHiNhPz zF0&7I&^_-xf-2Zbf9M`L4~iNH%Ao3z&I~wfS`hYik#MocVp+%&0qOnW99y11_ml`Z z7AYT^V?Y8u68$|oK1`4-5A;H$jX8+e%e#%da98Ak&=`7aX3Voh>}YXwmVF)TlNFY( zK_!lNAg<~>C0&XLMTS9jxh@|`7f8m>1TH2s9jo8zg*zIk$(f}~%;7i9vUA56_fHsi zz|$zKko9D~TS8-WO#^MW5%_|!M1r5ECxwO^goOS zFg1X=R9K^eNF~?S88m>CAmH1PSENY@=G#y!*WPBY;J#aMyFM^7rhbH)#glG|0j`6Z z2V;2@JUTuao#b?jlb_pt?{{8LO%z$vi`NUg6%HJmbvF85EA3y0Q02pLJ6a@Wf-4hK zh8d)`y!{AsSUos!>zhyYtZAmEjCL-eK1+E@zc}uCv~)DZ;!8yagr>FF{GqdAr``jq zlxVEcyZaS1$5H9F&%pxtolaTTGTNYLzXSJP98mpN;j&cS7f(uBNnB1}@E2`WjBfI- zMOQN-!YDn|uvKtt+|PB#LE7uB5~ZR&^2K0*@k^D?4;BMwg#9{y<6|!@R`f#KF!1)% z9v=!i@KwR>izoI_mit`ardr0N6ZSvf?-|yf!UPXXWcmtPZn|h~6-SopfL0KVU369NCj6tOLho>l%9+t>$AX$;%iK>1y@9frn#VsFAiZ1xhMr(uQr$> z>vUmO*N^l6;qZztOo*oLf=Rl9N!vh*@6wt6@^}shCJqmsKOe>^oV{7LwwGTB0MZ$G zLQY81W$W!!4$sQXI-oUVe19rAgc6ll+!;g}#}CF~P9){59-S-LK~!_b5{}sbs{gSo zXAz|xWCc;pILJ8WpeX;3y@Z2K#_~V*|L_>98K$%Y7sCi;!-z$Hs?>Z5kVkcv?7N4E zw_L%$91Kd&nnO8DSk#L^f_5kYcbsmQzlwxo-%x_T?2uOX$nmp#tPPE1KN(^)jN$IaXzu)lButbaKv>Bm~u&{i-as?Ql>&P zO&9jmC6f-<^cyPXb~^%~aJ*{L^sexAl7mp82Cufl#)1r>hdG65CZL5xj z=|Dyi`v>apx^Bx_AGB{hJWt6iALQ0dP$l0C5z^PU3?z9?6uFgu!g`Gq1n>%q_$S_U z-R=tI?0~3m1-Zsu`8|Oh!lgwF zm6I)-QL$)fcM}`^mH5(L08G`S#nQ#h1o!&JG*n8u$SITT*~lE~Cz6)*TvA#i;c5FI z-(V!!d)0y;jP90}C+gBQgO*TXjvae%QwG(`Q=i|7X2D_>9agALw79P|YfTU>ws{lE zLn)ZYVr3umghOd%CCOzQ^LlEvB8*bX9LYnfPHXKcIV*cdHab|ew{?g{r>5j0C%A6) zr36Y_YqbU#1#W6HRb8WQpr-OBsaYG}CK!F}S0s7?@ROIY>NB|_HBnfob z#KS~BO>lkj&ZaOi*~uE^0(}Z$wPW=eu{n4&rk8~dN4dO!SDMhMj$TRCnmWS`Bm+kt zD^5$ZYK*yXOsIy1IQm@-DK*^=mu|f;I^V5jT@Wa?O80^4wMfuTSwlNDK%U2zfQt`FvhNq%&IL_<&q8b2aMWyAOZ)_GCF#wk*>Z zqj=Oseeq+b<+i^-&h5>k*u(n5Q^Qg>qf<{!>-6N9sI@Gr$pKRqK>I9mP`qwEiYabg z89AiIR9{EbQ-%=17pR+z*La#-(J=`A%EQt}(E5nJxqCUn#%&`0DCoJq{JCK?-#grl zzq<0ltNlY_fAPWtNi~~kKK*0yZu?BSSm9vsPRI2o3P1$JQ{Ffz8MO=I6II4>bO*v% zwUM~M1Y_}Gp!?^HRd6PJAUJ>l&+RrasskesUkbjO+%e{$Zo-d0N}<{g@6aWAK z2mrN=URkSfA)qTr000_N0RSTa003cnb#i4dVQDXLa&Ky7V{~&bUvp)0X<=+>dSP^F zZ*DGddF_2|cN@2r@b{jR|A3C49Fq-2+etRtYNKQoTTay4l8-DmZ5b_hM2@7X$r$!{KroqPKLGz9pxT&$}6@~RQNNngCoCskRO7Y#hG7G;$-d07m_{%j_wP%Wyg z&Z>9WbSUeeUS;Ct;i-6$PqL!UL=S%S<-1o|HP7oBK#05+S6P*vuf%1Q7ELxCh>I%A zM0p`5S7~*b4MbB4=&D#`RSgx&^Cr!Uytovpm;jCl4+=L|00|MiPOA*cPeoeSE|%xByuKRX`~vjzWdjdu zd`M$A!2UccD+E_(FysIvhb~aJ4USX{8(QG-HgdqI>FcX6?YYh0AGS$U0poRq~h$F9}8)*Pqj<-3f!#ne)i4Pecv;G8VXT+3JWRSJDL z&*bny<9UJ5QmbbbqERTYPmd7t^Wzh-FJA4RoE|=X^J4!*yn1u;>iG2mAn^t=uI8gQIfC1siyAuRO@b{b72O6e$cCh~fz`dsN zKXS^eNxn}Ghwvo9?!uBr`g&6o*(9s$v|6367TMutQC8X0a*ljs?;@Sm8CJWfU?H8S zb@tVlBA;VDasJhp(`-^sVg13^tiZ3I{6@Zp$1%}k*b5jE9=JRx>e`oVF zpUH-@VmVjM9Kd&7=)1dQ}@#0Ix|cAvdc9E@}Cy_sMSre4YVc z8}QftVkN&#(po({Uf?QBXY%Kp0-2yL|GKH3SX5_D@u)uNml0R{j|D38i zFP9Czb8BD``SnFkX!LOsnrgMnPpL1 zIHW=cRaI6Yh~XlwV5hPH>CwBH&xTn8JJaxBmLW}?;x3ie;@}iflBM#x#0d_Ym&2a^ zyacW_fk#6|h`5@p{0w(cV0Zb?w1E(k1Mxa|7Q%AsDR4(`fNubTuwiFM%h?Q(7=L&C zQtU}m7{ZV7o73mNA2R*+h<0K0_mX9EvGe-Q!1C z<&Upn)$e%|I)Z&|fK+mZFhBXtWCq)_I7zQfr!$-po)chn6Pm81$!?ki_KHagyQjF$ z9>UgDF0w+*^8$B{MOH3m*>E`IirDt}d7hYB|SYX|P(1w3+^9WaxuC@GE1~x1sLB@&zP$1P_bFvca)h&ZdYRRVBHC zyV6r=Gwn}Ff)ltJ`dG@$H9W*&MICYA+5%tRM4nscyx&?{$JLrcvuBKT9+gSA$`?|n04$L4l&D6QB zlk(SahQ${>r-3AzZ#*hvlL`fPUp!J+xTfaGo}ktDX(gp9r&cMp{4)IK*XK z_blxDZh5(p{yCj3Gun=j8)Q`#1Doc+v}4;^FQHum`kNQ;;MH_j+}9xNb?(H!U_<4YQ?(pGU zyjlVKFU04=f2CuQ1SS6R@&$9fdO|D-nmt6UU{NO6Z>F&X7^#04C<3HQ9n>HMo@#jp;F6JuPsV_^E(d_hC&F9G#wCwXh8PAeQC zj~Ddg)dFU)9{h7WN)3q5VUM4c#X~$MRisG(ae|Zv@G?eA^>TtoG{$ZW+;}-_fX>7I zhgD$)WbGCdEgmQ#N2v@Z5>_;-tOh)#D2(82TR(wJ268HSX~!TD2@-?EnFcAbQ8Fg$ zo?sNtXXWHAE2@xJXex+wk99E@%YrmhKa4!sAVWw~Hsr-P~FF!fY%bt5>Yf1J)Jk+ldX?Z&@Iq}E zQWk1vtL(p)S>4o+(!50MaUZ_Ef^#r1UIVILWRv_NpWykFkI<|{HYI+L;AvBYHc@qp z$A`oo=p-WYGlupk;cCF&N@Hks&Z|4kL2A_FhV@i0JE}4f)%PT{!{UWagEhqNhC{QX z@Bvy+-@#hKW3{R52ta)Nb7Vw!@Q}Bt&bsTugCh%#-0Ek;8qUy7FZs8mKY9$mNUrU} zMsb~0y}sS0 zpOLmY$K&SyvMEtBFRo#m2aM|+kf+lvwgLM->v;zp)MRNA^oX? zuDj_+&LrO8C6=n;5$-67C%9Xr8s$zX*vFLwrlzY1u*P1(IFg&_C%=(=8W5AJ!r^7s zynwGTXX9}Jg57xRDb~ibvba>;!SAgaHD4}tYUV{_>wDguKJ6(5=&<=YFD^>Oo?$_p z!c*}#lnd|$t^6zCI=FXWOI*=VYg?;p<7=NA2-mymCH$FYGd#LQ*S^_~yz;%reY?BO&p1zQeZ`@Jt#7_S zWj3Eu6?47E&NeNrgxz;`)mVR%zd4gRty`z@s06%LGZO9V^c@m|oX-30oZpCF_TJ|8 zs$5p}-jhBr3{RJ>(UwYF{Qfg83E)KI=lM-GJ!X>LM8S=P%-K_o7B58`ShyzJPleD) zs;QP%PO8`??!Otzu+$5l990Exk{`kGkhXJtEpeKbllJ-3<0Tu~wHh?N#MBP1&TgF`Spn z0uE<=@ko5})#Jzgu-~{yWxrd1Ctuqnb$j=XmSCw#i6Lo}1Nd!Awww54c*16cQ?4O<<9Qij6y>Gw%?N2}T ze;OtdQ|vCPX6b@|+*D~%<8Z?+{5D$+=+zi@{mB5Olcm%(`KBMs0QVxUz$r%}v&Pmh4hNi+b(K~XmVdclT!FsI zGMW){Czdstcf=6z_ZQ7`6^YPD^6;5KzgW&@c&KmEMLvcS|A4Va6vPRju>b0iN-xsp z>SLUMSq@wrjy`}#EoVZZU9VunzZtqyf#toqpsIU9tqXZ((D;rLD3F}>-H98G`9@%D zR>(YE;B58Y_G!z1i@YCUpM^7w`jc&Ec$?`X{fsqzAK%QK#PHDrCsj&epZpF^hgEh73n{C{ z8i^j4#-ZtJ2u?MlT9+;MlG{Xl28G~Ha))1GSlmgn3iCU2I-?u>9+R6j4=?i@Sa-Mp z$v|tC;}w`x`Orc3kIuPI% zRk_HjCU<;M=O?j7VeJ9(4MYgeKIQhH0um|RJz?#Q((d!cEx zzU(ER)_9&q7^!$$l-HJELDri@Q=hWpP+hjO&@@d3;_X05$5fCM5O#B<+I?%#Gm}IB z{fDEsXQ6lOk&D7PGx-OEsSX<9`7~x99e<s+TU>btm$Sxvx4ByD@cX)q9G>(2af|X<-*UI%c^lkg7bo3uGRf%r=mF0{RO_ zO%2%IJ&vD&X|`)?1cULB<$3c!*$aq3LEC(8&x zFeRz&Khv64bg%0?;B{h;_uBvTt^8KyQe3A6-v~R>-hkdspkXu|p{{VhnP=^r&WX$Noz>o=&}xk>|v(M`NB1j zoxVe{1q-E@nKVEur8GZV@eMgT0nE9VST{mfQ$Ihlf7 zCmtfjK4g;<@`+L)<~3c}(p4eK^bY|)Q%>tK*m7-Z=`-*{CPxbW3AZXW8OnTym#)X} zv|+I}|59Q;bvoc4ZmWmNB!Ky^wAoBa2_`SQb8`U=@UHT#N~_5gn#b6SoGh1c_#E_J zXWVFWh0X=pO^TKhweAo)t~q406JHBFSeS=_AmPG%dZpcc^_gpsDHKx!|P%w~{oKI>u?W z)vDTya#+er=xP`klQ1)i{o_{EC{F0#>RF?XS?Ll zG}7KoXUhKu-QPC#v(dF(*@CQ=*}p=H5ca0VS1FbqGL#I(b4y1p@v^{aP))U*H0TS) z9O`_9T}@$w360%C&lIl;s$Lpln=b*|MoLA~=O}M1gralphD{x@3nRrs*_dG^8RnKa zPvl08yZCig+BWWrt?F@Z;jPx(B6qbN%X&mbo3YnvP)|}H(}qhHdyWZK>~grB7Rjc| zlcl3HX?0N(rz=WlH^8GOumo*g^2Q>yqGk)|deR?Qg7umeK$|Di>}CEgqy1QDl)LEv zJ585breYyh6)+taJ>)+mxlGbJgUN?V)xy!5T2Xg2?7dpO z)=&h?w_AR(r+D8R!I<#!f9rkSdbjHj-5~~Wfk5T%Q=|2MGn*aLyTCV$l7k@Y-J2E{PMCR(w&#EmXF#r=v)Y} zl=_8`%Tb9I4tK#}P^crw@jbd^owGx}10c&jGP96wR54}kaTM{fLIVS&e{*y(vuF$l z;uf9*(L&(3E!jCZB48>DcS2CTE?ha4lF%Z4; zB{}<}0SXY3KCu})4RNzGuXlhaOsagI7bz6jL6C88I_K!Rx3{(vOeM;@A$+g6)|@?; zlm`Jd<8w4;;1zobLAJX)N<~GJ&ttm$im#M?fa~84*SRom8^_a0BO`xq3;vh zL6L7a!i@^>s+C=H^GP7*%evt(TEgKwEjmnP*r~Ac+6&A%WoH~Irx_FGlDT^Zo)HeH zP(O2RKCQv;GW(Q+Ev-N0FYK<1$(dzn*aggXHNvTosa3%Bfrn~$%UU?AZ=gYZY_$C53UM>y~B)C)^Fb;HMu=y}_75A`SpiEO0eqj{wt4xN9fi3d}CDY-Xqr<1i&kp)FfMt=x zdTwd#w|n#rouF>|PPI9l6!XO_sCXkj6)UXw*pP{}$GYaU^2lfD9-Tm9bkcRS@G)y! z<3B5fNs9;x)x0iue*e|uCxEJ9fmStm?+HLjburm_^5pX`+N!{NzY2`w%?^4Swbj7_ zex>P>W30B-QSXC#uzR%Dfp>oSF1+wv0H4DZwl=}9{aWY~+*SqO`Q_2UIjyR6)mBLt z2x?Mn#@1@|*000+71Z&lhM)VTM`vM4SeCw8ExEl5%T03!-knFV_QjZOi%#Tj)JwE9 z`g{nZ@2rix^}%_Uw`*KHyvp)c4aJ(V!^v$UL|VD-C3LIMP*6aJ9SUkvW2{~I{2Wl2 zTxIqnz^@@ygZ&WdrS`#*83noxf^-g3#hOG`AhJ)1dmZfw>6$(`+8N+n@@*ZN^V;F@ zg0Oh5MX$j?I~u1_|1 zI(k$%y>i<3B3d{{f{?;^#91}vy-fyDvh3U7EOUYYnDtIu_dBXwGZWpB)O^(!ol;17 z;>XY6%LDn!fH$V;`n2fWy8+?vM7!umtWlRrNh~_@mfDQ+7occqE%Rk>V<0-0MqFnb~K zrS1C=;4^S0RDJrJ`!nGOugvmd8L0GSzpTz0R|NHY%po3=QR_$jOWl4uiX<5GHP+3X1)v^2QQ0<=G5A*lo4LBHOi z0x7ZgOCon3XynZt3rsA%l7;5s6w?zXv69N8Jz@uazF5@ikU*(TecBD+?-i|s+WCj*=EIo4In zR%CzPck;0YF)s^$Uhljq+}?GJEU{_kV+xMrzS81o-v&xLCHuf!N0&9&)FCeQ`l>K` zZY84WHH^-yT(re=v_EnGYSa0F1l577(_J3?$rmB`XJf9eDnHLNbNnl2Beq9MS_mR_-H7;Te9Gy z3{5qe`xds5v1Z1hOkdRgXR*da`Q|Ze+F-@e!V2W`L2r4Zv|{v_p!0S^$QF4?`2-}MmG4-<1@2>yLhMiwA^rRfPiXcV}ec>i}xmI zDH5DsrD(LB@(m2tUQ5PBlU?Gilp!h-l~uZw?)pTdbgaM|!q{u5nk)) zvDtP|4Y&=5bwepj2W_Y@9BQ3SN&eX;jyQfSF$TR5)X%#%!2~~JtCITKQQA2jnjahV z3_G-Cf9&`ZR?8c#qj7jt7{BL!X%CS8K6<->sYeS!2*>;aNMX$_!sp9zvbG^87fT4! z#gIuQXj6$qpyzr~542umK=$VhH;&u9ChlpB5pM5r8l^fEeoQ!2va107sjvhk>+EY( zYy(=rmO9E?!|eDHcE1M*#iB#|{!&w0YmK35RQx(JK#ggj)@h70%0WX)2`3^>hqjn4 z!GA?P@x7{uWo3(crEV}Z5^mKe+XLmPm2G|BAJMu6Egn+}kuLqzz3$)~RHzrwBV?yO zkP*Q#L~$}YyLAMPu%*YBurwGaewx^G=iuYDs zhOLAuOuL~LNvX4aFAzq1?>)oS*a%<>wapTubomwpL=p|h|C-`blY?AYxa&%03P@-3 z5=gvWRvEjVGjCK1Gjh~8Ie2{4m9Sn@NOjv3-lZL6QuW?n| znDy(?39%<;TTMu}2gU|27V7g0TrKbu+os!v`ZZX0Y{l>8)p1XK#Ls&=h;$5-Ocdn| z$=G(Xv{oM_=Gb0cF1caUmuOAqp@^uEyeZU*IbWi0fpk0D6&NiK;a4 z-7a=tU{TEAY9_@E7Ip4N=y-GT!VM&fA3L%kv}Ix&s*DDzmI+1?iXHzbam9%o-YP?= z9zYL+b&X!X z%@<=zZJG43lW5J+)c`ID4Y{=xe=%mJw;&x*Blxx7H!tqY3lPUPlMi$&T+zY^P7LWq zwwFY_+#~WWa*LaZe<4qtLK6+(d#4SnX&P?thWglImaa_gBKgG4B;XQ^q0Iq6>aA8E zhzAht?U(>n`A9jyz%xVt;ETJJ(Rib@F*`t)oh)TH05ZH!(U3}|D?yV5y7p7Hr5Ovj->B(I~L;pyIJ3j{ZJ+vK#fgnwHESP-%ph;c?y(+TVEeA2E=V zY%nI7t48L0~Hc~~}PoW8BuD50nm$yw}_&Zm!2l2A2;6dM)rlu{ToEEkv; ze1u%#<6d;$5WTPNRA#n|q@hMP)LAYqPS;u8{))>{|i zr$L5Ohn7Nt#QgY7d}jR&#AnL#t18~dgllMLKH0JK-a-NDiqEXXjW6|#dQ79DGLPK; zwz|W*%t7$iFo~`I_ywKXhrE9DJ1_2HingG~9X{I=*bU3M?GMU++tK|hrkaG)8pfTf zDFY^>WjUu9jDv!_!%NQ$z~CJ}yw6?Qm~&}K_cwXYYQzrHXjb2>ALRw?F?td74W0O=T4b5!Wh zEm}B`s;g4GIeotKdmJiRXJC?tGkjVEpq(qrX1N#tjCmR!32i>5?Aqnuaxnw9F0+} z#0`{Ggwjf)zl)Py+CXze0ywq7cww0D<->=HHd;lSsS{DFC2z1-2M?j~MPt2*Q9NlH z?Zc@SqVRn4&T|cI-EJ(dXKgSXC<()Fg!@G3pTJSWWF#;tY{UN*MT2o&q0py7)Tm8j zImx-F4GiuL>7=sJC zAbWwJP_|V@G5#qYu5bNpxow3_b^330`)q}Z54?I)bt05xfs1So?DiGvgmgyD>ndGP zW+%svU-Z^q;=@DkyhrTU z*5XygmS?ho$XH$Ec-g2!w61YMXmfz`-#V$D?B-go-#jcvXa3~u!`4P4tTr;-aT4Q| z;OSa$6=gGb8Lj74vrQbBGVQKm`_ZrIpIb2)WIe<8G|E>0a1<;bV;sw4eeTFHymXF! z=n1|}#O}@_4$10(?N5@;A}!mKsra?5>)Wie%xYJN=(%DB>eeoXQD0c1Wp^wJ|GJ^t zge|7gqLal=sTgUEiHj|4t3gocw268KgAMG{L%GRRZ;_ntL5gv z{t^s9VX zF_!r9L5AP;0E`s$vo=MtX}%T|v2OF=PFT9LL$#M+w;hz?q}|ZaClW*V4b_*8VCQwY z4ctxRT5XK%#)x9UZGcX*S)fm7L0869TnC+F91frHzng*PvI?@PLfU8c2a*AEVF@2n zLUq=A>Fe{Ar>{%dqpN$BIG69r;(-sv-inR7hqc_q2EDMG-s3ohUHSn(-qBV<7Jk|z zyT7-vCHE&OZnel*_zC2!UyMm;ywbX-Mg|){+mV7gk7iyD zzHqSI60wmo2cs>AOP>?&iMa5VL#rTR01jUtQ=E5sx!#z&-^d73?R#JN*v0lEcOZ>N zE`DX88aSsRtlKS_Nrn7AO;;gvX*Qlm zeKfnDc|6VMzhEAnL*V^SC_?=J6B;|+stNu4ZrA$jPUuy+)DxN)OZ1?lA2sY8#ne5_ z%2Jc62nNuivrxusval+K zY94DwH)qk+#pIqjbmOn?ljlzm@Vkzh}5xUtpa|;90GObaQK8o2w zApn2Qi;FUH018v1sjiaOMo|i`s`c3_H8RFUIDIV{5dFl#hvD(RDSK;wg$H_yW)JVIH-n%v$E1hE~AB1Suy2-u$Z{^hCWN-l1izGx$> zN6_72Gap~WkF!BADEMkV4Kj#WKsbGq0t3HVpwMO-eM4M1-g54zZjmp5y;?6eU!Y2V z`vDi|)?(B>F3|9(zV%9l5&A$9Saj3=r&;|HH;b6XH{uWQ!NZ3A^lR~?HP+7YyR3qf z(zWCYKjgp)(i?;@XOlk9-w!{QI8h6u9dg8sVfA<5D7~-X#QGS|u=0e9-)HpZ3w{%H z#|9q3+G{%*V*DTbp<4wz5EZLW+vT#bQJY@~!&U|kJ92o3%`Pks;ew9aoDj-xpWtWm zH(TKlaTIeVa(id7sn78@)VsCBaBSb1+K|#rYO@Wgdw27&+K?4vKCchXi;ISiM}fKc zsSK4^Ws54q{Hc7?Eh*q$Idxua9$C`m)a{HKu*Koqf>Gxi-Z6h93|R^0Mbn$4v#gk= z6`fEo`3Az{(*1jq(%!(B3Y&qx`_5Oi4%J6hfu6JmbpK|QOx}0Nb*0hG%5eWtSPH>qZCDQ`I zYczD{6aOvtie{2n zel&6~ov|9Q_k`$;xBZh$k}U9Yo}HdL)#KJ9bl07tG4V<)O4L;HL|&9L*l@`Ej1zIQ zrxJyztFuh7%MMBuSy}{6>SU*!&YWnM%K{c4xiyjbIZW?$Hk(BkqI>zuV+WMQHs@xj zp6s4!`9;VNH0@p^0Z(%Pdp8sYYlRSV7yZ+d^56i6Tk42-jZ>$vBzC@|k@n$Wf06a)QI zyf-xNqg3TGGL)Gj%*7qa2+o4nsRJCN!f~rkacvq%eeo;dGdLd^U87wq44ESvpuJv} zm!h3*Bj^T~k#(}EX;u%@dS;>kL zK)YvvkhBne@_#h;9yHcLCz}vm8^JP-ja>(P+kYH|2d$2e!CFhe9`K72*t*;U4c8{4 z8@aRp@AwY_N^K0~Y-bG<8acb}B%2|9rSp`EGosO|K<$#N& zY~<3xk+kyKFi=S5k*mGLttAf!&KOl}N$J+=dBSs?I9a^}ad z)wQD$aoo@Y5& zKM*_OM@f0;xn-UnI-5vds~9n&XDR!PUy!mI5370^0Ig;mFJ`-f z#%6H{svmS(cBrj0@kOwu-0&X5q4Ma#!a-A9)i1|4+D=x(f&e<3#l5U7JBRro<$w8;7A=#|JGKB zgKjM?SbhZsr@GEK{CcbR#psMfaWz8LMP+gg!U0Fp^x~v?E$(wky&ljb9U7gdD-5Lx zXSapS(L)aBE_3u3g@b}RxXflOYx{d{>#&(67aukizsvzAk;3pXh>6BR#vP()5R3-) zo4o%iYkCjqm%>cANwR`j|81xYfAH~R$IyBV+;D`b$LNWqx@@H#&wmId?rXs`9NxWItq8X0vJ}7v@K>DB@Eqqf+qfqGJWN(z24j zai+9mI+N$QH5n)Y<5bA48r^48#xT2CP=X*=q(N@to(QZl;X?t3t982{Sj!q?|e#a&|AV=AFEnr65@6E9E8Vpewtk@U~oC(fbbFO*w=iNuKZ>{w5r~aaYDLmmbaVlm1O~ zrct^u97}tMDjQ$lalAorxU*3&&&fwqA^}na|ch~y+)9~A$roa2!x1*iU&b}Sd zqqA>!^*3WCLJ9!b#qwr6mVV=U(2phi9KD3q2&2n^ILU=qdDQjA&NselUHU{?7R!8O zxOJCYlGh~}5hS|~@iR2LJnVC<>}W&CP*;k|>`uU+-9kY7<*b#~QLWrDhB zlG9ZW-urdd;fU{pcG$BEomHuXUynIQvK!JD zzwyhD&SGVe3;QME7#Ar?Q3g!OyAA?ZtkbOib{gs_%eH5VW+I-{eIG?@t@Hxd^L{6q z#y1&;T!+)8RV>(xxF=V9pQ5?)caA1@>w^nZ@r7#fL8v0KZu&uLi{?(GJr6IPYF681 zu+l?~JDv+=U_u*YX59{;{ul)fyuHHx4H!9sg$)me>m7#Z<3fhn(;YxriurPKWka<> zoeZ=gN`*NfYjxlaGd{v;xTN%u(0Ym&h?I6g$}BB;BX#P>A>T<*Egf~zhE08k@c{{{ zk~=m>|8aMIZ1U*%6nl`dkx6QDU5a{DH0h0lvkvAoP!6*wlr0NI*&Z3J&tQp}b=*A$ zgEZ?s#v~x721zy;v)T<#`*;aYYbkILhW+*_O66{!aZ*bhP}BuMSE-i@Y@6GmL19;% z(svW@+81@3GK|V3)7aEQE!#L9*>$l9!=+fL*j?Tgudma~OXyMp9hxqoOBClXeV695 zAVjn@2a6_d#1MiWS+u0IaCq@Ff@76h~su5(GQJ zrA;kCR9dHGNL}r^=uP9!x6&L8sEjA!(AYB^h$73TI;q2qbU zqDe70AZ%}i3>PdjV8OeK{1O{c`fCM~M0VcfIpKf|tU-G!)net2f}ZrfkP-2K5Tx>_ z`xQXdv`&g2w;wu^$M)%8t)ZgJM;t>n2rbbAO=M9u+!0)v#!y!bi zbvAFA<2lMxhaNU{A=1)#ERUZ7)Ry7g!#@H=Dv1MO%!?1RX)5i_N1+bJeGp--ri(H# zOe~N{G{iW5HVMFC0Jz>ryd%itrU|r)2-2hcVl`%-*Utadu$yr-aARSetqsOIhN*O9 zs(ycc1GIbjN#V`w*zC0-U?tA65O7ei?bwiZ)bEzGP0=X}S&Zf&H7OdT#N;v-KO)K2 z>}5*u>Xw*9-tDmpnZsChgeQ6+o?c~>w^9|S!i=kXFVbjnE+(`}#zEt|6q4T)Bf!4W z@@q02Ml!c6o`?x4qGE4CB;a4&Qu$btI{dUR+$y~uE5;e>%(>eK#T8PbHDq))A>-@m z3Ko(~{1(zwv5V+V78+-tG1l2K zs#c56b+nE{Wy2VSZ3RIm@gwbZ#@1o6h#iGnaAJEKHKUuDO|a8I^fxR@BPR(=!PJP|+g zI&u@8&4xip+x9?v*CwGsZHnf6!X_=z>Lx`S?VfaF8SI|-zu|Az%G z*h-;jf-a^jaUowGqzJC&m^TM64S`^pHEOj|U#6q82OIVRXSCk z{~T`lW_gpQF}=t((EF~xOdugOtH}k7qEglr=5L9I1CCAZu>k9;jVxW#*$mch%IpIN zz_mv}CL&j_I00rppW_T!*D1)*mNka}CEcpu9y^P%6;)H}5xlaN$`4JmP?r#_poM|} zl%x!4+C-KnPzyu-!G4G*Myn?QqvHsjn`ol{5lrVkZcgq`Jsk^LtA)WpcjeJ!%T)+3 zz^E$sJgu@Fe(y;O@~|?^&X<=lE3OlE)hJu%Tj()7zc?fQg;25*na<;w1l(z|x$#McsXP&tb^}r$VLq0Dn%~~p6<%O8>_A%L&+P61`qu+ z9Io>f?Gku;H?&p&583fy3zyQ?vT9LhMY+7Z;)!oaN;A}`ue5QWD3=ZOs%qGx z!oZ{^DWi$H`0nNJWde$O5A-K%Th9 z`U4Z3rG@`pRE3k7q`7(xuKXkh9A~Id0F5#xh!&YJB73H z6>RClr?VU;bi=u@t~sqqI4`HG;DS>QmOn_g`iN}X5s9%(_fl)9bfWF`2YM|Hud;Ls zXm|8C*4fa0BG$p-x*n=s0{_JZryrubYdY)Q5NYH%bq%fVJ~@s=@W%`7_ePnfBECI# z#IIMe>t#LX>>R4DShO|@tS6y1o?=p^>P*XV+M0@~*TXg@kIWS|Ta**E$}z}U zx;&RxG@5DaxlP9Mt?$#SKJgDkE@EvZ6S>s)IOzQ$KbhA zZnvC&$@foB5*~^dvEFQSQ+2bj_v7G7k9T9~2(NCge^G9~SJG^jjzy6pvH-qSR%FkN zl&ee*+mu5QZ4Mu^4KQjW}w5lt0U$<@M;S?Nx;iE0K2*IbzN2 zr8HiPb>56_U+a+daj1Kg<915~4=68Ytbomoj2%v|#Sq4tMTF$fq#XuB0~h?x?Tue`0*p-ev$LIXA2gF8RF)99K!=- z<6!&h^6Gw?7VdQ;g_RuL-knk81D*#Ae}^+;5w@PVft3ZgA6hbv;wELOO?fgPk(B<= zS_RkK%So;Ctas6_o6$b1ig{#F@H68U9-(2eKdVcWWP#z>XT4Orep{(g7inHals_b! zD$JSe?JG|iYLHGqY5_Q1=w1RXMY$~#sVue#0+OQC*zx6Xdn3(yVjizJ!SJ3&Avv?> ziDvpn&GcQn@-tjgE*cNSX_Xc=5~KL~Puc1lYV7Mr_?6GWw+Vbtc7;UaF1o-vEUYAg ze!t(gb@*M-Pg~WZPPBJz#QmXCuDfgDmnB{A&VJs#a^CxxiikVzV^Khco`46qIl*vC$sJ(ZIzG4vAgEIaH(EehLCpMyJFJz z8g$R&ti?q$GHZ{G-Uyp@+F}#o`fw0gb>w8~++{dua&q;gB*Gw|Hh4-XS2;d;I);#Y zDZFcHLxU?fd(clcJq0O3{!=l*zb^({o?pOfiro~H8Hl4>DjEQ76xr5}&&SJ$DA zhC}SnRX@*FR~)78fie7kiHRJI_n+Z9;E9zurmzr6ea)=|InYdJOzhYGVAhsmKO^vJz+)XNAO+CBe^9G?%zo}#60 zL3}4(F!V}wu3}e;Xa&T^KY~8K1hEudm76d%ra3?nTr)v}nz;v23WE^}L$sg#ja@9s zQe{{~CVz{N$h=@iW9uwtF7r<)0B$%r@ZD>*4rpk-cYyG~hR9|^=CZ{lVhBhE0NK26 z;t*CF0)#BQmH`sGBt_O5R{rA4s>7!J!(lx`HARqUKb-Tkh1QmptBh!{=Eh+GX;xfI zG2wK+hqTRP2}g%vjx5mzsOoBeIFr>SqY;Hj7lm$tn)p-fRQgzAe47{-Os^*3n2)a2-w`B4SGsbMV;kRnU>gLPtI#E}abET;*G zmgX3fD2A5dx<19RQ7Kw?(Odxu*lkdp)sQrVz8s*#MtaTSW$Q=Y#|r@lLyGXFBZc$_WF2rA($$lyE3p`0H*4J9bh_N##f#g{SLjDam+3 zN8mB>e!kP#If06@hd9GvzSRBW{OJMr!5`;+9E$N2ISG7a9ZywVU8Dpzn#821s9;3U z&*ZFn)^$tiB*>$62Ut*wVm{vF&d;W3(44y)M)KXm zed~g?G_qW58yFFiZoK-mM$atO-}rZyYO&z~u*c&gZX)~&t1k7zgidmm<~6GfgfdHx z(1SaktUNQ+_q}rLeZDQ;VccxEC=1tx1iZM&O5nvSyDDx!#6t*wR5y-ZbrQ1q=8L{H zi~jcd`6R28Wh;D`7N-eK-f6CZX#bir>7{^%Wis=|I4IIm8u%tO`R8Yt3ropQ#K8?> z`p>y#7E%Qy8{D~03tcJja1+7nR3S^^TIL@pLfBP4-vOAIR>bB^4UeE;#ESWL{u&!! zaN-Bbj(1OH)SLv>CN=Tz)xiFXU;GA|&B%sJ$p?@ANL)l^Nqo1co{c>X%s>mwb7@zSghsn8>K!sCF$aMaS&THInmc7^7aqSY$HOmKJfmIuEWcPt?J@O~ zzTy|8JMQ@pq04Z*k<8yh>H3Khmz_5KNeJcl6C8QiGttrJ*p~j$-##x4+ zW>2OO^0-9#A!ZS>0GmN5W0Fl9jDF_Y#u3DiZ3rntjDj>aQT|b^GI!&|7JWGo9DJelo9+%#|5h|l2&8D^tY{V=y^qzI9c`q8* zwzs3`U+{7cx~Ucxo&jSFScr-&K=b^b4~#ETVkdXGTCq@zUA8mMK+f0p2R1zEte==* zj^9fhp+nr+A~6%Zj!AkE7UgmVKrEOnSvZ{C8c^yXM)IzobX9Z$zskzLIr}wnVinXa zUtX&r8E+fe$_6~Xgc*Fo*spp~LJMTj6%QFNk47Xi&e$`dtYh{`Rk|tB-v?#*ewnee zNG_D%^zee$0e;)n3mz_*&hy6dBkuoj6BlM!dWZf}mIJI803ewsv26`Ip^O>hJxwyS zg8&8j6_Fu@lj+Q4dT6ky#T~{`W}6LRJ9ZL-{!v|&P6-fwr!3l6w5cETSMMG!KegX& zZhcYz2?cw>vm-7rkpIw=SclkOA+oWiCbC>p`1*+(xd|I7LNOmRfySz$BfF5eJbY7{ zVENb2>nFN__+sTay0s%1k$Hf zb|uIPAbPvM3cM~;%BRB#H73cmzT`E7r7rcU#ItGX}$KE=pfy9bY$MZ7rOH? zU+V@{gZ7=E;s>i*6@e4KL(P^+I&|oNT5fcbeXfq6tT-XHl6I`cFSN_R66ue8t|5rQ zS94}QtV=w`II=7ZL_@P6gWr@c@#m=E$}*w8;f6W>)0GEi21@vEp4tog!&9PTvq3~Fe^FvEYe0P3k((*?}eWUQ|t`5XQ|V!#}$t6;J{+(8Wyo-X3=237OA zKe;&HXE5a$nbE%yiYxXAGB~w1O(yES?7rXGJIOSn8J*OzHsZCJqWP+`luyRf%&}9G zB!Ob8DQjvPCpD&v*#IlljZ|+R3Kme{YUP;T#I$wFeDQg3IX9QRd4iYOnmj@Y^t!Nu z1ui34fc64ZK7-hnz~7!HPPBP$sB%)shRcwSnDv5nN$Q%Oo12hy(xEE`Y- zCHdc#^La5}+EX3#bbKF257ma}0-?HL(6tMrXzJTL+59s-IkP>pb#!riWh-If@=q;F zT+_^RtgaNgV>unR!07;SXHM9Uh?bR*t$gQ~acnXJWrd%CA_``1a^aNZ_dGT(KLyZCEK(M+LSR1u^-a3CQRctmJU*{x@Dst=6Kmi!JRDZMm({?yP84!_ zCNx;XlEJ)KB!tQ)8*m_GJ4&z1??J4LS4uKXbVTq2mkptc&GO-7_UOx;be+RN?uyE) z7?Av^PpzVJtzdKx<{Q`n^GAn@c6`3{ z|H_U+T-%hf=vqF7?`FjDm^T|6u|bAKQzWYts8_ktimYaqj&gVczeKx~-qLS}`!r8~AM*?%# zsQ^2|DojYTXrrpcDpt(dnpbqkHXuuWAlYU_M7rGRgI98jbn^@(RQ zapqY5V))G&$vZL#vTXEg;=tzO?O_HM?=fLNS!Uz!gi$v1w75Fd&-X&Vg{YX&Tik8P z^Y%L*N;MIktA49^UbMUgJXhXJI1zB}n|)W=i0P|L7DduhdKOqF*qu8aJHm0$M0v$C z#rLcfi$LvT;~d1)O5;my9`OanZ^-5R&C*;o-^*rM|1f9Tcz{aWK4s54TrP`S6`p3S z7Dvt}=zpINHlp^FSHJV%=GV31{!jD4(dmDQr`5#w+YT@wh}=lLg&}J1`h&LVawwx# z#!G1lE_E8&A*uCa*Wj*y`sApKegSxIY_%~r>GsvT^lU#hX!4^pfiAmw6|Ez?1^w-a zP|rk-oq+(aH9VIdEi5vsyIpNf&j%6Z|Ja2y^9YGeA3M*-n8 zS~%-D>Dy=lHmK$X})W}_u z;lAyL)%pz}#`~^GTiRc7bm)BdL1rX;>)fW9CGZArsjj|lHzR zI&>s4r((v9KEs7Y{hW2D(Z1MhI z(U-QJXbP#tK}j?%zX*vLuh0j5-3E0sA}v~|rtI(6`(bLfFI)aXSE`3@q^cH!BKN87 zD0NBNG_V&HI#hNcQ$lV@B~>7cQh}h3FcOkOJyDp9&|p*zpvVl?`j<3zTW;eOfTsZ- z46;TfGPV0Z;jl`ISgpyCC1_x?4lOM*HTID8sK)+*1Zkb!kZ10tK0pVJJ80HO~F?n=dR#1DOg8ZsrSPof8uLdZ*IM`zK^0x z619v|ZZcL2D`2Go95vO%P4kL&w)P}j^Xiju(L;Ai7!25dy1C-yc5?E*9pCl}LlFCe z1g#2TTZDT;oi&;c^`Jlrv4AbtJ@bauh{BYO?K7dqWZ>DRs+_`-r5`f^w!(%G7-|3A zM33_a&L|KiZ`OXR5h&9tVTfU<2A1thpZSFOg4tp(f-KqZz|lsUw4ziAwbaYe)maB? z=*anCgi$)xW49#8&8><3sNVcxsBMI)m>byP>pijP_u62OA3%#TO#KZ?5$2xIGN3ndcaMeJAp?+dUCjvcSfKSbP$gKgMywqr71_ewqg6R z1aS72$Y+h__f*GO?^&peEg0kO0iJuRGPMe=R2EzWE)@&?Glu|rdG~s8CinInA!*5M z^*fR&4AEDocql4Y69{T))$0Tf3PvK0K71KW8doDr2Nf?Om01*3YTwXq7W z6T5<<5vzSAAVw1&T!b&2kiS` z+H_zkipsLFamAR0R}{mX&aR)J6hf1~uerFS^xdnaM_f&lyH~7M%Yt;EnZJ$z*S7$?Wff>3Xc9PB4tGY}P0TSJ9_{K*& zoeLpra~z1(Q<319Ibprzns(7G-!S@4J3HQEhVDXWk>|$Kbz03m2MnhNbLmq5iJ|@) z1*eS+A9dUWd@zu|hU+!s#>=!m78ue#B_6N=M`rTZ9b=V-O~Rd?dw!Ahy~0PCN-ZZ; zCCVp5dw$0EkOcS7yF?HFAgetT>7>~Y3JVz-YRdel3<%5X;5UOcEx#CIEaNdu`Tn;K z?wn4bX}8%#ak;1$S+yD?1zBDg3i|q(O>?T_gG{t?tt!hDuT42~fQ8H^YI>d>N*v-D z=5l32orN;XKHheUEx&Alndo+jK)_pi0A{gzK80ppG~MM(p?J#2<|MOgJtmeC<=dm1 zxSO`Ha=9}i>sRH1yMkW6q>tBVEf1^AMLV(vi_?kuW{7lO*yG6(pS2H~W(rY^B=R`@QSY!!fln8wbCSS?m)<$S0Us$<5Ss zR(kx-uE^soC!0;|$ZAw&YU9TFUsb2;-cWrWxpGp#o}4CbN+opoq@XRaFM`L4m%013 zD(qE%pCPtdYfEN^MIa7Hd-#h(OB?(isctbw^a0?VW6EH~8q^jUNB5jdMp~%i?7+2KlYv(prjj@Wt=0<&}`9IB$7^r&dYLn=)RGSOlS z%9AQlV>~j6a3iMW$zY{P1{=V1>PG^2OZLEI^@up2XyJ-q{eLMSZPy7mK@;W*Z{eNg zJ9gj$%b#T z>MrZIbfdOuzWxq&j+}j+J3`GRnC5q#NU*Yis+DYaxzXDak2I6755j8U%hvO4<88tX zBGwEXpPDGD{lY-bf)zY4V5_U-e^x4F9Vw1dM08L!SNV1GM3@V^*$h)8JzbkfqC;p6@+8I6Ye-T;jPra48-7%f`V(N?RE)ADsBHt z*!269lELEU0ZHBcKTax?7YlRDK!3NlNB{uj{~v1%J6lr=GZ)AITN$}VO~-D74aEmO z{>Q$6Z;{TB^a9M9;TR|byLe=MN@4+Mkc%SPnbs*)GNw4&bMSe?t%6>uSsPyP%lJ$; zckshSf;UK=OuIN~fJTfzJC`SDUhPApxnimE{$Q|Owy}CFRTKML7p~0*ji9pu` zBSj7i#aanVR-p5lI!eJpCLa!hnoc^v;AW!sgMEajyMQe;X?^(NY(YKjJCc4YFf9~7G^)sMtMhA(<~*2fI7-GFuLJqm}}o0 zJ<$brwS_!0_LUmqk1BZ#MF@;zp3!J%Yt^H~`%#6q9s>*;d5a0dgZsPl=da5&>~`*SP0BxmtM{E%YcaPb4!LtH0UPRrhkta?2Gc(79+T zR}~a+`YZUnOuu6I-=}W#UJs|>{K_|*WBC) zR(_GT?_)!mh`edX{0k(n8z5%LYtt#h<3N3wssH>A@QCL>D$&sL>=*-MrkdDrS1 zVs+u^UynXZUc-D-k9*E_;ox5Zy{~i$<_FUWX;&78ih|x9X=8!XuQc4kx@vzlFQDk_ zzaskmBCUx0Y$X%XJaAQ{%u>o}CsHdncKJQw6sFgu6s(rkQV^ZhPA34<*Y7&C_ z)`1$7hECs$t>ew#@oJh(y=m_aBP1?OB1mluzYoQD*0-t@dTypS7mY52-o7LyWBGVI z1i2-X#(5SzpBe~Kmw-hSNUw@*suFB?q;zMb4$&k*ENGpB4Rs+9eKr8j~Ls^BgC)Dv9lY#&MSuovo&WBj${jqs%7Y%R*!Rbb8{v7 zE@kS`cGROr8il$sJrb)2dnZvm-}qWGmBcIaiW4gQYdt}uthBh>@m~wTyrx?2YHjZ9P9AN)IVX8T}ek#oo6FY$p6%e z?`s8IvUTS03P>@}(zbJYoEa%*e*U*3fdA|V0Vj5$;C>-c5X=Ao`2Vx7{x1-eo!v$k zqMu&=PJol%)HM!gA{5N+u7Th`SFnF&qFL7-3LsR(jBMx{iy{*hT92JKu}q}re~8w` zp7#Z}h!VyQwi3EJcM^KK2*`o?X7joUPKdTl{=O4xZSSA@1i4`k)(57nG+riXm2o6Bd$Bqn7V4aL#dN8vS!HM!B zx{v-OKiSJsW>Gp+H4gSE%3?8flv|c6apcRI=RUVSjP^~N-=f*7Xpt~gi2U^Lw19|_ zsOft!^9F8GBANAg{9LmkV-t~RwEGlTdQaSG@DYcqW9)74df~N9yEiuBqH9-Ha!kD} zJ#+$^WFtlAQT9@N=MAd}Au&;C+$j!p`HYg?$waJcl#elSG~Xk86{w~de4bzq1A=t zM#D*;C60DCndbJwq7|@E;DLUH?0D~XpCz%{Rp=#HyRFxim*f{fC|ZveOm0#8 zzZSjznMu7d+A0Xo^$c;kp2bIqYvftH*xDA?ExS3m!W6?-o6^oR;3T4iXRQ&6XbD0l z_&l;W`pFK+onjd`G)C_)Izk-%H=NH5KXr(~W~_<~VGN;5n=fZEl69>q7sGD!58**F z&GR3G;e{>te1w{D#x`wvI7uuzVe1yt@V&@8d=6?}li46Ykr1IngDWoU`*IT5&AhJg848>hn zp=~BsB78l+j(=V_|2SO76a^o{jT%d}OsPX;7`l|t`a;Q^LDc~hVdHI0TfryS;4^`2 z(H0=EX1<(EkDt)K>IFCViuuiUHMQU*6S8e&-Vf6end5VX;z4e`{F9CqWGNXKVPZ~Q zA6Kiz{sNrQEw3UvNZJ{;_F3=+nxJT2>1 zwpi)bwUOv$a#V^C%OA1x%EZ>ZT^fUZqgW7|`yVCSW#~>jSKh(y)5V%%`1L02bga2D z8%36Aht-&(QS>5Lp5snqEWnYRyK{*3<2$bK$Z1XhlOcy{It((e@Oj|YOa!VN>NPM< za|J^zVYeV;D3)zlT$LP^AXbFep>PquC@AoN@1u@gj2An{F{L^ttbu$&D^<9k;1ihP zw#z)vpIIZZBp#av0cIcP9LOj@*Ll|uT3By7cjv&B8iq2XOgN`2;pNv*DYQe4u5zKP z=Ip&f$6Sk}e%#Y{PkvRTi+W~L$)0&T|7z6bfwy7*yRxP~{z38Plak_7ZeB*d$m5># zRp1R1z`YN#p;qd}(qc^@EFlNGXfw}_u6FU5>1zouCk?j;-+}npzPdTt-%p2&ypqhn z9H?(UFkxHVP^k^(XWgUXYeIs<=YV)G5{P!6{taH3;LRYxF&`uZEQYv2fiYf?;LW1n z0w;L045VO&mHW3H4Web)g8`y_G$@`MBY2Yz!I2ulkz1hruSyd_Ij|B>3?={6#caki z0Ov->%o#p_Y?q$-Jw>K+nq!`l4{4hLIDiZffO;36e#JFYm$3iv1u)u;g#O(-P@@}0 zy*oH?)C)-;lRjP;V3Zp~y}S5t!BOx22a+bo%JsLMR^OuLL0|ta797ovq267mZ(pTv z-vwaOgXVtho9@^l`YsD2Xr*%FHZG9yn?Cxj*FYvJO+pB)v*0B)*ebI+orJ}xo`GfE zML2N>SaRvA-4BA~%_sg4A5zj+kKzSBh~!6K;yw=~5p3#!LE;`hfaHhbw+JKop(Lzu znuZG^=>?UnalwO;{Jx7ngbyX@g--m0O8mqkL1miI1dUf*qFUXFMs-GPqP)TiW3yR1 zL1Bg<(U+;G?dcw&A4fZc4GHyw!tcUnTZZhpl6N?+QB+zOKl>z$S?M3Up@kCj^eRg^8P%r%ZP-Lno`3#Eo#yD z-6i9jk*S>$;urfgOsJ`A(TJiWu;Lrs5MO_^ir{BYaJb&@bbt)P&09xAICPR4H@vwOm3efq7}ZW~p2d<8kGvRg=Ebcg2RBnp zJ67EHa=A~02GjEYB0(+vlAz|zS5zOEN|xVM}%POIf#D5w%7vSMHB2Xv|SI@6)diK=}-> zc0F|$y?y)7=PdS+OQRn(vAwsj`po&PO!b?_fUS%sJk!OeVfob5wUjulET|7l_(XE# zeH$b6h&r*WdxE?PV>K3!KvU08!CsA<8L&_vT7qYn=uEC8(-vCDY+$L_$`ODKz@+_& zh^8D1ivWeSq(TjyjXnCN3DzvtTU9uu+nXX}DNj13l{7yvT7oue3BYNkjeb#3!hJ>z z*h(r9)N)r)EN!+D1gnk82_>a-bSq~Gs(!>Si%M;+sn)yoiW^$p3Vp(A+FQpFu7+XW z{z-u}E;br|D`jyUuXoJ?Z}t7!S@YznRyt?72Q*}owo;O7HChQk zA65kI@V(F^x~66Rqfe93pwL2W<_P}%7@S}*Y-8A9K z+;>jXHD$I{{gK|GMy8eZJAm{@10_s27IjpRVZ{%^pSiczHc0af4yIQOm_G^ts1JD< z)>TS|eT-KGHSw6;o+j2U*p^UbFl(Z_$gHulu6Pd@rwib*jfO6{FJ`XgG9dbTBM@l;Jlgd(81zT7nQb;MYL@V(CEs5MZp{O@0SXRs|I z!6`kBRrKLi?0<)|0(gdu##2Y0_)!Q}D9|gAqgIRzM4P+V5EeX?BX}R=cpsene$RUU z{c6Rb6qa-H_cm<`1OR~Me_Tr2*_-^Y6A!2VcCn_cW3|EXd-n0luf3jDJmrfQz>|!y z-snQDr7K1$mQZVB(^wmS*!=yHR6S(D-6T}8b3NLAvPnFC(kCgQQ^%!ul-IPzd5Hf! zY+=RJo#Jv}FoSMS-A*c=0`Flp#zZfPZeM`{BMV2v)$D~L3gVZ7(;^I*gJ#~(4$;QG zVbtND7jCqh$0Nb}h#}pZ;8ibzN7b0G_@_LqT((#;TcBLQ2mwjm^@};+0U!GBg^w^- zi%tn!Bjg%`PEk#Ro~{N{$plh*kaGB)^Tn_;S3&mc zgSA*V(VoLA)b+w!PB+`z2SSv{IpZJC493C#=Ubn`-zsj26|o?$$@Uz9DLvckkkI6*V9v8XBi zVa-m(g?)`Ai>M;)i2^W!v~fpA=c`Iw?PolL)|+0UHoF16Q&{gYiJ>dKqkkU=FY0xY z{`)X`paFgJX$_u917kcJ-qxPp z(CnNpJAu2bQQQE39R8gRB^G~Vt_QNkF8Ih}b*1@wyHwm4DMV=$ z8rKeLFq?zDZKu8A^&a}^0p9_mn15fi`X6}|W_;j`6E021j7t}U7&~M$QhC`$m!prK zuh&&fB3<%E2xj=+#uZH1(o^Tm$Ir|2^zPEmcGvseaoR6j%aH7QGNxn34v^&ZH*-7u za}KxcX_k2BCA2#O+W=ZcY4aynybxTN%9D=GfWhfzy0yYocBkXTusSmWmeLG8PdsoP z?PAJI&v&oyB;_W8pgngm86<+8sL>r+)L=2?<|mb;Nl%m~D0{#gZg#+f1<8(2*r(xY zn%>~v2ZBZG?%GV<0r}6NZm%@ao}3z}Ax+W_f?aOOL)a6617I2Bine4o0cKr| zKyMv7vs`yyu2EuwmjG~BctiR-ykUKq$4o`Fx|Ib;a3%GaZ~aq4{4=l1zYU%^W@jJ}s9i66@v3!&?_6KSflEwQ5vJw{MteWO_#G>(9GO?Z4Td z1M-Fx@I#!8Tf@yJ*2gNJG&vCG*8F2t$EPxB^1P_<;}e!pm+h*51;!xU{0I+h+ObLE z_ZS}}KtLZ?_UPZEiVT5L9xOzneXL6vNd&ziIj#fT@7CVu1G7lMLYuIx?y7 zwj6y!?m<_Jb;IuqRJ$67lrz;J(;oH)kVbUp`Vwl#2cUFQu>A;UMG^JeO?oikiR{8W zYKI7;AoY72-evb6kB7S#jJQ9;jGp&;EeURGn)!g^@i-cN1<19sxCugo;Pg6>!e7G2iKFkuc(cXfUKt{=RXX)DxzMa!N}moRxYPrHDMD6d5V^stTSSC02A1)w}F{4-22lpvtsLv zKbTj?&%4*=bh6K%qcz%d3w`wsm&j$;Adf&s z^mPxU_nfVEkKXXdER{@%7QaEHdbE7ggO-eLYz591zu1{NPP}dvovM>1Rg9_+?t$WO zVpqjUSJ;!BUc;vXM~>iLUkXkzR*4T0wMeS9#{02$I;J*#sK+aQm2H*UKh-0%23(gT z$ZjhJ=>u-oq|g!f)p(F57{IArmDW6g*tmGmjD!RTRj4bi_)<1nraN;!#Vk=-!=ZUo zDrG|7xu`wfE|7P@8Av;RRby~{LRK$RPE$n92lNdn1f_L6eX*EL0_g~3EvlXll^CNG~x8ZX}Vr|>0A z_~j~AwZ`uIPoU9tz_CH0iSB&JF;?P|D72b!H50p7L&BT!`XW(KED-O2mPi0Mf5#|I zR#BB8iA&+9Tm^j%)M-|YW!CyvkgP1eAhC{!12LemsA|JiOUpa82J5iRhkrO=9!9P1 zWMbPx*aka{)Gd0j60?AE2jR2V&Y`L#-ac+&?@j>a^|q#nwYi<#MIuv2B964gMtz8V z|K!yGtnl?O7l3_JL=(UW(QH{f|8`bQQMb^Fkruo4|I?g};7px7Ia;~5H)%4w2JSt0 z9pwfoid(OQ7mbYB^>CLy((2{ z&MlX{Hhv|HcJtltZSkPk?j!~D9AkLp+>Aco{Vy<4+S>JvOO0n11Sq%qkg`Lu^Mpx{yI}%5hvpccOlmxGJ>S zB{N1lAQ$6b$^F7axTFE(3aaye&6qLS@_xcZTy8wiB-$)F^f+!1I1*^I(1I(lD+yV& z&UV%2#V4N>X#XaGD$CfgP`{3}%pL)R`K9bbgdlq$t_>K8$Q8XOr_Me14M0h_HIvGTJtT)^sZ4jk zd|9up4R(R6cGAxQzQ9pG>Ei-l=B%Fy_)nEN?b{i?bG`wCi$M;$cIo>}Z!}`yY+D+A zt>vt}aYS#orY8@v^eeuaw4D3tY%l6W6Yg2xEPiV3Q}NGw#u-#%&!uyY-Jz*7oyX-jPK4G}DhT1MsW`BK5Cl7>!~l6UjUssY9g{02R}Dt%sSM0*YTtnbDcm znYPmYiWps^{H-e?Uto%8xvNZ=5CBZ+7~`oNVGfKw*Mcf&IgLbs`QTCje$bHL^?!EC zs814HQ~&6^0##?RxZ$zz@e!ZYijxozF-e5^t)fHMsy&dSs4d@MS}BpLaz)^n5UUG= z4<~R8raI>^dsM^Mb4GrjoPcVwO$0et($L&Dg}&SinvIqH8I+<(|^)a5w>c9LEjtbTHfH<9L3QG8@dg&$pm$t$fjU zsZLeZwX5&79A@|o%g3aF3H!so2+~Fe9Ai6Va61EV%nBh$1c*V~Ms<4}77-WD7qB?2 zH1L5_Ky?*5>6+V-KLLa${KaIioS0&|9T~=guB)P2j(Q2B$e#60fEiJ3GdVi0TsVTc zZpa60s1%B#kyNg_4@p}uXP8M`KH4b!r-g0M(-b|9f8-K?3ZRj0+rlf#rrwePV?(Oi zI6)kmJ`;<^CijMr`Oyun-B+x1)XO`!`B~{~iW2FVr;RY+6oYe`-EEGSy|&q8z<`7S z!`Ks#_YZWri1z_^t+mI}-4t=6rmC?KBU8oF`v#D}?7a#A@t;VaY!YWZ0Z)94H;(&f zSXx>d{$#me%XlDKqPc-bBtECAg~=GzY`Ew*N{0~=1*s~eerImzd|+@mA|7CAngho> zNuuLCk{Y*JYf=A^)6lRiVUBGZ2mD#UKC_YfduzjaX^xbh8?*PupI%h`gdr7DjooTx zb;N&b;5+ttc)*awupzKqSaY%NrYwDpC#X;iTkW%syUZ7M@a&^a4~D>qZD{XOiWof{ z)bpn7YE2-U(rj`n%C#-1<5`(A(Lp}b-abBd=NZcw^z|Bc0yF3d2@`YCr*|UEOPvf- zwu}|ikNa|o+L*2vEAjvrRc$>>YYw(%M1OnwF@VO(>TTMPqijyV6VfxaIqelwZi6km zG)VBe?eRXKO_Hao#uahHv4*YQh9OPB_3Qo~Z6unj^-RExrV5E1YeY0C< zG8Y@lqn-kR#6pX===o5%as5m(CcXr+yvZ=V>1UoZae}WX=CV;yBy$0cT*)!PRdQ9e zmD`Jz6OP7Kn5d#HD>LSJ!v!oaljQ_(ptbS=auk@Y6idbhqOlMb(P${A3qbWz!eM|h zf(ik$@c<=^!q7lEhkWip5sL?rBCK;Gj1fZ;`I%S}!m~j2mYl`qKuoAUgMI+{5S@*X z;TQGU1caiL3VG-Vr)gWKRgbG2k`Mx|$O+MS$-`$(fj%o}f<;7YF=$Q2Vk@@L3)T6y zmnI#9_}*)Ane!_+lCuJW30t0Ej|3YzGE{5j%KWN5t>q*!p|!Qy)z$H+sk4Rk)e5q; z6&cNEFw~U!1$Yfo8U_*J@(3Ch50?u+A(Z(h>t#Ptp3wVckA8bGnwR&p@9S`?X7yY_ zOPJL&`Yt08mCRHx!$nFC#r-9V3Lg3JafRFfYHG3AHL?9aRQalR6cXMD;Z0*J`4h9u zdRx;N^LV>864FBx3&sCBn-;a9FHNES=oo>ISpgo%`Wz^8wE(}~y80t;*C;L(Z zXn{BG!vd}t*Uu{9)G`CGq{FCb5nPc0^J!cep}$pL%}8If_&t(yqZ10~)j;}jT+Rvf zf3O~Nzi5zspJ$pC+u-<0;98f|6W;R4@gJwmJ$Eqn3L2Zx%9OM)sIc)=a;PkHb2XOA zNYwb6*3LIAHQPM=U9QNgox@peCa}shV7b-~+n1Xyrs4jo;@GlcxfzaX$3&}u>#pz} zTmJsz-ITcYdqy?BUo10xc^i+#Vgi)_uEe6{I$*snB*u{r$i1z zIfyrW4uWXCs8!>M>MIz1l>o-K*d>PbE(YZHE*A8Cl^C2jaV)SZw2yN6C~B{3K-hi1 z31_%x!t72mO+Vq!$+9aaTs+pZ795&Z>jS!>%sH5z{mLx!oCci)_re5ahB8H|=8F!* z1ib+PJz;Mi>>pxvD<^{&Nz_<7Cav7yT>Qwb)OK|#utpJ5`NURwqN7dV07F2S6eY6J z?z5W%p-dQ~_dzE*xCjRI)B<=*48;yPbh;2B~B6r9@vN^K8dDo8s<^*$$F~yk99j_z* zqpwBI{h|q5leo)vxxX=wjmEh(QK!>MZCj&9-C4l*Gu`UQd{Skz)_9G=XRTp2+0kCx zi2t9LcR891q<)-O(eB|ZdMR8|l`2bQ+jD(OrI9(>dJ~Hon3sY>*Qk!+^4?3^%Hc05 zROy~48gtGv8gt$xB@1c|vo%yk={tL=v#&>N?gXYqlk!RVv;y0=LHQT=0$bVSIVk)< zqPeXW<_cCAU1II*ICOG7mdHT0h}bpoCxN2?7gd4hrh1e{bSus>yj1XhKH5=X9cAkm zvrhhvuRmkgy`TWCMrAWTh98&Eo+woXI=jy)4QpI-g)q}>4PtH=$P@XIf~Y~2$N(zu z;2W>28IEN$$(L*vlvZ(DWKIx{Cd`c7s*NofHPhBMrdG_ptLrrU);8NRuQRAV)JOR& z(c5pIx+$&4QuC9~rcF%gHDG8XazlIn*xs@r55{NGV8Srrm~m9`LkD5P+F-+Mvex!? z_cJBr&i$XA+6|6{QfZ=ai`LJAjfoOm>6`m6u{85)rA=)sWhjMs*F#_PBe%0R>z511 zeA(`&qJ{LdGt!hT3)Q;cQMa?y6e}eu(AL)bm9QuvVU$I)6lwp;DXrrGx9-W<+h6c@ zA10F}$=u$`rbRuGKwAuo-jC9qdg+vTmS`Vrl@PUzcmiT#)z-t0tbeVycV>;6hyQ%+ z;GPOIjJ%;XXrL`45)1c@sWUJX8DGDfd&EMp55ezk;wM$0->8bpBaV1H`nz&MDWgVU zTJx!+nfAt~jRWyW6T3b_*+|!kmRsqoCVON!&%VVlz>>soLazHi_fzcju%s@NK$U6O zN@zMdVb=uaJ{TeJfqKU4bp81oq;oMh=lt*3?NV8P^IVDgEld9HAMif9LUyi6|Mrwi}cC;`<3kf!Pq-?XBMu_qOomsY}>Xv))U*d zZQHh;j-8He+qTg=YrXsIvCoGy#`$uMd)_}_&YD$MRc!$>XfL2zxVNrQsGG7O|vzPu(3OIk;=3cHr#UuFnKp1-2hJDI5V77lQqlyE;nv{qQE zcnoFEF91Ps+-PTXbzhu%oE4X-KgMoHOJD!C;dj@P%EQTj({f(52}u54sL)!JDv!na4~$m zP;gnH5*vSw%Aito1nlGDTXQ)0GO ztdx_9Kq!R;SX|NqopZ4eaAsFXr6dPd$qYlxHL7A}uo?$+Unk98$WPF7k|$t6-zXAV zoND;z$Rbdk=R`~IvhCK@(`5NGVogA!RQQRVE1LqZ#q>zW#Uup-8S@~IN$M58aP{|C z@dPU-T#Dnyl>gHCD4hSS{lCCWp4k2z>`6l|a8YSB1D&ZLV&fK)cBi@|p1Dn9m+qqZ zLnhArdZdPxC-KOpC6&PxiyhZzd!wghVR+A{vb#i!_;oML&9cc zWI@g|gy5X}h=s-5^f&{{NIALj;oya0YVD|uCy_^ zW>PELD&d2QUZFTgkSdY8f{WzS&2&Mk4`)GQszTfkfw?8LFzV_VxVk;VLGda%be)GU zLC#cIWbi~yHNs3edm85+*P`!WQ2nlw{Lp4W8bQv=FAqSJZrnlG@B$H=gzIrTMhMzu z_u}cL?fQuzQiN?wz!}>N(Y$AEB^9<(I%-VUL31LfF_Q+TNPLwWxCa**VJx?iN@J{e zGK!vQN`y`t4xSpm@>Eq(o4L9kH!n$#pRTbUghAaNH8Lx*PN;YX$QwH9bq=2Gqv^5w z>e4AoiSqmYL_u*~Ouu8j&-0_n!su|t*!)O~=f4+Pokfy5o#Y>`MUwCPV+b4~L{pF*WP*l7f zvS{4g86S_fkvMB1v1q(#h}T7!nF%CN8HALmn*bbG9ImhR8^OUHuc@(VQq?F`a`o*9q>LoCyb1T+h94wl zv*(!pj?xbo$Ljy3r_64iv^>wqU#1d^>>Gtc6mBG&god6o-91O^2?A*ySfg)Nvdt#Y z-TA&hKG@PRb<&PVOOXI^NQpuEt^LGfBTJu;d+zfLW9BIbV}s6koal_r;5EI|<)xiE zj&$Oc7wok5Q8l+pG4o=g4I8<`EN|-6#GtHAg^Y$F*U6}lFNu#O*ag^^Df-2b&`!P= zF6=iU$lwT=i{#aGm~<2o3ZLt+htkjmrP6;T$Uc+6$#q^e7mjJ{K=S}y$DWkvNguJ0 zzN`xu4Hyq!joGR97{<@Y3XciLdPgsF57{lNM9~Trst>!KePB}hKm!t)@xUB-?FRC6 zBqAFcpLRSx&zL4=SpI~OcGA`UZdbt%9hcf5y@#53(r34`cQ#PBSk(hBBd?3k(AI8&xcWJjy7Gy z2_HpZA%&x1AYMYB47928n;dIbvX%hn`&SiO3cM5p{weo0C5*vg86zV;6n?C+f$0;+ zncF;mq{C)Ms&HsC3ul0+o{|7m^f+uX5ZG_@QJL_~CSY2zl?Nkz1ILFE1+IQlZS>@n zvN?RYN@2#P8IM%^vo6fx;;*hOaAP!u^aMvE&FOBFb2RirE9&a!aqf-jUPW6PX>;y> zsTO}0{8cB1spfkhX%!^vDU-k9s3M(=*rtHD=xz`DYah{0+#iYvyI@hQWP**X)=JQyfV)rlcyM zHW2#1?PvB7-K0}PVMsRE@vdHUS;l>DAba4}x6E5JzijaAo)a}UQvF_Xue1rZCRk;kw;ZH9x-ks$3aEe|o@Wz+>{~tUPcf1^AqO#~%-uaM|i1(dxbN_vO#L)w3-mci%jp=++W9Ow_WTmH) zIkFhj?FhmB+OMu|%s}w%Mk&@23!laHOs1Lz0Nn|D!C{xCtl`F? z{*$d;QvEh%#Wcc%(?A&9;G1n^5Gt>luIk#1v;eSEj*0xsBghA;R%KYn?yD$b-su{0 zm{lOID-PjJ8y8C02G1?}^0nogtZ?L4m(q9e3d0WO3_zcNE9JZ26oY@O^J<~nTi{da z>9A=Bv6qhL7lFF56MojiYWB!6?`J)iyzgrE%5*klw&%IQ@0eMF(NO@?=c?PoHjkxC zwV}t*{DxfUyo-^Kg2a&iV7ayXB6;dSAzJ$hH@*QOVaBgu(U5~F%lRSYTFX@or2uONxkvD0`%%uXu#fRMBuwkj3I@+S|CFBaSRdNp`rT1aL;5dw!vXJ?* z(^2wuMOz66!3vWl2I#}0o@xK(8DLeJzSK6c%{@OzOB<^a?{I`3k!TkToE_^H3h_2R7JnrI+|GHnbvsXp{Y@7h=ZEF2 ziEo$NXL`*nsW`P?J@k)a<2WU=<64r0#hxKmg@7rCP!9LJ~o1eew>owQjpwUh8 zsx^SIZPRS!=%x$^dsX~IhrhSSrSfewKlqY;q7U5ZAU{M%B#zsH0JF=tiQj)!%8N-2fosn5jl|LTb8*n5J4}Rr{Jow0cIDG z0c@aF?~L`fCtX$aUrIa_vzbe{My<8&b>*^9y`Xo8NN}@eb`DJL%K6raO0TfZJ)#j1 z=MMlJk5Rd|X0Vc`s59XHPgx}U=Y{6YtTZ(YJ`hc>&~XT?;p9#98At8#`nwMMHMgjM zy!%Dn2qWD*jjZ&`4)MywumP*Coxo}74TRaGT?v)z1j@}2(V>K45;|bXa^T!9Ua3@{* zPjBX@%h#`15_V`|=%O*17+1A3J4$h48reNPlpks;TrLs4P)1*9R>q z@i!$99gW&hA=zhOe?=F-PL^(=P&IdWf>jdvn=n>yYrDCf&bYX}y!7(WaJpcN5N&l@ z%juABt#5Yv*0|ox=SI4@IVOGFzW=P$5Zqk{heDJNcd-KN;ne*U&(P35H0QAzdqIy!}wj?1sNUmx;8 zJOmT)rcQaCryP+nu9e~>Zeg&yP8y8dOBSbz)v%?6+R|9TE$Fi%1ShEco8eo$ClwY$ zzSzZ*ke)9-y4<&j3s_Hvj`C!V5_(H*lSYevow)4*4P6(l5r4}uZiFi~1@%1ffN!`U!JrQRcDMpQ;L_Sql4->zm&mkl4KF(=?l?}Kpn zp(tV6qJ~i6024%tO$$Ejaygi)oC`zOSA~y(*;OZBgoO&Ujzx@z7O#YYh+~TpMSr3} z41*H&C(uq-f0KX7t#dQQYON@Z#=AmL#GlHvYwc`#1fZz-SAcjxCwQ?d#KQrwY+0I> zn535@qvn}oodXfbt1;P)3EKrq_(kYw<{EIqDb+==O!wm_iu=2{_|=dzWtFo~Lx%U~M-=E;eI9D53u^J< z+wnN`X>4g&imXwy{$p5$u2r*YIiyC@qWS-IacxiWbI6_YtC8WjJ0Iq2Ow zHX-a^M)&s%!ltpaFVV>F)yG$ny9B><h308u`aGqPd@{9|Shwak_yF)U#Z0^$p_O3{bWY6|*yVx+MyT z83=$fqxI3#m1d{XzqPU;YwvV{O9pkpZ@BVkkk6Qp=)qqc6eXEA-)YId{`n02?(|q8 zw1|(L)8|EtET6miqL7YFy&Z+W7CQ%e2f;3EDF3g1CqaIg!T>)(xZKrceMC`|Y2kLG zco=?2-fP8yaa1B8=m%p5vysA+b0(yWchUcjlb{Op4T2(45i-vBPKYO^`X8R_f=d8m zPdQ)ql3vLQa{OGO1%dpg`MmO6wkA&0Hbg^QjIQ3wj5Tgw0slgTfFe5NW;=<&5z1L) ztX`}F78HMv&@7nAGhHMP186Ec<0keVUyC)mP04fmMWKb=)H&ggFviuhxRn$v=6_i) z=UDLh*``^S#rVQ-D;1DBV1^K#HL&0s0D?#L2mg!<% z+70g0`Z_ae+ni3u*6}P>(yq3(I^i59@Y+bgRwNMhw+M6Eh!0d;Rzpv7@;``_+XQ+f zjXISKn${AtsG*8RKUHN+Is;X4oVFl<4V}%yxeZ+v{%XMI2ZM$#d;O4J)b`;_KS~}) zq}8ZE^|Qer#3~=a)u3hGeb^Fz%p$)`%kqH=xGb+;@}eLXm>GMVsR3=Om3dFtrk%;a zZvo{hseWzF=1khuN_p197tCqzPzT@H6g*rT#H}25+`IPof+3g5pH?A7=?=+b;KrxR zkq~Yq3y3$4YydIb~;X!xpFoL z)eKsm?Xs&jZO%~&YJz$sYA-ZV2tY8zzYs%8@5`jYe+UEv7C@`tkpF4Wke>ih*z8A; zz$lN5rD|ZcDKbl?*{0^>Eb$LMNPslxRrG+`Y#3bxFlloZ@UqHL#6V5kobtDHrG9%2 zJZC83``Kaim>$_8w6&y@MumsYkR?mBnS@)jC1y@WcqxS_b`{WhJE`QCaI6)*NUJ%W zlH%nw4!CGz?#P<9{3gur(ElaQ$EW0CSQJ*~qcBZ78prk4bn=N|}JQ?(;__(5_{ zpV#YRqLma*>TqDZ-`WL|AL7GEW0?_ho9`hnVls!Kmi)zP$iFO_GSx({bzV9-nc5oK zjV-&*lt%-$HaTFQ9Ar03S?el7<)nCAI4R~fDE5S?#&=zE&XjdO6|$I4Ij|{72~S&% zB@B8#%j=}PRDNF>=;B@ZMOKKWTXEg`k#3=0}m6{N)Nr@!K86X#fP`bPgW z5G)os=hF%03RVansfB@7+;nFPxlz$W-Hz5R~O;)XViH{@f*r)(!)wCQ+MMMll zQWefvpN~UYQbfXT2BPvy{6{D2z^&+mXH_cz)f1YK?LMuVMsp^e?fLFQSq)}8sKz#% z;kGyA7!ynU#Y zO_FBjCzjcq6FQf?-d3s#Ax6~}W;U`b5K@;rf zrKcl;1;hem3N#7S_GtjLxynY`8-a(1G*2RitG&`O!1mUyM50YxxbjB{I#$SyjA0CATfPYcqCwK_4 zI$PNxXbGTaqXEqXq6hJ%zvh!gG94usl%Xsv?WfP{OT`Pjawg1g#A$U?mKs6!N70es z-Ckrx5yyopV93BBsY?)PcmaF;FoX!!6PV}neCszW`BZh~1nE>sY5^u~%D zZs^U)XdkIje=dqPR4P$)6|)pl^ed6r(Pt&2q<%W#!es7hdKPthyZU|>_);1P#*_Y8 z5GPkr`hw*Yvz4}!N+gGk(5ohgE)#1dABIb380bhD&?xo4Kbo)fvlWli1~oAg#C6C$oE|L+0sE$N%fk-(*NldzB{hD^vPM z{h}(98-%0Is6wG1Z|kxbRUp{O zFWM6uW|}$UWAT|3?h9-D)mZuyiwT@MJOo$K9i19kl@LX~LU78)C}b4kBlDPUs}YiX zOx7q%+NNL1Sv4f(0f%z&fyp`U;gL{b2aN1wSl+~Z$zPZ(hEvZWXT7|oOU_~P(MUpI zcnrTtGjh9Fj?C=NW2QX=31kRJrmw|kC;h7(B>4JQ<9Va!w9PK4aWZT4q;AM$pGHam zK_Dzs4q22MiSe0qkz(a8Uuyrj`wZJNMua8*ppeHMCgi*~2`-mYH|6xHH&nMgirXXM z2*Z-PtA%7tLnh^WpMl$mk-Q^E6e2HrO>(Y(pU$t_B8akLb65;M8U#IuuTi-av498f58c)%k;NHhn)=!Tv3 zg$BFJX|)N;#?jP-tKL9;S4Ed`3>^R4?+=->BEuMWreF7&e%kRTF;k{ML0coE5mGKc zJ1Me}?SOOw^Ng)+uhU$hi2G%ixhu=~_{engYDskSYT>p!f6h=P4q?G}=N-jgKRb}- zA>cUh=@4H9P*%p!df=BG38#iddzGVRg9HWYF7`=>%PfKAmv)7crzggG8Hi5f|Bge= zQF?5Oi$sU`YfL&}prgkirGT7`c-&yHO1@&n`A^CUr$|iV*()r`tNVP`$MfSqvK6Y9 zOH)`wIHSmGOUxoWt$@y=(x=@Izxy-QM+FLyP;sp$nsYT@c$(Z;;xKZ)JC6Rq#q z+S0D)Zw)Urp9(8fULMW&_xdB?uG*_t-wkMnSF1y=H|>lcFZe@_7Uf+#r0<#|Uupd- z_;epz@1M-phO2+;Bk0^NZ#=-hbJ^rFUCk!4?Z|kP`HNUez!82r#wKgitmRF;m^YHv za-#`aC?*g$k~o~;-%Pt1F6<}-K=giZxE!a{(aq-yk>MtMyk%;ax;fL!xGFt)q9Ayw;7>X-{y-D31Ss2KHmzF-a-DeWVx!FiA`s6cd#%7U! zfXF|WIk{>Ds>m1o*u^Td5R{|RT@z_YFeDoU*e=}#0$=`msTW1!cU1@%(ho-}W^o{T zSbg+Qez}QOsJJ?)YDtJs6mPwyEl`rldut)7@ZuoQ&N>hX~(Jc&82A>}-q5D0Pe&Or46cnzBpL|+2JkPscrw^WQRb?d_Z&g)*vG%hzYtEzi`>6{SYlhK=QoZ{A zwo7s#;O+Z*y1a7k23`}!$!?z)uUk~o9L*bh3U!y-fM66#vTyOjPi4GnU!u5OVnEb% zG&QV+D5XfX7_SQ z{nJ6rA2`AOyTzapKFKECdXQHT_qczZM!gGI%#ts)0>kM!$#lfA#`hwD0$(QWO*-S{ zjSZMa>SzMYF;)D|sbl`MDR*YeKddN4-g>+@L8+qm(rq+7hl$6?b@=iK@jvrqC?N@<9 zkiq`#OMz!P#;h#7>N$8y<;xZ-3WudIWJ=N{p|?W25{9Cjvgn#87E!7Oz|Jtq3lINlnBaIesaC-()pNC*6jf1u ztbHe=(c{vR?W>yiJ4#I`uWsG0TX@~7^Cu(W6vZX*rD7~m4UyX8Idvewb&;F1|6VTf3C2=ydgWN!MT4PTn3X?r~ZEq9}Wzi z>lx7Lb=PhgNnDL5-Yy^8+FP-3qkO(z@OmgSX@4Kc?!tWJx&C|R@s{GfSVB;#d)7|- zo2B4OQP~2$Loov*p!V7@5Qpwteak}`veU3h@$U$eguwJyTs!2fcW~V7pYZq`TOAl| zFFwd+9iZ3Sar4&|z1|)d-*%sWPb<>*lDugkxrGH8Fa%zN7NpFik$!P z_6YqZV<$}EEVv1iC)Fss3c&2^xRC{AQMGq5>tCwHeAW*=l!w;7>0v(b=#WCu*@|h5 z-6?<#Tnu`S&Yh?$2f~Bv>XU&0b)gtq84Y5#6{Y4B)gNAU@3)ro#&UB7(=khCt|MRi zh5BRQiJ;M&Ut=#qDqaS;9?Z^hjA-7fRv|v3O-rAj``^YLh=^LH=7by=yRrpxJ+=4+ zfgu*jB8rxKV&tzE$b`>Y7K_pp%tk`7>MwPFe^kW3Y$Z04W`?5su=Q$PVQ7asL}@8W zEu?jZOM%rjnpExU+t$kqMj9&`%zVgW&e+J+)QLF1ID2tuL=`Yr0NO14w6zUw!~2@g z1`bn5E8{`S#uPMCwpZ$d{6E(BW+r-a_=W~H^-kAxejF0GD_|@A_Eu4HYvQ*0b{R^e z`MxKgqH+VQ_td}8jF<`4S8N9Fj#&Hkc-zXPlorEs+A|c^ajA@rtY#TGEMsx?98kJ@ ze=rNEGP5!KUGh!>d~sl?@kZ3ovoP?LoQ+kC*m(3vfYK}@vv-6}a>5xs3mld6jd$Mm z>PciDaxQRx?*dD;vZ$KL*8WjDIoX;2+I-vrGXi^@Z772j66#GooQV_lmV_ zcBS!m!I{_fhmP6K($I9KUm+wFktt%s?kVe?IH?j_>Hu_FGz9`m6aaUQJdOrpKN;n@ z>E-|-$gFsTsGt8u|8g!xJwK}7(GBSz!!N?r?bq-3h+1$OU?#}PVhR{S69gDSD`-MA zuD?@-OI*k|Zc{wSy##+ZJU_dMEY5_s&s!=dp8w+Yy3Bg*mPzNzrYI#fbBbj6!&6p{#~@M7W0boO5S%^Y%EmScc;~%;n0q>`{>zy^qIJ96q^&{5 zPQ@d|ZTs}aLb_+{n9H_NqmZ4s^)==+UfeqkzN!#_K2%AmCdO4AIZvP_cJ+CC?zIJSUK%0bTnQ zMGE&*ow6v;%7@{V6Tuu?yE4aDUs0CojE+tt{(yJyCJ*c68}*s%lys{4xto|d0#`@Y zA3b)_^FAz^cE|CL+J8!*XRKdZQorBV&l{BF_LRu;pXqr_AtM5Xl)T$MuF6|qB-m~8 zQK_|FhWeDcWq;~Sw+@|2#-R#>iAO8jP;v?V^6#8nnuriMwI?zuj&YQQYFm46V35*-v+iPFY+W@F!vq+WgHmh4w<^+&;v z)(L1N?=--eZh_IdcwL55Zm3mgHgTnSiU%llQRfq5+gNLg>65;8YW|bsCI)w+!9&*L z>gaIrax#SlIyjHRK0Tz-M?9%FfF7f_>E*VdgqueZqYY-a()|m>oEgl8SK;~N5aJrx zT`huzAyvAOIc_#l)+^4i+uF*_2bgp3ZNSJHf9FyB@X+1Py92lfg~FI)YJVUN?Cf^A znHQOF9;Dc#jnJj32)uqyFhczdnf=z}3W`!0a-}2aEgo}T>neEw2UJBG=DfO=M})N9 zwMHgX4&j)57B3-uB^9^?HKMf`RONp0uMFNsem1*Lz|_M6gKNaugXF0b&q!Eqo@82% z$QoP;LU$kd>PYi?tQzk5A=+6gv>N`u#(?1cg!+_b_bkHMtW{{x1l`yS>IR2JBbG4B zCLzAHimDhPXbGpK$OVlNL9KVl3;4I!g>~tPtGo|n2uO3^cL@N7+yRTAX^Iv%wDGws z*+(t^WL0nB+5%ZNRG-nIC!ToLz)t{DhJ$fkR5M3zF++a|vQRa41Xs z#BE<*_o$P);TvbD5jP!D`$%5C-nk^E)-8ix!%*7g{`VcI;1mQDdKv+j*{P4yeB*Qk`vd$(LY4c;uTtOg<8zpdG0Z%(& zemWmo+BH6(b^F~y>OKcvV&~|j7+)30vX5m-qH}o<_eG(^QQw!M&Qdg1qywuD^~(QPTJX^F_U#8Hn+ZYY`}A;J&f!|q`iuecOvJ`7EB)5Q%~vMZP8tpG z_91ttQXYs_D*dK~jCs6xDJH5f@A~`V>73X1xeL42^w3GXAl)?KBBICCbTlQ>&bhBUfnEEZ| z%s}st8jJs(_L$EEqq&qKUbSkBnRoCvftDGUQKh)Vfxp?*N-9EQTEr=WR`yh?^RZdW zdyS~m`a8=@Dm4wIj*u^~OE}gor1^2-(8N%W-0K`;yvhU|bM83G%p`BFNSl1aMcxMT ze3dJOF6=V9gY0B+zSa;+%FA>Y0e>psh47c(Aiusl8lila3EVYAz^0nA>rQir zONW*#Ytza1a}70rrg76#<7X)nrxFLjkYNLW0Yk6hj90eNGH*x{?}btOP9pM*G=7r? z#zUa0dUm$}zjEA1mD}2xGlH2(ihQB~SLY#im|XsvBEFOB5Uln2$IbSUMdnVuw_3g5 zWa8XPV`OAx%tPRv-JEgeyQeKj-xv2g&J)Ga#pw+5_q!)|UG4p)3-8c#zRQz- zaR(_-&p%u3L)7J)m#`JysDd?PkfNH^PSPW@2dd;m#Bq-`BdKj8MXnifsan0_wZU)aw8|F$+MmMt0 zk}^RNzGq*xy|kBE{N_0$3NV%A=hYi*@3RKQVDx({-C_^4172*Ah{W&a(SJ#C)O^uI zf66#Y8zO?nd)D?=#>U(R}N{FTq6SP%{$WOt}Yb=?_y$OZ_)A}{3 zU2B=IdTc9S-#id`dhV(mAj#|@Lbti@VWbAT+a9oNh@}e$)uO(89&Zx5-gISi;kb3K zR^@2FP^bmV!0PFhy=PvwZ&DDWBhGDmr(^-Dtm z$x$nkLv5)6W$=rI*LwHo9G=T~2uk6q;dRZF~kbv5r336W(A}uW{f2j#19Y`57k2r ze$bX(s}L9PlOQ~3^BXJYF>uvOu`%7k_%@j=$W-9dA`Q(YJ_3CMSNlmh4+r=S4QMaq z8lcne_~^D71pgzaT|e5Haz;gZR;+$}rYzzRA-+!&!eCkb6$8xG6V|DdQDT)cDF~OO z`P1F%&|c%8WTtFTTSNDR!?wGeixvxr1vLL04Cq)UNdBDCHdqD3dd=GVwmNbwfe-LH zQ?by+6a7vm5T+7S)x)!o%U;%n6(H)`gB;SP5K1b8@P9{Jz#o1={Z!9F8@aM1Pl!S~ zJ^(RC@y;A*2KqN7PKD*Oh9<*dw<*P5Ljh3Fm;GPy&Ztw!igQqB9EpWua*AY_6=Az~}wy z^wHVf{eEw7Zg1^w3{r3qGJi#f9jjgr9O?{!B{h7-hiyI*2Rz^}#-XU>@h06%FR=^1 zw7FWdMwgh*SkKYo%a@DaDOFjuSH8=HVws!@n!S-ZxN38=E?^L?q1&(=uqQzaDXjX1 zBAFq;ih}TcbCVYv3OT~sIT9xE5)<{#cG)Ipp!HbQE~o-qF2flBc)Ik#pHb3UBwOn{ zi(3t?tB0(?n_76HAD7$tre4-oZJOl&2>-3aq6oplO_Shq{X40`ciniHCkLXCLsKo^ z`?nJkmVYiBL_scsnOH|WVa)kK?0ncav!?LgQQnu5tu?1&Z{aG z{&z7|$}=KAKB6DrJ0c`Eky-$+D^usA?7UfA_<|lGz}p}UJj{@h&sRwBHy+Sn&plUD zznvTamT4i>n3j<)`d~xv?NgzbnJJ6_m~1ixlN%9Y@ezIzQ=!56BFHpM$H-AXxU)uN z|7@7W<90b?Nd3|WEr+^*Z`uNUsvW~?RT08*|4wV*rHBv+BwQ+7t;C;BJ~!aALha>U z^*hB3;-x1DnwO8$=J)Q}*am6~B=1%xXS@#mG3kfo_pF)3PO0$qmtLLUJHeL(QwC$M z&Gf-|)3MyrwXirXds(l<*>9*C!Xy(tp{|Kvt8@GZPzH{Js)5h%mRNb(x112#bSizZ z&K2-346OkpMXsu!T0@q!UB7E4a&q(Se=_sF!9uLKP;%P_mZrf1YtfzQ>YSJ3@!{I5 z8;%4pz$d`1BLJ=1NuJ^z3lONDJRucK*h1ropXGq@gt`87o3*&sx;_ zoxNHWRs2b|55=rWpu8Fc{ad~6=~`em7$fhn=c5S$ze2F=^+r(AVULo7M!(rBiP>dI z`aX2&gq#7uh1?ZZ*$F4fVi45MmynWZV#|5u<>>2H9xWV$_DDcaY@^7QBEEEt4;{OW zaq67@C>RcFW+O%c@LY~X6ja0d?Z(-+Z6n8Tzx6R$i2@N-0>P3Gp{FlhR7kPm6ezwS6J7)9R>S7OKDA;H?w8#e66;DOtAIOwHd(nB5jm#w5H!me{tS z9QZMbKUpIVhg#KEO_Aw!?{qjF2cT&HH4D_2EaW0(hk5$hD(Y3^+30)sVhZ$k%MOVD zuqN>NsU(<9} zsqZDTQ*^Nzx&e_1kVAE=oUQ;!*tOZYIUwC$f0M%)C|fU{=acYUa|qk$I4E{PZ1*FI z*cO+|%>h@$_Kfb7-b==^e&rq+DZ{dch`XaUAfrVI3NYuY<4A_$qrVb}o_1te@aL2m z8gQYSz>O_~N^w~1gR=>h?eKs6{l_E&Gf~kfPg|te?P^%z?m(g2Zb#Astl)(I-3CIJ zn&e0mHWu=%A!3oAs?ZDs$#0?>JtPl|FLqU3^MF4+#kGz(tq4^+dIMe!(c)ATnESK# z2t&(o4@ECgitVP``ar0uClZCy+z`F+8K%|^&EVAB#+htx3q_bfdK!xaAg6=qOoN0$B4yoIZ*0%de{eh(1(}yG=3lBwqyUpKE|zE!56vL1@4bBc9#U?}8p=3oWv?UDr%CVOGY6*tFGmfk+DvOYt z@uEqqwO3u%7Q#aZ@C;Gj?C8#RYzI`c^T~&fx$Ki1Hk^RQ=Tv$|rt}Te#*x8ubWyb% z;|8VP=r#Ct4^20!!TazEuwnL$Ir3M4ye~ZU>da5UX^L$}a} zP6%~++}FLP^7(vId&cY2ko8@_R--V}x*ZSB^(YTuSs$S`9`xLuJL<=1RpH!1&DWvR zS)*lN7$wFJDn|rw&VsS;4gFzDZB1Tpl^@7JVR?<4Qw0?1@Qz6Y_teD1f>mx1AM__z z)ac6!O;*cDbF1egeUvDw(~6O)&g0J?(1pYEG2>aCBfN6|s0m!B(L2FR^}nE!Y8Wl@LmSTjyS=p#1Xx7KuP?FvuRPQsU?+ zuBVwk9aT0`o>z{op^VnMZ%>G(?~9dT-G`A{7p5l9BrOPtTpKa-*l!tb!%$R-$x6aUvv*CTug0 z)M@0lqb9={D1~xSDUrR$xUu=&^J#ma#kC&!gMrn}I`50a8>bFgHc}8{F4$acYW#}; zjczeuXD_76`D#hXti6e4Mw-dLRFbIPzd}a~^)1i5>2=e^hLzof-2)^G}r&mC6 zPuc%Ew@C3AagJEH7lKjPuNs(J62IX1w(@J}H!4mLiqY!k-Mzfem3#U0%j=}rh4)tCq^ z)79rm z9&(PaPq@Ps@BV0(1(vSb>kVBL(O};c5K(+a#yzS}sYvq@*5O0zm3%N()`6mmSK>7g zC>4KK^MsMgmJl#RCGhRA*qtxaLSYtlXY)1rD@Cqs{%eIS!q;`U!X^51@$k8M%%yyy zA!Sj(kFf_eec;Qa!mKJ@Uq`4dz*{<85lStyQIwu8s!*N@m3U@;0R5EFlxm)E$&fQB zO;Dg*w{L@iZt1Dkrp1W8pxU^k4w#=v7l_4j5q}U&b^E$>@C@cCxt=lDgeii$NL=FZ z3AI@j|2L`_^G$g%<;oo^^aO2W5jFGr!0%w@K}MijUvfv*{2W)c<+2l~{T!t}B6dEVK|;G~a*;f7X*!ZuGU4}2ogA1J z3IwGbqha+~ZvCy_u-belC*n~6*p9+K(a}O{P9sv0Rs^iqSu~&2nFD2mi4sGn=bv4F zuGz+7#VN=>i(Lqq+;`Az?IFP%1`p8cak2Y}?A%t+^nX_ceJ!HusI&MS&R`_x;po^qoVDt=2AF z5Sna}hWP<*%J7z|mGt$(A>c)0J6>*0JDN&~%PRIP%O>5kEQu#xgA4KhqD5tWflG`lR zv*7(5@SG}#`uQFn{u4|It7Ps>m$fcjl*TMc1 z{mOC1h|+0ajd3mgG_6*RaS2jZNbpN{B3|;&9>mHyRwd6qhECF$d?E=w*cfKp2*u)U zw>uOUMlfEhCi-TE1#x@fVfTcKo{6khgmY%Xd&3_9eJw}IEeG;2YscuyEVdLGHZY> zc3YK|k`{S;W~C9b%+v&Xp{@ps!S)FgzQ9nASoYN1C4j%1oXi*+*Zu7|K|>EA;S=mOq^fgxb0ZUsl) z;r3lSEn@q_8G-;w;pe#UpYj#$u~0=IL<7$>CX@u1X**}iN61Sc$383$*+NsUCv*jE zt)bWz1bD(+s@0*?zq)?$fywr_1@Vbk^p~y@T=4#0xci2SYBb3G)zW z@4^S~lF4}nMkzI}D)_O1=*ZLTu~y5ub07&C%fj^9(Pv_o>SgjVHVMcK5FeY=h82Bf za$5>~8{(5ji_2>W=kyoXP@*$v8@%jE&6v_Vl9|>%4obP`&zI>)@vf_~ugy!{w^mAT z%U*83b>HMzB6X2lm zkH4-Y`eCSpKv`ifGg>&a$MXWglk)G>?MI6{7%=7r>Jb_hy5)Jdhm(mwwK8Jo=@fsM z@Kj?N4OcfsFRRkMIgP%HgfOEWT_r;{pG=P-uJWl%Pl)N*CJ0CBjFv*U`>(Ux6_uYm zHiPAc&iYcNcj`FJl#be5YY0a}Z=maSMqw~li6hT^y%1F#h(Hb|qI+Rfyv0}C5cE>L zsfw=|{o{Iy`=PQ-Xng$r#Qn&0>+;$3C>Cndv3o7q-ji0{b$Ck&=vI5CQF|80UfW@C z3OQAyi&ogvn?bt8Yt#Oqz6-@;o%B5nBU8RKrTuCX43WJe61b1%9qdezqO2TK5 zf!J!KTMC>uIu_#{pXihrn5aB4C;*!*vB6p1-lgfJrG7aovLvF)qaE~KcsX6gp?T^L zIZ_y>I0B3mlJ#0dwwR3-S-*{BDwk@F-0DTd{I+3mT#Ap9UIGo@pojc~&I7VQ2+zzt z|8iVMP1nJSiFy1up2cTxjfs5$&&>IW7uPZGJ|(!b=uYB=7E0^vnTZ;G`NIe8U#AvCp+OMyb&Xbzo<7?3PFPf~>&fT?` zh)J?cKtZ-7<}YLKJR&)9V@H4n_a#4$)On=!|P~>wnHn>@dp8n)*nwy{6_T~`haIt3g8PRBw~hf8mBHzAZ!V5sxA%gD>s-7+`RE2g%4zF{(><&IxvaC zbh4*FNz7M z;D?v!e~~8$O+AdzQ4W~wdL37+`{QB=%u&UYi(EBgcSkQQ@R{jg*!uMVob-SdHWKs( zJ80Swuobke*@k-pUn&p^OOx4dd2I%2lBpm@JrpLM;z$^mO`mc-m6!5Uo zqJSkW-$YZBblT5)m>Pj7O>IwqjVvAmo&QQ72$P=|gWL`hV0mRR_#@CH%as>}a@CJF z?hX{Xy_q(a1m@C_UIIeNi?i_*%r8@SXnvjd@g&X7p0t|+t3UC-i|>T~1ej@CQ}ukS=oK!x=T^fgE6RAWa9^N}>$+ltw0SWesO5sHZ;$gw{^+ z$X$shHV%lFI0BpaJ}F}z(o2t4sX2*kowM1H`~(+F&5{_>yI{#pXQ-xujqE;kdC2qE z&OYB7PX}ly=^NzXecf_J70E6*l!A3+04C84n(WDZn_ zpa<`pZ(}jDo-s3Bq#_{(Ame1;svH@xMG5uIU0i{IFHeyOZg%#E@1L7TpA3} zO4#(Wd4DOp$j@0}5b6)N67%3lNp2mCJJ+Z@*1m4hQJ9cF13z0c;n`TLT$C1M8$)pZ z!z2EnK%KQ3PfTyPYMOrZzSDYwXLZ-CR3VY97sQb@8DFc5>N)*A;0WZ#Y3PBNY||8%h~+N*`g}S{16>4297xy z2i9ZJ)bk+COcnUtAp|t?jc_ylfz$ss`|Eqvlyio!Z4=zN-{{BAq zd#6)x9Sff#-iKG)BJZ+hW;Y-u0}6~-;}T%7nD~tE6DDFyBybue%%st0p;b^GBM@xK zpauht(Ym^=TwuO~Q@$YS>^r-pWP3{Wn&^H`ADox?W~)~j40~!k@O@2Q^u}ZHHa!Po zUqCiJXHC0cu)2dq7&sq;{->zlkp0)Q+2Z2eIT-k!|CAzjgScQ|0U|FiNqzgLch|(U z;MZnC53i|>Kb^eA^a0tlXYeX%7gDm0!60|w?i`!?aYqVAtXRJpRn_%&x^k16H$BpQ z0(B}kfC?xcKqBaTPPtmQn>e1fN}MQR;(B@X@5B|OIKczjASZN?MWabkOQd1?NBc#J z1F=-qWLXBLq^VupwjmR#q>O_gN=UPu@MTC<7bNvwiZdzPeyBT-Ns|&A5lEX44(HdD z@cB8WLvLHKs1M^HFL*o-e^i>5w0F`+(NFfKxR<_%9ah%|rRxG(NBh!k`uyL6afSjzI zz!~zHFu$!AvQ;4T%g@H1O+gW$ZhhOQJ7M^(v^mq>Yc_D-v9W4EtK)MGVqU)^Q2h1% z)@1bwhVoOydZ+TY&+VVr_($5ysUDf~e!t<3n-VDMlJM3+yc11b#i(HAFAzPWD`oN#O(jIws zh9%OXyxOrs|JbP3;u<0#nPjI_#+p9|2!D7C7OlCjCG*g7G12VF&QUiKNKeq9v>^fP z9hA4w!%@1SFZ{- zElu;-JW1%f`*L#pOmPD;)9X`d{vyjKD%;_aK>V9+P&CtE$)H#v__dg^%5SbCTpFc; z6*JZ1I?mjmci6_C(7Jf4DW4IPbtl7jhso+c zHw5}CTlbfXVHmK|GIOzyBTd63+G7G2spJ2vAHARK7}nf0^|?O$G|T;Yt%&L{s}?vQpW%|U*gT4o0fIn|H%`wG2alDRIUbdx@oe8 zf=&qiP48bO=_FknvtB%cZ>b1;e_#GL(Ciz0K{)M(+jZXluokO+?dL-2d3_8O`zQ)l ztX3}0o)tE*97V`&h4~CNkTGnLSB|eWhxy2tTXqfuW^Q7$jnT^?H*8(vjO6-X+&k1X z-h9$uusF>A9APu*x}NP*gl%vifA16^jw)Wt5Kphomu5gkS z(Sb&xx+AWw(!1u1F|9!_y}MF?8EN$C3wQiak$`1_1g=Y zImCWta#N-h*U(M3fHYh3iM5kB?_gY1hLd2oAcJVFut3Kg276Ir#|Hkpl-g-Mca2<0 zSm0u<=0Is4WP%GjD{}lYX(SB@{#vA^cU}NBdltW~@NL&`BWBXKJSVVDRT9B2VJKiZ z`z3BPz0F`R^}iocZ5ajyk0#X^AnDAmvG?Rfi(boh=kq}S44!lZpQh%@!&Fqg^2p^U zcewyHdL{0`4W-SgudmNFt;=Vgt~H-71P$KoutwXOniCdB&ZQl_$Eh{ZnGjJ4>nwP* z()F9vkI!;y=8@h&-;=lv z{4QU*?Y}nQ?efUc70UHh^kRP92g&PD;dg=I*m_={IfmzpH$9hWBp{vnICelda_%z0 zdO4bmVhCl~A7fl+U|PlbTi;4I`Ijl$t8C2ig0?R3q3fiM!EowLCRVyt{HB8v?UPh z19P5NgCU+%X)?e1w+Sbfj+#xO(7Hy=O~m@uRCyfP3mY4_@tyO) zyIs$ORAiKOrjVjgiVhNjUM|@+zVN6}Rp*R4kOR5Rgio{sZVIa_VXxsQ>XCDn9R08) zxbtag1Pr~?FB5Pg>}Zo}IV7{+=P>$Pj=K>Kh^wRYcgJG{BOQLW?5T>N-2z|jD}U&LeVjBj0LIbZyJNcOLk#8} zy$oa^&C5vZ(Dj}cH3gINwA0uoblM2&hnakaMOsReO*iFyq*z(vY4^{W{EJRF+>+8L zc(NLa1L?-fGp>l@%vxdgkXdlOcL`_rj(!R zduwW@h4TrRqu5QP4HpKgQAqSdJ zTC*KSLj?451tw^1A8CCkb(HKIdqRnYx}>ypTTAzAKNHagCjJRA4t9* zta#+0Ci*Zu%ADKqh`T|-Zvc(TSb8oG=omWHWd_`@ZDZ6x=pj{{R!Am{2eGNzzHOXz z$R9|k5~muCT;e(^hUGTY%4cqqR0MmVYvL}NsIY{jR~EghMCoP|0_N&T(hZiBzi2AK z#VM|&><-!EOzh`5e3@32F`3PQH&%j2A})ef{l+ETw&JyyN`!G3M?mgiyAx%N$pN;1 z{_-D%MI>#h%AH$s)c8hp{{5?sj3tJ7Yg)&@1Y zGRP!kt1NHa z%!t#zyw+TWJPFCF@(+pOA!Ly)EK`p_JOsMVt5E0Vkw!nXP%=Ivs`gQowbr8$)5xdL zE6lYkDk)OZJ^!cC0O6tTvB_&4oh%5MtGyw~-sjwo#8&xmlYPSSgh9HZ`=FrApJn5j z#vR*?5h1`Ev3z2tR(TSd88}wfOD}+c_flyb3mXw1OqdML0Gn^RC2n4~g)xWVel)7*PvpVj9!|Q^`kR19w+a8>Mbr}3#NUU+ zEzc-p!qic)YbOlPFb!zR<8&E6Nwy<_>sGH7&hc)M|A6lbqGCwX9)4i@pi7Wv5T^V} zTS?SCN5VbW4VezW>hZk;^pw}W;z=m)v1pil?ocex7>&;B8Ud23T)6Lzi!kJhCz;q0 zYA*nZ)#-{iP|w`_k%V;8+OJ)70$oNu%1pwGy~khy4D)h&K=_L%n43$ zMW4?NGl zU<&xz`honPG}!}gc8qUGARsO}ARyBJb^gN6!PLz5f1-u8c4Y1Vk`=cpUAW>Uy3POLKai+ zEwptfNAoJPSLo;@H87Gdo;{qwUsO=1+00hkx*-a@~4vvYqI={0hyU zb%olr^!^Z_b#I`M`K$>0Zt(Z&zE>S~o%b>X_#I~*^j41WD685%H<#T6II7>!SArJn z>9SVWm}1K-$SbsF<3(_?Gr~j!O&s5RT#OyvtWF82=Ltx|i`uVm=j0;3US#R>vuBJ? zHC*8cf6jDaJFDsnvPbbAj39iH7wfSugWBORE@t_cYM!243P!`3e3(uA!xd^S z_J5x1)tmGxuW9UM#kK~8k=F1aK;X*D<7})i*C%u=sP>tWpnaF_?^uh2Ni1u z4t`yB;H$=w^CuEF*THJToTn3!cxq~>86JYiRMt~mGHs)mgKnz!J8nH#ULEq4JSjoG z!za-UlgR#5p`qM{{O`OQ)Sf>qD?p4ux`aF93Z7#2y>C`D<8XuA*#7`)rJRpX0@XcF z1XKnz+yn~YSQ|vhfvUsJOUa@^G!u7hqTOJ}RH1uvzQt{I&buM;if)LHGu0=F7S}_^ z#bn?%99|mUju^J33l?eizTY6^fkGC3boG|uc)}3N;olG;JUp?Rd=7vc*uBO-|HmDz zY=oF2ksW)wvgPmd2i6*XPQnrU^?6BV&D?!-0zFVImxZr4t1~~Zmru!+rgHc6LK!EI zQD6HtH!!$I?u%esvw}(Td*l@|F1Z+nqr*mTYyYX(oKS=)zNLk$?8W(nN_ zary(6bLCGzkl~UlKEF1fN{;}@+DW+Jg%g%ozU0Ln5F@Vb3Dy9rIQKjXj9s*>tSQ;- z5%G5|ON)3yHiz6E*a}Ny%PUjORLo-7fF9)7fjSTOMp|2JO;?%7vWRtOt9s9~;@C?= zXo(dr`7(V-ZfQg8-^O(g3J(F1;5-l(*aI&OpT^b_xbVB@vWv9R-!LwR{i# zCfZKxU;!%Zw9)eQy{dz$P3ZUXeLRy_@vX!uwp)6z?u{F+X{YTtuTQh3{~*9V5NR7l zvyAY#aZkahppKSMKFr7-xB4fJf1`{A8>LdZ7zl8AvhiiDBWhKA>@6{yui>STAzlmC z_uki)SbTx^(aAff(n)_kCE|}EQL`fsMTCRJ$tTY_&oRY7EavPm>NjL&HoSnEV80J} zkKvf_j1Z-~XH12xdRxn3V3w1*UnPcbv5`K;VRUka)bb&)+H7qMfi9}J)oUinZfqi* zMYjmCzO)=A-#bwVmILS21Iu~kU|O@+>z2~YH|+iPhqc}3Pp>Oq)m zG$lwt#<8hk`l7HZBDhZVQGWTS;OVp|GWFcwA-V65NhG$20^ehm^$tu|s_FQ0`1U7N z!xTNd99Bi0sPzdO^swb!0xV3d$qm^h#+s@8iJTnEL}gE7GP#hL_)sLSPy&xdS>>i9 zD>Io=F_3C)iR%&M&P!Y2-b?*+!Q_Tnw}mw`d9o zi7Hbp5QUAd3PaqKd4PSZJbGqI&DxH>&iv8d`#s6wl&X2MgrzsM62PGDALNT^6_H?C z-6kI*z5)cDNgrUe7rrzX4Xh`}mp{A6`@x74eFcAv6}5XosjVW=73d3-<&)FZE47le z&(jfmSSK;#xRv7EYGe(AW+|sQ!He&!Ii6Znz?@$|bOfIM*4i@3IF3!LDN*z|Oas7@cnX!?EKkGK6= z^+%G|u+;0}!Im`BjxQSMO=hk~v6RgyKx(JLoa!KJrmay*XSnmbtc;;+Kr_26cFjr| z>5|k%DXN;FI<0FUl%KTAgj5^c+SAResMZn)<=W)Rcsv@sn8;(X-Eq>fkSZV!G$jaR zd!Yh*;&4DtOcu`(AjFq9A0ZM%$I$e)2A8eufHbWA;7gaeX+>*tFpaRrRBYKyZCU}< zY8z7FbDcGAUj)fII>>(jSEg9YItP>27j4+hsGI8-84HejnW|2DSu7*IWUKV|=<8}O zJvm?{kbX3BtF3RU3aeu0C!9nEit^R9D9c;Pg$0jWmXVU0N9yiMWE^qSIULQ2u`5L@ zG;ll3&)!fP#@ZMb23g;2{jr}Zx1^7gJBRFGwTnGkEwApi{)2!YQm^;fEU9%q9s$0$ z|2DsQ)1|K^JtbSni3|jkqyYp({QuoQnAyA8x%>x!URUQo0QCL@hTkGX501!$NYA?X z@F0Id=@uj1U2!6%%`rgdP?sCq3nb~ftaQ58etOlGG1#fjuenY}fD_kLJ)TzGF3u|p z{f(V^B^$@`WI8@y`vkskQ9fR+1O8}p?AS&hI+3k+z4GCZIweH=Qtf#)OhikPd#xDh zXEI}xY7T%i96a!;IZTb>DZV*+@J~ zrgID~vyAzQ>#tKKhSm;l5zl)71g4(hfcN``{AS&gM#HN#%ujvjUU*tpY@Gzd7SB!# zH${|ZCK@Cy=Rxf;xxZ1V)o>Q-(r!j86Q;k7)R$>N#<9-*YR1OpdyF7etk;~EW|dY8 zw2JIu&*F>oT|(;?9_aXZ$ez>_!818hlw1LK48A?)&s@B~uoWrT15gd>HhG3)!-UZ# zACn7EmluWUT_E~v{|aL)`Db_d@rQ!IcmM9}^z?LygW|4WDrOV;sOhCw$}r6bshTWU z9D}mF0u22Wv59m#twCeN1h0Y+vK0WhF#=2D)_fr1>#u#G@-c_|JWp@Tq-tXsC7n>@ zyDqoPm5x|~81&HmoJ65k?p@SrvJ8~DC`u$Fp)mpi=jq+Rx{i z!X>+Qe^XzYt|X{$_!h8jP1mGQxCD;smJKHV)-9(Nd45OLXGTBuD3VuIb^a_&TKts` z{Q3Pv|C%CDeUn+nNJKI%;Y7$`y6lOEe0@ZDKAP-)!{0>_DW#*l#T6Mmsc<5Ot_m}3Q|_cz>s(`czs-d>oPThgFiTr zok{bqt^^@3+gHV_VnH?sB|~Pc42kVIrY^}MuJ0pRuLnqsh!c@&s<(3RvQ`wTe%F6) zzqzws3szk)#r4@@5`$%JU>8tv&bd;+<5#{>K0Pbc-;vrC<4}{^3QSsFBWBe3(Ek-4 zcJKR1S$>Ph6X1_q6X2sK#Oz{l%5rr7*-#L7;KAeW=bu^R{r;Zd4-;VhLGeT*>^dF3 zWyrRDRw;go{CXhQ+VnN%uvUD{`+3^oAXt;*9|P_3hM(omndyVQa>%}OGjwh(3 zsjrF=U}3{TQ0+N{B#(~Z1T8~-H)4~Qe7yzbhQj1N$v2PcGzOJW7-3fehUo@PBO$r# z9omgB`6SbJP)>iVHsa+yr9(F}Z-vSh*7T-&6`Xe$S}r@1Y+^^kXL-={C8UbTHu8Op zg)o)onA185f@uM|l&9Nm9}v@`#Q23uv!n#x-);aGYc;UQghtiLW0FJ*rsf#}Dhp(q z2@H*8wy{+(%*P^mW13;Qo6+Vo(e;_{g(vZfX(kp8{!LaOUZE6NZAM%L@jQxeSHSP%@;j{8 z^T_~a$=D0Tg~*?aYDi9zSqM;gZCE%IO|}^9y#b}+*o?ZEP9E%-5C3R*Y#RPBRJOU8 z9&Nx2J{Y|mrOdC%xPyMB)heA;9QQAOgK!>tfkN72)IYgIoz@FBGI9f(DVf^0tQ8pz z8Z6U4cCb-9!-EFw`K@Jy|Gu(OCb-W#{4{8cwCRjE{DHk@7C&0UtikG@*JmEqLC-J^ z634nDK-@s@!$;sMM7nTDQhui9bePpiP}fjNCrt#%vrIrdkIKEka+y{`-oaX&Q~h!q zQtcuxZXoyi6rM=aY%ryG&bc^k(aas$Sbj?v3W)o^KK=R`M_M02xPIB5S^sDaE79$- z?5N072BuY}7EBq2NfI!InuFsa@*{}Ojl?pu`c_E(;nfdYOE>xN~^!P@XWiF%( z@W2J7bsXQCLJpYL{j3MF(pUqW0)dPe%IJ}3Vg`6eh-)X#pd%+;bjJ=;84#ZS2A=g{bMDUt-)T+^;sMe^j%%aL zbjkBW7di*b*FL2c>HB{~MsN)4S3FvIijfg&hQ&~+V`XmTlML|NGb)8VN->~SkHE74 zM0he0I}p5yZ!d1_u%Zot4?XQ$2jW@boQj5v8L$N}Pe=Z0K}CH|ImVCQ*|chjt=iCh z;<+U{SygB}mvlzP>6fPHp$7<$Tr71$42sTUVO^9vLPnwWV6h&G)C`~Q%3ei z{55Krqdm76KMdpeb0G$=t^2T(Nci>Tt&S-IkK-Ku0denUjS-qR_B+`X61~{pF3j=-*8AZFgusPQqg4@pIV~ zCKl({2*Uc^OhKg$oA)wST{tC;l@!)hnfmra1>VjT-rrv{6GzHg4l2FH*_TQ488@FL z+7Ja}$agX5{%o-3aTx8gu%~$KdDBrq@xB2r-a|$%&Pqg+#9QE;DC0M$30U@@n-e75 z%jY27oVEjfI;qWYZ;f--4zb%K!OvoAtpkh1&~#F7y;>F3IF4}iCVEp1p5{G%gu0j} z9LW>GSIdSUpbM>Hp+?(v-urknsUbE&bDgwoot;w5?Ef|hi%IRWL0XuLMwK^$udK#e z#9^YlS({aE&mjb7B%U)*yh>HDr+H}6bfD?1Rr3plu363fLPPw z3r(Zh_Xu(Ydy(p4I3jOCU_nwSb)gdbfGEIkq9c<3_rnYdY7SCd`h4+y> z4ER+U=Fl;GkL4|ghD{;NkW~&`In*C1w1oUVJk$uaDduAOCo1t?7_Q$Fhm%ENLDZh7 znxcXqz9E<2KPiARH}PNq>^5oJfsB;XTh0qz-Db(mC?NIilB+RIL2XuJO>Gh%oc&~( zUJhoaahPy8urx3)2I2ZiBo^WNcpcc65-eSJT#q$et0|l*2`T$Ph0I6hYg#fUyNW8~XUsx_`q1^J=g$jX4-9=fH(n!_rqN(U>w26BuIB zB~F-zaz;(i=F$dZM?cw7>;;sLzdhBZgG2yU`Uo9MmCa5GtV&ceNuCvZOn(VkuE=UF z8r!wke6BQE-_o;2r%_%AfjI9snk znsj26O&lzvSs=Vqi`th_CA`v+Ompi(O&UNZ8oeuEM7YafAXTuXwXKpc!4Wg$qun z{4>8?*Md)VGjFhPTrJB$2`gILeeeUN9d7F0EY9i5uAyf7HP(>f zJ-<4KuK8PMB9ULo=RKAH=WGc6^WG(!0y#^DuwECXOjB57lPFA`()oj;o)RpznhQ%6 zuK4OH19c@T%26l4n`EHd=s)JHcCvC^WIwc#4Blag+=kZJN)@$myJi!#t0@^ZI9R43uX0dpD);50Wr(%=B9$FSVIFl$$c4BHRv`A; zZ+lVpF3_US2ooHSUVz>WDz|Ih#!wa&nuLBR&u8cu8JCNilheA{n$k_@vXWvC^pf`T zo$Xa0Eun1!qUyY#pdC_*YeGtFc%MCGLw5Hhu*)-v}Sif z*{Fitf3TExXZ@EYLsM*eP1$GKx#a7f{60XUU@|^Tn3QO&7OWt-> zUI~E(9ZF+4y>fySZ~}I*Ae9=S_V8!vicz)eO#d!5v4u^Iyx`@ic|D_C0rHePZKP_H zXZ27uma&rqr=kfPVe>u41kZ6T>}xw8L$G=C$u9?cbTvb`b1M8fbwheZH7uJL zwfvLWi#B0eQoICgcV-gCzV5Hj>qj_Gqq@2Np-Xw0G+D3q*33G)B$$+xO^8r_Ax+KOe-+L$JG5*47YVh77|a za&XW5v~*IYU<EPpZ-{S>#MR%J6(;G_tWBJpQ)V|xzu?K zi6y)~$uuodxw1Pk%AtsU4%q3uv^ga80a%%xnmy`AwN-6$>!_q3x4%)~>>1BF8Cdiv z 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 RPg8`f{|fT89oR0R-vJe3KcxTw literal 0 HcmV?d00001 From 5221fa8a254216cee67f57bf12cdf31a62d76f4a Mon Sep 17 00:00:00 2001 From: e-straight Date: Mon, 4 Nov 2024 13:48:24 -0500 Subject: [PATCH 042/180] small edit --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index c4834ac4..a15a05fe 100644 --- a/quickstart.md +++ b/quickstart.md @@ -149,7 +149,7 @@ Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-an Run the following commands to install the python packages. ```console -pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall azure-identity +pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall pip install azure-identity ``` From 75e006691f3ce5b01272aeadc87b3be8cbbf2c82 Mon Sep 17 00:00:00 2001 From: e-straight <142330569+e-straight@users.noreply.github.com> Date: Mon, 4 Nov 2024 13:50:00 -0500 Subject: [PATCH 043/180] Update quickstart.md deleted duplicate line --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index c4834ac4..acd9747d 100644 --- a/quickstart.md +++ b/quickstart.md @@ -149,7 +149,7 @@ Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-an Run the following commands to install the python packages. ```console -pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall azure-identity +pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall pip install azure-identity ``` @@ -236,4 +236,4 @@ with project_client: ``` ## C# -C# support coming soon! \ No newline at end of file +C# support coming soon! From 9a1dfe8d7b2edd4cda387982fad83b455bbd36f1 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 4 Nov 2024 14:22:42 -0500 Subject: [PATCH 044/180] ARM template with model deployment --- modules/ai-hub.bicep | 10 +++++++--- modules/dependent-resources.bicep | 7 +++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/ai-hub.bicep b/modules/ai-hub.bicep index acddd4ee..92da7bc4 100644 --- a/modules/ai-hub.bicep +++ b/modules/ai-hub.bicep @@ -56,14 +56,18 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' resource aiServicesConnection 'connections@2024-07-01-preview' = { name: '${aiHubName}-connection-AIServices' properties: { - category: 'OpenAI' + category: 'AIServices' target: aiServicesTarget // useWorkspaceManagedIdentity: true - peRequirement: 'Required' authType: 'ApiKey' isSharedToAll: true credentials: { - key: '${listKeys(aiServicesId, '2021-10-01').key1}' + key: '${listKeys(aiServicesId, '2022-10-01').key1}' + } + metadata: { + ApiType: 'Azure' + ResourceId: aiServicesId + Location: location } } } diff --git a/modules/dependent-resources.bicep b/modules/dependent-resources.bicep index 900f3c35..c670c754 100644 --- a/modules/dependent-resources.bicep +++ b/modules/dependent-resources.bicep @@ -126,29 +126,28 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = type: 'SystemAssigned' } properties: { + customSubDomainName: toLower('${aiServicesName}') apiProperties: { statisticsEnabled: false } publicNetworkAccess: 'Enabled' } } -/* resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { parent: aiServices name: 'gpt-4o-mini' sku : { capacity: 1 - name: 'Standard' + name: 'GlobalStandard' } properties: { model:{ name: 'gpt-4o-mini' format: 'OpenAI' - // version: '2024-07-18' + version: '2024-07-18' } } } -*/ resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { name: storageNameCleaned From 4fffe2da3dc30272bdcedf374de12289b46666f9 Mon Sep 17 00:00:00 2001 From: e-straight Date: Mon, 4 Nov 2024 15:54:55 -0500 Subject: [PATCH 045/180] update quickstart --- quickstart.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/quickstart.md b/quickstart.md index acd9747d..73d12fce 100644 --- a/quickstart.md +++ b/quickstart.md @@ -10,15 +10,17 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A ## Setup your Azure AI Hub and Agent project -To set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground): +TThe following section will show you how to set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground) by: -1. Create an Azure AI Hub to set up your app environment and network HOBO resources +1. Creating an Azure AI Hub to set up your app environment and network HOBO resources -1. Create an Azure AI project under your Hub to provides an endpoint for your app to call, and set up proxy app services to access to resources in your tenant. +1. Creating an Azure AI project under your Hub to provides an endpoint for your app to call, and set up proxy app services to access to resources in your tenant. -1. Connect an Azure OpenAI resource or an Azure AI resource +1. Connecting an Azure OpenAI resource or an Azure AI resource -Follow these steps to set up your hub and project: +If you already have these resources set up, skip to the [configure and run your first agent section below](#configure-and-run-your-first-agent). + +### Follow these steps to set up hub and project: 1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). If you have the CLI already installed, make sure it's updated to the latest version. @@ -44,7 +46,7 @@ Follow these steps to set up your hub and project: 2. Create a resource group: ```console - az group create --name {my_resource_group} --location westus2 + az group create --name {my_resource_group} --location westus ``` @@ -157,14 +159,15 @@ Use the following code to create and run an agent. ```python import os -from azure.ai.projects import * -from azure.ai.projects.models import * +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import CodeInterpreterTool from azure.identity import DefaultAzureCredential from typing import Any # Create an Azure AI Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" # HostName can be found by navigating to your discovery_url and removing the leading "https://" and trailing "/discovery" +# To find your HostName, run the CLI command: az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url # Customer needs to login to Azure subscription via Azure CLI and set the environment variables project_client = AIProjectClient.from_connection_string( From 623a09ce1236cfbf510ab990ee94e5ebc54edc80 Mon Sep 17 00:00:00 2001 From: e-straight <142330569+e-straight@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:19:49 -0500 Subject: [PATCH 046/180] Update quickstart.md added pathlib --- quickstart.md | 1 + 1 file changed, 1 insertion(+) diff --git a/quickstart.md b/quickstart.md index acd9747d..0e8b404f 100644 --- a/quickstart.md +++ b/quickstart.md @@ -161,6 +161,7 @@ from azure.ai.projects import * from azure.ai.projects.models import * from azure.identity import DefaultAzureCredential from typing import Any +from pathlib import Path # Create an Azure AI Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" From a88c73263d41caa34585e3b35d3f96430ced7e11 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 4 Nov 2024 17:12:45 -0500 Subject: [PATCH 047/180] removing unnecesary components --- main.bicep | 2 - modules/ai-hub.bicep | 4 -- modules/dependent-resources.bicep | 63 +++++++++++-------------------- 3 files changed, 21 insertions(+), 48 deletions(-) diff --git a/main.bicep b/main.bicep index 48e6900c..96ee62af 100644 --- a/main.bicep +++ b/main.bicep @@ -43,7 +43,6 @@ module aiDependencies 'modules/dependent-resources.bicep' = { location: location storageName: 'st${name}${uniqueSuffix}' keyvaultName: 'kv-${name}-${uniqueSuffix}' - applicationInsightsName: 'appi-${name}-${uniqueSuffix}' containerRegistryName: 'cr${name}${uniqueSuffix}' aiServicesName: 'ais${name}${uniqueSuffix}' tags: tags @@ -63,7 +62,6 @@ module aiHub 'modules/ai-hub.bicep' = { // dependent resources aiServicesId: aiDependencies.outputs.aiservicesID aiServicesTarget: aiDependencies.outputs.aiservicesTarget - applicationInsightsId: aiDependencies.outputs.applicationInsightsId containerRegistryId: aiDependencies.outputs.containerRegistryId keyVaultId: aiDependencies.outputs.keyvaultId storageAccountId: aiDependencies.outputs.storageId diff --git a/modules/ai-hub.bicep b/modules/ai-hub.bicep index 92da7bc4..6415ff07 100644 --- a/modules/ai-hub.bicep +++ b/modules/ai-hub.bicep @@ -15,9 +15,6 @@ param aiHubFriendlyName string = aiHubName @description('AI hub description') param aiHubDescription string -@description('Resource ID of the application insights resource for storing diagnostics logs') -param applicationInsightsId string - @description('Resource ID of the container registry resource for storing docker images') param containerRegistryId string @@ -48,7 +45,6 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' // dependent resources keyVault: keyVaultId storageAccount: storageAccountId - applicationInsights: applicationInsightsId containerRegistry: containerRegistryId } kind: 'hub' diff --git a/modules/dependent-resources.bicep b/modules/dependent-resources.bicep index c670c754..dd64ef85 100644 --- a/modules/dependent-resources.bicep +++ b/modules/dependent-resources.bicep @@ -9,9 +9,6 @@ param tags object = {} @description('AI services name') param aiServicesName string -@description('Application Insights resource name') -param applicationInsightsName string - @description('Container registry name') param containerRegistryName string @@ -20,24 +17,6 @@ param keyvaultName string var containerRegistryNameCleaned = replace(containerRegistryName, '-', '') -resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { - name: applicationInsightsName - location: location - tags: tags - kind: 'web' - properties: { - Application_Type: 'web' - DisableIpMasking: false - DisableLocalAuth: false - Flow_Type: 'Bluefield' - ForceCustomerStorageForProfiler: false - ImmediatePurgeDataOn30Days: true - IngestionMode: 'ApplicationInsights' - publicNetworkAccessForIngestion: 'Enabled' - publicNetworkAccessForQuery: 'Disabled' - Request_Source: 'rest' - } -} resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' = { name: containerRegistryNameCleaned @@ -96,28 +75,10 @@ resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { } } -@description('Name of the storage account') -param storageName string - -@allowed([ - 'Standard_LRS' - 'Standard_ZRS' - 'Standard_GRS' - 'Standard_GZRS' - 'Standard_RAGRS' - 'Standard_RAGZRS' - 'Premium_LRS' - 'Premium_ZRS' -]) - -@description('Storage SKU') -param storageSkuName string = 'Standard_LRS' - -var storageNameCleaned = replace(storageName, '-', '') resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { name: aiServicesName - location: location + location: 'eastus2' sku: { name: 'S0' } @@ -126,7 +87,7 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = type: 'SystemAssigned' } properties: { - customSubDomainName: toLower('${aiServicesName}') + customSubDomainName: toLower('${toLower(aiServicesName)}') apiProperties: { statisticsEnabled: false } @@ -149,6 +110,25 @@ resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024- } } +@description('Name of the storage account') +param storageName string + +@allowed([ + 'Standard_LRS' + 'Standard_ZRS' + 'Standard_GRS' + 'Standard_GZRS' + 'Standard_RAGRS' + 'Standard_RAGZRS' + 'Premium_LRS' + 'Premium_ZRS' +]) + +@description('Storage SKU') +param storageSkuName string = 'Standard_LRS' + +var storageNameCleaned = replace(storageName, '-', '') + resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { name: storageNameCleaned location: location @@ -204,4 +184,3 @@ output aiservicesTarget string = aiServices.properties.endpoint output storageId string = storage.id output keyvaultId string = keyVault.id output containerRegistryId string = containerRegistry.id -output applicationInsightsId string = applicationInsights.id From 3da23426d6e7052b235df23a90f1f1f530c49562 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 4 Nov 2024 14:43:19 -0800 Subject: [PATCH 048/180] removing link --- samples/bing-search/readme.md | 1 - samples/code-interpreter/readme.md | 1 - samples/file-search/readme.md | 1 - samples/function-calling/readme.md | 2 +- samples/openapi/readme.md | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 693667cc..a40c6290 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -34,4 +34,3 @@ Run the code samples below and view the output. > Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) -* [C#](./csharp-sample.cs) diff --git a/samples/code-interpreter/readme.md b/samples/code-interpreter/readme.md index 73652fd1..589b7241 100644 --- a/samples/code-interpreter/readme.md +++ b/samples/code-interpreter/readme.md @@ -11,7 +11,6 @@ Run the code samples below and view the output. > Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) -* [C#](./csharp-sample.cs) # Additional samples diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index 69ad2961..f3baa016 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -12,7 +12,6 @@ Run the code samples below and view the output. > Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) -* [C#](./csharp-sample.cs) ## Additional samples diff --git a/samples/function-calling/readme.md b/samples/function-calling/readme.md index f29b6d2c..3fd07b1e 100644 --- a/samples/function-calling/readme.md +++ b/samples/function-calling/readme.md @@ -14,7 +14,7 @@ Run the code samples below and view the output. > Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) -* [C#](./csharp-sample.cs) + # Additional samples diff --git a/samples/openapi/readme.md b/samples/openapi/readme.md index 917110f8..b5fe1e3b 100644 --- a/samples/openapi/readme.md +++ b/samples/openapi/readme.md @@ -38,5 +38,4 @@ Run the code samples below and view the output. > Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) -* [C#](./csharp-sample.cs) From 6a5555640a96009c21d95fb847c87d398b1f7e78 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 4 Nov 2024 17:57:59 -0500 Subject: [PATCH 049/180] removing ACR dependency --- main.bicep | 3 --- modules/ai-hub.bicep | 4 --- modules/dependent-resources.bicep | 41 +------------------------------ 3 files changed, 1 insertion(+), 47 deletions(-) diff --git a/main.bicep b/main.bicep index 96ee62af..33892ea3 100644 --- a/main.bicep +++ b/main.bicep @@ -43,7 +43,6 @@ module aiDependencies 'modules/dependent-resources.bicep' = { location: location storageName: 'st${name}${uniqueSuffix}' keyvaultName: 'kv-${name}-${uniqueSuffix}' - containerRegistryName: 'cr${name}${uniqueSuffix}' aiServicesName: 'ais${name}${uniqueSuffix}' tags: tags } @@ -62,7 +61,6 @@ module aiHub 'modules/ai-hub.bicep' = { // dependent resources aiServicesId: aiDependencies.outputs.aiservicesID aiServicesTarget: aiDependencies.outputs.aiservicesTarget - containerRegistryId: aiDependencies.outputs.containerRegistryId keyVaultId: aiDependencies.outputs.keyvaultId storageAccountId: aiDependencies.outputs.storageId } @@ -82,4 +80,3 @@ module aiProject 'modules/ai-project.bicep' = { aiHubId: aiHub.outputs.aiHubID } } - diff --git a/modules/ai-hub.bicep b/modules/ai-hub.bicep index 6415ff07..1edf9f25 100644 --- a/modules/ai-hub.bicep +++ b/modules/ai-hub.bicep @@ -15,9 +15,6 @@ param aiHubFriendlyName string = aiHubName @description('AI hub description') param aiHubDescription string -@description('Resource ID of the container registry resource for storing docker images') -param containerRegistryId string - @description('Resource ID of the key vault resource for storing connection strings') param keyVaultId string @@ -45,7 +42,6 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' // dependent resources keyVault: keyVaultId storageAccount: storageAccountId - containerRegistry: containerRegistryId } kind: 'hub' diff --git a/modules/dependent-resources.bicep b/modules/dependent-resources.bicep index dd64ef85..4c5ec3bc 100644 --- a/modules/dependent-resources.bicep +++ b/modules/dependent-resources.bicep @@ -9,47 +9,9 @@ param tags object = {} @description('AI services name') param aiServicesName string -@description('Container registry name') -param containerRegistryName string - @description('The name of the Key Vault') param keyvaultName string -var containerRegistryNameCleaned = replace(containerRegistryName, '-', '') - - -resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' = { - name: containerRegistryNameCleaned - location: location - tags: tags - sku: { - name: 'Premium' - } - properties: { - adminUserEnabled: true - dataEndpointEnabled: false - networkRuleBypassOptions: 'AzureServices' - networkRuleSet: { - defaultAction: 'Deny' - } - policies: { - quarantinePolicy: { - status: 'enabled' - } - retentionPolicy: { - status: 'enabled' - days: 7 - } - trustPolicy: { - status: 'disabled' - type: 'Notary' - } - } - publicNetworkAccess: 'Disabled' - zoneRedundancy: 'Disabled' - } -} - resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { name: keyvaultName location: location @@ -87,7 +49,7 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = type: 'SystemAssigned' } properties: { - customSubDomainName: toLower('${toLower(aiServicesName)}') + customSubDomainName: toLower('${(aiServicesName)}') apiProperties: { statisticsEnabled: false } @@ -183,4 +145,3 @@ output aiservicesID string = aiServices.id output aiservicesTarget string = aiServices.properties.endpoint output storageId string = storage.id output keyvaultId string = keyVault.id -output containerRegistryId string = containerRegistry.id From 00b0bc6e7a4a421fcbd2d356581b3637bb543b24 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 4 Nov 2024 15:16:17 -0800 Subject: [PATCH 050/180] updating samples --- quickstart.md | 6 +- ...erpreter.py => python-code-interpreter.py} | 0 .../python-function-calling.py | 2 +- samples/function-calling/user_functions.py | 61 ++++++ samples/openapi/python-openapi.py | 2 + samples/use-openai.md | 203 ++++++++++++++++++ 6 files changed, 270 insertions(+), 4 deletions(-) rename samples/code-interpreter/{python-code-inerpreter.py => python-code-interpreter.py} (100%) create mode 100644 samples/function-calling/user_functions.py create mode 100644 samples/use-openai.md diff --git a/quickstart.md b/quickstart.md index 8f9178b8..8e9d6339 100644 --- a/quickstart.md +++ b/quickstart.md @@ -143,9 +143,6 @@ Use the following code to create an agent and send a message to it. This agent w ## Python SDK -> [!NOTE] -> You can find [C# code below](#c). - Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. Run the following commands to install the python packages. @@ -157,6 +154,9 @@ pip install azure-identity Use the following code to create and run an agent. +> [!TIP] +> Want to use the OpenAI SDK? You can find [examples of using the Azure AI Agent service with the OpenAI SDK](./samples/use-openai.md) in the samples folder of this repo. + ```python import os from azure.ai.projects import AIProjectClient diff --git a/samples/code-interpreter/python-code-inerpreter.py b/samples/code-interpreter/python-code-interpreter.py similarity index 100% rename from samples/code-interpreter/python-code-inerpreter.py rename to samples/code-interpreter/python-code-interpreter.py diff --git a/samples/function-calling/python-function-calling.py b/samples/function-calling/python-function-calling.py index 30c5d0a2..bf5d07b8 100644 --- a/samples/function-calling/python-function-calling.py +++ b/samples/function-calling/python-function-calling.py @@ -2,7 +2,7 @@ from azure.ai.projects import AIProjectClient from azure.identity import DefaultAzureCredential from azure.ai.projects.models import FunctionTool, SubmitToolOutputsAction, RequiredFunctionToolCall -from user_functions import user_functions +from user_functions import user_functions # found in the user_functions.py file in this directory. # Create an Azure AI Client from a connection string, copied from your AI Studio project. diff --git a/samples/function-calling/user_functions.py b/samples/function-calling/user_functions.py new file mode 100644 index 00000000..47edb64d --- /dev/null +++ b/samples/function-calling/user_functions.py @@ -0,0 +1,61 @@ +import json +import datetime +from typing import Any, Callable, Set + +# These are the user-defined functions that can be called by the agent. + + +def fetch_current_datetime() -> str: + """ + Get the current time as a JSON string. + + :return: The current time in JSON format. + :rtype: str + """ + current_time = datetime.datetime.now() + time_json = json.dumps({"current_time": current_time.strftime("%Y-%m-%d %H:%M:%S")}) + return time_json + + +def fetch_weather(location: str) -> str: + """ + Fetches the weather information for the specified location. + + :param location (str): The location to fetch weather for. + :return: Weather information as a JSON string. + :rtype: str + """ + # In a real-world scenario, you'd integrate with a weather API. + # Here, we'll mock the response. + mock_weather_data = {"New York": "Sunny, 25°C", "London": "Cloudy, 18°C", "Tokyo": "Rainy, 22°C"} + weather = mock_weather_data.get(location, "Weather data not available for this location.") + weather_json = json.dumps({"weather": weather}) + return weather_json + + +def send_email(recipient: str, subject: str, body: str) -> str: + """ + Sends an email with the specified subject and body to the recipient. + + :param recipient (str): Email address of the recipient. + :param subject (str): Subject of the email. + :param body (str): Body content of the email. + :return: Confirmation message. + :rtype: str + """ + # In a real-world scenario, you'd use an SMTP server or an email service API. + # Here, we'll mock the email sending. + print(f"Sending email to {recipient}...") + print(f"Subject: {subject}") + print(f"Body:\n{body}") + + message_json = json.dumps({"message": f"Email successfully sent to {recipient}."}) + return message_json + + +# Statically defined user functions for fast reference +user_functions: Set[Callable[..., Any]] = { + fetch_current_datetime, + fetch_weather, + send_email, +} \ No newline at end of file diff --git a/samples/openapi/python-openapi.py b/samples/openapi/python-openapi.py index d1d272d8..da9ecbc6 100644 --- a/samples/openapi/python-openapi.py +++ b/samples/openapi/python-openapi.py @@ -1,3 +1,5 @@ +# Use this sample to call an OpenAPI tool. You might + import os, time from azure.ai.projects import AIProjectClient from azure.identity import DefaultAzureCredential diff --git a/samples/use-openai.md b/samples/use-openai.md new file mode 100644 index 00000000..289109ba --- /dev/null +++ b/samples/use-openai.md @@ -0,0 +1,203 @@ +# Use the OpenAI Python SDK with Azure AI Agent service + +In addition to the AI Agent SDK, you can also use the Azure AI Agent service with the OpenAPI SDK. This can be useful if you're an existing Azure OpenAI Assistants customer, and have applications that already utilize the OpenAPI SDK. See the following examples for more information. + +## Basic example + +> [!TIP] +> You can find a streaming example in the Azure Python SDK repo on [Github](https://github.com/Azure/azure-sdk-for-python/blob/jhakulin/oai-agents/sdk/ai/azure-ai-projects/samples/agents/sample_openai_assistants_streaming.py). + +```python +import os, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from openai import AzureOpenAI + + +with AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) as project_client: + + # Explicit type hinting for IntelliSense + client: AzureOpenAI = project_client.inference.get_azure_openai_client() + + with client: + agent = client.beta.assistants.create( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant" + ) + print(f"Created agent, agent ID: {agent.id}") + + thread = client.beta.threads.create() + print(f"Created thread, thread ID: {thread.id}") + + message = client.beta.threads.messages.create(thread_id=thread.id, role="user", content="Hello, tell me a joke") + print(f"Created message, message ID: {message.id}") + + run = client.beta.threads.runs.create(thread_id=thread.id, assistant_id=agent.id) + + # Poll the run while run status is queued or in progress + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) # Wait for a second + run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id) + print(f"Run status: {run.status}") + + client.beta.assistants.delete(agent.id) + print("Deleted agent") + + messages = client.beta.threads.messages.list(thread_id=thread.id) + print(f"Messages: {messages}") +``` + + + +## Function calling + +> [!TIP] +> You can find a streaming example in the Azure Python SDK repo on [Github](https://github.com/Azure/azure-sdk-for-python/blob/jhakulin/oai-agents/sdk/ai/azure-ai-projects/samples/agents/sample_openai_assistants_streaming_functions.py). + +```python +import os, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from openai import AzureOpenAI +from openai.types.beta.threads.required_action_function_tool_call import RequiredActionFunctionToolCall +from azure.ai.projects.models import FunctionTool +from user_functions import user_functions + + +with AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) as project_client: + + # Explicit type hinting for IntelliSense + client: AzureOpenAI = project_client.inference.get_azure_openai_client() + + # Initialize function tool with user functions + functions = FunctionTool(functions=user_functions) + + with client: + agent = client.beta.assistants.create( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", tools=functions.definitions + ) + print(f"Created agent, agent ID: {agent.id}") + + thread = client.beta.threads.create() + print(f"Created thread, thread ID: {thread.id}") + + message = client.beta.threads.messages.create(thread_id=thread.id, role="user", content="Hello, send an email with the datetime and weather information in New York?") + print(f"Created message, message ID: {message.id}") + + run = client.beta.threads.runs.create(thread_id=thread.id, assistant_id=agent.id) + + # Poll the run while run status is queued or in progress + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) # Wait for a second + run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id) + print(f"Run status: {run.status}") + + if run.status == "requires_action" and run.required_action is not None: + + tool_calls = run.required_action.submit_tool_outputs.tool_calls + if not tool_calls: + print("No tool calls provided - cancelling run") + client.beta.threads.runs.cancel(thread_id=thread.id, run_id=run.id) + break + + tool_outputs = [] + for tool_call in tool_calls: + if isinstance(tool_call, RequiredActionFunctionToolCall): + try: + output = functions.execute(tool_call) + tool_outputs.append( + { + "tool_call_id": tool_call.id, + "output": output, + } + ) + except Exception as e: + print(f"Error executing tool_call {tool_call.id}: {e}") + + print(f"Tool outputs: {tool_outputs}") + if tool_outputs: + client.beta.threads.runs.submit_tool_outputs( + thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs + ) + + client.beta.assistants.delete(agent.id) + print("Deleted agent") + + messages = client.beta.threads.messages.list(thread_id=thread.id) + print(f"Messages: {messages}") +``` + + +## File search + +```python +import os, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from openai import AzureOpenAI +from azure.ai.projects.models import FileSearchTool + + +with AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) as project_client: + + # Explicit type hinting for IntelliSense + client: AzureOpenAI = project_client.inference.get_azure_openai_client() + + openai_file = client.files.create(file=open("product_info_1.md", "rb"), purpose="assistants") + print(f"Uploaded file, file ID: {openai_file.id}") + + # Create vector store with file, note: there is no poll method to check the status of vector store is ready + openai_vectorstore = client.beta.vector_stores.create(file_ids=[openai_file.id], name="my_vectorstore") + + # poll the vector store status, the vector store status can be "in_progress", "completed", "expired" + # status can be get from client.beta.vector_stores.retrieve(openai_vectorstore.id) + while openai_vectorstore.status == "in_progress": + time.sleep(1) + openai_vectorstore = client.beta.vector_stores.retrieve(openai_vectorstore.id) + + print(f"Created vector store, vector store ID: {openai_vectorstore.id}") + + # Create file search tool with resources + file_search = FileSearchTool(vector_store_ids=[openai_vectorstore.id]) + + with client: + agent = client.beta.assistants.create( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", tools=file_search.definitions, tool_resources=file_search.resources + ) + print(f"Created agent, agent ID: {agent.id}") + + thread = client.beta.threads.create() + print(f"Created thread, thread ID: {thread.id}") + + message = client.beta.threads.messages.create(thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?") + print(f"Created message, message ID: {message.id}") + + run = client.beta.threads.runs.create(thread_id=thread.id, assistant_id=agent.id) + + # Poll the run while run status is queued or in progress + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) # Wait for a second + run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id) + print(f"Run status: {run.status}") + + if run.status == "failed": + # Check if you got "Rate limit is exceeded.", then you want to get more quota + print(f"Run failed: {run.last_error}") + + client.beta.vector_stores.delete(openai_vectorstore.id) + print("Deleted vector store") + + client.beta.assistants.delete(agent.id) + print("Deleted agent") + + messages = client.beta.threads.messages.list(thread_id=thread.id) + print(f"Messages: {messages}") +``` From 036b27544b25cd383b20fb8004d566ff5981829a Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 4 Nov 2024 15:34:34 -0800 Subject: [PATCH 051/180] wording update --- samples/bing-search/readme.md | 2 +- samples/code-interpreter/python-code-interpreter.py | 4 ++-- samples/code-interpreter/readme.md | 2 +- samples/file-search/readme.md | 2 +- samples/function-calling/readme.md | 4 ++-- samples/openapi/readme.md | 2 +- samples/use-openai.md | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index a40c6290..082ebfda 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -31,6 +31,6 @@ Please note that developers and end users don’t have access to raw chunks retu Run the code samples below and view the output. >[!NOTE] -> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. +> Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) diff --git a/samples/code-interpreter/python-code-interpreter.py b/samples/code-interpreter/python-code-interpreter.py index 90cd6f41..38ccc743 100644 --- a/samples/code-interpreter/python-code-interpreter.py +++ b/samples/code-interpreter/python-code-interpreter.py @@ -49,8 +49,8 @@ # notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment agent = project_client.agents.create_agent( model="gpt-4-1106-preview", - name="my-assistant", - instructions="You are helpful assistant", + name="my-agent", + instructions="You are helpful agent", tools=code_interpreter.definitions, tool_resources=code_interpreter.resources, ) diff --git a/samples/code-interpreter/readme.md b/samples/code-interpreter/readme.md index 589b7241..c3abcd1b 100644 --- a/samples/code-interpreter/readme.md +++ b/samples/code-interpreter/readme.md @@ -8,7 +8,7 @@ Code Interpreter allows the Agent to write and run Python code in a sandboxed ex Run the code samples below and view the output. >[!NOTE] -> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. +> Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index f3baa016..f64d3a69 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -9,7 +9,7 @@ To access your files, the file search tool uses the vector store object. Upload Run the code samples below and view the output. >[!NOTE] -> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. +> Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) diff --git a/samples/function-calling/readme.md b/samples/function-calling/readme.md index 3fd07b1e..16919c0f 100644 --- a/samples/function-calling/readme.md +++ b/samples/function-calling/readme.md @@ -4,14 +4,14 @@ Azure AI Agents Service supports function calling, which allows you to describe ## Setup - +To use function calling, you need a function defined that can be called by the AI Agent service. You can find an example in the [user_functions.py](./user_functions.py) file in this folder. ## Examples Run the code samples below and view the output. >[!NOTE] -> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. +> Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) diff --git a/samples/openapi/readme.md b/samples/openapi/readme.md index b5fe1e3b..c92b7f9f 100644 --- a/samples/openapi/readme.md +++ b/samples/openapi/readme.md @@ -35,7 +35,7 @@ Authentication can be either `anonymous` (no authentication) or `managed_identit Run the code samples below and view the output. >[!NOTE] -> Be sure that you've installed the [correct SDK](../../quickstart.md#install-the-sdk-package) for your language. +> Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-sample.py) diff --git a/samples/use-openai.md b/samples/use-openai.md index 289109ba..147e4c82 100644 --- a/samples/use-openai.md +++ b/samples/use-openai.md @@ -24,7 +24,7 @@ with AIProjectClient.from_connection_string( with client: agent = client.beta.assistants.create( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant" + model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent" ) print(f"Created agent, agent ID: {agent.id}") @@ -79,7 +79,7 @@ with AIProjectClient.from_connection_string( with client: agent = client.beta.assistants.create( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", tools=functions.definitions + model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent", tools=functions.definitions ) print(f"Created agent, agent ID: {agent.id}") @@ -170,7 +170,7 @@ with AIProjectClient.from_connection_string( with client: agent = client.beta.assistants.create( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", tools=file_search.definitions, tool_resources=file_search.resources + model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent", tools=file_search.definitions, tool_resources=file_search.resources ) print(f"Created agent, agent ID: {agent.id}") From 1e38b93429ae63e655ec8cfe79b1981966c18c14 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 4 Nov 2024 15:51:02 -0800 Subject: [PATCH 052/180] adding function calling samples --- .../python-function-calling-streaming.py | 93 +++++++++++++++++++ .../python-function-calling-toolset.py | 59 ++++++++++++ samples/function-calling/readme.md | 6 +- 3 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 samples/function-calling/python-function-calling-streaming.py create mode 100644 samples/function-calling/python-function-calling-toolset.py diff --git a/samples/function-calling/python-function-calling-streaming.py b/samples/function-calling/python-function-calling-streaming.py new file mode 100644 index 00000000..839f0ddd --- /dev/null +++ b/samples/function-calling/python-function-calling-streaming.py @@ -0,0 +1,93 @@ +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import ( + Agent, + MessageDeltaChunk, + MessageDeltaTextContent, + RunStep, + ThreadMessage, + ThreadRun, +) +from azure.ai.projects.models import AgentEventHandler +from azure.ai.projects.operations import AgentsOperations +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import FunctionTool, ToolSet + + +import os +from typing import Any + +from user_functions import user_functions + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + + +# When using FunctionTool with ToolSet in agent creation, the tool call events are handled inside the create_stream +# method and functions gets automatically called by default. +class MyEventHandler(AgentEventHandler): + + def on_message_delta(self, delta: "MessageDeltaChunk") -> None: + for content_part in delta.delta.content: + if isinstance(content_part, MessageDeltaTextContent): + text_value = content_part.text.value if content_part.text else "No text" + print(f"Text delta received: {text_value}") + + def on_thread_message(self, message: "ThreadMessage") -> None: + print(f"ThreadMessage created. ID: {message.id}, Status: {message.status}") + + def on_thread_run(self, run: "ThreadRun") -> None: + print(f"ThreadRun status: {run.status}") + + if run.status == "failed": + print(f"Run failed. Error: {run.last_error}") + + def on_run_step(self, step: "RunStep") -> None: + print(f"RunStep type: {step.type}, Status: {step.status}") + + def on_error(self, data: str) -> None: + print(f"An error occurred. Data: {data}") + + def on_done(self) -> None: + print("Stream completed.") + + def on_unhandled_event(self, event_type: str, event_data: Any) -> None: + print(f"Unhandled Event Type: {event_type}, Data: {event_data}") + + +with project_client: + functions = FunctionTool(user_functions) + toolset = ToolSet() + toolset.add(functions) + + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset + ) + print(f"Created agent, ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Hello, send an email with the datetime and weather information in New York? Also let me know the details", + ) + print(f"Created message, message ID {message.id}") + + with project_client.agents.create_stream( + thread_id=thread.id, assistant_id=agent.id, event_handler=MyEventHandler() + ) as stream: + stream.until_done() + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/function-calling/python-function-calling-toolset.py b/samples/function-calling/python-function-calling-toolset.py new file mode 100644 index 00000000..cfa5f542 --- /dev/null +++ b/samples/function-calling/python-function-calling-toolset.py @@ -0,0 +1,59 @@ +# This sample demonstrates how to use agent operations with toolset from the Azure Agents service using a synchronous client. It's purpose is to showcase automatic tool calling using ToolSet in non-streaming scenario + +import os +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import FunctionTool, ToolSet, CodeInterpreterTool +from user_functions import user_functions + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) + +# Initialize agent toolset with user functions and code interpreter +functions = FunctionTool(user_functions) +code_interpreter = CodeInterpreterTool() + +toolset = ToolSet() +toolset.add(functions) +toolset.add(code_interpreter) + +# Create agent with toolset and process assistant run +with project_client: + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset + ) + print(f"Created agent, ID: {agent.id}") + + # Create thread for communication + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + # Create message to thread + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Hello, send an email with the datetime and weather information in New York?", + ) + print(f"Created message, ID: {message.id}") + + # Create and process agent run in thread with tools + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + print(f"Run failed: {run.last_error}") + + # Delete the assistant when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/function-calling/readme.md b/samples/function-calling/readme.md index 16919c0f..698f949f 100644 --- a/samples/function-calling/readme.md +++ b/samples/function-calling/readme.md @@ -13,9 +13,9 @@ Run the code samples below and view the output. >[!NOTE] > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. -* [Python](./python-sample.py) - - +* [Python - function calling](./python-sample.py) +* [Python - function calling with automatic tool calling](./python-function-calling-toolset.py) +* [Python - function calling with streaming](./python-function-calling-streaming.py) # Additional samples From 88874f1bacb7366fce6ca09939435cc517085958 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:11:32 -0800 Subject: [PATCH 053/180] Create bingsearch_arm.json update with bing search creation process --- samples/bing-search/bingsearch_arm.json | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 samples/bing-search/bingsearch_arm.json diff --git a/samples/bing-search/bingsearch_arm.json b/samples/bing-search/bingsearch_arm.json new file mode 100644 index 00000000..7193d3bb --- /dev/null +++ b/samples/bing-search/bingsearch_arm.json @@ -0,0 +1,47 @@ +{  + +    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",  + +    "contentVersion": "1.0.0.0",  + +    "parameters": {  + +        "name": { "type": "String" },  + +        "location": {  + +            "type": "String",  + +            "defaultValue": "global"  + +        },  + +        "sku": { "type": "String" },  + +        "resourceTags": { "type": "object" }  + +    },  + +    "resources": [  + +        {  + +            "type": "Microsoft.Bing/accounts",  + +            "apiVersion": "2020-06-10",  + +            "name": "[parameters('name')]",  + +            "location": "[parameters('location')]",  + +            "tags": "[parameters('resourceTags')]",  + +            "sku": { "name": "G1" },  + +            "kind": "Bing.Grounding"  + +        }  + +    ]  + +}  From 762e4df4645119c50883e0b204e64bf06e6b83c2 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:20:24 -0800 Subject: [PATCH 054/180] Update readme.md update readme for creating bing resource --- samples/bing-search/readme.md | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 082ebfda..8982a939 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -1,10 +1,8 @@ # Grounding with Bing Search -Grounding with Bing Search allows your Azure Agents to incorporate real-time public web data when generating responses. To start with, you need to create a Grounding with Bing Search resource, then connect this resource to your Azure Agents. When a user sends a query, Azure Agents will decide if Grounding with Bing Search should be leveraged or not. If so, it will leverage Bing to search over public web data and return relevant chunks. Lastly, Azure Agents will use returned chunks to generate a response. +Grounding with Bing Search allows your Azure AI Agents to incorporate real-time public web data when generating responses. To start with, you need to create a Grounding with Bing Search resource, then connect this resource to your Azure AI Agents. When a user sends a query, Azure AI Agents will decide if Grounding with Bing Search should be leveraged or not. If so, it will leverage Bing to search over public web data and return relevant chunks. Lastly, Azure AI Agents will use returned chunks to generate a response. -Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Bing - -Please note that developers and end users don’t have access to raw chunks returned by Grounding with Bing Search. Grounding with Bing Search is a free service during private preview. +Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Grounding with Bing Search. Grounding with Bing Search is a free service during private preview. ## Setup @@ -13,18 +11,26 @@ Please note that developers and end users don’t have access to raw chunks retu 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). -1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI to create one[pending Bing update]: +1. Ensure you have loged in to Azure, using `az login` + +1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI to create one ```console - az cognitiveservices account create \ - - --name bing-grounding-resource \ - --resource-group \ - --kind Bing.Grounding \ - --sku G1 \ - --location Global \ - --yes + az deployment group create​  + --name "$deployment_name"​  + --resource-group "$resource_group"​  + --template-file "$path_to_arm_template_file"​  + --parameters "$path_to_parameters_file";​  ``` +You can find the the template file [here](../bingsearch_arm.json). +An example of the CLI template: +```console + az deployment group create​  + --name "az-cli-ARM-TEST"​  + --resource-group "ApiSearch-Test-WestUS2"​  + --template-file ".\bingsearch_arm.json"​  + --parameters ".\bingsearch_arm_params.json"; +``` ## Examples From b5daff07a837872a93226d1c48a01cc07c97ce54 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:25:31 -0800 Subject: [PATCH 055/180] Update readme.md update region availability --- samples/bing-search/readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 8982a939..6c8dc8be 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -8,6 +8,7 @@ Citations show links to websites used to generate response, but don’t show lin > [!IMPORTANT] > Grounding with Bing Search has a separate [Terms of Use agreement](https://www.microsoft.com/en-us/bing/apis/grounding-legal-preview) you need to agree to in order to move forward. Please [use this form](https://forms.office.com/r/2j3Sgu8S9K) to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. +> Please make sure your resource is created in `EastUS`. 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). From f8d71921eb6d2f7c7d2cfe987fa5ef94cb5703fb Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:05:18 -0800 Subject: [PATCH 056/180] Update readme.md model recommendation --- samples/bing-search/readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 6c8dc8be..639dbb42 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -7,8 +7,9 @@ Citations show links to websites used to generate response, but don’t show lin ## Setup > [!IMPORTANT] -> Grounding with Bing Search has a separate [Terms of Use agreement](https://www.microsoft.com/en-us/bing/apis/grounding-legal-preview) you need to agree to in order to move forward. Please [use this form](https://forms.office.com/r/2j3Sgu8S9K) to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. -> Please make sure your resource is created in `EastUS`. +> 1. Grounding with Bing Search has a separate [Terms of Use agreement](https://www.microsoft.com/en-us/bing/apis/grounding-legal-preview) you need to agree to in order to move forward. Please [use this form](https://forms.office.com/r/2j3Sgu8S9K) to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. +> 2. Please make sure your resource is created in `EastUS`. +> 3. We recommend using the following models: `gpt-4o` and `gpt-4-1106-preview` 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). From 6ef63c122ed49b93fde866e3464731f4c9fee592 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:21:17 -0800 Subject: [PATCH 057/180] Update readme.md --- samples/bing-search/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 639dbb42..50bc5e88 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -9,7 +9,7 @@ Citations show links to websites used to generate response, but don’t show lin > [!IMPORTANT] > 1. Grounding with Bing Search has a separate [Terms of Use agreement](https://www.microsoft.com/en-us/bing/apis/grounding-legal-preview) you need to agree to in order to move forward. Please [use this form](https://forms.office.com/r/2j3Sgu8S9K) to sign the agreement. After you have signed the form, it will take 1-3 days for us to whitelist your subscription. > 2. Please make sure your resource is created in `EastUS`. -> 3. We recommend using the following models: `gpt-4o` and `gpt-4-1106-preview` +> 3. We recommend using the following models: `gpt-3.5-turbo-0125`, `gpt-4-0125-preview`, `gpt-4-turbo-preview`, `gpt-4-turbo`, `gpt-4-turbo-2024-04-09`, `gpt-4o`, `gpt-4o-mini`, `gpt-4o-mini-2024-07-18` 1. Ensure you've completed the prerequisites and setup steps in the [quickstart](../../quickstart.md). From 1c50aeddf4080df9ec9f52761c4decc45297cb0c Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:21:51 -0800 Subject: [PATCH 058/180] Update readme.md update bing pricing language --- samples/bing-search/readme.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 50bc5e88..a2435153 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -2,7 +2,10 @@ Grounding with Bing Search allows your Azure AI Agents to incorporate real-time public web data when generating responses. To start with, you need to create a Grounding with Bing Search resource, then connect this resource to your Azure AI Agents. When a user sends a query, Azure AI Agents will decide if Grounding with Bing Search should be leveraged or not. If so, it will leverage Bing to search over public web data and return relevant chunks. Lastly, Azure AI Agents will use returned chunks to generate a response. -Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Grounding with Bing Search. Grounding with Bing Search is a free service during private preview. +Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Grounding with Bing Search. + +> [!IMPORTANT] +Grounding with Bing Search is a free service during private preview and your usage will start incurring cost since the integration with Azure AI Agent Service releases to public preview. ## Setup From deee267e032a5497e524504f29a380d7eaa5ead0 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 00:01:13 -0500 Subject: [PATCH 059/180] adding to setup details --- quickstart.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 8e9d6339..4badac79 100644 --- a/quickstart.md +++ b/quickstart.md @@ -25,6 +25,12 @@ If you already have these resources set up, skip to the [configure and run your 1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). If you have the CLI already installed, make sure it's updated to the latest version. 1. Register a provider. + + The following providers must be registered: + - Microsoft.KeyVault + - Microsoft.CognitiveServices + - Microsoft.Storage + - Microsoft.MachineLearningServices ```console az provider register –namespace {my_resource_namespace} @@ -37,7 +43,6 @@ If you already have these resources set up, skip to the [configure and run your [--wait] ``` - 1. To authenticate to your Azure subscription from the Azure CLI, use the following command: ```console @@ -49,6 +54,12 @@ If you already have these resources set up, skip to the [configure and run your az group create --name {my_resource_group} --location westus ``` +3. Option 1: Use the standard agent configuration + ```console + az deployment group create --resource-group {my_resource_group} --template-file main.bicep + ``` + An hub, project, storage account, key vault, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus2 region. + 1. Create an Azure OpenAI resource: From 35e2769a63faf3242d1d43e633cdb51faf3c4a67 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 00:06:01 -0500 Subject: [PATCH 060/180] adding to quickstart --- quickstart.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/quickstart.md b/quickstart.md index 4badac79..cde1c664 100644 --- a/quickstart.md +++ b/quickstart.md @@ -6,7 +6,9 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A 1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. -1. check the [RBAC roles](./rbac.md). +2. Make sure all developers have the role: **Azure AI Develeper** assigned at the hub level. [Learn more](https://learn.microsoft.com/en-us/azure/ai-studio/concepts/rbac-ai-studio) + +3. Check the [RBAC roles](./rbac.md). ## Setup your Azure AI Hub and Agent project @@ -31,6 +33,7 @@ If you already have these resources set up, skip to the [configure and run your - Microsoft.CognitiveServices - Microsoft.Storage - Microsoft.MachineLearningServices + - Microsoft.Search ```console az provider register –namespace {my_resource_namespace} @@ -54,13 +57,17 @@ If you already have these resources set up, skip to the [configure and run your az group create --name {my_resource_group} --location westus ``` -3. Option 1: Use the standard agent configuration +3.
+ + **Option 1**: Use the standard agent configuration ```console az deployment group create --resource-group {my_resource_group} --template-file main.bicep ``` An hub, project, storage account, key vault, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus2 region. - +
+ + **Option 2**: Follw steps 6-10 if you want specific control over the creation and configuration of these resources. 1. Create an Azure OpenAI resource: @@ -99,9 +106,9 @@ If you already have these resources set up, skip to the [configure and run your 1. Connect your Hub to your Azure AI resource or Azure OpenAI resource. Replace the resource group and hub name with your resource and hub name. - 1. Save the following in a file named `connection.yml`. + - Save the following in a file named `connection.yml`. - 1. If using an AI Services resource, use the following and replace ai_services_resource_id with the fully qualified ID from earlier. + - If using an AI Services resource, use the following and replace ai_services_resource_id with the fully qualified ID from earlier. ```yml name: myazai_connection @@ -110,7 +117,7 @@ If you already have these resources set up, skip to the [configure and run your ai_services_resource_id: /subscriptions/12345678-abcd-1234-9fc6-62780b3d3e05/resourceGroups/my-ai-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource ``` - 1. If using an Azure OpenAI resource, create the following `connection.yml` file: + - If using an Azure OpenAI resource, create the following `connection.yml` file: ```yml name: {my_connection_name} type: azure_open_ai @@ -125,14 +132,13 @@ If you already have these resources set up, skip to the [configure and run your ``` 1. Create a Project. - - 1. Run the following command to find your ARM ID: + - Run the following command to find your ARM ID: ```console az ml workspace show -n {my_hub_name} --resource-group {my_resource_group} --query id ``` - 1. Now run this command to create your project + - Now run this command to create your project ```console az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} From 23248e85dd28bdf3b6a6930871d626114aea1ffd Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 00:11:02 -0500 Subject: [PATCH 061/180] adding to quickstart --- quickstart.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/quickstart.md b/quickstart.md index cde1c664..d0fec645 100644 --- a/quickstart.md +++ b/quickstart.md @@ -160,15 +160,16 @@ Use the following code to create an agent and send a message to it. This agent w ## Python SDK -Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. +### Setup +1. Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. -Run the following commands to install the python packages. - -```console -pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall -pip install azure-identity -``` +2. Run the following commands to install the python packages. + ```console + pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall + pip install azure-identity + ``` +### Create an Agent Use the following code to create and run an agent. > [!TIP] From 5b70e48460ad355d79005555e88a8af700af9c8b Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 00:13:02 -0500 Subject: [PATCH 062/180] Update quickstart.md --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index d0fec645..87d51874 100644 --- a/quickstart.md +++ b/quickstart.md @@ -12,7 +12,7 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A ## Setup your Azure AI Hub and Agent project -TThe following section will show you how to set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground) by: +The following section will show you how to set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground) by: 1. Creating an Azure AI Hub to set up your app environment and network HOBO resources From c6512093f411b62ec778ca8d7770d00b6fb59fa8 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 00:17:57 -0500 Subject: [PATCH 063/180] Update quickstart.md --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 87d51874..a950465b 100644 --- a/quickstart.md +++ b/quickstart.md @@ -59,7 +59,7 @@ If you already have these resources set up, skip to the [configure and run your 3.
- **Option 1**: Use the standard agent configuration + **Option 1**: Use the standard agent configuration. Download the `main.bicep` file and the `modules` folder to your project directory. ```console az deployment group create --resource-group {my_resource_group} --template-file main.bicep ``` From 7a0abb7c26ba9c47a8153128f856024dbcf7ed61 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 00:19:24 -0500 Subject: [PATCH 064/180] Update quickstart.md --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index a950465b..7a47b236 100644 --- a/quickstart.md +++ b/quickstart.md @@ -59,7 +59,7 @@ If you already have these resources set up, skip to the [configure and run your 3.
- **Option 1**: Use the standard agent configuration. Download the `main.bicep` file and the `modules` folder to your project directory. + **Option 1**: Use the standard agent configuration. Download the `main.bicep` file and the `modules` folder to your project directory. Using the resource group you created in the previous step, run the command: ```console az deployment group create --resource-group {my_resource_group} --template-file main.bicep ``` From 23e10f152bc72987d3ff0895eaf29a2b67b61de1 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 21:20:13 -0800 Subject: [PATCH 065/180] Update bing-python.py update the sample code with Glenn's recent updates --- samples/bing-search/bing-python.py | 168 +++++++++++++++-------------- 1 file changed, 87 insertions(+), 81 deletions(-) diff --git a/samples/bing-search/bing-python.py b/samples/bing-search/bing-python.py index 022c4932..cf91d96b 100644 --- a/samples/bing-search/bing-python.py +++ b/samples/bing-search/bing-python.py @@ -1,81 +1,87 @@ -import os - -from azure.ai.projects.models import bing_grounding, ToolSet -from azure.ai.projects import AIProjectClient -from azure.identity import DefaultAzureCredential - -from azure.ai.ml.entities import WorkspaceConnection -from azure.ai.ml.entities import UsernamePasswordConfiguration, ApiKeyConfiguration - - -# Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# Customer needs to login to Azure subscription via Azure CLI and set the environment variables - -project_client = AIProjectClient.from_connection_string( - credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] -) - - - -# Customer needs to create a connection to the Grounding with Bing Search resource - -connection_name = "bing_grounding_connection" - - - -target = “GROUNDING_WITH_BING_SEARCH_API” - -wps_connection = WorkspaceConnection( - name=connection_name, - type="custom", - target=target, - credentials=ApiKeyConfiguration(key="API_KEY"), - ) - ml_client.connections.create_or_update(workspace_connection=wps_connection) - -with project_client: - - # Create Grounding with Bing Search tool with resources - bing_grounding_tool = bing_grounding(connection_id=[connection id of Grounding with Bing Search resource]) - - # Create agent with SharePoint tool and process agent run - agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", - name="my-agent", - instructions="Hello, you are helpful agent and can search information from uploaded files", - tools=bing_grounding_tool.definitions, - tool_resources= bing_grounding_tool.resources, - ) - print(f"Created agent, agent ID: {agent.id}") - - # Create thread for communication - thread = project_client.agents.create_thread() - print(f"Created thread, ID: {thread.id}") - - # Create message to thread - message = project_client.agents.create_message( - thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" - ) - print(f"Created message, ID: {message.id}") - - # Create and process agent run in thread with tools - run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Run finished with status: {run.status}") - - if run.status == "failed": - # Check if you got "Rate limit is exceeded.", then you want to get more quota - print(f"Run failed: {run.last_error}") - - if run.status == “complete”: - -print(f"Run complete: {run.id}") - - -# Delete the agent when done -project_client.agents.delete_agent(agent.id) -print("Deleted agent") - -# Fetch and log all messages -messages = project_client.agents.list_messages(thread_id=thread.id) -print(f"Messages: {messages}") \ No newline at end of file +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_bing_grounding.py + +DESCRIPTION: + This sample demonstrates how to use agent operations with the Grounding with Bing Search tool from + the Azure Agents service using a synchronous client. + +USAGE: + python sample_agents_bing_grounding.py + + Before running the sample: + + pip install azure.ai.projects azure-identity + + Set this environment variables with your own values: + PROJECT_CONNECTION_STRING - the Azure AI Project connection string, as found in your AI Studio Project. + BING_CONNECTION_NAME - the name of the connection of Grounding with Bing Search + +""" + +import os +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import BingGroundingTool + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) + +bing_connection = project_client.connections.get( + connection_name=os.environ["BING_CONNECTION_NAME"] +) +conn_id = bing_connection.id + +print(conn_id) + +# Initialize agent bing tool and add the connection id +bing = BingGroundingTool(connection_id=conn_id) + +# Create agent with the bing tool and process assistant run +with project_client: + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-assistant", + instructions="You are a helpful assistant", + tools=bing.definitions, + headers={"x-ms-enable-preview": "true"} + ) + print(f"Created agent, ID: {agent.id}") + + # Create thread for communication + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + # Create message to thread + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="How does wikipedia explain Euler's Identity?", + ) + print(f"Created message, ID: {message.id}") + + # Create and process agent run in thread with tools + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Run finished with status: {run.status}") + + if run.status == "failed": + print(f"Run failed: {run.last_error}") + + # Delete the assistant when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") From 8e6766e44384270fe6c2bb496e93f479b3e7bcc1 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 21:55:41 -0800 Subject: [PATCH 066/180] Update readme.md --- samples/bing-search/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index a2435153..52a59e5b 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -27,7 +27,7 @@ Grounding with Bing Search is a free service during private preview and your usa --template-file "$path_to_arm_template_file"​  --parameters "$path_to_parameters_file";​  ``` -You can find the the template file [here](../bingsearch_arm.json). +You can find the the template file [here](../bing-search/bingsearch_arm.json). An example of the CLI template: ```console az deployment group create​  From 276525ed54a22e9ed95cb49cba05191c1ee89d7a Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 21:58:26 -0800 Subject: [PATCH 067/180] Update bingsearch_arm.json --- samples/bing-search/bingsearch_arm.json | 69 +++++++++---------------- 1 file changed, 23 insertions(+), 46 deletions(-) diff --git a/samples/bing-search/bingsearch_arm.json b/samples/bing-search/bingsearch_arm.json index 7193d3bb..655a482d 100644 --- a/samples/bing-search/bingsearch_arm.json +++ b/samples/bing-search/bingsearch_arm.json @@ -1,47 +1,24 @@ {  - -    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",  - -    "contentVersion": "1.0.0.0",  - -    "parameters": {  - -        "name": { "type": "String" },  - -        "location": {  - -            "type": "String",  - -            "defaultValue": "global"  - -        },  - -        "sku": { "type": "String" },  - -        "resourceTags": { "type": "object" }  - -    },  - -    "resources": [  - -        {  - -            "type": "Microsoft.Bing/accounts",  - -            "apiVersion": "2020-06-10",  - -            "name": "[parameters('name')]",  - -            "location": "[parameters('location')]",  - -            "tags": "[parameters('resourceTags')]",  - -            "sku": { "name": "G1" },  - -            "kind": "Bing.Grounding"  - -        }  - -    ]  - -}  + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",  + "contentVersion": "1.0.0.0",  + "parameters": {  + "name": { "type": "String" },  + "location": {  + "type": "String",  + "defaultValue": "global"  + },  + "sku": { "type": "String" },  + "resourceTags": { "type": "object" }  + },  + "resources": [  + {  + "type": "Microsoft.Bing/accounts",  + "apiVersion": "2020-06-10",  + "name": "[parameters('name')]",  + "location": "[parameters('location')]", + "tags": "[parameters('resourceTags')]", + "sku": { "name": "G1" }, + "kind": "Bing.Grounding"  + } + ] +} From 890da47b96bb427b233a64b22a6b3f790d876df2 Mon Sep 17 00:00:00 2001 From: e-straight Date: Tue, 5 Nov 2024 01:03:49 -0500 Subject: [PATCH 068/180] updated quickstart --- quickstart.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/quickstart.md b/quickstart.md index 7a47b236..6317c533 100644 --- a/quickstart.md +++ b/quickstart.md @@ -67,22 +67,23 @@ If you already have these resources set up, skip to the [configure and run your
- **Option 2**: Follw steps 6-10 if you want specific control over the creation and configuration of these resources. +

+ Option 2: Follow steps 6-10 if you want specific control over the creation and configuration of these resources. -1. Create an Azure OpenAI resource: +6. Create an Azure OpenAI resource: > [!NOTE] > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. ```console - az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location westus --kind OpenAI --sku s0 + az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location eastus --kind OpenAI --sku s0 ``` Alternatively, you can create an AI Services resource: ```console - az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location westus + az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location eastus ``` @@ -143,6 +144,7 @@ If you already have these resources set up, skip to the [configure and run your ```console az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} ``` +
## Configure and run your first agent From 2c4fa1ba9b255586ea64877e30f7b09fa96117bb Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:07:23 -0800 Subject: [PATCH 069/180] Update bingsearch_arm.json --- samples/bing-search/bingsearch_arm.json | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/samples/bing-search/bingsearch_arm.json b/samples/bing-search/bingsearch_arm.json index 655a482d..c98967fb 100644 --- a/samples/bing-search/bingsearch_arm.json +++ b/samples/bing-search/bingsearch_arm.json @@ -1,24 +1,24 @@ -{  - "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",  - "contentVersion": "1.0.0.0",  - "parameters": {  - "name": { "type": "String" },  - "location": {  - "type": "String",  - "defaultValue": "global"  - },  - "sku": { "type": "String" },  - "resourceTags": { "type": "object" }  - },  - "resources": [  - {  - "type": "Microsoft.Bing/accounts",  - "apiVersion": "2020-06-10",  - "name": "[parameters('name')]",  +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { "type": "String" }, + "location": { + "type": "String", + "defaultValue": "global" + }, + "sku": { "type": "String" }, + "resourceTags": { "type": "object" } + }, + "resources": [ + { + "type": "Microsoft.Bing/accounts", + "apiVersion": "2020-06-10", + "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('resourceTags')]", "sku": { "name": "G1" }, - "kind": "Bing.Grounding"  + "kind": "Bing.Grounding" } ] } From d1e11cf7d3942aa14359c53e85bc9f534a40fc78 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 01:13:18 -0500 Subject: [PATCH 070/180] Update quickstart.md --- quickstart.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index 6317c533..241c36a6 100644 --- a/quickstart.md +++ b/quickstart.md @@ -61,9 +61,13 @@ If you already have these resources set up, skip to the [configure and run your **Option 1**: Use the standard agent configuration. Download the `main.bicep` file and the `modules` folder to your project directory. Using the resource group you created in the previous step, run the command: ```console - az deployment group create --resource-group {my_resource_group} --template-file main.bicep + az deployment group create --resource-group --template-file main.bicep --parameters aiHubName= aiProjectName= ``` - An hub, project, storage account, key vault, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus2 region. + [Optional] Name the hub and project: + ```console + az deployment group create --resource-group --template-file main.bicep --parameters aiHubName= aiProjectName= + ``` + An hub, project, storage account, key vault, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region.
From f1f666bf2b8cc72e4e3237164315e31757ea9113 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 01:14:50 -0500 Subject: [PATCH 071/180] Update quickstart.md --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index 241c36a6..adaf92a3 100644 --- a/quickstart.md +++ b/quickstart.md @@ -61,11 +61,11 @@ If you already have these resources set up, skip to the [configure and run your **Option 1**: Use the standard agent configuration. Download the `main.bicep` file and the `modules` folder to your project directory. Using the resource group you created in the previous step, run the command: ```console - az deployment group create --resource-group --template-file main.bicep --parameters aiHubName= aiProjectName= + az deployment group create --resource-group --template-file main.bicep ``` [Optional] Name the hub and project: ```console - az deployment group create --resource-group --template-file main.bicep --parameters aiHubName= aiProjectName= + az deployment group create --resource-group --template-file main.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' ``` An hub, project, storage account, key vault, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. From 824b43fb1e63955167f92b5997e23d37e031d977 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 01:35:42 -0500 Subject: [PATCH 072/180] bicep template for standard agent setup --- modules-standard/standard-ai-hub.bicep | 65 ++++++++++ modules-standard/standard-ai-project.bicep | 42 +++++++ .../standard-dependent-resources.bicep | 116 ++++++++++++++++++ standard-agent.bicep | 85 +++++++++++++ 4 files changed, 308 insertions(+) create mode 100644 modules-standard/standard-ai-hub.bicep create mode 100644 modules-standard/standard-ai-project.bicep create mode 100644 modules-standard/standard-dependent-resources.bicep create mode 100644 standard-agent.bicep diff --git a/modules-standard/standard-ai-hub.bicep b/modules-standard/standard-ai-hub.bicep new file mode 100644 index 00000000..145f1012 --- /dev/null +++ b/modules-standard/standard-ai-hub.bicep @@ -0,0 +1,65 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI hub name') +param aiHubName string + +@description('AI hub display name') +param aiHubFriendlyName string = aiHubName + +@description('AI hub description') +param aiHubDescription string + +@description('Resource ID of the storage account resource for storing experimentation outputs') +param storageAccountId string + +@description('Resource ID of the AI Services resource') +param aiServicesId string + +@description('Resource ID of the AI Services endpoint') +param aiServicesTarget string + +resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { + name: aiHubName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiHubFriendlyName + description: aiHubDescription + + // dependent resources + storageAccount: storageAccountId + } + kind: 'hub' + + resource aiServicesConnection 'connections@2024-07-01-preview' = { + name: '${aiHubName}-connection-AIServices' + properties: { + category: 'AIServices' + target: aiServicesTarget + // useWorkspaceManagedIdentity: true + authType: 'ApiKey' + isSharedToAll: true + credentials: { + key: '${listKeys(aiServicesId, '2022-10-01').key1}' + } + metadata: { + ApiType: 'Azure' + ResourceId: aiServicesId + Location: location + } + } + } +} + + +output aiHubID string = aiHub.id diff --git a/modules-standard/standard-ai-project.bicep b/modules-standard/standard-ai-project.bicep new file mode 100644 index 00000000..764ca201 --- /dev/null +++ b/modules-standard/standard-ai-project.bicep @@ -0,0 +1,42 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI Project name') +param aiProjectName string + +@description('AI Project display name') +param aiProjectFriendlyName string = aiProjectName + +@description('AI Project description') +param aiProjectDescription string + +@description('Resource ID of the AI Hub resource') +param aiHubId string + + + +resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { + name: aiProjectName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiProjectFriendlyName + description: aiProjectDescription + + // dependent resources + hubResourceId: aiHubId + + } + kind: 'project' +} + +output aiProjectID string = aiProject.id diff --git a/modules-standard/standard-dependent-resources.bicep b/modules-standard/standard-dependent-resources.bicep new file mode 100644 index 00000000..56e2f2f6 --- /dev/null +++ b/modules-standard/standard-dependent-resources.bicep @@ -0,0 +1,116 @@ +@description('Azure region of the deployment') +param location string = resourceGroup().location + +@description('Tags to add to the resources') +param tags object = {} + +@description('AI services name') +param aiServicesName string + + +resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { + name: aiServicesName + location: 'eastus' + sku: { + name: 'S0' + } + kind: 'AIServices' // or 'OpenAI' + identity: { + type: 'SystemAssigned' + } + properties: { + customSubDomainName: toLower('${toLower(aiServicesName)}') + apiProperties: { + statisticsEnabled: false + } + publicNetworkAccess: 'Enabled' + } +} +resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { + parent: aiServices + name: 'gpt-4o-mini' + sku : { + capacity: 1 + name: 'GlobalStandard' + } + properties: { + model:{ + name: 'gpt-4o-mini' + format: 'OpenAI' + version: '2024-07-18' + } + } +} + +@description('Name of the storage account') +param storageName string + +@allowed([ + 'Standard_LRS' + 'Standard_ZRS' + 'Standard_GRS' + 'Standard_GZRS' + 'Standard_RAGRS' + 'Standard_RAGZRS' + 'Premium_LRS' + 'Premium_ZRS' +]) + +@description('Storage SKU') +param storageSkuName string = 'Standard_LRS' + +var storageNameCleaned = replace(storageName, '-', '') + +resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { + name: storageNameCleaned + location: location + tags: tags + sku: { + name: storageSkuName + } + kind: 'StorageV2' + properties: { + accessTier: 'Hot' + allowBlobPublicAccess: false + allowCrossTenantReplication: false + allowSharedKeyAccess: true + encryption: { + keySource: 'Microsoft.Storage' + requireInfrastructureEncryption: false + services: { + blob: { + enabled: true + keyType: 'Account' + } + file: { + enabled: true + keyType: 'Account' + } + queue: { + enabled: true + keyType: 'Service' + } + table: { + enabled: true + keyType: 'Service' + } + } + } + isHnsEnabled: false + isNfsV3Enabled: false + keyPolicy: { + keyExpirationPeriodInDays: 7 + } + largeFileSharesState: 'Disabled' + minimumTlsVersion: 'TLS1_2' + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + supportsHttpsTrafficOnly: true + } +} + +output aiservicesID string = aiServices.id +output aiservicesTarget string = aiServices.properties.endpoint +output storageId string = storage.id diff --git a/standard-agent.bicep b/standard-agent.bicep new file mode 100644 index 00000000..b7a6b80b --- /dev/null +++ b/standard-agent.bicep @@ -0,0 +1,85 @@ +// Execute this main file to depoy Azure AI studio resources in the basic security configuraiton + +// Parameters +@minLength(2) +@maxLength(12) +@description('Name for the AI resource and used to derive name of dependent resources.') +param aiHubName string = 'standard-hub' + +@description('Friendly name for your Azure AI resource') +param aiHubFriendlyName string = 'Agents standard hub resource' + +@description('Description of your Azure AI resource dispayed in AI studio') +param aiHubDescription string = 'A standard hub resource required for the agent setup.' +param aiProjectName string = 'standard-project' + +@description('Friendly name for your Azure AI resource') +param aiProjectFriendlyName string = 'Agents standard project resource' + +@description('Description of your Azure AI resource dispayed in AI studio') +param aiProjectDescription string = 'A standard project resource required for the agent setup.' + + +@description('Azure region used for the deployment of all resources.') +param location string = resourceGroup().location + +@description('Set of tags to apply to all resources.') +param tags object = {} + +// Variables +var name = toLower('${aiHubName}') +var projectName = toLower('${aiProjectName}') + +@description('Name of the storage account') +param storageName string = 'agent-storage' + +@description('Name of the Azure AI Services account') +param aiServicesName string = 'agent-ai-services' + +// Create a short, unique suffix, that will be unique to each resource group +// var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) +param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') +var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) + +// Dependent resources for the Azure Machine Learning workspace +module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { + name: 'dependencies-${name}-${uniqueSuffix}-deployment' + params: { + aiServicesName: '${aiServicesName}${uniqueSuffix}' + storageName: '${storageName}${uniqueSuffix}' + location: location + tags: tags + } +} + +module aiHub 'modules-standard/standard-ai-hub.bicep' = { + name: '${name}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiHubName: 'ai-${name}-${uniqueSuffix}' + aiHubFriendlyName: aiHubFriendlyName + aiHubDescription: aiHubDescription + location: location + tags: tags + + // dependent resources + storageAccountId: aiDependencies.outputs.storageId + aiServicesId: aiDependencies.outputs.aiservicesID + aiServicesTarget: aiDependencies.outputs.aiservicesTarget + } +} + +module aiProject 'modules-standard/standard-ai-project.bicep' = { + name: 'ai-${projectName}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiProjectName: 'ai-${projectName}-${uniqueSuffix}' + aiProjectFriendlyName: aiProjectFriendlyName + aiProjectDescription: aiProjectDescription + location: location + tags: tags + + // dependent resources + aiHubId: aiHub.outputs.aiHubID + } +} From 2207444b35cee008b78ca870c0cc830973ffe856 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 01:40:00 -0500 Subject: [PATCH 073/180] fixing spacing --- standard-agent.bicep | 1 - 1 file changed, 1 deletion(-) diff --git a/standard-agent.bicep b/standard-agent.bicep index b7a6b80b..19b282d5 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -19,7 +19,6 @@ param aiProjectFriendlyName string = 'Agents standard project resource' @description('Description of your Azure AI resource dispayed in AI studio') param aiProjectDescription string = 'A standard project resource required for the agent setup.' - @description('Azure region used for the deployment of all resources.') param location string = resourceGroup().location From 6cd991e3adcd8d42d8f55ddca4592b7ab23d6f79 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 02:00:52 -0500 Subject: [PATCH 074/180] Update quickstart.md --- quickstart.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/quickstart.md b/quickstart.md index adaf92a3..c00a587d 100644 --- a/quickstart.md +++ b/quickstart.md @@ -59,15 +59,16 @@ If you already have these resources set up, skip to the [configure and run your 3.
- **Option 1**: Use the standard agent configuration. Download the `main.bicep` file and the `modules` folder to your project directory. Using the resource group you created in the previous step, run the command: + **Option 1**: Use the standard agent configuration. Download the `standard-agent.bicep` file and the `standard-modules` folder to your project directory. Using the resource group you created in the previous step, run the command: ```console - az deployment group create --resource-group --template-file main.bicep + az deployment group create --resource-group --template-file standard-agent.bicep ``` - [Optional] Name the hub and project: + [Optional] Name the hub, project, storage account, and/or azure ai service resource: + Note: A randomly generated suffix will be added to each name to prevent accidental duplication of resource names ```console - az deployment group create --resource-group --template-file main.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' + az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` - An hub, project, storage account, key vault, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. + An hub, project, storage account, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A microsoft managed key-vault is used. If you want to use your deploy your own key vault, download the `main.bicep` file and the `modules` folder and rerun the command, replacing `--template-file standard-agent.bicep` with `--template-file main.bicep.`
From fc24f76196acb350c3257f895d6ecd83ac982d75 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 02:11:19 -0500 Subject: [PATCH 075/180] Update quickstart.md --- quickstart.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index c00a587d..71cccc5b 100644 --- a/quickstart.md +++ b/quickstart.md @@ -68,7 +68,11 @@ If you already have these resources set up, skip to the [configure and run your ```console az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` - An hub, project, storage account, and AI Services resource will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A microsoft managed key-vault is used. If you want to use your deploy your own key vault, download the `main.bicep` file and the `modules` folder and rerun the command, replacing `--template-file standard-agent.bicep` with `--template-file main.bicep.` + Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. + + If you prefer to deploy your own key vault, download the `main.bicep` file and `modules` folder and rerun the command, replacing `--template-file standard-agent.bicep` with `--template-file main.bicep.` + +
From ee0ae5f31059df729e3b4fec3dd8ce02817a6492 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 02:26:54 -0500 Subject: [PATCH 076/180] Update quickstart.md --- quickstart.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/quickstart.md b/quickstart.md index 71cccc5b..83079e50 100644 --- a/quickstart.md +++ b/quickstart.md @@ -59,15 +59,20 @@ If you already have these resources set up, skip to the [configure and run your 3.
- **Option 1**: Use the standard agent configuration. Download the `standard-agent.bicep` file and the `standard-modules` folder to your project directory. Using the resource group you created in the previous step, run the command: - ```console - az deployment group create --resource-group --template-file standard-agent.bicep - ``` - [Optional] Name the hub, project, storage account, and/or azure ai service resource: - Note: A randomly generated suffix will be added to each name to prevent accidental duplication of resource names - ```console - az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' - ``` +**Option 1**: Use the standard agent configuration. +- Download the `standard-agent.bicep` file and the `standard-modules` folder to your project directory. +- Using the resource group you created in the previous step, run one of the following commands: + - To use default resource names, run: + + ```console + az deployment group create --resource-group --template-file standard-agent.bicep + ``` + + - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: + ```console + az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' + ``` + Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. If you prefer to deploy your own key vault, download the `main.bicep` file and `modules` folder and rerun the command, replacing `--template-file standard-agent.bicep` with `--template-file main.bicep.` From 108149b8a8a7b12f06704bbc4f35b49c0dd68548 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 11:12:30 -0500 Subject: [PATCH 077/180] Update quickstart.md --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 83079e50..75b9542f 100644 --- a/quickstart.md +++ b/quickstart.md @@ -54,7 +54,7 @@ If you already have these resources set up, skip to the [configure and run your 2. Create a resource group: ```console - az group create --name {my_resource_group} --location westus + az group create --name {my_resource_group} --location eastus ``` 3.
From 1c2404ddaade72cd3f62b8dab6c8373847942f36 Mon Sep 17 00:00:00 2001 From: e-straight <142330569+e-straight@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:19:27 -0500 Subject: [PATCH 078/180] Update quickstart.md spelling, example project connection string --- quickstart.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/quickstart.md b/quickstart.md index 75b9542f..87346f69 100644 --- a/quickstart.md +++ b/quickstart.md @@ -6,7 +6,7 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A 1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. -2. Make sure all developers have the role: **Azure AI Develeper** assigned at the hub level. [Learn more](https://learn.microsoft.com/en-us/azure/ai-studio/concepts/rbac-ai-studio) +2. Make sure all developers have the role: **Azure AI Developer** assigned at the hub level. [Learn more](https://learn.microsoft.com/en-us/azure/ai-studio/concepts/rbac-ai-studio) 3. Check the [RBAC roles](./rbac.md). @@ -60,7 +60,7 @@ If you already have these resources set up, skip to the [configure and run your 3.
**Option 1**: Use the standard agent configuration. -- Download the `standard-agent.bicep` file and the `standard-modules` folder to your project directory. +- Download the `standard-agent.bicep` file and the `modules-standard` folder to your project directory. - Using the resource group you created in the previous step, run one of the following commands: - To use default resource names, run: @@ -202,7 +202,8 @@ from pathlib import Path # Create an Azure AI Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" # HostName can be found by navigating to your discovery_url and removing the leading "https://" and trailing "/discovery" -# To find your HostName, run the CLI command: az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url +# To find your discovery_url, run the CLI command: az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url +# Project Connection example: eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-hub-name # Customer needs to login to Azure subscription via Azure CLI and set the environment variables project_client = AIProjectClient.from_connection_string( From f04372e774febbfa82346d8d7447ba02f77f9f32 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:41:35 -0800 Subject: [PATCH 079/180] Create bingsearch_para.json update creating bing resource json --- samples/bing-search/bingsearch_para.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 samples/bing-search/bingsearch_para.json diff --git a/samples/bing-search/bingsearch_para.json b/samples/bing-search/bingsearch_para.json new file mode 100644 index 00000000..0f0142e7 --- /dev/null +++ b/samples/bing-search/bingsearch_para.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "BING_RESOURCE_NAME"}, + "sku": { + "value": "G1" + }, + "location": { + "value": "GLOBAL" + }, + "resourceTags": { + "value": { + "Name1": "Value1", + "Name2": "Value2", + "Name3": "Value3" + } + } + } +} From 5069f003beab26b3dab9001ec4ae82ffcd8f7ed4 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:59:30 -0800 Subject: [PATCH 080/180] Update readme.md update Bing instructions --- samples/bing-search/readme.md | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 52a59e5b..00e39d70 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -18,7 +18,7 @@ Grounding with Bing Search is a free service during private preview and your usa 1. Ensure you have loged in to Azure, using `az login` -1. Create a Bing Search resource. If you don’t have one, you can use the Azure CLI to create one +1. Create a new Grounding with Bing Search resource. You can find the the template file [here](./bingsearch_arm.json) and parameter file [here](./bing_search_para.json). Make sure you have replace "BING_RESOURCE_NAME" in the parameter file. You can use Azure cli command: ```console az deployment group create​  @@ -27,15 +27,29 @@ Grounding with Bing Search is a free service during private preview and your usa --template-file "$path_to_arm_template_file"​  --parameters "$path_to_parameters_file";​  ``` -You can find the the template file [here](../bing-search/bingsearch_arm.json). -An example of the CLI template: -```console - az deployment group create​  - --name "az-cli-ARM-TEST"​  - --resource-group "ApiSearch-Test-WestUS2"​  - --template-file ".\bingsearch_arm.json"​  - --parameters ".\bingsearch_arm_params.json"; -``` + An example of the CLI command: + ```console + az deployment group create​  + --name az-cli-ARM-TEST + --resource-group ApiSearch-Test-WestUS2 + --template-file bingsearch_arm.json + --parameters bingsearch_para.json + ``` + Make sure you have created this Grounding with Bing Search resource in the same resource group of your Azure AI Agent, AI Project, etc. +1. After you have created a Grounding with Bing Search resource, you can find it in [Azure Portal](https://ms.portal.azure.com/#home). Going to the resource group you have created the resource at, search for the Grounding with Bing Search resource you have created. +![image](https://github.com/user-attachments/assets/3b22c48d-987c-4234-a9eb-67aefe3af81c) +1. Click the Grounding with Bing Search resource you have created and copy any of the API key +![image](https://github.com/user-attachments/assets/be98e07d-c91d-4ff9-a97c-6f02c3265221) +1. Go to [Azure AI Studio](https://ai.azure.com/) and select the AI Project(make sure it's in the same resource group of your Grounding with Bing Search resource). Click Settings and then "+new connection" button in Settings page + ![image](https://github.com/user-attachments/assets/28bfebda-f3a4-4638-b714-a128a8fa48cb) + ![image](https://github.com/user-attachments/assets/7bb9c98e-dd46-4031-be9d-17c70613f222) +1. Select "API key" custom connection in other resource types +![image](https://github.com/user-attachments/assets/7577c912-cf0f-433a-910b-3d9e0ad138c4) +1. Enter the following information and then create +- Endpoint: https://api.bing.microsoft.com/ +- Key: YOUR_API_KEY +- Connection name: YOUR_CONNECTION_NAME +You will use this connection name in the sample code below. ## Examples From 0a2eb72a4d3b1f57ea18add2d145d4febfd4d404 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:00:44 -0800 Subject: [PATCH 081/180] Update readme.md --- samples/bing-search/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 00e39d70..6136b2fd 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -18,7 +18,7 @@ Grounding with Bing Search is a free service during private preview and your usa 1. Ensure you have loged in to Azure, using `az login` -1. Create a new Grounding with Bing Search resource. You can find the the template file [here](./bingsearch_arm.json) and parameter file [here](./bing_search_para.json). Make sure you have replace "BING_RESOURCE_NAME" in the parameter file. You can use Azure cli command: +1. Create a new Grounding with Bing Search resource. You can find the the template file [here](./bingsearch_arm.json) and parameter file [here](./bingsearch_para.json). Make sure you have replace "BING_RESOURCE_NAME" in the parameter file. You can use Azure cli command: ```console az deployment group create​  From 127fa1340c0210a4c4fb430d9556aef40c73b65c Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:04:11 -0800 Subject: [PATCH 082/180] Update readme.md --- samples/bing-search/readme.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 6136b2fd..1eb498da 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -18,7 +18,7 @@ Grounding with Bing Search is a free service during private preview and your usa 1. Ensure you have loged in to Azure, using `az login` -1. Create a new Grounding with Bing Search resource. You can find the the template file [here](./bingsearch_arm.json) and parameter file [here](./bingsearch_para.json). Make sure you have replace "BING_RESOURCE_NAME" in the parameter file. You can use Azure cli command: +1. Create a new Grounding with Bing Search resource. You can find the the template file [here](./bingsearch_arm.json) and parameter file [here](./bingsearch_para.json). Make sure you have replace "BING_RESOURCE_NAME" in the parameter file. You can use Azure CLI command: ```console az deployment group create​  @@ -41,15 +41,16 @@ Grounding with Bing Search is a free service during private preview and your usa 1. Click the Grounding with Bing Search resource you have created and copy any of the API key ![image](https://github.com/user-attachments/assets/be98e07d-c91d-4ff9-a97c-6f02c3265221) 1. Go to [Azure AI Studio](https://ai.azure.com/) and select the AI Project(make sure it's in the same resource group of your Grounding with Bing Search resource). Click Settings and then "+new connection" button in Settings page - ![image](https://github.com/user-attachments/assets/28bfebda-f3a4-4638-b714-a128a8fa48cb) - ![image](https://github.com/user-attachments/assets/7bb9c98e-dd46-4031-be9d-17c70613f222) +![image](https://github.com/user-attachments/assets/28bfebda-f3a4-4638-b714-a128a8fa48cb) +![image](https://github.com/user-attachments/assets/7bb9c98e-dd46-4031-be9d-17c70613f222) 1. Select "API key" custom connection in other resource types ![image](https://github.com/user-attachments/assets/7577c912-cf0f-433a-910b-3d9e0ad138c4) -1. Enter the following information and then create +1. Enter the following information and then create a new connection to your Grounding with Bing Search resource - Endpoint: https://api.bing.microsoft.com/ - Key: YOUR_API_KEY - Connection name: YOUR_CONNECTION_NAME -You will use this connection name in the sample code below. +- Access: you can choose either "this project only" or "shared to all projects". Just make sure in the sample code below, the project you entered connection string for has access to this connection. +You will use this connection name in the sample code below. ## Examples From ed098c4baf38859cc4fa59979da5cb5941fb8888 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:05:50 -0800 Subject: [PATCH 083/180] Update readme.md --- samples/bing-search/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 1eb498da..41b19364 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -48,9 +48,9 @@ Grounding with Bing Search is a free service during private preview and your usa 1. Enter the following information and then create a new connection to your Grounding with Bing Search resource - Endpoint: https://api.bing.microsoft.com/ - Key: YOUR_API_KEY -- Connection name: YOUR_CONNECTION_NAME +- Connection name: YOUR_CONNECTION_NAME (You will use this connection name in the sample code below.) - Access: you can choose either "this project only" or "shared to all projects". Just make sure in the sample code below, the project you entered connection string for has access to this connection. -You will use this connection name in the sample code below. + ## Examples From 711f35ae4d09bb843359c2599a3ea7384ed54315 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 13:30:43 -0500 Subject: [PATCH 084/180] Delete main.bicep deleting old ARM template. I will bring it back when we support BYO setup --- main.bicep | 82 ------------------------------------------------------ 1 file changed, 82 deletions(-) delete mode 100644 main.bicep diff --git a/main.bicep b/main.bicep deleted file mode 100644 index 33892ea3..00000000 --- a/main.bicep +++ /dev/null @@ -1,82 +0,0 @@ -// Execute this main file to depoy Azure AI studio resources in the basic security configuraiton - -// Parameters -@minLength(2) -@maxLength(12) -@description('Name for the AI resource and used to derive name of dependent resources.') -param aiHubName string = 'hub-demo' - -@description('Friendly name for your Azure AI resource') -param aiHubFriendlyName string = 'Demo AI resource' - -@description('Description of your Azure AI resource dispayed in AI studio') -param aiHubDescription string = 'This is an example AI resource for use in Azure AI Studio.' - -param aiProjectName string = 'project-demo' - -@description('Friendly name for your Azure AI resource') -param aiProjectFriendlyName string = 'Demo AI Project resource' - -@description('Description of your Azure AI resource dispayed in AI studio') -param aiProjectDescription string = 'This is an example AI Project resource for use in Azure AI Studio.' - -@description('Azure region used for the deployment of all resources.') -param location string = resourceGroup().location - -@description('Set of tags to apply to all resources.') -param tags object = {} - -// Variables -var name = toLower('${aiHubName}') -var projectName = toLower('${aiProjectName}') - -// Create a short, unique suffix, that will be unique to each resource group -// var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) -param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') -var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) - - -// Dependent resources for the Azure Machine Learning workspace -module aiDependencies 'modules/dependent-resources.bicep' = { - name: 'dependencies-${name}-${uniqueSuffix}-deployment' - params: { - location: location - storageName: 'st${name}${uniqueSuffix}' - keyvaultName: 'kv-${name}-${uniqueSuffix}' - aiServicesName: 'ais${name}${uniqueSuffix}' - tags: tags - } -} - -module aiHub 'modules/ai-hub.bicep' = { - name: 'ai-${name}-${uniqueSuffix}-deployment' - params: { - // workspace organization - aiHubName: 'ai-${name}-${uniqueSuffix}' - aiHubFriendlyName: aiHubFriendlyName - aiHubDescription: aiHubDescription - location: location - tags: tags - - // dependent resources - aiServicesId: aiDependencies.outputs.aiservicesID - aiServicesTarget: aiDependencies.outputs.aiservicesTarget - keyVaultId: aiDependencies.outputs.keyvaultId - storageAccountId: aiDependencies.outputs.storageId - } -} - -module aiProject 'modules/ai-project.bicep' = { - name: 'ai-${projectName}-${uniqueSuffix}-deployment' - params: { - // workspace organization - aiProjectName: 'ai-${projectName}-${uniqueSuffix}' - aiProjectFriendlyName: aiProjectFriendlyName - aiProjectDescription: aiProjectDescription - location: location - tags: tags - - // dependent resources - aiHubId: aiHub.outputs.aiHubID - } -} From 8add1c5184ecf9580781489c7dc8fe53eaf0d1b1 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 13:31:29 -0500 Subject: [PATCH 085/180] Delete modules directory Deleting old agent setup components. Will bring these back when we support byo-agent-setup --- modules/ai-hub.bicep | 69 -------------- modules/ai-project.bicep | 42 --------- modules/dependent-resources.bicep | 147 ------------------------------ 3 files changed, 258 deletions(-) delete mode 100644 modules/ai-hub.bicep delete mode 100644 modules/ai-project.bicep delete mode 100644 modules/dependent-resources.bicep diff --git a/modules/ai-hub.bicep b/modules/ai-hub.bicep deleted file mode 100644 index 1edf9f25..00000000 --- a/modules/ai-hub.bicep +++ /dev/null @@ -1,69 +0,0 @@ -// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider - -@description('Azure region of the deployment') -param location string - -@description('Tags to add to the resources') -param tags object - -@description('AI hub name') -param aiHubName string - -@description('AI hub display name') -param aiHubFriendlyName string = aiHubName - -@description('AI hub description') -param aiHubDescription string - -@description('Resource ID of the key vault resource for storing connection strings') -param keyVaultId string - -@description('Resource ID of the storage account resource for storing experimentation outputs') -param storageAccountId string - -@description('Resource ID of the AI Services resource') -param aiServicesId string - -@description('Resource ID of the AI Services endpoint') -param aiServicesTarget string - -resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { - name: aiHubName - location: location - tags: tags - identity: { - type: 'SystemAssigned' - } - properties: { - // organization - friendlyName: aiHubFriendlyName - description: aiHubDescription - - // dependent resources - keyVault: keyVaultId - storageAccount: storageAccountId - } - kind: 'hub' - - resource aiServicesConnection 'connections@2024-07-01-preview' = { - name: '${aiHubName}-connection-AIServices' - properties: { - category: 'AIServices' - target: aiServicesTarget - // useWorkspaceManagedIdentity: true - authType: 'ApiKey' - isSharedToAll: true - credentials: { - key: '${listKeys(aiServicesId, '2022-10-01').key1}' - } - metadata: { - ApiType: 'Azure' - ResourceId: aiServicesId - Location: location - } - } - } -} - - -output aiHubID string = aiHub.id diff --git a/modules/ai-project.bicep b/modules/ai-project.bicep deleted file mode 100644 index 764ca201..00000000 --- a/modules/ai-project.bicep +++ /dev/null @@ -1,42 +0,0 @@ -// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider - -@description('Azure region of the deployment') -param location string - -@description('Tags to add to the resources') -param tags object - -@description('AI Project name') -param aiProjectName string - -@description('AI Project display name') -param aiProjectFriendlyName string = aiProjectName - -@description('AI Project description') -param aiProjectDescription string - -@description('Resource ID of the AI Hub resource') -param aiHubId string - - - -resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { - name: aiProjectName - location: location - tags: tags - identity: { - type: 'SystemAssigned' - } - properties: { - // organization - friendlyName: aiProjectFriendlyName - description: aiProjectDescription - - // dependent resources - hubResourceId: aiHubId - - } - kind: 'project' -} - -output aiProjectID string = aiProject.id diff --git a/modules/dependent-resources.bicep b/modules/dependent-resources.bicep deleted file mode 100644 index 4c5ec3bc..00000000 --- a/modules/dependent-resources.bicep +++ /dev/null @@ -1,147 +0,0 @@ -// Creates Azure dependent resources for Azure AI studio - -@description('Azure region of the deployment') -param location string = resourceGroup().location - -@description('Tags to add to the resources') -param tags object = {} - -@description('AI services name') -param aiServicesName string - -@description('The name of the Key Vault') -param keyvaultName string - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyvaultName - location: location - tags: tags - properties: { - createMode: 'default' - enabledForDeployment: false - enabledForDiskEncryption: false - enabledForTemplateDeployment: false - enableSoftDelete: true - enableRbacAuthorization: true - enablePurgeProtection: true - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Deny' - } - sku: { - family: 'A' - name: 'standard' - } - softDeleteRetentionInDays: 7 - tenantId: subscription().tenantId - } -} - - -resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { - name: aiServicesName - location: 'eastus2' - sku: { - name: 'S0' - } - kind: 'AIServices' // or 'OpenAI' - identity: { - type: 'SystemAssigned' - } - properties: { - customSubDomainName: toLower('${(aiServicesName)}') - apiProperties: { - statisticsEnabled: false - } - publicNetworkAccess: 'Enabled' - } -} -resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { - parent: aiServices - name: 'gpt-4o-mini' - sku : { - capacity: 1 - name: 'GlobalStandard' - } - properties: { - model:{ - name: 'gpt-4o-mini' - format: 'OpenAI' - version: '2024-07-18' - } - } -} - -@description('Name of the storage account') -param storageName string - -@allowed([ - 'Standard_LRS' - 'Standard_ZRS' - 'Standard_GRS' - 'Standard_GZRS' - 'Standard_RAGRS' - 'Standard_RAGZRS' - 'Premium_LRS' - 'Premium_ZRS' -]) - -@description('Storage SKU') -param storageSkuName string = 'Standard_LRS' - -var storageNameCleaned = replace(storageName, '-', '') - -resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { - name: storageNameCleaned - location: location - tags: tags - sku: { - name: storageSkuName - } - kind: 'StorageV2' - properties: { - accessTier: 'Hot' - allowBlobPublicAccess: false - allowCrossTenantReplication: false - allowSharedKeyAccess: true - encryption: { - keySource: 'Microsoft.Storage' - requireInfrastructureEncryption: false - services: { - blob: { - enabled: true - keyType: 'Account' - } - file: { - enabled: true - keyType: 'Account' - } - queue: { - enabled: true - keyType: 'Service' - } - table: { - enabled: true - keyType: 'Service' - } - } - } - isHnsEnabled: false - isNfsV3Enabled: false - keyPolicy: { - keyExpirationPeriodInDays: 7 - } - largeFileSharesState: 'Disabled' - minimumTlsVersion: 'TLS1_2' - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Deny' - } - supportsHttpsTrafficOnly: true - } -} - -output aiservicesID string = aiServices.id -output aiservicesTarget string = aiServices.properties.endpoint -output storageId string = storage.id -output keyvaultId string = keyVault.id From 715ccfdad3b93f8ec3b03b46f06adc3fcc38dce6 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 13:31:59 -0500 Subject: [PATCH 086/180] Update quickstart.md --- quickstart.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/quickstart.md b/quickstart.md index 87346f69..7a33b499 100644 --- a/quickstart.md +++ b/quickstart.md @@ -75,9 +75,6 @@ If you already have these resources set up, skip to the [configure and run your Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. - If you prefer to deploy your own key vault, download the `main.bicep` file and `modules` folder and rerun the command, replacing `--template-file standard-agent.bicep` with `--template-file main.bicep.` - -
From ff43ed65e8ce66eea04cead5c790e2d6ed8ec9e4 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 11:13:51 -0800 Subject: [PATCH 087/180] updates --- ...azure_ai_projects-1.0.0b1-py3-none-any.whl | Bin 153467 -> 167160 bytes samples/function-calling/readme.md | 2 +- samples/function-calling/user_functions.py | 169 ++- samples/openapi/function-example.json | 1317 +---------------- samples/openapi/readme.md | 9 +- 5 files changed, 251 insertions(+), 1246 deletions(-) diff --git a/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl b/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl index 06dffa63c4af553f115f5d1d93b492acf2c0eb40..e17d1733335c68d5149aaa8af28453174f683774 100644 GIT binary patch delta 85006 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 delta 71707 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
wH{X0N@Wj`Ru*!j@{PO7ky?%k4#zg_9$0F7ji{h zgQ~$JZuLv>KnVWTp7^kc{kf|a=e#{5*3+fy0Pwdq={{Bv36h_N!0BE&l zn_yY$3@vrcoiqv&j_{6!JPD$0)2Mf5N4YQeY!f^S=zgzz?s-(}{MR%847={vq~Tqv z5-JOZY(gJ?-nJZOel+3g>JluxW{{#^aw`tGa4M`_ZS@5bBP$&j9{V}->u=lXLXbTr zeNNStmd>Qk5qZO`deM&d@sj{$q(V~TvcB*mFX}Xm!aIF$8bG6qq}f#ji6-Uk-BEb$~0MX1C(V#J#3fm zvOY-64E?ygb*mIb)3ckk+f~RL{SpKTn++kVk&%LRrNN3dw+uGInX1DPEu!d=#+H&e zoRD|}E1Sd8^tFD0o0qs@rDck8+L3$w$Dt0V5L<{*vADVF3QW$uvsq4}O`zbpV1KIV z{~YUbQ-DvjV%a!WCVBP?1FF_vsgk^x;YW+F_~Rq`^R?Q4rtug*JGpvJf0}@Fqo*CD z>ulsV86}^*J)+|=q*^SlOI$Vt2f+^(448<4yMhLY!?yWhXy{H3cU};Hf&W!l_Hv)K zJDM5sno1Y6NFr$&=?FD8R~!nC3I;&uyr#Z`%084uZO>5XY!6Yh0Zvmm*^}dISsVSZ zm`BZE*hSo5D~z@Q1<>_YAPd^Px!rXd*{b0#REX4~{aMfX&4}O8o1m^w}1 zOkXMWW7KDnj~ow+hYby}vZN-Kiy}Zw<&Lm)L3c!x_6gN79=jZ10ON9pf>F%h>Q^=* z`Q69__#eU%z9|O<12g>Jc`_)51L_D|kbv^qWd%h-7Gc;Z()Omi+FTe6X!blO$AI%n zGad-sv^e;w`QI;vFi+0bq49Ut2oBk`ZDXYhf%6 zZpx*ekh$Z)3d4w z4fsmI(K$Q5(-IA#G>-IEqMksq93~23uZ$E{iBdp1hRQgn)#(@s0$A}3Si==8PNyF} zD+(miGLix}kgV){_C2|LGz{f6nGpUqo{d_FQ0D0@RV(01@*?`#y}f`Ml_lCC4FmDZ_8K8lNEjG*qj{Jm98zEwYp*dC(_6 z4LyQk^5WO?4og%labHn>3ar5e|7#cYe43I>kR?$*fNP%4A7-gY&;tU^nHd@IU(D`* zhj~Cmas0zug?SM7nw4+8&qPq*uhq@aW+L7w&AWY<6*WQYbeK8uos2-at8fV;dj2)p zYuhel^B7?~Xy2}hI0>;F?C+(pf8Q_ms>i67FlE&1S^L;l4b_d6-a%1qbxQuBkpU$Q z9-E&S!1wRj!^RChDElCW5Jb_VOi7MF9zP7dOsGjc0l5 zd-_xjbX((NCURfjk`HJ-8mao=z|*DkFrD?KO4uGx5BmgBbQLjS@teJWBfUUXZ`o^p z2*3+Q+>eAlQ!}Vpz#?Iqh-p7zgWAp~-JWg|16_G(!q{b$pB|Z|FbgbDEd5Re?;tQ@ zISvJUG-M>L#IP~@Z^hAqtX;ZzpY#X-R!H}^O1l~+n@w_jd?m@~{rXmn61N|nW1$u( zvU9oU3tpHyyiS<03Av!er-zB{b9z`GnfT3f!NqfO$YLmASkH2_fnDa7_Zz8IU;+qy zK!fsydqEaEBXa~=nhjl6S|r+0gV96d@fx=Svy7VQKRvMVBxXc(Fh}c~`F0@qMSTSo za=C_f$ta+FRbvvG`fKjCmQMg=qW_oFdnHH6jG5)$72>$|pIJ!hjxzUR)63MS ?4 zMledtU)Iu=EpaZ+9S1>ZV0hs&#u0RpKw{X^N$uv^_dw&4XEVCH*!QCbT4f5=9oS(DoISP}7w^cG0t|A? zj^S-gAj)@R&Q1+}*GPr;uB3af4XU#5RgiVfH*x%$a0XooySTo6}8{dF1Kz{{wz4dE&faWE9xKPJ)7+H-E7pZtLB)U9;!a zgJXM>COVRa+N^zY!BxA1u1(2{n+ISUQd$Mcv&#O4qjD#PQVv`@esgvN^sWI~hqb{+ zIOY^nR5^NT44clj;Z@JWvr!kfVj801z?c173T~wWBu>c!&x~y~KR?#wUr%>jHnyj( z574p@!{-e;B929`&3G?;Y*K<{H0Iz2#6P?C#zjl)RDR4V(nr<5ZNlf8wEQ-IaS;8u)}A=!ZjR3|wzzhdxWPhM z$iPg(0Qpz-aa}Vtn;G@>rr>I)SjzrMh67dk)1QrA3ly$?o9r6nh3AX4vgqZDDEEGR z0crm2pgB^DL(27U=a6?vK}Q0cIn+Jy;iQ`8gh+@nTVE`%VRB}G;jhU0{3rAL81WEF z!maI){3j^>PtSX^&=@LfIZUli8Bs@Dr(0Qqktf-Zs!vvybfuZO5CaTy@iHnHe^@Q;=@T7 z+A^k&%$UEZ{v|4Mj~u`cpL6kkrY`y|oxPUwhj@x{FFO)&AF)A<+6yNWoSu}{Wvv_Y zl9jcaR$Py+vZ1&8*5PgbE(;RwpgMlH`un*ImgJwgnK^c_flKLiZlY;0BKfzB#9(O! zOSJB#Ycl{|(QmeV!HmcF5{hVorqG@LRWtM9-$$QV+aH zRUG5yBUl<_MY>0Hxj7G;)_~RwMy06<{0|9hT*{V5!TPS&0e(^CXIGVLhHRba;V74C zNj(;Ti(0DV22@MiOHM|IK07(a#aXr9$nIOWvY6xma@g=+O36N=+nd|pcL_f7vs?ho z@^nrC=n`=X95w}2{}$BOIQF(IycAaahQP&y||?Bqm=n*TIeduih{R(__& zVzwDt9$FAt-%2{@gFg#TY5v@?F^rO|$_yrORA{sc%jhU6)GOz%f;pQ%O95}Astr!j zIOWVJ`J6XH4#o79U->(<^4njmdmwBX8^yjzepAuCiibexI)}iWAZr+gpgG%r#@@7W z6a?V!5yLf7A=6ThWK+e1G*7K5BjE zptK7cjES11x2;J>m}zT*YJN9T(-hv6lq=$ z+lFpN5XQf5Z3IE9=bw#;_cR$AsCTfK%-gTO>6Tz)sp-OPO)yDLLrxVY%NM>Gzi+4b zE#}Vth!Kd=t~6H8ajkvAoUBqBv&N`M^e{MCblEbfZ0b}4d|q{zMem8!wMb6#$2P^DeyW@nO0ls{7=6cv0v*c=Vrd)6o%P(}hb z2(=zd@zl8DTD8x9gPIQBx5gR{PZk)TDiReu(*`g^8a`C343y>;d@P5XmMabyJwbTE zIzv`9ay(YS2C8-?R?EQybxVZcf#3hasXen>VKYJlho9>_9PPTR5WnxMc>9ie-axL|KX@4VNDFC4888s@*j(NBXG4yfD z_%p7;%_5f?A@*kXG4DzgTZZD98LQHMp^MK|)J4@SxsuGZ)Aj{1xA2D<KM9OA~b~F4UJOm-6pVYvpcz6CG{o1j74i8alD6toh74Z*XdQ zipNG49h|BScl1y1sumVfQ$%jY79ZJ8TF4u}5?BM&v^h^=P@Yly7Gi{jtGy)gt z<63$V>_MLTcEh5=Wn%~3qAA&4Eh1?zcf*a)SPJU};lB-?Qoc-+FEOVoxKHbH&e%O%RE6u#0HhqX~`Zp`p@I3eu3o2_M}f8AO`!wjGV6TvVlH>QVldid?!VOJY+(TzBu4`M(Jb&e?T5Un5M4hS$m+E6Mj_ zm6uQA+Wzxg=2os)o5bFZ1)0K)s5f@m!wgl*bJy+Dp$1=2k$zID9tUbbZs?M|bBb$b z$|n;%-V|)b#dr$ zW-;%{tcPAxlXig6HxFi)gHb zpprjOb@j6(YKzd$1}T!x{6n&_AC#eEb`$jTZjqP|sZ^!D_>xhK_YIYU_s3&(%0HKN zVw`{S1Bbjp(I)Vq3*pYwKgoJ6ba2ab+9seS_ z3HTPmI-N$ig3SSBeaOYf%*50}2;XDtZRi@oIs!}*BNkSjJF74*wpfofIN|>`Hq8xt zT_tp|c3&+y)M$PdjQwqLfm-vNI7i`Jjy!5_TTS9xuJFxDE}tZgR5upg%6Nk(j5~sEZPLN)|_Z zjDN6>7TZy12N~qTZ!|7VI4QA~icrOTaQ7N4yLiWffT{8T>7$L_(bqdWHU&jLW>Ob} z#SE|M1xesXjn^+VFXQa9sqWcJt%MoZPu}^{V$f= zmcjH3dSv;{CGC|%s4c6%lv#Sc6cqBxu2*+dt@Z)yVU%YOlO&tYG88E1>Gg#P(BfZ? z7^s!#e7V6QxplFl`Xk~)ksR9cSR1pVZak^S(a9zUb`IO?)3GJurbAvgA=z16snuPx zM$FYyx>Evw&zrhnGu?{sE}b_sDQoC>&T}iOFXT_(nKJc@?#7*cQ>T8;znF4$M{+A> z>YD+bdR*NyN69DusSgzt{CDwR#v|1i=lw;lf49Z$5yxxL7czrV2w&tY3OkHlAbBMO zc3DAB0!Qb%Zi|`!0g|9t@WP~mXO!RhCzc3Y8(SjGk-}Pjvnm#kzhOEi)lrYb-b^Do zQMbl~gC^uzk8SdxK5N`-bJH+jbhG5ml62T|0IGia*B%vztwVn^0F~!=mRnZZB$Uk! zROYP%+nin5&Kd*tx>LPs@6hxG;x?>%8sZM>ly0w&hS$78ImIPHr@asI-@=OABVBO2 zLK#Mu&&LFvD?i34%Ryq}cMn9|z3ML7 ziH5U2w(1u}m#AbSCNL7gnVR2gXz~%@251_u-`fO|@y*UUk~5!fAv}IY1l_fA#3FY1 z(LyL3hlJeP$6?cB)vG)O5gNDaO`D$tu1~Do)g%Wpfzbdo?xaiU*<3AdHhFi_zW)q` zgj%dggf4Z4nAdR(!2BM>3UD`rhz@8>jS&l~_UFJ(iMs_Bb_vK`$%pIoNS6uU9lXv} z3Dkcm&JT-vN;Mt%asKos_-kwtTLtvMP+{J2j(~}p?(5OC=WeV$;#HpRV4w}L1|+hG zdY71hkmUp6u8lF{IqIcieGnU*=X6i3`?>f|jr36V(sqhffUj1HR2KR^l}TCz};(8X41Li30! zsFtx~M>yB2qR1CNOV>rf?bi!{QNMR@d1W*1RY4qtnY6cL%eO4+fe0*Bm-z-XE6zUF zZ(9S$cvAYUXax%7Ot}%~^=5T?^4hA=50LOFRIInT5#0JBWj6l3z7NI4gfU0zAGmY4 z>Y7{q)-#_LSdoQD>|u;2_SIs!hY7h3WNC3E453Y50p(+Oip*jvVURg6tpsI(AxUV~ z;7rarbzY6b&MhNO4Up>aV$l^^ncP_{5BtC~vVFRIIo#~7wJBbcXo6`L_eu8?zT7}2 zvTREqDABDh_^iPMuDqlSf@)aMHKl3gpQvG>=lA=={g2tB8x6~QU8cPYz0a3-lkLeQ z)rVzM?n@G>w$M1QNUEKs7A|_~8u}-qU_XvNA(H1Q@nRZdxu!ZF-X*H|;wEDk%KKy* zRxlXA&ux}b*I7o|Z1LX=@qd=^XL-hL$0_t&MG?^+0sk^G6ULEYCvwN#GZNUt4Z)Eq zdWWIl4mlcvl0}7;cc?b|-tE~ovlp@{vaN#I$!`}P zX1TtbXVwpf7f~CIx@o6VbW5!VS(VzCK+kaOwB_;oF`oA)ILExZ(?$kBCdCT9k`B5B1q4~Ik9R&UM$Q|9G>*3M3OGe|C ztO4vN3S_OvL3#*)`sXNeL3Z9bcQsU7*;P*C*40Aw1KS@!{C+Tt=Qe|aaJl_)Dh@f0 z+MCRpCeLsU)j>+PkUyq~tmoFTwGCWBkx=N&By!v4e z8Wdcz;^X+At}B>!ypqAwe)hb^PQB7*gSG>eZ(#=)*jszaty$*YH_G}~(j=jT0+8*} ze;m0}CzqrsBRbKO?rU~(k!U}{{OweKmo-*}ttU?bZ0^4A$iO6GYzPZo(`ZWxSp~O; zU`0c66V^VxfTzriOU?H?A;dI#=*BDXzx{0ysxL2-r)Zs?b&Z#^xA)t^8eYknEiL_e z`V#hc`RkY26F9L`f7UaT)(4tuZ*oVmj4dyhH}8zSGEv&uI zjbtCp4CE?~_b?!a zcx!vl7j1g1*@4=?WoaFg{+o>x4$)@M&>a!5dla!s=OS)Yz3+jSp)A>nCI7(Zrcm%xhrH)qGS)XX$&o4Cz~dnqA5wGT#)BmaZ4(P9 z-}rT(Y86%(lQH4p>F|zOwgNU{zd#^$xJ>4#kZ>aKfLxl$#Pw4wFH#(HYrwoIszA`tZKR=A|8U$32^v*1REp3hRX@klZTEUY+@OAz$cKwy3O($Kszg z$3i;WwYzE-G{(FG+%T%W)LfK`Osa7JJQ!L24Oh6kU`4hp8VE`0DPfON?$V}LLXEiZ zubLndsf*(h(Mlm8z3bFj)OhBhrA&T}IR*cL)M>qZIFry|RD!#n7zP@7Vk=Oda>*Kp zu9En^Sb^2NdrdBJdr-)t1~gBFdmUqtbCiMpBGqmT`Ae5(F0v&pQzs3*(O3ffv*~Wu z%YK-9)@Cr*6|Oasrwcq++y6gpodr;o(YL^tkC1KzBm`+BB}KZsBv(3BkQ5|@Wl1R! z5tf!lU;!mo=?3YLZjoHNLFz5|eDCkPw==u<&iQ`l+_QJ?H{YGzd(NSBs``$lSDKm6 zk}`A0Zahx`EKy-zf}R)}Z2tWq`d(GGGFDjVm~bGercx!9_9&fozBQQJI=qsfB}49^ z$^8~H9>zuN-26wqR*)2-`}QYt$~edJ!gs+sPo7?xosdouI=F?gu;o$oK`@H%b!WmW z9=xK?+}!f)f8i?B^zrj7s>XE+_mDE*y?C&emZUHZo}7lZ^ZZF`A=ZfuZJPr0u?j48cgfa(SxXECR9ATI|%eQ!d^a zc_K>0Klr9l3=W2lWbj4W?xaDdeB=%^WKEwX4p_}0Wv4vqem#?ODI_EMNv&sx;A~}R z6D3}kO!<&OV2sVaAc9+-=h&PmX}sape$KQ)7>Q4{_>qC;;PkB=NpJf~#7x9Y{TBg>E4=HQDR!5&f7 zF_$pc+x<^RotnStsg#nSe`ETTGarw4=OaeF7xNOn+E1ZX4ADU%|BI%`&Xt0@6*&mS ziwvGq2kYUT>#cGk@N8_}gu9x_WmJbdxCvL0NgP1RDJS_gII$ zq9Y@3EuZf~ohn;e@0aq2k`=wXIA7-a#D6m^>j=eEpnsyu9Z}TPPg}SnQej`R;p1Lp zM^LL#oLp>?(;gNo@gry<_5?Gs z_h#KX(gdjA#zr_uA)+t9tfHPNym~;{0nf`7*_o6^lH6wbE@=b$Rh(bhxpc2C@Yxg3rO$&4nOy#y zY7p|3Zp6#pZ3Dr)O}@hXJ}1tuM*}dYq1&G4?cbb#$jW~!oBei%WzLJf44jiO-)>EghR?h1uD|T za~-0bjeN@wr__q7Ci6txlM?H~4fiXX8+I(~6<@0L=Y|XmU#gL@FV)iqiqq$Noo-@Q z=pP6l=>2{}N*8}y0eo?G5pNeOq=6mGP696jmwtIJ49VSR3b9x7=|y0A;BTLh+**$t zH-)AJTgvw8PSk~d_=Vk0rDcu3xc5Rax~zt%E@eVNOlf0`@|Ixn$RcpDG>d^T(_;8Q z-6^ic*aL_;10{J_!jt@=agj8#I(#xtejuc@}tweOz+7tx6GMx`7<|`7FaXE zu6^RXVd5Nt-P4>?vpyk-Wg~k_g0vNANBT_H>U1iD>BSoVU1xsG-x3+mCGy+BiniIm zd@Fd*cIUw<+seFFzMc(Kzaq0)KJ6NnM_0dC#DaKqDY0-MX`W#p#Ooh!h-uaz=ULa> z#gQbb&Jd6f!E6B|w+uf}^Da1~7i!Xw;V_7QZ+JVG7$&07%tUp!!3?34#I)zq9rU4~ zV!zqpHO)RV>AS)+JH0R@pK}_M*wZTX?#E&5YZ%$J^Pw92;H))RC zz+h9v^j>PZQq_`RcQ+Xq5-;8@yWxBXyKQZ2O{~opbDNoG(*qlqb;zWk|HMDw!ME&R zRGN7PBN1ZSvb{^y1W7aXQMpF0o!X|36n7yocwhT^*azwSJnB{)y-g1=zP$UR-<@iV+Lk!u zPo6%p?V-)Uz|$Y+s+BE{&BCSlN{I(?ZMJllAJQ)8vmni7&!$OhTp1MX#sY$^T+J*V zJyW4{Cq8UjV>XsI!MA4bW^xH64sgt;4WWx|*;Wg;Hrx$RRI;LS=y~5-0@2}6{Dylx zG<2{S%iI11INMJ(@1TBD>4p`RUibyhkB-|Zh)KWJvAid%_EPl9;83n+6AKDa+&@t@ zYl5C(+=5c|_c9+S?14z{IBFi5y_>=e)Y^OJ@Z7_WGyKX&_h2JaA3)D|;m z->Y3-Hf2FDXljWydN!(ph~*2|oruAFQc(#yufLKQV@uU(u)(|&fS)X1F~XUu?(@^2 zCvzMPRnC4g5o}A<+QHmNqJ~32SfKY2ZZ*0H^PF9&+Xiu6c_wj(PgGA7*?Orh7Sp4x zowVs*TlVVi@w1{$jRv)4ETtFPk% z#CFTO*aT12#R~@-mn*pL?)s!94F<)KT0GCc7x*Y_>tKw^diZuhsc{bsA_q`IH0V>P zKguV3vPJ4j9DhklF~T}&Cjq+?Oh0#=)W=zp13O(r(0WR@rO2s$PGQ^!a2~0ZctgTU z9EWnhm&xe|b!sfmzEU`ivNzNw{Dw=a#OOSXicZenh@f9Ll+_VqjXibC-CfrP< zVDKz1%Ir#|APAMMp5xO>oPV1pq=kI>ClL`KG%=x%Yb?WR7pszn6Z^YOQ@fNcY!#Ks zDnn2+O<=0#-s|i$_RdN>+|PK)xRtd}x-|+HkW-g92ZF<*V(xX#^7Z}C9S%)cHRF^F zESzjtu3m3a7c&oV3Jhp#x26-Vc<5aau77#UW|IE-)N~?OCDG*!j~(568={y?7ehAJ zqsz{fwDqfkrJC74y5exSG2k$K4gbw?us8ke*2(SYhn;9{bjEXWmb4IpE5@&vG7wo0fRQAc54Wb14ih@N#;e{r6aOA%LZu)k-S`(qY^ zl#)&?nTJ#yqAUCCRp4_yrgBKaagm4c=TC0h(e4>u$8UM7s)7^LqG)sOg-~|0R>&xd zj)65N?IC-Ut2o8jQ(xzz6d9l~iio-0IQH4>Gnz=UG;(bPnFGRd!KIhJS=;N>S||7h zBgHFIu3{k?cfWUC9#K=a$zT++uA+Bo2Xu94V0T;9i)t<4Sb@!%*-Id}?KBx`t~}4_ zHA}QIUm zb#w(<0rcyhz)N5V3merlJ}2~5gAw=wR_LPw128vVK=>Mf75M^sB-hsk!d1uaV}d|n zTo8y8Ci4`g6%Q7&!{U*pCZ`R8Ndvj!7b%*7c|86b3N37qs$UaBIFEtBdABa{I^jgGG z#2wk(ZdFi>C+H`cQt_^TBTx#*kv50Ti2;;7K6eh$g|vuAc5h*d^|SQwqLFHEWD6m2~Lc->tSSW6K!TX??ZoTZkPF` zY>%GwRY9ptngtf@D}bYF2wX2Q~AiHX>Z` zzlPE-JSa@2%wq@}fj{P)}5S}z9jq*Puxj*R$2uyEJ}e!Tkg}(=rq|N zH7AtoiA3Pv*{9D|kZwvdVWzuu{5?${g;7&A7Ar6#J0`8{)N6BiezbeO8b=kPaW*ad z^AKWZKCqMNj0oMFTa&f%<8Swc`zAg>n&s=N62C6i_ctgGfluN#=gmAl(s_#3G2@cx zT{&rVW|sO219gT%{0mZ^y6I5DhU!vaPbv^Wj(D^$VKW{29F3p6;Q1Twf})7s)`6g} zdq01mcAqE7dj3WT`f!JUKZKDfj=48R8){`&9woN9aVJaZ!qhY-w?Uz zcg$_oicPK7uG9purt^8mHIDggG`_e4&*MPoG=8rd&(ZG((s>yHmvj3OZ;I3P^Fl}* zvfJa9TkaFDGV7Y|7X7sgm+g2)_fGk}7rD<~)zj->1-gReOXPKzWdXQk9zpf>S8%$ucF~Mfr2lY4G*agJ1_q96H_AyWCNqI zcr*BFCi`lwKii9)>u^YmsIuHBQK*2ufmejL=3B8^u5p*Rn#Zxlr`z{1RN`8}=$E}I zN)L<(@!ba)28}DvMCmW6R70#rbv$$*4MzvYI$I~JjmL;uFTO(ShkOj0!_?jht+Pb) ziY!COmG2q&4eHBG8V}`n$uT!VIu}HZutnNal{2>#Y4q5mAJ@E;60d;2<0-7=-uiV$ zeldN1m1(IgOrA*~rEursGQ&Qx&z(_B_w8Ogx3}!1;H%E!9@05fM8(uLSEP#MB`|JI z>PoIMbfw;suvQz^;=IhiLlzxzU$a;j33 z=fx@2sIyWek5_sqxa{`v)Q?lnnA6KlGb+1vC!T2wkIGVeWEio^UcK+pAw5zek?}u6 z*H%LV$U)>F5C|Jo8D$205C|xvua=m>`~m?b^lM2+AfS2Ep$Y=jZZ6pc0g5-0(jY*S z0L2(n(p;}YVb<_Q%(diNhX{9|0^M@CptIDmgMxN9E4!)}zDJs2Pm*FWSi3>peN zVz^E=GCB8t0VjUc;Bjch{4jzr)WClL7=`JG!W-M?RTyf{ukD$7LdV@KP<|GngP8tus1^a;miU7*NTT7ujNYKU{r@V5{8d3f zv(o?YsInn{O#kORvH#_6OdHi*qvU^rbMrz`tLOjZXZeSJ*6@dy3

kuf6yu&i5bG z0vCwO6e9bdxZgihceBOdi$twCGRcG}fEDH*36R|g!>@&t(l^4MNR;P)_b4VPv)6Bq zf6SLEp-7P%O)*p=d_Y(EMswa5Ab>?gq2}oSY+?RGy#iYB2cM1t2np#>w}=W3YI$k` HDCWNaN_c$K diff --git a/samples/function-calling/readme.md b/samples/function-calling/readme.md index 698f949f..6184d763 100644 --- a/samples/function-calling/readme.md +++ b/samples/function-calling/readme.md @@ -17,6 +17,6 @@ Run the code samples below and view the output. * [Python - function calling with automatic tool calling](./python-function-calling-toolset.py) * [Python - function calling with streaming](./python-function-calling-streaming.py) -# Additional samples +## Additional samples Get the latest stock price using function calling with Yfinance ([shown in Personal Finance Assistant](https://github.com/Azure-Samples/azureai-samples/blob/main/scenarios/Assistants/api-in-a-box/personal_finance/assistant-personal_finance.ipynb)) diff --git a/samples/function-calling/user_functions.py b/samples/function-calling/user_functions.py index 47edb64d..265913dd 100644 --- a/samples/function-calling/user_functions.py +++ b/samples/function-calling/user_functions.py @@ -1,19 +1,27 @@ import json import datetime -from typing import Any, Callable, Set +from typing import Any, Callable, Set, Dict, List, Optional # These are the user-defined functions that can be called by the agent. -def fetch_current_datetime() -> str: +def fetch_current_datetime(format: Optional[str] = None) -> str: """ - Get the current time as a JSON string. + Get the current time as a JSON string, optionally formatted. + :param format (Optional[str]): The format in which to return the current time. Defaults to None, which uses a standard format. :return: The current time in JSON format. :rtype: str """ current_time = datetime.datetime.now() - time_json = json.dumps({"current_time": current_time.strftime("%Y-%m-%d %H:%M:%S")}) + + # Use the provided format if available, else use a default format + if format: + time_format = format + else: + time_format = "%Y-%m-%d %H:%M:%S" + + time_json = json.dumps({"current_time": current_time.strftime(time_format)}) return time_json @@ -53,9 +61,162 @@ def send_email(recipient: str, subject: str, body: str) -> str: return message_json +def calculate_sum(a: int, b: int) -> str: + """Calculates the sum of two integers. + + :param a (int): First integer. + :rtype: int + :param b (int): Second integer. + :rtype: int + + :return: The sum of the two integers. + :rtype: str + """ + result = a + b + return json.dumps({"result": result}) + + +def convert_temperature(celsius: float) -> str: + """Converts temperature from Celsius to Fahrenheit. + + :param celsius (float): Temperature in Celsius. + :rtype: float + + :return: Temperature in Fahrenheit. + :rtype: str + """ + fahrenheit = (celsius * 9 / 5) + 32 + return json.dumps({"fahrenheit": fahrenheit}) + + +def toggle_flag(flag: bool) -> str: + """Toggles a boolean flag. + + :param flag (bool): The flag to toggle. + :rtype: bool + + :return: The toggled flag. + :rtype: str + """ + toggled = not flag + return json.dumps({"toggled_flag": toggled}) + + +def merge_dicts(dict1: Dict[str, Any], dict2: Dict[str, Any]) -> str: + """Merges two dictionaries. + + :param dict1 (Dict[str, Any]): First dictionary. + :rtype: dict + :param dict2 (Dict[str, Any]): Second dictionary. + :rtype: dict + + :return: The merged dictionary. + :rtype: str + """ + merged = dict1.copy() + merged.update(dict2) + return json.dumps({"merged_dict": merged}) + + +def get_user_info(user_id: int) -> str: + """Retrieves user information based on user ID. + + :param user_id (int): ID of the user. + :rtype: int + + :return: User information as a JSON string. + :rtype: str + """ + mock_users = { + 1: {"name": "Alice", "email": "alice@example.com"}, + 2: {"name": "Bob", "email": "bob@example.com"}, + 3: {"name": "Charlie", "email": "charlie@example.com"}, + } + user_info = mock_users.get(user_id, {"error": "User not found."}) + return json.dumps({"user_info": user_info}) + + +def longest_word_in_sentences(sentences: List[str]) -> str: + """Finds the longest word in each sentence. + + :param sentences (List[str]): A list of sentences. + :return: A JSON string mapping each sentence to its longest word. + :rtype: str + """ + if not sentences: + return json.dumps({"error": "The list of sentences is empty"}) + + longest_words = {} + for sentence in sentences: + # Split sentence into words + words = sentence.split() + if words: + # Find the longest word + longest_word = max(words, key=len) + longest_words[sentence] = longest_word + else: + longest_words[sentence] = "" + + return json.dumps({"longest_words": longest_words}) + + +def process_records(records: List[Dict[str, int]]) -> str: + """ + Process a list of records, where each record is a dictionary with string keys and integer values. + + :param records: A list containing dictionaries that map strings to integers. + :return: A list of sums of the integer values in each record. + """ + sums = [] + for record in records: + # Sum up all the values in each dictionary and append the result to the sums list + total = sum(record.values()) + sums.append(total) + return json.dumps({"sums": sums}) + + +# Example User Input for Each Function +# 1. Fetch Current DateTime +# User Input: "What is the current date and time?" +# User Input: "What is the current date and time in '%Y-%m-%d %H:%M:%S' format?" + +# 2. Fetch Weather +# User Input: "Can you provide the weather information for New York?" + +# 3. Send Email +# User Input: "Send an email to john.doe@example.com with the subject 'Meeting Reminder' and body 'Don't forget our meeting at 3 PM.'" + +# 4. Calculate Sum +# User Input: "What is the sum of 45 and 55?" + +# 5. Convert Temperature +# User Input: "Convert 25 degrees Celsius to Fahrenheit." + +# 6. Toggle Flag +# User Input: "Toggle the flag True." + +# 7. Merge Dictionaries +# User Input: "Merge these two dictionaries: {'name': 'Alice'} and {'age': 30}." + +# 8. Get User Info +# User Input: "Retrieve user information for user ID 1." + +# 9. Longest Word in Sentences +# User Input: "Find the longest word in each of these sentences: ['The quick brown fox jumps over the lazy dog', 'Python is an amazing programming language', 'Azure AI capabilities are impressive']." + +# 10. Process Records +# User Input: "Process the following records: [{'a': 10, 'b': 20}, {'x': 5, 'y': 15, 'z': 25}, {'m': 30}]." + # Statically defined user functions for fast reference user_functions: Set[Callable[..., Any]] = { fetch_current_datetime, fetch_weather, send_email, + calculate_sum, + convert_temperature, + toggle_flag, + merge_dicts, + get_user_info, + longest_word_in_sentences, + process_records, } \ No newline at end of file diff --git a/samples/openapi/function-example.json b/samples/openapi/function-example.json index 0ac5aa72..3e06e256 100644 --- a/samples/openapi/function-example.json +++ b/samples/openapi/function-example.json @@ -1,1239 +1,78 @@ -{ - "openapi": "3.0.2", - "servers": [ - { - "url": "/v3" - } - ], - "info": { - "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)", - "version": "1.0.20-SNAPSHOT", - "title": "Swagger Petstore - OpenAPI 3.0", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "email": "apiteam@swagger.io" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - } - }, - "tags": [ - { - "name": "pet", - "description": "Everything about your Pets", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - }, - { - "name": "store", - "description": "Access to Petstore orders", - "externalDocs": { - "description": "Find out more about our store", - "url": "http://swagger.io" - } - }, - { - "name": "user", - "description": "Operations about user" - } - ], - "paths": { - "/pet": { - "post": { - "tags": [ - "pet" - ], - "summary": "Add a new pet to the store", - "description": "Add a new pet to the store", - "operationId": "addPet", - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - } - } - }, - "405": { - "description": "Invalid input" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "requestBody": { - "description": "Create a new pet in the store", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - } - } - } - }, - "put": { - "tags": [ - "pet" - ], - "summary": "Update an existing pet", - "description": "Update an existing pet by Id", - "operationId": "updatePet", - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - } - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - }, - "405": { - "description": "Validation exception" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "requestBody": { - "description": "Update an existent pet in the store", - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - } - } - } - } - }, - "/pet/findByStatus": { - "get": { - "tags": [ - "pet" - ], - "summary": "Finds Pets by status", - "description": "Multiple status values can be provided with comma separated strings", - "operationId": "findPetsByStatus", - "parameters": [ - { - "name": "status", - "in": "query", - "description": "Status values that need to be considered for filter", - "required": false, - "explode": true, - "schema": { - "type": "string", - "enum": [ - "available", - "pending", - "sold" - ], - "default": "available" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/xml": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet" - } - } - }, - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet" - } - } - } - } - }, - "400": { - "description": "Invalid status value" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - } - }, - "/pet/findByTags": { - "get": { - "tags": [ - "pet" - ], - "summary": "Finds Pets by tags", - "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", - "operationId": "findPetsByTags", - "parameters": [ - { - "name": "tags", - "in": "query", - "description": "Tags to filter by", - "required": false, - "explode": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/xml": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet" - } - } - }, - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Pet" - } - } - } - } - }, - "400": { - "description": "Invalid tag value" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - } - }, - "/pet/{petId}": { - "get": { - "tags": [ - "pet" - ], - "summary": "Find pet by ID", - "description": "Returns a single pet", - "operationId": "getPetById", - "parameters": [ - { - "name": "petId", - "in": "path", - "description": "ID of pet to return", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - } - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - } - }, - "security": [ - { - "api_key": [] - }, - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - }, - "post": { - "tags": [ - "pet" - ], - "summary": "Updates a pet in the store with form data", - "description": "", - "operationId": "updatePetWithForm", - "parameters": [ - { - "name": "petId", - "in": "path", - "description": "ID of pet that needs to be updated", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "name", - "in": "query", - "description": "Name of pet that needs to be updated", - "schema": { - "type": "string" - } - }, - { - "name": "status", - "in": "query", - "description": "Status of pet that needs to be updated", - "schema": { - "type": "string" - } - } - ], - "responses": { - "405": { - "description": "Invalid input" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - }, - "delete": { - "tags": [ - "pet" - ], - "summary": "Deletes a pet", - "description": "", - "operationId": "deletePet", - "parameters": [ - { - "name": "api_key", - "in": "header", - "description": "", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "petId", - "in": "path", - "description": "Pet id to delete", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "400": { - "description": "Invalid pet value" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - } - }, - "/pet/{petId}/uploadImage": { - "post": { - "tags": [ - "pet" - ], - "summary": "uploads an image", - "description": "", - "operationId": "uploadFile", - "parameters": [ - { - "name": "petId", - "in": "path", - "description": "ID of pet to update", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "additionalMetadata", - "in": "query", - "description": "Additional Metadata", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiResponse" - } - } - } - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "requestBody": { - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - } - } - }, - "/store/inventory": { - "get": { - "tags": [ - "store" - ], - "summary": "Returns pet inventories by status", - "description": "Returns a map of status codes to quantities", - "operationId": "getInventory", - "x-swagger-router-controller": "OrderController", - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int32" - } - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/store/order": { - "post": { - "tags": [ - "store" - ], - "summary": "Place an order for a pet", - "description": "Place a new order in the store", - "operationId": "placeOrder", - "x-swagger-router-controller": "OrderController", - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Order" - } - } - } - }, - "405": { - "description": "Invalid input" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Order" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Order" - } - }, - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/Order" - } - } - } - } - } - }, - "/store/order/{orderId}": { - "get": { - "tags": [ - "store" - ], - "summary": "Find purchase order by ID", - "x-swagger-router-controller": "OrderController", - "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.", - "operationId": "getOrderById", - "parameters": [ - { - "name": "orderId", - "in": "path", - "description": "ID of order that needs to be fetched", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Order" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/Order" - } - } - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - }, - "delete": { - "tags": [ - "store" - ], - "summary": "Delete purchase order by ID", - "x-swagger-router-controller": "OrderController", - "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", - "operationId": "deleteOrder", - "parameters": [ - { - "name": "orderId", - "in": "path", - "description": "ID of the order that needs to be deleted", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - } - }, - "/user": { - "post": { - "tags": [ - "user" - ], - "summary": "Create user", - "description": "This can only be done by the logged in user.", - "operationId": "createUser", - "responses": { - "default": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - } - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/User" - } - }, - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - }, - "description": "Created user object" - } - } - }, - "/user/createWithList": { - "post": { - "tags": [ - "user" - ], - "summary": "Creates list of users with given input array", - "description": "Creates list of users with given input array", - "x-swagger-router-controller": "UserController", - "operationId": "createUsersWithListInput", - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/xml": { - "schema": { - "$ref": "#/components/schemas/User" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - } - }, - "default": { - "description": "successful operation" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/User" - } - } - } - } - } - } - }, - "/user/login": { - "get": { - "tags": [ - "user" - ], - "summary": "Logs user into the system", - "description": "", - "operationId": "loginUser", - "parameters": [ - { - "name": "username", - "in": "query", - "description": "The user name for login", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "password", - "in": "query", - "description": "The password for login in clear text", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "headers": { - "X-Rate-Limit": { - "description": "calls per hour allowed by the user", - "schema": { - "type": "integer", - "format": "int32" - } - }, - "X-Expires-After": { - "description": "date in UTC when token expires", - "schema": { - "type": "string", - "format": "date-time" - } - } - }, - "content": { - "application/xml": { - "schema": { - "type": "string" - } - }, - "application/json": { - "schema": { - "type": "string" - } - } - } - }, - "400": { - "description": "Invalid username/password supplied" - } - } - } - }, - "/user/logout": { - "get": { - "tags": [ - "user" - ], - "summary": "Logs out current logged in user session", - "description": "", - "operationId": "logoutUser", - "parameters": [], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/{username}": { - "get": { - "tags": [ - "user" - ], - "summary": "Get user by user name", - "description": "", - "operationId": "getUserByName", - "parameters": [ - { - "name": "username", - "in": "path", - "description": "The name that needs to be fetched. Use user1 for testing. ", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/xml": { - "schema": { - "$ref": "#/components/schemas/User" - } - }, - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - } - }, - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - }, - "put": { - "tags": [ - "user" - ], - "summary": "Update user", - "x-swagger-router-controller": "UserController", - "description": "This can only be done by the logged in user.", - "operationId": "updateUser", - "parameters": [ - { - "name": "username", - "in": "path", - "description": "name that needs to be updated", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "default": { - "description": "successful operation" - } - }, - "requestBody": { - "description": "Update an existent user in the store", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/User" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/User" - } - }, - "application/x-www-form-urlencoded": { - "schema": { - "$ref": "#/components/schemas/User" - } - } - } - } - }, - "delete": { - "tags": [ - "user" - ], - "summary": "Delete user", - "description": "This can only be done by the logged in user.", - "operationId": "deleteUser", - "parameters": [ - { - "name": "username", - "in": "path", - "description": "The name that needs to be deleted", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - } - } - }, - "externalDocs": { - "description": "Find out more about Swagger", - "url": "http://swagger.io" - }, - "components": { - "schemas": { - "Order": { - "x-swagger-router-model": "io.swagger.petstore.model.Order", - "properties": { - "id": { - "type": "integer", - "format": "int64", - "example": 10 - }, - "petId": { - "type": "integer", - "format": "int64", - "example": 198772 - }, - "quantity": { - "type": "integer", - "format": "int32", - "example": 7 - }, - "shipDate": { - "type": "string", - "format": "date-time" - }, - "status": { - "type": "string", - "description": "Order Status", - "enum": [ - "placed", - "approved", - "delivered" - ], - "example": "approved" - }, - "complete": { - "type": "boolean" - } - }, - "xml": { - "name": "order" - }, - "type": "object" - }, - "Customer": { - "properties": { - "id": { - "type": "integer", - "format": "int64", - "example": 100000 - }, - "username": { - "type": "string", - "example": "fehguy" - }, - "address": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Address" - }, - "xml": { - "wrapped": true, - "name": "addresses" - } - } - }, - "xml": { - "name": "customer" - }, - "type": "object" - }, - "Address": { - "properties": { - "street": { - "type": "string", - "example": "437 Lytton" - }, - "city": { - "type": "string", - "example": "Palo Alto" - }, - "state": { - "type": "string", - "example": "CA" - }, - "zip": { - "type": "string", - "example": 94301 - } - }, - "xml": { - "name": "address" - }, - "type": "object" - }, - "Category": { - "x-swagger-router-model": "io.swagger.petstore.model.Category", - "properties": { - "id": { - "type": "integer", - "format": "int64", - "example": 1 - }, - "name": { - "type": "string", - "example": "Dogs" - } - }, - "xml": { - "name": "category" - }, - "type": "object" - }, - "User": { - "x-swagger-router-model": "io.swagger.petstore.model.User", - "properties": { - "id": { - "type": "integer", - "format": "int64", - "example": 10 - }, - "username": { - "type": "string", - "example": "theUser" - }, - "firstName": { - "type": "string", - "example": "John" - }, - "lastName": { - "type": "string", - "example": "James" - }, - "email": { - "type": "string", - "example": "john@email.com" - }, - "password": { - "type": "string", - "example": 12345 - }, - "phone": { - "type": "string", - "example": 12345 - }, - "userStatus": { - "type": "integer", - "format": "int32", - "example": 1, - "description": "User Status" - } - }, - "xml": { - "name": "user" - }, - "type": "object" - }, - "Tag": { - "x-swagger-router-model": "io.swagger.petstore.model.Tag", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "xml": { - "name": "tag" - }, - "type": "object" - }, - "Pet": { - "x-swagger-router-model": "io.swagger.petstore.model.Pet", - "required": [ - "name", - "photoUrls" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64", - "example": 10 - }, - "name": { - "type": "string", - "example": "doggie" - }, - "category": { - "$ref": "#/components/schemas/Category" - }, - "photoUrls": { - "type": "array", - "xml": { - "wrapped": true - }, - "items": { - "type": "string", - "xml": { - "name": "photoUrl" - } - } - }, - "tags": { - "type": "array", - "xml": { - "wrapped": true - }, - "items": { - "$ref": "#/components/schemas/Tag", - "xml": { - "name": "tag" - } - } - }, - "status": { - "type": "string", - "description": "pet status in the store", - "enum": [ - "available", - "pending", - "sold" - ] - } - }, - "xml": { - "name": "pet" - }, - "type": "object" - }, - "ApiResponse": { - "properties": { - "code": { - "type": "integer", - "format": "int32" - }, - "type": { - "type": "string" - }, - "message": { - "type": "string" - } - }, - "xml": { - "name": "##default" - }, - "type": "object" - } - }, - "requestBodies": { - "Pet": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - }, - "application/xml": { - "schema": { - "$ref": "#/components/schemas/Pet" - } - } - }, - "description": "Pet object that needs to be added to the store" - }, - "UserArray": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/User" - } - } - } - }, - "description": "List of user object" - } - }, - "securitySchemes": { - "petstore_auth": { - "type": "oauth2", - "flows": { - "implicit": { - "authorizationUrl": "https://petstore.swagger.io/oauth/authorize", - "scopes": { - "write:pets": "modify pets in your account", - "read:pets": "read your pets" - } - } - } - }, - "api_key": { - "type": "apiKey", - "name": "api_key", - "in": "header" - } - } - } - } \ No newline at end of file +openapi: 3.0.1 +info: + title: Weather Service API + description: This is a sample API for retrieving weather information. + version: 1.0.0 +servers: + - url: https://api.example.com/weather + description: Main API Server +paths: + /current: + get: + summary: Get current weather + operationId: getCurrentWeather + tags: + - weather + parameters: + - name: location + in: query + required: true + description: Location to get weather for + schema: + type: string + responses: + '200': + description: Current weather details + content: + application/json: + schema: + $ref: '#/components/schemas/Weather' + '404': + description: Location not found + /forecast: + get: + summary: Get weather forecast + operationId: getWeatherForecast + tags: + - weather + parameters: + - name: location + in: query + required: true + description: Location to get weather forecast for + schema: + type: string + - name: days + in: query + required: true + description: Number of days to forecast + schema: + type: integer + minimum: 1 + maximum: 7 + responses: + '200': + description: Weather forecast details + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Weather' + '404': + description: Location not found +components: + schemas: + Weather: + type: object + properties: + location: + type: string + temperature: + type: number + description: + type: string + humidity: + type: number + windSpeed: + type: number diff --git a/samples/openapi/readme.md b/samples/openapi/readme.md index c92b7f9f..1a6e00c7 100644 --- a/samples/openapi/readme.md +++ b/samples/openapi/readme.md @@ -1,10 +1,15 @@ # Use OpenAPI 3.0 Specified Tools -The Custom Tools feature allows developers to describe custom tools in the Agent API using an [OpenAPI schema](https://www.openapis.org/), enabling the model to intelligently call these functions based on user input. You can use any API spec that is written according to the OpenAPI 3.0 schema. +The Custom Tools feature allows developers to describe custom tools in the Agent API using an [OpenAPI schema](https://www.openapis.org/), enabling the model to intelligently call these functions based on user input. You can use any API spec that is written according to the OpenAPI 3.0 schema. + +While you can use [function calling](../function-calling/readme.md) to define functions you want your agent to call, the OpenAPI tool described here gives you: + +* Standardization by letting you leverage the OpenAPI spec when defining your tools +* Server-side integration with the ability to use managed identity ## Setup -You need a function defined using the OpenAPI Schema. See the [example function](./function-example.json) for details. It will look something like this: +You need a function defined using the OpenAPI Schema. See the [example function](./function-example.json) for a full sample of a possible tool definition. It will look something like this: ```yml openapi: 3.0.1  From 288885c32d564e8e130be3113d58929baf60e930 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 11:35:27 -0800 Subject: [PATCH 088/180] adding directory structure --- quickstart.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 7a33b499..88a4448d 100644 --- a/quickstart.md +++ b/quickstart.md @@ -60,7 +60,17 @@ If you already have these resources set up, skip to the [configure and run your 3.
**Option 1**: Use the standard agent configuration. -- Download the `standard-agent.bicep` file and the `modules-standard` folder to your project directory. +- Download the `standard-agent.bicep` file and the `modules-standard` folder to your project directory. Your directory should look like this + + ``` + /my-project + - standard-agent.bicep + /modules-standard + - standard-ai-hub.bicep + - standard-ai-project.bicep + - standard-dependent-resources.bicep + ``` + - Using the resource group you created in the previous step, run one of the following commands: - To use default resource names, run: From 51afafe1ec4473cdd98f5b4bb3006e480a38b72f Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 11:47:44 -0800 Subject: [PATCH 089/180] consistency --- quickstart.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/quickstart.md b/quickstart.md index 88a4448d..29495311 100644 --- a/quickstart.md +++ b/quickstart.md @@ -64,11 +64,11 @@ If you already have these resources set up, skip to the [configure and run your ``` /my-project - - standard-agent.bicep - /modules-standard - - standard-ai-hub.bicep - - standard-ai-project.bicep - - standard-dependent-resources.bicep + - standard-agent.bicep + /modules-standard + - standard-ai-hub.bicep + - standard-ai-project.bicep + - standard-dependent-resources.bicep ``` - Using the resource group you created in the previous step, run one of the following commands: From 4f5af48960944161fa3e382acea1bcdb5bf98061 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 12:38:53 -0800 Subject: [PATCH 090/180] updating code --- quickstart.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 29495311..0f6d3f7d 100644 --- a/quickstart.md +++ b/quickstart.md @@ -275,7 +275,8 @@ with project_client: print(f"File ID: {file_path_annotation.file_path.file_id}") print(f"Start Index: {file_path_annotation.start_index}") print(f"End Index: {file_path_annotation.end_index}") - + project_client.agents.save_file(file_id=file_path_annotation.file_path.file_id, file_name=Path(file_path_annotation.text).name) + # Delete the agent once done project_client.agents.delete_agent(agent.id) print("Deleted agent") From 3203321ef6088a7a03d5dca33081616d511ed64d Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 13:55:35 -0800 Subject: [PATCH 091/180] updating model in samples --- quickstart.md | 2 +- samples/bing-search/bing-python.py | 2 +- samples/code-interpreter/python-code-interpreter.py | 2 +- samples/file-search/python-file-search.py | 2 +- .../function-calling/python-function-calling-streaming.py | 2 +- .../function-calling/python-function-calling-toolset.py | 2 +- samples/function-calling/python-function-calling.py | 2 +- samples/llama-3.md | 8 -------- samples/openapi/python-openapi.py | 2 +- samples/use-openai.md | 6 +++--- 10 files changed, 11 insertions(+), 19 deletions(-) diff --git a/quickstart.md b/quickstart.md index 0f6d3f7d..f54721fe 100644 --- a/quickstart.md +++ b/quickstart.md @@ -223,7 +223,7 @@ with project_client: # The CodeInterpeterTool needs to be included in creation of the agent agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o-mini", name="my-assistant", instructions="You are helpful assistant", tools=code_interpreter.definitions, diff --git a/samples/bing-search/bing-python.py b/samples/bing-search/bing-python.py index cf91d96b..c9c2938b 100644 --- a/samples/bing-search/bing-python.py +++ b/samples/bing-search/bing-python.py @@ -51,7 +51,7 @@ # Create agent with the bing tool and process assistant run with project_client: agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o-mini", name="my-assistant", instructions="You are a helpful assistant", tools=bing.definitions, diff --git a/samples/code-interpreter/python-code-interpreter.py b/samples/code-interpreter/python-code-interpreter.py index 38ccc743..9ebacd98 100644 --- a/samples/code-interpreter/python-code-interpreter.py +++ b/samples/code-interpreter/python-code-interpreter.py @@ -48,7 +48,7 @@ # notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent", tools=code_interpreter.definitions, diff --git a/samples/file-search/python-file-search.py b/samples/file-search/python-file-search.py index c982b40b..71ca0490 100644 --- a/samples/file-search/python-file-search.py +++ b/samples/file-search/python-file-search.py @@ -26,7 +26,7 @@ # Create agent with file search tool and process the agent run agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o-mini", name="my-agent", instructions="Hello, you are helpful agent and can search information from uploaded files", tools=file_search.definitions, diff --git a/samples/function-calling/python-function-calling-streaming.py b/samples/function-calling/python-function-calling-streaming.py index 839f0ddd..55a65bdf 100644 --- a/samples/function-calling/python-function-calling-streaming.py +++ b/samples/function-calling/python-function-calling-streaming.py @@ -67,7 +67,7 @@ def on_unhandled_event(self, event_type: str, event_data: Any) -> None: toolset.add(functions) agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset + model="gpt-4o-mini", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset ) print(f"Created agent, ID: {agent.id}") diff --git a/samples/function-calling/python-function-calling-toolset.py b/samples/function-calling/python-function-calling-toolset.py index cfa5f542..3eb2a4e1 100644 --- a/samples/function-calling/python-function-calling-toolset.py +++ b/samples/function-calling/python-function-calling-toolset.py @@ -27,7 +27,7 @@ # Create agent with toolset and process assistant run with project_client: agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset + model="gpt-4o-mini", name="my-assistant", instructions="You are a helpful assistant", toolset=toolset ) print(f"Created agent, ID: {agent.id}") diff --git a/samples/function-calling/python-function-calling.py b/samples/function-calling/python-function-calling.py index bf5d07b8..084076cc 100644 --- a/samples/function-calling/python-function-calling.py +++ b/samples/function-calling/python-function-calling.py @@ -19,7 +19,7 @@ with project_client: # Create an agent and run user's request with function calls agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o-mini", name="my-agent", instructions="You are a helpful agent", tools=functions.definitions, diff --git a/samples/llama-3.md b/samples/llama-3.md index e6aa4eca..da6c61cc 100644 --- a/samples/llama-3.md +++ b/samples/llama-3.md @@ -21,11 +21,3 @@ You can now create agents using Llama 3 in Azure AI Agents Service. To get start ```python agent = project_client.agents.create_agent( model="llama-3", name="my-agent", instructions="You are a helpful agent" ) ``` - - ```csharp - Response agentResponse = await client.CreateAgentAsync( - model: "llama-3", - name: "Math Tutor", - instructions: "You are a helpful agent", - ); - ``` \ No newline at end of file diff --git a/samples/openapi/python-openapi.py b/samples/openapi/python-openapi.py index da9ecbc6..d1c555db 100644 --- a/samples/openapi/python-openapi.py +++ b/samples/openapi/python-openapi.py @@ -16,7 +16,7 @@ with project_client: # Create an agent and run user's request with function calls agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o-mini", name="my-agent", instructions="You are a helpful agent", tools=[{ diff --git a/samples/use-openai.md b/samples/use-openai.md index 147e4c82..ac319704 100644 --- a/samples/use-openai.md +++ b/samples/use-openai.md @@ -24,7 +24,7 @@ with AIProjectClient.from_connection_string( with client: agent = client.beta.assistants.create( - model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent" + model="gpt-4o-mini", name="my-agent", instructions="You are a helpful agent" ) print(f"Created agent, agent ID: {agent.id}") @@ -79,7 +79,7 @@ with AIProjectClient.from_connection_string( with client: agent = client.beta.assistants.create( - model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent", tools=functions.definitions + model="gpt-4o-mini", name="my-agent", instructions="You are a helpful agent", tools=functions.definitions ) print(f"Created agent, agent ID: {agent.id}") @@ -170,7 +170,7 @@ with AIProjectClient.from_connection_string( with client: agent = client.beta.assistants.create( - model="gpt-4-1106-preview", name="my-agent", instructions="You are a helpful agent", tools=file_search.definitions, tool_resources=file_search.resources + model="gpt-4o-mini", name="my-agent", instructions="You are a helpful agent", tools=file_search.definitions, tool_resources=file_search.resources ) print(f"Created agent, agent ID: {agent.id}") From 6a4f466e48d138d6025074dbd978c1f54e0acd4e Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 14:06:17 -0800 Subject: [PATCH 092/180] updating links --- quickstart.md | 2 +- samples/bing-search/readme.md | 2 +- samples/code-interpreter/readme.md | 2 +- samples/file-search/readme.md | 2 +- samples/function-calling/readme.md | 2 +- samples/openapi/readme.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/quickstart.md b/quickstart.md index f54721fe..9f46c9ef 100644 --- a/quickstart.md +++ b/quickstart.md @@ -6,7 +6,7 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A 1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. -2. Make sure all developers have the role: **Azure AI Developer** assigned at the hub level. [Learn more](https://learn.microsoft.com/en-us/azure/ai-studio/concepts/rbac-ai-studio) +2. Make sure all developers have the role: **Azure AI Developer** assigned at the hub level. [Learn more](https://learn.microsoft.com/azure/ai-studio/concepts/rbac-ai-studio) 3. Check the [RBAC roles](./rbac.md). diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 41b19364..3f6ad6e4 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -59,4 +59,4 @@ Run the code samples below and view the output. >[!NOTE] > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. -* [Python](./python-sample.py) +* [Python](./bing-python.py) diff --git a/samples/code-interpreter/readme.md b/samples/code-interpreter/readme.md index c3abcd1b..28de2e01 100644 --- a/samples/code-interpreter/readme.md +++ b/samples/code-interpreter/readme.md @@ -10,7 +10,7 @@ Run the code samples below and view the output. >[!NOTE] > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. -* [Python](./python-sample.py) +* [Python](./python-code-interpreter.py) # Additional samples diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index f64d3a69..1ac73f99 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -11,7 +11,7 @@ Run the code samples below and view the output. >[!NOTE] > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. -* [Python](./python-sample.py) +* [Python](./python-file-search.py) ## Additional samples diff --git a/samples/function-calling/readme.md b/samples/function-calling/readme.md index 6184d763..e9e82eac 100644 --- a/samples/function-calling/readme.md +++ b/samples/function-calling/readme.md @@ -13,7 +13,7 @@ Run the code samples below and view the output. >[!NOTE] > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. -* [Python - function calling](./python-sample.py) +* [Python - function calling](./python-function-calling.py) * [Python - function calling with automatic tool calling](./python-function-calling-toolset.py) * [Python - function calling with streaming](./python-function-calling-streaming.py) diff --git a/samples/openapi/readme.md b/samples/openapi/readme.md index 1a6e00c7..19e5c91f 100644 --- a/samples/openapi/readme.md +++ b/samples/openapi/readme.md @@ -42,5 +42,5 @@ Run the code samples below and view the output. >[!NOTE] > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. -* [Python](./python-sample.py) +* [Python](./python-openapi.py) From b9b72950cd95541285675e05959979c5fbd8a9f3 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 14:27:36 -0800 Subject: [PATCH 093/180] region update --- quickstart.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quickstart.md b/quickstart.md index 9f46c9ef..b5ec8bb0 100644 --- a/quickstart.md +++ b/quickstart.md @@ -8,15 +8,15 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A 2. Make sure all developers have the role: **Azure AI Developer** assigned at the hub level. [Learn more](https://learn.microsoft.com/azure/ai-studio/concepts/rbac-ai-studio) -3. Check the [RBAC roles](./rbac.md). + If you're using a hub/project that already exists, check the [RBAC roles](./rbac.md). ## Setup your Azure AI Hub and Agent project The following section will show you how to set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground) by: -1. Creating an Azure AI Hub to set up your app environment and network HOBO resources +1. Creating an Azure AI Hub to set up your app environment and Azure resources -1. Creating an Azure AI project under your Hub to provides an endpoint for your app to call, and set up proxy app services to access to resources in your tenant. +1. Creating an Azure AI project under your Hub provisions an endpoint for your app to call, and sets up app services to access to resources in your tenant. 1. Connecting an Azure OpenAI resource or an Azure AI resource @@ -94,7 +94,7 @@ If you already have these resources set up, skip to the [configure and run your 6. Create an Azure OpenAI resource: > [!NOTE] - > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. + > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions that are compatible with Azure Assisants (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#assistants-preview)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. ```console az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location eastus --kind OpenAI --sku s0 From dd16d82d98532238d1214cbe9a924736bf6cfd27 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 15:09:36 -0800 Subject: [PATCH 094/180] connection string info --- quickstart.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index b5ec8bb0..25c2d523 100644 --- a/quickstart.md +++ b/quickstart.md @@ -48,6 +48,9 @@ If you already have these resources set up, skip to the [configure and run your ``` 1. To authenticate to your Azure subscription from the Azure CLI, use the following command: + > [!NOTE] + > Be sure to run these commands with the subscription that has been allowlisted for the private preview. + ```console az login ``` @@ -193,7 +196,19 @@ Use the following code to create an agent and send a message to it. This agent w pip install azure-identity ``` ### Create an Agent -Use the following code to create and run an agent. +Use the following code to create and run an agent. To run this code, you will need to create a connection string using information from your project. This string is in the format: + +`;;;` + +`HostName` can be found by navigating to your `discovery_url` and removing the leading `https://` and trailing `/discovery`. To find your `discovery_url`, run this CLI command: + +`az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url` + +For example, your connection string may look something like: + +`eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-hub-name` + +Set this connection string as an evironment variable named `PROJECT_CONNECTION_STRING`. > [!TIP] > Want to use the OpenAI SDK? You can find [examples of using the Azure AI Agent service with the OpenAI SDK](./samples/use-openai.md) in the samples folder of this repo. From 574409bef823a42c055b26f956f45f057a8cee79 Mon Sep 17 00:00:00 2001 From: Shruti <47434204+shrgupta773@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:43:56 -0800 Subject: [PATCH 095/180] Update bing-python.py --- samples/bing-search/bing-python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bing-search/bing-python.py b/samples/bing-search/bing-python.py index c9c2938b..934981e8 100644 --- a/samples/bing-search/bing-python.py +++ b/samples/bing-search/bing-python.py @@ -67,7 +67,7 @@ message = project_client.agents.create_message( thread_id=thread.id, role="user", - content="How does wikipedia explain Euler's Identity?", + content="How is the weather in Seattle today?", ) print(f"Created message, ID: {message.id}") From d17359ce5998a7d85771b7cbae107d2eaefee862 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 5 Nov 2024 15:50:41 -0800 Subject: [PATCH 096/180] updating .whl --- ...azure_ai_projects-1.0.0b1-py3-none-any.whl | Bin 167160 -> 167169 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl b/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl index e17d1733335c68d5149aaa8af28453174f683774..570a192d3463d3ef181749a013c86402106c6344 100644 GIT binary patch delta 27466 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 hM@9osk^Ym`T!Ae0b(SNMkFg{{ul4X3zit delta 27354 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
Sl^KRueGj5cx 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 Lr3iX|%Mkw$>d*ya From 1ab0bdaa4037238c97a7bdbb65292ffb326de181 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:15:31 -0800 Subject: [PATCH 097/180] Update readme.md --- samples/bing-search/readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 3f6ad6e4..151bd861 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -4,6 +4,8 @@ Grounding with Bing Search allows your Azure AI Agents to incorporate real-time Citations show links to websites used to generate response, but don’t show links to the bing query used for the search. Developers and end users don’t have access to raw content returned from Grounding with Bing Search. +You can ask questions such as "what is the weather in Seattle?" "what is the recent update in ratail industry in the US?" that require real-time public data. + > [!IMPORTANT] Grounding with Bing Search is a free service during private preview and your usage will start incurring cost since the integration with Azure AI Agent Service releases to public preview. From 84d918d2905763720c4f30815d18e0cd386487a4 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 5 Nov 2024 21:27:02 -0500 Subject: [PATCH 098/180] adding support for model customization in template --- modules-standard/standard-ai-hub.bicep | 5 ++- .../standard-dependent-resources.bicep | 32 +++++++++++++---- standard-agent.bicep | 27 ++++++++++++++ standard-agent.parameters.json | 36 +++++++++++++++++++ 4 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 standard-agent.parameters.json diff --git a/modules-standard/standard-ai-hub.bicep b/modules-standard/standard-ai-hub.bicep index 145f1012..d848c457 100644 --- a/modules-standard/standard-ai-hub.bicep +++ b/modules-standard/standard-ai-hub.bicep @@ -24,6 +24,9 @@ param aiServicesId string @description('Resource ID of the AI Services endpoint') param aiServicesTarget string +@description('Model/AI Resource deployment location') +param modelLocation string + resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { name: aiHubName location: location @@ -55,7 +58,7 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' metadata: { ApiType: 'Azure' ResourceId: aiServicesId - Location: location + Location: modelLocation } } } diff --git a/modules-standard/standard-dependent-resources.bicep b/modules-standard/standard-dependent-resources.bicep index 56e2f2f6..e048f685 100644 --- a/modules-standard/standard-dependent-resources.bicep +++ b/modules-standard/standard-dependent-resources.bicep @@ -7,10 +7,27 @@ param tags object = {} @description('AI services name') param aiServicesName string +@description('Model name for deployment') +param modelName string + +@description('Model format for deployment') +param modelFormat string + +@description('Model version for deployment') +param modelVersion string + +@description('Model deployment SKU name') +param modelSkuName string + +@description('Model deployment capacity') +param modelCapacity int + +@description('Model/AI Resource deployment location') +param modelLocation string resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { name: aiServicesName - location: 'eastus' + location: modelLocation sku: { name: 'S0' } @@ -26,18 +43,19 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = publicNetworkAccess: 'Enabled' } } + resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { parent: aiServices - name: 'gpt-4o-mini' + name: modelName sku : { - capacity: 1 - name: 'GlobalStandard' + capacity: modelCapacity + name: modelSkuName } properties: { model:{ - name: 'gpt-4o-mini' - format: 'OpenAI' - version: '2024-07-18' + name: modelName + format: modelFormat + version: modelVersion } } } diff --git a/standard-agent.bicep b/standard-agent.bicep index 19b282d5..16623e17 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -25,6 +25,24 @@ param location string = resourceGroup().location @description('Set of tags to apply to all resources.') param tags object = {} +@description('Model name for deployment') +param modelName string = 'gpt-4o-mini' + +@description('Model format for deployment') +param modelFormat string = 'OpenAI' + +@description('Model version for deployment') +param modelVersion string = '2024-07-18' + +@description('Model deployment SKU name') +param modelSkuName string = 'GlobalStandard' + +@description('Model deployment capacity') +param modelCapacity int = 10 + +@description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') +param modelLocation string = 'eastus' + // Variables var name = toLower('${aiHubName}') var projectName = toLower('${aiProjectName}') @@ -48,6 +66,14 @@ module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { storageName: '${storageName}${uniqueSuffix}' location: location tags: tags + + // Model deployment parameters + modelName: modelName + modelFormat: modelFormat + modelVersion: modelVersion + modelSkuName: modelSkuName + modelCapacity: modelCapacity + modelLocation: modelLocation } } @@ -62,6 +88,7 @@ module aiHub 'modules-standard/standard-ai-hub.bicep' = { tags: tags // dependent resources + modelLocation: modelLocation storageAccountId: aiDependencies.outputs.storageId aiServicesId: aiDependencies.outputs.aiservicesID aiServicesTarget: aiDependencies.outputs.aiservicesTarget diff --git a/standard-agent.parameters.json b/standard-agent.parameters.json new file mode 100644 index 00000000..bbd56445 --- /dev/null +++ b/standard-agent.parameters.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "aiHubName": { + "value": "standard-hub" + }, + "aiProjectName": { + "value": "standard-project" + }, + "modelName": { + "value": "gpt-4o-mini" + }, + "modelFormat": { + "value": "OpenAI" + }, + "modelVersion": { + "value": "2024-07-18" + }, + "modelSkuName": { + "value": "GlobalStandard" + }, + "modelCapacity": { + "value": 10 + }, + "modelLocation": { + "value": "eastus" + }, + "storageName": { + "value": "agent-storage" + }, + "aiServicesName": { + "value": "agent-ai-services" + } + } +} From 1487d33922b8a29e90b5f90387abb78fdf5fda74 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 6 Nov 2024 11:56:53 -0500 Subject: [PATCH 099/180] updating quickstart --- quickstart.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 83079e50..a384b852 100644 --- a/quickstart.md +++ b/quickstart.md @@ -72,7 +72,11 @@ If you already have these resources set up, skip to the [configure and run your ```console az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` - + - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: + ```console + az deployment group create --resource-group --template-file standard-agent.bicep --parameters @standard-agent.parameters.json + ``` + Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. If you prefer to deploy your own key vault, download the `main.bicep` file and `modules` folder and rerun the command, replacing `--template-file standard-agent.bicep` with `--template-file main.bicep.` From 67b1fbf67d6004cf4ed520366617cce3c2fbb0d5 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 6 Nov 2024 12:03:50 -0500 Subject: [PATCH 100/180] updating quickstart 2 --- quickstart.md | 1 + 1 file changed, 1 insertion(+) diff --git a/quickstart.md b/quickstart.md index a384b852..ec391a06 100644 --- a/quickstart.md +++ b/quickstart.md @@ -72,6 +72,7 @@ If you already have these resources set up, skip to the [configure and run your ```console az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` + - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: ```console az deployment group create --resource-group --template-file standard-agent.bicep --parameters @standard-agent.parameters.json From cdf3a090a9c610213ff28e204495b38bb229448c Mon Sep 17 00:00:00 2001 From: aahill Date: Wed, 6 Nov 2024 14:34:18 -0800 Subject: [PATCH 101/180] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 57e04784..1f780fe8 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,9 @@ See the QuickStart to [get started](./quickstart.md). * GitHub Issues (Preferred) * For other communications, please contact azureaiagents-preview@microsoft.com +## Feedback +Send us your feedback at: [https://aka.ms/azureagents-feedback](https://aka.ms/azureagents-feedback) + ## Contributing This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). From 64774c029668d5a0cc66e656cf40d42c702cf374 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Thu, 7 Nov 2024 17:26:45 -0500 Subject: [PATCH 102/180] byo agent setup template --- byo-agent.bicep | 100 ++++++++++++++++ modules-byo/byo-ai-hub.bicep | 107 +++++++++++++++++ modules-byo/byo-ai-project.bicep | 70 +++++++++++ modules-byo/byo-dependent-resources.bicep | 139 ++++++++++++++++++++++ 4 files changed, 416 insertions(+) create mode 100644 byo-agent.bicep create mode 100644 modules-byo/byo-ai-hub.bicep create mode 100644 modules-byo/byo-ai-project.bicep create mode 100644 modules-byo/byo-dependent-resources.bicep diff --git a/byo-agent.bicep b/byo-agent.bicep new file mode 100644 index 00000000..4e45b0ca --- /dev/null +++ b/byo-agent.bicep @@ -0,0 +1,100 @@ +// Execute this main file to depoy Azure AI studio resources in the basic security configuraiton + +// Parameters +@minLength(2) +@maxLength(12) +@description('Name for the AI resource and used to derive name of dependent resources.') +param aiHubName string = 'hub-demo' + +@description('Friendly name for your Hub resource') +param aiHubFriendlyName string = 'Agents Hub resource' + +@description('Description of your Azure AI resource dispayed in AI studio') +param aiHubDescription string = 'This is an example AI resource for use in Azure AI Studio.' + +@description('Name for the AI project resources.') +param aiProjectName string = 'project-demo' + +@description('Friendly name for your Azure AI resource') +param aiProjectFriendlyName string = 'Agents Project resource' + +@description('Description of your Azure AI resource dispayed in AI studio') +param aiProjectDescription string = 'This is an example AI Project resource for use in Azure AI Studio.' + +@description('Azure region used for the deployment of all resources.') +param location string = resourceGroup().location + +@description('Set of tags to apply to all resources.') +param tags object = {} + +@description('Name of the Azure AI Search account') +param aiSearchName string = 'agent-ai-search' + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +// Variables +var name = toLower('${aiHubName}') +var projectName = toLower('${aiProjectName}') + +// Create a short, unique suffix, that will be unique to each resource group +// var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) +param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') +var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) + + +// Dependent resources for the Azure Machine Learning workspace +module aiDependencies 'modules-byo/byo-dependent-resources.bicep' = { + name: 'dependencies-${name}-${uniqueSuffix}-deployment' + params: { + location: location + storageName: 'st${name}${uniqueSuffix}' + keyvaultName: 'kv-${name}-${uniqueSuffix}' + aiServicesName: 'ais${name}${uniqueSuffix}' + aiSearchName: '${aiSearchName}-${uniqueSuffix}' + tags: tags + } +} + +module aiHub 'modules-byo/byo-ai-hub.bicep' = { + name: 'ai-${name}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiHubName: 'ai-${name}-${uniqueSuffix}' + aiHubFriendlyName: aiHubFriendlyName + aiHubDescription: aiHubDescription + location: location + tags: tags + capabilityHostName: capabilityHostName + + + aiSearchName: aiDependencies.outputs.aiSearchName + aiSearchId: aiDependencies.outputs.aisearchID + aiServicesId: aiDependencies.outputs.aiservicesID + aiServicesTarget: aiDependencies.outputs.aiservicesTarget + keyVaultId: aiDependencies.outputs.keyvaultId + storageAccountId: aiDependencies.outputs.storageId + } +} + + +module aiProject 'modules-byo/byo-ai-project.bicep' = { + name: 'ai-${projectName}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiProjectName: 'ai-${projectName}-${uniqueSuffix}' + aiProjectFriendlyName: aiProjectFriendlyName + aiProjectDescription: aiProjectDescription + location: location + tags: tags + + capabilityHostName: capabilityHostName + // dependent resources + aiHubId: aiHub.outputs.aiHubID + acsConnectionName: aiHub.outputs.acsConnectionName + aoaiConnectionName: aiHub.outputs.aoaiConnectionName + } +} + +output ENTERPRISE_AGENTS_ENDPOINT string = aiProject.outputs.enterpriseAgentsEndpoint + diff --git a/modules-byo/byo-ai-hub.bicep b/modules-byo/byo-ai-hub.bicep new file mode 100644 index 00000000..cad04de3 --- /dev/null +++ b/modules-byo/byo-ai-hub.bicep @@ -0,0 +1,107 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI hub name') +param aiHubName string + +@description('AI hub display name') +param aiHubFriendlyName string = aiHubName + +@description('AI hub description') +param aiHubDescription string + +@description('Resource ID of the key vault resource for storing connection strings') +param keyVaultId string + +@description('Resource ID of the storage account resource for storing experimentation outputs') +param storageAccountId string + +@description('Resource ID of the AI Services resource') +param aiServicesId string + +@description('Resource ID of the AI Services endpoint') +param aiServicesTarget string + +@description('Name AI Search resource') +param aiSearchName string + +@description('Resource ID of the AI Search resource') +param aiSearchId string + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +var acsConnectionName = '${aiHubName}-connection-AISearch' + +var aoaiConnection = '${aiHubName}-connection-AIServices-aoai' + +resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { + name: aiHubName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiHubFriendlyName + description: aiHubDescription + + // dependent resources + keyVault: keyVaultId + storageAccount: storageAccountId + } + kind: 'hub' + + resource aiServicesConnection 'connections@2024-07-01-preview' = { + name: '${aiHubName}-connection-AIServices' + properties: { + category: 'AIServices' + target: aiServicesTarget + // useWorkspaceManagedIdentity: true + authType: 'ApiKey' + isSharedToAll: true + credentials: { + key: '${listKeys(aiServicesId, '2022-10-01').key1}' + } + metadata: { + ApiType: 'Azure' + ResourceId: aiServicesId + Location: location + } + } + } + resource hub_connection_azureai_search 'connections@2024-07-01-preview' = { + name: acsConnectionName + properties: { + category: 'CognitiveSearch' + target: 'https://${aiSearchName}.search.windows.net' + authType: 'AAD' + //useWorkspaceManagedIdentity: false + isSharedToAll: true + metadata: { + ApiType: 'Azure' + ResourceId: aiSearchId + location: location + } + } + } + + // Resource definition for the capability host + resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { + name: '${aiHubName}-${capabilityHostName}' + properties: { + capabilityHostKind: 'Agents' + } + } + +} + +output aiHubID string = aiHub.id +output aoaiConnectionName string = aoaiConnection +output acsConnectionName string = acsConnectionName diff --git a/modules-byo/byo-ai-project.bicep b/modules-byo/byo-ai-project.bicep new file mode 100644 index 00000000..77acc86c --- /dev/null +++ b/modules-byo/byo-ai-project.bicep @@ -0,0 +1,70 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI Project name') +param aiProjectName string + +@description('AI Project display name') +param aiProjectFriendlyName string = aiProjectName + +@description('AI Project description') +param aiProjectDescription string + +@description('Resource ID of the AI Hub resource') +param aiHubId string + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +@description('Name for ACS connection.') +param acsConnectionName string + +@description('Name for ACS connection.') +param aoaiConnectionName string + + +var storageConnections = ['${aiProjectName}/workspaceblobstore'] +var aiSearchConnection = ['${acsConnectionName}'] +var aiServiceConnections = ['${aoaiConnectionName}'] + + +resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { + name: aiProjectName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiProjectFriendlyName + description: aiProjectDescription + + // dependent resources + hubResourceId: aiHubId + + } + kind: 'project' + + // Resource definition for the capability host + resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { + name: '${aiProjectName}-${capabilityHostName}' + properties: { + capabilityHostKind: 'Agents' + aoaiConnections: aiServiceConnections + vectorStoreConnections: aiSearchConnection + storageConnections: storageConnections + } + } +} + +output aiProjectName string = aiProject.name +output aiProjectResourceId string = aiProject.id +output aiProjectWorkspaceId string = aiProject.properties.workspaceId + +output enterpriseAgentsEndpoint string = aiProject.tags.AgentsEndpointUri diff --git a/modules-byo/byo-dependent-resources.bicep b/modules-byo/byo-dependent-resources.bicep new file mode 100644 index 00000000..b7ea5554 --- /dev/null +++ b/modules-byo/byo-dependent-resources.bicep @@ -0,0 +1,139 @@ +// Creates Azure dependent resources for Azure AI studio + +@description('Azure region of the deployment') +param location string = resourceGroup().location + +@description('Tags to add to the resources') +param tags object = {} + +@description('AI services name') +param aiServicesName string + +@description('The name of the Key Vault') +param keyvaultName string + +@description('The name of the AI Search resource') +param aiSearchName string + +@description('Name of the storage account') +param storageName string + +var storageNameCleaned = replace(storageName, '-', '') + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyvaultName + location: location + tags: tags + properties: { + createMode: 'default' + enabledForDeployment: false + enabledForDiskEncryption: false + enabledForTemplateDeployment: false + enableSoftDelete: true + enableRbacAuthorization: true + enablePurgeProtection: true + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + sku: { + family: 'A' + name: 'standard' + } + softDeleteRetentionInDays: 7 + tenantId: subscription().tenantId + } +} + + +resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { + name: aiServicesName + location: 'eastus' + sku: { + name: 'S0' + } + kind: 'AIServices' // or 'OpenAI' + identity: { + type: 'SystemAssigned' + } + properties: { + customSubDomainName: toLower('${(aiServicesName)}') + apiProperties: { + statisticsEnabled: false + } + publicNetworkAccess: 'Enabled' + } +} +resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { + parent: aiServices + name: 'gpt-4o-mini' + sku : { + capacity: 10 + name: 'GlobalStandard' + } + properties: { + model:{ + name: 'gpt-4o-mini' + format: 'OpenAI' + version: '2024-07-18' + } + } +} + +resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = { + name: aiSearchName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + disableLocalAuth: false + authOptions: { aadOrApiKey: { aadAuthFailureMode: 'http401WithBearerChallenge'}} + encryptionWithCmk: { + enforcement: 'Unspecified' + } + hostingMode: 'default' + partitionCount: 3 + publicNetworkAccess: 'enabled' + replicaCount: 3 + semanticSearch: 'disabled' + } + sku: { + name: 'standard' + } +} + +// Some regions doesn't support Standard Zone-Redundant storage, need to use Geo-redundant storage +param noZRSRegions array = ['southindia', 'westus'] +param sku object = contains(noZRSRegions, location) ? { name: 'Standard_GRS' } : { name: 'Standard_ZRS' } + +resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = { + name: storageNameCleaned + location: location + kind: 'StorageV2' + sku: sku + properties: { + minimumTlsVersion: 'TLS1_2' + allowBlobPublicAccess: false + publicNetworkAccess: 'Enabled' + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Allow' + virtualNetworkRules: [] + } + allowSharedKeyAccess: false + } +} + +output aiServicesName string = aiServices.name +output aiservicesID string = aiServices.id +output aiservicesTarget string = aiServices.properties.endpoint + +output aiSearchName string = aiSearch.name +output aisearchID string = aiSearch.id + +output storageAccountName string = storage.name +output storageId string = storage.id + +output keyvaultId string = keyVault.id From 6b3aecf8c4ffa0e17169b9dd223a4b8ac80a6268 Mon Sep 17 00:00:00 2001 From: Shu Peng Date: Thu, 7 Nov 2024 16:45:41 -0800 Subject: [PATCH 103/180] Using project name in connection string; spelling fix; formatting --- quickstart.md | 315 +++++++++++++++++++++++++------------------------- 1 file changed, 160 insertions(+), 155 deletions(-) diff --git a/quickstart.md b/quickstart.md index 6488af4a..ccce07e4 100644 --- a/quickstart.md +++ b/quickstart.md @@ -1,222 +1,226 @@ -# AI Agents Quick Start +# AI Agents Quick Start -This QuickStart demonstrates how to quickly set up your first agent with Azure AI Agent Service. - -## Complete Azure prerequisites +This QuickStart demonstrates how to quickly set up your first agent with Azure AI Agent Service. -1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. +## Complete Azure prerequisites + +1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. 2. Make sure all developers have the role: **Azure AI Developer** assigned at the hub level. [Learn more](https://learn.microsoft.com/azure/ai-studio/concepts/rbac-ai-studio) - If you're using a hub/project that already exists, check the [RBAC roles](./rbac.md). + If you're using a hub/project that already exists, check the [RBAC roles](./rbac.md). -## Setup your Azure AI Hub and Agent project +## Setup your Azure AI Hub and Agent project -The following section will show you how to set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground) by: +The following section will show you how to set up an [Azure AI hub and project](https://learn.microsoft.com/azure/ai-studio/quickstarts/get-started-playground) by: -1. Creating an Azure AI Hub to set up your app environment and Azure resources +1. Creating an Azure AI Hub to set up your app environment and Azure resources -1. Creating an Azure AI project under your Hub provisions an endpoint for your app to call, and sets up app services to access to resources in your tenant. +1. Creating an Azure AI project under your Hub provisions an endpoint for your app to call, and sets up app services to access to resources in your tenant. -1. Connecting an Azure OpenAI resource or an Azure AI resource +1. Connecting an Azure OpenAI resource or an Azure AI resource If you already have these resources set up, skip to the [configure and run your first agent section below](#configure-and-run-your-first-agent). -### Follow these steps to set up hub and project: +### Follow these steps to set up hub and project: 1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). If you have the CLI already installed, make sure it's updated to the latest version. -1. Register a provider. +1. Register a provider. - The following providers must be registered: - - Microsoft.KeyVault - - Microsoft.CognitiveServices - - Microsoft.Storage - - Microsoft.MachineLearningServices - - Microsoft.Search - - ```console - az provider register –namespace {my_resource_namespace} - - [--accept-terms] - - [--consent-to-permissions] - - [--management-group-id] - - [--wait] - ``` -1. To authenticate to your Azure subscription from the Azure CLI, use the following command: + The following providers must be registered: - > [!NOTE] - > Be sure to run these commands with the subscription that has been allowlisted for the private preview. + - Microsoft.KeyVault + - Microsoft.CognitiveServices + - Microsoft.Storage + - Microsoft.MachineLearningServices + - Microsoft.Search - ```console - az login - ``` -2. Create a resource group: + ```console + az provider register –namespace {my_resource_namespace} + [--accept-terms] + [--consent-to-permissions] + [--management-group-id] + [--wait] + ``` - ```console - az group create --name {my_resource_group} --location eastus - ``` +1. To authenticate to your Azure subscription from the Azure CLI, use the following command: + + > [!NOTE] + > Be sure to run these commands with the subscription that has been allowlisted for the private preview. -3.
+ ```console + az login + ``` + +1. Create a resource group: + + ```console + az group create --name {my_resource_group} --location eastus + ``` + +1.
**Option 1**: Use the standard agent configuration. + - Download the `standard-agent.bicep` file and the `modules-standard` folder to your project directory. Your directory should look like this + ```console + /my-project + - standard-agent.bicep + /modules-standard + - standard-ai-hub.bicep + - standard-ai-project.bicep + - standard-dependent-resources.bicep + ``` + +- Using the resource group you created in the previous step, run one of the following commands: + + - To use default resource names, run: + + ```console + az deployment group create --resource-group --template-file standard-agent.bicep ``` - /my-project - - standard-agent.bicep - /modules-standard - - standard-ai-hub.bicep - - standard-ai-project.bicep - - standard-dependent-resources.bicep + + - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: + + ```console + az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` -- Using the resource group you created in the previous step, run one of the following commands: - - To use default resource names, run: - - ```console - az deployment group create --resource-group --template-file standard-agent.bicep - ``` - - - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: - ```console - az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' - ``` - - - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: - ```console - az deployment group create --resource-group --template-file standard-agent.bicep --parameters @standard-agent.parameters.json - ``` - - Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. + - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: + ```console + az deployment group create --resource-group --template-file standard-agent.bicep --parameters @standard-agent.parameters.json + ``` + + Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default.

Option 2: Follow steps 6-10 if you want specific control over the creation and configuration of these resources. -6. Create an Azure OpenAI resource: +6. Create an Azure OpenAI resource: - > [!NOTE] - > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions that are compatible with Azure Assisants (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#assistants-preview)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. + > [!NOTE] + > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions that are compatible with Azure Assisants (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#assistants-preview)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. - ```console - az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location eastus --kind OpenAI --sku s0 - ``` - + ```console + az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location eastus --kind OpenAI --sku s0 + ``` - Alternatively, you can create an AI Services resource: - - ```console - az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location eastus - ``` - + Alternatively, you can create an AI Services resource: - Save the id that gets output, you’ll need it later. It will look similar to: `https://eastus.api.cognitive.microsoft.com/ai_services_resource_id: /subscriptions/1234-5678-abcd-9fc6-62780b3d3e05/resourceGroups/my-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource` + ```console + az cognitiveservices account create --name {my-multi-service-resource} --resource-group {my_resource_group} --kind AIServices --sku s0 --location eastus + ``` -1. Create an Azure AI Hub. + Save the id that gets output, you’ll need it later. It will look similar to: `https://eastus.api.cognitive.microsoft.com/ai_services_resource_id: /subscriptions/1234-5678-abcd-9fc6-62780b3d3e05/resourceGroups/my-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource` - > [!NOTE] the following command auto creates a storage account, AML workspace and Key Vault. +1. Create an Azure AI Hub. - ```console - az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} - ``` + > [!NOTE] the following command auto creates a storage account, AML workspace and Key Vault. - OR + ```console + az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} + ``` - Optional: If you want to connect an existing storage account and/or key vault you can specify them here: + OR - ```console - az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} --location {hub-region} --storage-account {my_storage_account_id} --key-vault {my_key_vault_id} - ``` - -1. Connect your Hub to your Azure AI resource or Azure OpenAI resource. Replace the resource group and hub name with your resource and hub name. + Optional: If you want to connect an existing storage account and/or key vault you can specify them here: - - Save the following in a file named `connection.yml`. + ```console + az ml workspace create --kind hub --resource-group {my_resource_group} --name {my_hub_name} --location {hub-region} --storage-account {my_storage_account_id} --key-vault {my_key_vault_id} + ``` - - If using an AI Services resource, use the following and replace ai_services_resource_id with the fully qualified ID from earlier. +1. Connect your Hub to your Azure AI resource or Azure OpenAI resource. Replace the resource group and hub name with your resource and hub name. - ```yml - name: myazai_connection - type: azure_ai_services - endpoint: https://eastus.api.cognitive.microsoft.com/ - ai_services_resource_id: /subscriptions/12345678-abcd-1234-9fc6-62780b3d3e05/resourceGroups/my-ai-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource - ``` + - Save the following in a file named `connection.yml`. - - If using an Azure OpenAI resource, create the following `connection.yml` file: - ```yml - name: {my_connection_name} - type: azure_open_ai - azure_endpoint: https://eastus.api.cognitive.microsoft.com/ - ``` - + - If using an AI Services resource, use the following and replace ai_services_resource_id with the fully qualified ID from earlier. -1. Then run the following command: + ```yml + name: myazai_connection + type: azure_ai_services + endpoint: https://eastus.api.cognitive.microsoft.com/ + ai_services_resource_id: /subscriptions/12345678-abcd-1234-9fc6-62780b3d3e05/resourceGroups/my-ai-resource-group/providers/Microsoft.CognitiveServices/accounts/multi-service-resource + ``` - ```console - az ml connection create --file connection.yml --resource-group {my_resource_group} --workspace-name {my_hub_name} - ``` + - If using an Azure OpenAI resource, create the following `connection.yml` file: -1. Create a Project. - - Run the following command to find your ARM ID: + ```yml + name: { my_connection_name } + type: azure_open_ai + azure_endpoint: https://eastus.api.cognitive.microsoft.com/ + ``` - ```console - az ml workspace show -n {my_hub_name} --resource-group {my_resource_group} --query id - ``` +1. Then run the following command: - - Now run this command to create your project + ```console + az ml connection create --file connection.yml --resource-group {my_resource_group} --workspace-name {my_hub_name} + ``` - ```console - az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} - ``` -
+1. Create a Project. -## Configure and run your first agent + - Run the following command to find your ARM ID: + + ```console + az ml workspace show -n {my_hub_name} --resource-group {my_resource_group} --query id + ``` + + - Now run this command to create your project + + ```console + az ml workspace create --kind project --hub-id {my_hub_ARM_ID} --resource-group {my_resource_group} --name {my_project_name} + ``` + + +## Configure and run your first agent -| Component | Description | -|---|---| -| Agent | Custom AI that uses AI models in conjunction with tools. | -| Tool | Tools help extend an agent’s ability to reliably and accurately respond during conversation. Such as connecting to user-defined knowledge bases to ground the model, or enabling web search to provide current information. | -| Thread | A conversation session between an agent and a user. Threads store Messages and automatically handle truncation to fit content into a model’s context. | -| Message | A message created by an agent or a user. Messages can include text, images, and other files. Messages are stored as a list on the Thread. | -| Run | Activation of an agent to begin running based on the contents of Thread. The agent uses its configuration and Thread’s Messages to perform tasks by calling models and tools. As part of a Run, the agent appends Messages to the Thread. -| Run Step | A detailed list of steps the agent took as part of a Run. An agent can call tools or create Messages during its run. Examining Run Steps allows you to understand how the agent is getting to its results. | +| Component | Description | +| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Agent | Custom AI that uses AI models in conjunction with tools. | +| Tool | Tools help extend an agent’s ability to reliably and accurately respond during conversation. Such as connecting to user-defined knowledge bases to ground the model, or enabling web search to provide current information. | +| Thread | A conversation session between an agent and a user. Threads store Messages and automatically handle truncation to fit content into a model’s context. | +| Message | A message created by an agent or a user. Messages can include text, images, and other files. Messages are stored as a list on the Thread. | +| Run | Activation of an agent to begin running based on the contents of Thread. The agent uses its configuration and Thread’s Messages to perform tasks by calling models and tools. As part of a Run, the agent appends Messages to the Thread. | +| Run Step | A detailed list of steps the agent took as part of a Run. An agent can call tools or create Messages during its run. Examining Run Steps allows you to understand how the agent is getting to its results. | -Use the following code to create an agent and send a message to it. This agent will have the code interpreter tool to enable your agent to perform advanced data analysis in a sandboxed environment. +Use the following code to create an agent and send a message to it. This agent will have the code interpreter tool to enable your agent to perform advanced data analysis in a sandboxed environment. ## Python SDK ### Setup + 1. Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. -2. Run the following commands to install the python packages. +2. Run the following commands to install the python packages. + + ```console + pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall + pip install azure-identity + ``` - ```console - pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall - pip install azure-identity - ``` ### Create an Agent -Use the following code to create and run an agent. To run this code, you will need to create a connection string using information from your project. This string is in the format: -`;;;` +Use the following code to create and run an agent. To run this code, you will need to create a connection string using information from your project. This string is in the format: + +`;;;` -`HostName` can be found by navigating to your `discovery_url` and removing the leading `https://` and trailing `/discovery`. To find your `discovery_url`, run this CLI command: +`HostName` can be found by navigating to your `discovery_url` and removing the leading `https://` and trailing `/discovery`. To find your `discovery_url`, run this CLI command: `az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url` For example, your connection string may look something like: -`eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-hub-name` +`eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-project-name` -Set this connection string as an evironment variable named `PROJECT_CONNECTION_STRING`. +Set this connection string as an environment variable named `PROJECT_CONNECTION_STRING`. > [!TIP] -> Want to use the OpenAI SDK? You can find [examples of using the Azure AI Agent service with the OpenAI SDK](./samples/use-openai.md) in the samples folder of this repo. +> Want to use the OpenAI SDK? You can find [examples of using the Azure AI Agent service with the OpenAI SDK](./samples/use-openai.md) in the samples folder of this repo. ```python import os @@ -227,10 +231,10 @@ from typing import Any from pathlib import Path # Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# HostName can be found by navigating to your discovery_url and removing the leading "https://" and trailing "/discovery" +# At the moment, it should be in the format ";;;" +# HostName can be found by navigating to your discovery_url and removing the leading "https://" and trailing "/discovery" # To find your discovery_url, run the CLI command: az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url -# Project Connection example: eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-hub-name +# Project Connection example: eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-project-name # Customer needs to login to Azure subscription via Azure CLI and set the environment variables project_client = AIProjectClient.from_connection_string( @@ -240,8 +244,8 @@ project_client = AIProjectClient.from_connection_string( with project_client: # Create an instance of the CodeInterpreterTool code_interpreter = CodeInterpreterTool() - - # The CodeInterpeterTool needs to be included in creation of the agent + + # The CodeInterpreterTool needs to be included in creation of the agent agent = project_client.agents.create_agent( model="gpt-4o-mini", name="my-assistant", @@ -250,11 +254,11 @@ with project_client: tool_resources=code_interpreter.resources, ) print(f"Created agent, agent ID: {agent.id}") - + # Create a thread thread = project_client.agents.create_thread() print(f"Created thread, thread ID: {thread.id}") - + # Create a message message = project_client.agents.create_message( thread_id=thread.id, @@ -262,31 +266,31 @@ with project_client: content="Could you please create a bar chart for the operating profit using the following data and provide the file to me? Company A: $1.2 million, Company B: $2.5 million, Company C: $3.0 million, Company D: $1.8 million", ) print(f"Created message, message ID: {message.id}") - + # Run the agent run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) print(f"Run finished with status: {run.status}") - + if run.status == "failed": # Check if you got "Rate limit is exceeded.", then you want to get more quota print(f"Run failed: {run.last_error}") - # Get messages from the thread + # Get messages from the thread messages = project_client.agents.get_messages(thread_id=thread.id) print(f"Messages: {messages}") - + # Get the last message from the sender last_msg = messages.get_last_text_message_by_sender("assistant") if last_msg: print(f"Last Message: {last_msg.text.value}") - + # Generate an image file for the bar chart for image_content in messages.image_contents: print(f"Image File ID: {image_content.image_file.file_id}") file_name = f"{image_content.image_file.file_id}_image_file.png" project_client.agents.save_file(file_id=image_content.image_file.file_id, file_name=file_name) print(f"Saved image file to: {Path.cwd() / file_name}") - + # Print the file path(s) from the messages for file_path_annotation in messages.file_path_annotations: print(f"File Paths:") @@ -303,4 +307,5 @@ with project_client: ``` ## C# + C# support coming soon! From 926d3ee4b49e9d9176b1ec9c66fac1218252b384 Mon Sep 17 00:00:00 2001 From: Shu Peng Date: Thu, 7 Nov 2024 17:37:57 -0800 Subject: [PATCH 104/180] Address review feedbacks --- quickstart.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quickstart.md b/quickstart.md index ccce07e4..fbba31f0 100644 --- a/quickstart.md +++ b/quickstart.md @@ -26,7 +26,7 @@ If you already have these resources set up, skip to the [configure and run your 1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). If you have the CLI already installed, make sure it's updated to the latest version. -1. Register a provider. +1. Register providers. The following providers must be registered: @@ -79,19 +79,19 @@ If you already have these resources set up, skip to the [configure and run your - To use default resource names, run: ```console - az deployment group create --resource-group --template-file standard-agent.bicep + az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep ``` - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: ```console - az deployment group create --resource-group --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' + az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: ```console - az deployment group create --resource-group --template-file standard-agent.bicep --parameters @standard-agent.parameters.json + az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters @standard-agent.parameters.json ``` Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. From 992a1bae04f210c3fdc5abd99bd39e9f8f13a14b Mon Sep 17 00:00:00 2001 From: Shu Peng Date: Thu, 7 Nov 2024 17:43:11 -0800 Subject: [PATCH 105/180] Spelling fix. --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index fbba31f0..1e87306b 100644 --- a/quickstart.md +++ b/quickstart.md @@ -22,7 +22,7 @@ The following section will show you how to set up an [Azure AI hub and project]( If you already have these resources set up, skip to the [configure and run your first agent section below](#configure-and-run-your-first-agent). -### Follow these steps to set up hub and project: +### Follow these steps to set up hub and project 1. Install [the Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli-windows?tabs=azure-cli). If you have the CLI already installed, make sure it's updated to the latest version. @@ -104,7 +104,7 @@ If you already have these resources set up, skip to the [configure and run your 6. Create an Azure OpenAI resource: > [!NOTE] - > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions that are compatible with Azure Assisants (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#assistants-preview)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. + > Azure AI Agent Service is currently available for all OpenAI models in available Azure Regions that are compatible with Azure Assistants (see the [models guide](https://learn.microsoft.com/azure/ai-services/openai/concepts/models#assistants-preview)) and Llama 3.1-405B-instruct. We will be expanding to more models in the future. ```console az cognitiveservices account create --name {MyOpenAIResource} --resource-group {my_resource_group} --location eastus --kind OpenAI --sku s0 From 8d0b7b915b63b134d70de0dffe5aa1601a3cca00 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Fri, 8 Nov 2024 10:50:32 -0500 Subject: [PATCH 106/180] standard agent setup with managed identity --- .../standard-ai-hub-identity.bicep | 116 ++++++++++++++++++ .../standard-ai-project-identity.bicep | 40 ++++++ standard-agent-identity.bicep | 115 +++++++++++++++++ standard-agent.bicep | 2 + 4 files changed, 273 insertions(+) create mode 100644 modules-standard/standard-ai-hub-identity.bicep create mode 100644 modules-standard/standard-ai-project-identity.bicep create mode 100644 standard-agent-identity.bicep diff --git a/modules-standard/standard-ai-hub-identity.bicep b/modules-standard/standard-ai-hub-identity.bicep new file mode 100644 index 00000000..e8c99a4e --- /dev/null +++ b/modules-standard/standard-ai-hub-identity.bicep @@ -0,0 +1,116 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI hub name') +param aiHubName string + +@description('AI hub display name') +param aiHubFriendlyName string = aiHubName + +@description('AI hub description') +param aiHubDescription string + +@description('Resource ID of the storage account resource for storing experimentation outputs') +param storageAccountId string + +@description('Resource ID of the AI Services resource') +param aiServicesId string + +param aiServicesName string + +@description('Resource ID of the AI Services endpoint') +param aiServicesTarget string + +@description('Model/AI Resource deployment location') +param modelLocation string + +resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { + name: aiServicesName +} + +resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { + name: aiHubName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiHubFriendlyName + description: aiHubDescription + + // dependent resources + storageAccount: storageAccountId + } + kind: 'hub' + + resource aiServicesConnection 'connections@2024-07-01-preview' = { + name: '${aiHubName}-connection-AIServices' + properties: { + category: 'AIServices' + target: aiServicesTarget + authType: 'AAD' + isSharedToAll: true + metadata: { + ApiType: 'Azure' + ResourceId: aiServicesId + Location: modelLocation + } + } + } + +} + +resource cognitiveServicesContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + scope: resourceGroup() +} + +resource cognitiveServicesContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01'= { + scope: aiServices + name: guid(aiServices.id, cognitiveServicesContributorRole.id, aiHub.id) + properties: { + principalId: aiHub.identity.principalId + roleDefinitionId: cognitiveServicesContributorRole.id + principalType: 'ServicePrincipal' + } + } + + +resource cognitiveServicesOpenAIUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + scope: resourceGroup() +} +resource cognitiveServicesOpenAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiHub.id, cognitiveServicesOpenAIUserRole.id, aiServices.id) + properties: { + principalId: aiHub.identity.principalId + roleDefinitionId: cognitiveServicesOpenAIUserRole.id + principalType: 'ServicePrincipal' + } +} + +resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: 'a97b65f3-24c7-4388-baec-2e87135dc908' + scope: resourceGroup() +} + +resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiHub.id, cognitiveServicesUserRole.id, aiServices.id) + properties: { + principalId: aiHub.identity.principalId + roleDefinitionId: cognitiveServicesUserRole.id + principalType: 'ServicePrincipal' + } +} + + +output aiHubID string = aiHub.id diff --git a/modules-standard/standard-ai-project-identity.bicep b/modules-standard/standard-ai-project-identity.bicep new file mode 100644 index 00000000..20be4570 --- /dev/null +++ b/modules-standard/standard-ai-project-identity.bicep @@ -0,0 +1,40 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI Project name') +param aiProjectName string + +@description('AI Project display name') +param aiProjectFriendlyName string = aiProjectName + +@description('AI Project description') +param aiProjectDescription string + +@description('Resource ID of the AI Hub resource') +param aiHubId string + +resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { + name: aiProjectName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiProjectFriendlyName + description: aiProjectDescription + + // dependent resources + hubResourceId: aiHubId + + } + kind: 'project' +} + +output aiProjectID string = aiProject.id diff --git a/standard-agent-identity.bicep b/standard-agent-identity.bicep new file mode 100644 index 00000000..5845c83b --- /dev/null +++ b/standard-agent-identity.bicep @@ -0,0 +1,115 @@ +// Execute this main file to depoy Azure AI studio resources in the basic security configuraiton + +// Parameters +@minLength(2) +@maxLength(12) +@description('Name for the AI resource and used to derive name of dependent resources.') +param aiHubName string = 'standard-hub' + +@description('Friendly name for your Azure AI resource') +param aiHubFriendlyName string = 'Agents standard hub resource' + +@description('Description of your Azure AI resource dispayed in AI studio') +param aiHubDescription string = 'A standard hub resource required for the agent setup.' + +@description('Name for the project') +param aiProjectName string = 'standard-project' + +@description('Friendly name for your Azure AI project resource') +param aiProjectFriendlyName string = 'Agents standard project resource' + +@description('Description of your Azure AI project resource dispayed in AI studio') +param aiProjectDescription string = 'A standard project resource required for the agent setup.' + +@description('Azure region used for the deployment of all resources.') +param location string = resourceGroup().location + +@description('Set of tags to apply to all resources.') +param tags object = {} + +// Variables +var name = toLower('${aiHubName}') +var projectName = toLower('${aiProjectName}') + +@description('Name of the storage account') +param storageName string = 'agent-storage' + +@description('Name of the Azure AI Services account') +param aiServicesName string = 'agent-ai-services' + +@description('Model name for deployment') +param modelName string = 'gpt-4o-mini' + +@description('Model format for deployment') +param modelFormat string = 'OpenAI' + +@description('Model version for deployment') +param modelVersion string = '2024-07-18' + +@description('Model deployment SKU name') +param modelSkuName string = 'GlobalStandard' + +@description('Model deployment capacity') +param modelCapacity int = 10 + +@description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') +param modelLocation string = 'eastus' + + +// Create a short, unique suffix, that will be unique to each resource group +// var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) +param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') +var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) + +// Dependent resources for the Azure Machine Learning workspace +module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { + name: 'dependencies-${name}-${uniqueSuffix}-deployment' + params: { + aiServicesName: '${aiServicesName}${uniqueSuffix}' + storageName: '${storageName}${uniqueSuffix}' + location: location + tags: tags + + // Model deployment parameters + modelName: modelName + modelFormat: modelFormat + modelVersion: modelVersion + modelSkuName: modelSkuName + modelCapacity: modelCapacity + modelLocation: modelLocation + } +} + +module aiHub 'modules-standard/standard-ai-hub-identity.bicep' = { + name: '${name}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiHubName: 'ai-${name}-${uniqueSuffix}' + aiHubFriendlyName: aiHubFriendlyName + aiHubDescription: aiHubDescription + location: location + tags: tags + + // dependent resources + modelLocation: modelLocation + aiServicesName: '${aiServicesName}${uniqueSuffix}' + storageAccountId: aiDependencies.outputs.storageId + aiServicesId: aiDependencies.outputs.aiservicesID + aiServicesTarget: aiDependencies.outputs.aiservicesTarget + } +} + +module aiProject 'modules-standard/standard-ai-project-identity.bicep' = { + name: 'ai-${projectName}-${uniqueSuffix}-deployment' + params: { + // workspace organization + aiProjectName: 'ai-${projectName}-${uniqueSuffix}' + aiProjectFriendlyName: aiProjectFriendlyName + aiProjectDescription: aiProjectDescription + location: location + tags: tags + + // dependent resources + aiHubId: aiHub.outputs.aiHubID + } +} diff --git a/standard-agent.bicep b/standard-agent.bicep index 16623e17..11568f8f 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -11,6 +11,8 @@ param aiHubFriendlyName string = 'Agents standard hub resource' @description('Description of your Azure AI resource dispayed in AI studio') param aiHubDescription string = 'A standard hub resource required for the agent setup.' + +@description('Name for the project') param aiProjectName string = 'standard-project' @description('Friendly name for your Azure AI resource') From 764d3bc9a003be99f4b2132299a7964281aa3656 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Fri, 8 Nov 2024 10:59:29 -0500 Subject: [PATCH 107/180] fixing comments --- standard-agent-identity.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard-agent-identity.bicep b/standard-agent-identity.bicep index 5845c83b..64a0225f 100644 --- a/standard-agent-identity.bicep +++ b/standard-agent-identity.bicep @@ -1,4 +1,4 @@ -// Execute this main file to depoy Azure AI studio resources in the basic security configuraiton +// Execute this main file to depoy Azure AI studio resources in the standard agent configuraiton wit Managed Identity // Parameters @minLength(2) From 11304feaf6ed8ab5105415505e3641ca56d8892c Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 11 Nov 2024 14:21:14 -0500 Subject: [PATCH 108/180] updating agent setups --- byo-agent.bicep | 41 ++++++++++++-- modules-byo/byo-ai-hub.bicep | 13 +++-- modules-byo/byo-ai-project.bicep | 53 ++++++++++++++++++- modules-byo/byo-dependent-resources.bicep | 32 ++++++++--- .../standard-ai-hub-identity.bicep | 50 ----------------- .../standard-ai-project-identity.bicep | 51 ++++++++++++++++++ standard-agent-identity.bicep | 24 ++++----- standard-agent.bicep | 2 +- 8 files changed, 185 insertions(+), 81 deletions(-) diff --git a/byo-agent.bicep b/byo-agent.bicep index 4e45b0ca..ac466d87 100644 --- a/byo-agent.bicep +++ b/byo-agent.bicep @@ -33,6 +33,31 @@ param aiSearchName string = 'agent-ai-search' @description('Name for capabilityHost.') param capabilityHostName string = 'caphost1' +@description('Name of the storage account') +param storageName string = 'agent-storage' + +@description('Name of the Azure AI Services account') +param aiServicesName string = 'agent-ai-services' + +@description('Model name for deployment') +param modelName string = 'gpt-4o-mini' + +@description('Model format for deployment') +param modelFormat string = 'OpenAI' + +@description('Model version for deployment') +param modelVersion string = '2024-07-18' + +@description('Model deployment SKU name') +param modelSkuName string = 'GlobalStandard' + +@description('Model deployment capacity') +param modelCapacity int = 10 + +@description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') +param modelLocation string = 'eastus' + + // Variables var name = toLower('${aiHubName}') var projectName = toLower('${aiProjectName}') @@ -48,12 +73,20 @@ module aiDependencies 'modules-byo/byo-dependent-resources.bicep' = { name: 'dependencies-${name}-${uniqueSuffix}-deployment' params: { location: location - storageName: 'st${name}${uniqueSuffix}' + storageName: '${storageName}${uniqueSuffix}' keyvaultName: 'kv-${name}-${uniqueSuffix}' - aiServicesName: 'ais${name}${uniqueSuffix}' + aiServicesName: '${aiServicesName}${uniqueSuffix}' aiSearchName: '${aiSearchName}-${uniqueSuffix}' tags: tags - } + + // Model deployment parameters + modelName: modelName + modelFormat: modelFormat + modelVersion: modelVersion + modelSkuName: modelSkuName + modelCapacity: modelCapacity + modelLocation: modelLocation + } } module aiHub 'modules-byo/byo-ai-hub.bicep' = { @@ -66,6 +99,7 @@ module aiHub 'modules-byo/byo-ai-hub.bicep' = { location: location tags: tags capabilityHostName: capabilityHostName + modelLocation: modelLocation aiSearchName: aiDependencies.outputs.aiSearchName @@ -90,6 +124,7 @@ module aiProject 'modules-byo/byo-ai-project.bicep' = { capabilityHostName: capabilityHostName // dependent resources + aiServicesName: '${aiServicesName}${uniqueSuffix}' aiHubId: aiHub.outputs.aiHubID acsConnectionName: aiHub.outputs.acsConnectionName aoaiConnectionName: aiHub.outputs.aoaiConnectionName diff --git a/modules-byo/byo-ai-hub.bicep b/modules-byo/byo-ai-hub.bicep index cad04de3..e41596a9 100644 --- a/modules-byo/byo-ai-hub.bicep +++ b/modules-byo/byo-ai-hub.bicep @@ -21,6 +21,9 @@ param keyVaultId string @description('Resource ID of the storage account resource for storing experimentation outputs') param storageAccountId string +@description('Model/AI Resource deployment location') +param modelLocation string + @description('Resource ID of the AI Services resource') param aiServicesId string @@ -38,7 +41,7 @@ param capabilityHostName string = 'caphost1' var acsConnectionName = '${aiHubName}-connection-AISearch' -var aoaiConnection = '${aiHubName}-connection-AIServices-aoai' +var aoaiConnection = '${aiHubName}-connection-AIServices_aoai' resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { name: aiHubName @@ -63,16 +66,12 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' properties: { category: 'AIServices' target: aiServicesTarget - // useWorkspaceManagedIdentity: true - authType: 'ApiKey' + authType: 'AAD' isSharedToAll: true - credentials: { - key: '${listKeys(aiServicesId, '2022-10-01').key1}' - } metadata: { ApiType: 'Azure' ResourceId: aiServicesId - Location: location + Location: modelLocation } } } diff --git a/modules-byo/byo-ai-project.bicep b/modules-byo/byo-ai-project.bicep index 77acc86c..3d911cc8 100644 --- a/modules-byo/byo-ai-project.bicep +++ b/modules-byo/byo-ai-project.bicep @@ -27,6 +27,12 @@ param acsConnectionName string @description('Name for ACS connection.') param aoaiConnectionName string +param aiServicesName string + +resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { + name: aiServicesName +} + var storageConnections = ['${aiProjectName}/workspaceblobstore'] var aiSearchConnection = ['${acsConnectionName}'] @@ -56,13 +62,58 @@ resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-prev name: '${aiProjectName}-${capabilityHostName}' properties: { capabilityHostKind: 'Agents' - aoaiConnections: aiServiceConnections + aiServicesConnections: aiServiceConnections vectorStoreConnections: aiSearchConnection storageConnections: storageConnections } } } +resource cognitiveServicesContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + scope: resourceGroup() +} + +resource cognitiveServicesContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01'= { + scope: aiServices + name: guid(aiServices.id, cognitiveServicesContributorRole.id, aiProject.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesContributorRole.id + principalType: 'ServicePrincipal' + } + } + + +resource cognitiveServicesOpenAIUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + scope: resourceGroup() +} +resource cognitiveServicesOpenAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProject.id, cognitiveServicesOpenAIUserRole.id, aiServices.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesOpenAIUserRole.id + principalType: 'ServicePrincipal' + } +} + +resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: 'a97b65f3-24c7-4388-baec-2e87135dc908' + scope: resourceGroup() +} + +resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProject.id, cognitiveServicesUserRole.id, aiServices.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesUserRole.id + principalType: 'ServicePrincipal' + } +} + output aiProjectName string = aiProject.name output aiProjectResourceId string = aiProject.id output aiProjectWorkspaceId string = aiProject.properties.workspaceId diff --git a/modules-byo/byo-dependent-resources.bicep b/modules-byo/byo-dependent-resources.bicep index b7ea5554..5540356c 100644 --- a/modules-byo/byo-dependent-resources.bicep +++ b/modules-byo/byo-dependent-resources.bicep @@ -20,6 +20,24 @@ param storageName string var storageNameCleaned = replace(storageName, '-', '') +@description('Model name for deployment') +param modelName string + +@description('Model format for deployment') +param modelFormat string + +@description('Model version for deployment') +param modelVersion string + +@description('Model deployment SKU name') +param modelSkuName string + +@description('Model deployment capacity') +param modelCapacity int + +@description('Model/AI Resource deployment location') +param modelLocation string + resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { name: keyvaultName location: location @@ -48,7 +66,7 @@ resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { name: aiServicesName - location: 'eastus' + location: modelLocation sku: { name: 'S0' } @@ -66,16 +84,16 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = } resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { parent: aiServices - name: 'gpt-4o-mini' + name: modelName sku : { - capacity: 10 - name: 'GlobalStandard' + capacity: modelCapacity + name: modelSkuName } properties: { model:{ - name: 'gpt-4o-mini' - format: 'OpenAI' - version: '2024-07-18' + name: modelName + format: modelFormat + version: modelVersion } } } diff --git a/modules-standard/standard-ai-hub-identity.bicep b/modules-standard/standard-ai-hub-identity.bicep index e8c99a4e..dee5d7ae 100644 --- a/modules-standard/standard-ai-hub-identity.bicep +++ b/modules-standard/standard-ai-hub-identity.bicep @@ -21,17 +21,12 @@ param storageAccountId string @description('Resource ID of the AI Services resource') param aiServicesId string -param aiServicesName string - @description('Resource ID of the AI Services endpoint') param aiServicesTarget string @description('Model/AI Resource deployment location') param modelLocation string -resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { - name: aiServicesName -} resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { name: aiHubName @@ -67,50 +62,5 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' } -resource cognitiveServicesContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' - scope: resourceGroup() -} - -resource cognitiveServicesContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01'= { - scope: aiServices - name: guid(aiServices.id, cognitiveServicesContributorRole.id, aiHub.id) - properties: { - principalId: aiHub.identity.principalId - roleDefinitionId: cognitiveServicesContributorRole.id - principalType: 'ServicePrincipal' - } - } - - -resource cognitiveServicesOpenAIUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - scope: resourceGroup() -} -resource cognitiveServicesOpenAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: aiServices - name: guid(aiHub.id, cognitiveServicesOpenAIUserRole.id, aiServices.id) - properties: { - principalId: aiHub.identity.principalId - roleDefinitionId: cognitiveServicesOpenAIUserRole.id - principalType: 'ServicePrincipal' - } -} - -resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: 'a97b65f3-24c7-4388-baec-2e87135dc908' - scope: resourceGroup() -} - -resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: aiServices - name: guid(aiHub.id, cognitiveServicesUserRole.id, aiServices.id) - properties: { - principalId: aiHub.identity.principalId - roleDefinitionId: cognitiveServicesUserRole.id - principalType: 'ServicePrincipal' - } -} - output aiHubID string = aiHub.id diff --git a/modules-standard/standard-ai-project-identity.bicep b/modules-standard/standard-ai-project-identity.bicep index 20be4570..fa6a736b 100644 --- a/modules-standard/standard-ai-project-identity.bicep +++ b/modules-standard/standard-ai-project-identity.bicep @@ -18,6 +18,12 @@ param aiProjectDescription string @description('Resource ID of the AI Hub resource') param aiHubId string +param aiServicesName string + +resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { + name: aiServicesName +} + resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { name: aiProjectName location: location @@ -37,4 +43,49 @@ resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-prev kind: 'project' } +resource cognitiveServicesContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + scope: resourceGroup() +} + +resource cognitiveServicesContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01'= { + scope: aiServices + name: guid(aiProject.id, cognitiveServicesContributorRole.id, aiServices.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesContributorRole.id + principalType: 'ServicePrincipal' + } + } + + +resource cognitiveServicesOpenAIUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + scope: resourceGroup() +} +resource cognitiveServicesOpenAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProject.id, cognitiveServicesOpenAIUserRole.id, aiServices.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesOpenAIUserRole.id + principalType: 'ServicePrincipal' + } +} + +resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: 'a97b65f3-24c7-4388-baec-2e87135dc908' + scope: resourceGroup() +} + +resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProject.id, cognitiveServicesUserRole.id, aiServices.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesUserRole.id + principalType: 'ServicePrincipal' + } +} + output aiProjectID string = aiProject.id diff --git a/standard-agent-identity.bicep b/standard-agent-identity.bicep index 64a0225f..46a32769 100644 --- a/standard-agent-identity.bicep +++ b/standard-agent-identity.bicep @@ -27,16 +27,6 @@ param location string = resourceGroup().location @description('Set of tags to apply to all resources.') param tags object = {} -// Variables -var name = toLower('${aiHubName}') -var projectName = toLower('${aiProjectName}') - -@description('Name of the storage account') -param storageName string = 'agent-storage' - -@description('Name of the Azure AI Services account') -param aiServicesName string = 'agent-ai-services' - @description('Model name for deployment') param modelName string = 'gpt-4o-mini' @@ -55,6 +45,16 @@ param modelCapacity int = 10 @description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') param modelLocation string = 'eastus' +// Variables +var name = toLower('${aiHubName}') +var projectName = toLower('${aiProjectName}') + +@description('Name of the storage account') +param storageName string = 'agent-storage' + +@description('Name of the Azure AI Services account') +param aiServicesName string = 'agent-ai-services' + // Create a short, unique suffix, that will be unique to each resource group // var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) @@ -81,7 +81,7 @@ module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { } module aiHub 'modules-standard/standard-ai-hub-identity.bicep' = { - name: '${name}-${uniqueSuffix}-deployment' + name: 'ai-${name}-${uniqueSuffix}-deployment' params: { // workspace organization aiHubName: 'ai-${name}-${uniqueSuffix}' @@ -92,7 +92,6 @@ module aiHub 'modules-standard/standard-ai-hub-identity.bicep' = { // dependent resources modelLocation: modelLocation - aiServicesName: '${aiServicesName}${uniqueSuffix}' storageAccountId: aiDependencies.outputs.storageId aiServicesId: aiDependencies.outputs.aiservicesID aiServicesTarget: aiDependencies.outputs.aiservicesTarget @@ -110,6 +109,7 @@ module aiProject 'modules-standard/standard-ai-project-identity.bicep' = { tags: tags // dependent resources + aiServicesName: '${aiServicesName}${uniqueSuffix}' aiHubId: aiHub.outputs.aiHubID } } diff --git a/standard-agent.bicep b/standard-agent.bicep index 11568f8f..c0d59721 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -80,7 +80,7 @@ module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { } module aiHub 'modules-standard/standard-ai-hub.bicep' = { - name: '${name}-${uniqueSuffix}-deployment' + name: 'ai-${name}-${uniqueSuffix}-deployment' params: { // workspace organization aiHubName: 'ai-${name}-${uniqueSuffix}' From 0a01b9d94f230c8d3a649147db3958c0f38f06e5 Mon Sep 17 00:00:00 2001 From: e-straight Date: Mon, 11 Nov 2024 16:57:36 -0500 Subject: [PATCH 109/180] initial commit for tracing --- ...basics_async_with_azure_monitor_tracing.py | 92 +++++++++++ ...gents_basics_async_with_console_tracing.py | 93 +++++++++++ ...gents_basics_with_azure_monitor_tracing.py | 86 ++++++++++ .../agents_basics_with_console_tracing.py | 83 ++++++++++ ...ts_functions_with_azure_monitor_tracing.py | 153 +++++++++++++++++ .../agents_functions_with_console_tracing.py | 154 ++++++++++++++++++ ...eventhandler_with_azure_monitor_tracing.py | 121 ++++++++++++++ ...tream_eventhandler_with_console_tracing.py | 122 ++++++++++++++ 8 files changed, 904 insertions(+) create mode 100644 samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py create mode 100644 samples/tracing/async/agents_basics_async_with_console_tracing.py create mode 100644 samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py create mode 100644 samples/tracing/sync/agents_basics_with_console_tracing.py create mode 100644 samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py create mode 100644 samples/tracing/sync/agents_functions_with_console_tracing.py create mode 100644 samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py create mode 100644 samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py diff --git a/samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py b/samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py new file mode 100644 index 00000000..552131c3 --- /dev/null +++ b/samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py @@ -0,0 +1,92 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_basics_async_with_azure_monitor_tracing.py + +DESCRIPTION: + This sample demonstrates how to use basic agent operations from + the Azure Agents service using a asynchronous client with Azure Monitor tracing. + View the results in the "Tracing" tab in your Azure AI Studio project page. + +USAGE: + python sample_agents_basics_async_with_azure_monitor_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity opentelemetry-sdk azure-monitor-opentelemetry + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. +""" +import asyncio +import time +from azure.ai.projects.aio import AIProjectClient +from azure.identity.aio import DefaultAzureCredential +from azure.ai.projects.tracing.agents import AIAgentsInstrumentor +from opentelemetry import trace +import os +from azure.monitor.opentelemetry import configure_azure_monitor + + +tracer = trace.get_tracer(__name__) + + +@tracer.start_as_current_span(__file__) +async def main() -> None: + + # Create an Azure AI Project Client from a connection string, copied from your AI Studio project. + # At the moment, it should be in the format ";;;" + # Customer needs to login to Azure subscription via Azure CLI and set the environment variables + + project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] + ) + + # Enable Azure Monitor tracing + application_insights_connection_string = project_client.telemetry.get_connection_string() + if not application_insights_connection_string: + print("Application Insights was not enabled for this project.") + print("Enable it via the 'Tracing' tab in your AI Studio project page.") + exit() + configure_azure_monitor(connection_string=application_insights_connection_string) + + async with project_client: + agent = await project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + ) + print(f"Created agent, agent ID: {agent.id}") + + thread = await project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + message = await project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, tell me a joke" + ) + print(f"Created message, message ID: {message.id}") + + run = await project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) + + # poll the run as long as run status is queued or in progress + while run.status in ["queued", "in_progress", "requires_action"]: + # wait for a second + time.sleep(1) + run = await project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + print(f"Run status: {run.status}") + + print(f"Run completed with status: {run.status}") + + await project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = await project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/samples/tracing/async/agents_basics_async_with_console_tracing.py b/samples/tracing/async/agents_basics_async_with_console_tracing.py new file mode 100644 index 00000000..a82c5591 --- /dev/null +++ b/samples/tracing/async/agents_basics_async_with_console_tracing.py @@ -0,0 +1,93 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_basics_async_with_console_tracing.py + +DESCRIPTION: + This sample demonstrates how to use basic agent operations from + the Azure Agents service using a asynchronous client with tracing to console. + +USAGE: + python sample_agents_basics_async_with_console_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity opentelemetry-sdk azure-core-tracing-opentelemetry + + If you want to export telemetry to OTLP endpoint (such as Aspire dashboard + https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone?tabs=bash) + install: + + pip install opentelemetry-exporter-otlp-proto-grpc + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. +""" +import asyncio +import time +import sys +from azure.ai.projects.aio import AIProjectClient +from azure.identity.aio import DefaultAzureCredential +from opentelemetry import trace +import os + + +tracer = trace.get_tracer(__name__) + + +@tracer.start_as_current_span(__file__) +async def main() -> None: + + # Create an Azure AI Project Client from a connection string, copied from your AI Studio project. + # At the moment, it should be in the format ";;;" + # Customer needs to login to Azure subscription via Azure CLI and set the environment variables + + project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] + ) + + # Enable console tracing + # or, if you have local OTLP endpoint running, change it to + # project_client.telemetry.enable(destination="http://localhost:4317") + await project_client.telemetry.enable(destination=sys.stdout) + + async with project_client: + agent = await project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + ) + print(f"Created agent, agent ID: {agent.id}") + + thread = await project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + message = await project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, tell me a joke" + ) + print(f"Created message, message ID: {message.id}") + + run = await project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) + + # poll the run as long as run status is queued or in progress + while run.status in ["queued", "in_progress", "requires_action"]: + # wait for a second + time.sleep(1) + run = await project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + print(f"Run status: {run.status}") + + print(f"Run completed with status: {run.status}") + + await project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = await project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py b/samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py new file mode 100644 index 00000000..8ac9fe34 --- /dev/null +++ b/samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py @@ -0,0 +1,86 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_basics_with_azure_monitor_tracing.py + +DESCRIPTION: + This sample demonstrates how to use basic agent operations from + the Azure Agents service using a synchronous client with Azure Monitor tracing. + View the results in the "Tracing" tab in your Azure AI Studio project page. + +USAGE: + python sample_agents_basics_with_azure_monitor_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity azure-monitor-opentelemetry + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. +""" + +import os, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential + +# Create an AI Project Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) + +# [START enable_tracing] +from opentelemetry import trace +from azure.monitor.opentelemetry import configure_azure_monitor + +# Enable Azure Monitor tracing +application_insights_connection_string = project_client.telemetry.get_connection_string() +if not application_insights_connection_string: + print("Application Insights was not enabled for this project.") + print("Enable it via the 'Tracing' tab in your AI Studio project page.") + exit() +configure_azure_monitor(connection_string=application_insights_connection_string) + +scenario = os.path.basename(__file__) +tracer = trace.get_tracer(__name__) + +with tracer.start_as_current_span(scenario): + with project_client: + + # [END enable_tracing] + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + ) + print(f"Created agent, agent ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, tell me a joke" + ) + print(f"Created message, message ID: {message.id}") + + run = project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) + + # poll the run as long as run status is queued or in progress + while run.status in ["queued", "in_progress", "requires_action"]: + # wait for a second + time.sleep(1) + run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + print(f"Run status: {run.status}") + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"messages: {messages}") \ No newline at end of file diff --git a/samples/tracing/sync/agents_basics_with_console_tracing.py b/samples/tracing/sync/agents_basics_with_console_tracing.py new file mode 100644 index 00000000..fb575e15 --- /dev/null +++ b/samples/tracing/sync/agents_basics_with_console_tracing.py @@ -0,0 +1,83 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_basics_with_console_tracing.py + +DESCRIPTION: + This sample demonstrates how to use basic agent operations from + the Azure Agents service using a synchronous client with tracing to console. + +USAGE: + python sample_agents_basics_with_console_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity opentelemetry-sdk azure-core-tracing-opentelemetry + + If you want to export telemetry to OTLP endpoint (such as Aspire dashboard + https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone?tabs=bash) + install: + + pip install opentelemetry-exporter-otlp-proto-grpc + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. +""" + +import os, sys, time +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from opentelemetry import trace + +# Create an AI Project Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) + +# Enable console tracing +# or, if you have local OTLP endpoint running, change it to +# project_client.telemetry.enable(destination="http://localhost:4317") +project_client.telemetry.enable(destination=sys.stdout) + +scenario = os.path.basename(__file__) +tracer = trace.get_tracer(__name__) + +with tracer.start_as_current_span(scenario): + with project_client: + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + ) + print(f"Created agent, agent ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, tell me a joke" + ) + print(f"Created message, message ID: {message.id}") + + run = project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) + + # poll the run as long as run status is queued or in progress + while run.status in ["queued", "in_progress", "requires_action"]: + # wait for a second + time.sleep(1) + run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + print(f"Run status: {run.status}") + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"messages: {messages}") \ No newline at end of file diff --git a/samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py b/samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py new file mode 100644 index 00000000..6c95fed7 --- /dev/null +++ b/samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py @@ -0,0 +1,153 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_functions_with_azure_monitor_tracing.py + +DESCRIPTION: + This sample demonstrates how to use basic agent operations with function tools from + the Azure Agents service using a synchronous client with Azure Monitor tracing. + View the results in the "Tracing" tab in your Azure AI Studio project page. + +USAGE: + python sample_agents_functions_with_azure_monitor_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity opentelemetry-sdk azure-monitor-opentelemetry + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. +""" +from typing import Any, Callable, Set + +import os, time, json +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import FunctionTool, RequiredFunctionToolCall, SubmitToolOutputsAction, ToolOutput +from opentelemetry import trace +from azure.monitor.opentelemetry import configure_azure_monitor + + +# Create an AI Project Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +# Enable Azure Monitor tracing +application_insights_connection_string = project_client.telemetry.get_connection_string() +if not application_insights_connection_string: + print("Application Insights was not enabled for this project.") + print("Enable it via the 'Tracing' tab in your AI Studio project page.") + exit() +configure_azure_monitor(connection_string=application_insights_connection_string) + +scenario = os.path.basename(__file__) +tracer = trace.get_tracer(__name__) + + +# The tracer.start_as_current_span decorator will trace the function call and enable adding additional attributes +# to the span in the function implementation. Note that this will trace the function parameters and their values. +@tracer.start_as_current_span("fetch_weather") # type: ignore +def fetch_weather(location: str) -> str: + """ + Fetches the weather information for the specified location. + + :param location (str): The location to fetch weather for. + :return: Weather information as a JSON string. + :rtype: str + """ + # In a real-world scenario, you'd integrate with a weather API. + # Here, we'll mock the response. + mock_weather_data = {"New York": "Sunny, 25°C", "London": "Cloudy, 18°C", "Tokyo": "Rainy, 22°C"} + + # Adding attributes to the current span + span = trace.get_current_span() + span.set_attribute("requested_location", location) + + weather = mock_weather_data.get(location, "Weather data not available for this location.") + weather_json = json.dumps({"weather": weather}) + return weather_json + + +# Statically defined user functions for fast reference +user_functions: Set[Callable[..., Any]] = { + fetch_weather, +} + +# Initialize function tool with user function +functions = FunctionTool(functions=user_functions) + +with tracer.start_as_current_span(scenario): + with project_client: + # Create an agent and run user's request with function calls + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-assistant", + instructions="You are a helpful assistant", + tools=functions.definitions, + ) + print(f"Created agent, ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Hello, what is the weather in New York?", + ) + print(f"Created message, ID: {message.id}") + + run = project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Created run, ID: {run.id}") + + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) + run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + if run.status == "requires_action" and isinstance(run.required_action, SubmitToolOutputsAction): + tool_calls = run.required_action.submit_tool_outputs.tool_calls + if not tool_calls: + print("No tool calls provided - cancelling run") + project_client.agents.cancel_run(thread_id=thread.id, run_id=run.id) + break + + tool_outputs = [] + for tool_call in tool_calls: + if isinstance(tool_call, RequiredFunctionToolCall): + try: + output = functions.execute(tool_call) + tool_outputs.append( + ToolOutput( + tool_call_id=tool_call.id, + output=output, + ) + ) + except Exception as e: + print(f"Error executing tool_call {tool_call.id}: {e}") + + print(f"Tool outputs: {tool_outputs}") + if tool_outputs: + project_client.agents.submit_tool_outputs_to_run( + thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs + ) + + print(f"Current run status: {run.status}") + + print(f"Run completed with status: {run.status}") + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/tracing/sync/agents_functions_with_console_tracing.py b/samples/tracing/sync/agents_functions_with_console_tracing.py new file mode 100644 index 00000000..4304dd70 --- /dev/null +++ b/samples/tracing/sync/agents_functions_with_console_tracing.py @@ -0,0 +1,154 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_functions_with_console_tracing.py + +DESCRIPTION: + This sample demonstrates how to use basic agent operations with function tools from + the Azure Agents service using a synchronous client with tracing to console. + +USAGE: + python sample_agents_functions_with_console_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity opentelemetry-sdk azure-core-tracing-opentelemetry + + If you want to export telemetry to OTLP endpoint (such as Aspire dashboard + https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone?tabs=bash) + install: + + pip install opentelemetry-exporter-otlp-proto-grpc + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. +""" +from typing import Any, Callable, Set + +import os, sys, time, json +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import FunctionTool, RequiredFunctionToolCall, SubmitToolOutputsAction, ToolOutput +from opentelemetry import trace + + +# Create an AI Project Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +# Enable console tracing +# or, if you have local OTLP endpoint running, change it to +# project_client.telemetry.enable(destination="http://localhost:4317") +project_client.telemetry.enable(destination=sys.stdout) + +scenario = os.path.basename(__file__) +tracer = trace.get_tracer(__name__) + + +# The tracer.start_as_current_span decorator will trace the function call and enable adding additional attributes +# to the span in the function implementation. Note that this will trace the function parameters and their values. +@tracer.start_as_current_span("fetch_weather") # type: ignore +def fetch_weather(location: str) -> str: + """ + Fetches the weather information for the specified location. + + :param location (str): The location to fetch weather for. + :return: Weather information as a JSON string. + :rtype: str + """ + # In a real-world scenario, you'd integrate with a weather API. + # Here, we'll mock the response. + mock_weather_data = {"New York": "Sunny, 25°C", "London": "Cloudy, 18°C", "Tokyo": "Rainy, 22°C"} + + # Adding attributes to the current span + span = trace.get_current_span() + span.set_attribute("requested_location", location) + + weather = mock_weather_data.get(location, "Weather data not available for this location.") + weather_json = json.dumps({"weather": weather}) + return weather_json + + +# Statically defined user functions for fast reference +user_functions: Set[Callable[..., Any]] = { + fetch_weather, +} + +# Initialize function tool with user function +functions = FunctionTool(functions=user_functions) + +with tracer.start_as_current_span(scenario): + with project_client: + # Create an agent and run user's request with function calls + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", + name="my-assistant", + instructions="You are a helpful assistant", + tools=functions.definitions, + ) + print(f"Created agent, ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, + role="user", + content="Hello, what is the weather in New York?", + ) + print(f"Created message, ID: {message.id}") + + run = project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Created run, ID: {run.id}") + + while run.status in ["queued", "in_progress", "requires_action"]: + time.sleep(1) + run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) + + if run.status == "requires_action" and isinstance(run.required_action, SubmitToolOutputsAction): + tool_calls = run.required_action.submit_tool_outputs.tool_calls + if not tool_calls: + print("No tool calls provided - cancelling run") + project_client.agents.cancel_run(thread_id=thread.id, run_id=run.id) + break + + tool_outputs = [] + for tool_call in tool_calls: + if isinstance(tool_call, RequiredFunctionToolCall): + try: + output = functions.execute(tool_call) + tool_outputs.append( + ToolOutput( + tool_call_id=tool_call.id, + output=output, + ) + ) + except Exception as e: + print(f"Error executing tool_call {tool_call.id}: {e}") + + print(f"Tool outputs: {tool_outputs}") + if tool_outputs: + project_client.agents.submit_tool_outputs_to_run( + thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs + ) + + print(f"Current run status: {run.status}") + + print(f"Run completed with status: {run.status}") + + # Delete the agent when done + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + # Fetch and log all messages + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py b/samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py new file mode 100644 index 00000000..b9a30ea3 --- /dev/null +++ b/samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py @@ -0,0 +1,121 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_stream_eventhandler_with_azure_monitor_tracing.py + +DESCRIPTION: + This sample demonstrates how to use agent operations with an event handler in streaming from + the Azure Agents service using a synchronous client with Azure Monitor tracing. + View the results in the "Tracing" tab in your Azure AI Studio project page. + +USAGE: + python sample_agents_stream_eventhandler_with_azure_monitor_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity opentelemetry-sdk azure-monitor-opentelemetry + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. + +""" + +import os +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import ( + AgentEventHandler, + MessageDeltaTextContent, + MessageDeltaChunk, + ThreadMessage, + ThreadRun, + RunStep, +) +from typing import Any +from opentelemetry import trace +from azure.monitor.opentelemetry import configure_azure_monitor + +# Create an Azure AI Project Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) + + +class MyEventHandler(AgentEventHandler): + def on_message_delta(self, delta: "MessageDeltaChunk") -> None: + for content_part in delta.delta.content: + if isinstance(content_part, MessageDeltaTextContent): + text_value = content_part.text.value if content_part.text else "No text" + print(f"Text delta received: {text_value}") + + def on_thread_message(self, message: "ThreadMessage") -> None: + if len(message.content): + print( + f"ThreadMessage created. ID: {message.id}, " + f"Status: {message.status}, Content: {message.content[0].as_dict()}" + ) + else: + print(f"ThreadMessage created. ID: {message.id}, " f"Status: {message.status}") + + def on_thread_run(self, run: "ThreadRun") -> None: + print(f"ThreadRun status: {run.status}") + + def on_run_step(self, step: "RunStep") -> None: + print(f"RunStep type: {step.type}, Status: {step.status}") + + def on_error(self, data: str) -> None: + print(f"An error occurred. Data: {data}") + + def on_done(self) -> None: + print("Stream completed.") + + def on_unhandled_event(self, event_type: str, event_data: Any) -> None: + print(f"Unhandled Event Type: {event_type}, Data: {event_data}") + + +# Enable Azure Monitor tracing +application_insights_connection_string = project_client.telemetry.get_connection_string() +if not application_insights_connection_string: + print("Application Insights was not enabled for this project.") + print("Enable it via the 'Tracing' tab in your AI Studio project page.") + exit() +configure_azure_monitor(connection_string=application_insights_connection_string) + +scenario = os.path.basename(__file__) +tracer = trace.get_tracer(__name__) + +with tracer.start_as_current_span(scenario): + with project_client: + # Create an agent and run stream with event handler + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant" + ) + print(f"Created agent, agent ID {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, tell me a joke" + ) + print(f"Created message, message ID {message.id}") + + with project_client.agents.create_stream( + thread_id=thread.id, assistant_id=agent.id, event_handler=MyEventHandler() + ) as stream: + stream.until_done() + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py b/samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py new file mode 100644 index 00000000..0dec71d1 --- /dev/null +++ b/samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py @@ -0,0 +1,122 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +FILE: sample_agents_stream_eventhandler_with_console_tracing.py + +DESCRIPTION: + This sample demonstrates how to use agent operations with an event handler in streaming from + the Azure Agents service using a synchronous client with tracing to console. + +USAGE: + python sample_agents_stream_eventhandler_with_console_tracing.py + + Before running the sample: + + pip install azure-ai-projects azure-identity opentelemetry-sdk azure-core-tracing-opentelemetry + + If you want to export telemetry to OTLP endpoint (such as Aspire dashboard + https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone?tabs=bash) + install: + + pip install opentelemetry-exporter-otlp-proto-grpc + + Set these environment variables with your own values: + * PROJECT_CONNECTION_STRING - The Azure AI Project connection string, as found in your AI Studio Project. + * AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED - Optional. Set to `true` to trace the content of chat + messages, which may contain personal data. False by default. +""" + +import os, sys +from azure.ai.projects import AIProjectClient +from azure.identity import DefaultAzureCredential +from azure.ai.projects.models import ( + AgentEventHandler, + MessageDeltaTextContent, + MessageDeltaChunk, + ThreadMessage, + ThreadRun, + RunStep, +) +from typing import Any +from opentelemetry import trace + + +# Create an Azure AI Project Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +project_client = AIProjectClient.from_connection_string( + credential=DefaultAzureCredential(), + conn_str=os.environ["PROJECT_CONNECTION_STRING"], +) + + +class MyEventHandler(AgentEventHandler): + def on_message_delta(self, delta: "MessageDeltaChunk") -> None: + for content_part in delta.delta.content: + if isinstance(content_part, MessageDeltaTextContent): + text_value = content_part.text.value if content_part.text else "No text" + print(f"Text delta received: {text_value}") + + def on_thread_message(self, message: "ThreadMessage") -> None: + if len(message.content): + print( + f"ThreadMessage created. ID: {message.id}, " + f"Status: {message.status}, Content: {message.content[0].as_dict()}" + ) + else: + print(f"ThreadMessage created. ID: {message.id}, " f"Status: {message.status}") + + def on_thread_run(self, run: "ThreadRun") -> None: + print(f"ThreadRun status: {run.status}") + + def on_run_step(self, step: "RunStep") -> None: + print(f"RunStep type: {step.type}, Status: {step.status}") + + def on_error(self, data: str) -> None: + print(f"An error occurred. Data: {data}") + + def on_done(self) -> None: + print("Stream completed.") + + def on_unhandled_event(self, event_type: str, event_data: Any) -> None: + print(f"Unhandled Event Type: {event_type}, Data: {event_data}") + + +# Enable console tracing +# or, if you have local OTLP endpoint running, change it to +# project_client.telemetry.enable(destination="http://localhost:4317") +project_client.telemetry.enable(destination=sys.stdout) + +scenario = os.path.basename(__file__) +tracer = trace.get_tracer(__name__) + +with tracer.start_as_current_span(scenario): + with project_client: + # Create an agent and run stream with event handler + agent = project_client.agents.create_agent( + model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant" + ) + print(f"Created agent, agent ID {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="Hello, tell me a joke" + ) + print(f"Created message, message ID {message.id}") + + with project_client.agents.create_stream( + thread_id=thread.id, assistant_id=agent.id, event_handler=MyEventHandler() + ) as stream: + stream.until_done() + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file From 10f9e241a9b2b862eeced828f61c5c7e51716481 Mon Sep 17 00:00:00 2001 From: Linda Li <139801625+lindazqli@users.noreply.github.com> Date: Mon, 11 Nov 2024 21:20:54 -0800 Subject: [PATCH 110/180] Update python-function-calling.py --- samples/function-calling/python-function-calling.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/function-calling/python-function-calling.py b/samples/function-calling/python-function-calling.py index 084076cc..7f13c5fd 100644 --- a/samples/function-calling/python-function-calling.py +++ b/samples/function-calling/python-function-calling.py @@ -36,7 +36,7 @@ ) print(f"Created message, ID: {message.id}") - run = project_client.agents.create_run(thread_id=thread.id, agent_id=agent.id) + run = project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) print(f"Created run, ID: {run.id}") while run.status in ["queued", "in_progress", "requires_action"]: @@ -80,4 +80,4 @@ # Fetch and log all messages messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") \ No newline at end of file + print(f"Messages: {messages}") From 672f3024474ad28c4b17d041e53c4726473c0e2a Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 12:57:49 -0500 Subject: [PATCH 111/180] Update quickstart.md --- quickstart.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/quickstart.md b/quickstart.md index 1e87306b..061c3cfe 100644 --- a/quickstart.md +++ b/quickstart.md @@ -63,35 +63,43 @@ If you already have these resources set up, skip to the [configure and run your **Option 1**: Use the standard agent configuration. -- Download the `standard-agent.bicep` file and the `modules-standard` folder to your project directory. Your directory should look like this +- Download the `standard-agent.bicep` file, `standard-agent-identity.bicep` file, and the `modules-standard` folder to your project directory. Your directory should look like this ```console /my-project - standard-agent.bicep + - standard-agent-identity.bicep /modules-standard - standard-ai-hub.bicep - standard-ai-project.bicep + - standard-ai-hub-identity.bicep + - standard-ai-project-identity.bicep - standard-dependent-resources.bicep ``` -- Using the resource group you created in the previous step, run one of the following commands: +- Before deploying resources, decide which configuration file to use: + - `standard-agent.bicep`: Use this file to use API keys for authentication. + - `standard-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. + + +- Using the resource group you created in the previous step and one of the template files (either standard-agent.bicep or standard-agent-identity.bicep), run one of the following commands: - To use default resource names, run: ```console - az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep + az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} ``` - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: ```console - az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' + az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: ```console - az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters @standard-agent.parameters.json + az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters @standard-agent.parameters.json ``` Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. From aba300e3b51b6f1ea7549a8b737952e93a467cfa Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 14:41:16 -0500 Subject: [PATCH 112/180] updating quickstart --- quickstart.md | 83 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/quickstart.md b/quickstart.md index 061c3cfe..1dc99f03 100644 --- a/quickstart.md +++ b/quickstart.md @@ -59,55 +59,72 @@ If you already have these resources set up, skip to the [configure and run your az group create --name {my_resource_group} --location eastus ``` -1.
+1. Choose Standard or Custom Agent Setup +
-**Option 1**: Use the standard agent configuration. + **Standard Setup**: Agents use multi-tenant search and storage resources fully managed by Microsoft. You won’t have visibility or control over these underlying Azure resources. -- Download the `standard-agent.bicep` file, `standard-agent-identity.bicep` file, and the `modules-standard` folder to your project directory. Your directory should look like this + **Custom Setup**: Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage. - ```console - /my-project - - standard-agent.bicep - - standard-agent-identity.bicep - /modules-standard - - standard-ai-hub.bicep - - standard-ai-project.bicep - - standard-ai-hub-identity.bicep - - standard-ai-project-identity.bicep - - standard-dependent-resources.bicep - ``` +
-- Before deploying resources, decide which configuration file to use: - - `standard-agent.bicep`: Use this file to use API keys for authentication. - - `standard-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. +
+ Option 1: Use standard agent configuration. + - Download the `standard-agent.bicep` file, `standard-agent-identity.bicep` file, and the `modules-standard` folder to your project directory. Your directory should look like this -- Using the resource group you created in the previous step and one of the template files (either standard-agent.bicep or standard-agent-identity.bicep), run one of the following commands: + ```console + /my-project + - standard-agent.bicep + - standard-agent-identity.bicep + /modules-standard + - standard-ai-hub.bicep + - standard-ai-project.bicep + - standard-ai-hub-identity.bicep + - standard-ai-project-identity.bicep + - standard-dependent-resources.bicep + ``` - - To use default resource names, run: + - Before deploying resources, decide which configuration file to use: + - `standard-agent.bicep`: Use this file to use API keys for authentication. + - `standard-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. - ```console - az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} - ``` - - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: + - Using the resource group you created in the previous step and one of the template files (either standard-agent.bicep or standard-agent-identity.bicep), run one of the following commands: - ```console - az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' - ``` + - To use default resource names, run: - - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: + ```console + az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} + ``` - ```console - az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters @standard-agent.parameters.json - ``` + - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: - Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. + ```console + az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' + ``` -
+ - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: + + ```console + az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters @standard-agent.parameters.json + ``` + + Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. + +
+ + +
+ Option 2: Use custom agent configuration. +
+ + +
+
- Option 2: Follow steps 6-10 if you want specific control over the creation and configuration of these resources. + Option 3: Follow steps 6-10 if you want specific control over the creation and configuration of these resources. 6. Create an Azure OpenAI resource: From c959af9465e5d4d9ae7f5baf9274fc6e17383059 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 14:52:29 -0500 Subject: [PATCH 113/180] Update readme.md --- samples/file-search/readme.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index 1ac73f99..ba55b1eb 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -4,6 +4,21 @@ File Search augments the Agent with knowledge from outside its model, such as pr To access your files, the file search tool uses the vector store object. Upload your files and create a vector store to contain them. Once the vector store is created, you should poll its status until all files are out of the in_progress state to ensure that all content has finished processing. The SDK provides helpers for uploading and polling. +### File Sources +- Uploading local files +- Files from message attachments +- [coming soon] Azure Blob Storage + +### Standard Agent Setup
+The File Search tool has the same functionality as AOAI Assistants. Microsoft managed search and storage resources are used. +- Uploaded files get stored in Microsoft managed storage +- A vector store is created using Microsoft managed search resources + +### Custom Agent Setup
+The File Search tool uses the Azure AI Search and Azure Blob Storage resources you connected during project and agent setup. +- Uploaded files get stored in your connected Azure Blob Storage account. +- Vector stores get created using your connected Azure AI Seach resource. + ## Examples Run the code samples below and view the output. @@ -15,4 +30,4 @@ Run the code samples below and view the output. ## Additional samples -* [Python Quart app](https://github.com/Azure-Samples/azureai-assistant-tool/tree/main/samples/FileSearch) \ No newline at end of file +* [Python Quart app](https://github.com/Azure-Samples/azureai-assistant-tool/tree/main/samples/FileSearch) From c8b7a33e6486a7ece65d7c2805e04069c86ea542 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 15:01:57 -0500 Subject: [PATCH 114/180] Update readme.md --- samples/file-search/readme.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index ba55b1eb..46941519 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -1,6 +1,6 @@ # File Search -File Search augments the Agent with knowledge from outside its model, such as proprietary product information or documents provided by your users. OpenAI automatically parses and chunks your documents, creates and stores the embeddings, and use both vector and keyword search to retrieve relevant content to answer user queries. +File Search augments the Agent with knowledge from outside its model, such as proprietary product information or documents provided by your users. To access your files, the file search tool uses the vector store object. Upload your files and create a vector store to contain them. Once the vector store is created, you should poll its status until all files are out of the in_progress state to ensure that all content has finished processing. The SDK provides helpers for uploading and polling. @@ -14,10 +14,15 @@ The File Search tool has the same functionality as AOAI Assistants. Microsoft ma - Uploaded files get stored in Microsoft managed storage - A vector store is created using Microsoft managed search resources -### Custom Agent Setup
+### Custom Agent Setup The File Search tool uses the Azure AI Search and Azure Blob Storage resources you connected during project and agent setup. - Uploaded files get stored in your connected Azure Blob Storage account. -- Vector stores get created using your connected Azure AI Seach resource. +- Vector stores get created using your connected Azure AI Seach resource. +

+ +For both Agent setups, OpenAI handles the entire ingestion process, including automatically parsing and chunking documents, generating and storing embeddings, and utilizing both vector and keyword searches to retrieve relevant content for user queries. + +There is no difference in the code between the two setups; the only variation is in where your files and created vector stores are stored. ## Examples From 5f3148d2323ebb6623375d0fa6ae4bcff533f0a5 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 15:03:59 -0500 Subject: [PATCH 115/180] Update readme.md --- samples/file-search/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index 46941519..bf12e36f 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -15,7 +15,7 @@ The File Search tool has the same functionality as AOAI Assistants. Microsoft ma - A vector store is created using Microsoft managed search resources ### Custom Agent Setup -The File Search tool uses the Azure AI Search and Azure Blob Storage resources you connected during project and agent setup. +The File Search tool uses the Azure AI Search and Azure Blob Storage resources you connected during agent setup. - Uploaded files get stored in your connected Azure Blob Storage account. - Vector stores get created using your connected Azure AI Seach resource.

From 1dc77f61c15f36b7bef7ae6283bed07a29a3a815 Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Tue, 12 Nov 2024 15:25:53 -0500 Subject: [PATCH 116/180] add investment advisor sample --- samples/investment_advisor/README.md | 16 + .../assistant-investment_portfolio.ipynb | 1136 +++++++++++++++++ .../data/investment_portfolio.csv | 7 + samples/investment_advisor/requirements.txt | 4 + 4 files changed, 1163 insertions(+) create mode 100644 samples/investment_advisor/README.md create mode 100644 samples/investment_advisor/assistant-investment_portfolio.ipynb create mode 100644 samples/investment_advisor/data/investment_portfolio.csv create mode 100644 samples/investment_advisor/requirements.txt diff --git a/samples/investment_advisor/README.md b/samples/investment_advisor/README.md new file mode 100644 index 00000000..2fd638e2 --- /dev/null +++ b/samples/investment_advisor/README.md @@ -0,0 +1,16 @@ + +## Personal Financial Assistant + +### Overview + +Function Calling with Yfinance to get latest stock prices. Summarization of user provided article. Extract country info from article, extract country, capital and other aspects, and call an API to get more information about each country. + +### Objective + +The objective of the provided notebook file is to create an Azure OpenAI Assistant named "Portfolio Management Assistant" using the Azure OpenAI API. The assistant is designed to act as a personal financial assistant, providing information and insights related to a user's investment portfolio. The script initiates a conversation with the assistant, guiding it through various financial queries and scenarios to showcase its capabilities. + +### Programming Languages + +- Python + +### Estimated Runtime: 10 mins \ No newline at end of file diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb new file mode 100644 index 00000000..d3b2abf9 --- /dev/null +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -0,0 +1,1136 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# **Investment Portfolio Management**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **About the scenario**\n", + "This scenario demonstrates best practices in a data engineering context, where notebooks are used to orchestrate complex tasks involving real-time data fetching, computation, and report delivery. The notebook is modular, and secure, employing batch processing, error handling, and proper separation of concerns.\n", + "\n", + "In this scenario, we will:\n", + "\n", + "1. Ingest a CSV file containing the user’s investment portfolio.\n", + "2. Fetch real-time stock prices via an API using *Function Calling*.\n", + "3. Perform calculations on the portfolio, including total value and percentage changes, using *Code Interpreter*.\n", + "4. Generate a detailed report summarizing the portfolio's performance.\n", + "5. Save the report to Azure Blob Storage using *Function Calling*." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Time**\n", + "You should expect to spend 10-15 minutes building and running this scenario. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Before you begin**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 1: Install required libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: pandas==2.2.3 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 1)) (2.2.3)\n", + "Requirement already satisfied: yfinance==0.2.48 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 2)) (0.2.48)\n", + "Requirement already satisfied: openai==1.30.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 3)) (1.30.1)\n", + "Requirement already satisfied: python-dotenv==1.0.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", + "Requirement already satisfied: numpy>=1.26.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.1.2)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.9.0.post0)\n", + "Requirement already satisfied: pytz>=2020.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", + "Requirement already satisfied: requests>=2.31 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.32.3)\n", + "Requirement already satisfied: multitasking>=0.0.7 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.0.11)\n", + "Requirement already satisfied: lxml>=4.9.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (5.3.0)\n", + "Requirement already satisfied: platformdirs>=2.0.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.3.6)\n", + "Requirement already satisfied: frozendict>=2.3.4 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.4.6)\n", + "Requirement already satisfied: peewee>=3.16.2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.17.7)\n", + "Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.12.3)\n", + "Requirement already satisfied: html5lib>=1.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.1)\n", + "Requirement already satisfied: anyio<5,>=3.5.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.6.2.post1)\n", + "Requirement already satisfied: distro<2,>=1.7.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.9.0)\n", + "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (0.27.2)\n", + "Requirement already satisfied: pydantic<3,>=1.9.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (2.9.2)\n", + "Requirement already satisfied: sniffio in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.3.1)\n", + "Requirement already satisfied: tqdm>4 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.66.6)\n", + "Requirement already satisfied: typing-extensions<5,>=4.7 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.12.2)\n", + "Requirement already satisfied: idna>=2.8 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from anyio<5,>=3.5.0->openai==1.30.1->-r ./requirements.txt (line 3)) (3.10)\n", + "Requirement already satisfied: soupsieve>1.2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.6)\n", + "Requirement already satisfied: six>=1.9 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.16.0)\n", + "Requirement already satisfied: webencodings in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.5.1)\n", + "Requirement already satisfied: certifi in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2024.8.30)\n", + "Requirement already satisfied: httpcore==1.* in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (1.0.6)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.14.0)\n", + "Requirement already satisfied: annotated-types>=0.6.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.7.0)\n", + "Requirement already satisfied: pydantic-core==2.23.4 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2.23.4)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.4.0)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.2.3)\n", + "Requirement already satisfied: colorama in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from tqdm>4->openai==1.30.1->-r ./requirements.txt (line 3)) (0.4.6)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[notice] A new release of pip is available: 24.2 -> 24.3.1\n", + "[notice] To update, run: python.exe -m pip install --upgrade pip\n" + ] + } + ], + "source": [ + "# Install the packages\n", + "%pip install -r ./requirements.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Azure OpenAI setup**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 1: Setting Up the Environment\n", + "\n", + "Before we begin, we'll load necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.env/.development.env` format. Here we will also import key libraries needed to support this notebook.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Environment variables loaded successfully.\n" + ] + } + ], + "source": [ + "import os\n", + "from dotenv import load_dotenv\n", + "\n", + "# Load environment variables from .env file\n", + "load_dotenv(dotenv_path=\".env/.development.env\")\n", + "\n", + "# Retrieve the secrets\n", + "__AZURE_OPENAI_API_KEY = os.getenv(\"AZURE_OPENAI_API_KEY\")\n", + "__AZURE_OPENAI_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", + "__AZURE_OPENAI_DEPLOYMENT = os.getenv(\"AZURE_OPENAI_DEPLOYMENT\")\n", + "__AZURE_OPENAI_API_VERSION = os.getenv(\"AZURE_OPENAI_API_VERSION\")\n", + "\n", + "# Verify environment variables\n", + "if not all([__AZURE_OPENAI_API_KEY, __AZURE_OPENAI_ENDPOINT, __AZURE_OPENAI_DEPLOYMENT, __AZURE_OPENAI_API_VERSION]):\n", + " raise EnvironmentError(\"One or more environment variables are missing. Please check the .env file.\")\n", + "\n", + "print(\"Environment variables loaded successfully.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 2: Initializing the Azure OpenAI Client\n", + "\n", + "Next, we’ll initialize the Azure OpenAI client. This client allows us to interact with Azure OpenAI's file management APIs. You’ll need your API key, endpoint, and API version, which we just loaded from the environment." + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "AzureOpenAI client initialized.\n" + ] + } + ], + "source": [ + "from openai import AzureOpenAI, OpenAIError\n", + "\n", + "# Initialize the AzureOpenAI client\n", + "try:\n", + " openai_client = AzureOpenAI(\n", + " api_key=__AZURE_OPENAI_API_KEY,\n", + " api_version=__AZURE_OPENAI_API_VERSION,\n", + " azure_endpoint=__AZURE_OPENAI_ENDPOINT\n", + " )\n", + " print(\"AzureOpenAI client initialized.\")\n", + "except OpenAIError as e:\n", + " raise ConnectionError(f\"Failed to initialize AzureOpenAI client: {e}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 3 - Upload Support File(s)\n", + "\n", + "In this section, we’ll define a function to check if a file already exists in Azure OpenAI. If it exists, we’ll delete it before uploading the new version. This function will handle the complete upload process.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deleted existing file: investment_portfolio.csv\n", + "Uploaded file: investment_portfolio.csv\n" + ] + } + ], + "source": [ + "# Directory containing files to upload\n", + "directory = \"data\"\n", + "purpose = \"assistants\"\n", + "\n", + "# Check if the directory exists\n", + "if not os.path.isdir(directory):\n", + " print(f\"Directory '{directory}' does not exist.\")\n", + "else:\n", + " # Process each file in the directory\n", + " for file_name in os.listdir(directory):\n", + " file_path = os.path.join(directory, file_name)\n", + "\n", + " # Skip if not a file\n", + " if not os.path.isfile(file_path):\n", + " print(f\"Skipping non-file item: {file_name}\")\n", + " continue\n", + "\n", + " try:\n", + " # Check if the file already exists on OpenAI\n", + " existing_files = openai_client.files.list()\n", + " file_exists = False\n", + " for f in existing_files:\n", + " if f.filename == file_name and f.purpose == purpose:\n", + " # Delete the existing file\n", + " openai_client.files.delete(file_id=f.id)\n", + " print(f\"Deleted existing file: {file_name}\")\n", + " file_exists = True\n", + " break\n", + "\n", + " # Upload the new file\n", + " with open(file_path, \"rb\") as file_data:\n", + " portfolio_file = openai_client.files.create(\n", + " file=file_data,\n", + " purpose=purpose\n", + " )\n", + " print(f\"Uploaded file: {file_name}\")\n", + " \n", + " except OpenAIError as e:\n", + " print(f\"Error processing file '{file_name}': {e}\")\n", + " except Exception as e:\n", + " print(f\"Unexpected error with file '{file_name}': {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Function Calling**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 1: Define function for Assistant\n", + "The Get Latest Stock Prices function retrieves the stock data for a specified `ticker symbol` using the yfinance library, specifically pulling the latest data for the last trading day.\n", + "\n", + "The `fetch_stock_price` function uses the `yfinance` library to retrieve stock information, including:\n", + "- Company name\n", + "- Latest open price\n", + "- Latest close price" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function defined successfully.\n" + ] + } + ], + "source": [ + "import yfinance as yf\n", + "\n", + "def fetch_stock_price(ticker_symbol):\n", + " \"\"\"\n", + " Fetch the latest stock price and opening price for a given ticker symbol.\n", + "\n", + " Parameters:\n", + " - ticker_symbol (str): The ticker symbol of the stock to retrieve data for.\n", + "\n", + " Returns:\n", + " - dict: A dictionary containing the following keys:\n", + " - \"company_name\" (str): The name of the company corresponding to the ticker symbol.\n", + " - \"ticker\" (str): The ticker symbol provided as input.\n", + " - \"open_price\" (float): The opening price of the stock for the latest trading day.\n", + " - \"latest_close_price\" (float): The closing price of the stock for the latest trading day.\n", + " - \"error\" (str): An error message if an issue occurred, or if no data was found.\n", + " \n", + " Example:\n", + " >>> fetch_stock_price(\"AAPL\")\n", + " {'ticker': 'AAPL', 'open_price': 145.3, 'latest_close_price': 148.9}\n", + " \"\"\"\n", + " \n", + " # Define the default return structure\n", + " default_response = {\n", + " \"company_name\": None,\n", + " \"ticker\": ticker_symbol,\n", + " \"latest_open_price\": None,\n", + " \"latest_close_price\": None,\n", + " \"error\": None\n", + " }\n", + "\n", + " try:\n", + " # Fetch the stock's trading history for the last day\n", + " stock = yf.Ticker(ticker_symbol)\n", + " stock_data = stock.history(period=\"1d\")\n", + "\n", + " # Check if the data is empty, indicating an invalid ticker or no data available\n", + " if stock_data.empty:\n", + " return {\"error\": f\"No data found for ticker symbol: {ticker_symbol}\"}\n", + "\n", + " # Extract the company name from the 'info' dictionary\n", + " company_name = stock.info.get('longName', \"Company name not available\")\n", + "\n", + " # Extract the latest available open and close prices\n", + " latest_open_price = stock_data['Open'].iloc[-1]\n", + " latest_close_price = stock_data['Close'].iloc[-1]\n", + " \n", + "\n", + " return str(round(latest_close_price,3))\n", + " #return f\"{company_name} ({ticker_symbol}) stock opened at {round(latest_open_price,3)} and closed at {round(latest_close_price)}.\\n\"\n", + "\n", + " #return {\n", + " # \"company_name\": company_name,\n", + " # \"ticker\": ticker_symbol,\n", + " # \"latest_open_price\": latest_open_price,\n", + " # \"latest_close_price\": latest_close_price,\n", + " # \"error\": None\n", + " #}\n", + "\n", + " except KeyError as e:\n", + " return {**default_response, \"error\": f\"Data missing for key: {e}. Verify the ticker symbol.\"}\n", + "\n", + " except Exception as e:\n", + " return {**default_response, \"error\": f\"Unexpected error: {type(e).__name__}: {e}\"}\n", + " \n", + "print(\"Function defined successfully.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 2: Integrating defined function into the Assistant\n", + "Create the `fetch_stock_price` function configuration to be used within the code interpreter. By adding this tool to the Assistant, we enable it to retrieve and interpret stock data when a user prompts it with related queries." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tools list defined successfully.\n" + ] + } + ], + "source": [ + "tools_list = [\n", + " {\"type\": \"code_interpreter\"},\n", + " {\n", + " \"type\": \"function\",\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\"ticker_symbol\": {\"type\": \"string\", \"description\": \"The ticker symbol of the stock\"}},\n", + " \"required\": [\"ticker_symbol\"],\n", + " },\n", + " },\n", + " }\n", + "]\n", + "\n", + "print(\"Tools list defined successfully.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Assistant**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 1: Creating the Investment Management Assistant\n", + "In this step, we create an assistant with specific tools, including a code interpreter, to answer investment-related questions. This assistant will help analyze and provide insights based on the uploaded portfolio file.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Assistant created successfully: Assistant(id='asst_0F1BeDTYLExyx8GfFpuJCrsT', created_at=1731442454, description=None, instructions='You are an expert investment analyst. Use your knowledge base to answer questions about personal investment portfolio management.', metadata={}, model='gpt-4o', name='Investment Management Assistant', object='assistant', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], response_format='auto', temperature=1.0, tool_resources=ToolResources(code_interpreter=ToolResourcesCodeInterpreter(file_ids=[]), file_search=None), top_p=1.0)\n" + ] + } + ], + "source": [ + "# Create the assistant with code interpreter enabled\n", + "try:\n", + " assistant = openai_client.beta.assistants.create(\n", + " name=\"Investment Management Assistant\",\n", + " instructions=(\n", + " \"You are an expert investment analyst. \"\n", + " \"Use your knowledge base to answer questions about personal investment portfolio management.\"\n", + " ),\n", + " model=__AZURE_OPENAI_DEPLOYMENT,\n", + " tools=tools_list\n", + " )\n", + " print(\"Assistant created successfully:\", assistant)\n", + "except OpenAIError as e:\n", + " print(\"Error creating assistant:\", e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 2: Starting a New Conversation Thread\n", + "Let's create a new thread to handle user interactions. Each thread allows for a dedicated conversation with the assistant." + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Thread created: Thread(id='thread_nNEa3nenX9EG7xdtnc8md9xA', created_at=1731442454, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" + ] + } + ], + "source": [ + "# Create a conversation thread\n", + "try:\n", + " thread = openai_client.beta.threads.create()\n", + " print(\"Thread created:\", thread)\n", + "except OpenAIError as e:\n", + " print(\"Error creating thread:\", e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 3: Adding User Message\n", + "In this step, we add a question to the thread. For this demonstration, we're asking which stock ticker has the most investment in the portfolio." + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User question added: Message(id='msg_jdyTyCObzhD0NJogt2KI9rH8', assistant_id=None, attachments=[Attachment(file_id='assistant-byvyRpwiVS4ThTl3blekxTvT', tools=[CodeInterpreterTool(type='code_interpreter')])], completed_at=None, content=[TextContentBlock(text=Text(annotations=[], value='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?'), type='text')], created_at=1731442454, incomplete_at=None, incomplete_details=None, metadata={}, object='thread.message', role='user', run_id=None, status=None, thread_id='thread_nNEa3nenX9EG7xdtnc8md9xA')\n" + ] + } + ], + "source": [ + "# Define the user question\n", + "#prompt_content = \"What ticker symbol has the most stock? Which has the most investment?\"\n", + "\n", + "#prompt_content = \"What is the latest closing price of AAPL?\"\n", + "\n", + "prompt_content = \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\"\n", + "\n", + "# Add the question to the thread\n", + "try:\n", + " message = openai_client.beta.threads.messages.create(\n", + " thread_id=thread.id,\n", + " role=\"user\",\n", + " content=prompt_content,\n", + " attachments=[ # Add files by using the attachments parameter\n", + " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", + " ],\n", + " )\n", + " print(\"User question added:\", message)\n", + "except OpenAIError as e:\n", + " print(\"Error adding user question:\", e)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 4: Running the Assistant\n", + "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Run started: Run(id='run_nTlD90Zrnpzi5vr3x2l59RpV', assistant_id='asst_0F1BeDTYLExyx8GfFpuJCrsT', cancelled_at=None, completed_at=None, created_at=1731442454, expires_at=1731443054, failed_at=None, incomplete_details=None, instructions='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?', last_error=None, max_completion_tokens=None, max_prompt_tokens=None, metadata={}, model='gpt-4o', object='thread.run', required_action=None, response_format='auto', started_at=None, status='queued', thread_id='thread_nNEa3nenX9EG7xdtnc8md9xA', tool_choice='auto', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], truncation_strategy=TruncationStrategy(type='auto', last_messages=None), usage=None, temperature=1.0, top_p=1.0, tool_resources={}, parallel_tool_calls=True)\n" + ] + } + ], + "source": [ + "# Initiate the assistant's response\n", + "try:\n", + " run = openai_client.beta.threads.runs.create(\n", + " thread_id=thread.id,\n", + " assistant_id=assistant.id,\n", + " instructions=prompt_content,\n", + " )\n", + " print(\"Run started:\", run)\n", + "except OpenAIError as e:\n", + " print(\"Error starting run:\", e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 5: Checking for Results\n", + "The assistant may take some time to analyze and respond. We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**>>>>>>> TO DO: create a function to simply sending multiple prompts**" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", + " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", + " \"cancelled_at\": null,\n", + " \"completed_at\": null,\n", + " \"created_at\": 1731442454,\n", + " \"expires_at\": 1731443054,\n", + " \"failed_at\": null,\n", + " \"incomplete_details\": null,\n", + " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", + " \"last_error\": null,\n", + " \"max_completion_tokens\": null,\n", + " \"max_prompt_tokens\": null,\n", + " \"metadata\": {},\n", + " \"model\": \"gpt-4o\",\n", + " \"object\": \"thread.run\",\n", + " \"required_action\": null,\n", + " \"response_format\": \"auto\",\n", + " \"started_at\": null,\n", + " \"status\": \"queued\",\n", + " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", + " \"tool_choice\": \"auto\",\n", + " \"tools\": [\n", + " {\n", + " \"type\": \"code_interpreter\"\n", + " },\n", + " {\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"ticker_symbol\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The ticker symbol of the stock\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"ticker_symbol\"\n", + " ]\n", + " },\n", + " \"strict\": false\n", + " },\n", + " \"type\": \"function\"\n", + " }\n", + " ],\n", + " \"truncation_strategy\": {\n", + " \"type\": \"auto\",\n", + " \"last_messages\": null\n", + " },\n", + " \"usage\": null,\n", + " \"temperature\": 1.0,\n", + " \"top_p\": 1.0,\n", + " \"tool_resources\": {},\n", + " \"parallel_tool_calls\": true\n", + "}\n", + "Waiting for the Assistant to process...\n", + "{\n", + " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", + " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", + " \"cancelled_at\": null,\n", + " \"completed_at\": null,\n", + " \"created_at\": 1731442454,\n", + " \"expires_at\": 1731443054,\n", + " \"failed_at\": null,\n", + " \"incomplete_details\": null,\n", + " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", + " \"last_error\": null,\n", + " \"max_completion_tokens\": null,\n", + " \"max_prompt_tokens\": null,\n", + " \"metadata\": {},\n", + " \"model\": \"gpt-4o\",\n", + " \"object\": \"thread.run\",\n", + " \"required_action\": {\n", + " \"submit_tool_outputs\": {\n", + " \"tool_calls\": [\n", + " {\n", + " \"id\": \"call_z00fpMZXt5gAqMOTjkzsRowf\",\n", + " \"function\": {\n", + " \"arguments\": \"{\\\"ticker_symbol\\\": \\\"MSFT\\\"}\",\n", + " \"name\": \"fetch_stock_price\"\n", + " },\n", + " \"type\": \"function\"\n", + " }\n", + " ]\n", + " },\n", + " \"type\": \"submit_tool_outputs\"\n", + " },\n", + " \"response_format\": \"auto\",\n", + " \"started_at\": 1731442455,\n", + " \"status\": \"requires_action\",\n", + " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", + " \"tool_choice\": \"auto\",\n", + " \"tools\": [\n", + " {\n", + " \"type\": \"code_interpreter\"\n", + " },\n", + " {\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"ticker_symbol\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The ticker symbol of the stock\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"ticker_symbol\"\n", + " ]\n", + " },\n", + " \"strict\": false\n", + " },\n", + " \"type\": \"function\"\n", + " }\n", + " ],\n", + " \"truncation_strategy\": {\n", + " \"type\": \"auto\",\n", + " \"last_messages\": null\n", + " },\n", + " \"usage\": null,\n", + " \"temperature\": 1.0,\n", + " \"top_p\": 1.0,\n", + " \"tool_resources\": {},\n", + " \"parallel_tool_calls\": true\n", + "}\n", + "Function Calling ...\n", + "Function 'fetch_stock_price' called successfully. \n", + "Output: 423.98\n", + "\n", + "Function called successfully.\n", + "{\n", + " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", + " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", + " \"cancelled_at\": null,\n", + " \"completed_at\": null,\n", + " \"created_at\": 1731442454,\n", + " \"expires_at\": 1731443054,\n", + " \"failed_at\": null,\n", + " \"incomplete_details\": null,\n", + " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", + " \"last_error\": null,\n", + " \"max_completion_tokens\": null,\n", + " \"max_prompt_tokens\": null,\n", + " \"metadata\": {},\n", + " \"model\": \"gpt-4o\",\n", + " \"object\": \"thread.run\",\n", + " \"required_action\": null,\n", + " \"response_format\": \"auto\",\n", + " \"started_at\": 1731442455,\n", + " \"status\": \"queued\",\n", + " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", + " \"tool_choice\": \"auto\",\n", + " \"tools\": [\n", + " {\n", + " \"type\": \"code_interpreter\"\n", + " },\n", + " {\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"ticker_symbol\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The ticker symbol of the stock\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"ticker_symbol\"\n", + " ]\n", + " },\n", + " \"strict\": false\n", + " },\n", + " \"type\": \"function\"\n", + " }\n", + " ],\n", + " \"truncation_strategy\": {\n", + " \"type\": \"auto\",\n", + " \"last_messages\": null\n", + " },\n", + " \"usage\": null,\n", + " \"temperature\": 1.0,\n", + " \"top_p\": 1.0,\n", + " \"tool_resources\": {},\n", + " \"parallel_tool_calls\": true\n", + "}\n", + "Waiting for the Assistant to process...\n", + "{\n", + " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", + " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", + " \"cancelled_at\": null,\n", + " \"completed_at\": null,\n", + " \"created_at\": 1731442454,\n", + " \"expires_at\": 1731443054,\n", + " \"failed_at\": null,\n", + " \"incomplete_details\": null,\n", + " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", + " \"last_error\": null,\n", + " \"max_completion_tokens\": null,\n", + " \"max_prompt_tokens\": null,\n", + " \"metadata\": {},\n", + " \"model\": \"gpt-4o\",\n", + " \"object\": \"thread.run\",\n", + " \"required_action\": null,\n", + " \"response_format\": \"auto\",\n", + " \"started_at\": 1731442460,\n", + " \"status\": \"in_progress\",\n", + " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", + " \"tool_choice\": \"auto\",\n", + " \"tools\": [\n", + " {\n", + " \"type\": \"code_interpreter\"\n", + " },\n", + " {\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"ticker_symbol\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The ticker symbol of the stock\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"ticker_symbol\"\n", + " ]\n", + " },\n", + " \"strict\": false\n", + " },\n", + " \"type\": \"function\"\n", + " }\n", + " ],\n", + " \"truncation_strategy\": {\n", + " \"type\": \"auto\",\n", + " \"last_messages\": null\n", + " },\n", + " \"usage\": null,\n", + " \"temperature\": 1.0,\n", + " \"top_p\": 1.0,\n", + " \"tool_resources\": {},\n", + " \"parallel_tool_calls\": true\n", + "}\n", + "Waiting for the Assistant to process...\n", + "{\n", + " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", + " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", + " \"cancelled_at\": null,\n", + " \"completed_at\": null,\n", + " \"created_at\": 1731442454,\n", + " \"expires_at\": 1731443054,\n", + " \"failed_at\": null,\n", + " \"incomplete_details\": null,\n", + " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", + " \"last_error\": null,\n", + " \"max_completion_tokens\": null,\n", + " \"max_prompt_tokens\": null,\n", + " \"metadata\": {},\n", + " \"model\": \"gpt-4o\",\n", + " \"object\": \"thread.run\",\n", + " \"required_action\": null,\n", + " \"response_format\": \"auto\",\n", + " \"started_at\": 1731442460,\n", + " \"status\": \"in_progress\",\n", + " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", + " \"tool_choice\": \"auto\",\n", + " \"tools\": [\n", + " {\n", + " \"type\": \"code_interpreter\"\n", + " },\n", + " {\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"ticker_symbol\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The ticker symbol of the stock\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"ticker_symbol\"\n", + " ]\n", + " },\n", + " \"strict\": false\n", + " },\n", + " \"type\": \"function\"\n", + " }\n", + " ],\n", + " \"truncation_strategy\": {\n", + " \"type\": \"auto\",\n", + " \"last_messages\": null\n", + " },\n", + " \"usage\": null,\n", + " \"temperature\": 1.0,\n", + " \"top_p\": 1.0,\n", + " \"tool_resources\": {},\n", + " \"parallel_tool_calls\": true\n", + "}\n", + "Waiting for the Assistant to process...\n", + "{\n", + " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", + " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", + " \"cancelled_at\": null,\n", + " \"completed_at\": null,\n", + " \"created_at\": 1731442454,\n", + " \"expires_at\": null,\n", + " \"failed_at\": 1731442472,\n", + " \"incomplete_details\": null,\n", + " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", + " \"last_error\": {\n", + " \"code\": \"rate_limit_exceeded\",\n", + " \"message\": \"Rate limit is exceeded. Try again in 43 seconds.\"\n", + " },\n", + " \"max_completion_tokens\": null,\n", + " \"max_prompt_tokens\": null,\n", + " \"metadata\": {},\n", + " \"model\": \"gpt-4o\",\n", + " \"object\": \"thread.run\",\n", + " \"required_action\": null,\n", + " \"response_format\": \"auto\",\n", + " \"started_at\": 1731442460,\n", + " \"status\": \"failed\",\n", + " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", + " \"tool_choice\": \"auto\",\n", + " \"tools\": [\n", + " {\n", + " \"type\": \"code_interpreter\"\n", + " },\n", + " {\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"ticker_symbol\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The ticker symbol of the stock\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"ticker_symbol\"\n", + " ]\n", + " },\n", + " \"strict\": false\n", + " },\n", + " \"type\": \"function\"\n", + " }\n", + " ],\n", + " \"truncation_strategy\": {\n", + " \"type\": \"auto\",\n", + " \"last_messages\": null\n", + " },\n", + " \"usage\": {\n", + " \"completion_tokens\": 171,\n", + " \"prompt_tokens\": 523,\n", + " \"total_tokens\": 694\n", + " },\n", + " \"temperature\": 1.0,\n", + " \"top_p\": 1.0,\n", + " \"tool_resources\": {},\n", + " \"parallel_tool_calls\": true\n", + "}\n", + "Assistant run failed. Please try again.\n" + ] + } + ], + "source": [ + "import json\n", + "import time\n", + "\n", + "\n", + "available_functions = {\"fetch_stock_price\": fetch_stock_price}\n", + "\n", + "while True:\n", + "\n", + " # Retrieve the run status\n", + " run = openai_client.beta.threads.runs.retrieve(\n", + " thread_id=thread.id,\n", + " run_id=run.id\n", + " )\n", + " print(run.model_dump_json(indent=4))\n", + "\n", + " if run.status == \"failed\":\n", + " print(\"Assistant run failed. Please try again.\")\n", + " break\n", + " elif run.status == \"completed\":\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread.id)\n", + "\n", + " # Loop through messages and print content based on role\n", + " for msg in messages.data:\n", + " role = msg.role\n", + " content = msg.content[0].text.value\n", + " print(f\"{role.capitalize()}: {content}\")\n", + " break\n", + " elif run.status == \"requires_action\":\n", + " print(\"Function Calling ...\")\n", + " tool_responses = []\n", + " if (\n", + " run.required_action.type == \"submit_tool_outputs\"\n", + " and run.required_action.submit_tool_outputs.tool_calls is not None\n", + " ):\n", + " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", + "\n", + " for call in tool_calls:\n", + " if call.type == \"function\":\n", + " if call.function.name not in available_functions:\n", + " raise Exception(\"Function requested by the model does not exist\")\n", + " function_to_call = available_functions[call.function.name]\n", + " tool_response = function_to_call(**json.loads(call.function.arguments))\n", + " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", + " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", + "\n", + " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", + " )\n", + "\n", + " print(\"Function called successfully.\")\n", + " else:\n", + " print(\"Waiting for the Assistant to process...\")\n", + " time.sleep(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Cleanup Resources**\n", + "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources. Run this cell at the end of your session to clean up.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "AssistantDeleted(id='asst_0F1BeDTYLExyx8GfFpuJCrsT', deleted=True, object='assistant.deleted')\n" + ] + } + ], + "source": [ + "response = openai_client.beta.assistants.delete(assistant.id)\n", + "print(response)\n", + "\n", + "# Optionally delete any other temporary files or datas\n", + "# Note: Any uploaded files to OpenAI could also be cleaned up if needed\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----------------\n", + "\n", + "## Scratch Pad" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nimport time\\nfrom IPython.display import clear_output\\n\\nstart_time = time.time()\\n\\nstatus = run.status\\n\\nwhile status not in [\"completed\", \"cancelled\", \"expired\", \"failed\"]:\\n time.sleep(5)\\n run = openai_client.beta.threads.runs.retrieve(thread_id=thread.id,run_id=run.id)\\n print(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\\n status = run.status\\n print(f\\'Status: {status}\\')\\n clear_output(wait=True)\\n\\nmessages = openai_client.beta.threads.messages.list(\\n thread_id=thread.id\\n) \\n\\nprint(f\\'Status: {status}\\')\\nprint(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\\nprint(messages.model_dump_json(indent=2))\\n'" + ] + }, + "execution_count": 61, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "import time\n", + "from IPython.display import clear_output\n", + "\n", + "start_time = time.time()\n", + "\n", + "status = run.status\n", + "\n", + "while status not in [\"completed\", \"cancelled\", \"expired\", \"failed\"]:\n", + " time.sleep(5)\n", + " run = openai_client.beta.threads.runs.retrieve(thread_id=thread.id,run_id=run.id)\n", + " print(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\n", + " status = run.status\n", + " print(f'Status: {status}')\n", + " clear_output(wait=True)\n", + "\n", + "messages = openai_client.beta.threads.messages.list(\n", + " thread_id=thread.id\n", + ") \n", + "\n", + "print(f'Status: {status}')\n", + "print(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\n", + "print(messages.model_dump_json(indent=2))\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Everything after deployment --- everything else should be in notebook (data plane - private endpoint) --- before should not, its control plane (public only)\n", + "\n", + "1. Portal Creation for Deployment (note iteration two, bicep code??)\n", + "2. Assistant Creation (API)\n", + " - code to do it not portal (delete for cleanup)\n", + "3. Create Thread, Message, Thread run (instructs assistant to create messages) - wait for complete (look at SDK to do this), Listing Messages, Check history of the thread (will see my message, and one from assistant) first message response will be answer (POST/THREADS, POST/THREADS Messages, POST Threads thr)\n", + " - POST /threads\n", + " - POST /threads/:thread_id/messages\n", + " - POST /threads/:thread_id/runs\n", + " - GET /threads/:thread_id/runs/:run_id\n", + " - GET /threads/:thread_id/messages\n", + "4. " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/samples/investment_advisor/data/investment_portfolio.csv b/samples/investment_advisor/data/investment_portfolio.csv new file mode 100644 index 00000000..bb2df97b --- /dev/null +++ b/samples/investment_advisor/data/investment_portfolio.csv @@ -0,0 +1,7 @@ +Symbol,Average_Cost,QTY +MSFT,200,300 +AAPL,114,200 +amzn,125,50 +TSLA,900,100 +NfLx,540,80 +NVDA,450,50 \ No newline at end of file diff --git a/samples/investment_advisor/requirements.txt b/samples/investment_advisor/requirements.txt new file mode 100644 index 00000000..226deed0 --- /dev/null +++ b/samples/investment_advisor/requirements.txt @@ -0,0 +1,4 @@ +pandas==2.2.3 +yfinance==0.2.48 +openai==1.30.1 +python-dotenv==1.0.1 \ No newline at end of file From d45baab5fdf803df6f283e7ade3e1d405da55e6a Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Tue, 12 Nov 2024 15:28:58 -0500 Subject: [PATCH 117/180] adjust gitignore for venv --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 8a30d258..afddf1fc 100644 --- a/.gitignore +++ b/.gitignore @@ -396,3 +396,7 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml + +# Virtual Environments +.venv +.env \ No newline at end of file From d2ccb757ab7e482e4c89737cf69fba4656637ec7 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 15:30:38 -0500 Subject: [PATCH 118/180] Update quickstart.md --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index 1dc99f03..a3d27d60 100644 --- a/quickstart.md +++ b/quickstart.md @@ -69,7 +69,7 @@ If you already have these resources set up, skip to the [configure and run your
- Option 1: Use standard agent configuration. + Option 1: Use standard agent setup. - Download the `standard-agent.bicep` file, `standard-agent-identity.bicep` file, and the `modules-standard` folder to your project directory. Your directory should look like this @@ -116,7 +116,7 @@ If you already have these resources set up, skip to the [configure and run your
- Option 2: Use custom agent configuration. + Option 2: Use custom agent setup.
From 0f80686c835f6d89d10c796ce84fcf66cdac7581 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 17:31:08 -0500 Subject: [PATCH 119/180] renaming agent setup --- ...entity.bicep => basic-agent-identity.bicep | 6 +- byo-agent.bicep => basic-agent-keys.bicep | 72 +++----- basic-agent.parameters.json | 36 ++++ .../basic-ai-hub-identity.bicep | 0 .../basic-ai-hub-keys.bicep | 54 +----- .../basic-ai-project-identity.bicep | 0 modules-basic/basic-ai-project-keys.bicep | 42 +++++ modules-basic/basic-dependent-resources.bicep | 134 +++++++++++++++ modules-byo/byo-ai-project.bicep | 121 -------------- modules-byo/byo-dependent-resources.bicep | 157 ------------------ modules-standard/standard-ai-hub.bicep | 54 +++++- modules-standard/standard-ai-project.bicep | 81 ++++++++- .../standard-dependent-resources.bicep | 139 +++++++++------- standard-agent.bicep | 66 +++++--- standard-agent.parameters.json | 88 ++++++---- 15 files changed, 554 insertions(+), 496 deletions(-) rename standard-agent-identity.bicep => basic-agent-identity.bicep (94%) rename byo-agent.bicep => basic-agent-keys.bicep (67%) create mode 100644 basic-agent.parameters.json rename modules-standard/standard-ai-hub-identity.bicep => modules-basic/basic-ai-hub-identity.bicep (100%) rename modules-byo/byo-ai-hub.bicep => modules-basic/basic-ai-hub-keys.bicep (55%) rename modules-standard/standard-ai-project-identity.bicep => modules-basic/basic-ai-project-identity.bicep (100%) create mode 100644 modules-basic/basic-ai-project-keys.bicep create mode 100644 modules-basic/basic-dependent-resources.bicep delete mode 100644 modules-byo/byo-ai-project.bicep delete mode 100644 modules-byo/byo-dependent-resources.bicep diff --git a/standard-agent-identity.bicep b/basic-agent-identity.bicep similarity index 94% rename from standard-agent-identity.bicep rename to basic-agent-identity.bicep index 46a32769..5a480a94 100644 --- a/standard-agent-identity.bicep +++ b/basic-agent-identity.bicep @@ -62,7 +62,7 @@ param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) // Dependent resources for the Azure Machine Learning workspace -module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { +module aiDependencies 'modules-basic/basic-dependent-resources.bicep' = { name: 'dependencies-${name}-${uniqueSuffix}-deployment' params: { aiServicesName: '${aiServicesName}${uniqueSuffix}' @@ -80,7 +80,7 @@ module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { } } -module aiHub 'modules-standard/standard-ai-hub-identity.bicep' = { +module aiHub 'modules-basic/basic-ai-hub-identity.bicep' = { name: 'ai-${name}-${uniqueSuffix}-deployment' params: { // workspace organization @@ -98,7 +98,7 @@ module aiHub 'modules-standard/standard-ai-hub-identity.bicep' = { } } -module aiProject 'modules-standard/standard-ai-project-identity.bicep' = { +module aiProject 'modules-basic/basic-ai-project-identity.bicep' = { name: 'ai-${projectName}-${uniqueSuffix}-deployment' params: { // workspace organization diff --git a/byo-agent.bicep b/basic-agent-keys.bicep similarity index 67% rename from byo-agent.bicep rename to basic-agent-keys.bicep index ac466d87..d252e23b 100644 --- a/byo-agent.bicep +++ b/basic-agent-keys.bicep @@ -4,22 +4,22 @@ @minLength(2) @maxLength(12) @description('Name for the AI resource and used to derive name of dependent resources.') -param aiHubName string = 'hub-demo' +param aiHubName string = 'standard-hub' -@description('Friendly name for your Hub resource') -param aiHubFriendlyName string = 'Agents Hub resource' +@description('Friendly name for your Azure AI resource') +param aiHubFriendlyName string = 'Agents standard hub resource' @description('Description of your Azure AI resource dispayed in AI studio') -param aiHubDescription string = 'This is an example AI resource for use in Azure AI Studio.' +param aiHubDescription string = 'A standard hub resource required for the agent setup.' -@description('Name for the AI project resources.') -param aiProjectName string = 'project-demo' +@description('Name for the project') +param aiProjectName string = 'standard-project' @description('Friendly name for your Azure AI resource') -param aiProjectFriendlyName string = 'Agents Project resource' +param aiProjectFriendlyName string = 'Agents standard project resource' @description('Description of your Azure AI resource dispayed in AI studio') -param aiProjectDescription string = 'This is an example AI Project resource for use in Azure AI Studio.' +param aiProjectDescription string = 'A standard project resource required for the agent setup.' @description('Azure region used for the deployment of all resources.') param location string = resourceGroup().location @@ -27,18 +27,6 @@ param location string = resourceGroup().location @description('Set of tags to apply to all resources.') param tags object = {} -@description('Name of the Azure AI Search account') -param aiSearchName string = 'agent-ai-search' - -@description('Name for capabilityHost.') -param capabilityHostName string = 'caphost1' - -@description('Name of the storage account') -param storageName string = 'agent-storage' - -@description('Name of the Azure AI Services account') -param aiServicesName string = 'agent-ai-services' - @description('Model name for deployment') param modelName string = 'gpt-4o-mini' @@ -57,26 +45,28 @@ param modelCapacity int = 10 @description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') param modelLocation string = 'eastus' - // Variables var name = toLower('${aiHubName}') var projectName = toLower('${aiProjectName}') +@description('Name of the storage account') +param storageName string = 'agent-storage' + +@description('Name of the Azure AI Services account') +param aiServicesName string = 'agent-ai-services' + // Create a short, unique suffix, that will be unique to each resource group // var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) - // Dependent resources for the Azure Machine Learning workspace -module aiDependencies 'modules-byo/byo-dependent-resources.bicep' = { +module aiDependencies 'modules-basic/basic-dependent-resources.bicep' = { name: 'dependencies-${name}-${uniqueSuffix}-deployment' params: { - location: location - storageName: '${storageName}${uniqueSuffix}' - keyvaultName: 'kv-${name}-${uniqueSuffix}' aiServicesName: '${aiServicesName}${uniqueSuffix}' - aiSearchName: '${aiSearchName}-${uniqueSuffix}' + storageName: '${storageName}${uniqueSuffix}' + location: location tags: tags // Model deployment parameters @@ -84,12 +74,12 @@ module aiDependencies 'modules-byo/byo-dependent-resources.bicep' = { modelFormat: modelFormat modelVersion: modelVersion modelSkuName: modelSkuName - modelCapacity: modelCapacity + modelCapacity: modelCapacity modelLocation: modelLocation - } + } } -module aiHub 'modules-byo/byo-ai-hub.bicep' = { +module aiHub 'modules-basic/basic-ai-hub-keys.bicep' = { name: 'ai-${name}-${uniqueSuffix}-deployment' params: { // workspace organization @@ -98,21 +88,16 @@ module aiHub 'modules-byo/byo-ai-hub.bicep' = { aiHubDescription: aiHubDescription location: location tags: tags - capabilityHostName: capabilityHostName - modelLocation: modelLocation - - aiSearchName: aiDependencies.outputs.aiSearchName - aiSearchId: aiDependencies.outputs.aisearchID + // dependent resources + modelLocation: modelLocation + storageAccountId: aiDependencies.outputs.storageId aiServicesId: aiDependencies.outputs.aiservicesID aiServicesTarget: aiDependencies.outputs.aiservicesTarget - keyVaultId: aiDependencies.outputs.keyvaultId - storageAccountId: aiDependencies.outputs.storageId } } - -module aiProject 'modules-byo/byo-ai-project.bicep' = { +module aiProject 'modules-basic/basic-ai-project-keys.bicep' = { name: 'ai-${projectName}-${uniqueSuffix}-deployment' params: { // workspace organization @@ -121,15 +106,8 @@ module aiProject 'modules-byo/byo-ai-project.bicep' = { aiProjectDescription: aiProjectDescription location: location tags: tags - - capabilityHostName: capabilityHostName + // dependent resources - aiServicesName: '${aiServicesName}${uniqueSuffix}' aiHubId: aiHub.outputs.aiHubID - acsConnectionName: aiHub.outputs.acsConnectionName - aoaiConnectionName: aiHub.outputs.aoaiConnectionName } } - -output ENTERPRISE_AGENTS_ENDPOINT string = aiProject.outputs.enterpriseAgentsEndpoint - diff --git a/basic-agent.parameters.json b/basic-agent.parameters.json new file mode 100644 index 00000000..bbd56445 --- /dev/null +++ b/basic-agent.parameters.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "aiHubName": { + "value": "standard-hub" + }, + "aiProjectName": { + "value": "standard-project" + }, + "modelName": { + "value": "gpt-4o-mini" + }, + "modelFormat": { + "value": "OpenAI" + }, + "modelVersion": { + "value": "2024-07-18" + }, + "modelSkuName": { + "value": "GlobalStandard" + }, + "modelCapacity": { + "value": 10 + }, + "modelLocation": { + "value": "eastus" + }, + "storageName": { + "value": "agent-storage" + }, + "aiServicesName": { + "value": "agent-ai-services" + } + } +} diff --git a/modules-standard/standard-ai-hub-identity.bicep b/modules-basic/basic-ai-hub-identity.bicep similarity index 100% rename from modules-standard/standard-ai-hub-identity.bicep rename to modules-basic/basic-ai-hub-identity.bicep diff --git a/modules-byo/byo-ai-hub.bicep b/modules-basic/basic-ai-hub-keys.bicep similarity index 55% rename from modules-byo/byo-ai-hub.bicep rename to modules-basic/basic-ai-hub-keys.bicep index e41596a9..d848c457 100644 --- a/modules-byo/byo-ai-hub.bicep +++ b/modules-basic/basic-ai-hub-keys.bicep @@ -15,33 +15,17 @@ param aiHubFriendlyName string = aiHubName @description('AI hub description') param aiHubDescription string -@description('Resource ID of the key vault resource for storing connection strings') -param keyVaultId string - @description('Resource ID of the storage account resource for storing experimentation outputs') param storageAccountId string -@description('Model/AI Resource deployment location') -param modelLocation string - @description('Resource ID of the AI Services resource') param aiServicesId string @description('Resource ID of the AI Services endpoint') param aiServicesTarget string -@description('Name AI Search resource') -param aiSearchName string - -@description('Resource ID of the AI Search resource') -param aiSearchId string - -@description('Name for capabilityHost.') -param capabilityHostName string = 'caphost1' - -var acsConnectionName = '${aiHubName}-connection-AISearch' - -var aoaiConnection = '${aiHubName}-connection-AIServices_aoai' +@description('Model/AI Resource deployment location') +param modelLocation string resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { name: aiHubName @@ -56,7 +40,6 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' description: aiHubDescription // dependent resources - keyVault: keyVaultId storageAccount: storageAccountId } kind: 'hub' @@ -66,8 +49,12 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' properties: { category: 'AIServices' target: aiServicesTarget - authType: 'AAD' + // useWorkspaceManagedIdentity: true + authType: 'ApiKey' isSharedToAll: true + credentials: { + key: '${listKeys(aiServicesId, '2022-10-01').key1}' + } metadata: { ApiType: 'Azure' ResourceId: aiServicesId @@ -75,32 +62,7 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' } } } - resource hub_connection_azureai_search 'connections@2024-07-01-preview' = { - name: acsConnectionName - properties: { - category: 'CognitiveSearch' - target: 'https://${aiSearchName}.search.windows.net' - authType: 'AAD' - //useWorkspaceManagedIdentity: false - isSharedToAll: true - metadata: { - ApiType: 'Azure' - ResourceId: aiSearchId - location: location - } - } - } - - // Resource definition for the capability host - resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { - name: '${aiHubName}-${capabilityHostName}' - properties: { - capabilityHostKind: 'Agents' - } - } - } + output aiHubID string = aiHub.id -output aoaiConnectionName string = aoaiConnection -output acsConnectionName string = acsConnectionName diff --git a/modules-standard/standard-ai-project-identity.bicep b/modules-basic/basic-ai-project-identity.bicep similarity index 100% rename from modules-standard/standard-ai-project-identity.bicep rename to modules-basic/basic-ai-project-identity.bicep diff --git a/modules-basic/basic-ai-project-keys.bicep b/modules-basic/basic-ai-project-keys.bicep new file mode 100644 index 00000000..764ca201 --- /dev/null +++ b/modules-basic/basic-ai-project-keys.bicep @@ -0,0 +1,42 @@ +// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider + +@description('Azure region of the deployment') +param location string + +@description('Tags to add to the resources') +param tags object + +@description('AI Project name') +param aiProjectName string + +@description('AI Project display name') +param aiProjectFriendlyName string = aiProjectName + +@description('AI Project description') +param aiProjectDescription string + +@description('Resource ID of the AI Hub resource') +param aiHubId string + + + +resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { + name: aiProjectName + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + // organization + friendlyName: aiProjectFriendlyName + description: aiProjectDescription + + // dependent resources + hubResourceId: aiHubId + + } + kind: 'project' +} + +output aiProjectID string = aiProject.id diff --git a/modules-basic/basic-dependent-resources.bicep b/modules-basic/basic-dependent-resources.bicep new file mode 100644 index 00000000..e048f685 --- /dev/null +++ b/modules-basic/basic-dependent-resources.bicep @@ -0,0 +1,134 @@ +@description('Azure region of the deployment') +param location string = resourceGroup().location + +@description('Tags to add to the resources') +param tags object = {} + +@description('AI services name') +param aiServicesName string + +@description('Model name for deployment') +param modelName string + +@description('Model format for deployment') +param modelFormat string + +@description('Model version for deployment') +param modelVersion string + +@description('Model deployment SKU name') +param modelSkuName string + +@description('Model deployment capacity') +param modelCapacity int + +@description('Model/AI Resource deployment location') +param modelLocation string + +resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { + name: aiServicesName + location: modelLocation + sku: { + name: 'S0' + } + kind: 'AIServices' // or 'OpenAI' + identity: { + type: 'SystemAssigned' + } + properties: { + customSubDomainName: toLower('${toLower(aiServicesName)}') + apiProperties: { + statisticsEnabled: false + } + publicNetworkAccess: 'Enabled' + } +} + +resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { + parent: aiServices + name: modelName + sku : { + capacity: modelCapacity + name: modelSkuName + } + properties: { + model:{ + name: modelName + format: modelFormat + version: modelVersion + } + } +} + +@description('Name of the storage account') +param storageName string + +@allowed([ + 'Standard_LRS' + 'Standard_ZRS' + 'Standard_GRS' + 'Standard_GZRS' + 'Standard_RAGRS' + 'Standard_RAGZRS' + 'Premium_LRS' + 'Premium_ZRS' +]) + +@description('Storage SKU') +param storageSkuName string = 'Standard_LRS' + +var storageNameCleaned = replace(storageName, '-', '') + +resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { + name: storageNameCleaned + location: location + tags: tags + sku: { + name: storageSkuName + } + kind: 'StorageV2' + properties: { + accessTier: 'Hot' + allowBlobPublicAccess: false + allowCrossTenantReplication: false + allowSharedKeyAccess: true + encryption: { + keySource: 'Microsoft.Storage' + requireInfrastructureEncryption: false + services: { + blob: { + enabled: true + keyType: 'Account' + } + file: { + enabled: true + keyType: 'Account' + } + queue: { + enabled: true + keyType: 'Service' + } + table: { + enabled: true + keyType: 'Service' + } + } + } + isHnsEnabled: false + isNfsV3Enabled: false + keyPolicy: { + keyExpirationPeriodInDays: 7 + } + largeFileSharesState: 'Disabled' + minimumTlsVersion: 'TLS1_2' + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + supportsHttpsTrafficOnly: true + } +} + +output aiservicesID string = aiServices.id +output aiservicesTarget string = aiServices.properties.endpoint +output storageId string = storage.id diff --git a/modules-byo/byo-ai-project.bicep b/modules-byo/byo-ai-project.bicep deleted file mode 100644 index 3d911cc8..00000000 --- a/modules-byo/byo-ai-project.bicep +++ /dev/null @@ -1,121 +0,0 @@ -// Creates an Azure AI resource with proxied endpoints for the Azure AI services provider - -@description('Azure region of the deployment') -param location string - -@description('Tags to add to the resources') -param tags object - -@description('AI Project name') -param aiProjectName string - -@description('AI Project display name') -param aiProjectFriendlyName string = aiProjectName - -@description('AI Project description') -param aiProjectDescription string - -@description('Resource ID of the AI Hub resource') -param aiHubId string - -@description('Name for capabilityHost.') -param capabilityHostName string = 'caphost1' - -@description('Name for ACS connection.') -param acsConnectionName string - -@description('Name for ACS connection.') -param aoaiConnectionName string - -param aiServicesName string - -resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { - name: aiServicesName -} - - -var storageConnections = ['${aiProjectName}/workspaceblobstore'] -var aiSearchConnection = ['${acsConnectionName}'] -var aiServiceConnections = ['${aoaiConnectionName}'] - - -resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { - name: aiProjectName - location: location - tags: tags - identity: { - type: 'SystemAssigned' - } - properties: { - // organization - friendlyName: aiProjectFriendlyName - description: aiProjectDescription - - // dependent resources - hubResourceId: aiHubId - - } - kind: 'project' - - // Resource definition for the capability host - resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { - name: '${aiProjectName}-${capabilityHostName}' - properties: { - capabilityHostKind: 'Agents' - aiServicesConnections: aiServiceConnections - vectorStoreConnections: aiSearchConnection - storageConnections: storageConnections - } - } -} - -resource cognitiveServicesContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' - scope: resourceGroup() -} - -resource cognitiveServicesContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01'= { - scope: aiServices - name: guid(aiServices.id, cognitiveServicesContributorRole.id, aiProject.id) - properties: { - principalId: aiProject.identity.principalId - roleDefinitionId: cognitiveServicesContributorRole.id - principalType: 'ServicePrincipal' - } - } - - -resource cognitiveServicesOpenAIUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - scope: resourceGroup() -} -resource cognitiveServicesOpenAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: aiServices - name: guid(aiProject.id, cognitiveServicesOpenAIUserRole.id, aiServices.id) - properties: { - principalId: aiProject.identity.principalId - roleDefinitionId: cognitiveServicesOpenAIUserRole.id - principalType: 'ServicePrincipal' - } -} - -resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: 'a97b65f3-24c7-4388-baec-2e87135dc908' - scope: resourceGroup() -} - -resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: aiServices - name: guid(aiProject.id, cognitiveServicesUserRole.id, aiServices.id) - properties: { - principalId: aiProject.identity.principalId - roleDefinitionId: cognitiveServicesUserRole.id - principalType: 'ServicePrincipal' - } -} - -output aiProjectName string = aiProject.name -output aiProjectResourceId string = aiProject.id -output aiProjectWorkspaceId string = aiProject.properties.workspaceId - -output enterpriseAgentsEndpoint string = aiProject.tags.AgentsEndpointUri diff --git a/modules-byo/byo-dependent-resources.bicep b/modules-byo/byo-dependent-resources.bicep deleted file mode 100644 index 5540356c..00000000 --- a/modules-byo/byo-dependent-resources.bicep +++ /dev/null @@ -1,157 +0,0 @@ -// Creates Azure dependent resources for Azure AI studio - -@description('Azure region of the deployment') -param location string = resourceGroup().location - -@description('Tags to add to the resources') -param tags object = {} - -@description('AI services name') -param aiServicesName string - -@description('The name of the Key Vault') -param keyvaultName string - -@description('The name of the AI Search resource') -param aiSearchName string - -@description('Name of the storage account') -param storageName string - -var storageNameCleaned = replace(storageName, '-', '') - -@description('Model name for deployment') -param modelName string - -@description('Model format for deployment') -param modelFormat string - -@description('Model version for deployment') -param modelVersion string - -@description('Model deployment SKU name') -param modelSkuName string - -@description('Model deployment capacity') -param modelCapacity int - -@description('Model/AI Resource deployment location') -param modelLocation string - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyvaultName - location: location - tags: tags - properties: { - createMode: 'default' - enabledForDeployment: false - enabledForDiskEncryption: false - enabledForTemplateDeployment: false - enableSoftDelete: true - enableRbacAuthorization: true - enablePurgeProtection: true - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Deny' - } - sku: { - family: 'A' - name: 'standard' - } - softDeleteRetentionInDays: 7 - tenantId: subscription().tenantId - } -} - - -resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { - name: aiServicesName - location: modelLocation - sku: { - name: 'S0' - } - kind: 'AIServices' // or 'OpenAI' - identity: { - type: 'SystemAssigned' - } - properties: { - customSubDomainName: toLower('${(aiServicesName)}') - apiProperties: { - statisticsEnabled: false - } - publicNetworkAccess: 'Enabled' - } -} -resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { - parent: aiServices - name: modelName - sku : { - capacity: modelCapacity - name: modelSkuName - } - properties: { - model:{ - name: modelName - format: modelFormat - version: modelVersion - } - } -} - -resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = { - name: aiSearchName - location: location - tags: tags - identity: { - type: 'SystemAssigned' - } - properties: { - disableLocalAuth: false - authOptions: { aadOrApiKey: { aadAuthFailureMode: 'http401WithBearerChallenge'}} - encryptionWithCmk: { - enforcement: 'Unspecified' - } - hostingMode: 'default' - partitionCount: 3 - publicNetworkAccess: 'enabled' - replicaCount: 3 - semanticSearch: 'disabled' - } - sku: { - name: 'standard' - } -} - -// Some regions doesn't support Standard Zone-Redundant storage, need to use Geo-redundant storage -param noZRSRegions array = ['southindia', 'westus'] -param sku object = contains(noZRSRegions, location) ? { name: 'Standard_GRS' } : { name: 'Standard_ZRS' } - -resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = { - name: storageNameCleaned - location: location - kind: 'StorageV2' - sku: sku - properties: { - minimumTlsVersion: 'TLS1_2' - allowBlobPublicAccess: false - publicNetworkAccess: 'Enabled' - networkAcls: { - bypass: 'AzureServices' - defaultAction: 'Allow' - virtualNetworkRules: [] - } - allowSharedKeyAccess: false - } -} - -output aiServicesName string = aiServices.name -output aiservicesID string = aiServices.id -output aiservicesTarget string = aiServices.properties.endpoint - -output aiSearchName string = aiSearch.name -output aisearchID string = aiSearch.id - -output storageAccountName string = storage.name -output storageId string = storage.id - -output keyvaultId string = keyVault.id diff --git a/modules-standard/standard-ai-hub.bicep b/modules-standard/standard-ai-hub.bicep index d848c457..e41596a9 100644 --- a/modules-standard/standard-ai-hub.bicep +++ b/modules-standard/standard-ai-hub.bicep @@ -15,17 +15,33 @@ param aiHubFriendlyName string = aiHubName @description('AI hub description') param aiHubDescription string +@description('Resource ID of the key vault resource for storing connection strings') +param keyVaultId string + @description('Resource ID of the storage account resource for storing experimentation outputs') param storageAccountId string +@description('Model/AI Resource deployment location') +param modelLocation string + @description('Resource ID of the AI Services resource') param aiServicesId string @description('Resource ID of the AI Services endpoint') param aiServicesTarget string -@description('Model/AI Resource deployment location') -param modelLocation string +@description('Name AI Search resource') +param aiSearchName string + +@description('Resource ID of the AI Search resource') +param aiSearchId string + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +var acsConnectionName = '${aiHubName}-connection-AISearch' + +var aoaiConnection = '${aiHubName}-connection-AIServices_aoai' resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' = { name: aiHubName @@ -40,6 +56,7 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' description: aiHubDescription // dependent resources + keyVault: keyVaultId storageAccount: storageAccountId } kind: 'hub' @@ -49,12 +66,8 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' properties: { category: 'AIServices' target: aiServicesTarget - // useWorkspaceManagedIdentity: true - authType: 'ApiKey' + authType: 'AAD' isSharedToAll: true - credentials: { - key: '${listKeys(aiServicesId, '2022-10-01').key1}' - } metadata: { ApiType: 'Azure' ResourceId: aiServicesId @@ -62,7 +75,32 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' } } } -} + resource hub_connection_azureai_search 'connections@2024-07-01-preview' = { + name: acsConnectionName + properties: { + category: 'CognitiveSearch' + target: 'https://${aiSearchName}.search.windows.net' + authType: 'AAD' + //useWorkspaceManagedIdentity: false + isSharedToAll: true + metadata: { + ApiType: 'Azure' + ResourceId: aiSearchId + location: location + } + } + } + // Resource definition for the capability host + resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { + name: '${aiHubName}-${capabilityHostName}' + properties: { + capabilityHostKind: 'Agents' + } + } + +} output aiHubID string = aiHub.id +output aoaiConnectionName string = aoaiConnection +output acsConnectionName string = acsConnectionName diff --git a/modules-standard/standard-ai-project.bicep b/modules-standard/standard-ai-project.bicep index 764ca201..3d911cc8 100644 --- a/modules-standard/standard-ai-project.bicep +++ b/modules-standard/standard-ai-project.bicep @@ -18,6 +18,25 @@ param aiProjectDescription string @description('Resource ID of the AI Hub resource') param aiHubId string +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +@description('Name for ACS connection.') +param acsConnectionName string + +@description('Name for ACS connection.') +param aoaiConnectionName string + +param aiServicesName string + +resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { + name: aiServicesName +} + + +var storageConnections = ['${aiProjectName}/workspaceblobstore'] +var aiSearchConnection = ['${acsConnectionName}'] +var aiServiceConnections = ['${aoaiConnectionName}'] resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { @@ -37,6 +56,66 @@ resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-prev } kind: 'project' + + // Resource definition for the capability host + resource capabilityHost 'capabilityHosts@2024-10-01-preview' = { + name: '${aiProjectName}-${capabilityHostName}' + properties: { + capabilityHostKind: 'Agents' + aiServicesConnections: aiServiceConnections + vectorStoreConnections: aiSearchConnection + storageConnections: storageConnections + } + } +} + +resource cognitiveServicesContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + scope: resourceGroup() } -output aiProjectID string = aiProject.id +resource cognitiveServicesContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01'= { + scope: aiServices + name: guid(aiServices.id, cognitiveServicesContributorRole.id, aiProject.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesContributorRole.id + principalType: 'ServicePrincipal' + } + } + + +resource cognitiveServicesOpenAIUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + scope: resourceGroup() +} +resource cognitiveServicesOpenAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProject.id, cognitiveServicesOpenAIUserRole.id, aiServices.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesOpenAIUserRole.id + principalType: 'ServicePrincipal' + } +} + +resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: 'a97b65f3-24c7-4388-baec-2e87135dc908' + scope: resourceGroup() +} + +resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aiServices + name: guid(aiProject.id, cognitiveServicesUserRole.id, aiServices.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: cognitiveServicesUserRole.id + principalType: 'ServicePrincipal' + } +} + +output aiProjectName string = aiProject.name +output aiProjectResourceId string = aiProject.id +output aiProjectWorkspaceId string = aiProject.properties.workspaceId + +output enterpriseAgentsEndpoint string = aiProject.tags.AgentsEndpointUri diff --git a/modules-standard/standard-dependent-resources.bicep b/modules-standard/standard-dependent-resources.bicep index e048f685..5540356c 100644 --- a/modules-standard/standard-dependent-resources.bicep +++ b/modules-standard/standard-dependent-resources.bicep @@ -1,3 +1,5 @@ +// Creates Azure dependent resources for Azure AI studio + @description('Azure region of the deployment') param location string = resourceGroup().location @@ -7,6 +9,17 @@ param tags object = {} @description('AI services name') param aiServicesName string +@description('The name of the Key Vault') +param keyvaultName string + +@description('The name of the AI Search resource') +param aiSearchName string + +@description('Name of the storage account') +param storageName string + +var storageNameCleaned = replace(storageName, '-', '') + @description('Model name for deployment') param modelName string @@ -25,6 +38,32 @@ param modelCapacity int @description('Model/AI Resource deployment location') param modelLocation string +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyvaultName + location: location + tags: tags + properties: { + createMode: 'default' + enabledForDeployment: false + enabledForDiskEncryption: false + enabledForTemplateDeployment: false + enableSoftDelete: true + enableRbacAuthorization: true + enablePurgeProtection: true + networkAcls: { + bypass: 'AzureServices' + defaultAction: 'Deny' + } + sku: { + family: 'A' + name: 'standard' + } + softDeleteRetentionInDays: 7 + tenantId: subscription().tenantId + } +} + + resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = { name: aiServicesName location: modelLocation @@ -36,14 +75,13 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' = type: 'SystemAssigned' } properties: { - customSubDomainName: toLower('${toLower(aiServicesName)}') + customSubDomainName: toLower('${(aiServicesName)}') apiProperties: { statisticsEnabled: false } publicNetworkAccess: 'Enabled' } } - resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-06-01-preview'= { parent: aiServices name: modelName @@ -60,75 +98,60 @@ resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024- } } -@description('Name of the storage account') -param storageName string - -@allowed([ - 'Standard_LRS' - 'Standard_ZRS' - 'Standard_GRS' - 'Standard_GZRS' - 'Standard_RAGRS' - 'Standard_RAGZRS' - 'Premium_LRS' - 'Premium_ZRS' -]) - -@description('Storage SKU') -param storageSkuName string = 'Standard_LRS' - -var storageNameCleaned = replace(storageName, '-', '') - -resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = { - name: storageNameCleaned +resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = { + name: aiSearchName location: location tags: tags + identity: { + type: 'SystemAssigned' + } + properties: { + disableLocalAuth: false + authOptions: { aadOrApiKey: { aadAuthFailureMode: 'http401WithBearerChallenge'}} + encryptionWithCmk: { + enforcement: 'Unspecified' + } + hostingMode: 'default' + partitionCount: 3 + publicNetworkAccess: 'enabled' + replicaCount: 3 + semanticSearch: 'disabled' + } sku: { - name: storageSkuName + name: 'standard' } +} + +// Some regions doesn't support Standard Zone-Redundant storage, need to use Geo-redundant storage +param noZRSRegions array = ['southindia', 'westus'] +param sku object = contains(noZRSRegions, location) ? { name: 'Standard_GRS' } : { name: 'Standard_ZRS' } + +resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = { + name: storageNameCleaned + location: location kind: 'StorageV2' + sku: sku properties: { - accessTier: 'Hot' - allowBlobPublicAccess: false - allowCrossTenantReplication: false - allowSharedKeyAccess: true - encryption: { - keySource: 'Microsoft.Storage' - requireInfrastructureEncryption: false - services: { - blob: { - enabled: true - keyType: 'Account' - } - file: { - enabled: true - keyType: 'Account' - } - queue: { - enabled: true - keyType: 'Service' - } - table: { - enabled: true - keyType: 'Service' - } - } - } - isHnsEnabled: false - isNfsV3Enabled: false - keyPolicy: { - keyExpirationPeriodInDays: 7 - } - largeFileSharesState: 'Disabled' minimumTlsVersion: 'TLS1_2' + allowBlobPublicAccess: false + publicNetworkAccess: 'Enabled' networkAcls: { bypass: 'AzureServices' - defaultAction: 'Deny' + defaultAction: 'Allow' + virtualNetworkRules: [] } - supportsHttpsTrafficOnly: true + allowSharedKeyAccess: false } } +output aiServicesName string = aiServices.name output aiservicesID string = aiServices.id output aiservicesTarget string = aiServices.properties.endpoint + +output aiSearchName string = aiSearch.name +output aisearchID string = aiSearch.id + +output storageAccountName string = storage.name output storageId string = storage.id + +output keyvaultId string = keyVault.id diff --git a/standard-agent.bicep b/standard-agent.bicep index c0d59721..a7ef096f 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -4,22 +4,22 @@ @minLength(2) @maxLength(12) @description('Name for the AI resource and used to derive name of dependent resources.') -param aiHubName string = 'standard-hub' +param aiHubName string = 'hub-demo' -@description('Friendly name for your Azure AI resource') -param aiHubFriendlyName string = 'Agents standard hub resource' +@description('Friendly name for your Hub resource') +param aiHubFriendlyName string = 'Agents Hub resource' @description('Description of your Azure AI resource dispayed in AI studio') -param aiHubDescription string = 'A standard hub resource required for the agent setup.' +param aiHubDescription string = 'This is an example AI resource for use in Azure AI Studio.' -@description('Name for the project') -param aiProjectName string = 'standard-project' +@description('Name for the AI project resources.') +param aiProjectName string = 'project-demo' @description('Friendly name for your Azure AI resource') -param aiProjectFriendlyName string = 'Agents standard project resource' +param aiProjectFriendlyName string = 'Agents Project resource' @description('Description of your Azure AI resource dispayed in AI studio') -param aiProjectDescription string = 'A standard project resource required for the agent setup.' +param aiProjectDescription string = 'This is an example AI Project resource for use in Azure AI Studio.' @description('Azure region used for the deployment of all resources.') param location string = resourceGroup().location @@ -27,6 +27,18 @@ param location string = resourceGroup().location @description('Set of tags to apply to all resources.') param tags object = {} +@description('Name of the Azure AI Search account') +param aiSearchName string = 'agent-ai-search' + +@description('Name for capabilityHost.') +param capabilityHostName string = 'caphost1' + +@description('Name of the storage account') +param storageName string = 'agent-storage' + +@description('Name of the Azure AI Services account') +param aiServicesName string = 'agent-ai-services' + @description('Model name for deployment') param modelName string = 'gpt-4o-mini' @@ -45,28 +57,26 @@ param modelCapacity int = 10 @description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') param modelLocation string = 'eastus' + // Variables var name = toLower('${aiHubName}') var projectName = toLower('${aiProjectName}') -@description('Name of the storage account') -param storageName string = 'agent-storage' - -@description('Name of the Azure AI Services account') -param aiServicesName string = 'agent-ai-services' - // Create a short, unique suffix, that will be unique to each resource group // var uniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 4) param deploymentTimestamp string = utcNow('yyyyMMddHHmmss') var uniqueSuffix = substring(uniqueString('${resourceGroup().id}-${deploymentTimestamp}'), 0, 4) + // Dependent resources for the Azure Machine Learning workspace module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { name: 'dependencies-${name}-${uniqueSuffix}-deployment' params: { - aiServicesName: '${aiServicesName}${uniqueSuffix}' - storageName: '${storageName}${uniqueSuffix}' location: location + storageName: '${storageName}${uniqueSuffix}' + keyvaultName: 'kv-${name}-${uniqueSuffix}' + aiServicesName: '${aiServicesName}${uniqueSuffix}' + aiSearchName: '${aiSearchName}-${uniqueSuffix}' tags: tags // Model deployment parameters @@ -74,9 +84,9 @@ module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { modelFormat: modelFormat modelVersion: modelVersion modelSkuName: modelSkuName - modelCapacity: modelCapacity + modelCapacity: modelCapacity modelLocation: modelLocation - } + } } module aiHub 'modules-standard/standard-ai-hub.bicep' = { @@ -88,15 +98,20 @@ module aiHub 'modules-standard/standard-ai-hub.bicep' = { aiHubDescription: aiHubDescription location: location tags: tags - - // dependent resources + capabilityHostName: capabilityHostName modelLocation: modelLocation - storageAccountId: aiDependencies.outputs.storageId + + + aiSearchName: aiDependencies.outputs.aiSearchName + aiSearchId: aiDependencies.outputs.aisearchID aiServicesId: aiDependencies.outputs.aiservicesID aiServicesTarget: aiDependencies.outputs.aiservicesTarget + keyVaultId: aiDependencies.outputs.keyvaultId + storageAccountId: aiDependencies.outputs.storageId } } + module aiProject 'modules-standard/standard-ai-project.bicep' = { name: 'ai-${projectName}-${uniqueSuffix}-deployment' params: { @@ -106,8 +121,15 @@ module aiProject 'modules-standard/standard-ai-project.bicep' = { aiProjectDescription: aiProjectDescription location: location tags: tags - + + capabilityHostName: capabilityHostName // dependent resources + aiServicesName: '${aiServicesName}${uniqueSuffix}' aiHubId: aiHub.outputs.aiHubID + acsConnectionName: aiHub.outputs.acsConnectionName + aoaiConnectionName: aiHub.outputs.aoaiConnectionName } } + +output ENTERPRISE_AGENTS_ENDPOINT string = aiProject.outputs.enterpriseAgentsEndpoint + diff --git a/standard-agent.parameters.json b/standard-agent.parameters.json index bbd56445..67c336ba 100644 --- a/standard-agent.parameters.json +++ b/standard-agent.parameters.json @@ -1,36 +1,58 @@ { - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "aiHubName": { - "value": "standard-hub" - }, - "aiProjectName": { - "value": "standard-project" - }, - "modelName": { - "value": "gpt-4o-mini" - }, - "modelFormat": { - "value": "OpenAI" - }, - "modelVersion": { - "value": "2024-07-18" - }, - "modelSkuName": { - "value": "GlobalStandard" - }, - "modelCapacity": { - "value": 10 - }, - "modelLocation": { - "value": "eastus" - }, - "storageName": { - "value": "agent-storage" - }, - "aiServicesName": { - "value": "agent-ai-services" + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "aiHubName": { + "value": "hub-demo" + }, + "aiHubFriendlyName": { + "value": "Agents Hub resource" + }, + "aiHubDescription": { + "value": "This is an example AI resource for use in Azure AI Studio." + }, + "aiProjectName": { + "value": "project-demo" + }, + "aiProjectFriendlyName": { + "value": "Agents Project resource" + }, + "aiProjectDescription": { + "value": "This is an example AI Project resource for use in Azure AI Studio." + }, + "tags": { + "value": {} + }, + "aiSearchName": { + "value": "agent-ai-search" + }, + "capabilityHostName": { + "value": "caphost1" + }, + "storageName": { + "value": "agent-storage" + }, + "aiServicesName": { + "value": "agent-ai-services" + }, + "modelName": { + "value": "gpt-4o-mini" + }, + "modelFormat": { + "value": "OpenAI" + }, + "modelVersion": { + "value": "2024-07-18" + }, + "modelSkuName": { + "value": "GlobalStandard" + }, + "modelCapacity": { + "value": 10 + }, + "modelLocation": { + "value": "eastus" + } } } -} + \ No newline at end of file From 5235448ad92c64be6cc0ec49af6fc081e8890e92 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 17:52:09 -0500 Subject: [PATCH 120/180] updating docs naming --- quickstart.md | 32 ++++++++++++++++---------------- samples/file-search/readme.md | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/quickstart.md b/quickstart.md index a3d27d60..b870d840 100644 --- a/quickstart.md +++ b/quickstart.md @@ -62,32 +62,32 @@ If you already have these resources set up, skip to the [configure and run your 1. Choose Standard or Custom Agent Setup
- **Standard Setup**: Agents use multi-tenant search and storage resources fully managed by Microsoft. You won’t have visibility or control over these underlying Azure resources. + **Basic Setup**: Agents use multi-tenant search and storage resources fully managed by Microsoft. You won’t have visibility or control over these underlying Azure resources. - **Custom Setup**: Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage. + **Standard Setup**: Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage.
- Option 1: Use standard agent setup. + Option 1: Use basic agent setup. - - Download the `standard-agent.bicep` file, `standard-agent-identity.bicep` file, and the `modules-standard` folder to your project directory. Your directory should look like this + - Download the `basic-agent-keys.bicep` file, `basic-agent-identity.bicep` file, and the `modules-basic` folder to your project directory. Your directory should look like this ```console /my-project - - standard-agent.bicep - - standard-agent-identity.bicep - /modules-standard - - standard-ai-hub.bicep - - standard-ai-project.bicep - - standard-ai-hub-identity.bicep - - standard-ai-project-identity.bicep - - standard-dependent-resources.bicep + - basic-agent-keys.bicep + - basic-agent-identity.bicep + /modules-basic + - basic-ai-hub-keys.bicep + - basic-ai-project-keys.bicep + - basic-ai-hub-identity.bicep + - basic-ai-project-identity.bicep + - basic-dependent-resources.bicep ``` - Before deploying resources, decide which configuration file to use: - - `standard-agent.bicep`: Use this file to use API keys for authentication. - - `standard-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. + - `basic-agent-keys.bicep`: Use this file to use API keys for authentication. + - `basic-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. - Using the resource group you created in the previous step and one of the template files (either standard-agent.bicep or standard-agent-identity.bicep), run one of the following commands: @@ -104,7 +104,7 @@ If you already have these resources set up, skip to the [configure and run your az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` - - To customize additional parameters, including the OpenAI model deployment, download and edit the `standard-agent.parameters.json` file, then run: + - To customize additional parameters, including the OpenAI model deployment, download and edit the `basic-agent.parameters.json` file, then run: ```console az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters @standard-agent.parameters.json @@ -116,7 +116,7 @@ If you already have these resources set up, skip to the [configure and run your
- Option 2: Use custom agent setup. + Option 2: Use standard agent setup.
diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index bf12e36f..ab78bae9 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -9,12 +9,12 @@ To access your files, the file search tool uses the vector store object. Upload - Files from message attachments - [coming soon] Azure Blob Storage -### Standard Agent Setup
+### Basic Agent Setup
The File Search tool has the same functionality as AOAI Assistants. Microsoft managed search and storage resources are used. - Uploaded files get stored in Microsoft managed storage - A vector store is created using Microsoft managed search resources -### Custom Agent Setup +### Standard Agent Setup The File Search tool uses the Azure AI Search and Azure Blob Storage resources you connected during agent setup. - Uploaded files get stored in your connected Azure Blob Storage account. - Vector stores get created using your connected Azure AI Seach resource. From fbded5119b612c2de84023d3bf312a399f66c142 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 18:27:37 -0500 Subject: [PATCH 121/180] updates --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index b870d840..7bb7e671 100644 --- a/quickstart.md +++ b/quickstart.md @@ -59,7 +59,7 @@ If you already have these resources set up, skip to the [configure and run your az group create --name {my_resource_group} --location eastus ``` -1. Choose Standard or Custom Agent Setup +1. Choose Basic or Standard Agent Setup
**Basic Setup**: Agents use multi-tenant search and storage resources fully managed by Microsoft. You won’t have visibility or control over these underlying Azure resources. From ac6db086c30858deecc62db43f560130c7f9f05b Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 18:29:16 -0500 Subject: [PATCH 122/180] updates docs --- quickstart.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/quickstart.md b/quickstart.md index 7bb7e671..cfe5d72b 100644 --- a/quickstart.md +++ b/quickstart.md @@ -117,6 +117,17 @@ If you already have these resources set up, skip to the [configure and run your
Option 2: Use standard agent setup. + + - Download the `basic-agent-keys.bicep` file, `basic-agent-identity.bicep` file, and the `modules-basic` folder to your project directory. Your directory should look like this + + ```console + /my-project + - standard-agent.bicep + /modules-standard + - standard-ai-hub.bicep + - standard-ai-project.bicep + - standard-dependent-resources.bicep + ```
From 8f6c30776aba4a8926457bb9bf2e44e770293dce Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 18:43:33 -0500 Subject: [PATCH 123/180] Update quickstart.md --- quickstart.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index cfe5d72b..59276127 100644 --- a/quickstart.md +++ b/quickstart.md @@ -90,7 +90,7 @@ If you already have these resources set up, skip to the [configure and run your - `basic-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. - - Using the resource group you created in the previous step and one of the template files (either standard-agent.bicep or standard-agent-identity.bicep), run one of the following commands: + - Using the resource group you created in the previous step and one of the template files (either basic-agent-keys.bicep or basic-agent-identity.bicep), run one of the following commands: - To use default resource names, run: @@ -118,16 +118,31 @@ If you already have these resources set up, skip to the [configure and run your
Option 2: Use standard agent setup. - - Download the `basic-agent-keys.bicep` file, `basic-agent-identity.bicep` file, and the `modules-basic` folder to your project directory. Your directory should look like this + - Download the `standard-agent.bicep` file, `standard-agent.parameters.json` file, and the `modules-standard` folder to your project directory. Your directory should look like this ```console /my-project - standard-agent.bicep + - standard-agent.parameters.json /modules-standard - standard-ai-hub.bicep - standard-ai-project.bicep - standard-dependent-resources.bicep ``` + - Using the resource group you created in the previous step, run one of the following commands: + + - To use default resource names, run: + + ```console + az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep + ``` + + - To customize additional parameters, including the OpenAI model deployment, hub name, etc, download and edit the `standard-agent.parameters.json` file, then run: + + ```console + az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters @standard-agent.parameters.json + ``` +
From 3d492d66563e60b4050b5748bc38baaa3ea8376c Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 18:48:50 -0500 Subject: [PATCH 124/180] Update quickstart.md --- quickstart.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/quickstart.md b/quickstart.md index 59276127..4cd01df0 100644 --- a/quickstart.md +++ b/quickstart.md @@ -77,6 +77,7 @@ If you already have these resources set up, skip to the [configure and run your /my-project - basic-agent-keys.bicep - basic-agent-identity.bicep + - basic-agent.parameters.json /modules-basic - basic-ai-hub-keys.bicep - basic-ai-project-keys.bicep @@ -95,19 +96,19 @@ If you already have these resources set up, skip to the [configure and run your - To use default resource names, run: ```console - az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} + az deployment group create --resource-group {my_resource_group} --template-file {my-template-file.bicep} ``` - To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: ```console - az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' + az deployment group create --resource-group {my_resource_group} --template-file {my-template-file.bicep} --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' ``` - To customize additional parameters, including the OpenAI model deployment, download and edit the `basic-agent.parameters.json` file, then run: ```console - az deployment group create --resource-group {my_resource_group} --template-file {template-file-name.bicep} --parameters @standard-agent.parameters.json + az deployment group create --resource-group {my_resource_group} --template-file {my-template-file.bicep} --parameters @basic-agent.parameters.json ``` Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. @@ -118,7 +119,7 @@ If you already have these resources set up, skip to the [configure and run your
Option 2: Use standard agent setup. - - Download the `standard-agent.bicep` file, `standard-agent.parameters.json` file, and the `modules-standard` folder to your project directory. Your directory should look like this + - Download the `standard-agent.bicep` file, the `standard-agent.parameters.json` file, and the `modules-standard` folder to your project directory. Your directory should look like this ```console /my-project From 30f9cae1f8ae14ab667f04ade6296e3cac126e4d Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 18:51:01 -0500 Subject: [PATCH 125/180] Update quickstart.md --- quickstart.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/quickstart.md b/quickstart.md index 4cd01df0..5c86b0d0 100644 --- a/quickstart.md +++ b/quickstart.md @@ -144,6 +144,9 @@ If you already have these resources set up, skip to the [configure and run your az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters @standard-agent.parameters.json ``` + Resources for the hub, project, storage account, key vault, AI Services, and Azure AI Search will be created for you. The AI Services, AI Search, and Azure Blob Storage account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. + +
From 13095ca2eeec183c9cd395001e6f3562a4110f27 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 18:52:31 -0500 Subject: [PATCH 126/180] Update quickstart.md --- quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 5c86b0d0..a38458f5 100644 --- a/quickstart.md +++ b/quickstart.md @@ -144,7 +144,7 @@ If you already have these resources set up, skip to the [configure and run your az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters @standard-agent.parameters.json ``` - Resources for the hub, project, storage account, key vault, AI Services, and Azure AI Search will be created for you. The AI Services, AI Search, and Azure Blob Storage account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. + Resources for the hub, project, storage account, key vault, AI Services, and Azure AI Search will be created for you. The AI Services, AI Search, and Azure Blob Storage account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region.
From a96eee9c9f6f933b98b929025d67f4b3aaa999bd Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 12 Nov 2024 18:53:36 -0500 Subject: [PATCH 127/180] Update readme.md --- samples/file-search/readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index ab78bae9..34f42900 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -6,7 +6,6 @@ To access your files, the file search tool uses the vector store object. Upload ### File Sources - Uploading local files -- Files from message attachments - [coming soon] Azure Blob Storage ### Basic Agent Setup
From 16a5d3ea09ec53d546259ce332b1c3a8b381ab67 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 13 Nov 2024 11:49:14 -0500 Subject: [PATCH 128/180] Update quickstart.md --- quickstart.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index a38458f5..e1647aef 100644 --- a/quickstart.md +++ b/quickstart.md @@ -35,9 +35,10 @@ If you already have these resources set up, skip to the [configure and run your - Microsoft.Storage - Microsoft.MachineLearningServices - Microsoft.Search + - To use Bing Search tool: Microsoft.Bing ```console - az provider register –namespace {my_resource_namespace} + az provider register -–namespace {my_resource_namespace} [--accept-terms] [--consent-to-permissions] [--management-group-id] From 2cb729d191e0a81df553623f27e4b6da178513b7 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 13 Nov 2024 11:52:24 -0500 Subject: [PATCH 129/180] Update readme.md --- samples/bing-search/readme.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 151bd861..70bd99f8 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -20,6 +20,11 @@ Grounding with Bing Search is a free service during private preview and your usa 1. Ensure you have loged in to Azure, using `az login` +1. Register the Bing Search provider + ```console + az provider register --namespace 'Microsoft.Bing' + ``` + 1. Create a new Grounding with Bing Search resource. You can find the the template file [here](./bingsearch_arm.json) and parameter file [here](./bingsearch_para.json). Make sure you have replace "BING_RESOURCE_NAME" in the parameter file. You can use Azure CLI command: ```console From 02ddbb00399beb079c4e061fbb0fcba855a3b94e Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Wed, 13 Nov 2024 15:52:27 -0500 Subject: [PATCH 130/180] update - manual loop version --- .../assistant-investment_portfolio.ipynb | 952 ++++++------------ 1 file changed, 335 insertions(+), 617 deletions(-) diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index d3b2abf9..c1d6f7d8 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -42,64 +42,56 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 1: Install required libraries" + "#### Step 1: Install required libraries\n", + "Including a cell to install dependencies directly within a Jupyter notebook is a good practice because it ensures that all required packages are installed in the correct versions, making the notebook self-contained and reproducible. This approach helps other users or collaborators to set up the environment quickly and avoid potential issues related to missing or incompatible packages." ] }, { "cell_type": "code", - "execution_count": 49, + "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: pandas==2.2.3 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 1)) (2.2.3)\n", - "Requirement already satisfied: yfinance==0.2.48 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 2)) (0.2.48)\n", - "Requirement already satisfied: openai==1.30.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 3)) (1.30.1)\n", - "Requirement already satisfied: python-dotenv==1.0.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", - "Requirement already satisfied: numpy>=1.26.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.1.2)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", - "Requirement already satisfied: requests>=2.31 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.32.3)\n", - "Requirement already satisfied: multitasking>=0.0.7 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.0.11)\n", - "Requirement already satisfied: lxml>=4.9.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (5.3.0)\n", - "Requirement already satisfied: platformdirs>=2.0.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.3.6)\n", - "Requirement already satisfied: frozendict>=2.3.4 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.4.6)\n", - "Requirement already satisfied: peewee>=3.16.2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.17.7)\n", - "Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.12.3)\n", - "Requirement already satisfied: html5lib>=1.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.1)\n", - "Requirement already satisfied: anyio<5,>=3.5.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.6.2.post1)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (0.27.2)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (2.9.2)\n", - "Requirement already satisfied: sniffio in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.3.1)\n", - "Requirement already satisfied: tqdm>4 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.66.6)\n", - "Requirement already satisfied: typing-extensions<5,>=4.7 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.12.2)\n", - "Requirement already satisfied: idna>=2.8 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from anyio<5,>=3.5.0->openai==1.30.1->-r ./requirements.txt (line 3)) (3.10)\n", - "Requirement already satisfied: soupsieve>1.2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.6)\n", - "Requirement already satisfied: six>=1.9 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.16.0)\n", - "Requirement already satisfied: webencodings in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.5.1)\n", - "Requirement already satisfied: certifi in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2024.8.30)\n", - "Requirement already satisfied: httpcore==1.* in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (1.0.6)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.6.0 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.7.0)\n", - "Requirement already satisfied: pydantic-core==2.23.4 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2.23.4)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.4.0)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.2.3)\n", - "Requirement already satisfied: colorama in c:\\developer\\repos\\github\\ai-in-a-box\\gen-ai\\assistants\\notebooks\\personal_finance\\.env\\lib\\site-packages (from tqdm>4->openai==1.30.1->-r ./requirements.txt (line 3)) (0.4.6)\n", + "Requirement already satisfied: pandas==2.2.3 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 1)) (2.2.3)\n", + "Requirement already satisfied: yfinance==0.2.48 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 2)) (0.2.48)\n", + "Requirement already satisfied: openai==1.30.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 3)) (1.30.1)\n", + "Requirement already satisfied: python-dotenv==1.0.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", + "Requirement already satisfied: numpy>=1.26.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.1.3)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.9.0.post0)\n", + "Requirement already satisfied: pytz>=2020.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", + "Requirement already satisfied: requests>=2.31 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.32.3)\n", + "Requirement already satisfied: multitasking>=0.0.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.0.11)\n", + "Requirement already satisfied: lxml>=4.9.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (5.3.0)\n", + "Requirement already satisfied: platformdirs>=2.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.3.6)\n", + "Requirement already satisfied: frozendict>=2.3.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.4.6)\n", + "Requirement already satisfied: peewee>=3.16.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.17.8)\n", + "Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.12.3)\n", + "Requirement already satisfied: html5lib>=1.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.1)\n", + "Requirement already satisfied: anyio<5,>=3.5.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.6.2.post1)\n", + "Requirement already satisfied: distro<2,>=1.7.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.9.0)\n", + "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (0.27.2)\n", + "Requirement already satisfied: pydantic<3,>=1.9.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (2.9.2)\n", + "Requirement already satisfied: sniffio in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.3.1)\n", + "Requirement already satisfied: tqdm>4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.67.0)\n", + "Requirement already satisfied: typing-extensions<5,>=4.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.12.2)\n", + "Requirement already satisfied: idna>=2.8 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from anyio<5,>=3.5.0->openai==1.30.1->-r ./requirements.txt (line 3)) (3.10)\n", + "Requirement already satisfied: soupsieve>1.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.6)\n", + "Requirement already satisfied: six>=1.9 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.16.0)\n", + "Requirement already satisfied: webencodings in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.5.1)\n", + "Requirement already satisfied: certifi in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2024.8.30)\n", + "Requirement already satisfied: httpcore==1.* in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (1.0.6)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.14.0)\n", + "Requirement already satisfied: annotated-types>=0.6.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.7.0)\n", + "Requirement already satisfied: pydantic-core==2.23.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2.23.4)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.4.0)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.2.3)\n", + "Requirement already satisfied: colorama in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from tqdm>4->openai==1.30.1->-r ./requirements.txt (line 3)) (0.4.6)\n", "Note: you may need to restart the kernel to use updated packages.\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n", - "[notice] A new release of pip is available: 24.2 -> 24.3.1\n", - "[notice] To update, run: python.exe -m pip install --upgrade pip\n" - ] } ], "source": [ @@ -111,21 +103,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Azure OpenAI setup**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 1: Setting Up the Environment\n", + "#### Step 2: Setting up the environment\n", "\n", - "Before we begin, we'll load necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.env/.development.env` format. Here we will also import key libraries needed to support this notebook.\n" + "Before we begin, we'll load necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.venv/.env` format. " ] }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 202, "metadata": {}, "outputs": [ { @@ -141,7 +126,7 @@ "from dotenv import load_dotenv\n", "\n", "# Load environment variables from .env file\n", - "load_dotenv(dotenv_path=\".env/.development.env\")\n", + "load_dotenv(dotenv_path=\".venv/.env\")\n", "\n", "# Retrieve the secrets\n", "__AZURE_OPENAI_API_KEY = os.getenv(\"AZURE_OPENAI_API_KEY\")\n", @@ -160,14 +145,21 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 2: Initializing the Azure OpenAI Client\n", + "## **Azure OpenAI setup**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 1: Initializing the Azure OpenAI Client\n", "\n", "Next, we’ll initialize the Azure OpenAI client. This client allows us to interact with Azure OpenAI's file management APIs. You’ll need your API key, endpoint, and API version, which we just loaded from the environment." ] }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 203, "metadata": {}, "outputs": [ { @@ -197,14 +189,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 3 - Upload Support File(s)\n", + "#### Step 2: Upload supporting file to Azure OpenAI deployment\n", "\n", - "In this section, we’ll define a function to check if a file already exists in Azure OpenAI. If it exists, we’ll delete it before uploading the new version. This function will handle the complete upload process.\n" + "Now, we'll upload the `investment_portfolio.csv` file from the `\\data` directory to Azure OpenAI, ensuring any duplicates are removed beforehand. This process will handle the entire upload. The file is necessary for this scenario, but its contents can be modified as long as the file structure remains unchanged." ] }, { "cell_type": "code", - "execution_count": 52, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -218,71 +210,57 @@ ], "source": [ "# Directory containing files to upload\n", - "directory = \"data\"\n", - "purpose = \"assistants\"\n", + "directory=\"data\"\n", + "portfolio_file=\"investment_portfolio.csv\"\n", "\n", "# Check if the directory exists\n", "if not os.path.isdir(directory):\n", " print(f\"Directory '{directory}' does not exist.\")\n", - "else:\n", - " # Process each file in the directory\n", - " for file_name in os.listdir(directory):\n", - " file_path = os.path.join(directory, file_name)\n", + " raise FileNotFoundError(f\"Directory '{directory}' does not exist.\")\n", "\n", - " # Skip if not a file\n", - " if not os.path.isfile(file_path):\n", - " print(f\"Skipping non-file item: {file_name}\")\n", - " continue\n", + "file_path = os.path.join(directory, portfolio_file)\n", "\n", - " try:\n", - " # Check if the file already exists on OpenAI\n", - " existing_files = openai_client.files.list()\n", - " file_exists = False\n", - " for f in existing_files:\n", - " if f.filename == file_name and f.purpose == purpose:\n", - " # Delete the existing file\n", - " openai_client.files.delete(file_id=f.id)\n", - " print(f\"Deleted existing file: {file_name}\")\n", - " file_exists = True\n", - " break\n", + "# Check if the file exists\n", + "if not os.path.isfile(file_path):\n", + " print(f\"Skipping non-file item: {portfolio_file}\")\n", "\n", - " # Upload the new file\n", - " with open(file_path, \"rb\") as file_data:\n", - " portfolio_file = openai_client.files.create(\n", - " file=file_data,\n", - " purpose=purpose\n", - " )\n", - " print(f\"Uploaded file: {file_name}\")\n", - " \n", - " except OpenAIError as e:\n", - " print(f\"Error processing file '{file_name}': {e}\")\n", - " except Exception as e:\n", - " print(f\"Unexpected error with file '{file_name}': {e}\")" + "try:\n", + " # Delete existing file on Azure if it has the same name and purpose\n", + " existing_files = openai_client.files.list()\n", + " for f in existing_files:\n", + " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", + " openai_client.files.delete(file_id=f.id)\n", + " print(f\"Deleted existing file: {portfolio_file}\")\n", + "\n", + " # Upload new file\n", + " with open(file_path, \"rb\") as file_data:\n", + " openai_client.files.create(file=file_data, purpose=\"assistants\")\n", + " print(f\"Uploaded file: {portfolio_file}\")\n", + "\n", + "except OpenAIError as e:\n", + " print(f\"Error processing file '{portfolio_file}': {e}\")\n", + "except Exception as e:\n", + " print(f\"Unexpected error with file '{portfolio_file}': {e}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## **Function Calling**" + "## **Azure OpenAI Assistant**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 1: Define function for Assistant\n", - "The Get Latest Stock Prices function retrieves the stock data for a specified `ticker symbol` using the yfinance library, specifically pulling the latest data for the last trading day.\n", - "\n", - "The `fetch_stock_price` function uses the `yfinance` library to retrieve stock information, including:\n", - "- Company name\n", - "- Latest open price\n", - "- Latest close price" + "### Step 1: Define function for Assistant\n", + "The `fetch_stock_price` function retrieves the stock data for a specified `ticker symbol` using the `yfinance` library, specifically pulling the latest data for the last trading day." ] }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 228, "metadata": {}, "outputs": [ { @@ -298,33 +276,19 @@ "\n", "def fetch_stock_price(ticker_symbol):\n", " \"\"\"\n", - " Fetch the latest stock price and opening price for a given ticker symbol.\n", + " Fetch the latest stock price for a given ticker symbol.\n", "\n", " Parameters:\n", " - ticker_symbol (str): The ticker symbol of the stock to retrieve data for.\n", "\n", " Returns:\n", - " - dict: A dictionary containing the following keys:\n", - " - \"company_name\" (str): The name of the company corresponding to the ticker symbol.\n", - " - \"ticker\" (str): The ticker symbol provided as input.\n", - " - \"open_price\" (float): The opening price of the stock for the latest trading day.\n", - " - \"latest_close_price\" (float): The closing price of the stock for the latest trading day.\n", - " - \"error\" (str): An error message if an issue occurred, or if no data was found.\n", - " \n", + " - str: The closing price of the stock for the latest trading day, or an error message if data is unavailable.\n", + "\n", " Example:\n", " >>> fetch_stock_price(\"AAPL\")\n", - " {'ticker': 'AAPL', 'open_price': 145.3, 'latest_close_price': 148.9}\n", + " \"148.9\"\n", " \"\"\"\n", " \n", - " # Define the default return structure\n", - " default_response = {\n", - " \"company_name\": None,\n", - " \"ticker\": ticker_symbol,\n", - " \"latest_open_price\": None,\n", - " \"latest_close_price\": None,\n", - " \"error\": None\n", - " }\n", - "\n", " try:\n", " # Fetch the stock's trading history for the last day\n", " stock = yf.Ticker(ticker_symbol)\n", @@ -332,32 +296,17 @@ "\n", " # Check if the data is empty, indicating an invalid ticker or no data available\n", " if stock_data.empty:\n", - " return {\"error\": f\"No data found for ticker symbol: {ticker_symbol}\"}\n", - "\n", - " # Extract the company name from the 'info' dictionary\n", - " company_name = stock.info.get('longName', \"Company name not available\")\n", + " return f\"Error: No data found for ticker symbol: {ticker_symbol}\"\n", "\n", - " # Extract the latest available open and close prices\n", - " latest_open_price = stock_data['Open'].iloc[-1]\n", + " # Retrieve and return the latest closing price\n", " latest_close_price = stock_data['Close'].iloc[-1]\n", - " \n", - "\n", - " return str(round(latest_close_price,3))\n", - " #return f\"{company_name} ({ticker_symbol}) stock opened at {round(latest_open_price,3)} and closed at {round(latest_close_price)}.\\n\"\n", - "\n", - " #return {\n", - " # \"company_name\": company_name,\n", - " # \"ticker\": ticker_symbol,\n", - " # \"latest_open_price\": latest_open_price,\n", - " # \"latest_close_price\": latest_close_price,\n", - " # \"error\": None\n", - " #}\n", + " return str(round(latest_close_price, 3))\n", "\n", " except KeyError as e:\n", - " return {**default_response, \"error\": f\"Data missing for key: {e}. Verify the ticker symbol.\"}\n", + " return f\"Error: Data missing for key: {e}. Verify the ticker symbol.\"\n", "\n", " except Exception as e:\n", - " return {**default_response, \"error\": f\"Unexpected error: {type(e).__name__}: {e}\"}\n", + " return f\"Error: Unexpected issue occurred - {type(e).__name__}: {e}\"\n", " \n", "print(\"Function defined successfully.\")" ] @@ -366,13 +315,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 2: Integrating defined function into the Assistant\n", + "### Step 2: Define Function Calling tool for Assistant\n", "Create the `fetch_stock_price` function configuration to be used within the code interpreter. By adding this tool to the Assistant, we enable it to retrieve and interpret stock data when a user prompts it with related queries." ] }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 206, "metadata": {}, "outputs": [ { @@ -407,27 +356,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Assistant**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 1: Creating the Investment Management Assistant\n", - "In this step, we create an assistant with specific tools, including a code interpreter, to answer investment-related questions. This assistant will help analyze and provide insights based on the uploaded portfolio file.\n" + "### Step 3: Creating the Investment Management Assistant\n", + "In this step, we create an assistant equipped with specialized tools, including a code interpreter, to handle investment-related queries and utilize the previously defined function calls. This assistant will analyze the uploaded portfolio file and offer valuable insights." ] }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 230, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Assistant created successfully: Assistant(id='asst_0F1BeDTYLExyx8GfFpuJCrsT', created_at=1731442454, description=None, instructions='You are an expert investment analyst. Use your knowledge base to answer questions about personal investment portfolio management.', metadata={}, model='gpt-4o', name='Investment Management Assistant', object='assistant', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], response_format='auto', temperature=1.0, tool_resources=ToolResources(code_interpreter=ToolResourcesCodeInterpreter(file_ids=[]), file_search=None), top_p=1.0)\n" + "Assistant created successfully.\n" ] } ], @@ -443,7 +385,7 @@ " model=__AZURE_OPENAI_DEPLOYMENT,\n", " tools=tools_list\n", " )\n", - " print(\"Assistant created successfully:\", assistant)\n", + " print(\"Assistant created successfully.\")\n", "except OpenAIError as e:\n", " print(\"Error creating assistant:\", e)" ] @@ -452,20 +394,27 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 2: Starting a New Conversation Thread\n", + "## **Query Assistant**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 1: Starting a New Conversation Thread\n", "Let's create a new thread to handle user interactions. Each thread allows for a dedicated conversation with the assistant." ] }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 208, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Thread created: Thread(id='thread_nNEa3nenX9EG7xdtnc8md9xA', created_at=1731442454, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" + "Thread created: Thread(id='thread_5vg4RVr6m1PLLD5LwfNhdtMg', created_at=1731527292, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" ] } ], @@ -482,20 +431,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 3: Adding User Message\n", + "### Step 2: Adding User Message\n", "In this step, we add a question to the thread. For this demonstration, we're asking which stock ticker has the most investment in the portfolio." ] }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 209, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "User question added: Message(id='msg_jdyTyCObzhD0NJogt2KI9rH8', assistant_id=None, attachments=[Attachment(file_id='assistant-byvyRpwiVS4ThTl3blekxTvT', tools=[CodeInterpreterTool(type='code_interpreter')])], completed_at=None, content=[TextContentBlock(text=Text(annotations=[], value='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?'), type='text')], created_at=1731442454, incomplete_at=None, incomplete_details=None, metadata={}, object='thread.message', role='user', run_id=None, status=None, thread_id='thread_nNEa3nenX9EG7xdtnc8md9xA')\n" + "User question added: Message(id='msg_JeT18F1yiXMnjQpDWEeUXHwE', assistant_id=None, attachments=[Attachment(file_id='assistant-cOAyVn8FSeCER5PL0ruwAOK9', tools=[CodeInterpreterTool(type='code_interpreter')])], completed_at=None, content=[TextContentBlock(text=Text(annotations=[], value='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?'), type='text')], created_at=1731527292, incomplete_at=None, incomplete_details=None, metadata={}, object='thread.message', role='user', run_id=None, status=None, thread_id='thread_5vg4RVr6m1PLLD5LwfNhdtMg')\n" ] } ], @@ -526,20 +475,20 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 4: Running the Assistant\n", + "### Step 3: Running the Assistant\n", "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" ] }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 210, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Run started: Run(id='run_nTlD90Zrnpzi5vr3x2l59RpV', assistant_id='asst_0F1BeDTYLExyx8GfFpuJCrsT', cancelled_at=None, completed_at=None, created_at=1731442454, expires_at=1731443054, failed_at=None, incomplete_details=None, instructions='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?', last_error=None, max_completion_tokens=None, max_prompt_tokens=None, metadata={}, model='gpt-4o', object='thread.run', required_action=None, response_format='auto', started_at=None, status='queued', thread_id='thread_nNEa3nenX9EG7xdtnc8md9xA', tool_choice='auto', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], truncation_strategy=TruncationStrategy(type='auto', last_messages=None), usage=None, temperature=1.0, top_p=1.0, tool_resources={}, parallel_tool_calls=True)\n" + "Run started: Run(id='run_emdA243wUC3jMMwwfywNcfWM', assistant_id='asst_dy9pQwPHiMh5iw2URC1eA5j8', cancelled_at=None, completed_at=None, created_at=1731527293, expires_at=1731527893, failed_at=None, incomplete_details=None, instructions='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?', last_error=None, max_completion_tokens=None, max_prompt_tokens=None, metadata={}, model='gpt-4o', object='thread.run', required_action=None, response_format='auto', started_at=None, status='queued', thread_id='thread_5vg4RVr6m1PLLD5LwfNhdtMg', tool_choice='auto', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], truncation_strategy=TruncationStrategy(type='auto', last_messages=None), usage=None, temperature=1.0, top_p=1.0, tool_resources={}, parallel_tool_calls=True)\n" ] } ], @@ -560,403 +509,233 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 5: Checking for Results\n", - "The assistant may take some time to analyze and respond. We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available." + " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" + ] + }, + { + "cell_type": "code", + "execution_count": 211, + "metadata": {}, + "outputs": [], + "source": [ + "available_functions = {\"fetch_stock_price\": fetch_stock_price}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "**>>>>>>> TO DO: create a function to simply sending multiple prompts**" + "### Step 4: Monitor run status\n", + "\n", + "The assistant may take some time to analyze and respond. We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available.\n", + "Generally we use a loop to check the status and perform actions based on the outcome of each check. To understand the status actions more, lets simulate a loops. Click the next 4 cells multiple times to see the progress of the Assitant Run.\n", + "Retrieves the current status of the OpenAI Assistant run. The status is printed in a formatted JSON string for clarity. Depending on the status of the run, *different actions are taken*." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Status: Queued*\n", + "What does this mean - probably wont use. but explain" ] }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 221, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Monitoring the run status...\n", + "Current Status: completed\n" + ] + } + ], + "source": [ + "import json\n", + "\n", + "# Retrieve the run status\n", + "run = openai_client.beta.threads.runs.retrieve(\n", + " thread_id=thread.id,\n", + " run_id=run.id\n", + ")\n", + "#print(run.model_dump_json(indent=4))\n", + "\n", + "\n", + "if run.status in ('queued', 'in_progress'):\n", + " print(f\"Run this cell again to monitor the status.\\n Current Status: {run.status}\")\n", + "else:\n", + " print(f\"Monitoring the run status...\\nCurrent Status: {run.status}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 4a: Failed status\n", + "\n", + "IF the status is `failed` we will print the error message with relevant information to aid in troubleshooting." + ] + }, + { + "cell_type": "code", + "execution_count": 213, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Assistant run has not failed...\n", + "Navigate to and execute the 'queued' cell.\n" + ] + } + ], + "source": [ + "#print(run.model_dump_json(indent=4))\n", + "\n", + "if run.status == \"failed\":\n", + " print(\"Assistant run failed. Please try again.\")\n", + "else:\n", + " print(f\"Assistant run has not failed...\\nNavigate to and execute the '{run.status}' cell.\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 4b: Requires Action status\n", + "\n", + "If the status is `requires_action`, first we need to check if the required action is to submit tool outputs and iterate over the tool calls, ensuring that the requested function exists in the available_functions dictionary. If the function exists, it is called with the provided arguments, and the response is stored. After processing all tool calls, we submit the tool outputs back to the OpenAI client." + ] + }, + { + "cell_type": "code", + "execution_count": 219, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{\n", - " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", - " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", - " \"cancelled_at\": null,\n", - " \"completed_at\": null,\n", - " \"created_at\": 1731442454,\n", - " \"expires_at\": 1731443054,\n", - " \"failed_at\": null,\n", - " \"incomplete_details\": null,\n", - " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", - " \"last_error\": null,\n", - " \"max_completion_tokens\": null,\n", - " \"max_prompt_tokens\": null,\n", - " \"metadata\": {},\n", - " \"model\": \"gpt-4o\",\n", - " \"object\": \"thread.run\",\n", - " \"required_action\": null,\n", - " \"response_format\": \"auto\",\n", - " \"started_at\": null,\n", - " \"status\": \"queued\",\n", - " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", - " \"tool_choice\": \"auto\",\n", - " \"tools\": [\n", - " {\n", - " \"type\": \"code_interpreter\"\n", - " },\n", - " {\n", - " \"function\": {\n", - " \"name\": \"fetch_stock_price\",\n", - " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"ticker_symbol\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The ticker symbol of the stock\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"ticker_symbol\"\n", - " ]\n", - " },\n", - " \"strict\": false\n", - " },\n", - " \"type\": \"function\"\n", - " }\n", - " ],\n", - " \"truncation_strategy\": {\n", - " \"type\": \"auto\",\n", - " \"last_messages\": null\n", - " },\n", - " \"usage\": null,\n", - " \"temperature\": 1.0,\n", - " \"top_p\": 1.0,\n", - " \"tool_resources\": {},\n", - " \"parallel_tool_calls\": true\n", - "}\n", - "Waiting for the Assistant to process...\n", - "{\n", - " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", - " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", - " \"cancelled_at\": null,\n", - " \"completed_at\": null,\n", - " \"created_at\": 1731442454,\n", - " \"expires_at\": 1731443054,\n", - " \"failed_at\": null,\n", - " \"incomplete_details\": null,\n", - " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", - " \"last_error\": null,\n", - " \"max_completion_tokens\": null,\n", - " \"max_prompt_tokens\": null,\n", - " \"metadata\": {},\n", - " \"model\": \"gpt-4o\",\n", - " \"object\": \"thread.run\",\n", - " \"required_action\": {\n", - " \"submit_tool_outputs\": {\n", - " \"tool_calls\": [\n", - " {\n", - " \"id\": \"call_z00fpMZXt5gAqMOTjkzsRowf\",\n", - " \"function\": {\n", - " \"arguments\": \"{\\\"ticker_symbol\\\": \\\"MSFT\\\"}\",\n", - " \"name\": \"fetch_stock_price\"\n", - " },\n", - " \"type\": \"function\"\n", - " }\n", - " ]\n", - " },\n", - " \"type\": \"submit_tool_outputs\"\n", - " },\n", - " \"response_format\": \"auto\",\n", - " \"started_at\": 1731442455,\n", - " \"status\": \"requires_action\",\n", - " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", - " \"tool_choice\": \"auto\",\n", - " \"tools\": [\n", - " {\n", - " \"type\": \"code_interpreter\"\n", - " },\n", - " {\n", - " \"function\": {\n", - " \"name\": \"fetch_stock_price\",\n", - " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"ticker_symbol\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The ticker symbol of the stock\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"ticker_symbol\"\n", - " ]\n", - " },\n", - " \"strict\": false\n", - " },\n", - " \"type\": \"function\"\n", - " }\n", - " ],\n", - " \"truncation_strategy\": {\n", - " \"type\": \"auto\",\n", - " \"last_messages\": null\n", - " },\n", - " \"usage\": null,\n", - " \"temperature\": 1.0,\n", - " \"top_p\": 1.0,\n", - " \"tool_resources\": {},\n", - " \"parallel_tool_calls\": true\n", - "}\n", "Function Calling ...\n", "Function 'fetch_stock_price' called successfully. \n", - "Output: 423.98\n", + "Output: 426.48\n", "\n", - "Function called successfully.\n", - "{\n", - " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", - " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", - " \"cancelled_at\": null,\n", - " \"completed_at\": null,\n", - " \"created_at\": 1731442454,\n", - " \"expires_at\": 1731443054,\n", - " \"failed_at\": null,\n", - " \"incomplete_details\": null,\n", - " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", - " \"last_error\": null,\n", - " \"max_completion_tokens\": null,\n", - " \"max_prompt_tokens\": null,\n", - " \"metadata\": {},\n", - " \"model\": \"gpt-4o\",\n", - " \"object\": \"thread.run\",\n", - " \"required_action\": null,\n", - " \"response_format\": \"auto\",\n", - " \"started_at\": 1731442455,\n", - " \"status\": \"queued\",\n", - " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", - " \"tool_choice\": \"auto\",\n", - " \"tools\": [\n", - " {\n", - " \"type\": \"code_interpreter\"\n", - " },\n", - " {\n", - " \"function\": {\n", - " \"name\": \"fetch_stock_price\",\n", - " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"ticker_symbol\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The ticker symbol of the stock\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"ticker_symbol\"\n", - " ]\n", - " },\n", - " \"strict\": false\n", - " },\n", - " \"type\": \"function\"\n", - " }\n", - " ],\n", - " \"truncation_strategy\": {\n", - " \"type\": \"auto\",\n", - " \"last_messages\": null\n", - " },\n", - " \"usage\": null,\n", - " \"temperature\": 1.0,\n", - " \"top_p\": 1.0,\n", - " \"tool_resources\": {},\n", - " \"parallel_tool_calls\": true\n", - "}\n", - "Waiting for the Assistant to process...\n", - "{\n", - " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", - " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", - " \"cancelled_at\": null,\n", - " \"completed_at\": null,\n", - " \"created_at\": 1731442454,\n", - " \"expires_at\": 1731443054,\n", - " \"failed_at\": null,\n", - " \"incomplete_details\": null,\n", - " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", - " \"last_error\": null,\n", - " \"max_completion_tokens\": null,\n", - " \"max_prompt_tokens\": null,\n", - " \"metadata\": {},\n", - " \"model\": \"gpt-4o\",\n", - " \"object\": \"thread.run\",\n", - " \"required_action\": null,\n", - " \"response_format\": \"auto\",\n", - " \"started_at\": 1731442460,\n", - " \"status\": \"in_progress\",\n", - " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", - " \"tool_choice\": \"auto\",\n", - " \"tools\": [\n", - " {\n", - " \"type\": \"code_interpreter\"\n", - " },\n", - " {\n", - " \"function\": {\n", - " \"name\": \"fetch_stock_price\",\n", - " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"ticker_symbol\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The ticker symbol of the stock\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"ticker_symbol\"\n", - " ]\n", - " },\n", - " \"strict\": false\n", - " },\n", - " \"type\": \"function\"\n", - " }\n", - " ],\n", - " \"truncation_strategy\": {\n", - " \"type\": \"auto\",\n", - " \"last_messages\": null\n", - " },\n", - " \"usage\": null,\n", - " \"temperature\": 1.0,\n", - " \"top_p\": 1.0,\n", - " \"tool_resources\": {},\n", - " \"parallel_tool_calls\": true\n", - "}\n", - "Waiting for the Assistant to process...\n", - "{\n", - " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", - " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", - " \"cancelled_at\": null,\n", - " \"completed_at\": null,\n", - " \"created_at\": 1731442454,\n", - " \"expires_at\": 1731443054,\n", - " \"failed_at\": null,\n", - " \"incomplete_details\": null,\n", - " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", - " \"last_error\": null,\n", - " \"max_completion_tokens\": null,\n", - " \"max_prompt_tokens\": null,\n", - " \"metadata\": {},\n", - " \"model\": \"gpt-4o\",\n", - " \"object\": \"thread.run\",\n", - " \"required_action\": null,\n", - " \"response_format\": \"auto\",\n", - " \"started_at\": 1731442460,\n", - " \"status\": \"in_progress\",\n", - " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", - " \"tool_choice\": \"auto\",\n", - " \"tools\": [\n", - " {\n", - " \"type\": \"code_interpreter\"\n", - " },\n", - " {\n", - " \"function\": {\n", - " \"name\": \"fetch_stock_price\",\n", - " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"ticker_symbol\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The ticker symbol of the stock\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"ticker_symbol\"\n", - " ]\n", - " },\n", - " \"strict\": false\n", - " },\n", - " \"type\": \"function\"\n", - " }\n", - " ],\n", - " \"truncation_strategy\": {\n", - " \"type\": \"auto\",\n", - " \"last_messages\": null\n", - " },\n", - " \"usage\": null,\n", - " \"temperature\": 1.0,\n", - " \"top_p\": 1.0,\n", - " \"tool_resources\": {},\n", - " \"parallel_tool_calls\": true\n", - "}\n", - "Waiting for the Assistant to process...\n", - "{\n", - " \"id\": \"run_nTlD90Zrnpzi5vr3x2l59RpV\",\n", - " \"assistant_id\": \"asst_0F1BeDTYLExyx8GfFpuJCrsT\",\n", - " \"cancelled_at\": null,\n", - " \"completed_at\": null,\n", - " \"created_at\": 1731442454,\n", - " \"expires_at\": null,\n", - " \"failed_at\": 1731442472,\n", - " \"incomplete_details\": null,\n", - " \"instructions\": \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\",\n", - " \"last_error\": {\n", - " \"code\": \"rate_limit_exceeded\",\n", - " \"message\": \"Rate limit is exceeded. Try again in 43 seconds.\"\n", - " },\n", - " \"max_completion_tokens\": null,\n", - " \"max_prompt_tokens\": null,\n", - " \"metadata\": {},\n", - " \"model\": \"gpt-4o\",\n", - " \"object\": \"thread.run\",\n", - " \"required_action\": null,\n", - " \"response_format\": \"auto\",\n", - " \"started_at\": 1731442460,\n", - " \"status\": \"failed\",\n", - " \"thread_id\": \"thread_nNEa3nenX9EG7xdtnc8md9xA\",\n", - " \"tool_choice\": \"auto\",\n", - " \"tools\": [\n", - " {\n", - " \"type\": \"code_interpreter\"\n", - " },\n", - " {\n", - " \"function\": {\n", - " \"name\": \"fetch_stock_price\",\n", - " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"ticker_symbol\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The ticker symbol of the stock\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"ticker_symbol\"\n", - " ]\n", - " },\n", - " \"strict\": false\n", - " },\n", - " \"type\": \"function\"\n", - " }\n", - " ],\n", - " \"truncation_strategy\": {\n", - " \"type\": \"auto\",\n", - " \"last_messages\": null\n", - " },\n", - " \"usage\": {\n", - " \"completion_tokens\": 171,\n", - " \"prompt_tokens\": 523,\n", - " \"total_tokens\": 694\n", - " },\n", - " \"temperature\": 1.0,\n", - " \"top_p\": 1.0,\n", - " \"tool_resources\": {},\n", - " \"parallel_tool_calls\": true\n", - "}\n", - "Assistant run failed. Please try again.\n" + "Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\n" ] } ], "source": [ + "if run.status == \"requires_action\":\n", + " print(\"Function Calling ...\")\n", + " tool_responses = []\n", + " if (\n", + " run.required_action.type == \"submit_tool_outputs\"\n", + " and run.required_action.submit_tool_outputs.tool_calls is not None\n", + " ):\n", + " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", + "\n", + " for call in tool_calls:\n", + " if call.type == \"function\":\n", + " if call.function.name not in available_functions:\n", + " raise Exception(\"Function requested by the model does not exist\")\n", + " function_to_call = available_functions[call.function.name]\n", + " tool_response = function_to_call(**json.loads(call.function.arguments))\n", + " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", + " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", + "\n", + " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", + " )\n", + "\n", + " print(f\"Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\")\n", + "else:\n", + " print(f\"Navigate to and execute the {run.status} cell.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 4c: Completed status\n", + "\n", + "If the status is `completed`, we will fetch and print all messages in the thread, displaying the role and content of each message.The messages are printed in reverse order because messages in a thread are in FILO (First-In-Last-Out) order and in order to make the messages more conversational for ease of user reading, we must reverse the order." + ] + }, + { + "cell_type": "code", + "execution_count": 227, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Run completed!\n", + "\n", + "MESSAGES\n", + "\n", + "Assistant: The latest closing price for MSFT (Microsoft) is $426.48.\n", + "\n", + "Now, I will calculate your total investment in MSFT. I will first inspect the contents of the file you uploaded.\n", + "Assistant: The file contains information about your investments. Here are the relevant columns:\n", + "- Symbol: The ticker symbol of the stock\n", + "- Average_Cost: The average cost price of the stock\n", + "- QTY: The quantity of the stock you own\n", + "\n", + "Let's calculate your total investment in MSFT as of today.\n", + "Assistant: Your total investment in MSFT as of today is $127,944.00.\n" + ] + } + ], + "source": [ + "if run.status == \"completed\":\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\", after=message.id)\n", + "\n", + " print(f'Run completed!\\n\\nMESSAGES\\n')\n", + "\n", + " # Loop through messages and print content based on role\n", + " for msg in messages.data:\n", + " role = msg.role\n", + " content = msg.content[0].text.value\n", + " print(f\"{role.capitalize()}: {content}\")\n", + "\n", + "else:\n", + " print(f\"Navigate to and execute the {run.status} cell.\")\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Next Step / Let's refine \n", + "Wrap in function - explain the function" + ] + }, + { + "cell_type": "code", + "execution_count": 216, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\n\\nimport json\\nimport time\\n\\n\\navailable_functions = {\"fetch_stock_price\": fetch_stock_price}\\n\\nwhile True:\\n\\n # Retrieve the run status\\n run = openai_client.beta.threads.runs.retrieve(\\n thread_id=thread.id,\\n run_id=run.id\\n )\\n print(run.model_dump_json(indent=4))\\n\\n if run.status == \"failed\":\\n print(\"Assistant run failed. Please try again.\")\\n break\\n elif run.status == \"completed\":\\n messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\")\\n\\n # Loop through messages and print content based on role\\n for msg in messages.data:\\n role = msg.role\\n content = msg.content[0].text.value\\n print(f\"{role.capitalize()}: {content}\")\\n break\\n elif run.status == \"requires_action\":\\n print(\"Function Calling ...\")\\n tool_responses = []\\n if (\\n run.required_action.type == \"submit_tool_outputs\"\\n and run.required_action.submit_tool_outputs.tool_calls is not None\\n ):\\n tool_calls = run.required_action.submit_tool_outputs.tool_calls\\n\\n for call in tool_calls:\\n if call.type == \"function\":\\n if call.function.name not in available_functions:\\n raise Exception(\"Function requested by the model does not exist\")\\n function_to_call = available_functions[call.function.name]\\n tool_response = function_to_call(**json.loads(call.function.arguments))\\n tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\\n print(f\"Function \\'{call.function.name}\\' called successfully. \\nOutput: {tool_response}\\n\")\\n\\n run = openai_client.beta.threads.runs.submit_tool_outputs(\\n thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\\n )\\n\\n print(\"Function called successfully.\")\\n else:\\n print(\"Waiting for the Assistant to process...\")\\n time.sleep(5)\\n'" + ] + }, + "execution_count": 216, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "\n", "import json\n", "import time\n", "\n", @@ -976,7 +755,7 @@ " print(\"Assistant run failed. Please try again.\")\n", " break\n", " elif run.status == \"completed\":\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread.id)\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\")\n", "\n", " # Loop through messages and print content based on role\n", " for msg in messages.data:\n", @@ -1009,112 +788,51 @@ " print(\"Function called successfully.\")\n", " else:\n", " print(\"Waiting for the Assistant to process...\")\n", - " time.sleep(5)" + " time.sleep(5)\n", + "\"\"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## **Cleanup Resources**\n", - "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources. Run this cell at the end of your session to clean up.\n" + "#### More Examples using Function\n", + "- one basic with image (uses CI)\n", + "- one basic function calling " ] }, { - "cell_type": "code", - "execution_count": 60, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "AssistantDeleted(id='asst_0F1BeDTYLExyx8GfFpuJCrsT', deleted=True, object='assistant.deleted')\n" - ] - } - ], "source": [ - "response = openai_client.beta.assistants.delete(assistant.id)\n", - "print(response)\n", - "\n", - "# Optionally delete any other temporary files or datas\n", - "# Note: Any uploaded files to OpenAI could also be cleaned up if needed\n" + "### Wrap Up" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "----------------\n", - "\n", - "## Scratch Pad" + "## **Cleanup Resources**\n", + "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources. Run this cell at the end of your session to clean up.\n" ] }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 217, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'\\nimport time\\nfrom IPython.display import clear_output\\n\\nstart_time = time.time()\\n\\nstatus = run.status\\n\\nwhile status not in [\"completed\", \"cancelled\", \"expired\", \"failed\"]:\\n time.sleep(5)\\n run = openai_client.beta.threads.runs.retrieve(thread_id=thread.id,run_id=run.id)\\n print(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\\n status = run.status\\n print(f\\'Status: {status}\\')\\n clear_output(wait=True)\\n\\nmessages = openai_client.beta.threads.messages.list(\\n thread_id=thread.id\\n) \\n\\nprint(f\\'Status: {status}\\')\\nprint(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\\nprint(messages.model_dump_json(indent=2))\\n'" - ] - }, - "execution_count": 61, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "\"\"\"\n", - "import time\n", - "from IPython.display import clear_output\n", - "\n", - "start_time = time.time()\n", - "\n", - "status = run.status\n", + "#response = openai_client.beta.assistants.delete(assistant.id)\n", + "#print(response)\n", "\n", - "while status not in [\"completed\", \"cancelled\", \"expired\", \"failed\"]:\n", - " time.sleep(5)\n", - " run = openai_client.beta.threads.runs.retrieve(thread_id=thread.id,run_id=run.id)\n", - " print(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\n", - " status = run.status\n", - " print(f'Status: {status}')\n", - " clear_output(wait=True)\n", - "\n", - "messages = openai_client.beta.threads.messages.list(\n", - " thread_id=thread.id\n", - ") \n", - "\n", - "print(f'Status: {status}')\n", - "print(\"Elapsed time: {} minutes {} seconds\".format(int((time.time() - start_time) // 60), int((time.time() - start_time) % 60)))\n", - "print(messages.model_dump_json(indent=2))\n", - "\"\"\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Everything after deployment --- everything else should be in notebook (data plane - private endpoint) --- before should not, its control plane (public only)\n", - "\n", - "1. Portal Creation for Deployment (note iteration two, bicep code??)\n", - "2. Assistant Creation (API)\n", - " - code to do it not portal (delete for cleanup)\n", - "3. Create Thread, Message, Thread run (instructs assistant to create messages) - wait for complete (look at SDK to do this), Listing Messages, Check history of the thread (will see my message, and one from assistant) first message response will be answer (POST/THREADS, POST/THREADS Messages, POST Threads thr)\n", - " - POST /threads\n", - " - POST /threads/:thread_id/messages\n", - " - POST /threads/:thread_id/runs\n", - " - GET /threads/:thread_id/runs/:run_id\n", - " - GET /threads/:thread_id/messages\n", - "4. " + "# Optionally delete any other temporary files or datas\n", + "# Note: Any uploaded files to OpenAI could also be cleaned up if needed\n" ] } ], "metadata": { "kernelspec": { - "display_name": ".env", + "display_name": ".venv", "language": "python", "name": "python3" }, From f2c049cea05faeef0efbe2ca1cc14bd137d3a333 Mon Sep 17 00:00:00 2001 From: e-straight Date: Thu, 14 Nov 2024 10:17:46 -0500 Subject: [PATCH 131/180] C# samples --- quickstart.md | 108 ++++++++++- .../human-approval/AgentFunctions.cs | 179 ++++++++++++++++++ samples/bing-search/BingSearch.cs | 90 +++++++++ samples/file-search/FileSearch.cs | 101 ++++++++++ samples/function-calling/FunctionCalling.cs | 179 ++++++++++++++++++ 5 files changed, 655 insertions(+), 2 deletions(-) create mode 100644 samples/azure-functions/human-approval/AgentFunctions.cs create mode 100644 samples/bing-search/BingSearch.cs create mode 100644 samples/file-search/FileSearch.cs create mode 100644 samples/function-calling/FunctionCalling.cs diff --git a/quickstart.md b/quickstart.md index e1647aef..eea3f584 100644 --- a/quickstart.md +++ b/quickstart.md @@ -6,7 +6,7 @@ This QuickStart demonstrates how to quickly set up your first agent with Azure A 1. Create an Azure Subscription for [free](https://azure.microsoft.com/free/ai-services/), if you don't have one already. -2. Make sure all developers have the role: **Azure AI Developer** assigned at the hub level. [Learn more](https://learn.microsoft.com/azure/ai-studio/concepts/rbac-ai-studio) +2. Make sure all developers have the role: **Azure AI Developer** assigned at the appropriate level. [Learn more](https://learn.microsoft.com/azure/ai-studio/concepts/rbac-ai-studio) If you're using a hub/project that already exists, check the [RBAC roles](./rbac.md). @@ -364,4 +364,108 @@ with project_client: ## C# -C# support coming soon! +```Cs +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.AI.Projects.Tests; + +public partial class Sample_Agent_Basics : SamplesBase +{ + [Test] + public async Task BasicExample() + { + var connectionString = Environment.GetEnvironmentVariable("AZURE_AI_CONNECTION_STRING"); + + AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); + #endregion + + // Step 1: Create an agent + #region Snippet:OverviewCreateAgent + Response agentResponse = await client.CreateAgentAsync( + model: "gpt-4o", + name: "Math Tutor", + instructions: "You are a personal math tutor. Write and run code to answer math questions.", + tools: new List { new CodeInterpreterToolDefinition() }); + Agent agent = agentResponse.Value; + #endregion + + // Intermission: agent should now be listed + + Response> agentListResponse = await client.GetAgentsAsync(); + + //// Step 2: Create a thread + #region Snippet:OverviewCreateThread + Response threadResponse = await client.CreateThreadAsync(); + AgentThread thread = threadResponse.Value; + #endregion + + // Step 3: Add a message to a thread + #region Snippet:OverviewCreateMessage + Response messageResponse = await client.CreateMessageAsync( + thread.Id, + MessageRole.User, + "I need to solve the equation `3x + 11 = 14`. Can you help me?"); + ThreadMessage message = messageResponse.Value; + #endregion + + // Intermission: message is now correlated with thread + // Intermission: listing messages will retrieve the message just added + + Response> messagesListResponse = await client.GetMessagesAsync(thread.Id); + Assert.That(messagesListResponse.Value.Data[0].Id == message.Id); + + // Step 4: Run the agent + #region Snippet:OverviewCreateRun + Response runResponse = await client.CreateRunAsync( + thread.Id, + agent.Id, + additionalInstructions: "Please address the user as Jane Doe. The user has a premium account."); + ThreadRun run = runResponse.Value; + #endregion + + #region Snippet:OverviewWaitForRun + do + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); + } + while (runResponse.Value.Status == RunStatus.Queued + || runResponse.Value.Status == RunStatus.InProgress); + #endregion + + #region Snippet:OverviewListUpdatedMessages + Response> afterRunMessagesResponse + = await client.GetMessagesAsync(thread.Id); + IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + + // Note: messages iterate from newest to oldest, with the messages[0] being the most recent + foreach (ThreadMessage threadMessage in messages) + { + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($" + /// Orchestration function to start approval process + /// + [FunctionName(nameof(WorkflowOrchestrator))] + public static async Task WorkflowOrchestrator( + [OrchestrationTrigger] IDurableOrchestrationContext context, + ILogger log) + { + log.LogInformation($"{nameof(WorkflowOrchestrator)} triggered, orchestration instanceId: {context.InstanceId}"); + var workflowInput = context.GetInput(); + + // call activity function(s) to perform actual work + await context.CallActivityAsync(nameof(StartApprovalAsync), workflowInput); + + // wait for the approval response + var response = await context.WaitForExternalEvent("ApprovalResponse"); + + log.LogInformation($"{nameof(WorkflowOrchestrator)} ApprovalResponse received: {response}, orchestration instanceId: {context.InstanceId}"); + + // complete the approval process + await context.CallActivityAsync( + nameof(CompleteApprovalAsync), + new ApprovalCompleteArgs + { + Approved = response, + CorrelationId = workflowInput.CorrelationId, + }); + } + + /// + /// Activity function to start approval process + /// + [FunctionName(nameof(StartApprovalAsync))] + public static async Task StartApprovalAsync( + [ActivityTrigger] IDurableActivityContext context, + string instanceId, + ILogger log) + { + log.LogInformation($"{nameof(StartApprovalAsync)} triggered, orchestration instanceId:{instanceId}"); + var workflowInput = context.GetInput(); + + // Send an email notification to the approver with a link to trigger the approval via the http trigger function. + var credential = new DefaultAzureCredential(); + var emailClient = new EmailClient(new Uri(AZURE_COMMUNICATION_SERVICE_URI), credential); + var baseApprovalUrl = $"{APPROVAL_HTTP_TRIGGER_FUNCTION_URL}"; + var approveCurlCommand = $@"curl -X POST {baseApprovalUrl} \ + -H ""Content-Type: application/json"" \ + -d '{{""instanceId"": ""{instanceId}"", ""approved"": true}}'"; + + var denyCurlCommand = $@"curl -X POST {baseApprovalUrl} \ + -H ""Content-Type: application/json"" \ + -d '{{""instanceId"": ""{instanceId}"", ""approved"": false}}'"; + + + var emailMessage = new EmailMessage( + senderAddress: "DoNotReply@b5ec5bee-db41-4759-8bbc-31594a5c909c.azurecomm.net", + content: new EmailContent("Approval Request") + { + Html = $@" + + +

Agents Approval Requested

+

We request your approval for the agent application.

+

To approve, run the following command in your terminal:

+
{approveCurlCommand}
+ +

To deny, run the following command in your terminal:

+
{denyCurlCommand}
+ +

Thank you,

+

Your Team

+ + " + }, + recipients: new EmailRecipients([new EmailAddress("pwiese@microsoft.com")])); + + + await emailClient.SendAsync( + WaitUntil.Completed, + emailMessage); + } + + [FunctionName(nameof(TriggerApproval))] + public static async Task TriggerApproval( + [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, + [DurableClient] IDurableOrchestrationClient durableOrchestrationClient, + ILogger log) + { + // Ensure the request content is JSON + if (req.ContentType == "application/json") + { + // Read the request body as a JSON document + using var stream = req.Body; + using var jsonDoc = await JsonDocument.ParseAsync(stream); + + // Access the top-level fields + var root = jsonDoc.RootElement; + if (root.TryGetProperty("instanceId", out var instanceIdElement) && + root.TryGetProperty("approved", out var approvedElement)) + { + var instanceId = instanceIdElement.GetString(); + bool approved = approvedElement.GetBoolean(); + + log.LogInformation($"{nameof(TriggerApproval)} triggered, target orchestration instanceId:{instanceId}"); + await durableOrchestrationClient.RaiseEventAsync(instanceId, "ApprovalResponse", approved); + return new OkObjectResult(new { Approved = approved }); + } + } + + return new BadRequestResult(); + } + + /// + /// Activity function to complete the approval process. This function writes the result to the output queue configured on the assistant. + /// + [FunctionName(nameof(CompleteApprovalAsync))] + [return: Queue(OUTPUT_QUEUE, Connection = "QUEUECONNECTION")] + public static Task CompleteApprovalAsync( + [ActivityTrigger] IDurableActivityContext context, + string instanceId, + ILogger log) + { + log.LogInformation($"{nameof(CompleteApprovalAsync)} triggered, orchestration instanceId:{instanceId}"); + var approvalCompleteArgs = context.GetInput(); + + // return the result to the output queue using the standard Response POCO. + return Task.FromResult(new Response + { + Value = approvalCompleteArgs.Approved ? "APPROVED" : "DENIED", + CorrelationId = approvalCompleteArgs.CorrelationId + }); + } + } +} \ No newline at end of file diff --git a/samples/bing-search/BingSearch.cs b/samples/bing-search/BingSearch.cs new file mode 100644 index 00000000..8669f027 --- /dev/null +++ b/samples/bing-search/BingSearch.cs @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.AI.Projects.Tests; + +public partial class Sample_Agent_Bing_Grounding : SamplesBase +{ + [Test] + public async Task BingGroundingExample() + { + var connectionString = TestEnvironment.AzureAICONNECTIONSTRING; + + var clientOptions = new AIProjectClientOptions(); + + // Adding the custom headers policy + clientOptions.AddPolicy(new CustomHeadersPolicy(), HttpPipelinePosition.PerCall); + var projectClient = new AIProjectClient(connectionString, new DefaultAzureCredential(), clientOptions); + + GetConnectionResponse bingConnection = await projectClient.GetConnectionsClient().GetConnectionAsync(TestEnvironment.BINGCONNECTIONNAME); + var connectionId = bingConnection.Id; + + AgentsClient agentClient = projectClient.GetAgentsClient(); + + ToolConnectionList connectionList = new ToolConnectionList + { + ConnectionList = { new ToolConnection(connectionId) } + }; + BingGroundingToolDefinition bingGroundingTool = new BingGroundingToolDefinition(connectionList); + + Response agentResponse = await agentClient.CreateAgentAsync( + model: "gpt-4-1106-preview", + name: "my-assistant", + instructions: "You are a helpful assistant.", + tools: new List { bingGroundingTool }); + Agent agent = agentResponse.Value; + + // Create thread for communication + Response threadResponse = await agentClient.CreateThreadAsync(); + AgentThread thread = threadResponse.Value; + + // Create message to thread + Response messageResponse = await agentClient.CreateMessageAsync( + thread.Id, + MessageRole.User, + "How does wikipedia explain Euler's Identity?"); + ThreadMessage message = messageResponse.Value; + + // Run the agent + Response runResponse = await agentClient.CreateRunAsync(thread, agent); + + do + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await agentClient.GetRunAsync(thread.Id, runResponse.Value.Id); + } + while (runResponse.Value.Status == RunStatus.Queued + || runResponse.Value.Status == RunStatus.InProgress); + + Response> afterRunMessagesResponse + = await agentClient.GetMessagesAsync(thread.Id); + IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + + // Note: messages iterate from newest to oldest, with the messages[0] being the most recent + foreach (ThreadMessage threadMessage in messages) + { + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($" +{ + [Test] + public async Task FilesSearchExample() + { + var connectionString = TestEnvironment.AzureAICONNECTIONSTRING; + AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); + + #region Snippet:UploadAgentFilesToUse + // Upload a file and wait for it to be processed + File.WriteAllText( + path: "sample_file_for_upload.txt", + contents: "The word 'apple' uses the code 442345, while the word 'banana' uses the code 673457."); + Response uploadAgentFileResponse = await client.UploadFileAsync( + filePath: "sample_file_for_upload.txt", + purpose: AgentFilePurpose.Agents); + + AgentFile uploadedAgentFile = uploadAgentFileResponse.Value; + #endregion + + #region Snippet:CreateVectorStore + // Create a vector store with the file and wait for it to be processed. + // If you do not specify a vector store, create_message will create a vector store with a default expiration policy of seven days after they were last active + VectorStore vectorStore = await client.CreateVectorStoreAsync( + fileIds: new List { uploadedAgentFile.Id }, + name: "my_vector_store"); + #endregion + + #region Snippet:CreateAgentWithFiles + FileSearchToolResource fileSearchToolResource = new FileSearchToolResource(); + fileSearchToolResource.VectorStoreIds.Add(vectorStore.Id); + + // Create an agent with toolResources and process assistant run + Response agentResponse = await client.CreateAgentAsync( + model: "gpt-4-1106-preview", + name: "SDK Test Agent - Retrieval", + instructions: "You are a helpful agent that can help fetch data from files you know about.", + tools: new List { new FileSearchToolDefinition() }, + toolResources: new ToolResources() { FileSearch = fileSearchToolResource }); + Agent agent = agentResponse.Value; + #endregion + + // Create thread for communication + Response threadResponse = await client.CreateThreadAsync(); + AgentThread thread = threadResponse.Value; + + // Create message to thread + Response messageResponse = await client.CreateMessageAsync( + thread.Id, + MessageRole.User, + "Can you give me the documented codes for 'banana' and 'orange'?"); + ThreadMessage message = messageResponse.Value; + + // Run the agent + Response runResponse = await client.CreateRunAsync(thread, agent); + + do + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); + } + while (runResponse.Value.Status == RunStatus.Queued + || runResponse.Value.Status == RunStatus.InProgress); + + Response> afterRunMessagesResponse + = await client.GetMessagesAsync(thread.Id); + IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + + // Note: messages iterate from newest to oldest, with the messages[0] being the most recent + foreach (ThreadMessage threadMessage in messages) + { + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($" +{ + [Test] + public async Task FunctionCallingExample() + { + var connectionString = TestEnvironment.AzureAICONNECTIONSTRING; + AgentsClient client = new AgentsClient(connectionString, new DefaultAzureCredential()); + + #region Snippet:FunctionsDefineFunctionTools + // Example of a function that defines no parameters + string GetUserFavoriteCity() => "Seattle, WA"; + FunctionToolDefinition getUserFavoriteCityTool = new("getUserFavoriteCity", "Gets the user's favorite city."); + // Example of a function with a single required parameter + string GetCityNickname(string location) => location switch + { + "Seattle, WA" => "The Emerald City", + _ => throw new NotImplementedException(), + }; + FunctionToolDefinition getCityNicknameTool = new( + name: "getCityNickname", + description: "Gets the nickname of a city, e.g. 'LA' for 'Los Angeles, CA'.", + parameters: BinaryData.FromObjectAsJson( + new + { + Type = "object", + Properties = new + { + Location = new + { + Type = "string", + Description = "The city and state, e.g. San Francisco, CA", + }, + }, + Required = new[] { "location" }, + }, + new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); + // Example of a function with one required and one optional, enum parameter + string GetWeatherAtLocation(string location, string temperatureUnit = "f") => location switch + { + "Seattle, WA" => temperatureUnit == "f" ? "70f" : "21c", + _ => throw new NotImplementedException() + }; + FunctionToolDefinition getCurrentWeatherAtLocationTool = new( + name: "getCurrentWeatherAtLocation", + description: "Gets the current weather at a provided location.", + parameters: BinaryData.FromObjectAsJson( + new + { + Type = "object", + Properties = new + { + Location = new + { + Type = "string", + Description = "The city and state, e.g. San Francisco, CA", + }, + Unit = new + { + Type = "string", + Enum = new[] { "c", "f" }, + }, + }, + Required = new[] { "location" }, + }, + new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); + #endregion + + #region Snippet:FunctionsHandleFunctionCalls + ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall) + { + if (toolCall is RequiredFunctionToolCall functionToolCall) + { + if (functionToolCall.Name == getUserFavoriteCityTool.Name) + { + return new ToolOutput(toolCall, GetUserFavoriteCity()); + } + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + if (functionToolCall.Name == getCityNicknameTool.Name) + { + string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString(); + return new ToolOutput(toolCall, GetCityNickname(locationArgument)); + } + if (functionToolCall.Name == getCurrentWeatherAtLocationTool.Name) + { + string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString(); + if (argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unitElement)) + { + string unitArgument = unitElement.GetString(); + return new ToolOutput(toolCall, GetWeatherAtLocation(locationArgument, unitArgument)); + } + return new ToolOutput(toolCall, GetWeatherAtLocation(locationArgument)); + } + } + return null; + } + #endregion + + #region Snippet:FunctionsCreateAgentWithFunctionTools + // note: parallel function calling is only supported with newer models like gpt-4-1106-preview + Response agentResponse = await client.CreateAgentAsync( + model: "gpt-4-1106-preview", + name: "SDK Test Agent - Functions", + instructions: "You are a weather bot. Use the provided functions to help answer questions. " + + "Customize your responses to the user's preferences as much as possible and use friendly " + + "nicknames for cities whenever possible.", + tools: new List { getUserFavoriteCityTool, getCityNicknameTool, getCurrentWeatherAtLocationTool } + ); + Agent agent = agentResponse.Value; + #endregion + + Response threadResponse = await client.CreateThreadAsync(); + AgentThread thread = threadResponse.Value; + + Response messageResponse = await client.CreateMessageAsync( + thread.Id, + MessageRole.User, + "What's the weather like in my favorite city?"); + ThreadMessage message = messageResponse.Value; + + Response runResponse = await client.CreateRunAsync(thread, agent); + + #region Snippet:FunctionsHandlePollingWithRequiredAction + do + { + await Task.Delay(TimeSpan.FromMilliseconds(500)); + runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id); + + if (runResponse.Value.Status == RunStatus.RequiresAction + && runResponse.Value.RequiredAction is SubmitToolOutputsAction submitToolOutputsAction) + { + List toolOutputs = new(); + foreach (RequiredToolCall toolCall in submitToolOutputsAction.ToolCalls) + { + toolOutputs.Add(GetResolvedToolOutput(toolCall)); + } + runResponse = await client.SubmitToolOutputsToRunAsync(runResponse.Value, toolOutputs); + } + } + while (runResponse.Value.Status == RunStatus.Queued + || runResponse.Value.Status == RunStatus.InProgress); + #endregion + + Response> afterRunMessagesResponse + = await client.GetMessagesAsync(thread.Id); + IReadOnlyList messages = afterRunMessagesResponse.Value.Data; + + // Note: messages iterate from newest to oldest, with the messages[0] being the most recent + foreach (ThreadMessage threadMessage in messages) + { + Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: "); + foreach (MessageContent contentItem in threadMessage.ContentItems) + { + if (contentItem is MessageTextContent textItem) + { + Console.Write(textItem.Text); + } + else if (contentItem is MessageImageFileContent imageFileItem) + { + Console.Write($" Date: Thu, 14 Nov 2024 10:03:25 -0800 Subject: [PATCH 132/180] removing openapi --- samples/openapi/function-example.json | 78 ----------------------- samples/openapi/python-openapi.py | 89 --------------------------- samples/openapi/readme.md | 46 -------------- 3 files changed, 213 deletions(-) delete mode 100644 samples/openapi/function-example.json delete mode 100644 samples/openapi/python-openapi.py delete mode 100644 samples/openapi/readme.md diff --git a/samples/openapi/function-example.json b/samples/openapi/function-example.json deleted file mode 100644 index 3e06e256..00000000 --- a/samples/openapi/function-example.json +++ /dev/null @@ -1,78 +0,0 @@ -openapi: 3.0.1 -info: - title: Weather Service API - description: This is a sample API for retrieving weather information. - version: 1.0.0 -servers: - - url: https://api.example.com/weather - description: Main API Server -paths: - /current: - get: - summary: Get current weather - operationId: getCurrentWeather - tags: - - weather - parameters: - - name: location - in: query - required: true - description: Location to get weather for - schema: - type: string - responses: - '200': - description: Current weather details - content: - application/json: - schema: - $ref: '#/components/schemas/Weather' - '404': - description: Location not found - /forecast: - get: - summary: Get weather forecast - operationId: getWeatherForecast - tags: - - weather - parameters: - - name: location - in: query - required: true - description: Location to get weather forecast for - schema: - type: string - - name: days - in: query - required: true - description: Number of days to forecast - schema: - type: integer - minimum: 1 - maximum: 7 - responses: - '200': - description: Weather forecast details - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Weather' - '404': - description: Location not found -components: - schemas: - Weather: - type: object - properties: - location: - type: string - temperature: - type: number - description: - type: string - humidity: - type: number - windSpeed: - type: number diff --git a/samples/openapi/python-openapi.py b/samples/openapi/python-openapi.py deleted file mode 100644 index d1c555db..00000000 --- a/samples/openapi/python-openapi.py +++ /dev/null @@ -1,89 +0,0 @@ -# Use this sample to call an OpenAPI tool. You might - -import os, time -from azure.ai.projects import AIProjectClient -from azure.identity import DefaultAzureCredential -from azure.ai.projects.models import openapi, SubmitToolOutputsAction, RequiredFunctionToolCall - -# Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# Customer needs to login to Azure subscription via Azure CLI and set the environment variables - -project_client = AIProjectClient.from_connection_string( - credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] -) - -with project_client: - # Create an agent and run user's request with function calls - agent = project_client.agents.create_agent( - model="gpt-4o-mini", - name="my-agent", - instructions="You are a helpful agent", - tools=[{ - "type": "openapi", - "openapi": { - "name": "mytool", - "description": "My tool", - "spec": { - "openapi": "3.0.0", - - } - }, - "auth": { - "type": "anonymous | managed_identity | connection" - } - }] - ) - print(f"Created agent, ID: {agent.id}") - - thread = project_client.agents.create_thread() - print(f"Created thread, ID: {thread.id}") - - message = project_client.agents.create_message( - thread_id=thread.id, - role="user", - content="Hello, send an email with the datetime and weather information in New York?", - ) - print(f"Created message, ID: {message.id}") - - run = project_client.agents.create_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Created run, ID: {run.id}") - - while run.status in ["queued", "in_progress", "requires_action"]: - time.sleep(1) - run = project_client.agents.get_run(thread_id=thread.id, run_id=run.id) - - if run.status == "requires_action" and isinstance(run.required_action, SubmitToolOutputsAction): - tool_calls = run.required_action.submit_tool_outputs.tool_calls - if not tool_calls: - print("No tool calls provided - cancelling run") - project_client.agents.cancel_run(thread_id=thread.id, run_id=run.id) - break - - tool_outputs = [] - for tool_call in tool_calls: - if isinstance(tool_call, RequiredFunctionToolCall): - try: - tool_outputs.append({ - "tool_call_id": tool_call.id, - }) - except Exception as e: - print(f"Error executing tool_call {tool_call.id}: {e}") - - print(f"Tool outputs: {tool_outputs}") - if tool_outputs: - project_client.agents.submit_tool_outputs_to_run( - thread_id=thread.id, run_id=run.id, tool_outputs=tool_outputs - ) - - print(f"Current run status: {run.status}") - - print(f"Run completed with status: {run.status}") - - # Delete the agent when done - project_client.agents.delete_agent(agent.id) - print("Deleted agent") - - # Fetch and log all messages - messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/openapi/readme.md b/samples/openapi/readme.md deleted file mode 100644 index 19e5c91f..00000000 --- a/samples/openapi/readme.md +++ /dev/null @@ -1,46 +0,0 @@ -# Use OpenAPI 3.0 Specified Tools - -The Custom Tools feature allows developers to describe custom tools in the Agent API using an [OpenAPI schema](https://www.openapis.org/), enabling the model to intelligently call these functions based on user input. You can use any API spec that is written according to the OpenAPI 3.0 schema. - -While you can use [function calling](../function-calling/readme.md) to define functions you want your agent to call, the OpenAPI tool described here gives you: - -* Standardization by letting you leverage the OpenAPI spec when defining your tools -* Server-side integration with the ability to use managed identity - -## Setup - -You need a function defined using the OpenAPI Schema. See the [example function](./function-example.json) for a full sample of a possible tool definition. It will look something like this: - -```yml -openapi: 3.0.1  -info:  -  title: Weather Service API  -  description: This is a sample API for retrieving weather information.  -  version: 1.0.0  -servers:  -  - url: https://api.example.com/weather  -    description: Main API Server  -paths:  -  /current:  -    get:  -      summary: Get current weather  -      operationId: getCurrentWeather  -... -``` - - -Authentication can be either `anonymous` (no authentication) or `managed_identity`: - -`"auth": { "type": "managed_identity", "security_scheme": { "audience": "https://cognitiveservices.azure.com/" }}` - -`Anonymous` is not authentication, `managed_identity` is authenticating with various Azure Services using RBAC. - -## Examples - -Run the code samples below and view the output. - ->[!NOTE] -> Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. - -* [Python](./python-openapi.py) - From 7edf989d2f97c685a17ad7a8fb2a5032485f41ce Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 14 Nov 2024 14:33:11 -0800 Subject: [PATCH 133/180] adding nuget package --- ...re.AI.Projects.1.0.0-alpha.20241114.1.nupkg | Bin 0 -> 414473 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/Azure.AI.Projects.1.0.0-alpha.20241114.1.nupkg diff --git a/packages/Azure.AI.Projects.1.0.0-alpha.20241114.1.nupkg b/packages/Azure.AI.Projects.1.0.0-alpha.20241114.1.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..f8ad0b86c8412293802b21da93a1fc37e3d60e2b GIT binary patch literal 414473 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

  • z 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
  • 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 literal 0 HcmV?d00001 From 7934c560bf6639be3820be899782a0c63838b43e Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Thu, 14 Nov 2024 19:09:50 -0500 Subject: [PATCH 134/180] adding permissions --- modules-standard/standard-ai-hub.bicep | 4 +- modules-standard/standard-ai-project.bicep | 64 ++++++++++++++++++- .../standard-dependent-resources.bicep | 6 +- standard-agent.bicep | 4 +- 4 files changed, 70 insertions(+), 8 deletions(-) diff --git a/modules-standard/standard-ai-hub.bicep b/modules-standard/standard-ai-hub.bicep index e41596a9..d73203af 100644 --- a/modules-standard/standard-ai-hub.bicep +++ b/modules-standard/standard-ai-hub.bicep @@ -71,7 +71,7 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' metadata: { ApiType: 'Azure' ResourceId: aiServicesId - Location: modelLocation + location: modelLocation } } } @@ -86,7 +86,7 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' metadata: { ApiType: 'Azure' ResourceId: aiSearchId - location: location + location: 'eastus2' } } } diff --git a/modules-standard/standard-ai-project.bicep b/modules-standard/standard-ai-project.bicep index 3d911cc8..9a43f235 100644 --- a/modules-standard/standard-ai-project.bicep +++ b/modules-standard/standard-ai-project.bicep @@ -29,10 +29,24 @@ param aoaiConnectionName string param aiServicesName string -resource aiServices 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { +@description('Name AI Search resource') +param aiSearchName string + +@description('Name storage resource') +param aiStorageName string + +resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' existing = { name: aiServicesName } +resource searchService 'Microsoft.Search/searchServices@2024-06-01-preview' existing = { + name: aiSearchName +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2024-06-01-preview' existing = { + name: aiStorageName +} + var storageConnections = ['${aiProjectName}/workspaceblobstore'] var aiSearchConnection = ['${acsConnectionName}'] @@ -114,8 +128,54 @@ resource cognitiveServicesUserRoleAssignment 'Microsoft.Authorization/roleAssign } } +// search roles +resource searchIndexDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '8ebe5a00-799e-43f5-93ac-243d3dce84a7' + scope: resourceGroup() +} + +resource searchIndexDataContributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: searchService + name: guid(aiProject.id, searchIndexDataContributorRole.id, searchService.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: searchIndexDataContributorRole.id + principalType: 'ServicePrincipal' + } +} + +resource searchServiceContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '7ca78c08-252a-4471-8644-bb5ff32d4ba0' + scope: resourceGroup() +} + +resource searchServiceContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: searchService + name: guid(aiProject.id, searchServiceContributorRole.id, searchService.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: searchServiceContributorRole.id + principalType: 'ServicePrincipal' + } +} + +//blob storage +resource storageBlobDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' + scope: resourceGroup() +} + +resource storageBlobDataContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: storageAccount + name: guid(aiProject.id, storageBlobDataContributorRole.id, storageAccount.id) + properties: { + principalId: aiProject.identity.principalId + roleDefinitionId: storageBlobDataContributorRole.id + principalType: 'ServicePrincipal' + } +} + output aiProjectName string = aiProject.name output aiProjectResourceId string = aiProject.id output aiProjectWorkspaceId string = aiProject.properties.workspaceId - output enterpriseAgentsEndpoint string = aiProject.tags.AgentsEndpointUri diff --git a/modules-standard/standard-dependent-resources.bicep b/modules-standard/standard-dependent-resources.bicep index 5540356c..dd0e4a3a 100644 --- a/modules-standard/standard-dependent-resources.bicep +++ b/modules-standard/standard-dependent-resources.bicep @@ -100,7 +100,7 @@ resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024- resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = { name: aiSearchName - location: location + location: 'eastus2' tags: tags identity: { type: 'SystemAssigned' @@ -112,9 +112,9 @@ resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = { enforcement: 'Unspecified' } hostingMode: 'default' - partitionCount: 3 + partitionCount: 1 publicNetworkAccess: 'enabled' - replicaCount: 3 + replicaCount: 1 semanticSearch: 'disabled' } sku: { diff --git a/standard-agent.bicep b/standard-agent.bicep index a7ef096f..a5d1e9b1 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -102,7 +102,7 @@ module aiHub 'modules-standard/standard-ai-hub.bicep' = { modelLocation: modelLocation - aiSearchName: aiDependencies.outputs.aiSearchName + aiSearchName: '${aiSearchName}-${uniqueSuffix}' aiSearchId: aiDependencies.outputs.aisearchID aiServicesId: aiDependencies.outputs.aiservicesID aiServicesTarget: aiDependencies.outputs.aiservicesTarget @@ -124,7 +124,9 @@ module aiProject 'modules-standard/standard-ai-project.bicep' = { capabilityHostName: capabilityHostName // dependent resources + aiSearchName: '${aiSearchName}-${uniqueSuffix}' aiServicesName: '${aiServicesName}${uniqueSuffix}' + aiStorageName: aiDependencies.outputs.storageAccountName aiHubId: aiHub.outputs.aiHubID acsConnectionName: aiHub.outputs.acsConnectionName aoaiConnectionName: aiHub.outputs.aoaiConnectionName From ce5011d2df44650baba1b8f206de3e021ac9f4d4 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Thu, 14 Nov 2024 19:15:33 -0500 Subject: [PATCH 135/180] fixing location --- modules-standard/standard-ai-hub.bicep | 2 +- modules-standard/standard-dependent-resources.bicep | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules-standard/standard-ai-hub.bicep b/modules-standard/standard-ai-hub.bicep index d73203af..1ba0759c 100644 --- a/modules-standard/standard-ai-hub.bicep +++ b/modules-standard/standard-ai-hub.bicep @@ -86,7 +86,7 @@ resource aiHub 'Microsoft.MachineLearningServices/workspaces@2024-07-01-preview' metadata: { ApiType: 'Azure' ResourceId: aiSearchId - location: 'eastus2' + location: location } } } diff --git a/modules-standard/standard-dependent-resources.bicep b/modules-standard/standard-dependent-resources.bicep index dd0e4a3a..660c4c60 100644 --- a/modules-standard/standard-dependent-resources.bicep +++ b/modules-standard/standard-dependent-resources.bicep @@ -100,7 +100,7 @@ resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024- resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = { name: aiSearchName - location: 'eastus2' + location: location tags: tags identity: { type: 'SystemAssigned' From 1b0bf9597b396b9a727842f40f43414e001e7c46 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Thu, 14 Nov 2024 19:35:17 -0500 Subject: [PATCH 136/180] Update quickstart.md --- quickstart.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quickstart.md b/quickstart.md index eea3f584..24fece0c 100644 --- a/quickstart.md +++ b/quickstart.md @@ -60,6 +60,8 @@ If you already have these resources set up, skip to the [configure and run your az group create --name {my_resource_group} --location eastus ``` + Make sure you have the role **Azure AI Developer** on the resource group you just created. + 1. Choose Basic or Standard Agent Setup
    From d9c85f350721b7e51e6d5ed7996358551134d5f4 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Thu, 14 Nov 2024 20:29:36 -0500 Subject: [PATCH 137/180] Update standard-ai-project.bicep --- modules-standard/standard-ai-project.bicep | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/modules-standard/standard-ai-project.bicep b/modules-standard/standard-ai-project.bicep index 9a43f235..bd2e6c70 100644 --- a/modules-standard/standard-ai-project.bicep +++ b/modules-standard/standard-ai-project.bicep @@ -159,22 +159,6 @@ resource searchServiceContributorRoleAssignment 'Microsoft.Authorization/roleAss } } -//blob storage -resource storageBlobDataContributorRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { - name: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' - scope: resourceGroup() -} - -resource storageBlobDataContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: storageAccount - name: guid(aiProject.id, storageBlobDataContributorRole.id, storageAccount.id) - properties: { - principalId: aiProject.identity.principalId - roleDefinitionId: storageBlobDataContributorRole.id - principalType: 'ServicePrincipal' - } -} - output aiProjectName string = aiProject.name output aiProjectResourceId string = aiProject.id output aiProjectWorkspaceId string = aiProject.properties.workspaceId From 3973cf1166c039fd1d7d80d42c4de256d4fc0839 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 15 Nov 2024 10:26:11 -0800 Subject: [PATCH 138/180] updating pip instructions --- .../azure_ai_projects-1.0.0b1-py3-none-any.whl | Bin 167169 -> 0 bytes quickstart.md | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 packages/azure_ai_projects-1.0.0b1-py3-none-any.whl diff --git a/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl b/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl deleted file mode 100644 index 570a192d3463d3ef181749a013c86402106c6344..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167169 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
    PHDrCsj&epZpF^hgEh73n{C{ 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

    5uH-Gw9XcW{Jn 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 diff --git a/quickstart.md b/quickstart.md index 25c2d523..5d6fae7d 100644 --- a/quickstart.md +++ b/quickstart.md @@ -187,14 +187,14 @@ Use the following code to create an agent and send a message to it. This agent w ## Python SDK ### Setup -1. Download the [Python .whl file](./packages/azure_ai_projects-1.0.0b1-py3-none-any.whl) to your project directory. -2. Run the following commands to install the python packages. +1. Run the following commands to install the python packages. ```console - pip install azure_ai_projects-1.0.0b1-py3-none-any.whl --user --force-reinstall + pip install azure-ai-projects pip install azure-identity ``` + ### Create an Agent Use the following code to create and run an agent. To run this code, you will need to create a connection string using information from your project. This string is in the format: From 513fb1d61e9ede92b1b8000a40c7861e9a1a811e Mon Sep 17 00:00:00 2001 From: e-straight Date: Fri, 15 Nov 2024 15:22:03 -0400 Subject: [PATCH 139/180] tracing readme --- samples/tracing/readme.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 samples/tracing/readme.md diff --git a/samples/tracing/readme.md b/samples/tracing/readme.md new file mode 100644 index 00000000..742d244e --- /dev/null +++ b/samples/tracing/readme.md @@ -0,0 +1,22 @@ +### Tracing + +You can add an Application Insights Azure resource to your Azure AI Studio project. See the Tracing tab in your studio. If one was enabled, you can get the Application Insights connection string, configure your Agents, and observe the full execution path through Azure Monitor. Typically, you might want to start tracing before you create an Agent. + +#### Installation + +Make sure to install OpenTelemetry and the Azure SDK tracing plugin via + +```bash +pip install opentelemetry +pip install azure-core-tracing-opentelemetry +``` + +You will also need an exporter to send telemetry to your observability backend. You can print traces to the console or use a local viewer such as [Aspire Dashboard](https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone?tabs=bash). + +To connect to Aspire Dashboard or another OpenTelemetry compatible backend, install OTLP exporter: + +```bash +pip install opentelemetry-exporter-otlp +``` + +These samples are broken into asynchronous and synchrounous samples. From there, each sample has two versions, one that traces and displays the results locally in the console, and one that sends the traces to the Azure Monitor in AI Studio. Navigate to the to the 'Tracing' tab in your AI Studio project page to enable the second set of samples. \ No newline at end of file From 20c092df1f0f4619f4bedb11b08b59013fc7dc4f Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Fri, 15 Nov 2024 13:46:28 -0600 Subject: [PATCH 140/180] func work --- .../assistant-investment_portfolio-bkup.ipynb | 778 ++++++++++++++++++ .../assistant-investment_portfolio.ipynb | 613 +++++++++----- 2 files changed, 1163 insertions(+), 228 deletions(-) create mode 100644 samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb diff --git a/samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb b/samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb new file mode 100644 index 00000000..8889fe4f --- /dev/null +++ b/samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb @@ -0,0 +1,778 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# **Investment Portfolio Management**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **About the scenario**\n", + "This scenario demonstrates a common project, where notebooks are used to orchestrate complex tasks involving real-time data fetching, computation, and report delivery. The notebook is modular, and secure, employing batch processing, error handling, and proper separation of concerns.\n", + "\n", + "In this scenario, we will:\n", + "\n", + "1. Upload a CSV file containing the user’s investment portfolio to the Azure OpenAI Service.\n", + "2. Fetch real-time stock prices via the Yahoo! Finanace API utilizing *Function Calling*.\n", + "3. Perform calculations on the portfolio using *Code Interpreter*." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Time**\n", + "You should expect to spend 10-15 minutes building and running this scenario. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Before you begin**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 1: Install required libraries\n", + "Install dependencies directly within a Jupyter notebook is a good practice because it ensures that all required packages are installed in the correct versions, making the notebook self-contained and reproducible. This approach helps other users or collaborators to set up the environment quickly and avoid potential issues related to missing or incompatible packages." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Install the packages\n", + "%pip install -r ./requirements.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 2: Setting up the environment\n", + "\n", + "Before we begin, we'll load all necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.venv/.env` format. In order to run the following code, the `.env` file must contain the follow secrets:\n", + "\n", + "- AZURE_OPENAI_API_KEY\n", + "- AZURE_OPENAI_ENDPOINT\n", + "- AZURE_OPENAI_DEPLOYMENT\n", + "- AZURE_OPENAI_API_VERSION \n", + "\n", + "For more information about leveraging Python Virtual Environments can be found [here]()." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from dotenv import load_dotenv\n", + "\n", + "# Load environment variables from .env file\n", + "load_dotenv(dotenv_path=\".venv/.env\")\n", + "\n", + "# Retrieve the secrets\n", + "__AZURE_OPENAI_API_KEY = os.getenv(\"AZURE_OPENAI_API_KEY\")\n", + "__AZURE_OPENAI_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", + "__AZURE_OPENAI_DEPLOYMENT = os.getenv(\"AZURE_OPENAI_DEPLOYMENT\")\n", + "__AZURE_OPENAI_API_VERSION = os.getenv(\"AZURE_OPENAI_API_VERSION\")\n", + "\n", + "# Verify environment variables\n", + "if not all([ __AZURE_OPENAI_API_KEY,\n", + " __AZURE_OPENAI_ENDPOINT, \n", + " __AZURE_OPENAI_DEPLOYMENT, \n", + " __AZURE_OPENAI_API_VERSION]):\n", + " raise EnvironmentError(\"One or more environment variables are missing. Please check the .env file.\")\n", + "else:\n", + " print(\"Environment variables loaded successfully.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Azure OpenAI setup**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 1: Initializing the Azure OpenAI Client\n", + "\n", + "Next, we’ll initialize the Azure OpenAI client. This client allows us to interact with Azure OpenAI's service and file management APIs. You’ll need your API key, endpoint, and API version, which we just loaded from the environment." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from openai import AzureOpenAI, OpenAIError\n", + "\n", + "# Initialize the AzureOpenAI client\n", + "try:\n", + " openai_client = AzureOpenAI(\n", + " api_key=__AZURE_OPENAI_API_KEY,\n", + " api_version=__AZURE_OPENAI_API_VERSION,\n", + " azure_endpoint=__AZURE_OPENAI_ENDPOINT\n", + " )\n", + " print(\"AzureOpenAI client initialized.\")\n", + "except OpenAIError as e:\n", + " raise ConnectionError(f\"Failed to initialize AzureOpenAI client: {e}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 2: Upload supporting file to Azure OpenAI deployment\n", + "\n", + "Now, we'll upload the `investment_portfolio.csv` file from the `\\data` directory to Azure OpenAI, ensuring any existing `investment_portfolio.csv` removed beforehand to ensure the latest version of the file is used and no duplicates exist. This process will handle the entire upload. The file is necessary for this scenario, but its contents can be modified as long as the file structure remains unchanged. The file schema must be as follows:\n", + "\n", + "- Symbol\n", + "- Average_Cost\n", + "- QTY" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Directory containing files to upload\n", + "directory=\"data\"\n", + "portfolio_file=\"investment_portfolio.csv\"\n", + "\n", + "# Check if the directory exists\n", + "if not os.path.isdir(directory):\n", + " print(f\"Directory '{directory}' does not exist.\")\n", + " raise FileNotFoundError(f\"Directory '{directory}' does not exist.\")\n", + "\n", + "file_path = os.path.join(directory, portfolio_file)\n", + "\n", + "# Check if the file exists\n", + "if not os.path.isfile(file_path):\n", + " print(f\"Skipping non-file item: {portfolio_file}\")\n", + "\n", + "try:\n", + " # Delete existing file in Azure OpenAI Service if it has the same name and purpose\n", + " existing_files = openai_client.files.list()\n", + " for f in existing_files:\n", + " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", + " openai_client.files.delete(file_id=f.id)\n", + " print(f\"Deleted existing file: {portfolio_file}\")\n", + "\n", + " # Upload new file\n", + " with open(file_path, \"rb\") as file_data:\n", + " portfolio_file = openai_client.files.create(file=file_data, purpose=\"assistants\")\n", + " print(f\"Uploaded file: {portfolio_file}\")\n", + "\n", + "except OpenAIError as e:\n", + " print(f\"Error processing file '{portfolio_file}': {e}\")\n", + "except Exception as e:\n", + " print(f\"Unexpected error with file '{portfolio_file}': {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Azure OpenAI Assistant**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 1: Define function for Assistant\n", + "The `fetch_stock_price` function retrieves the stock data for a specified `ticker symbol` using the `yfinance` library, specifically pulling the latest data for the last trading day." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import yfinance as yf\n", + "\n", + "def fetch_stock_price(ticker_symbol: str) -> str:\n", + " \"\"\"\n", + " Fetch the latest stock price for a given ticker symbol.\n", + "\n", + " Parameters:\n", + " - ticker_symbol (str): The ticker symbol of the stock to retrieve data for.\n", + "\n", + " Returns:\n", + " - str: The closing price of the stock for the latest trading day, or an error message if data is unavailable.\n", + "\n", + " Example:\n", + " >>> fetch_stock_price(\"AAPL\")\n", + " \"148.9\"\n", + " \"\"\"\n", + " \n", + " try:\n", + " # Fetch the stock's trading history for the last day\n", + " stock = yf.Ticker(ticker_symbol)\n", + " stock_data = stock.history(period=\"1d\")\n", + "\n", + " # Check if the data is empty, indicating an invalid ticker or no data available\n", + " if stock_data.empty:\n", + " return f\"Error: No data found for ticker symbol: {ticker_symbol}\"\n", + "\n", + " # Retrieve and return the latest closing price\n", + " latest_close_price = stock_data['Close'].iloc[-1]\n", + " return str(round(latest_close_price, 3))\n", + "\n", + " except KeyError as e:\n", + " return f\"Error: Data missing for key: {e}. Verify the ticker symbol.\"\n", + "\n", + " except Exception as e:\n", + " return f\"Error: Unexpected issue occurred - {type(e).__name__}: {e}\"\n", + " \n", + "print(\"Function defined successfully.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 2: Define Function Calling tool for Assistant\n", + "The tool-calling definition informs the LLM about available tools. For our scenario, it enables code interpretation and function calling. The `fetch_stock_price` function configuration is to be used along side the code interpreter tool. By adding this tool to the Assistant, we enable it to retrieve and interpret stock data when a user prompts it with related queries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tools_list = [\n", + " {\"type\": \"code_interpreter\"},\n", + " {\n", + " \"type\": \"function\",\n", + " \"function\": {\n", + " \"name\": \"fetch_stock_price\",\n", + " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\"ticker_symbol\": {\"type\": \"string\", \"description\": \"The ticker symbol of the stock\"}},\n", + " \"required\": [\"ticker_symbol\"],\n", + " },\n", + " },\n", + " }\n", + "]\n", + "\n", + "print(\"Tools list defined successfully.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 3: Creating the Investment Management Assistant\n", + "In this step, we create an assistant equipped with specialized tools, including a code interpreter, to handle investment-related queries and utilize the previously defined function calls. This assistant will analyze the uploaded portfolio file and offer valuable insights." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create the assistant with code interpreter and function calling tools enabled\n", + "try:\n", + " assistant = openai_client.beta.assistants.create(\n", + " name=\"Investment Management Assistant\",\n", + " instructions=(\n", + " \"You are an expert investment analyst. \"\n", + " \"Use your knowledge base to answer questions about personal investment portfolio management.\"\n", + " ),\n", + " model=__AZURE_OPENAI_DEPLOYMENT,\n", + " tools=tools_list\n", + " )\n", + " print(\"Assistant created successfully.\\n\", assistant)\n", + "except OpenAIError as e:\n", + " print(\"Error creating assistant:\", e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Querying the Assistant**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 1: Starting a New Conversation Thread\n", + "Let's create a new thread to handle user interactions. Each thread allows for a dedicated conversation with the assistant." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a conversation thread\n", + "try:\n", + " thread = openai_client.beta.threads.create()\n", + " print(\"Thread created successfully.\\n\", thread)\n", + "except OpenAIError as e:\n", + " print(\"Error creating thread:\", e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 2: Adding User Message\n", + "In this step, we add a question to the thread. For this demonstration, we'll what the latest closing price is for specified company (*Microsoft*) that will leverage *function calling* to retrieve this information from the `fetch_stock_price` function. Then, code interpreter will use this information as well as the `QTY` data from the `investment_portfolio.csv` that was uploaded to calculate the **total investment**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define the user question\n", + "prompt_content = \"What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\"\n", + "\n", + "# Add the question to the thread\n", + "try:\n", + " message = openai_client.beta.threads.messages.create(\n", + " thread_id=thread.id,\n", + " role=\"user\",\n", + " content=prompt_content,\n", + " attachments=[ # Add files by using the attachments parameter\n", + " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", + " ],\n", + " )\n", + " print(\"User question added:\", message)\n", + "except OpenAIError as e:\n", + " print(\"Error adding user question:\", e)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 3: Running the Assistant\n", + "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Initiate the assistant's response\n", + "try:\n", + " run = openai_client.beta.threads.runs.create(\n", + " thread_id=thread.id,\n", + " assistant_id=assistant.id,\n", + " instructions=prompt_content,\n", + " )\n", + " print(\"Run started:\", run)\n", + "except OpenAIError as e:\n", + " print(\"Error starting run:\", e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "available_functions = {\"fetch_stock_price\": fetch_stock_price}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 4: Monitor run status\n", + " The assistant may take some time to analyze and respond so we must monitor the run status. Each status will perform an action. To understand the status actions more, lets simulate a loops. Click the next 4 cells multiple times to see the progress of the Assitant Run.\n", + "\n", + "\n", + "Generally we use a loop to check the status and perform actions based on the outcome of each check. \n", + "Retrieves the current status of the OpenAI Assistant run. The status is printed in a formatted JSON string for clarity. Depending on the status of the run, *different actions are taken*. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*Status: Queued*\n", + "What does this mean - probably wont use. but explain" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A Run is an instance where an Assistant operates within a Thread. During a Run, the Assistant processes the Thread's Messages and its configuration to perform tasks using models and tools, adding additional Messages to the Thread as part of its operations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "\n", + "# Retrieve the run status\n", + "run = openai_client.beta.threads.runs.retrieve(\n", + " thread_id=thread.id,\n", + " run_id=run.id\n", + ")\n", + "#print(run.model_dump_json(indent=4))\n", + "\n", + "if run.status in ('queued', 'in_progress'):\n", + " print(f\"Run this cell again to monitor the status.\\nCurrent Status: {run.status}\")\n", + "else:\n", + " print(f\"Monitoring the run status...\\nCurrent Status: {run.status}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 4a: Failed status\n", + "\n", + "If the status is `failed` we will print the error message with relevant information to aid in troubleshooting." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#print(run.model_dump_json(indent=4))\n", + "\n", + "if run.status == \"failed\":\n", + " print(\"Assistant run failed. Please try again.\")\n", + "else:\n", + " print(f\"Assistant run has not failed...\\nNavigate to and execute the '{run.status}' cell.\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 4b: Requires Action status\n", + "\n", + "If the status is `requires_action`, first we need to check if the required action is to submit tool outputs and iterate over the tool calls, ensuring that the requested function exists in the available_functions dictionary. If the function exists, it is called with the provided arguments, and the response is stored. After processing all tool calls, we submit the tool outputs back to the OpenAI client." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if run.status == \"requires_action\":\n", + " print(\"Function Calling ...\")\n", + " tool_responses = []\n", + " if (\n", + " run.required_action.type == \"submit_tool_outputs\"\n", + " and run.required_action.submit_tool_outputs.tool_calls is not None\n", + " ):\n", + " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", + "\n", + " for call in tool_calls:\n", + " if call.type == \"function\":\n", + " if call.function.name not in available_functions:\n", + " raise Exception(\"Function requested by the model does not exist\")\n", + " function_to_call = available_functions[call.function.name]\n", + " tool_response = function_to_call(**json.loads(call.function.arguments))\n", + " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", + " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", + "\n", + " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", + " )\n", + "\n", + " print(f\"Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\")\n", + "else:\n", + " print(f\"Navigate to and execute the {run.status} cell.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Step 4c: Completed status\n", + "\n", + "If the status is `completed`, we will fetch and print all messages in the thread, displaying the role and content of each message.The messages are printed in reverse order because messages in a thread are in FILO (First-In-Last-Out) order and in order to make the messages more conversational for ease of user reading, we must reverse the order." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if run.status == \"completed\":\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\", after=message.id) # Ascending order for output\n", + "\n", + " print(f'Run completed!\\n\\nMESSAGES\\n')\n", + "\n", + " # Loop through messages and print content based on role\n", + " for msg in messages.data:\n", + " role = msg.role\n", + " content = msg.content[0].text.value\n", + " print(f\"{role.capitalize()}: {content}\")\n", + "\n", + "else:\n", + " print(f\"Navigate to and execute the {run.status} cell.\")\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Next Step / Let's refine \n", + "Wrap in function - explain the \n", + "\n", + "We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def process_message():\n", + " messages = []\n", + " \n", + " # Retrieve the run status\n", + " run = openai_client.beta.threads.runs.retrieve(\n", + " thread_id=thread.id,\n", + " run_id=run.id\n", + " )\n", + "\n", + " if run.status in ('queued', 'in_progress'):\n", + " print(f\"Run this cell again to monitor the status.\\nCurrent Status: {run.status}\")\n", + " else:\n", + " print(f\"Monitoring the run status...\\nCurrent Status: {run.status}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "import time \n", + "\n", + "def get_assistant_response(thread_id, run_id, user_prompt):\n", + " \n", + " Interacts with the assistant by sending a user prompt, handling function calls if required, \n", + " and retrieving the conversation messages as a response.\n", + "\n", + " Parameters:\n", + " thread_id (str): ID of the conversation thread.\n", + " run_id (str): ID of the current assistant run.\n", + " user_prompt (str): The user's prompt or question.\n", + "\n", + " Returns:\n", + " list of dict: Each message as a dictionary with 'role' and 'content' keys.\n", + " \n", + " # Send initial prompt - Add a message to the thread with the role of \"user\" and the provided content \n", + " openai_client.beta.threads.messages.create(\n", + " thread_id=thread_id, # Use the ID of the thread passed through to the function\n", + " content=user_prompt, # User content message\n", + " role=\"user\" # Role of the message sender\n", + " )\n", + "\n", + " # Polling to monitor Run status\n", + " while True:\n", + " # Retrieve and inspect the assistant's current run status\n", + " run = openai_client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)\n", + "\n", + " if run.status == \"failed\":\n", + " print(\"Assistant run failed. Please try again.\")\n", + " break\n", + " #return [{\"role\": \"system\", \"content\": \"Assistant run failed. Please try again.\"}]\n", + " \n", + " elif run.status == \"completed\":\n", + " # Collect messages if run is complete\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\")\n", + " #conversation = [{\"role\": msg.role, \"content\": msg.content[0].text.value} for msg in messages.data]\n", + "\n", + " # Loop through messages and print content based on role\n", + " for msg in messages.data:\n", + " role = msg.role\n", + " content = msg.content[0].text.value\n", + " print(f\"{role.capitalize()}: {content}\")\n", + " break\n", + "\n", + " #for msg in conversation: # Display the conversation\n", + " # print(f\"{msg['role'].capitalize()}: {msg['content']}\")\n", + " #return conversation\n", + " \n", + " elif run.status == \"requires_action\" and run.required_action.type == \"submit_tool_outputs\":\n", + " print(\"Function calling initiated...\")\n", + " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", + " tool_responses = []\n", + " \n", + " # Iterate over each function call requested by the assistant\n", + " for call in tool_calls:\n", + " # Check if the call is a function and if the function exists is our custom function\n", + " if call.type == \"function\" and call.function.name == \"fetch_stock_price\":\n", + " func = available_functions[call.function.name] # Retrieve the function reference\n", + " \n", + " # Parse the function arguments from JSON and execute the function\n", + " tool_response = func(**json.loads(call.function.arguments))\n", + " \n", + " # Store the tool call ID and output to later send back to the assistant\n", + " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", + " print(f\"Executed '{call.function.name}'. Output: {tool_response}\")\n", + " \n", + " else:\n", + " # Raise an error if the function is not in available_functions to handle unexpected requests\n", + " raise ValueError(f\"Requested function '{call.function.name}' is not available.\")\n", + " \n", + " # Submit all collected tool outputs back to the assistant to satisfy the required action\n", + " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " thread_id=thread_id, \n", + " run_id=run_id, \n", + " tool_outputs=tool_responses\n", + " )\n", + " print(\"Function call(s) completed successfully.\")\n", + " \n", + " else:\n", + " # If the assistant is still processing, wait before checking the status again\n", + " print(\"Waiting for the Assistant to process...\")\n", + " time.sleep(5)\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: The file contains information about various stocks, with details such as their symbol, average cost, and quantity. For Microsoft (MSFT), the data indicates the following:\n", + "\n", + "- Average Cost: 200\n", + "- Quantity: 300\n", + "\n", + "Given the latest closing price for Microsoft is $318.24, we can calculate the total investment for MSFT as of today. However, there appears to be a discrepancy in the price fetched (418.24) and thus this needs to be assumed correctly.\n", + "\n", + "Here's the calculation:\n", + "\n", + "Total Investment = Quantity × Latest Closing Price\n", + "\n", + "Let's proceed with the calculation.\n", + "Assistant: Your total investment for Microsoft (MSFT) as of today, based on the latest closing price of $318.24, is $95,472.\n", + "User: What is the current stock price for Amazon?\n", + "User: What is the current stock price for Amazon?\n" + ] + } + ], + "source": [ + "user_prompt = \"What is the current stock price for Amazon?\"\n", + "\n", + "response = get_assistant_response(thread.id, run.id, user_prompt)\n", + "#for message in response:\n", + "# print(f\"{message['role'].capitalize()}: {message['content']}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### More Examples using Function\n", + "- one basic with image (uses CI)\n", + "- one basic function calling " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Wrap Up" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Cleanup Resources**\n", + "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources. Run this cell at the end of your session to clean up.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#response = openai_client.beta.assistants.delete(assistant.id)\n", + "#print(response)\n", + "\n", + "# Optionally delete any other temporary files or datas\n", + "# Note: Any uploaded files to OpenAI could also be cleaned up if needed\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index c1d6f7d8..158999b3 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -12,15 +12,13 @@ "metadata": {}, "source": [ "## **About the scenario**\n", - "This scenario demonstrates best practices in a data engineering context, where notebooks are used to orchestrate complex tasks involving real-time data fetching, computation, and report delivery. The notebook is modular, and secure, employing batch processing, error handling, and proper separation of concerns.\n", + "This scenario demonstrates a common project, where notebooks are used to orchestrate complex tasks involving real-time data fetching, computation, and report delivery. The notebook is modular, and secure, employing batch processing, error handling, and proper separation of concerns.\n", "\n", "In this scenario, we will:\n", "\n", - "1. Ingest a CSV file containing the user’s investment portfolio.\n", - "2. Fetch real-time stock prices via an API using *Function Calling*.\n", - "3. Perform calculations on the portfolio, including total value and percentage changes, using *Code Interpreter*.\n", - "4. Generate a detailed report summarizing the portfolio's performance.\n", - "5. Save the report to Azure Blob Storage using *Function Calling*." + "1. Upload a CSV file containing the user’s investment portfolio to the Azure OpenAI Service.\n", + "2. Fetch real-time stock prices via the Yahoo! Finanace API utilizing *Function Calling*.\n", + "3. Perform calculations on the portfolio using *Code Interpreter*." ] }, { @@ -43,57 +41,14 @@ "metadata": {}, "source": [ "#### Step 1: Install required libraries\n", - "Including a cell to install dependencies directly within a Jupyter notebook is a good practice because it ensures that all required packages are installed in the correct versions, making the notebook self-contained and reproducible. This approach helps other users or collaborators to set up the environment quickly and avoid potential issues related to missing or incompatible packages." + "Install dependencies directly within a Jupyter notebook is a good practice because it ensures that all required packages are installed in the correct versions, making the notebook self-contained and reproducible. This approach helps other users or collaborators to set up the environment quickly and avoid potential issues related to missing or incompatible packages." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: pandas==2.2.3 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 1)) (2.2.3)\n", - "Requirement already satisfied: yfinance==0.2.48 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 2)) (0.2.48)\n", - "Requirement already satisfied: openai==1.30.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 3)) (1.30.1)\n", - "Requirement already satisfied: python-dotenv==1.0.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", - "Requirement already satisfied: numpy>=1.26.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.1.3)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 1)) (2024.2)\n", - "Requirement already satisfied: requests>=2.31 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.32.3)\n", - "Requirement already satisfied: multitasking>=0.0.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.0.11)\n", - "Requirement already satisfied: lxml>=4.9.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (5.3.0)\n", - "Requirement already satisfied: platformdirs>=2.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.3.6)\n", - "Requirement already satisfied: frozendict>=2.3.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.4.6)\n", - "Requirement already satisfied: peewee>=3.16.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.17.8)\n", - "Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (4.12.3)\n", - "Requirement already satisfied: html5lib>=1.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.1)\n", - "Requirement already satisfied: anyio<5,>=3.5.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.6.2.post1)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (0.27.2)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (2.9.2)\n", - "Requirement already satisfied: sniffio in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (1.3.1)\n", - "Requirement already satisfied: tqdm>4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.67.0)\n", - "Requirement already satisfied: typing-extensions<5,>=4.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from openai==1.30.1->-r ./requirements.txt (line 3)) (4.12.2)\n", - "Requirement already satisfied: idna>=2.8 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from anyio<5,>=3.5.0->openai==1.30.1->-r ./requirements.txt (line 3)) (3.10)\n", - "Requirement already satisfied: soupsieve>1.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.6)\n", - "Requirement already satisfied: six>=1.9 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (1.16.0)\n", - "Requirement already satisfied: webencodings in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 2)) (0.5.1)\n", - "Requirement already satisfied: certifi in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2024.8.30)\n", - "Requirement already satisfied: httpcore==1.* in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (1.0.6)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.6.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (0.7.0)\n", - "Requirement already satisfied: pydantic-core==2.23.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pydantic<3,>=1.9.0->openai==1.30.1->-r ./requirements.txt (line 3)) (2.23.4)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (3.4.0)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 2)) (2.2.3)\n", - "Requirement already satisfied: colorama in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from tqdm>4->openai==1.30.1->-r ./requirements.txt (line 3)) (0.4.6)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], + "outputs": [], "source": [ "# Install the packages\n", "%pip install -r ./requirements.txt" @@ -105,12 +60,19 @@ "source": [ "#### Step 2: Setting up the environment\n", "\n", - "Before we begin, we'll load necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.venv/.env` format. " + "Before we begin, we'll load all necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.venv/.env` format. In order to run the following code, the `.env` file must contain the follow secrets:\n", + "\n", + "- AZURE_OPENAI_API_KEY\n", + "- AZURE_OPENAI_ENDPOINT\n", + "- AZURE_OPENAI_DEPLOYMENT\n", + "- AZURE_OPENAI_API_VERSION \n", + "\n", + "For more information about leveraging Python Virtual Environments can be found [here]()." ] }, { "cell_type": "code", - "execution_count": 202, + "execution_count": 47, "metadata": {}, "outputs": [ { @@ -135,10 +97,13 @@ "__AZURE_OPENAI_API_VERSION = os.getenv(\"AZURE_OPENAI_API_VERSION\")\n", "\n", "# Verify environment variables\n", - "if not all([__AZURE_OPENAI_API_KEY, __AZURE_OPENAI_ENDPOINT, __AZURE_OPENAI_DEPLOYMENT, __AZURE_OPENAI_API_VERSION]):\n", + "if not all([ __AZURE_OPENAI_API_KEY,\n", + " __AZURE_OPENAI_ENDPOINT, \n", + " __AZURE_OPENAI_DEPLOYMENT, \n", + " __AZURE_OPENAI_API_VERSION]):\n", " raise EnvironmentError(\"One or more environment variables are missing. Please check the .env file.\")\n", - "\n", - "print(\"Environment variables loaded successfully.\")" + "else:\n", + " print(\"Environment variables loaded successfully.\")" ] }, { @@ -154,12 +119,12 @@ "source": [ "#### Step 1: Initializing the Azure OpenAI Client\n", "\n", - "Next, we’ll initialize the Azure OpenAI client. This client allows us to interact with Azure OpenAI's file management APIs. You’ll need your API key, endpoint, and API version, which we just loaded from the environment." + "Next, we’ll initialize the Azure OpenAI client. This client allows us to interact with Azure OpenAI's service and file management APIs. You’ll need your API key, endpoint, and API version, which we just loaded from the environment." ] }, { "cell_type": "code", - "execution_count": 203, + "execution_count": 48, "metadata": {}, "outputs": [ { @@ -191,12 +156,16 @@ "source": [ "#### Step 2: Upload supporting file to Azure OpenAI deployment\n", "\n", - "Now, we'll upload the `investment_portfolio.csv` file from the `\\data` directory to Azure OpenAI, ensuring any duplicates are removed beforehand. This process will handle the entire upload. The file is necessary for this scenario, but its contents can be modified as long as the file structure remains unchanged." + "Now, we'll upload the `investment_portfolio.csv` file from the `\\data` directory to Azure OpenAI, ensuring any existing `investment_portfolio.csv` removed beforehand to ensure the latest version of the file is used and no duplicates exist. This process will handle the entire upload. The file is necessary for this scenario, but its contents can be modified as long as the file structure remains unchanged. The file schema must be as follows:\n", + "\n", + "- Symbol\n", + "- Average_Cost\n", + "- QTY" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "metadata": {}, "outputs": [ { @@ -204,7 +173,7 @@ "output_type": "stream", "text": [ "Deleted existing file: investment_portfolio.csv\n", - "Uploaded file: investment_portfolio.csv\n" + "Uploaded file: FileObject(id='assistant-FmXSjOD0yuvCqUEpp5QTYoeX', bytes=104, created_at=1731699733, filename='investment_portfolio.csv', object='file', purpose='assistants', status='processed', status_details=None)\n" ] } ], @@ -225,7 +194,7 @@ " print(f\"Skipping non-file item: {portfolio_file}\")\n", "\n", "try:\n", - " # Delete existing file on Azure if it has the same name and purpose\n", + " # Delete existing file in Azure OpenAI Service if it has the same name and purpose\n", " existing_files = openai_client.files.list()\n", " for f in existing_files:\n", " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", @@ -234,7 +203,7 @@ "\n", " # Upload new file\n", " with open(file_path, \"rb\") as file_data:\n", - " openai_client.files.create(file=file_data, purpose=\"assistants\")\n", + " portfolio_file = openai_client.files.create(file=file_data, purpose=\"assistants\")\n", " print(f\"Uploaded file: {portfolio_file}\")\n", "\n", "except OpenAIError as e:\n", @@ -260,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 228, + "execution_count": 50, "metadata": {}, "outputs": [ { @@ -274,7 +243,7 @@ "source": [ "import yfinance as yf\n", "\n", - "def fetch_stock_price(ticker_symbol):\n", + "def fetch_stock_price(ticker_symbol: str) -> str:\n", " \"\"\"\n", " Fetch the latest stock price for a given ticker symbol.\n", "\n", @@ -316,12 +285,12 @@ "metadata": {}, "source": [ "### Step 2: Define Function Calling tool for Assistant\n", - "Create the `fetch_stock_price` function configuration to be used within the code interpreter. By adding this tool to the Assistant, we enable it to retrieve and interpret stock data when a user prompts it with related queries." + "The tool-calling definition informs the LLM about available tools. For our scenario, it enables code interpretation and function calling. The `fetch_stock_price` function configuration is to be used along side the code interpreter tool. By adding this tool to the Assistant, we enable it to retrieve and interpret stock data when a user prompts it with related queries." ] }, { "cell_type": "code", - "execution_count": 206, + "execution_count": 51, "metadata": {}, "outputs": [ { @@ -362,19 +331,20 @@ }, { "cell_type": "code", - "execution_count": 230, + "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Assistant created successfully.\n" + "Assistant created successfully.\n", + " Assistant(id='asst_aExvRDZIJe9suJkaMQ79tAvj', created_at=1731699746, description=None, instructions='You are an expert investment analyst. Use your knowledge base to answer questions about personal investment portfolio management.', metadata={}, model='gpt-4o', name='Investment Management Assistant', object='assistant', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], response_format='auto', temperature=1.0, tool_resources=ToolResources(code_interpreter=ToolResourcesCodeInterpreter(file_ids=[]), file_search=None), top_p=1.0)\n" ] } ], "source": [ - "# Create the assistant with code interpreter enabled\n", + "# Create the assistant with code interpreter and function calling tools enabled\n", "try:\n", " assistant = openai_client.beta.assistants.create(\n", " name=\"Investment Management Assistant\",\n", @@ -385,7 +355,7 @@ " model=__AZURE_OPENAI_DEPLOYMENT,\n", " tools=tools_list\n", " )\n", - " print(\"Assistant created successfully.\")\n", + " print(\"Assistant created successfully.\\n\", assistant)\n", "except OpenAIError as e:\n", " print(\"Error creating assistant:\", e)" ] @@ -394,7 +364,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Query Assistant**" + "## **Querying the Assistant**" ] }, { @@ -407,14 +377,15 @@ }, { "cell_type": "code", - "execution_count": 208, + "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Thread created: Thread(id='thread_5vg4RVr6m1PLLD5LwfNhdtMg', created_at=1731527292, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" + "Thread created successfully.\n", + " Thread(id='thread_G5Bf3Ul82M04GDQcR0czEsry', created_at=1731699749, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" ] } ], @@ -422,7 +393,7 @@ "# Create a conversation thread\n", "try:\n", " thread = openai_client.beta.threads.create()\n", - " print(\"Thread created:\", thread)\n", + " print(\"Thread created successfully.\\n\", thread)\n", "except OpenAIError as e:\n", " print(\"Error creating thread:\", e)" ] @@ -432,29 +403,17 @@ "metadata": {}, "source": [ "### Step 2: Adding User Message\n", - "In this step, we add a question to the thread. For this demonstration, we're asking which stock ticker has the most investment in the portfolio." + "In this step, we add a question to the thread. For this demonstration, we'll what the latest closing price is for specified company (*Microsoft*) that will leverage *function calling* to retrieve this information from the `fetch_stock_price` function. Then, code interpreter will use this information as well as the `QTY` data from the `investment_portfolio.csv` that was uploaded to calculate the **total investment**." ] }, { "cell_type": "code", - "execution_count": 209, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User question added: Message(id='msg_JeT18F1yiXMnjQpDWEeUXHwE', assistant_id=None, attachments=[Attachment(file_id='assistant-cOAyVn8FSeCER5PL0ruwAOK9', tools=[CodeInterpreterTool(type='code_interpreter')])], completed_at=None, content=[TextContentBlock(text=Text(annotations=[], value='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?'), type='text')], created_at=1731527292, incomplete_at=None, incomplete_details=None, metadata={}, object='thread.message', role='user', run_id=None, status=None, thread_id='thread_5vg4RVr6m1PLLD5LwfNhdtMg')\n" - ] - } - ], + "outputs": [], "source": [ "# Define the user question\n", - "#prompt_content = \"What ticker symbol has the most stock? Which has the most investment?\"\n", - "\n", - "#prompt_content = \"What is the latest closing price of AAPL?\"\n", - "\n", - "prompt_content = \"What is the latest closing price for MSFT? What is my total investment for MSFT as of today?\"\n", + "prompt_content = \"What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\"\n", "\n", "# Add the question to the thread\n", "try:\n", @@ -481,17 +440,9 @@ }, { "cell_type": "code", - "execution_count": 210, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Run started: Run(id='run_emdA243wUC3jMMwwfywNcfWM', assistant_id='asst_dy9pQwPHiMh5iw2URC1eA5j8', cancelled_at=None, completed_at=None, created_at=1731527293, expires_at=1731527893, failed_at=None, incomplete_details=None, instructions='What is the latest closing price for MSFT? What is my total investment for MSFT as of today?', last_error=None, max_completion_tokens=None, max_prompt_tokens=None, metadata={}, model='gpt-4o', object='thread.run', required_action=None, response_format='auto', started_at=None, status='queued', thread_id='thread_5vg4RVr6m1PLLD5LwfNhdtMg', tool_choice='auto', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], truncation_strategy=TruncationStrategy(type='auto', last_messages=None), usage=None, temperature=1.0, top_p=1.0, tool_resources={}, parallel_tool_calls=True)\n" - ] - } - ], + "outputs": [], "source": [ "# Initiate the assistant's response\n", "try:\n", @@ -509,12 +460,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" + " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" ] }, { "cell_type": "code", - "execution_count": 211, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -526,10 +477,11 @@ "metadata": {}, "source": [ "### Step 4: Monitor run status\n", + " The assistant may take some time to analyze and respond so we must monitor the run status. Each status will perform an action. To understand the status actions more, lets simulate a loops. Click the next 4 cells multiple times to see the progress of the Assitant Run.\n", + "\n", "\n", - "The assistant may take some time to analyze and respond. We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available.\n", - "Generally we use a loop to check the status and perform actions based on the outcome of each check. To understand the status actions more, lets simulate a loops. Click the next 4 cells multiple times to see the progress of the Assitant Run.\n", - "Retrieves the current status of the OpenAI Assistant run. The status is printed in a formatted JSON string for clarity. Depending on the status of the run, *different actions are taken*." + "Generally we use a loop to check the status and perform actions based on the outcome of each check. \n", + "Retrieves the current status of the OpenAI Assistant run. The status is printed in a formatted JSON string for clarity. Depending on the status of the run, *different actions are taken*. " ] }, { @@ -537,23 +489,21 @@ "metadata": {}, "source": [ "*Status: Queued*\n", - "What does this mean - probably wont use. but explain" + "What does this mean - probably wont use. but explain" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A Run is an instance where an Assistant operates within a Thread. During a Run, the Assistant processes the Thread's Messages and its configuration to perform tasks using models and tools, adding additional Messages to the Thread as part of its operations." ] }, { "cell_type": "code", - "execution_count": 221, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Monitoring the run status...\n", - "Current Status: completed\n" - ] - } - ], + "outputs": [], "source": [ "import json\n", "\n", @@ -564,9 +514,8 @@ ")\n", "#print(run.model_dump_json(indent=4))\n", "\n", - "\n", "if run.status in ('queued', 'in_progress'):\n", - " print(f\"Run this cell again to monitor the status.\\n Current Status: {run.status}\")\n", + " print(f\"Run this cell again to monitor the status.\\nCurrent Status: {run.status}\")\n", "else:\n", " print(f\"Monitoring the run status...\\nCurrent Status: {run.status}\")" ] @@ -577,23 +526,14 @@ "source": [ "#### Step 4a: Failed status\n", "\n", - "IF the status is `failed` we will print the error message with relevant information to aid in troubleshooting." + "If the status is `failed` we will print the error message with relevant information to aid in troubleshooting." ] }, { "cell_type": "code", - "execution_count": 213, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Assistant run has not failed...\n", - "Navigate to and execute the 'queued' cell.\n" - ] - } - ], + "outputs": [], "source": [ "#print(run.model_dump_json(indent=4))\n", "\n", @@ -614,21 +554,9 @@ }, { "cell_type": "code", - "execution_count": 219, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function Calling ...\n", - "Function 'fetch_stock_price' called successfully. \n", - "Output: 426.48\n", - "\n", - "Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\n" - ] - } - ], + "outputs": [], "source": [ "if run.status == \"requires_action\":\n", " print(\"Function Calling ...\")\n", @@ -668,33 +596,12 @@ }, { "cell_type": "code", - "execution_count": 227, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Run completed!\n", - "\n", - "MESSAGES\n", - "\n", - "Assistant: The latest closing price for MSFT (Microsoft) is $426.48.\n", - "\n", - "Now, I will calculate your total investment in MSFT. I will first inspect the contents of the file you uploaded.\n", - "Assistant: The file contains information about your investments. Here are the relevant columns:\n", - "- Symbol: The ticker symbol of the stock\n", - "- Average_Cost: The average cost price of the stock\n", - "- QTY: The quantity of the stock you own\n", - "\n", - "Let's calculate your total investment in MSFT as of today.\n", - "Assistant: Your total investment in MSFT as of today is $127,944.00.\n" - ] - } - ], + "outputs": [], "source": [ "if run.status == \"completed\":\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\", after=message.id)\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\", after=message.id) # Ascending order for output\n", "\n", " print(f'Run completed!\\n\\nMESSAGES\\n')\n", "\n", @@ -714,84 +621,334 @@ "metadata": {}, "source": [ "#### Next Step / Let's refine \n", - "Wrap in function - explain the function" + "Wrap in function - explain the \n", + "\n", + "We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available." ] }, { "cell_type": "code", - "execution_count": 216, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'\\n\\nimport json\\nimport time\\n\\n\\navailable_functions = {\"fetch_stock_price\": fetch_stock_price}\\n\\nwhile True:\\n\\n # Retrieve the run status\\n run = openai_client.beta.threads.runs.retrieve(\\n thread_id=thread.id,\\n run_id=run.id\\n )\\n print(run.model_dump_json(indent=4))\\n\\n if run.status == \"failed\":\\n print(\"Assistant run failed. Please try again.\")\\n break\\n elif run.status == \"completed\":\\n messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\")\\n\\n # Loop through messages and print content based on role\\n for msg in messages.data:\\n role = msg.role\\n content = msg.content[0].text.value\\n print(f\"{role.capitalize()}: {content}\")\\n break\\n elif run.status == \"requires_action\":\\n print(\"Function Calling ...\")\\n tool_responses = []\\n if (\\n run.required_action.type == \"submit_tool_outputs\"\\n and run.required_action.submit_tool_outputs.tool_calls is not None\\n ):\\n tool_calls = run.required_action.submit_tool_outputs.tool_calls\\n\\n for call in tool_calls:\\n if call.type == \"function\":\\n if call.function.name not in available_functions:\\n raise Exception(\"Function requested by the model does not exist\")\\n function_to_call = available_functions[call.function.name]\\n tool_response = function_to_call(**json.loads(call.function.arguments))\\n tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\\n print(f\"Function \\'{call.function.name}\\' called successfully. \\nOutput: {tool_response}\\n\")\\n\\n run = openai_client.beta.threads.runs.submit_tool_outputs(\\n thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\\n )\\n\\n print(\"Function called successfully.\")\\n else:\\n print(\"Waiting for the Assistant to process...\")\\n time.sleep(5)\\n'" - ] - }, - "execution_count": 216, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "\"\"\"\n", + "import time\n", "\n", - "import json\n", + "def process_message(thread_id, prompt_message, attachments_list=None):\n", + " try:\n", + " # Add the prompt to the thread\n", + " message = openai_client.beta.threads.messages.create(\n", + " thread_id=thread_id,\n", + " role=\"user\",\n", + " content=prompt_message,\n", + " attachments=attachments_list,\n", + " )\n", + " print(\"User message added...\") #:\", message)\n", + "\n", + " # Initiate the assistant's response\n", + " run = openai_client.beta.threads.runs.create(\n", + " thread_id=thread_id,\n", + " assistant_id=assistant.id,\n", + " instructions=prompt_message,\n", + " )\n", + " print(\"Run started...\") #:\", run)\n", + " except OpenAIError as e:\n", + " print(\"Error starting run:\", e)\n", + "\n", + " while True: # Polling to monitor Run status\n", + " time.sleep(5) # Wait 5 seconds to give the process time to move past `queued` state\n", + "\n", + " # Retrieves the thread’s response.\n", + " run = openai_client.beta.threads.runs.retrieve(\n", + " thread_id=thread_id,\n", + " run_id=run.id\n", + " )\n", + "\n", + " run_status = run.status\n", + " print(f\"Run Status: {run_status}\\n\")\n", + " if run_status == 'completed':\n", + " # Get all messages in thread to read\n", + " thread_messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\") #, after=message.id)\n", + "\n", + " # Loop through thread messages and print content\n", + " for thread_message in thread_messages.data:\n", + " role = thread_message.role\n", + " content = None\n", + " if isinstance(thread_message.content, list) and thread_message.content:\n", + " first_content = thread_message.content[0]\n", + " if hasattr(first_content, 'text') and hasattr(first_content.text, 'value'):\n", + " content = first_content.text.value\n", + " else:\n", + " content = str(first_content)\n", + " else:\n", + " content = str(thread_message.content)\n", + "\n", + " print(f\"{role.capitalize()}: {content}\")\n", + " \n", + " break\n", + " elif run.status == \"failed\":\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread.id)\n", + " answer = messages.data[0].content[0].text.value\n", + " print(f\"Failed User:\\n{prompt_message}\\nAssistant:\\n{answer}\\n\")\n", + "\n", + " # Handle failed\n", + " break\n", + "\n", + " if run.status == \"requires_action\":\n", + " print(\"Function Calling ...\")\n", + " tool_responses = []\n", + " if (\n", + " run.required_action.type == \"submit_tool_outputs\"\n", + " and run.required_action.submit_tool_outputs.tool_calls is not None\n", + " ):\n", + " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", + "\n", + " for call in tool_calls:\n", + " if call.type == \"function\":\n", + " if call.function.name != \"fetch_stock_price\":\n", + " raise Exception(\"Function requested by the model does not exist\")\n", + " function_to_call = available_functions[call.function.name]\n", + " tool_response = function_to_call(**json.loads(call.function.arguments))\n", + " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", + " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", + "\n", + " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", + " )\n", + "\n", + " else:\n", + " time.sleep(5)\n", + "\n", + "print(\"Function `process_message` created successfully.\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "attachments=[ # Add files by using the attachments parameter\n", + " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", + " ]\n", + "\n", + "process_message(thread_id=thread.id, prompt_message=\"What stock do I have the most investment in?\", attachments_list=attachments)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "import time\n", "\n", + "def process_message_old(thread_id, prompt_message, attachments_list=None):\n", "\n", - "available_functions = {\"fetch_stock_price\": fetch_stock_price}\n", + " try:\n", + " # Add the prompt to the thread\n", + " message = openai_client.beta.threads.messages.create(\n", + " thread_id=thread_id,\n", + " role=\"user\",\n", + " content=prompt_message,\n", + " attachments=attachments_list,\n", + " )\n", + " print(\"User question added:\", message)\n", "\n", - "while True:\n", + " # Initiate the assistant's response\n", + " run = openai_client.beta.threads.runs.create(\n", + " thread_id=thread.id,\n", + " assistant_id=assistant.id,\n", + " instructions=prompt_message,\n", + " )\n", + " print(\"Run started:\", run)\n", + " except OpenAIError as e:\n", + " print(\"Error starting run:\", e)\n", "\n", - " # Retrieve the run status\n", - " run = openai_client.beta.threads.runs.retrieve(\n", - " thread_id=thread.id,\n", - " run_id=run.id\n", - " )\n", - " print(run.model_dump_json(indent=4))\n", - "\n", - " if run.status == \"failed\":\n", - " print(\"Assistant run failed. Please try again.\")\n", - " break\n", - " elif run.status == \"completed\":\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\")\n", - "\n", - " # Loop through messages and print content based on role\n", - " for msg in messages.data:\n", - " role = msg.role\n", - " content = msg.content[0].text.value\n", - " print(f\"{role.capitalize()}: {content}\")\n", - " break\n", - " elif run.status == \"requires_action\":\n", - " print(\"Function Calling ...\")\n", - " tool_responses = []\n", - " if (\n", - " run.required_action.type == \"submit_tool_outputs\"\n", - " and run.required_action.submit_tool_outputs.tool_calls is not None\n", - " ):\n", - " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", "\n", - " for call in tool_calls:\n", - " if call.type == \"function\":\n", - " if call.function.name not in available_functions:\n", - " raise Exception(\"Function requested by the model does not exist\")\n", - " function_to_call = available_functions[call.function.name]\n", - " tool_response = function_to_call(**json.loads(call.function.arguments))\n", - " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", - " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", + " while True: # Polling to monitor Run status\n", + " \n", + " # Wait 5 seconds to give the process time to move past `queued` state\n", + " time.sleep(5)\n", "\n", - " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", - " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", + " # Retrieves the thread’s response.\n", + " run = openai_client.beta.threads.runs.retrieve(\n", + " thread_id=thread_id,\n", + " run_id=run.id\n", " )\n", "\n", - " print(\"Function called successfully.\")\n", - " else:\n", + " run_status = run.status\n", + " print(f\"Run Status: {run_status}\\n\")\n", + " if run_status =='completed':\n", + "\n", + " # Get all messages in thread to read\n", + " thread_messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\") #, after=message.id)\n", + "\n", + " # Loop through thread messages and print content\n", + " for thread_message in thread_messages.data:\n", + " role = thread_message.role\n", + " #content = thread_message.content[0].text.value\n", + " \n", + " # Safely access content based on its actual structure\n", + " if isinstance(thread_message.content, list) and thread_message.content:\n", + " first_content = thread_message.content[0]\n", + " if hasattr(first_content, 'text') and hasattr(first_content.text, 'value'):\n", + " content = first_content.text.value\n", + " else:\n", + " content = str(first_content) # Fallback to string representation\n", + " else:\n", + " content = str(thread_message.content) # Handle non-list or empty content\n", + "\n", + " # Printing the `role` makes the result conversational for users\n", + " print(f\"{role.capitalize()}: {content}\")\n", + " \n", + " break\n", + " elif run.status == \"failed\":\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread.id)\n", + " answer = messages.data[0].content[0].text.value\n", + " print(f\"Failed User:\\n{prompt_message}\\nAssistant:\\n{answer}\\n\")\n", + " # Handle failed\n", + " break\n", + "\n", + " \n", + " else:\n", + " time.sleep(5)\n", + "\n", + "print(\"Function `process_message` created successfully.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "import time \n", + "\n", + "def get_assistant_response(thread_id, run_id, user_prompt):\n", + " \n", + " Interacts with the assistant by sending a user prompt, handling function calls if required, \n", + " and retrieving the conversation messages as a response.\n", + "\n", + " Parameters:\n", + " thread_id (str): ID of the conversation thread.\n", + " run_id (str): ID of the current assistant run.\n", + " user_prompt (str): The user's prompt or question.\n", + "\n", + " Returns:\n", + " list of dict: Each message as a dictionary with 'role' and 'content' keys.\n", + " \n", + " # Send initial prompt - Add a message to the thread with the role of \"user\" and the provided content \n", + " openai_client.beta.threads.messages.create(\n", + " thread_id=thread_id, # Use the ID of the thread passed through to the function\n", + " content=user_prompt, # User content message\n", + " role=\"user\" # Role of the message sender\n", + " )\n", + "\n", + " # Polling to monitor Run status\n", + " while True:\n", + " # Retrieve and inspect the assistant's current run status\n", + " run = openai_client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)\n", + "\n", + " if run.status == \"failed\":\n", + " print(\"Assistant run failed. Please try again.\")\n", + " break\n", + " #return [{\"role\": \"system\", \"content\": \"Assistant run failed. Please try again.\"}]\n", + " \n", + " elif run.status == \"completed\":\n", + " # Collect messages if run is complete\n", + " messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\")\n", + " #conversation = [{\"role\": msg.role, \"content\": msg.content[0].text.value} for msg in messages.data]\n", + "\n", + " # Loop through messages and print content based on role\n", + " for msg in messages.data:\n", + " role = msg.role\n", + " content = msg.content[0].text.value\n", + " print(f\"{role.capitalize()}: {content}\")\n", + " break\n", + "\n", + " #for msg in conversation: # Display the conversation\n", + " # print(f\"{msg['role'].capitalize()}: {msg['content']}\")\n", + " #return conversation\n", + " \n", + " elif run.status == \"requires_action\" and run.required_action.type == \"submit_tool_outputs\":\n", + " print(\"Function calling initiated...\")\n", + " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", + " tool_responses = []\n", + " \n", + " # Iterate over each function call requested by the assistant\n", + " for call in tool_calls:\n", + " # Check if the call is a function and if the function exists is our custom function\n", + " if call.type == \"function\" and call.function.name == \"fetch_stock_price\":\n", + " func = available_functions[call.function.name] # Retrieve the function reference\n", + " \n", + " # Parse the function arguments from JSON and execute the function\n", + " tool_response = func(**json.loads(call.function.arguments))\n", + " \n", + " # Store the tool call ID and output to later send back to the assistant\n", + " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", + " print(f\"Executed '{call.function.name}'. Output: {tool_response}\")\n", + " \n", + " else:\n", + " # Raise an error if the function is not in available_functions to handle unexpected requests\n", + " raise ValueError(f\"Requested function '{call.function.name}' is not available.\")\n", + " \n", + " # Submit all collected tool outputs back to the assistant to satisfy the required action\n", + " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " thread_id=thread_id, \n", + " run_id=run_id, \n", + " tool_outputs=tool_responses\n", + " )\n", + " print(\"Function call(s) completed successfully.\")\n", + " \n", + " else:\n", + " # If the assistant is still processing, wait before checking the status again\n", " print(\"Waiting for the Assistant to process...\")\n", " time.sleep(5)\n", "\"\"\"" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "user_prompt = \"What is the current stock price for Amazon?\"\n", + "\n", + "response = get_assistant_response(thread.id, run.id, user_prompt)\n", + "#for message in response:\n", + "# print(f\"{message['role'].capitalize()}: {message['content']}\")" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -818,7 +975,7 @@ }, { "cell_type": "code", - "execution_count": 217, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ From de61efcd83b00037ba5f0cbb614074750be98547 Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Fri, 15 Nov 2024 14:01:32 -0600 Subject: [PATCH 141/180] func 3/4 use cases working --- .../assistant-investment_portfolio.ipynb | 151 +++++++++++++----- 1 file changed, 114 insertions(+), 37 deletions(-) diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index 158999b3..2965c83e 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -72,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 94, "metadata": {}, "outputs": [ { @@ -124,7 +124,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 95, "metadata": {}, "outputs": [ { @@ -165,7 +165,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 96, "metadata": {}, "outputs": [ { @@ -173,7 +173,7 @@ "output_type": "stream", "text": [ "Deleted existing file: investment_portfolio.csv\n", - "Uploaded file: FileObject(id='assistant-FmXSjOD0yuvCqUEpp5QTYoeX', bytes=104, created_at=1731699733, filename='investment_portfolio.csv', object='file', purpose='assistants', status='processed', status_details=None)\n" + "Uploaded file: investment_portfolio.csv\n" ] } ], @@ -204,7 +204,7 @@ " # Upload new file\n", " with open(file_path, \"rb\") as file_data:\n", " portfolio_file = openai_client.files.create(file=file_data, purpose=\"assistants\")\n", - " print(f\"Uploaded file: {portfolio_file}\")\n", + " print(f\"Uploaded file: {portfolio_file.filename}\")\n", "\n", "except OpenAIError as e:\n", " print(f\"Error processing file '{portfolio_file}': {e}\")\n", @@ -229,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 97, "metadata": {}, "outputs": [ { @@ -290,7 +290,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 98, "metadata": {}, "outputs": [ { @@ -331,7 +331,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 99, "metadata": {}, "outputs": [ { @@ -339,7 +339,7 @@ "output_type": "stream", "text": [ "Assistant created successfully.\n", - " Assistant(id='asst_aExvRDZIJe9suJkaMQ79tAvj', created_at=1731699746, description=None, instructions='You are an expert investment analyst. Use your knowledge base to answer questions about personal investment portfolio management.', metadata={}, model='gpt-4o', name='Investment Management Assistant', object='assistant', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], response_format='auto', temperature=1.0, tool_resources=ToolResources(code_interpreter=ToolResourcesCodeInterpreter(file_ids=[]), file_search=None), top_p=1.0)\n" + " Assistant(id='asst_xvxLgxK8MUMutkrrMp5IMR92', created_at=1731700777, description=None, instructions='You are an expert investment analyst. Use your knowledge base to answer questions about personal investment portfolio management.', metadata={}, model='gpt-4o', name='Investment Management Assistant', object='assistant', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], response_format='auto', temperature=1.0, tool_resources=ToolResources(code_interpreter=ToolResourcesCodeInterpreter(file_ids=[]), file_search=None), top_p=1.0)\n" ] } ], @@ -377,7 +377,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 100, "metadata": {}, "outputs": [ { @@ -385,7 +385,7 @@ "output_type": "stream", "text": [ "Thread created successfully.\n", - " Thread(id='thread_G5Bf3Ul82M04GDQcR0czEsry', created_at=1731699749, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" + " Thread(id='thread_aDZQEiy8QK3QwMaHk3JiM6TI', created_at=1731700780, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" ] } ], @@ -628,11 +628,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 101, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function `process_message` created successfully.\n" + ] + } + ], "source": [ "import time\n", + "import json\n", + "\n", + "available_functions = {\"fetch_stock_price\": fetch_stock_price}\n", "\n", "def process_message(thread_id, prompt_message, attachments_list=None):\n", " try:\n", @@ -694,27 +705,35 @@ " # Handle failed\n", " break\n", "\n", - " if run.status == \"requires_action\":\n", - " print(\"Function Calling ...\")\n", + " elif run.status == \"requires_action\" and run.required_action.type == \"submit_tool_outputs\":\n", + " print(\"Function calling initiated...\")\n", + " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", " tool_responses = []\n", - " if (\n", - " run.required_action.type == \"submit_tool_outputs\"\n", - " and run.required_action.submit_tool_outputs.tool_calls is not None\n", - " ):\n", - " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", - "\n", - " for call in tool_calls:\n", - " if call.type == \"function\":\n", - " if call.function.name != \"fetch_stock_price\":\n", - " raise Exception(\"Function requested by the model does not exist\")\n", - " function_to_call = available_functions[call.function.name]\n", - " tool_response = function_to_call(**json.loads(call.function.arguments))\n", - " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", - " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", - "\n", + " \n", + " # Iterate over each function call requested by the assistant\n", + " for call in tool_calls:\n", + " # Check if the call is a function and if the function exists is our custom function\n", + " if call.type == \"function\" and call.function.name in available_functions:\n", + " func = available_functions[call.function.name] # Retrieve the function reference\n", + " \n", + " # Parse the function arguments from JSON and execute the function\n", + " tool_response = func(**json.loads(call.function.arguments))\n", + " \n", + " # Store the tool call ID and output to later send back to the assistant\n", + " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", + " print(f\"Executed '{call.function.name}'. Output: {tool_response}\")\n", + " \n", + " else:\n", + " # Raise an error if the function is not in available_functions to handle unexpected requests\n", + " raise ValueError(f\"Requested function '{call.function.name}' is not available.\")\n", + " \n", + " # Submit all collected tool outputs back to the assistant to satisfy the required action\n", " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", - " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", + " thread_id=thread_id, \n", + " run_id=run.id, \n", + " tool_outputs=tool_responses\n", " )\n", + " print(\"Function call(s) completed successfully.\")\n", "\n", " else:\n", " time.sleep(5)\n", @@ -724,18 +743,51 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 102, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: completed\n", + "\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 15, 2024.\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 103, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: in_progress\n", + "\n", + "Run Status: completed\n", + "\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 15, 2024.\n", + "User: What stock do I have the most investment in?\n", + "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the stock, the average cost per share, and the quantity of shares held, respectively.\n", + "\n", + "To determine which stock you have the most investment in, I will calculate the total investment for each stock (Average Cost * Quantity) and identify the one with the highest value.\n", + "Assistant: The stock you have the most investment in is Tesla (TSLA) with a total investment of $90,000.\n" + ] + } + ], "source": [ "attachments=[ # Add files by using the attachments parameter\n", " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", @@ -746,9 +798,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 104, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: requires_action\n", + "\n", + "Function calling initiated...\n", + "Executed 'fetch_stock_price'. Output: 200.65\n", + "Function call(s) completed successfully.\n", + "Run Status: completed\n", + "\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 15, 2024.\n", + "User: What stock do I have the most investment in?\n", + "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the stock, the average cost per share, and the quantity of shares held, respectively.\n", + "\n", + "To determine which stock you have the most investment in, I will calculate the total investment for each stock (Average Cost * Quantity) and identify the one with the highest value.\n", + "Assistant: The stock you have the most investment in is Tesla (TSLA) with a total investment of $90,000.\n", + "User: What is the current stock price for Amazon?\n", + "Assistant: The current stock price for Amazon (AMZN) is $200.65.\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon?\")" ] From 7bc8d65d6a4e8998ddbc73d43208a84b0cf8038c Mon Sep 17 00:00:00 2001 From: e-straight Date: Fri, 15 Nov 2024 16:03:23 -0400 Subject: [PATCH 142/180] AzureFunctions --- .../human-approval/AgentFunctionsSample.sln | 25 +++++++++++ .../ApprovalWithHumanInteraction.csproj | 23 ++++++++++ .../ApprovalWithHumanInteraction.cs} | 10 ++--- .../Functions/Input.cs | 14 ++++++ .../Functions/Response.cs | 19 ++++++++ .../Properties/launchSettings.json | 9 ++++ .../Properties/serviceDependencies.json | 11 +++++ .../Properties/serviceDependencies.local.json | 11 +++++ .../ApprovalWithHumanInteraction/host.json | 12 ++++++ .../azure-functions/human-approval/readme.md | 43 +++++++++++++++++++ 10 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 samples/azure-functions/human-approval/AgentFunctionsSample.sln create mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj rename samples/azure-functions/human-approval/{AgentFunctions.cs => ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs} (94%) create mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs create mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs create mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json create mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json create mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json create mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json create mode 100644 samples/azure-functions/human-approval/readme.md diff --git a/samples/azure-functions/human-approval/AgentFunctionsSample.sln b/samples/azure-functions/human-approval/AgentFunctionsSample.sln new file mode 100644 index 00000000..4476f3ff --- /dev/null +++ b/samples/azure-functions/human-approval/AgentFunctionsSample.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApprovalWithHumanInteraction", "ApprovalWithHumanInteraction\ApprovalWithHumanInteraction.csproj", "{A6871579-7804-47E2-BD34-780B00D4493E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A6871579-7804-47E2-BD34-780B00D4493E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6871579-7804-47E2-BD34-780B00D4493E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6871579-7804-47E2-BD34-780B00D4493E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6871579-7804-47E2-BD34-780B00D4493E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C655EA00-81D8-45B1-9768-EC94B569075B} + EndGlobalSection +EndGlobal \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj new file mode 100644 index 00000000..bbbce003 --- /dev/null +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj @@ -0,0 +1,23 @@ + + + net8.0 + v4 + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + \ No newline at end of file diff --git a/samples/azure-functions/human-approval/AgentFunctions.cs b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs similarity index 94% rename from samples/azure-functions/human-approval/AgentFunctions.cs rename to samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs index 74a99a6b..00ee93c9 100644 --- a/samples/azure-functions/human-approval/AgentFunctions.cs +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs @@ -39,19 +39,19 @@ public static async Task TriggerOrchestrator( ILogger log) { // initiate the overall workflow by starting the orchestrator. - var instanceId = await durableOrchestrationClient.StartNewAsync(nameof(WorkflowOrchestrator), input); + var instanceId = await durableOrchestrationClient.StartNewAsync(nameof(WorklowOrchestrator), input); log.LogInformation($"Started orchestration instanceId: {instanceId}"); } ///

    /// Orchestration function to start approval process /// - [FunctionName(nameof(WorkflowOrchestrator))] - public static async Task WorkflowOrchestrator( + [FunctionName(nameof(WorklowOrchestrator))] + public static async Task WorklowOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log) { - log.LogInformation($"{nameof(WorkflowOrchestrator)} triggered, orchestration instanceId: {context.InstanceId}"); + log.LogInformation($"{nameof(WorklowOrchestrator)} triggered, orchestration instanceId: {context.InstanceId}"); var workflowInput = context.GetInput(); // call activity function(s) to perform actual work @@ -60,7 +60,7 @@ public static async Task WorkflowOrchestrator( // wait for the approval response var response = await context.WaitForExternalEvent("ApprovalResponse"); - log.LogInformation($"{nameof(WorkflowOrchestrator)} ApprovalResponse received: {response}, orchestration instanceId: {context.InstanceId}"); + log.LogInformation($"{nameof(WorklowOrchestrator)} ApprovalResponse received: {response}, orchestration instanceId: {context.InstanceId}"); // complete the approval process await context.CallActivityAsync( diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs new file mode 100644 index 00000000..5cf09f68 --- /dev/null +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs @@ -0,0 +1,14 @@ +namespace ApprovalWithHumanInteraction.Functions +{ + /// + /// All Azure Functions that participate in the Agents framework must accept a json serializable input object that contains an opaque string named CorrelationId. + /// + /// This is a REQUIRED class structure + public abstract class Input + { + /// + /// An opaque internal identifier that is used to correlate the response with the request. + /// + public string CorrelationId { get; set; } + } +} \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs new file mode 100644 index 00000000..ff2161e7 --- /dev/null +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs @@ -0,0 +1,19 @@ +namespace ApprovalWithHumanInteraction.Functions +{ + /// + /// All Azure Functions that participate in the Agents framework must return a json serializable response object that contains these values. + /// + /// This is a REQUIRED class structure + public class Response + { + /// + /// This value is fed back to the model as the tool's response. + /// + public string Value { get; set; } + + /// + /// An opaque internal identifier that is used to correlate the response with the request. + /// + public string CorrelationId { get; set; } + } +} \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json new file mode 100644 index 00000000..f210469e --- /dev/null +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "Project": { + "commandName": "Project", + "commandLineArgs": "--port 7146", + "launchBrowser": false + } + } + } \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json new file mode 100644 index 00000000..9e14b0a2 --- /dev/null +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "connectionId": "APPLICATIONINSIGHTS_CONNECTION_STRING" + }, + "storage1": { + "type": "storage", + "connectionId": "AzureWebJobsStorage" + } + } + } \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json new file mode 100644 index 00000000..a87eee0c --- /dev/null +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk" + }, + "storage1": { + "type": "storage.emulator", + "connectionId": "AzureWebJobsStorage" + } + } + } \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json new file mode 100644 index 00000000..ee5cf5f8 --- /dev/null +++ b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/samples/azure-functions/human-approval/readme.md b/samples/azure-functions/human-approval/readme.md new file mode 100644 index 00000000..e57a65dc --- /dev/null +++ b/samples/azure-functions/human-approval/readme.md @@ -0,0 +1,43 @@ +## Azure Functions +Azure Functions are a serverless compute service that lets you run event-triggered code without having to explicitly provision or manage infrastructure. This section provides an example of how to set up an AzureFunction. NOTE: Currently, agents are not included in the sample, but will be added shortly. + +Important notes: +The identity of your AI Project MUST be part of the Azure Storage Queue Data Contributor RBAC role for the provisioned storage account. + +Azure Functions intended for use by agents can be deployed anywhere, but they require read/write access to Azure storage queues within the storage account that was provisioned for your AI project. To do that we recommend also adding the identity of your Azure Functions to the Azure Storage Queue Data Contributor RBAC role for the storage account. The identity can be either a system-assigned or user-assigned managed identity. + + + +Known Limitations + +Azure Function support is limited to functions triggered by queue messages. No other triggers are allowed. + +Queue message size is limited by Azure Storage Queues to 64k + +Parallel invocation of multiple Azure Functions from the same agent run is not supported. + +Limit = 128 functions + +FAQ + +Q: How do you integrate a function that is in Azure Functions SDK with Agents SDK? + +A: During the provisioning process, a storage account is created. + +Step 1: connect the Azure Function to this queue that was provisioned for you during hub creation. + +Step 2: when you create an assistant, you create with a payload. Like any other tool, you register the Azure Function, give it a set of functions. Two things are done independently: + +write a function attached to the queue + +issue an assistant request with configuration. These two things are entirely independent (don’t even need to be in the same region), but will talk to each other in the cloud. + +Q: Which Microsoft solution is right for me? + +A: + +Local function calling – Use this option if you’re going to interact with a system device, like opening Spotify (or something on your machine). + +Azure Functions – Use this option if you want to write logic that interacts with other services, that is naturally event-driven or long-running, or if you want to scale. + +Logic Apps – Use this option when you don’t want to write the logic, if you just want to see if there’s an existing connector/tool. E.g., converting a doc to PDF or sending an email. In these examples, the tools already have built-in functions, so there’s no need to create your own. \ No newline at end of file From ff4502b322ada299c564b989d17e46830ee36773 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 15 Nov 2024 12:40:12 -0800 Subject: [PATCH 143/180] updating readme --- .../azure-functions/human-approval/readme.md | 47 ++++++++++--------- samples/tracing/readme.md | 8 ++-- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/samples/azure-functions/human-approval/readme.md b/samples/azure-functions/human-approval/readme.md index e57a65dc..7ee1262e 100644 --- a/samples/azure-functions/human-approval/readme.md +++ b/samples/azure-functions/human-approval/readme.md @@ -1,43 +1,46 @@ ## Azure Functions -Azure Functions are a serverless compute service that lets you run event-triggered code without having to explicitly provision or manage infrastructure. This section provides an example of how to set up an AzureFunction. NOTE: Currently, agents are not included in the sample, but will be added shortly. -Important notes: -The identity of your AI Project MUST be part of the Azure Storage Queue Data Contributor RBAC role for the provisioned storage account. +Azure Functions are a serverless compute service that lets you run event-triggered code without having to explicitly provision or manage infrastructure. This section provides an example of how to set up an AzureFunction. -Azure Functions intended for use by agents can be deployed anywhere, but they require read/write access to Azure storage queues within the storage account that was provisioned for your AI project. To do that we recommend also adding the identity of your Azure Functions to the Azure Storage Queue Data Contributor RBAC role for the storage account. The identity can be either a system-assigned or user-assigned managed identity. +> [!NOTE] +> Currently, agents are not included in the sample, but will be added shortly. - +## Important notes -Known Limitations +* The identity of your AI Project MUST be part of the Azure Storage Queue Data Contributor RBAC role for the provisioned storage account. -Azure Function support is limited to functions triggered by queue messages. No other triggers are allowed. +* Azure Functions intended for use by agents can be deployed anywhere, but they require read/write access to Azure storage queues within the storage account that was provisioned for your AI project. To do that we recommend also adding the identity of your Azure Functions to the Azure Storage Queue Data Contributor RBAC role for the storage account. The identity can be either a system-assigned or user-assigned managed identity. -Queue message size is limited by Azure Storage Queues to 64k +## Known Limitations -Parallel invocation of multiple Azure Functions from the same agent run is not supported. +* Azure Function support is limited to functions triggered by queue messages. No other triggers are allowed. -Limit = 128 functions +* Queue message size is limited by Azure Storage Queues to 64k. -FAQ +* Parallel invocation of multiple Azure Functions from the same agent run is not supported. -Q: How do you integrate a function that is in Azure Functions SDK with Agents SDK? +* There is a limit of 128 functions. -A: During the provisioning process, a storage account is created. +## FAQ + +**Q: How do you integrate a function that is in Azure Functions SDK with Agents SDK?** -Step 1: connect the Azure Function to this queue that was provisioned for you during hub creation. +A: During the provisioning process, a storage account is created. -Step 2: when you create an assistant, you create with a payload. Like any other tool, you register the Azure Function, give it a set of functions. Two things are done independently: +1. connect the Azure Function to this queue that was provisioned for you during hub creation. -write a function attached to the queue +1. when you create an assistant, you create with a payload. Like any other tool, you register the Azure Function, give it a set of functions. Two things are done independently: -issue an assistant request with configuration. These two things are entirely independent (don’t even need to be in the same region), but will talk to each other in the cloud. +1. Write a function attached to the queue. + +1. Issue an assistant request with the configuration. The assistant and configuration are entirely independent (they don't even need to be in the same region), but will talk to each other in the cloud. -Q: Which Microsoft solution is right for me? +**Q: Which Microsoft solution is right for me?** -A: +A: There are multiple possibilities: -Local function calling – Use this option if you’re going to interact with a system device, like opening Spotify (or something on your machine). +* Local function calling – Use this option if you’re going to interact with a system device, like opening Spotify (or something on your machine). -Azure Functions – Use this option if you want to write logic that interacts with other services, that is naturally event-driven or long-running, or if you want to scale. +* Azure Functions – Use this option if you want to write logic that interacts with other services, that is naturally event-driven or long-running, or if you want to scale. -Logic Apps – Use this option when you don’t want to write the logic, if you just want to see if there’s an existing connector/tool. E.g., converting a doc to PDF or sending an email. In these examples, the tools already have built-in functions, so there’s no need to create your own. \ No newline at end of file +* Logic Apps – Use this option when you don’t want to write the logic, or if you just want to see if there’s an existing connector/tool. For example converting a doc to PDF or sending an email. In these examples, the tools already have built-in functions, so there’s no need to create your own. \ No newline at end of file diff --git a/samples/tracing/readme.md b/samples/tracing/readme.md index 742d244e..78437265 100644 --- a/samples/tracing/readme.md +++ b/samples/tracing/readme.md @@ -1,10 +1,10 @@ -### Tracing +### Tracing using Application Insights -You can add an Application Insights Azure resource to your Azure AI Studio project. See the Tracing tab in your studio. If one was enabled, you can get the Application Insights connection string, configure your Agents, and observe the full execution path through Azure Monitor. Typically, you might want to start tracing before you create an Agent. +Tracing lets you analyze your agent's performance and behavior by using OpenTelemetry and adding an Application Insights Azure resource to your Azure AI Studio project. See the Tracing tab in your [AI studio](https://ai.azure.com/) project page. If one was enabled, you can get the Application Insights connection string, configure your Agents, and observe the full execution path through Azure Monitor. Typically, you might want to start tracing before you create an Agent. #### Installation -Make sure to install OpenTelemetry and the Azure SDK tracing plugin via +Make sure to install OpenTelemetry and the Azure SDK tracing plugin: ```bash pip install opentelemetry @@ -13,7 +13,7 @@ pip install azure-core-tracing-opentelemetry You will also need an exporter to send telemetry to your observability backend. You can print traces to the console or use a local viewer such as [Aspire Dashboard](https://learn.microsoft.com/dotnet/aspire/fundamentals/dashboard/standalone?tabs=bash). -To connect to Aspire Dashboard or another OpenTelemetry compatible backend, install OTLP exporter: +To connect to Aspire Dashboard or another OpenTelemetry compatible backend, install the OTLP exporter: ```bash pip install opentelemetry-exporter-otlp From 135c6840ce1e73d55b0728ab7ff029e6ae91ebcd Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Fri, 15 Nov 2024 15:08:38 -0600 Subject: [PATCH 144/180] cleanup markdown --- .../assistant-investment_portfolio.ipynb | 512 +++++------------- 1 file changed, 148 insertions(+), 364 deletions(-) diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index 2965c83e..a0a0ed2f 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -59,30 +59,35 @@ "metadata": {}, "source": [ "#### Step 2: Setting up the environment\n", + "Before we begin, we need to load the necessary environment variables from a `.env` file. These variables include sensitive information such as API keys and endpoint URLs, which are crucial for running the code successfully.\n", "\n", - "Before we begin, we'll load all necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.venv/.env` format. In order to run the following code, the `.env` file must contain the follow secrets:\n", + "Here’s what you need to do:\n", + "- Ensure your `.env` file is properly configured in the `.venv/.env` format.\n", + "- Verify that all required secrets are included in the file before running the code.\n", "\n", - "- AZURE_OPENAI_API_KEY\n", - "- AZURE_OPENAI_ENDPOINT\n", + "\n", + "The `.env` file must contain the following secrets:\n", + "- AZURE_OPENAI_API_KEY: Your unique API key for accessing the service.\n", + "- AZURE_OPENAI_ENDPOINT: The URL endpoint for the API.\n", "- AZURE_OPENAI_DEPLOYMENT\n", "- AZURE_OPENAI_API_VERSION \n", "\n", - "For more information about leveraging Python Virtual Environments can be found [here]()." + "Now, let’s load these variables and get started!\n", + "\n", + "Note: Make sure to keep your `.env` file secure and avoid sharing it publicly. \n", + "\n", + "*For more information about leveraging Python Virtual Environments can be found [here](https://docs.python.org/3/library/venv.html).*" ] }, { "cell_type": "code", - "execution_count": 94, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment variables loaded successfully.\n" - ] + "execution_count": null, + "metadata": { + "notebookRunGroups": { + "groupValue": "2" } - ], + }, + "outputs": [], "source": [ "import os\n", "from dotenv import load_dotenv\n", @@ -124,17 +129,13 @@ }, { "cell_type": "code", - "execution_count": 95, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "AzureOpenAI client initialized.\n" - ] + "execution_count": null, + "metadata": { + "notebookRunGroups": { + "groupValue": "2" } - ], + }, + "outputs": [], "source": [ "from openai import AzureOpenAI, OpenAIError\n", "\n", @@ -165,18 +166,13 @@ }, { "cell_type": "code", - "execution_count": 96, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Deleted existing file: investment_portfolio.csv\n", - "Uploaded file: investment_portfolio.csv\n" - ] + "execution_count": null, + "metadata": { + "notebookRunGroups": { + "groupValue": "2" } - ], + }, + "outputs": [], "source": [ "# Directory containing files to upload\n", "directory=\"data\"\n", @@ -223,23 +219,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 1: Define function for Assistant\n", - "The `fetch_stock_price` function retrieves the stock data for a specified `ticker symbol` using the `yfinance` library, specifically pulling the latest data for the last trading day." + "### Step 1: Define function for Assistant Function Calling tool\n", + "In this scenario, we will utilize the *Function Calling* tool within the Assistant to enhance our insights by invoking a custom function. Since the LLM and Assistant currently lack direct access to the internet for user prompts, Function Calling serves as a powerful alternative.\n", + "\n", + "We will use the `fetch_stock_price` function to retrieve stock data for a specified *ticker symbol*. This function leverages the `yfinance` library to fetch the most recent stock price data, specifically for the last trading day.\n", + "\n", + "This approach enables the Assistant to provide real-time, actionable insights by integrating external data sources through custom functions. Let’s explore how to implement and use this functionality!" ] }, { "cell_type": "code", - "execution_count": 97, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import yfinance as yf\n", "\n", @@ -284,23 +276,24 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2: Define Function Calling tool for Assistant\n", - "The tool-calling definition informs the LLM about available tools. For our scenario, it enables code interpretation and function calling. The `fetch_stock_price` function configuration is to be used along side the code interpreter tool. By adding this tool to the Assistant, we enable it to retrieve and interpret stock data when a user prompts it with related queries." + "### Step 2: Configure Assistant Tool-Calling for Enhanced Functionality\n", + "The tool-calling definition informs the LLM about the tools available for its use. In our scenario, this configuration enables both *code interpretation* and *function calling*, allowing the Assistant to perform complex operations and retrieve external data.\n", + "\n", + "We will specifically configure the `fetch_stock_price` function alongside the *code interpreter tool*. By integrating this tool into the Assistant, we empower it to:\n", + "\n", + "- Retrieve stock data for a specified ticker symbol using the `fetch_stock_price` function.\n", + "- Interpret and analyze the retrieved data to provide meaningful insights in response to user queries.\n", + "\n", + "This setup allows the Assistant to seamlessly combine external data retrieval with code-based reasoning, ensuring accurate and actionable responses to stock-related prompts. \n", + "\n", + "Let’s define and integrate this tool to unlock its full potential!" ] }, { "cell_type": "code", - "execution_count": 98, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tools list defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "tools_list = [\n", " {\"type\": \"code_interpreter\"},\n", @@ -325,24 +318,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 3: Creating the Investment Management Assistant\n", - "In this step, we create an assistant equipped with specialized tools, including a code interpreter, to handle investment-related queries and utilize the previously defined function calls. This assistant will analyze the uploaded portfolio file and offer valuable insights." + "### Step 3: Creating an Investment Analysis Assistant\n", + "In this step, we’ll set up an assistant with specialized tools, including a *code interpreter*, to handle investment-related queries. This assistant will also leverage the previously defined function calls to provide accurate and actionable insights. \n", + "\n", + "Let’s configure the assistant and enable its capabilities! " ] }, { "cell_type": "code", - "execution_count": 99, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Assistant created successfully.\n", - " Assistant(id='asst_xvxLgxK8MUMutkrrMp5IMR92', created_at=1731700777, description=None, instructions='You are an expert investment analyst. Use your knowledge base to answer questions about personal investment portfolio management.', metadata={}, model='gpt-4o', name='Investment Management Assistant', object='assistant', tools=[CodeInterpreterTool(type='code_interpreter'), FunctionTool(function=FunctionDefinition(name='fetch_stock_price', description='Retrieve the latest closing price of a stock using its ticker symbol.', parameters={'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, strict=False), type='function')], response_format='auto', temperature=1.0, tool_resources=ToolResources(code_interpreter=ToolResourcesCodeInterpreter(file_ids=[]), file_search=None), top_p=1.0)\n" - ] - } - ], + "outputs": [], "source": [ "# Create the assistant with code interpreter and function calling tools enabled\n", "try:\n", @@ -355,7 +341,7 @@ " model=__AZURE_OPENAI_DEPLOYMENT,\n", " tools=tools_list\n", " )\n", - " print(\"Assistant created successfully.\\n\", assistant)\n", + " print(\"Assistant created successfully.\\n\", assistant.id)\n", "except OpenAIError as e:\n", " print(\"Error creating assistant:\", e)" ] @@ -372,28 +358,21 @@ "metadata": {}, "source": [ "### Step 1: Starting a New Conversation Thread\n", - "Let's create a new thread to handle user interactions. Each thread allows for a dedicated conversation with the assistant." + "Let’s create a new thread to handle user interactions. Each thread provides a dedicated space for conversations with the assistant, keeping the context focused and organized. \n", + "\n", + "This setup ensures clear and seamless communication for each user interaction." ] }, { "cell_type": "code", - "execution_count": 100, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Thread created successfully.\n", - " Thread(id='thread_aDZQEiy8QK3QwMaHk3JiM6TI', created_at=1731700780, metadata={}, object='thread', tool_resources=ToolResources(code_interpreter=None, file_search=None))\n" - ] - } - ], + "outputs": [], "source": [ "# Create a conversation thread\n", "try:\n", " thread = openai_client.beta.threads.create()\n", - " print(\"Thread created successfully.\\n\", thread)\n", + " print(\"Thread created successfully.\\n\", thread.id)\n", "except OpenAIError as e:\n", " print(\"Error creating thread:\", e)" ] @@ -402,8 +381,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2: Adding User Message\n", - "In this step, we add a question to the thread. For this demonstration, we'll what the latest closing price is for specified company (*Microsoft*) that will leverage *function calling* to retrieve this information from the `fetch_stock_price` function. Then, code interpreter will use this information as well as the `QTY` data from the `investment_portfolio.csv` that was uploaded to calculate the **total investment**." + "### Step 2: Adding User Message to the Thread\n", + "In this step, we’ll add a user message to the thread to demonstrate the assistant’s capabilities. Specifically, we’ll ask for the latest closing price of a specified company (*Microsoft*), which will leverage *function calling* to retrieve this data using the `fetch_stock_price` function.\n", + "\n", + "The assistant will then use the *code interpreter* to combine this information with the `QTY` data from the uploaded `investment_portfolio.csv` file to calculate the **total investment**. \n", + "\n", + "This workflow showcases how the assistant integrates external data retrieval with computational analysis to deliver actionable insights." ] }, { @@ -434,8 +417,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 3: Running the Assistant\n", - "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" + " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" ] }, { @@ -444,23 +426,26 @@ "metadata": {}, "outputs": [], "source": [ - "# Initiate the assistant's response\n", - "try:\n", - " run = openai_client.beta.threads.runs.create(\n", - " thread_id=thread.id,\n", - " assistant_id=assistant.id,\n", - " instructions=prompt_content,\n", - " )\n", - " print(\"Run started:\", run)\n", - "except OpenAIError as e:\n", - " print(\"Error starting run:\", e)" + "available_functions = {\"fetch_stock_price\": fetch_stock_price}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" + "## **Demonstrating the Thread Run Process (Manual)**\n", + "\n", + "The next four cells will demonstrate how the assistant's thread run process works. Instead of running a typical loop with polling to monitor the run status, we’ll manually step through the cells to better understand each stage of the process.\n", + "\n", + "In the subsequent section, these cells will be wrapped into a processing function that incorporates the polling functionality, providing a more streamlined and automated workflow. This approach helps clarify how the thread execution operates while offering a hands-on view of each step." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 3: Running the Assistant\n", + "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" ] }, { @@ -469,7 +454,16 @@ "metadata": {}, "outputs": [], "source": [ - "available_functions = {\"fetch_stock_price\": fetch_stock_price}" + "# Initiate the assistant's response\n", + "try:\n", + " run = openai_client.beta.threads.runs.create(\n", + " thread_id=thread.id,\n", + " assistant_id=assistant.id,\n", + " instructions=prompt_content,\n", + " )\n", + " print(\"Run started:\", run)\n", + "except OpenAIError as e:\n", + " print(\"Error starting run:\", e)" ] }, { @@ -620,25 +614,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Next Step / Let's refine \n", - "Wrap in function - explain the \n", + "## **Refining the Process**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 1: Wrapping the Thread Run Process into a Function\n", + "In this section we will refine the manual approach and encapsulate the thread run process into a single processing function. This function automates the steps demonstrated in the previous cells by including the polling functionality to monitor the run status.\n", + "\n", + "By wrapping the process into a reusable function, we streamline the workflow and ensure that the thread execution is both efficient and easy to integrate into broader applications. \n", "\n", - "We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available." + "Let’s implement this functionality!" ] }, { "cell_type": "code", - "execution_count": 101, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function `process_message` created successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import time\n", "import json\n", @@ -742,92 +737,27 @@ ] }, { - "cell_type": "code", - "execution_count": 102, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: completed\n", - "\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 15, 2024.\n" - ] - } - ], "source": [ - "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" + "### Step 2a: Basic Message Sample\n", + "This sample uses the user message asking \"What is today's date?\" which uses the standard/base LLM system to determine the response." ] }, { "cell_type": "code", - "execution_count": 103, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: in_progress\n", - "\n", - "Run Status: completed\n", - "\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 15, 2024.\n", - "User: What stock do I have the most investment in?\n", - "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the stock, the average cost per share, and the quantity of shares held, respectively.\n", - "\n", - "To determine which stock you have the most investment in, I will calculate the total investment for each stock (Average Cost * Quantity) and identify the one with the highest value.\n", - "Assistant: The stock you have the most investment in is Tesla (TSLA) with a total investment of $90,000.\n" - ] - } - ], + "outputs": [], "source": [ - "attachments=[ # Add files by using the attachments parameter\n", - " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", - " ]\n", - "\n", - "process_message(thread_id=thread.id, prompt_message=\"What stock do I have the most investment in?\", attachments_list=attachments)" + "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] }, { - "cell_type": "code", - "execution_count": 104, + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: requires_action\n", - "\n", - "Function calling initiated...\n", - "Executed 'fetch_stock_price'. Output: 200.65\n", - "Function call(s) completed successfully.\n", - "Run Status: completed\n", - "\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 15, 2024.\n", - "User: What stock do I have the most investment in?\n", - "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the stock, the average cost per share, and the quantity of shares held, respectively.\n", - "\n", - "To determine which stock you have the most investment in, I will calculate the total investment for each stock (Average Cost * Quantity) and identify the one with the highest value.\n", - "Assistant: The stock you have the most investment in is Tesla (TSLA) with a total investment of $90,000.\n", - "User: What is the current stock price for Amazon?\n", - "Assistant: The current stock price for Amazon (AMZN) is $200.65.\n" - ] - } - ], "source": [ - "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon?\")" + "### Step 2b: Code Interpreter Sample" ] }, { @@ -836,89 +766,18 @@ "metadata": {}, "outputs": [], "source": [ - "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments?\")" + "attachments=[ # Add files by using the attachments parameter\n", + " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", + " ]\n", + "\n", + "process_message(thread_id=thread.id, prompt_message=\"What stock do I have the most investment in?\", attachments_list=attachments)" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "import time\n", - "\n", - "def process_message_old(thread_id, prompt_message, attachments_list=None):\n", - "\n", - " try:\n", - " # Add the prompt to the thread\n", - " message = openai_client.beta.threads.messages.create(\n", - " thread_id=thread_id,\n", - " role=\"user\",\n", - " content=prompt_message,\n", - " attachments=attachments_list,\n", - " )\n", - " print(\"User question added:\", message)\n", - "\n", - " # Initiate the assistant's response\n", - " run = openai_client.beta.threads.runs.create(\n", - " thread_id=thread.id,\n", - " assistant_id=assistant.id,\n", - " instructions=prompt_message,\n", - " )\n", - " print(\"Run started:\", run)\n", - " except OpenAIError as e:\n", - " print(\"Error starting run:\", e)\n", - "\n", - "\n", - " while True: # Polling to monitor Run status\n", - " \n", - " # Wait 5 seconds to give the process time to move past `queued` state\n", - " time.sleep(5)\n", - "\n", - " # Retrieves the thread’s response.\n", - " run = openai_client.beta.threads.runs.retrieve(\n", - " thread_id=thread_id,\n", - " run_id=run.id\n", - " )\n", - "\n", - " run_status = run.status\n", - " print(f\"Run Status: {run_status}\\n\")\n", - " if run_status =='completed':\n", - "\n", - " # Get all messages in thread to read\n", - " thread_messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\") #, after=message.id)\n", - "\n", - " # Loop through thread messages and print content\n", - " for thread_message in thread_messages.data:\n", - " role = thread_message.role\n", - " #content = thread_message.content[0].text.value\n", - " \n", - " # Safely access content based on its actual structure\n", - " if isinstance(thread_message.content, list) and thread_message.content:\n", - " first_content = thread_message.content[0]\n", - " if hasattr(first_content, 'text') and hasattr(first_content.text, 'value'):\n", - " content = first_content.text.value\n", - " else:\n", - " content = str(first_content) # Fallback to string representation\n", - " else:\n", - " content = str(thread_message.content) # Handle non-list or empty content\n", - "\n", - " # Printing the `role` makes the result conversational for users\n", - " print(f\"{role.capitalize()}: {content}\")\n", - " \n", - " break\n", - " elif run.status == \"failed\":\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread.id)\n", - " answer = messages.data[0].content[0].text.value\n", - " print(f\"Failed User:\\n{prompt_message}\\nAssistant:\\n{answer}\\n\")\n", - " # Handle failed\n", - " break\n", - "\n", - " \n", - " else:\n", - " time.sleep(5)\n", - "\n", - "print(\"Function `process_message` created successfully.\")" + "### Step 2c: Function Calling Sample" ] }, { @@ -927,126 +786,37 @@ "metadata": {}, "outputs": [], "source": [ - "\"\"\"\n", - "import time \n", - "\n", - "def get_assistant_response(thread_id, run_id, user_prompt):\n", - " \n", - " Interacts with the assistant by sending a user prompt, handling function calls if required, \n", - " and retrieving the conversation messages as a response.\n", - "\n", - " Parameters:\n", - " thread_id (str): ID of the conversation thread.\n", - " run_id (str): ID of the current assistant run.\n", - " user_prompt (str): The user's prompt or question.\n", - "\n", - " Returns:\n", - " list of dict: Each message as a dictionary with 'role' and 'content' keys.\n", - " \n", - " # Send initial prompt - Add a message to the thread with the role of \"user\" and the provided content \n", - " openai_client.beta.threads.messages.create(\n", - " thread_id=thread_id, # Use the ID of the thread passed through to the function\n", - " content=user_prompt, # User content message\n", - " role=\"user\" # Role of the message sender\n", - " )\n", - "\n", - " # Polling to monitor Run status\n", - " while True:\n", - " # Retrieve and inspect the assistant's current run status\n", - " run = openai_client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)\n", - "\n", - " if run.status == \"failed\":\n", - " print(\"Assistant run failed. Please try again.\")\n", - " break\n", - " #return [{\"role\": \"system\", \"content\": \"Assistant run failed. Please try again.\"}]\n", - " \n", - " elif run.status == \"completed\":\n", - " # Collect messages if run is complete\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\")\n", - " #conversation = [{\"role\": msg.role, \"content\": msg.content[0].text.value} for msg in messages.data]\n", - "\n", - " # Loop through messages and print content based on role\n", - " for msg in messages.data:\n", - " role = msg.role\n", - " content = msg.content[0].text.value\n", - " print(f\"{role.capitalize()}: {content}\")\n", - " break\n", - "\n", - " #for msg in conversation: # Display the conversation\n", - " # print(f\"{msg['role'].capitalize()}: {msg['content']}\")\n", - " #return conversation\n", - " \n", - " elif run.status == \"requires_action\" and run.required_action.type == \"submit_tool_outputs\":\n", - " print(\"Function calling initiated...\")\n", - " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", - " tool_responses = []\n", - " \n", - " # Iterate over each function call requested by the assistant\n", - " for call in tool_calls:\n", - " # Check if the call is a function and if the function exists is our custom function\n", - " if call.type == \"function\" and call.function.name == \"fetch_stock_price\":\n", - " func = available_functions[call.function.name] # Retrieve the function reference\n", - " \n", - " # Parse the function arguments from JSON and execute the function\n", - " tool_response = func(**json.loads(call.function.arguments))\n", - " \n", - " # Store the tool call ID and output to later send back to the assistant\n", - " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", - " print(f\"Executed '{call.function.name}'. Output: {tool_response}\")\n", - " \n", - " else:\n", - " # Raise an error if the function is not in available_functions to handle unexpected requests\n", - " raise ValueError(f\"Requested function '{call.function.name}' is not available.\")\n", - " \n", - " # Submit all collected tool outputs back to the assistant to satisfy the required action\n", - " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", - " thread_id=thread_id, \n", - " run_id=run_id, \n", - " tool_outputs=tool_responses\n", - " )\n", - " print(\"Function call(s) completed successfully.\")\n", - " \n", - " else:\n", - " # If the assistant is still processing, wait before checking the status again\n", - " print(\"Waiting for the Assistant to process...\")\n", - " time.sleep(5)\n", - "\"\"\"" + "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon?\")" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "user_prompt = \"What is the current stock price for Amazon?\"\n", - "\n", - "response = get_assistant_response(thread.id, run.id, user_prompt)\n", - "#for message in response:\n", - "# print(f\"{message['role'].capitalize()}: {message['content']}\")" + "### Step 2d: Image Response" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "#### More Examples using Function\n", - "- one basic with image (uses CI)\n", - "- one basic function calling " + "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments?\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Wrap Up" + "## **Wrap Up**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## **Cleanup Resources**\n", + "### Step 1: Cleanup Assistant Resource\n", "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources. Run this cell at the end of your session to clean up.\n" ] }, @@ -1062,6 +832,20 @@ "# Optionally delete any other temporary files or datas\n", "# Note: Any uploaded files to OpenAI could also be cleaned up if needed\n" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 2: Cleanup File(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 3: Next Steps" + ] } ], "metadata": { From 5d21bc4135e726469ecb2263e46f68a29700aebf Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Fri, 15 Nov 2024 15:22:33 -0600 Subject: [PATCH 145/180] added markdown content to samples --- .../assistant-investment_portfolio.ipynb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index a0a0ed2f..799f5a64 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -741,7 +741,7 @@ "metadata": {}, "source": [ "### Step 2a: Basic Message Sample\n", - "This sample uses the user message asking \"What is today's date?\" which uses the standard/base LLM system to determine the response." + "This sample demonstrates how the assistant uses the standard LLM system to answer the query: *\"What is today's date?\"* The assistant responds by retrieving the current date directly from its built-in capabilities, without relying on additional tools or attachments." ] }, { @@ -757,7 +757,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2b: Code Interpreter Sample" + "### Step 2b: Code Interpreter Sample\n", + "This sample demonstrates using the *Code Interpreter* to analyze an uploaded portfolio file and answer the query: \"What stock do I have the most investment in?\". The Code Interpreter analyzes the file to identify the stock with the highest investment and provides the result, showcasing its ability to integrate data analysis seamlessly into the conversation." ] }, { @@ -777,7 +778,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2c: Function Calling Sample" + "### Step 2c: Function Calling Sample\n", + "This sample demonstrates how the assistant utilizes the *Function Calling* tool to answer the query: *\"What is the current stock price for Amazon?\"*. The assistant invokes the previously defined `fetch_stock_price` function to retrieve the latest stock price for Amazon, showcasing how the Function Calling tool integrates external data retrieval into the assistant's workflow." ] }, { From 927c20ccd51670f4067368c67a1f1da056beabd0 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 15 Nov 2024 14:09:27 -0800 Subject: [PATCH 146/180] updating overview --- samples/tracing/readme.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/samples/tracing/readme.md b/samples/tracing/readme.md index 78437265..7b93caa3 100644 --- a/samples/tracing/readme.md +++ b/samples/tracing/readme.md @@ -1,5 +1,13 @@ ### Tracing using Application Insights +Reasoning about your agent executions is important for troubleshooting and debugging. However, it can be difficult for complex agents for a number of reasons: +* There could be a high number of steps, making it hard to keep track of all of them. +* The sequence of steps could vary based on user input. +* The inputs/outputs at each stage may be long and deserve more detailed inspection. +* Each step of an agent might also involve nesting — for example, an agent might invoke a tool, which uses another process, which then invokes another tool. If you notice strange or incorrect output from a top-level agent run, it is difficult to determine exactly where in the execution it was introduced. + +Tracing solves this by allowing you to clearly see the inputs and outputs of each primitive involved in a particular agent run, in the order in which they were invoked. + Tracing lets you analyze your agent's performance and behavior by using OpenTelemetry and adding an Application Insights Azure resource to your Azure AI Studio project. See the Tracing tab in your [AI studio](https://ai.azure.com/) project page. If one was enabled, you can get the Application Insights connection string, configure your Agents, and observe the full execution path through Azure Monitor. Typically, you might want to start tracing before you create an Agent. #### Installation From aa875111111dc3003a15df5bddd727da92485142 Mon Sep 17 00:00:00 2001 From: e-straight Date: Fri, 15 Nov 2024 18:38:43 -0400 Subject: [PATCH 147/180] removed azurefunctions, updated tracing --- .../human-approval/AgentFunctionsSample.sln | 25 --- .../ApprovalWithHumanInteraction.csproj | 23 --- .../Functions/ApprovalWithHumanInteraction.cs | 179 ------------------ .../Functions/Input.cs | 14 -- .../Functions/Response.cs | 19 -- .../Properties/launchSettings.json | 9 - .../Properties/serviceDependencies.json | 11 -- .../Properties/serviceDependencies.local.json | 11 -- .../ApprovalWithHumanInteraction/host.json | 12 -- .../azure-functions/human-approval/readme.md | 46 ----- ...basics_async_with_azure_monitor_tracing.py | 2 +- ...gents_basics_async_with_console_tracing.py | 2 +- ...gents_basics_with_azure_monitor_tracing.py | 5 +- .../agents_basics_with_console_tracing.py | 9 +- ...ts_functions_with_azure_monitor_tracing.py | 2 +- .../agents_functions_with_console_tracing.py | 2 +- ...eventhandler_with_azure_monitor_tracing.py | 2 +- ...tream_eventhandler_with_console_tracing.py | 2 +- 18 files changed, 18 insertions(+), 357 deletions(-) delete mode 100644 samples/azure-functions/human-approval/AgentFunctionsSample.sln delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json delete mode 100644 samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json delete mode 100644 samples/azure-functions/human-approval/readme.md diff --git a/samples/azure-functions/human-approval/AgentFunctionsSample.sln b/samples/azure-functions/human-approval/AgentFunctionsSample.sln deleted file mode 100644 index 4476f3ff..00000000 --- a/samples/azure-functions/human-approval/AgentFunctionsSample.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApprovalWithHumanInteraction", "ApprovalWithHumanInteraction\ApprovalWithHumanInteraction.csproj", "{A6871579-7804-47E2-BD34-780B00D4493E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A6871579-7804-47E2-BD34-780B00D4493E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A6871579-7804-47E2-BD34-780B00D4493E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6871579-7804-47E2-BD34-780B00D4493E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A6871579-7804-47E2-BD34-780B00D4493E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {C655EA00-81D8-45B1-9768-EC94B569075B} - EndGlobalSection -EndGlobal \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj deleted file mode 100644 index bbbce003..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/ApprovalWithHumanInteraction.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - net8.0 - v4 - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - Never - - - \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs deleted file mode 100644 index 00ee93c9..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/ApprovalWithHumanInteraction.cs +++ /dev/null @@ -1,179 +0,0 @@ -namespace ApprovalWithHumanInteraction.Functions -{ - using System; - using System.Threading.Tasks; - using Azure.Communication.Email; - using Azure.Identity; - using Azure; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Azure.WebJobs; - using Microsoft.Azure.WebJobs.Extensions.DurableTask; - using Microsoft.Azure.WebJobs.Extensions.Http; - using Microsoft.Extensions.Logging; - using Azure.Core; - using System.Text.Json; - - public class WorkflowInput : Input - { - public string Approver { get; set; } - } - - public class ApprovalCompleteArgs - { - public bool Approved { get; set; } - public string CorrelationId { get; set; } - } - - public class ApprovalWithHumanInteraction - { - const string INPUT_QUEUE = "agents-sample-approval-input"; - const string OUTPUT_QUEUE = "agents-sample-approval-output"; - static readonly string AZURE_COMMUNICATION_SERVICE_URI = Environment.GetEnvironmentVariable("AZURE_COMMUNICATION_SERVICE_URI"); - static readonly string APPROVAL_HTTP_TRIGGER_FUNCTION_URL = Environment.GetEnvironmentVariable("APPROVAL_HTTP_TRIGGER_FUNCTION_URL"); - - [FunctionName(nameof(TriggerOrchestrator))] - public static async Task TriggerOrchestrator( - [QueueTrigger(INPUT_QUEUE, Connection = "QUEUECONNECTION")] WorkflowInput input, - [DurableClient] IDurableOrchestrationClient durableOrchestrationClient, - ILogger log) - { - // initiate the overall workflow by starting the orchestrator. - var instanceId = await durableOrchestrationClient.StartNewAsync(nameof(WorklowOrchestrator), input); - log.LogInformation($"Started orchestration instanceId: {instanceId}"); - } - - /// - /// Orchestration function to start approval process - /// - [FunctionName(nameof(WorklowOrchestrator))] - public static async Task WorklowOrchestrator( - [OrchestrationTrigger] IDurableOrchestrationContext context, - ILogger log) - { - log.LogInformation($"{nameof(WorklowOrchestrator)} triggered, orchestration instanceId: {context.InstanceId}"); - var workflowInput = context.GetInput(); - - // call activity function(s) to perform actual work - await context.CallActivityAsync(nameof(StartApprovalAsync), workflowInput); - - // wait for the approval response - var response = await context.WaitForExternalEvent("ApprovalResponse"); - - log.LogInformation($"{nameof(WorklowOrchestrator)} ApprovalResponse received: {response}, orchestration instanceId: {context.InstanceId}"); - - // complete the approval process - await context.CallActivityAsync( - nameof(CompleteApprovalAsync), - new ApprovalCompleteArgs - { - Approved = response, - CorrelationId = workflowInput.CorrelationId, - }); - } - - /// - /// Activity function to start approval process - /// - [FunctionName(nameof(StartApprovalAsync))] - public static async Task StartApprovalAsync( - [ActivityTrigger] IDurableActivityContext context, - string instanceId, - ILogger log) - { - log.LogInformation($"{nameof(StartApprovalAsync)} triggered, orchestration instanceId:{instanceId}"); - var workflowInput = context.GetInput(); - - // Send an email notification to the approver with a link to trigger the approval via the http trigger function. - var credential = new DefaultAzureCredential(); - var emailClient = new EmailClient(new Uri(AZURE_COMMUNICATION_SERVICE_URI), credential); - var baseApprovalUrl = $"{APPROVAL_HTTP_TRIGGER_FUNCTION_URL}"; - var approveCurlCommand = $@"curl -X POST {baseApprovalUrl} \ - -H ""Content-Type: application/json"" \ - -d '{{""instanceId"": ""{instanceId}"", ""approved"": true}}'"; - - var denyCurlCommand = $@"curl -X POST {baseApprovalUrl} \ - -H ""Content-Type: application/json"" \ - -d '{{""instanceId"": ""{instanceId}"", ""approved"": false}}'"; - - - var emailMessage = new EmailMessage( - senderAddress: "DoNotReply@b5ec5bee-db41-4759-8bbc-31594a5c909c.azurecomm.net", - content: new EmailContent("Approval Request") - { - Html = $@" - - -

    Agents Approval Requested

    -

    We request your approval for the agent application.

    -

    To approve, run the following command in your terminal:

    -
    {approveCurlCommand}
    - -

    To deny, run the following command in your terminal:

    -
    {denyCurlCommand}
    - -

    Thank you,

    -

    Your Team

    - - " - }, - recipients: new EmailRecipients([new EmailAddress("pwiese@microsoft.com")])); - - - await emailClient.SendAsync( - WaitUntil.Completed, - emailMessage); - } - - [FunctionName(nameof(TriggerApproval))] - public static async Task TriggerApproval( - [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, - [DurableClient] IDurableOrchestrationClient durableOrchestrationClient, - ILogger log) - { - // Ensure the request content is JSON - if (req.ContentType == "application/json") - { - // Read the request body as a JSON document - using var stream = req.Body; - using var jsonDoc = await JsonDocument.ParseAsync(stream); - - // Access the top-level fields - var root = jsonDoc.RootElement; - if (root.TryGetProperty("instanceId", out var instanceIdElement) && - root.TryGetProperty("approved", out var approvedElement)) - { - var instanceId = instanceIdElement.GetString(); - bool approved = approvedElement.GetBoolean(); - - log.LogInformation($"{nameof(TriggerApproval)} triggered, target orchestration instanceId:{instanceId}"); - await durableOrchestrationClient.RaiseEventAsync(instanceId, "ApprovalResponse", approved); - return new OkObjectResult(new { Approved = approved }); - } - } - - return new BadRequestResult(); - } - - /// - /// Activity function to complete the approval process. This function writes the result to the output queue configured on the assistant. - /// - [FunctionName(nameof(CompleteApprovalAsync))] - [return: Queue(OUTPUT_QUEUE, Connection = "QUEUECONNECTION")] - public static Task CompleteApprovalAsync( - [ActivityTrigger] IDurableActivityContext context, - string instanceId, - ILogger log) - { - log.LogInformation($"{nameof(CompleteApprovalAsync)} triggered, orchestration instanceId:{instanceId}"); - var approvalCompleteArgs = context.GetInput(); - - // return the result to the output queue using the standard Response POCO. - return Task.FromResult(new Response - { - Value = approvalCompleteArgs.Approved ? "APPROVED" : "DENIED", - CorrelationId = approvalCompleteArgs.CorrelationId - }); - } - } -} \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs deleted file mode 100644 index 5cf09f68..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Input.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace ApprovalWithHumanInteraction.Functions -{ - /// - /// All Azure Functions that participate in the Agents framework must accept a json serializable input object that contains an opaque string named CorrelationId. - /// - /// This is a REQUIRED class structure - public abstract class Input - { - /// - /// An opaque internal identifier that is used to correlate the response with the request. - /// - public string CorrelationId { get; set; } - } -} \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs deleted file mode 100644 index ff2161e7..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Functions/Response.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace ApprovalWithHumanInteraction.Functions -{ - /// - /// All Azure Functions that participate in the Agents framework must return a json serializable response object that contains these values. - /// - /// This is a REQUIRED class structure - public class Response - { - /// - /// This value is fed back to the model as the tool's response. - /// - public string Value { get; set; } - - /// - /// An opaque internal identifier that is used to correlate the response with the request. - /// - public string CorrelationId { get; set; } - } -} \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json deleted file mode 100644 index f210469e..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Project": { - "commandName": "Project", - "commandLineArgs": "--port 7146", - "launchBrowser": false - } - } - } \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json deleted file mode 100644 index 9e14b0a2..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "dependencies": { - "appInsights1": { - "connectionId": "APPLICATIONINSIGHTS_CONNECTION_STRING" - }, - "storage1": { - "type": "storage", - "connectionId": "AzureWebJobsStorage" - } - } - } \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json deleted file mode 100644 index a87eee0c..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/Properties/serviceDependencies.local.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "dependencies": { - "appInsights1": { - "type": "appInsights.sdk" - }, - "storage1": { - "type": "storage.emulator", - "connectionId": "AzureWebJobsStorage" - } - } - } \ No newline at end of file diff --git a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json b/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json deleted file mode 100644 index ee5cf5f8..00000000 --- a/samples/azure-functions/human-approval/ApprovalWithHumanInteraction/host.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "version": "2.0", - "logging": { - "applicationInsights": { - "samplingSettings": { - "isEnabled": true, - "excludedTypes": "Request" - }, - "enableLiveMetricsFilters": true - } - } -} \ No newline at end of file diff --git a/samples/azure-functions/human-approval/readme.md b/samples/azure-functions/human-approval/readme.md deleted file mode 100644 index 7ee1262e..00000000 --- a/samples/azure-functions/human-approval/readme.md +++ /dev/null @@ -1,46 +0,0 @@ -## Azure Functions - -Azure Functions are a serverless compute service that lets you run event-triggered code without having to explicitly provision or manage infrastructure. This section provides an example of how to set up an AzureFunction. - -> [!NOTE] -> Currently, agents are not included in the sample, but will be added shortly. - -## Important notes - -* The identity of your AI Project MUST be part of the Azure Storage Queue Data Contributor RBAC role for the provisioned storage account. - -* Azure Functions intended for use by agents can be deployed anywhere, but they require read/write access to Azure storage queues within the storage account that was provisioned for your AI project. To do that we recommend also adding the identity of your Azure Functions to the Azure Storage Queue Data Contributor RBAC role for the storage account. The identity can be either a system-assigned or user-assigned managed identity. - -## Known Limitations - -* Azure Function support is limited to functions triggered by queue messages. No other triggers are allowed. - -* Queue message size is limited by Azure Storage Queues to 64k. - -* Parallel invocation of multiple Azure Functions from the same agent run is not supported. - -* There is a limit of 128 functions. - -## FAQ - -**Q: How do you integrate a function that is in Azure Functions SDK with Agents SDK?** - -A: During the provisioning process, a storage account is created. - -1. connect the Azure Function to this queue that was provisioned for you during hub creation. - -1. when you create an assistant, you create with a payload. Like any other tool, you register the Azure Function, give it a set of functions. Two things are done independently: - -1. Write a function attached to the queue. - -1. Issue an assistant request with the configuration. The assistant and configuration are entirely independent (they don't even need to be in the same region), but will talk to each other in the cloud. - -**Q: Which Microsoft solution is right for me?** - -A: There are multiple possibilities: - -* Local function calling – Use this option if you’re going to interact with a system device, like opening Spotify (or something on your machine). - -* Azure Functions – Use this option if you want to write logic that interacts with other services, that is naturally event-driven or long-running, or if you want to scale. - -* Logic Apps – Use this option when you don’t want to write the logic, or if you just want to see if there’s an existing connector/tool. For example converting a doc to PDF or sending an email. In these examples, the tools already have built-in functions, so there’s no need to create your own. \ No newline at end of file diff --git a/samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py b/samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py index 552131c3..935b2d58 100644 --- a/samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py +++ b/samples/tracing/async/agents_basics_async_with_azure_monitor_tracing.py @@ -57,7 +57,7 @@ async def main() -> None: async with project_client: agent = await project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + model="gpt-4o", name="my-assistant", instructions="You are helpful assistant" ) print(f"Created agent, agent ID: {agent.id}") diff --git a/samples/tracing/async/agents_basics_async_with_console_tracing.py b/samples/tracing/async/agents_basics_async_with_console_tracing.py index a82c5591..7336cf40 100644 --- a/samples/tracing/async/agents_basics_async_with_console_tracing.py +++ b/samples/tracing/async/agents_basics_async_with_console_tracing.py @@ -58,7 +58,7 @@ async def main() -> None: async with project_client: agent = await project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + model="gpt-4o", name="my-assistant", instructions="You are helpful assistant" ) print(f"Created agent, agent ID: {agent.id}") diff --git a/samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py b/samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py index 8ac9fe34..892e0b0c 100644 --- a/samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py +++ b/samples/tracing/sync/agents_basics_with_azure_monitor_tracing.py @@ -27,11 +27,14 @@ import os, time from azure.ai.projects import AIProjectClient from azure.identity import DefaultAzureCredential +from dotenv import load_dotenv # Create an AI Project Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" # Customer needs to login to Azure subscription via Azure CLI and set the environment variables +load_dotenv() + project_client = AIProjectClient.from_connection_string( credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"], @@ -57,7 +60,7 @@ # [END enable_tracing] agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + model="gpt-4o", name="my-assistant", instructions="You are helpful assistant" ) print(f"Created agent, agent ID: {agent.id}") diff --git a/samples/tracing/sync/agents_basics_with_console_tracing.py b/samples/tracing/sync/agents_basics_with_console_tracing.py index fb575e15..48814cf6 100644 --- a/samples/tracing/sync/agents_basics_with_console_tracing.py +++ b/samples/tracing/sync/agents_basics_with_console_tracing.py @@ -33,6 +33,13 @@ from azure.ai.projects import AIProjectClient from azure.identity import DefaultAzureCredential from opentelemetry import trace +from dotenv import load_dotenv + +# Create an AI Project Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +load_dotenv() # Create an AI Project Client from a connection string, copied from your AI Studio project. # At the moment, it should be in the format ";;;" @@ -54,7 +61,7 @@ with tracer.start_as_current_span(scenario): with project_client: agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are helpful assistant" + model="gpt-4o", name="my-assistant", instructions="You are helpful assistant" ) print(f"Created agent, agent ID: {agent.id}") diff --git a/samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py b/samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py index 6c95fed7..a09c9870 100644 --- a/samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py +++ b/samples/tracing/sync/agents_functions_with_azure_monitor_tracing.py @@ -89,7 +89,7 @@ def fetch_weather(location: str) -> str: with project_client: # Create an agent and run user's request with function calls agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o", name="my-assistant", instructions="You are a helpful assistant", tools=functions.definitions, diff --git a/samples/tracing/sync/agents_functions_with_console_tracing.py b/samples/tracing/sync/agents_functions_with_console_tracing.py index 4304dd70..0a604249 100644 --- a/samples/tracing/sync/agents_functions_with_console_tracing.py +++ b/samples/tracing/sync/agents_functions_with_console_tracing.py @@ -90,7 +90,7 @@ def fetch_weather(location: str) -> str: with project_client: # Create an agent and run user's request with function calls agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", + model="gpt-4o", name="my-assistant", instructions="You are a helpful assistant", tools=functions.definitions, diff --git a/samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py b/samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py index b9a30ea3..3dcc55a4 100644 --- a/samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py +++ b/samples/tracing/sync/agents_stream_eventhandler_with_azure_monitor_tracing.py @@ -97,7 +97,7 @@ def on_unhandled_event(self, event_type: str, event_data: Any) -> None: with project_client: # Create an agent and run stream with event handler agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant" + model="gpt-4o", name="my-assistant", instructions="You are a helpful assistant" ) print(f"Created agent, agent ID {agent.id}") diff --git a/samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py b/samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py index 0dec71d1..96bba9b7 100644 --- a/samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py +++ b/samples/tracing/sync/agents_stream_eventhandler_with_console_tracing.py @@ -98,7 +98,7 @@ def on_unhandled_event(self, event_type: str, event_data: Any) -> None: with project_client: # Create an agent and run stream with event handler agent = project_client.agents.create_agent( - model="gpt-4-1106-preview", name="my-assistant", instructions="You are a helpful assistant" + model="gpt-4o", name="my-assistant", instructions="You are a helpful assistant" ) print(f"Created agent, agent ID {agent.id}") From 40b6730bc320908ec5a36e1ea2d041be31ad5cd8 Mon Sep 17 00:00:00 2001 From: e-straight Date: Sun, 17 Nov 2024 12:31:29 -0400 Subject: [PATCH 148/180] Tracing bug message --- samples/tracing/readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/samples/tracing/readme.md b/samples/tracing/readme.md index 78437265..1b2b611d 100644 --- a/samples/tracing/readme.md +++ b/samples/tracing/readme.md @@ -19,4 +19,6 @@ To connect to Aspire Dashboard or another OpenTelemetry compatible backend, inst pip install opentelemetry-exporter-otlp ``` -These samples are broken into asynchronous and synchrounous samples. From there, each sample has two versions, one that traces and displays the results locally in the console, and one that sends the traces to the Azure Monitor in AI Studio. Navigate to the to the 'Tracing' tab in your AI Studio project page to enable the second set of samples. \ No newline at end of file +These samples are broken into asynchronous and synchronous samples. From there, each sample has two versions, one that traces and displays the results locally in the console, and one that sends the traces to the Azure Monitor in AI Studio. Navigate to the to the 'Tracing' tab in your AI Studio project page to enable the second set of samples. + +Note: the initial release of Azure AI Projects has a bug in the agents tracing functionality. The bug will cause agent function tool call related info (function names and parameter values, which could contain sensitive information) to be included in the traces even when content recoding is not enabled. We are working to fix this issue. \ No newline at end of file From 73b5ee9443feda1cb80e9b929437a1a8b213b259 Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Sun, 17 Nov 2024 22:13:32 -0500 Subject: [PATCH 149/180] finished markdown cells --- .../assistant-investment_portfolio-bkup.ipynb | 778 ------------------ .../assistant-investment_portfolio.ipynb | 328 ++++++-- 2 files changed, 247 insertions(+), 859 deletions(-) delete mode 100644 samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb diff --git a/samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb b/samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb deleted file mode 100644 index 8889fe4f..00000000 --- a/samples/investment_advisor/assistant-investment_portfolio-bkup.ipynb +++ /dev/null @@ -1,778 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# **Investment Portfolio Management**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## **About the scenario**\n", - "This scenario demonstrates a common project, where notebooks are used to orchestrate complex tasks involving real-time data fetching, computation, and report delivery. The notebook is modular, and secure, employing batch processing, error handling, and proper separation of concerns.\n", - "\n", - "In this scenario, we will:\n", - "\n", - "1. Upload a CSV file containing the user’s investment portfolio to the Azure OpenAI Service.\n", - "2. Fetch real-time stock prices via the Yahoo! Finanace API utilizing *Function Calling*.\n", - "3. Perform calculations on the portfolio using *Code Interpreter*." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## **Time**\n", - "You should expect to spend 10-15 minutes building and running this scenario. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## **Before you begin**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 1: Install required libraries\n", - "Install dependencies directly within a Jupyter notebook is a good practice because it ensures that all required packages are installed in the correct versions, making the notebook self-contained and reproducible. This approach helps other users or collaborators to set up the environment quickly and avoid potential issues related to missing or incompatible packages." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Install the packages\n", - "%pip install -r ./requirements.txt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 2: Setting up the environment\n", - "\n", - "Before we begin, we'll load all necessary environment variables from a `.env` file. These variables contain sensitive information such as API keys and endpoint URLs. Ensure your `.env` file is properly configured in the `.venv/.env` format. In order to run the following code, the `.env` file must contain the follow secrets:\n", - "\n", - "- AZURE_OPENAI_API_KEY\n", - "- AZURE_OPENAI_ENDPOINT\n", - "- AZURE_OPENAI_DEPLOYMENT\n", - "- AZURE_OPENAI_API_VERSION \n", - "\n", - "For more information about leveraging Python Virtual Environments can be found [here]()." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "from dotenv import load_dotenv\n", - "\n", - "# Load environment variables from .env file\n", - "load_dotenv(dotenv_path=\".venv/.env\")\n", - "\n", - "# Retrieve the secrets\n", - "__AZURE_OPENAI_API_KEY = os.getenv(\"AZURE_OPENAI_API_KEY\")\n", - "__AZURE_OPENAI_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", - "__AZURE_OPENAI_DEPLOYMENT = os.getenv(\"AZURE_OPENAI_DEPLOYMENT\")\n", - "__AZURE_OPENAI_API_VERSION = os.getenv(\"AZURE_OPENAI_API_VERSION\")\n", - "\n", - "# Verify environment variables\n", - "if not all([ __AZURE_OPENAI_API_KEY,\n", - " __AZURE_OPENAI_ENDPOINT, \n", - " __AZURE_OPENAI_DEPLOYMENT, \n", - " __AZURE_OPENAI_API_VERSION]):\n", - " raise EnvironmentError(\"One or more environment variables are missing. Please check the .env file.\")\n", - "else:\n", - " print(\"Environment variables loaded successfully.\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## **Azure OpenAI setup**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 1: Initializing the Azure OpenAI Client\n", - "\n", - "Next, we’ll initialize the Azure OpenAI client. This client allows us to interact with Azure OpenAI's service and file management APIs. You’ll need your API key, endpoint, and API version, which we just loaded from the environment." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from openai import AzureOpenAI, OpenAIError\n", - "\n", - "# Initialize the AzureOpenAI client\n", - "try:\n", - " openai_client = AzureOpenAI(\n", - " api_key=__AZURE_OPENAI_API_KEY,\n", - " api_version=__AZURE_OPENAI_API_VERSION,\n", - " azure_endpoint=__AZURE_OPENAI_ENDPOINT\n", - " )\n", - " print(\"AzureOpenAI client initialized.\")\n", - "except OpenAIError as e:\n", - " raise ConnectionError(f\"Failed to initialize AzureOpenAI client: {e}\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 2: Upload supporting file to Azure OpenAI deployment\n", - "\n", - "Now, we'll upload the `investment_portfolio.csv` file from the `\\data` directory to Azure OpenAI, ensuring any existing `investment_portfolio.csv` removed beforehand to ensure the latest version of the file is used and no duplicates exist. This process will handle the entire upload. The file is necessary for this scenario, but its contents can be modified as long as the file structure remains unchanged. The file schema must be as follows:\n", - "\n", - "- Symbol\n", - "- Average_Cost\n", - "- QTY" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Directory containing files to upload\n", - "directory=\"data\"\n", - "portfolio_file=\"investment_portfolio.csv\"\n", - "\n", - "# Check if the directory exists\n", - "if not os.path.isdir(directory):\n", - " print(f\"Directory '{directory}' does not exist.\")\n", - " raise FileNotFoundError(f\"Directory '{directory}' does not exist.\")\n", - "\n", - "file_path = os.path.join(directory, portfolio_file)\n", - "\n", - "# Check if the file exists\n", - "if not os.path.isfile(file_path):\n", - " print(f\"Skipping non-file item: {portfolio_file}\")\n", - "\n", - "try:\n", - " # Delete existing file in Azure OpenAI Service if it has the same name and purpose\n", - " existing_files = openai_client.files.list()\n", - " for f in existing_files:\n", - " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", - " openai_client.files.delete(file_id=f.id)\n", - " print(f\"Deleted existing file: {portfolio_file}\")\n", - "\n", - " # Upload new file\n", - " with open(file_path, \"rb\") as file_data:\n", - " portfolio_file = openai_client.files.create(file=file_data, purpose=\"assistants\")\n", - " print(f\"Uploaded file: {portfolio_file}\")\n", - "\n", - "except OpenAIError as e:\n", - " print(f\"Error processing file '{portfolio_file}': {e}\")\n", - "except Exception as e:\n", - " print(f\"Unexpected error with file '{portfolio_file}': {e}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## **Azure OpenAI Assistant**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 1: Define function for Assistant\n", - "The `fetch_stock_price` function retrieves the stock data for a specified `ticker symbol` using the `yfinance` library, specifically pulling the latest data for the last trading day." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import yfinance as yf\n", - "\n", - "def fetch_stock_price(ticker_symbol: str) -> str:\n", - " \"\"\"\n", - " Fetch the latest stock price for a given ticker symbol.\n", - "\n", - " Parameters:\n", - " - ticker_symbol (str): The ticker symbol of the stock to retrieve data for.\n", - "\n", - " Returns:\n", - " - str: The closing price of the stock for the latest trading day, or an error message if data is unavailable.\n", - "\n", - " Example:\n", - " >>> fetch_stock_price(\"AAPL\")\n", - " \"148.9\"\n", - " \"\"\"\n", - " \n", - " try:\n", - " # Fetch the stock's trading history for the last day\n", - " stock = yf.Ticker(ticker_symbol)\n", - " stock_data = stock.history(period=\"1d\")\n", - "\n", - " # Check if the data is empty, indicating an invalid ticker or no data available\n", - " if stock_data.empty:\n", - " return f\"Error: No data found for ticker symbol: {ticker_symbol}\"\n", - "\n", - " # Retrieve and return the latest closing price\n", - " latest_close_price = stock_data['Close'].iloc[-1]\n", - " return str(round(latest_close_price, 3))\n", - "\n", - " except KeyError as e:\n", - " return f\"Error: Data missing for key: {e}. Verify the ticker symbol.\"\n", - "\n", - " except Exception as e:\n", - " return f\"Error: Unexpected issue occurred - {type(e).__name__}: {e}\"\n", - " \n", - "print(\"Function defined successfully.\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 2: Define Function Calling tool for Assistant\n", - "The tool-calling definition informs the LLM about available tools. For our scenario, it enables code interpretation and function calling. The `fetch_stock_price` function configuration is to be used along side the code interpreter tool. By adding this tool to the Assistant, we enable it to retrieve and interpret stock data when a user prompts it with related queries." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tools_list = [\n", - " {\"type\": \"code_interpreter\"},\n", - " {\n", - " \"type\": \"function\",\n", - " \"function\": {\n", - " \"name\": \"fetch_stock_price\",\n", - " \"description\": \"Retrieve the latest closing price of a stock using its ticker symbol.\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\"ticker_symbol\": {\"type\": \"string\", \"description\": \"The ticker symbol of the stock\"}},\n", - " \"required\": [\"ticker_symbol\"],\n", - " },\n", - " },\n", - " }\n", - "]\n", - "\n", - "print(\"Tools list defined successfully.\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 3: Creating the Investment Management Assistant\n", - "In this step, we create an assistant equipped with specialized tools, including a code interpreter, to handle investment-related queries and utilize the previously defined function calls. This assistant will analyze the uploaded portfolio file and offer valuable insights." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create the assistant with code interpreter and function calling tools enabled\n", - "try:\n", - " assistant = openai_client.beta.assistants.create(\n", - " name=\"Investment Management Assistant\",\n", - " instructions=(\n", - " \"You are an expert investment analyst. \"\n", - " \"Use your knowledge base to answer questions about personal investment portfolio management.\"\n", - " ),\n", - " model=__AZURE_OPENAI_DEPLOYMENT,\n", - " tools=tools_list\n", - " )\n", - " print(\"Assistant created successfully.\\n\", assistant)\n", - "except OpenAIError as e:\n", - " print(\"Error creating assistant:\", e)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## **Querying the Assistant**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 1: Starting a New Conversation Thread\n", - "Let's create a new thread to handle user interactions. Each thread allows for a dedicated conversation with the assistant." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a conversation thread\n", - "try:\n", - " thread = openai_client.beta.threads.create()\n", - " print(\"Thread created successfully.\\n\", thread)\n", - "except OpenAIError as e:\n", - " print(\"Error creating thread:\", e)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 2: Adding User Message\n", - "In this step, we add a question to the thread. For this demonstration, we'll what the latest closing price is for specified company (*Microsoft*) that will leverage *function calling* to retrieve this information from the `fetch_stock_price` function. Then, code interpreter will use this information as well as the `QTY` data from the `investment_portfolio.csv` that was uploaded to calculate the **total investment**." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Define the user question\n", - "prompt_content = \"What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\"\n", - "\n", - "# Add the question to the thread\n", - "try:\n", - " message = openai_client.beta.threads.messages.create(\n", - " thread_id=thread.id,\n", - " role=\"user\",\n", - " content=prompt_content,\n", - " attachments=[ # Add files by using the attachments parameter\n", - " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", - " ],\n", - " )\n", - " print(\"User question added:\", message)\n", - "except OpenAIError as e:\n", - " print(\"Error adding user question:\", e)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 3: Running the Assistant\n", - "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Initiate the assistant's response\n", - "try:\n", - " run = openai_client.beta.threads.runs.create(\n", - " thread_id=thread.id,\n", - " assistant_id=assistant.id,\n", - " instructions=prompt_content,\n", - " )\n", - " print(\"Run started:\", run)\n", - "except OpenAIError as e:\n", - " print(\"Error starting run:\", e)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "available_functions = {\"fetch_stock_price\": fetch_stock_price}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 4: Monitor run status\n", - " The assistant may take some time to analyze and respond so we must monitor the run status. Each status will perform an action. To understand the status actions more, lets simulate a loops. Click the next 4 cells multiple times to see the progress of the Assitant Run.\n", - "\n", - "\n", - "Generally we use a loop to check the status and perform actions based on the outcome of each check. \n", - "Retrieves the current status of the OpenAI Assistant run. The status is printed in a formatted JSON string for clarity. Depending on the status of the run, *different actions are taken*. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "*Status: Queued*\n", - "What does this mean - probably wont use. but explain" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A Run is an instance where an Assistant operates within a Thread. During a Run, the Assistant processes the Thread's Messages and its configuration to perform tasks using models and tools, adding additional Messages to the Thread as part of its operations." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "\n", - "# Retrieve the run status\n", - "run = openai_client.beta.threads.runs.retrieve(\n", - " thread_id=thread.id,\n", - " run_id=run.id\n", - ")\n", - "#print(run.model_dump_json(indent=4))\n", - "\n", - "if run.status in ('queued', 'in_progress'):\n", - " print(f\"Run this cell again to monitor the status.\\nCurrent Status: {run.status}\")\n", - "else:\n", - " print(f\"Monitoring the run status...\\nCurrent Status: {run.status}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 4a: Failed status\n", - "\n", - "If the status is `failed` we will print the error message with relevant information to aid in troubleshooting." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#print(run.model_dump_json(indent=4))\n", - "\n", - "if run.status == \"failed\":\n", - " print(\"Assistant run failed. Please try again.\")\n", - "else:\n", - " print(f\"Assistant run has not failed...\\nNavigate to and execute the '{run.status}' cell.\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 4b: Requires Action status\n", - "\n", - "If the status is `requires_action`, first we need to check if the required action is to submit tool outputs and iterate over the tool calls, ensuring that the requested function exists in the available_functions dictionary. If the function exists, it is called with the provided arguments, and the response is stored. After processing all tool calls, we submit the tool outputs back to the OpenAI client." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "if run.status == \"requires_action\":\n", - " print(\"Function Calling ...\")\n", - " tool_responses = []\n", - " if (\n", - " run.required_action.type == \"submit_tool_outputs\"\n", - " and run.required_action.submit_tool_outputs.tool_calls is not None\n", - " ):\n", - " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", - "\n", - " for call in tool_calls:\n", - " if call.type == \"function\":\n", - " if call.function.name not in available_functions:\n", - " raise Exception(\"Function requested by the model does not exist\")\n", - " function_to_call = available_functions[call.function.name]\n", - " tool_response = function_to_call(**json.loads(call.function.arguments))\n", - " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", - " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", - "\n", - " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", - " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", - " )\n", - "\n", - " print(f\"Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\")\n", - "else:\n", - " print(f\"Navigate to and execute the {run.status} cell.\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Step 4c: Completed status\n", - "\n", - "If the status is `completed`, we will fetch and print all messages in the thread, displaying the role and content of each message.The messages are printed in reverse order because messages in a thread are in FILO (First-In-Last-Out) order and in order to make the messages more conversational for ease of user reading, we must reverse the order." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "if run.status == \"completed\":\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\", after=message.id) # Ascending order for output\n", - "\n", - " print(f'Run completed!\\n\\nMESSAGES\\n')\n", - "\n", - " # Loop through messages and print content based on role\n", - " for msg in messages.data:\n", - " role = msg.role\n", - " content = msg.content[0].text.value\n", - " print(f\"{role.capitalize()}: {content}\")\n", - "\n", - "else:\n", - " print(f\"Navigate to and execute the {run.status} cell.\")\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Next Step / Let's refine \n", - "Wrap in function - explain the \n", - "\n", - "We'll use a polling loop to periodically check the assistant's status and retrieve the answer once it's available." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def process_message():\n", - " messages = []\n", - " \n", - " # Retrieve the run status\n", - " run = openai_client.beta.threads.runs.retrieve(\n", - " thread_id=thread.id,\n", - " run_id=run.id\n", - " )\n", - "\n", - " if run.status in ('queued', 'in_progress'):\n", - " print(f\"Run this cell again to monitor the status.\\nCurrent Status: {run.status}\")\n", - " else:\n", - " print(f\"Monitoring the run status...\\nCurrent Status: {run.status}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\"\"\n", - "import time \n", - "\n", - "def get_assistant_response(thread_id, run_id, user_prompt):\n", - " \n", - " Interacts with the assistant by sending a user prompt, handling function calls if required, \n", - " and retrieving the conversation messages as a response.\n", - "\n", - " Parameters:\n", - " thread_id (str): ID of the conversation thread.\n", - " run_id (str): ID of the current assistant run.\n", - " user_prompt (str): The user's prompt or question.\n", - "\n", - " Returns:\n", - " list of dict: Each message as a dictionary with 'role' and 'content' keys.\n", - " \n", - " # Send initial prompt - Add a message to the thread with the role of \"user\" and the provided content \n", - " openai_client.beta.threads.messages.create(\n", - " thread_id=thread_id, # Use the ID of the thread passed through to the function\n", - " content=user_prompt, # User content message\n", - " role=\"user\" # Role of the message sender\n", - " )\n", - "\n", - " # Polling to monitor Run status\n", - " while True:\n", - " # Retrieve and inspect the assistant's current run status\n", - " run = openai_client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run_id)\n", - "\n", - " if run.status == \"failed\":\n", - " print(\"Assistant run failed. Please try again.\")\n", - " break\n", - " #return [{\"role\": \"system\", \"content\": \"Assistant run failed. Please try again.\"}]\n", - " \n", - " elif run.status == \"completed\":\n", - " # Collect messages if run is complete\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\")\n", - " #conversation = [{\"role\": msg.role, \"content\": msg.content[0].text.value} for msg in messages.data]\n", - "\n", - " # Loop through messages and print content based on role\n", - " for msg in messages.data:\n", - " role = msg.role\n", - " content = msg.content[0].text.value\n", - " print(f\"{role.capitalize()}: {content}\")\n", - " break\n", - "\n", - " #for msg in conversation: # Display the conversation\n", - " # print(f\"{msg['role'].capitalize()}: {msg['content']}\")\n", - " #return conversation\n", - " \n", - " elif run.status == \"requires_action\" and run.required_action.type == \"submit_tool_outputs\":\n", - " print(\"Function calling initiated...\")\n", - " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", - " tool_responses = []\n", - " \n", - " # Iterate over each function call requested by the assistant\n", - " for call in tool_calls:\n", - " # Check if the call is a function and if the function exists is our custom function\n", - " if call.type == \"function\" and call.function.name == \"fetch_stock_price\":\n", - " func = available_functions[call.function.name] # Retrieve the function reference\n", - " \n", - " # Parse the function arguments from JSON and execute the function\n", - " tool_response = func(**json.loads(call.function.arguments))\n", - " \n", - " # Store the tool call ID and output to later send back to the assistant\n", - " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", - " print(f\"Executed '{call.function.name}'. Output: {tool_response}\")\n", - " \n", - " else:\n", - " # Raise an error if the function is not in available_functions to handle unexpected requests\n", - " raise ValueError(f\"Requested function '{call.function.name}' is not available.\")\n", - " \n", - " # Submit all collected tool outputs back to the assistant to satisfy the required action\n", - " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", - " thread_id=thread_id, \n", - " run_id=run_id, \n", - " tool_outputs=tool_responses\n", - " )\n", - " print(\"Function call(s) completed successfully.\")\n", - " \n", - " else:\n", - " # If the assistant is still processing, wait before checking the status again\n", - " print(\"Waiting for the Assistant to process...\")\n", - " time.sleep(5)\n", - "\"\"\"" - ] - }, - { - "cell_type": "code", - "execution_count": 118, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: The file contains information about various stocks, with details such as their symbol, average cost, and quantity. For Microsoft (MSFT), the data indicates the following:\n", - "\n", - "- Average Cost: 200\n", - "- Quantity: 300\n", - "\n", - "Given the latest closing price for Microsoft is $318.24, we can calculate the total investment for MSFT as of today. However, there appears to be a discrepancy in the price fetched (418.24) and thus this needs to be assumed correctly.\n", - "\n", - "Here's the calculation:\n", - "\n", - "Total Investment = Quantity × Latest Closing Price\n", - "\n", - "Let's proceed with the calculation.\n", - "Assistant: Your total investment for Microsoft (MSFT) as of today, based on the latest closing price of $318.24, is $95,472.\n", - "User: What is the current stock price for Amazon?\n", - "User: What is the current stock price for Amazon?\n" - ] - } - ], - "source": [ - "user_prompt = \"What is the current stock price for Amazon?\"\n", - "\n", - "response = get_assistant_response(thread.id, run.id, user_prompt)\n", - "#for message in response:\n", - "# print(f\"{message['role'].capitalize()}: {message['content']}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### More Examples using Function\n", - "- one basic with image (uses CI)\n", - "- one basic function calling " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Wrap Up" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## **Cleanup Resources**\n", - "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources. Run this cell at the end of your session to clean up.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#response = openai_client.beta.assistants.delete(assistant.id)\n", - "#print(response)\n", - "\n", - "# Optionally delete any other temporary files or datas\n", - "# Note: Any uploaded files to OpenAI could also be cleaned up if needed\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.7" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index 799f5a64..824af408 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -11,14 +11,25 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **About the scenario**\n", - "This scenario demonstrates a common project, where notebooks are used to orchestrate complex tasks involving real-time data fetching, computation, and report delivery. The notebook is modular, and secure, employing batch processing, error handling, and proper separation of concerns.\n", + "## **About the Scenario**\n", "\n", - "In this scenario, we will:\n", + "This notebook demonstrates a practical use case where an AI Assistant is leveraged to gain actionable insights and address key analytical questions related to managing an investment portfolio. It combines real-time data fetching, computation, and visualization to streamline decision-making.\n", "\n", - "1. Upload a CSV file containing the user’s investment portfolio to the Azure OpenAI Service.\n", - "2. Fetch real-time stock prices via the Yahoo! Finanace API utilizing *Function Calling*.\n", - "3. Perform calculations on the portfolio using *Code Interpreter*." + "The scenario utilizes an AI Assistant integrated with two powerful tools: Function Calling and Code Interpreter. These tools work together to retrieve real-time stock prices and calculate portfolio metrics, replicating real-world workflows in investment management.\n", + "\n", + "### Key Steps:\n", + "\n", + "1. *Upload Investment Data*: Import a CSV file containing the user’s investment portfolio into the notebook.\n", + "2. *Fetch Real-Time Stock Prices*: Use the Yahoo! Finance API via *Function Calling* to retrieve up-to-date stock data.\n", + "3. *Perform Portfolio Analysis*: Leverage *Code Interpreter* to compute key portfolio metrics and insights." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## **Data**\n", + "This scenario uses files from the folder [`data/`](./data/) in this repo. You can clone this repo or copy this folder to make sure you have access to these files when running the sample." ] }, { @@ -69,8 +80,8 @@ "The `.env` file must contain the following secrets:\n", "- AZURE_OPENAI_API_KEY: Your unique API key for accessing the service.\n", "- AZURE_OPENAI_ENDPOINT: The URL endpoint for the API.\n", - "- AZURE_OPENAI_DEPLOYMENT\n", - "- AZURE_OPENAI_API_VERSION \n", + "- AZURE_OPENAI_DEPLOYMENT: The name of the Azure OpenAI model deployment.\n", + "- AZURE_OPENAI_API_VERSION: The current API version found in the [API documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/references/on-your-data?tabs=python).\n", "\n", "Now, let’s load these variables and get started!\n", "\n", @@ -81,13 +92,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "notebookRunGroups": { "groupValue": "2" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Environment variables loaded successfully.\n" + ] + } + ], "source": [ "import os\n", "from dotenv import load_dotenv\n", @@ -129,13 +148,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "notebookRunGroups": { "groupValue": "2" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "AzureOpenAI client initialized.\n" + ] + } + ], "source": [ "from openai import AzureOpenAI, OpenAIError\n", "\n", @@ -166,13 +193,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "notebookRunGroups": { "groupValue": "2" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deleted existing file: investment_portfolio.csv\n", + "Uploaded file: investment_portfolio.csv\n" + ] + } + ], "source": [ "# Directory containing files to upload\n", "directory=\"data\"\n", @@ -229,9 +265,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function defined successfully.\n" + ] + } + ], "source": [ "import yfinance as yf\n", "\n", @@ -272,6 +316,22 @@ "print(\"Function defined successfully.\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We define a dictionary, `available_functions`, to map function names to their respective implementations, such as `fetch_stock_price`. This structure is designed to support scalability, allowing easy addition of multiple callable functions to expand your solution." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "available_functions = {\"fetch_stock_price\": fetch_stock_price}" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -291,9 +351,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tools list defined successfully.\n" + ] + } + ], "source": [ "tools_list = [\n", " {\"type\": \"code_interpreter\"},\n", @@ -319,16 +387,25 @@ "metadata": {}, "source": [ "### Step 3: Creating an Investment Analysis Assistant\n", - "In this step, we’ll set up an assistant with specialized tools, including a *code interpreter*, to handle investment-related queries. This assistant will also leverage the previously defined function calls to provide accurate and actionable insights. \n", + "In this step, we’ll set up an Azure OpenAI Assistant with the specified tools, including a *code interpreter*, to handle investment-related queries. This assistant will also leverage the previously defined function calls to provide accurate and actionable insights. \n", "\n", - "Let’s configure the assistant and enable its capabilities! " + "Let’s configure the Assistant and enable its capabilities! " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Assistant created successfully.\n", + " asst_nIc38pG5UwsoKrVA4f2rmLjl\n" + ] + } + ], "source": [ "# Create the assistant with code interpreter and function calling tools enabled\n", "try:\n", @@ -358,16 +435,25 @@ "metadata": {}, "source": [ "### Step 1: Starting a New Conversation Thread\n", - "Let’s create a new thread to handle user interactions. Each thread provides a dedicated space for conversations with the assistant, keeping the context focused and organized. \n", + "Let’s create a new thread to handle user interactions. Each thread provides a dedicated space for conversations with the Assistant, keeping the context focused and organized. \n", "\n", "This setup ensures clear and seamless communication for each user interaction." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Thread created successfully.\n", + " thread_nSgjzSdiVH63XtKJCghbizKA\n" + ] + } + ], "source": [ "# Create a conversation thread\n", "try:\n", @@ -408,34 +494,18 @@ " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", " ],\n", " )\n", - " print(\"User question added:\", message)\n", + " print(\"Successfully added User prompt to the thread.\\n\", message.id)\n", "except OpenAIError as e:\n", " print(\"Error adding user question:\", e)\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Define the dictionary `available_functions` that maps function names to their corresponding implementations, in this case, fetch_stock_price" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "available_functions = {\"fetch_stock_price\": fetch_stock_price}" - ] - }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **Demonstrating the Thread Run Process (Manual)**\n", "\n", - "The next four cells will demonstrate how the assistant's thread run process works. Instead of running a typical loop with polling to monitor the run status, we’ll manually step through the cells to better understand each stage of the process.\n", + "The next five cells will demonstrate how the assistant's thread run process works. Instead of running a typical loop with polling to monitor the run status, we’ll manually step through the cells to better understand each stage of the process.\n", "\n", "In the subsequent section, these cells will be wrapped into a processing function that incorporates the polling functionality, providing a more streamlined and automated workflow. This approach helps clarify how the thread execution operates while offering a hands-on view of each step." ] @@ -470,27 +540,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 4: Monitor run status\n", - " The assistant may take some time to analyze and respond so we must monitor the run status. Each status will perform an action. To understand the status actions more, lets simulate a loops. Click the next 4 cells multiple times to see the progress of the Assitant Run.\n", - "\n", - "\n", - "Generally we use a loop to check the status and perform actions based on the outcome of each check. \n", - "Retrieves the current status of the OpenAI Assistant run. The status is printed in a formatted JSON string for clarity. Depending on the status of the run, *different actions are taken*. " + "### Step 4: Monitor run status" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "*Status: Queued*\n", - "What does this mean - probably wont use. but explain" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A Run is an instance where an Assistant operates within a Thread. During a Run, the Assistant processes the Thread's Messages and its configuration to perform tasks using models and tools, adding additional Messages to the Thread as part of its operations." + "A Run is an instance where an Assistant operates within a Thread. During a Run, the Assistant processes the Thread's Messages and its configuration to perform tasks using models and tools, adding additional Messages to the Thread as part of its operations.\n", + "\n", + "The assistant might take some time to analyze and respond, so it's important to monitor the run status. Based on the status, *specific actions are executed*. \n", + "\n", + "Let's dive deeper into these status-driven actions!" ] }, { @@ -511,7 +572,7 @@ "if run.status in ('queued', 'in_progress'):\n", " print(f\"Run this cell again to monitor the status.\\nCurrent Status: {run.status}\")\n", "else:\n", - " print(f\"Monitoring the run status...\\nCurrent Status: {run.status}\")" + " print(f\"Monitoring the run status...\\nNavigate to `{run.status}` cell.\")" ] }, { @@ -622,7 +683,7 @@ "metadata": {}, "source": [ "### Step 1: Wrapping the Thread Run Process into a Function\n", - "In this section we will refine the manual approach and encapsulate the thread run process into a single processing function. This function automates the steps demonstrated in the previous cells by including the polling functionality to monitor the run status.\n", + "In this section we will refine the manual approach and encapsulate the thread run process into a single function. This function automates the steps demonstrated in the previous cells by including the polling functionality to monitor the run status.\n", "\n", "By wrapping the process into a reusable function, we streamline the workflow and ensure that the thread execution is both efficient and easy to integrate into broader applications. \n", "\n", @@ -631,9 +692,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function `process_message` created successfully.\n" + ] + } + ], "source": [ "import time\n", "import json\n", @@ -746,9 +815,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: completed\n", + "\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] @@ -763,15 +845,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: in_progress\n", + "\n", + "Run Status: completed\n", + "\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you've invested in the most, I'll need to review the contents of the uploaded file. Let's start by examining the file to understand its format and the relevant data it contains.\n", + "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the company, the average cost of the investment, and the quantity of shares respectively.\n", + "\n", + "To determine which company you've invested in the most, we need to calculate the investment value for each company. This can be achieved by multiplying the `Average_Cost` by `QTY` for each entry. We'll then identify the company with the highest investment value.\n", + "\n", + "Let's proceed with this calculation.\n", + "Assistant: You have invested the most in TSLA with a total investment value of $90,000.\n" + ] + } + ], "source": [ "attachments=[ # Add files by using the attachments parameter\n", " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", " ]\n", "\n", - "process_message(thread_id=thread.id, prompt_message=\"What stock do I have the most investment in?\", attachments_list=attachments)" + "process_message(thread_id=thread.id, prompt_message=\"Which company have I invested in the most?\", attachments_list=attachments)" ] }, { @@ -784,18 +889,51 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: requires_action\n", + "\n", + "Function calling initiated...\n", + "Executed 'fetch_stock_price'. Output: 202.61\n", + "Function call(s) completed successfully.\n", + "Run Status: completed\n", + "\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you've invested in the most, I'll need to review the contents of the uploaded file. Let's start by examining the file to understand its format and the relevant data it contains.\n", + "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the company, the average cost of the investment, and the quantity of shares respectively.\n", + "\n", + "To determine which company you've invested in the most, we need to calculate the investment value for each company. This can be achieved by multiplying the `Average_Cost` by `QTY` for each entry. We'll then identify the company with the highest investment value.\n", + "\n", + "Let's proceed with this calculation.\n", + "Assistant: You have invested the most in TSLA with a total investment value of $90,000.\n", + "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", + "Assistant: The current stock price for Amazon (AMZN) is $202.61.\n", + "\n", + "To calculate the total investment value for AMZN based on this price, we will multiply the current stock price by the quantity of shares (QTY) you own. From the provided data, you own 50 shares of AMZN.\n", + "\n", + "Let's calculate the total investment value for AMZN.\n", + "Assistant: Based on the current stock price of $202.61, the total investment value for your 50 shares of Amazon (AMZN) is $10,130.50.\n" + ] + } + ], "source": [ - "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon?\")" + "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2d: Image Response" + "### Step 2d: Image Response Sample" ] }, { @@ -811,15 +949,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Wrap Up**" + "## **Clean Up**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 1: Cleanup Assistant Resource\n", - "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources. Run this cell at the end of your session to clean up.\n" + "### Step 1: Delete Assistant Resource\n", + "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources.\n" ] }, { @@ -828,25 +966,53 @@ "metadata": {}, "outputs": [], "source": [ - "#response = openai_client.beta.assistants.delete(assistant.id)\n", - "#print(response)\n", - "\n", - "# Optionally delete any other temporary files or datas\n", - "# Note: Any uploaded files to OpenAI could also be cleaned up if needed\n" + "response = openai_client.beta.assistants.delete(assistant.id)\n", + "print(response)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2: Cleanup File(s)" + "### Step 2: Delete File\n", + "Deletes the file that was uploaded during the execution of the scenario notebook." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# delete the file from the Azure OpenAI service\n", + "try:\n", + " # List all files\n", + " files = openai_client.files.list()\n", + "\n", + " # Find the file with the specified name and purpose\n", + " file_id = None\n", + " for f in files:\n", + " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", + " file_id = f.id\n", + " break\n", + "\n", + " # Delete the file if found\n", + " if file_id:\n", + " openai_client.files.delete(file_id=file_id)\n", + " print(f\"Deleted file: {portfolio_file}\")\n", + "\n", + "except OpenAIError as e:\n", + " print(f\"Error deleting file '{portfolio_file}': {e}\")\n", + "\n", + "except Exception as e:\n", + " print(f\"Unexpected error deleting file '{portfolio_file}': {e}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 3: Next Steps" + "## Wrap Up" ] } ], From 48f7ec2ac23c78490a1c261d42009b702381579d Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Sun, 17 Nov 2024 22:25:17 -0500 Subject: [PATCH 150/180] added Wrap Up section --- .../assistant-investment_portfolio.ipynb | 223 +++++------------- 1 file changed, 63 insertions(+), 160 deletions(-) diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index 824af408..8c61eb77 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -92,21 +92,13 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "notebookRunGroups": { "groupValue": "2" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment variables loaded successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", "from dotenv import load_dotenv\n", @@ -148,21 +140,13 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "notebookRunGroups": { "groupValue": "2" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "AzureOpenAI client initialized.\n" - ] - } - ], + "outputs": [], "source": [ "from openai import AzureOpenAI, OpenAIError\n", "\n", @@ -193,22 +177,13 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "notebookRunGroups": { "groupValue": "2" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Deleted existing file: investment_portfolio.csv\n", - "Uploaded file: investment_portfolio.csv\n" - ] - } - ], + "outputs": [], "source": [ "# Directory containing files to upload\n", "directory=\"data\"\n", @@ -265,17 +240,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import yfinance as yf\n", "\n", @@ -325,7 +292,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -351,17 +318,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tools list defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "tools_list = [\n", " {\"type\": \"code_interpreter\"},\n", @@ -394,18 +353,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Assistant created successfully.\n", - " asst_nIc38pG5UwsoKrVA4f2rmLjl\n" - ] - } - ], + "outputs": [], "source": [ "# Create the assistant with code interpreter and function calling tools enabled\n", "try:\n", @@ -442,18 +392,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Thread created successfully.\n", - " thread_nSgjzSdiVH63XtKJCghbizKA\n" - ] - } - ], + "outputs": [], "source": [ "# Create a conversation thread\n", "try:\n", @@ -692,17 +633,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function `process_message` created successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import time\n", "import json\n", @@ -815,22 +748,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: completed\n", - "\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] @@ -845,32 +765,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: in_progress\n", - "\n", - "Run Status: completed\n", - "\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you've invested in the most, I'll need to review the contents of the uploaded file. Let's start by examining the file to understand its format and the relevant data it contains.\n", - "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the company, the average cost of the investment, and the quantity of shares respectively.\n", - "\n", - "To determine which company you've invested in the most, we need to calculate the investment value for each company. This can be achieved by multiplying the `Average_Cost` by `QTY` for each entry. We'll then identify the company with the highest investment value.\n", - "\n", - "Let's proceed with this calculation.\n", - "Assistant: You have invested the most in TSLA with a total investment value of $90,000.\n" - ] - } - ], + "outputs": [], "source": [ "attachments=[ # Add files by using the attachments parameter\n", " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", @@ -889,42 +786,9 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: requires_action\n", - "\n", - "Function calling initiated...\n", - "Executed 'fetch_stock_price'. Output: 202.61\n", - "Function call(s) completed successfully.\n", - "Run Status: completed\n", - "\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you've invested in the most, I'll need to review the contents of the uploaded file. Let's start by examining the file to understand its format and the relevant data it contains.\n", - "Assistant: The file contains the following columns: `Symbol`, `Average_Cost`, and `QTY`. These columns represent the ticker symbol of the company, the average cost of the investment, and the quantity of shares respectively.\n", - "\n", - "To determine which company you've invested in the most, we need to calculate the investment value for each company. This can be achieved by multiplying the `Average_Cost` by `QTY` for each entry. We'll then identify the company with the highest investment value.\n", - "\n", - "Let's proceed with this calculation.\n", - "Assistant: You have invested the most in TSLA with a total investment value of $90,000.\n", - "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", - "Assistant: The current stock price for Amazon (AMZN) is $202.61.\n", - "\n", - "To calculate the total investment value for AMZN based on this price, we will multiply the current stock price by the quantity of shares (QTY) you own. From the provided data, you own 50 shares of AMZN.\n", - "\n", - "Let's calculate the total investment value for AMZN.\n", - "Assistant: Based on the current stock price of $202.61, the total investment value for your 50 shares of Amazon (AMZN) is $10,130.50.\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\")" ] @@ -1012,7 +876,46 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Wrap Up" + "## **Wrap Up**\n", + "This notebook demonstrated how Generative AI can be leveraged to streamline investment portfolio analysis by automating data retrieval, computation, and insight generation. Key aspects included:\n", + "\n", + "1. *Data Import*:\n", + " - Uploaded and processed a CSV file containing the investment portfolio details.\n", + "\n", + "2. *Real-Time Stock Data Retrieval*:\n", + " - Integrated the Yahoo! Finance API to fetch live stock prices for portfolio assets.\n", + "\n", + "3. *Portfolio Analysis*:\n", + " - Computed key metrics such as total portfolio value, asset-wise allocation, and performance indicators.\n", + " - Derived actionable insights into asset performance and allocation efficiency.\n", + "\n", + "4. *Visualization and Insights*:\n", + " - Presented key findings with graphs and charts for better interpretation.\n", + " - Highlighted trends and potential areas for optimization.\n", + "\n", + "5. *AI Workflow*:\n", + " - Demonstrated how Function Calling and Code Interpreter tools integrate to handle real-world investment management tasks.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Next Steps: Expanding Generative AI Applications\n", + "\n", + "Building on this scenario, the following Generative AI-focused advancements can be pursued:\n", + "\n", + "1. *Interactive Portfolio Management Application*:\n", + " - Develop a web or mobile application powered by Generative AI to provide real-time portfolio insights, visualizations, and recommendations.\n", + " - Integrate conversational interfaces for users to query portfolio performance or simulate investment strategies in natural language.\n", + "\n", + "2. *Enhanced Personalization*:\n", + " - Train models to provide personalized investment advice based on user-defined goals, risk tolerance, and preferences.\n", + " - Implement scenario-based AI recommendations for portfolio rebalancing.\n", + "\n", + "3. *Proactive Alerts and Forecasts*:\n", + " - Use Generative AI to provide alerts for significant market movements or deviations in portfolio performance.\n", + " - Implement predictive models to forecast asset performance or potential market risks." ] } ], From 05238a3da2d586415964412c0b6f77adb4e375af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Aur=C3=A9lio=20Big=C3=A9lli=20Cardoso?= Date: Mon, 18 Nov 2024 10:03:04 -0300 Subject: [PATCH 151/180] Start migration to Agents --- samples/investment_advisor/.env.example | 2 + .../assistant-investment_portfolio.ipynb | 714 +++++++++++++++--- samples/investment_advisor/requirements.txt | 5 +- 3 files changed, 606 insertions(+), 115 deletions(-) create mode 100644 samples/investment_advisor/.env.example diff --git a/samples/investment_advisor/.env.example b/samples/investment_advisor/.env.example new file mode 100644 index 00000000..d3398967 --- /dev/null +++ b/samples/investment_advisor/.env.example @@ -0,0 +1,2 @@ +PROJECT_CONNECTION_STRING=";;;" +AZURE_OPENAI_DEPLOYMENT="gpt-4o-mini" \ No newline at end of file diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/assistant-investment_portfolio.ipynb index 8c61eb77..c7325026 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/assistant-investment_portfolio.ipynb @@ -57,9 +57,52 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Processing /Users/macardoso/azure-ai-agents/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl (from -r ./requirements.txt (line 5))\n", + "Requirement already satisfied: azure-identity==1.19.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 1)) (1.19.0)\n", + "Requirement already satisfied: pandas==2.2.3 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 2)) (2.2.3)\n", + "Requirement already satisfied: yfinance==0.2.48 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 3)) (0.2.48)\n", + "Requirement already satisfied: python-dotenv==1.0.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", + "Requirement already satisfied: azure-core>=1.31.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.32.0)\n", + "Requirement already satisfied: cryptography>=2.5 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (43.0.3)\n", + "Requirement already satisfied: msal>=1.30.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.31.1)\n", + "Requirement already satisfied: msal-extensions>=1.2.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.2.0)\n", + "Requirement already satisfied: typing-extensions>=4.0.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (4.12.2)\n", + "Requirement already satisfied: numpy>=1.26.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.1.3)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.9.0.post0)\n", + "Requirement already satisfied: pytz>=2020.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", + "Requirement already satisfied: requests>=2.31 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.32.3)\n", + "Requirement already satisfied: multitasking>=0.0.7 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.0.11)\n", + "Requirement already satisfied: lxml>=4.9.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (5.3.0)\n", + "Requirement already satisfied: platformdirs>=2.0.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.3.6)\n", + "Requirement already satisfied: frozendict>=2.3.4 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.4.6)\n", + "Requirement already satisfied: peewee>=3.16.2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.17.8)\n", + "Requirement already satisfied: beautifulsoup4>=4.11.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.12.3)\n", + "Requirement already satisfied: html5lib>=1.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (1.1)\n", + "Requirement already satisfied: isodate>=0.6.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-ai-projects==1.0.0b1->-r ./requirements.txt (line 5)) (0.7.2)\n", + "Requirement already satisfied: six>=1.11.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-core>=1.31.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.16.0)\n", + "Requirement already satisfied: soupsieve>1.2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.6)\n", + "Requirement already satisfied: cffi>=1.12 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.17.1)\n", + "Requirement already satisfied: webencodings in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.5.1)\n", + "Requirement already satisfied: PyJWT<3,>=1.0.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from PyJWT[crypto]<3,>=1.0.0->msal>=1.30.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.0)\n", + "Requirement already satisfied: portalocker<3,>=1.4 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from msal-extensions>=1.2.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.1)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.4.0)\n", + "Requirement already satisfied: idna<4,>=2.5 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.10)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.2.3)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2024.8.30)\n", + "Requirement already satisfied: pycparser in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from cffi>=1.12->cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.22)\n", + "azure-ai-projects is already installed with the same version as the provided wheel. Use --force-reinstall to force an installation of the wheel.\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], "source": [ "# Install the packages\n", "%pip install -r ./requirements.txt" @@ -92,31 +135,30 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "notebookRunGroups": { - "groupValue": "2" + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Environment variables loaded successfully.\n" + ] } - }, - "outputs": [], + ], "source": [ "import os\n", "from dotenv import load_dotenv\n", "\n", "# Load environment variables from .env file\n", - "load_dotenv(dotenv_path=\".venv/.env\")\n", + "load_dotenv()\n", "\n", "# Retrieve the secrets\n", - "__AZURE_OPENAI_API_KEY = os.getenv(\"AZURE_OPENAI_API_KEY\")\n", - "__AZURE_OPENAI_ENDPOINT = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n", + "__PROJECT_CONNECTION_STRING = os.getenv(\"PROJECT_CONNECTION_STRING\")\n", "__AZURE_OPENAI_DEPLOYMENT = os.getenv(\"AZURE_OPENAI_DEPLOYMENT\")\n", - "__AZURE_OPENAI_API_VERSION = os.getenv(\"AZURE_OPENAI_API_VERSION\")\n", "\n", "# Verify environment variables\n", - "if not all([ __AZURE_OPENAI_API_KEY,\n", - " __AZURE_OPENAI_ENDPOINT, \n", - " __AZURE_OPENAI_DEPLOYMENT, \n", - " __AZURE_OPENAI_API_VERSION]):\n", + "if not all([__PROJECT_CONNECTION_STRING, __AZURE_OPENAI_DEPLOYMENT]):\n", " raise EnvironmentError(\"One or more environment variables are missing. Please check the .env file.\")\n", "else:\n", " print(\"Environment variables loaded successfully.\")" @@ -126,40 +168,35 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Azure OpenAI setup**" + "## **Azure Agent Runtime setup**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 1: Initializing the Azure OpenAI Client\n", + "#### Step 1: Initializing the Azure Agent Runtime Client\n", "\n", - "Next, we’ll initialize the Azure OpenAI client. This client allows us to interact with Azure OpenAI's service and file management APIs. You’ll need your API key, endpoint, and API version, which we just loaded from the environment." + "Next, we’ll initialize the Azure Agent Runtime client. This client allows us to interact with Azure Agents. We will use a DefaultAzureCredential to authenticate, meaning you will have to be logged in with the Azure CLI." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "notebookRunGroups": { - "groupValue": "2" - } - }, + "execution_count": 3, + "metadata": {}, "outputs": [], "source": [ - "from openai import AzureOpenAI, OpenAIError\n", + "import os\n", + "from azure.ai.projects import AIProjectClient\n", + "from azure.identity import DefaultAzureCredential\n", "\n", - "# Initialize the AzureOpenAI client\n", - "try:\n", - " openai_client = AzureOpenAI(\n", - " api_key=__AZURE_OPENAI_API_KEY,\n", - " api_version=__AZURE_OPENAI_API_VERSION,\n", - " azure_endpoint=__AZURE_OPENAI_ENDPOINT\n", - " )\n", - " print(\"AzureOpenAI client initialized.\")\n", - "except OpenAIError as e:\n", - " raise ConnectionError(f\"Failed to initialize AzureOpenAI client: {e}\")\n" + "# Initialize the Azure AI Project client\n", + "project_client = AIProjectClient.from_connection_string(\n", + " credential=DefaultAzureCredential(),\n", + " conn_str=os.environ[\"PROJECT_CONNECTION_STRING\"],\n", + ")\n", + "\n", + "agents_client = project_client.agents" ] }, { @@ -177,17 +214,23 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "notebookRunGroups": { - "groupValue": "2" + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deleted existing file: investment_portfolio.csv\n", + "Uploaded file: investment_portfolio.csv\n" + ] } - }, - "outputs": [], + ], "source": [ "# Directory containing files to upload\n", "directory=\"data\"\n", "portfolio_file=\"investment_portfolio.csv\"\n", + "portfolio_file_id=None\n", "\n", "# Check if the directory exists\n", "if not os.path.isdir(directory):\n", @@ -201,22 +244,20 @@ " print(f\"Skipping non-file item: {portfolio_file}\")\n", "\n", "try:\n", - " # Delete existing file in Azure OpenAI Service if it has the same name and purpose\n", - " existing_files = openai_client.files.list()\n", - " for f in existing_files:\n", + " # Delete existing file on Azure if it has the same name and purpose\n", + " existing_files = agents_client.list_files()\n", + " for f in existing_files.data:\n", " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", - " openai_client.files.delete(file_id=f.id)\n", + " agents_client.delete_file(f.id)\n", " print(f\"Deleted existing file: {portfolio_file}\")\n", "\n", " # Upload new file\n", " with open(file_path, \"rb\") as file_data:\n", - " portfolio_file = openai_client.files.create(file=file_data, purpose=\"assistants\")\n", - " print(f\"Uploaded file: {portfolio_file.filename}\")\n", - "\n", - "except OpenAIError as e:\n", - " print(f\"Error processing file '{portfolio_file}': {e}\")\n", + " file = agents_client.upload_file(file=file_data, purpose=\"assistants\")\n", + " portfolio_file_id = file.id\n", + " print(f\"Uploaded file: {portfolio_file}\")\n", "except Exception as e:\n", - " print(f\"Unexpected error with file '{portfolio_file}': {e}\")" + " print(f\"Error processing file '{portfolio_file}': {e}\")" ] }, { @@ -240,9 +281,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function defined successfully.\n" + ] + } + ], "source": [ "import yfinance as yf\n", "\n", @@ -292,7 +341,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -318,9 +367,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tools list defined successfully.\n" + ] + } + ], "source": [ "tools_list = [\n", " {\"type\": \"code_interpreter\"},\n", @@ -353,13 +410,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Assistant created successfully.\n", + " asst_tXMQBuztYifTQfNE5Lp1VNgW\n" + ] + } + ], "source": [ "# Create the assistant with code interpreter and function calling tools enabled\n", "try:\n", - " assistant = openai_client.beta.assistants.create(\n", + " assistant = agents_client.create_agent(\n", " name=\"Investment Management Assistant\",\n", " instructions=(\n", " \"You are an expert investment analyst. \"\n", @@ -369,7 +435,7 @@ " tools=tools_list\n", " )\n", " print(\"Assistant created successfully.\\n\", assistant.id)\n", - "except OpenAIError as e:\n", + "except Exception as e:\n", " print(\"Error creating assistant:\", e)" ] }, @@ -392,15 +458,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Thread created successfully: thread_BOpdNUWOKc1PWuhV02QH1v89\n" + ] + } + ], "source": [ "# Create a conversation thread\n", "try:\n", - " thread = openai_client.beta.threads.create()\n", - " print(\"Thread created successfully.\\n\", thread.id)\n", - "except OpenAIError as e:\n", + " thread = agents_client.create_thread()\n", + " print(\"Thread created successfully:\", thread.id)\n", + "except Exception as e:\n", " print(\"Error creating thread:\", e)" ] }, @@ -418,25 +492,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Successfully added User prompt to the thread.\n", + " msg_AUX9UYDcg11oxMlPDlRJeXF1\n" + ] + } + ], "source": [ "# Define the user question\n", "prompt_content = \"What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\"\n", "\n", "# Add the question to the thread\n", "try:\n", - " message = openai_client.beta.threads.messages.create(\n", + " message = agents_client.create_message(\n", " thread_id=thread.id,\n", " role=\"user\",\n", " content=prompt_content,\n", " attachments=[ # Add files by using the attachments parameter\n", - " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", + " {\"file_id\": portfolio_file_id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", " ],\n", " )\n", " print(\"Successfully added User prompt to the thread.\\n\", message.id)\n", - "except OpenAIError as e:\n", + "except Exception as e:\n", " print(\"Error adding user question:\", e)\n" ] }, @@ -463,17 +546,25 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Run started: {'id': 'run_MRzNQ9n63w0wGCjTAOJ3pZDU', 'object': 'thread.run', 'created_at': 1731936023, 'assistant_id': 'asst_tXMQBuztYifTQfNE5Lp1VNgW', 'thread_id': 'thread_BOpdNUWOKc1PWuhV02QH1v89', 'status': 'queued', 'started_at': None, 'expires_at': 1731936623, 'cancelled_at': None, 'failed_at': None, 'completed_at': None, 'required_action': None, 'last_error': None, 'model': 'gpt-4o', 'instructions': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'tools': [{'type': 'code_interpreter'}, {'type': 'function', 'function': {'name': 'fetch_stock_price', 'description': 'Retrieve the latest closing price of a stock using its ticker symbol.', 'parameters': {'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, 'strict': False}}], 'tool_resources': {}, 'metadata': {}, 'temperature': 1.0, 'top_p': 1.0, 'max_completion_tokens': None, 'max_prompt_tokens': None, 'truncation_strategy': {'type': 'auto', 'last_messages': None}, 'incomplete_details': None, 'usage': None, 'response_format': 'auto', 'tool_choice': 'auto', 'parallel_tool_calls': True}\n" + ] + } + ], "source": [ "# Initiate the assistant's response\n", "try:\n", - " run = openai_client.beta.threads.runs.create(\n", + " run = agents_client.create_run(\n", " thread_id=thread.id,\n", " assistant_id=assistant.id,\n", " instructions=prompt_content,\n", " )\n", - " print(\"Run started:\", run)\n", - "except OpenAIError as e:\n", + " print(\"Run started:\", run.id)\n", + "except Exception as e:\n", " print(\"Error starting run:\", e)" ] }, @@ -497,14 +588,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Monitoring the run status...\n", + "Navigate to `RunStatus.COMPLETED` cell.\n" + ] + } + ], "source": [ "import json\n", "\n", "# Retrieve the run status\n", - "run = openai_client.beta.threads.runs.retrieve(\n", + "run = agents_client.get_run(\n", " thread_id=thread.id,\n", " run_id=run.id\n", ")\n", @@ -527,14 +627,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Assistant run failed. Please try again.\n", + "{'id': 'run_MXRH9lBIAQ0sv93TXWdxqh9n', 'object': 'thread.run', 'created_at': 1731935669, 'assistant_id': 'asst_DYdmKFTdWR3HfEFxxVVIuWxu', 'thread_id': 'thread_WBikiRkfRlan1KxlkdM5biNq', 'status': 'failed', 'started_at': 1731935678, 'expires_at': None, 'cancelled_at': None, 'failed_at': 1731935694, 'completed_at': None, 'required_action': None, 'last_error': {'code': 'rate_limit_exceeded', 'message': 'Rate limit is exceeded. Try again in 35 seconds.'}, 'model': 'gpt-4o-mini', 'instructions': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'tools': [{'type': 'code_interpreter'}, {'type': 'function', 'function': {'name': 'fetch_stock_price', 'description': 'Retrieve the latest closing price of a stock using its ticker symbol.', 'parameters': {'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, 'strict': False}}], 'tool_resources': {}, 'metadata': {}, 'temperature': 1.0, 'top_p': 1.0, 'max_completion_tokens': None, 'max_prompt_tokens': None, 'truncation_strategy': {'type': 'auto', 'last_messages': None}, 'incomplete_details': None, 'usage': {'prompt_tokens': 565, 'completion_tokens': 197, 'total_tokens': 762}, 'response_format': 'auto', 'tool_choice': 'auto', 'parallel_tool_calls': True}\n" + ] + } + ], "source": [ "#print(run.model_dump_json(indent=4))\n", "\n", "if run.status == \"failed\":\n", " print(\"Assistant run failed. Please try again.\")\n", + " print(run)\n", "else:\n", " print(f\"Assistant run has not failed...\\nNavigate to and execute the '{run.status}' cell.\")\n" ] @@ -550,9 +660,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function Calling ...\n", + "Function 'fetch_stock_price' called successfully. \n", + "Output: 415.0\n", + "\n", + "Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\n" + ] + } + ], "source": [ "if run.status == \"requires_action\":\n", " print(\"Function Calling ...\")\n", @@ -572,7 +694,7 @@ " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", " print(f\"Function '{call.function.name}' called successfully. \\nOutput: {tool_response}\\n\")\n", "\n", - " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " run = agents_client.submit_tool_outputs_to_run(\n", " thread_id=thread.id, run_id=run.id, tool_outputs=tool_responses\n", " )\n", "\n", @@ -592,12 +714,53 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Run completed!\n", + "\n", + "MESSAGES\n", + "\n", + "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", + "\n", + "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", + "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", + "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", + "\n", + "### Understanding the Data\n", + "Let's filter the data to only include records for Microsoft (`MSFT`).\n", + "\n", + "#### Data\n", + "- `MSFT`\n", + "- Average Cost: 200\n", + "- Quantity: 300\n", + "\n", + "### Latest Closing Price\n", + "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", + "\n", + "### Total Investment Calculation\n", + "The total investment for MSFT is calculated as follows:\n", + "\n", + "\\[\n", + "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", + "\\]\n", + "\n", + "Let's compute this.\n", + "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", + "\n", + "### Summary:\n", + "- **Latest Closing Price for MSFT:** $415.00\n", + "- **Total Investment in MSFT:** $124,500.00\n" + ] + } + ], "source": [ "if run.status == \"completed\":\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread.id, order=\"asc\", after=message.id) # Ascending order for output\n", + " messages = agents_client.list_messages(thread_id=thread.id, order=\"asc\", after=message.id)\n", "\n", " print(f'Run completed!\\n\\nMESSAGES\\n')\n", "\n", @@ -633,9 +796,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function `process_message` created successfully.\n" + ] + } + ], "source": [ "import time\n", "import json\n", @@ -645,7 +816,7 @@ "def process_message(thread_id, prompt_message, attachments_list=None):\n", " try:\n", " # Add the prompt to the thread\n", - " message = openai_client.beta.threads.messages.create(\n", + " message = agents_client.create_message(\n", " thread_id=thread_id,\n", " role=\"user\",\n", " content=prompt_message,\n", @@ -654,20 +825,20 @@ " print(\"User message added...\") #:\", message)\n", "\n", " # Initiate the assistant's response\n", - " run = openai_client.beta.threads.runs.create(\n", + " run = agents_client.create_run(\n", " thread_id=thread_id,\n", " assistant_id=assistant.id,\n", " instructions=prompt_message,\n", " )\n", " print(\"Run started...\") #:\", run)\n", - " except OpenAIError as e:\n", + " except Exception as e:\n", " print(\"Error starting run:\", e)\n", "\n", " while True: # Polling to monitor Run status\n", " time.sleep(5) # Wait 5 seconds to give the process time to move past `queued` state\n", "\n", " # Retrieves the thread’s response.\n", - " run = openai_client.beta.threads.runs.retrieve(\n", + " run = agents_client.get_run(\n", " thread_id=thread_id,\n", " run_id=run.id\n", " )\n", @@ -676,7 +847,7 @@ " print(f\"Run Status: {run_status}\\n\")\n", " if run_status == 'completed':\n", " # Get all messages in thread to read\n", - " thread_messages = openai_client.beta.threads.messages.list(thread_id=thread_id, order=\"asc\") #, after=message.id)\n", + " thread_messages = agents_client.list_messages(thread_id=thread_id, order=\"asc\") #, after=message.id)\n", "\n", " # Loop through thread messages and print content\n", " for thread_message in thread_messages.data:\n", @@ -695,7 +866,7 @@ " \n", " break\n", " elif run.status == \"failed\":\n", - " messages = openai_client.beta.threads.messages.list(thread_id=thread.id)\n", + " messages = agents_client.list_messages(thread_id=thread.id)\n", " answer = messages.data[0].content[0].text.value\n", " print(f\"Failed User:\\n{prompt_message}\\nAssistant:\\n{answer}\\n\")\n", "\n", @@ -725,7 +896,7 @@ " raise ValueError(f\"Requested function '{call.function.name}' is not available.\")\n", " \n", " # Submit all collected tool outputs back to the assistant to satisfy the required action\n", - " run = openai_client.beta.threads.runs.submit_tool_outputs(\n", + " run = agents_client.submit_tool_outputs_to_run(\n", " thread_id=thread_id, \n", " run_id=run.id, \n", " tool_outputs=tool_responses\n", @@ -748,9 +919,53 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", + "\n", + "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", + "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", + "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", + "\n", + "### Understanding the Data\n", + "Let's filter the data to only include records for Microsoft (`MSFT`).\n", + "\n", + "#### Data\n", + "- `MSFT`\n", + "- Average Cost: 200\n", + "- Quantity: 300\n", + "\n", + "### Latest Closing Price\n", + "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", + "\n", + "### Total Investment Calculation\n", + "The total investment for MSFT is calculated as follows:\n", + "\n", + "\\[\n", + "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", + "\\]\n", + "\n", + "Let's compute this.\n", + "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", + "\n", + "### Summary:\n", + "- **Latest Closing Price for MSFT:** $415.00\n", + "- **Total Investment in MSFT:** $124,500.00\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] @@ -765,12 +980,89 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.IN_PROGRESS\n", + "\n", + "Run Status: RunStatus.REQUIRES_ACTION\n", + "\n", + "Function calling initiated...\n", + "Executed 'fetch_stock_price'. Output: 225.0\n", + "Executed 'fetch_stock_price'. Output: 202.61\n", + "Executed 'fetch_stock_price'. Output: 320.72\n", + "Executed 'fetch_stock_price'. Output: 823.96\n", + "Function call(s) completed successfully.\n", + "Run Status: RunStatus.IN_PROGRESS\n", + "\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", + "\n", + "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", + "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", + "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", + "\n", + "### Understanding the Data\n", + "Let's filter the data to only include records for Microsoft (`MSFT`).\n", + "\n", + "#### Data\n", + "- `MSFT`\n", + "- Average Cost: 200\n", + "- Quantity: 300\n", + "\n", + "### Latest Closing Price\n", + "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", + "\n", + "### Total Investment Calculation\n", + "The total investment for MSFT is calculated as follows:\n", + "\n", + "\\[\n", + "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", + "\\]\n", + "\n", + "Let's compute this.\n", + "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", + "\n", + "### Summary:\n", + "- **Latest Closing Price for MSFT:** $415.00\n", + "- **Total Investment in MSFT:** $124,500.00\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you have invested in the most, we will calculate the total investment for each company listed in your data. We already know the latest closing price for Microsoft (MSFT). We will also need to fetch the latest closing prices for the other companies: Apple (AAPL), Amazon (AMZN), Tesla (TSLA), and Netflix (NFLX).\n", + "\n", + "We will then compute the total investment value for each company and identify the company with the highest investment.\n", + "\n", + "### Your Data\n", + "- Apple (AAPL): 200 shares\n", + "- Amazon (AMZN): 50 shares\n", + "- Tesla (TSLA): 100 shares\n", + "- Netflix (NFLX): 80 shares\n", + "\n", + "### Steps:\n", + "1. Fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\n", + "2. Calculate the total investment for each company.\n", + "3. Identify the company with the highest investment.\n", + "\n", + "Let's start by fetching the latest closing prices for the remaining companies.\n", + "Assistant: It appears that there was an issue with retrieving the closing price for a symbol that is misspelled or not available in the `latest_prices` dictionary. I will correct the data to handle these mismatches. \n", + "\n", + "Let's clean the symbols to match their correct representations and re-compute the total investments.\n", + "Assistant: The company you have invested the most in is **Microsoft (MSFT)** with a total investment of \\$124,500.00.\n" + ] + } + ], "source": [ "attachments=[ # Add files by using the attachments parameter\n", - " {\"file_id\": portfolio_file.id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", + " {\"file_id\": portfolio_file_id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", " ]\n", "\n", "process_message(thread_id=thread.id, prompt_message=\"Which company have I invested in the most?\", attachments_list=attachments)" @@ -786,9 +1078,98 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.IN_PROGRESS\n", + "\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", + "\n", + "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", + "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", + "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", + "\n", + "### Understanding the Data\n", + "Let's filter the data to only include records for Microsoft (`MSFT`).\n", + "\n", + "#### Data\n", + "- `MSFT`\n", + "- Average Cost: 200\n", + "- Quantity: 300\n", + "\n", + "### Latest Closing Price\n", + "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", + "\n", + "### Total Investment Calculation\n", + "The total investment for MSFT is calculated as follows:\n", + "\n", + "\\[\n", + "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", + "\\]\n", + "\n", + "Let's compute this.\n", + "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", + "\n", + "### Summary:\n", + "- **Latest Closing Price for MSFT:** $415.00\n", + "- **Total Investment in MSFT:** $124,500.00\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you have invested in the most, we will calculate the total investment for each company listed in your data. We already know the latest closing price for Microsoft (MSFT). We will also need to fetch the latest closing prices for the other companies: Apple (AAPL), Amazon (AMZN), Tesla (TSLA), and Netflix (NFLX).\n", + "\n", + "We will then compute the total investment value for each company and identify the company with the highest investment.\n", + "\n", + "### Your Data\n", + "- Apple (AAPL): 200 shares\n", + "- Amazon (AMZN): 50 shares\n", + "- Tesla (TSLA): 100 shares\n", + "- Netflix (NFLX): 80 shares\n", + "\n", + "### Steps:\n", + "1. Fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\n", + "2. Calculate the total investment for each company.\n", + "3. Identify the company with the highest investment.\n", + "\n", + "Let's start by fetching the latest closing prices for the remaining companies.\n", + "Assistant: It appears that there was an issue with retrieving the closing price for a symbol that is misspelled or not available in the `latest_prices` dictionary. I will correct the data to handle these mismatches. \n", + "\n", + "Let's clean the symbols to match their correct representations and re-compute the total investments.\n", + "Assistant: The company you have invested the most in is **Microsoft (MSFT)** with a total investment of \\$124,500.00.\n", + "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", + "Assistant: The latest closing price for Amazon (AMZN) is $202.61.\n", + "\n", + "### Calculation:\n", + "To calculate the total investment value for Amazon, we use the formula:\n", + "\n", + "\\[\n", + "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", + "\\]\n", + "\n", + "From your data, the quantity of AMZN shares you hold is 50.\n", + "\n", + "\\[\n", + "\\text{Total Investment in AMZN} = 202.61 \\times 50\n", + "\\]\n", + "\n", + "Let's perform the calculation.\n", + "Assistant: Your total investment in Amazon (AMZN) as of today is \\$10,130.50.\n", + "\n", + "### Summary:\n", + "- **Latest Closing Price for AMZN:** $202.61\n", + "- **Total Investment in AMZN:** $10,130.50\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\")" ] @@ -802,9 +1183,100 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.IN_PROGRESS\n", + "\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", + "\n", + "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", + "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", + "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", + "\n", + "### Understanding the Data\n", + "Let's filter the data to only include records for Microsoft (`MSFT`).\n", + "\n", + "#### Data\n", + "- `MSFT`\n", + "- Average Cost: 200\n", + "- Quantity: 300\n", + "\n", + "### Latest Closing Price\n", + "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", + "\n", + "### Total Investment Calculation\n", + "The total investment for MSFT is calculated as follows:\n", + "\n", + "\\[\n", + "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", + "\\]\n", + "\n", + "Let's compute this.\n", + "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", + "\n", + "### Summary:\n", + "- **Latest Closing Price for MSFT:** $415.00\n", + "- **Total Investment in MSFT:** $124,500.00\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you have invested in the most, we will calculate the total investment for each company listed in your data. We already know the latest closing price for Microsoft (MSFT). We will also need to fetch the latest closing prices for the other companies: Apple (AAPL), Amazon (AMZN), Tesla (TSLA), and Netflix (NFLX).\n", + "\n", + "We will then compute the total investment value for each company and identify the company with the highest investment.\n", + "\n", + "### Your Data\n", + "- Apple (AAPL): 200 shares\n", + "- Amazon (AMZN): 50 shares\n", + "- Tesla (TSLA): 100 shares\n", + "- Netflix (NFLX): 80 shares\n", + "\n", + "### Steps:\n", + "1. Fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\n", + "2. Calculate the total investment for each company.\n", + "3. Identify the company with the highest investment.\n", + "\n", + "Let's start by fetching the latest closing prices for the remaining companies.\n", + "Assistant: It appears that there was an issue with retrieving the closing price for a symbol that is misspelled or not available in the `latest_prices` dictionary. I will correct the data to handle these mismatches. \n", + "\n", + "Let's clean the symbols to match their correct representations and re-compute the total investments.\n", + "Assistant: The company you have invested the most in is **Microsoft (MSFT)** with a total investment of \\$124,500.00.\n", + "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", + "Assistant: The latest closing price for Amazon (AMZN) is $202.61.\n", + "\n", + "### Calculation:\n", + "To calculate the total investment value for Amazon, we use the formula:\n", + "\n", + "\\[\n", + "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", + "\\]\n", + "\n", + "From your data, the quantity of AMZN shares you hold is 50.\n", + "\n", + "\\[\n", + "\\text{Total Investment in AMZN} = 202.61 \\times 50\n", + "\\]\n", + "\n", + "Let's perform the calculation.\n", + "Assistant: Your total investment in Amazon (AMZN) as of today is \\$10,130.50.\n", + "\n", + "### Summary:\n", + "- **Latest Closing Price for AMZN:** $202.61\n", + "- **Total Investment in AMZN:** $10,130.50\n", + "User: Show a pie chart of my investments?\n", + "Assistant: {'type': 'image_file', 'image_file': {'file_id': 'assistant-pAF34olTVSKkCmp9plgTRHUW'}}\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments?\")" ] @@ -826,11 +1298,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id': 'asst_tXMQBuztYifTQfNE5Lp1VNgW', 'object': 'assistant.deleted', 'deleted': True}\n" + ] + } + ], "source": [ - "response = openai_client.beta.assistants.delete(assistant.id)\n", + "response = agents_client.delete_agent(assistant.id)\n", "print(response)" ] }, @@ -844,14 +1324,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Error deleting file 'investment_portfolio.csv': 'str' object has no attribute 'filename'\n" + ] + } + ], "source": [ "# delete the file from the Azure OpenAI service\n", "try:\n", " # List all files\n", - " files = openai_client.files.list()\n", + " files = agents_client.list_files()\n", "\n", " # Find the file with the specified name and purpose\n", " file_id = None\n", @@ -862,10 +1350,10 @@ "\n", " # Delete the file if found\n", " if file_id:\n", - " openai_client.files.delete(file_id=file_id)\n", + " agents_client.delete_file(file_id)\n", " print(f\"Deleted file: {portfolio_file}\")\n", "\n", - "except OpenAIError as e:\n", + "except Exception as e:\n", " print(f\"Error deleting file '{portfolio_file}': {e}\")\n", "\n", "except Exception as e:\n", @@ -935,7 +1423,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.7" + "version": "3.12.6" } }, "nbformat": 4, diff --git a/samples/investment_advisor/requirements.txt b/samples/investment_advisor/requirements.txt index 226deed0..8ae07274 100644 --- a/samples/investment_advisor/requirements.txt +++ b/samples/investment_advisor/requirements.txt @@ -1,4 +1,5 @@ +azure-identity==1.19.0 pandas==2.2.3 yfinance==0.2.48 -openai==1.30.1 -python-dotenv==1.0.1 \ No newline at end of file +python-dotenv==1.0.1 +../../packages/azure_ai_projects-1.0.0b1-py3-none-any.whl \ No newline at end of file From ac9e4d8438a53b8953b5f04fc601adaef456f061 Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Mon, 18 Nov 2024 10:01:50 -0500 Subject: [PATCH 152/180] rename file, added TODOs --- ...ent_portfolio.ipynb => agent-investment_advisor.ipynb} | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) rename samples/investment_advisor/{assistant-investment_portfolio.ipynb => agent-investment_advisor.ipynb} (99%) diff --git a/samples/investment_advisor/assistant-investment_portfolio.ipynb b/samples/investment_advisor/agent-investment_advisor.ipynb similarity index 99% rename from samples/investment_advisor/assistant-investment_portfolio.ipynb rename to samples/investment_advisor/agent-investment_advisor.ipynb index c7325026..997ed608 100644 --- a/samples/investment_advisor/assistant-investment_portfolio.ipynb +++ b/samples/investment_advisor/agent-investment_advisor.ipynb @@ -538,7 +538,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 3: Running the Assistant\n", + "### Step 1: Running the Assistant\n", "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" ] }, @@ -796,7 +796,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -857,6 +857,10 @@ " first_content = thread_message.content[0]\n", " if hasattr(first_content, 'text') and hasattr(first_content.text, 'value'):\n", " content = first_content.text.value\n", + " if hasattr(first_content, 'image_file') and hasattr(first_content.text, 'value'):\n", + " # Download the file locally\n", + " # Use Matplotlib to display the image\n", + " content = first_content.text.value\n", " else:\n", " content = str(first_content)\n", " else:\n", From ba6f4c7251e26247c1b38a96d80101f1837a91fb Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Mon, 18 Nov 2024 11:23:23 -0500 Subject: [PATCH 153/180] completed Image rendering example --- .../agent-investment_advisor.ipynb | 738 +++--------------- samples/investment_advisor/requirements.txt | 2 + 2 files changed, 132 insertions(+), 608 deletions(-) diff --git a/samples/investment_advisor/agent-investment_advisor.ipynb b/samples/investment_advisor/agent-investment_advisor.ipynb index 997ed608..5e95c633 100644 --- a/samples/investment_advisor/agent-investment_advisor.ipynb +++ b/samples/investment_advisor/agent-investment_advisor.ipynb @@ -4,7 +4,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# **Investment Portfolio Management**" + "# **Investment Advisor**\n", + "\n", + "## TODO:\n", + "- Review text, \"Assistant\" should be \"Agent\" everywhere\n", + "- \"Assistant API\" should be \"Agent Runtime\"\n", + "- Review text for typos and quality" ] }, { @@ -13,9 +18,9 @@ "source": [ "## **About the Scenario**\n", "\n", - "This notebook demonstrates a practical use case where an AI Assistant is leveraged to gain actionable insights and address key analytical questions related to managing an investment portfolio. It combines real-time data fetching, computation, and visualization to streamline decision-making.\n", + "This notebook demonstrates a practical use case where an AI Agent is leveraged to gain actionable insights and address key analytical questions related to managing an investment portfolio. It combines real-time data fetching, computation, and visualization to streamline decision-making.\n", "\n", - "The scenario utilizes an AI Assistant integrated with two powerful tools: Function Calling and Code Interpreter. These tools work together to retrieve real-time stock prices and calculate portfolio metrics, replicating real-world workflows in investment management.\n", + "The scenario utilizes an AI Agent integrated with two powerful tools: Function Calling and Code Interpreter. These tools work together to retrieve real-time stock prices and calculate portfolio metrics, replicating real-world workflows in investment management.\n", "\n", "### Key Steps:\n", "\n", @@ -57,52 +62,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Processing /Users/macardoso/azure-ai-agents/packages/azure_ai_projects-1.0.0b1-py3-none-any.whl (from -r ./requirements.txt (line 5))\n", - "Requirement already satisfied: azure-identity==1.19.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 1)) (1.19.0)\n", - "Requirement already satisfied: pandas==2.2.3 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 2)) (2.2.3)\n", - "Requirement already satisfied: yfinance==0.2.48 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 3)) (0.2.48)\n", - "Requirement already satisfied: python-dotenv==1.0.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", - "Requirement already satisfied: azure-core>=1.31.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.32.0)\n", - "Requirement already satisfied: cryptography>=2.5 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (43.0.3)\n", - "Requirement already satisfied: msal>=1.30.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.31.1)\n", - "Requirement already satisfied: msal-extensions>=1.2.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.2.0)\n", - "Requirement already satisfied: typing-extensions>=4.0.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (4.12.2)\n", - "Requirement already satisfied: numpy>=1.26.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.1.3)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", - "Requirement already satisfied: requests>=2.31 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.32.3)\n", - "Requirement already satisfied: multitasking>=0.0.7 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.0.11)\n", - "Requirement already satisfied: lxml>=4.9.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (5.3.0)\n", - "Requirement already satisfied: platformdirs>=2.0.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.3.6)\n", - "Requirement already satisfied: frozendict>=2.3.4 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.4.6)\n", - "Requirement already satisfied: peewee>=3.16.2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.17.8)\n", - "Requirement already satisfied: beautifulsoup4>=4.11.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.12.3)\n", - "Requirement already satisfied: html5lib>=1.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (1.1)\n", - "Requirement already satisfied: isodate>=0.6.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-ai-projects==1.0.0b1->-r ./requirements.txt (line 5)) (0.7.2)\n", - "Requirement already satisfied: six>=1.11.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from azure-core>=1.31.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.16.0)\n", - "Requirement already satisfied: soupsieve>1.2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.6)\n", - "Requirement already satisfied: cffi>=1.12 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.17.1)\n", - "Requirement already satisfied: webencodings in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.5.1)\n", - "Requirement already satisfied: PyJWT<3,>=1.0.0 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from PyJWT[crypto]<3,>=1.0.0->msal>=1.30.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.0)\n", - "Requirement already satisfied: portalocker<3,>=1.4 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from msal-extensions>=1.2.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.1)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.4.0)\n", - "Requirement already satisfied: idna<4,>=2.5 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.10)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.2.3)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2024.8.30)\n", - "Requirement already satisfied: pycparser in /Users/macardoso/azure-ai-agents/.venv/lib/python3.12/site-packages (from cffi>=1.12->cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.22)\n", - "azure-ai-projects is already installed with the same version as the provided wheel. Use --force-reinstall to force an installation of the wheel.\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], + "outputs": [], "source": [ "# Install the packages\n", "%pip install -r ./requirements.txt" @@ -116,15 +78,13 @@ "Before we begin, we need to load the necessary environment variables from a `.env` file. These variables include sensitive information such as API keys and endpoint URLs, which are crucial for running the code successfully.\n", "\n", "Here’s what you need to do:\n", - "- Ensure your `.env` file is properly configured in the `.venv/.env` format.\n", + "- Ensure your `.env` file is properly configured in the `.venv/.env` format. We have provided an template `.env` file, `.env.example` for your reference.\n", "- Verify that all required secrets are included in the file before running the code.\n", "\n", "\n", "The `.env` file must contain the following secrets:\n", - "- AZURE_OPENAI_API_KEY: Your unique API key for accessing the service.\n", - "- AZURE_OPENAI_ENDPOINT: The URL endpoint for the API.\n", + "- PROJECT_CONNECTION_STRING: URL to connect to the Azure OpenAI Project to access project resources.\n", "- AZURE_OPENAI_DEPLOYMENT: The name of the Azure OpenAI model deployment.\n", - "- AZURE_OPENAI_API_VERSION: The current API version found in the [API documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/references/on-your-data?tabs=python).\n", "\n", "Now, let’s load these variables and get started!\n", "\n", @@ -135,17 +95,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment variables loaded successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", "from dotenv import load_dotenv\n", @@ -182,7 +134,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -196,7 +148,9 @@ " conn_str=os.environ[\"PROJECT_CONNECTION_STRING\"],\n", ")\n", "\n", - "agents_client = project_client.agents" + "agents_client = project_client.agents\n", + "\n", + "print(\"Agent client created successfully.\")" ] }, { @@ -214,18 +168,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Deleted existing file: investment_portfolio.csv\n", - "Uploaded file: investment_portfolio.csv\n" - ] - } - ], + "outputs": [], "source": [ "# Directory containing files to upload\n", "directory=\"data\"\n", @@ -264,34 +209,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Azure OpenAI Assistant**" + "## **Azure OpenAI Agent**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 1: Define function for Assistant Function Calling tool\n", - "In this scenario, we will utilize the *Function Calling* tool within the Assistant to enhance our insights by invoking a custom function. Since the LLM and Assistant currently lack direct access to the internet for user prompts, Function Calling serves as a powerful alternative.\n", + "### Step 1: Define function for Agent Function Calling tool\n", + "In this scenario, we will utilize the *Function Calling* tool within the Agent to enhance our insights by invoking a custom function. Since the LLM and Agent currently lack direct access to the internet for user prompts, Function Calling serves as a powerful alternative.\n", "\n", "We will use the `fetch_stock_price` function to retrieve stock data for a specified *ticker symbol*. This function leverages the `yfinance` library to fetch the most recent stock price data, specifically for the last trading day.\n", "\n", - "This approach enables the Assistant to provide real-time, actionable insights by integrating external data sources through custom functions. Let’s explore how to implement and use this functionality!" + "This approach enables the Agent to provide real-time, actionable insights by integrating external data sources through custom functions. Let’s explore how to implement and use this functionality!" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import yfinance as yf\n", "\n", @@ -341,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -352,32 +289,24 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2: Configure Assistant Tool-Calling for Enhanced Functionality\n", - "The tool-calling definition informs the LLM about the tools available for its use. In our scenario, this configuration enables both *code interpretation* and *function calling*, allowing the Assistant to perform complex operations and retrieve external data.\n", + "### Step 2: Configure Agent Tool-Calling for Enhanced Functionality\n", + "The tool-calling definition informs the LLM about the tools available for its use. In our scenario, this configuration enables both *code interpretation* and *function calling*, allowing the Agent to perform complex operations and retrieve external data.\n", "\n", - "We will specifically configure the `fetch_stock_price` function alongside the *code interpreter tool*. By integrating this tool into the Assistant, we empower it to:\n", + "We will specifically configure the `fetch_stock_price` function alongside the *code interpreter tool*. By integrating this tool into the Agent, we empower it to:\n", "\n", "- Retrieve stock data for a specified ticker symbol using the `fetch_stock_price` function.\n", "- Interpret and analyze the retrieved data to provide meaningful insights in response to user queries.\n", "\n", - "This setup allows the Assistant to seamlessly combine external data retrieval with code-based reasoning, ensuring accurate and actionable responses to stock-related prompts. \n", + "This setup allows the Agent to seamlessly combine external data retrieval with code-based reasoning, ensuring accurate and actionable responses to stock-related prompts. \n", "\n", "Let’s define and integrate this tool to unlock its full potential!" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tools list defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "tools_list = [\n", " {\"type\": \"code_interpreter\"},\n", @@ -402,31 +331,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 3: Creating an Investment Analysis Assistant\n", - "In this step, we’ll set up an Azure OpenAI Assistant with the specified tools, including a *code interpreter*, to handle investment-related queries. This assistant will also leverage the previously defined function calls to provide accurate and actionable insights. \n", + "### Step 3: Creating an Investment Analysis Agent\n", + "In this step, we’ll set up an Azure OpenAI Agent with the specified tools, including a *code interpreter*, to handle investment-related queries. This Agent will also leverage the previously defined function calls to provide accurate and actionable insights. \n", "\n", - "Let’s configure the Assistant and enable its capabilities! " + "Let’s configure the Agent and enable its capabilities! " ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Assistant created successfully.\n", - " asst_tXMQBuztYifTQfNE5Lp1VNgW\n" - ] - } - ], + "outputs": [], "source": [ - "# Create the assistant with code interpreter and function calling tools enabled\n", + "# Create the Agent with code interpreter and function calling tools enabled\n", "try:\n", - " assistant = agents_client.create_agent(\n", - " name=\"Investment Management Assistant\",\n", + " agent = agents_client.create_agent(\n", + " name=\"Investment Advisor Agent\",\n", " instructions=(\n", " \"You are an expert investment analyst. \"\n", " \"Use your knowledge base to answer questions about personal investment portfolio management.\"\n", @@ -434,16 +354,16 @@ " model=__AZURE_OPENAI_DEPLOYMENT,\n", " tools=tools_list\n", " )\n", - " print(\"Assistant created successfully.\\n\", assistant.id)\n", + " print(\"Agent created successfully.\\n\", agent.id)\n", "except Exception as e:\n", - " print(\"Error creating assistant:\", e)" + " print(\"Error creating Agent:\", e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## **Querying the Assistant**" + "## **Querying the Agent**" ] }, { @@ -451,24 +371,16 @@ "metadata": {}, "source": [ "### Step 1: Starting a New Conversation Thread\n", - "Let’s create a new thread to handle user interactions. Each thread provides a dedicated space for conversations with the Assistant, keeping the context focused and organized. \n", + "Let’s create a new thread to handle user interactions. Each thread provides a dedicated space for conversations with the Agent, keeping the context focused and organized. \n", "\n", "This setup ensures clear and seamless communication for each user interaction." ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Thread created successfully: thread_BOpdNUWOKc1PWuhV02QH1v89\n" - ] - } - ], + "outputs": [], "source": [ "# Create a conversation thread\n", "try:\n", @@ -483,27 +395,18 @@ "metadata": {}, "source": [ "### Step 2: Adding User Message to the Thread\n", - "In this step, we’ll add a user message to the thread to demonstrate the assistant’s capabilities. Specifically, we’ll ask for the latest closing price of a specified company (*Microsoft*), which will leverage *function calling* to retrieve this data using the `fetch_stock_price` function.\n", + "In this step, we’ll add a user message to the thread to demonstrate the Agent’s capabilities. Specifically, we’ll ask for the latest closing price of a specified company (*Microsoft*), which will leverage *function calling* to retrieve this data using the `fetch_stock_price` function.\n", "\n", - "The assistant will then use the *code interpreter* to combine this information with the `QTY` data from the uploaded `investment_portfolio.csv` file to calculate the **total investment**. \n", + "The Agent will then use the *code interpreter* to combine this information with the `QTY` data from the uploaded `investment_portfolio.csv` file to calculate the **total investment**. \n", "\n", - "This workflow showcases how the assistant integrates external data retrieval with computational analysis to deliver actionable insights." + "This workflow showcases how the Agent integrates external data retrieval with computational analysis to deliver actionable insights." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Successfully added User prompt to the thread.\n", - " msg_AUX9UYDcg11oxMlPDlRJeXF1\n" - ] - } - ], + "outputs": [], "source": [ "# Define the user question\n", "prompt_content = \"What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\"\n", @@ -529,7 +432,7 @@ "source": [ "## **Demonstrating the Thread Run Process (Manual)**\n", "\n", - "The next five cells will demonstrate how the assistant's thread run process works. Instead of running a typical loop with polling to monitor the run status, we’ll manually step through the cells to better understand each stage of the process.\n", + "The next five cells will demonstrate how the Agent's thread run process works. Instead of running a typical loop with polling to monitor the run status, we’ll manually step through the cells to better understand each stage of the process.\n", "\n", "In the subsequent section, these cells will be wrapped into a processing function that incorporates the polling functionality, providing a more streamlined and automated workflow. This approach helps clarify how the thread execution operates while offering a hands-on view of each step." ] @@ -538,29 +441,21 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 1: Running the Assistant\n", - "Now that the assistant and thread are set up, we'll initiate the assistant's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" + "### Step 1: Running the Agent\n", + "Now that the Agent and thread are set up, we'll initiate the Agent's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Run started: {'id': 'run_MRzNQ9n63w0wGCjTAOJ3pZDU', 'object': 'thread.run', 'created_at': 1731936023, 'assistant_id': 'asst_tXMQBuztYifTQfNE5Lp1VNgW', 'thread_id': 'thread_BOpdNUWOKc1PWuhV02QH1v89', 'status': 'queued', 'started_at': None, 'expires_at': 1731936623, 'cancelled_at': None, 'failed_at': None, 'completed_at': None, 'required_action': None, 'last_error': None, 'model': 'gpt-4o', 'instructions': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'tools': [{'type': 'code_interpreter'}, {'type': 'function', 'function': {'name': 'fetch_stock_price', 'description': 'Retrieve the latest closing price of a stock using its ticker symbol.', 'parameters': {'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, 'strict': False}}], 'tool_resources': {}, 'metadata': {}, 'temperature': 1.0, 'top_p': 1.0, 'max_completion_tokens': None, 'max_prompt_tokens': None, 'truncation_strategy': {'type': 'auto', 'last_messages': None}, 'incomplete_details': None, 'usage': None, 'response_format': 'auto', 'tool_choice': 'auto', 'parallel_tool_calls': True}\n" - ] - } - ], + "outputs": [], "source": [ - "# Initiate the assistant's response\n", + "# Initiate the Agent's response\n", "try:\n", " run = agents_client.create_run(\n", " thread_id=thread.id,\n", - " assistant_id=assistant.id,\n", + " assistant_id=agent.id,\n", " instructions=prompt_content,\n", " )\n", " print(\"Run started:\", run.id)\n", @@ -572,34 +467,25 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 4: Monitor run status" + "### Step 2: Monitor run status" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "A Run is an instance where an Assistant operates within a Thread. During a Run, the Assistant processes the Thread's Messages and its configuration to perform tasks using models and tools, adding additional Messages to the Thread as part of its operations.\n", + "A Run is an instance where an Agent operates within a Thread. During a Run, the Agent processes the Thread's Messages and its configuration to perform tasks using models and tools, adding additional Messages to the Thread as part of its operations.\n", "\n", - "The assistant might take some time to analyze and respond, so it's important to monitor the run status. Based on the status, *specific actions are executed*. \n", + "The Agent might take some time to analyze and respond, so it's important to monitor the run status. Based on the status, *specific actions are executed*. \n", "\n", "Let's dive deeper into these status-driven actions!" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Monitoring the run status...\n", - "Navigate to `RunStatus.COMPLETED` cell.\n" - ] - } - ], + "outputs": [], "source": [ "import json\n", "\n", @@ -620,61 +506,40 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 4a: Failed status\n", + "#### Step 3a: Failed status\n", "\n", "If the status is `failed` we will print the error message with relevant information to aid in troubleshooting." ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Assistant run failed. Please try again.\n", - "{'id': 'run_MXRH9lBIAQ0sv93TXWdxqh9n', 'object': 'thread.run', 'created_at': 1731935669, 'assistant_id': 'asst_DYdmKFTdWR3HfEFxxVVIuWxu', 'thread_id': 'thread_WBikiRkfRlan1KxlkdM5biNq', 'status': 'failed', 'started_at': 1731935678, 'expires_at': None, 'cancelled_at': None, 'failed_at': 1731935694, 'completed_at': None, 'required_action': None, 'last_error': {'code': 'rate_limit_exceeded', 'message': 'Rate limit is exceeded. Try again in 35 seconds.'}, 'model': 'gpt-4o-mini', 'instructions': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'tools': [{'type': 'code_interpreter'}, {'type': 'function', 'function': {'name': 'fetch_stock_price', 'description': 'Retrieve the latest closing price of a stock using its ticker symbol.', 'parameters': {'type': 'object', 'properties': {'ticker_symbol': {'type': 'string', 'description': 'The ticker symbol of the stock'}}, 'required': ['ticker_symbol']}, 'strict': False}}], 'tool_resources': {}, 'metadata': {}, 'temperature': 1.0, 'top_p': 1.0, 'max_completion_tokens': None, 'max_prompt_tokens': None, 'truncation_strategy': {'type': 'auto', 'last_messages': None}, 'incomplete_details': None, 'usage': {'prompt_tokens': 565, 'completion_tokens': 197, 'total_tokens': 762}, 'response_format': 'auto', 'tool_choice': 'auto', 'parallel_tool_calls': True}\n" - ] - } - ], + "outputs": [], "source": [ "#print(run.model_dump_json(indent=4))\n", "\n", "if run.status == \"failed\":\n", - " print(\"Assistant run failed. Please try again.\")\n", + " print(\"Agent run failed. Please try again.\")\n", " print(run)\n", "else:\n", - " print(f\"Assistant run has not failed...\\nNavigate to and execute the '{run.status}' cell.\")\n" + " print(f\"Agent run has not failed...\\nNavigate to and execute the '{run.status}' cell.\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 4b: Requires Action status\n", + "#### Step 3b: Requires Action status\n", "\n", "If the status is `requires_action`, first we need to check if the required action is to submit tool outputs and iterate over the tool calls, ensuring that the requested function exists in the available_functions dictionary. If the function exists, it is called with the provided arguments, and the response is stored. After processing all tool calls, we submit the tool outputs back to the OpenAI client." ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function Calling ...\n", - "Function 'fetch_stock_price' called successfully. \n", - "Output: 415.0\n", - "\n", - "Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\n" - ] - } - ], + "outputs": [], "source": [ "if run.status == \"requires_action\":\n", " print(\"Function Calling ...\")\n", @@ -707,57 +572,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 4c: Completed status\n", + "#### Step 3c: Completed status\n", "\n", "If the status is `completed`, we will fetch and print all messages in the thread, displaying the role and content of each message.The messages are printed in reverse order because messages in a thread are in FILO (First-In-Last-Out) order and in order to make the messages more conversational for ease of user reading, we must reverse the order." ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Run completed!\n", - "\n", - "MESSAGES\n", - "\n", - "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", - "\n", - "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", - "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", - "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", - "\n", - "### Understanding the Data\n", - "Let's filter the data to only include records for Microsoft (`MSFT`).\n", - "\n", - "#### Data\n", - "- `MSFT`\n", - "- Average Cost: 200\n", - "- Quantity: 300\n", - "\n", - "### Latest Closing Price\n", - "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", - "\n", - "### Total Investment Calculation\n", - "The total investment for MSFT is calculated as follows:\n", - "\n", - "\\[\n", - "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", - "\\]\n", - "\n", - "Let's compute this.\n", - "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", - "\n", - "### Summary:\n", - "- **Latest Closing Price for MSFT:** $415.00\n", - "- **Total Investment in MSFT:** $124,500.00\n" - ] - } - ], + "outputs": [], "source": [ "if run.status == \"completed\":\n", " messages = agents_client.list_messages(thread_id=thread.id, order=\"asc\", after=message.id)\n", @@ -771,8 +595,7 @@ " print(f\"{role.capitalize()}: {content}\")\n", "\n", "else:\n", - " print(f\"Navigate to and execute the {run.status} cell.\")\n", - "\n" + " print(f\"Navigate to and execute the {run.status} cell.\")" ] }, { @@ -798,18 +621,12 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function `process_message` created successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import time\n", "import json\n", + "import matplotlib.pyplot as plt\n", + "from PIL import Image\n", "\n", "available_functions = {\"fetch_stock_price\": fetch_stock_price}\n", "\n", @@ -824,10 +641,10 @@ " )\n", " print(\"User message added...\") #:\", message)\n", "\n", - " # Initiate the assistant's response\n", + " # Initiate the Agent's response\n", " run = agents_client.create_run(\n", " thread_id=thread_id,\n", - " assistant_id=assistant.id,\n", + " assistant_id=agent.id,\n", " instructions=prompt_message,\n", " )\n", " print(\"Run started...\") #:\", run)\n", @@ -855,12 +672,33 @@ " content = None\n", " if isinstance(thread_message.content, list) and thread_message.content:\n", " first_content = thread_message.content[0]\n", - " if hasattr(first_content, 'text') and hasattr(first_content.text, 'value'):\n", + "\n", + " # handle text\n", + " if hasattr(first_content, \"text\") and hasattr(first_content.text, \"value\"):\n", " content = first_content.text.value\n", - " if hasattr(first_content, 'image_file') and hasattr(first_content.text, 'value'):\n", + "\n", + " # handle image file\n", + " elif hasattr(first_content, \"image_file\"):\n", + " \n", " # Download the file locally\n", - " # Use Matplotlib to display the image\n", - " content = first_content.text.value\n", + " file_content = agents_client.get_file_content(first_content.image_file.file_id)\n", + "\n", + " # Delete existing file locally if it has the same name\n", + " if os.path.exists(\"./data/sample_chart.png\"):\n", + " os.remove(\"./data/sample_chart.png\")\n", + " print(\"Deleted existing file: ./data/sample_chart.png\")\n", + " \n", + " with open(\"./data/sample_chart.png\", \"wb\") as f:\n", + " for chunk in file_content: \n", + " f.write(chunk)\n", + " print(\"Image File downloaded to './data' successfully.\")\n", + "\n", + " # Display the image using Pillow and Matplotlib\n", + " img = Image.open(\"./data/sample_chart.png\")\n", + " plt.imshow(img)\n", + " plt.axis('off')\n", + " plt.show()\n", + " \n", " else:\n", " content = str(first_content)\n", " else:\n", @@ -872,7 +710,7 @@ " elif run.status == \"failed\":\n", " messages = agents_client.list_messages(thread_id=thread.id)\n", " answer = messages.data[0].content[0].text.value\n", - " print(f\"Failed User:\\n{prompt_message}\\nAssistant:\\n{answer}\\n\")\n", + " print(f\"Failed User:\\n{prompt_message}\\nAgent:\\n{answer}\\n\")\n", "\n", " # Handle failed\n", " break\n", @@ -882,7 +720,7 @@ " tool_calls = run.required_action.submit_tool_outputs.tool_calls\n", " tool_responses = []\n", " \n", - " # Iterate over each function call requested by the assistant\n", + " # Iterate over each function call requested by the Agent\n", " for call in tool_calls:\n", " # Check if the call is a function and if the function exists is our custom function\n", " if call.type == \"function\" and call.function.name in available_functions:\n", @@ -891,7 +729,7 @@ " # Parse the function arguments from JSON and execute the function\n", " tool_response = func(**json.loads(call.function.arguments))\n", " \n", - " # Store the tool call ID and output to later send back to the assistant\n", + " # Store the tool call ID and output to later send back to the Agent\n", " tool_responses.append({\"tool_call_id\": call.id, \"output\": tool_response})\n", " print(f\"Executed '{call.function.name}'. Output: {tool_response}\")\n", " \n", @@ -899,7 +737,7 @@ " # Raise an error if the function is not in available_functions to handle unexpected requests\n", " raise ValueError(f\"Requested function '{call.function.name}' is not available.\")\n", " \n", - " # Submit all collected tool outputs back to the assistant to satisfy the required action\n", + " # Submit all collected tool outputs back to the Agent to satisfy the required action\n", " run = agents_client.submit_tool_outputs_to_run(\n", " thread_id=thread_id, \n", " run_id=run.id, \n", @@ -918,58 +756,14 @@ "metadata": {}, "source": [ "### Step 2a: Basic Message Sample\n", - "This sample demonstrates how the assistant uses the standard LLM system to answer the query: *\"What is today's date?\"* The assistant responds by retrieving the current date directly from its built-in capabilities, without relying on additional tools or attachments." + "This sample demonstrates how the Agent uses the standard LLM system to answer the query: *\"What is today's date?\"* The Agent responds by retrieving the current date directly from its built-in capabilities, without relying on additional tools or attachments." ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", - "\n", - "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", - "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", - "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", - "\n", - "### Understanding the Data\n", - "Let's filter the data to only include records for Microsoft (`MSFT`).\n", - "\n", - "#### Data\n", - "- `MSFT`\n", - "- Average Cost: 200\n", - "- Quantity: 300\n", - "\n", - "### Latest Closing Price\n", - "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", - "\n", - "### Total Investment Calculation\n", - "The total investment for MSFT is calculated as follows:\n", - "\n", - "\\[\n", - "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", - "\\]\n", - "\n", - "Let's compute this.\n", - "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", - "\n", - "### Summary:\n", - "- **Latest Closing Price for MSFT:** $415.00\n", - "- **Total Investment in MSFT:** $124,500.00\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] @@ -984,86 +778,9 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.IN_PROGRESS\n", - "\n", - "Run Status: RunStatus.REQUIRES_ACTION\n", - "\n", - "Function calling initiated...\n", - "Executed 'fetch_stock_price'. Output: 225.0\n", - "Executed 'fetch_stock_price'. Output: 202.61\n", - "Executed 'fetch_stock_price'. Output: 320.72\n", - "Executed 'fetch_stock_price'. Output: 823.96\n", - "Function call(s) completed successfully.\n", - "Run Status: RunStatus.IN_PROGRESS\n", - "\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", - "\n", - "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", - "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", - "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", - "\n", - "### Understanding the Data\n", - "Let's filter the data to only include records for Microsoft (`MSFT`).\n", - "\n", - "#### Data\n", - "- `MSFT`\n", - "- Average Cost: 200\n", - "- Quantity: 300\n", - "\n", - "### Latest Closing Price\n", - "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", - "\n", - "### Total Investment Calculation\n", - "The total investment for MSFT is calculated as follows:\n", - "\n", - "\\[\n", - "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", - "\\]\n", - "\n", - "Let's compute this.\n", - "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", - "\n", - "### Summary:\n", - "- **Latest Closing Price for MSFT:** $415.00\n", - "- **Total Investment in MSFT:** $124,500.00\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you have invested in the most, we will calculate the total investment for each company listed in your data. We already know the latest closing price for Microsoft (MSFT). We will also need to fetch the latest closing prices for the other companies: Apple (AAPL), Amazon (AMZN), Tesla (TSLA), and Netflix (NFLX).\n", - "\n", - "We will then compute the total investment value for each company and identify the company with the highest investment.\n", - "\n", - "### Your Data\n", - "- Apple (AAPL): 200 shares\n", - "- Amazon (AMZN): 50 shares\n", - "- Tesla (TSLA): 100 shares\n", - "- Netflix (NFLX): 80 shares\n", - "\n", - "### Steps:\n", - "1. Fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\n", - "2. Calculate the total investment for each company.\n", - "3. Identify the company with the highest investment.\n", - "\n", - "Let's start by fetching the latest closing prices for the remaining companies.\n", - "Assistant: It appears that there was an issue with retrieving the closing price for a symbol that is misspelled or not available in the `latest_prices` dictionary. I will correct the data to handle these mismatches. \n", - "\n", - "Let's clean the symbols to match their correct representations and re-compute the total investments.\n", - "Assistant: The company you have invested the most in is **Microsoft (MSFT)** with a total investment of \\$124,500.00.\n" - ] - } - ], + "outputs": [], "source": [ "attachments=[ # Add files by using the attachments parameter\n", " {\"file_id\": portfolio_file_id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", @@ -1077,103 +794,14 @@ "metadata": {}, "source": [ "### Step 2c: Function Calling Sample\n", - "This sample demonstrates how the assistant utilizes the *Function Calling* tool to answer the query: *\"What is the current stock price for Amazon?\"*. The assistant invokes the previously defined `fetch_stock_price` function to retrieve the latest stock price for Amazon, showcasing how the Function Calling tool integrates external data retrieval into the assistant's workflow." + "This sample demonstrates how the Agent utilizes the *Function Calling* tool to answer the query: *\"What is the current stock price for Amazon?\"*. The Agent invokes the previously defined `fetch_stock_price` function to retrieve the latest stock price for Amazon, showcasing how the Function Calling tool integrates external data retrieval into the Agent's workflow." ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.IN_PROGRESS\n", - "\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", - "\n", - "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", - "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", - "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", - "\n", - "### Understanding the Data\n", - "Let's filter the data to only include records for Microsoft (`MSFT`).\n", - "\n", - "#### Data\n", - "- `MSFT`\n", - "- Average Cost: 200\n", - "- Quantity: 300\n", - "\n", - "### Latest Closing Price\n", - "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", - "\n", - "### Total Investment Calculation\n", - "The total investment for MSFT is calculated as follows:\n", - "\n", - "\\[\n", - "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", - "\\]\n", - "\n", - "Let's compute this.\n", - "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", - "\n", - "### Summary:\n", - "- **Latest Closing Price for MSFT:** $415.00\n", - "- **Total Investment in MSFT:** $124,500.00\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you have invested in the most, we will calculate the total investment for each company listed in your data. We already know the latest closing price for Microsoft (MSFT). We will also need to fetch the latest closing prices for the other companies: Apple (AAPL), Amazon (AMZN), Tesla (TSLA), and Netflix (NFLX).\n", - "\n", - "We will then compute the total investment value for each company and identify the company with the highest investment.\n", - "\n", - "### Your Data\n", - "- Apple (AAPL): 200 shares\n", - "- Amazon (AMZN): 50 shares\n", - "- Tesla (TSLA): 100 shares\n", - "- Netflix (NFLX): 80 shares\n", - "\n", - "### Steps:\n", - "1. Fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\n", - "2. Calculate the total investment for each company.\n", - "3. Identify the company with the highest investment.\n", - "\n", - "Let's start by fetching the latest closing prices for the remaining companies.\n", - "Assistant: It appears that there was an issue with retrieving the closing price for a symbol that is misspelled or not available in the `latest_prices` dictionary. I will correct the data to handle these mismatches. \n", - "\n", - "Let's clean the symbols to match their correct representations and re-compute the total investments.\n", - "Assistant: The company you have invested the most in is **Microsoft (MSFT)** with a total investment of \\$124,500.00.\n", - "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", - "Assistant: The latest closing price for Amazon (AMZN) is $202.61.\n", - "\n", - "### Calculation:\n", - "To calculate the total investment value for Amazon, we use the formula:\n", - "\n", - "\\[\n", - "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", - "\\]\n", - "\n", - "From your data, the quantity of AMZN shares you hold is 50.\n", - "\n", - "\\[\n", - "\\text{Total Investment in AMZN} = 202.61 \\times 50\n", - "\\]\n", - "\n", - "Let's perform the calculation.\n", - "Assistant: Your total investment in Amazon (AMZN) as of today is \\$10,130.50.\n", - "\n", - "### Summary:\n", - "- **Latest Closing Price for AMZN:** $202.61\n", - "- **Total Investment in AMZN:** $10,130.50\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\")" ] @@ -1182,105 +810,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2d: Image Response Sample" + "### Step 2d: Generating and Visualizing Data\n", + "This sample shows how the Agent generates visualizations, saves them locally, and integrates with Python libraries like `Pillow` and `Matplotlib` for rendering. For example, when asked *\"Show a pie chart of my investments\"*, the Agent analyzes the `investment_portfolio` file using Code Interpreter and creates a downloadable pie chart image." ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.IN_PROGRESS\n", - "\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: It looks like the file format could not be easily inferred. Let's attempt to read the file again by specifying different potential engines. \n", - "\n", - "We'll try the Pandas `read_excel` function with different engines: 'openpyxl' (for .xlsx files) and 'xlrd' (for .xls files).\n", - "Assistant: It appears that the file might not be an Excel file but instead a CSV file or another text-based format. Let's try to read the file as a CSV.\n", - "Assistant: The file has been successfully read as a CSV. It contains the following columns: `Symbol`, `Average_Cost`, and `QTY`.\n", - "\n", - "### Understanding the Data\n", - "Let's filter the data to only include records for Microsoft (`MSFT`).\n", - "\n", - "#### Data\n", - "- `MSFT`\n", - "- Average Cost: 200\n", - "- Quantity: 300\n", - "\n", - "### Latest Closing Price\n", - "The latest closing price for Microsoft (MSFT) is \\$415.00.\n", - "\n", - "### Total Investment Calculation\n", - "The total investment for MSFT is calculated as follows:\n", - "\n", - "\\[\n", - "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", - "\\]\n", - "\n", - "Let's compute this.\n", - "Assistant: Your total investment in Microsoft (MSFT) as of today is $124,500.00.\n", - "\n", - "### Summary:\n", - "- **Latest Closing Price for MSFT:** $415.00\n", - "- **Total Investment in MSFT:** $124,500.00\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you have invested in the most, we will calculate the total investment for each company listed in your data. We already know the latest closing price for Microsoft (MSFT). We will also need to fetch the latest closing prices for the other companies: Apple (AAPL), Amazon (AMZN), Tesla (TSLA), and Netflix (NFLX).\n", - "\n", - "We will then compute the total investment value for each company and identify the company with the highest investment.\n", - "\n", - "### Your Data\n", - "- Apple (AAPL): 200 shares\n", - "- Amazon (AMZN): 50 shares\n", - "- Tesla (TSLA): 100 shares\n", - "- Netflix (NFLX): 80 shares\n", - "\n", - "### Steps:\n", - "1. Fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\n", - "2. Calculate the total investment for each company.\n", - "3. Identify the company with the highest investment.\n", - "\n", - "Let's start by fetching the latest closing prices for the remaining companies.\n", - "Assistant: It appears that there was an issue with retrieving the closing price for a symbol that is misspelled or not available in the `latest_prices` dictionary. I will correct the data to handle these mismatches. \n", - "\n", - "Let's clean the symbols to match their correct representations and re-compute the total investments.\n", - "Assistant: The company you have invested the most in is **Microsoft (MSFT)** with a total investment of \\$124,500.00.\n", - "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", - "Assistant: The latest closing price for Amazon (AMZN) is $202.61.\n", - "\n", - "### Calculation:\n", - "To calculate the total investment value for Amazon, we use the formula:\n", - "\n", - "\\[\n", - "\\text{Total Investment} = \\text{Latest Closing Price} \\times \\text{Quantity}\n", - "\\]\n", - "\n", - "From your data, the quantity of AMZN shares you hold is 50.\n", - "\n", - "\\[\n", - "\\text{Total Investment in AMZN} = 202.61 \\times 50\n", - "\\]\n", - "\n", - "Let's perform the calculation.\n", - "Assistant: Your total investment in Amazon (AMZN) as of today is \\$10,130.50.\n", - "\n", - "### Summary:\n", - "- **Latest Closing Price for AMZN:** $202.61\n", - "- **Total Investment in AMZN:** $10,130.50\n", - "User: Show a pie chart of my investments?\n", - "Assistant: {'type': 'image_file', 'image_file': {'file_id': 'assistant-pAF34olTVSKkCmp9plgTRHUW'}}\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments?\")" ] @@ -1296,25 +834,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 1: Delete Assistant Resource\n", - "To avoid creating redundant resources and ensure a clean environment, this cell deletes the assistant, thread, and any other created resources.\n" + "### Step 1: Delete Agent Resource\n", + "To avoid creating redundant resources and ensure a clean environment, this cell deletes the Agent, thread, and any other created resources.\n" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'id': 'asst_tXMQBuztYifTQfNE5Lp1VNgW', 'object': 'assistant.deleted', 'deleted': True}\n" - ] - } - ], + "outputs": [], "source": [ - "response = agents_client.delete_agent(assistant.id)\n", + "response = agents_client.delete_agent(agent.id)\n", "print(response)" ] }, @@ -1328,17 +858,9 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Error deleting file 'investment_portfolio.csv': 'str' object has no attribute 'filename'\n" - ] - } - ], + "outputs": [], "source": [ "# delete the file from the Azure OpenAI service\n", "try:\n", @@ -1393,7 +915,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Next Steps: Expanding Generative AI Applications\n", + "## **Next Steps: Expanding Generative AI Applications**\n", "\n", "Building on this scenario, the following Generative AI-focused advancements can be pursued:\n", "\n", @@ -1427,7 +949,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.6" + "version": "3.12.7" } }, "nbformat": 4, diff --git a/samples/investment_advisor/requirements.txt b/samples/investment_advisor/requirements.txt index 8ae07274..7a3c67cf 100644 --- a/samples/investment_advisor/requirements.txt +++ b/samples/investment_advisor/requirements.txt @@ -2,4 +2,6 @@ azure-identity==1.19.0 pandas==2.2.3 yfinance==0.2.48 python-dotenv==1.0.1 +Pillow==11.0.0 +matplotlib==3.9.2 ../../packages/azure_ai_projects-1.0.0b1-py3-none-any.whl \ No newline at end of file From 97a16e72a179a6bbcc0adb808556138c7218b728 Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Mon, 18 Nov 2024 13:53:19 -0500 Subject: [PATCH 154/180] added accessibility to image & cleanup markdown --- .../agent-investment_advisor.ipynb | 642 +++++++++++++++--- 1 file changed, 534 insertions(+), 108 deletions(-) diff --git a/samples/investment_advisor/agent-investment_advisor.ipynb b/samples/investment_advisor/agent-investment_advisor.ipynb index 5e95c633..d679b49c 100644 --- a/samples/investment_advisor/agent-investment_advisor.ipynb +++ b/samples/investment_advisor/agent-investment_advisor.ipynb @@ -4,12 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# **Investment Advisor**\n", - "\n", - "## TODO:\n", - "- Review text, \"Assistant\" should be \"Agent\" everywhere\n", - "- \"Assistant API\" should be \"Agent Runtime\"\n", - "- Review text for typos and quality" + "# **Investment Advisor**" ] }, { @@ -18,15 +13,16 @@ "source": [ "## **About the Scenario**\n", "\n", - "This notebook demonstrates a practical use case where an AI Agent is leveraged to gain actionable insights and address key analytical questions related to managing an investment portfolio. It combines real-time data fetching, computation, and visualization to streamline decision-making.\n", + "This notebook demonstrates a practical use case where an AI Agent is leveraged to gain actionable insights and address key analytical questions related to managing an investment portfolio. It combines data fetching, computation, and visualization to streamline decision-making.\n", "\n", - "The scenario utilizes an AI Agent integrated with two powerful tools: Function Calling and Code Interpreter. These tools work together to retrieve real-time stock prices and calculate portfolio metrics, replicating real-world workflows in investment management.\n", + "The scenario utilizes an AI Agent integrated with two powerful tools: Function Calling and Code Interpreter. These tools work together to retrieve stock prices and calculate portfolio metrics, replicating real-world workflows in investment management.\n", "\n", "### Key Steps:\n", "\n", - "1. *Upload Investment Data*: Import a CSV file containing the user’s investment portfolio into the notebook.\n", - "2. *Fetch Real-Time Stock Prices*: Use the Yahoo! Finance API via *Function Calling* to retrieve up-to-date stock data.\n", - "3. *Perform Portfolio Analysis*: Leverage *Code Interpreter* to compute key portfolio metrics and insights." + "1. *Upload Investment Data*: Import a CSV file containing the user’s investment portfolio into the OpenAI Project.\n", + "2. *Fetch Real-Time Stock Prices*: Use the Yahoo! Finance API via *Function Calling* to retrieve up-to-date closing stock data.\n", + "3. *Perform Portfolio Analysis*: Leverage *Code Interpreter* to compute key portfolio metrics and insights.\n", + "4. *Create Data Visualations*: Leverage *Color Interpreter* to generate portfolio visualization, and leverage Python libraries to render image." ] }, { @@ -62,9 +58,61 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 64, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Processing c:\\developer\\repos\\github\\azure-ai-agents\\packages\\azure_ai_projects-1.0.0b1-py3-none-any.whl (from -r ./requirements.txt (line 7))\n", + "Requirement already satisfied: azure-identity==1.19.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 1)) (1.19.0)\n", + "Requirement already satisfied: pandas==2.2.3 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 2)) (2.2.3)\n", + "Requirement already satisfied: yfinance==0.2.48 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 3)) (0.2.48)\n", + "Requirement already satisfied: python-dotenv==1.0.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", + "Requirement already satisfied: Pillow==11.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 5)) (11.0.0)\n", + "Requirement already satisfied: matplotlib==3.9.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 6)) (3.9.2)\n", + "Requirement already satisfied: azure-core>=1.31.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.32.0)\n", + "Requirement already satisfied: cryptography>=2.5 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (43.0.3)\n", + "Requirement already satisfied: msal>=1.30.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.31.1)\n", + "Requirement already satisfied: msal-extensions>=1.2.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.2.0)\n", + "Requirement already satisfied: typing-extensions>=4.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (4.12.2)\n", + "Requirement already satisfied: numpy>=1.26.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.1.3)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.9.0.post0)\n", + "Requirement already satisfied: pytz>=2020.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", + "Requirement already satisfied: requests>=2.31 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.32.3)\n", + "Requirement already satisfied: multitasking>=0.0.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.0.11)\n", + "Requirement already satisfied: lxml>=4.9.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (5.3.0)\n", + "Requirement already satisfied: platformdirs>=2.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.3.6)\n", + "Requirement already satisfied: frozendict>=2.3.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.4.6)\n", + "Requirement already satisfied: peewee>=3.16.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.17.8)\n", + "Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.12.3)\n", + "Requirement already satisfied: html5lib>=1.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (1.1)\n", + "Requirement already satisfied: contourpy>=1.0.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (1.3.1)\n", + "Requirement already satisfied: cycler>=0.10 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (4.55.0)\n", + "Requirement already satisfied: kiwisolver>=1.3.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (1.4.7)\n", + "Requirement already satisfied: packaging>=20.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (24.2)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (3.2.0)\n", + "Requirement already satisfied: isodate>=0.6.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-ai-projects==1.0.0b1->-r ./requirements.txt (line 7)) (0.7.2)\n", + "Requirement already satisfied: six>=1.11.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-core>=1.31.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.16.0)\n", + "Requirement already satisfied: soupsieve>1.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.6)\n", + "Requirement already satisfied: cffi>=1.12 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.17.1)\n", + "Requirement already satisfied: webencodings in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.5.1)\n", + "Requirement already satisfied: PyJWT<3,>=1.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from PyJWT[crypto]<3,>=1.0.0->msal>=1.30.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.0)\n", + "Requirement already satisfied: portalocker<3,>=1.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from msal-extensions>=1.2.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.1)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.4.0)\n", + "Requirement already satisfied: idna<4,>=2.5 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.10)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.2.3)\n", + "Requirement already satisfied: certifi>=2017.4.17 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2024.8.30)\n", + "Requirement already satisfied: pycparser in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from cffi>=1.12->cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.22)\n", + "Requirement already satisfied: pywin32>=226 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from portalocker<3,>=1.4->msal-extensions>=1.2.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (308)\n", + "azure-ai-projects is already installed with the same version as the provided wheel. Use --force-reinstall to force an installation of the wheel.\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], "source": [ "# Install the packages\n", "%pip install -r ./requirements.txt" @@ -95,9 +143,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 65, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Environment variables loaded successfully.\n" + ] + } + ], "source": [ "import os\n", "from dotenv import load_dotenv\n", @@ -129,14 +185,22 @@ "source": [ "#### Step 1: Initializing the Azure Agent Runtime Client\n", "\n", - "Next, we’ll initialize the Azure Agent Runtime client. This client allows us to interact with Azure Agents. We will use a DefaultAzureCredential to authenticate, meaning you will have to be logged in with the Azure CLI." + "Next, we’ll initialize the Azure Agent Runtime client. This client allows us to interact with Azure OpenAI Project Agents. We will use a `DefaultAzureCredential` to authenticate, meaning you will have to be logged in with the Azure CLI." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 66, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Agent client created successfully.\n" + ] + } + ], "source": [ "import os\n", "from azure.ai.projects import AIProjectClient\n", @@ -159,7 +223,7 @@ "source": [ "#### Step 2: Upload supporting file to Azure OpenAI deployment\n", "\n", - "Now, we'll upload the `investment_portfolio.csv` file from the `\\data` directory to Azure OpenAI, ensuring any existing `investment_portfolio.csv` removed beforehand to ensure the latest version of the file is used and no duplicates exist. This process will handle the entire upload. The file is necessary for this scenario, but its contents can be modified as long as the file structure remains unchanged. The file schema must be as follows:\n", + "Now, we'll upload the `investment_portfolio.csv` file from the `\\data` directory to Azure OpenAI, ensuring any existing `investment_portfolio.csv` is removed beforehand to ensure the latest version of the file is used and no duplicates exist. This process will handle the entire upload. The file is necessary for this scenario, but its contents can be modified as long as the file structure remains unchanged. The file schema must be as followed:\n", "\n", "- Symbol\n", "- Average_Cost\n", @@ -168,9 +232,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 67, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deleted existing file: investment_portfolio.csv\n", + "Uploaded file: investment_portfolio.csv\n" + ] + } + ], "source": [ "# Directory containing files to upload\n", "directory=\"data\"\n", @@ -217,18 +290,28 @@ "metadata": {}, "source": [ "### Step 1: Define function for Agent Function Calling tool\n", - "In this scenario, we will utilize the *Function Calling* tool within the Agent to enhance our insights by invoking a custom function. Since the LLM and Agent currently lack direct access to the internet for user prompts, Function Calling serves as a powerful alternative.\n", + "In this scenario, we will utilize the *Function Calling* tool within the Agent to enhance our insights by invoking a custom function. Since the LLM and Agent currently lack direct access to the internet for user prompts, *Function Calling* serves as a powerful alternative.\n", "\n", "We will use the `fetch_stock_price` function to retrieve stock data for a specified *ticker symbol*. This function leverages the `yfinance` library to fetch the most recent stock price data, specifically for the last trading day.\n", "\n", - "This approach enables the Agent to provide real-time, actionable insights by integrating external data sources through custom functions. Let’s explore how to implement and use this functionality!" + "This approach enables the Agent to provide up-to-date, actionable insights by integrating external data sources through custom functions. \n", + "\n", + "Let’s explore how to implement and use this functionality!" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 68, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function defined successfully.\n" + ] + } + ], "source": [ "import yfinance as yf\n", "\n", @@ -278,7 +361,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 69, "metadata": {}, "outputs": [], "source": [ @@ -290,7 +373,7 @@ "metadata": {}, "source": [ "### Step 2: Configure Agent Tool-Calling for Enhanced Functionality\n", - "The tool-calling definition informs the LLM about the tools available for its use. In our scenario, this configuration enables both *code interpretation* and *function calling*, allowing the Agent to perform complex operations and retrieve external data.\n", + "The tool-calling definition informs the LLM about the tools available for its use. In our scenario, this configuration enables both *code interpretation* and *function calling*.\n", "\n", "We will specifically configure the `fetch_stock_price` function alongside the *code interpreter tool*. By integrating this tool into the Agent, we empower it to:\n", "\n", @@ -304,9 +387,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 70, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tools list defined successfully.\n" + ] + } + ], "source": [ "tools_list = [\n", " {\"type\": \"code_interpreter\"},\n", @@ -332,16 +423,25 @@ "metadata": {}, "source": [ "### Step 3: Creating an Investment Analysis Agent\n", - "In this step, we’ll set up an Azure OpenAI Agent with the specified tools, including a *code interpreter*, to handle investment-related queries. This Agent will also leverage the previously defined function calls to provide accurate and actionable insights. \n", + "In this step, we’ll set up an Azure OpenAI Agent with the specified tools to handle investment-related queries. This Agent will also leverage the previously defined function calls to provide accurate and actionable insights. \n", "\n", "Let’s configure the Agent and enable its capabilities! " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 71, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Agent created successfully.\n", + " asst_DrCppIg6J2qV3pDLx2Ec3VWp\n" + ] + } + ], "source": [ "# Create the Agent with code interpreter and function calling tools enabled\n", "try:\n", @@ -363,14 +463,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Querying the Agent**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 1: Starting a New Conversation Thread\n", + "### Step 4: Starting a New Conversation Thread\n", "Let’s create a new thread to handle user interactions. Each thread provides a dedicated space for conversations with the Agent, keeping the context focused and organized. \n", "\n", "This setup ensures clear and seamless communication for each user interaction." @@ -378,9 +471,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 72, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Thread created successfully: thread_tJFrlqwuXbCT79Axb9E0SEl0\n" + ] + } + ], "source": [ "# Create a conversation thread\n", "try:\n", @@ -394,7 +495,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2: Adding User Message to the Thread\n", + "## **Demonstrating the Thread Run Process (Manual)**\n", + "\n", + "The next six cells will demonstrate how the Agent's thread run process works. Instead of running a typical loop with a polling mechanism to monitor the run status, we’ll manually step through the cells to better understand each stage of the process.\n", + "\n", + "In the subsequent section, these cells will be wrapped into a processing function to expand the functionality by incorporating polling and different completion content type, providing a more streamlined and automated workflow. This approach helps clarify how the thread execution operates while offering a hands-on view of each step." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Step 1: Adding User Message to the Thread\n", "In this step, we’ll add a user message to the thread to demonstrate the Agent’s capabilities. Specifically, we’ll ask for the latest closing price of a specified company (*Microsoft*), which will leverage *function calling* to retrieve this data using the `fetch_stock_price` function.\n", "\n", "The Agent will then use the *code interpreter* to combine this information with the `QTY` data from the uploaded `investment_portfolio.csv` file to calculate the **total investment**. \n", @@ -404,9 +516,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 74, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Successfully added User prompt to the thread.\n", + " msg_OA2BNixqKJ6aqPQGTlS9OoVi\n" + ] + } + ], "source": [ "# Define the user question\n", "prompt_content = \"What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\"\n", @@ -430,26 +551,23 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## **Demonstrating the Thread Run Process (Manual)**\n", - "\n", - "The next five cells will demonstrate how the Agent's thread run process works. Instead of running a typical loop with polling to monitor the run status, we’ll manually step through the cells to better understand each stage of the process.\n", - "\n", - "In the subsequent section, these cells will be wrapped into a processing function that incorporates the polling functionality, providing a more streamlined and automated workflow. This approach helps clarify how the thread execution operates while offering a hands-on view of each step." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Step 1: Running the Agent\n", + "### Step 2: Running the Agent\n", "Now that the Agent and thread are set up, we'll initiate the Agent's response process. This will analyze the user prompt and provide insights based on the investment portfolio data.\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 75, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Run started: run_tqp6osVT8klJzYvvxW4KVkSU\n" + ] + } + ], "source": [ "# Initiate the Agent's response\n", "try:\n", @@ -467,7 +585,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Step 2: Monitor run status" + "### Step 3: Monitor run status" ] }, { @@ -483,9 +601,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 79, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Monitoring the run status...\n", + "Navigate to `RunStatus.COMPLETED` cell.\n" + ] + } + ], "source": [ "import json\n", "\n", @@ -506,16 +633,25 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 3a: Failed status\n", + "#### Step 4a: Failed status\n", "\n", "If the status is `failed` we will print the error message with relevant information to aid in troubleshooting." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 77, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Agent run has not failed...\n", + "Navigate to and execute the 'RunStatus.REQUIRES_ACTION' cell.\n" + ] + } + ], "source": [ "#print(run.model_dump_json(indent=4))\n", "\n", @@ -530,16 +666,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 3b: Requires Action status\n", + "#### Step 4b: Requires Action status\n", "\n", "If the status is `requires_action`, first we need to check if the required action is to submit tool outputs and iterate over the tool calls, ensuring that the requested function exists in the available_functions dictionary. If the function exists, it is called with the provided arguments, and the response is stored. After processing all tool calls, we submit the tool outputs back to the OpenAI client." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 78, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function Calling ...\n", + "Function 'fetch_stock_price' called successfully. \n", + "Output: 415.69\n", + "\n", + "Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\n" + ] + } + ], "source": [ "if run.status == \"requires_action\":\n", " print(\"Function Calling ...\")\n", @@ -572,16 +720,43 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 3c: Completed status\n", + "#### Step 4c: Completed status\n", "\n", "If the status is `completed`, we will fetch and print all messages in the thread, displaying the role and content of each message.The messages are printed in reverse order because messages in a thread are in FILO (First-In-Last-Out) order and in order to make the messages more conversational for ease of user reading, we must reverse the order." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 80, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Run completed!\n", + "\n", + "MESSAGES\n", + "\n", + "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", + "\n", + "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", + "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", + "\n", + "- Symbol: MSFT\n", + "- Average Cost: $200\n", + "- Quantity: 300 shares\n", + "\n", + "To determine your total investment for MSFT as of today:\n", + "\n", + "1. Multiply the quantity of MSFT shares by the latest closing price.\n", + "2. Calculate the total investment value.\n", + "\n", + "Let's calculate that.\n", + "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n" + ] + } + ], "source": [ "if run.status == \"completed\":\n", " messages = agents_client.list_messages(thread_id=thread.id, order=\"asc\", after=message.id)\n", @@ -612,16 +787,24 @@ "### Step 1: Wrapping the Thread Run Process into a Function\n", "In this section we will refine the manual approach and encapsulate the thread run process into a single function. This function automates the steps demonstrated in the previous cells by including the polling functionality to monitor the run status.\n", "\n", - "By wrapping the process into a reusable function, we streamline the workflow and ensure that the thread execution is both efficient and easy to integrate into broader applications. \n", + "By wrapping the process into a reusable function, we streamline the workflow and ensure that the thread execution is both efficient and easy to integrate into broader applications. The function also expands the functionality for handling different completion content types, such as image rendering.\n", "\n", "Let’s implement this functionality!" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 81, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function `process_message` created successfully.\n" + ] + } + ], "source": [ "import time\n", "import json\n", @@ -761,9 +944,39 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 82, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", + "\n", + "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", + "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", + "\n", + "- Symbol: MSFT\n", + "- Average Cost: $200\n", + "- Quantity: 300 shares\n", + "\n", + "To determine your total investment for MSFT as of today:\n", + "\n", + "1. Multiply the quantity of MSFT shares by the latest closing price.\n", + "2. Calculate the total investment value.\n", + "\n", + "Let's calculate that.\n", + "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] @@ -773,14 +986,75 @@ "metadata": {}, "source": [ "### Step 2b: Code Interpreter Sample\n", - "This sample demonstrates using the *Code Interpreter* to analyze an uploaded portfolio file and answer the query: \"What stock do I have the most investment in?\". The Code Interpreter analyzes the file to identify the stock with the highest investment and provides the result, showcasing its ability to integrate data analysis seamlessly into the conversation." + "This sample demonstrates the use of *Code Interpreter* to analyze an uploaded portfolio file and answer the query: \"What stock do I have the most investment in?\". The Code Interpreter analyzes the file to identify the stock with the highest investment and provides the result, showcasing its ability to integrate data analysis seamlessly into the conversation." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 83, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.REQUIRES_ACTION\n", + "\n", + "Function calling initiated...\n", + "Executed 'fetch_stock_price'. Output: 229.075\n", + "Executed 'fetch_stock_price'. Output: 202.0\n", + "Executed 'fetch_stock_price'. Output: 338.36\n", + "Executed 'fetch_stock_price'. Output: 841.705\n", + "Function call(s) completed successfully.\n", + "Run Status: RunStatus.IN_PROGRESS\n", + "\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", + "\n", + "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", + "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", + "\n", + "- Symbol: MSFT\n", + "- Average Cost: $200\n", + "- Quantity: 300 shares\n", + "\n", + "To determine your total investment for MSFT as of today:\n", + "\n", + "1. Multiply the quantity of MSFT shares by the latest closing price.\n", + "2. Calculate the total investment value.\n", + "\n", + "Let's calculate that.\n", + "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you have invested in the most, I will calculate the total value of your investment for each company based on the latest closing prices. For this, I need the latest prices for each of the stocks listed in your file.\n", + "\n", + "Here are the stocks that need their latest prices fetched:\n", + "\n", + "- MSFT (Microsoft)\n", + "- AAPL (Apple)\n", + "- AMZN (Amazon)\n", + "- TSLA (Tesla)\n", + "- NFLX (Netflix)\n", + "\n", + "I will fetch the latest closing prices for these stocks and then compute the total investment for each.\n", + "Assistant: The latest closing prices for the following stocks are:\n", + "\n", + "- Apple (AAPL): $229.075\n", + "- Amazon (AMZN): $202.00\n", + "- Tesla (TSLA): $338.36\n", + "- Netflix (NFLX): $841.705\n", + "\n", + "Let's calculate the total investment for each company and determine which one is the highest.\n", + "Assistant: The company you have invested in the most is Microsoft (MSFT) with a total investment of $124,707.00.\n" + ] + } + ], "source": [ "attachments=[ # Add files by using the attachments parameter\n", " {\"file_id\": portfolio_file_id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", @@ -799,9 +1073,73 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 84, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", + "\n", + "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", + "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", + "\n", + "- Symbol: MSFT\n", + "- Average Cost: $200\n", + "- Quantity: 300 shares\n", + "\n", + "To determine your total investment for MSFT as of today:\n", + "\n", + "1. Multiply the quantity of MSFT shares by the latest closing price.\n", + "2. Calculate the total investment value.\n", + "\n", + "Let's calculate that.\n", + "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you have invested in the most, I will calculate the total value of your investment for each company based on the latest closing prices. For this, I need the latest prices for each of the stocks listed in your file.\n", + "\n", + "Here are the stocks that need their latest prices fetched:\n", + "\n", + "- MSFT (Microsoft)\n", + "- AAPL (Apple)\n", + "- AMZN (Amazon)\n", + "- TSLA (Tesla)\n", + "- NFLX (Netflix)\n", + "\n", + "I will fetch the latest closing prices for these stocks and then compute the total investment for each.\n", + "Assistant: The latest closing prices for the following stocks are:\n", + "\n", + "- Apple (AAPL): $229.075\n", + "- Amazon (AMZN): $202.00\n", + "- Tesla (TSLA): $338.36\n", + "- Netflix (NFLX): $841.705\n", + "\n", + "Let's calculate the total investment for each company and determine which one is the highest.\n", + "Assistant: The company you have invested in the most is Microsoft (MSFT) with a total investment of $124,707.00.\n", + "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", + "Assistant: The current stock price for Amazon (AMZN) is $202.00.\n", + "\n", + "According to the uploaded file, you have the following investment details for Amazon (AMZN):\n", + "\n", + "- Symbol: AMZN\n", + "- Average Cost: $125\n", + "- Quantity: 50 shares\n", + "\n", + "To determine your total investment value for AMZN based on the current price, we will multiply the quantity of AMZN shares by the latest closing price.\n", + "\n", + "Let's calculate that.\n", + "Assistant: Your total investment value for Amazon (AMZN) based on the current price is $10,100.00.\n" + ] + } + ], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\")" ] @@ -811,16 +1149,101 @@ "metadata": {}, "source": [ "### Step 2d: Generating and Visualizing Data\n", - "This sample shows how the Agent generates visualizations, saves them locally, and integrates with Python libraries like `Pillow` and `Matplotlib` for rendering. For example, when asked *\"Show a pie chart of my investments\"*, the Agent analyzes the `investment_portfolio` file using Code Interpreter and creates a downloadable pie chart image." + "This sample shows how an Agent can be used to generate data visualizations, save them locally, and leverage with Python libraries like `Pillow` and `Matplotlib` for rendering. For example, when asked *\"Show a pie chart of my investments\"*, the Agent analyzes the `investment_portfolio` file using Code Interpreter and creates a downloadable pie chart image." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 85, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "User message added...\n", + "Run started...\n", + "Run Status: RunStatus.IN_PROGRESS\n", + "\n", + "Run Status: RunStatus.COMPLETED\n", + "\n", + "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", + "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", + "\n", + "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", + "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", + "\n", + "- Symbol: MSFT\n", + "- Average Cost: $200\n", + "- Quantity: 300 shares\n", + "\n", + "To determine your total investment for MSFT as of today:\n", + "\n", + "1. Multiply the quantity of MSFT shares by the latest closing price.\n", + "2. Calculate the total investment value.\n", + "\n", + "Let's calculate that.\n", + "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", + "User: What is today's date?\n", + "Assistant: Today's date is November 18, 2024.\n", + "User: Which company have I invested in the most?\n", + "Assistant: To determine which company you have invested in the most, I will calculate the total value of your investment for each company based on the latest closing prices. For this, I need the latest prices for each of the stocks listed in your file.\n", + "\n", + "Here are the stocks that need their latest prices fetched:\n", + "\n", + "- MSFT (Microsoft)\n", + "- AAPL (Apple)\n", + "- AMZN (Amazon)\n", + "- TSLA (Tesla)\n", + "- NFLX (Netflix)\n", + "\n", + "I will fetch the latest closing prices for these stocks and then compute the total investment for each.\n", + "Assistant: The latest closing prices for the following stocks are:\n", + "\n", + "- Apple (AAPL): $229.075\n", + "- Amazon (AMZN): $202.00\n", + "- Tesla (TSLA): $338.36\n", + "- Netflix (NFLX): $841.705\n", + "\n", + "Let's calculate the total investment for each company and determine which one is the highest.\n", + "Assistant: The company you have invested in the most is Microsoft (MSFT) with a total investment of $124,707.00.\n", + "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", + "Assistant: The current stock price for Amazon (AMZN) is $202.00.\n", + "\n", + "According to the uploaded file, you have the following investment details for Amazon (AMZN):\n", + "\n", + "- Symbol: AMZN\n", + "- Average Cost: $125\n", + "- Quantity: 50 shares\n", + "\n", + "To determine your total investment value for AMZN based on the current price, we will multiply the quantity of AMZN shares by the latest closing price.\n", + "\n", + "Let's calculate that.\n", + "Assistant: Your total investment value for Amazon (AMZN) based on the current price is $10,100.00.\n", + "User: Show a pie chart of my investments? Ensure the pie chart color schema aligns with accessibility standards.\n", + "Image File downloaded to './data' successfully.\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAFQCAYAAAAiKX2TAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABfBklEQVR4nO3dd5xb1Z3//9e596pO7zOeGffesMFgijEY2zTTcUxIIVlI2U12s99kNwkJ2U2yId9Nvtnklw2bkE3bQAiwlFBMQomxjTFgG2zAGPfu8Xh6n9FIuvee3x/yCA/u0ySNPs/HY8BWufORLOm8dc655yittUYIIYQQactIdAFCCCGESCwJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0KIftNa47ouA70J6oePO1i/Z7CPLUSykzAgUs7Bgwd56qmn6OjoSHQpcaFQiLa2tqRpSGzbprm5Gcdx+nyMUCjE008/zSOPPMIjjzzCE088wapVqzh48CC2bfd6rBs3buQ73/kO4XD4tMeNRCK0tLTguu5pb9vc3My3vvUtdu3aBcCOHTv4l3/5F1paWvr8uAA6Oztpb2/v9RgaGxv5xje+wb59+/p1bCFSkYQBkXJ27tzJ/fffT1tbW6JLiXvmmWf44Q9/iG3biS4FgP379/OlL32JmpqaPh+js7OTX/7yl7z88svs3LmTt99+mz/+8Y988Ytf5Ac/+AGNjY3xxtS2bUKh0BmFoS1btvBP//RPZ9Sga60JhULxUNPW1sa7775LJBLp8+MC+OMf/8jPfvazXvW6rksoFDqjkCLEcGMlugAhBorWGq01juNgWRZKqT4dw7ZtlFKYpnncMVzXxbZtDMPodX1HRwdNTU2nPW7PfZRSuK6L4zi9LjvRYzEMA8MwTvh4eo774dtEo1Hq6upOGE56fi9wRs/TjTfeyJIlS+LHfffdd/n3f/93fvzjH/Od73wHn8/HBRdcwJw5czBN87jaPvx7wuEw9fX1J+21OPbfID8/nx/96Ee9jvvhx9GXf+u2trbjwkhRURE/+clPjvtdJ3uOP3ybnsdzoteNEMlOwoBIee+99x6rV69m3rx5PPPMM9TX1zNp0iQ+/vGPk5+fz549e3jqqae46667yM/PB2If3q+//jqbN2/mzjvvxOv1UlNTw1NPPcW2bdvweDxcfPHFLFmyhEAggNaaLVu28PTTT3PkyBE8Hg/jx4/njjvuYPv27axatYqGhga+973vYZomt9xyC+Xl5fzud7/jiiuuYM2aNezatYuKigo+9alP4boujzzyCPv372fs2LF86lOfoqCgAKUUWmu2bdvGM888Q1VVFdnZ2VxzzTVccsklmKZJa2srv/vd75g/fz7r16/n/fffJz8/n2XLljF9+nQaGxt54IEH6Ojo4L777iMzM5Np06axdOlStm/fzp/+9CcOHz6MZVmMHTuWO+64I/68nIhSCsOIdSL6fD7OP/987rrrLn70ox+xY8cOZs6cydatW1m5ciWf//zn8Xq9VFdX8/jjj7N7924ARowYwe23345pmjz66KM0Nzfz4x//GL/fz4UXXsjChQv5n//5HyZMmEBVVRVvvvkm559/PjfccAO/+93vuOmmmxgzZky8pt27d/OrX/2Kmpoaxo8fz0c/+lFKS0tRSrF69WoOHjzIxz/+cUzTRGvN22+/zbp16/jsZz/L2rVrWb9+PaFQiO9+97uYpsnHPvYxCgoK+O1vf8ttt91GZWUlWmsOHDjAk08+yb59+wgGgyxYsICFCxfi9XpxXZcHHniAyspKWlpaePXVVzFNk6uvvpqFCxeeMMAIkaxkmECkvOrqap544gl+97vfMWvWLK655hrWrl3L/fffj+u65ObmsnbtWtatWxfvFo5GozzyyCN0dnbi8Xiora3lG9/4BgcPHuT6669n/vz5PPXUU/z2t7/FcRzq6+v59re/jWEYLF26lGuvvRalFF1dXeTm5lJQUEAwGGT8+PFMmDCBrKwsurq6eOGFF/jP//xP8vPzufHGG9m1axf33nsv9913H5WVlVx33XVs3LiRX/7yl/HJa2+//Tb33HMPXq+XW2+9lcmTJ/OTn/yElStXorWmu7ubl156iZ/+9Kd4vV5uueUWIpEI//Zv/0ZTUxNer5eKigosy2L06NFMmDCBsrIympub+c53vkM0GmXp0qVcd911WJZFZ2fnWT3fSinOPfdcPB4P27Zti/8brFq1Ctu2iUQi/PCHP2TPnj1cf/313HLLLRQVFdHc3EwgEKCsrAyPx8PYsWOZMGECRUVFOI7Dq6++ys9+9jNqamq46aabmDp1KqFQiBUrVtDY2Bj//R0dHfzqV79iwoQJLFmyhC1btvDd736X9vZ2IDaMtH79+l7d/YcOHeKVV17BcRwKCgrIzc0lMzOTCRMmMGHCBILBIF1dXaxYsYLm5ub4Y/r6179OVVUVN9xwA1OnTuW+++7j0UcfxXVdXNfljTfe4Be/+AW7d+/mhhtuYPTo0fzHf/wHmzdvTpr5I0KcCekZEMPGZz/7WWbMmAHEupD/53/+h46ODvLz87nooot46aWXWLx4MR6Ph/3797Nr1y4+85nPoJRi+fLleDwe7rnnHjIyMoDYt9l7772XpUuX0tjYSCgU4rbbbmPcuHEAXHnllQCUlZUxc+ZMotEot99+Ox6PB4Cqqipc1+Wqq67iox/9KEopgsEgX/va1/jWt77FNddcA8R6Kf77v/+bzs5OAoEADz74IJdccglf+tKX4t9sAR5//HHmz58fv89ll13GnXfeiVKKSZMm8bnPfY6dO3dy0UUXsXDhQpYvX87111/PqFGjgNi36ZaWFm677TYmT54MwOLFi/v0XAeDQQKBwAnH/UOhEIcOHeLv/u7vWLRoEUopFixYgNYawzC47LLLeP3117n55pspKioCoLu7G4Dx48fzj//4j3i9XoATznmIRqMsW7aMa6+9FoDJkyfzhS98gQ0bNrBw4cLT1j5z5kwmTZpEbW0tH/vYx+K9HocPH47fRmvN888/j+u6fOtb36KgoADXdbEsi8cee4wlS5aQk5MDwMiRI/nyl7+Mz+dj3rx5bN68mQ0bNjBr1qwzf0KFSDAJA2JYyMvLY/To0fGx2tLSUqLRKN3d3eTk5LB48WLuueceDhw4wLhx41i1ahXl5eVMmjQJx3HYvHkzzc3N/OQnP4kfs6uri7a2Nmpraxk9ejQjR47kO9/5DhdeeCEzZ85kxowZ5ObmnrIuy7KYOnVqvMEpKCggKyuLiRMnxmstKiqK12rbNrt376arq4v/+3//b/w4dXV1VFVVxRtN0zSZPn16/Lg5OTkEg8FTTqosLS1l4sSJfO9734s/hpkzZ5KXl3fWz7fjONi2HW+0j5WZmckFF1zA/fffz9tvv83MmTOZNWsWJSUlpz3uzJkz42HqZDIzM5k5c2b8+ausrGTEiBFs3779jMLAmXBdl+3btzN16tT4EIphGMyZM4ff//73VFdXx8PA1KlT48+Dx+OhqKio32c7CDHUJAyIYaFnclePnoai51v1lClTKC0tZfXq1RQXF7N69Wquv/56/H4/juMQiUQoKChgwoQJvSZ/nXvuuZSWlpKdnc0PfvAD1q1bx9tvv80vfvELPB4P3/3udxk7duwp6zp27LhnouDJarVtG9d1GTFiBBMnTozfZuLEiSxcuBCfz0d3dzdKKSyr99u3Z77ByWRkZHDvvfeyfv16Nm3axK9+9SsAvv3tbzNp0qSTP7kforWmqqqKzs7OeK/DsUzT5P/8n//Dxo0beeutt3j88cf57//+b77yla9w6aWXnvS4Sil8Pt9pJ999+Dnt+fuxkyU//Dyc7RkCPRMCPxxMep7zYyc/fvg2hmHIEIFIORIGRFoIBAIsXLiQF198kZEjR9La2sqll14ab5jHjBlDdXU1S5cujX/L+/AHem5uLldffTVXX301DQ0N/P3f/z1r1qxh7NixGIYxIAvWZGVlUVRURFlZWXxo4US1nE5P2Pjw/bKzs1m8eDGLFy+mubmZL33pS7z88su9eipORWtNV1cXjz32GEVFRcycOfOEt/P7/VxyySVccsklhEIhvve97/Hss88yb968eGjp63PV2dnJwYMHKSsrQylFc3MzdXV18WGXYDBIZ2dnr8b84MGDvY5xun8v0zSprKxky5YtdHd3xyeR7tmzB9M048MbQgwXEgZEWlBKMX/+fB5++GF+/etfc8455zBixIj4dTfccAN33303v/3tb7n66qvx+/3U1dWxY8cOrrvuOg4fPsyWLVuYMWMGmZmZ7Nmzh87OTgoLC4HYvIGqqipee+01CgsLqays7FOdfr+fpUuX8qtf/YqSkhLmzJmDUoqDBw/S2NgYP8XvdHJzczFNk1WrVnHeeeeRm5uL4zhs2rSJGTNmkJ2dzYEDB2hvbz9tw3bo0CE2b95MNBqlurqal156iX379vHVr36VgoKC427f0tLCiy++yIwZMygoKKCpqYmamhomT56MUorCwkLC4TCrV69m8uTJFBYWnvJshg/rmcWfmZlJZmYmDz/8MKZpctFFF6GUYsqUKTzwwAP89a9/5bzzzmPLli2sXr2615BGeXk5r776Km+88QY5OTmMHj36uN9z5ZVX8tJLL/GHP/yBa665htraWn7/+99z6aWXntGQhxCpRMKASDnBYJDKysp4l21GRgbl5eW9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", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Assistant: None\n" + ] + } + ], "source": [ - "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments?\")" + "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments? Ensure the pie chart color schema aligns with accessibility standards.\")" ] }, { @@ -840,12 +1263,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 101, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Agent does not exist to delete.\n" + ] + } + ], "source": [ - "response = agents_client.delete_agent(agent.id)\n", - "print(response)" + "# Get agent list\n", + "agents = agents_client.list_agents()\n", + "\n", + "# If the agent exists in the list, delete it\n", + "if agent.id in [a.id for a in agents.data]:\n", + " response = agents_client.delete_agent(agent.id)\n", + " print(\"Deleted Agent Client\\n\",response)\n", + "else:\n", + " print(\"Agent does not exist to delete.\")" ] }, { @@ -858,32 +1296,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 105, "metadata": {}, "outputs": [], "source": [ - "# delete the file from the Azure OpenAI service\n", "try:\n", - " # List all files\n", - " files = agents_client.list_files()\n", - "\n", - " # Find the file with the specified name and purpose\n", - " file_id = None\n", - " for f in files:\n", + " # Delete existing file on Azure if it has the same name and purpose\n", + " existing_files = agents_client.list_files()\n", + " for f in existing_files.data:\n", " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", - " file_id = f.id\n", - " break\n", - "\n", - " # Delete the file if found\n", - " if file_id:\n", - " agents_client.delete_file(file_id)\n", - " print(f\"Deleted file: {portfolio_file}\")\n", - "\n", - "except Exception as e:\n", - " print(f\"Error deleting file '{portfolio_file}': {e}\")\n", + " agents_client.delete_file(f.id)\n", + " print(f\"Deleted existing file: {portfolio_file}\")\n", "\n", "except Exception as e:\n", - " print(f\"Unexpected error deleting file '{portfolio_file}': {e}\")" + " print(f\"Error processing file '{portfolio_file}': {e}\")" ] }, { From 8e99cbd1743b3547b18be71cfea0a08186a42d26 Mon Sep 17 00:00:00 2001 From: Jess M Johnson Date: Mon, 18 Nov 2024 14:14:57 -0500 Subject: [PATCH 155/180] todo: formatting inconsistancies in response outputs --- .../agent-investment_advisor.ipynb | 352 ++++++------------ .../investment_advisor/data/sample_chart.png | Bin 0 -> 76467 bytes 2 files changed, 111 insertions(+), 241 deletions(-) create mode 100644 samples/investment_advisor/data/sample_chart.png diff --git a/samples/investment_advisor/agent-investment_advisor.ipynb b/samples/investment_advisor/agent-investment_advisor.ipynb index d679b49c..caecd9dc 100644 --- a/samples/investment_advisor/agent-investment_advisor.ipynb +++ b/samples/investment_advisor/agent-investment_advisor.ipynb @@ -143,7 +143,7 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 109, "metadata": {}, "outputs": [ { @@ -190,7 +190,7 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 110, "metadata": {}, "outputs": [ { @@ -232,14 +232,13 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 111, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Deleted existing file: investment_portfolio.csv\n", "Uploaded file: investment_portfolio.csv\n" ] } @@ -301,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 112, "metadata": {}, "outputs": [ { @@ -361,7 +360,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 113, "metadata": {}, "outputs": [], "source": [ @@ -387,7 +386,7 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": 114, "metadata": {}, "outputs": [ { @@ -430,7 +429,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": 115, "metadata": {}, "outputs": [ { @@ -438,7 +437,7 @@ "output_type": "stream", "text": [ "Agent created successfully.\n", - " asst_DrCppIg6J2qV3pDLx2Ec3VWp\n" + " asst_HDXCOrEVyVBvnC1TtauXadCJ\n" ] } ], @@ -471,14 +470,14 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 116, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Thread created successfully: thread_tJFrlqwuXbCT79Axb9E0SEl0\n" + "Thread created successfully: thread_8dFPBiLlCDzjqS4iIeGoGIoQ\n" ] } ], @@ -516,7 +515,7 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": 117, "metadata": {}, "outputs": [ { @@ -524,7 +523,7 @@ "output_type": "stream", "text": [ "Successfully added User prompt to the thread.\n", - " msg_OA2BNixqKJ6aqPQGTlS9OoVi\n" + " msg_4nH05SlmZmSqfp4nt8s2Udzo\n" ] } ], @@ -557,14 +556,14 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 118, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Run started: run_tqp6osVT8klJzYvvxW4KVkSU\n" + "Run started: run_XxGGa5z2bRLQhjD9jIQerJEz\n" ] } ], @@ -601,7 +600,7 @@ }, { "cell_type": "code", - "execution_count": 79, + "execution_count": 122, "metadata": {}, "outputs": [ { @@ -640,7 +639,7 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": 120, "metadata": {}, "outputs": [ { @@ -673,7 +672,7 @@ }, { "cell_type": "code", - "execution_count": 78, + "execution_count": 121, "metadata": {}, "outputs": [ { @@ -682,7 +681,7 @@ "text": [ "Function Calling ...\n", "Function 'fetch_stock_price' called successfully. \n", - "Output: 415.69\n", + "Output: 415.88\n", "\n", "Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\n" ] @@ -727,7 +726,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": 123, "metadata": {}, "outputs": [ { @@ -738,22 +737,16 @@ "\n", "MESSAGES\n", "\n", - "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", + "Assistant: The latest closing price for Microsoft (MSFT) is $415.88.\n", "\n", - "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", - "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", + "I will now open the uploaded file to check your MSFT investment details and calculate the total investment.\n", + "Assistant: Based on the data provided, your MSFT investment details are as follows:\n", "\n", - "- Symbol: MSFT\n", - "- Average Cost: $200\n", + "- Average Cost: $200 per share\n", "- Quantity: 300 shares\n", "\n", - "To determine your total investment for MSFT as of today:\n", - "\n", - "1. Multiply the quantity of MSFT shares by the latest closing price.\n", - "2. Calculate the total investment value.\n", - "\n", - "Let's calculate that.\n", - "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n" + "I will now calculate your total investment in MSFT as of today's price.\n", + "Assistant: Your total investment in Microsoft (MSFT) as of today is valued at $124,764.\n" ] } ], @@ -794,7 +787,7 @@ }, { "cell_type": "code", - "execution_count": 81, + "execution_count": 124, "metadata": {}, "outputs": [ { @@ -854,40 +847,41 @@ " role = thread_message.role\n", " content = None\n", " if isinstance(thread_message.content, list) and thread_message.content:\n", - " first_content = thread_message.content[0]\n", "\n", - " # handle text\n", - " if hasattr(first_content, \"text\") and hasattr(first_content.text, \"value\"):\n", - " content = first_content.text.value\n", - "\n", - " # handle image file\n", - " elif hasattr(first_content, \"image_file\"):\n", - " \n", - " # Download the file locally\n", - " file_content = agents_client.get_file_content(first_content.image_file.file_id)\n", + " for message_content in thread_message.content:\n", + " \n", + " # handle text\n", + " if hasattr(message_content, \"text\") and hasattr(message_content.text, \"value\"):\n", + " content = message_content.text.value\n", "\n", - " # Delete existing file locally if it has the same name\n", - " if os.path.exists(\"./data/sample_chart.png\"):\n", - " os.remove(\"./data/sample_chart.png\")\n", - " print(\"Deleted existing file: ./data/sample_chart.png\")\n", + " # handle image file\n", + " elif hasattr(message_content, \"image_file\"):\n", " \n", - " with open(\"./data/sample_chart.png\", \"wb\") as f:\n", - " for chunk in file_content: \n", - " f.write(chunk)\n", - " print(\"Image File downloaded to './data' successfully.\")\n", - "\n", - " # Display the image using Pillow and Matplotlib\n", - " img = Image.open(\"./data/sample_chart.png\")\n", - " plt.imshow(img)\n", - " plt.axis('off')\n", - " plt.show()\n", - " \n", + " # Download the file locally\n", + " file_content = agents_client.get_file_content(message_content.image_file.file_id)\n", + "\n", + " # Delete existing file locally if it has the same name\n", + " if os.path.exists(\"./data/sample_chart.png\"):\n", + " os.remove(\"./data/sample_chart.png\")\n", + " print(\"Deleted existing file: ./data/sample_chart.png\")\n", + " \n", + " with open(\"./data/sample_chart.png\", \"wb\") as f:\n", + " for chunk in file_content: \n", + " f.write(chunk)\n", + " print(\"Image File downloaded to './data' successfully.\")\n", + "\n", + " # Display the image using Pillow and Matplotlib\n", + " img = Image.open(\"./data/sample_chart.png\")\n", + " plt.imshow(img)\n", + " plt.axis('off')\n", + " plt.show()\n", + " \n", + " else:\n", + " content = str(message_content)\n", " else:\n", - " content = str(first_content)\n", - " else:\n", - " content = str(thread_message.content)\n", + " content = str(thread_message.content)\n", "\n", - " print(f\"{role.capitalize()}: {content}\")\n", + " print(f\"{role.capitalize()}: {content}\")\n", " \n", " break\n", " elif run.status == \"failed\":\n", @@ -944,7 +938,7 @@ }, { "cell_type": "code", - "execution_count": 82, + "execution_count": 125, "metadata": {}, "outputs": [ { @@ -955,25 +949,12 @@ "Run started...\n", "Run Status: RunStatus.COMPLETED\n", "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", - "\n", - "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", - "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", - "\n", - "- Symbol: MSFT\n", - "- Average Cost: $200\n", - "- Quantity: 300 shares\n", - "\n", - "To determine your total investment for MSFT as of today:\n", - "\n", - "1. Multiply the quantity of MSFT shares by the latest closing price.\n", - "2. Calculate the total investment value.\n", - "\n", - "Let's calculate that.\n", - "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n" + "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n" ] } ], @@ -991,7 +972,7 @@ }, { "cell_type": "code", - "execution_count": 83, + "execution_count": 126, "metadata": {}, "outputs": [ { @@ -1003,55 +984,23 @@ "Run Status: RunStatus.REQUIRES_ACTION\n", "\n", "Function calling initiated...\n", - "Executed 'fetch_stock_price'. Output: 229.075\n", - "Executed 'fetch_stock_price'. Output: 202.0\n", - "Executed 'fetch_stock_price'. Output: 338.36\n", - "Executed 'fetch_stock_price'. Output: 841.705\n", + "Executed 'fetch_stock_price'. Output: 229.105\n", + "Executed 'fetch_stock_price'. Output: 201.695\n", + "Executed 'fetch_stock_price'. Output: 333.06\n", + "Executed 'fetch_stock_price'. Output: 843.52\n", "Function call(s) completed successfully.\n", - "Run Status: RunStatus.IN_PROGRESS\n", - "\n", "Run Status: RunStatus.COMPLETED\n", "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", - "\n", - "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", - "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", - "\n", - "- Symbol: MSFT\n", - "- Average Cost: $200\n", - "- Quantity: 300 shares\n", - "\n", - "To determine your total investment for MSFT as of today:\n", - "\n", - "1. Multiply the quantity of MSFT shares by the latest closing price.\n", - "2. Calculate the total investment value.\n", - "\n", - "Let's calculate that.\n", - "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you have invested in the most, I will calculate the total value of your investment for each company based on the latest closing prices. For this, I need the latest prices for each of the stocks listed in your file.\n", - "\n", - "Here are the stocks that need their latest prices fetched:\n", - "\n", - "- MSFT (Microsoft)\n", - "- AAPL (Apple)\n", - "- AMZN (Amazon)\n", - "- TSLA (Tesla)\n", - "- NFLX (Netflix)\n", - "\n", - "I will fetch the latest closing prices for these stocks and then compute the total investment for each.\n", - "Assistant: The latest closing prices for the following stocks are:\n", - "\n", - "- Apple (AAPL): $229.075\n", - "- Amazon (AMZN): $202.00\n", - "- Tesla (TSLA): $338.36\n", - "- Netflix (NFLX): $841.705\n", - "\n", - "Let's calculate the total investment for each company and determine which one is the highest.\n", - "Assistant: The company you have invested in the most is Microsoft (MSFT) with a total investment of $124,707.00.\n" + "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': 'Which company have I invested in the most?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Let's determine which company you have invested in the most by calculating the total value of your investments for each company and identifying the one with the highest value.\\n\\nTo do this, we will use the latest closing prices and your investment data. Here is the list again:\\n- MSFT (Microsoft): $415.88\\n- AAPL (Apple): $ \\n- AMZN (Amazon): $ \\n- TSLA (Tesla): $ \\n- NFLX (Netflix): $\\n\\nLet's fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Here are the latest closing prices for the stocks in your portfolio:\\n- AAPL (Apple): $229.11\\n- AMZN (Amazon): $201.70\\n- TSLA (Tesla): $333.06\\n- NFLX (Netflix): $843.52\\n- MSFT (Microsoft): $415.88\\n\\nI will now calculate the total investments for each company and determine which one you have invested in the most.', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'You have invested the most in Microsoft (MSFT), with a total investment value of $124,764.', 'annotations': []}}]\n" ] } ], @@ -1073,7 +1022,7 @@ }, { "cell_type": "code", - "execution_count": 84, + "execution_count": 127, "metadata": {}, "outputs": [ { @@ -1084,59 +1033,19 @@ "Run started...\n", "Run Status: RunStatus.COMPLETED\n", "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", - "\n", - "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", - "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", - "\n", - "- Symbol: MSFT\n", - "- Average Cost: $200\n", - "- Quantity: 300 shares\n", - "\n", - "To determine your total investment for MSFT as of today:\n", - "\n", - "1. Multiply the quantity of MSFT shares by the latest closing price.\n", - "2. Calculate the total investment value.\n", - "\n", - "Let's calculate that.\n", - "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you have invested in the most, I will calculate the total value of your investment for each company based on the latest closing prices. For this, I need the latest prices for each of the stocks listed in your file.\n", - "\n", - "Here are the stocks that need their latest prices fetched:\n", - "\n", - "- MSFT (Microsoft)\n", - "- AAPL (Apple)\n", - "- AMZN (Amazon)\n", - "- TSLA (Tesla)\n", - "- NFLX (Netflix)\n", - "\n", - "I will fetch the latest closing prices for these stocks and then compute the total investment for each.\n", - "Assistant: The latest closing prices for the following stocks are:\n", - "\n", - "- Apple (AAPL): $229.075\n", - "- Amazon (AMZN): $202.00\n", - "- Tesla (TSLA): $338.36\n", - "- Netflix (NFLX): $841.705\n", - "\n", - "Let's calculate the total investment for each company and determine which one is the highest.\n", - "Assistant: The company you have invested in the most is Microsoft (MSFT) with a total investment of $124,707.00.\n", - "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", - "Assistant: The current stock price for Amazon (AMZN) is $202.00.\n", - "\n", - "According to the uploaded file, you have the following investment details for Amazon (AMZN):\n", - "\n", - "- Symbol: AMZN\n", - "- Average Cost: $125\n", - "- Quantity: 50 shares\n", - "\n", - "To determine your total investment value for AMZN based on the current price, we will multiply the quantity of AMZN shares by the latest closing price.\n", - "\n", - "Let's calculate that.\n", - "Assistant: Your total investment value for Amazon (AMZN) based on the current price is $10,100.00.\n" + "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': 'Which company have I invested in the most?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Let's determine which company you have invested in the most by calculating the total value of your investments for each company and identifying the one with the highest value.\\n\\nTo do this, we will use the latest closing prices and your investment data. Here is the list again:\\n- MSFT (Microsoft): $415.88\\n- AAPL (Apple): $ \\n- AMZN (Amazon): $ \\n- TSLA (Tesla): $ \\n- NFLX (Netflix): $\\n\\nLet's fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Here are the latest closing prices for the stocks in your portfolio:\\n- AAPL (Apple): $229.11\\n- AMZN (Amazon): $201.70\\n- TSLA (Tesla): $333.06\\n- NFLX (Netflix): $843.52\\n- MSFT (Microsoft): $415.88\\n\\nI will now calculate the total investments for each company and determine which one you have invested in the most.', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'You have invested the most in Microsoft (MSFT), with a total investment value of $124,764.', 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': 'What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"The current stock price for Amazon (AMZN) is $201.70.\\n\\nBased on this price, let's calculate the total investment value for AMZN. \\n\\nAccording to your provided investment details:\\n- AMZN average cost: $125 per share\\n- Quantity: 50 shares\\n\\nWe will use this information to calculate the total investment value.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Based on the current stock price, your total investment value for Amazon (AMZN) is $10,085.', 'annotations': []}}]\n" ] } ], @@ -1154,7 +1063,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 128, "metadata": {}, "outputs": [ { @@ -1167,66 +1076,26 @@ "\n", "Run Status: RunStatus.COMPLETED\n", "\n", - "User: What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\n", - "Assistant: The latest closing price for Microsoft (MSFT) is $415.69.\n", - "\n", - "Next, I'll check the uploaded file to determine your total investment in MSFT as of today. Let's take a look at the contents of the file first.\n", - "Assistant: According to the uploaded file, you have the following investment details for Microsoft (MSFT):\n", - "\n", - "- Symbol: MSFT\n", - "- Average Cost: $200\n", - "- Quantity: 300 shares\n", - "\n", - "To determine your total investment for MSFT as of today:\n", - "\n", - "1. Multiply the quantity of MSFT shares by the latest closing price.\n", - "2. Calculate the total investment value.\n", - "\n", - "Let's calculate that.\n", - "Assistant: Your total investment for Microsoft (MSFT) as of today is $124,707.00.\n", - "User: What is today's date?\n", - "Assistant: Today's date is November 18, 2024.\n", - "User: Which company have I invested in the most?\n", - "Assistant: To determine which company you have invested in the most, I will calculate the total value of your investment for each company based on the latest closing prices. For this, I need the latest prices for each of the stocks listed in your file.\n", - "\n", - "Here are the stocks that need their latest prices fetched:\n", - "\n", - "- MSFT (Microsoft)\n", - "- AAPL (Apple)\n", - "- AMZN (Amazon)\n", - "- TSLA (Tesla)\n", - "- NFLX (Netflix)\n", - "\n", - "I will fetch the latest closing prices for these stocks and then compute the total investment for each.\n", - "Assistant: The latest closing prices for the following stocks are:\n", - "\n", - "- Apple (AAPL): $229.075\n", - "- Amazon (AMZN): $202.00\n", - "- Tesla (TSLA): $338.36\n", - "- Netflix (NFLX): $841.705\n", - "\n", - "Let's calculate the total investment for each company and determine which one is the highest.\n", - "Assistant: The company you have invested in the most is Microsoft (MSFT) with a total investment of $124,707.00.\n", - "User: What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\n", - "Assistant: The current stock price for Amazon (AMZN) is $202.00.\n", - "\n", - "According to the uploaded file, you have the following investment details for Amazon (AMZN):\n", - "\n", - "- Symbol: AMZN\n", - "- Average Cost: $125\n", - "- Quantity: 50 shares\n", - "\n", - "To determine your total investment value for AMZN based on the current price, we will multiply the quantity of AMZN shares by the latest closing price.\n", - "\n", - "Let's calculate that.\n", - "Assistant: Your total investment value for Amazon (AMZN) based on the current price is $10,100.00.\n", - "User: Show a pie chart of my investments? Ensure the pie chart color schema aligns with accessibility standards.\n", + "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': 'Which company have I invested in the most?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"Let's determine which company you have invested in the most by calculating the total value of your investments for each company and identifying the one with the highest value.\\n\\nTo do this, we will use the latest closing prices and your investment data. Here is the list again:\\n- MSFT (Microsoft): $415.88\\n- AAPL (Apple): $ \\n- AMZN (Amazon): $ \\n- TSLA (Tesla): $ \\n- NFLX (Netflix): $\\n\\nLet's fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Here are the latest closing prices for the stocks in your portfolio:\\n- AAPL (Apple): $229.11\\n- AMZN (Amazon): $201.70\\n- TSLA (Tesla): $333.06\\n- NFLX (Netflix): $843.52\\n- MSFT (Microsoft): $415.88\\n\\nI will now calculate the total investments for each company and determine which one you have invested in the most.', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'You have invested the most in Microsoft (MSFT), with a total investment value of $124,764.', 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': 'What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?', 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': \"The current stock price for Amazon (AMZN) is $201.70.\\n\\nBased on this price, let's calculate the total investment value for AMZN. \\n\\nAccording to your provided investment details:\\n- AMZN average cost: $125 per share\\n- Quantity: 50 shares\\n\\nWe will use this information to calculate the total investment value.\", 'annotations': []}}]\n", + "Assistant: [{'type': 'text', 'text': {'value': 'Based on the current stock price, your total investment value for Amazon (AMZN) is $10,085.', 'annotations': []}}]\n", + "User: [{'type': 'text', 'text': {'value': 'Show a pie chart of my investments? Ensure the pie chart color schema aligns with accessibility standards.', 'annotations': []}}]\n", "Image File downloaded to './data' successfully.\n" ] }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAFQCAYAAAAiKX2TAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABfBklEQVR4nO3dd5xb1Z3//9e596pO7zOeGffesMFgijEY2zTTcUxIIVlI2U12s99kNwkJ2U2yId9Nvtnklw2bkE3bQAiwlFBMQomxjTFgG2zAGPfu8Xh6n9FIuvee3x/yCA/u0ySNPs/HY8BWufORLOm8dc655yittUYIIYQQactIdAFCCCGESCwJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0IIIUSakzAghBBCpDkJA0KIftNa47ouA70J6oePO1i/Z7CPLUSykzAgUs7Bgwd56qmn6OjoSHQpcaFQiLa2tqRpSGzbprm5Gcdx+nyMUCjE008/zSOPPMIjjzzCE088wapVqzh48CC2bfd6rBs3buQ73/kO4XD4tMeNRCK0tLTguu5pb9vc3My3vvUtdu3aBcCOHTv4l3/5F1paWvr8uAA6Oztpb2/v9RgaGxv5xje+wb59+/p1bCFSkYQBkXJ27tzJ/fffT1tbW6JLiXvmmWf44Q9/iG3biS4FgP379/OlL32JmpqaPh+js7OTX/7yl7z88svs3LmTt99+mz/+8Y988Ytf5Ac/+AGNjY3xxtS2bUKh0BmFoS1btvBP//RPZ9Sga60JhULxUNPW1sa7775LJBLp8+MC+OMf/8jPfvazXvW6rksoFDqjkCLEcGMlugAhBorWGq01juNgWRZKqT4dw7ZtlFKYpnncMVzXxbZtDMPodX1HRwdNTU2nPW7PfZRSuK6L4zi9LjvRYzEMA8MwTvh4eo774dtEo1Hq6upOGE56fi9wRs/TjTfeyJIlS+LHfffdd/n3f/93fvzjH/Od73wHn8/HBRdcwJw5czBN87jaPvx7wuEw9fX1J+21OPbfID8/nx/96Ee9jvvhx9GXf+u2trbjwkhRURE/+clPjvtdJ3uOP3ybnsdzoteNEMlOwoBIee+99x6rV69m3rx5PPPMM9TX1zNp0iQ+/vGPk5+fz549e3jqqae46667yM/PB2If3q+//jqbN2/mzjvvxOv1UlNTw1NPPcW2bdvweDxcfPHFLFmyhEAggNaaLVu28PTTT3PkyBE8Hg/jx4/njjvuYPv27axatYqGhga+973vYZomt9xyC+Xl5fzud7/jiiuuYM2aNezatYuKigo+9alP4boujzzyCPv372fs2LF86lOfoqCgAKUUWmu2bdvGM888Q1VVFdnZ2VxzzTVccsklmKZJa2srv/vd75g/fz7r16/n/fffJz8/n2XLljF9+nQaGxt54IEH6Ojo4L777iMzM5Np06axdOlStm/fzp/+9CcOHz6MZVmMHTuWO+64I/68nIhSCsOIdSL6fD7OP/987rrrLn70ox+xY8cOZs6cydatW1m5ciWf//zn8Xq9VFdX8/jjj7N7924ARowYwe23345pmjz66KM0Nzfz4x//GL/fz4UXXsjChQv5n//5HyZMmEBVVRVvvvkm559/PjfccAO/+93vuOmmmxgzZky8pt27d/OrX/2Kmpoaxo8fz0c/+lFKS0tRSrF69WoOHjzIxz/+cUzTRGvN22+/zbp16/jsZz/L2rVrWb9+PaFQiO9+97uYpsnHPvYxCgoK+O1vf8ttt91GZWUlWmsOHDjAk08+yb59+wgGgyxYsICFCxfi9XpxXZcHHniAyspKWlpaePXVVzFNk6uvvpqFCxeeMMAIkaxkmECkvOrqap544gl+97vfMWvWLK655hrWrl3L/fffj+u65ObmsnbtWtatWxfvFo5GozzyyCN0dnbi8Xiora3lG9/4BgcPHuT6669n/vz5PPXUU/z2t7/FcRzq6+v59re/jWEYLF26lGuvvRalFF1dXeTm5lJQUEAwGGT8+PFMmDCBrKwsurq6eOGFF/jP//xP8vPzufHGG9m1axf33nsv9913H5WVlVx33XVs3LiRX/7yl/HJa2+//Tb33HMPXq+XW2+9lcmTJ/OTn/yElStXorWmu7ubl156iZ/+9Kd4vV5uueUWIpEI//Zv/0ZTUxNer5eKigosy2L06NFMmDCBsrIympub+c53vkM0GmXp0qVcd911WJZFZ2fnWT3fSinOPfdcPB4P27Zti/8brFq1Ctu2iUQi/PCHP2TPnj1cf/313HLLLRQVFdHc3EwgEKCsrAyPx8PYsWOZMGECRUVFOI7Dq6++ys9+9jNqamq46aabmDp1KqFQiBUrVtDY2Bj//R0dHfzqV79iwoQJLFmyhC1btvDd736X9vZ2IDaMtH79+l7d/YcOHeKVV17BcRwKCgrIzc0lMzOTCRMmMGHCBILBIF1dXaxYsYLm5ub4Y/r6179OVVUVN9xwA1OnTuW+++7j0UcfxXVdXNfljTfe4Be/+AW7d+/mhhtuYPTo0fzHf/wHmzdvTpr5I0KcCekZEMPGZz/7WWbMmAHEupD/53/+h46ODvLz87nooot46aWXWLx4MR6Ph/3797Nr1y4+85nPoJRi+fLleDwe7rnnHjIyMoDYt9l7772XpUuX0tjYSCgU4rbbbmPcuHEAXHnllQCUlZUxc+ZMotEot99+Ox6PB4Cqqipc1+Wqq67iox/9KEopgsEgX/va1/jWt77FNddcA8R6Kf77v/+bzs5OAoEADz74IJdccglf+tKX4t9sAR5//HHmz58fv89ll13GnXfeiVKKSZMm8bnPfY6dO3dy0UUXsXDhQpYvX87111/PqFGjgNi36ZaWFm677TYmT54MwOLFi/v0XAeDQQKBwAnH/UOhEIcOHeLv/u7vWLRoEUopFixYgNYawzC47LLLeP3117n55pspKioCoLu7G4Dx48fzj//4j3i9XoATznmIRqMsW7aMa6+9FoDJkyfzhS98gQ0bNrBw4cLT1j5z5kwmTZpEbW0tH/vYx+K9HocPH47fRmvN888/j+u6fOtb36KgoADXdbEsi8cee4wlS5aQk5MDwMiRI/nyl7+Mz+dj3rx5bN68mQ0bNjBr1qwzf0KFSDAJA2JYyMvLY/To0fGx2tLSUqLRKN3d3eTk5LB48WLuueceDhw4wLhx41i1ahXl5eVMmjQJx3HYvHkzzc3N/OQnP4kfs6uri7a2Nmpraxk9ejQjR47kO9/5DhdeeCEzZ85kxowZ5ObmnrIuy7KYOnVqvMEpKCggKyuLiRMnxmstKiqK12rbNrt376arq4v/+3//b/w4dXV1VFVVxRtN0zSZPn16/Lg5OTkEg8FTTqosLS1l4sSJfO9734s/hpkzZ5KXl3fWz7fjONi2HW+0j5WZmckFF1zA/fffz9tvv83MmTOZNWsWJSUlpz3uzJkz42HqZDIzM5k5c2b8+ausrGTEiBFs3779jMLAmXBdl+3btzN16tT4EIphGMyZM4ff//73VFdXx8PA1KlT48+Dx+OhqKio32c7CDHUJAyIYaFnclePnoai51v1lClTKC0tZfXq1RQXF7N69Wquv/56/H4/juMQiUQoKChgwoQJvSZ/nXvuuZSWlpKdnc0PfvAD1q1bx9tvv80vfvELPB4P3/3udxk7duwp6zp27LhnouDJarVtG9d1GTFiBBMnTozfZuLEiSxcuBCfz0d3dzdKKSyr99u3Z77ByWRkZHDvvfeyfv16Nm3axK9+9SsAvv3tbzNp0qSTP7kforWmqqqKzs7OeK/DsUzT5P/8n//Dxo0beeutt3j88cf57//+b77yla9w6aWXnvS4Sil8Pt9pJ999+Dnt+fuxkyU//Dyc7RkCPRMCPxxMep7zYyc/fvg2hmHIEIFIORIGRFoIBAIsXLiQF198kZEjR9La2sqll14ab5jHjBlDdXU1S5cujX/L+/AHem5uLldffTVXX301DQ0N/P3f/z1r1qxh7NixGIYxIAvWZGVlUVRURFlZWXxo4US1nE5P2Pjw/bKzs1m8eDGLFy+mubmZL33pS7z88su9eipORWtNV1cXjz32GEVFRcycOfOEt/P7/VxyySVccsklhEIhvve97/Hss88yb968eGjp63PV2dnJwYMHKSsrQylFc3MzdXV18WGXYDBIZ2dnr8b84MGDvY5xun8v0zSprKxky5YtdHd3xyeR7tmzB9M048MbQgwXEgZEWlBKMX/+fB5++GF+/etfc8455zBixIj4dTfccAN33303v/3tb7n66qvx+/3U1dWxY8cOrrvuOg4fPsyWLVuYMWMGmZmZ7Nmzh87OTgoLC4HYvIGqqipee+01CgsLqays7FOdfr+fpUuX8qtf/YqSkhLmzJmDUoqDBw/S2NgYP8XvdHJzczFNk1WrVnHeeeeRm5uL4zhs2rSJGTNmkJ2dzYEDB2hvbz9tw3bo0CE2b95MNBqlurqal156iX379vHVr36VgoKC427f0tLCiy++yIwZMygoKKCpqYmamhomT56MUorCwkLC4TCrV69m8uTJFBYWnvJshg/rmcWfmZlJZmYmDz/8MKZpctFFF6GUYsqUKTzwwAP89a9/5bzzzmPLli2sXr2615BGeXk5r776Km+88QY5OTmMHj36uN9z5ZVX8tJLL/GHP/yBa665htraWn7/+99z6aWXntGQhxCpRMKASDnBYJDKysp4l21GRgbl5eW9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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAFQCAYAAAAiKX2TAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABeK0lEQVR4nO3dd5xb1Z3//9e5V300vbr3jhvGmGIgQOglITFlE5Is2ZBkE0ICmyV8s8kvjeT7/aawIRu+SdgNgRRCh0AowQZMB4Mbxsa9jacXzWjUde89vz/GI3uwjdvMSBp9no8HDzwaSfORZqT71rnnfI7SWmuEEEIIUbCMbBcghBBCiOySMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIFzZbsAIUT+0VqjtUYphVJq0O77gwbyZ31ww9aBfhxC5BMJAyKvaa1ZuXIloVCIc845B9M0s10SWmt6enpwuVz4/f6cOMgkEgmSySQlJSWHrEdrzfvvv8/atWuB3oNjIBBgzJgxTJw4sd9tLcviP//zPznxxBP56Ec/+qE/+2ifj6eeeoqtW7dyww03oJTid7/7HXV1dVxxxRXH8Mh7OY5Dd3c3wWAQt9udufzxxx+nsbGRL3/5yznxtyNEtshpApH3XnzxRf76179i23a2SwHAtm1+9rOf8dhjj2W7lIznn3+e733ve6RSqQ+93ttvv81vfvMb3n//fd5//31eeuklfvKTn/Cv//qvLF26NPMca61JJBJYlnXYn+04Dj//+c955JFHjqjWVCpFMpnMfL1lyxb27NlzRLc9lFAoxFe/+lW2bNnyoT9LiEIlIwNi2NJaY9s2WmtcLtcxfUJ3HAfbtjEMA8Mw+t2H1jrzfdM0+30/FArR09NzyLr6auurq+++HMc5aK37f7/vZ31YvR+8TiwWo729/YCh8YOpqKjgW9/6Fn6/H601XV1d/OlPf+KnP/0pxcXFnHLKKbjdbv7jP/7jiJ+Pzs5OIpHIET0fH//4x9FaYxgGjuP0u25f+DBN86h+n47j0NraSjqd7nf5kiVLAPo9V4f7XXyw5g/7fQiRLyQMiGHnySefJB6PU1lZyTPPPEMqleK0007jiiuuwOPx8MILL7Bz504+97nP4XL1vgRs2+bBBx+kqKiIyy67DK01GzZs4IknnqChoYHS0lIuvvhiTj31VEzTxLIsli9fzrJly+ju7qaoqIiFCxfyiU98gkceeYRt27bR0dFBc3MzPp+PL3zhC7S2trJ06VIWL17ME088QXt7OyeeeCJXX301mzdv5tFHH6Wrq4tTTjmFJUuW4PP50FpjWRavvfYaS5cupauri5EjR7JkyRKmTp2KUootW7bw9NNPc9ZZZ/H3v/+dxsZGJk6cyLXXXkttbS3r1q3jqaeeoqmpiR//+MeYpskll1zCwoULD/kc9oUf6A0H119/PWvXruXhhx/O3O6ee+5h1qxZnHrqqViWxUsvvcTSpUsPeD4ee+yxzPPR0tKSeT7a2tpYunQpp512Gk899RSdnZ3ccsstbNmyhd27d/PpT386U08qleLRRx/llVdewTRNzj//fM4991xcLheRSITf//73XHTRRUydOjVz/bvvvpuFCxcyY8YM7rrrLmKxGL///e+pqKhg7NixfPazn+XFF1+kra2Na665BqUUqVSKF154gRdeeIFoNMrEiRP55Cc/ybhx41BKsWPHDh5++GEuuuginnjiCfbs2cP48eO59tprGTFiRE6cEhLiWEicFcPOunXruOeee3jxxRc5//zzWbhwIXfffTf/+Mc/ACgpKeGhhx5i9+7dmU/KbW1t3HfffQQCAQBWrlzJd7/7Xfx+P5/85CeZMmUKP//5z3nppZcy8xR+8YtfMGXKFK655hrOOOMMuru7sW2bESNGEAgEqKysZMqUKUyaNAmPx0NTUxOPPvoof/jDH1iwYAHnnnsujz/+OD/72c+4//77OfXUU1m8eDF//vOfee655zKfPh955BF+9atfMXXqVJYsWYLb7eY73/kOO3bsQGtNa2srjz32GL/73e+YMWMGl112GWvWrOGXv/wllmVRXFxMTU0NXq+XyZMnM2XKFMrKyo74+eybO3DSSSexdetWIpEItm3z2muvsX37dgBWrVrFz3/+88zzceaZZ2aej7q6OgKBABUVFZnnw+1209TUxCOPPMJdd93F7NmzueyyywgEAmzatIk333yz36jASy+9xOrVq7n00kuZMmUKt99+O8888wxa68wBvLW1NXN927Z5+eWX2bVrF6ZpMmbMmMz/p0yZwpgxY1BKsXHjRlasWJEZDXjg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", "text/plain": [ "
    " ] @@ -1238,7 +1107,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Assistant: None\n" + "Assistant: [{'type': 'image_file', 'image_file': {'file_id': 'assistant-IfUQ6bDRVr7JCqZGlIACfEoX'}}, {'type': 'text', 'text': {'value': 'Here is the pie chart of your investments with a color scheme that aligns with accessibility standards. Each slice represents the proportion of your investment in each company.', 'annotations': []}}]\n" ] } ], @@ -1296,7 +1165,7 @@ }, { "cell_type": "code", - "execution_count": 105, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1307,6 +1176,7 @@ " if f.filename == portfolio_file and f.purpose == \"assistants\":\n", " agents_client.delete_file(f.id)\n", " print(f\"Deleted existing file: {portfolio_file}\")\n", + " \n", "\n", "except Exception as e:\n", " print(f\"Error processing file '{portfolio_file}': {e}\")" diff --git a/samples/investment_advisor/data/sample_chart.png b/samples/investment_advisor/data/sample_chart.png new file mode 100644 index 0000000000000000000000000000000000000000..fbb557f71d05fcc099f1be68ef37d478dafca9cf GIT binary patch literal 76467 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 wFDh!# Date: Mon, 18 Nov 2024 17:44:32 -0300 Subject: [PATCH 156/180] Update incorrect else block --- samples/.DS_Store | Bin 0 -> 6148 bytes .../agent-investment_advisor.ipynb | 394 ++---------------- .../investment_advisor/data/sample_chart.png | Bin 76467 -> 0 bytes 3 files changed, 42 insertions(+), 352 deletions(-) create mode 100644 samples/.DS_Store delete mode 100644 samples/investment_advisor/data/sample_chart.png diff --git a/samples/.DS_Store b/samples/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a5da40ca6c3e98c4f723effea185cebfee66cc41 GIT binary patch literal 6148 zcmeHK%Sr=55Ukc50$zeAkMj%u!4TpX1+*hOWGNaq=Ec*iTAFc8l(=U!t=#*w_A{ChlN z!|ayX9rnldet6jp&w1B*hpS2oNC7Dz1*Cu!m?+@Amo~pjRFnczKni>-;NOQvckG2@ zVthInVgw-0m=5DQW(i{R1hE&6iOkR}sl=pOjTn}6=3CYE!Z9)Fuo^zBZnm0GENn<&b<=4(Fhg=1pSnGZTqKLf6dObYz90$&2g894v| literal 0 HcmV?d00001 diff --git a/samples/investment_advisor/agent-investment_advisor.ipynb b/samples/investment_advisor/agent-investment_advisor.ipynb index caecd9dc..7608ae3c 100644 --- a/samples/investment_advisor/agent-investment_advisor.ipynb +++ b/samples/investment_advisor/agent-investment_advisor.ipynb @@ -58,61 +58,9 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Processing c:\\developer\\repos\\github\\azure-ai-agents\\packages\\azure_ai_projects-1.0.0b1-py3-none-any.whl (from -r ./requirements.txt (line 7))\n", - "Requirement already satisfied: azure-identity==1.19.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 1)) (1.19.0)\n", - "Requirement already satisfied: pandas==2.2.3 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 2)) (2.2.3)\n", - "Requirement already satisfied: yfinance==0.2.48 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 3)) (0.2.48)\n", - "Requirement already satisfied: python-dotenv==1.0.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 4)) (1.0.1)\n", - "Requirement already satisfied: Pillow==11.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 5)) (11.0.0)\n", - "Requirement already satisfied: matplotlib==3.9.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from -r ./requirements.txt (line 6)) (3.9.2)\n", - "Requirement already satisfied: azure-core>=1.31.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.32.0)\n", - "Requirement already satisfied: cryptography>=2.5 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (43.0.3)\n", - "Requirement already satisfied: msal>=1.30.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.31.1)\n", - "Requirement already satisfied: msal-extensions>=1.2.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.2.0)\n", - "Requirement already satisfied: typing-extensions>=4.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-identity==1.19.0->-r ./requirements.txt (line 1)) (4.12.2)\n", - "Requirement already satisfied: numpy>=1.26.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.1.3)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from pandas==2.2.3->-r ./requirements.txt (line 2)) (2024.2)\n", - "Requirement already satisfied: requests>=2.31 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.32.3)\n", - "Requirement already satisfied: multitasking>=0.0.7 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.0.11)\n", - "Requirement already satisfied: lxml>=4.9.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (5.3.0)\n", - "Requirement already satisfied: platformdirs>=2.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.3.6)\n", - "Requirement already satisfied: frozendict>=2.3.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.4.6)\n", - "Requirement already satisfied: peewee>=3.16.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.17.8)\n", - "Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (4.12.3)\n", - "Requirement already satisfied: html5lib>=1.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from yfinance==0.2.48->-r ./requirements.txt (line 3)) (1.1)\n", - "Requirement already satisfied: contourpy>=1.0.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (1.3.1)\n", - "Requirement already satisfied: cycler>=0.10 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (0.12.1)\n", - "Requirement already satisfied: fonttools>=4.22.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (4.55.0)\n", - "Requirement already satisfied: kiwisolver>=1.3.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (1.4.7)\n", - "Requirement already satisfied: packaging>=20.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (24.2)\n", - "Requirement already satisfied: pyparsing>=2.3.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from matplotlib==3.9.2->-r ./requirements.txt (line 6)) (3.2.0)\n", - "Requirement already satisfied: isodate>=0.6.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-ai-projects==1.0.0b1->-r ./requirements.txt (line 7)) (0.7.2)\n", - "Requirement already satisfied: six>=1.11.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from azure-core>=1.31.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.16.0)\n", - "Requirement already satisfied: soupsieve>1.2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from beautifulsoup4>=4.11.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.6)\n", - "Requirement already satisfied: cffi>=1.12 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (1.17.1)\n", - "Requirement already satisfied: webencodings in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from html5lib>=1.1->yfinance==0.2.48->-r ./requirements.txt (line 3)) (0.5.1)\n", - "Requirement already satisfied: PyJWT<3,>=1.0.0 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from PyJWT[crypto]<3,>=1.0.0->msal>=1.30.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.0)\n", - "Requirement already satisfied: portalocker<3,>=1.4 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from msal-extensions>=1.2.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.10.1)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.4.0)\n", - "Requirement already satisfied: idna<4,>=2.5 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (3.10)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2.2.3)\n", - "Requirement already satisfied: certifi>=2017.4.17 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from requests>=2.31->yfinance==0.2.48->-r ./requirements.txt (line 3)) (2024.8.30)\n", - "Requirement already satisfied: pycparser in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from cffi>=1.12->cryptography>=2.5->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (2.22)\n", - "Requirement already satisfied: pywin32>=226 in c:\\developer\\repos\\github\\azure-ai-agents\\samples\\investment_advisor\\.venv\\lib\\site-packages (from portalocker<3,>=1.4->msal-extensions>=1.2.0->azure-identity==1.19.0->-r ./requirements.txt (line 1)) (308)\n", - "azure-ai-projects is already installed with the same version as the provided wheel. Use --force-reinstall to force an installation of the wheel.\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], + "outputs": [], "source": [ "# Install the packages\n", "%pip install -r ./requirements.txt" @@ -143,17 +91,9 @@ }, { "cell_type": "code", - "execution_count": 109, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment variables loaded successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", "from dotenv import load_dotenv\n", @@ -190,17 +130,9 @@ }, { "cell_type": "code", - "execution_count": 110, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Agent client created successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import os\n", "from azure.ai.projects import AIProjectClient\n", @@ -232,17 +164,9 @@ }, { "cell_type": "code", - "execution_count": 111, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Uploaded file: investment_portfolio.csv\n" - ] - } - ], + "outputs": [], "source": [ "# Directory containing files to upload\n", "directory=\"data\"\n", @@ -300,17 +224,9 @@ }, { "cell_type": "code", - "execution_count": 112, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import yfinance as yf\n", "\n", @@ -360,7 +276,7 @@ }, { "cell_type": "code", - "execution_count": 113, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -386,17 +302,9 @@ }, { "cell_type": "code", - "execution_count": 114, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tools list defined successfully.\n" - ] - } - ], + "outputs": [], "source": [ "tools_list = [\n", " {\"type\": \"code_interpreter\"},\n", @@ -429,18 +337,9 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Agent created successfully.\n", - " asst_HDXCOrEVyVBvnC1TtauXadCJ\n" - ] - } - ], + "outputs": [], "source": [ "# Create the Agent with code interpreter and function calling tools enabled\n", "try:\n", @@ -470,17 +369,9 @@ }, { "cell_type": "code", - "execution_count": 116, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Thread created successfully: thread_8dFPBiLlCDzjqS4iIeGoGIoQ\n" - ] - } - ], + "outputs": [], "source": [ "# Create a conversation thread\n", "try:\n", @@ -515,18 +406,9 @@ }, { "cell_type": "code", - "execution_count": 117, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Successfully added User prompt to the thread.\n", - " msg_4nH05SlmZmSqfp4nt8s2Udzo\n" - ] - } - ], + "outputs": [], "source": [ "# Define the user question\n", "prompt_content = \"What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?\"\n", @@ -556,17 +438,9 @@ }, { "cell_type": "code", - "execution_count": 118, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Run started: run_XxGGa5z2bRLQhjD9jIQerJEz\n" - ] - } - ], + "outputs": [], "source": [ "# Initiate the Agent's response\n", "try:\n", @@ -600,18 +474,9 @@ }, { "cell_type": "code", - "execution_count": 122, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Monitoring the run status...\n", - "Navigate to `RunStatus.COMPLETED` cell.\n" - ] - } - ], + "outputs": [], "source": [ "import json\n", "\n", @@ -639,18 +504,9 @@ }, { "cell_type": "code", - "execution_count": 120, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Agent run has not failed...\n", - "Navigate to and execute the 'RunStatus.REQUIRES_ACTION' cell.\n" - ] - } - ], + "outputs": [], "source": [ "#print(run.model_dump_json(indent=4))\n", "\n", @@ -672,21 +528,9 @@ }, { "cell_type": "code", - "execution_count": 121, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function Calling ...\n", - "Function 'fetch_stock_price' called successfully. \n", - "Output: 415.88\n", - "\n", - "Results submitted successfully. Go back to the first cell, 'Monitor Run Status' and execute again.\n" - ] - } - ], + "outputs": [], "source": [ "if run.status == \"requires_action\":\n", " print(\"Function Calling ...\")\n", @@ -726,30 +570,9 @@ }, { "cell_type": "code", - "execution_count": 123, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Run completed!\n", - "\n", - "MESSAGES\n", - "\n", - "Assistant: The latest closing price for Microsoft (MSFT) is $415.88.\n", - "\n", - "I will now open the uploaded file to check your MSFT investment details and calculate the total investment.\n", - "Assistant: Based on the data provided, your MSFT investment details are as follows:\n", - "\n", - "- Average Cost: $200 per share\n", - "- Quantity: 300 shares\n", - "\n", - "I will now calculate your total investment in MSFT as of today's price.\n", - "Assistant: Your total investment in Microsoft (MSFT) as of today is valued at $124,764.\n" - ] - } - ], + "outputs": [], "source": [ "if run.status == \"completed\":\n", " messages = agents_client.list_messages(thread_id=thread.id, order=\"asc\", after=message.id)\n", @@ -787,17 +610,9 @@ }, { "cell_type": "code", - "execution_count": 124, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Function `process_message` created successfully.\n" - ] - } - ], + "outputs": [], "source": [ "import time\n", "import json\n", @@ -878,8 +693,6 @@ " \n", " else:\n", " content = str(message_content)\n", - " else:\n", - " content = str(thread_message.content)\n", "\n", " print(f\"{role.capitalize()}: {content}\")\n", " \n", @@ -938,26 +751,9 @@ }, { "cell_type": "code", - "execution_count": 125, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is today's date?\")" ] @@ -972,38 +768,9 @@ }, { "cell_type": "code", - "execution_count": 126, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.REQUIRES_ACTION\n", - "\n", - "Function calling initiated...\n", - "Executed 'fetch_stock_price'. Output: 229.105\n", - "Executed 'fetch_stock_price'. Output: 201.695\n", - "Executed 'fetch_stock_price'. Output: 333.06\n", - "Executed 'fetch_stock_price'. Output: 843.52\n", - "Function call(s) completed successfully.\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': 'Which company have I invested in the most?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Let's determine which company you have invested in the most by calculating the total value of your investments for each company and identifying the one with the highest value.\\n\\nTo do this, we will use the latest closing prices and your investment data. Here is the list again:\\n- MSFT (Microsoft): $415.88\\n- AAPL (Apple): $ \\n- AMZN (Amazon): $ \\n- TSLA (Tesla): $ \\n- NFLX (Netflix): $\\n\\nLet's fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Here are the latest closing prices for the stocks in your portfolio:\\n- AAPL (Apple): $229.11\\n- AMZN (Amazon): $201.70\\n- TSLA (Tesla): $333.06\\n- NFLX (Netflix): $843.52\\n- MSFT (Microsoft): $415.88\\n\\nI will now calculate the total investments for each company and determine which one you have invested in the most.', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'You have invested the most in Microsoft (MSFT), with a total investment value of $124,764.', 'annotations': []}}]\n" - ] - } - ], + "outputs": [], "source": [ "attachments=[ # Add files by using the attachments parameter\n", " {\"file_id\": portfolio_file_id, \"tools\": [{\"type\": \"code_interpreter\"}]}\n", @@ -1022,33 +789,9 @@ }, { "cell_type": "code", - "execution_count": 127, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': 'Which company have I invested in the most?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Let's determine which company you have invested in the most by calculating the total value of your investments for each company and identifying the one with the highest value.\\n\\nTo do this, we will use the latest closing prices and your investment data. Here is the list again:\\n- MSFT (Microsoft): $415.88\\n- AAPL (Apple): $ \\n- AMZN (Amazon): $ \\n- TSLA (Tesla): $ \\n- NFLX (Netflix): $\\n\\nLet's fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Here are the latest closing prices for the stocks in your portfolio:\\n- AAPL (Apple): $229.11\\n- AMZN (Amazon): $201.70\\n- TSLA (Tesla): $333.06\\n- NFLX (Netflix): $843.52\\n- MSFT (Microsoft): $415.88\\n\\nI will now calculate the total investments for each company and determine which one you have invested in the most.', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'You have invested the most in Microsoft (MSFT), with a total investment value of $124,764.', 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': 'What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"The current stock price for Amazon (AMZN) is $201.70.\\n\\nBased on this price, let's calculate the total investment value for AMZN. \\n\\nAccording to your provided investment details:\\n- AMZN average cost: $125 per share\\n- Quantity: 50 shares\\n\\nWe will use this information to calculate the total investment value.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Based on the current stock price, your total investment value for Amazon (AMZN) is $10,085.', 'annotations': []}}]\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?\")" ] @@ -1063,54 +806,9 @@ }, { "cell_type": "code", - "execution_count": 128, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User message added...\n", - "Run started...\n", - "Run Status: RunStatus.IN_PROGRESS\n", - "\n", - "Run Status: RunStatus.COMPLETED\n", - "\n", - "User: [{'type': 'text', 'text': {'value': 'What is the latest closing price for Microsoft? What is my total investment for MSFT as of today?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'The latest closing price for Microsoft (MSFT) is $415.88.\\n\\nI will now open the uploaded file to check your MSFT investment details and calculate the total investment.', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Based on the data provided, your MSFT investment details are as follows:\\n\\n- Average Cost: $200 per share\\n- Quantity: 300 shares\\n\\nI will now calculate your total investment in MSFT as of today's price.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Your total investment in Microsoft (MSFT) as of today is valued at $124,764.', 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': \"What is today's date?\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Today's date is November 18, 2024.\", 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': 'Which company have I invested in the most?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"Let's determine which company you have invested in the most by calculating the total value of your investments for each company and identifying the one with the highest value.\\n\\nTo do this, we will use the latest closing prices and your investment data. Here is the list again:\\n- MSFT (Microsoft): $415.88\\n- AAPL (Apple): $ \\n- AMZN (Amazon): $ \\n- TSLA (Tesla): $ \\n- NFLX (Netflix): $\\n\\nLet's fetch the latest closing prices for AAPL, AMZN, TSLA, and NFLX.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Here are the latest closing prices for the stocks in your portfolio:\\n- AAPL (Apple): $229.11\\n- AMZN (Amazon): $201.70\\n- TSLA (Tesla): $333.06\\n- NFLX (Netflix): $843.52\\n- MSFT (Microsoft): $415.88\\n\\nI will now calculate the total investments for each company and determine which one you have invested in the most.', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'You have invested the most in Microsoft (MSFT), with a total investment value of $124,764.', 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': 'What is the current stock price for Amazon? Based on this price, what is the total investment value for AMZN?', 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': \"The current stock price for Amazon (AMZN) is $201.70.\\n\\nBased on this price, let's calculate the total investment value for AMZN. \\n\\nAccording to your provided investment details:\\n- AMZN average cost: $125 per share\\n- Quantity: 50 shares\\n\\nWe will use this information to calculate the total investment value.\", 'annotations': []}}]\n", - "Assistant: [{'type': 'text', 'text': {'value': 'Based on the current stock price, your total investment value for Amazon (AMZN) is $10,085.', 'annotations': []}}]\n", - "User: [{'type': 'text', 'text': {'value': 'Show a pie chart of my investments? Ensure the pie chart color schema aligns with accessibility standards.', 'annotations': []}}]\n", - "Image File downloaded to './data' successfully.\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAFQCAYAAAAiKX2TAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABeK0lEQVR4nO3dd5xb1Z3//9e5V300vbr3jhvGmGIgQOglITFlE5Is2ZBkE0ICmyV8s8kvjeT7/aawIRu+SdgNgRRCh0AowQZMB4Mbxsa9jacXzWjUde89vz/GI3uwjdvMSBp9no8HDzwaSfORZqT71rnnfI7SWmuEEEIIUbCMbBcghBBCiOySMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIGTMCCEEEIUOAkDQgghRIFzZbsAIUT+0VqjtUYphVJq0O77gwbyZ31ww9aBfhxC5BMJAyKvaa1ZuXIloVCIc845B9M0s10SWmt6enpwuVz4/f6cOMgkEgmSySQlJSWHrEdrzfvvv8/atWuB3oNjIBBgzJgxTJw4sd9tLcviP//zPznxxBP56Ec/+qE/+2ifj6eeeoqtW7dyww03oJTid7/7HXV1dVxxxRXH8Mh7OY5Dd3c3wWAQt9udufzxxx+nsbGRL3/5yznxtyNEtshpApH3XnzxRf76179i23a2SwHAtm1+9rOf8dhjj2W7lIznn3+e733ve6RSqQ+93ttvv81vfvMb3n//fd5//31eeuklfvKTn/Cv//qvLF26NPMca61JJBJYlnXYn+04Dj//+c955JFHjqjWVCpFMpnMfL1lyxb27NlzRLc9lFAoxFe/+lW2bNnyoT9LiEIlIwNi2NJaY9s2WmtcLtcxfUJ3HAfbtjEMA8Mw+t2H1jrzfdM0+30/FArR09NzyLr6auurq+++HMc5aK37f7/vZ31YvR+8TiwWo729/YCh8YOpqKjgW9/6Fn6/H601XV1d/OlPf+KnP/0pxcXFnHLKKbjdbv7jP/7jiJ+Pzs5OIpHIET0fH//4x9FaYxgGjuP0u25f+DBN86h+n47j0NraSjqd7nf5kiVLAPo9V4f7XXyw5g/7fQiRLyQMiGHnySefJB6PU1lZyTPPPEMqleK0007jiiuuwOPx8MILL7Bz504+97nP4XL1vgRs2+bBBx+kqKiIyy67DK01GzZs4IknnqChoYHS0lIuvvhiTj31VEzTxLIsli9fzrJly+ju7qaoqIiFCxfyiU98gkceeYRt27bR0dFBc3MzPp+PL3zhC7S2trJ06VIWL17ME088QXt7OyeeeCJXX301mzdv5tFHH6Wrq4tTTjmFJUuW4PP50FpjWRavvfYaS5cupauri5EjR7JkyRKmTp2KUootW7bw9NNPc9ZZZ/H3v/+dxsZGJk6cyLXXXkttbS3r1q3jqaeeoqmpiR//+MeYpskll1zCwoULD/kc9oUf6A0H119/PWvXruXhhx/O3O6ee+5h1qxZnHrqqViWxUsvvcTSpUsPeD4ee+yxzPPR0tKSeT7a2tpYunQpp512Gk899RSdnZ3ccsstbNmyhd27d/PpT386U08qleLRRx/llVdewTRNzj//fM4991xcLheRSITf//73XHTRRUydOjVz/bvvvpuFCxcyY8YM7rrrLmKxGL///e+pqKhg7NixfPazn+XFF1+kra2Na665BqUUqVSKF154gRdeeIFoNMrEiRP55Cc/ybhx41BKsWPHDh5++GEuuuginnjiCfbs2cP48eO59tprGTFiRE6cEhLiWEicFcPOunXruOeee3jxxRc5//zzWbhwIXfffTf/+Mc/ACgpKeGhhx5i9+7dmU/KbW1t3HfffQQCAQBWrlzJd7/7Xfx+P5/85CeZMmUKP//5z3nppZcy8xR+8YtfMGXKFK655hrOOOMMuru7sW2bESNGEAgEqKysZMqUKUyaNAmPx0NTUxOPPvoof/jDH1iwYAHnnnsujz/+OD/72c+4//77OfXUU1m8eDF//vOfee655zKfPh955BF+9atfMXXqVJYsWYLb7eY73/kOO3bsQGtNa2srjz32GL/73e+YMWMGl112GWvWrOGXv/wllmVRXFxMTU0NXq+XyZMnM2XKFMrKyo74+eybO3DSSSexdetWIpEItm3z2muvsX37dgBWrVrFz3/+88zzceaZZ2aej7q6OgKBABUVFZnnw+1209TUxCOPPMJdd93F7NmzueyyywgEAmzatIk333yz36jASy+9xOrVq7n00kuZMmUKt99+O8888wxa68wBvLW1NXN927Z5+eWX2bVrF6ZpMmbMmMz/p0yZwpgxY1BKsXHjRlasWJEZDXjg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", - "text/plain": [ - "
    " - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Assistant: [{'type': 'image_file', 'image_file': {'file_id': 'assistant-IfUQ6bDRVr7JCqZGlIACfEoX'}}, {'type': 'text', 'text': {'value': 'Here is the pie chart of your investments with a color scheme that aligns with accessibility standards. Each slice represents the proportion of your investment in each company.', 'annotations': []}}]\n" - ] - } - ], + "outputs": [], "source": [ "process_message(thread_id=thread.id, prompt_message=\"Show a pie chart of my investments? Ensure the pie chart color schema aligns with accessibility standards.\")" ] @@ -1132,17 +830,9 @@ }, { "cell_type": "code", - "execution_count": 101, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Agent does not exist to delete.\n" - ] - } - ], + "outputs": [], "source": [ "# Get agent list\n", "agents = agents_client.list_agents()\n", @@ -1245,7 +935,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.7" + "version": "3.12.6" } }, "nbformat": 4, diff --git a/samples/investment_advisor/data/sample_chart.png b/samples/investment_advisor/data/sample_chart.png deleted file mode 100644 index fbb557f71d05fcc099f1be68ef37d478dafca9cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76467 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 wFDh!# Date: Mon, 18 Nov 2024 15:27:16 -0800 Subject: [PATCH 157/180] Update quickstart.md update azure resource register script --- quickstart.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/quickstart.md b/quickstart.md index b850311b..ab50e86b 100644 --- a/quickstart.md +++ b/quickstart.md @@ -38,11 +38,13 @@ If you already have these resources set up, skip to the [configure and run your - To use Bing Search tool: Microsoft.Bing ```console - az provider register -–namespace {my_resource_namespace} - [--accept-terms] - [--consent-to-permissions] - [--management-group-id] - [--wait] + az provider register -–namespace 'Microsoft.KeyVault' + az provider register -–namespace 'Microsoft.CognitiveServices' + az provider register -–namespace 'Microsoft.Storage' + az provider register -–namespace 'Microsoft.MachineLearningServices' + az provider register -–namespace 'Microsoft.Search' + # only to use Grounding with Bing Search tool + az provider register -–namespace 'Microsoft.Bing' ``` 1. To authenticate to your Azure subscription from the Azure CLI, use the following command: From 19eb08650081691774b62e9f6285a8d36607f86c Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 18 Nov 2024 17:59:23 -0800 Subject: [PATCH 158/180] adding file search with customer resources --- samples/file-search/python-byo-file-search.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 samples/file-search/python-byo-file-search.py diff --git a/samples/file-search/python-byo-file-search.py b/samples/file-search/python-byo-file-search.py new file mode 100644 index 00000000..f5d59328 --- /dev/null +++ b/samples/file-search/python-byo-file-search.py @@ -0,0 +1,59 @@ +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import FileSearchTool, VectorStoreDataSource, VectorStoreDataSourceAssetType +from azure.identity import DefaultAzureCredential + + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +credential = DefaultAzureCredential() +project_client = AIProjectClient.from_connection_string( + credential=credential, conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +with project_client: + + # [START upload_file_and_create_agent_with_file_search] + # We will upload the local file to Azure and will use it for vector store creation. + _, asset_uri = project_client.upload_file("./data/product_info_1.md") + + # create a vector store with no file and wait for it to be processed + ds = VectorStoreDataSource(asset_identifier=asset_uri, asset_type=VectorStoreDataSourceAssetType.URI_ASSET) + vector_store = project_client.agents.create_vector_store_and_poll(data_sources=[ds], name="sample_vector_store") + print(f"Created vector store, vector store ID: {vector_store.id}") + + # create a file search tool + file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id]) + + # notices that FileSearchTool as tool and tool_resources must be added or the assistant unable to search the file + agent = project_client.agents.create_agent( + model="gpt-4o-mini", + name="my-assistant", + instructions="You are helpful assistant", + tools=file_search_tool.definitions, + tool_resources=file_search_tool.resources, + ) + # [END upload_file_and_create_agent_with_file_search] + print(f"Created agent, agent ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="What feature does Smart Eyewear offer?" + ) + print(f"Created message, message ID: {message.id}") + + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Created run, run ID: {run.id}") + + project_client.agents.delete_vector_store(vector_store.id) + print("Deleted vector store") + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file From aaffa2063e0803f6fd0df7293c6f1e6549187cec Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 18 Nov 2024 18:48:08 -0800 Subject: [PATCH 159/180] adding deploy button --- quickstart.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/quickstart.md b/quickstart.md index ab50e86b..55865679 100644 --- a/quickstart.md +++ b/quickstart.md @@ -72,7 +72,14 @@ If you already have these resources set up, skip to the [configure and run your **Standard Setup**: Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage.
    - + + | Template | Description | Auto-deploy | + | ------------------- | -----------------------------------------------| -----------------------| + |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://raw.githubusercontent.com/Azure/azure-ai-agents/refs/heads/main/basic-agent-identity.bicep?token=GHSAT0AAAAAACZNMQAEU5UTLTW3A6Z3APQAZZ4AQNA) + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://raw.githubusercontent.com/Azure/azure-ai-agents/refs/heads/main/basic-agent-keys.bicep?token=GHSAT0AAAAAACZNMQAE36JD2ZDYQYKAOBCIZZ4ASBQ) + | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://raw.githubusercontent.com/Azure/azure-ai-agents/refs/heads/main/standard-agent.bicep?token=GHSAT0AAAAAACZNMQAE2AKFTITYODN3T62QZZ4BGYQ) + + **Manually Deploy Templates**
    Option 1: Use basic agent setup. @@ -90,12 +97,10 @@ If you already have these resources set up, skip to the [configure and run your - basic-ai-project-identity.bicep - basic-dependent-resources.bicep ``` - - Before deploying resources, decide which configuration file to use: - `basic-agent-keys.bicep`: Use this file to use API keys for authentication. - `basic-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. - - Using the resource group you created in the previous step and one of the template files (either basic-agent-keys.bicep or basic-agent-identity.bicep), run one of the following commands: - To use default resource names, run: From 1275c20f15a456c50d9624b3ce96225a0b97e257 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 18 Nov 2024 18:56:58 -0800 Subject: [PATCH 160/180] fixing links --- quickstart.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/quickstart.md b/quickstart.md index 55865679..de2c4777 100644 --- a/quickstart.md +++ b/quickstart.md @@ -75,9 +75,10 @@ If you already have these resources set up, skip to the [configure and run your | Template | Description | Auto-deploy | | ------------------- | -----------------------------------------------| -----------------------| - |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://raw.githubusercontent.com/Azure/azure-ai-agents/refs/heads/main/basic-agent-identity.bicep?token=GHSAT0AAAAAACZNMQAEU5UTLTW3A6Z3APQAZZ4AQNA) - |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://raw.githubusercontent.com/Azure/azure-ai-agents/refs/heads/main/basic-agent-keys.bicep?token=GHSAT0AAAAAACZNMQAE36JD2ZDYQYKAOBCIZZ4ASBQ) - | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://raw.githubusercontent.com/Azure/azure-ai-agents/refs/heads/main/standard-agent.bicep?token=GHSAT0AAAAAACZNMQAE2AKFTITYODN3T62QZZ4BGYQ) + |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-identity.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAEU5UTLTW3A6Z3APQAZZ4AQNA) + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-keys.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE36JD2ZDYQYKAOBCIZZ4ASBQ) + | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fstandard-agent.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE2AKFTITYODN3T62QZZ4BGYQ) + **Manually Deploy Templates**
    From 338299fab60eb29af5eb1b527807c4b135a9f0e6 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 18 Nov 2024 18:59:39 -0800 Subject: [PATCH 161/180] fixing links p2 --- quickstart.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quickstart.md b/quickstart.md index de2c4777..a22eacf0 100644 --- a/quickstart.md +++ b/quickstart.md @@ -75,9 +75,9 @@ If you already have these resources set up, skip to the [configure and run your | Template | Description | Auto-deploy | | ------------------- | -----------------------------------------------| -----------------------| - |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-identity.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAEU5UTLTW3A6Z3APQAZZ4AQNA) - |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-keys.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE36JD2ZDYQYKAOBCIZZ4ASBQ) - | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fstandard-agent.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE2AKFTITYODN3T62QZZ4BGYQ) + |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-identity.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAEU5UTLTW3A6Z3APQAZZ4AQNA) + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-keys.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE36JD2ZDYQYKAOBCIZZ4ASBQ) + | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fstandard-agent.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE2AKFTITYODN3T62QZZ4BGYQ) **Manually Deploy Templates** From d170a1cdf64df8901ac16dc13bc2fd319add3d56 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 16:17:36 -0800 Subject: [PATCH 162/180] updating file search python file --- samples/file-search/python-byo-file-search.py | 59 --------- samples/file-search/python-file-search.py | 122 +++++++++--------- 2 files changed, 58 insertions(+), 123 deletions(-) delete mode 100644 samples/file-search/python-byo-file-search.py diff --git a/samples/file-search/python-byo-file-search.py b/samples/file-search/python-byo-file-search.py deleted file mode 100644 index f5d59328..00000000 --- a/samples/file-search/python-byo-file-search.py +++ /dev/null @@ -1,59 +0,0 @@ -import os -from azure.ai.projects import AIProjectClient -from azure.ai.projects.models import FileSearchTool, VectorStoreDataSource, VectorStoreDataSourceAssetType -from azure.identity import DefaultAzureCredential - - -# Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# Customer needs to login to Azure subscription via Azure CLI and set the environment variables - -credential = DefaultAzureCredential() -project_client = AIProjectClient.from_connection_string( - credential=credential, conn_str=os.environ["PROJECT_CONNECTION_STRING"] -) - -with project_client: - - # [START upload_file_and_create_agent_with_file_search] - # We will upload the local file to Azure and will use it for vector store creation. - _, asset_uri = project_client.upload_file("./data/product_info_1.md") - - # create a vector store with no file and wait for it to be processed - ds = VectorStoreDataSource(asset_identifier=asset_uri, asset_type=VectorStoreDataSourceAssetType.URI_ASSET) - vector_store = project_client.agents.create_vector_store_and_poll(data_sources=[ds], name="sample_vector_store") - print(f"Created vector store, vector store ID: {vector_store.id}") - - # create a file search tool - file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id]) - - # notices that FileSearchTool as tool and tool_resources must be added or the assistant unable to search the file - agent = project_client.agents.create_agent( - model="gpt-4o-mini", - name="my-assistant", - instructions="You are helpful assistant", - tools=file_search_tool.definitions, - tool_resources=file_search_tool.resources, - ) - # [END upload_file_and_create_agent_with_file_search] - print(f"Created agent, agent ID: {agent.id}") - - thread = project_client.agents.create_thread() - print(f"Created thread, thread ID: {thread.id}") - - message = project_client.agents.create_message( - thread_id=thread.id, role="user", content="What feature does Smart Eyewear offer?" - ) - print(f"Created message, message ID: {message.id}") - - run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Created run, run ID: {run.id}") - - project_client.agents.delete_vector_store(vector_store.id) - print("Deleted vector store") - - project_client.agents.delete_agent(agent.id) - print("Deleted agent") - - messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") \ No newline at end of file diff --git a/samples/file-search/python-file-search.py b/samples/file-search/python-file-search.py index 71ca0490..f5d59328 100644 --- a/samples/file-search/python-file-search.py +++ b/samples/file-search/python-file-search.py @@ -1,65 +1,59 @@ -import os -from azure.ai.projects import AIProjectClient -from azure.ai.projects.models._patch import FileSearchTool -from azure.identity import DefaultAzureCredential - - -# Create an Azure AI Client from a connection string, copied from your AI Studio project. -# At the moment, it should be in the format ";;;" -# Customer needs to login to Azure subscription via Azure CLI and set the environment variables - -project_client = AIProjectClient.from_connection_string( - credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] -) +import os +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import FileSearchTool, VectorStoreDataSource, VectorStoreDataSourceAssetType +from azure.identity import DefaultAzureCredential - -with project_client: - - openai_file = project_client.agents.upload_file_and_poll(file_path="product_info_1.md", purpose="assistants") - print(f"Uploaded file, file ID: {openai_file.id}") - - openai_vectorstore = project_client.agents.create_vector_store_and_poll(file_ids=[openai_file.id], name="my_vectorstore") - print(f"Created vector store, vector store ID: {openai_vectorstore.id}") - - # Create file search tool with resources - file_search = FileSearchTool(vector_store_ids=[openai_vectorstore.id]) - - # Create agent with file search tool and process the agent run - agent = project_client.agents.create_agent( - model="gpt-4o-mini", - name="my-agent", - instructions="Hello, you are helpful agent and can search information from uploaded files", - tools=file_search.definitions, - tool_resources=file_search.resources, - ) - print(f"Created agent, agent ID: {agent.id}") - - # Create thread for communication - thread = project_client.agents.create_thread() - print(f"Created thread, ID: {thread.id}") - - # Create message to thread - message = project_client.agents.create_message( - thread_id=thread.id, role="user", content="Hello, what Contoso products do you know?" - ) - print(f"Created message, ID: {message.id}") - - # Create and process agent run in thread with tools - run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) - print(f"Run finished with status: {run.status}") - - if run.status == "failed": - # Check if you got "Rate limit is exceeded.", then you want to get more quota - print(f"Run failed: {run.last_error}") - - # Delete the file when done - project_client.agents.delete_vector_store(openai_vectorstore.id) - print("Deleted vector store") - - # Delete the agent when done - project_client.agents.delete_agent(agent.id) - print("Deleted agent") - - # Fetch and log all messages - messages = project_client.agents.list_messages(thread_id=thread.id) - print(f"Messages: {messages}") \ No newline at end of file + +# Create an Azure AI Client from a connection string, copied from your AI Studio project. +# At the moment, it should be in the format ";;;" +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables + +credential = DefaultAzureCredential() +project_client = AIProjectClient.from_connection_string( + credential=credential, conn_str=os.environ["PROJECT_CONNECTION_STRING"] +) + +with project_client: + + # [START upload_file_and_create_agent_with_file_search] + # We will upload the local file to Azure and will use it for vector store creation. + _, asset_uri = project_client.upload_file("./data/product_info_1.md") + + # create a vector store with no file and wait for it to be processed + ds = VectorStoreDataSource(asset_identifier=asset_uri, asset_type=VectorStoreDataSourceAssetType.URI_ASSET) + vector_store = project_client.agents.create_vector_store_and_poll(data_sources=[ds], name="sample_vector_store") + print(f"Created vector store, vector store ID: {vector_store.id}") + + # create a file search tool + file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id]) + + # notices that FileSearchTool as tool and tool_resources must be added or the assistant unable to search the file + agent = project_client.agents.create_agent( + model="gpt-4o-mini", + name="my-assistant", + instructions="You are helpful assistant", + tools=file_search_tool.definitions, + tool_resources=file_search_tool.resources, + ) + # [END upload_file_and_create_agent_with_file_search] + print(f"Created agent, agent ID: {agent.id}") + + thread = project_client.agents.create_thread() + print(f"Created thread, thread ID: {thread.id}") + + message = project_client.agents.create_message( + thread_id=thread.id, role="user", content="What feature does Smart Eyewear offer?" + ) + print(f"Created message, message ID: {message.id}") + + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) + print(f"Created run, run ID: {run.id}") + + project_client.agents.delete_vector_store(vector_store.id) + print("Deleted vector store") + + project_client.agents.delete_agent(agent.id) + print("Deleted agent") + + messages = project_client.agents.list_messages(thread_id=thread.id) + print(f"Messages: {messages}") \ No newline at end of file From a3b220a17977918108d9652742e762bc84734473 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 16:25:50 -0800 Subject: [PATCH 163/180] Update readme.md --- samples/file-search/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index 34f42900..78831834 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -6,7 +6,7 @@ To access your files, the file search tool uses the vector store object. Upload ### File Sources - Uploading local files -- [coming soon] Azure Blob Storage +- [Coming Soon] Azure Blob Storage ### Basic Agent Setup
    The File Search tool has the same functionality as AOAI Assistants. Microsoft managed search and storage resources are used. From 989ba5f3b19f5200879617d169dd2cd8887c4255 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 16:28:58 -0800 Subject: [PATCH 164/180] Update readme.md --- samples/file-search/readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index 78831834..ca978ffa 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -11,12 +11,12 @@ To access your files, the file search tool uses the vector store object. Upload ### Basic Agent Setup
    The File Search tool has the same functionality as AOAI Assistants. Microsoft managed search and storage resources are used. - Uploaded files get stored in Microsoft managed storage -- A vector store is created using Microsoft managed search resources +- A vector store is created using a Microsoft managed search resource ### Standard Agent Setup The File Search tool uses the Azure AI Search and Azure Blob Storage resources you connected during agent setup. -- Uploaded files get stored in your connected Azure Blob Storage account. -- Vector stores get created using your connected Azure AI Seach resource. +- Uploaded files get stored in your connected Azure Blob Storage account +- Vector stores get created using your connected Azure AI Seach resource

    For both Agent setups, OpenAI handles the entire ingestion process, including automatically parsing and chunking documents, generating and storing embeddings, and utilizing both vector and keyword searches to retrieve relevant content for user queries. From 481040b756297fab9bc2629304ac0212a3f5025d Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 16:30:01 -0800 Subject: [PATCH 165/180] Update readme.md --- samples/file-search/readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/file-search/readme.md b/samples/file-search/readme.md index ca978ffa..97e8c3c0 100644 --- a/samples/file-search/readme.md +++ b/samples/file-search/readme.md @@ -31,6 +31,7 @@ Run the code samples below and view the output. > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./python-file-search.py) +* [C#](./FileSearch.cs) ## Additional samples From 9a1f869a4e64ee14e58550fba1819d587c628274 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 16:31:48 -0800 Subject: [PATCH 166/180] Update readme.md --- samples/bing-search/readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/bing-search/readme.md b/samples/bing-search/readme.md index 70bd99f8..fd5782b3 100644 --- a/samples/bing-search/readme.md +++ b/samples/bing-search/readme.md @@ -67,3 +67,4 @@ Run the code samples below and view the output. > Be sure that you've [installed the SDK](../../quickstart.md#install-the-sdk-package) for your language. * [Python](./bing-python.py) +* [C#](./BingSearch.cs) From 71c811a17d4b6431f5b9cae70e2ab198686e44a9 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 17:50:04 -0800 Subject: [PATCH 167/180] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1f780fe8..71a8e27c 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,10 @@ Azure AI Agent Service is a fully-managed service designed to empower developers See the QuickStart to [get started](./quickstart.md). +**E2E Agent Samples** +* [Azure AI Travel Agent](https://github.com/Azure-Samples/azureai-travel-agent-python/tree/main) +* [Sample App using Azure AI Agents](https://github.com/Azure-Samples/azure-ai-projects-file-search) + ## ❓Get help * GitHub Issues (Preferred) From 9d860c6f3896a0a05d82dd5894e55f6a30099a76 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 17:55:37 -0800 Subject: [PATCH 168/180] Create README.md for samples --- samples/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 samples/README.md diff --git a/samples/README.md b/samples/README.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/samples/README.md @@ -0,0 +1 @@ + From 2ce7174d3c4af0307f7bd70119dcf37259b98231 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Tue, 19 Nov 2024 18:09:37 -0800 Subject: [PATCH 169/180] Update sample specific README.md --- samples/README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/samples/README.md b/samples/README.md index 8b137891..060d6609 100644 --- a/samples/README.md +++ b/samples/README.md @@ -1 +1,20 @@ +# Azure AI Agent Service Samples +## Getting Started +* [Quickstart](https://github.com/Azure/azure-ai-agents/blob/main/quickstart.md) +* [Use Llama models with Agents](https://github.com/Azure/azure-ai-agents/blob/main/samples/llama-3.md) +* [Use OpenAI Python SDK with Azure AI Agent Service](https://github.com/Azure/azure-ai-agents/blob/main/samples/use-openai.md) + +## E2E Samples +* [Azure AI Travel Agent](https://github.com/Azure-Samples/azureai-travel-agent-python/tree/main) +* [Sample App using Azure AI Agents](https://github.com/Azure-Samples/azure-ai-projects-file-search) + +## Tool Specific Samples +* [File Search](https://github.com/Azure/azure-ai-agents/tree/main/samples/file-search) +* [Code Interpreter](https://github.com/Azure/azure-ai-agents/tree/main/samples/code-interpreter) +* [Bing Search](https://github.com/Azure/azure-ai-agents/tree/main/samples/bing-search) +* [Function Calling](https://github.com/Azure/azure-ai-agents/tree/main/samples/function-calling) + +## Other Samples +* [Tracing using Application Insights](https://github.com/Azure/azure-ai-agents/tree/main/samples/tracing) +* [Personal Finance Agent](https://github.com/Azure/azure-ai-agents/tree/main/samples/investment_advisor) From 34be39916b83e06c897e0d90b77e5025dfb44de8 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 20 Nov 2024 12:25:41 -0800 Subject: [PATCH 170/180] adding json arm templates --- basic-agent-identity.json | 692 +++++++++++++++++++++++++++ basic-agent-keys.json | 647 +++++++++++++++++++++++++ standard-agent.json | 959 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 2298 insertions(+) create mode 100644 basic-agent-identity.json create mode 100644 basic-agent-keys.json create mode 100644 standard-agent.json diff --git a/basic-agent-identity.json b/basic-agent-identity.json new file mode 100644 index 00000000..8c2feda0 --- /dev/null +++ b/basic-agent-identity.json @@ -0,0 +1,692 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "3607113709869687219" + } + }, + "parameters": { + "aiHubName": { + "type": "string", + "defaultValue": "standard-hub", + "minLength": 2, + "maxLength": 12, + "metadata": { + "description": "Name for the AI resource and used to derive name of dependent resources." + } + }, + "aiHubFriendlyName": { + "type": "string", + "defaultValue": "Agents standard hub resource", + "metadata": { + "description": "Friendly name for your Azure AI resource" + } + }, + "aiHubDescription": { + "type": "string", + "defaultValue": "A standard hub resource required for the agent setup.", + "metadata": { + "description": "Description of your Azure AI resource dispayed in AI studio" + } + }, + "aiProjectName": { + "type": "string", + "defaultValue": "standard-project", + "metadata": { + "description": "Name for the project" + } + }, + "aiProjectFriendlyName": { + "type": "string", + "defaultValue": "Agents standard project resource", + "metadata": { + "description": "Friendly name for your Azure AI project resource" + } + }, + "aiProjectDescription": { + "type": "string", + "defaultValue": "A standard project resource required for the agent setup.", + "metadata": { + "description": "Description of your Azure AI project resource dispayed in AI studio" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Azure region used for the deployment of all resources." + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Set of tags to apply to all resources." + } + }, + "modelName": { + "type": "string", + "defaultValue": "gpt-4o-mini", + "metadata": { + "description": "Model name for deployment" + } + }, + "modelFormat": { + "type": "string", + "defaultValue": "OpenAI", + "metadata": { + "description": "Model format for deployment" + } + }, + "modelVersion": { + "type": "string", + "defaultValue": "2024-07-18", + "metadata": { + "description": "Model version for deployment" + } + }, + "modelSkuName": { + "type": "string", + "defaultValue": "GlobalStandard", + "metadata": { + "description": "Model deployment SKU name" + } + }, + "modelCapacity": { + "type": "int", + "defaultValue": 10, + "metadata": { + "description": "Model deployment capacity" + } + }, + "modelLocation": { + "type": "string", + "defaultValue": "eastus", + "metadata": { + "description": "Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created." + } + }, + "storageName": { + "type": "string", + "defaultValue": "agent-storage", + "metadata": { + "description": "Name of the storage account" + } + }, + "aiServicesName": { + "type": "string", + "defaultValue": "agent-ai-services", + "metadata": { + "description": "Name of the Azure AI Services account" + } + }, + "deploymentTimestamp": { + "type": "string", + "defaultValue": "[utcNow('yyyyMMddHHmmss')]" + } + }, + "variables": { + "name": "[toLower(format('{0}', parameters('aiHubName')))]", + "projectName": "[toLower(format('{0}', parameters('aiProjectName')))]", + "uniqueSuffix": "[substring(uniqueString(format('{0}-{1}', resourceGroup().id, parameters('deploymentTimestamp'))), 0, 4)]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiServicesName": { + "value": "[format('{0}{1}', parameters('aiServicesName'), variables('uniqueSuffix'))]" + }, + "storageName": { + "value": "[format('{0}{1}', parameters('storageName'), variables('uniqueSuffix'))]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "modelName": { + "value": "[parameters('modelName')]" + }, + "modelFormat": { + "value": "[parameters('modelFormat')]" + }, + "modelVersion": { + "value": "[parameters('modelVersion')]" + }, + "modelSkuName": { + "value": "[parameters('modelSkuName')]" + }, + "modelCapacity": { + "value": "[parameters('modelCapacity')]" + }, + "modelLocation": { + "value": "[parameters('modelLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "8251659815924226998" + } + }, + "parameters": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiServicesName": { + "type": "string", + "metadata": { + "description": "AI services name" + } + }, + "modelName": { + "type": "string", + "metadata": { + "description": "Model name for deployment" + } + }, + "modelFormat": { + "type": "string", + "metadata": { + "description": "Model format for deployment" + } + }, + "modelVersion": { + "type": "string", + "metadata": { + "description": "Model version for deployment" + } + }, + "modelSkuName": { + "type": "string", + "metadata": { + "description": "Model deployment SKU name" + } + }, + "modelCapacity": { + "type": "int", + "metadata": { + "description": "Model deployment capacity" + } + }, + "modelLocation": { + "type": "string", + "metadata": { + "description": "Model/AI Resource deployment location" + } + }, + "storageName": { + "type": "string", + "metadata": { + "description": "Name of the storage account" + } + }, + "storageSkuName": { + "type": "string", + "defaultValue": "Standard_LRS", + "allowedValues": [ + "Standard_LRS", + "Standard_ZRS", + "Standard_GRS", + "Standard_GZRS", + "Standard_RAGRS", + "Standard_RAGZRS", + "Premium_LRS", + "Premium_ZRS" + ], + "metadata": { + "description": "Storage SKU" + } + } + }, + "variables": { + "storageNameCleaned": "[replace(parameters('storageName'), '-', '')]" + }, + "resources": [ + { + "type": "Microsoft.CognitiveServices/accounts", + "apiVersion": "2024-06-01-preview", + "name": "[parameters('aiServicesName')]", + "location": "[parameters('modelLocation')]", + "sku": { + "name": "S0" + }, + "kind": "AIServices", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "customSubDomainName": "[toLower(format('{0}', toLower(parameters('aiServicesName'))))]", + "apiProperties": { + "statisticsEnabled": false + }, + "publicNetworkAccess": "Enabled" + } + }, + { + "type": "Microsoft.CognitiveServices/accounts/deployments", + "apiVersion": "2024-06-01-preview", + "name": "[format('{0}/{1}', parameters('aiServicesName'), parameters('modelName'))]", + "sku": { + "capacity": "[parameters('modelCapacity')]", + "name": "[parameters('modelSkuName')]" + }, + "properties": { + "model": { + "name": "[parameters('modelName')]", + "format": "[parameters('modelFormat')]", + "version": "[parameters('modelVersion')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName'))]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2023-05-01", + "name": "[variables('storageNameCleaned')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('storageSkuName')]" + }, + "kind": "StorageV2", + "properties": { + "accessTier": "Hot", + "allowBlobPublicAccess": false, + "allowCrossTenantReplication": false, + "allowSharedKeyAccess": true, + "encryption": { + "keySource": "Microsoft.Storage", + "requireInfrastructureEncryption": false, + "services": { + "blob": { + "enabled": true, + "keyType": "Account" + }, + "file": { + "enabled": true, + "keyType": "Account" + }, + "queue": { + "enabled": true, + "keyType": "Service" + }, + "table": { + "enabled": true, + "keyType": "Service" + } + } + }, + "isHnsEnabled": false, + "isNfsV3Enabled": false, + "keyPolicy": { + "keyExpirationPeriodInDays": 7 + }, + "largeFileSharesState": "Disabled", + "minimumTlsVersion": "TLS1_2", + "networkAcls": { + "bypass": "AzureServices", + "defaultAction": "Deny" + }, + "supportsHttpsTrafficOnly": true + } + } + ], + "outputs": { + "aiservicesID": { + "type": "string", + "value": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName'))]" + }, + "aiservicesTarget": { + "type": "string", + "value": "[reference(resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')), '2024-06-01-preview').endpoint]" + }, + "storageId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageNameCleaned'))]" + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiHubName": { + "value": "[format('ai-{0}-{1}', variables('name'), variables('uniqueSuffix'))]" + }, + "aiHubFriendlyName": { + "value": "[parameters('aiHubFriendlyName')]" + }, + "aiHubDescription": { + "value": "[parameters('aiHubDescription')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "modelLocation": { + "value": "[parameters('modelLocation')]" + }, + "storageAccountId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.storageId.value]" + }, + "aiServicesId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiservicesID.value]" + }, + "aiServicesTarget": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiservicesTarget.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "5580448247188524490" + } + }, + "parameters": { + "location": { + "type": "string", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiHubName": { + "type": "string", + "metadata": { + "description": "AI hub name" + } + }, + "aiHubFriendlyName": { + "type": "string", + "defaultValue": "[parameters('aiHubName')]", + "metadata": { + "description": "AI hub display name" + } + }, + "aiHubDescription": { + "type": "string", + "metadata": { + "description": "AI hub description" + } + }, + "storageAccountId": { + "type": "string", + "metadata": { + "description": "Resource ID of the storage account resource for storing experimentation outputs" + } + }, + "aiServicesId": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Services resource" + } + }, + "aiServicesTarget": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Services endpoint" + } + }, + "modelLocation": { + "type": "string", + "metadata": { + "description": "Model/AI Resource deployment location" + } + } + }, + "resources": [ + { + "type": "Microsoft.MachineLearningServices/workspaces/connections", + "apiVersion": "2024-07-01-preview", + "name": "[format('{0}/{1}', parameters('aiHubName'), format('{0}-connection-AIServices', parameters('aiHubName')))]", + "properties": { + "category": "AIServices", + "target": "[parameters('aiServicesTarget')]", + "authType": "AAD", + "isSharedToAll": true, + "metadata": { + "ApiType": "Azure", + "ResourceId": "[parameters('aiServicesId')]", + "Location": "[parameters('modelLocation')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + ] + }, + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2024-07-01-preview", + "name": "[parameters('aiHubName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('aiHubFriendlyName')]", + "description": "[parameters('aiHubDescription')]", + "storageAccount": "[parameters('storageAccountId')]" + }, + "kind": "hub" + } + ], + "outputs": { + "aiHubID": { + "type": "string", + "value": "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('ai-{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiProjectName": { + "value": "[format('ai-{0}-{1}', variables('projectName'), variables('uniqueSuffix'))]" + }, + "aiProjectFriendlyName": { + "value": "[parameters('aiProjectFriendlyName')]" + }, + "aiProjectDescription": { + "value": "[parameters('aiProjectDescription')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "aiServicesName": { + "value": "[format('{0}{1}', parameters('aiServicesName'), variables('uniqueSuffix'))]" + }, + "aiHubId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiHubID.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "18235459759430841665" + } + }, + "parameters": { + "location": { + "type": "string", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiProjectName": { + "type": "string", + "metadata": { + "description": "AI Project name" + } + }, + "aiProjectFriendlyName": { + "type": "string", + "defaultValue": "[parameters('aiProjectName')]", + "metadata": { + "description": "AI Project display name" + } + }, + "aiProjectDescription": { + "type": "string", + "metadata": { + "description": "AI Project description" + } + }, + "aiHubId": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Hub resource" + } + }, + "aiServicesName": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('aiProjectName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('aiProjectFriendlyName')]", + "description": "[parameters('aiProjectDescription')]", + "hubResourceId": "[parameters('aiHubId')]" + }, + "kind": "project" + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', parameters('aiServicesName'))]", + "name": "[guid(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), resourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68'), resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', parameters('aiServicesName'))]", + "name": "[guid(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'), resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', parameters('aiServicesName'))]", + "name": "[guid(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), resourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908'), resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + } + ], + "outputs": { + "aiProjectID": { + "type": "string", + "value": "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" + ] + } + ] +} \ No newline at end of file diff --git a/basic-agent-keys.json b/basic-agent-keys.json new file mode 100644 index 00000000..eea47722 --- /dev/null +++ b/basic-agent-keys.json @@ -0,0 +1,647 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "16944875249252966269" + } + }, + "parameters": { + "aiHubName": { + "type": "string", + "defaultValue": "standard-hub", + "minLength": 2, + "maxLength": 12, + "metadata": { + "description": "Name for the AI resource and used to derive name of dependent resources." + } + }, + "aiHubFriendlyName": { + "type": "string", + "defaultValue": "Agents standard hub resource", + "metadata": { + "description": "Friendly name for your Azure AI resource" + } + }, + "aiHubDescription": { + "type": "string", + "defaultValue": "A standard hub resource required for the agent setup.", + "metadata": { + "description": "Description of your Azure AI resource dispayed in AI studio" + } + }, + "aiProjectName": { + "type": "string", + "defaultValue": "standard-project", + "metadata": { + "description": "Name for the project" + } + }, + "aiProjectFriendlyName": { + "type": "string", + "defaultValue": "Agents standard project resource", + "metadata": { + "description": "Friendly name for your Azure AI resource" + } + }, + "aiProjectDescription": { + "type": "string", + "defaultValue": "A standard project resource required for the agent setup.", + "metadata": { + "description": "Description of your Azure AI resource dispayed in AI studio" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Azure region used for the deployment of all resources." + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Set of tags to apply to all resources." + } + }, + "modelName": { + "type": "string", + "defaultValue": "gpt-4o-mini", + "metadata": { + "description": "Model name for deployment" + } + }, + "modelFormat": { + "type": "string", + "defaultValue": "OpenAI", + "metadata": { + "description": "Model format for deployment" + } + }, + "modelVersion": { + "type": "string", + "defaultValue": "2024-07-18", + "metadata": { + "description": "Model version for deployment" + } + }, + "modelSkuName": { + "type": "string", + "defaultValue": "GlobalStandard", + "metadata": { + "description": "Model deployment SKU name" + } + }, + "modelCapacity": { + "type": "int", + "defaultValue": 10, + "metadata": { + "description": "Model deployment capacity" + } + }, + "modelLocation": { + "type": "string", + "defaultValue": "eastus", + "metadata": { + "description": "Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created." + } + }, + "storageName": { + "type": "string", + "defaultValue": "agent-storage", + "metadata": { + "description": "Name of the storage account" + } + }, + "aiServicesName": { + "type": "string", + "defaultValue": "agent-ai-services", + "metadata": { + "description": "Name of the Azure AI Services account" + } + }, + "deploymentTimestamp": { + "type": "string", + "defaultValue": "[utcNow('yyyyMMddHHmmss')]" + } + }, + "variables": { + "name": "[toLower(format('{0}', parameters('aiHubName')))]", + "projectName": "[toLower(format('{0}', parameters('aiProjectName')))]", + "uniqueSuffix": "[substring(uniqueString(format('{0}-{1}', resourceGroup().id, parameters('deploymentTimestamp'))), 0, 4)]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiServicesName": { + "value": "[format('{0}{1}', parameters('aiServicesName'), variables('uniqueSuffix'))]" + }, + "storageName": { + "value": "[format('{0}{1}', parameters('storageName'), variables('uniqueSuffix'))]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "modelName": { + "value": "[parameters('modelName')]" + }, + "modelFormat": { + "value": "[parameters('modelFormat')]" + }, + "modelVersion": { + "value": "[parameters('modelVersion')]" + }, + "modelSkuName": { + "value": "[parameters('modelSkuName')]" + }, + "modelCapacity": { + "value": "[parameters('modelCapacity')]" + }, + "modelLocation": { + "value": "[parameters('modelLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "8251659815924226998" + } + }, + "parameters": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiServicesName": { + "type": "string", + "metadata": { + "description": "AI services name" + } + }, + "modelName": { + "type": "string", + "metadata": { + "description": "Model name for deployment" + } + }, + "modelFormat": { + "type": "string", + "metadata": { + "description": "Model format for deployment" + } + }, + "modelVersion": { + "type": "string", + "metadata": { + "description": "Model version for deployment" + } + }, + "modelSkuName": { + "type": "string", + "metadata": { + "description": "Model deployment SKU name" + } + }, + "modelCapacity": { + "type": "int", + "metadata": { + "description": "Model deployment capacity" + } + }, + "modelLocation": { + "type": "string", + "metadata": { + "description": "Model/AI Resource deployment location" + } + }, + "storageName": { + "type": "string", + "metadata": { + "description": "Name of the storage account" + } + }, + "storageSkuName": { + "type": "string", + "defaultValue": "Standard_LRS", + "allowedValues": [ + "Standard_LRS", + "Standard_ZRS", + "Standard_GRS", + "Standard_GZRS", + "Standard_RAGRS", + "Standard_RAGZRS", + "Premium_LRS", + "Premium_ZRS" + ], + "metadata": { + "description": "Storage SKU" + } + } + }, + "variables": { + "storageNameCleaned": "[replace(parameters('storageName'), '-', '')]" + }, + "resources": [ + { + "type": "Microsoft.CognitiveServices/accounts", + "apiVersion": "2024-06-01-preview", + "name": "[parameters('aiServicesName')]", + "location": "[parameters('modelLocation')]", + "sku": { + "name": "S0" + }, + "kind": "AIServices", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "customSubDomainName": "[toLower(format('{0}', toLower(parameters('aiServicesName'))))]", + "apiProperties": { + "statisticsEnabled": false + }, + "publicNetworkAccess": "Enabled" + } + }, + { + "type": "Microsoft.CognitiveServices/accounts/deployments", + "apiVersion": "2024-06-01-preview", + "name": "[format('{0}/{1}', parameters('aiServicesName'), parameters('modelName'))]", + "sku": { + "capacity": "[parameters('modelCapacity')]", + "name": "[parameters('modelSkuName')]" + }, + "properties": { + "model": { + "name": "[parameters('modelName')]", + "format": "[parameters('modelFormat')]", + "version": "[parameters('modelVersion')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName'))]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2023-05-01", + "name": "[variables('storageNameCleaned')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('storageSkuName')]" + }, + "kind": "StorageV2", + "properties": { + "accessTier": "Hot", + "allowBlobPublicAccess": false, + "allowCrossTenantReplication": false, + "allowSharedKeyAccess": true, + "encryption": { + "keySource": "Microsoft.Storage", + "requireInfrastructureEncryption": false, + "services": { + "blob": { + "enabled": true, + "keyType": "Account" + }, + "file": { + "enabled": true, + "keyType": "Account" + }, + "queue": { + "enabled": true, + "keyType": "Service" + }, + "table": { + "enabled": true, + "keyType": "Service" + } + } + }, + "isHnsEnabled": false, + "isNfsV3Enabled": false, + "keyPolicy": { + "keyExpirationPeriodInDays": 7 + }, + "largeFileSharesState": "Disabled", + "minimumTlsVersion": "TLS1_2", + "networkAcls": { + "bypass": "AzureServices", + "defaultAction": "Deny" + }, + "supportsHttpsTrafficOnly": true + } + } + ], + "outputs": { + "aiservicesID": { + "type": "string", + "value": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName'))]" + }, + "aiservicesTarget": { + "type": "string", + "value": "[reference(resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')), '2024-06-01-preview').endpoint]" + }, + "storageId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageNameCleaned'))]" + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiHubName": { + "value": "[format('ai-{0}-{1}', variables('name'), variables('uniqueSuffix'))]" + }, + "aiHubFriendlyName": { + "value": "[parameters('aiHubFriendlyName')]" + }, + "aiHubDescription": { + "value": "[parameters('aiHubDescription')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "modelLocation": { + "value": "[parameters('modelLocation')]" + }, + "storageAccountId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.storageId.value]" + }, + "aiServicesId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiservicesID.value]" + }, + "aiServicesTarget": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiservicesTarget.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "6462883308359606930" + } + }, + "parameters": { + "location": { + "type": "string", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiHubName": { + "type": "string", + "metadata": { + "description": "AI hub name" + } + }, + "aiHubFriendlyName": { + "type": "string", + "defaultValue": "[parameters('aiHubName')]", + "metadata": { + "description": "AI hub display name" + } + }, + "aiHubDescription": { + "type": "string", + "metadata": { + "description": "AI hub description" + } + }, + "storageAccountId": { + "type": "string", + "metadata": { + "description": "Resource ID of the storage account resource for storing experimentation outputs" + } + }, + "aiServicesId": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Services resource" + } + }, + "aiServicesTarget": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Services endpoint" + } + }, + "modelLocation": { + "type": "string", + "metadata": { + "description": "Model/AI Resource deployment location" + } + } + }, + "resources": [ + { + "type": "Microsoft.MachineLearningServices/workspaces/connections", + "apiVersion": "2024-07-01-preview", + "name": "[format('{0}/{1}', parameters('aiHubName'), format('{0}-connection-AIServices', parameters('aiHubName')))]", + "properties": { + "category": "AIServices", + "target": "[parameters('aiServicesTarget')]", + "authType": "ApiKey", + "isSharedToAll": true, + "credentials": { + "key": "[format('{0}', listKeys(parameters('aiServicesId'), '2022-10-01').key1)]" + }, + "metadata": { + "ApiType": "Azure", + "ResourceId": "[parameters('aiServicesId')]", + "Location": "[parameters('modelLocation')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + ] + }, + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2024-07-01-preview", + "name": "[parameters('aiHubName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('aiHubFriendlyName')]", + "description": "[parameters('aiHubDescription')]", + "storageAccount": "[parameters('storageAccountId')]" + }, + "kind": "hub" + } + ], + "outputs": { + "aiHubID": { + "type": "string", + "value": "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('ai-{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiProjectName": { + "value": "[format('ai-{0}-{1}', variables('projectName'), variables('uniqueSuffix'))]" + }, + "aiProjectFriendlyName": { + "value": "[parameters('aiProjectFriendlyName')]" + }, + "aiProjectDescription": { + "value": "[parameters('aiProjectDescription')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "aiHubId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiHubID.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.92.45157", + "templateHash": "14604927427609317320" + } + }, + "parameters": { + "location": { + "type": "string", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiProjectName": { + "type": "string", + "metadata": { + "description": "AI Project name" + } + }, + "aiProjectFriendlyName": { + "type": "string", + "defaultValue": "[parameters('aiProjectName')]", + "metadata": { + "description": "AI Project display name" + } + }, + "aiProjectDescription": { + "type": "string", + "metadata": { + "description": "AI Project description" + } + }, + "aiHubId": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Hub resource" + } + } + }, + "resources": [ + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('aiProjectName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('aiProjectFriendlyName')]", + "description": "[parameters('aiProjectDescription')]", + "hubResourceId": "[parameters('aiHubId')]" + }, + "kind": "project" + } + ], + "outputs": { + "aiProjectID": { + "type": "string", + "value": "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" + ] + } + ] +} \ No newline at end of file diff --git a/standard-agent.json b/standard-agent.json new file mode 100644 index 00000000..76bf1dd2 --- /dev/null +++ b/standard-agent.json @@ -0,0 +1,959 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.34.60546", + "templateHash": "4179746770464772620" + } + }, + "parameters": { + "aiHubName": { + "type": "string", + "defaultValue": "hub-demo", + "minLength": 2, + "maxLength": 12, + "metadata": { + "description": "Name for the AI resource and used to derive name of dependent resources." + } + }, + "aiHubFriendlyName": { + "type": "string", + "defaultValue": "Agents Hub resource", + "metadata": { + "description": "Friendly name for your Hub resource" + } + }, + "aiHubDescription": { + "type": "string", + "defaultValue": "This is an example AI resource for use in Azure AI Studio.", + "metadata": { + "description": "Description of your Azure AI resource dispayed in AI studio" + } + }, + "aiProjectName": { + "type": "string", + "defaultValue": "project-demo", + "metadata": { + "description": "Name for the AI project resources." + } + }, + "aiProjectFriendlyName": { + "type": "string", + "defaultValue": "Agents Project resource", + "metadata": { + "description": "Friendly name for your Azure AI resource" + } + }, + "aiProjectDescription": { + "type": "string", + "defaultValue": "This is an example AI Project resource for use in Azure AI Studio.", + "metadata": { + "description": "Description of your Azure AI resource dispayed in AI studio" + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Azure region used for the deployment of all resources." + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Set of tags to apply to all resources." + } + }, + "aiSearchName": { + "type": "string", + "defaultValue": "agent-ai-search", + "metadata": { + "description": "Name of the Azure AI Search account" + } + }, + "capabilityHostName": { + "type": "string", + "defaultValue": "caphost1", + "metadata": { + "description": "Name for capabilityHost." + } + }, + "storageName": { + "type": "string", + "defaultValue": "agent-storage", + "metadata": { + "description": "Name of the storage account" + } + }, + "aiServicesName": { + "type": "string", + "defaultValue": "agent-ai-services", + "metadata": { + "description": "Name of the Azure AI Services account" + } + }, + "modelName": { + "type": "string", + "defaultValue": "gpt-4o-mini", + "metadata": { + "description": "Model name for deployment" + } + }, + "modelFormat": { + "type": "string", + "defaultValue": "OpenAI", + "metadata": { + "description": "Model format for deployment" + } + }, + "modelVersion": { + "type": "string", + "defaultValue": "2024-07-18", + "metadata": { + "description": "Model version for deployment" + } + }, + "modelSkuName": { + "type": "string", + "defaultValue": "GlobalStandard", + "metadata": { + "description": "Model deployment SKU name" + } + }, + "modelCapacity": { + "type": "int", + "defaultValue": 10, + "metadata": { + "description": "Model deployment capacity" + } + }, + "modelLocation": { + "type": "string", + "defaultValue": "eastus", + "metadata": { + "description": "Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created." + } + }, + "deploymentTimestamp": { + "type": "string", + "defaultValue": "[utcNow('yyyyMMddHHmmss')]" + } + }, + "variables": { + "name": "[toLower(format('{0}', parameters('aiHubName')))]", + "projectName": "[toLower(format('{0}', parameters('aiProjectName')))]", + "uniqueSuffix": "[substring(uniqueString(format('{0}-{1}', resourceGroup().id, parameters('deploymentTimestamp'))), 0, 4)]" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "location": { + "value": "[parameters('location')]" + }, + "storageName": { + "value": "[format('{0}{1}', parameters('storageName'), variables('uniqueSuffix'))]" + }, + "keyvaultName": { + "value": "[format('kv-{0}-{1}', variables('name'), variables('uniqueSuffix'))]" + }, + "aiServicesName": { + "value": "[format('{0}{1}', parameters('aiServicesName'), variables('uniqueSuffix'))]" + }, + "aiSearchName": { + "value": "[format('{0}-{1}', parameters('aiSearchName'), variables('uniqueSuffix'))]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "modelName": { + "value": "[parameters('modelName')]" + }, + "modelFormat": { + "value": "[parameters('modelFormat')]" + }, + "modelVersion": { + "value": "[parameters('modelVersion')]" + }, + "modelSkuName": { + "value": "[parameters('modelSkuName')]" + }, + "modelCapacity": { + "value": "[parameters('modelCapacity')]" + }, + "modelLocation": { + "value": "[parameters('modelLocation')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.34.60546", + "templateHash": "15472978165973317626" + } + }, + "parameters": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiServicesName": { + "type": "string", + "metadata": { + "description": "AI services name" + } + }, + "keyvaultName": { + "type": "string", + "metadata": { + "description": "The name of the Key Vault" + } + }, + "aiSearchName": { + "type": "string", + "metadata": { + "description": "The name of the AI Search resource" + } + }, + "storageName": { + "type": "string", + "metadata": { + "description": "Name of the storage account" + } + }, + "modelName": { + "type": "string", + "metadata": { + "description": "Model name for deployment" + } + }, + "modelFormat": { + "type": "string", + "metadata": { + "description": "Model format for deployment" + } + }, + "modelVersion": { + "type": "string", + "metadata": { + "description": "Model version for deployment" + } + }, + "modelSkuName": { + "type": "string", + "metadata": { + "description": "Model deployment SKU name" + } + }, + "modelCapacity": { + "type": "int", + "metadata": { + "description": "Model deployment capacity" + } + }, + "modelLocation": { + "type": "string", + "metadata": { + "description": "Model/AI Resource deployment location" + } + }, + "noZRSRegions": { + "type": "array", + "defaultValue": [ + "southindia", + "westus" + ] + }, + "sku": { + "type": "object", + "defaultValue": "[if(contains(parameters('noZRSRegions'), parameters('location')), createObject('name', 'Standard_GRS'), createObject('name', 'Standard_ZRS'))]" + } + }, + "variables": { + "storageNameCleaned": "[replace(parameters('storageName'), '-', '')]" + }, + "resources": [ + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyvaultName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "createMode": "default", + "enabledForDeployment": false, + "enabledForDiskEncryption": false, + "enabledForTemplateDeployment": false, + "enableSoftDelete": true, + "enableRbacAuthorization": true, + "enablePurgeProtection": true, + "networkAcls": { + "bypass": "AzureServices", + "defaultAction": "Deny" + }, + "sku": { + "family": "A", + "name": "standard" + }, + "softDeleteRetentionInDays": 7, + "tenantId": "[subscription().tenantId]" + } + }, + { + "type": "Microsoft.CognitiveServices/accounts", + "apiVersion": "2024-06-01-preview", + "name": "[parameters('aiServicesName')]", + "location": "[parameters('modelLocation')]", + "sku": { + "name": "S0" + }, + "kind": "AIServices", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "customSubDomainName": "[toLower(format('{0}', parameters('aiServicesName')))]", + "apiProperties": { + "statisticsEnabled": false + }, + "publicNetworkAccess": "Enabled" + } + }, + { + "type": "Microsoft.CognitiveServices/accounts/deployments", + "apiVersion": "2024-06-01-preview", + "name": "[format('{0}/{1}', parameters('aiServicesName'), parameters('modelName'))]", + "sku": { + "capacity": "[parameters('modelCapacity')]", + "name": "[parameters('modelSkuName')]" + }, + "properties": { + "model": { + "name": "[parameters('modelName')]", + "format": "[parameters('modelFormat')]", + "version": "[parameters('modelVersion')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName'))]" + ] + }, + { + "type": "Microsoft.Search/searchServices", + "apiVersion": "2024-06-01-preview", + "name": "[parameters('aiSearchName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "disableLocalAuth": false, + "authOptions": { + "aadOrApiKey": { + "aadAuthFailureMode": "http401WithBearerChallenge" + } + }, + "encryptionWithCmk": { + "enforcement": "Unspecified" + }, + "hostingMode": "default", + "partitionCount": 1, + "publicNetworkAccess": "enabled", + "replicaCount": 1, + "semanticSearch": "disabled" + }, + "sku": { + "name": "standard" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2022-05-01", + "name": "[variables('storageNameCleaned')]", + "location": "[parameters('location')]", + "kind": "StorageV2", + "sku": "[parameters('sku')]", + "properties": { + "minimumTlsVersion": "TLS1_2", + "allowBlobPublicAccess": false, + "publicNetworkAccess": "Enabled", + "networkAcls": { + "bypass": "AzureServices", + "defaultAction": "Allow", + "virtualNetworkRules": [] + }, + "allowSharedKeyAccess": false + } + } + ], + "outputs": { + "aiServicesName": { + "type": "string", + "value": "[parameters('aiServicesName')]" + }, + "aiservicesID": { + "type": "string", + "value": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName'))]" + }, + "aiservicesTarget": { + "type": "string", + "value": "[reference(resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')), '2024-06-01-preview').endpoint]" + }, + "aiSearchName": { + "type": "string", + "value": "[parameters('aiSearchName')]" + }, + "aisearchID": { + "type": "string", + "value": "[resourceId('Microsoft.Search/searchServices', parameters('aiSearchName'))]" + }, + "storageAccountName": { + "type": "string", + "value": "[variables('storageNameCleaned')]" + }, + "storageId": { + "type": "string", + "value": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageNameCleaned'))]" + }, + "keyvaultId": { + "type": "string", + "value": "[resourceId('Microsoft.KeyVault/vaults', parameters('keyvaultName'))]" + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiHubName": { + "value": "[format('ai-{0}-{1}', variables('name'), variables('uniqueSuffix'))]" + }, + "aiHubFriendlyName": { + "value": "[parameters('aiHubFriendlyName')]" + }, + "aiHubDescription": { + "value": "[parameters('aiHubDescription')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "capabilityHostName": { + "value": "[parameters('capabilityHostName')]" + }, + "modelLocation": { + "value": "[parameters('modelLocation')]" + }, + "aiSearchName": { + "value": "[format('{0}-{1}', parameters('aiSearchName'), variables('uniqueSuffix'))]" + }, + "aiSearchId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aisearchID.value]" + }, + "aiServicesId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiservicesID.value]" + }, + "aiServicesTarget": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiservicesTarget.value]" + }, + "keyVaultId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.keyvaultId.value]" + }, + "storageAccountId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.storageId.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.34.60546", + "templateHash": "9088426074194653241" + } + }, + "parameters": { + "location": { + "type": "string", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiHubName": { + "type": "string", + "metadata": { + "description": "AI hub name" + } + }, + "aiHubFriendlyName": { + "type": "string", + "defaultValue": "[parameters('aiHubName')]", + "metadata": { + "description": "AI hub display name" + } + }, + "aiHubDescription": { + "type": "string", + "metadata": { + "description": "AI hub description" + } + }, + "keyVaultId": { + "type": "string", + "metadata": { + "description": "Resource ID of the key vault resource for storing connection strings" + } + }, + "storageAccountId": { + "type": "string", + "metadata": { + "description": "Resource ID of the storage account resource for storing experimentation outputs" + } + }, + "modelLocation": { + "type": "string", + "metadata": { + "description": "Model/AI Resource deployment location" + } + }, + "aiServicesId": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Services resource" + } + }, + "aiServicesTarget": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Services endpoint" + } + }, + "aiSearchName": { + "type": "string", + "metadata": { + "description": "Name AI Search resource" + } + }, + "aiSearchId": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Search resource" + } + }, + "capabilityHostName": { + "type": "string", + "defaultValue": "caphost1", + "metadata": { + "description": "Name for capabilityHost." + } + } + }, + "variables": { + "acsConnectionName": "[format('{0}-connection-AISearch', parameters('aiHubName'))]", + "aoaiConnection": "[format('{0}-connection-AIServices_aoai', parameters('aiHubName'))]" + }, + "resources": [ + { + "type": "Microsoft.MachineLearningServices/workspaces/connections", + "apiVersion": "2024-07-01-preview", + "name": "[format('{0}/{1}', parameters('aiHubName'), format('{0}-connection-AIServices', parameters('aiHubName')))]", + "properties": { + "category": "AIServices", + "target": "[parameters('aiServicesTarget')]", + "authType": "AAD", + "isSharedToAll": true, + "metadata": { + "ApiType": "Azure", + "ResourceId": "[parameters('aiServicesId')]", + "location": "[parameters('modelLocation')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + ] + }, + { + "type": "Microsoft.MachineLearningServices/workspaces/connections", + "apiVersion": "2024-07-01-preview", + "name": "[format('{0}/{1}', parameters('aiHubName'), variables('acsConnectionName'))]", + "properties": { + "category": "CognitiveSearch", + "target": "[format('https://{0}.search.windows.net', parameters('aiSearchName'))]", + "authType": "AAD", + "isSharedToAll": true, + "metadata": { + "ApiType": "Azure", + "ResourceId": "[parameters('aiSearchId')]", + "location": "[parameters('location')]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + ] + }, + { + "type": "Microsoft.MachineLearningServices/workspaces/capabilityHosts", + "apiVersion": "2024-10-01-preview", + "name": "[format('{0}/{1}', parameters('aiHubName'), format('{0}-{1}', parameters('aiHubName'), parameters('capabilityHostName')))]", + "properties": { + "capabilityHostKind": "Agents" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + ] + }, + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2024-07-01-preview", + "name": "[parameters('aiHubName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('aiHubFriendlyName')]", + "description": "[parameters('aiHubDescription')]", + "keyVault": "[parameters('keyVaultId')]", + "storageAccount": "[parameters('storageAccountId')]" + }, + "kind": "hub" + } + ], + "outputs": { + "aiHubID": { + "type": "string", + "value": "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiHubName'))]" + }, + "aoaiConnectionName": { + "type": "string", + "value": "[variables('aoaiConnection')]" + }, + "acsConnectionName": { + "type": "string", + "value": "[variables('acsConnectionName')]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('ai-{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aiProjectName": { + "value": "[format('ai-{0}-{1}', variables('projectName'), variables('uniqueSuffix'))]" + }, + "aiProjectFriendlyName": { + "value": "[parameters('aiProjectFriendlyName')]" + }, + "aiProjectDescription": { + "value": "[parameters('aiProjectDescription')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "capabilityHostName": { + "value": "[parameters('capabilityHostName')]" + }, + "aiSearchName": { + "value": "[format('{0}-{1}', parameters('aiSearchName'), variables('uniqueSuffix'))]" + }, + "aiServicesName": { + "value": "[format('{0}{1}', parameters('aiServicesName'), variables('uniqueSuffix'))]" + }, + "aiStorageName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.storageAccountName.value]" + }, + "aiHubId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiHubID.value]" + }, + "acsConnectionName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.acsConnectionName.value]" + }, + "aoaiConnectionName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aoaiConnectionName.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.31.34.60546", + "templateHash": "8872693358960831805" + } + }, + "parameters": { + "location": { + "type": "string", + "metadata": { + "description": "Azure region of the deployment" + } + }, + "tags": { + "type": "object", + "metadata": { + "description": "Tags to add to the resources" + } + }, + "aiProjectName": { + "type": "string", + "metadata": { + "description": "AI Project name" + } + }, + "aiProjectFriendlyName": { + "type": "string", + "defaultValue": "[parameters('aiProjectName')]", + "metadata": { + "description": "AI Project display name" + } + }, + "aiProjectDescription": { + "type": "string", + "metadata": { + "description": "AI Project description" + } + }, + "aiHubId": { + "type": "string", + "metadata": { + "description": "Resource ID of the AI Hub resource" + } + }, + "capabilityHostName": { + "type": "string", + "defaultValue": "caphost1", + "metadata": { + "description": "Name for capabilityHost." + } + }, + "acsConnectionName": { + "type": "string", + "metadata": { + "description": "Name for ACS connection." + } + }, + "aoaiConnectionName": { + "type": "string", + "metadata": { + "description": "Name for ACS connection." + } + }, + "aiServicesName": { + "type": "string" + }, + "aiSearchName": { + "type": "string", + "metadata": { + "description": "Name AI Search resource" + } + }, + "aiStorageName": { + "type": "string", + "metadata": { + "description": "Name storage resource" + } + } + }, + "variables": { + "storageConnections": [ + "[format('{0}/workspaceblobstore', parameters('aiProjectName'))]" + ], + "aiSearchConnection": [ + "[format('{0}', parameters('acsConnectionName'))]" + ], + "aiServiceConnections": [ + "[format('{0}', parameters('aoaiConnectionName'))]" + ] + }, + "resources": [ + { + "type": "Microsoft.MachineLearningServices/workspaces/capabilityHosts", + "apiVersion": "2024-10-01-preview", + "name": "[format('{0}/{1}', parameters('aiProjectName'), format('{0}-{1}', parameters('aiProjectName'), parameters('capabilityHostName')))]", + "properties": { + "capabilityHostKind": "Agents", + "aiServicesConnections": "[variables('aiServiceConnections')]", + "vectorStoreConnections": "[variables('aiSearchConnection')]", + "storageConnections": "[variables('storageConnections')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + }, + { + "type": "Microsoft.MachineLearningServices/workspaces", + "apiVersion": "2023-08-01-preview", + "name": "[parameters('aiProjectName')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": { + "type": "SystemAssigned" + }, + "properties": { + "friendlyName": "[parameters('aiProjectFriendlyName')]", + "description": "[parameters('aiProjectDescription')]", + "hubResourceId": "[parameters('aiHubId')]" + }, + "kind": "project" + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', parameters('aiServicesName'))]", + "name": "[guid(resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')), resourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68'), resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', parameters('aiServicesName'))]", + "name": "[guid(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'), resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.CognitiveServices/accounts/{0}', parameters('aiServicesName'))]", + "name": "[guid(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), resourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908'), resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Search/searchServices/{0}', parameters('aiSearchName'))]", + "name": "[guid(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), resourceId('Microsoft.Authorization/roleDefinitions', '8ebe5a00-799e-43f5-93ac-243d3dce84a7'), resourceId('Microsoft.Search/searchServices', parameters('aiSearchName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '8ebe5a00-799e-43f5-93ac-243d3dce84a7')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Search/searchServices/{0}', parameters('aiSearchName'))]", + "name": "[guid(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), resourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0'), resourceId('Microsoft.Search/searchServices', parameters('aiSearchName')))]", + "properties": { + "principalId": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').identity.principalId]", + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0')]", + "principalType": "ServicePrincipal" + }, + "dependsOn": [ + "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + ] + } + ], + "outputs": { + "aiProjectName": { + "type": "string", + "value": "[parameters('aiProjectName')]" + }, + "aiProjectResourceId": { + "type": "string", + "value": "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName'))]" + }, + "aiProjectWorkspaceId": { + "type": "string", + "value": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview').workspaceId]" + }, + "enterpriseAgentsEndpoint": { + "type": "string", + "value": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').tags.AgentsEndpointUri]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]", + "[resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" + ] + } + ], + "outputs": { + "ENTERPRISE_AGENTS_ENDPOINT": { + "type": "string", + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))), '2022-09-01').outputs.enterpriseAgentsEndpoint.value]" + } + } +} \ No newline at end of file From 2a7bffd1c0534c3f5336a2bd6803cc976f5a20b9 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 20 Nov 2024 13:19:59 -0800 Subject: [PATCH 171/180] updating model capacity --- basic-agent-identity.bicep | 2 +- basic-agent-identity.json | 2 +- basic-agent-keys.bicep | 2 +- basic-agent-keys.json | 2 +- basic-agent.parameters.json | 2 +- quickstart.md | 6 +++--- standard-agent.bicep | 2 +- standard-agent.json | 2 +- standard-agent.parameters.json | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/basic-agent-identity.bicep b/basic-agent-identity.bicep index 5a480a94..4f846716 100644 --- a/basic-agent-identity.bicep +++ b/basic-agent-identity.bicep @@ -40,7 +40,7 @@ param modelVersion string = '2024-07-18' param modelSkuName string = 'GlobalStandard' @description('Model deployment capacity') -param modelCapacity int = 10 +param modelCapacity int = 50 @description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') param modelLocation string = 'eastus' diff --git a/basic-agent-identity.json b/basic-agent-identity.json index 8c2feda0..a22f97b6 100644 --- a/basic-agent-identity.json +++ b/basic-agent-identity.json @@ -97,7 +97,7 @@ }, "modelCapacity": { "type": "int", - "defaultValue": 10, + "defaultValue": 50, "metadata": { "description": "Model deployment capacity" } diff --git a/basic-agent-keys.bicep b/basic-agent-keys.bicep index d252e23b..65a43185 100644 --- a/basic-agent-keys.bicep +++ b/basic-agent-keys.bicep @@ -40,7 +40,7 @@ param modelVersion string = '2024-07-18' param modelSkuName string = 'GlobalStandard' @description('Model deployment capacity') -param modelCapacity int = 10 +param modelCapacity int = 50 @description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') param modelLocation string = 'eastus' diff --git a/basic-agent-keys.json b/basic-agent-keys.json index eea47722..30c980a4 100644 --- a/basic-agent-keys.json +++ b/basic-agent-keys.json @@ -97,7 +97,7 @@ }, "modelCapacity": { "type": "int", - "defaultValue": 10, + "defaultValue": 50, "metadata": { "description": "Model deployment capacity" } diff --git a/basic-agent.parameters.json b/basic-agent.parameters.json index bbd56445..1bbb3a73 100644 --- a/basic-agent.parameters.json +++ b/basic-agent.parameters.json @@ -21,7 +21,7 @@ "value": "GlobalStandard" }, "modelCapacity": { - "value": 10 + "value": 50 }, "modelLocation": { "value": "eastus" diff --git a/quickstart.md b/quickstart.md index a22eacf0..59d84929 100644 --- a/quickstart.md +++ b/quickstart.md @@ -75,9 +75,9 @@ If you already have these resources set up, skip to the [configure and run your | Template | Description | Auto-deploy | | ------------------- | -----------------------------------------------| -----------------------| - |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-identity.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAEU5UTLTW3A6Z3APQAZZ4AQNA) - |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fbasic-agent-keys.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE36JD2ZDYQYKAOBCIZZ4ASBQ) - | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://portal.azure.com/#create/Microsoft.Template/uri/https://aka.ms/deploytoazurebutton)](https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Fmain%2Fstandard-agent.bicep%3Ftoken%3DGHSAT0AAAAAACZNMQAE2AKFTITYODN3T62QZZ4BGYQ) + |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-keys.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGRUUYPILZH2RVUZCZZ6KQ6Q) + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) + | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fstandard-agent.json%3Ftoken%3DGHSAT0AAAAAACZNMQAEN6NEEEU76OQBPN62ZZ6KYGQ) **Manually Deploy Templates** diff --git a/standard-agent.bicep b/standard-agent.bicep index a5d1e9b1..9d474991 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -52,7 +52,7 @@ param modelVersion string = '2024-07-18' param modelSkuName string = 'GlobalStandard' @description('Model deployment capacity') -param modelCapacity int = 10 +param modelCapacity int = 50 @description('Model deployment location. If you want to deploy an Azure AI resource/model in different location than the rest of the resources created.') param modelLocation string = 'eastus' diff --git a/standard-agent.json b/standard-agent.json index 76bf1dd2..6ffc9eb9 100644 --- a/standard-agent.json +++ b/standard-agent.json @@ -125,7 +125,7 @@ }, "modelCapacity": { "type": "int", - "defaultValue": 10, + "defaultValue": 50, "metadata": { "description": "Model deployment capacity" } diff --git a/standard-agent.parameters.json b/standard-agent.parameters.json index 67c336ba..c8258086 100644 --- a/standard-agent.parameters.json +++ b/standard-agent.parameters.json @@ -48,7 +48,7 @@ "value": "GlobalStandard" }, "modelCapacity": { - "value": 10 + "value": 50 }, "modelLocation": { "value": "eastus" From 75666ff34a0d4744cf6536db2c755cc1e85d7abf Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 20 Nov 2024 13:50:12 -0800 Subject: [PATCH 172/180] Update quickstart.md --- quickstart.md | 1 - 1 file changed, 1 deletion(-) diff --git a/quickstart.md b/quickstart.md index 59d84929..9bad774a 100644 --- a/quickstart.md +++ b/quickstart.md @@ -163,7 +163,6 @@ If you already have these resources set up, skip to the [configure and run your

    -
    Option 3: Follow steps 6-10 if you want specific control over the creation and configuration of these resources. From 0be5f2e8b3c5633464c1e7c1dbed51b8c2c8d87b Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 20 Nov 2024 16:39:16 -0800 Subject: [PATCH 173/180] Update quickstart.md --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index 9bad774a..4f398616 100644 --- a/quickstart.md +++ b/quickstart.md @@ -76,8 +76,8 @@ If you already have these resources set up, skip to the [configure and run your | Template | Description | Auto-deploy | | ------------------- | -----------------------------------------------| -----------------------| |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-keys.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGRUUYPILZH2RVUZCZZ6KQ6Q) - |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) - | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authetication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fstandard-agent.json%3Ftoken%3DGHSAT0AAAAAACZNMQAEN6NEEEU76OQBPN62ZZ6KYGQ) + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) + | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fstandard-agent.json%3Ftoken%3DGHSAT0AAAAAACZNMQAEN6NEEEU76OQBPN62ZZ6KYGQ) **Manually Deploy Templates** From 76a2742c63ad1a19ab9312f038a331e3d005b043 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 20 Nov 2024 18:45:58 -0800 Subject: [PATCH 174/180] Update quickstart.md - removing deploy buttons --- quickstart.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/quickstart.md b/quickstart.md index 4f398616..ec62e17f 100644 --- a/quickstart.md +++ b/quickstart.md @@ -73,14 +73,6 @@ If you already have these resources set up, skip to the [configure and run your
    - | Template | Description | Auto-deploy | - | ------------------- | -----------------------------------------------| -----------------------| - |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-keys.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGRUUYPILZH2RVUZCZZ6KQ6Q) - |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) - | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fstandard-agent.json%3Ftoken%3DGHSAT0AAAAAACZNMQAEN6NEEEU76OQBPN62ZZ6KYGQ) - - - **Manually Deploy Templates**
    Option 1: Use basic agent setup. From 09e899aead7009fee2e673a1d136851b5c58e1fd Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Wed, 20 Nov 2024 18:48:31 -0800 Subject: [PATCH 175/180] adding deploy buttons --- quickstart.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/quickstart.md b/quickstart.md index ec62e17f..e951c8cf 100644 --- a/quickstart.md +++ b/quickstart.md @@ -72,6 +72,15 @@ If you already have these resources set up, skip to the [configure and run your **Standard Setup**: Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage.
    + + | Template | Description | Auto-deploy | + | ------------------- | -----------------------------------------------| -----------------------| + |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-keys.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGRUUYPILZH2RVUZCZZ6KQ6Q) + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) + | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fstandard-agent.json%3Ftoken%3DGHSAT0AAAAAACZNMQAEN6NEEEU76OQBPN62ZZ6KYGQ) + + + **Manually Deploy Templates**
    Option 1: Use basic agent setup. From 5d1c2f05aa7da62e49eb832bdb1125d369783262 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Thu, 21 Nov 2024 13:45:12 -0800 Subject: [PATCH 176/180] Update quickstart.md Add link to Llama model deployment guide. Temporary fix until bicep is updated. --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index ec62e17f..db0ccdd0 100644 --- a/quickstart.md +++ b/quickstart.md @@ -114,7 +114,7 @@ If you already have these resources set up, skip to the [configure and run your az deployment group create --resource-group {my_resource_group} --template-file {my-template-file.bicep} --parameters @basic-agent.parameters.json ``` - Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. + Resources for the hub, project, storage account, and AI Services will be created for you. The AI Services account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. A Microsoft-managed key vault will be used by default. To deploy a Llama model see [here](https://github.com/Azure/azure-ai-agents/blob/main/samples/llama-3.md).
    @@ -147,7 +147,7 @@ If you already have these resources set up, skip to the [configure and run your az deployment group create --resource-group {my_resource_group} --template-file standard-agent.bicep --parameters @standard-agent.parameters.json ``` - Resources for the hub, project, storage account, key vault, AI Services, and Azure AI Search will be created for you. The AI Services, AI Search, and Azure Blob Storage account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. + Resources for the hub, project, storage account, key vault, AI Services, and Azure AI Search will be created for you. The AI Services, AI Search, and Azure Blob Storage account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the eastus region. To deploy a Llama model see [here](https://github.com/Azure/azure-ai-agents/blob/main/samples/llama-3.md).
    From 8caff7999a33afee749af5fea9c9bdee92085264 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 25 Nov 2024 11:38:13 -0800 Subject: [PATCH 177/180] adding project connection output --- modules-standard/standard-ai-project.bicep | 17 ++++--- standard-agent.bicep | 15 +++--- standard-agent.json | 59 ++++++++++------------ 3 files changed, 42 insertions(+), 49 deletions(-) diff --git a/modules-standard/standard-ai-project.bicep b/modules-standard/standard-ai-project.bicep index bd2e6c70..a80d550d 100644 --- a/modules-standard/standard-ai-project.bicep +++ b/modules-standard/standard-ai-project.bicep @@ -32,9 +32,6 @@ param aiServicesName string @description('Name AI Search resource') param aiSearchName string -@description('Name storage resource') -param aiStorageName string - resource aiServices 'Microsoft.CognitiveServices/accounts@2024-06-01-preview' existing = { name: aiServicesName } @@ -43,9 +40,11 @@ resource searchService 'Microsoft.Search/searchServices@2024-06-01-preview' exis name: aiSearchName } -resource storageAccount 'Microsoft.Storage/storageAccounts@2024-06-01-preview' existing = { - name: aiStorageName -} +//for constructing endpoint +var subscriptionId = subscription().subscriptionId +var resourceGroupName = resourceGroup().name + +var projectConnectionString = '${location}.api.azureml.ms;${subscriptionId};${resourceGroupName};${aiProjectName}' var storageConnections = ['${aiProjectName}/workspaceblobstore'] @@ -56,7 +55,9 @@ var aiServiceConnections = ['${aoaiConnectionName}'] resource aiProject 'Microsoft.MachineLearningServices/workspaces@2023-08-01-preview' = { name: aiProjectName location: location - tags: tags + tags: union(tags, { + ProjectConnectionString: projectConnectionString + }) identity: { type: 'SystemAssigned' } @@ -162,4 +163,4 @@ resource searchServiceContributorRoleAssignment 'Microsoft.Authorization/roleAss output aiProjectName string = aiProject.name output aiProjectResourceId string = aiProject.id output aiProjectWorkspaceId string = aiProject.properties.workspaceId -output enterpriseAgentsEndpoint string = aiProject.tags.AgentsEndpointUri +output projectConnectionString string = aiProject.tags.ProjectConnectionString diff --git a/standard-agent.bicep b/standard-agent.bicep index 9d474991..d2ad0989 100644 --- a/standard-agent.bicep +++ b/standard-agent.bicep @@ -90,15 +90,15 @@ module aiDependencies 'modules-standard/standard-dependent-resources.bicep' = { } module aiHub 'modules-standard/standard-ai-hub.bicep' = { - name: 'ai-${name}-${uniqueSuffix}-deployment' + name: '${name}-${uniqueSuffix}-deployment' params: { // workspace organization - aiHubName: 'ai-${name}-${uniqueSuffix}' + aiHubName: '${name}-${uniqueSuffix}' aiHubFriendlyName: aiHubFriendlyName aiHubDescription: aiHubDescription location: location tags: tags - capabilityHostName: capabilityHostName + capabilityHostName: '${name}-${uniqueSuffix}-${capabilityHostName}' modelLocation: modelLocation @@ -113,25 +113,24 @@ module aiHub 'modules-standard/standard-ai-hub.bicep' = { module aiProject 'modules-standard/standard-ai-project.bicep' = { - name: 'ai-${projectName}-${uniqueSuffix}-deployment' + name: '${projectName}-${uniqueSuffix}-deployment' params: { // workspace organization - aiProjectName: 'ai-${projectName}-${uniqueSuffix}' + aiProjectName: '${projectName}-${uniqueSuffix}' aiProjectFriendlyName: aiProjectFriendlyName aiProjectDescription: aiProjectDescription location: location tags: tags - capabilityHostName: capabilityHostName + capabilityHostName: '${projectName}-${uniqueSuffix}-${capabilityHostName}' // dependent resources aiSearchName: '${aiSearchName}-${uniqueSuffix}' aiServicesName: '${aiServicesName}${uniqueSuffix}' - aiStorageName: aiDependencies.outputs.storageAccountName aiHubId: aiHub.outputs.aiHubID acsConnectionName: aiHub.outputs.acsConnectionName aoaiConnectionName: aiHub.outputs.aoaiConnectionName } } -output ENTERPRISE_AGENTS_ENDPOINT string = aiProject.outputs.enterpriseAgentsEndpoint +output PROJECT_CONNECTION_STRING string = aiProject.outputs.projectConnectionString diff --git a/standard-agent.json b/standard-agent.json index 6ffc9eb9..1fb110b2 100644 --- a/standard-agent.json +++ b/standard-agent.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.34.60546", - "templateHash": "4179746770464772620" + "version": "0.31.92.45157", + "templateHash": "1114174486229467923" } }, "parameters": { @@ -201,8 +201,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.34.60546", - "templateHash": "15472978165973317626" + "version": "0.31.92.45157", + "templateHash": "12339427843824755564" } }, "parameters": { @@ -450,7 +450,7 @@ { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", + "name": "[format('{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -458,7 +458,7 @@ "mode": "Incremental", "parameters": { "aiHubName": { - "value": "[format('ai-{0}-{1}', variables('name'), variables('uniqueSuffix'))]" + "value": "[format('{0}-{1}', variables('name'), variables('uniqueSuffix'))]" }, "aiHubFriendlyName": { "value": "[parameters('aiHubFriendlyName')]" @@ -473,7 +473,7 @@ "value": "[parameters('tags')]" }, "capabilityHostName": { - "value": "[parameters('capabilityHostName')]" + "value": "[format('{0}-{1}-{2}', variables('name'), variables('uniqueSuffix'), parameters('capabilityHostName'))]" }, "modelLocation": { "value": "[parameters('modelLocation')]" @@ -503,8 +503,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.34.60546", - "templateHash": "9088426074194653241" + "version": "0.31.92.45157", + "templateHash": "68227875889195354" } }, "parameters": { @@ -684,7 +684,7 @@ { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('ai-{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))]", + "name": "[format('{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -692,7 +692,7 @@ "mode": "Incremental", "parameters": { "aiProjectName": { - "value": "[format('ai-{0}-{1}', variables('projectName'), variables('uniqueSuffix'))]" + "value": "[format('{0}-{1}', variables('projectName'), variables('uniqueSuffix'))]" }, "aiProjectFriendlyName": { "value": "[parameters('aiProjectFriendlyName')]" @@ -707,7 +707,7 @@ "value": "[parameters('tags')]" }, "capabilityHostName": { - "value": "[parameters('capabilityHostName')]" + "value": "[format('{0}-{1}-{2}', variables('projectName'), variables('uniqueSuffix'), parameters('capabilityHostName'))]" }, "aiSearchName": { "value": "[format('{0}-{1}', parameters('aiSearchName'), variables('uniqueSuffix'))]" @@ -715,17 +715,14 @@ "aiServicesName": { "value": "[format('{0}{1}', parameters('aiServicesName'), variables('uniqueSuffix'))]" }, - "aiStorageName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.storageAccountName.value]" - }, "aiHubId": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiHubID.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aiHubID.value]" }, "acsConnectionName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.acsConnectionName.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.acsConnectionName.value]" }, "aoaiConnectionName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aoaiConnectionName.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-{1}-deployment', variables('name'), variables('uniqueSuffix'))), '2022-09-01').outputs.aoaiConnectionName.value]" } }, "template": { @@ -734,8 +731,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.34.60546", - "templateHash": "8872693358960831805" + "version": "0.31.92.45157", + "templateHash": "5076019979158593319" } }, "parameters": { @@ -803,15 +800,12 @@ "metadata": { "description": "Name AI Search resource" } - }, - "aiStorageName": { - "type": "string", - "metadata": { - "description": "Name storage resource" - } } }, "variables": { + "subscriptionId": "[subscription().subscriptionId]", + "resourceGroupName": "[resourceGroup().name]", + "projectConnectionString": "[format('{0}.api.azureml.ms;{1};{2};{3}', parameters('location'), variables('subscriptionId'), variables('resourceGroupName'), parameters('aiProjectName'))]", "storageConnections": [ "[format('{0}/workspaceblobstore', parameters('aiProjectName'))]" ], @@ -842,7 +836,7 @@ "apiVersion": "2023-08-01-preview", "name": "[parameters('aiProjectName')]", "location": "[parameters('location')]", - "tags": "[parameters('tags')]", + "tags": "[union(parameters('tags'), createObject('ProjectConnectionString', variables('projectConnectionString')))]", "identity": { "type": "SystemAssigned" }, @@ -937,23 +931,22 @@ "type": "string", "value": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview').workspaceId]" }, - "enterpriseAgentsEndpoint": { + "projectConnectionString": { "type": "string", - "value": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').tags.AgentsEndpointUri]" + "value": "[reference(resourceId('Microsoft.MachineLearningServices/workspaces', parameters('aiProjectName')), '2023-08-01-preview', 'full').tags.ProjectConnectionString]" } } } }, "dependsOn": [ - "[resourceId('Microsoft.Resources/deployments', format('dependencies-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]", - "[resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" + "[resourceId('Microsoft.Resources/deployments', format('{0}-{1}-deployment', variables('name'), variables('uniqueSuffix')))]" ] } ], "outputs": { - "ENTERPRISE_AGENTS_ENDPOINT": { + "PROJECT_CONNECTION_STRING": { "type": "string", - "value": "[reference(resourceId('Microsoft.Resources/deployments', format('ai-{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))), '2022-09-01').outputs.enterpriseAgentsEndpoint.value]" + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-{1}-deployment', variables('projectName'), variables('uniqueSuffix'))), '2022-09-01').outputs.projectConnectionString.value]" } } } \ No newline at end of file From cacc048d7afad8237b939cad6a53dfc4ee6b6f06 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 25 Nov 2024 12:51:33 -0800 Subject: [PATCH 178/180] Update quickstart.md Adding clarity to agent setup --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index db0ccdd0..92b8c6ae 100644 --- a/quickstart.md +++ b/quickstart.md @@ -91,8 +91,8 @@ If you already have these resources set up, skip to the [configure and run your - basic-dependent-resources.bicep ``` - Before deploying resources, decide which configuration file to use: - - `basic-agent-keys.bicep`: Use this file to use API keys for authentication. - - `basic-agent-identity.bicep`: Use this file if you prefer Managed Identity to securely access resources without API keys. + - `basic-agent-keys.bicep`: Uses API key authentication on the AI Services/AOAI connection. + - `basic-agent-identity.bicep`: Uses Managed Identity authentication on the AI Services/AOAI connection. - Using the resource group you created in the previous step and one of the template files (either basic-agent-keys.bicep or basic-agent-identity.bicep), run one of the following commands: From 4c9a6ef24f009435af4cc0c4da5461b18ebcf532 Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 25 Nov 2024 14:49:56 -0800 Subject: [PATCH 179/180] updating link standard setup --- quickstart.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quickstart.md b/quickstart.md index e951c8cf..033acc82 100644 --- a/quickstart.md +++ b/quickstart.md @@ -75,9 +75,9 @@ If you already have these resources set up, skip to the [configure and run your | Template | Description | Auto-deploy | | ------------------- | -----------------------------------------------| -----------------------| - |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API keys for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-keys.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGRUUYPILZH2RVUZCZZ6KQ6Q) - |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) - | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity for authentication. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fstandard-agent.json%3Ftoken%3DGHSAT0AAAAAACZNMQAEN6NEEEU76OQBPN62ZZ6KYGQ) + |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API key authentication on the AI Services/AOAI connection. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-keys.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGRUUYPILZH2RVUZCZZ6KQ6Q) + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity authentication on the AI Services/AOAI connection. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) + | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity authentication on the AI Services/AOAI connection. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Frefs%2Fheads%2Fmaster%2Fquickstarts%2Fmicrosoft.azure-ai-agent-service%2Fstandard-agent%2Fazuredeploy.json) **Manually Deploy Templates** From 4582a0f8cc421a6edb532e2f2cb7019dfb9fa96c Mon Sep 17 00:00:00 2001 From: Amanda Foster Date: Mon, 25 Nov 2024 15:29:53 -0800 Subject: [PATCH 180/180] Update quickstart.md --- quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart.md b/quickstart.md index 033acc82..9cca9b97 100644 --- a/quickstart.md +++ b/quickstart.md @@ -75,8 +75,8 @@ If you already have these resources set up, skip to the [configure and run your | Template | Description | Auto-deploy | | ------------------- | -----------------------------------------------| -----------------------| - |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API key authentication on the AI Services/AOAI connection. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-keys.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGRUUYPILZH2RVUZCZZ6KQ6Q) - |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity authentication on the AI Services/AOAI connection. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-ai-agents%2Frefs%2Fheads%2Farm-template-updates%2Fbasic-agent-identity.json%3Ftoken%3DGHSAT0AAAAAACZNMQAFGV5RA2GPXABKXFLQZZ6KWGQ) + |`basic-agent-keys.bicep` | Deploy a basic agent setup that uses API key authentication on the AI Services/AOAI connection. | Coming Soon + |`basic-agent-identity.bicep`| Deploy a basic agent setup that uses Managed Identity authentication on the AI Services/AOAI connection. | Coming Soon | `standard-agent.bicep` | Deploy a standard agent setup that uses Managed Identity authentication on the AI Services/AOAI connection. | [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Frefs%2Fheads%2Fmaster%2Fquickstarts%2Fmicrosoft.azure-ai-agent-service%2Fstandard-agent%2Fazuredeploy.json)