Skip to content

Commit

Permalink
Merge pull request #225 from Azure-Samples/gk/autogen-nb
Browse files Browse the repository at this point in the history
add aca sessions example
  • Loading branch information
thegovind authored May 19, 2024
2 parents 6c4f86f + 0b1d7f4 commit 51d5d43
Show file tree
Hide file tree
Showing 7 changed files with 446 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.2"
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
1 change: 1 addition & 0 deletions agents/autogen/notebooks/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ACA_SESSIONS_ENDPOINT=<YOUR_SESSIONS_ENDPOINT>
9 changes: 9 additions & 0 deletions agents/autogen/notebooks/OAI_CONFIG_LIST.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"model": "gpt-4",
"api_key": "<YOUR_API_KEY>",
"api_type": "azure",
"base_url": "https://<YOUR_ENDPOINT>.openai.azure.com",
"api_version": "2023-12-01-preview"
}
]
327 changes: 327 additions & 0 deletions agents/autogen/notebooks/aca-sessions.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Azure Container Apps' Dynamic Sessions with Autogen\n",
"\n",
"Demonstrates how to use Dynamic Sessions feature of Azure Container Apps to execute code"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"! pip -qqq install pyautogen matplotlib yfinance python-dotenv azure-identity"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from typing import List\n",
"\n",
"from autogen import ConversableAgent, config_list_from_json\n",
"from autogen.coding import CodeBlock, CodeExecutor, CodeExtractor, CodeResult, MarkdownCodeExtractor\n",
"\n",
"import requests\n",
"from typing import List"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Setup Sessions pool and get Sessions endpoint\n",
"\n",
"Azure Container Apps is a serverless platform that enables you to run containerized workloads without managing the underlying infrastructure. Dynamic sessions adds the ability to execute untrusted code in secure, sandboxed environments at scale. [Learn more here](https://techcommunity.microsoft.com/t5/apps-on-azure-blog/new-secure-sandboxes-at-scale-with-azure-container-apps-dynamic/ba-p/4142148). \n",
"\n",
"![sessions](https://techcommunity.microsoft.com/t5/image/serverpage/image-id/581694i61DE419D1A04B7F5/image-size/large?v=v2&px=999)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Prerequisites\n",
"\n",
"1. Get the Pool endpoint from [Azure Container Apps - Sessions Code Interpreter](https://learn.microsoft.com/en-us/azure/container-apps/sessions-code-interpreter?tabs=azure-cli).\n",
"\n",
"2. Copy `.env.example` to `.env` and update it with your sessions endpoint.\n",
"\n",
"3. Copy `OAI_CONFIG_LIST.example` to `OAI_CONFIG_LIST` and update it with your Azure OpenAI values."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from dotenv import load_dotenv\n",
"import os\n",
"\n",
"load_dotenv()\n",
"\n",
"ACA_SESSIONS_ENDPOINT = os.getenv('ACA_SESSIONS_ENDPOINT')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Why Managed Identity:\n",
"Managed Identity (MI) simplifies Azure service authentication by automatically managing credentials. Using MI, there is no need to store or manage secrets in your application, significantly reducing the risk of credential leakage and enhancing security.\n",
"\n",
"#### How `DefaultAzureCredential` Works:\n",
"`DefaultAzureCredential` attempts to find a best-available credential from a series of providers, including managed identity and developer credentials from Azure CLI or Visual Studio. This makes it both flexible and convenient for development and production environments without code changes.\n",
"\n",
"![Azure Identity](https://raw.githubusercontent.com/Azure/azure-sdk-for-net/main/sdk/identity/Azure.Identity/images/mermaidjs/DefaultAzureCredentialAuthFlow.svg)\n",
"\n",
"#### Setup for Azure OpenAI:\n",
"1. **Azure Managed Identity**:\n",
" - Ensure that the Azure resource (e.g., Azure OpenAI, Logic Apps, AI Search) running in this notebook is assigned a Managed Identity.\n",
" - Configure the Managed Identity to have access to the Azure OpenAI service by setting appropriate role assignments in Azure RBAC.\n",
"\n",
"- **Keys required in .env File**:\n",
" - `OPENAI_ENDPOINT`: The endpoint URL for the Azure OpenAI service.\n",
" - `OPENAI_MODEL_NAME`: The deployed model name in Azure OpenAI\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ACA code executor class implemented by subclassing the `CodeExecutor` protocol and implementing the `execute_code_blocks` method."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"import requests\n",
"from typing import List\n",
"from azure.identity import DefaultAzureCredential\n",
"from autogen.coding import CodeBlock, CodeExecutor, CodeExtractor, CodeResult, MarkdownCodeExtractor\n",
"\n",
"class ACASessionsExecutor(CodeExecutor):\n",
"\n",
" @property\n",
" def code_extractor(self) -> CodeExtractor:\n",
" # Extract code from markdown blocks.\n",
" return MarkdownCodeExtractor()\n",
"\n",
" def __init__(self, pool_management_endpoint: str) -> None:\n",
" self.pool_management_endpoint = pool_management_endpoint\n",
" self.access_token = None\n",
"\n",
" def ensure_access_token(self) -> None:\n",
" \"\"\"Ensures that the access token is valid and updates it if necessary.\"\"\"\n",
" if not self.access_token:\n",
" credential = DefaultAzureCredential()\n",
" scope = \"https://dynamicsessions.io\" # \"https://acasessions.io/.default\" could also be used\n",
" self.access_token = credential.get_token(scope).token\n",
"\n",
" def execute_code_blocks(self, code_blocks: List[CodeBlock]) -> CodeResult:\n",
" self.ensure_access_token() # Ensure the access token is valid before making calls\n",
" log = \"\"\n",
" print(self.access_token)\n",
" \n",
" exitcode = 0\n",
" headers = {\n",
" \"Authorization\": f\"Bearer {self.access_token}\"\n",
" }\n",
"\n",
" for code_block in code_blocks:\n",
" properties = {\n",
" \"identifier\": \"adslfjlad\",\n",
" \"codeInputType\": \"inline\",\n",
" \"executionType\": \"synchronous\",\n",
" \"pythonCode\": code_block.code,\n",
" \"timeoutInSeconds\": 100\n",
" }\n",
"\n",
" try:\n",
" response = requests.post(\n",
" self.pool_management_endpoint + \"/python/execute\",\n",
" headers=headers,\n",
" json={\"properties\": properties}\n",
" )\n",
" response.raise_for_status() # Raises an HTTPError for bad responses\n",
" data = response.json()\n",
" log += data.get(\"stdout\", \"\") + data.get(\"stderr\", \"\")\n",
" if \"result\" in data and data[\"result\"] is not None:\n",
" log += str(data[\"result\"])\n",
" if \"error\" in data:\n",
" log += f\"\\n{data['error']}\"\n",
" exitcode = 1\n",
" except requests.RequestException as e:\n",
" log += f\"\\nError while sending code block to endpoint: {str(e)}\"\n",
" exitcode = 1\n",
" break\n",
"\n",
" return CodeResult(exit_code=exitcode, output=log)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ACA Code executor used in Agents"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"config_list = config_list_from_json(\n",
" \"OAI_CONFIG_LIST\",\n",
" filter_dict={\n",
" \"model\": [\"gpt-4\"],\n",
" },\n",
")\n",
"\n",
"code_writer_agent = ConversableAgent(\n",
" name=\"CodeWriter\",\n",
" system_message=\"You are a helpful AI assistant.\\n\"\n",
" \"You use your coding skill to solve problems.\\n\"\n",
" \"You have access to a IPython kernel to execute Python code.\\n\"\n",
" \"You output only valid python code. \\n\"\n",
" \"This valid code will be executed in a sandbox, resutling in result, stdout, or stderr. \\n\"\n",
" \"All necessary libraries have already been installed.\\n\"\n",
" \"Once the task is done, returns 'TERMINATE'.\",\n",
" llm_config={\"config_list\":config_list},\n",
")\n",
"\n",
"aca_pool_management_endpoint = ACA_SESSIONS_ENDPOINT\n",
"aca_sessions_executor = ACASessionsExecutor(aca_pool_management_endpoint)\n",
"\n",
"code_executor_agent = ConversableAgent(\n",
" name=\"CodeExecutor\",\n",
" llm_config=False,\n",
" code_execution_config={\"executor\": aca_sessions_executor},\n",
" is_termination_msg=lambda msg: \"TERMINATE\" in msg.get(\"content\", \"\").strip().upper(),\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Simple math task for testing ACA Sessions"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[33mCodeExecutor\u001b[0m (to CodeWriter):\n",
"\n",
"What is 30 plus 20?\n",
"\n",
"--------------------------------------------------------------------------------\n",
"\u001b[31m\n",
">>>>>>>> USING AUTO REPLY...\u001b[0m\n",
"\u001b[33mCodeWriter\u001b[0m (to CodeExecutor):\n",
"\n",
"To solve this, you can simply add the two numbers in Python:\n",
"\n",
"```python\n",
"result = 30 + 20\n",
"print(result)\n",
"```\n",
"\n",
"When you run this code, it will output the sum of 30 and 20. \n",
"\n",
"Would you like me to execute this code to get the result?\n",
"\n",
"--------------------------------------------------------------------------------\n",
"\u001b[31m\n",
">>>>>>>> USING AUTO REPLY...\u001b[0m\n",
"\u001b[31m\n",
">>>>>>>> EXECUTING CODE BLOCK (inferred language is python)...\u001b[0m\n",
"eyJ0eXAiOiJKV1QiLCJyaCI6IjAuQW84RF9YSmZkVHdadDBDMVo3YkJMQXplY3pfWGZTd2hlbHRJdVgyaVVJLWhVc1AtQU5NLiIsImFsZyI6IlJTMjU2IiwieDV0IjoiTDFLZktGSV9qblhid1djMjJ4Wnh3MXNVSEgwIiwia2lkIjoiTDFLZktGSV9qblhid1djMjJ4Wnh3MXNVSEgwIn0.eyJhdWQiOiJodHRwczovL2R5bmFtaWNzZXNzaW9ucy5pbyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0Lzc1NWY3MmZkLTE5M2MtNDBiNy1iNTY3LWI2YzEyYzBjZGU3My8iLCJpYXQiOjE3MTQ5MjM1MTUsIm5iZiI6MTcxNDkyMzUxNSwiZXhwIjoxNzE0OTI3NjgwLCJhY3IiOiIxIiwiYWlvIjoiQVRRQnkvNFdBQUFBMHpDUjgwejRUY1FhMHp3eUdQZjUvSnJuNXNrY0M0czNKZEdsR2N4NVBvZnU5YW5MYkxSdlRNYmlwK0Evc1I0bmFBQ0l2TzNmRnk0dVFhQjJjbnFxcXFWdUxCNHBGWlkzandBcU1Pd1Q3WW01ck1BM0M5b01WUW1IMWxJUFVrQmFmL2ttdjdCaG5hUzF1TE5qOXorelBSQ3ZINVg4QjJJaVZEV0tWOFZjRGx1NmFBdFBNVXJNVG9xc0kwMzF6b0dsOUlvV0lic1lXaFBxK1pnUjVDSHhvT1BidUNCOWpVYWM0c2N3ZjlqZXN4TVU3L1lRZSs3TnNzME54SHI5Z3JYMUZhSXVMM0NYNDRUVnJ4YXY2SFZJWGs0Zy9yNDBwejBJaFpNMXpKUXdDdG04TFBBUnZ0cmdTc1QzWFBIOXZ4NlQrN0FtMXBJbWpTaUpzRzV3Ti9pUDlPb0pqcE1EZ2hWRzJkN3lOVkFnZ1RvVjV2YkhPanZlMS9ORzJkR21QeWNzMDF0a21yaHhnRmRtem9wQTYwb0YzQT09IiwiYWx0c2VjaWQiOiI1OjoxMDAzMjAwMjAwRjg2NDRBIiwiYW1yIjpbInJzYSIsIm1mYSJdLCJhcHBpZCI6IjA0YjA3Nzk1LThkZGItNDYxYS1iYmVlLTAyZjllMWJmN2I0NiIsImFwcGlkYWNyIjoiMCIsImVtYWlsIjoiZ29rQG1pY3Jvc29mdC5jb20iLCJmYW1pbHlfbmFtZSI6IkthbXRhbW5lbmkiLCJnaXZlbl9uYW1lIjoiR292aW5kIiwiZ3JvdXBzIjpbImY4ZDNjNzFlLWU0NzMtNDgyMi04ZWY3LTZjYzU2MTZhZThjNiIsImNlOTQ4YzQ3LTMxMTktNDFhMy1hMDk3LTI5OTIzMTA2MzNlOSIsIjAzMGJiMzUxLTIxOGMtNDlmNi05NmFhLTA0OTUzNDIxZDJmYiIsIjliYjhkMDU3LWRiZDAtNDQ0MS05NGNmLWQ0OGEwMTgwMGY5MiIsImY5OTdjMDYxLTQwYjktNDQyOC1hYTYwLWQ1NzBkYjAxNWJiMyIsIjQ4MTA4OTY1LTgyNzQtNDllOC1iODQyLWY5OGI1MmE1Y2U5ZSIsIjhmNzlkMTY5LTExMDEtNDUyMS05NGU1LTAyNmVhZTg0ODY0NyIsIjU5MTE5MjZiLTQ4MmMtNDJlMy04Y2UxLTlmNjczMjhjNmMzMiIsIjQ0NTQwZjc1LTJlZTgtNDgwYS1hMWE3LTkyYjM5ZmQ2OWMzYyIsIjI4ODM5NTgzLWQxOWItNDQzZC04Mzg5LWExYjAwZGUwYzIxZSIsIjAxYjg2MmEyLWQyYTQtNGJmNS05Mzg4LTIzYmIxOGRmZTQxOSIsImEwODhlNGE0LWI1NWYtNGU5ZS05OGU2LTVhYzRlNTZkNjA3ZSIsImIzYmYzMmE1LTllNmYtNDdkMy1iNDhjLWZjZDM2NjljMmMyMSIsIjQ4YmE1MGMyLTMxNTAtNDBiMS04NWM3LWFiNGQyOWU0NzlmYiIsImFhZGMzZWNjLTMzOWEtNGU3Mi1hNGRhLTYyNDBhYTBjMTNjMSIsImNlNzdhY2Q1LTIxM2EtNGMwZS1hZWQ5LTYzYjZhMGZmNDFmNiIsIjMyYmFkNmQ3LTlmODgtNDE1Zi1hNTk0LTJiYmFlMzNjNWE4ZCIsIjY1MTE5ZmU0LTlkZWUtNDlmMi04ZjBhLTI1YmEzNjBkMmY4MSIsIjJjN2Y3NGU3LTliZjAtNGFkZS05MmNlLWE0ZWFkZTc5ZGM2ZCIsIjAyZjdjOWViLWY0ZjItNDY3ZC05ZTJjLTNiZmRhMGQ0OWI3YiJdLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaXBhZGRyIjoiMjAuMTcxLjEwOS4xODkiLCJuYW1lIjoiR292aW5kIEthbXRhbW5lbmkiLCJvaWQiOiI4NDAyNmRkMS0xOWQ2LTQ4MmItOTEyNC1mNGI2YTkyMzRkZjYiLCJwdWlkIjoiMTAwMzIwMDJCN0JCODhCMyIsInJoIjoiSSIsInNjcCI6IlNlc3Npb25zLlJlYWRXcml0ZS5BbGwiLCJzdWIiOiI5V0Y5VGtrS25aM2ZIcnNreXhXV0J3QUV2QndxVHJ5RkJaMjVRYVBIaFBVIiwidGlkIjoiNzU1ZjcyZmQtMTkzYy00MGI3LWI1NjctYjZjMTJjMGNkZTczIiwidW5pcXVlX25hbWUiOiJnb2tAbWljcm9zb2Z0LmNvbSIsInV0aSI6Im9qMTB1RXBxVUVhMnZFNVp5Y3BGQUEiLCJ2ZXIiOiIxLjAiLCJ3aWRzIjpbIjg4ZDhlM2UzLThmNTUtNGExZS05NTNhLTliOTg5OGI4ODc2YiIsImUzOTczYmRmLTQ5ODctNDlhZS04MzdhLWJhOGUyMzFjNzI4NiIsIjc2OThhNzcyLTc4N2ItNGFjOC05MDFmLTYwZDZiMDhhZmZkMiIsIjA1MjY3MTZiLTExM2QtNGMxNS1iMmM4LTY4ZTNjMjJiOWY4MCIsImIxYmUxYzNlLWI2NWQtNGYxOS04NDI3LWY2ZmEwZDk3ZmViOSIsImFhZjQzMjM2LTBjMGQtNGQ1Zi04ODNhLTY5NTUzODJhYzA4MSIsImU2ZDFhMjNhLWRhMTEtNGJlNC05NTcwLWJlZmM4NmQwNjdhNyIsIjg5MmM1ODQyLWE5YTYtNDYzYS04MDQxLTcyYWEwOGNhM2NmNiIsIjNlZGFmNjYzLTM0MWUtNDQ3NS05Zjk0LTVjMzk4ZWY2YzA3MCIsIjFkMzM2ZDJjLTRhZTgtNDJlZi05NzExLWIzNjA0Y2UzZmMyYyIsImM0ZTM5YmQ5LTExMDAtNDZkMy04YzY1LWZiMTYwZGEwMDcxZiIsImZmZDUyZmE1LTk4ZGMtNDY1Yy05OTFkLWZjMDczZWI1OWY4ZiIsIjI1YTUxNmVkLTJmYTAtNDBlYS1hMmQwLTEyOTIzYTIxNDczYSIsIjE3MzE1Nzk3LTEwMmQtNDBiNC05M2UwLTQzMjA2MmNhY2ExOCIsImIwZjU0NjYxLTJkNzQtNGM1MC1hZmEzLTFlYzgwM2YxMmVmZSIsIjVjNGY5ZGNkLTQ3ZGMtNGNmNy04YzlhLTllNDIwN2NiZmM5MSIsIjg0MjRjNmYwLWExODktNDk5ZS1iYmQwLTI2YzE3NTNjOTZkNCIsIjlmMDYyMDRkLTczYzEtNGQ0Yy04ODBhLTZlZGI5MDYwNmZkOCIsIjc0OTVmZGM0LTM0YzQtNGQxNS1hMjg5LTk4Nzg4Y2UzOTlmZCIsIjE1OGMwNDdhLWM5MDctNDU1Ni1iN2VmLTQ0NjU1MWE2YjVmNyIsImI3OWZiZjRkLTNlZjktNDY4OS04MTQzLTc2YjE5NGU4NTUwOSJdfQ.cYjJ814-Ybk6Z8ZWOpGO33N4a4g7GNM7CrbTsdtctTYYVlwtK7m0v6H7TFc56LjX-EgxrE17Emm8fUESXsKEDltHxWus-Na3ZiBQgRGh65dgs1dfHWXZ9upvlqAzwtcUB_-TVL7VObNJSh_6IZe3ORsxyi7AlB6gcIMr4EoKlGrYg1mdZxan2EI-46ZPpJBu071ce2Zz1hQxDRlPE4TxCwedhHEl9wB3IfM7cx_mabAZW9Gqktc6hwDI8atBWtXvUzRqS6tTG7vxzfwPGp7AKx1vloQivxgCTA6GaRnqSBz_-k0Hz8Ro9zR43kQ99qWHSafsdhQX5YjGjVSNukUscg\n",
"\u001b[33mCodeExecutor\u001b[0m (to CodeWriter):\n",
"\n",
"exitcode: 0 (execution succeeded)\n",
"Code output: 50\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"\u001b[31m\n",
">>>>>>>> USING AUTO REPLY...\u001b[0m\n",
"\u001b[33mCodeWriter\u001b[0m (to CodeExecutor):\n",
"\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"\u001b[31m\n",
">>>>>>>> USING AUTO REPLY...\u001b[0m\n",
"\u001b[33mCodeExecutor\u001b[0m (to CodeWriter):\n",
"\n",
"\n",
"\n",
"--------------------------------------------------------------------------------\n",
"\u001b[31m\n",
">>>>>>>> USING AUTO REPLY...\u001b[0m\n",
"\u001b[33mCodeWriter\u001b[0m (to CodeExecutor):\n",
"\n",
"TERMINATE\n",
"\n",
"--------------------------------------------------------------------------------\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\gok\\AppData\\Roaming\\Python\\Python312\\site-packages\\autogen\\agentchat\\conversable_agent.py:1306: UserWarning: Extracted_response from {response} is None.\n",
" warnings.warn(\"Extracted_response from {response} is None.\", UserWarning)\n"
]
}
],
"source": [
"chat_result = code_executor_agent.initiate_chat(\n",
" code_writer_agent,\n",
" message=\"What is 30 plus 20?\",\n",
")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "autogen",
"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.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
2 changes: 1 addition & 1 deletion agents/autogen/notebooks/retirement-planning.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.2"
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
Loading

0 comments on commit 51d5d43

Please sign in to comment.