From e172ed3cd7f2fe0d528c7c3653f654aee67a367c Mon Sep 17 00:00:00 2001 From: Omar Abdelwahab Date: Mon, 24 Nov 2025 14:25:26 -0800 Subject: [PATCH 1/7] Added an autogen_llamastack integration notebook with examples showing how to use llama stack with auto gen --- .../autogen_llama_stack_integration.ipynb | 698 ++++++++++++++++++ 1 file changed, 698 insertions(+) create mode 100644 docs/notebooks/autogen/autogen_llama_stack_integration.ipynb diff --git a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb new file mode 100644 index 000000000..def4f04ac --- /dev/null +++ b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb @@ -0,0 +1,698 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AutoGen + Llama Stack Integration\n", + "\n", + "## Overview\n", + "\n", + "This notebook demonstrates how to use **AutoGen (AG2)** with **Llama Stack** as the backend.\n", + "\n", + "### What is AutoGen?\n", + "- Microsoft's framework for **conversational multi-agent** systems\n", + "- Emphasizes **chat-based** interactions between agents\n", + "- Built-in **code execution** and **human-in-the-loop**\n", + "- Great for **interactive problem-solving**\n", + "\n", + "### Why Llama Stack?\n", + "- **Unified backend** for any LLM (Ollama, Together, vLLM, etc.)\n", + "- **One integration point** instead of many\n", + "- **Production-ready** infrastructure\n", + "- **Open-source** and flexible\n", + "\n", + "### Use Cases Covered:\n", + "1. **Two-Agent Conversation** - UserProxy + Assistant solving a problem\n", + "2. **Code Generation & Execution** - AutoGen generates and runs code\n", + "3. **Group Chat** - Multiple specialists collaborating\n", + "4. **Human-in-the-Loop** - Interactive problem-solving\n", + "5. **Sequential Task Solving** - Math problem → Code → Execute → Verify\n", + "\n", + "---\n", + "\n", + "## Prerequisites\n", + "\n", + "```bash\n", + "# Install AutoGen (AG2)\n", + "pip install pyautogen\n", + "\n", + "# Llama Stack should already be running\n", + "# Default: http://localhost:8321\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Imports\n", + "import os\n", + "from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager\n", + "from autogen.oai import OpenAIWrapper\n", + "\n", + "# Check Llama Stack connectivity\n", + "import httpx\n", + "\n", + "LLAMA_STACK_URL = \"http://localhost:8321\"\n", + "\n", + "try:\n", + " response = httpx.get(f\"{LLAMA_STACK_URL}/health\")\n", + " print(f\"✅ Llama Stack is running at {LLAMA_STACK_URL}\")\n", + " print(f\"Status: {response.status_code}\")\n", + "except Exception as e:\n", + " print(f\"❌ Llama Stack not accessible: {e}\")\n", + " print(\"Make sure Llama Stack is running on port 8321\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Configuration: AutoGen with Llama Stack\n", + "\n", + "### How It Works\n", + "\n", + "AutoGen uses the **OpenAI API format**, which Llama Stack is compatible with!\n", + "\n", + "```python\n", + "config_list = [\n", + " {\n", + " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", + " \"base_url\": \"http://localhost:8321/v1\", # Llama Stack endpoint\n", + " \"api_key\": \"not-needed\", # Llama Stack doesn't need auth\n", + " }\n", + "]\n", + "```\n", + "\n", + "**Key Points:**\n", + "- Use `/v1` suffix for OpenAI-compatible endpoint\n", + "- `api_key` can be any string (Llama Stack ignores it)\n", + "- `model` must match what's available in Llama Stack" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# AutoGen configuration for Llama Stack\n", + "config_list = [\n", + " {\n", + " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", + " \"base_url\": \"http://localhost:8321/v1\", # OpenAI-compatible endpoint\n", + " \"api_key\": \"not-needed\", # Llama Stack doesn't require auth\n", + " }\n", + "]\n", + "\n", + "llm_config = {\n", + " \"config_list\": config_list,\n", + " \"temperature\": 0.7,\n", + " \"timeout\": 120,\n", + "}\n", + "\n", + "print(\"✅ AutoGen configuration ready for Llama Stack\")\n", + "print(f\"Model: {config_list[0]['model']}\")\n", + "print(f\"Base URL: {config_list[0]['base_url']}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 1: Two-Agent Conversation\n", + "\n", + "### Pattern: User Proxy + Assistant\n", + "\n", + "**UserProxyAgent:**\n", + "- Represents the human user\n", + "- Can execute code\n", + "- Provides feedback to assistant\n", + "\n", + "**AssistantAgent:**\n", + "- AI assistant powered by Llama Stack\n", + "- Generates responses and code\n", + "- Solves problems conversationally\n", + "\n", + "### Use Case: Solve a Math Problem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create AssistantAgent (AI assistant)\n", + "assistant = AssistantAgent(\n", + " name=\"MathAssistant\",\n", + " system_message=\"You are a helpful AI assistant that solves math problems. Provide clear explanations.\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "# Create UserProxyAgent (represents human)\n", + "user_proxy = UserProxyAgent(\n", + " name=\"User\",\n", + " human_input_mode=\"NEVER\", # Fully automated (no human input)\n", + " max_consecutive_auto_reply=5,\n", + " code_execution_config={\"use_docker\": False}, # Allow local code execution\n", + ")\n", + "\n", + "print(\"✅ Agents created\")\n", + "print(f\"Assistant: {assistant.name}\")\n", + "print(f\"User Proxy: {user_proxy.name}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Start conversation\n", + "user_proxy.initiate_chat(\n", + " assistant,\n", + " message=\"What is the sum of the first 100 prime numbers? Please write Python code to calculate it.\"\n", + ")\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Conversation complete!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 2: Code Generation & Execution\n", + "\n", + "### Pattern: Assistant generates code → UserProxy executes it\n", + "\n", + "This is AutoGen's killer feature: **automatic code execution**!\n", + "\n", + "### Use Case: Data Analysis Task" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a coding assistant\n", + "coding_assistant = AssistantAgent(\n", + " name=\"DataScientist\",\n", + " system_message=\"\"\"You are an expert data scientist.\n", + " Write Python code to solve data analysis problems.\n", + " Always include visualizations when appropriate.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "# User proxy with code execution enabled\n", + "user_proxy_code = UserProxyAgent(\n", + " name=\"UserProxy\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=3,\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " },\n", + ")\n", + "\n", + "# Start data analysis task\n", + "user_proxy_code.initiate_chat(\n", + " coding_assistant,\n", + " message=\"\"\"Generate 100 random numbers from a normal distribution (mean=50, std=10).\n", + " Calculate the mean, median, and standard deviation.\n", + " Create a histogram to visualize the distribution.\"\"\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 3: Group Chat (Multi-Agent Collaboration)\n", + "\n", + "### Pattern: Multiple Specialists Collaborating\n", + "\n", + "**Scenario:** Write a technical blog post about AI\n", + "\n", + "**Agents:**\n", + "1. **Researcher** - Finds information\n", + "2. **Writer** - Writes content\n", + "3. **Critic** - Reviews and suggests improvements\n", + "4. **UserProxy** - Orchestrates and provides final approval\n", + "\n", + "This is similar to llamacrew's workflow but **conversational** instead of DAG-based!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create specialist agents\n", + "researcher = AssistantAgent(\n", + " name=\"Researcher\",\n", + " system_message=\"\"\"You are a researcher. Your job is to find accurate information\n", + " about topics and provide facts, statistics, and recent developments.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "writer = AssistantAgent(\n", + " name=\"Writer\",\n", + " system_message=\"\"\"You are a technical writer. Your job is to write clear,\n", + " engaging content based on research provided. Use simple language and examples.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "critic = AssistantAgent(\n", + " name=\"Critic\",\n", + " system_message=\"\"\"You are an editor. Review content for clarity, accuracy,\n", + " and engagement. Suggest specific improvements.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "# User proxy to orchestrate\n", + "user_proxy_group = UserProxyAgent(\n", + " name=\"UserProxy\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=10,\n", + " code_execution_config=False,\n", + ")\n", + "\n", + "print(\"✅ Group chat agents created\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create group chat\n", + "groupchat = GroupChat(\n", + " agents=[user_proxy_group, researcher, writer, critic],\n", + " messages=[],\n", + " max_round=12, # Maximum conversation rounds\n", + ")\n", + "\n", + "# Create manager to orchestrate\n", + "manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config)\n", + "\n", + "# Start group chat\n", + "user_proxy_group.initiate_chat(\n", + " manager,\n", + " message=\"\"\"Write a 300-word blog post about the benefits of using\n", + " Llama Stack for LLM applications. Include:\n", + " 1. What Llama Stack is\n", + " 2. Key benefits\n", + " 3. A simple use case example\n", + "\n", + " Researcher: gather information\n", + " Writer: create the blog post\n", + " Critic: review and suggest improvements\n", + " \"\"\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 4: Human-in-the-Loop\n", + "\n", + "### Pattern: Interactive Problem Solving\n", + "\n", + "Autogen excels at **human-in-the-loop** workflows where you can:\n", + "- Provide feedback mid-conversation\n", + "- Approve/reject suggestions\n", + "- Guide the agent's direction\n", + "\n", + "**Note:** In notebooks, this requires `human_input_mode=\"ALWAYS\"` or `\"TERMINATE\"` and manual input." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Interactive assistant (uncomment to try)\n", + "# WARNING: This will prompt for user input!\n", + "\n", + "# assistant_interactive = AssistantAgent(\n", + "# name=\"InteractiveAssistant\",\n", + "# system_message=\"You are a helpful assistant. Ask clarifying questions when needed.\",\n", + "# llm_config=llm_config,\n", + "# )\n", + "\n", + "# user_proxy_interactive = UserProxyAgent(\n", + "# name=\"Human\",\n", + "# human_input_mode=\"TERMINATE\", # Ask for human input when TERMINATE is mentioned\n", + "# max_consecutive_auto_reply=5,\n", + "# )\n", + "\n", + "# user_proxy_interactive.initiate_chat(\n", + "# assistant_interactive,\n", + "# message=\"Help me plan a machine learning project for customer churn prediction.\"\n", + "# )\n", + "\n", + "print(\"💡 Human-in-the-loop example (commented out to avoid blocking notebook execution)\")\n", + "print(\"Uncomment the code above to try interactive mode!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 5: Sequential Task Solving\n", + "\n", + "### Pattern: Chain of Thought Problem Solving\n", + "\n", + "**Scenario:** Solve a complex problem requiring multiple steps\n", + "\n", + "1. **Understand** the problem\n", + "2. **Plan** the solution approach\n", + "3. **Implement** the solution (code)\n", + "4. **Execute** and verify\n", + "5. **Explain** the results\n", + "\n", + "### Use Case: Fibonacci Sequence Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a reasoning assistant\n", + "reasoning_assistant = AssistantAgent(\n", + " name=\"ReasoningAssistant\",\n", + " system_message=\"\"\"You are a problem-solving assistant.\n", + " For complex problems:\n", + " 1. Break down the problem\n", + " 2. Plan the solution step-by-step\n", + " 3. Write clean, well-commented code\n", + " 4. Explain results clearly\n", + " \"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "user_proxy_reasoning = UserProxyAgent(\n", + " name=\"User\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=5,\n", + " code_execution_config={\"work_dir\": \"reasoning\", \"use_docker\": False},\n", + ")\n", + "\n", + "# Complex problem requiring sequential reasoning\n", + "user_proxy_reasoning.initiate_chat(\n", + " reasoning_assistant,\n", + " message=\"\"\"Find the first 20 Fibonacci numbers where the number is also a prime number.\n", + "\n", + " Requirements:\n", + " 1. Explain the approach\n", + " 2. Write efficient Python code\n", + " 3. Display the results in a table\n", + " 4. Calculate what percentage of the first 100 Fibonacci numbers are prime\n", + " \"\"\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comparison: AutoGen vs llamacrew\n", + "\n", + "### When to Use AutoGen + Llama Stack\n", + "\n", + "✅ **Use AutoGen when you need:**\n", + "- **Conversational** interactions between agents\n", + "- **Human-in-the-loop** workflows (interactive approval, feedback)\n", + "- **Code generation & execution** (data analysis, scripting)\n", + "- **Group discussions** (multiple agents debating, collaborating)\n", + "- **Dynamic problem-solving** (unknown number of back-and-forth exchanges)\n", + "- **Research/prototyping** (exploratory work)\n", + "\n", + "**Example Use Cases:**\n", + "- Interactive coding assistant\n", + "- Research assistant with human feedback\n", + "- Multi-agent debate/discussion\n", + "- Tutoring/educational applications\n", + "- Dynamic customer support\n", + "\n", + "---\n", + "\n", + "### When to Use llamacrew\n", + "\n", + "✅ **Use llamacrew when you need:**\n", + "- **Production workflows** (blog writing, data pipelines)\n", + "- **Declarative DAGs** (predefined task dependencies)\n", + "- **Automatic parallelization** (framework optimizes)\n", + "- **Non-interactive automation** (scheduled jobs)\n", + "- **Minimal dependencies** (lightweight deployment)\n", + "- **Predictable workflows** (known steps)\n", + "\n", + "**Example Use Cases:**\n", + "- Automated blog post generation\n", + "- Data ETL pipelines\n", + "- Report generation\n", + "- Batch processing\n", + "- Production automation\n", + "\n", + "---\n", + "\n", + "### They're Complementary!\n", + "\n", + "- **AutoGen**: Conversational, interactive, exploratory\n", + "- **llamacrew**: Workflow, automated, production\n", + "\n", + "You might use **AutoGen for prototyping** then move to **llamacrew for production**!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Advanced: Custom Agent Behaviors\n", + "\n", + "### Pattern: Specialized Agent with Custom Logic\n", + "\n", + "You can create agents with custom behavior beyond just prompts." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Dict, List, Union\n", + "import re\n", + "\n", + "class CodeReviewAgent(AssistantAgent):\n", + " \"\"\"Custom agent that reviews code for specific patterns.\"\"\"\n", + "\n", + " def __init__(self, *args, **kwargs):\n", + " super().__init__(*args, **kwargs)\n", + " self.issues_found = []\n", + "\n", + " def review_code(self, code: str) -> Dict[str, List[str]]:\n", + " \"\"\"Custom method to review code for common issues.\"\"\"\n", + " issues = []\n", + "\n", + " # Check for common issues\n", + " if \"TODO\" in code or \"FIXME\" in code:\n", + " issues.append(\"Code contains TODO/FIXME comments\")\n", + "\n", + " if not re.search(r'def \\w+\\(.*\\):', code):\n", + " issues.append(\"No function definitions found\")\n", + "\n", + " if \"print(\" in code:\n", + " issues.append(\"Contains print statements (consider logging)\")\n", + "\n", + " self.issues_found.extend(issues)\n", + " return {\"issues\": issues, \"total\": len(issues)}\n", + "\n", + "# Create custom reviewer\n", + "code_reviewer = CodeReviewAgent(\n", + " name=\"CodeReviewer\",\n", + " system_message=\"\"\"You are a code reviewer. Analyze code for:\n", + " - Code quality\n", + " - Best practices\n", + " - Potential bugs\n", + " - Performance issues\n", + " Provide specific, actionable feedback.\n", + " \"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "print(\"✅ Custom CodeReviewAgent created with specialized review logic\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Performance Tips\n", + "\n", + "### 1. Model Selection\n", + "\n", + "```python\n", + "# Fast models for simple tasks\n", + "config_fast = {\n", + " \"model\": \"ollama/llama3.2:3b\", # Smaller, faster\n", + " \"temperature\": 0.5,\n", + "}\n", + "\n", + "# Powerful models for complex reasoning\n", + "config_powerful = {\n", + " \"model\": \"ollama/llama3.3:70b\", # Larger, better quality\n", + " \"temperature\": 0.7,\n", + "}\n", + "```\n", + "\n", + "### 2. Limit Conversation Rounds\n", + "\n", + "```python\n", + "user_proxy = UserProxyAgent(\n", + " name=\"User\",\n", + " max_consecutive_auto_reply=3, # Prevent infinite loops\n", + ")\n", + "```\n", + "\n", + "### 3. Set Timeouts\n", + "\n", + "```python\n", + "llm_config = {\n", + " \"timeout\": 60, # 60 second timeout per request\n", + " \"config_list\": config_list,\n", + "}\n", + "```\n", + "\n", + "### 4. Use Work Directories\n", + "\n", + "```python\n", + "code_execution_config = {\n", + " \"work_dir\": \"autogen_workspace\", # Isolate generated files\n", + " \"use_docker\": False,\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Troubleshooting\n", + "\n", + "### Common Issues\n", + "\n", + "#### 1. \"Could not connect to Llama Stack\"\n", + "\n", + "```bash\n", + "# Check if Llama Stack is running\n", + "curl http://localhost:8321/health\n", + "\n", + "# Start Llama Stack if needed\n", + "llama stack run\n", + "```\n", + "\n", + "#### 2. \"Model not found\"\n", + "\n", + "```bash\n", + "# List available models\n", + "curl http://localhost:8321/models\n", + "\n", + "# Make sure model name matches exactly:\n", + "# ✅ \"ollama/llama3.3:70b\"\n", + "# ❌ \"llama3.3:70b\"\n", + "```\n", + "\n", + "#### 3. \"Agent not responding\"\n", + "\n", + "- Check `max_consecutive_auto_reply` isn't set too low\n", + "- Increase `timeout` in `llm_config`\n", + "- Verify Llama Stack model is loaded and warm\n", + "\n", + "#### 4. \"Code execution failed\"\n", + "\n", + "- Make sure `code_execution_config` is set correctly\n", + "- Check file permissions on `work_dir`\n", + "- Install required Python packages\n", + "\n", + "---\n", + "\n", + "### Debug Mode\n", + "\n", + "```python\n", + "import logging\n", + "\n", + "# Enable AutoGen debug logging\n", + "logging.basicConfig(level=logging.DEBUG)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Summary\n", + "\n", + "### What We Covered\n", + "\n", + "1. ✅ **Two-Agent Conversations** - UserProxy + Assistant pattern\n", + "2. ✅ **Code Generation & Execution** - AutoGen's killer feature\n", + "3. ✅ **Group Chat** - Multiple agents collaborating\n", + "4. ✅ **Human-in-the-Loop** - Interactive workflows\n", + "5. ✅ **Sequential Reasoning** - Complex problem solving\n", + "6. ✅ **Custom Agents** - Specialized behaviors\n", + "\n", + "### Key Takeaways\n", + "\n", + "**AutoGen + Llama Stack is powerful for:**\n", + "- 🗣️ **Conversational** multi-agent systems\n", + "- 👤 **Interactive** problem-solving with humans\n", + "- 💻 **Code generation** and execution\n", + "- 🤝 **Collaborative** agent discussions\n", + "\n", + "**vs llamacrew which is better for:**\n", + "- 🔄 **Production workflows** and pipelines\n", + "- 📊 **Declarative** task orchestration\n", + "- ⚡ **Automatic parallelization**\n", + "- 🤖 **Non-interactive** automation\n", + "\n", + "---\n", + "\n", + "### Next Steps\n", + "\n", + "1. Experiment with different agent combinations\n", + "2. Try human-in-the-loop workflows\n", + "3. Build custom agents for your use case\n", + "4. Compare AutoGen vs llamacrew for your specific needs\n", + "\n", + "### Resources\n", + "\n", + "- **AutoGen Docs**: https://microsoft.github.io/autogen/\n", + "- **Llama Stack Docs**: https://llama-stack.readthedocs.io/\n", + "- **llamacrew Docs**: `/home/omara/Desktop/llamacrew/README.md`\n", + "\n", + "---\n", + "\n", + "**Happy multi-agent building! 🚀**" + ] + } + ], + "metadata": { + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 8942c213dc8792618fd1a81573ca3cded92cb208 Mon Sep 17 00:00:00 2001 From: Omar Abdelwahab Date: Mon, 24 Nov 2025 14:33:41 -0800 Subject: [PATCH 2/7] updated the description --- .../autogen_llama_stack_integration.ipynb | 1394 +++++++++-------- 1 file changed, 699 insertions(+), 695 deletions(-) diff --git a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb index def4f04ac..2e59ac0d7 100644 --- a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb +++ b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb @@ -1,698 +1,702 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# AutoGen + Llama Stack Integration\n", - "\n", - "## Overview\n", - "\n", - "This notebook demonstrates how to use **AutoGen (AG2)** with **Llama Stack** as the backend.\n", - "\n", - "### What is AutoGen?\n", - "- Microsoft's framework for **conversational multi-agent** systems\n", - "- Emphasizes **chat-based** interactions between agents\n", - "- Built-in **code execution** and **human-in-the-loop**\n", - "- Great for **interactive problem-solving**\n", - "\n", - "### Why Llama Stack?\n", - "- **Unified backend** for any LLM (Ollama, Together, vLLM, etc.)\n", - "- **One integration point** instead of many\n", - "- **Production-ready** infrastructure\n", - "- **Open-source** and flexible\n", - "\n", - "### Use Cases Covered:\n", - "1. **Two-Agent Conversation** - UserProxy + Assistant solving a problem\n", - "2. **Code Generation & Execution** - AutoGen generates and runs code\n", - "3. **Group Chat** - Multiple specialists collaborating\n", - "4. **Human-in-the-Loop** - Interactive problem-solving\n", - "5. **Sequential Task Solving** - Math problem → Code → Execute → Verify\n", - "\n", - "---\n", - "\n", - "## Prerequisites\n", - "\n", - "```bash\n", - "# Install AutoGen (AG2)\n", - "pip install pyautogen\n", - "\n", - "# Llama Stack should already be running\n", - "# Default: http://localhost:8321\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Imports\n", - "import os\n", - "from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager\n", - "from autogen.oai import OpenAIWrapper\n", - "\n", - "# Check Llama Stack connectivity\n", - "import httpx\n", - "\n", - "LLAMA_STACK_URL = \"http://localhost:8321\"\n", - "\n", - "try:\n", - " response = httpx.get(f\"{LLAMA_STACK_URL}/health\")\n", - " print(f\"✅ Llama Stack is running at {LLAMA_STACK_URL}\")\n", - " print(f\"Status: {response.status_code}\")\n", - "except Exception as e:\n", - " print(f\"❌ Llama Stack not accessible: {e}\")\n", - " print(\"Make sure Llama Stack is running on port 8321\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Configuration: AutoGen with Llama Stack\n", - "\n", - "### How It Works\n", - "\n", - "AutoGen uses the **OpenAI API format**, which Llama Stack is compatible with!\n", - "\n", - "```python\n", - "config_list = [\n", - " {\n", - " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", - " \"base_url\": \"http://localhost:8321/v1\", # Llama Stack endpoint\n", - " \"api_key\": \"not-needed\", # Llama Stack doesn't need auth\n", - " }\n", - "]\n", - "```\n", - "\n", - "**Key Points:**\n", - "- Use `/v1` suffix for OpenAI-compatible endpoint\n", - "- `api_key` can be any string (Llama Stack ignores it)\n", - "- `model` must match what's available in Llama Stack" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# AutoGen configuration for Llama Stack\n", - "config_list = [\n", - " {\n", - " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", - " \"base_url\": \"http://localhost:8321/v1\", # OpenAI-compatible endpoint\n", - " \"api_key\": \"not-needed\", # Llama Stack doesn't require auth\n", - " }\n", - "]\n", - "\n", - "llm_config = {\n", - " \"config_list\": config_list,\n", - " \"temperature\": 0.7,\n", - " \"timeout\": 120,\n", - "}\n", - "\n", - "print(\"✅ AutoGen configuration ready for Llama Stack\")\n", - "print(f\"Model: {config_list[0]['model']}\")\n", - "print(f\"Base URL: {config_list[0]['base_url']}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 1: Two-Agent Conversation\n", - "\n", - "### Pattern: User Proxy + Assistant\n", - "\n", - "**UserProxyAgent:**\n", - "- Represents the human user\n", - "- Can execute code\n", - "- Provides feedback to assistant\n", - "\n", - "**AssistantAgent:**\n", - "- AI assistant powered by Llama Stack\n", - "- Generates responses and code\n", - "- Solves problems conversationally\n", - "\n", - "### Use Case: Solve a Math Problem" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create AssistantAgent (AI assistant)\n", - "assistant = AssistantAgent(\n", - " name=\"MathAssistant\",\n", - " system_message=\"You are a helpful AI assistant that solves math problems. Provide clear explanations.\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "# Create UserProxyAgent (represents human)\n", - "user_proxy = UserProxyAgent(\n", - " name=\"User\",\n", - " human_input_mode=\"NEVER\", # Fully automated (no human input)\n", - " max_consecutive_auto_reply=5,\n", - " code_execution_config={\"use_docker\": False}, # Allow local code execution\n", - ")\n", - "\n", - "print(\"✅ Agents created\")\n", - "print(f\"Assistant: {assistant.name}\")\n", - "print(f\"User Proxy: {user_proxy.name}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Start conversation\n", - "user_proxy.initiate_chat(\n", - " assistant,\n", - " message=\"What is the sum of the first 100 prime numbers? Please write Python code to calculate it.\"\n", - ")\n", - "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(\"Conversation complete!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 2: Code Generation & Execution\n", - "\n", - "### Pattern: Assistant generates code → UserProxy executes it\n", - "\n", - "This is AutoGen's killer feature: **automatic code execution**!\n", - "\n", - "### Use Case: Data Analysis Task" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a coding assistant\n", - "coding_assistant = AssistantAgent(\n", - " name=\"DataScientist\",\n", - " system_message=\"\"\"You are an expert data scientist.\n", - " Write Python code to solve data analysis problems.\n", - " Always include visualizations when appropriate.\"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "# User proxy with code execution enabled\n", - "user_proxy_code = UserProxyAgent(\n", - " name=\"UserProxy\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=3,\n", - " code_execution_config={\n", - " \"work_dir\": \"coding\",\n", - " \"use_docker\": False,\n", - " },\n", - ")\n", - "\n", - "# Start data analysis task\n", - "user_proxy_code.initiate_chat(\n", - " coding_assistant,\n", - " message=\"\"\"Generate 100 random numbers from a normal distribution (mean=50, std=10).\n", - " Calculate the mean, median, and standard deviation.\n", - " Create a histogram to visualize the distribution.\"\"\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 3: Group Chat (Multi-Agent Collaboration)\n", - "\n", - "### Pattern: Multiple Specialists Collaborating\n", - "\n", - "**Scenario:** Write a technical blog post about AI\n", - "\n", - "**Agents:**\n", - "1. **Researcher** - Finds information\n", - "2. **Writer** - Writes content\n", - "3. **Critic** - Reviews and suggests improvements\n", - "4. **UserProxy** - Orchestrates and provides final approval\n", - "\n", - "This is similar to llamacrew's workflow but **conversational** instead of DAG-based!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create specialist agents\n", - "researcher = AssistantAgent(\n", - " name=\"Researcher\",\n", - " system_message=\"\"\"You are a researcher. Your job is to find accurate information\n", - " about topics and provide facts, statistics, and recent developments.\"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "writer = AssistantAgent(\n", - " name=\"Writer\",\n", - " system_message=\"\"\"You are a technical writer. Your job is to write clear,\n", - " engaging content based on research provided. Use simple language and examples.\"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "critic = AssistantAgent(\n", - " name=\"Critic\",\n", - " system_message=\"\"\"You are an editor. Review content for clarity, accuracy,\n", - " and engagement. Suggest specific improvements.\"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "# User proxy to orchestrate\n", - "user_proxy_group = UserProxyAgent(\n", - " name=\"UserProxy\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=10,\n", - " code_execution_config=False,\n", - ")\n", - "\n", - "print(\"✅ Group chat agents created\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create group chat\n", - "groupchat = GroupChat(\n", - " agents=[user_proxy_group, researcher, writer, critic],\n", - " messages=[],\n", - " max_round=12, # Maximum conversation rounds\n", - ")\n", - "\n", - "# Create manager to orchestrate\n", - "manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config)\n", - "\n", - "# Start group chat\n", - "user_proxy_group.initiate_chat(\n", - " manager,\n", - " message=\"\"\"Write a 300-word blog post about the benefits of using\n", - " Llama Stack for LLM applications. Include:\n", - " 1. What Llama Stack is\n", - " 2. Key benefits\n", - " 3. A simple use case example\n", - "\n", - " Researcher: gather information\n", - " Writer: create the blog post\n", - " Critic: review and suggest improvements\n", - " \"\"\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 4: Human-in-the-Loop\n", - "\n", - "### Pattern: Interactive Problem Solving\n", - "\n", - "Autogen excels at **human-in-the-loop** workflows where you can:\n", - "- Provide feedback mid-conversation\n", - "- Approve/reject suggestions\n", - "- Guide the agent's direction\n", - "\n", - "**Note:** In notebooks, this requires `human_input_mode=\"ALWAYS\"` or `\"TERMINATE\"` and manual input." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Interactive assistant (uncomment to try)\n", - "# WARNING: This will prompt for user input!\n", - "\n", - "# assistant_interactive = AssistantAgent(\n", - "# name=\"InteractiveAssistant\",\n", - "# system_message=\"You are a helpful assistant. Ask clarifying questions when needed.\",\n", - "# llm_config=llm_config,\n", - "# )\n", - "\n", - "# user_proxy_interactive = UserProxyAgent(\n", - "# name=\"Human\",\n", - "# human_input_mode=\"TERMINATE\", # Ask for human input when TERMINATE is mentioned\n", - "# max_consecutive_auto_reply=5,\n", - "# )\n", - "\n", - "# user_proxy_interactive.initiate_chat(\n", - "# assistant_interactive,\n", - "# message=\"Help me plan a machine learning project for customer churn prediction.\"\n", - "# )\n", - "\n", - "print(\"💡 Human-in-the-loop example (commented out to avoid blocking notebook execution)\")\n", - "print(\"Uncomment the code above to try interactive mode!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 5: Sequential Task Solving\n", - "\n", - "### Pattern: Chain of Thought Problem Solving\n", - "\n", - "**Scenario:** Solve a complex problem requiring multiple steps\n", - "\n", - "1. **Understand** the problem\n", - "2. **Plan** the solution approach\n", - "3. **Implement** the solution (code)\n", - "4. **Execute** and verify\n", - "5. **Explain** the results\n", - "\n", - "### Use Case: Fibonacci Sequence Analysis" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a reasoning assistant\n", - "reasoning_assistant = AssistantAgent(\n", - " name=\"ReasoningAssistant\",\n", - " system_message=\"\"\"You are a problem-solving assistant.\n", - " For complex problems:\n", - " 1. Break down the problem\n", - " 2. Plan the solution step-by-step\n", - " 3. Write clean, well-commented code\n", - " 4. Explain results clearly\n", - " \"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "user_proxy_reasoning = UserProxyAgent(\n", - " name=\"User\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=5,\n", - " code_execution_config={\"work_dir\": \"reasoning\", \"use_docker\": False},\n", - ")\n", - "\n", - "# Complex problem requiring sequential reasoning\n", - "user_proxy_reasoning.initiate_chat(\n", - " reasoning_assistant,\n", - " message=\"\"\"Find the first 20 Fibonacci numbers where the number is also a prime number.\n", - "\n", - " Requirements:\n", - " 1. Explain the approach\n", - " 2. Write efficient Python code\n", - " 3. Display the results in a table\n", - " 4. Calculate what percentage of the first 100 Fibonacci numbers are prime\n", - " \"\"\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Comparison: AutoGen vs llamacrew\n", - "\n", - "### When to Use AutoGen + Llama Stack\n", - "\n", - "✅ **Use AutoGen when you need:**\n", - "- **Conversational** interactions between agents\n", - "- **Human-in-the-loop** workflows (interactive approval, feedback)\n", - "- **Code generation & execution** (data analysis, scripting)\n", - "- **Group discussions** (multiple agents debating, collaborating)\n", - "- **Dynamic problem-solving** (unknown number of back-and-forth exchanges)\n", - "- **Research/prototyping** (exploratory work)\n", - "\n", - "**Example Use Cases:**\n", - "- Interactive coding assistant\n", - "- Research assistant with human feedback\n", - "- Multi-agent debate/discussion\n", - "- Tutoring/educational applications\n", - "- Dynamic customer support\n", - "\n", - "---\n", - "\n", - "### When to Use llamacrew\n", - "\n", - "✅ **Use llamacrew when you need:**\n", - "- **Production workflows** (blog writing, data pipelines)\n", - "- **Declarative DAGs** (predefined task dependencies)\n", - "- **Automatic parallelization** (framework optimizes)\n", - "- **Non-interactive automation** (scheduled jobs)\n", - "- **Minimal dependencies** (lightweight deployment)\n", - "- **Predictable workflows** (known steps)\n", - "\n", - "**Example Use Cases:**\n", - "- Automated blog post generation\n", - "- Data ETL pipelines\n", - "- Report generation\n", - "- Batch processing\n", - "- Production automation\n", - "\n", - "---\n", - "\n", - "### They're Complementary!\n", - "\n", - "- **AutoGen**: Conversational, interactive, exploratory\n", - "- **llamacrew**: Workflow, automated, production\n", - "\n", - "You might use **AutoGen for prototyping** then move to **llamacrew for production**!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Advanced: Custom Agent Behaviors\n", - "\n", - "### Pattern: Specialized Agent with Custom Logic\n", - "\n", - "You can create agents with custom behavior beyond just prompts." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from typing import Dict, List, Union\n", - "import re\n", - "\n", - "class CodeReviewAgent(AssistantAgent):\n", - " \"\"\"Custom agent that reviews code for specific patterns.\"\"\"\n", - "\n", - " def __init__(self, *args, **kwargs):\n", - " super().__init__(*args, **kwargs)\n", - " self.issues_found = []\n", - "\n", - " def review_code(self, code: str) -> Dict[str, List[str]]:\n", - " \"\"\"Custom method to review code for common issues.\"\"\"\n", - " issues = []\n", - "\n", - " # Check for common issues\n", - " if \"TODO\" in code or \"FIXME\" in code:\n", - " issues.append(\"Code contains TODO/FIXME comments\")\n", - "\n", - " if not re.search(r'def \\w+\\(.*\\):', code):\n", - " issues.append(\"No function definitions found\")\n", - "\n", - " if \"print(\" in code:\n", - " issues.append(\"Contains print statements (consider logging)\")\n", - "\n", - " self.issues_found.extend(issues)\n", - " return {\"issues\": issues, \"total\": len(issues)}\n", - "\n", - "# Create custom reviewer\n", - "code_reviewer = CodeReviewAgent(\n", - " name=\"CodeReviewer\",\n", - " system_message=\"\"\"You are a code reviewer. Analyze code for:\n", - " - Code quality\n", - " - Best practices\n", - " - Potential bugs\n", - " - Performance issues\n", - " Provide specific, actionable feedback.\n", - " \"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "print(\"✅ Custom CodeReviewAgent created with specialized review logic\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Performance Tips\n", - "\n", - "### 1. Model Selection\n", - "\n", - "```python\n", - "# Fast models for simple tasks\n", - "config_fast = {\n", - " \"model\": \"ollama/llama3.2:3b\", # Smaller, faster\n", - " \"temperature\": 0.5,\n", - "}\n", - "\n", - "# Powerful models for complex reasoning\n", - "config_powerful = {\n", - " \"model\": \"ollama/llama3.3:70b\", # Larger, better quality\n", - " \"temperature\": 0.7,\n", - "}\n", - "```\n", - "\n", - "### 2. Limit Conversation Rounds\n", - "\n", - "```python\n", - "user_proxy = UserProxyAgent(\n", - " name=\"User\",\n", - " max_consecutive_auto_reply=3, # Prevent infinite loops\n", - ")\n", - "```\n", - "\n", - "### 3. Set Timeouts\n", - "\n", - "```python\n", - "llm_config = {\n", - " \"timeout\": 60, # 60 second timeout per request\n", - " \"config_list\": config_list,\n", - "}\n", - "```\n", - "\n", - "### 4. Use Work Directories\n", - "\n", - "```python\n", - "code_execution_config = {\n", - " \"work_dir\": \"autogen_workspace\", # Isolate generated files\n", - " \"use_docker\": False,\n", - "}\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Troubleshooting\n", - "\n", - "### Common Issues\n", - "\n", - "#### 1. \"Could not connect to Llama Stack\"\n", - "\n", - "```bash\n", - "# Check if Llama Stack is running\n", - "curl http://localhost:8321/health\n", - "\n", - "# Start Llama Stack if needed\n", - "llama stack run\n", - "```\n", - "\n", - "#### 2. \"Model not found\"\n", - "\n", - "```bash\n", - "# List available models\n", - "curl http://localhost:8321/models\n", - "\n", - "# Make sure model name matches exactly:\n", - "# ✅ \"ollama/llama3.3:70b\"\n", - "# ❌ \"llama3.3:70b\"\n", - "```\n", - "\n", - "#### 3. \"Agent not responding\"\n", - "\n", - "- Check `max_consecutive_auto_reply` isn't set too low\n", - "- Increase `timeout` in `llm_config`\n", - "- Verify Llama Stack model is loaded and warm\n", - "\n", - "#### 4. \"Code execution failed\"\n", - "\n", - "- Make sure `code_execution_config` is set correctly\n", - "- Check file permissions on `work_dir`\n", - "- Install required Python packages\n", - "\n", - "---\n", - "\n", - "### Debug Mode\n", - "\n", - "```python\n", - "import logging\n", - "\n", - "# Enable AutoGen debug logging\n", - "logging.basicConfig(level=logging.DEBUG)\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Summary\n", - "\n", - "### What We Covered\n", - "\n", - "1. ✅ **Two-Agent Conversations** - UserProxy + Assistant pattern\n", - "2. ✅ **Code Generation & Execution** - AutoGen's killer feature\n", - "3. ✅ **Group Chat** - Multiple agents collaborating\n", - "4. ✅ **Human-in-the-Loop** - Interactive workflows\n", - "5. ✅ **Sequential Reasoning** - Complex problem solving\n", - "6. ✅ **Custom Agents** - Specialized behaviors\n", - "\n", - "### Key Takeaways\n", - "\n", - "**AutoGen + Llama Stack is powerful for:**\n", - "- 🗣️ **Conversational** multi-agent systems\n", - "- 👤 **Interactive** problem-solving with humans\n", - "- 💻 **Code generation** and execution\n", - "- 🤝 **Collaborative** agent discussions\n", - "\n", - "**vs llamacrew which is better for:**\n", - "- 🔄 **Production workflows** and pipelines\n", - "- 📊 **Declarative** task orchestration\n", - "- ⚡ **Automatic parallelization**\n", - "- 🤖 **Non-interactive** automation\n", - "\n", - "---\n", - "\n", - "### Next Steps\n", - "\n", - "1. Experiment with different agent combinations\n", - "2. Try human-in-the-loop workflows\n", - "3. Build custom agents for your use case\n", - "4. Compare AutoGen vs llamacrew for your specific needs\n", - "\n", - "### Resources\n", - "\n", - "- **AutoGen Docs**: https://microsoft.github.io/autogen/\n", - "- **Llama Stack Docs**: https://llama-stack.readthedocs.io/\n", - "- **llamacrew Docs**: `/home/omara/Desktop/llamacrew/README.md`\n", - "\n", - "---\n", - "\n", - "**Happy multi-agent building! 🚀**" - ] - } - ], - "metadata": { - "orig_nbformat": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AutoGen + Llama Stack Integration\n", + "\n", + "## Overview\n", + "\n", + "This notebook demonstrates how to use **AutoGen (AG2)** with **Llama Stack** as the backend.\n", + "\n", + "### Use Cases Covered:\n", + "1. **Two-Agent Conversation** - UserProxy + Assistant solving a problem\n", + "2. **Code Generation & Execution** - AutoGen generates and runs code\n", + "3. **Group Chat** - Multiple specialists collaborating\n", + "4. **Human-in-the-Loop** - Interactive problem-solving\n", + "5. **Sequential Task Solving** - Math problem → Code → Execute → Verify\n", + "\n", + "---\n", + "\n", + "## Prerequisites\n", + "\n", + "```bash\n", + "# Install AutoGen (AG2)\n", + "pip install pyautogen\n", + "\n", + "# Llama Stack should already be running\n", + "# Default: http://localhost:8321\n", + "```" + ] }, - "nbformat": 4, - "nbformat_minor": 2 + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Imports\n", + "import os\n", + "from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager\n", + "from autogen.oai import OpenAIWrapper\n", + "\n", + "# Check Llama Stack connectivity\n", + "import httpx\n", + "\n", + "LLAMA_STACK_URL = \"http://localhost:8321\"\n", + "\n", + "try:\n", + " response = httpx.get(f\"{LLAMA_STACK_URL}/health\")\n", + " print(f\"✅ Llama Stack is running at {LLAMA_STACK_URL}\")\n", + " print(f\"Status: {response.status_code}\")\n", + "except Exception as e:\n", + " print(f\"❌ Llama Stack not accessible: {e}\")\n", + " print(\"Make sure Llama Stack is running on port 8321\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Configuration: AutoGen with Llama Stack\n", + "\n", + "### How It Works\n", + "\n", + "AutoGen uses the **OpenAI API format**, which Llama Stack is compatible with!\n", + "\n", + "```python\n", + "config_list = [\n", + " {\n", + " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", + " \"base_url\": \"http://localhost:8321/v1\", # Llama Stack endpoint\n", + " \"api_key\": \"not-needed\", # Llama Stack doesn't need auth\n", + " }\n", + "]\n", + "```\n", + "\n", + "**Key Points:**\n", + "- Use `/v1` suffix for OpenAI-compatible endpoint\n", + "- `api_key` can be any string (Llama Stack ignores it)\n", + "- `model` must match what's available in Llama Stack" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# AutoGen configuration for Llama Stack\n", + "config_list = [\n", + " {\n", + " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", + " \"base_url\": \"http://localhost:8321/v1\", # OpenAI-compatible endpoint\n", + " \"api_key\": \"not-needed\", # Llama Stack doesn't require auth\n", + " }\n", + "]\n", + "\n", + "llm_config = {\n", + " \"config_list\": config_list,\n", + " \"temperature\": 0.7,\n", + " \"timeout\": 120,\n", + "}\n", + "\n", + "print(\"✅ AutoGen configuration ready for Llama Stack\")\n", + "print(f\"Model: {config_list[0]['model']}\")\n", + "print(f\"Base URL: {config_list[0]['base_url']}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 1: Two-Agent Conversation\n", + "\n", + "### Pattern: User Proxy + Assistant\n", + "\n", + "**UserProxyAgent:**\n", + "- Represents the human user\n", + "- Can execute code\n", + "- Provides feedback to assistant\n", + "\n", + "**AssistantAgent:**\n", + "- AI assistant powered by Llama Stack\n", + "- Generates responses and code\n", + "- Solves problems conversationally\n", + "\n", + "### Use Case: Solve a Math Problem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create AssistantAgent (AI assistant)\n", + "assistant = AssistantAgent(\n", + " name=\"MathAssistant\",\n", + " system_message=\"You are a helpful AI assistant that solves math problems. Provide clear explanations.\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "# Create UserProxyAgent (represents human)\n", + "user_proxy = UserProxyAgent(\n", + " name=\"User\",\n", + " human_input_mode=\"NEVER\", # Fully automated (no human input)\n", + " max_consecutive_auto_reply=5,\n", + " code_execution_config={\"use_docker\": False}, # Allow local code execution\n", + ")\n", + "\n", + "print(\"✅ Agents created\")\n", + "print(f\"Assistant: {assistant.name}\")\n", + "print(f\"User Proxy: {user_proxy.name}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Start conversation\n", + "user_proxy.initiate_chat(\n", + " assistant,\n", + " message=\"What is the sum of the first 100 prime numbers? Please write Python code to calculate it.\"\n", + ")\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Conversation complete!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 2: Code Generation & Execution\n", + "\n", + "### Pattern: Assistant generates code → UserProxy executes it\n", + "\n", + "This is AutoGen's killer feature: **automatic code execution**!\n", + "\n", + "### Use Case: Data Analysis Task" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a coding assistant\n", + "coding_assistant = AssistantAgent(\n", + " name=\"DataScientist\",\n", + " system_message=\"\"\"You are an expert data scientist.\n", + " Write Python code to solve data analysis problems.\n", + " Always include visualizations when appropriate.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "# User proxy with code execution enabled\n", + "user_proxy_code = UserProxyAgent(\n", + " name=\"UserProxy\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=3,\n", + " code_execution_config={\n", + " \"work_dir\": \"coding\",\n", + " \"use_docker\": False,\n", + " },\n", + ")\n", + "\n", + "# Start data analysis task\n", + "user_proxy_code.initiate_chat(\n", + " coding_assistant,\n", + " message=\"\"\"Generate 100 random numbers from a normal distribution (mean=50, std=10).\n", + " Calculate the mean, median, and standard deviation.\n", + " Create a histogram to visualize the distribution.\"\"\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 3: Group Chat (Multi-Agent Collaboration)\n", + "\n", + "### Pattern: Multiple Specialists Collaborating\n", + "\n", + "**Scenario:** Write a technical blog post about AI\n", + "\n", + "**Agents:**\n", + "1. **Researcher** - Finds information\n", + "2. **Writer** - Writes content\n", + "3. **Critic** - Reviews and suggests improvements\n", + "4. **UserProxy** - Orchestrates and provides final approval\n", + "\n", + "This is similar to llamacrew's workflow but **conversational** instead of DAG-based!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create specialist agents\n", + "researcher = AssistantAgent(\n", + " name=\"Researcher\",\n", + " system_message=\"\"\"You are a researcher. Your job is to find accurate information\n", + " about topics and provide facts, statistics, and recent developments.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "writer = AssistantAgent(\n", + " name=\"Writer\",\n", + " system_message=\"\"\"You are a technical writer. Your job is to write clear,\n", + " engaging content based on research provided. Use simple language and examples.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "critic = AssistantAgent(\n", + " name=\"Critic\",\n", + " system_message=\"\"\"You are an editor. Review content for clarity, accuracy,\n", + " and engagement. Suggest specific improvements.\"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "# User proxy to orchestrate\n", + "user_proxy_group = UserProxyAgent(\n", + " name=\"UserProxy\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=10,\n", + " code_execution_config=False,\n", + ")\n", + "\n", + "print(\"✅ Group chat agents created\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create group chat\n", + "groupchat = GroupChat(\n", + " agents=[user_proxy_group, researcher, writer, critic],\n", + " messages=[],\n", + " max_round=12, # Maximum conversation rounds\n", + ")\n", + "\n", + "# Create manager to orchestrate\n", + "manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config)\n", + "\n", + "# Start group chat\n", + "user_proxy_group.initiate_chat(\n", + " manager,\n", + " message=\"\"\"Write a 300-word blog post about the benefits of using\n", + " Llama Stack for LLM applications. Include:\n", + " 1. What Llama Stack is\n", + " 2. Key benefits\n", + " 3. A simple use case example\n", + "\n", + " Researcher: gather information\n", + " Writer: create the blog post\n", + " Critic: review and suggest improvements\n", + " \"\"\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 4: Human-in-the-Loop\n", + "\n", + "### Pattern: Interactive Problem Solving\n", + "\n", + "Autogen excels at **human-in-the-loop** workflows where you can:\n", + "- Provide feedback mid-conversation\n", + "- Approve/reject suggestions\n", + "- Guide the agent's direction\n", + "\n", + "**Note:** In notebooks, this requires `human_input_mode=\"ALWAYS\"` or `\"TERMINATE\"` and manual input." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Interactive assistant (uncomment to try)\n", + "# WARNING: This will prompt for user input!\n", + "\n", + "# assistant_interactive = AssistantAgent(\n", + "# name=\"InteractiveAssistant\",\n", + "# system_message=\"You are a helpful assistant. Ask clarifying questions when needed.\",\n", + "# llm_config=llm_config,\n", + "# )\n", + "\n", + "# user_proxy_interactive = UserProxyAgent(\n", + "# name=\"Human\",\n", + "# human_input_mode=\"TERMINATE\", # Ask for human input when TERMINATE is mentioned\n", + "# max_consecutive_auto_reply=5,\n", + "# )\n", + "\n", + "# user_proxy_interactive.initiate_chat(\n", + "# assistant_interactive,\n", + "# message=\"Help me plan a machine learning project for customer churn prediction.\"\n", + "# )\n", + "\n", + "print(\"💡 Human-in-the-loop example (commented out to avoid blocking notebook execution)\")\n", + "print(\"Uncomment the code above to try interactive mode!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 5: Sequential Task Solving\n", + "\n", + "### Pattern: Chain of Thought Problem Solving\n", + "\n", + "**Scenario:** Solve a complex problem requiring multiple steps\n", + "\n", + "1. **Understand** the problem\n", + "2. **Plan** the solution approach\n", + "3. **Implement** the solution (code)\n", + "4. **Execute** and verify\n", + "5. **Explain** the results\n", + "\n", + "### Use Case: Fibonacci Sequence Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a reasoning assistant\n", + "reasoning_assistant = AssistantAgent(\n", + " name=\"ReasoningAssistant\",\n", + " system_message=\"\"\"You are a problem-solving assistant.\n", + " For complex problems:\n", + " 1. Break down the problem\n", + " 2. Plan the solution step-by-step\n", + " 3. Write clean, well-commented code\n", + " 4. Explain results clearly\n", + " \"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "user_proxy_reasoning = UserProxyAgent(\n", + " name=\"User\",\n", + " human_input_mode=\"NEVER\",\n", + " max_consecutive_auto_reply=5,\n", + " code_execution_config={\"work_dir\": \"reasoning\", \"use_docker\": False},\n", + ")\n", + "\n", + "# Complex problem requiring sequential reasoning\n", + "user_proxy_reasoning.initiate_chat(\n", + " reasoning_assistant,\n", + " message=\"\"\"Find the first 20 Fibonacci numbers where the number is also a prime number.\n", + "\n", + " Requirements:\n", + " 1. Explain the approach\n", + " 2. Write efficient Python code\n", + " 3. Display the results in a table\n", + " 4. Calculate what percentage of the first 100 Fibonacci numbers are prime\n", + " \"\"\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comparison: AutoGen vs llamacrew\n", + "\n", + "### When to Use AutoGen + Llama Stack\n", + "\n", + "✅ **Use AutoGen when you need:**\n", + "- **Conversational** interactions between agents\n", + "- **Human-in-the-loop** workflows (interactive approval, feedback)\n", + "- **Code generation & execution** (data analysis, scripting)\n", + "- **Group discussions** (multiple agents debating, collaborating)\n", + "- **Dynamic problem-solving** (unknown number of back-and-forth exchanges)\n", + "- **Research/prototyping** (exploratory work)\n", + "\n", + "**Example Use Cases:**\n", + "- Interactive coding assistant\n", + "- Research assistant with human feedback\n", + "- Multi-agent debate/discussion\n", + "- Tutoring/educational applications\n", + "- Dynamic customer support\n", + "\n", + "---\n", + "\n", + "### When to Use llamacrew\n", + "\n", + "✅ **Use llamacrew when you need:**\n", + "- **Production workflows** (blog writing, data pipelines)\n", + "- **Declarative DAGs** (predefined task dependencies)\n", + "- **Automatic parallelization** (framework optimizes)\n", + "- **Non-interactive automation** (scheduled jobs)\n", + "- **Minimal dependencies** (lightweight deployment)\n", + "- **Predictable workflows** (known steps)\n", + "\n", + "**Example Use Cases:**\n", + "- Automated blog post generation\n", + "- Data ETL pipelines\n", + "- Report generation\n", + "- Batch processing\n", + "- Production automation\n", + "\n", + "---\n", + "\n", + "### They're Complementary!\n", + "\n", + "- **AutoGen**: Conversational, interactive, exploratory\n", + "- **llamacrew**: Workflow, automated, production\n", + "\n", + "You might use **AutoGen for prototyping** then move to **llamacrew for production**!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Advanced: Custom Agent Behaviors\n", + "\n", + "### Pattern: Specialized Agent with Custom Logic\n", + "\n", + "You can create agents with custom behavior beyond just prompts." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Dict, List, Union\n", + "import re\n", + "\n", + "class CodeReviewAgent(AssistantAgent):\n", + " \"\"\"Custom agent that reviews code for specific patterns.\"\"\"\n", + "\n", + " def __init__(self, *args, **kwargs):\n", + " super().__init__(*args, **kwargs)\n", + " self.issues_found = []\n", + "\n", + " def review_code(self, code: str) -> Dict[str, List[str]]:\n", + " \"\"\"Custom method to review code for common issues.\"\"\"\n", + " issues = []\n", + "\n", + " # Check for common issues\n", + " if \"TODO\" in code or \"FIXME\" in code:\n", + " issues.append(\"Code contains TODO/FIXME comments\")\n", + "\n", + " if not re.search(r'def \\w+\\(.*\\):', code):\n", + " issues.append(\"No function definitions found\")\n", + "\n", + " if \"print(\" in code:\n", + " issues.append(\"Contains print statements (consider logging)\")\n", + "\n", + " self.issues_found.extend(issues)\n", + " return {\"issues\": issues, \"total\": len(issues)}\n", + "\n", + "# Create custom reviewer\n", + "code_reviewer = CodeReviewAgent(\n", + " name=\"CodeReviewer\",\n", + " system_message=\"\"\"You are a code reviewer. Analyze code for:\n", + " - Code quality\n", + " - Best practices\n", + " - Potential bugs\n", + " - Performance issues\n", + " Provide specific, actionable feedback.\n", + " \"\"\",\n", + " llm_config=llm_config,\n", + ")\n", + "\n", + "print(\"✅ Custom CodeReviewAgent created with specialized review logic\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Performance Tips\n", + "\n", + "### 1. Model Selection\n", + "\n", + "```python\n", + "# Fast models for simple tasks\n", + "config_fast = {\n", + " \"model\": \"ollama/llama3.2:3b\", # Smaller, faster\n", + " \"temperature\": 0.5,\n", + "}\n", + "\n", + "# Powerful models for complex reasoning\n", + "config_powerful = {\n", + " \"model\": \"ollama/llama3.3:70b\", # Larger, better quality\n", + " \"temperature\": 0.7,\n", + "}\n", + "```\n", + "\n", + "### 2. Limit Conversation Rounds\n", + "\n", + "```python\n", + "user_proxy = UserProxyAgent(\n", + " name=\"User\",\n", + " max_consecutive_auto_reply=3, # Prevent infinite loops\n", + ")\n", + "```\n", + "\n", + "### 3. Set Timeouts\n", + "\n", + "```python\n", + "llm_config = {\n", + " \"timeout\": 60, # 60 second timeout per request\n", + " \"config_list\": config_list,\n", + "}\n", + "```\n", + "\n", + "### 4. Use Work Directories\n", + "\n", + "```python\n", + "code_execution_config = {\n", + " \"work_dir\": \"autogen_workspace\", # Isolate generated files\n", + " \"use_docker\": False,\n", + "}\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Troubleshooting\n", + "\n", + "### Common Issues\n", + "\n", + "#### 1. \"Could not connect to Llama Stack\"\n", + "\n", + "```bash\n", + "# Check if Llama Stack is running\n", + "curl http://localhost:8321/health\n", + "\n", + "# Start Llama Stack if needed\n", + "llama stack run\n", + "```\n", + "\n", + "#### 2. \"Model not found\"\n", + "\n", + "```bash\n", + "# List available models\n", + "curl http://localhost:8321/models\n", + "\n", + "# Make sure model name matches exactly:\n", + "# ✅ \"ollama/llama3.3:70b\"\n", + "# ❌ \"llama3.3:70b\"\n", + "```\n", + "\n", + "#### 3. \"Agent not responding\"\n", + "\n", + "- Check `max_consecutive_auto_reply` isn't set too low\n", + "- Increase `timeout` in `llm_config`\n", + "- Verify Llama Stack model is loaded and warm\n", + "\n", + "#### 4. \"Code execution failed\"\n", + "\n", + "- Make sure `code_execution_config` is set correctly\n", + "- Check file permissions on `work_dir`\n", + "- Install required Python packages\n", + "\n", + "---\n", + "\n", + "### Debug Mode\n", + "\n", + "```python\n", + "import logging\n", + "\n", + "# Enable AutoGen debug logging\n", + "logging.basicConfig(level=logging.DEBUG)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Summary\n", + "\n", + "### What We Covered\n", + "\n", + "1. ✅ **Two-Agent Conversations** - UserProxy + Assistant pattern\n", + "2. ✅ **Code Generation & Execution** - AutoGen's killer feature\n", + "3. ✅ **Group Chat** - Multiple agents collaborating\n", + "4. ✅ **Human-in-the-Loop** - Interactive workflows\n", + "5. ✅ **Sequential Reasoning** - Complex problem solving\n", + "6. ✅ **Custom Agents** - Specialized behaviors\n", + "\n", + "### Key Takeaways\n", + "\n", + "**AutoGen + Llama Stack is powerful for:**\n", + "- 🗣️ **Conversational** multi-agent systems\n", + "- 👤 **Interactive** problem-solving with humans\n", + "- 💻 **Code generation** and execution\n", + "- 🤝 **Collaborative** agent discussions\n", + "\n", + "**vs llamacrew which is better for:**\n", + "- 🔄 **Production workflows** and pipelines\n", + "- 📊 **Declarative** task orchestration\n", + "- ⚡ **Automatic parallelization**\n", + "- 🤖 **Non-interactive** automation\n", + "\n", + "---\n", + "\n", + "### Next Steps\n", + "\n", + "1. Experiment with different agent combinations\n", + "2. Try human-in-the-loop workflows\n", + "3. Build custom agents for your use case\n", + "4. Compare AutoGen vs llamacrew for your specific needs\n", + "\n", + "### Resources\n", + "\n", + "- **AutoGen Docs**: https://microsoft.github.io/autogen/\n", + "- **Llama Stack Docs**: https://llama-stack.readthedocs.io/\n", + "- **llamacrew Docs**: `/home/omara/Desktop/llamacrew/README.md`\n", + "\n", + "---\n", + "\n", + "**Happy multi-agent building! 🚀**" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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": 4 } From 1494ea5e43ab3155c2a519c7719d176de7193ab0 Mon Sep 17 00:00:00 2001 From: Omar Abdelwahab Date: Wed, 26 Nov 2025 12:22:31 -0800 Subject: [PATCH 3/7] Refined the notebook --- .../autogen_llama_stack_integration.ipynb | 1020 +++++++++-------- 1 file changed, 528 insertions(+), 492 deletions(-) diff --git a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb index 2e59ac0d7..36cf409e0 100644 --- a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb +++ b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb @@ -8,22 +8,20 @@ "\n", "## Overview\n", "\n", - "This notebook demonstrates how to use **AutoGen (AG2)** with **Llama Stack** as the backend.\n", + "This notebook demonstrates how to use **AutoGen v0.7.5** with **Llama Stack** as the backend.\n", "\n", "### Use Cases Covered:\n", - "1. **Two-Agent Conversation** - UserProxy + Assistant solving a problem\n", + "1. **Two-Agent Conversation** - Teams working together on tasks\n", "2. **Code Generation & Execution** - AutoGen generates and runs code\n", - "3. **Group Chat** - Multiple specialists collaborating\n", - "4. **Human-in-the-Loop** - Interactive problem-solving\n", - "5. **Sequential Task Solving** - Math problem → Code → Execute → Verify\n", + "3. **Group Chat** - Multiple specialists collaborating \n", "\n", "---\n", "\n", "## Prerequisites\n", "\n", "```bash\n", - "# Install AutoGen (AG2)\n", - "pip install pyautogen\n", + "# Install AutoGen v0.7.5 (new API)\n", + "pip install autogen-agentchat autogen-ext\n", "\n", "# Llama Stack should already be running\n", "# Default: http://localhost:8321\n", @@ -32,14 +30,34 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 1, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ AutoGen imports successful\n", + "Using AutoGen v0.7.5 with new team-based API\n", + "✅ Llama Stack is running at http://localhost:8321\n", + "Status: 200\n" + ] + } + ], "source": [ "# Imports\n", "import os\n", - "from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager\n", - "from autogen.oai import OpenAIWrapper\n", + "import asyncio\n", + "from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent\n", + "from autogen_agentchat.teams import RoundRobinGroupChat\n", + "from autogen_agentchat.base import TaskResult\n", + "from autogen_agentchat.messages import TextMessage\n", + "from autogen_ext.models.openai import OpenAIChatCompletionClient\n", + "\n", + "print(\"✅ AutoGen imports successful\")\n", + "print(\"Using AutoGen v0.7.5 with new team-based API\")\n", "\n", "# Check Llama Stack connectivity\n", "import httpx\n", @@ -47,7 +65,7 @@ "LLAMA_STACK_URL = \"http://localhost:8321\"\n", "\n", "try:\n", - " response = httpx.get(f\"{LLAMA_STACK_URL}/health\")\n", + " response = httpx.get(f\"{LLAMA_STACK_URL}/v1/models\")\n", " print(f\"✅ Llama Stack is running at {LLAMA_STACK_URL}\")\n", " print(f\"Status: {response.status_code}\")\n", "except Exception as e:\n", @@ -59,622 +77,640 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Configuration: AutoGen with Llama Stack\n", + "## Configuration: AutoGen v0.7.5 with Llama Stack\n", "\n", "### How It Works\n", "\n", - "AutoGen uses the **OpenAI API format**, which Llama Stack is compatible with!\n", - "\n", - "```python\n", - "config_list = [\n", - " {\n", - " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", - " \"base_url\": \"http://localhost:8321/v1\", # Llama Stack endpoint\n", - " \"api_key\": \"not-needed\", # Llama Stack doesn't need auth\n", - " }\n", - "]\n", - "```\n", - "\n", - "**Key Points:**\n", - "- Use `/v1` suffix for OpenAI-compatible endpoint\n", - "- `api_key` can be any string (Llama Stack ignores it)\n", - "- `model` must match what's available in Llama Stack" + "AutoGen v0.7.5 uses **OpenAIChatCompletionClient** to connect to OpenAI-compatible endpoints like Llama Stack's /v1/chat/completions." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Model client configured for Llama Stack\n", + "Model: ollama/llama3.3:70b\n", + "Base URL: http://localhost:8321/v1\n" + ] + } + ], "source": [ - "# AutoGen configuration for Llama Stack\n", - "config_list = [\n", - " {\n", - " \"model\": \"ollama/llama3.3:70b\", # Your Llama Stack model\n", - " \"base_url\": \"http://localhost:8321/v1\", # OpenAI-compatible endpoint\n", - " \"api_key\": \"not-needed\", # Llama Stack doesn't require auth\n", + "# Create OpenAI-compatible client for Llama Stack\n", + "model_client = OpenAIChatCompletionClient(\n", + " model=\"ollama/llama3.3:70b\", # Choose any other model of your choice.\n", + " api_key=\"not-needed\",\n", + " base_url=\"http://localhost:8321/v1\", # For pointing to llama stack end points.\n", + " model_capabilities={\n", + " \"vision\": False,\n", + " \"function_calling\": True,\n", + " \"json_output\": True,\n", " }\n", - "]\n", + ")\n", "\n", - "llm_config = {\n", - " \"config_list\": config_list,\n", - " \"temperature\": 0.7,\n", - " \"timeout\": 120,\n", - "}\n", - "\n", - "print(\"✅ AutoGen configuration ready for Llama Stack\")\n", - "print(f\"Model: {config_list[0]['model']}\")\n", - "print(f\"Base URL: {config_list[0]['base_url']}\")" + "print(\"✅ Model client configured for Llama Stack\")\n", + "print(f\"Model: ollama/llama3.3:70b\")\n", + "print(f\"Base URL: http://localhost:8321/v1\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Example 1: Two-Agent Conversation\n", + "## Example 1: Simple Task with Assistant Agent\n", "\n", - "### Pattern: User Proxy + Assistant\n", + "### Pattern: Single Agent Task\n", "\n", - "**UserProxyAgent:**\n", - "- Represents the human user\n", - "- Can execute code\n", - "- Provides feedback to assistant\n", + "In v0.7.5, Autogen uses **Teams** to orchestrate agents, even for simple single-agent tasks.\n", "\n", "**AssistantAgent:**\n", "- AI assistant powered by Llama Stack\n", - "- Generates responses and code\n", - "- Solves problems conversationally\n", + "- Executes tasks and provides responses\n", "\n", "### Use Case: Solve a Math Problem" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Agent created: MathAssistant\n", + "\n", + "==================================================\n", + "Task Result:\n", + "To find the sum of the first 10 prime numbers, we need to follow these steps:\n", + "\n", + "1. **Identify the first 10 prime numbers**: Prime numbers are natural numbers greater than 1 that have no divisors other than 1 and themselves.\n", + "\n", + "2. **List the first 10 prime numbers**:\n", + " - Start with 2 (the smallest prime number).\n", + " - Check each subsequent natural number to see if it is divisible by any prime number less than or equal to its square root. If not, it's a prime number.\n", + " - Continue until we have 10 prime numbers.\n", + "\n", + "3. **Calculate the sum** of these numbers.\n", + "\n", + "Let's list the first 10 prime numbers step by step:\n", + "\n", + "1. The smallest prime number is **2**.\n", + "2. The next prime number after 2 is **3**, since it's only divisible by 1 and itself.\n", + "3. Then comes **5**, because it has no divisors other than 1 and itself.\n", + "4. Next is **7**, for the same reason as above.\n", + "5. **11** is also a prime number, as it cannot be divided evenly by any number other than 1 and itself.\n", + "6. Following this pattern, we identify **13** as a prime number.\n", + "7. Then, **17**.\n", + "8. Next in line is **19**.\n", + "9. After that, we have **23**.\n", + "10. The tenth prime number is **29**.\n", + "\n", + "So, the first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29.\n", + "\n", + "Now, let's **calculate their sum**:\n", + "\n", + "- Start with 0 (or any starting number for summation).\n", + "- Add each prime number to the total:\n", + " - 0 + 2 = 2\n", + " - 2 + 3 = 5\n", + " - 5 + 5 = 10\n", + " - 10 + 7 = 17\n", + " - 17 + 11 = 28\n", + " - 28 + 13 = 41\n", + " - 41 + 17 = 58\n", + " - 58 + 19 = 77\n", + " - 77 + 23 = 100\n", + " - 100 + 29 = 129\n", + "\n", + "Therefore, the sum of the first 10 prime numbers is **129**.\n" + ] + } + ], "source": [ - "# Create AssistantAgent (AI assistant)\n", + "import asyncio\n", + "\n", + "# Create an AssistantAgent\n", "assistant = AssistantAgent(\n", " name=\"MathAssistant\",\n", - " system_message=\"You are a helpful AI assistant that solves math problems. Provide clear explanations.\",\n", - " llm_config=llm_config,\n", + " model_client=model_client,\n", + " system_message=\"You are a helpful AI assistant that solves math problems. Provide clear explanations and show your work.\"\n", ")\n", "\n", - "# Create UserProxyAgent (represents human)\n", - "user_proxy = UserProxyAgent(\n", - " name=\"User\",\n", - " human_input_mode=\"NEVER\", # Fully automated (no human input)\n", - " max_consecutive_auto_reply=5,\n", - " code_execution_config={\"use_docker\": False}, # Allow local code execution\n", - ")\n", + "print(\"✅ Agent created:\", assistant.name)\n", "\n", - "print(\"✅ Agents created\")\n", - "print(f\"Assistant: {assistant.name}\")\n", - "print(f\"User Proxy: {user_proxy.name}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Start conversation\n", - "user_proxy.initiate_chat(\n", - " assistant,\n", - " message=\"What is the sum of the first 100 prime numbers? Please write Python code to calculate it.\"\n", - ")\n", + "# Define the task\n", + "task = \"What is the sum of the first 10 prime numbers? Please calculate it step by step.\"\n", + "\n", + "# Run the task (AutoGen v0.7.5 uses async)\n", + "async def run_simple_task():\n", + " # Create a simple team with just the assistant\n", + " team = RoundRobinGroupChat([assistant], max_turns=1)\n", + " result = await team.run(task=task)\n", + " return result\n", + "\n", + "# Execute in notebook\n", + "result = await run_simple_task()\n", "\n", "print(\"\\n\" + \"=\"*50)\n", - "print(\"Conversation complete!\")" + "print(\"Task Result:\")\n", + "print(result.messages[-1].content if result.messages else \"No response\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Example 2: Code Generation & Execution\n", + "## Example 2: Multi-Agent Team Collaboration\n", "\n", - "### Pattern: Assistant generates code → UserProxy executes it\n", + "### Pattern: Multiple Agents Working Together\n", "\n", - "This is AutoGen's killer feature: **automatic code execution**!\n", + "In v0.7.5, Autogen uses **RoundRobinGroupChat** to create teams where agents take turns contributing to a task.\n", "\n", - "### Use Case: Data Analysis Task" + "### Use Case: Write a Technical Blog Post" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a coding assistant\n", - "coding_assistant = AssistantAgent(\n", - " name=\"DataScientist\",\n", - " system_message=\"\"\"You are an expert data scientist.\n", - " Write Python code to solve data analysis problems.\n", - " Always include visualizations when appropriate.\"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "# User proxy with code execution enabled\n", - "user_proxy_code = UserProxyAgent(\n", - " name=\"UserProxy\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=3,\n", - " code_execution_config={\n", - " \"work_dir\": \"coding\",\n", - " \"use_docker\": False,\n", - " },\n", - ")\n", - "\n", - "# Start data analysis task\n", - "user_proxy_code.initiate_chat(\n", - " coding_assistant,\n", - " message=\"\"\"Generate 100 random numbers from a normal distribution (mean=50, std=10).\n", - " Calculate the mean, median, and standard deviation.\n", - " Create a histogram to visualize the distribution.\"\"\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 3: Group Chat (Multi-Agent Collaboration)\n", - "\n", - "### Pattern: Multiple Specialists Collaborating\n", - "\n", - "**Scenario:** Write a technical blog post about AI\n", - "\n", - "**Agents:**\n", - "1. **Researcher** - Finds information\n", - "2. **Writer** - Writes content\n", - "3. **Critic** - Reviews and suggests improvements\n", - "4. **UserProxy** - Orchestrates and provides final approval\n", - "\n", - "This is similar to llamacrew's workflow but **conversational** instead of DAG-based!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Team agents created: Researcher, Writer, Critic\n", + "\n", + "==================================================\n", + "Final Blog Post:\n", + "==================================================\n", + "Turn 1\n", + "\n", + "[user]: Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", + "\n", + " Steps:\n", + " 1. Researcher: Gather key information about Llama Stack\n", + " 2. Writer: Create the blog post\n", + " ...\n", + "Turn 2\n", + "\n", + "[Researcher]: **Unlocking Efficient LLM Applications with Llama Stack**\n", + "\n", + "The Llama Stack is a cutting-edge framework designed to optimize Large Language Model (LLM) applications, offering numerous benefits for deve...\n", + "Turn 3\n", + "\n", + "[Writer]: **Unlocking Efficient LLM Applications with Llama Stack**\n", + "\n", + "The Llama Stack is a revolutionary framework that optimizes Large Language Model (LLM) applications, offering numerous benefits for developer...\n", + "Turn 4\n", + "\n", + "[Critic]: **Reviewed Blog Post:**\n", + "\n", + "The provided blog post effectively highlights the benefits of using the Llama Stack for Large Language Model (LLM) applications. However, there are a few areas that could be i...\n", + "Turn 5\n", + "\n", + "[Researcher]: Here's a 200-word blog post about the benefits of using Llama Stack for LLM applications:\n", + "\n", + "**Unlocking Efficient LLM Applications with Llama Stack**\n", + "\n", + "The Llama Stack is a revolutionary framework that ...\n", + "Turn 6\n", + "\n", + "[Writer]: **Unlocking Efficient LLM Applications with Llama Stack**\n", + "\n", + "The Llama Stack is a game-changer for Large Language Model (LLM) applications, offering numerous benefits for developers and users. By utiliz...\n", + "Turn 7\n", + "\n", + "[Critic]: **Critic's Review:**\n", + "\n", + "The provided blog post effectively communicates the benefits of using the Llama Stack for Large Language Model (LLM) applications. Here are some key observations and suggestions ...\n", + "Turn 8\n", + "\n", + "[Researcher]: Here's a rewritten 200-word blog post about the benefits of using Llama Stack for LLM applications:\n", + "\n", + "**Unlock Efficient LLM Applications with Llama Stack**\n", + "\n", + "In the rapidly evolving landscape of Large ...\n", + "Turn 9\n", + "\n", + "[Writer]: **Unlock Efficient LLM Applications with Llama Stack**\n", + "\n", + "The Llama Stack revolutionizes Large Language Model (LLM) applications by providing a game-changing framework that optimizes development and dep...\n", + "Turn 10\n", + "\n", + "[Critic]: **Editor's Review:**\n", + "\n", + "The rewritten blog post effectively communicates the benefits of using the Llama Stack for Large Language Model (LLM) applications. Here are some key observations and suggestions...\n", + "Turn 11\n", + "\n", + "[Researcher]: Here's a rewritten 200-word blog post about the benefits of using Llama Stack for LLM applications:\n", + "\n", + "**Unlock Efficient LLM Applications with Llama Stack**\n", + "\n", + "In the rapidly evolving landscape of Large ...\n", + "Turn 12\n", + "\n", + "[Writer]: **Unlock Efficient LLM Applications with Llama Stack**\n", + "\n", + "The rapidly evolving landscape of Large Language Models (LLMs) demands efficiency and scalability for success. The Llama Stack is a game-changin...\n", + "Turn 13\n", + "\n", + "[Critic]: **Editor's Review:**\n", + "\n", + "The rewritten blog post effectively communicates the benefits of using the Llama Stack for Large Language Model (LLM) applications. Here are some key observations and suggestions...\n" + ] + } + ], "source": [ "# Create specialist agents\n", "researcher = AssistantAgent(\n", " name=\"Researcher\",\n", - " system_message=\"\"\"You are a researcher. Your job is to find accurate information\n", - " about topics and provide facts, statistics, and recent developments.\"\"\",\n", - " llm_config=llm_config,\n", + " model_client=model_client,\n", + " system_message=\"You are a researcher. Provide accurate information, facts, and statistics about topics.\"\n", ")\n", "\n", "writer = AssistantAgent(\n", " name=\"Writer\",\n", - " system_message=\"\"\"You are a technical writer. Your job is to write clear,\n", - " engaging content based on research provided. Use simple language and examples.\"\"\",\n", - " llm_config=llm_config,\n", + " model_client=model_client,\n", + " system_message=\"You are a technical writer. Write clear, engaging content based on research provided.\"\n", ")\n", "\n", "critic = AssistantAgent(\n", " name=\"Critic\",\n", - " system_message=\"\"\"You are an editor. Review content for clarity, accuracy,\n", - " and engagement. Suggest specific improvements.\"\"\",\n", - " llm_config=llm_config,\n", + " model_client=model_client,\n", + " system_message=\"You are an editor. Review content for clarity, accuracy, and engagement. Suggest improvements.\"\n", ")\n", "\n", - "# User proxy to orchestrate\n", - "user_proxy_group = UserProxyAgent(\n", - " name=\"UserProxy\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=10,\n", - " code_execution_config=False,\n", - ")\n", + "print(\"✅ Team agents created: Researcher, Writer, Critic\")\n", "\n", - "print(\"✅ Group chat agents created\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create group chat\n", - "groupchat = GroupChat(\n", - " agents=[user_proxy_group, researcher, writer, critic],\n", - " messages=[],\n", - " max_round=12, # Maximum conversation rounds\n", - ")\n", + "# Create a team with round-robin collaboration\n", + "async def run_blog_team():\n", + " team = RoundRobinGroupChat([researcher, writer, critic], max_turns=12)\n", "\n", - "# Create manager to orchestrate\n", - "manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config)\n", + " task = \"\"\"Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", "\n", - "# Start group chat\n", - "user_proxy_group.initiate_chat(\n", - " manager,\n", - " message=\"\"\"Write a 300-word blog post about the benefits of using\n", - " Llama Stack for LLM applications. Include:\n", - " 1. What Llama Stack is\n", - " 2. Key benefits\n", - " 3. A simple use case example\n", - "\n", - " Researcher: gather information\n", - " Writer: create the blog post\n", - " Critic: review and suggest improvements\n", + " Steps:\n", + " 1. Researcher: Gather key information about Llama Stack\n", + " 2. Writer: Create the blog post\n", + " 3. Critic: Review and suggest improvements\n", " \"\"\"\n", - ")" + "\n", + " result = await team.run(task=task)\n", + " return result\n", + "\n", + "# Run the team\n", + "result = await run_blog_team()\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Final Blog Post:\")\n", + "print(\"=\"*50)\n", + "# Print the last message which should contain the final output\n", + "# for msg in result.messages[-3:]:\n", + "# print(f\"\\n[{msg.source}]: {msg.content[:200]}...\" if len(msg.content) > 200 else f\"\\n[{msg.source}]: {msg.content}\")\n", + "i=1\n", + "for msg in result.messages:\n", + " print (f\"Turn {i}\")\n", + " i+=1\n", + " print(f\"\\n[{msg.source}]: {msg.content[:200]}...\" if len(msg.content) > 200 else f\"\\n[{msg.source}]: {msg.content}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Example 4: Human-in-the-Loop\n", + "## Example 3: Multi-Turn Task\n", "\n", - "### Pattern: Interactive Problem Solving\n", + "### Pattern: Extended Team Collaboration\n", "\n", - "Autogen excels at **human-in-the-loop** workflows where you can:\n", - "- Provide feedback mid-conversation\n", - "- Approve/reject suggestions\n", - "- Guide the agent's direction\n", + "Use longer conversations for problem-solving where agents need multiple rounds of discussion.\n", "\n", - "**Note:** In notebooks, this requires `human_input_mode=\"ALWAYS\"` or `\"TERMINATE\"` and manual input." + "### Use Case: Technical Analysis" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 6, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Analyst agent created\n", + "\n", + "==================================================\n", + "Analysis Result:\n", + "==================================================\n", + "Turn 1\n", + "Analyze the trade-offs between using local LLMs (like Llama via Llama Stack)\n", + " versus cloud-based APIs (like OpenAI) for production applications.\n", + " Consider: cost, latency, privacy, scalability, and maintenance.\n", + "==================================================\n", + "Turn 2\n", + "The debate between using local Large Language Models (LLMs) like Llama via Llama Stack and cloud-based APIs like OpenAI for production applications revolves around several key trade-offs. Here's a detailed analysis of the pros and cons of each approach considering cost, latency, privacy, scalability, and maintenance.\n", + "\n", + "### Local LLMs (e.g., Llama via Llama Stack)\n", + "\n", + "**Pros:**\n", + "1. **Privacy:** Running models locally can offer enhanced data privacy since sensitive information doesn't need to be transmitted over the internet or stored on third-party servers.\n", + "2. **Latency:** Local deployment typically results in lower latency for inference, as it eliminates the need for network requests and responses to cloud services.\n", + "3. **Customizability:** Users have full control over the model's training data, allowing for fine-tuning that is more tailored to their specific use case or industry.\n", + "4. **Dependence:** Reduced dependence on external APIs means applications are less vulnerable to service outages or changes in API terms of service.\n", + "\n", + "**Cons:**\n", + "1. **Cost:** While the cost per inference might be lower once models are set up, the initial investment for hardware and potentially personnel with expertise in machine learning can be high.\n", + "2. **Scalability:** Scaling local deployments to meet growing demand requires purchasing more powerful or additional servers, which can become prohibitively expensive.\n", + "3. **Maintenance:** Continuous updates to the model for maintaining performance or adapting to new data distributions require significant technical expertise and resource commitment.\n", + "\n", + "### Cloud-Based APIs (e.g., OpenAI)\n", + "\n", + "**Pros:**\n", + "1. **Scalability:** Cloud services can easily scale up or down based on demand, without requiring large upfront investments in hardware.\n", + "2. **Maintenance:** The maintenance burden, including model updates and security patches, is handled by the cloud provider.\n", + "3. **Accessibility:** Lower barrier to entry due to a lack of need for significant initial investment in hardware or ML expertise; users can start with basic development resources.\n", + "4. **Cost-Effectiveness:** Pricing models often include a free tier and are usually billed per use (e.g., per API call), making it more predictable and manageable for businesses with fluctuating demand.\n", + "\n", + "**Cons:**\n", + "1. **Privacy:** Sending data to cloud services may pose significant privacy risks, especially for sensitive information.\n", + "2. **Latency:** Network latency can impact the speed of inferences compared to local deployments.\n", + "3. **Dependence on Third Parties:** Applications relying on external APIs are at risk if those services change their pricing model, terms of service, or experience outages.\n", + "4. **Cost at Scale:** While cost-effective for small projects, as usage scales up, costs can quickly add up and become significant.\n", + "\n", + "### Recommendations\n", + "\n", + "- **Use Local LLMs:**\n", + " - When data privacy is paramount (e.g., in healthcare, finance).\n", + " - For applications requiring ultra-low latency.\n", + " - In scenarios where customizability of the model for a specific task or domain is critical.\n", + "\n", + "- **Use Cloud-Based APIs:**\n", + " - For proofs-of-concept, prototypes, or early-stage startups with variable and potentially low initial demand.\n", + " - When scalability needs are high and unpredictable, requiring rapid adjustments.\n", + " - In cases where the expertise and resources to manage local ML deployments are lacking.\n", + "\n", + "### Hybrid Approach\n", + "\n", + "A potential middle ground involves a hybrid approach: using cloud services for initial development and testing (benefiting from ease of use and scalability), and then transitioning to local deployment once the application has grown and can justify the investment in hardware and expertise. This transition point depends on various factors, including cost considerations, privacy requirements, and specific latency needs.\n", + "\n", + "In conclusion, the choice between local LLMs like Llama via Llama Stack and cloud-based APIs such as OpenAI for production applications hinges on a careful evaluation of trade-offs related to cost, latency, privacy, scalability, and maintenance. Each approach has its place, depending on the specific requirements and constraints of an application or project.\n", + "==================================================\n", + "Turn 3\n", + "\n", + "==================================================\n", + "Turn 4\n", + "When planning your deployment strategy:\n", + "- **Evaluate Privacy Requirements:** If data privacy is a significant concern, favor local deployments.\n", + "- **Assess Scalability Needs:** For high variability in demand, cloud services might offer more flexibility.\n", + "- **Consider Cost Predictability:** Cloud APIs provide cost predictability for variable usage patterns but can become expensive at large scales. Local deployments have higher upfront costs but potentially lower long-term costs per inference.\n", + "\n", + "Ultimately, the best approach may involve a combination of both local and cloud solutions, tailored to meet the evolving needs of your application as it grows and matures.\n", + "==================================================\n", + "Turn 5\n", + "\n", + "==================================================\n", + "Turn 6\n", + "**Final Consideration:** Regardless of which path you choose, ensure you have a deep understanding of your data's privacy implications and the legal requirements surrounding its handling. Additionally, maintaining flexibility in your architecture can allow for transitions between deployment strategies as needed.\n", + "==================================================\n" + ] + } + ], "source": [ - "# Interactive assistant (uncomment to try)\n", - "# WARNING: This will prompt for user input!\n", - "\n", - "# assistant_interactive = AssistantAgent(\n", - "# name=\"InteractiveAssistant\",\n", - "# system_message=\"You are a helpful assistant. Ask clarifying questions when needed.\",\n", - "# llm_config=llm_config,\n", - "# )\n", - "\n", - "# user_proxy_interactive = UserProxyAgent(\n", - "# name=\"Human\",\n", - "# human_input_mode=\"TERMINATE\", # Ask for human input when TERMINATE is mentioned\n", - "# max_consecutive_auto_reply=5,\n", - "# )\n", - "\n", - "# user_proxy_interactive.initiate_chat(\n", - "# assistant_interactive,\n", - "# message=\"Help me plan a machine learning project for customer churn prediction.\"\n", - "# )\n", - "\n", - "print(\"💡 Human-in-the-loop example (commented out to avoid blocking notebook execution)\")\n", - "print(\"Uncomment the code above to try interactive mode!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 5: Sequential Task Solving\n", - "\n", - "### Pattern: Chain of Thought Problem Solving\n", - "\n", - "**Scenario:** Solve a complex problem requiring multiple steps\n", - "\n", - "1. **Understand** the problem\n", - "2. **Plan** the solution approach\n", - "3. **Implement** the solution (code)\n", - "4. **Execute** and verify\n", - "5. **Explain** the results\n", - "\n", - "### Use Case: Fibonacci Sequence Analysis" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a reasoning assistant\n", - "reasoning_assistant = AssistantAgent(\n", - " name=\"ReasoningAssistant\",\n", - " system_message=\"\"\"You are a problem-solving assistant.\n", - " For complex problems:\n", - " 1. Break down the problem\n", - " 2. Plan the solution step-by-step\n", - " 3. Write clean, well-commented code\n", - " 4. Explain results clearly\n", - " \"\"\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "user_proxy_reasoning = UserProxyAgent(\n", - " name=\"User\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=5,\n", - " code_execution_config={\"work_dir\": \"reasoning\", \"use_docker\": False},\n", - ")\n", - "\n", - "# Complex problem requiring sequential reasoning\n", - "user_proxy_reasoning.initiate_chat(\n", - " reasoning_assistant,\n", - " message=\"\"\"Find the first 20 Fibonacci numbers where the number is also a prime number.\n", - "\n", - " Requirements:\n", - " 1. Explain the approach\n", - " 2. Write efficient Python code\n", - " 3. Display the results in a table\n", - " 4. Calculate what percentage of the first 100 Fibonacci numbers are prime\n", + "# Create an analyst agent\n", + "analyst = AssistantAgent(\n", + " name=\"TechAnalyst\",\n", + " model_client=model_client,\n", + " system_message=\"\"\"You are a technical analyst. Analyze technical topics deeply:\n", + " 1. Break down complex concepts\n", + " 2. Identify pros and cons\n", + " 3. Provide recommendations\n", " \"\"\"\n", - ")" + ")\n", + "\n", + "print(\"✅ Analyst agent created\")\n", + "\n", + "# Run extended analysis\n", + "async def run_analysis():\n", + " team = RoundRobinGroupChat([analyst], max_turns=5)\n", + "\n", + " task = \"\"\"Analyze the trade-offs between using local LLMs (like Llama via Llama Stack)\n", + " versus cloud-based APIs (like OpenAI) for production applications.\n", + " Consider: cost, latency, privacy, scalability, and maintenance.\"\"\"\n", + "\n", + " result = await team.run(task=task)\n", + " return result\n", + "\n", + "result = await run_analysis()\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Analysis Result:\")\n", + "print(\"=\"*50)\n", + "i=1\n", + "for message in result.messages:\n", + " print (f\"Turn {i}\")\n", + " i+=1\n", + " print(message.content)\n", + " print(\"=\"*50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Comparison: AutoGen vs llamacrew\n", + "## Example 4: Advanced Termination Conditions\n", "\n", - "### When to Use AutoGen + Llama Stack\n", + "### Pattern: Code Review Loop with Stopping Logic\n", "\n", - "✅ **Use AutoGen when you need:**\n", - "- **Conversational** interactions between agents\n", - "- **Human-in-the-loop** workflows (interactive approval, feedback)\n", - "- **Code generation & execution** (data analysis, scripting)\n", - "- **Group discussions** (multiple agents debating, collaborating)\n", - "- **Dynamic problem-solving** (unknown number of back-and-forth exchanges)\n", - "- **Research/prototyping** (exploratory work)\n", + "This example demonstrates termination using:\n", + "1. **Multiple agents** in a review loop\n", + "2. **Termination on approval** - Stops when reviewer says \"LGTM\"\n", + "3. **Fallback with max_turns** for safety\n", "\n", - "**Example Use Cases:**\n", - "- Interactive coding assistant\n", - "- Research assistant with human feedback\n", - "- Multi-agent debate/discussion\n", - "- Tutoring/educational applications\n", - "- Dynamic customer support\n", - "\n", - "---\n", - "\n", - "### When to Use llamacrew\n", - "\n", - "✅ **Use llamacrew when you need:**\n", - "- **Production workflows** (blog writing, data pipelines)\n", - "- **Declarative DAGs** (predefined task dependencies)\n", - "- **Automatic parallelization** (framework optimizes)\n", - "- **Non-interactive automation** (scheduled jobs)\n", - "- **Minimal dependencies** (lightweight deployment)\n", - "- **Predictable workflows** (known steps)\n", - "\n", - "**Example Use Cases:**\n", - "- Automated blog post generation\n", - "- Data ETL pipelines\n", - "- Report generation\n", - "- Batch processing\n", - "- Production automation\n", - "\n", - "---\n", - "\n", - "### They're Complementary!\n", - "\n", - "- **AutoGen**: Conversational, interactive, exploratory\n", - "- **llamacrew**: Workflow, automated, production\n", - "\n", - "You might use **AutoGen for prototyping** then move to **llamacrew for production**!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Advanced: Custom Agent Behaviors\n", - "\n", - "### Pattern: Specialized Agent with Custom Logic\n", - "\n", - "You can create agents with custom behavior beyond just prompts." + "### Use Case: Iterative Code Review Until Approved" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Code review team created\n" + ] + } + ], "source": [ - "from typing import Dict, List, Union\n", - "import re\n", + "from autogen_agentchat.conditions import TextMentionTermination\n", "\n", - "class CodeReviewAgent(AssistantAgent):\n", - " \"\"\"Custom agent that reviews code for specific patterns.\"\"\"\n", - "\n", - " def __init__(self, *args, **kwargs):\n", - " super().__init__(*args, **kwargs)\n", - " self.issues_found = []\n", - "\n", - " def review_code(self, code: str) -> Dict[str, List[str]]:\n", - " \"\"\"Custom method to review code for common issues.\"\"\"\n", - " issues = []\n", - "\n", - " # Check for common issues\n", - " if \"TODO\" in code or \"FIXME\" in code:\n", - " issues.append(\"Code contains TODO/FIXME comments\")\n", - "\n", - " if not re.search(r'def \\w+\\(.*\\):', code):\n", - " issues.append(\"No function definitions found\")\n", - "\n", - " if \"print(\" in code:\n", - " issues.append(\"Contains print statements (consider logging)\")\n", - "\n", - " self.issues_found.extend(issues)\n", - " return {\"issues\": issues, \"total\": len(issues)}\n", - "\n", - "# Create custom reviewer\n", - "code_reviewer = CodeReviewAgent(\n", + "# Create code review agents\n", + "code_reviewer = AssistantAgent(\n", " name=\"CodeReviewer\",\n", - " system_message=\"\"\"You are a code reviewer. Analyze code for:\n", - " - Code quality\n", - " - Best practices\n", - " - Potential bugs\n", + " model_client=model_client,\n", + " system_message=\"\"\"You are a senior code reviewer. Review code for:\n", + " - Bugs and edge cases\n", " - Performance issues\n", - " Provide specific, actionable feedback.\n", - " \"\"\",\n", - " llm_config=llm_config,\n", + " - Security vulnerabilities\n", + " - Best practices\n", + "\n", + " If the code looks good, say 'LGTM' (Looks Good To Me).\n", + " If issues found, provide specific feedback for improvement.\"\"\"\n", ")\n", "\n", - "print(\"✅ Custom CodeReviewAgent created with specialized review logic\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Performance Tips\n", + "code_developer = AssistantAgent(\n", + " name=\"Developer\",\n", + " model_client=model_client,\n", + " system_message=\"\"\"You are a developer. When you receive code review feedback:\n", + " - Address ALL issues mentioned\n", + " - Explain your changes\n", + " - Present the improved code\n", "\n", - "### 1. Model Selection\n", - "\n", - "```python\n", - "# Fast models for simple tasks\n", - "config_fast = {\n", - " \"model\": \"ollama/llama3.2:3b\", # Smaller, faster\n", - " \"temperature\": 0.5,\n", - "}\n", - "\n", - "# Powerful models for complex reasoning\n", - "config_powerful = {\n", - " \"model\": \"ollama/llama3.3:70b\", # Larger, better quality\n", - " \"temperature\": 0.7,\n", - "}\n", - "```\n", - "\n", - "### 2. Limit Conversation Rounds\n", - "\n", - "```python\n", - "user_proxy = UserProxyAgent(\n", - " name=\"User\",\n", - " max_consecutive_auto_reply=3, # Prevent infinite loops\n", + " If no feedback is given, present your initial implementation.\"\"\"\n", ")\n", - "```\n", "\n", - "### 3. Set Timeouts\n", + "print(\"✅ Code review team created\")\n", "\n", - "```python\n", - "llm_config = {\n", - " \"timeout\": 60, # 60 second timeout per request\n", - " \"config_list\": config_list,\n", - "}\n", - "```\n", + "# Complex termination: Stops when reviewer approves OR max iterations reached\n", + "async def run_code_review_loop():\n", + " # Stop when reviewer says \"LGTM\"\n", + " approval_termination = TextMentionTermination(\"LGTM\")\n", "\n", - "### 4. Use Work Directories\n", + " team = RoundRobinGroupChat(\n", + " [code_developer, code_reviewer],\n", + " max_turns=16, # Max 4 review cycles (developer + reviewer = 2 turns per cycle)\n", + " termination_condition=approval_termination\n", + " )\n", "\n", - "```python\n", - "code_execution_config = {\n", - " \"work_dir\": \"autogen_workspace\", # Isolate generated files\n", - " \"use_docker\": False,\n", - "}\n", - "```" + " task = \"\"\"Implement a Python function to check if a string is a palindrome.\n", + "\n", + " The Developer should implement the function first.\n", + " The Reviewer should then review it and provide feedback.\n", + " Continue iterating until the Reviewer approves the code.\n", + " \"\"\"\n", + "\n", + " result = await team.run(task=task)\n", + " return result\n", + "\n", + "result = await run_code_review_loop()\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(f\"✅ Review completed in {len(result.messages)} message(s)\")\n", + "print(f\"Stop reason: {result.stop_reason}\")\n", + "print(\"=\"*50)\n", + "\n", + "# Show the conversation flow\n", + "print(\"\\n📝 Review Conversation Flow:\")\n", + "for i, msg in enumerate(result.messages, 1):\n", + " preview = msg.content[:150].replace('\\n', ' ')\n", + " print(f\"{i}. [{msg.source}]: {preview}...\")\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Final Code (last message):\")\n", + "print(\"=\"*50)\n", + "if result.messages:\n", + " print(result.messages[-1].content)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Troubleshooting\n", + "## Example 5: Practical Team Use Case\n", "\n", - "### Common Issues\n", + "### Pattern: Research → Write → Review Pipeline\n", "\n", - "#### 1. \"Could not connect to Llama Stack\"\n", + "A common pattern in content creation: research, draft, review, finalize.\n", "\n", - "```bash\n", - "# Check if Llama Stack is running\n", - "curl http://localhost:8321/health\n", + "### Use Case: Documentation Generator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Create documentation team\n", + "doc_researcher = AssistantAgent(\n", + " name=\"DocResearcher\",\n", + " model_client=model_client,\n", + " system_message=\"You research technical topics and gather key information for documentation.\"\n", + ")\n", "\n", - "# Start Llama Stack if needed\n", - "llama stack run\n", - "```\n", + "doc_writer = AssistantAgent(\n", + " name=\"DocWriter\",\n", + " model_client=model_client,\n", + " system_message=\"You write clear, concise technical documentation with examples.\"\n", + ")\n", "\n", - "#### 2. \"Model not found\"\n", + "print(\"✅ Documentation team created\")\n", "\n", - "```bash\n", - "# List available models\n", - "curl http://localhost:8321/models\n", + "# Run documentation pipeline\n", + "async def create_documentation():\n", + " team = RoundRobinGroupChat([doc_researcher, doc_writer], max_turns=4)\n", + " task = \"\"\"Create documentation for a hypothetical food recipe:\n", "\n", - "# Make sure model name matches exactly:\n", - "# ✅ \"ollama/llama3.3:70b\"\n", - "# ❌ \"llama3.3:70b\"\n", - "```\n", + " Food: `Cheese Pizza`\n", "\n", - "#### 3. \"Agent not responding\"\n", + " Include:\n", + " - Description\n", + " - Ingredients\n", + " - How to make it\n", + " - Steps\n", + " \"\"\"\n", "\n", - "- Check `max_consecutive_auto_reply` isn't set too low\n", - "- Increase `timeout` in `llm_config`\n", - "- Verify Llama Stack model is loaded and warm\n", + " result = await team.run(task=task)\n", + " return result\n", "\n", - "#### 4. \"Code execution failed\"\n", + "result = await create_documentation()\n", "\n", - "- Make sure `code_execution_config` is set correctly\n", - "- Check file permissions on `work_dir`\n", - "- Install required Python packages\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Generated Documentation:\")\n", + "print(\"=\"*50)\n", + "i=1\n", + "for message in result.messages:\n", + " print(f\"Turn {i}\")\n", + " i+=1\n", + " print(message.content)\n", "\n", - "---\n", - "\n", - "### Debug Mode\n", - "\n", - "```python\n", - "import logging\n", - "\n", - "# Enable AutoGen debug logging\n", - "logging.basicConfig(level=logging.DEBUG)\n", - "```" + "# Turn 1: `DocResearcher` receives the task → researches the topic\n", + "# Turn 2: `DocWriter` sees the task + researcher's output → writes documentation\n", + "# Turn 3**: `DocResearcher` sees everything → can add more info\n", + "# Turn 4: `DocWriter` sees everything → refines documentation\n", + "# Stops at `max_turns=4`\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Summary\n", - "\n", - "### What We Covered\n", - "\n", - "1. ✅ **Two-Agent Conversations** - UserProxy + Assistant pattern\n", - "2. ✅ **Code Generation & Execution** - AutoGen's killer feature\n", - "3. ✅ **Group Chat** - Multiple agents collaborating\n", - "4. ✅ **Human-in-the-Loop** - Interactive workflows\n", - "5. ✅ **Sequential Reasoning** - Complex problem solving\n", - "6. ✅ **Custom Agents** - Specialized behaviors\n", - "\n", - "### Key Takeaways\n", - "\n", - "**AutoGen + Llama Stack is powerful for:**\n", - "- 🗣️ **Conversational** multi-agent systems\n", - "- 👤 **Interactive** problem-solving with humans\n", - "- 💻 **Code generation** and execution\n", - "- 🤝 **Collaborative** agent discussions\n", - "\n", - "**vs llamacrew which is better for:**\n", - "- 🔄 **Production workflows** and pipelines\n", - "- 📊 **Declarative** task orchestration\n", - "- ⚡ **Automatic parallelization**\n", - "- 🤖 **Non-interactive** automation\n", - "\n", - "---\n", - "\n", "### Next Steps\n", "\n", - "1. Experiment with different agent combinations\n", - "2. Try human-in-the-loop workflows\n", - "3. Build custom agents for your use case\n", - "4. Compare AutoGen vs llamacrew for your specific needs\n", + "1. **Install autogen-ext**: `pip install autogen-agentchat autogen-ext`\n", + "2. **Start Llama Stack**: Ensure it's running on `http://localhost:8321`\n", + "3. **Experiment**: Try different team compositions and task types\n", + "4. **Explore**: Check out SelectorGroupChat and other team types\n", "\n", "### Resources\n", "\n", - "- **AutoGen Docs**: https://microsoft.github.io/autogen/\n", - "- **Llama Stack Docs**: https://llama-stack.readthedocs.io/\n", - "- **llamacrew Docs**: `/home/omara/Desktop/llamacrew/README.md`\n", - "\n", - "---\n", - "\n", - "**Happy multi-agent building! 🚀**" + "- **AutoGen v0.7.5 Docs**: https://microsoft.github.io/autogen/\n", + "- **Llama Stack Docs**: https://llama-stack.readthedocs.io/" ] } ], From ac284f3f56fefd3e83fa140751f33a7e9a2c82e1 Mon Sep 17 00:00:00 2001 From: Omar Abdelwahab Date: Wed, 26 Nov 2025 12:24:43 -0800 Subject: [PATCH 4/7] Added the open in collab badge --- .../autogen_llama_stack_integration.ipynb | 288 +++++++++++++++++- 1 file changed, 284 insertions(+), 4 deletions(-) diff --git a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb index 36cf409e0..4154c5fb7 100644 --- a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb +++ b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb @@ -6,6 +6,8 @@ "source": [ "# AutoGen + Llama Stack Integration\n", "\n", + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/meta-llama/llama-stack/blob/main/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb)\n", + "\n", "## Overview\n", "\n", "This notebook demonstrates how to use **AutoGen v0.7.5** with **Llama Stack** as the backend.\n", @@ -541,7 +543,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "scrolled": true }, @@ -550,7 +552,97 @@ "name": "stdout", "output_type": "stream", "text": [ - "✅ Code review team created\n" + "✅ Code review team created\n", + "\n", + "==================================================\n", + "✅ Review completed in 5 message(s)\n", + "Stop reason: Text 'LGTM' mentioned\n", + "==================================================\n", + "\n", + "📝 Review Conversation Flow:\n", + "1. [user]: Implement a Python function to check if a string is a palindrome. The Developer should implement the function first. The Reviewer should then...\n", + "2. [Developer]: ### Initial Implementation ```python def is_palindrome(s: str) -> bool: \"\"\" Checks if a given string is a palindrome. Args: s (st...\n", + "3. [CodeReviewer]: ### Code Review Feedback #### Bugs and Edge Cases * The function does not handle non-string inputs. It should raise a `TypeError` when given a non-st...\n", + "4. [Developer]: ### Revised Implementation ```python def is_palindrome(s: str, ignore_case: bool = True, ignore_whitespace_and_punctuation: bool = True) -> bool: ...\n", + "5. [CodeReviewer]: ### Code Review Feedback The revised implementation has addressed all the concerns raised during the initial code review. Here's a summary of the key...\n", + "\n", + "==================================================\n", + "Final Code (last message):\n", + "==================================================\n", + "### Code Review Feedback\n", + "\n", + "The revised implementation has addressed all the concerns raised during the initial code review. Here's a summary of the key points:\n", + "\n", + "* **Type checking**: The function now correctly raises a `TypeError` if the input is not a string.\n", + "* **Optional parameters**: The addition of optional parameters for ignoring case and whitespace/punctuation provides flexibility in how palindromes are checked.\n", + "* **Preprocessing**: The preprocessing steps to ignore case and remove non-alphanumeric characters are implemented correctly and efficiently.\n", + "* **Efficient palindrome check**: The two-pointer approach used to compare characters from both ends of the string is efficient, with a time complexity of O(n).\n", + "* **Documentation and examples**: The docstring has been improved with clear explanations and examples, making it easier for users to understand how to use the function.\n", + "\n", + "#### Minor Suggestions\n", + "\n", + "1. **Input Validation**: Consider adding input validation for the optional parameters `ignore_case` and `ignore_whitespace_and_punctuation`. Currently, they are expected to be boolean values, but there is no explicit check for this.\n", + "2. **Type Hints for Optional Parameters**: While not required, adding type hints for the optional parameters can improve code readability and help catch potential errors.\n", + "\n", + "#### Revised Implementation with Minor Suggestions\n", + "\n", + "```python\n", + "def is_palindrome(s: str, ignore_case: bool = True, ignore_whitespace_and_punctuation: bool = True) -> bool:\n", + " \"\"\"\n", + " Checks if a given string is a palindrome.\n", + "\n", + " Args:\n", + " s (str): The input string to check.\n", + " ignore_case (bool): Whether to ignore case when checking for palindromes. Defaults to True.\n", + " ignore_whitespace_and_punctuation (bool): Whether to ignore whitespace and punctuation when checking for palindromes. Defaults to True.\n", + "\n", + " Returns:\n", + " bool: True if the string is a palindrome, False otherwise.\n", + "\n", + " Raises:\n", + " TypeError: If s is not a string or if ignore_case/ignore_whitespace_and_punctuation are not boolean values.\n", + "\n", + " Examples:\n", + " >>> is_palindrome(\"radar\")\n", + " True\n", + " >>> is_palindrome(\"hello\")\n", + " False\n", + " >>> is_palindrome(\"A man, a plan, a canal: Panama\", ignore_whitespace_and_punctuation=True)\n", + " True\n", + " \"\"\"\n", + " # Check input type\n", + " if not isinstance(s, str):\n", + " raise TypeError(\"Input must be a string\")\n", + " \n", + " # Validate optional parameters\n", + " if not isinstance(ignore_case, bool) or not isinstance(ignore_whitespace_and_punctuation, bool):\n", + " raise TypeError(\"Optional parameters must be boolean values\")\n", + "\n", + " # Preprocess the string based on options\n", + " if ignore_case:\n", + " s = s.casefold()\n", + " if ignore_whitespace_and_punctuation:\n", + " s = ''.join(c for c in s if c.isalnum())\n", + "\n", + " # Compare characters from both ends of the string, moving towards the center\n", + " left, right = 0, len(s) - 1\n", + " while left < right:\n", + " if s[left] != s[right]:\n", + " return False\n", + " left += 1\n", + " right -= 1\n", + " return True\n", + "\n", + "# Example usage:\n", + "if __name__ == \"__main__\":\n", + " print(is_palindrome(\"radar\")) # Expected output: True\n", + " print(is_palindrome(\"hello\")) # Expected output: False\n", + " print(is_palindrome(\"A man, a plan, a canal: Panama\", ignore_whitespace_and_punctuation=True)) # Expected output: True\n", + "```\n", + "\n", + "With these minor suggestions addressed, the code is robust and follows best practices for readability, maintainability, and error handling.\n", + "\n", + "LGTM!\n" ] } ], @@ -640,11 +732,199 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Documentation team created\n", + "\n", + "==================================================\n", + "Generated Documentation:\n", + "==================================================\n", + "Turn 1\n", + "Create documentation for a hypothetical food recipe:\n", + "\n", + " Food: `Cheese Pizza`\n", + "\n", + " Include:\n", + " - Description\n", + " - Ingredients\n", + " - How to make it\n", + " - Steps\n", + " \n", + "Turn 2\n", + "**Cheese Pizza Recipe Documentation**\n", + "=====================================\n", + "\n", + "### Description\n", + "\n", + "A classic Cheese Pizza is a delicious and satisfying dish that consists of a crispy crust topped with a rich tomato sauce, melted mozzarella cheese, and various seasonings. This recipe provides a simple and easy-to-follow guide to making a mouth-watering Cheese Pizza at home.\n", + "\n", + "### Ingredients\n", + "\n", + "* **Crust:**\n", + "\t+ 2 cups of warm water\n", + "\t+ 1 tablespoon of sugar\n", + "\t+ 2 teaspoons of active dry yeast\n", + "\t+ 3 cups of all-purpose flour\n", + "\t+ 1 teaspoon of salt\n", + "\t+ 2 tablespoons of olive oil\n", + "* **Sauce:**\n", + "\t+ 2 cups of crushed tomatoes\n", + "\t+ 1/4 cup of olive oil\n", + "\t+ 4 cloves of garlic, minced\n", + "\t+ 1 teaspoon of dried oregano\n", + "\t+ Salt and pepper to taste\n", + "* **Toppings:**\n", + "\t+ 8 ounces of mozzarella cheese, shredded\n", + "\t+ Fresh basil leaves, chopped (optional)\n", + "\n", + "### How to Make It\n", + "\n", + "To make a Cheese Pizza, follow these steps:\n", + "\n", + "#### Steps\n", + "\n", + "1. **Activate the Yeast:**\n", + "\t* In a large bowl, combine the warm water, sugar, and yeast.\n", + "\t* Stir gently to dissolve the yeast, and let it sit for 5-10 minutes until frothy.\n", + "2. **Make the Crust:**\n", + "\t* Add the flour, salt, and olive oil to the bowl with the yeast mixture.\n", + "\t* Mix the dough until it comes together in a ball.\n", + "\t* Knead the dough on a floured surface for 5-10 minutes until smooth and elastic.\n", + "3. **Prepare the Sauce:**\n", + "\t* In a separate bowl, combine the crushed tomatoes, olive oil, garlic, oregano, salt, and pepper.\n", + "\t* Mix well to create a smooth sauce.\n", + "4. **Assemble the Pizza:**\n", + "\t* Preheat the oven to 425°F (220°C).\n", + "\t* Roll out the dough into a circle or rectangle shape, depending on your preference.\n", + "\t* Place the dough on a baking sheet or pizza stone.\n", + "\t* Spread the tomato sauce evenly over the dough, leaving a small border around the edges.\n", + "5. **Add the Cheese:**\n", + "\t* Sprinkle the shredded mozzarella cheese over the sauce.\n", + "6. **Bake the Pizza:**\n", + "\t* Bake the pizza in the preheated oven for 15-20 minutes until the crust is golden brown and the cheese is melted and bubbly.\n", + "7. **Garnish with Fresh Basil (Optional):**\n", + "\t* Remove the pizza from the oven and sprinkle chopped fresh basil leaves over the top, if desired.\n", + "\n", + "### Tips and Variations\n", + "\n", + "* For a crispy crust, bake the pizza for an additional 2-3 minutes.\n", + "* Add other toppings such as pepperoni, sausage, or mushrooms to create a unique flavor combination.\n", + "* Use different types of cheese, such as cheddar or parmesan, for a varied flavor profile.\n", + "\n", + "Enjoy your delicious homemade Cheese Pizza!\n", + "Turn 3\n", + "**Cheese Pizza Recipe Documentation**\n", + "=====================================\n", + "\n", + "### Description\n", + "\n", + "A classic Cheese Pizza is a delicious and satisfying dish that consists of a crispy crust topped with a rich tomato sauce, melted mozzarella cheese, and various seasonings. This recipe provides a simple and easy-to-follow guide to making a mouth-watering Cheese Pizza at home.\n", + "\n", + "### Ingredients\n", + "\n", + "* **Crust:**\n", + "\t+ 2 cups of warm water\n", + "\t+ 1 tablespoon of sugar\n", + "\t+ 2 teaspoons of active dry yeast\n", + "\t+ 3 cups of all-purpose flour\n", + "\t+ 1 teaspoon of salt\n", + "\t+ 2 tablespoons of olive oil\n", + "* **Sauce:**\n", + "\t+ 2 cups of crushed tomatoes\n", + "\t+ 1/4 cup of olive oil\n", + "\t+ 4 cloves of garlic, minced\n", + "\t+ 1 teaspoon of dried oregano\n", + "\t+ Salt and pepper to taste\n", + "* **Toppings:**\n", + "\t+ 8 ounces of mozzarella cheese, shredded\n", + "\t+ Fresh basil leaves, chopped (optional)\n", + "\n", + "### How to Make It\n", + "\n", + "To make a Cheese Pizza, follow these steps:\n", + "\n", + "#### Steps\n", + "\n", + "1. **Activate the Yeast:**\n", + "\t* In a large bowl, combine the warm water, sugar, and yeast.\n", + "\t* Stir gently to dissolve the yeast, and let it sit for 5-10 minutes until frothy.\n", + "2. **Make the Crust:**\n", + "\t* Add the flour, salt, and olive oil to the bowl with the yeast mixture.\n", + "\t* Mix the dough until it comes together in a ball.\n", + "\t* Knead the dough on a floured surface for 5-10 minutes until smooth and elastic.\n", + "3. **Prepare the Sauce:**\n", + "\t* In a separate bowl, combine the crushed tomatoes, olive oil, garlic, oregano, salt, and pepper.\n", + "\t* Mix well to create a smooth sauce.\n", + "4. **Assemble the Pizza:**\n", + "\t* Preheat the oven to 425°F (220°C).\n", + "\t* Roll out the dough into a circle or rectangle shape, depending on your preference.\n", + "\t* Place the dough on a baking sheet or pizza stone.\n", + "\t* Spread the tomato sauce evenly over the dough, leaving a small border around the edges.\n", + "5. **Add the Cheese:**\n", + "\t* Sprinkle the shredded mozzarella cheese over the sauce.\n", + "6. **Bake the Pizza:**\n", + "\t* Bake the pizza in the preheated oven for 15-20 minutes until the crust is golden brown and the cheese is melted and bubbly.\n", + "7. **Garnish with Fresh Basil (Optional):**\n", + "\t* Remove the pizza from the oven and sprinkle chopped fresh basil leaves over the top, if desired.\n", + "\n", + "### Tips and Variations\n", + "\n", + "* For a crispy crust, bake the pizza for an additional 2-3 minutes.\n", + "* Add other toppings such as pepperoni, sausage, or mushrooms to create a unique flavor combination.\n", + "* Use different types of cheese, such as cheddar or parmesan, for a varied flavor profile.\n", + "\n", + "Enjoy your delicious homemade Cheese Pizza!\n", + "Turn 4\n", + "It seems like you've copied the entire Cheese Pizza Recipe Documentation I provided earlier. If you'd like to make any changes or additions to the recipe, or if you have any questions about it, feel free to ask and I'll be happy to help! \n", + "\n", + "If you're looking for some suggestions on how to improve the documentation, here are a few ideas:\n", + "\n", + "1. **Add nutritional information**: Providing the nutritional content of the Cheese Pizza, such as calories, fat, carbohydrates, and protein, can be helpful for people who are tracking their diet.\n", + "2. **Include images or diagrams**: Adding images or diagrams of the different steps in the recipe can help to clarify the process and make it easier to follow.\n", + "3. **Provide variations for special diets**: Offering suggestions for how to modify the recipe to accommodate special dietary needs, such as gluten-free or vegan, can make the recipe more accessible to a wider range of people.\n", + "4. **Add a troubleshooting section**: Including a section that addresses common problems or issues that may arise during the cooking process, such as a crust that's too thick or cheese that's not melting properly, can help to ensure that the recipe turns out well.\n", + "\n", + "Let me know if you have any other questions or if there's anything else I can help with!\n", + "Turn 5\n", + "I apologize for copying the entire documentation earlier. You're right; it would be more helpful to provide suggestions or improvements to the existing recipe. Here are some potential additions and modifications:\n", + "\n", + "1. **Nutritional Information:**\n", + "\t* Calculating the nutritional content of the Cheese Pizza could involve breaking down the ingredients and their corresponding calorie, fat, carbohydrate, and protein contributions.\n", + "\t* For example:\n", + "\t\t+ Crust (2 cups flour, 1 teaspoon sugar, 1/4 cup olive oil): approximately 300-350 calories, 10-12g fat, 50-60g carbohydrates, 10-12g protein\n", + "\t\t+ Sauce (2 cups crushed tomatoes, 1/4 cup olive oil, 4 cloves garlic, 1 teaspoon dried oregano): approximately 100-150 calories, 10-12g fat, 20-25g carbohydrates, 5-7g protein\n", + "\t\t+ Cheese (8 ounces mozzarella): approximately 200-250 calories, 15-18g fat, 5-7g carbohydrates, 20-25g protein\n", + "\t* Total estimated nutritional content: approximately 600-750 calories, 35-42g fat, 75-92g carbohydrates, 35-44g protein (per serving)\n", + "2. **Images and Diagrams:**\n", + "\t* Adding images of the different steps in the recipe could help illustrate the process, such as:\n", + "\t\t+ A photo of the yeast mixture after it has sat for 5-10 minutes\n", + "\t\t+ An image of the dough being kneaded on a floured surface\n", + "\t\t+ A diagram showing how to roll out the dough into a circle or rectangle shape\n", + "3. **Variations for Special Diets:**\n", + "\t* Gluten-free crust option:\n", + "\t\t+ Replace all-purpose flour with gluten-free flour blend (containing rice flour, potato starch, and tapioca flour)\n", + "\t\t+ Add xanthan gum to help improve texture and structure\n", + "\t* Vegan cheese alternative:\n", + "\t\t+ Use vegan mozzarella cheese or soy-based cheese alternative\n", + "\t\t+ Consider adding nutritional yeast for a cheesy flavor\n", + "4. **Troubleshooting Section:**\n", + "\t* Common issues with the crust:\n", + "\t\t+ Too thick: try reducing the amount of flour or increasing the yeast fermentation time\n", + "\t\t+ Too thin: try increasing the amount of flour or adding more water\n", + "\t* Issues with the cheese melting:\n", + "\t\t+ Not melting properly: try broiling the pizza for an additional 1-2 minutes or using a higher-quality mozzarella cheese\n", + "\n", + "Please let me know if you'd like to discuss any of these suggestions further or if there's anything else I can help with!\n" + ] + } + ], "source": [ "# Create documentation team\n", "doc_researcher = AssistantAgent(\n", From 9bc1cf1248f743648f2bb7358fbaea3d7feedcfe Mon Sep 17 00:00:00 2001 From: Omar Abdelwahab Date: Fri, 28 Nov 2025 10:09:36 -0800 Subject: [PATCH 5/7] Added migration steps from autogen to microsoft agent framework --- .../autogen_llama_stack_integration.ipynb | 1018 ----------------- ...nt_framework_llama_stack_integration.ipynb | 918 +++++++++++++++ 2 files changed, 918 insertions(+), 1018 deletions(-) delete mode 100644 docs/notebooks/autogen/autogen_llama_stack_integration.ipynb create mode 100644 docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb diff --git a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb b/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb deleted file mode 100644 index 4154c5fb7..000000000 --- a/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb +++ /dev/null @@ -1,1018 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# AutoGen + Llama Stack Integration\n", - "\n", - "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/meta-llama/llama-stack/blob/main/docs/notebooks/autogen/autogen_llama_stack_integration.ipynb)\n", - "\n", - "## Overview\n", - "\n", - "This notebook demonstrates how to use **AutoGen v0.7.5** with **Llama Stack** as the backend.\n", - "\n", - "### Use Cases Covered:\n", - "1. **Two-Agent Conversation** - Teams working together on tasks\n", - "2. **Code Generation & Execution** - AutoGen generates and runs code\n", - "3. **Group Chat** - Multiple specialists collaborating \n", - "\n", - "---\n", - "\n", - "## Prerequisites\n", - "\n", - "```bash\n", - "# Install AutoGen v0.7.5 (new API)\n", - "pip install autogen-agentchat autogen-ext\n", - "\n", - "# Llama Stack should already be running\n", - "# Default: http://localhost:8321\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ AutoGen imports successful\n", - "Using AutoGen v0.7.5 with new team-based API\n", - "✅ Llama Stack is running at http://localhost:8321\n", - "Status: 200\n" - ] - } - ], - "source": [ - "# Imports\n", - "import os\n", - "import asyncio\n", - "from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent\n", - "from autogen_agentchat.teams import RoundRobinGroupChat\n", - "from autogen_agentchat.base import TaskResult\n", - "from autogen_agentchat.messages import TextMessage\n", - "from autogen_ext.models.openai import OpenAIChatCompletionClient\n", - "\n", - "print(\"✅ AutoGen imports successful\")\n", - "print(\"Using AutoGen v0.7.5 with new team-based API\")\n", - "\n", - "# Check Llama Stack connectivity\n", - "import httpx\n", - "\n", - "LLAMA_STACK_URL = \"http://localhost:8321\"\n", - "\n", - "try:\n", - " response = httpx.get(f\"{LLAMA_STACK_URL}/v1/models\")\n", - " print(f\"✅ Llama Stack is running at {LLAMA_STACK_URL}\")\n", - " print(f\"Status: {response.status_code}\")\n", - "except Exception as e:\n", - " print(f\"❌ Llama Stack not accessible: {e}\")\n", - " print(\"Make sure Llama Stack is running on port 8321\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Configuration: AutoGen v0.7.5 with Llama Stack\n", - "\n", - "### How It Works\n", - "\n", - "AutoGen v0.7.5 uses **OpenAIChatCompletionClient** to connect to OpenAI-compatible endpoints like Llama Stack's /v1/chat/completions." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Model client configured for Llama Stack\n", - "Model: ollama/llama3.3:70b\n", - "Base URL: http://localhost:8321/v1\n" - ] - } - ], - "source": [ - "# Create OpenAI-compatible client for Llama Stack\n", - "model_client = OpenAIChatCompletionClient(\n", - " model=\"ollama/llama3.3:70b\", # Choose any other model of your choice.\n", - " api_key=\"not-needed\",\n", - " base_url=\"http://localhost:8321/v1\", # For pointing to llama stack end points.\n", - " model_capabilities={\n", - " \"vision\": False,\n", - " \"function_calling\": True,\n", - " \"json_output\": True,\n", - " }\n", - ")\n", - "\n", - "print(\"✅ Model client configured for Llama Stack\")\n", - "print(f\"Model: ollama/llama3.3:70b\")\n", - "print(f\"Base URL: http://localhost:8321/v1\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 1: Simple Task with Assistant Agent\n", - "\n", - "### Pattern: Single Agent Task\n", - "\n", - "In v0.7.5, Autogen uses **Teams** to orchestrate agents, even for simple single-agent tasks.\n", - "\n", - "**AssistantAgent:**\n", - "- AI assistant powered by Llama Stack\n", - "- Executes tasks and provides responses\n", - "\n", - "### Use Case: Solve a Math Problem" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Agent created: MathAssistant\n", - "\n", - "==================================================\n", - "Task Result:\n", - "To find the sum of the first 10 prime numbers, we need to follow these steps:\n", - "\n", - "1. **Identify the first 10 prime numbers**: Prime numbers are natural numbers greater than 1 that have no divisors other than 1 and themselves.\n", - "\n", - "2. **List the first 10 prime numbers**:\n", - " - Start with 2 (the smallest prime number).\n", - " - Check each subsequent natural number to see if it is divisible by any prime number less than or equal to its square root. If not, it's a prime number.\n", - " - Continue until we have 10 prime numbers.\n", - "\n", - "3. **Calculate the sum** of these numbers.\n", - "\n", - "Let's list the first 10 prime numbers step by step:\n", - "\n", - "1. The smallest prime number is **2**.\n", - "2. The next prime number after 2 is **3**, since it's only divisible by 1 and itself.\n", - "3. Then comes **5**, because it has no divisors other than 1 and itself.\n", - "4. Next is **7**, for the same reason as above.\n", - "5. **11** is also a prime number, as it cannot be divided evenly by any number other than 1 and itself.\n", - "6. Following this pattern, we identify **13** as a prime number.\n", - "7. Then, **17**.\n", - "8. Next in line is **19**.\n", - "9. After that, we have **23**.\n", - "10. The tenth prime number is **29**.\n", - "\n", - "So, the first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29.\n", - "\n", - "Now, let's **calculate their sum**:\n", - "\n", - "- Start with 0 (or any starting number for summation).\n", - "- Add each prime number to the total:\n", - " - 0 + 2 = 2\n", - " - 2 + 3 = 5\n", - " - 5 + 5 = 10\n", - " - 10 + 7 = 17\n", - " - 17 + 11 = 28\n", - " - 28 + 13 = 41\n", - " - 41 + 17 = 58\n", - " - 58 + 19 = 77\n", - " - 77 + 23 = 100\n", - " - 100 + 29 = 129\n", - "\n", - "Therefore, the sum of the first 10 prime numbers is **129**.\n" - ] - } - ], - "source": [ - "import asyncio\n", - "\n", - "# Create an AssistantAgent\n", - "assistant = AssistantAgent(\n", - " name=\"MathAssistant\",\n", - " model_client=model_client,\n", - " system_message=\"You are a helpful AI assistant that solves math problems. Provide clear explanations and show your work.\"\n", - ")\n", - "\n", - "print(\"✅ Agent created:\", assistant.name)\n", - "\n", - "# Define the task\n", - "task = \"What is the sum of the first 10 prime numbers? Please calculate it step by step.\"\n", - "\n", - "# Run the task (AutoGen v0.7.5 uses async)\n", - "async def run_simple_task():\n", - " # Create a simple team with just the assistant\n", - " team = RoundRobinGroupChat([assistant], max_turns=1)\n", - " result = await team.run(task=task)\n", - " return result\n", - "\n", - "# Execute in notebook\n", - "result = await run_simple_task()\n", - "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(\"Task Result:\")\n", - "print(result.messages[-1].content if result.messages else \"No response\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 2: Multi-Agent Team Collaboration\n", - "\n", - "### Pattern: Multiple Agents Working Together\n", - "\n", - "In v0.7.5, Autogen uses **RoundRobinGroupChat** to create teams where agents take turns contributing to a task.\n", - "\n", - "### Use Case: Write a Technical Blog Post" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Team agents created: Researcher, Writer, Critic\n", - "\n", - "==================================================\n", - "Final Blog Post:\n", - "==================================================\n", - "Turn 1\n", - "\n", - "[user]: Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", - "\n", - " Steps:\n", - " 1. Researcher: Gather key information about Llama Stack\n", - " 2. Writer: Create the blog post\n", - " ...\n", - "Turn 2\n", - "\n", - "[Researcher]: **Unlocking Efficient LLM Applications with Llama Stack**\n", - "\n", - "The Llama Stack is a cutting-edge framework designed to optimize Large Language Model (LLM) applications, offering numerous benefits for deve...\n", - "Turn 3\n", - "\n", - "[Writer]: **Unlocking Efficient LLM Applications with Llama Stack**\n", - "\n", - "The Llama Stack is a revolutionary framework that optimizes Large Language Model (LLM) applications, offering numerous benefits for developer...\n", - "Turn 4\n", - "\n", - "[Critic]: **Reviewed Blog Post:**\n", - "\n", - "The provided blog post effectively highlights the benefits of using the Llama Stack for Large Language Model (LLM) applications. However, there are a few areas that could be i...\n", - "Turn 5\n", - "\n", - "[Researcher]: Here's a 200-word blog post about the benefits of using Llama Stack for LLM applications:\n", - "\n", - "**Unlocking Efficient LLM Applications with Llama Stack**\n", - "\n", - "The Llama Stack is a revolutionary framework that ...\n", - "Turn 6\n", - "\n", - "[Writer]: **Unlocking Efficient LLM Applications with Llama Stack**\n", - "\n", - "The Llama Stack is a game-changer for Large Language Model (LLM) applications, offering numerous benefits for developers and users. By utiliz...\n", - "Turn 7\n", - "\n", - "[Critic]: **Critic's Review:**\n", - "\n", - "The provided blog post effectively communicates the benefits of using the Llama Stack for Large Language Model (LLM) applications. Here are some key observations and suggestions ...\n", - "Turn 8\n", - "\n", - "[Researcher]: Here's a rewritten 200-word blog post about the benefits of using Llama Stack for LLM applications:\n", - "\n", - "**Unlock Efficient LLM Applications with Llama Stack**\n", - "\n", - "In the rapidly evolving landscape of Large ...\n", - "Turn 9\n", - "\n", - "[Writer]: **Unlock Efficient LLM Applications with Llama Stack**\n", - "\n", - "The Llama Stack revolutionizes Large Language Model (LLM) applications by providing a game-changing framework that optimizes development and dep...\n", - "Turn 10\n", - "\n", - "[Critic]: **Editor's Review:**\n", - "\n", - "The rewritten blog post effectively communicates the benefits of using the Llama Stack for Large Language Model (LLM) applications. Here are some key observations and suggestions...\n", - "Turn 11\n", - "\n", - "[Researcher]: Here's a rewritten 200-word blog post about the benefits of using Llama Stack for LLM applications:\n", - "\n", - "**Unlock Efficient LLM Applications with Llama Stack**\n", - "\n", - "In the rapidly evolving landscape of Large ...\n", - "Turn 12\n", - "\n", - "[Writer]: **Unlock Efficient LLM Applications with Llama Stack**\n", - "\n", - "The rapidly evolving landscape of Large Language Models (LLMs) demands efficiency and scalability for success. The Llama Stack is a game-changin...\n", - "Turn 13\n", - "\n", - "[Critic]: **Editor's Review:**\n", - "\n", - "The rewritten blog post effectively communicates the benefits of using the Llama Stack for Large Language Model (LLM) applications. Here are some key observations and suggestions...\n" - ] - } - ], - "source": [ - "# Create specialist agents\n", - "researcher = AssistantAgent(\n", - " name=\"Researcher\",\n", - " model_client=model_client,\n", - " system_message=\"You are a researcher. Provide accurate information, facts, and statistics about topics.\"\n", - ")\n", - "\n", - "writer = AssistantAgent(\n", - " name=\"Writer\",\n", - " model_client=model_client,\n", - " system_message=\"You are a technical writer. Write clear, engaging content based on research provided.\"\n", - ")\n", - "\n", - "critic = AssistantAgent(\n", - " name=\"Critic\",\n", - " model_client=model_client,\n", - " system_message=\"You are an editor. Review content for clarity, accuracy, and engagement. Suggest improvements.\"\n", - ")\n", - "\n", - "print(\"✅ Team agents created: Researcher, Writer, Critic\")\n", - "\n", - "# Create a team with round-robin collaboration\n", - "async def run_blog_team():\n", - " team = RoundRobinGroupChat([researcher, writer, critic], max_turns=12)\n", - "\n", - " task = \"\"\"Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", - "\n", - " Steps:\n", - " 1. Researcher: Gather key information about Llama Stack\n", - " 2. Writer: Create the blog post\n", - " 3. Critic: Review and suggest improvements\n", - " \"\"\"\n", - "\n", - " result = await team.run(task=task)\n", - " return result\n", - "\n", - "# Run the team\n", - "result = await run_blog_team()\n", - "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(\"Final Blog Post:\")\n", - "print(\"=\"*50)\n", - "# Print the last message which should contain the final output\n", - "# for msg in result.messages[-3:]:\n", - "# print(f\"\\n[{msg.source}]: {msg.content[:200]}...\" if len(msg.content) > 200 else f\"\\n[{msg.source}]: {msg.content}\")\n", - "i=1\n", - "for msg in result.messages:\n", - " print (f\"Turn {i}\")\n", - " i+=1\n", - " print(f\"\\n[{msg.source}]: {msg.content[:200]}...\" if len(msg.content) > 200 else f\"\\n[{msg.source}]: {msg.content}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 3: Multi-Turn Task\n", - "\n", - "### Pattern: Extended Team Collaboration\n", - "\n", - "Use longer conversations for problem-solving where agents need multiple rounds of discussion.\n", - "\n", - "### Use Case: Technical Analysis" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Analyst agent created\n", - "\n", - "==================================================\n", - "Analysis Result:\n", - "==================================================\n", - "Turn 1\n", - "Analyze the trade-offs between using local LLMs (like Llama via Llama Stack)\n", - " versus cloud-based APIs (like OpenAI) for production applications.\n", - " Consider: cost, latency, privacy, scalability, and maintenance.\n", - "==================================================\n", - "Turn 2\n", - "The debate between using local Large Language Models (LLMs) like Llama via Llama Stack and cloud-based APIs like OpenAI for production applications revolves around several key trade-offs. Here's a detailed analysis of the pros and cons of each approach considering cost, latency, privacy, scalability, and maintenance.\n", - "\n", - "### Local LLMs (e.g., Llama via Llama Stack)\n", - "\n", - "**Pros:**\n", - "1. **Privacy:** Running models locally can offer enhanced data privacy since sensitive information doesn't need to be transmitted over the internet or stored on third-party servers.\n", - "2. **Latency:** Local deployment typically results in lower latency for inference, as it eliminates the need for network requests and responses to cloud services.\n", - "3. **Customizability:** Users have full control over the model's training data, allowing for fine-tuning that is more tailored to their specific use case or industry.\n", - "4. **Dependence:** Reduced dependence on external APIs means applications are less vulnerable to service outages or changes in API terms of service.\n", - "\n", - "**Cons:**\n", - "1. **Cost:** While the cost per inference might be lower once models are set up, the initial investment for hardware and potentially personnel with expertise in machine learning can be high.\n", - "2. **Scalability:** Scaling local deployments to meet growing demand requires purchasing more powerful or additional servers, which can become prohibitively expensive.\n", - "3. **Maintenance:** Continuous updates to the model for maintaining performance or adapting to new data distributions require significant technical expertise and resource commitment.\n", - "\n", - "### Cloud-Based APIs (e.g., OpenAI)\n", - "\n", - "**Pros:**\n", - "1. **Scalability:** Cloud services can easily scale up or down based on demand, without requiring large upfront investments in hardware.\n", - "2. **Maintenance:** The maintenance burden, including model updates and security patches, is handled by the cloud provider.\n", - "3. **Accessibility:** Lower barrier to entry due to a lack of need for significant initial investment in hardware or ML expertise; users can start with basic development resources.\n", - "4. **Cost-Effectiveness:** Pricing models often include a free tier and are usually billed per use (e.g., per API call), making it more predictable and manageable for businesses with fluctuating demand.\n", - "\n", - "**Cons:**\n", - "1. **Privacy:** Sending data to cloud services may pose significant privacy risks, especially for sensitive information.\n", - "2. **Latency:** Network latency can impact the speed of inferences compared to local deployments.\n", - "3. **Dependence on Third Parties:** Applications relying on external APIs are at risk if those services change their pricing model, terms of service, or experience outages.\n", - "4. **Cost at Scale:** While cost-effective for small projects, as usage scales up, costs can quickly add up and become significant.\n", - "\n", - "### Recommendations\n", - "\n", - "- **Use Local LLMs:**\n", - " - When data privacy is paramount (e.g., in healthcare, finance).\n", - " - For applications requiring ultra-low latency.\n", - " - In scenarios where customizability of the model for a specific task or domain is critical.\n", - "\n", - "- **Use Cloud-Based APIs:**\n", - " - For proofs-of-concept, prototypes, or early-stage startups with variable and potentially low initial demand.\n", - " - When scalability needs are high and unpredictable, requiring rapid adjustments.\n", - " - In cases where the expertise and resources to manage local ML deployments are lacking.\n", - "\n", - "### Hybrid Approach\n", - "\n", - "A potential middle ground involves a hybrid approach: using cloud services for initial development and testing (benefiting from ease of use and scalability), and then transitioning to local deployment once the application has grown and can justify the investment in hardware and expertise. This transition point depends on various factors, including cost considerations, privacy requirements, and specific latency needs.\n", - "\n", - "In conclusion, the choice between local LLMs like Llama via Llama Stack and cloud-based APIs such as OpenAI for production applications hinges on a careful evaluation of trade-offs related to cost, latency, privacy, scalability, and maintenance. Each approach has its place, depending on the specific requirements and constraints of an application or project.\n", - "==================================================\n", - "Turn 3\n", - "\n", - "==================================================\n", - "Turn 4\n", - "When planning your deployment strategy:\n", - "- **Evaluate Privacy Requirements:** If data privacy is a significant concern, favor local deployments.\n", - "- **Assess Scalability Needs:** For high variability in demand, cloud services might offer more flexibility.\n", - "- **Consider Cost Predictability:** Cloud APIs provide cost predictability for variable usage patterns but can become expensive at large scales. Local deployments have higher upfront costs but potentially lower long-term costs per inference.\n", - "\n", - "Ultimately, the best approach may involve a combination of both local and cloud solutions, tailored to meet the evolving needs of your application as it grows and matures.\n", - "==================================================\n", - "Turn 5\n", - "\n", - "==================================================\n", - "Turn 6\n", - "**Final Consideration:** Regardless of which path you choose, ensure you have a deep understanding of your data's privacy implications and the legal requirements surrounding its handling. Additionally, maintaining flexibility in your architecture can allow for transitions between deployment strategies as needed.\n", - "==================================================\n" - ] - } - ], - "source": [ - "# Create an analyst agent\n", - "analyst = AssistantAgent(\n", - " name=\"TechAnalyst\",\n", - " model_client=model_client,\n", - " system_message=\"\"\"You are a technical analyst. Analyze technical topics deeply:\n", - " 1. Break down complex concepts\n", - " 2. Identify pros and cons\n", - " 3. Provide recommendations\n", - " \"\"\"\n", - ")\n", - "\n", - "print(\"✅ Analyst agent created\")\n", - "\n", - "# Run extended analysis\n", - "async def run_analysis():\n", - " team = RoundRobinGroupChat([analyst], max_turns=5)\n", - "\n", - " task = \"\"\"Analyze the trade-offs between using local LLMs (like Llama via Llama Stack)\n", - " versus cloud-based APIs (like OpenAI) for production applications.\n", - " Consider: cost, latency, privacy, scalability, and maintenance.\"\"\"\n", - "\n", - " result = await team.run(task=task)\n", - " return result\n", - "\n", - "result = await run_analysis()\n", - "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(\"Analysis Result:\")\n", - "print(\"=\"*50)\n", - "i=1\n", - "for message in result.messages:\n", - " print (f\"Turn {i}\")\n", - " i+=1\n", - " print(message.content)\n", - " print(\"=\"*50)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 4: Advanced Termination Conditions\n", - "\n", - "### Pattern: Code Review Loop with Stopping Logic\n", - "\n", - "This example demonstrates termination using:\n", - "1. **Multiple agents** in a review loop\n", - "2. **Termination on approval** - Stops when reviewer says \"LGTM\"\n", - "3. **Fallback with max_turns** for safety\n", - "\n", - "### Use Case: Iterative Code Review Until Approved" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Code review team created\n", - "\n", - "==================================================\n", - "✅ Review completed in 5 message(s)\n", - "Stop reason: Text 'LGTM' mentioned\n", - "==================================================\n", - "\n", - "📝 Review Conversation Flow:\n", - "1. [user]: Implement a Python function to check if a string is a palindrome. The Developer should implement the function first. The Reviewer should then...\n", - "2. [Developer]: ### Initial Implementation ```python def is_palindrome(s: str) -> bool: \"\"\" Checks if a given string is a palindrome. Args: s (st...\n", - "3. [CodeReviewer]: ### Code Review Feedback #### Bugs and Edge Cases * The function does not handle non-string inputs. It should raise a `TypeError` when given a non-st...\n", - "4. [Developer]: ### Revised Implementation ```python def is_palindrome(s: str, ignore_case: bool = True, ignore_whitespace_and_punctuation: bool = True) -> bool: ...\n", - "5. [CodeReviewer]: ### Code Review Feedback The revised implementation has addressed all the concerns raised during the initial code review. Here's a summary of the key...\n", - "\n", - "==================================================\n", - "Final Code (last message):\n", - "==================================================\n", - "### Code Review Feedback\n", - "\n", - "The revised implementation has addressed all the concerns raised during the initial code review. Here's a summary of the key points:\n", - "\n", - "* **Type checking**: The function now correctly raises a `TypeError` if the input is not a string.\n", - "* **Optional parameters**: The addition of optional parameters for ignoring case and whitespace/punctuation provides flexibility in how palindromes are checked.\n", - "* **Preprocessing**: The preprocessing steps to ignore case and remove non-alphanumeric characters are implemented correctly and efficiently.\n", - "* **Efficient palindrome check**: The two-pointer approach used to compare characters from both ends of the string is efficient, with a time complexity of O(n).\n", - "* **Documentation and examples**: The docstring has been improved with clear explanations and examples, making it easier for users to understand how to use the function.\n", - "\n", - "#### Minor Suggestions\n", - "\n", - "1. **Input Validation**: Consider adding input validation for the optional parameters `ignore_case` and `ignore_whitespace_and_punctuation`. Currently, they are expected to be boolean values, but there is no explicit check for this.\n", - "2. **Type Hints for Optional Parameters**: While not required, adding type hints for the optional parameters can improve code readability and help catch potential errors.\n", - "\n", - "#### Revised Implementation with Minor Suggestions\n", - "\n", - "```python\n", - "def is_palindrome(s: str, ignore_case: bool = True, ignore_whitespace_and_punctuation: bool = True) -> bool:\n", - " \"\"\"\n", - " Checks if a given string is a palindrome.\n", - "\n", - " Args:\n", - " s (str): The input string to check.\n", - " ignore_case (bool): Whether to ignore case when checking for palindromes. Defaults to True.\n", - " ignore_whitespace_and_punctuation (bool): Whether to ignore whitespace and punctuation when checking for palindromes. Defaults to True.\n", - "\n", - " Returns:\n", - " bool: True if the string is a palindrome, False otherwise.\n", - "\n", - " Raises:\n", - " TypeError: If s is not a string or if ignore_case/ignore_whitespace_and_punctuation are not boolean values.\n", - "\n", - " Examples:\n", - " >>> is_palindrome(\"radar\")\n", - " True\n", - " >>> is_palindrome(\"hello\")\n", - " False\n", - " >>> is_palindrome(\"A man, a plan, a canal: Panama\", ignore_whitespace_and_punctuation=True)\n", - " True\n", - " \"\"\"\n", - " # Check input type\n", - " if not isinstance(s, str):\n", - " raise TypeError(\"Input must be a string\")\n", - " \n", - " # Validate optional parameters\n", - " if not isinstance(ignore_case, bool) or not isinstance(ignore_whitespace_and_punctuation, bool):\n", - " raise TypeError(\"Optional parameters must be boolean values\")\n", - "\n", - " # Preprocess the string based on options\n", - " if ignore_case:\n", - " s = s.casefold()\n", - " if ignore_whitespace_and_punctuation:\n", - " s = ''.join(c for c in s if c.isalnum())\n", - "\n", - " # Compare characters from both ends of the string, moving towards the center\n", - " left, right = 0, len(s) - 1\n", - " while left < right:\n", - " if s[left] != s[right]:\n", - " return False\n", - " left += 1\n", - " right -= 1\n", - " return True\n", - "\n", - "# Example usage:\n", - "if __name__ == \"__main__\":\n", - " print(is_palindrome(\"radar\")) # Expected output: True\n", - " print(is_palindrome(\"hello\")) # Expected output: False\n", - " print(is_palindrome(\"A man, a plan, a canal: Panama\", ignore_whitespace_and_punctuation=True)) # Expected output: True\n", - "```\n", - "\n", - "With these minor suggestions addressed, the code is robust and follows best practices for readability, maintainability, and error handling.\n", - "\n", - "LGTM!\n" - ] - } - ], - "source": [ - "from autogen_agentchat.conditions import TextMentionTermination\n", - "\n", - "# Create code review agents\n", - "code_reviewer = AssistantAgent(\n", - " name=\"CodeReviewer\",\n", - " model_client=model_client,\n", - " system_message=\"\"\"You are a senior code reviewer. Review code for:\n", - " - Bugs and edge cases\n", - " - Performance issues\n", - " - Security vulnerabilities\n", - " - Best practices\n", - "\n", - " If the code looks good, say 'LGTM' (Looks Good To Me).\n", - " If issues found, provide specific feedback for improvement.\"\"\"\n", - ")\n", - "\n", - "code_developer = AssistantAgent(\n", - " name=\"Developer\",\n", - " model_client=model_client,\n", - " system_message=\"\"\"You are a developer. When you receive code review feedback:\n", - " - Address ALL issues mentioned\n", - " - Explain your changes\n", - " - Present the improved code\n", - "\n", - " If no feedback is given, present your initial implementation.\"\"\"\n", - ")\n", - "\n", - "print(\"✅ Code review team created\")\n", - "\n", - "# Complex termination: Stops when reviewer approves OR max iterations reached\n", - "async def run_code_review_loop():\n", - " # Stop when reviewer says \"LGTM\"\n", - " approval_termination = TextMentionTermination(\"LGTM\")\n", - "\n", - " team = RoundRobinGroupChat(\n", - " [code_developer, code_reviewer],\n", - " max_turns=16, # Max 4 review cycles (developer + reviewer = 2 turns per cycle)\n", - " termination_condition=approval_termination\n", - " )\n", - "\n", - " task = \"\"\"Implement a Python function to check if a string is a palindrome.\n", - "\n", - " The Developer should implement the function first.\n", - " The Reviewer should then review it and provide feedback.\n", - " Continue iterating until the Reviewer approves the code.\n", - " \"\"\"\n", - "\n", - " result = await team.run(task=task)\n", - " return result\n", - "\n", - "result = await run_code_review_loop()\n", - "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(f\"✅ Review completed in {len(result.messages)} message(s)\")\n", - "print(f\"Stop reason: {result.stop_reason}\")\n", - "print(\"=\"*50)\n", - "\n", - "# Show the conversation flow\n", - "print(\"\\n📝 Review Conversation Flow:\")\n", - "for i, msg in enumerate(result.messages, 1):\n", - " preview = msg.content[:150].replace('\\n', ' ')\n", - " print(f\"{i}. [{msg.source}]: {preview}...\")\n", - "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(\"Final Code (last message):\")\n", - "print(\"=\"*50)\n", - "if result.messages:\n", - " print(result.messages[-1].content)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Example 5: Practical Team Use Case\n", - "\n", - "### Pattern: Research → Write → Review Pipeline\n", - "\n", - "A common pattern in content creation: research, draft, review, finalize.\n", - "\n", - "### Use Case: Documentation Generator" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "✅ Documentation team created\n", - "\n", - "==================================================\n", - "Generated Documentation:\n", - "==================================================\n", - "Turn 1\n", - "Create documentation for a hypothetical food recipe:\n", - "\n", - " Food: `Cheese Pizza`\n", - "\n", - " Include:\n", - " - Description\n", - " - Ingredients\n", - " - How to make it\n", - " - Steps\n", - " \n", - "Turn 2\n", - "**Cheese Pizza Recipe Documentation**\n", - "=====================================\n", - "\n", - "### Description\n", - "\n", - "A classic Cheese Pizza is a delicious and satisfying dish that consists of a crispy crust topped with a rich tomato sauce, melted mozzarella cheese, and various seasonings. This recipe provides a simple and easy-to-follow guide to making a mouth-watering Cheese Pizza at home.\n", - "\n", - "### Ingredients\n", - "\n", - "* **Crust:**\n", - "\t+ 2 cups of warm water\n", - "\t+ 1 tablespoon of sugar\n", - "\t+ 2 teaspoons of active dry yeast\n", - "\t+ 3 cups of all-purpose flour\n", - "\t+ 1 teaspoon of salt\n", - "\t+ 2 tablespoons of olive oil\n", - "* **Sauce:**\n", - "\t+ 2 cups of crushed tomatoes\n", - "\t+ 1/4 cup of olive oil\n", - "\t+ 4 cloves of garlic, minced\n", - "\t+ 1 teaspoon of dried oregano\n", - "\t+ Salt and pepper to taste\n", - "* **Toppings:**\n", - "\t+ 8 ounces of mozzarella cheese, shredded\n", - "\t+ Fresh basil leaves, chopped (optional)\n", - "\n", - "### How to Make It\n", - "\n", - "To make a Cheese Pizza, follow these steps:\n", - "\n", - "#### Steps\n", - "\n", - "1. **Activate the Yeast:**\n", - "\t* In a large bowl, combine the warm water, sugar, and yeast.\n", - "\t* Stir gently to dissolve the yeast, and let it sit for 5-10 minutes until frothy.\n", - "2. **Make the Crust:**\n", - "\t* Add the flour, salt, and olive oil to the bowl with the yeast mixture.\n", - "\t* Mix the dough until it comes together in a ball.\n", - "\t* Knead the dough on a floured surface for 5-10 minutes until smooth and elastic.\n", - "3. **Prepare the Sauce:**\n", - "\t* In a separate bowl, combine the crushed tomatoes, olive oil, garlic, oregano, salt, and pepper.\n", - "\t* Mix well to create a smooth sauce.\n", - "4. **Assemble the Pizza:**\n", - "\t* Preheat the oven to 425°F (220°C).\n", - "\t* Roll out the dough into a circle or rectangle shape, depending on your preference.\n", - "\t* Place the dough on a baking sheet or pizza stone.\n", - "\t* Spread the tomato sauce evenly over the dough, leaving a small border around the edges.\n", - "5. **Add the Cheese:**\n", - "\t* Sprinkle the shredded mozzarella cheese over the sauce.\n", - "6. **Bake the Pizza:**\n", - "\t* Bake the pizza in the preheated oven for 15-20 minutes until the crust is golden brown and the cheese is melted and bubbly.\n", - "7. **Garnish with Fresh Basil (Optional):**\n", - "\t* Remove the pizza from the oven and sprinkle chopped fresh basil leaves over the top, if desired.\n", - "\n", - "### Tips and Variations\n", - "\n", - "* For a crispy crust, bake the pizza for an additional 2-3 minutes.\n", - "* Add other toppings such as pepperoni, sausage, or mushrooms to create a unique flavor combination.\n", - "* Use different types of cheese, such as cheddar or parmesan, for a varied flavor profile.\n", - "\n", - "Enjoy your delicious homemade Cheese Pizza!\n", - "Turn 3\n", - "**Cheese Pizza Recipe Documentation**\n", - "=====================================\n", - "\n", - "### Description\n", - "\n", - "A classic Cheese Pizza is a delicious and satisfying dish that consists of a crispy crust topped with a rich tomato sauce, melted mozzarella cheese, and various seasonings. This recipe provides a simple and easy-to-follow guide to making a mouth-watering Cheese Pizza at home.\n", - "\n", - "### Ingredients\n", - "\n", - "* **Crust:**\n", - "\t+ 2 cups of warm water\n", - "\t+ 1 tablespoon of sugar\n", - "\t+ 2 teaspoons of active dry yeast\n", - "\t+ 3 cups of all-purpose flour\n", - "\t+ 1 teaspoon of salt\n", - "\t+ 2 tablespoons of olive oil\n", - "* **Sauce:**\n", - "\t+ 2 cups of crushed tomatoes\n", - "\t+ 1/4 cup of olive oil\n", - "\t+ 4 cloves of garlic, minced\n", - "\t+ 1 teaspoon of dried oregano\n", - "\t+ Salt and pepper to taste\n", - "* **Toppings:**\n", - "\t+ 8 ounces of mozzarella cheese, shredded\n", - "\t+ Fresh basil leaves, chopped (optional)\n", - "\n", - "### How to Make It\n", - "\n", - "To make a Cheese Pizza, follow these steps:\n", - "\n", - "#### Steps\n", - "\n", - "1. **Activate the Yeast:**\n", - "\t* In a large bowl, combine the warm water, sugar, and yeast.\n", - "\t* Stir gently to dissolve the yeast, and let it sit for 5-10 minutes until frothy.\n", - "2. **Make the Crust:**\n", - "\t* Add the flour, salt, and olive oil to the bowl with the yeast mixture.\n", - "\t* Mix the dough until it comes together in a ball.\n", - "\t* Knead the dough on a floured surface for 5-10 minutes until smooth and elastic.\n", - "3. **Prepare the Sauce:**\n", - "\t* In a separate bowl, combine the crushed tomatoes, olive oil, garlic, oregano, salt, and pepper.\n", - "\t* Mix well to create a smooth sauce.\n", - "4. **Assemble the Pizza:**\n", - "\t* Preheat the oven to 425°F (220°C).\n", - "\t* Roll out the dough into a circle or rectangle shape, depending on your preference.\n", - "\t* Place the dough on a baking sheet or pizza stone.\n", - "\t* Spread the tomato sauce evenly over the dough, leaving a small border around the edges.\n", - "5. **Add the Cheese:**\n", - "\t* Sprinkle the shredded mozzarella cheese over the sauce.\n", - "6. **Bake the Pizza:**\n", - "\t* Bake the pizza in the preheated oven for 15-20 minutes until the crust is golden brown and the cheese is melted and bubbly.\n", - "7. **Garnish with Fresh Basil (Optional):**\n", - "\t* Remove the pizza from the oven and sprinkle chopped fresh basil leaves over the top, if desired.\n", - "\n", - "### Tips and Variations\n", - "\n", - "* For a crispy crust, bake the pizza for an additional 2-3 minutes.\n", - "* Add other toppings such as pepperoni, sausage, or mushrooms to create a unique flavor combination.\n", - "* Use different types of cheese, such as cheddar or parmesan, for a varied flavor profile.\n", - "\n", - "Enjoy your delicious homemade Cheese Pizza!\n", - "Turn 4\n", - "It seems like you've copied the entire Cheese Pizza Recipe Documentation I provided earlier. If you'd like to make any changes or additions to the recipe, or if you have any questions about it, feel free to ask and I'll be happy to help! \n", - "\n", - "If you're looking for some suggestions on how to improve the documentation, here are a few ideas:\n", - "\n", - "1. **Add nutritional information**: Providing the nutritional content of the Cheese Pizza, such as calories, fat, carbohydrates, and protein, can be helpful for people who are tracking their diet.\n", - "2. **Include images or diagrams**: Adding images or diagrams of the different steps in the recipe can help to clarify the process and make it easier to follow.\n", - "3. **Provide variations for special diets**: Offering suggestions for how to modify the recipe to accommodate special dietary needs, such as gluten-free or vegan, can make the recipe more accessible to a wider range of people.\n", - "4. **Add a troubleshooting section**: Including a section that addresses common problems or issues that may arise during the cooking process, such as a crust that's too thick or cheese that's not melting properly, can help to ensure that the recipe turns out well.\n", - "\n", - "Let me know if you have any other questions or if there's anything else I can help with!\n", - "Turn 5\n", - "I apologize for copying the entire documentation earlier. You're right; it would be more helpful to provide suggestions or improvements to the existing recipe. Here are some potential additions and modifications:\n", - "\n", - "1. **Nutritional Information:**\n", - "\t* Calculating the nutritional content of the Cheese Pizza could involve breaking down the ingredients and their corresponding calorie, fat, carbohydrate, and protein contributions.\n", - "\t* For example:\n", - "\t\t+ Crust (2 cups flour, 1 teaspoon sugar, 1/4 cup olive oil): approximately 300-350 calories, 10-12g fat, 50-60g carbohydrates, 10-12g protein\n", - "\t\t+ Sauce (2 cups crushed tomatoes, 1/4 cup olive oil, 4 cloves garlic, 1 teaspoon dried oregano): approximately 100-150 calories, 10-12g fat, 20-25g carbohydrates, 5-7g protein\n", - "\t\t+ Cheese (8 ounces mozzarella): approximately 200-250 calories, 15-18g fat, 5-7g carbohydrates, 20-25g protein\n", - "\t* Total estimated nutritional content: approximately 600-750 calories, 35-42g fat, 75-92g carbohydrates, 35-44g protein (per serving)\n", - "2. **Images and Diagrams:**\n", - "\t* Adding images of the different steps in the recipe could help illustrate the process, such as:\n", - "\t\t+ A photo of the yeast mixture after it has sat for 5-10 minutes\n", - "\t\t+ An image of the dough being kneaded on a floured surface\n", - "\t\t+ A diagram showing how to roll out the dough into a circle or rectangle shape\n", - "3. **Variations for Special Diets:**\n", - "\t* Gluten-free crust option:\n", - "\t\t+ Replace all-purpose flour with gluten-free flour blend (containing rice flour, potato starch, and tapioca flour)\n", - "\t\t+ Add xanthan gum to help improve texture and structure\n", - "\t* Vegan cheese alternative:\n", - "\t\t+ Use vegan mozzarella cheese or soy-based cheese alternative\n", - "\t\t+ Consider adding nutritional yeast for a cheesy flavor\n", - "4. **Troubleshooting Section:**\n", - "\t* Common issues with the crust:\n", - "\t\t+ Too thick: try reducing the amount of flour or increasing the yeast fermentation time\n", - "\t\t+ Too thin: try increasing the amount of flour or adding more water\n", - "\t* Issues with the cheese melting:\n", - "\t\t+ Not melting properly: try broiling the pizza for an additional 1-2 minutes or using a higher-quality mozzarella cheese\n", - "\n", - "Please let me know if you'd like to discuss any of these suggestions further or if there's anything else I can help with!\n" - ] - } - ], - "source": [ - "# Create documentation team\n", - "doc_researcher = AssistantAgent(\n", - " name=\"DocResearcher\",\n", - " model_client=model_client,\n", - " system_message=\"You research technical topics and gather key information for documentation.\"\n", - ")\n", - "\n", - "doc_writer = AssistantAgent(\n", - " name=\"DocWriter\",\n", - " model_client=model_client,\n", - " system_message=\"You write clear, concise technical documentation with examples.\"\n", - ")\n", - "\n", - "print(\"✅ Documentation team created\")\n", - "\n", - "# Run documentation pipeline\n", - "async def create_documentation():\n", - " team = RoundRobinGroupChat([doc_researcher, doc_writer], max_turns=4)\n", - " task = \"\"\"Create documentation for a hypothetical food recipe:\n", - "\n", - " Food: `Cheese Pizza`\n", - "\n", - " Include:\n", - " - Description\n", - " - Ingredients\n", - " - How to make it\n", - " - Steps\n", - " \"\"\"\n", - "\n", - " result = await team.run(task=task)\n", - " return result\n", - "\n", - "result = await create_documentation()\n", - "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(\"Generated Documentation:\")\n", - "print(\"=\"*50)\n", - "i=1\n", - "for message in result.messages:\n", - " print(f\"Turn {i}\")\n", - " i+=1\n", - " print(message.content)\n", - "\n", - "# Turn 1: `DocResearcher` receives the task → researches the topic\n", - "# Turn 2: `DocWriter` sees the task + researcher's output → writes documentation\n", - "# Turn 3**: `DocResearcher` sees everything → can add more info\n", - "# Turn 4: `DocWriter` sees everything → refines documentation\n", - "# Stops at `max_turns=4`\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Next Steps\n", - "\n", - "1. **Install autogen-ext**: `pip install autogen-agentchat autogen-ext`\n", - "2. **Start Llama Stack**: Ensure it's running on `http://localhost:8321`\n", - "3. **Experiment**: Try different team compositions and task types\n", - "4. **Explore**: Check out SelectorGroupChat and other team types\n", - "\n", - "### Resources\n", - "\n", - "- **AutoGen v0.7.5 Docs**: https://microsoft.github.io/autogen/\n", - "- **Llama Stack Docs**: https://llama-stack.readthedocs.io/" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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": 4 -} diff --git a/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb b/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb new file mode 100644 index 000000000..9c70c8bd2 --- /dev/null +++ b/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb @@ -0,0 +1,918 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Microsoft Agent Framework + Llama Stack Integration\n", + "\n", + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/meta-llama/llama-stack/blob/main/docs/notebooks/autogen/microsoft_agent_framework_llama_stack_integration.ipynb)\n", + "\n", + "## Overview\n", + "\n", + "This notebook demonstrates how to use **Microsoft Agent Framework** (successor to AutoGen) with **Llama Stack** as the backend.\n", + "\n", + "> **Note:** This notebook uses Microsoft Agent Framework, which replaces AutoGen. For the migration guide, see: [Microsoft Agent Framework Migration Guide](https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-autogen/)\n", + "\n", + "### Use Cases Covered:\n", + "1. **Two-Agent Conversation** - Teams working together on tasks\n", + "2. **Code Generation & Execution** - Agents generating and running code\n", + "3. **Group Chat** - Multiple specialists collaborating \n", + "4. **Advanced Termination** - Stopping conditions\n", + "\n", + "---\n", + "\n", + "## Prerequisites\n", + "\n", + "```bash\n", + "# Install Microsoft Agent Framework\n", + "pip install agent-framework\n", + "\n", + "# Llama Stack should already be running\n", + "# Default: http://localhost:8321\n", + "```\n", + "\n", + "**Migration Note:** If you're migrating from AutoGen, the main changes are:\n", + "- Package: `autogen-*` → `agent-framework`\n", + "- Client: `OpenAIChatCompletionClient` → `OpenAIResponsesClient`\n", + "- Agent: `AssistantAgent` → `ChatAgent`\n", + "- Team: `RoundRobinGroupChat` → `SequentialBuilder`" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Microsoft Agent Framework imports successful\n", + "Using Microsoft Agent Framework (successor to AutoGen)\n", + "✅ Llama Stack is running at http://localhost:8321\n", + "Status: 200\n" + ] + } + ], + "source": [ + "# Imports for Microsoft Agent Framework\n", + "import os\n", + "import asyncio\n", + "from agent_framework import ChatAgent\n", + "from agent_framework.openai import OpenAIResponsesClient\n", + "\n", + "print(\"✅ Microsoft Agent Framework imports successful\")\n", + "print(\"Using Microsoft Agent Framework (successor to AutoGen)\")\n", + "\n", + "# Check Llama Stack connectivity\n", + "import httpx\n", + "\n", + "LLAMA_STACK_URL = \"http://localhost:8321\"\n", + "\n", + "try:\n", + " response = httpx.get(f\"{LLAMA_STACK_URL}/v1/models\")\n", + " print(f\"✅ Llama Stack is running at {LLAMA_STACK_URL}\")\n", + " print(f\"Status: {response.status_code}\")\n", + "except Exception as e:\n", + " print(f\"❌ Llama Stack not accessible: {e}\")\n", + " print(\"Make sure Llama Stack is running on port 8321\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Configuration: Microsoft Agent Framework with Llama Stack\n", + "\n", + "### How It Works\n", + "\n", + "Microsoft Agent Framework uses **OpenAIResponsesClient** to connect to OpenAI-compatible servers like Llama Stack.\n", + "\n", + "**Key Changes from AutoGen:**\n", + "- `OpenAIChatCompletionClient` → `OpenAIResponsesClient`\n", + "- Team-based architecture (similar to AutoGen v0.7.5)\n", + "- Async/await pattern for running tasks" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Model client configured for Llama Stack\n", + "Model: ollama/llama3.3:70b\n", + "Base URL: http://localhost:8321/v1\n", + "Client type: OpenAIResponsesClient\n" + ] + } + ], + "source": [ + "# Create OpenAI Responses Client for Llama Stack\n", + "# Uses the /responses API (specialized for reasoning models)\n", + "chat_client = OpenAIResponsesClient(\n", + " model_id=\"ollama/llama3.3:70b\", # Choose any other model of your choice\n", + " api_key=\"not-needed\",\n", + " base_url=\"http://localhost:8321/v1\" # Llama Stack OpenAI-compatible endpoint\n", + ")\n", + "\n", + "print(\"✅ Model client configured for Llama Stack\")\n", + "print(f\"Model: ollama/llama3.3:70b\")\n", + "print(f\"Base URL: http://localhost:8321/v1\")\n", + "print(f\"Client type: OpenAIResponsesClient\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 1: Simple Task with ChatAgent\n", + "\n", + "### Pattern: Single Agent Task\n", + "\n", + "Microsoft Agent Framework uses **ChatAgent** to create AI assistants powered by your model.\n", + "\n", + "**ChatAgent Features:**\n", + "- Multi-turn by default (keeps calling tools until complete)\n", + "- Stateless (use `AgentThread` for conversation history)\n", + "- Configured with `instructions` (replaces AutoGen's `system_message`)\n", + "- Can be created directly or via client factory method\n", + "\n", + "### Use Case: Solve a Math Problem" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Agent created: MathAssistant\n", + "\n", + "==================================================\n", + "Task Result:\n", + "To find the sum of the first 10 prime numbers, we need to follow these steps:\n", + "\n", + "**Step 1: List out the first few prime numbers**\n", + "Prime numbers are numbers greater than 1 that have no divisors other than 1 and themselves. Let's start listing them out:\n", + "2, 3, 5, 7, 11, ...\n", + "\n", + "**Step 2: Identify the first 10 prime numbers**\n", + "We need to find the next 4 prime numbers after 7 and 11.\n", + "13 is a prime number (only divisible by 1 and 13).\n", + "17 is a prime number (only divisible by 1 and 17).\n", + "19 is a prime number (only divisible by 1 and 19).\n", + "23 is a prime number (only divisible by 1 and 23).\n", + "\n", + "So, the first 10 prime numbers are:\n", + "2, 3, 5, 7, 11, 13, 17, 19, 23, 29\n", + "\n", + "**Step 3: Calculate the sum of these prime numbers**\n", + "Now, let's add them up:\n", + "2 + 3 = 5\n", + "5 + 5 = 10\n", + "10 + 7 = 17\n", + "17 + 11 = 28\n", + "28 + 13 = 41\n", + "41 + 17 = 58\n", + "58 + 19 = 77\n", + "77 + 23 = 100\n", + "100 + 29 = 129\n", + "\n", + "**Step 4: Write the final answer**\n", + "The sum of the first 10 prime numbers is:\n", + "129\n", + "\n", + "Therefore, the sum of the first 10 prime numbers is **129**.\n", + "==================================================\n" + ] + } + ], + "source": [ + "import asyncio\n", + "\n", + "# Create a ChatAgent (replaces AutoGen's AssistantAgent)\n", + "# Method 1: Direct creation\n", + "assistant = ChatAgent(\n", + " name=\"MathAssistant\",\n", + " chat_client=chat_client,\n", + " instructions=\"You are a helpful AI assistant that solves math problems. Provide clear explanations and show your work.\"\n", + ")\n", + "\n", + "# Method 2: Using client factory (more convenient)\n", + "# assistant = chat_client.create_agent(\n", + "# name=\"MathAssistant\",\n", + "# instructions=\"You are a helpful AI assistant.\"\n", + "# )\n", + "\n", + "print(\"✅ Agent created:\", assistant.name)\n", + "\n", + "# Define the task\n", + "task = \"What is the sum of the first 10 prime numbers? Please calculate it step by step.\"\n", + "\n", + "# Run the task (Agent Framework uses async)\n", + "# Note: ChatAgent is stateless - no conversation history between calls\n", + "result = await assistant.run(task)\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Task Result:\")\n", + "print(result.text if result.text else \"No response\")\n", + "print(\"=\"*50)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 2: Multi-Agent Team Collaboration\n", + "\n", + "### Pattern: Sequential Workflow (Round-Robin Style)\n", + "\n", + "Agent Framework uses **SequentialBuilder** to create workflows where agents take turns.\n", + "This replaces AutoGen's `RoundRobinGroupChat`.\n", + "\n", + "**Key Concepts:**\n", + "- `SequentialBuilder`: Agents process messages sequentially\n", + "- Shared conversation history across all agents\n", + "- Each agent sees all previous messages\n", + "\n", + "### Use Case: Write a Technical Blog Post" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Team agents created: Researcher, Writer, Critic\n", + "\n", + "==================================================\n", + "Running Sequential Workflow:\n", + "==================================================\n", + "\n", + "Turn 1 [user]:\n", + "Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", + "\n", + "Steps:\n", + "1. Researcher: Gather key information about Llama Stack\n", + "2. Writer: Create the blog post\n", + "3. Critic: Revi...\n", + "\n", + "Turn 2 [assistant]:\n", + "**Unlocking Efficient LLM Applications with Llama Stack**\n", + "\n", + "The rise of Large Language Models (LLMs) has transformed the artificial intelligence landscape, enabling cutting-edge natural language proces...\n", + "\n", + "Turn 3 [assistant]:\n", + "\n", + "\n", + "Turn 4 [assistant]:\n", + " \n", + "\n", + "---\n", + "\n", + "**Critic's Review:**\n", + "\n", + "The blog post effectively introduces the benefits of using Llama Stack for LLM applications, highlighting key advantages such as simplified model deployment and improved ...\n" + ] + } + ], + "source": [ + "from agent_framework import SequentialBuilder, WorkflowOutputEvent\n", + "\n", + "# Create specialist agents\n", + "researcher = ChatAgent(\n", + " name=\"Researcher\",\n", + " chat_client=chat_client,\n", + " instructions=\"You are a researcher. Provide accurate information, facts, and statistics about topics.\"\n", + ")\n", + "\n", + "writer = ChatAgent(\n", + " name=\"Writer\",\n", + " chat_client=chat_client,\n", + " instructions=\"You are a technical writer. Write clear, engaging content based on research provided.\"\n", + ")\n", + "\n", + "critic = ChatAgent(\n", + " name=\"Critic\",\n", + " chat_client=chat_client,\n", + " instructions=\"You are an editor. Review content for clarity, accuracy, and engagement. Suggest improvements.\"\n", + ")\n", + "\n", + "print(\"✅ Team agents created: Researcher, Writer, Critic\")\n", + "\n", + "# Create a sequential workflow (round-robin collaboration)\n", + "# Each agent processes the input and builds on previous agents' work\n", + "workflow = SequentialBuilder().participants([researcher, writer, critic]).build()\n", + "\n", + "task = \"\"\"Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", + "\n", + "Steps:\n", + "1. Researcher: Gather key information about Llama Stack\n", + "2. Writer: Create the blog post\n", + "3. Critic: Review and suggest improvements\n", + "\"\"\"\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Running Sequential Workflow:\")\n", + "print(\"=\"*50)\n", + "\n", + "# Run the workflow and collect results\n", + "turn = 1\n", + "async for event in workflow.run_stream(task):\n", + " if isinstance(event, WorkflowOutputEvent):\n", + " # Final output contains full conversation history\n", + " conversation_history = event.data\n", + " for msg in conversation_history:\n", + " print(f\"\\nTurn {turn} [{msg.role}]:\")\n", + " print(msg.text[:200] + \"...\" if len(msg.text or \"\") > 200 else msg.text)\n", + " turn += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 3: Multi-Turn Conversations with AgentThread\n", + "\n", + "### Pattern: Stateful Conversations\n", + "\n", + "Unlike AutoGen, `ChatAgent` is **stateless by default**. To maintain conversation history across multiple interactions, use **AgentThread**.\n", + "\n", + "**AgentThread Features:**\n", + "- Stores conversation history\n", + "- Allows context to carry across multiple `agent.run()` calls\n", + "- Can be backed by external storage (Redis, databases)\n", + "\n", + "### Use Case: Interactive Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Analyst agent created\n", + "\n", + "==================================================\n", + "Multi-Turn Conversation with Thread:\n", + "==================================================\n", + "\n", + "[Turn 1 - Initial Analysis]:\n", + "**Introduction**\n", + "\n", + "Large Language Models (LLMs) have revolutionized the field of natural language processing, enabling applications such as text classification, sentiment analysis, and language translation. Two popular approaches to deploying LLMs are using local models and cloud-based APIs. In this analysis, we will break down the trade-offs between these two approaches, highlighting their pros an...\n", + "\n", + "[Turn 2 - Follow-up on Cost]:\n", + "**Cost Implications: Local LLMs vs Cloud-based APIs**\n", + "\n", + "The cost implications of using local LLMs versus cloud-based APIs are significant and can vary greatly depending on the specific requirements and deployment scenarios. Here's a detailed breakdown of the costs associated with each approach:\n", + "\n", + "**Local LLMs**\n", + "\n", + "1. **Initial Investment**:\n", + "\t* Hardware: High-performance GPUs, high-capacity storage, an...\n", + "\n", + "[Turn 3 - Summary]:\n", + "Organizations should choose between local LLMs and cloud-based APIs based on their specific requirements, weighing factors such as security, customizability, scalability, and cost, with local LLMs suitable for high-traffic or sensitive applications and cloud-based APIs ideal for low-traffic or prototyping scenarios.\n", + "\n", + "==================================================\n", + "Thread maintained context across 3 turns\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Create an analyst agent\n", + "analyst = ChatAgent(\n", + " name=\"TechAnalyst\",\n", + " chat_client=chat_client,\n", + " instructions=\"\"\"You are a technical analyst. Analyze technical topics deeply:\n", + " 1. Break down complex concepts\n", + " 2. Identify pros and cons\n", + " 3. Provide recommendations\n", + " \"\"\"\n", + ")\n", + "\n", + "print(\"✅ Analyst agent created\")\n", + "\n", + "# Create a new thread to maintain conversation state\n", + "thread = analyst.get_new_thread()\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Multi-Turn Conversation with Thread:\")\n", + "print(\"=\"*50)\n", + "\n", + "# First interaction\n", + "result1 = await analyst.run(\n", + " \"Analyze the trade-offs between using local LLMs versus cloud-based APIs.\",\n", + " thread=thread\n", + ")\n", + "print(\"\\n[Turn 1 - Initial Analysis]:\")\n", + "print(result1.text[:400] + \"...\" if len(result1.text or \"\") > 400 else result1.text)\n", + "\n", + "# Second interaction - builds on previous context\n", + "result2 = await analyst.run(\n", + " \"What about cost implications specifically?\",\n", + " thread=thread\n", + ")\n", + "print(\"\\n[Turn 2 - Follow-up on Cost]:\")\n", + "print(result2.text[:400] + \"...\" if len(result2.text or \"\") > 400 else result2.text)\n", + "\n", + "# Third interaction - continues the conversation\n", + "result3 = await analyst.run(\n", + " \"Summarize your recommendation in one sentence.\",\n", + " thread=thread\n", + ")\n", + "print(\"\\n[Turn 3 - Summary]:\")\n", + "print(result3.text)\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(f\"Thread maintained context across {3} turns\")\n", + "print(\"=\"*50)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 4: Advanced Workflow with Custom Executors\n", + "\n", + "### Pattern: Data-Flow Workflow with Code Review Loop\n", + "\n", + "Agent Framework's **Workflow** enables complex orchestration using executors and edges.\n", + "Unlike AutoGen's event-driven model, workflows use **data-flow** architecture.\n", + "\n", + "**Key Concepts:**\n", + "- `Executor`: Processing units (agents, functions, or sub-workflows)\n", + "- `WorkflowBuilder`: Build typed data-flow graphs\n", + "- `@executor` decorator: Define custom processing logic\n", + "- Edges route messages between executors\n", + "\n", + "### Use Case: Iterative Code Review Until Approved" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Code review team created\n", + "\n", + "==================================================\n", + "Code Review Workflow:\n", + "==================================================\n", + "\n", + "[Iteration 1 - Final Result]:\n", + "✅ APPROVED\n", + "\n", + "Code:\n", + "**Email Validation Function in Python**\n", + "=====================================\n", + "\n", + "The following Python function validates an email address, ensuring it meets the specified requirements.\n", + "\n", + "### Implementation\n", + "```python\n", + "import re\n", + "\n", + "def validate_email(email: str) -> bool:\n", + " \"\"\"\n", + " Validates an email address.\n", + "\n", + " Args:\n", + " - email (str): The email address to be validated.\n", + "\n", + " Returns:\n", + " - bool: True if the email is valid, False otherwise.\n", + " \"\"\"\n", + "\n", + " # Define a regular expression pattern for email validation\n", + " pattern = r\"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$\"\n", + "\n", + " try:\n", + " # Check if the input is a string\n", + " if not isinstance(email, str):\n", + " raise TypeError(\"Input must be a string.\")\n", + "\n", + " # Remove leading and trailing whitespaces\n", + " email = email.strip()\n", + "\n", + " # Check for spaces in the email address\n", + " if \" \" in email:\n", + " print(\"Error: No spaces are allowed in the email address.\")\n", + " return False\n", + "\n", + " # Check if the email matches the pattern\n", + " if not re.match(pattern, email):\n", + " print(\"Error: Invalid email format. Please use a valid email address.\")\n", + " return False\n", + "\n", + " return True\n", + "\n", + " except TypeError as e:\n", + " print(f\"Error: {e}\")\n", + " return False\n", + "\n", + " except Exception as e:\n", + " print(f\"An unexpected error occurred: {e}\")\n", + " return False\n", + "\n", + "\n", + "# Example usage\n", + "if __name__ == \"__main__\":\n", + " emails = [\n", + " \"test@example.com\",\n", + " \"invalid_email\",\n", + " \"test@ example.com\",\n", + " \"test@example\",\n", + " 123, # Test with an invalid input type\n", + " ]\n", + "\n", + " for email in emails:\n", + " print(f\"Email: {email}\")\n", + " is_valid = validate_email(email)\n", + " print(f\"Is Valid: {is_valid}\")\n", + " print(\"-\" * 50)\n", + "\n", + "```\n", + "\n", + "### Explanation\n", + "\n", + "This function uses a regular expression pattern to match the general format of an email address. The `validate_email` function checks for the following:\n", + "\n", + "* The input is a string.\n", + "* There are no spaces in the email address.\n", + "* The email address matches the defined pattern, which includes:\n", + " * One or more alphanumeric characters, dots, underscores, pluses, or hyphens before the `@` symbol.\n", + " * The `@` symbol.\n", + " * One or more alphanumeric characters, hyphens, or dots after the `@` symbol and before the first dot in the domain.\n", + " * At least one dot in the domain.\n", + "\n", + "If any of these conditions are not met, the function prints an error message indicating what went wrong and returns `False`. If all checks pass, it returns `True`, indicating a valid email address.\n", + "\n", + "### Error Handling\n", + "\n", + "The code includes proper error handling:\n", + "\n", + "* **TypeError**: Raised if the input is not a string.\n", + "* **Exception**: Catches any unexpected errors and prints an error message.\n", + "\n", + "Each error case provides informative messages to help with debugging.\n", + "\n", + "Review:\n", + "**Code Review**\n", + "\n", + "Overall, the provided Python function for email validation looks clean and well-structured. It effectively checks if the input string matches the typical format of an email address using a regular expression pattern. However, there are some areas that can be improved upon:\n", + "\n", + "### Bugs and Edge Cases\n", + "1. **Input Validation**: In the current implementation, `TypeError` is raised when the input is not a string, but then immediately caught and handled within the same function. Consider letting it propagate up instead of catching it here since you're already returning an error message and `False`.\n", + "2. **Email Length Limitation**: The regular expression does not account for email length limits. As per [RFC 5321](https://tools.ietf.org/html/rfc5321#section-4.5.3), the maximum total length of a mailbox (local part plus domain) is 320 characters, but some mail servers may enforce shorter limits.\n", + "3. **Internationalized Domain Names (IDNs)**: The function does not support IDNs which are domain names that contain non-ASCII characters.\n", + "\n", + "### Performance Issues\n", + "1. **Regular Expression Compilation**: If this function is called frequently, compiling the regular expression pattern once outside of it and storing the result in a variable can improve performance.\n", + "2. **Exception Handling Overhead**: Python exceptions come with some overhead. Using if-statements to handle anticipated conditions (like type checking) instead of using exceptions for control flow might be more efficient.\n", + "\n", + "### Security Vulnerabilities\n", + "No significant security vulnerabilities were identified, but it's essential to note that validating an email address does not necessarily mean the provided email exists or can receive mail; a separate verification process (usually involving sending a confirmation link) should be implemented if you need to confirm the existence of the email account.\n", + "\n", + "### Best Practices\n", + "1. **Direct Printing**: Instead of directly printing error messages from within the function, consider raising exceptions with descriptive messages. This approach allows the caller to handle errors as needed.\n", + "2. **Variable Naming and Comments**: Although comments are provided in the docstring and around code blocks explaining what each segment does, variable names like `email` could be more descriptive (e.g., `input_email_address`). However, given the context, `email` is sufficient here.\n", + "3. **Example Usage**: The example usage section provides a simple demonstration of how to use the `validate_email` function with different inputs.\n", + "\n", + "### Code Improvements\n", + "\n", + "```python\n", + "import re\n", + "\n", + "EMAIL_PATTERN = re.compile(\n", + " r\"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$\",\n", + " flags=re.IGNORECASE,\n", + ")\n", + "\n", + "def validate_email_address(input_string: str) -> bool:\n", + " \"\"\"Validate an email address.\"\"\"\n", + " \n", + " # Input type check\n", + " if not isinstance(input_string, str):\n", + " raise TypeError(\"Input must be a string.\")\n", + "\n", + " input_string = input_string.strip()\n", + " \n", + " if \" \" in input_string:\n", + " raise ValueError(\"No spaces are allowed in the email address.\")\n", + " \n", + " if len(input_string) > 320: # Basic length validation as per RFC5321\n", + " raise ValueError(\"Email address exceeds maximum length limit.\")\n", + "\n", + " # Regular expression match for basic email format validity\n", + " return bool(EMAIL_PATTERN.match(input_string))\n", + "\n", + "# Example usage with error handling\n", + "if __name__ == \"__main__\":\n", + " emails = [\n", + " \"test@example.com\",\n", + " \"invalid_email\",\n", + " \"test@ example.com\",\n", + " \"test@example\",\n", + " 123, \n", + " ]\n", + "\n", + " for email in emails:\n", + " print(f\"Email: {email}\")\n", + " try:\n", + " is_valid = validate_email_address(email)\n", + " print(f\"Is Valid: {is_valid}\")\n", + " except (TypeError, ValueError) as e:\n", + " print(f\"Error: {e}\")\n", + " print(\"-\" * 50)\n", + "```\n", + "\n", + "In summary, while the original code provides a good basic structure for validating email addresses, a few adjustments can enhance its flexibility and robustness. These changes primarily focus on improving exception handling, avoiding unnecessary overhead, and adhering to best practices in Python coding standards.\n", + "\n", + "LGTM with the suggested modifications.\n" + ] + } + ], + "source": [ + "from agent_framework import WorkflowBuilder, executor, WorkflowContext, WorkflowOutputEvent\n", + "from typing_extensions import Never\n", + "\n", + "# Create code review agents\n", + "code_developer = ChatAgent(\n", + " name=\"Developer\",\n", + " chat_client=chat_client,\n", + " instructions=\"\"\"You are a developer. When you receive code review feedback:\n", + " - Address ALL issues mentioned\n", + " - Explain your changes\n", + " - Present the improved code\n", + "\n", + " If no feedback is given, present your initial implementation.\"\"\"\n", + ")\n", + "\n", + "code_reviewer = ChatAgent(\n", + " name=\"CodeReviewer\",\n", + " chat_client=chat_client,\n", + " instructions=\"\"\"You are a senior code reviewer. Review code for:\n", + " - Bugs and edge cases\n", + " - Performance issues\n", + " - Security vulnerabilities\n", + " - Best practices\n", + "\n", + " If the code looks good, say 'LGTM' (Looks Good To Me).\n", + " If issues found, provide specific feedback for improvement.\"\"\"\n", + ")\n", + "\n", + "print(\"✅ Code review team created\")\n", + "\n", + "# Define custom executors for workflow\n", + "@executor(id=\"developer\")\n", + "async def developer_executor(task: str, ctx: WorkflowContext[str]) -> None:\n", + " \"\"\"Developer creates or improves code based on input.\"\"\"\n", + " result = await code_developer.run(task)\n", + " await ctx.send_message(result.text)\n", + "\n", + "@executor(id=\"reviewer\")\n", + "async def reviewer_executor(code: str, ctx: WorkflowContext[str, str]) -> None:\n", + " \"\"\"Reviewer checks code and either approves or requests changes.\"\"\"\n", + " result = await code_reviewer.run(f\"Review this code:\\n{code}\")\n", + "\n", + " # Check if approved\n", + " if \"LGTM\" in result.text or \"looks good\" in result.text.lower():\n", + " await ctx.yield_output(f\"✅ APPROVED\\n\\nCode:\\n{code}\\n\\nReview:\\n{result.text}\")\n", + " else:\n", + " # Send feedback back to developer for revision\n", + " await ctx.send_message(f\"Feedback: {result.text}\\n\\nOriginal code:\\n{code}\", target_id=\"developer\")\n", + "\n", + "# Build workflow: developer → reviewer (with feedback loop)\n", + "workflow = (\n", + " WorkflowBuilder()\n", + " .add_edge(developer_executor, reviewer_executor)\n", + " .add_edge(reviewer_executor, developer_executor) # Feedback loop\n", + " .set_start_executor(developer_executor)\n", + " .build()\n", + ")\n", + "\n", + "# task = \"Implement a Python function to check if a string is a palindrome.\"\n", + "task = \"\"\"Implement a Python function to validate email addresses with these requirements:\n", + "- Must have @ symbol\n", + "- Must have domain with at least one dot\n", + "- No spaces allowed\n", + "- Handle edge cases\n", + "- Include error messages\n", + "Make it production-ready with proper error handling.\"\"\"\n", + "\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Code Review Workflow:\")\n", + "print(\"=\"*50)\n", + "\n", + "# Run workflow with streaming\n", + "iteration = 1\n", + "async for event in workflow.run_stream(task):\n", + " if isinstance(event, WorkflowOutputEvent):\n", + " print(f\"\\n[Iteration {iteration} - Final Result]:\")\n", + " print(event.data)\n", + " iteration += 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 5: Concurrent Workflow Pattern\n", + "\n", + "### Pattern: Parallel Processing\n", + "\n", + "Agent Framework's **ConcurrentBuilder** enables parallel agent execution.\n", + "All agents process the input simultaneously and results are aggregated.\n", + "\n", + "### Use Case: Multi-Perspective Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✅ Analyst team created: Technical, Business, Security\n", + "\n", + "==================================================\n", + "Concurrent Analysis (Parallel Processing):\n", + "==================================================\n", + "\n", + "[Analysis 1]:\n", + "Evaluate the proposal to deploy a customer service chatbot.\n", + "--------------------------------------------------\n", + "\n", + "[Analysis 2]:\n", + "**Proposal Evaluation: Deploying a Customer Service Chatbot**\n", + "\n", + "**Executive Summary:**\n", + "The proposal to deploy a customer service chatbot aims to enhance customer experience, reduce support queries, and optimize resource allocation. This evaluation assesses the technical feasibility and implementation complexity of the proposed solution.\n", + "\n", + "**Technical Feasibility:**\n", + "\n", + "1. **Natural Language Processing (NLP) Capabilities:** The chatbot's ability to understand and respond to customer inquiries accurately is crucial. Modern NLP libraries (e.g., NLTK, spaCy) and machine learning frameworks (e.g., TensorFlow, PyTorch) can support this requirement.\n", + "2. **Integration with Existing Systems:** Seamless integration with the CRM, helpdesk software, and other relevant systems is necessary. APIs and webhooks can facilitate data exchange and synchronization.\n", + "3. **Security and Compliance:** The chatbot must ensure customer data protection and adhere to regulations (e.g., GDPR, HIPAA). Implementing encrypti...\n", + "--------------------------------------------------\n", + "\n", + "[Analysis 3]:\n", + "**Evaluation of Customer Service Chatbot Proposal**\n", + "\n", + "**Introduction:**\n", + "The proposal to deploy a customer service chatbot aims to improve customer experience, reduce support costs, and increase efficiency in handling customer inquiries. This evaluation assesses the business value, ROI, and market impact of implementing a customer service chatbot.\n", + "\n", + "**Benefits:**\n", + "\n", + "1. **Improved Customer Experience:** A chatbot can provide 24/7 support, quick responses to common queries, and personalized experiences, leading to increased customer satisfaction.\n", + "2. **Cost Savings:** Automating routine inquiries can reduce the workload of human customer support agents, resulting in cost savings and allowing them to focus on complex issues.\n", + "3. **Increased Efficiency:** Chatbots can handle multiple conversations simultaneously, reducing wait times and improving response rates.\n", + "4. **Data Collection and Analysis:** Chatbots can collect valuable data on customer interactions, providing insights for business improv...\n", + "--------------------------------------------------\n", + "\n", + "[Analysis 4]:\n", + "**Evaluation of Customer Service Chatbot Proposal**\n", + "\n", + "**Introduction:**\n", + "The proposal to deploy a customer service chatbot aims to enhance customer experience, reduce support queries, and improve response times. This evaluation assesses the feasibility, security implications, risks, and compliance of implementing a chatbot solution.\n", + "\n", + "**Benefits:**\n", + "\n", + "1. **24/7 Support**: A chatbot can provide round-the-clock support, improving customer satisfaction and reducing the workload on human customer support agents.\n", + "2. **Faster Response Times**: Chatbots can respond to queries instantly, ensuring that customers receive timely assistance.\n", + "3. **Cost Savings**: Automating routine inquiries can lead to significant cost savings by reducing the need for human customer support agents.\n", + "4. **Personalization**: Chatbots can be programmed to offer personalized recommendations and solutions based on customer interactions.\n", + "\n", + "**Security Implications:**\n", + "\n", + "1. **Data Security**: The chatbot will handle sensitive cust...\n", + "--------------------------------------------------\n", + "\n", + "==================================================\n", + "All agents completed in parallel\n", + "==================================================\n" + ] + } + ], + "source": [ + "from agent_framework import ConcurrentBuilder, WorkflowOutputEvent\n", + "\n", + "# Create specialized analysts\n", + "technical_analyst = ChatAgent(\n", + " name=\"TechnicalAnalyst\",\n", + " chat_client=chat_client,\n", + " instructions=\"You analyze technical feasibility and implementation complexity.\"\n", + ")\n", + "\n", + "business_analyst = ChatAgent(\n", + " name=\"BusinessAnalyst\",\n", + " chat_client=chat_client,\n", + " instructions=\"You analyze business value, ROI, and market impact.\"\n", + ")\n", + "\n", + "security_analyst = ChatAgent(\n", + " name=\"SecurityAnalyst\",\n", + " chat_client=chat_client,\n", + " instructions=\"You analyze security implications, risks, and compliance.\"\n", + ")\n", + "\n", + "print(\"✅ Analyst team created: Technical, Business, Security\")\n", + "\n", + "# Create concurrent workflow - all agents process in parallel\n", + "workflow = (\n", + " ConcurrentBuilder()\n", + " .participants([technical_analyst, business_analyst, security_analyst])\n", + " .build()\n", + ")\n", + "\n", + "# task = \"Evaluate the proposal to deploy Llama Stack for our customer service chatbot.\"\n", + "task = \"Evaluate the proposal to deploy a customer service chatbot.\"\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"Concurrent Analysis (Parallel Processing):\")\n", + "print(\"=\"*50)\n", + "\n", + "# Run workflow - agents work in parallel\n", + "async for event in workflow.run_stream(task):\n", + " if isinstance(event, WorkflowOutputEvent):\n", + " # Combined results from all agents\n", + " results = event.data\n", + " for i, result in enumerate(results, 1):\n", + " print(f\"\\n[Analysis {i}]:\")\n", + " print(result.text[:1000] + \"...\" if len(result.text or \"\") > 1000 else result.text)\n", + " print(\"-\" * 50)\n", + "\n", + "print(\"\\n\" + \"=\"*50)\n", + "print(\"All agents completed in parallel\")\n", + "print(\"=\"*50)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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": 4 +} From e64f78be6e45b341b66fbbf81881e1a176e47c72 Mon Sep 17 00:00:00 2001 From: Omar Abdelwahab Date: Fri, 28 Nov 2025 10:17:21 -0800 Subject: [PATCH 6/7] migration hints --- .../microsoft_agent_framework_llama_stack_integration.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb b/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb index 9c70c8bd2..00013090e 100644 --- a/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb +++ b/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb @@ -34,7 +34,8 @@ "\n", "**Migration Note:** If you're migrating from AutoGen, the main changes are:\n", "- Package: `autogen-*` → `agent-framework`\n", - "- Client: `OpenAIChatCompletionClient` → `OpenAIResponsesClient`\n", + "- Client: `OpenAIChatCompletionClient` → `OpenAIResponsesClient` or `OpenAIChatClient`\n", + "- Client: `AzureOpenAIChatCompletionClient` → `AzureOpenAIResponsesClient` or `AzureOpenAIChatClient`\n", "- Agent: `AssistantAgent` → `ChatAgent`\n", "- Team: `RoundRobinGroupChat` → `SequentialBuilder`" ] From 8f7244e980a807bb43c42daeac3013f3bb44b36f Mon Sep 17 00:00:00 2001 From: Omar Abdelwahab Date: Fri, 28 Nov 2025 12:40:06 -0800 Subject: [PATCH 7/7] Updated some examples --- ...nt_framework_llama_stack_integration.ipynb | 687 ++++++++++-------- 1 file changed, 396 insertions(+), 291 deletions(-) diff --git a/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb b/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb index 00013090e..6bd5f4507 100644 --- a/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb +++ b/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb @@ -6,7 +6,7 @@ "source": [ "# Microsoft Agent Framework + Llama Stack Integration\n", "\n", - "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/meta-llama/llama-stack/blob/main/docs/notebooks/autogen/microsoft_agent_framework_llama_stack_integration.ipynb)\n", + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/meta-llama/llama-stack/blob/main/docs/notebooks/microsoft_agent_framework/microsoft_agent_framework_llama_stack_integration.ipynb)\n", "\n", "## Overview\n", "\n", @@ -15,10 +15,11 @@ "> **Note:** This notebook uses Microsoft Agent Framework, which replaces AutoGen. For the migration guide, see: [Microsoft Agent Framework Migration Guide](https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-autogen/)\n", "\n", "### Use Cases Covered:\n", - "1. **Two-Agent Conversation** - Teams working together on tasks\n", - "2. **Code Generation & Execution** - Agents generating and running code\n", - "3. **Group Chat** - Multiple specialists collaborating \n", - "4. **Advanced Termination** - Stopping conditions\n", + "1. **Simple ChatAgent** - Single agent task execution\n", + "2. **Sequential Workflow** - Round-robin multi-agent collaboration\n", + "3. **AgentThread** - Stateful multi-turn conversations\n", + "4. **Custom Workflow** - Data-flow with executors and feedback loops\n", + "5. **Concurrent Workflow** - Parallel agent processing\n", "\n", "---\n", "\n", @@ -42,7 +43,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 1, "metadata": { "scrolled": true }, @@ -100,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -150,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 3, "metadata": { "scrolled": true }, @@ -165,22 +166,16 @@ "Task Result:\n", "To find the sum of the first 10 prime numbers, we need to follow these steps:\n", "\n", - "**Step 1: List out the first few prime numbers**\n", - "Prime numbers are numbers greater than 1 that have no divisors other than 1 and themselves. Let's start listing them out:\n", - "2, 3, 5, 7, 11, ...\n", + "**Step 1: Identify the first 10 prime numbers**\n", "\n", - "**Step 2: Identify the first 10 prime numbers**\n", - "We need to find the next 4 prime numbers after 7 and 11.\n", - "13 is a prime number (only divisible by 1 and 13).\n", - "17 is a prime number (only divisible by 1 and 17).\n", - "19 is a prime number (only divisible by 1 and 19).\n", - "23 is a prime number (only divisible by 1 and 23).\n", - "\n", - "So, the first 10 prime numbers are:\n", + "A prime number is a positive integer that is divisible only by itself and 1. We will list out the first few prime numbers until we have 10:\n", "2, 3, 5, 7, 11, 13, 17, 19, 23, 29\n", "\n", - "**Step 3: Calculate the sum of these prime numbers**\n", - "Now, let's add them up:\n", + "These are the first 10 prime numbers.\n", + "\n", + "**Step 2: Add up the prime numbers**\n", + "\n", + "Now, we simply need to add these numbers together:\n", "2 + 3 = 5\n", "5 + 5 = 10\n", "10 + 7 = 17\n", @@ -191,11 +186,11 @@ "77 + 23 = 100\n", "100 + 29 = 129\n", "\n", - "**Step 4: Write the final answer**\n", - "The sum of the first 10 prime numbers is:\n", - "129\n", - "\n", "Therefore, the sum of the first 10 prime numbers is **129**.\n", + "\n", + "So, to summarize:\n", + "The first 10 prime numbers are: 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29.\n", + "Their sum is: 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 + 29 = **129**.\n", "==================================================\n" ] } @@ -203,7 +198,6 @@ "source": [ "import asyncio\n", "\n", - "# Create a ChatAgent (replaces AutoGen's AssistantAgent)\n", "# Method 1: Direct creation\n", "assistant = ChatAgent(\n", " name=\"MathAssistant\",\n", @@ -211,12 +205,6 @@ " instructions=\"You are a helpful AI assistant that solves math problems. Provide clear explanations and show your work.\"\n", ")\n", "\n", - "# Method 2: Using client factory (more convenient)\n", - "# assistant = chat_client.create_agent(\n", - "# name=\"MathAssistant\",\n", - "# instructions=\"You are a helpful AI assistant.\"\n", - "# )\n", - "\n", "print(\"✅ Agent created:\", assistant.name)\n", "\n", "# Define the task\n", @@ -241,7 +229,6 @@ "### Pattern: Sequential Workflow (Round-Robin Style)\n", "\n", "Agent Framework uses **SequentialBuilder** to create workflows where agents take turns.\n", - "This replaces AutoGen's `RoundRobinGroupChat`.\n", "\n", "**Key Concepts:**\n", "- `SequentialBuilder`: Agents process messages sequentially\n", @@ -253,7 +240,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 4, "metadata": { "scrolled": true }, @@ -271,80 +258,157 @@ "Turn 1 [user]:\n", "Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", "\n", - "Steps:\n", - "1. Researcher: Gather key information about Llama Stack\n", - "2. Writer: Create the blog post\n", - "3. Critic: Revi...\n", - "\n", - "Turn 2 [assistant]:\n", - "**Unlocking Efficient LLM Applications with Llama Stack**\n", - "\n", - "The rise of Large Language Models (LLMs) has transformed the artificial intelligence landscape, enabling cutting-edge natural language proces...\n", - "\n", - "Turn 3 [assistant]:\n", + "Topic: Benefits of Llama Stack for LLM applications\n", + "Target length: 200 words\n", + "Audience: Developers and technical decision-makers\n", "\n", "\n", - "Turn 4 [assistant]:\n", + "Turn 2 [assistant - Researcher]:\n", + "* Llama Stack is an open-source framework for building LLM applications\n", + "* Improves model performance with optimized algorithms and hyperparameters\n", + "* Supports multiple frameworks, including PyTorch and TensorFlow\n", + "* Reduces development time by up to 30% with pre-built components\n", + "* Enhances scalability with distributed training capabilities\n", + "* Provides seamless integration with popular libraries and tools\n", + "\n", + "Research complete. Passing to Writer.\n", + "\n", + "Turn 3 [assistant - Writer]:\n", " \n", "\n", - "---\n", + "### Introduction to Llama Stack \n", + "The Llama Stack is designed to simplify the development of LLM applications, providing numerous benefits for developers and technical decision-makers.\n", "\n", - "**Critic's Review:**\n", + "### Benefits of Using Llama Stack\n", + "Using Llama Stack offers several advantages, including improved model performance, reduced development time, and enhanced scalability. With its optimized algorithms and hyperparameters, Llama Stack enables developers to build high-performing LLM models. The framework's pre-built components and support for multiple frameworks reduce development time, allowing developers to focus on other aspects of their project.\n", "\n", - "The blog post effectively introduces the benefits of using Llama Stack for LLM applications, highlighting key advantages such as simplified model deployment and improved ...\n" + "By leveraging Llama Stack, developers can streamline their workflow, improve model accuracy, and deploy LLM applications more efficiently. Whether building chatbots, language translators, or text generators, Llama Stack provides a robust foundation for developing innovative LLM applications.\n", + "Draft complete. Passing to Critic.\n", + "\n", + "Turn 4 [assistant - Critic]:\n", + " \n", + "\n", + "**Review:**\n", + "1. The blog post jumps abruptly from introducing Llama Stack to listing its benefits without providing a clear connection between the two sections. Consider adding a transitional sentence or phrase to guide the reader more smoothly through the text.\n", + "2. While the benefits of using Llama Stack are mentioned, such as improved model performance and reduced development time, specific examples or case studies that illustrate these benefits would make the content more engaging and concrete for the audience.\n", + "3. The tone of the blog post is quite formal, which may suit technical decision-makers but could be more approachable for a broader developer audience. Incorporating more conversational language or anecdotes about the challenges of LLM development and how Llama Stack addresses them might enhance readability and appeal.\n" ] } ], "source": [ "from agent_framework import SequentialBuilder, WorkflowOutputEvent\n", "\n", - "# Create specialist agents\n", + "# Create specialist agents with very strict role separation\n", "researcher = ChatAgent(\n", " name=\"Researcher\",\n", " chat_client=chat_client,\n", - " instructions=\"You are a researcher. Provide accurate information, facts, and statistics about topics.\"\n", + " instructions=\"\"\"You are a researcher. Your ONLY job is to gather facts, statistics, and key information.\n", + " \n", + " DO:\n", + " - Provide bullet points of facts and key information\n", + " - Include relevant statistics if available\n", + " - Keep it concise (50-100 words max)\n", + " \n", + " DO NOT:\n", + " - Write full paragraphs or blog posts\n", + " - Act as a writer or editor\n", + " - Provide any writing beyond factual bullet points\n", + " \n", + " End your response by saying: \"Research complete. Passing to Writer.\"\n", + " \"\"\"\n", ")\n", "\n", "writer = ChatAgent(\n", " name=\"Writer\",\n", " chat_client=chat_client,\n", - " instructions=\"You are a technical writer. Write clear, engaging content based on research provided.\"\n", + " instructions=\"\"\"You are a technical writer. Your ONLY job is to take research and write a blog post.\n", + " \n", + " DO:\n", + " - Use the research provided by the Researcher\n", + " - Write a clear, engaging 200-word blog post\n", + " - Use proper formatting (headers, paragraphs)\n", + " - Focus on benefits and value\n", + " \n", + " DO NOT:\n", + " - Do research yourself\n", + " - Review or critique your own work\n", + " - Act as an editor or critic\n", + " \n", + " End your response by saying: \"Draft complete. Passing to Critic.\"\n", + " \"\"\"\n", ")\n", "\n", "critic = ChatAgent(\n", " name=\"Critic\",\n", " chat_client=chat_client,\n", - " instructions=\"You are an editor. Review content for clarity, accuracy, and engagement. Suggest improvements.\"\n", + " instructions=\"\"\"You are an editor and critic. Your ONLY job is to review the blog post written by the Writer.\n", + " \n", + " DO:\n", + " - Review the blog post for clarity, accuracy, and engagement\n", + " - Provide 3-5 specific, constructive suggestions for improvement\n", + " - Comment on structure, tone, and effectiveness\n", + " - Be constructive but honest\n", + " \n", + " DO NOT:\n", + " - Rewrite the blog post yourself\n", + " - Do research or writing\n", + " - Say \"looks good\" without providing specific feedback\n", + " \n", + " Provide your review in this format:\n", + " **Review:**\n", + " 1. [Suggestion 1]\n", + " 2. [Suggestion 2]\n", + " 3. [Suggestion 3]\n", + " \"\"\"\n", ")\n", "\n", "print(\"✅ Team agents created: Researcher, Writer, Critic\")\n", "\n", "# Create a sequential workflow (round-robin collaboration)\n", - "# Each agent processes the input and builds on previous agents' work\n", "workflow = SequentialBuilder().participants([researcher, writer, critic]).build()\n", "\n", + "# Simpler task that doesn't list all the steps (to avoid confusion)\n", "task = \"\"\"Write a 200-word blog post about the benefits of using Llama Stack for LLM applications.\n", "\n", - "Steps:\n", - "1. Researcher: Gather key information about Llama Stack\n", - "2. Writer: Create the blog post\n", - "3. Critic: Review and suggest improvements\n", + "Topic: Benefits of Llama Stack for LLM applications\n", + "Target length: 200 words\n", + "Audience: Developers and technical decision-makers\n", "\"\"\"\n", "\n", "print(\"\\n\" + \"=\"*50)\n", "print(\"Running Sequential Workflow:\")\n", "print(\"=\"*50)\n", "\n", - "# Run the workflow and collect results\n", - "turn = 1\n", + "# Run the workflow and display results with agent names\n", "async for event in workflow.run_stream(task):\n", " if isinstance(event, WorkflowOutputEvent):\n", - " # Final output contains full conversation history\n", " conversation_history = event.data\n", + " \n", + " # Map assistant messages to agent names using position\n", + " agent_names = [\"Researcher\", \"Writer\", \"Critic\"]\n", + " turn = 1\n", + " assistant_count = 0\n", + " \n", " for msg in conversation_history:\n", - " print(f\"\\nTurn {turn} [{msg.role}]:\")\n", - " print(msg.text[:200] + \"...\" if len(msg.text or \"\") > 200 else msg.text)\n", - " turn += 1" + " # Normalize role to string for comparison (msg.role is a Role enum)\n", + " role_str = str(msg.role).lower().strip()\n", + " \n", + " # Determine the speaker label\n", + " if role_str == \"user\":\n", + " speaker = \"user\"\n", + " elif role_str == \"assistant\":\n", + " if assistant_count < len(agent_names):\n", + " speaker = f\"assistant - {agent_names[assistant_count]}\"\n", + " else:\n", + " speaker = \"assistant\"\n", + " assistant_count += 1\n", + " else:\n", + " speaker = str(msg.role)\n", + " \n", + " # Display the message\n", + " print(f\"\\nTurn {turn} [{speaker}]:\")\n", + " print(msg.text[:1000] + \"...\" if len(msg.text or \"\") > 1000 else msg.text)\n", + " turn += 1\n" ] }, { @@ -360,17 +424,14 @@ "**AgentThread Features:**\n", "- Stores conversation history\n", "- Allows context to carry across multiple `agent.run()` calls\n", - "- Can be backed by external storage (Redis, databases)\n", "\n", "### Use Case: Interactive Analysis" ] }, { "cell_type": "code", - "execution_count": 15, - "metadata": { - "scrolled": true - }, + "execution_count": 5, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -383,22 +444,19 @@ "==================================================\n", "\n", "[Turn 1 - Initial Analysis]:\n", - "**Introduction**\n", + "**Introduction to Local LLMs vs Cloud-Based APIs**\n", "\n", - "Large Language Models (LLMs) have revolutionized the field of natural language processing, enabling applications such as text classification, sentiment analysis, and language translation. Two popular approaches to deploying LLMs are using local models and cloud-based APIs. In this analysis, we will break down the trade-offs between these two approaches, highlighting their pros an...\n", + "The rise of Large Language Models (LLMs) has revolutionized natural language processing, offering unparalleled capabilities in text generation, comprehension, and analysis. Users can access these powerful models via two primary avenues: local deployment or cloud-based Application Programming Interfaces (APIs). Each approach presents distinct adva...\n", "\n", "[Turn 2 - Follow-up on Cost]:\n", - "**Cost Implications: Local LLMs vs Cloud-based APIs**\n", + "**Cost Implications: Local LLMs vs Cloud-Based APIs**\n", "\n", - "The cost implications of using local LLMs versus cloud-based APIs are significant and can vary greatly depending on the specific requirements and deployment scenarios. Here's a detailed breakdown of the costs associated with each approach:\n", + "When evaluating the cost implications of local LLMs versus cloud-based APIs, several factors come into play. These include initial investment, ongoing expenses, scalability costs, and potential savings. Each approach has distinct cost characteristics that can significantly impact an organization's budget and ROI (Return on Investment).\n", "\n", - "**Local LLMs**\n", - "\n", - "1. **Initial Investment**:\n", - "\t* Hardware: High-performance GPUs, high-capacity storage, an...\n", + "### **...\n", "\n", "[Turn 3 - Summary]:\n", - "Organizations should choose between local LLMs and cloud-based APIs based on their specific requirements, weighing factors such as security, customizability, scalability, and cost, with local LLMs suitable for high-traffic or sensitive applications and cloud-based APIs ideal for low-traffic or prototyping scenarios.\n", + "I recommend choosing between local LLM deployment and cloud-based APIs based on a careful consideration of factors such as data sensitivity, scalability needs, budget constraints, and the importance of customization and control, with local deployment suitable for high-security applications and cloud-based APIs ideal for scalable, cost-efficient solutions with lower security demands.\n", "\n", "==================================================\n", "Thread maintained context across 3 turns\n", @@ -478,7 +536,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 6, "metadata": { "scrolled": true }, @@ -487,182 +545,196 @@ "name": "stdout", "output_type": "stream", "text": [ - "✅ Code review team created\n", + "✅ Code review team created with strict instructions\n", "\n", - "==================================================\n", - "Code Review Workflow:\n", - "==================================================\n", + "============================================================\n", + "Code Review Workflow (with iteration tracking):\n", + "============================================================\n", "\n", - "[Iteration 1 - Final Result]:\n", - "✅ APPROVED\n", - "\n", - "Code:\n", - "**Email Validation Function in Python**\n", - "=====================================\n", - "\n", - "The following Python function validates an email address, ensuring it meets the specified requirements.\n", - "\n", - "### Implementation\n", - "```python\n", + " [Developer - Iteration 1]\n", + " Code submitted for review (preview): ```python\n", "import re\n", "\n", "def validate_email(email: str) -> bool:\n", " \"\"\"\n", - " Validates an email address.\n", + " Validat...\n", "\n", - " Args:\n", - " - email (str): The email address to be validated.\n", + " [Reviewer - Iteration 1]\n", + " Decision: ❌ NEEDS REVISION\n", + " Sending feedback to developer...\n", "\n", - " Returns:\n", - " - bool: True if the email is valid, False otherwise.\n", - " \"\"\"\n", - "\n", - " # Define a regular expression pattern for email validation\n", - " pattern = r\"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$\"\n", - "\n", - " try:\n", - " # Check if the input is a string\n", - " if not isinstance(email, str):\n", - " raise TypeError(\"Input must be a string.\")\n", - "\n", - " # Remove leading and trailing whitespaces\n", - " email = email.strip()\n", - "\n", - " # Check for spaces in the email address\n", - " if \" \" in email:\n", - " print(\"Error: No spaces are allowed in the email address.\")\n", - " return False\n", - "\n", - " # Check if the email matches the pattern\n", - " if not re.match(pattern, email):\n", - " print(\"Error: Invalid email format. Please use a valid email address.\")\n", - " return False\n", - "\n", - " return True\n", - "\n", - " except TypeError as e:\n", - " print(f\"Error: {e}\")\n", - " return False\n", - "\n", - " except Exception as e:\n", - " print(f\"An unexpected error occurred: {e}\")\n", - " return False\n", - "\n", - "\n", - "# Example usage\n", - "if __name__ == \"__main__\":\n", - " emails = [\n", - " \"test@example.com\",\n", - " \"invalid_email\",\n", - " \"test@ example.com\",\n", - " \"test@example\",\n", - " 123, # Test with an invalid input type\n", - " ]\n", - "\n", - " for email in emails:\n", - " print(f\"Email: {email}\")\n", - " is_valid = validate_email(email)\n", - " print(f\"Is Valid: {is_valid}\")\n", - " print(\"-\" * 50)\n", - "\n", - "```\n", - "\n", - "### Explanation\n", - "\n", - "This function uses a regular expression pattern to match the general format of an email address. The `validate_email` function checks for the following:\n", - "\n", - "* The input is a string.\n", - "* There are no spaces in the email address.\n", - "* The email address matches the defined pattern, which includes:\n", - " * One or more alphanumeric characters, dots, underscores, pluses, or hyphens before the `@` symbol.\n", - " * The `@` symbol.\n", - " * One or more alphanumeric characters, hyphens, or dots after the `@` symbol and before the first dot in the domain.\n", - " * At least one dot in the domain.\n", - "\n", - "If any of these conditions are not met, the function prints an error message indicating what went wrong and returns `False`. If all checks pass, it returns `True`, indicating a valid email address.\n", - "\n", - "### Error Handling\n", - "\n", - "The code includes proper error handling:\n", - "\n", - "* **TypeError**: Raised if the input is not a string.\n", - "* **Exception**: Catches any unexpected errors and prints an error message.\n", - "\n", - "Each error case provides informative messages to help with debugging.\n", - "\n", - "Review:\n", - "**Code Review**\n", - "\n", - "Overall, the provided Python function for email validation looks clean and well-structured. It effectively checks if the input string matches the typical format of an email address using a regular expression pattern. However, there are some areas that can be improved upon:\n", - "\n", - "### Bugs and Edge Cases\n", - "1. **Input Validation**: In the current implementation, `TypeError` is raised when the input is not a string, but then immediately caught and handled within the same function. Consider letting it propagate up instead of catching it here since you're already returning an error message and `False`.\n", - "2. **Email Length Limitation**: The regular expression does not account for email length limits. As per [RFC 5321](https://tools.ietf.org/html/rfc5321#section-4.5.3), the maximum total length of a mailbox (local part plus domain) is 320 characters, but some mail servers may enforce shorter limits.\n", - "3. **Internationalized Domain Names (IDNs)**: The function does not support IDNs which are domain names that contain non-ASCII characters.\n", - "\n", - "### Performance Issues\n", - "1. **Regular Expression Compilation**: If this function is called frequently, compiling the regular expression pattern once outside of it and storing the result in a variable can improve performance.\n", - "2. **Exception Handling Overhead**: Python exceptions come with some overhead. Using if-statements to handle anticipated conditions (like type checking) instead of using exceptions for control flow might be more efficient.\n", - "\n", - "### Security Vulnerabilities\n", - "No significant security vulnerabilities were identified, but it's essential to note that validating an email address does not necessarily mean the provided email exists or can receive mail; a separate verification process (usually involving sending a confirmation link) should be implemented if you need to confirm the existence of the email account.\n", - "\n", - "### Best Practices\n", - "1. **Direct Printing**: Instead of directly printing error messages from within the function, consider raising exceptions with descriptive messages. This approach allows the caller to handle errors as needed.\n", - "2. **Variable Naming and Comments**: Although comments are provided in the docstring and around code blocks explaining what each segment does, variable names like `email` could be more descriptive (e.g., `input_email_address`). However, given the context, `email` is sufficient here.\n", - "3. **Example Usage**: The example usage section provides a simple demonstration of how to use the `validate_email` function with different inputs.\n", - "\n", - "### Code Improvements\n", - "\n", - "```python\n", + " [Developer - Iteration 2]\n", + " Code submitted for review (preview): ```python\n", "import re\n", "\n", - "EMAIL_PATTERN = re.compile(\n", - " r\"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$\",\n", - " flags=re.IGNORECASE,\n", - ")\n", + "# Define a regular expression pattern for email validation ...\n", "\n", - "def validate_email_address(input_string: str) -> bool:\n", - " \"\"\"Validate an email address.\"\"\"\n", - " \n", - " # Input type check\n", - " if not isinstance(input_string, str):\n", - " raise TypeError(\"Input must be a string.\")\n", + " [Reviewer - Iteration 2]\n", + " Decision: ❌ NEEDS REVISION\n", + " Sending feedback to developer...\n", "\n", - " input_string = input_string.strip()\n", - " \n", - " if \" \" in input_string:\n", - " raise ValueError(\"No spaces are allowed in the email address.\")\n", - " \n", - " if len(input_string) > 320: # Basic length validation as per RFC5321\n", - " raise ValueError(\"Email address exceeds maximum length limit.\")\n", + " [Developer - Iteration 3]\n", + " Code submitted for review (preview): ```python\n", + "import re\n", "\n", - " # Regular expression match for basic email format validity\n", - " return bool(EMAIL_PATTERN.match(input_string))\n", + "# Define a regular expression pattern for email validation ...\n", "\n", - "# Example usage with error handling\n", + " [Reviewer - Iteration 3]\n", + " Decision: ❌ NEEDS REVISION\n", + " Sending feedback to developer...\n", + "\n", + " [Developer - Iteration 4]\n", + " Code submitted for review (preview): ```python\n", + "import re\n", + "import logging\n", + "\n", + "# Define constants for email validation\n", + "EMAI...\n", + "\n", + " [Reviewer - Iteration 4]\n", + " Decision: ❌ NEEDS REVISION\n", + "\n", + "============================================================\n", + "FINAL RESULT:\n", + "============================================================\n", + "⚠️ MAX ITERATIONS REACHED (4)\n", + "\n", + "📝 Last Review:\n", + "NEEDS REVISION: \n", + "The code provided has several areas that need improvement. Here are the specific issues:\n", + "\n", + "1. **Input Validation**: The `validate_input` function checks if the input email is a string and raises a TypeError if not. However, in the example usage, there's an attempt to call `validate_email(None)`. When this happens, the code does indeed raise an error, but it would be more Pythonic to explicitly check for `None` before calling `validate_input`, since `isinstance(None, str)` is False.\n", + "\n", + "2. **Internationalized Domain Name (IDN) Handling**: The code logs a warning when an IDN is detected but doesn't further validate the domain name according to IDN rules. It would be more robust to actually check if the domain can be encoded in ASCII using Punycode for validation purposes, rather than just logging a warning.\n", + "\n", + "3. **Error Handling in `validate_email_format`**: This function catches `re.error` exceptions but then immediately raises them again. If the intention is to log the error before re-raising it, this code achieves that. However, if not handling these errors further (e.g., providing a default return value or additional processing), consider removing the try-except block since it does not add any functionality beyond what's already built into Python.\n", + "\n", + "4. **Logging**: The code uses `logging.error` and `logging.warning` to log various events but does not configure logging anywhere in the provided snippet. Ensure that logging is configured appropriately at the application level, including setting a logging level and handlers for where log messages should be sent (e.g., console, file).\n", + "\n", + "5. **Type Hints for Exception Returns**: While type hints are used for function arguments and return types, consider adding them for raised exceptions as well to make the code's behavior more explicit.\n", + "\n", + "6. **Redundant Pattern Matching**: The `validate_email_format` function first checks if an email is non-ASCII before attempting a pattern match with `EMAIL_PATTERN`. However, since `EMAIL_PATTERN` only matches ASCII characters (due to its structure), the check for ASCII can be omitted as it's implicitly required by the regular expression. \n", + "\n", + "7. **Potential Regular Expression Denial of Service (ReDoS)**: Regular expressions are vulnerable to ReDoS when certain patterns cause catastrophic backtracking, leading to exponential time complexity in matching strings. While `EMAIL_PATTERN` seems safe, consider using more efficient validation methods or libraries specifically designed for email address validation if possible.\n", + "\n", + "8. **Comment on Edge Cases**: The code attempts to validate common email formats but notes it might not cover all edge cases according to the official standard (RFC 5322). It would be beneficial to document which specific edge cases this implementation does not handle to set expectations for its usage and limitations. \n", + "\n", + "9. **Testing Coverage**: Although there's an example usage with a range of test emails, consider using a unit testing framework like `unittest` to write and run structured tests against the validation functions. This approach ensures more comprehensive coverage of potential inputs and makes it easier to identify regressions if the code is modified in the future.\n", + "\n", + "10. **Consider Using Existing Libraries**: Email address validation can be complex, especially when considering international domain names and all possible valid formats according to RFCs. Consider using an existing library designed specifically for this purpose, like `email-validator`, which might offer more comprehensive and reliable validation capabilities than a custom implementation.\n", + "\n", + "💻 Last Code:\n", + "```python\n", + "import re\n", + "import logging\n", + "\n", + "# Define constants for email validation\n", + "EMAIL_PATTERN = r\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\"\n", + "MAX_EMAIL_LENGTH = 254 # Maximum allowed length of an email address\n", + "IDN_PATTERN = r\"^xn--.*$\" # Pattern to match internationalized domain names (IDNs)\n", + "\n", + "def validate_input(email: str) -> None:\n", + " \"\"\"\n", + " Validate input type and emptiness.\n", + "\n", + " Args:\n", + " email (str): The email address to validate.\n", + "\n", + " Raises:\n", + " TypeError: If the input email is not a string.\n", + " ValueError: If the input email is empty or exceeds the maximum allowed length.\n", + " \"\"\"\n", + "\n", + " # Check if email is a string\n", + " if not isinstance(email, str):\n", + " raise TypeError(\"Input must be a string\")\n", + "\n", + " # Trim leading/trailing whitespace from the input email\n", + " email = email.strip()\n", + "\n", + " # Check if email is empty after trimming or exceeds the maximum length\n", + " if not email or len(email) > MAX_EMAIL_LENGTH:\n", + " raise ValueError(f\"Email '{email}' cannot be empty and must not exceed {MAX_EMAIL_LENGTH} characters\")\n", + "\n", + "def validate_email_format(email: str) -> bool:\n", + " \"\"\"\n", + " Validate the format of an email address.\n", + "\n", + " An email address is considered valid if it matches the standard format of local-part@domain.\n", + " The local-part may contain letters (a-z, A-Z), numbers (0-9), and special characters (. _ % + -).\n", + " The domain must be at least two parts separated by a dot, with each part containing letters (a-z, A-Z), numbers (0-9), and hyphens (-).\n", + "\n", + " Note: This function does not check if the email address actually exists or if the domain is valid according to the official standard (RFC 5322).\n", + " It implements a simplified version of the standard that supports common email address formats but may not cover all edge cases.\n", + "\n", + " Args:\n", + " email (str): The email address to validate.\n", + "\n", + " Returns:\n", + " bool: True if the email format is valid, False otherwise.\n", + " \"\"\"\n", + "\n", + " # Check if the email contains non-ASCII characters\n", + " if not email.isascii():\n", + " logging.error(\"Email contains non-ASCII characters\")\n", + " return False\n", + "\n", + " try:\n", + " # Check if the email matches the pattern\n", + " if re.match(EMAIL_PATTERN, email):\n", + " # Additional check for internationalized domain names (IDNs)\n", + " domain = email.split('@')[1]\n", + " if IDN_PATTERN.match(domain):\n", + " logging.warning(\"Internationalized domain name detected\")\n", + " return True\n", + " else:\n", + " return False\n", + " except re.error as e:\n", + " logging.error(f\"Error occurred during regular expression matching: {e}\")\n", + " raise\n", + "\n", + "def validate_email(email: str) -> bool:\n", + " \"\"\"\n", + " Validate an email address.\n", + "\n", + " Args:\n", + " email (str): The email address to validate.\n", + "\n", + " Returns:\n", + " bool: True if the email is valid, False otherwise.\n", + "\n", + " Raises:\n", + " TypeError: If the input email is not a string.\n", + " ValueError: If the input email is empty or exceeds the maximum allowed length.\n", + " \"\"\"\n", + "\n", + " validate_input(email)\n", + " return validate_email_format(email)\n", + "\n", + "# Example usage and edge case testing\n", "if __name__ == \"__main__\":\n", " emails = [\n", " \"test@example.com\",\n", " \"invalid_email\",\n", - " \"test@ example.com\",\n", - " \"test@example\",\n", - " 123, \n", + " \"test@.com\",\n", + " \" test@example.com\",\n", + " \"test.example.com\",\n", + " None,\n", + " \"\",\n", + " \"verylongdomainname123456789012345678901234567890@example.com\",\n", + " \"special.chars(email)-test@example.co.uk\",\n", + " \"test@example.co.uk..uk\"\n", " ]\n", "\n", " for email in emails:\n", - " print(f\"Email: {email}\")\n", " try:\n", - " is_valid = validate_email_address(email)\n", - " print(f\"Is Valid: {is_valid}\")\n", + " print(f\"Email: {email}, Valid: {validate_email(email)}\")\n", " except (TypeError, ValueError) as e:\n", - " print(f\"Error: {e}\")\n", - " print(\"-\" * 50)\n", - "```\n", - "\n", - "In summary, while the original code provides a good basic structure for validating email addresses, a few adjustments can enhance its flexibility and robustness. These changes primarily focus on improving exception handling, avoiding unnecessary overhead, and adhering to best practices in Python coding standards.\n", - "\n", - "LGTM with the suggested modifications.\n" + " if email is None:\n", + " print(\"Email: None, Error: Input must be a string\")\n", + " else:\n", + " print(f\"Email: {email}, Error: {e}\")\n", + "```\n" ] } ], @@ -670,14 +742,14 @@ "from agent_framework import WorkflowBuilder, executor, WorkflowContext, WorkflowOutputEvent\n", "from typing_extensions import Never\n", "\n", - "# Create code review agents\n", + "# Create code review agents with better instructions\n", "code_developer = ChatAgent(\n", " name=\"Developer\",\n", " chat_client=chat_client,\n", " instructions=\"\"\"You are a developer. When you receive code review feedback:\n", " - Address ALL issues mentioned\n", - " - Explain your changes\n", - " - Present the improved code\n", + " - Explain your changes briefly\n", + " - Present ONLY the improved code (no extra commentary)\n", "\n", " If no feedback is given, present your initial implementation.\"\"\"\n", ")\n", @@ -685,36 +757,72 @@ "code_reviewer = ChatAgent(\n", " name=\"CodeReviewer\",\n", " chat_client=chat_client,\n", - " instructions=\"\"\"You are a senior code reviewer. Review code for:\n", - " - Bugs and edge cases\n", - " - Performance issues\n", - " - Security vulnerabilities\n", - " - Best practices\n", + " instructions=\"\"\"You are a senior code reviewer. Review code for bugs, performance, security, and best practices.\n", "\n", - " If the code looks good, say 'LGTM' (Looks Good To Me).\n", - " If issues found, provide specific feedback for improvement.\"\"\"\n", + " CRITICAL: Your response MUST start with one of these:\n", + "\n", + " If code is production-ready:\n", + " \"APPROVED: [brief reason why it's good]\"\n", + "\n", + " If code needs changes:\n", + " \"NEEDS REVISION: [list specific issues to fix]\"\n", + "\n", + " DO NOT provide fixed code examples.\n", + " DO NOT say LGTM or APPROVED unless the code is truly ready.\n", + " Be constructive but strict.\"\"\"\n", ")\n", "\n", - "print(\"✅ Code review team created\")\n", + "print(\"✅ Code review team created with strict instructions\")\n", + "\n", + "# Track iterations\n", + "review_state = {\"iteration\": 0, \"max_iterations\": 4}\n", "\n", "# Define custom executors for workflow\n", "@executor(id=\"developer\")\n", "async def developer_executor(task: str, ctx: WorkflowContext[str]) -> None:\n", " \"\"\"Developer creates or improves code based on input.\"\"\"\n", + " review_state[\"iteration\"] += 1\n", + " print(f\"\\n [Developer - Iteration {review_state['iteration']}]\")\n", + "\n", " result = await code_developer.run(task)\n", + " print(f\" Code submitted for review (preview): {result.text[:80]}...\")\n", " await ctx.send_message(result.text)\n", "\n", "@executor(id=\"reviewer\")\n", "async def reviewer_executor(code: str, ctx: WorkflowContext[str, str]) -> None:\n", " \"\"\"Reviewer checks code and either approves or requests changes.\"\"\"\n", - " result = await code_reviewer.run(f\"Review this code:\\n{code}\")\n", + " print(f\"\\n [Reviewer - Iteration {review_state['iteration']}]\")\n", "\n", - " # Check if approved\n", - " if \"LGTM\" in result.text or \"looks good\" in result.text.lower():\n", - " await ctx.yield_output(f\"✅ APPROVED\\n\\nCode:\\n{code}\\n\\nReview:\\n{result.text}\")\n", + " result = await code_reviewer.run(f\"Review this code:\\n\\n{code}\")\n", + "\n", + " # Smart approval detection - check the START of the response\n", + " response_start = result.text[:100].upper() # First 100 chars only\n", + " is_approved = response_start.startswith(\"APPROVED\")\n", + " needs_revision = \"NEEDS REVISION\" in response_start\n", + "\n", + " print(f\" Decision: {'✅ APPROVED' if is_approved else '❌ NEEDS REVISION' if needs_revision else '⚠️ UNCLEAR'}\")\n", + "\n", + " if is_approved:\n", + " # Code approved! Output final result\n", + " await ctx.yield_output(\n", + " f\"✅ APPROVED after {review_state['iteration']} iteration(s)\\n\\n\"\n", + " f\"📝 Review Comments:\\n{result.text}\\n\\n\"\n", + " f\"💻 Final Code:\\n{code}\"\n", + " )\n", + " elif review_state[\"iteration\"] >= review_state[\"max_iterations\"]:\n", + " # Hit max iterations - force stop\n", + " await ctx.yield_output(\n", + " f\"⚠️ MAX ITERATIONS REACHED ({review_state['max_iterations']})\\n\\n\"\n", + " f\"📝 Last Review:\\n{result.text}\\n\\n\"\n", + " f\"💻 Last Code:\\n{code}\"\n", + " )\n", " else:\n", " # Send feedback back to developer for revision\n", - " await ctx.send_message(f\"Feedback: {result.text}\\n\\nOriginal code:\\n{code}\", target_id=\"developer\")\n", + " print(f\" Sending feedback to developer...\")\n", + " await ctx.send_message(\n", + " f\"FEEDBACK FROM REVIEWER:\\n{result.text}\\n\\nPrevious code:\\n{code}\",\n", + " target_id=\"developer\"\n", + " )\n", "\n", "# Build workflow: developer → reviewer (with feedback loop)\n", "workflow = (\n", @@ -725,27 +833,29 @@ " .build()\n", ")\n", "\n", - "# task = \"Implement a Python function to check if a string is a palindrome.\"\n", + "# Use a task that's more likely to need multiple iterations\n", "task = \"\"\"Implement a Python function to validate email addresses with these requirements:\n", "- Must have @ symbol\n", "- Must have domain with at least one dot\n", "- No spaces allowed\n", "- Handle edge cases\n", - "- Include error messages\n", - "Make it production-ready with proper error handling.\"\"\"\n", + "- Include basic error handling\n", + "Keep it simple but correct.\"\"\"\n", "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"Code Review Workflow (with iteration tracking):\")\n", + "print(\"=\"*60)\n", "\n", - "print(\"\\n\" + \"=\"*50)\n", - "print(\"Code Review Workflow:\")\n", - "print(\"=\"*50)\n", + "# Reset state\n", + "review_state[\"iteration\"] = 0\n", "\n", "# Run workflow with streaming\n", - "iteration = 1\n", "async for event in workflow.run_stream(task):\n", " if isinstance(event, WorkflowOutputEvent):\n", - " print(f\"\\n[Iteration {iteration} - Final Result]:\")\n", - " print(event.data)\n", - " iteration += 1" + " print(\"\\n\" + \"=\"*60)\n", + " print(\"FINAL RESULT:\")\n", + " print(\"=\"*60)\n", + " print(event.data)" ] }, { @@ -764,7 +874,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 7, "metadata": { "scrolled": true }, @@ -784,48 +894,50 @@ "--------------------------------------------------\n", "\n", "[Analysis 2]:\n", - "**Proposal Evaluation: Deploying a Customer Service Chatbot**\n", + "**Proposal Evaluation: Customer Service Chatbot Deployment**\n", "\n", - "**Executive Summary:**\n", - "The proposal to deploy a customer service chatbot aims to enhance customer experience, reduce support queries, and optimize resource allocation. This evaluation assesses the technical feasibility and implementation complexity of the proposed solution.\n", + "**Introduction:**\n", + "The proposed project aims to deploy a customer service chatbot to enhance the user experience, reduce support queries, and increase efficiency. This evaluation assesses the technical feasibility and implementation complexity of the proposal.\n", "\n", "**Technical Feasibility:**\n", "\n", - "1. **Natural Language Processing (NLP) Capabilities:** The chatbot's ability to understand and respond to customer inquiries accurately is crucial. Modern NLP libraries (e.g., NLTK, spaCy) and machine learning frameworks (e.g., TensorFlow, PyTorch) can support this requirement.\n", - "2. **Integration with Existing Systems:** Seamless integration with the CRM, helpdesk software, and other relevant systems is necessary. APIs and webhooks can facilitate data exchange and synchronization.\n", - "3. **Security and Compliance:** The chatbot must ensure customer data protection and adhere to regulations (e.g., GDPR, HIPAA). Implementing encrypti...\n", + "1. **Platform Compatibility:** The chatbot can be integrated with various platforms, including websites, mobile apps, and social media messaging services.\n", + "2. **Natural Language Processing (NLP):** The proposed NLP engine is capable of understanding and processing human language, allowing for effective conversation flow.\n", + "3. **Integration with Existing Systems:** The chatbot can be integrated with the company's CRM system to access customer data and provide personalized support.\n", + "4. **Security:** The proposed solution includes robust security measures, such as encryption and secure authentication protocols, to ensure data protection.\n", + "\n", + "**Technic...\n", "--------------------------------------------------\n", "\n", "[Analysis 3]:\n", - "**Evaluation of Customer Service Chatbot Proposal**\n", + "**Proposal Evaluation: Deploying a Customer Service Chatbot**\n", "\n", - "**Introduction:**\n", - "The proposal to deploy a customer service chatbot aims to improve customer experience, reduce support costs, and increase efficiency in handling customer inquiries. This evaluation assesses the business value, ROI, and market impact of implementing a customer service chatbot.\n", + "**Introduction**\n", "\n", - "**Benefits:**\n", + "The proposal aims to deploy a customer service chatbot to enhance customer experience, reduce support queries, and improve operational efficiency. This evaluation will assess the business value, ROI, and market impact of the proposed solution.\n", "\n", - "1. **Improved Customer Experience:** A chatbot can provide 24/7 support, quick responses to common queries, and personalized experiences, leading to increased customer satisfaction.\n", - "2. **Cost Savings:** Automating routine inquiries can reduce the workload of human customer support agents, resulting in cost savings and allowing them to focus on complex issues.\n", - "3. **Increased Efficiency:** Chatbots can handle multiple conversations simultaneously, reducing wait times and improving response rates.\n", - "4. **Data Collection and Analysis:** Chatbots can collect valuable data on customer interactions, providing insights for business improv...\n", + "**Business Case**\n", + "\n", + "1. **Problem Statement**: The current customer support process is manual, time-consuming, and leads to long wait times, resulting in decreased customer satisfaction.\n", + "2. **Solution Overview**: Implement a conversational AI-powered chatbot that provides 24/7 support, automates routine inquiries, and directs complex issues to human agents.\n", + "3. **Key Benefits**:\n", + "\t* Improved response times (reduced average handle time by 30%)\n", + "\t* Enhanced customer experience (increased satisfaction ratings by 20%)\n", + "\t* Reduced support queries (decreased ticket volume by 25%)\n", + "\t* Cost savings (lowered labor costs by 15%)\n", + "4. **Target Audience**: Existing customers, new custom...\n", "--------------------------------------------------\n", "\n", "[Analysis 4]:\n", - "**Evaluation of Customer Service Chatbot Proposal**\n", + "**Proposal Evaluation: Customer Service Chatbot Deployment**\n", "\n", - "**Introduction:**\n", - "The proposal to deploy a customer service chatbot aims to enhance customer experience, reduce support queries, and improve response times. This evaluation assesses the feasibility, security implications, risks, and compliance of implementing a chatbot solution.\n", - "\n", - "**Benefits:**\n", - "\n", - "1. **24/7 Support**: A chatbot can provide round-the-clock support, improving customer satisfaction and reducing the workload on human customer support agents.\n", - "2. **Faster Response Times**: Chatbots can respond to queries instantly, ensuring that customers receive timely assistance.\n", - "3. **Cost Savings**: Automating routine inquiries can lead to significant cost savings by reducing the need for human customer support agents.\n", - "4. **Personalization**: Chatbots can be programmed to offer personalized recommendations and solutions based on customer interactions.\n", + "**Overview**\n", + "The proposal to deploy a customer service chatbot aims to enhance customer experience, improve response times, and reduce support costs. The chatbot will utilize natural language processing (NLP) and machine learning algorithms to provide automated support for frequently asked questions, routing complex issues to human representatives.\n", "\n", "**Security Implications:**\n", "\n", - "1. **Data Security**: The chatbot will handle sensitive cust...\n", + "1. **Data Protection**: The chatbot will collect and process sensitive customer data, including personal identifiable information (PII), payment details, and conversation history. Ensure that the chatbot's data storage and transmission protocols comply with relevant regulations, such as GDPR, HIPAA, or PCI-DSS.\n", + "2. **Authentication and Authorization**: Implement robust authentication and authorization mechanisms to prevent unauthorized access to customer data and ensure that only authorized personnel can modify chatbot configurations or access sensitive...\n", "--------------------------------------------------\n", "\n", "==================================================\n", @@ -886,13 +998,6 @@ "print(\"All agents completed in parallel\")\n", "print(\"=\"*50)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": {