mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-09 03:39:37 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0c6eed552 | ||
|
|
bd2774d44c | ||
|
|
89bbc960dd | ||
|
|
8214b8ac04 | ||
|
|
9d01b277a5 | ||
|
|
0c8efc283e | ||
|
|
c560957a38 | ||
|
|
5c73595f22 | ||
|
|
a88ea82bf0 | ||
|
|
9e35d6e46b | ||
|
|
4cc7ee7cfb | ||
|
|
1f260f419f | ||
|
|
ef0e3529e4 | ||
|
|
eafc33976c | ||
|
|
dd6e1e1309 | ||
|
|
730ee778dc | ||
|
|
3cd664bf7b | ||
|
|
25de69d3fa | ||
|
|
894a95cfc2 | ||
|
|
6f6979e616 | ||
|
|
e3b9ca6091 | ||
|
|
72e25f1ca2 | ||
|
|
3f1437e216 | ||
|
|
9f682a5a36 | ||
|
|
53acd2ae4b | ||
|
|
afadcbe687 | ||
|
|
a95fdede7c | ||
|
|
33ef1cdf48 | ||
|
|
5f38d7f9f4 | ||
|
|
be57dd2e73 | ||
|
|
bc6373036b | ||
|
|
ed41906af7 | ||
|
|
e456990a91 | ||
|
|
c5647bec54 | ||
|
|
1e45cc0ce1 | ||
|
|
6a1009462a | ||
|
|
6425758a25 | ||
|
|
1960cf9401 | ||
|
|
7f399f4870 | ||
|
|
81c35a35ca | ||
|
|
d0cf8e8b20 | ||
|
|
9eee37ad61 | ||
|
|
90cb5c57db | ||
|
|
4137d7dd45 | ||
|
|
5804bb7115 | ||
|
|
f641110bd1 | ||
|
|
de02eb7054 | ||
|
|
d579412eed | ||
|
|
22904cf41d | ||
|
|
c542d77b45 | ||
|
|
dce8becb5d | ||
|
|
9f7993ac40 | ||
|
|
2ce177890f | ||
|
|
11909566e9 | ||
|
|
57b4b10ddf | ||
|
|
7bafdd7a4a | ||
|
|
911e991f84 | ||
|
|
8164dfd1cf | ||
|
|
461bac900d | ||
|
|
a6b964d185 | ||
|
|
67e02cd88a | ||
|
|
4f7b6ed9f8 | ||
|
|
f157196759 | ||
|
|
41b1d9f885 | ||
|
|
9de8d57a1c | ||
|
|
58da95e139 |
No files matched your search
@@ -0,0 +1,21 @@
|
||||
name: Claude OAuth
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
code:
|
||||
description: 'Authorization code (leave empty for step 1)'
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
actions: write # Required for cache management
|
||||
contents: read # Required for basic repository access
|
||||
|
||||
jobs:
|
||||
auth:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: grll/claude-code-login@v1
|
||||
with:
|
||||
code: ${{ inputs.code }}
|
||||
secrets_admin_pat: ${{ secrets.SECRETS_ADMIN_PAT }}
|
||||
+1
-1
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
flask \
|
||||
"praisonai>=2.2.35" \
|
||||
"praisonai>=2.2.37" \
|
||||
"praisonai[api]" \
|
||||
gunicorn \
|
||||
markdown
|
||||
|
||||
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.2.35" \
|
||||
"praisonai>=2.2.37" \
|
||||
"praisonai[chat]" \
|
||||
"embedchain[github,youtube]"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.2.35" \
|
||||
"praisonai>=2.2.37" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[chat]" \
|
||||
"praisonai[realtime]" \
|
||||
|
||||
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=2.2.35" \
|
||||
"praisonai>=2.2.37" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
+2
-2
@@ -121,7 +121,7 @@ healthcheck:
|
||||
## 📦 Package Versions
|
||||
|
||||
All Docker images use consistent, up-to-date versions:
|
||||
- PraisonAI: `>=2.2.35`
|
||||
- PraisonAI: `>=2.2.37`
|
||||
- PraisonAI Agents: `>=0.0.92`
|
||||
- Python: `3.11-slim`
|
||||
|
||||
@@ -218,7 +218,7 @@ docker-compose up -d
|
||||
### Version Pinning
|
||||
To use specific versions, update the Dockerfile:
|
||||
```dockerfile
|
||||
RUN pip install "praisonai==2.2.35" "praisonaiagents==0.0.92"
|
||||
RUN pip install "praisonai==2.2.37" "praisonaiagents==0.0.92"
|
||||
```
|
||||
|
||||
## 🌐 Production Deployment
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,606 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"widgets": {
|
||||
"application/vnd.jupyter.widget-state+json": {
|
||||
"b53cc2ccefec4862bd0951005998e0cc": {
|
||||
"model_module": "@jupyter-widgets/output",
|
||||
"model_name": "OutputModel",
|
||||
"model_module_version": "1.0.0",
|
||||
"state": {
|
||||
"_dom_classes": [],
|
||||
"_model_module": "@jupyter-widgets/output",
|
||||
"_model_module_version": "1.0.0",
|
||||
"_model_name": "OutputModel",
|
||||
"_view_count": null,
|
||||
"_view_module": "@jupyter-widgets/output",
|
||||
"_view_module_version": "1.0.0",
|
||||
"_view_name": "OutputView",
|
||||
"layout": "IPY_MODEL_96120ef853404e0a995b4b425c4cc1d7",
|
||||
"msg_id": "",
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": "\u001b[32m╭─\u001b[0m\u001b[32m─────────────────────────────────────────────\u001b[0m\u001b[32m Generating... 2.9s \u001b[0m\u001b[32m──────────────────────────────────────────────\u001b[0m\u001b[32m─╮\u001b[0m\n\u001b[32m│\u001b[0m It looks like the applicant is missing the \"recommendation letter\" from the list of required documents. \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m To complete your application, please ensure you obtain a recommendation letter. This can typically be from a \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m teacher, professor, or professional who can speak to your qualifications and character. If you need further \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m guidance on how to request a recommendation letter or \u001b[32m│\u001b[0m\n\u001b[32m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n",
|
||||
"text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">╭────────────────────────────────────────────── Generating... 2.9s ───────────────────────────────────────────────╮</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> It looks like the applicant is missing the \"recommendation letter\" from the list of required documents. <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> To complete your application, please ensure you obtain a recommendation letter. This can typically be from a <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> teacher, professor, or professional who can speak to your qualifications and character. If you need further <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> guidance on how to request a recommendation letter or <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n</pre>\n"
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"96120ef853404e0a995b4b425c4cc1d7": {
|
||||
"model_module": "@jupyter-widgets/base",
|
||||
"model_name": "LayoutModel",
|
||||
"model_module_version": "1.2.0",
|
||||
"state": {
|
||||
"_model_module": "@jupyter-widgets/base",
|
||||
"_model_module_version": "1.2.0",
|
||||
"_model_name": "LayoutModel",
|
||||
"_view_count": null,
|
||||
"_view_module": "@jupyter-widgets/base",
|
||||
"_view_module_version": "1.2.0",
|
||||
"_view_name": "LayoutView",
|
||||
"align_content": null,
|
||||
"align_items": null,
|
||||
"align_self": null,
|
||||
"border": null,
|
||||
"bottom": null,
|
||||
"display": null,
|
||||
"flex": null,
|
||||
"flex_flow": null,
|
||||
"grid_area": null,
|
||||
"grid_auto_columns": null,
|
||||
"grid_auto_flow": null,
|
||||
"grid_auto_rows": null,
|
||||
"grid_column": null,
|
||||
"grid_gap": null,
|
||||
"grid_row": null,
|
||||
"grid_template_areas": null,
|
||||
"grid_template_columns": null,
|
||||
"grid_template_rows": null,
|
||||
"height": null,
|
||||
"justify_content": null,
|
||||
"justify_items": null,
|
||||
"left": null,
|
||||
"margin": null,
|
||||
"max_height": null,
|
||||
"max_width": null,
|
||||
"min_height": null,
|
||||
"min_width": null,
|
||||
"object_fit": null,
|
||||
"object_position": null,
|
||||
"order": null,
|
||||
"overflow": null,
|
||||
"overflow_x": null,
|
||||
"overflow_y": null,
|
||||
"padding": null,
|
||||
"right": null,
|
||||
"top": null,
|
||||
"visibility": null,
|
||||
"width": null
|
||||
}
|
||||
},
|
||||
"71d29f64b5b74d37bd92ea2e0c38fbcd": {
|
||||
"model_module": "@jupyter-widgets/output",
|
||||
"model_name": "OutputModel",
|
||||
"model_module_version": "1.0.0",
|
||||
"state": {
|
||||
"_dom_classes": [],
|
||||
"_model_module": "@jupyter-widgets/output",
|
||||
"_model_module_version": "1.0.0",
|
||||
"_model_name": "OutputModel",
|
||||
"_view_count": null,
|
||||
"_view_module": "@jupyter-widgets/output",
|
||||
"_view_module_version": "1.0.0",
|
||||
"_view_name": "OutputView",
|
||||
"layout": "IPY_MODEL_2974c3f12e704a3595f252433bdded8d",
|
||||
"msg_id": "",
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": "\u001b[32m╭─\u001b[0m\u001b[32m─────────────────────────────────────────────\u001b[0m\u001b[32m Generating... 3.0s \u001b[0m\u001b[32m──────────────────────────────────────────────\u001b[0m\u001b[32m─╮\u001b[0m\n\u001b[32m│\u001b[0m The deadline for undergraduate applications can vary depending on the university and the specific program you \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m are applying to. Generally, many universities have deadlines around January 1st for regular decision \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m applications, but some may have earlier deadlines for early action or early decision, often in November. It's \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m important to check the specific deadlines for the university you are interested in, as they can differ. If you \u001b[32m│\u001b[0m\n\u001b[32m│\u001b[0m have a particular university in mind, \u001b[32m│\u001b[0m\n\u001b[32m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n",
|
||||
"text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">╭────────────────────────────────────────────── Generating... 3.0s ───────────────────────────────────────────────╮</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> The deadline for undergraduate applications can vary depending on the university and the specific program you <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> are applying to. Generally, many universities have deadlines around January 1st for regular decision <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> applications, but some may have earlier deadlines for early action or early decision, often in November. It's <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> important to check the specific deadlines for the university you are interested in, as they can differ. If you <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">│</span> have a particular university in mind, <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n<span style=\"color: #008000; text-decoration-color: #008000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n</pre>\n"
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"2974c3f12e704a3595f252433bdded8d": {
|
||||
"model_module": "@jupyter-widgets/base",
|
||||
"model_name": "LayoutModel",
|
||||
"model_module_version": "1.2.0",
|
||||
"state": {
|
||||
"_model_module": "@jupyter-widgets/base",
|
||||
"_model_module_version": "1.2.0",
|
||||
"_model_name": "LayoutModel",
|
||||
"_view_count": null,
|
||||
"_view_module": "@jupyter-widgets/base",
|
||||
"_view_module_version": "1.2.0",
|
||||
"_view_name": "LayoutView",
|
||||
"align_content": null,
|
||||
"align_items": null,
|
||||
"align_self": null,
|
||||
"border": null,
|
||||
"bottom": null,
|
||||
"display": null,
|
||||
"flex": null,
|
||||
"flex_flow": null,
|
||||
"grid_area": null,
|
||||
"grid_auto_columns": null,
|
||||
"grid_auto_flow": null,
|
||||
"grid_auto_rows": null,
|
||||
"grid_column": null,
|
||||
"grid_gap": null,
|
||||
"grid_row": null,
|
||||
"grid_template_areas": null,
|
||||
"grid_template_columns": null,
|
||||
"grid_template_rows": null,
|
||||
"height": null,
|
||||
"justify_content": null,
|
||||
"justify_items": null,
|
||||
"left": null,
|
||||
"margin": null,
|
||||
"max_height": null,
|
||||
"max_width": null,
|
||||
"min_height": null,
|
||||
"min_width": null,
|
||||
"object_fit": null,
|
||||
"object_position": null,
|
||||
"order": null,
|
||||
"overflow": null,
|
||||
"overflow_x": null,
|
||||
"overflow_y": null,
|
||||
"padding": null,
|
||||
"right": null,
|
||||
"top": null,
|
||||
"visibility": null,
|
||||
"width": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# 🎓 AI Enrollment Counselor – Intelligent University Admissions Automation"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "g3aOhTmXMX8W"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"This notebook demonstrates an AI Enrollment Counselor agent that helps automate university admissions. The agent can answer applicant questions, check application completeness, and provide personalized guidance. It uses PraisonAI Agents and a custom tool to validate required documents."
|
||||
],
|
||||
"metadata": {
|
||||
"id": "_4IXzY5oMZHZ"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/Dhivya-Bharathy/PraisonAI/blob/main/examples/cookbooks/AI_Enrollment_Counselor.ipynb)\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "rL-UiB5NOspT"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Dependencies"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "uPbtGiQmOF4Q"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"!pip install praisonaiagents openai --quiet"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "HeTyAS59MlNI"
|
||||
},
|
||||
"execution_count": 6,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Set Up API Key"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "JtNXPqR-OIwM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import os\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"sk-...\" # <-- Replace with your actual OpenAI API key"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "BqxfwYKsMrkX"
|
||||
},
|
||||
"execution_count": 7,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Tools (Imports)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "gsA7ERuYOLMw"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"from praisonaiagents import Agent"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "yN-89djDMydt"
|
||||
},
|
||||
"execution_count": 8,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# YAML Prompt (Role, Goal, Instructions)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "SOHBWRdWONo1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"ROLE = (\n",
|
||||
" \"AI Enrollment Counselor. Expert in university admissions, document validation, and applicant guidance.\"\n",
|
||||
")\n",
|
||||
"GOAL = (\n",
|
||||
" \"Help applicants with admissions, check application completeness, and provide personalized advice.\"\n",
|
||||
")\n",
|
||||
"INSTRUCTIONS = (\n",
|
||||
" \"Given applicant questions or application data, answer clearly. \"\n",
|
||||
" \"If asked to check documents, list which required documents are missing from the provided list. \"\n",
|
||||
" \"Always be friendly, helpful, and accurate.\"\n",
|
||||
")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "ZOid3qvbM1kx"
|
||||
},
|
||||
"execution_count": 9,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Main (Agent Setup & Example)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "BYrWJTqNOQir"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"# Create the enrollment counselor agent (prompt-only, no custom tools)\n",
|
||||
"enrollment_agent = Agent(\n",
|
||||
" role=ROLE,\n",
|
||||
" goal=GOAL,\n",
|
||||
" instructions=INSTRUCTIONS\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"def ask_enrollment_agent(query, submitted=None, required=None):\n",
|
||||
" if submitted and required:\n",
|
||||
" prompt = (\n",
|
||||
" f\"Applicant submitted documents: {submitted}\\n\"\n",
|
||||
" f\"Required documents: {required}\\n\"\n",
|
||||
" f\"{query}\\n\"\n",
|
||||
" \"List any missing documents and provide guidance.\"\n",
|
||||
" )\n",
|
||||
" return enrollment_agent.start(prompt)\n",
|
||||
" else:\n",
|
||||
" return enrollment_agent.start(query)\n",
|
||||
"\n",
|
||||
"# Try a sample document check\n",
|
||||
"submitted_docs = [\"transcript\", \"passport\", \"SOP\"]\n",
|
||||
"required_docs = [\"transcript\", \"passport\", \"SOP\", \"recommendation letter\"]\n",
|
||||
"print(ask_enrollment_agent(\n",
|
||||
" \"Check which documents are missing.\", submitted=submitted_docs, required=required_docs))\n",
|
||||
"\n",
|
||||
"# Try a general admissions question\n",
|
||||
"print(ask_enrollment_agent(\"What is the deadline for undergraduate applications?\"))"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 688,
|
||||
"referenced_widgets": [
|
||||
"b53cc2ccefec4862bd0951005998e0cc",
|
||||
"96120ef853404e0a995b4b425c4cc1d7",
|
||||
"71d29f64b5b74d37bd92ea2e0c38fbcd",
|
||||
"2974c3f12e704a3595f252433bdded8d"
|
||||
]
|
||||
},
|
||||
"id": "ySEhe-G_M3aj",
|
||||
"outputId": "328ed274-2026-4c5d-9ea0-afd7cc400616"
|
||||
},
|
||||
"execution_count": 10,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mAI Enrollment Counselor. Expert in university admissions, document validation, and applicant guidance.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">AI Enrollment Counselor. Expert in university admissions, document validation, and applicant guidance.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
],
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"version_major": 2,
|
||||
"version_minor": 0,
|
||||
"model_id": "b53cc2ccefec4862bd0951005998e0cc"
|
||||
}
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 3.0s\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 3.0s</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Applicant submitted documents: ['transcript', 'passport', 'SOP'] Required documents: ['transcript', 'passport', \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m 'SOP', 'recommendation letter'] Check which documents are missing. List any missing documents and provide \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m guidance. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Applicant submitted documents: ['transcript', 'passport', 'SOP'] Required documents: ['transcript', 'passport', <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> 'SOP', 'recommendation letter'] Check which documents are missing. List any missing documents and provide <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> guidance. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m It looks like the applicant is missing the \"recommendation letter\" from the list of required documents. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m To complete your application, please ensure you obtain a recommendation letter. This can typically be from a \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m teacher, professor, or professional who can speak to your qualifications and character. If you need further \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m guidance on how to request a recommendation letter or whom to ask, feel free to ask! \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> It looks like the applicant is missing the \"recommendation letter\" from the list of required documents. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> To complete your application, please ensure you obtain a recommendation letter. This can typically be from a <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> teacher, professor, or professional who can speak to your qualifications and character. If you need further <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> guidance on how to request a recommendation letter or whom to ask, feel free to ask! <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"It looks like the applicant is missing the \"recommendation letter\" from the list of required documents. \n",
|
||||
"\n",
|
||||
"To complete your application, please ensure you obtain a recommendation letter. This can typically be from a teacher, professor, or professional who can speak to your qualifications and character. If you need further guidance on how to request a recommendation letter or whom to ask, feel free to ask!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mAI Enrollment Counselor. Expert in university admissions, document validation, and applicant guidance.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">AI Enrollment Counselor. Expert in university admissions, document validation, and applicant guidance.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
],
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"version_major": 2,
|
||||
"version_minor": 0,
|
||||
"model_id": "71d29f64b5b74d37bd92ea2e0c38fbcd"
|
||||
}
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 3.2s\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 3.2s</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m What is the deadline for undergraduate applications? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> What is the deadline for undergraduate applications? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "display_data",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m The deadline for undergraduate applications can vary depending on the university and the specific program you \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m are applying to. Generally, many universities have deadlines around January 1st for regular decision \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m applications, but some may have earlier deadlines for early action or early decision, often in November. It's \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m important to check the specific deadlines for the university you are interested in, as they can differ. If you \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m have a particular university in mind, I can help you find more detailed information! \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
],
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> The deadline for undergraduate applications can vary depending on the university and the specific program you <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> are applying to. Generally, many universities have deadlines around January 1st for regular decision <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> applications, but some may have earlier deadlines for early action or early decision, often in November. It's <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> important to check the specific deadlines for the university you are interested in, as they can differ. If you <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> have a particular university in mind, I can help you find more detailed information! <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
]
|
||||
},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"The deadline for undergraduate applications can vary depending on the university and the specific program you are applying to. Generally, many universities have deadlines around January 1st for regular decision applications, but some may have earlier deadlines for early action or early decision, often in November. It's important to check the specific deadlines for the university you are interested in, as they can differ. If you have a particular university in mind, I can help you find more detailed information!\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
{
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"name": "python3",
|
||||
"display_name": "Python 3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Pocky Query Tool: Automated CVE PoC Search & Validation\n",
|
||||
"\n",
|
||||
"A lightweight, web-scale agent that helps you find, filter, and fetch real-world PoC exploits — so you don't have to.\n",
|
||||
"\n",
|
||||
"**Features:**\n",
|
||||
"- Automatically searches multiple security-related websites\n",
|
||||
"- Intelligently analyzes and extracts PoC code\n",
|
||||
"- Automatically selects the most reliable PoC samples\n",
|
||||
"- Supports collection of PoCs from multiple sources"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "BdX56iM1r5aB"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Pocky_Cybersecurity_PoC_Agent.ipynb)\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "VW766102tUUY"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Install Dependencies"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "cBu2iXmJsVqE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"!pip install praisonaiagents exa-py python-dotenv requests beautifulsoup4"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "VvbA3A7XsTFm"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Set API Keys"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Q6B2VEkFsB32"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"# Set your API keys here (replace with your actual keys)\n",
|
||||
"os.environ[\"EXA_API_KEY\"] = \"your api key\"\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"your api key\"\n",
|
||||
"os.environ[\"OPENAI_BASE_URL\"] = \"https://api.openai.com/v1\" # Optional, for custom OpenAI endpoints"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "OlOI3yc_sAkN"
|
||||
},
|
||||
"execution_count": 1,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Tools (Core Functions)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "1BvjjjJdsanO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import json\n",
|
||||
"from openai import OpenAI\n",
|
||||
"from exa_py import Exa\n",
|
||||
"\n",
|
||||
"# Dummy/Minimal agent classes for notebook demo\n",
|
||||
"class ValidationAgent:\n",
|
||||
" def __init__(self, input_json):\n",
|
||||
" self.input_json = input_json\n",
|
||||
" def run(self):\n",
|
||||
" # Dummy validation logic for notebook demo\n",
|
||||
" data = json.loads(self.input_json)\n",
|
||||
" return True if \"attack_intent\" in data and \"poc_sample\" in data else False\n",
|
||||
"\n",
|
||||
"class AttackIntentAgent:\n",
|
||||
" def __init__(self, description):\n",
|
||||
" self.description = description\n",
|
||||
" def run(self):\n",
|
||||
" # Dummy intent extraction for notebook demo\n",
|
||||
" return f\"Intent for: {self.description[:50]}...\""
|
||||
],
|
||||
"metadata": {
|
||||
"id": "GYfAJLXOsbga"
|
||||
},
|
||||
"execution_count": 3,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"## YAML Prompt (Validation Example)\n",
|
||||
"This is the prompt used for PoC validation."
|
||||
],
|
||||
"metadata": {
|
||||
"id": "THrET8-psjx-"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"validation_prompt = \"\"\"\n",
|
||||
"You are a highly skilled technical assistant with deep expertise in PoC sample validation.\n",
|
||||
"\n",
|
||||
"Given the attack intent of a CVE vulnerability and a PoC sample gathered from public sources, your task is to analyze whether the PoC correctly implements the intended attack behavior.\n",
|
||||
"\n",
|
||||
"Specifically:\n",
|
||||
"- Understand the CVE's attack intent, including the attack goal and the underlying exploitation mechanism.\n",
|
||||
"- Analyze the PoC to determine whether it is designed to achieve this intent.\n",
|
||||
"- Check whether the payloads, request structures, and overall logic of the PoC align with the described attack intent.\n",
|
||||
"- You do not need to execute the PoC. Focus on static validation through reasoning and consistency.\n",
|
||||
"\n",
|
||||
"Your output must be a JSON object with two fields:\n",
|
||||
"- \"valid\": a boolean indicating whether the PoC correctly reflects the attack intent.\n",
|
||||
"- \"reasoning\": a brief explanation of your judgment. If \"valid\" is false, the reasoning must clearly explain what is incorrect or inconsistent in the PoC compared to the attack intent, so that the PoC can be revised accordingly.\n",
|
||||
"\"\"\"\n",
|
||||
"print(validation_prompt)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "9q3aKl1xshrb"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Main (Query and Validate a CVE PoC)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "531EZgcLsqP6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"def run_pocky_for_cve(cve_id):\n",
|
||||
" # Example: Simulate fetching a description and PoC (replace with real logic)\n",
|
||||
" description = f\"Description for {cve_id} (replace with real Exa/OpenAI search)\"\n",
|
||||
" poc_sample = f\"PoC code for {cve_id} (replace with real PoC search)\"\n",
|
||||
"\n",
|
||||
" # Stage 2: Attack Intent\n",
|
||||
" intent = AttackIntentAgent(description).run()\n",
|
||||
" print(f\"Attack Intent: {intent}\")\n",
|
||||
"\n",
|
||||
" # Stage 3: Validation\n",
|
||||
" validation_input = json.dumps({\"attack_intent\": intent, \"poc_sample\": poc_sample}, indent=2)\n",
|
||||
" valid = ValidationAgent(validation_input).run()\n",
|
||||
" print(f\"Validation Result: {valid}\")\n",
|
||||
" if valid:\n",
|
||||
" print(f\"PoC for {cve_id} is valid and ready to use.\")\n",
|
||||
" else:\n",
|
||||
" print(f\"PoC for {cve_id} failed validation.\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "PQvtF-RqsrP6"
|
||||
},
|
||||
"execution_count": 5,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Example Usage"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "XiQOiSz8su3u"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"run_pocky_for_cve(\"CVE-2023-4450\")"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "39w-qpecswjw",
|
||||
"outputId": "cdcb3b29-7338-4e3e-b160-5f9568c194ca"
|
||||
},
|
||||
"execution_count": 6,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Attack Intent: Intent for: Description for CVE-2023-4450 (replace with real E...\n",
|
||||
"Validation Result: True\n",
|
||||
"PoC for CVE-2023-4450 is valid and ready to use.\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ZH_nR-SvvkDG"
|
||||
},
|
||||
"source": [
|
||||
"# Government Services Assistant - AI Chatbot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "w8B741JgvpFj"
|
||||
},
|
||||
"source": [
|
||||
"This notebook demonstrates how to use an AI-powered assistant to answer questions about government services and procedures, using the Firecrawl API and a friendly, step-by-step conversational approach."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "y8jiJYf4FA0m"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Chile_Government_Services_Assistant.ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "RRw8sPG89KNb"
|
||||
},
|
||||
"source": [
|
||||
"# Install dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "rW8ltqCICV8o"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install flask firecrawl praisonaiagents google-genai python-dotenv deep-translator"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "XGjyt-B_EfbM"
|
||||
},
|
||||
"source": [
|
||||
"# Set API Keys"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "qf8B_YltDiIe"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"os.environ['FIRECRAWL_API_KEY'] = \"your api key here\"\n",
|
||||
"os.environ['OPENAI_API_KEY'] = \"your api key here\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ccO0vwvCEqUJ"
|
||||
},
|
||||
"source": [
|
||||
"# Import Libraries & Translator"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "0prDQ5TpDnFu"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from firecrawl import FirecrawlApp, ScrapeOptions\n",
|
||||
"from deep_translator import GoogleTranslator\n",
|
||||
"import re\n",
|
||||
"\n",
|
||||
"def translate_to_spanish(text):\n",
|
||||
" try:\n",
|
||||
" return GoogleTranslator(source='auto', target='es').translate(text)\n",
|
||||
" except Exception as e:\n",
|
||||
" print(\"Translation to Spanish failed:\", e)\n",
|
||||
" return text\n",
|
||||
"\n",
|
||||
"def translate_to_english(text):\n",
|
||||
" try:\n",
|
||||
" # Remove Markdown images and None values before translation\n",
|
||||
" text = str(text).replace(\"None\", \"\")\n",
|
||||
" text = re.sub(r'!\\[.*?\\]\\(.*?\\)', '', text)\n",
|
||||
" return GoogleTranslator(source='auto', target='en').translate(text)\n",
|
||||
" except Exception as e:\n",
|
||||
" print(\"Translation to English failed:\", e)\n",
|
||||
" return text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "WxOlCHMmEuK2"
|
||||
},
|
||||
"source": [
|
||||
"# Firecrawl Tool Class"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "G4RyzJ5mDp0t"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class FirecrawlTool:\n",
|
||||
" def __init__(self, api_key, instruction: str, template: str):\n",
|
||||
" if not api_key:\n",
|
||||
" raise ValueError(\"Firecrawl API key not provided.\")\n",
|
||||
" self.app = FirecrawlApp(api_key=api_key)\n",
|
||||
" self.instruction = instruction\n",
|
||||
" self.template = template\n",
|
||||
"\n",
|
||||
" def search(self, search: str) -> str:\n",
|
||||
" if not search or len(search) < 5:\n",
|
||||
" return \"Error: Please provide a valid search query (at least 5 characters).\"\n",
|
||||
" response_md = \"\"\n",
|
||||
" try:\n",
|
||||
" search_result = self.app.search(\n",
|
||||
" query=self.instruction + search,\n",
|
||||
" limit=2,\n",
|
||||
" country=\"cl\",\n",
|
||||
" lang=\"es\", # Always search in Spanish for best results\n",
|
||||
" scrape_options=ScrapeOptions(formats=[\"markdown\", \"links\"])\n",
|
||||
" )\n",
|
||||
" if search_result and hasattr(search_result, 'data') and search_result.data:\n",
|
||||
" filtered_results = [\n",
|
||||
" result for result in search_result.data\n",
|
||||
" if str(result.get(\"url\", \"\")).startswith(\"https://www.chileatiende.gob.cl/fichas\") and not str(result.get(\"url\", \"\")).endswith(\"pdf\")\n",
|
||||
" ]\n",
|
||||
" if filtered_results:\n",
|
||||
" for num, result in enumerate(filtered_results, start=1):\n",
|
||||
" response_md += self.template.format(\n",
|
||||
" result_number=num,\n",
|
||||
" page_title=str(result.get(\"title\", \"\")),\n",
|
||||
" page_url=str(result.get(\"url\", \"\")),\n",
|
||||
" page_content=str(result.get(\"markdown\", \"\"))\n",
|
||||
" )\n",
|
||||
" return response_md\n",
|
||||
" else:\n",
|
||||
" return None\n",
|
||||
" else:\n",
|
||||
" return None\n",
|
||||
" except Exception as e:\n",
|
||||
" return f\"Error during search: {e}\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "MjkjTWn_ExS0"
|
||||
},
|
||||
"source": [
|
||||
"# Firecrawl Prompt Template"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "AfivymU8Dufz"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"FIRECRAWL_INSTRUCTION = \"ChileAtiende: \"\n",
|
||||
"FIRECRAWL_TEMPLATE = \"\"\"\n",
|
||||
"# Result {result_number}\n",
|
||||
"\n",
|
||||
"## Page Name:\n",
|
||||
"\"{page_title}\"\n",
|
||||
"\n",
|
||||
"## URL:\n",
|
||||
"{page_url}\n",
|
||||
"\n",
|
||||
"## Content:\n",
|
||||
"{page_content}\n",
|
||||
"\n",
|
||||
"\"\"\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "zK8AA_DlEz9K"
|
||||
},
|
||||
"source": [
|
||||
"# Initialize Firecrawl Tool"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "c3NKK0ZjDwKT"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"firecrawl_tool = FirecrawlTool(\n",
|
||||
" api_key=os.environ['FIRECRAWL_API_KEY'],\n",
|
||||
" instruction=FIRECRAWL_INSTRUCTION,\n",
|
||||
" template=FIRECRAWL_TEMPLATE\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "uzXYIF_gE3XV"
|
||||
},
|
||||
"source": [
|
||||
"# Main Chat Loop"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "TXMgZQNkDx7n",
|
||||
"outputId": "76303cd1-a576-483f-a22d-9857e5e6d797"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Hello! I am your ChileAtiende assistant, Tomás. How can I help you today?\n",
|
||||
"You can ask me, for example: How to renew your ID card, How to apply for the Winter Bonus, etc.\n",
|
||||
"\n",
|
||||
"You: exit\n",
|
||||
"Tomás: It was a pleasure to help you. Goodbye!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(\"Hello! I am your ChileAtiende assistant, Tomás. How can I help you today?\")\n",
|
||||
"print(\"You can ask me, for example: How to renew your ID card, How to apply for the Winter Bonus, etc.\")\n",
|
||||
"\n",
|
||||
"while True:\n",
|
||||
" user_input = input(\"\\nYou: \")\n",
|
||||
" if user_input.lower() in [\"exit\", \"quit\"]:\n",
|
||||
" print(\"Tomás: It was a pleasure to help you. Goodbye!\")\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" # Translate English input to Spanish for Firecrawl\n",
|
||||
" spanish_query = translate_to_spanish(user_input)\n",
|
||||
" spanish_answer = firecrawl_tool.search(spanish_query)\n",
|
||||
"\n",
|
||||
" # Only translate if we got a real answer\n",
|
||||
" if spanish_answer and isinstance(spanish_answer, str) and spanish_answer.strip() and \"Error\" not in spanish_answer:\n",
|
||||
" try:\n",
|
||||
" english_answer = translate_to_english(spanish_answer)\n",
|
||||
" print(\"\\nTomás (in English):\\n\", english_answer)\n",
|
||||
" except Exception as e:\n",
|
||||
" print(f\"\\nTomás: I found information, but couldn't translate it. Here it is in Spanish:\\n{spanish_answer}\\n(Translation error: {e})\")\n",
|
||||
" else:\n",
|
||||
" print(\"\\nTomás: Sorry, I couldn't find relevant information. Try rephrasing your question or ask about another service.\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "xy4LeDEn7hQM"
|
||||
},
|
||||
"source": [
|
||||
"# 🧠 Cognitive Assistant Agent Team (PraisonAI)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ElVhkoB37j8Y"
|
||||
},
|
||||
"source": [
|
||||
"This notebook demonstrates a multi-specialist cognitive assistant using PraisonAI, with each specialist as a tool."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "WKiORZL790Fj"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Intelligent_Cognitive_Agent.ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "7l3cAapx7phr"
|
||||
},
|
||||
"source": [
|
||||
"# Install Dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "oHrh082q86Pp"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install praisonaiagents"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "AnA-11hm9R4z"
|
||||
},
|
||||
"source": [
|
||||
"# Set API Key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"id": "n1Fz52T489HE"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"# Set your OpenAI or OpenRouter API key for PraisonAI\n",
|
||||
"os.environ['OPENAI_API_KEY'] = 'Enter your api key' # <-- Replace with your actual OpenAI or OpenRouter API key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bGbZXPS29XJ-"
|
||||
},
|
||||
"source": [
|
||||
"# Imports and Specialist Agent Definitions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"id": "7MzNN_u_9DKL"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import re\n",
|
||||
"from praisonaiagents import Agent\n",
|
||||
"\n",
|
||||
"# Dummy specialist agent classes for demonstration.\n",
|
||||
"# Replace these with your actual specialist agent logic if needed.\n",
|
||||
"class SpecialistAgent:\n",
|
||||
" def __init__(self, name):\n",
|
||||
" self.name = name\n",
|
||||
" def run(self, query):\n",
|
||||
" return f\"{self.name} specialist response to: {query}\"\n",
|
||||
"\n",
|
||||
"# Instantiate all specialist agents (replace with your real classes if available)\n",
|
||||
"specialists = [\n",
|
||||
" SpecialistAgent(\"decision_risk_agent\"),\n",
|
||||
" SpecialistAgent(\"problem_solving_innovation_agent\"),\n",
|
||||
" SpecialistAgent(\"Systems___Complexity_Agent\"),\n",
|
||||
" SpecialistAgent(\"bias_psychology_agent\"),\n",
|
||||
" SpecialistAgent(\"Strategy___Competition_Agent\"),\n",
|
||||
" SpecialistAgent(\"Learning___Communication_Agent\"),\n",
|
||||
" SpecialistAgent(\"Efficiency___Process_Agent\"),\n",
|
||||
" SpecialistAgent(\"motivation_human_factors_agent\"),\n",
|
||||
"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "efcGipcd9bNL"
|
||||
},
|
||||
"source": [
|
||||
"# Tool Wrapping and Agent Setup"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"id": "-rotrhkh9FmF"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def make_tool(agent):\n",
|
||||
" def tool(query: str):\n",
|
||||
" return agent.run(query)\n",
|
||||
" # Sanitize the tool name to match PraisonAI's requirements\n",
|
||||
" safe_name = re.sub(r'[^a-zA-Z0-9_-]', '_', agent.name or \"tool\")\n",
|
||||
" tool.__name__ = safe_name\n",
|
||||
" return tool\n",
|
||||
"\n",
|
||||
"tools = [make_tool(agent) for agent in specialists]\n",
|
||||
"\n",
|
||||
"agent = Agent(\n",
|
||||
" instructions=\"\"\"\n",
|
||||
" You are a cognitive assistant with access to a set of specialist tools (decision making, problem solving, systems thinking, psychology, strategy, learning, efficiency, motivation).\n",
|
||||
" Use the most relevant tool(s) to answer the user's query.\n",
|
||||
" \"\"\",\n",
|
||||
" tools=tools,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "uZp3cCBs9fMS"
|
||||
},
|
||||
"source": [
|
||||
"# User Query and Agent Response"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 777,
|
||||
"referenced_widgets": [
|
||||
"5112c2c89e944d99a9bfbe35d7186a96",
|
||||
"8dd112d60a6148e3b6cce31d7fb4eb0f"
|
||||
]
|
||||
},
|
||||
"id": "VhcEo-2q9HSv",
|
||||
"outputId": "8bf73c8a-4d0d-47dd-b151-a2a49c79b1f8"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Ask your question (or type 'quit' to exit): hi\n",
|
||||
"\n",
|
||||
"--- Thinking ---\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Assistant</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #86a789; text-decoration-color: #86a789; font-weight: bold\">Tools:</span> <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">decision_risk_agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">problem_solving_innovation_agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Systems___Complexity_Agent</span>, <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">bias_psychology_agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Strategy___Competition_Agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Learning___Communication_Agent</span>, <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Efficiency___Process_Agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">motivation_human_factors_agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mAssistant\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;134;167;137mTools:\u001b[0m \u001b[3;38;2;180;212;255mdecision_risk_agent\u001b[0m, \u001b[3;38;2;180;212;255mproblem_solving_innovation_agent\u001b[0m, \u001b[3;38;2;180;212;255mSystems___Complexity_Agent\u001b[0m, \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[3;38;2;180;212;255mbias_psychology_agent\u001b[0m, \u001b[3;38;2;180;212;255mStrategy___Competition_Agent\u001b[0m, \u001b[3;38;2;180;212;255mLearning___Communication_Agent\u001b[0m, \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[3;38;2;180;212;255mEfficiency___Process_Agent\u001b[0m, \u001b[3;38;2;180;212;255mmotivation_human_factors_agent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 1.5s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 1.5s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> hi <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m hi \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Hello! How can I assist you today? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Hello! How can I assist you today? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Hello! How can I assist you today?\n",
|
||||
"\n",
|
||||
"---------------\n",
|
||||
"Ask your question (or type 'quit' to exit): exit\n",
|
||||
"\n",
|
||||
"--- Thinking ---\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Assistant</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #86a789; text-decoration-color: #86a789; font-weight: bold\">Tools:</span> <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">decision_risk_agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">problem_solving_innovation_agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Systems___Complexity_Agent</span>, <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">bias_psychology_agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Strategy___Competition_Agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Learning___Communication_Agent</span>, <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">Efficiency___Process_Agent</span>, <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">motivation_human_factors_agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mAssistant\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;134;167;137mTools:\u001b[0m \u001b[3;38;2;180;212;255mdecision_risk_agent\u001b[0m, \u001b[3;38;2;180;212;255mproblem_solving_innovation_agent\u001b[0m, \u001b[3;38;2;180;212;255mSystems___Complexity_Agent\u001b[0m, \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[3;38;2;180;212;255mbias_psychology_agent\u001b[0m, \u001b[3;38;2;180;212;255mStrategy___Competition_Agent\u001b[0m, \u001b[3;38;2;180;212;255mLearning___Communication_Agent\u001b[0m, \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[3;38;2;180;212;255mEfficiency___Process_Agent\u001b[0m, \u001b[3;38;2;180;212;255mmotivation_human_factors_agent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "5112c2c89e944d99a9bfbe35d7186a96",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 1.2s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 1.2s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> exit <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m exit \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> If you have any more questions in the future, feel free to ask. Have a great day! Goodbye! <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m If you have any more questions in the future, feel free to ask. Have a great day! Goodbye! \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"If you have any more questions in the future, feel free to ask. Have a great day! Goodbye!\n",
|
||||
"\n",
|
||||
"---------------\n",
|
||||
"Ask your question (or type 'quit' to exit): quit\n",
|
||||
"Cognitive Assistant Agent Team - Finished.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"user_query = input(\"Ask your question (or type 'quit' to exit): \")\n",
|
||||
"while user_query.lower() != 'quit':\n",
|
||||
" print(\"\\n--- Thinking ---\")\n",
|
||||
" response = agent.start(user_query)\n",
|
||||
" print(response)\n",
|
||||
" print(\"\\n---------------\")\n",
|
||||
" user_query = input(\"Ask your question (or type 'quit' to exit): \")\n",
|
||||
"print(\"Cognitive Assistant Agent Team - Finished.\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,481 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "KoeGA1N7R8G6"
|
||||
},
|
||||
"source": [
|
||||
"# Praison AI Real Estate Chatbot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "cwsqbQF0SAcR"
|
||||
},
|
||||
"source": [
|
||||
"Interact with a real estate AI assistant powered by PraisonAI and OpenAI.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BH0Y-SB9UjNZ"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/Praison_AI_Real_Estate_Chatbot.ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "M4lyScgcSIFX"
|
||||
},
|
||||
"source": [
|
||||
"## 1. Install Dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "p0UqhMK9TMLx"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install praisonaiagents openai"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "XjtPizGWSRuh"
|
||||
},
|
||||
"source": [
|
||||
"## 2. Set Your OpenAI API Key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"id": "FTzcJ7JTTPjp"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"# Enter your OpenAI API key here\n",
|
||||
"OPENAI_API_KEY = \"Enter your api key here\" # <-- Replace with your key\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = OPENAI_API_KEY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "5WIQ76LQSeOT"
|
||||
},
|
||||
"source": [
|
||||
"## 3. Create the Praison AI Agent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"id": "mJYmlRHtTW59"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from praisonaiagents import Agent\n",
|
||||
"\n",
|
||||
"praison_agent = Agent(\n",
|
||||
" name=\"Praison Real Estate Chatbot\",\n",
|
||||
" role=\"Answer real estate questions and provide helpful advice.\",\n",
|
||||
" instructions=[\n",
|
||||
" \"You are a helpful real estate assistant.\",\n",
|
||||
" \"Answer user questions about buying, selling, or renting property.\",\n",
|
||||
" \"Provide clear, concise, and friendly advice.\"\n",
|
||||
" ],\n",
|
||||
" markdown=True\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "wDOYoxf2SlSD"
|
||||
},
|
||||
"source": [
|
||||
"## 4. Chat with the Agent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000,
|
||||
"referenced_widgets": [
|
||||
"caca39e23f66484e941342713956f289",
|
||||
"a9f33a0ed67440f1aee8c84ee7e71b1d",
|
||||
"bcc0387223424b45aec4212eae3aff89",
|
||||
"030f0e16572a40a7b8e100a6228030e3",
|
||||
"c91fa91cf91c4697ac28756d6bdf2c73",
|
||||
"08b05be0ee174761974bc10c1d217b53",
|
||||
"a08f3878570c48f38bfa3a097cb1e4d6",
|
||||
"58b89df2db0344fe80f29508c55b2939",
|
||||
"73ced2df95814c068150e9357692f47b",
|
||||
"9fbf91ecc93f4230beac5dfc0bf734f6"
|
||||
]
|
||||
},
|
||||
"id": "zIyEMJJ6TZlb",
|
||||
"outputId": "817d4df6-ec88-425e-f00b-8ce6b4923e00"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "caca39e23f66484e941342713956f289",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Text(value='', description='You:', placeholder='Type your real estate question here...')"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "030f0e16572a40a7b8e100a6228030e3",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Button(description='Ask Praison AI', style=ButtonStyle())"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "a08f3878570c48f38bfa3a097cb1e4d6",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 1.7s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 1.7s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Hello! How can I assist you with your real estate needs today? Whether you have questions about buying, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> selling, or renting property, I'm here to help. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Hello! How can I assist you with your real estate needs today? Whether you have questions about buying, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m selling, or renting property, I'm here to help. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/markdown": [
|
||||
"**Praison AI:** Hello! How can I assist you with your real estate needs today? Whether you have questions about buying, selling, or renting property, I'm here to help."
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Markdown object>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Praison Real Estate Chatbot</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Answer real estate questions and provide helpful advice.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mPraison Real Estate Chatbot\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mAnswer real estate questions and provide helpful advice.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "73ced2df95814c068150e9357692f47b",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 6.3s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 6.3s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> What should I look for when buying my first home? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m What should I look for when buying my first home? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Buying your first home is an exciting milestone! Here are some key things to consider: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 1 </span><span style=\"font-weight: bold\">Budget and Financing</span>: Determine how much you can afford by reviewing your finances and getting pre-approved <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>for a mortgage. This will help you understand your price range and make your offer more attractive to <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>sellers. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 2 </span><span style=\"font-weight: bold\">Location</span>: Consider the neighborhood and its proximity to work, schools, public transportation, and amenities <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>like shopping and parks. Also, research the area's safety and future development plans. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 3 </span><span style=\"font-weight: bold\">Home Type and Size</span>: Decide what type of home suits your needs—single-family, townhouse, condo, etc. Consider <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>the number of bedrooms and bathrooms you need now and in the future. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 4 </span><span style=\"font-weight: bold\">Condition of the Property</span>: Look at the age and condition of the home. Be aware of potential repairs or <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>renovations needed. A home inspection can help identify any major issues. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 5 </span><span style=\"font-weight: bold\">Resale Value</span>: Consider the potential resale value of the home. Factors like location, school districts, and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>neighborhood development can impact future value. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 6 </span><span style=\"font-weight: bold\">Lifestyle Needs</span>: Think about your lifestyle and how the home fits into it. Consider things like yard space, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>commute times, and community amenities. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 7 </span><span style=\"font-weight: bold\">Homeowners Association (HOA)</span>: If applicable, understand the rules, fees, and restrictions of the HOA. This <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>can impact your living experience and costs. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 8 </span><span style=\"font-weight: bold\">Future Growth</span>: Consider your long-term plans. Will the home accommodate potential family growth or changes <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>in your lifestyle? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Taking the time to consider these factors will help you make a well-informed decision. Good luck with your home <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> search! If you have more questions, feel free to ask. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Buying your first home is an exciting milestone! Here are some key things to consider: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 1 \u001b[0m\u001b[1mBudget and Financing\u001b[0m: Determine how much you can afford by reviewing your finances and getting pre-approved \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mfor a mortgage. This will help you understand your price range and make your offer more attractive to \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0msellers. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 2 \u001b[0m\u001b[1mLocation\u001b[0m: Consider the neighborhood and its proximity to work, schools, public transportation, and amenities \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mlike shopping and parks. Also, research the area's safety and future development plans. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 3 \u001b[0m\u001b[1mHome Type and Size\u001b[0m: Decide what type of home suits your needs—single-family, townhouse, condo, etc. Consider \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mthe number of bedrooms and bathrooms you need now and in the future. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 4 \u001b[0m\u001b[1mCondition of the Property\u001b[0m: Look at the age and condition of the home. Be aware of potential repairs or \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mrenovations needed. A home inspection can help identify any major issues. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 5 \u001b[0m\u001b[1mResale Value\u001b[0m: Consider the potential resale value of the home. Factors like location, school districts, and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mneighborhood development can impact future value. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 6 \u001b[0m\u001b[1mLifestyle Needs\u001b[0m: Think about your lifestyle and how the home fits into it. Consider things like yard space, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mcommute times, and community amenities. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 7 \u001b[0m\u001b[1mHomeowners Association (HOA)\u001b[0m: If applicable, understand the rules, fees, and restrictions of the HOA. This \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mcan impact your living experience and costs. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 8 \u001b[0m\u001b[1mFuture Growth\u001b[0m: Consider your long-term plans. Will the home accommodate potential family growth or changes \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0min your lifestyle? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Taking the time to consider these factors will help you make a well-informed decision. Good luck with your home \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m search! If you have more questions, feel free to ask. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/markdown": [
|
||||
"**Praison AI:** Buying your first home is an exciting milestone! Here are some key things to consider:\n",
|
||||
"\n",
|
||||
"1. **Budget and Financing**: Determine how much you can afford by reviewing your finances and getting pre-approved for a mortgage. This will help you understand your price range and make your offer more attractive to sellers.\n",
|
||||
"\n",
|
||||
"2. **Location**: Consider the neighborhood and its proximity to work, schools, public transportation, and amenities like shopping and parks. Also, research the area's safety and future development plans.\n",
|
||||
"\n",
|
||||
"3. **Home Type and Size**: Decide what type of home suits your needs—single-family, townhouse, condo, etc. Consider the number of bedrooms and bathrooms you need now and in the future.\n",
|
||||
"\n",
|
||||
"4. **Condition of the Property**: Look at the age and condition of the home. Be aware of potential repairs or renovations needed. A home inspection can help identify any major issues.\n",
|
||||
"\n",
|
||||
"5. **Resale Value**: Consider the potential resale value of the home. Factors like location, school districts, and neighborhood development can impact future value.\n",
|
||||
"\n",
|
||||
"6. **Lifestyle Needs**: Think about your lifestyle and how the home fits into it. Consider things like yard space, commute times, and community amenities.\n",
|
||||
"\n",
|
||||
"7. **Homeowners Association (HOA)**: If applicable, understand the rules, fees, and restrictions of the HOA. This can impact your living experience and costs.\n",
|
||||
"\n",
|
||||
"8. **Future Growth**: Consider your long-term plans. Will the home accommodate potential family growth or changes in your lifestyle?\n",
|
||||
"\n",
|
||||
"Taking the time to consider these factors will help you make a well-informed decision. Good luck with your home search! If you have more questions, feel free to ask."
|
||||
],
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Markdown object>"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import ipywidgets as widgets\n",
|
||||
"from IPython.display import display, Markdown\n",
|
||||
"\n",
|
||||
"def ask_agent(question):\n",
|
||||
" # Use the .chat() method for the public praisonaiagents package\n",
|
||||
" response = praison_agent.chat(question)\n",
|
||||
" display(Markdown(f\"**Praison AI:** {response}\"))\n",
|
||||
"\n",
|
||||
"question = widgets.Text(\n",
|
||||
" value='',\n",
|
||||
" placeholder='Type your real estate question here...',\n",
|
||||
" description='You:',\n",
|
||||
" disabled=False\n",
|
||||
")\n",
|
||||
"button = widgets.Button(description=\"Ask Praison AI\")\n",
|
||||
"\n",
|
||||
"def on_button_clicked(b):\n",
|
||||
" ask_agent(question.value)\n",
|
||||
"\n",
|
||||
"button.on_click(on_button_clicked)\n",
|
||||
"display(question, button)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,499 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "-j-8RaEinSgs"
|
||||
},
|
||||
"source": [
|
||||
"# 🧠 Search Agent (PraisonAI Edition)\n",
|
||||
"\n",
|
||||
"A minimal example of using PraisonAI's Agent with a custom internet search tool in Python, ready for Google Colab."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tztyseN5pqeD"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/MemoryPal_Search_Agent.ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "Ls8fyQsTnXqR"
|
||||
},
|
||||
"source": [
|
||||
"# Install Dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "HihjK38YncNS"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install praisonaiagents duckduckgo-search"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "drGND5XAnpzd"
|
||||
},
|
||||
"source": [
|
||||
"# Set API Key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"id": "nkpbgwJwnrn_"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"# Enter your OpenAI API key here\n",
|
||||
"os.environ['OPENAI_API_KEY'] = 'Enter your api key' # <-- Replace with your OpenAI API key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "19dqWac7nzZf"
|
||||
},
|
||||
"source": [
|
||||
"# Tool Definition"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"id": "_M7EI96dn0qi"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from duckduckgo_search import DDGS\n",
|
||||
"\n",
|
||||
"def internet_search_tool(query: str):\n",
|
||||
" results = []\n",
|
||||
" ddgs = DDGS()\n",
|
||||
" for result in ddgs.text(keywords=query, max_results=5):\n",
|
||||
" results.append({\n",
|
||||
" 'title': result.get('title', ''),\n",
|
||||
" 'url': result.get('href', ''),\n",
|
||||
" 'snippet': result.get('body', '')\n",
|
||||
" })\n",
|
||||
" return results"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "SYPI8zhen4nd"
|
||||
},
|
||||
"source": [
|
||||
"# YAML Agent Config"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "Yag6EqYOn5h-",
|
||||
"outputId": "03f37769-3f05-479d-8d5a-a201bf403c73"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{'framework': 'praisonai', 'topic': 'internet search demo', 'roles': {'searcher': {'backstory': 'Expert in internet search.', 'goal': 'Find information online.', 'role': 'Searcher', 'tools': ['internet_search_tool'], 'tasks': {'search_task': {'description': \"Search for 'AI job trends in 2025'.\", 'expected_output': 'List of search results.'}}}}}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import yaml\n",
|
||||
"\n",
|
||||
"yaml_config = \"\"\"\n",
|
||||
"framework: praisonai\n",
|
||||
"topic: internet search demo\n",
|
||||
"roles:\n",
|
||||
" searcher:\n",
|
||||
" backstory: Expert in internet search.\n",
|
||||
" goal: Find information online.\n",
|
||||
" role: Searcher\n",
|
||||
" tools:\n",
|
||||
" - internet_search_tool\n",
|
||||
" tasks:\n",
|
||||
" search_task:\n",
|
||||
" description: Search for 'AI job trends in 2025'.\n",
|
||||
" expected_output: List of search results.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"config = yaml.safe_load(yaml_config)\n",
|
||||
"print(config)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "KbYjwEkvoUqV"
|
||||
},
|
||||
"source": [
|
||||
"# Prompt Example"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "7hslONZgoXph"
|
||||
},
|
||||
"source": [
|
||||
"Example prompt to use with the agent: \n",
|
||||
"`Search about AI job trends in 2025`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "KvzzBm-7oZ9c"
|
||||
},
|
||||
"source": [
|
||||
"# Main: Run the Agent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000,
|
||||
"referenced_widgets": [
|
||||
"4a9625800fe94aabb88e2ff78bce5a1d",
|
||||
"930e61499fac44f183c51ca93e3aad88",
|
||||
"bfb62f3af49c40f7934a7f245cd57d6d",
|
||||
"50486df133bf4e1582880c2cd6f2ca54"
|
||||
]
|
||||
},
|
||||
"id": "TxyynCXCobA0",
|
||||
"outputId": "148a9670-ebd7-4d23-e248-1e5cf13aeb8e"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Assistant</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #86a789; text-decoration-color: #86a789; font-weight: bold\">Tools:</span> <span style=\"color: #b4d4ff; text-decoration-color: #b4d4ff; font-style: italic\">internet_search_tool</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mAssistant\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;134;167;137mTools:\u001b[0m \u001b[3;38;2;180;212;255minternet_search_tool\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "4a9625800fe94aabb88e2ff78bce5a1d",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">╭──────────────────────────────────────────────── Tool Call ────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">Agent Agent is calling function 'internet_search_tool' with arguments: {'query': 'AI job trends in 2025'}</span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[32m╭─\u001b[0m\u001b[32m───────────────────────────────────────────────\u001b[0m\u001b[32m Tool Call \u001b[0m\u001b[32m───────────────────────────────────────────────\u001b[0m\u001b[32m─╮\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mAgent Agent is calling function 'internet_search_tool' with arguments: {'query': 'AI job trends in 2025'}\u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">╭─────────────────────────────────────────────────── Tool Call ───────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">Function 'internet_search_tool' returned: [{\"title\": \"AI Job Trends 2025: Top AI Jobs, Roles, and Hiring Data </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">Insights\", \"url\": \"https://blog.getaura.ai/ai-job-trends-2025\", \"snippet\": \"Explore the latest AI job trends </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">for 2025. Learn about top industries hiring, in-demand skills, and emerging roles shaping the future of AI </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">hiring.\"}, {\"title\": \" The Fearless Future: 2025 Global AI Jobs Barometer - PwC\", \"url\": </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">\"https://www.pwc.com/gx/en/issues/artificial-intelligence/job-barometer/aijb-2025-united-states-analysis.pdf\", </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">\"snippet\": \"Global Insights The AI Jobs Barometer reveals AI's global impact on jobs, wages, skills, and </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">productivity by examining close to a billion job ads from six continents.\"}, {\"title\": \"10 Hottest AI Jobs Of </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2025 With Six-Figure Salaries - Forbes\", \"url\": </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">\"https://www.forbes.com/sites/bryanrobinson/2025/01/17/10-hottest-ai-jobs-of-2025-paying-six-figure-salaries/\",</span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">\"snippet\": \"Explore the top AI roles of 2025, from Machine Learning Engineers to NLP Specialists, offering </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">six-figure salaries and high demand in the evolving tech landscape.\"}, {\"title\": \"AI Job Market 2025: Impact on</span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">Employment & Future Workforce Trends\", \"url\": </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">\"https://www.cognitivetoday.com/2025/03/ai-job-market-impact-on-employment-future-workforce-trends/\", </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">\"snippet\": \"Discover how AI will reshape jobs in 2025. Learn about AI-driven displacement, new roles, and </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">must-have skills to thrive in the evolving workforce. AI Job Market 2025.\"}, {\"title\": \"AI Job Market: Trends, </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">Opportunities, and Key Skills for 2025\", \"url\": </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">\"https://www.analyticsinsight.net/artificial-intelligence/ai-job-market-trends-opportunities-and-key-skills-for</span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">-2025\", \"snippet\": \"As artificial intelligence (AI) continues to reshape industries, the job market will see a </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">significant transformation in 2025. With new opportunities emerging and certain skills becoming essential, AI </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">adoption will also rise. From automation and machine learning to AI-driven healthcare and edge computing, </span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">│</span> <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">understanding the evolving trends and required skill sets will be crucial for anyone ...\"}]</span> <span style=\"color: #008000; text-decoration-color: #008000\">│</span>\n",
|
||||
"<span style=\"color: #008000; text-decoration-color: #008000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[32m╭─\u001b[0m\u001b[32m──────────────────────────────────────────────────\u001b[0m\u001b[32m Tool Call \u001b[0m\u001b[32m──────────────────────────────────────────────────\u001b[0m\u001b[32m─╮\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mFunction 'internet_search_tool' returned: [{\"title\": \"AI Job Trends 2025: Top AI Jobs, Roles, and Hiring Data \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mInsights\", \"url\": \"https://blog.getaura.ai/ai-job-trends-2025\", \"snippet\": \"Explore the latest AI job trends \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mfor 2025. Learn about top industries hiring, in-demand skills, and emerging roles shaping the future of AI \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mhiring.\"}, {\"title\": \" The Fearless Future: 2025 Global AI Jobs Barometer - PwC\", \"url\": \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m\"https://www.pwc.com/gx/en/issues/artificial-intelligence/job-barometer/aijb-2025-united-states-analysis.pdf\", \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m\"snippet\": \"Global Insights The AI Jobs Barometer reveals AI's global impact on jobs, wages, skills, and \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mproductivity by examining close to a billion job ads from six continents.\"}, {\"title\": \"10 Hottest AI Jobs Of \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m2025 With Six-Figure Salaries - Forbes\", \"url\": \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m\"https://www.forbes.com/sites/bryanrobinson/2025/01/17/10-hottest-ai-jobs-of-2025-paying-six-figure-salaries/\",\u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m\"snippet\": \"Explore the top AI roles of 2025, from Machine Learning Engineers to NLP Specialists, offering \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36msix-figure salaries and high demand in the evolving tech landscape.\"}, {\"title\": \"AI Job Market 2025: Impact on\u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mEmployment & Future Workforce Trends\", \"url\": \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m\"https://www.cognitivetoday.com/2025/03/ai-job-market-impact-on-employment-future-workforce-trends/\", \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m\"snippet\": \"Discover how AI will reshape jobs in 2025. Learn about AI-driven displacement, new roles, and \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mmust-have skills to thrive in the evolving workforce. AI Job Market 2025.\"}, {\"title\": \"AI Job Market: Trends, \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36mOpportunities, and Key Skills for 2025\", \"url\": \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m\"https://www.analyticsinsight.net/artificial-intelligence/ai-job-market-trends-opportunities-and-key-skills-for\u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36m-2025\", \"snippet\": \"As artificial intelligence (AI) continues to reshape industries, the job market will see a \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36msignificant transformation in 2025. With new opportunities emerging and certain skills becoming essential, AI \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36madoption will also rise. From automation and machine learning to AI-driven healthcare and edge computing, \u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m│\u001b[0m \u001b[1;36munderstanding the evolving trends and required skill sets will be crucial for anyone ...\"}]\u001b[0m \u001b[32m│\u001b[0m\n",
|
||||
"\u001b[32m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "bfb62f3af49c40f7934a7f245cd57d6d",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 14.7s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 14.7s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> AI job trends in 2025 <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m AI job trends in 2025 \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Here are some insights into AI job trends for 2025: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 1 </span><span style=\"font-weight: bold\">Top AI Jobs and Roles</span>: The AI job market in 2025 is expected to feature roles such as Machine Learning <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>Engineers, NLP Specialists, and other positions offering six-figure salaries. These roles are in high demand <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>as the tech landscape evolves. <a href=\"https://www.forbes.com/sites/bryanrobinson/2025/01/17/10-hottest-ai-jobs-of-2025-paying-six-figure-salaries/\" target=\"_blank\"><span style=\"color: #000080; text-decoration-color: #000080; text-decoration: underline\">Read more on Forbes</span></a>. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 2 </span><span style=\"font-weight: bold\">Industries and Skills</span>: AI is reshaping industries, with new opportunities emerging and certain skills <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>becoming essential. Key areas include automation, machine learning, AI-driven healthcare, and edge <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>computing. <a href=\"https://www.analyticsinsight.net/artificial-intelligence/ai-job-market-trends-opportunities-and-key-skills-for-2025\" target=\"_blank\"><span style=\"color: #000080; text-decoration-color: #000080; text-decoration: underline\">Explore more on Analytics Insight</span></a>. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 3 </span><span style=\"font-weight: bold\">Global Impact</span>: The AI Jobs Barometer by PwC examines AI's global impact on jobs, wages, skills, and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>productivity, analyzing job ads from six continents. <a href=\"https://www.pwc.com/gx/en/issues/artificial-intelligence/job-barometer/aijb-2025-united-states-analysis.pdf\" target=\"_blank\"><span style=\"color: #000080; text-decoration-color: #000080; text-decoration: underline\">Check the PwC report</span></a>. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 4 </span><span style=\"font-weight: bold\">Future Workforce Trends</span>: AI will reshape jobs, leading to AI-driven displacement and the creation of new <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>roles. Understanding these trends and acquiring must-have skills will be crucial for thriving in the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>evolving workforce. <a href=\"https://www.cognitivetoday.com/2025/03/ai-job-market-impact-on-employment-future-workforce-trends/\" target=\"_blank\"><span style=\"color: #000080; text-decoration-color: #000080; text-decoration: underline\">Learn more on Cognitive Today</span></a>. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 5 </span><span style=\"font-weight: bold\">Hiring Data Insights</span>: Insights into the latest AI job trends, including top industries hiring and emerging <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>roles, can be found in various reports and analyses. <a href=\"https://blog.getaura.ai/ai-job-trends-2025\" target=\"_blank\"><span style=\"color: #000080; text-decoration-color: #000080; text-decoration: underline\">Read more on GetAura</span></a>. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> These resources provide a comprehensive overview of the anticipated changes and opportunities in the AI job <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> market by 2025. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Here are some insights into AI job trends for 2025: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 1 \u001b[0m\u001b[1mTop AI Jobs and Roles\u001b[0m: The AI job market in 2025 is expected to feature roles such as Machine Learning \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mEngineers, NLP Specialists, and other positions offering six-figure salaries. These roles are in high demand \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mas the tech landscape evolves. \u001b]8;id=1080;https://www.forbes.com/sites/bryanrobinson/2025/01/17/10-hottest-ai-jobs-of-2025-paying-six-figure-salaries/\u001b\\\u001b[4;34mRead more on Forbes\u001b[0m\u001b]8;;\u001b\\. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 2 \u001b[0m\u001b[1mIndustries and Skills\u001b[0m: AI is reshaping industries, with new opportunities emerging and certain skills \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mbecoming essential. Key areas include automation, machine learning, AI-driven healthcare, and edge \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mcomputing. \u001b]8;id=337875;https://www.analyticsinsight.net/artificial-intelligence/ai-job-market-trends-opportunities-and-key-skills-for-2025\u001b\\\u001b[4;34mExplore more on Analytics Insight\u001b[0m\u001b]8;;\u001b\\. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 3 \u001b[0m\u001b[1mGlobal Impact\u001b[0m: The AI Jobs Barometer by PwC examines AI's global impact on jobs, wages, skills, and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mproductivity, analyzing job ads from six continents. \u001b]8;id=455296;https://www.pwc.com/gx/en/issues/artificial-intelligence/job-barometer/aijb-2025-united-states-analysis.pdf\u001b\\\u001b[4;34mCheck the PwC report\u001b[0m\u001b]8;;\u001b\\. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 4 \u001b[0m\u001b[1mFuture Workforce Trends\u001b[0m: AI will reshape jobs, leading to AI-driven displacement and the creation of new \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mroles. Understanding these trends and acquiring must-have skills will be crucial for thriving in the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mevolving workforce. \u001b]8;id=772466;https://www.cognitivetoday.com/2025/03/ai-job-market-impact-on-employment-future-workforce-trends/\u001b\\\u001b[4;34mLearn more on Cognitive Today\u001b[0m\u001b]8;;\u001b\\. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 5 \u001b[0m\u001b[1mHiring Data Insights\u001b[0m: Insights into the latest AI job trends, including top industries hiring and emerging \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0mroles, can be found in various reports and analyses. \u001b]8;id=262366;https://blog.getaura.ai/ai-job-trends-2025\u001b\\\u001b[4;34mRead more on GetAura\u001b[0m\u001b]8;;\u001b\\. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m These resources provide a comprehensive overview of the anticipated changes and opportunities in the AI job \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m market by 2025. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Response:\n",
|
||||
"Here are some insights into AI job trends for 2025:\n",
|
||||
"\n",
|
||||
"1. **Top AI Jobs and Roles**: The AI job market in 2025 is expected to feature roles such as Machine Learning Engineers, NLP Specialists, and other positions offering six-figure salaries. These roles are in high demand as the tech landscape evolves. [Read more on Forbes](https://www.forbes.com/sites/bryanrobinson/2025/01/17/10-hottest-ai-jobs-of-2025-paying-six-figure-salaries/).\n",
|
||||
"\n",
|
||||
"2. **Industries and Skills**: AI is reshaping industries, with new opportunities emerging and certain skills becoming essential. Key areas include automation, machine learning, AI-driven healthcare, and edge computing. [Explore more on Analytics Insight](https://www.analyticsinsight.net/artificial-intelligence/ai-job-market-trends-opportunities-and-key-skills-for-2025).\n",
|
||||
"\n",
|
||||
"3. **Global Impact**: The AI Jobs Barometer by PwC examines AI's global impact on jobs, wages, skills, and productivity, analyzing job ads from six continents. [Check the PwC report](https://www.pwc.com/gx/en/issues/artificial-intelligence/job-barometer/aijb-2025-united-states-analysis.pdf).\n",
|
||||
"\n",
|
||||
"4. **Future Workforce Trends**: AI will reshape jobs, leading to AI-driven displacement and the creation of new roles. Understanding these trends and acquiring must-have skills will be crucial for thriving in the evolving workforce. [Learn more on Cognitive Today](https://www.cognitivetoday.com/2025/03/ai-job-market-impact-on-employment-future-workforce-trends/).\n",
|
||||
"\n",
|
||||
"5. **Hiring Data Insights**: Insights into the latest AI job trends, including top industries hiring and emerging roles, can be found in various reports and analyses. [Read more on GetAura](https://blog.getaura.ai/ai-job-trends-2025).\n",
|
||||
"\n",
|
||||
"These resources provide a comprehensive overview of the anticipated changes and opportunities in the AI job market by 2025.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from praisonaiagents import Agent\n",
|
||||
"\n",
|
||||
"agent = Agent(\n",
|
||||
" instructions=\"You are an AI assistant with internet search capabilities.\",\n",
|
||||
" tools=[internet_search_tool]\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Main: Ask a question\n",
|
||||
"query = 'AI job trends in 2025' # You can change this prompt\n",
|
||||
"response = agent.start(query)\n",
|
||||
"print('Response:')\n",
|
||||
"print(response)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "_T4g3t5sLoag"
|
||||
},
|
||||
"source": [
|
||||
"# ZeroScript: AI-Powered Browser Test Automation using PraisonAI Agent & OpenAI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "O4PKfpalLsmn"
|
||||
},
|
||||
"source": [
|
||||
"# Description"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "CEG1pfumLysm"
|
||||
},
|
||||
"source": [
|
||||
"AI-powered browser testing using PraisonAI Agent and OpenAI. Executes YAML-defined test cases, captures screenshots, logs interactions, and generates JSON reports. Ideal for intelligent, automated UI testing.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "lbgxOG4gL1Wf"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/ZeroScript_AI_TestExecutor.ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "WCJqMUzXIndh"
|
||||
},
|
||||
"source": [
|
||||
"# Dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"metadata": {
|
||||
"id": "9AQhJ59cJPmR"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install --quiet praisonaiagents browser-use python-dotenv pyyaml openai\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "QD-dF-6_It1z"
|
||||
},
|
||||
"source": [
|
||||
"# Environment Setup"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 35,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "QkRQDli4JhCV",
|
||||
"outputId": "4b8957ed-a37a-4b11-8585-3537a0437d40"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 35,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"Enter your key\" # replace with actual key\n",
|
||||
"load_dotenv()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ELuogWnrIw3o"
|
||||
},
|
||||
"source": [
|
||||
"# Create my_secrets.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 36,
|
||||
"metadata": {
|
||||
"id": "sG6tO_v0Jm5N"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"with open(\"my_secrets.py\", \"w\") as f:\n",
|
||||
" f.write('''sensitive_data = {\n",
|
||||
" \"username\": \"standard_user\",\n",
|
||||
" \"password\": \"secret_sauce\"\n",
|
||||
"}''')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "rDB_viedIzRR"
|
||||
},
|
||||
"source": [
|
||||
"# Create views.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"metadata": {
|
||||
"id": "CtwcybdbJoV8"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"with open(\"views.py\", \"w\") as f:\n",
|
||||
" f.write('''\n",
|
||||
"from pydantic import BaseModel\n",
|
||||
"\n",
|
||||
"class TestResult(BaseModel):\n",
|
||||
" status: str\n",
|
||||
" message: str = \"\"\n",
|
||||
"''')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "YTRmBpTiI1kd"
|
||||
},
|
||||
"source": [
|
||||
"# Create agent.py"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 38,
|
||||
"metadata": {
|
||||
"id": "zdJJGt6TJpvr"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"with open(\"agent.py\", \"w\") as f:\n",
|
||||
" f.write('''\n",
|
||||
"import os\n",
|
||||
"from praisonaiagents import Agent\n",
|
||||
"from browser_use import Browser, BrowserConfig, Controller\n",
|
||||
"from browser_use.browser.context import BrowserContext, BrowserContextConfig\n",
|
||||
"from openai import OpenAI\n",
|
||||
"from views import TestResult\n",
|
||||
"from my_secrets import sensitive_data\n",
|
||||
"\n",
|
||||
"# Browser setup\n",
|
||||
"browser = Browser(config=BrowserConfig(headless=True))\n",
|
||||
"context_cfg = BrowserContextConfig(save_recording_path=\"data/recordings\")\n",
|
||||
"controller = Controller(output_model=TestResult)\n",
|
||||
"\n",
|
||||
"async def browser_use(task: str):\n",
|
||||
" context = BrowserContext(browser=browser, config=context_cfg)\n",
|
||||
" agent = Agent(\n",
|
||||
" task=task,\n",
|
||||
" llm=OpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"), model=\"gpt-4\"),\n",
|
||||
" browser_context=context,\n",
|
||||
" sensitive_data=sensitive_data,\n",
|
||||
" controller=controller,\n",
|
||||
" save_conversation_path=\"data/conversations/convo\",\n",
|
||||
" extend_system_message=(\n",
|
||||
" \"You are a professional software tester. Execute browser test steps precisely.\"\n",
|
||||
" )\n",
|
||||
" )\n",
|
||||
" response = await agent.run()\n",
|
||||
" await context.close()\n",
|
||||
" return response\n",
|
||||
"''')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "-LZtQIE3I4-_"
|
||||
},
|
||||
"source": [
|
||||
"# Create Sample Test YAML"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 39,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "l1OdXYI-JreK",
|
||||
"outputId": "62323fcd-c74f-498f-defc-2c170fa8983e"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"350"
|
||||
]
|
||||
},
|
||||
"execution_count": 39,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from pathlib import Path\n",
|
||||
"tests_dir = Path(\"tests\")\n",
|
||||
"tests_dir.mkdir(exist_ok=True)\n",
|
||||
"yaml_content = \"\"\"\n",
|
||||
"hooks:\n",
|
||||
" beforeEach: |\n",
|
||||
" Navigate to https://www.saucedemo.com\n",
|
||||
" afterEach: |\n",
|
||||
" Take screenshot\n",
|
||||
"\n",
|
||||
"tests:\n",
|
||||
" - id: \"login_test_001\"\n",
|
||||
" name: \"Valid Login Test\"\n",
|
||||
" instructions: |\n",
|
||||
" 1. Enter standard_user in username field\n",
|
||||
" 2. Enter secret_sauce in password field\n",
|
||||
" 3. Click login button\n",
|
||||
" 4. Verify page contains text \"Products\"\n",
|
||||
"\"\"\"\n",
|
||||
"(Path(\"tests/login_test.yml\")).write_text(yaml_content)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "sUjy-7OdI7p_"
|
||||
},
|
||||
"source": [
|
||||
"# Run Tests"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 40,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "Agkiwh7xJtY3",
|
||||
"outputId": "759aa77c-fd65-49b8-b239-550588059478"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Exception ignored in: <function BrowserSession.__del__ at 0x7e2f540fb100>\n",
|
||||
"Traceback (most recent call last):\n",
|
||||
" File \"/usr/local/lib/python3.11/dist-packages/browser_use/browser/session.py\", line 497, in __del__\n",
|
||||
" status = f'🪓 killing pid={self.browser_pid}...' if (self.browser_pid and owns_browser) else '☠️'\n",
|
||||
" ^^^^^^^^^^^^^^^^\n",
|
||||
" File \"/usr/local/lib/python3.11/dist-packages/pydantic/main.py\", line 991, in __getattr__\n",
|
||||
" raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')\n",
|
||||
"AttributeError: 'BrowserSession' object has no attribute 'browser_pid'\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"✅ Report saved to data/reports/report_20250630_092319.json\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import asyncio, yaml, json, base64, shutil\n",
|
||||
"from agent import browser_use, browser\n",
|
||||
"from pathlib import Path\n",
|
||||
"from datetime import datetime\n",
|
||||
"\n",
|
||||
"# Clean or create data dirs\n",
|
||||
"for sub in [\"recordings\", \"conversations\", \"screenshots\", \"reports\"]:\n",
|
||||
" d = Path(\"data\") / sub\n",
|
||||
" if d.exists(): shutil.rmtree(d)\n",
|
||||
" d.mkdir(parents=True, exist_ok=True)\n",
|
||||
"\n",
|
||||
"async def execute_test_file(path):\n",
|
||||
" cfg = yaml.safe_load(Path(path).read_text())\n",
|
||||
" hooks, results = cfg.get(\"hooks\", {}), []\n",
|
||||
" for t in cfg[\"tests\"]:\n",
|
||||
" task = f\"{hooks.get('beforeEach','')}\\n{t['instructions']}\\n{hooks.get('afterEach','')}\"\n",
|
||||
" res = {\"id\": t[\"id\"], \"name\": t[\"name\"]}\n",
|
||||
" try:\n",
|
||||
" r = await browser_use(task)\n",
|
||||
" imgs = r.screenshots()\n",
|
||||
" if imgs:\n",
|
||||
" out = Path(\"data/screenshots\") / f\"{t['id']}.png\"\n",
|
||||
" out.write_bytes(base64.b64decode(imgs[-1]))\n",
|
||||
" result_obj = r.final_result() if hasattr(r, \"final_result\") else str(r)\n",
|
||||
" res[\"result\"] = result_obj.dict() if hasattr(result_obj, \"dict\") else str(result_obj)\n",
|
||||
" except Exception as e:\n",
|
||||
" res[\"error\"] = str(e)\n",
|
||||
" results.append(res)\n",
|
||||
" return results\n",
|
||||
"\n",
|
||||
"async def main():\n",
|
||||
" all_results = []\n",
|
||||
" for file in Path(\"tests\").glob(\"*.yml\"):\n",
|
||||
" all_results.extend(await execute_test_file(str(file)))\n",
|
||||
" report = Path(\"data/reports\") / f\"report_{datetime.now():%Y%m%d_%H%M%S}.json\"\n",
|
||||
" report.write_text(json.dumps(all_results, indent=2))\n",
|
||||
" await browser.close()\n",
|
||||
" print(f\"✅ Report saved to {report}\")\n",
|
||||
"\n",
|
||||
"await main()\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,743 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "l3kzG83yPRHX"
|
||||
},
|
||||
"source": [
|
||||
"# AI Code Generation System: Multi-Agent Programming Assistant with PraisonAI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BozAlx2dPS3Y"
|
||||
},
|
||||
"source": [
|
||||
"An intelligent code generation system that creates specialized programming code from natural language descriptions. Features multiple AI agents for code generation, debugging, validation, and updates. Built with PraisonAI framework, it demonstrates advanced multi-agent collaboration for software development workflows. Perfect for rapid prototyping, educational content creation, and automated code generation across various programming domains."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "I9UqNin7PanL"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/DhivyaBharathy-web/PraisonAI/blob/main/examples/cookbooks/intelligent_programming_agent.ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "trQTNYiHO1mi",
|
||||
"outputId": "913e1419-c8de-49e4-d2ef-e02c0f0bea2c"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"📦 Dependencies installed successfully!\n",
|
||||
"🎬 Manim Code Generator ready!\n",
|
||||
"🤖 Using PraisonAI Multi-Agent Framework\n",
|
||||
"💡 Note: This generates Manim code only (no video rendering)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# @title **📦 Install Dependencies**\n",
|
||||
"\n",
|
||||
"# Install only essential packages\n",
|
||||
"!pip install praisonaiagents -q\n",
|
||||
"!pip install openai -q\n",
|
||||
"!pip install python-dotenv -q\n",
|
||||
"\n",
|
||||
"# Basic imports\n",
|
||||
"import os\n",
|
||||
"import json\n",
|
||||
"import tempfile\n",
|
||||
"import shutil\n",
|
||||
"import logging\n",
|
||||
"import subprocess\n",
|
||||
"import re\n",
|
||||
"from pathlib import Path\n",
|
||||
"from typing import Dict, List, Optional, Any, Tuple\n",
|
||||
"from datetime import datetime\n",
|
||||
"import getpass\n",
|
||||
"\n",
|
||||
"print(\"📦 Dependencies installed successfully!\")\n",
|
||||
"print(\"🎬 Manim Code Generator ready!\")\n",
|
||||
"print(\"🤖 Using PraisonAI Multi-Agent Framework\")\n",
|
||||
"print(\"💡 Note: This generates Manim code only (no video rendering)\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "bL_IuGP4O7Ua",
|
||||
"outputId": "24095118-2a75-4814-af3c-13b2245331b1"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"🔑 OpenAI API Key Setup\n",
|
||||
"Enter your OpenAI API key:\n",
|
||||
"OpenAI API Key: ··········\n",
|
||||
"✅ API key configured!\n",
|
||||
"🚀 Ready to generate Manim code!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# @title ** Set OpenAI API Key**\n",
|
||||
"\n",
|
||||
"# Set up API key\n",
|
||||
"print(\"🔑 OpenAI API Key Setup\")\n",
|
||||
"print(\"Enter your OpenAI API key:\")\n",
|
||||
"\n",
|
||||
"api_key = getpass.getpass(\"OpenAI API Key: \")\n",
|
||||
"\n",
|
||||
"if not api_key or api_key.strip() == \"\":\n",
|
||||
" print(\"⚠️ No API key provided. Using demo mode with mock responses.\")\n",
|
||||
" api_key = \"demo-key\"\n",
|
||||
"\n",
|
||||
"# Set environment variable\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = api_key\n",
|
||||
"\n",
|
||||
"print(\"✅ API key configured!\")\n",
|
||||
"print(\"🚀 Ready to generate Manim code!\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "fe0hQYhRO_VJ",
|
||||
"outputId": "5ed3217a-d505-4795-c94b-c0e96d04f7e4"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"✅ Custom Manim code tools initialized!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# @title **️ Custom Code Tools**\n",
|
||||
"\n",
|
||||
"class ManimCodeTools:\n",
|
||||
" \"\"\"Custom tools for Manim code generation and validation\"\"\"\n",
|
||||
"\n",
|
||||
" @staticmethod\n",
|
||||
" def clean_manim_code(code: str) -> str:\n",
|
||||
" \"\"\"Clean and format Manim code\"\"\"\n",
|
||||
" # Remove markdown code blocks if present\n",
|
||||
" if \"```python\" in code:\n",
|
||||
" code = code.split(\"```python\")[1]\n",
|
||||
" if \"```\" in code:\n",
|
||||
" code = code.split(\"```\")[0]\n",
|
||||
"\n",
|
||||
" # Clean up extra whitespace\n",
|
||||
" code = code.strip()\n",
|
||||
" return code\n",
|
||||
"\n",
|
||||
" @staticmethod\n",
|
||||
" def extract_scene_class_name(code: str) -> str:\n",
|
||||
" \"\"\"Extract scene class name from Manim code\"\"\"\n",
|
||||
" # Look for class definitions that inherit from Scene\n",
|
||||
" pattern = r'class\\s+(\\w+)\\s*\\(.*Scene.*\\):'\n",
|
||||
" match = re.search(pattern, code)\n",
|
||||
" if match:\n",
|
||||
" return match.group(1)\n",
|
||||
"\n",
|
||||
" # Fallback: look for any class definition\n",
|
||||
" pattern = r'class\\s+(\\w+)\\s*:'\n",
|
||||
" match = re.search(pattern, code)\n",
|
||||
" if match:\n",
|
||||
" return match.group(1)\n",
|
||||
"\n",
|
||||
" return \"\"\n",
|
||||
"\n",
|
||||
" @staticmethod\n",
|
||||
" def validate_python_syntax(code: str) -> Tuple[bool, str]:\n",
|
||||
" \"\"\"Validate Python syntax without executing\"\"\"\n",
|
||||
" try:\n",
|
||||
" compile(code, '<string>', 'exec')\n",
|
||||
" return True, \"Syntax is valid\"\n",
|
||||
" except SyntaxError as e:\n",
|
||||
" return False, f\"Syntax error: {str(e)}\"\n",
|
||||
" except Exception as e:\n",
|
||||
" return False, f\"Validation error: {str(e)}\"\n",
|
||||
"\n",
|
||||
" @staticmethod\n",
|
||||
" def check_manim_imports(code: str) -> Tuple[bool, str]:\n",
|
||||
" \"\"\"Check if Manim imports are present\"\"\"\n",
|
||||
" required_imports = ['from manim import', 'import manim']\n",
|
||||
" found_imports = []\n",
|
||||
"\n",
|
||||
" for import_line in required_imports:\n",
|
||||
" if import_line in code:\n",
|
||||
" found_imports.append(import_line)\n",
|
||||
"\n",
|
||||
" if found_imports:\n",
|
||||
" return True, f\"Found Manim imports: {', '.join(found_imports)}\"\n",
|
||||
" else:\n",
|
||||
" return False, \"No Manim imports found\"\n",
|
||||
"\n",
|
||||
" @staticmethod\n",
|
||||
" def check_scene_class(code: str) -> Tuple[bool, str]:\n",
|
||||
" \"\"\"Check if Scene class is properly defined\"\"\"\n",
|
||||
" scene_pattern = r'class\\s+\\w+\\s*\\(.*Scene.*\\):'\n",
|
||||
" if re.search(scene_pattern, code):\n",
|
||||
" return True, \"Scene class found\"\n",
|
||||
" else:\n",
|
||||
" return False, \"No Scene class found\"\n",
|
||||
"\n",
|
||||
" @staticmethod\n",
|
||||
" def generate_code_summary(code: str) -> Dict[str, Any]:\n",
|
||||
" \"\"\"Generate a summary of the code\"\"\"\n",
|
||||
" scene_name = ManimCodeTools.extract_scene_class_name(code)\n",
|
||||
" syntax_valid, syntax_msg = ManimCodeTools.validate_python_syntax(code)\n",
|
||||
" imports_ok, imports_msg = ManimCodeTools.check_manim_imports(code)\n",
|
||||
" scene_ok, scene_msg = ManimCodeTools.check_scene_class(code)\n",
|
||||
"\n",
|
||||
" return {\n",
|
||||
" \"scene_name\": scene_name,\n",
|
||||
" \"syntax_valid\": syntax_valid,\n",
|
||||
" \"syntax_message\": syntax_msg,\n",
|
||||
" \"imports_ok\": imports_ok,\n",
|
||||
" \"imports_message\": imports_msg,\n",
|
||||
" \"scene_ok\": scene_ok,\n",
|
||||
" \"scene_message\": scene_msg,\n",
|
||||
" \"code_length\": len(code),\n",
|
||||
" \"lines\": len(code.split('\\n'))\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Initialize tools\n",
|
||||
"manim_tools = ManimCodeTools()\n",
|
||||
"print(\"✅ Custom Manim code tools initialized!\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000,
|
||||
"referenced_widgets": [
|
||||
"5a67a4a41d0d48d3870a3c1eb967493b",
|
||||
"f748833f06464214a9d4e7cf0cec7a68"
|
||||
]
|
||||
},
|
||||
"id": "zsrklVrjPCFU",
|
||||
"outputId": "6327299f-416a-4f68-8b13-a9813e6528ad"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" AI Manim Code Generator Ready!\n",
|
||||
"============================================================\n",
|
||||
"🚀 Demo: Generating Manim code...\n",
|
||||
"🎬 Generating Manim code for: 'Create an animation showing a circle moving in a sine wave pattern'\n",
|
||||
"============================================================\n",
|
||||
"�� Step 1: Generating Manim code...\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Manim Code Generator</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Complete Manim Animation Specialist</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mManim Code Generator\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mComplete Manim Animation Specialist\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "5a67a4a41d0d48d3870a3c1eb967493b",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 7.6s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 7.6s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> You need to do the following task: Generate high-quality Manim code for this animation request: Create an <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> animation showing a circle moving in a sine wave pattern <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> Requirements:</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Create a class that inherits from Scene</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Include proper imports (from manim import *)</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Use descriptive class names</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Include a construct method with self.play() calls</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Add comments for clarity</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Ensure code is complete and runnable</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Follow Manim best practices</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Handle mathematical concepts properly</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> - Use appropriate animation timing</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> .</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Expected Output: Complete the task successfully. Please provide only the final result of your work. Do not add <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> any conversation or extra explanation. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m You need to do the following task: Generate high-quality Manim code for this animation request: Create an \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m animation showing a circle moving in a sine wave pattern \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m Requirements:\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Create a class that inherits from Scene\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Include proper imports (from manim import *)\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Use descriptive class names\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Include a construct method with self.play() calls\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Add comments for clarity\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Ensure code is complete and runnable\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Follow Manim best practices\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Handle mathematical concepts properly\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m - Use appropriate animation timing\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m .\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Expected Output: Complete the task successfully. Please provide only the final result of your work. Do not add \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m any conversation or extra explanation. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">from</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> manim </span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">import</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">*</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #66d9ef; text-decoration-color: #66d9ef; background-color: #272822\">class</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #a6e22e; text-decoration-color: #a6e22e; background-color: #272822\">CircleSineWave</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">(Scene):</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #66d9ef; text-decoration-color: #66d9ef; background-color: #272822\">def</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #a6e22e; text-decoration-color: #a6e22e; background-color: #272822\">construct</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">(self):</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #959077; text-decoration-color: #959077; background-color: #272822\"># Create a circle</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> circle </span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> Circle(radius</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #ae81ff; text-decoration-color: #ae81ff; background-color: #272822\">0.2</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">, color</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">BLUE)</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #959077; text-decoration-color: #959077; background-color: #272822\"># Define the sine wave path</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> sine_wave_path </span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> ParametricFunction(</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #66d9ef; text-decoration-color: #66d9ef; background-color: #272822\">lambda</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> t: np</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">.</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">array([t, np</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">.</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">sin(t), </span><span style=\"color: #ae81ff; text-decoration-color: #ae81ff; background-color: #272822\">0</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">]),</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> t_range</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">np</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">.</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">array([</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">-</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">PI, PI, </span><span style=\"color: #ae81ff; text-decoration-color: #ae81ff; background-color: #272822\">0.01</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">]),</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> color</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">YELLOW</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> )</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #959077; text-decoration-color: #959077; background-color: #272822\"># Add the sine wave path to the scene</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> self</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">.</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">add(sine_wave_path)</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #959077; text-decoration-color: #959077; background-color: #272822\"># Animate the circle moving along the sine wave path</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> self</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">.</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">play(</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> MoveAlongPath(circle, sine_wave_path, rate_func</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">linear),</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> run_time</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">=</span><span style=\"color: #ae81ff; text-decoration-color: #ae81ff; background-color: #272822\">4</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> )</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> </span><span style=\"color: #959077; text-decoration-color: #959077; background-color: #272822\"># Hold the final position for a moment</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\"> self</span><span style=\"color: #ff4689; text-decoration-color: #ff4689; background-color: #272822\">.</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">wait(</span><span style=\"color: #ae81ff; text-decoration-color: #ae81ff; background-color: #272822\">1</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">)</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34mfrom\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mmanim\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34mimport\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m*\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;102;217;239;48;2;39;40;34mclass\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;166;226;46;48;2;39;40;34mCircleSineWave\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mScene\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m:\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;102;217;239;48;2;39;40;34mdef\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;166;226;46;48;2;39;40;34mconstruct\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mself\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m:\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;149;144;119;48;2;39;40;34m# Create a circle\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mcircle\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mCircle\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mradius\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;174;129;255;48;2;39;40;34m0.2\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mcolor\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mBLUE\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;149;144;119;48;2;39;40;34m# Define the sine wave path\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34msine_wave_path\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mParametricFunction\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;102;217;239;48;2;39;40;34mlambda\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mt\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m:\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mnp\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m.\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34marray\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m[\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mt\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mnp\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m.\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34msin\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mt\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;174;129;255;48;2;39;40;34m0\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m]\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mt_range\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mnp\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m.\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34marray\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m[\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m-\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mPI\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mPI\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;174;129;255;48;2;39;40;34m0.01\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m]\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mcolor\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mYELLOW\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;149;144;119;48;2;39;40;34m# Add the sine wave path to the scene\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mself\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m.\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34madd\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34msine_wave_path\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;149;144;119;48;2;39;40;34m# Animate the circle moving along the sine wave path\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mself\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m.\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mplay\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mMoveAlongPath\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mcircle\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34msine_wave_path\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mrate_func\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mlinear\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m,\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mrun_time\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m=\u001b[0m\u001b[38;2;174;129;255;48;2;39;40;34m4\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;149;144;119;48;2;39;40;34m# Hold the final position for a moment\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mself\u001b[0m\u001b[38;2;255;70;137;48;2;39;40;34m.\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mwait\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m(\u001b[0m\u001b[38;2;174;129;255;48;2;39;40;34m1\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m)\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"✅ Generated code: from manim import *\n",
|
||||
"\n",
|
||||
"class CircleSineWave(Scene):\n",
|
||||
" def construct(self):\n",
|
||||
" # Create a circle\n",
|
||||
" circle = Circle(radius=0.2, color=BLUE)\n",
|
||||
" \n",
|
||||
" # Define the sine wave path\n",
|
||||
" ...\n",
|
||||
" Step 2: Validating generated code...\n",
|
||||
"📝 Code Summary:\n",
|
||||
" - Scene Name: CircleSineWave\n",
|
||||
" - Syntax Valid: True\n",
|
||||
" - Manim Imports: True\n",
|
||||
" - Scene Class: True\n",
|
||||
" - Code Length: 727 characters\n",
|
||||
" - Lines: 25\n",
|
||||
"\n",
|
||||
" Generated Code:\n",
|
||||
"========================================\n",
|
||||
"from manim import *\n",
|
||||
"\n",
|
||||
"class CircleSineWave(Scene):\n",
|
||||
" def construct(self):\n",
|
||||
" # Create a circle\n",
|
||||
" circle = Circle(radius=0.2, color=BLUE)\n",
|
||||
" \n",
|
||||
" # Define the sine wave path\n",
|
||||
" sine_wave_path = ParametricFunction(\n",
|
||||
" lambda t: np.array([t, np.sin(t), 0]),\n",
|
||||
" t_range=np.array([-PI, PI, 0.01]),\n",
|
||||
" color=YELLOW\n",
|
||||
" )\n",
|
||||
" \n",
|
||||
" # Add the sine wave path to the scene\n",
|
||||
" self.add(sine_wave_path)\n",
|
||||
" \n",
|
||||
" # Animate the circle moving along the sine wave path\n",
|
||||
" self.play(\n",
|
||||
" MoveAlongPath(circle, sine_wave_path, rate_func=linear),\n",
|
||||
" run_time=4\n",
|
||||
" )\n",
|
||||
" \n",
|
||||
" # Hold the final position for a moment\n",
|
||||
" self.wait(1)\n",
|
||||
"========================================\n",
|
||||
"\n",
|
||||
"✅ Code generation complete!\n",
|
||||
"🎬 Scene name: CircleSineWave\n",
|
||||
"📊 Code quality: 25 lines, 727 characters\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# @title **🚀 Execute Code Generation (FINAL WORKING VERSION)**\n",
|
||||
"\n",
|
||||
"# Import PraisonAI after setting API key\n",
|
||||
"from praisonaiagents import Agent, Task, PraisonAIAgents\n",
|
||||
"\n",
|
||||
"def generate_manim_code(query: str):\n",
|
||||
" \"\"\"Generate Manim code from user query using PraisonAI\"\"\"\n",
|
||||
" print(f\"🎬 Generating Manim code for: '{query}'\")\n",
|
||||
" print(\"=\" * 60)\n",
|
||||
"\n",
|
||||
" # Create agents\n",
|
||||
" manim_agent = Agent(\n",
|
||||
" name=\"Manim Code Generator\",\n",
|
||||
" role=\"Complete Manim Animation Specialist\",\n",
|
||||
" goal=\"Generate high-quality, working Manim code from natural language descriptions\",\n",
|
||||
" backstory=\"Expert Manim developer with deep knowledge of mathematical animations, code generation, debugging, and educational content creation\",\n",
|
||||
" verbose=True,\n",
|
||||
" allow_delegation=False,\n",
|
||||
" tools=[]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" debugger_agent = Agent(\n",
|
||||
" name=\"Code Debugger\",\n",
|
||||
" role=\"Manim Code Debugger\",\n",
|
||||
" goal=\"Fix errors in Manim code and ensure successful execution\",\n",
|
||||
" backstory=\"Expert in debugging Manim animations and resolving technical issues in mathematical visualization code\",\n",
|
||||
" verbose=True,\n",
|
||||
" allow_delegation=False,\n",
|
||||
" tools=[]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Create tasks\n",
|
||||
" code_generation_task = Task(\n",
|
||||
" description=f\"\"\"\n",
|
||||
" Generate high-quality Manim code for this animation request: {query}\n",
|
||||
"\n",
|
||||
" Requirements:\n",
|
||||
" - Create a class that inherits from Scene\n",
|
||||
" - Include proper imports (from manim import *)\n",
|
||||
" - Use descriptive class names\n",
|
||||
" - Include a construct method with self.play() calls\n",
|
||||
" - Add comments for clarity\n",
|
||||
" - Ensure code is complete and runnable\n",
|
||||
" - Follow Manim best practices\n",
|
||||
" - Handle mathematical concepts properly\n",
|
||||
" - Use appropriate animation timing\n",
|
||||
" \"\"\",\n",
|
||||
" agent=manim_agent\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Step 1: Generate code\n",
|
||||
" print(\"�� Step 1: Generating Manim code...\")\n",
|
||||
"\n",
|
||||
" # Use PraisonAIAgents to execute the task\n",
|
||||
" agents_system = PraisonAIAgents(\n",
|
||||
" agents=[manim_agent],\n",
|
||||
" tasks=[code_generation_task],\n",
|
||||
" verbose=True,\n",
|
||||
" process=\"sequential\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" result = agents_system.start()\n",
|
||||
" manim_code = manim_tools.clean_manim_code(result)\n",
|
||||
" print(f\"✅ Generated code: {manim_code[:200]}...\")\n",
|
||||
"\n",
|
||||
" # Step 2: Validate code\n",
|
||||
" print(\" Step 2: Validating generated code...\")\n",
|
||||
" code_summary = manim_tools.generate_code_summary(manim_code)\n",
|
||||
"\n",
|
||||
" print(f\"📝 Code Summary:\")\n",
|
||||
" print(f\" - Scene Name: {code_summary['scene_name']}\")\n",
|
||||
" print(f\" - Syntax Valid: {code_summary['syntax_valid']}\")\n",
|
||||
" print(f\" - Manim Imports: {code_summary['imports_ok']}\")\n",
|
||||
" print(f\" - Scene Class: {code_summary['scene_ok']}\")\n",
|
||||
" print(f\" - Code Length: {code_summary['code_length']} characters\")\n",
|
||||
" print(f\" - Lines: {code_summary['lines']}\")\n",
|
||||
"\n",
|
||||
" # Step 3: Debug if needed\n",
|
||||
" if not code_summary['syntax_valid'] or not code_summary['imports_ok'] or not code_summary['scene_ok']:\n",
|
||||
" print(\"🐛 Step 3: Fixing code issues...\")\n",
|
||||
" issues = []\n",
|
||||
" if not code_summary['syntax_valid']:\n",
|
||||
" issues.append(code_summary['syntax_message'])\n",
|
||||
" if not code_summary['imports_ok']:\n",
|
||||
" issues.append(code_summary['imports_message'])\n",
|
||||
" if not code_summary['scene_ok']:\n",
|
||||
" issues.append(code_summary['scene_message'])\n",
|
||||
"\n",
|
||||
" error_msg = \"; \".join(issues)\n",
|
||||
"\n",
|
||||
" debug_task = Task(\n",
|
||||
" description=f\"\"\"\n",
|
||||
" Fix these issues in the Manim code:\n",
|
||||
"\n",
|
||||
" Code: {manim_code}\n",
|
||||
" Errors: {error_msg}\n",
|
||||
"\n",
|
||||
" Provide corrected Manim code that:\n",
|
||||
" - Fixes all syntax errors\n",
|
||||
" - Includes proper Manim imports\n",
|
||||
" - Has a valid Scene class\n",
|
||||
" - Maintains the original animation intent\n",
|
||||
" - Is complete and runnable\n",
|
||||
" \"\"\",\n",
|
||||
" agent=debugger_agent\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" debug_system = PraisonAIAgents(\n",
|
||||
" agents=[debugger_agent],\n",
|
||||
" tasks=[debug_task],\n",
|
||||
" verbose=True,\n",
|
||||
" process=\"sequential\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" debug_result = debug_system.start()\n",
|
||||
" manim_code = manim_tools.clean_manim_code(debug_result)\n",
|
||||
"\n",
|
||||
" # Re-validate\n",
|
||||
" code_summary = manim_tools.generate_code_summary(manim_code)\n",
|
||||
" print(f\"✅ Debug completed! Code is now valid.\")\n",
|
||||
"\n",
|
||||
" return {\n",
|
||||
" \"manim_code\": manim_code,\n",
|
||||
" \"code_summary\": code_summary,\n",
|
||||
" \"scene_name\": code_summary['scene_name']\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"def update_manim_code(query: str, existing_code: str):\n",
|
||||
" \"\"\"Update existing Manim code with new requirements\"\"\"\n",
|
||||
" print(f\" Updating Manim code: '{query}'\")\n",
|
||||
" print(\"=\" * 60)\n",
|
||||
"\n",
|
||||
" # Create updater agent\n",
|
||||
" updater_agent = Agent(\n",
|
||||
" name=\"Code Updater\",\n",
|
||||
" role=\"Manim Code Updater\",\n",
|
||||
" goal=\"Modify existing Manim animations based on new requirements\",\n",
|
||||
" backstory=\"Specialist in updating and enhancing existing Manim animations while maintaining code quality and functionality\",\n",
|
||||
" verbose=True,\n",
|
||||
" allow_delegation=False,\n",
|
||||
" tools=[]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Create update task\n",
|
||||
" update_task = Task(\n",
|
||||
" description=f\"\"\"\n",
|
||||
" Update this Manim code based on the request:\n",
|
||||
"\n",
|
||||
" Original Code: {existing_code}\n",
|
||||
" Update Request: {query}\n",
|
||||
"\n",
|
||||
" Provide updated Manim code that:\n",
|
||||
" - Maintains the original structure\n",
|
||||
" - Applies the requested changes\n",
|
||||
" - Keeps the same Scene class\n",
|
||||
" - Ensures code remains runnable\n",
|
||||
" - Preserves existing functionality\n",
|
||||
" \"\"\",\n",
|
||||
" agent=updater_agent\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Execute update\n",
|
||||
" print(\"💻 Updating Manim code...\")\n",
|
||||
"\n",
|
||||
" update_system = PraisonAIAgents(\n",
|
||||
" agents=[updater_agent],\n",
|
||||
" tasks=[update_task],\n",
|
||||
" verbose=True,\n",
|
||||
" process=\"sequential\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" updated_result = update_system.start()\n",
|
||||
" updated_code = manim_tools.clean_manim_code(updated_result)\n",
|
||||
"\n",
|
||||
" # Validate updated code\n",
|
||||
" print(\" Validating updated code...\")\n",
|
||||
" code_summary = manim_tools.generate_code_summary(updated_code)\n",
|
||||
"\n",
|
||||
" print(f\"📝 Updated Code Summary:\")\n",
|
||||
" print(f\" - Scene Name: {code_summary['scene_name']}\")\n",
|
||||
" print(f\" - Syntax Valid: {code_summary['syntax_valid']}\")\n",
|
||||
" print(f\" - Manim Imports: {code_summary['imports_ok']}\")\n",
|
||||
" print(f\" - Scene Class: {code_summary['scene_ok']}\")\n",
|
||||
"\n",
|
||||
" return {\n",
|
||||
" \"manim_code\": updated_code,\n",
|
||||
" \"code_summary\": code_summary,\n",
|
||||
" \"scene_name\": code_summary['scene_name']\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Demo execution\n",
|
||||
"print(\" AI Manim Code Generator Ready!\")\n",
|
||||
"print(\"=\" * 60)\n",
|
||||
"\n",
|
||||
"# Example usage\n",
|
||||
"demo_query = \"Create an animation showing a circle moving in a sine wave pattern\"\n",
|
||||
"\n",
|
||||
"print(\"🚀 Demo: Generating Manim code...\")\n",
|
||||
"result = generate_manim_code(demo_query)\n",
|
||||
"\n",
|
||||
"print(\"\\n Generated Code:\")\n",
|
||||
"print(\"=\" * 40)\n",
|
||||
"print(result['manim_code'])\n",
|
||||
"print(\"=\" * 40)\n",
|
||||
"\n",
|
||||
"print(f\"\\n✅ Code generation complete!\")\n",
|
||||
"print(f\"🎬 Scene name: {result['scene_name']}\")\n",
|
||||
"print(f\"📊 Code quality: {result['code_summary']['lines']} lines, {result['code_summary']['code_length']} characters\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,774 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "E5vgaurA6rjL"
|
||||
},
|
||||
"source": [
|
||||
"# 🖥️ Universal Desktop Utility Agents (PraisonAI Agents)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "XlS85r0d6s93"
|
||||
},
|
||||
"source": [
|
||||
"This notebook demonstrates a set of desktop utility agents using PraisonAI Agents. The agents can execute terminal commands, summarize files, and perform general-purpose search and summarization tasks. Custom tools are provided for OS detection, folder location, and running platform-specific commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "hrOaiAK_9vtl"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/Dhivya-Bharathy/PraisonAI/blob/main/examples/cookbooks/universal_desktop_agents..ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "V1engZ4W9f0H"
|
||||
},
|
||||
"source": [
|
||||
"# Dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"id": "cLNbcVbD9NKB"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install praisonaiagents openai --quiet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "dtUWxbdz9izh"
|
||||
},
|
||||
"source": [
|
||||
"# Set Up API Key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"id": "wjTwTRSo9Pir"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"Enter your api key\" # <-- Replace with your actual OpenAI API key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "1EAWunl79oF4"
|
||||
},
|
||||
"source": [
|
||||
"# Tools (Imports)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"id": "eWeuVSDg9U8F"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from praisonaiagents import Agent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "qONZuK0A9qj1"
|
||||
},
|
||||
"source": [
|
||||
"# YAML Prompt (Role, Goal, Instructions)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"metadata": {
|
||||
"id": "HNZSMlTp9WjF"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Terminal Agent\n",
|
||||
"TERMINAL_ROLE = (\n",
|
||||
" \"You are a smart and proactive terminal agent designed to execute shell commands based on natural language prompts.\"\n",
|
||||
")\n",
|
||||
"TERMINAL_GOAL = (\n",
|
||||
" \"Explain how to execute user commands, resolve folder paths, and adapt to the user's operating system.\"\n",
|
||||
")\n",
|
||||
"TERMINAL_INSTRUCTIONS = (\n",
|
||||
" \"- If the command involves a known system directory (e.g., Documents, Desktop), explain how to resolve its path.\\n\"\n",
|
||||
" \"- If you do not know the OS, explain how to detect it.\\n\"\n",
|
||||
" \"- On macOS/Linux, explain how to use the terminal. On Windows, explain how to use Command Prompt or PowerShell.\\n\"\n",
|
||||
" \"- Prepend 'yes |' to commands that may prompt for confirmation.\\n\"\n",
|
||||
" \"- Never hardcode OS-specific commands until you know the platform.\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# File Summarize Agent\n",
|
||||
"FILE_ROLE = (\n",
|
||||
" \"You are FileSummarizeAgent, an intelligent assistant that processes and summarizes various types of files.\"\n",
|
||||
")\n",
|
||||
"FILE_GOAL = (\n",
|
||||
" \"Explain how to extract meaningful information and present it in an organized and user-friendly format.\"\n",
|
||||
")\n",
|
||||
"FILE_INSTRUCTIONS = (\n",
|
||||
" \"Describe how to summarize the file's purpose, content, and structure. For code, explain architecture and modules. For documents, highlight structure and key ideas.\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# General Purpose Agent\n",
|
||||
"GENERAL_ROLE = (\n",
|
||||
" \"You are an intelligent assistant embedded in a search interface.\"\n",
|
||||
")\n",
|
||||
"GENERAL_GOAL = (\n",
|
||||
" \"Help with searches, summarize information, define words, and write small code snippets.\"\n",
|
||||
")\n",
|
||||
"GENERAL_INSTRUCTIONS = (\n",
|
||||
" \"Keep all responses brief and focused. For web queries, explain how to search online.\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "57397P3b9tzq"
|
||||
},
|
||||
"source": [
|
||||
"# Main (Agent Setup & Example)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000,
|
||||
"referenced_widgets": [
|
||||
"fe56c8b8fbe84f5b948495de5bd9869c",
|
||||
"c245a4d56ce44c8dbe90d87c981f7fe9",
|
||||
"a9a7af0c281c4a8787d6cfe66dca0244",
|
||||
"98c0f7750c3b4eb5af428d16ee6f28c5",
|
||||
"b782f03372b44eab96597bde5522fcd2",
|
||||
"ec3c0a539dfc435787b6ecd7ed9129bf"
|
||||
]
|
||||
},
|
||||
"id": "K4hnUl5l9Yiv",
|
||||
"outputId": "d6355fc8-fafa-4db4-f7f8-9bfe1112bff7"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">You are a smart and proactive terminal agent designed to execute shell commands based on natural </span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">language prompts.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mYou are a smart and proactive terminal agent designed to execute shell commands based on natural \u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229mlanguage prompts.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "fe56c8b8fbe84f5b948495de5bd9869c",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 3.7s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 3.7s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> How can I list all files in the Documents folder on Windows? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m How can I list all files in the Documents folder on Windows? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> To list all files in the Documents folder on Windows, you can use either Command Prompt or PowerShell. Here's <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> how to do it: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 1 </span><span style=\"font-weight: bold\">Open Command Prompt:</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Press <span style=\"color: #008080; text-decoration-color: #008080; background-color: #000000; font-weight: bold\">Win + R</span>, type <span style=\"color: #008080; text-decoration-color: #008080; background-color: #000000; font-weight: bold\">cmd</span>, and press <span style=\"color: #008080; text-decoration-color: #008080; background-color: #000000; font-weight: bold\">Enter</span>. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 2 </span><span style=\"font-weight: bold\">Navigate to the Documents folder:</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>The Documents folder is typically located in your user directory. You can navigate to it by entering the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span>following command: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">cd %USERPROFILE%</span><span style=\"color: #ae81ff; text-decoration-color: #ae81ff; background-color: #272822\">\\D</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">ocuments</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 3 </span><span style=\"font-weight: bold\">List all files:</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Once you're in the Documents directory, you can list all files by typing: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">dir</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Alternatively, you can use PowerShell: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 1 </span><span style=\"font-weight: bold\">Open PowerShell:</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Press <span style=\"color: #008080; text-decoration-color: #008080; background-color: #000000; font-weight: bold\">Win + X</span> and select <span style=\"color: #008080; text-decoration-color: #008080; background-color: #000000; font-weight: bold\">Windows PowerShell</span>. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 2 </span><span style=\"font-weight: bold\">List all files in the Documents folder:</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>You can directly list all files in the Documents folder with: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">Get-ChildItem -Path $HOME</span><span style=\"color: #ae81ff; text-decoration-color: #ae81ff; background-color: #272822\">\\D</span><span style=\"color: #f8f8f2; text-decoration-color: #f8f8f2; background-color: #272822\">ocuments</span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> </span><span style=\"background-color: #272822\"> </span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> These commands will display all files and directories within your Documents folder. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m To list all files in the Documents folder on Windows, you can use either Command Prompt or PowerShell. Here's \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m how to do it: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 1 \u001b[0m\u001b[1mOpen Command Prompt:\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mPress \u001b[1;36;40mWin + R\u001b[0m, type \u001b[1;36;40mcmd\u001b[0m, and press \u001b[1;36;40mEnter\u001b[0m. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 2 \u001b[0m\u001b[1mNavigate to the Documents folder:\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mThe Documents folder is typically located in your user directory. You can navigate to it by entering the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0mfollowing command: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mcd\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m%USERPROFILE%\u001b[0m\u001b[38;2;174;129;255;48;2;39;40;34m\\D\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mocuments\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 3 \u001b[0m\u001b[1mList all files:\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mOnce you're in the Documents directory, you can list all files by typing: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mdir\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Alternatively, you can use PowerShell: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 1 \u001b[0m\u001b[1mOpen PowerShell:\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mPress \u001b[1;36;40mWin + X\u001b[0m and select \u001b[1;36;40mWindows PowerShell\u001b[0m. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 2 \u001b[0m\u001b[1mList all files in the Documents folder:\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mYou can directly list all files in the Documents folder with: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mGet-ChildItem\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m-Path\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m \u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34m$HOME\u001b[0m\u001b[38;2;174;129;255;48;2;39;40;34m\\D\u001b[0m\u001b[38;2;248;248;242;48;2;39;40;34mocuments\u001b[0m\u001b[48;2;39;40;34m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[48;2;39;40;34m \u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m These commands will display all files and directories within your Documents folder. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"To list all files in the Documents folder on Windows, you can use either Command Prompt or PowerShell. Here's how to do it:\n",
|
||||
"\n",
|
||||
"1. **Open Command Prompt:**\n",
|
||||
" - Press `Win + R`, type `cmd`, and press `Enter`.\n",
|
||||
"\n",
|
||||
"2. **Navigate to the Documents folder:**\n",
|
||||
" - The Documents folder is typically located in your user directory. You can navigate to it by entering the following command:\n",
|
||||
" ```shell\n",
|
||||
" cd %USERPROFILE%\\Documents\n",
|
||||
" ```\n",
|
||||
"\n",
|
||||
"3. **List all files:**\n",
|
||||
" - Once you're in the Documents directory, you can list all files by typing:\n",
|
||||
" ```shell\n",
|
||||
" dir\n",
|
||||
" ```\n",
|
||||
"\n",
|
||||
"Alternatively, you can use PowerShell:\n",
|
||||
"\n",
|
||||
"1. **Open PowerShell:**\n",
|
||||
" - Press `Win + X` and select `Windows PowerShell`.\n",
|
||||
"\n",
|
||||
"2. **List all files in the Documents folder:**\n",
|
||||
" - You can directly list all files in the Documents folder with:\n",
|
||||
" ```shell\n",
|
||||
" Get-ChildItem -Path $HOME\\Documents\n",
|
||||
" ```\n",
|
||||
"\n",
|
||||
"These commands will display all files and directories within your Documents folder.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">You are FileSummarizeAgent, an intelligent assistant that processes and summarizes various types of </span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">files.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mYou are FileSummarizeAgent, an intelligent assistant that processes and summarizes various types of \u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229mfiles.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "a9a7af0c281c4a8787d6cfe66dca0244",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 6.9s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 6.9s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> How would you summarize the file at: example.txt? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m How would you summarize the file at: example.txt? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> To summarize a file like \"example.txt,\" follow these steps: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 1 </span><span style=\"font-weight: bold\">Determine the File Type and Purpose</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Identify if the file is a document, code, or data file. This will guide how you approach the summary. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Understand the purpose of the file by looking at its title, metadata, or any introductory sections. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 2 </span><span style=\"font-weight: bold\">Content Analysis</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">For Documents</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Look for headings, subheadings, and bullet points to understand the structure. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Identify key ideas, arguments, or themes in each section. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Note any conclusions or summaries provided by the author. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">For Code</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Identify the main modules or functions and their purposes. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Look for comments and documentation within the code that explain its functionality. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Understand the architecture by identifying how different parts of the code interact. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 3 </span><span style=\"font-weight: bold\">Structure Identification</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Documents</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Note the introduction, body, and conclusion sections. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Identify any appendices, references, or additional resources. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">Code</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Identify the main script or entry point. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Note any libraries or frameworks used. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Understand the flow of execution and data handling. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 4 </span><span style=\"font-weight: bold\">Summarization</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">For Documents</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Create a concise summary that captures the main points and conclusions. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Highlight any unique insights or important data. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span><span style=\"font-weight: bold\">For Code</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Summarize the overall functionality and purpose of the code. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Highlight key modules and their roles within the application. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 5 </span><span style=\"font-weight: bold\">Presentation</span>: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Organize the summary in a logical order, starting with the most important information. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Use bullet points or numbered lists for clarity. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> • </span>Ensure the summary is concise and free of jargon, making it accessible to a broad audience. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> By following these steps, you can create a comprehensive and user-friendly summary of the file \"example.txt\" or <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> any similar file. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m To summarize a file like \"example.txt,\" follow these steps: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 1 \u001b[0m\u001b[1mDetermine the File Type and Purpose\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mIdentify if the file is a document, code, or data file. This will guide how you approach the summary. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mUnderstand the purpose of the file by looking at its title, metadata, or any introductory sections. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 2 \u001b[0m\u001b[1mContent Analysis\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0m\u001b[1mFor Documents\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mLook for headings, subheadings, and bullet points to understand the structure. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mIdentify key ideas, arguments, or themes in each section. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mNote any conclusions or summaries provided by the author. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0m\u001b[1mFor Code\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mIdentify the main modules or functions and their purposes. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mLook for comments and documentation within the code that explain its functionality. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mUnderstand the architecture by identifying how different parts of the code interact. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 3 \u001b[0m\u001b[1mStructure Identification\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0m\u001b[1mDocuments\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mNote the introduction, body, and conclusion sections. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mIdentify any appendices, references, or additional resources. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0m\u001b[1mCode\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mIdentify the main script or entry point. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mNote any libraries or frameworks used. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mUnderstand the flow of execution and data handling. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 4 \u001b[0m\u001b[1mSummarization\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0m\u001b[1mFor Documents\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mCreate a concise summary that captures the main points and conclusions. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mHighlight any unique insights or important data. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0m\u001b[1mFor Code\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mSummarize the overall functionality and purpose of the code. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mHighlight key modules and their roles within the application. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 5 \u001b[0m\u001b[1mPresentation\u001b[0m: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mOrganize the summary in a logical order, starting with the most important information. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mUse bullet points or numbered lists for clarity. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m \u001b[0m\u001b[1;33m • \u001b[0mEnsure the summary is concise and free of jargon, making it accessible to a broad audience. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m By following these steps, you can create a comprehensive and user-friendly summary of the file \"example.txt\" or \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m any similar file. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"To summarize a file like \"example.txt,\" follow these steps:\n",
|
||||
"\n",
|
||||
"1. **Determine the File Type and Purpose**: \n",
|
||||
" - Identify if the file is a document, code, or data file. This will guide how you approach the summary.\n",
|
||||
" - Understand the purpose of the file by looking at its title, metadata, or any introductory sections.\n",
|
||||
"\n",
|
||||
"2. **Content Analysis**:\n",
|
||||
" - **For Documents**: \n",
|
||||
" - Look for headings, subheadings, and bullet points to understand the structure.\n",
|
||||
" - Identify key ideas, arguments, or themes in each section.\n",
|
||||
" - Note any conclusions or summaries provided by the author.\n",
|
||||
" - **For Code**:\n",
|
||||
" - Identify the main modules or functions and their purposes.\n",
|
||||
" - Look for comments and documentation within the code that explain its functionality.\n",
|
||||
" - Understand the architecture by identifying how different parts of the code interact.\n",
|
||||
"\n",
|
||||
"3. **Structure Identification**:\n",
|
||||
" - **Documents**: \n",
|
||||
" - Note the introduction, body, and conclusion sections.\n",
|
||||
" - Identify any appendices, references, or additional resources.\n",
|
||||
" - **Code**:\n",
|
||||
" - Identify the main script or entry point.\n",
|
||||
" - Note any libraries or frameworks used.\n",
|
||||
" - Understand the flow of execution and data handling.\n",
|
||||
"\n",
|
||||
"4. **Summarization**:\n",
|
||||
" - **For Documents**: \n",
|
||||
" - Create a concise summary that captures the main points and conclusions.\n",
|
||||
" - Highlight any unique insights or important data.\n",
|
||||
" - **For Code**:\n",
|
||||
" - Summarize the overall functionality and purpose of the code.\n",
|
||||
" - Highlight key modules and their roles within the application.\n",
|
||||
"\n",
|
||||
"5. **Presentation**:\n",
|
||||
" - Organize the summary in a logical order, starting with the most important information.\n",
|
||||
" - Use bullet points or numbered lists for clarity.\n",
|
||||
" - Ensure the summary is concise and free of jargon, making it accessible to a broad audience.\n",
|
||||
"\n",
|
||||
"By following these steps, you can create a comprehensive and user-friendly summary of the file \"example.txt\" or any similar file.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">You are an intelligent assistant embedded in a search interface.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mYou are an intelligent assistant embedded in a search interface.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "b782f03372b44eab96597bde5522fcd2",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 1.8s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 1.8s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> How can I search the web for the latest AI news? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m How can I search the web for the latest AI news? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> To search for the latest AI news, go to a search engine like Google and enter keywords such as \"latest AI news\" <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> or \"recent developments in AI.\" You can also use news-specific platforms like Google News or set up alerts for <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> AI-related topics. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m To search for the latest AI news, go to a search engine like Google and enter keywords such as \"latest AI news\" \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m or \"recent developments in AI.\" You can also use news-specific platforms like Google News or set up alerts for \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m AI-related topics. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"To search for the latest AI news, go to a search engine like Google and enter keywords such as \"latest AI news\" or \"recent developments in AI.\" You can also use news-specific platforms like Google News or set up alerts for AI-related topics.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Terminal Agent\n",
|
||||
"terminal_agent = Agent(\n",
|
||||
" role=TERMINAL_ROLE,\n",
|
||||
" goal=TERMINAL_GOAL,\n",
|
||||
" instructions=TERMINAL_INSTRUCTIONS\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# File Summarize Agent\n",
|
||||
"file_summarize_agent = Agent(\n",
|
||||
" role=FILE_ROLE,\n",
|
||||
" goal=FILE_GOAL,\n",
|
||||
" instructions=FILE_INSTRUCTIONS\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# General Purpose Agent\n",
|
||||
"general_purpose_agent = Agent(\n",
|
||||
" role=GENERAL_ROLE,\n",
|
||||
" goal=GENERAL_GOAL,\n",
|
||||
" instructions=GENERAL_INSTRUCTIONS\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Example usage\n",
|
||||
"def run_terminal_agent(query):\n",
|
||||
" return terminal_agent.start(query)\n",
|
||||
"\n",
|
||||
"def run_file_summarize_agent(file_path):\n",
|
||||
" prompt = f\"How would you summarize the file at: {file_path}?\"\n",
|
||||
" return file_summarize_agent.start(prompt)\n",
|
||||
"\n",
|
||||
"def run_general_purpose_agent(query):\n",
|
||||
" return general_purpose_agent.start(query)\n",
|
||||
"\n",
|
||||
"# Try a sample terminal command\n",
|
||||
"print(run_terminal_agent(\"How can I list all files in the Documents folder on Windows?\"))\n",
|
||||
"\n",
|
||||
"# Try a file summary (replace 'example.txt' with a real file path)\n",
|
||||
"print(run_file_summarize_agent(\"example.txt\"))\n",
|
||||
"\n",
|
||||
"# Try a general search\n",
|
||||
"print(run_general_purpose_agent(\"How can I search the web for the latest AI news?\"))"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "3XNenYs9vwef"
|
||||
},
|
||||
"source": [
|
||||
"# 📧 Work Email Agent with Custom Tools (PraisonAI Agents)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TvFpalM6vywF"
|
||||
},
|
||||
"source": [
|
||||
"This notebook demonstrates an AI agent that manages, summarizes, and responds to work emails using PraisonAI Agents. It includes a custom tool for extracting action items from email content."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "dKVYAK_OwmBs"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/Dhivya-Bharathy/PraisonAI/blob/main/examples/cookbooks/work_email_agent.ipynb)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "HI3poa3Bv05X"
|
||||
},
|
||||
"source": [
|
||||
"# Dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "cxz7rFqTv0X_",
|
||||
"outputId": "0c6e3870-152b-49ac-c344-20f94e0d8c13"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m40.1/40.1 kB\u001b[0m \u001b[31m2.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m178.2/178.2 kB\u001b[0m \u001b[31m15.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m150.9/150.9 kB\u001b[0m \u001b[31m12.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m104.9/104.9 kB\u001b[0m \u001b[31m9.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.2/45.2 kB\u001b[0m \u001b[31m3.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
|
||||
"\u001b[?25h"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!pip install praisonaiagents openai --quiet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "76GwcX00wVhD"
|
||||
},
|
||||
"source": [
|
||||
"# Set Up API Key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"id": "J9vIRYwRv7IR"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"Enter your api key\" # <-- Replace with your actual OpenAI API key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "5VwIXAgjwbaH"
|
||||
},
|
||||
"source": [
|
||||
"# Tools (Imports & Custom Tool)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"id": "7N_trHCYwAfI"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from praisonaiagents import Agent\n",
|
||||
"\n",
|
||||
"# Custom tool: Extract action items from email text\n",
|
||||
"def extract_action_items(email_text: str) -> list:\n",
|
||||
" \"\"\"\n",
|
||||
" Extracts action items from the email content.\n",
|
||||
" Returns a list of sentences that are likely action items.\n",
|
||||
" \"\"\"\n",
|
||||
" import re\n",
|
||||
" action_keywords = [\"please\", \"make sure\", \"need to\", \"must\", \"required\", \"should\"]\n",
|
||||
" sentences = re.split(r'(?<=[.!?]) +', email_text)\n",
|
||||
" actions = [s for s in sentences if any(k in s.lower() for k in action_keywords)]\n",
|
||||
" return actions\n",
|
||||
"\n",
|
||||
"custom_tools = [\n",
|
||||
" {\n",
|
||||
" \"name\": \"extract_action_items\",\n",
|
||||
" \"description\": \"Extracts action items from the email content.\",\n",
|
||||
" \"function\": extract_action_items,\n",
|
||||
" \"args\": [\"email_text\"]\n",
|
||||
" }\n",
|
||||
"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "lp-U374NweMn"
|
||||
},
|
||||
"source": [
|
||||
"# YAML Prompt (Role, Goal, Instructions)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"id": "CTgnmMoRwDBJ"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ROLE = (\n",
|
||||
" \"Chill work email assistant. Expert in summarizing, organizing, and replying to work emails with a calm and professional tone.\"\n",
|
||||
")\n",
|
||||
"GOAL = (\n",
|
||||
" \"Help the user manage their inbox, summarize email threads, extract action items, and draft polite, effective replies.\"\n",
|
||||
")\n",
|
||||
"INSTRUCTIONS = (\n",
|
||||
" \"Given the content of one or more work emails, summarize the main points, extract action items using the provided tool, \"\n",
|
||||
" \"suggest actions, and draft a calm, professional reply if requested. \"\n",
|
||||
" \"Always keep the tone friendly and stress-free.\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "PCUnZPwgwhHL"
|
||||
},
|
||||
"source": [
|
||||
"# Main (Agent Setup & Example)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000,
|
||||
"referenced_widgets": [
|
||||
"046932f8510343a5b0d433d38fa73fc9",
|
||||
"399ad0a94d5f4130a86343896a66c655"
|
||||
]
|
||||
},
|
||||
"id": "X0yhFyOTwEt4",
|
||||
"outputId": "245003af-59ed-4f40-a896-dd44b33aad04"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Chill work email assistant. Expert in summarizing, organizing, and replying to work emails with a calm </span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">and professional tone.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;255;229;229mChill work email assistant. Expert in summarizing, organizing, and replying to work emails with a calm \u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229mand professional tone.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "046932f8510343a5b0d433d38fa73fc9",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 3.0s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 3.0s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> EMAIL: Hi team, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Just a reminder that the project update meeting is scheduled for tomorrow at 10am. Please make sure your slides <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> are ready. Let me know if you have any questions. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Best, Manager <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> REQUEST: summarize, extract action items, and draft reply Summarize the email, list any action items, and draft <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> a calm, professional reply. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m EMAIL: Hi team, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Just a reminder that the project update meeting is scheduled for tomorrow at 10am. Please make sure your slides \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m are ready. Let me know if you have any questions. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Best, Manager \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m REQUEST: summarize, extract action items, and draft reply Summarize the email, list any action items, and draft \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m a calm, professional reply. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"font-weight: bold\">Summary:</span> The manager is reminding the team about the project update meeting scheduled for tomorrow at 10 am and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> asks everyone to have their slides ready. The manager is open to questions if there are any. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"font-weight: bold\">Action Items:</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 1 </span>Prepare slides for the project update meeting. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 2 </span>Attend the meeting tomorrow at 10 am. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\"> 3 </span>Reach out to the manager if there are any questions. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"font-weight: bold\">Draft Reply:</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Subject: Re: Project Update Meeting Reminder <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Hi [Manager's Name], <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Thank you for the reminder about tomorrow's meeting. I will ensure my slides are ready and look forward to our <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> discussion. Please let me know if there's anything specific you would like me to focus on during my update. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Best regards, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> [Your Name] <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1mSummary:\u001b[0m The manager is reminding the team about the project update meeting scheduled for tomorrow at 10 am and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m asks everyone to have their slides ready. The manager is open to questions if there are any. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1mAction Items:\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 1 \u001b[0mPrepare slides for the project update meeting. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 2 \u001b[0mAttend the meeting tomorrow at 10 am. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1;33m 3 \u001b[0mReach out to the manager if there are any questions. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[1mDraft Reply:\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Subject: Re: Project Update Meeting Reminder \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Hi [Manager's Name], \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Thank you for the reminder about tomorrow's meeting. I will ensure my slides are ready and look forward to our \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m discussion. Please let me know if there's anything specific you would like me to focus on during my update. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Best regards, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m [Your Name] \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"**Summary:**\n",
|
||||
"The manager is reminding the team about the project update meeting scheduled for tomorrow at 10 am and asks everyone to have their slides ready. The manager is open to questions if there are any.\n",
|
||||
"\n",
|
||||
"**Action Items:**\n",
|
||||
"1. Prepare slides for the project update meeting.\n",
|
||||
"2. Attend the meeting tomorrow at 10 am.\n",
|
||||
"3. Reach out to the manager if there are any questions.\n",
|
||||
"\n",
|
||||
"**Draft Reply:**\n",
|
||||
"\n",
|
||||
"Subject: Re: Project Update Meeting Reminder\n",
|
||||
"\n",
|
||||
"Hi [Manager's Name],\n",
|
||||
"\n",
|
||||
"Thank you for the reminder about tomorrow's meeting. I will ensure my slides are ready and look forward to our discussion. Please let me know if there's anything specific you would like me to focus on during my update.\n",
|
||||
"\n",
|
||||
"Best regards,\n",
|
||||
"\n",
|
||||
"[Your Name]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Create the email agent (no custom tools)\n",
|
||||
"email_agent = Agent(\n",
|
||||
" role=ROLE,\n",
|
||||
" goal=GOAL,\n",
|
||||
" instructions=INSTRUCTIONS\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Example usage\n",
|
||||
"def chill_email_action(email_content, request=\"summarize, extract action items, and draft reply\"):\n",
|
||||
" prompt = (\n",
|
||||
" f\"EMAIL:\\n{email_content}\\n\\n\"\n",
|
||||
" f\"REQUEST: {request}\\n\"\n",
|
||||
" \"Summarize the email, list any action items, and draft a calm, professional reply.\"\n",
|
||||
" )\n",
|
||||
" return email_agent.start(prompt)\n",
|
||||
"\n",
|
||||
"# Try a sample email\n",
|
||||
"sample_email = (\n",
|
||||
" \"Hi team,\\n\\n\"\n",
|
||||
" \"Just a reminder that the project update meeting is scheduled for tomorrow at 10am. \"\n",
|
||||
" \"Please make sure your slides are ready. Let me know if you have any questions.\\n\\n\"\n",
|
||||
" \"Best,\\nManager\"\n",
|
||||
")\n",
|
||||
"result = chill_email_action(sample_email)\n",
|
||||
"print(result)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,773 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ghztCKohBcZP"
|
||||
},
|
||||
"source": [
|
||||
"# 🎬 YouTube Content Integrity Analyzer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "hUmdUm4eBfCg"
|
||||
},
|
||||
"source": [
|
||||
"This notebook uses PraisonAI to analyze YouTube video captions for harmful content (hate speech, misinformation, violence, fraud) and evaluates educational value, relevance, integrity, and clarity. The agent provides unbiased, category-based content quality assessments using only the transcript text."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TZylRAldFYwv"
|
||||
},
|
||||
"source": [
|
||||
"[](https://colab.research.google.com/github/Dhivya-Bharathy/PraisonAI/blob/main/examples/cookbooks/Qwen2.5_InstructionAgent.ipynb)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ALWJRTXZBsKg"
|
||||
},
|
||||
"source": [
|
||||
"# Dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "S4mLEe-RBrkq"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install praisonaiagents openai youtube-transcript-api --quiet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Set up API KEY"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "AjLdy4NYD-AV"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ZzOX1ASAB6S3"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from praisonaiagents import Agent\n",
|
||||
"import os\n",
|
||||
"import json\n",
|
||||
"\n",
|
||||
"# Set your OpenAI API key\n",
|
||||
"os.environ[\"OPENAI_API_KEY\"] = \"Enter your api key\" # <-- Replace with your actual OpenAI API key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Get YouTube Transcript"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "DFJH4Jf0E4gU"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "pGY3CzCyCBtH"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from youtube_transcript_api import YouTubeTranscriptApi\n",
|
||||
"\n",
|
||||
"def get_youtube_transcript(video_id, languages=['en']):\n",
|
||||
" try:\n",
|
||||
" transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=languages)\n",
|
||||
" text = \" \".join([entry['text'] for entry in transcript])\n",
|
||||
" return text\n",
|
||||
" except Exception as e:\n",
|
||||
" return None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Prompts (role, goal, instructions)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "x5vHRKqAE7az"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Trs-R1NRC4jv"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ROLE = \"\"\"\n",
|
||||
"Act as a content integrity and quality analyst trained to evaluate YouTube video captions. You are an expert in content policy enforcement, linguistic analysis, and media integrity.\n",
|
||||
"You specialize in detecting harmful content (e.g., hate speech, misinformation, fraud) and evaluating the clarity, educational value, and relevance of language in video captions, using only textual evidence and without assumptions about tone or intent.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"GOAL = \"\"\"\n",
|
||||
"Your task is to assess whether specific content categories are present based solely on the language in the transcript. Your judgments should be precise, unbiased, and strictly based on linguistic clues — do not rely on assumptions about video intent or tone.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"INSTRUCTIONS = \"\"\"\n",
|
||||
"You will receive a list of categories and a YouTube transcript. Analyze the transcript to determine the presence of the specified categories.\n",
|
||||
"Only use these categories: [\"hatred\", \"misinformation\", \"violence\", \"fraud\", \"educational\", \"relevance\", \"integrity\", \"clarity\"].\n",
|
||||
"Discard any other category. If none remain, return an error.\n",
|
||||
"For each valid category, assign a score from 0 to 10 and provide a reason.\n",
|
||||
"Return a JSON object with:\n",
|
||||
" - categories: list of {name, score, connotation, reason}\n",
|
||||
" - overall: {score, reason}\n",
|
||||
" - error: \"\"\n",
|
||||
" - content_summary: brief summary of the transcript\n",
|
||||
"Start your response with { and end with }.\n",
|
||||
"\"\"\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Main Agent Function"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "TYv88sNgE-h2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "BsYXppH5C6VF"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def analyze_youtube_content(video_url, categories, custom_prompts=None):\n",
|
||||
" # Extract video ID from URL\n",
|
||||
" import re\n",
|
||||
" match = re.search(r\"v=([A-Za-z0-9_-]+)\", video_url)\n",
|
||||
" if not match:\n",
|
||||
" return {\"error\": \"Invalid YouTube URL\"}\n",
|
||||
" video_id = match.group(1)\n",
|
||||
"\n",
|
||||
" transcript = get_youtube_transcript(video_id)\n",
|
||||
" if not transcript:\n",
|
||||
" return {\"error\": \"Could not fetch transcript for this video.\"}\n",
|
||||
"\n",
|
||||
" # Prepare the prompt for the agent\n",
|
||||
" prompt = f\"Categories: {categories}\\n\\nTranscript:\\n{transcript}\\n\"\n",
|
||||
" if custom_prompts:\n",
|
||||
" for cp in custom_prompts:\n",
|
||||
" prompt += f\"\\nAdditional user prompt: {cp}\"\n",
|
||||
"\n",
|
||||
" agent = Agent(\n",
|
||||
" role=ROLE,\n",
|
||||
" goal=GOAL,\n",
|
||||
" instructions=INSTRUCTIONS,\n",
|
||||
" )\n",
|
||||
" response = agent.start(prompt)\n",
|
||||
" return response"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"# Example Usage (with a valid video URL)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "Po1Cy_fYFBYw"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/",
|
||||
"height": 1000,
|
||||
"referenced_widgets": [
|
||||
"ec4ebabe2add44dfa8fc416e018b529e",
|
||||
"6e52cd63a78f444882ac82fe8e392907"
|
||||
]
|
||||
},
|
||||
"id": "SD7juBbZEP-h",
|
||||
"outputId": "e5f15618-24d0-4524-d011-f9e9eefa87a2"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╭─ </span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8; font-weight: bold\">Agent Info</span><span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\"> ────────────────────────────────────────────────────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ff9b9b; text-decoration-color: #ff9b9b; font-weight: bold\">👤 Agent:</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Agent</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #b4b4b3; text-decoration-color: #b4b4b3; font-weight: bold\">Role:</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">Act as a content integrity and quality analyst trained to evaluate YouTube video captions. You are an expert </span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">in content policy enforcement, linguistic analysis, and media integrity.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">You specialize in detecting harmful content (e.g., hate speech, misinformation, fraud) and evaluating the </span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">clarity, educational value, and relevance of language in video captions, using only textual evidence and </span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #ffe5e5; text-decoration-color: #ffe5e5\">without assumptions about tone or intent.</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span> <span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">│</span>\n",
|
||||
"<span style=\"color: #d2e3c8; text-decoration-color: #d2e3c8\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[38;2;210;227;200m╭─\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[1;38;2;210;227;200mAgent Info\u001b[0m\u001b[38;2;210;227;200m \u001b[0m\u001b[38;2;210;227;200m───────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[38;2;210;227;200m─╮\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;255;155;155m👤 Agent:\u001b[0m \u001b[38;2;255;229;229mAgent\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[1;38;2;180;180;179mRole:\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229mAct as a content integrity and quality analyst trained to evaluate YouTube video captions. You are an expert \u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229min content policy enforcement, linguistic analysis, and media integrity.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229mYou specialize in detecting harmful content (e.g., hate speech, misinformation, fraud) and evaluating the \u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229mclarity, educational value, and relevance of language in video captions, using only textual evidence and \u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;255;229;229mwithout assumptions about tone or intent.\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m│\u001b[0m \u001b[38;2;210;227;200m│\u001b[0m\n",
|
||||
"\u001b[38;2;210;227;200m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "ec4ebabe2add44dfa8fc416e018b529e",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/plain": [
|
||||
"Output()"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
|
||||
],
|
||||
"text/plain": []
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #7f7f7f; text-decoration-color: #7f7f7f\">Response generated in 6.0s</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[2mResponse generated in 6.0s\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭───────────────────────────────────────────────────── Task ──────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Categories: ['hatred', 'educational', 'clarity'] <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Transcript: Translator: Joseph Geni Reviewer: Morton Bast So I want to start by offering you a free no-tech <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> life hack, and all it requires of you is this: that you change your posture for two minutes. But before I give <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> it away, I want to ask you to right now do a little audit of your body and what you're doing with your body. So <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> how many of you are sort of making yourselves smaller? Maybe you're hunching, crossing your legs, maybe <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> wrapping your ankles. Sometimes we hold onto our arms like this. Sometimes we spread out. (Laughter) I see you. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> So I want you to pay attention to what you're doing right now. We're going to come back to that in a few <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> minutes, and I'm hoping that if you learn to tweak this a little bit, it could significantly change the way <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> your life unfolds. So, we're really fascinated with body language, and we're particularly interested in other <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> people's body language. You know, we're interested in, like, you know — (Laughter) — an awkward interaction, or <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> a smile, or a contemptuous glance, or maybe a very awkward wink, or maybe even something like a handshake. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Narrator: Here they are arriving at Number 10. This lucky policeman gets to shake hands with the President of <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> the United States. Here comes the Prime Minister -- No. (Laughter) (Applause) (Laughter) (Applause) Amy Cuddy: <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> So a handshake, or the lack of a handshake, can have us talking for weeks and weeks and weeks. Even the BBC and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> The New York Times. So obviously when we think about nonverbal behavior, or body language -- but we call it <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> nonverbals as social scientists -- it's language, so we think about communication. When we think about <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> communication, we think about interactions. So what is your body language communicating to me? What's mine <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> communicating to you? And there's a lot of reason to believe that this is a valid way to look at this. So <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> social scientists have spent a lot of time looking at the effects of our body language, or other people's body <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> language, on judgments. And we make sweeping judgments and inferences from body language. And those judgments <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> can predict really meaningful life outcomes like who we hire or promote, who we ask out on a date. For example, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Nalini Ambady, a researcher at Tufts University, shows that when people watch 30-second soundless clips of real <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> physician-patient interactions, their judgments of the physician's niceness predict whether or not that <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> physician will be sued. So it doesn't have to do so much with whether or not that physician was incompetent, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> but do we like that person and how they interacted? Even more dramatic, Alex Todorov at Princeton has shown us <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> that judgments of political candidates' faces in just one second predict 70 percent of U.S. Senate and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> gubernatorial race outcomes, and even, let's go digital, emoticons used well in online negotiations can lead <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> you to claim more value from that negotiation. If you use them poorly, bad idea. Right? So when we think of <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> nonverbals, we think of how we judge others, how they judge us and what the outcomes are. We tend to forget, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> though, the other audience that's influenced by our nonverbals, and that's ourselves. We are also influenced by <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> our nonverbals, our thoughts and our feelings and our physiology. So what nonverbals am I talking about? I'm a <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> social psychologist. I study prejudice, and I teach at a competitive business school, so it was inevitable that <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> I would become interested in power dynamics. I became especially interested in nonverbal expressions of power <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> and dominance. And what are nonverbal expressions of power and dominance? Well, this is what they are. So in <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> the animal kingdom, they are about expanding. So you make yourself big, you stretch out, you take up space, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> you're basically opening up. It's about opening up. And this is true across the animal kingdom. It's not just <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> limited to primates. And humans do the same thing. (Laughter) So they do this both when they have power sort of <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> chronically, and also when they're feeling powerful in the moment. And this one is especially interesting <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> because it really shows us how universal and old these expressions of power are. This expression, which is <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> known as pride, Jessica Tracy has studied. She shows that people who are born with sight and people who are <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> congenitally blind do this when they win at a physical competition. So when they cross the finish line and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> they've won, it doesn't matter if they've never seen anyone do it. They do this. So the arms up in the V, the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> chin is slightly lifted. What do we do when we feel powerless? We do exactly the opposite. We close up. We wrap <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> ourselves up. We make ourselves small. We don't want to bump into the person next to us. So again, both animals <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> and humans do the same thing. And this is what happens when you put together high and low power. So what we <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> tend to do when it comes to power is that we complement the other's nonverbals. So if someone is being really <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> powerful with us, we tend to make ourselves smaller. We don't mirror them. We do the opposite of them. So I'm <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> watching this behavior in the classroom, and what do I notice? I notice that MBA students really exhibit the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> full range of power nonverbals. So you have people who are like caricatures of alphas, really coming into the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> room, they get right into the middle of the room before class even starts, like they really want to occupy <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> space. When they sit down, they're sort of spread out. They raise their hands like this. You have other people <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> who are virtually collapsing when they come in. As soon they come in, you see it. You see it on their faces and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> their bodies, and they sit in their chair and they make themselves tiny, and they go like this when they raise <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> their hand. I notice a couple of things about this. One, you're not going to be surprised. It seems to be <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> related to gender. So women are much more likely to do this kind of thing than men. Women feel chronically less <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> powerful than men, so this is not surprising. But the other thing I noticed is that it also seemed to be <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> related to the extent to which the students were participating, and how well they were participating. And this <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> is really important in the MBA classroom, because participation counts for half the grade. So business schools <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> have been struggling with this gender grade gap. You get these equally qualified women and men coming in and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> then you get these differences in grades, and it seems to be partly attributable to participation. So I started <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> to wonder, you know, okay, so you have these people coming in like this, and they're participating. Is it <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> possible that we could get people to fake it and would it lead them to participate more? So my main <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> collaborator Dana Carney, who's at Berkeley, and I really wanted to know, can you fake it till you make it? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Like, can you do this just for a little while and actually experience a behavioral outcome that makes you seem <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> more powerful? So we know that our nonverbals govern how other people think and feel about us. There's a lot of <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> evidence. But our question really was, do our nonverbals govern how we think and feel about ourselves? There's <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> some evidence that they do. So, for example, we smile when we feel happy, but also, when we're forced to smile <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> by holding a pen in our teeth like this, it makes us feel happy. So it goes both ways. When it comes to power, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> it also goes both ways. So when you feel powerful, you're more likely to do this, but it's also possible that <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> when you pretend to be powerful, you are more likely to actually feel powerful. So the second question really <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> was, you know, so we know that our minds change our bodies, but is it also true that our bodies change our <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> minds? And when I say minds, in the case of the powerful, what am I talking about? So I'm talking about <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> thoughts and feelings and the sort of physiological things that make up our thoughts and feelings, and in my <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> case, that's hormones. I look at hormones. So what do the minds of the powerful versus the powerless look like? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> So powerful people tend to be, not surprisingly, more assertive and more confident, more optimistic. They <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> actually feel they're going to win even at games of chance. They also tend to be able to think more abstractly. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> So there are a lot of differences. They take more risks. There are a lot of differences between powerful and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> powerless people. Physiologically, there also are differences on two key hormones: testosterone, which is the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> dominance hormone, and cortisol, which is the stress hormone. So what we find is that high-power alpha males in <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> primate hierarchies have high testosterone and low cortisol, and powerful and effective leaders also have high <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> testosterone and low cortisol. So what does that mean? When you think about power, people tended to think only <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> about testosterone, because that was about dominance. But really, power is also about how you react to stress. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> So do you want the high-power leader that's dominant, high on testosterone, but really stress reactive? <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Probably not, right? You want the person who's powerful and assertive and dominant, but not very stress <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> reactive, the person who's laid back. So we know that in primate hierarchies, if an alpha needs to take over, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> if an individual needs to take over an alpha role sort of suddenly, within a few days, that individual's <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> testosterone has gone up significantly and his cortisol has dropped significantly. So we have this evidence, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> both that the body can shape the mind, at least at the facial level, and also that role changes can shape the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> mind. So what happens, okay, you take a role change, what happens if you do that at a really minimal level, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> like this tiny manipulation, this tiny intervention? \"For two minutes,\" you say, \"I want you to stand like <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> this, and it's going to make you feel more powerful.\" So this is what we did. We decided to bring people into <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> the lab and run a little experiment, and these people adopted, for two minutes, either high-power poses or <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> low-power poses, and I'm just going to show you five of the poses, although they took on only two. So here's <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> one. A couple more. This one has been dubbed the \"Wonder Woman\" by the media. Here are a couple more. So you <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> can be standing or you can be sitting. And here are the low-power poses. So you're folding up, you're making <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> yourself small. This one is very low-power. When you're touching your neck, you're really protecting yourself. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> So this is what happens. They come in, they spit into a vial, for two minutes, we say, \"You need to do this or <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> this.\" They don't look at pictures of the poses. We don't want to prime them with a concept of power. We want <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> them to be feeling power. So two minutes they do this. We then ask them, \"How powerful do you feel?\" on a <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> series of items, and then we give them an opportunity to gamble, and then we take another saliva sample. That's <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> it. That's the whole experiment. So this is what we find. Risk tolerance, which is the gambling, we find that <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> when you are in the high-power pose condition, 86 percent of you will gamble. When you're in the low-power pose <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> condition, only 60 percent, and that's a whopping significant difference. Here's what we find on testosterone. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> From their baseline when they come in, high-power people experience about a 20-percent increase, and low-power <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> people experience about a 10-percent decrease. So again, two minutes, and you get these changes. Here's what <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> you get on cortisol. High-power people experience about a 25-percent decrease, and the low-power people <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> experience about a 15-percent increase. So two minutes lead to these hormonal changes that configure your brain <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> to basically be either assertive, confident and comfortable, or really stress-reactive, and feeling sort of <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> shut down. And we've all had the feeling, right? So it seems that our nonverbals do govern how we think and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> feel about ourselves, so it's not just others, but it's also ourselves. Also, our bodies change our minds. But <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> the next question, of course, is, can power posing for a few minutes really change your life in meaningful <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> ways? This is in the lab, it's this little task, it's just a couple of minutes. Where can you actually apply <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> this? Which we cared about, of course. And so we think where you want to use this is evaluative situations, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> like social threat situations. Where are you being evaluated, either by your friends? For teenagers, it's at <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> the lunchroom table. For some people it's speaking at a school board meeting. It might be giving a pitch or <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> giving a talk like this or doing a job interview. We decided that the one that most people could relate to <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> because most people had been through, was the job interview. So we published these findings, and the media are <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> all over it, and they say, Okay, so this is what you do when you go in for the job interview, right? (Laughter) <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> You know, so we were of course horrified, and said, Oh my God, no, that's not what we meant at all. For <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> numerous reasons, no, don't do that. Again, this is not about you talking to other people. It's you talking to <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> yourself. What do you do before you go into a job interview? You do this. You're sitting down. You're looking <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> at your iPhone -- or your Android, not trying to leave anyone out. You're looking at your notes, you're <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> hunching up, making yourself small, when really what you should be doing maybe is this, like, in the bathroom, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> right? Do that. Find two minutes. So that's what we want to test. Okay? So we bring people into a lab, and they <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> do either high- or low-power poses again, they go through a very stressful job interview. It's five minutes <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> long. They are being recorded. They're being judged also, and the judges are trained to give no nonverbal <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> feedback, so they look like this. Imagine this is the person interviewing you. So for five minutes, nothing, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> and this is worse than being heckled. People hate this. It's what Marianne LaFrance calls \"standing in social <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> quicksand.\" So this really spikes your cortisol. So this is the job interview we put them through, because we <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> really wanted to see what happened. We then have these coders look at these tapes, four of them. They're blind <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> to the hypothesis. They're blind to the conditions. They have no idea who's been posing in what pose, and they <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> end up looking at these sets of tapes, and they say, \"We want to hire these people,\" all the high-power posers. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> \"We don't want to hire these people. We also evaluate these people much more positively overall.\" But what's <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> driving it? It's not about the content of the speech. It's about the presence that they're bringing to the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> speech. Because we rate them on all these variables related to competence, like, how well-structured is the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> speech? How good is it? What are their qualifications? No effect on those things. This is what's affected. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> These kinds of things. People are bringing their true selves, basically. They're bringing themselves. They <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> bring their ideas, but as themselves, with no, you know, residue over them. So this is what's driving the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> effect, or mediating the effect. So when I tell people about this, that our bodies change our minds and our <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> minds can change our behavior, and our behavior can change our outcomes, they say to me, \"It feels fake.\" <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Right? So I said, fake it till you make it. It's not me. I don't want to get there and then still feel like a <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> fraud. I don't want to feel like an impostor. I don't want to get there only to feel like I'm not supposed to <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> be here. And that really resonated with me, because I want to tell you a little story about being an impostor <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> and feeling like I'm not supposed to be here. When I was 19, I was in a really bad car accident. I was thrown <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> out of a car, rolled several times. I was thrown from the car. And I woke up in a head injury rehab ward, and I <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> had been withdrawn from college, and I learned that my IQ had dropped by two standard deviations, which was <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> very traumatic. I knew my IQ because I had identified with being smart, and I had been called gifted as a <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> child. So I'm taken out of college, I keep trying to go back. They say, \"You're not going to finish college. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Just, you know, there are other things for you to do, but that's not going to work out for you.\" So I really <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> struggled with this, and I have to say, having your identity taken from you, your core identity, and for me it <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> was being smart, having that taken from you, there's nothing that leaves you feeling more powerless than that. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> So I felt entirely powerless. I worked and worked, and I got lucky, and worked, and got lucky, and worked. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Eventually I graduated from college. It took me four years longer than my peers, and I convinced someone, my <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> angel advisor, Susan Fiske, to take me on, and so I ended up at Princeton, and I was like, I am not supposed to <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> be here. I am an impostor. And the night before my first-year talk, and the first-year talk at Princeton is a <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> 20-minute talk to 20 people. That's it. I was so afraid of being found out the next day that I called her and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> said, \"I'm quitting.\" She was like, \"You are not quitting, because I took a gamble on you, and you're staying. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> You're going to stay, and this is what you're going to do. You are going to fake it. You're going to do every <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> talk that you ever get asked to do. You're just going to do it and do it and do it, even if you're terrified <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> and just paralyzed and having an out-of-body experience, until you have this moment where you say, 'Oh my gosh, <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> I'm doing it. Like, I have become this. I am actually doing this.'\" So that's what I did. Five years in grad <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> school, a few years, you know, I'm at Northwestern, I moved to Harvard, I'm at Harvard, I'm not really thinking <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> about it anymore, but for a long time I had been thinking, \"Not supposed to be here.\" So at the end of my first <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> year at Harvard, a student who had not talked in class the entire semester, who I had said, \"Look, you've gotta <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> participate or else you're going to fail,\" came into my office. I really didn't know her at all. She came in <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> totally defeated, and she said, \"I'm not supposed to be here.\" And that was the moment for me. Because two <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> things happened. One was that I realized, oh my gosh, I don't feel like that anymore. I don't feel that <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> anymore, but she does, and I get that feeling. And the second was, she is supposed to be here! Like, she can <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> fake it, she can become it. So I was like, \"Yes, you are! You are supposed to be here! And tomorrow you're <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> going to fake it, you're going to make yourself powerful, and, you know -- (Applause) And you're going to go <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> into the classroom, and you are going to give the best comment ever.\" You know? And she gave the best comment <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> ever, and people turned around and were like, oh my God, I didn't even notice her sitting there. (Laughter) She <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> comes back to me months later, and I realized that she had not just faked it till she made it, she had actually <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> faked it till she became it. So she had changed. And so I want to say to you, don't fake it till you make it. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Fake it till you become it. Do it enough until you actually become it and internalize. The last thing I'm going <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> to leave you with is this. Tiny tweaks can lead to big changes. So, this is two minutes. Two minutes, two <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> minutes, two minutes. Before you go into the next stressful evaluative situation, for two minutes, try doing <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> this, in the elevator, in a bathroom stall, at your desk behind closed doors. That's what you want to do. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Configure your brain to cope the best in that situation. Get your testosterone up. Get your cortisol down. <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> Don't leave that situation feeling like, oh, I didn't show them who I am. Leave that situation feeling like, I <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> really feel like I got to say who I am and show who I am. So I want to ask you first, you know, both to try <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> power posing, and also I want to ask you to share the science, because this is simple. I don't have ego <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> involved in this. (Laughter) Give it away. Share it with people, because the people who can use it the most are <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> the ones with no resources and no technology and no status and no power. Give it to them bec... <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m────────────────────────────────────────────────────\u001b[0m\u001b[36m Task \u001b[0m\u001b[36m─────────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Categories: ['hatred', 'educational', 'clarity'] \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Transcript: Translator: Joseph Geni Reviewer: Morton Bast So I want to start by offering you a free no-tech \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m life hack, and all it requires of you is this: that you change your posture for two minutes. But before I give \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m it away, I want to ask you to right now do a little audit of your body and what you're doing with your body. So \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m how many of you are sort of making yourselves smaller? Maybe you're hunching, crossing your legs, maybe \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m wrapping your ankles. Sometimes we hold onto our arms like this. Sometimes we spread out. (Laughter) I see you. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m So I want you to pay attention to what you're doing right now. We're going to come back to that in a few \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m minutes, and I'm hoping that if you learn to tweak this a little bit, it could significantly change the way \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m your life unfolds. So, we're really fascinated with body language, and we're particularly interested in other \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m people's body language. You know, we're interested in, like, you know — (Laughter) — an awkward interaction, or \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m a smile, or a contemptuous glance, or maybe a very awkward wink, or maybe even something like a handshake. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Narrator: Here they are arriving at Number 10. This lucky policeman gets to shake hands with the President of \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m the United States. Here comes the Prime Minister -- No. (Laughter) (Applause) (Laughter) (Applause) Amy Cuddy: \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m So a handshake, or the lack of a handshake, can have us talking for weeks and weeks and weeks. Even the BBC and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m The New York Times. So obviously when we think about nonverbal behavior, or body language -- but we call it \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m nonverbals as social scientists -- it's language, so we think about communication. When we think about \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m communication, we think about interactions. So what is your body language communicating to me? What's mine \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m communicating to you? And there's a lot of reason to believe that this is a valid way to look at this. So \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m social scientists have spent a lot of time looking at the effects of our body language, or other people's body \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m language, on judgments. And we make sweeping judgments and inferences from body language. And those judgments \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m can predict really meaningful life outcomes like who we hire or promote, who we ask out on a date. For example, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Nalini Ambady, a researcher at Tufts University, shows that when people watch 30-second soundless clips of real \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m physician-patient interactions, their judgments of the physician's niceness predict whether or not that \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m physician will be sued. So it doesn't have to do so much with whether or not that physician was incompetent, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m but do we like that person and how they interacted? Even more dramatic, Alex Todorov at Princeton has shown us \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m that judgments of political candidates' faces in just one second predict 70 percent of U.S. Senate and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m gubernatorial race outcomes, and even, let's go digital, emoticons used well in online negotiations can lead \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m you to claim more value from that negotiation. If you use them poorly, bad idea. Right? So when we think of \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m nonverbals, we think of how we judge others, how they judge us and what the outcomes are. We tend to forget, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m though, the other audience that's influenced by our nonverbals, and that's ourselves. We are also influenced by \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m our nonverbals, our thoughts and our feelings and our physiology. So what nonverbals am I talking about? I'm a \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m social psychologist. I study prejudice, and I teach at a competitive business school, so it was inevitable that \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m I would become interested in power dynamics. I became especially interested in nonverbal expressions of power \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m and dominance. And what are nonverbal expressions of power and dominance? Well, this is what they are. So in \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m the animal kingdom, they are about expanding. So you make yourself big, you stretch out, you take up space, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m you're basically opening up. It's about opening up. And this is true across the animal kingdom. It's not just \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m limited to primates. And humans do the same thing. (Laughter) So they do this both when they have power sort of \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m chronically, and also when they're feeling powerful in the moment. And this one is especially interesting \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m because it really shows us how universal and old these expressions of power are. This expression, which is \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m known as pride, Jessica Tracy has studied. She shows that people who are born with sight and people who are \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m congenitally blind do this when they win at a physical competition. So when they cross the finish line and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m they've won, it doesn't matter if they've never seen anyone do it. They do this. So the arms up in the V, the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m chin is slightly lifted. What do we do when we feel powerless? We do exactly the opposite. We close up. We wrap \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m ourselves up. We make ourselves small. We don't want to bump into the person next to us. So again, both animals \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m and humans do the same thing. And this is what happens when you put together high and low power. So what we \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m tend to do when it comes to power is that we complement the other's nonverbals. So if someone is being really \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m powerful with us, we tend to make ourselves smaller. We don't mirror them. We do the opposite of them. So I'm \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m watching this behavior in the classroom, and what do I notice? I notice that MBA students really exhibit the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m full range of power nonverbals. So you have people who are like caricatures of alphas, really coming into the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m room, they get right into the middle of the room before class even starts, like they really want to occupy \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m space. When they sit down, they're sort of spread out. They raise their hands like this. You have other people \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m who are virtually collapsing when they come in. As soon they come in, you see it. You see it on their faces and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m their bodies, and they sit in their chair and they make themselves tiny, and they go like this when they raise \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m their hand. I notice a couple of things about this. One, you're not going to be surprised. It seems to be \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m related to gender. So women are much more likely to do this kind of thing than men. Women feel chronically less \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m powerful than men, so this is not surprising. But the other thing I noticed is that it also seemed to be \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m related to the extent to which the students were participating, and how well they were participating. And this \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m is really important in the MBA classroom, because participation counts for half the grade. So business schools \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m have been struggling with this gender grade gap. You get these equally qualified women and men coming in and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m then you get these differences in grades, and it seems to be partly attributable to participation. So I started \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m to wonder, you know, okay, so you have these people coming in like this, and they're participating. Is it \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m possible that we could get people to fake it and would it lead them to participate more? So my main \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m collaborator Dana Carney, who's at Berkeley, and I really wanted to know, can you fake it till you make it? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Like, can you do this just for a little while and actually experience a behavioral outcome that makes you seem \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m more powerful? So we know that our nonverbals govern how other people think and feel about us. There's a lot of \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m evidence. But our question really was, do our nonverbals govern how we think and feel about ourselves? There's \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m some evidence that they do. So, for example, we smile when we feel happy, but also, when we're forced to smile \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m by holding a pen in our teeth like this, it makes us feel happy. So it goes both ways. When it comes to power, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m it also goes both ways. So when you feel powerful, you're more likely to do this, but it's also possible that \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m when you pretend to be powerful, you are more likely to actually feel powerful. So the second question really \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m was, you know, so we know that our minds change our bodies, but is it also true that our bodies change our \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m minds? And when I say minds, in the case of the powerful, what am I talking about? So I'm talking about \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m thoughts and feelings and the sort of physiological things that make up our thoughts and feelings, and in my \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m case, that's hormones. I look at hormones. So what do the minds of the powerful versus the powerless look like? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m So powerful people tend to be, not surprisingly, more assertive and more confident, more optimistic. They \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m actually feel they're going to win even at games of chance. They also tend to be able to think more abstractly. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m So there are a lot of differences. They take more risks. There are a lot of differences between powerful and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m powerless people. Physiologically, there also are differences on two key hormones: testosterone, which is the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m dominance hormone, and cortisol, which is the stress hormone. So what we find is that high-power alpha males in \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m primate hierarchies have high testosterone and low cortisol, and powerful and effective leaders also have high \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m testosterone and low cortisol. So what does that mean? When you think about power, people tended to think only \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m about testosterone, because that was about dominance. But really, power is also about how you react to stress. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m So do you want the high-power leader that's dominant, high on testosterone, but really stress reactive? \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Probably not, right? You want the person who's powerful and assertive and dominant, but not very stress \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m reactive, the person who's laid back. So we know that in primate hierarchies, if an alpha needs to take over, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m if an individual needs to take over an alpha role sort of suddenly, within a few days, that individual's \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m testosterone has gone up significantly and his cortisol has dropped significantly. So we have this evidence, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m both that the body can shape the mind, at least at the facial level, and also that role changes can shape the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m mind. So what happens, okay, you take a role change, what happens if you do that at a really minimal level, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m like this tiny manipulation, this tiny intervention? \"For two minutes,\" you say, \"I want you to stand like \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m this, and it's going to make you feel more powerful.\" So this is what we did. We decided to bring people into \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m the lab and run a little experiment, and these people adopted, for two minutes, either high-power poses or \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m low-power poses, and I'm just going to show you five of the poses, although they took on only two. So here's \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m one. A couple more. This one has been dubbed the \"Wonder Woman\" by the media. Here are a couple more. So you \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m can be standing or you can be sitting. And here are the low-power poses. So you're folding up, you're making \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m yourself small. This one is very low-power. When you're touching your neck, you're really protecting yourself. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m So this is what happens. They come in, they spit into a vial, for two minutes, we say, \"You need to do this or \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m this.\" They don't look at pictures of the poses. We don't want to prime them with a concept of power. We want \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m them to be feeling power. So two minutes they do this. We then ask them, \"How powerful do you feel?\" on a \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m series of items, and then we give them an opportunity to gamble, and then we take another saliva sample. That's \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m it. That's the whole experiment. So this is what we find. Risk tolerance, which is the gambling, we find that \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m when you are in the high-power pose condition, 86 percent of you will gamble. When you're in the low-power pose \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m condition, only 60 percent, and that's a whopping significant difference. Here's what we find on testosterone. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m From their baseline when they come in, high-power people experience about a 20-percent increase, and low-power \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m people experience about a 10-percent decrease. So again, two minutes, and you get these changes. Here's what \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m you get on cortisol. High-power people experience about a 25-percent decrease, and the low-power people \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m experience about a 15-percent increase. So two minutes lead to these hormonal changes that configure your brain \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m to basically be either assertive, confident and comfortable, or really stress-reactive, and feeling sort of \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m shut down. And we've all had the feeling, right? So it seems that our nonverbals do govern how we think and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m feel about ourselves, so it's not just others, but it's also ourselves. Also, our bodies change our minds. But \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m the next question, of course, is, can power posing for a few minutes really change your life in meaningful \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m ways? This is in the lab, it's this little task, it's just a couple of minutes. Where can you actually apply \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m this? Which we cared about, of course. And so we think where you want to use this is evaluative situations, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m like social threat situations. Where are you being evaluated, either by your friends? For teenagers, it's at \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m the lunchroom table. For some people it's speaking at a school board meeting. It might be giving a pitch or \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m giving a talk like this or doing a job interview. We decided that the one that most people could relate to \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m because most people had been through, was the job interview. So we published these findings, and the media are \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m all over it, and they say, Okay, so this is what you do when you go in for the job interview, right? (Laughter) \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m You know, so we were of course horrified, and said, Oh my God, no, that's not what we meant at all. For \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m numerous reasons, no, don't do that. Again, this is not about you talking to other people. It's you talking to \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m yourself. What do you do before you go into a job interview? You do this. You're sitting down. You're looking \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m at your iPhone -- or your Android, not trying to leave anyone out. You're looking at your notes, you're \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m hunching up, making yourself small, when really what you should be doing maybe is this, like, in the bathroom, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m right? Do that. Find two minutes. So that's what we want to test. Okay? So we bring people into a lab, and they \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m do either high- or low-power poses again, they go through a very stressful job interview. It's five minutes \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m long. They are being recorded. They're being judged also, and the judges are trained to give no nonverbal \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m feedback, so they look like this. Imagine this is the person interviewing you. So for five minutes, nothing, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m and this is worse than being heckled. People hate this. It's what Marianne LaFrance calls \"standing in social \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m quicksand.\" So this really spikes your cortisol. So this is the job interview we put them through, because we \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m really wanted to see what happened. We then have these coders look at these tapes, four of them. They're blind \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m to the hypothesis. They're blind to the conditions. They have no idea who's been posing in what pose, and they \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m end up looking at these sets of tapes, and they say, \"We want to hire these people,\" all the high-power posers. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \"We don't want to hire these people. We also evaluate these people much more positively overall.\" But what's \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m driving it? It's not about the content of the speech. It's about the presence that they're bringing to the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m speech. Because we rate them on all these variables related to competence, like, how well-structured is the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m speech? How good is it? What are their qualifications? No effect on those things. This is what's affected. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m These kinds of things. People are bringing their true selves, basically. They're bringing themselves. They \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m bring their ideas, but as themselves, with no, you know, residue over them. So this is what's driving the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m effect, or mediating the effect. So when I tell people about this, that our bodies change our minds and our \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m minds can change our behavior, and our behavior can change our outcomes, they say to me, \"It feels fake.\" \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Right? So I said, fake it till you make it. It's not me. I don't want to get there and then still feel like a \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m fraud. I don't want to feel like an impostor. I don't want to get there only to feel like I'm not supposed to \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m be here. And that really resonated with me, because I want to tell you a little story about being an impostor \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m and feeling like I'm not supposed to be here. When I was 19, I was in a really bad car accident. I was thrown \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m out of a car, rolled several times. I was thrown from the car. And I woke up in a head injury rehab ward, and I \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m had been withdrawn from college, and I learned that my IQ had dropped by two standard deviations, which was \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m very traumatic. I knew my IQ because I had identified with being smart, and I had been called gifted as a \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m child. So I'm taken out of college, I keep trying to go back. They say, \"You're not going to finish college. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Just, you know, there are other things for you to do, but that's not going to work out for you.\" So I really \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m struggled with this, and I have to say, having your identity taken from you, your core identity, and for me it \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m was being smart, having that taken from you, there's nothing that leaves you feeling more powerless than that. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m So I felt entirely powerless. I worked and worked, and I got lucky, and worked, and got lucky, and worked. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Eventually I graduated from college. It took me four years longer than my peers, and I convinced someone, my \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m angel advisor, Susan Fiske, to take me on, and so I ended up at Princeton, and I was like, I am not supposed to \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m be here. I am an impostor. And the night before my first-year talk, and the first-year talk at Princeton is a \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m 20-minute talk to 20 people. That's it. I was so afraid of being found out the next day that I called her and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m said, \"I'm quitting.\" She was like, \"You are not quitting, because I took a gamble on you, and you're staying. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m You're going to stay, and this is what you're going to do. You are going to fake it. You're going to do every \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m talk that you ever get asked to do. You're just going to do it and do it and do it, even if you're terrified \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m and just paralyzed and having an out-of-body experience, until you have this moment where you say, 'Oh my gosh, \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m I'm doing it. Like, I have become this. I am actually doing this.'\" So that's what I did. Five years in grad \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m school, a few years, you know, I'm at Northwestern, I moved to Harvard, I'm at Harvard, I'm not really thinking \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m about it anymore, but for a long time I had been thinking, \"Not supposed to be here.\" So at the end of my first \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m year at Harvard, a student who had not talked in class the entire semester, who I had said, \"Look, you've gotta \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m participate or else you're going to fail,\" came into my office. I really didn't know her at all. She came in \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m totally defeated, and she said, \"I'm not supposed to be here.\" And that was the moment for me. Because two \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m things happened. One was that I realized, oh my gosh, I don't feel like that anymore. I don't feel that \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m anymore, but she does, and I get that feeling. And the second was, she is supposed to be here! Like, she can \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m fake it, she can become it. So I was like, \"Yes, you are! You are supposed to be here! And tomorrow you're \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m going to fake it, you're going to make yourself powerful, and, you know -- (Applause) And you're going to go \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m into the classroom, and you are going to give the best comment ever.\" You know? And she gave the best comment \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m ever, and people turned around and were like, oh my God, I didn't even notice her sitting there. (Laughter) She \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m comes back to me months later, and I realized that she had not just faked it till she made it, she had actually \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m faked it till she became it. So she had changed. And so I want to say to you, don't fake it till you make it. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Fake it till you become it. Do it enough until you actually become it and internalize. The last thing I'm going \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m to leave you with is this. Tiny tweaks can lead to big changes. So, this is two minutes. Two minutes, two \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m minutes, two minutes. Before you go into the next stressful evaluative situation, for two minutes, try doing \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m this, in the elevator, in a bathroom stall, at your desk behind closed doors. That's what you want to do. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Configure your brain to cope the best in that situation. Get your testosterone up. Get your cortisol down. \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m Don't leave that situation feeling like, oh, I didn't show them who I am. Leave that situation feeling like, I \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m really feel like I got to say who I am and show who I am. So I want to ask you first, you know, both to try \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m power posing, and also I want to ask you to share the science, because this is simple. I don't have ego \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m involved in this. (Laughter) Give it away. Share it with people, because the people who can use it the most are \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m the ones with no resources and no technology and no status and no power. Give it to them bec... \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080\">╭─────────────────────────────────────────────────── Response ────────────────────────────────────────────────────╮</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> { \"categories\": [ { \"name\": \"educational\", \"score\": 9, \"connotation\": \"positive\", \"reason\": \"The transcript <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> provides a detailed explanation of body language and its effects on personal and professional outcomes. It <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> includes scientific studies and practical advice, making it highly educational.\" }, { \"name\": \"clarity\", <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> \"score\": 8, \"connotation\": \"positive\", \"reason\": \"The transcript is clear in its explanation of concepts <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> related to body language and power dynamics. It uses examples and studies to illustrate points, although the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> length and detail might be overwhelming for some.\" } ], \"overall\": { \"score\": 8.5, \"reason\": \"The transcript is <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> highly educational and clear, providing valuable insights into body language and its impact on personal <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> empowerment. It effectively communicates scientific findings and practical applications.\" }, \"error\": \"\", <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> \"content_summary\": \"The transcript discusses the impact of body language on personal empowerment and <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> professional success. It explains scientific studies on nonverbal communication, power dynamics, and the <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> concept of 'faking it till you become it.' Practical advice is given on how to use body language to improve <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">│</span> self-confidence and outcomes in evaluative situations.\" } <span style=\"color: #008080; text-decoration-color: #008080\">│</span>\n",
|
||||
"<span style=\"color: #008080; text-decoration-color: #008080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
|
||||
"</pre>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"\u001b[36m╭─\u001b[0m\u001b[36m──────────────────────────────────────────────────\u001b[0m\u001b[36m Response \u001b[0m\u001b[36m───────────────────────────────────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m { \"categories\": [ { \"name\": \"educational\", \"score\": 9, \"connotation\": \"positive\", \"reason\": \"The transcript \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m provides a detailed explanation of body language and its effects on personal and professional outcomes. It \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m includes scientific studies and practical advice, making it highly educational.\" }, { \"name\": \"clarity\", \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \"score\": 8, \"connotation\": \"positive\", \"reason\": \"The transcript is clear in its explanation of concepts \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m related to body language and power dynamics. It uses examples and studies to illustrate points, although the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m length and detail might be overwhelming for some.\" } ], \"overall\": { \"score\": 8.5, \"reason\": \"The transcript is \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m highly educational and clear, providing valuable insights into body language and its impact on personal \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m empowerment. It effectively communicates scientific findings and practical applications.\" }, \"error\": \"\", \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m \"content_summary\": \"The transcript discusses the impact of body language on personal empowerment and \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m professional success. It explains scientific studies on nonverbal communication, power dynamics, and the \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m concept of 'faking it till you become it.' Practical advice is given on how to use body language to improve \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m│\u001b[0m self-confidence and outcomes in evaluative situations.\" } \u001b[36m│\u001b[0m\n",
|
||||
"\u001b[36m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\n",
|
||||
" \"categories\": [\n",
|
||||
" {\n",
|
||||
" \"name\": \"educational\",\n",
|
||||
" \"score\": 9,\n",
|
||||
" \"connotation\": \"positive\",\n",
|
||||
" \"reason\": \"The transcript provides a detailed explanation of body language and its effects on personal and professional outcomes. It includes scientific studies and practical advice, making it highly educational.\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"name\": \"clarity\",\n",
|
||||
" \"score\": 8,\n",
|
||||
" \"connotation\": \"positive\",\n",
|
||||
" \"reason\": \"The transcript is clear in its explanation of concepts related to body language and power dynamics. It uses examples and studies to illustrate points, although the length and detail might be overwhelming for some.\"\n",
|
||||
" }\n",
|
||||
" ],\n",
|
||||
" \"overall\": {\n",
|
||||
" \"score\": 8.5,\n",
|
||||
" \"reason\": \"The transcript is highly educational and clear, providing valuable insights into body language and its impact on personal empowerment. It effectively communicates scientific findings and practical applications.\"\n",
|
||||
" },\n",
|
||||
" \"error\": \"\",\n",
|
||||
" \"content_summary\": \"The transcript discusses the impact of body language on personal empowerment and professional success. It explains scientific studies on nonverbal communication, power dynamics, and the concept of 'faking it till you become it.' Practical advice is given on how to use body language to improve self-confidence and outcomes in evaluative situations.\"\n",
|
||||
"}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Example usage with a valid video URL (TED Talk with English transcript)\n",
|
||||
"video_url = \"https://www.youtube.com/watch?v=Ks-_Mh1QhMc\" # TED: Your body language may shape who you are\n",
|
||||
"categories = [\"hatred\", \"educational\", \"clarity\"]\n",
|
||||
"result = analyze_youtube_content(video_url, categories)\n",
|
||||
"print(result)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"provenance": []
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
Code Agent Example
|
||||
|
||||
This example demonstrates a comprehensive code agent that can write, analyze, debug, and execute code.
|
||||
It includes self-reflection for improving code quality and multiple specialized tools.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import CodeInterpreter
|
||||
|
||||
# Initialize code execution tool
|
||||
code_interpreter = CodeInterpreter()
|
||||
|
||||
# Custom code analysis tool
|
||||
def analyze_code_complexity(code: str) -> str:
|
||||
"""Analyze code complexity and provide feedback."""
|
||||
lines = code.strip().split('\n')
|
||||
num_lines = len(lines)
|
||||
num_functions = sum(1 for line in lines if line.strip().startswith('def '))
|
||||
num_classes = sum(1 for line in lines if line.strip().startswith('class '))
|
||||
|
||||
return f"""Code Analysis:
|
||||
- Lines of code: {num_lines}
|
||||
- Functions: {num_functions}
|
||||
- Classes: {num_classes}
|
||||
- Complexity: {'Simple' if num_lines < 50 else 'Moderate' if num_lines < 200 else 'Complex'}"""
|
||||
|
||||
# Create specialized code agents
|
||||
code_writer = Agent(
|
||||
name="CodeWriter",
|
||||
role="Expert Python developer",
|
||||
goal="Write clean, efficient, and well-documented Python code",
|
||||
backstory="You are a senior Python developer with 10+ years of experience in writing production-quality code.",
|
||||
instructions="Write Python code that follows PEP 8 standards, includes proper error handling, and has clear documentation.",
|
||||
self_reflect=True,
|
||||
min_reflect=2,
|
||||
max_reflect=5
|
||||
)
|
||||
|
||||
code_reviewer = Agent(
|
||||
name="CodeReviewer",
|
||||
role="Code quality expert",
|
||||
goal="Review code for bugs, security issues, and best practices",
|
||||
backstory="You are a code review specialist who ensures code quality and maintainability.",
|
||||
instructions="Review the provided code for potential issues, suggest improvements, and ensure it follows best practices.",
|
||||
tools=[analyze_code_complexity]
|
||||
)
|
||||
|
||||
code_executor = Agent(
|
||||
name="CodeExecutor",
|
||||
role="Code execution specialist",
|
||||
goal="Safely execute and test Python code",
|
||||
backstory="You are responsible for running code and reporting results or errors.",
|
||||
instructions="Execute the provided code safely and report the output or any errors encountered.",
|
||||
tools=[code_interpreter]
|
||||
)
|
||||
|
||||
# Example tasks
|
||||
def demonstrate_code_agent():
|
||||
# Task 1: Write a function
|
||||
write_task = Task(
|
||||
name="write_function",
|
||||
description="Write a Python function that calculates the Fibonacci sequence up to n terms",
|
||||
expected_output="A well-documented Python function with error handling",
|
||||
agent=code_writer
|
||||
)
|
||||
|
||||
# Task 2: Review the code
|
||||
review_task = Task(
|
||||
name="review_code",
|
||||
description="Review the Fibonacci function for quality and suggest improvements",
|
||||
expected_output="Detailed code review with suggestions",
|
||||
agent=code_reviewer,
|
||||
context=[write_task]
|
||||
)
|
||||
|
||||
# Task 3: Execute and test
|
||||
execute_task = Task(
|
||||
name="execute_code",
|
||||
description="Execute the Fibonacci function with n=10 and verify it works correctly",
|
||||
expected_output="Execution results showing the first 10 Fibonacci numbers",
|
||||
agent=code_executor,
|
||||
context=[write_task]
|
||||
)
|
||||
|
||||
# Create workflow
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[code_writer, code_reviewer, code_executor],
|
||||
tasks=[write_task, review_task, execute_task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Run the workflow
|
||||
result = workflow.start()
|
||||
return result
|
||||
|
||||
# Standalone code agent for general programming tasks
|
||||
general_code_agent = Agent(
|
||||
name="GeneralCodeAgent",
|
||||
role="Full-stack programming assistant",
|
||||
goal="Help with any programming task including writing, debugging, and explaining code",
|
||||
backstory="You are an AI programming assistant with expertise in multiple languages and frameworks.",
|
||||
instructions="""You can:
|
||||
1. Write code in any programming language
|
||||
2. Debug and fix code issues
|
||||
3. Explain code concepts
|
||||
4. Refactor code for better performance
|
||||
5. Add tests and documentation""",
|
||||
tools=[code_interpreter, analyze_code_complexity],
|
||||
self_reflect=True,
|
||||
min_reflect=1,
|
||||
max_reflect=3
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example 1: Run the multi-agent workflow
|
||||
print("=== Multi-Agent Code Workflow ===")
|
||||
result = demonstrate_code_agent()
|
||||
print(f"Workflow Result: {result}")
|
||||
|
||||
# Example 2: Use the general code agent
|
||||
print("\n=== General Code Agent ===")
|
||||
response = general_code_agent.start("""
|
||||
Write a Python class for a simple Calculator with methods for:
|
||||
- Addition
|
||||
- Subtraction
|
||||
- Multiplication
|
||||
- Division (with error handling for division by zero)
|
||||
|
||||
Then create a simple test to verify it works.
|
||||
""")
|
||||
print(response)
|
||||
@@ -0,0 +1,188 @@
|
||||
"""
|
||||
Math Agent Example
|
||||
|
||||
This example demonstrates a mathematical problem-solving agent that can handle various math tasks
|
||||
including calculations, equation solving, and step-by-step explanations.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from typing import Dict, Any
|
||||
import math
|
||||
import re
|
||||
|
||||
# Custom math tools
|
||||
def basic_calculator(expression: str) -> str:
|
||||
"""Evaluate basic mathematical expressions safely."""
|
||||
try:
|
||||
# Remove any non-mathematical characters for safety
|
||||
safe_expr = re.sub(r'[^0-9+\-*/().,\s]', '', expression)
|
||||
result = eval(safe_expr)
|
||||
return f"Result: {result}"
|
||||
except Exception as e:
|
||||
return f"Error in calculation: {str(e)}"
|
||||
|
||||
def solve_quadratic(a: float, b: float, c: float) -> str:
|
||||
"""Solve quadratic equation ax² + bx + c = 0."""
|
||||
discriminant = b**2 - 4*a*c
|
||||
|
||||
if discriminant > 0:
|
||||
x1 = (-b + math.sqrt(discriminant)) / (2*a)
|
||||
x2 = (-b - math.sqrt(discriminant)) / (2*a)
|
||||
return f"Two real solutions: x₁ = {x1:.4f}, x₂ = {x2:.4f}"
|
||||
elif discriminant == 0:
|
||||
x = -b / (2*a)
|
||||
return f"One real solution: x = {x:.4f}"
|
||||
else:
|
||||
real_part = -b / (2*a)
|
||||
imag_part = math.sqrt(-discriminant) / (2*a)
|
||||
return f"Two complex solutions: x₁ = {real_part:.4f} + {imag_part:.4f}i, x₂ = {real_part:.4f} - {imag_part:.4f}i"
|
||||
|
||||
def calculate_statistics(numbers: list) -> str:
|
||||
"""Calculate basic statistics for a list of numbers."""
|
||||
if not numbers:
|
||||
return "No numbers provided"
|
||||
|
||||
n = len(numbers)
|
||||
mean = sum(numbers) / n
|
||||
sorted_nums = sorted(numbers)
|
||||
median = sorted_nums[n//2] if n % 2 else (sorted_nums[n//2-1] + sorted_nums[n//2]) / 2
|
||||
variance = sum((x - mean)**2 for x in numbers) / n
|
||||
std_dev = math.sqrt(variance)
|
||||
|
||||
return f"""Statistics:
|
||||
- Count: {n}
|
||||
- Mean: {mean:.4f}
|
||||
- Median: {median:.4f}
|
||||
- Standard Deviation: {std_dev:.4f}
|
||||
- Min: {min(numbers)}
|
||||
- Max: {max(numbers)}"""
|
||||
|
||||
# Create specialized math agents
|
||||
calculation_agent = Agent(
|
||||
name="CalculationAgent",
|
||||
role="Mathematical calculation specialist",
|
||||
goal="Perform accurate mathematical calculations and computations",
|
||||
backstory="You are an expert mathematician who can handle complex calculations with precision.",
|
||||
instructions="Perform the requested calculations step by step, showing your work clearly.",
|
||||
tools=[basic_calculator, solve_quadratic, calculate_statistics],
|
||||
self_reflect=True,
|
||||
min_reflect=1,
|
||||
max_reflect=2
|
||||
)
|
||||
|
||||
problem_solver_agent = Agent(
|
||||
name="ProblemSolver",
|
||||
role="Mathematical problem solver",
|
||||
goal="Solve complex math problems with detailed explanations",
|
||||
backstory="You are a math teacher who excels at breaking down complex problems into understandable steps.",
|
||||
instructions="""When solving math problems:
|
||||
1. Identify the type of problem
|
||||
2. List the given information
|
||||
3. Determine what needs to be found
|
||||
4. Show each step of the solution
|
||||
5. Verify the answer makes sense""",
|
||||
self_reflect=True,
|
||||
min_reflect=2,
|
||||
max_reflect=4
|
||||
)
|
||||
|
||||
math_tutor_agent = Agent(
|
||||
name="MathTutor",
|
||||
role="Mathematics tutor and explainer",
|
||||
goal="Explain mathematical concepts clearly and help users understand math",
|
||||
backstory="You are a patient math tutor who can explain concepts at any level from elementary to advanced.",
|
||||
instructions="Explain mathematical concepts using simple language, provide examples, and check for understanding."
|
||||
)
|
||||
|
||||
# Example workflow for solving complex problems
|
||||
def solve_math_problem_workflow():
|
||||
# Task 1: Understand the problem
|
||||
understand_task = Task(
|
||||
name="understand_problem",
|
||||
description="""A farmer has a rectangular field. The length is 3 meters more than twice the width.
|
||||
If the perimeter is 96 meters, what are the dimensions of the field?""",
|
||||
expected_output="Clear problem statement with identified variables and equations",
|
||||
agent=problem_solver_agent
|
||||
)
|
||||
|
||||
# Task 2: Solve the problem
|
||||
solve_task = Task(
|
||||
name="solve_problem",
|
||||
description="Solve for the dimensions using the equations identified",
|
||||
expected_output="The width and length of the field with calculations shown",
|
||||
agent=calculation_agent,
|
||||
context=[understand_task]
|
||||
)
|
||||
|
||||
# Task 3: Verify and explain
|
||||
verify_task = Task(
|
||||
name="verify_solution",
|
||||
description="Verify the solution is correct and explain why it makes sense",
|
||||
expected_output="Verification that the solution satisfies all conditions",
|
||||
agent=math_tutor_agent,
|
||||
context=[solve_task]
|
||||
)
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[problem_solver_agent, calculation_agent, math_tutor_agent],
|
||||
tasks=[understand_task, solve_task, verify_task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
# General math assistant combining all capabilities
|
||||
math_assistant = Agent(
|
||||
name="MathAssistant",
|
||||
role="Comprehensive mathematics assistant",
|
||||
goal="Help with any mathematical task from basic arithmetic to complex problem solving",
|
||||
backstory="You are an AI math assistant with expertise in all areas of mathematics.",
|
||||
instructions="""You can help with:
|
||||
1. Basic arithmetic and calculations
|
||||
2. Algebra and equation solving
|
||||
3. Geometry and trigonometry
|
||||
4. Calculus and advanced mathematics
|
||||
5. Statistics and probability
|
||||
6. Math tutoring and explanations
|
||||
|
||||
Always show your work step by step.""",
|
||||
tools=[basic_calculator, solve_quadratic, calculate_statistics],
|
||||
self_reflect=True,
|
||||
min_reflect=1,
|
||||
max_reflect=3
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example 1: Basic calculation
|
||||
print("=== Basic Calculation ===")
|
||||
result = calculation_agent.start("Calculate: (15 + 23) * 4 - 18 / 3")
|
||||
print(result)
|
||||
|
||||
# Example 2: Quadratic equation
|
||||
print("\n=== Quadratic Equation ===")
|
||||
result = calculation_agent.start("Solve the equation: 2x² - 5x + 3 = 0")
|
||||
print(result)
|
||||
|
||||
# Example 3: Statistics
|
||||
print("\n=== Statistics ===")
|
||||
result = calculation_agent.start("Calculate statistics for: [12, 15, 18, 20, 22, 25, 28, 30]")
|
||||
print(result)
|
||||
|
||||
# Example 4: Complex problem workflow
|
||||
print("\n=== Complex Problem Workflow ===")
|
||||
result = solve_math_problem_workflow()
|
||||
print(f"Workflow Result: {result}")
|
||||
|
||||
# Example 5: General math assistance
|
||||
print("\n=== General Math Assistance ===")
|
||||
result = math_assistant.start("""
|
||||
I need help with this problem:
|
||||
A ball is thrown upward with an initial velocity of 20 m/s.
|
||||
The height h(t) = 20t - 5t² where t is time in seconds.
|
||||
|
||||
1. When does the ball reach maximum height?
|
||||
2. What is the maximum height?
|
||||
3. When does the ball hit the ground?
|
||||
""")
|
||||
print(result)
|
||||
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Chat with PDF Example
|
||||
|
||||
This example demonstrates how to create an agent that can read and answer questions about PDF documents.
|
||||
It uses the knowledge parameter to load PDF files and provides interactive Q&A capabilities.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Configure vector store for PDF storage
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"config": {
|
||||
"collection_name": "pdf_chat",
|
||||
"path": ".praison_pdf_chat",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Create a PDF chat agent
|
||||
pdf_agent = Agent(
|
||||
name="PDF Assistant",
|
||||
role="PDF document expert",
|
||||
goal="Help users understand and extract information from PDF documents",
|
||||
backstory="You are an expert at reading, analyzing, and answering questions about PDF documents. You provide accurate, detailed answers based on the document content.",
|
||||
instructions="Read the provided PDF document and answer questions about its content. Be specific and cite relevant sections when possible.",
|
||||
knowledge=["document.pdf"], # Replace with your PDF file path
|
||||
knowledge_config=config,
|
||||
self_reflect=True,
|
||||
min_reflect=1,
|
||||
max_reflect=3
|
||||
)
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
# Single question
|
||||
response = pdf_agent.start("What are the main topics covered in this document?")
|
||||
print(response)
|
||||
|
||||
# Interactive chat
|
||||
print("\nPDF Chat Assistant Ready! Type 'quit' to exit.")
|
||||
while True:
|
||||
question = input("\nYour question: ")
|
||||
if question.lower() == 'quit':
|
||||
break
|
||||
|
||||
response = pdf_agent.start(question)
|
||||
print(f"\nAnswer: {response}")
|
||||
@@ -0,0 +1,281 @@
|
||||
"""
|
||||
Reasoning Extraction Example
|
||||
|
||||
This example demonstrates how to extract and utilize reasoning patterns in PraisonAI:
|
||||
- Chain of Thought (CoT) reasoning
|
||||
- Step-by-step problem decomposition
|
||||
- Reasoning visualization
|
||||
- Decision rationale extraction
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from typing import Dict, List, Tuple
|
||||
from pydantic import BaseModel
|
||||
import json
|
||||
|
||||
# Pydantic models for structured reasoning
|
||||
class ReasoningStep(BaseModel):
|
||||
step_number: int
|
||||
description: str
|
||||
reasoning: str
|
||||
conclusion: str
|
||||
|
||||
class ChainOfThought(BaseModel):
|
||||
problem: str
|
||||
steps: List[ReasoningStep]
|
||||
final_answer: str
|
||||
confidence: float
|
||||
|
||||
# Tool for saving reasoning chains
|
||||
def save_reasoning_chain(chain: ChainOfThought) -> str:
|
||||
"""Save a chain of thought reasoning to analyze patterns."""
|
||||
filename = f"reasoning_{chain.problem[:20].replace(' ', '_')}.json"
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(chain.dict(), f, indent=2)
|
||||
return f"Reasoning chain saved to {filename}"
|
||||
|
||||
# Example 1: Chain of Thought Agent
|
||||
cot_agent = Agent(
|
||||
name="ChainOfThoughtAgent",
|
||||
role="Systematic reasoning specialist",
|
||||
goal="Solve problems using explicit chain of thought reasoning",
|
||||
backstory="You are a logic expert who breaks down complex problems into clear reasoning steps.",
|
||||
instructions="""When solving problems:
|
||||
1. State the problem clearly
|
||||
2. Break it down into logical steps
|
||||
3. Show your reasoning for each step
|
||||
4. Draw conclusions from each step
|
||||
5. Arrive at the final answer
|
||||
6. Assess your confidence level
|
||||
|
||||
Always make your thinking process explicit and transparent.""",
|
||||
self_reflect=True,
|
||||
min_reflect=2,
|
||||
max_reflect=3
|
||||
)
|
||||
|
||||
# Example 2: Reasoning Extractor Agent
|
||||
reasoning_extractor = Agent(
|
||||
name="ReasoningExtractor",
|
||||
role="Reasoning pattern analyzer",
|
||||
goal="Extract and analyze reasoning patterns from problem-solving processes",
|
||||
backstory="You specialize in understanding how problems are solved and extracting the underlying reasoning.",
|
||||
instructions="""Analyze the problem-solving process and extract:
|
||||
1. Key reasoning steps
|
||||
2. Decision points and rationale
|
||||
3. Assumptions made
|
||||
4. Logic patterns used
|
||||
5. Potential alternative approaches""",
|
||||
tools=[save_reasoning_chain]
|
||||
)
|
||||
|
||||
# Example 3: Multi-Step Reasoning Workflow
|
||||
def demonstrate_reasoning_extraction():
|
||||
"""Show how to extract reasoning from a complex problem-solving process."""
|
||||
|
||||
# Step 1: Present a complex problem
|
||||
problem_task = Task(
|
||||
name="solve_problem",
|
||||
description="""Solve this problem step by step:
|
||||
|
||||
A small tech startup has $50,000 budget for the next quarter.
|
||||
They need to decide between:
|
||||
1. Hiring 2 junior developers ($25,000 each)
|
||||
2. Hiring 1 senior developer ($40,000) + marketing budget ($10,000)
|
||||
3. Investing in AI tools ($30,000) + 1 junior developer ($20,000)
|
||||
|
||||
Consider: current team size is 3, main challenge is product development speed,
|
||||
but they also lack market visibility.""",
|
||||
expected_output="Detailed solution with reasoning for each consideration",
|
||||
agent=cot_agent,
|
||||
output_pydantic=ChainOfThought
|
||||
)
|
||||
|
||||
# Step 2: Extract reasoning patterns
|
||||
extract_task = Task(
|
||||
name="extract_reasoning",
|
||||
description="Extract and analyze the reasoning patterns used in solving the problem",
|
||||
expected_output="Structured analysis of reasoning patterns",
|
||||
agent=reasoning_extractor,
|
||||
context=[problem_task]
|
||||
)
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[cot_agent, reasoning_extractor],
|
||||
tasks=[problem_task, extract_task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
# Example 4: Socratic Reasoning Agent
|
||||
socratic_agent = Agent(
|
||||
name="SocraticReasoner",
|
||||
role="Socratic method practitioner",
|
||||
goal="Guide reasoning through questions and answers",
|
||||
backstory="You use the Socratic method to help uncover reasoning through thoughtful questions.",
|
||||
instructions="""Use the Socratic method:
|
||||
1. Ask clarifying questions
|
||||
2. Challenge assumptions
|
||||
3. Explore implications
|
||||
4. Consider alternatives
|
||||
5. Synthesize insights
|
||||
|
||||
Make the reasoning process interactive and exploratory."""
|
||||
)
|
||||
|
||||
# Example 5: Reasoning Validator
|
||||
reasoning_validator = Agent(
|
||||
name="ReasoningValidator",
|
||||
role="Logic and reasoning validator",
|
||||
goal="Validate reasoning chains for logical consistency",
|
||||
backstory="You are an expert at identifying logical fallacies and validating reasoning.",
|
||||
instructions="""Check reasoning for:
|
||||
1. Logical consistency
|
||||
2. Valid premises
|
||||
3. Sound conclusions
|
||||
4. Hidden assumptions
|
||||
5. Potential biases"""
|
||||
)
|
||||
|
||||
# Example 6: Advanced Reasoning Patterns
|
||||
def advanced_reasoning_patterns():
|
||||
"""Demonstrate different types of reasoning extraction."""
|
||||
|
||||
# Deductive reasoning
|
||||
deductive_task = Task(
|
||||
name="deductive_reasoning",
|
||||
description="""Use deductive reasoning to solve:
|
||||
All successful startups have strong leadership.
|
||||
Company X is a successful startup.
|
||||
What can we conclude about Company X?""",
|
||||
expected_output="Deductive reasoning chain with clear premises and conclusion",
|
||||
agent=cot_agent
|
||||
)
|
||||
|
||||
# Inductive reasoning
|
||||
inductive_task = Task(
|
||||
name="inductive_reasoning",
|
||||
description="""Use inductive reasoning based on these observations:
|
||||
- 5 observed AI companies grew 200% after implementing MLOps
|
||||
- 3 observed AI companies without MLOps grew only 50%
|
||||
What general conclusion might we draw?""",
|
||||
expected_output="Inductive reasoning with probability assessment",
|
||||
agent=cot_agent
|
||||
)
|
||||
|
||||
# Abductive reasoning
|
||||
abductive_task = Task(
|
||||
name="abductive_reasoning",
|
||||
description="""Use abductive reasoning:
|
||||
The server is down and users can't access the app.
|
||||
What are the most likely explanations?""",
|
||||
expected_output="Abductive reasoning with ranked hypotheses",
|
||||
agent=cot_agent
|
||||
)
|
||||
|
||||
# Validate all reasoning
|
||||
validation_task = Task(
|
||||
name="validate_reasoning",
|
||||
description="Validate all three reasoning approaches for logical soundness",
|
||||
expected_output="Validation report for each reasoning type",
|
||||
agent=reasoning_validator,
|
||||
context=[deductive_task, inductive_task, abductive_task]
|
||||
)
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[cot_agent, reasoning_validator],
|
||||
tasks=[deductive_task, inductive_task, abductive_task, validation_task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
# Example 7: Reasoning Patterns Library
|
||||
class ReasoningPattern:
|
||||
"""Base class for different reasoning patterns."""
|
||||
|
||||
@staticmethod
|
||||
def analogical_reasoning(source: str, target: str) -> str:
|
||||
"""Extract reasoning by analogy."""
|
||||
return f"If {source} works like X, then {target} might work like Y"
|
||||
|
||||
@staticmethod
|
||||
def causal_reasoning(cause: str, effect: str) -> str:
|
||||
"""Extract cause-effect reasoning."""
|
||||
return f"Because {cause}, therefore {effect}"
|
||||
|
||||
@staticmethod
|
||||
def counterfactual_reasoning(fact: str, alternative: str) -> str:
|
||||
"""Extract counterfactual reasoning."""
|
||||
return f"If {alternative} instead of {fact}, then what would change?"
|
||||
|
||||
# Specialized reasoning agent using patterns
|
||||
pattern_reasoning_agent = Agent(
|
||||
name="PatternReasoner",
|
||||
role="Reasoning pattern specialist",
|
||||
goal="Apply specific reasoning patterns to solve problems",
|
||||
backstory="You are an expert in various reasoning patterns and their applications.",
|
||||
instructions="""Apply these reasoning patterns as appropriate:
|
||||
1. Analogical: Find similar situations
|
||||
2. Causal: Identify cause-effect relationships
|
||||
3. Counterfactual: Explore what-if scenarios
|
||||
4. Systems thinking: Consider interconnections
|
||||
5. Probabilistic: Assess likelihoods""",
|
||||
self_reflect=True
|
||||
)
|
||||
|
||||
# Example 8: Interactive Reasoning Extraction
|
||||
def interactive_reasoning_demo():
|
||||
"""Interactive demonstration of reasoning extraction."""
|
||||
|
||||
print("=== Interactive Reasoning Extraction Demo ===\n")
|
||||
|
||||
# Problem categories
|
||||
problems = {
|
||||
"logical": "If all cats have tails, and Fluffy is a cat, what can we conclude?",
|
||||
"mathematical": "A store offers 20% off, then an additional 15% off. What's the total discount?",
|
||||
"strategic": "Should a startup focus on growth or profitability in its second year?",
|
||||
"ethical": "Is it ethical to use AI for hiring decisions?"
|
||||
}
|
||||
|
||||
for category, problem in problems.items():
|
||||
print(f"\n{category.upper()} REASONING:")
|
||||
print(f"Problem: {problem}")
|
||||
|
||||
# Extract reasoning
|
||||
result = cot_agent.start(f"Solve this {category} problem with clear reasoning: {problem}")
|
||||
print(f"Reasoning: {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Basic chain of thought demonstration
|
||||
print("=== Chain of Thought Reasoning ===")
|
||||
cot_result = cot_agent.start("""
|
||||
A company's revenue increased by 40% but profit decreased by 10%.
|
||||
What might this indicate about the company's situation?
|
||||
Show your reasoning step by step.
|
||||
""")
|
||||
print(cot_result)
|
||||
|
||||
# Reasoning extraction workflow
|
||||
print("\n=== Reasoning Extraction Workflow ===")
|
||||
extraction_result = demonstrate_reasoning_extraction()
|
||||
print(f"Result: {extraction_result}")
|
||||
|
||||
# Advanced reasoning patterns
|
||||
print("\n=== Advanced Reasoning Patterns ===")
|
||||
advanced_result = advanced_reasoning_patterns()
|
||||
print(f"Result: {advanced_result}")
|
||||
|
||||
# Interactive demo
|
||||
interactive_reasoning_demo()
|
||||
|
||||
# Summary
|
||||
print("\n=== Reasoning Extraction Benefits ===")
|
||||
print("1. Transparency: Makes decision-making process clear")
|
||||
print("2. Debugging: Helps identify where reasoning might be flawed")
|
||||
print("3. Learning: Extracts patterns for future use")
|
||||
print("4. Trust: Builds confidence through explainable AI")
|
||||
print("5. Improvement: Enables iterative refinement of reasoning")
|
||||
@@ -0,0 +1,299 @@
|
||||
"""
|
||||
Routing Patterns Example
|
||||
|
||||
This example demonstrates various routing patterns in PraisonAI including:
|
||||
- Conditional routing based on task outcomes
|
||||
- Loop patterns for iterative processing
|
||||
- Decision trees for complex workflows
|
||||
- Dynamic task selection
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from typing import Dict, Any
|
||||
import random
|
||||
|
||||
# Agents for different routing scenarios
|
||||
analyzer_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Data analyst",
|
||||
goal="Analyze input and determine appropriate routing",
|
||||
backstory="You are an expert at analyzing data and making routing decisions.",
|
||||
instructions="Analyze the input and determine the best path forward."
|
||||
)
|
||||
|
||||
processor_agent = Agent(
|
||||
name="Processor",
|
||||
role="Data processor",
|
||||
goal="Process data according to specific requirements",
|
||||
backstory="You specialize in processing different types of data.",
|
||||
instructions="Process the data based on the routing decision."
|
||||
)
|
||||
|
||||
validator_agent = Agent(
|
||||
name="Validator",
|
||||
role="Quality validator",
|
||||
goal="Validate processed data and determine if reprocessing is needed",
|
||||
backstory="You ensure data quality and correctness.",
|
||||
instructions="Validate the data and decide if it meets quality standards."
|
||||
)
|
||||
|
||||
# Example 1: Basic Conditional Routing
|
||||
def conditional_routing_example():
|
||||
"""Demonstrates routing based on analysis results."""
|
||||
|
||||
# Initial analysis task
|
||||
analysis_task = Task(
|
||||
name="analyze_data",
|
||||
description="Analyze the customer data and categorize as: high_value, medium_value, or low_value",
|
||||
expected_output="Customer category: high_value, medium_value, or low_value",
|
||||
agent=analyzer_agent,
|
||||
task_type="decision",
|
||||
condition={
|
||||
"high_value": ["premium_processing"],
|
||||
"medium_value": ["standard_processing"],
|
||||
"low_value": ["basic_processing"]
|
||||
}
|
||||
)
|
||||
|
||||
# Different processing paths
|
||||
premium_task = Task(
|
||||
name="premium_processing",
|
||||
description="Apply premium processing with personalized features",
|
||||
expected_output="Premium processed data with personalization",
|
||||
agent=processor_agent
|
||||
)
|
||||
|
||||
standard_task = Task(
|
||||
name="standard_processing",
|
||||
description="Apply standard processing",
|
||||
expected_output="Standard processed data",
|
||||
agent=processor_agent
|
||||
)
|
||||
|
||||
basic_task = Task(
|
||||
name="basic_processing",
|
||||
description="Apply basic processing",
|
||||
expected_output="Basic processed data",
|
||||
agent=processor_agent
|
||||
)
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[analyzer_agent, processor_agent],
|
||||
tasks=[analysis_task, premium_task, standard_task, basic_task],
|
||||
process="workflow",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
# Example 2: Loop Pattern with Exit Condition
|
||||
def loop_pattern_example():
|
||||
"""Demonstrates iterative processing with loop control."""
|
||||
|
||||
# Process items in a loop until quality threshold is met
|
||||
process_task = Task(
|
||||
name="process_batch",
|
||||
description="Process the current batch of items and check quality",
|
||||
expected_output="Processed batch with quality score",
|
||||
agent=processor_agent,
|
||||
task_type="loop",
|
||||
condition={
|
||||
"quality below threshold": ["process_batch"], # Loop back
|
||||
"quality meets threshold": ["finalize_batch"] # Exit loop
|
||||
}
|
||||
)
|
||||
|
||||
finalize_task = Task(
|
||||
name="finalize_batch",
|
||||
description="Finalize the batch processing and generate report",
|
||||
expected_output="Final batch report",
|
||||
agent=validator_agent
|
||||
)
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[processor_agent, validator_agent],
|
||||
tasks=[process_task, finalize_task],
|
||||
process="workflow",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
# Example 3: Complex Decision Tree
|
||||
def decision_tree_example():
|
||||
"""Demonstrates multi-level decision tree routing."""
|
||||
|
||||
# Level 1: Initial categorization
|
||||
categorize_task = Task(
|
||||
name="categorize_request",
|
||||
description="Categorize the request as: technical, business, or general",
|
||||
expected_output="Request category",
|
||||
agent=analyzer_agent,
|
||||
task_type="decision",
|
||||
condition={
|
||||
"technical": ["technical_analysis"],
|
||||
"business": ["business_analysis"],
|
||||
"general": ["general_handling"]
|
||||
}
|
||||
)
|
||||
|
||||
# Level 2: Technical branch
|
||||
technical_task = Task(
|
||||
name="technical_analysis",
|
||||
description="Analyze technical complexity: simple, moderate, or complex",
|
||||
expected_output="Technical complexity level",
|
||||
agent=analyzer_agent,
|
||||
task_type="decision",
|
||||
condition={
|
||||
"simple": ["quick_fix"],
|
||||
"moderate": ["standard_solution"],
|
||||
"complex": ["expert_consultation"]
|
||||
}
|
||||
)
|
||||
|
||||
# Level 2: Business branch
|
||||
business_task = Task(
|
||||
name="business_analysis",
|
||||
description="Analyze business impact: high, medium, or low",
|
||||
expected_output="Business impact level",
|
||||
agent=analyzer_agent,
|
||||
task_type="decision",
|
||||
condition={
|
||||
"high": ["executive_review"],
|
||||
"medium": ["manager_approval"],
|
||||
"low": ["auto_approve"]
|
||||
}
|
||||
)
|
||||
|
||||
# Terminal tasks
|
||||
terminal_tasks = [
|
||||
Task(name="general_handling", description="Handle general request",
|
||||
expected_output="General response", agent=processor_agent),
|
||||
Task(name="quick_fix", description="Apply quick fix",
|
||||
expected_output="Quick fix applied", agent=processor_agent),
|
||||
Task(name="standard_solution", description="Apply standard solution",
|
||||
expected_output="Standard solution applied", agent=processor_agent),
|
||||
Task(name="expert_consultation", description="Consult with expert",
|
||||
expected_output="Expert consultation result", agent=processor_agent),
|
||||
Task(name="executive_review", description="Send for executive review",
|
||||
expected_output="Executive decision", agent=processor_agent),
|
||||
Task(name="manager_approval", description="Send for manager approval",
|
||||
expected_output="Manager decision", agent=processor_agent),
|
||||
Task(name="auto_approve", description="Auto-approve request",
|
||||
expected_output="Auto-approved", agent=processor_agent)
|
||||
]
|
||||
|
||||
all_tasks = [categorize_task, technical_task, business_task] + terminal_tasks
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[analyzer_agent, processor_agent],
|
||||
tasks=all_tasks,
|
||||
process="workflow",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
# Example 4: Dynamic Router Agent
|
||||
dynamic_router = Agent(
|
||||
name="DynamicRouter",
|
||||
role="Intelligent routing specialist",
|
||||
goal="Dynamically route tasks based on complex conditions",
|
||||
backstory="You are an AI routing expert who can analyze multiple factors to determine optimal task paths.",
|
||||
instructions="""Analyze the input and determine routing based on:
|
||||
1. Content type and complexity
|
||||
2. Priority and urgency
|
||||
3. Available resources
|
||||
4. Historical performance
|
||||
5. Current system load
|
||||
|
||||
Provide clear routing decisions with reasoning.""",
|
||||
self_reflect=True
|
||||
)
|
||||
|
||||
def dynamic_routing_example():
|
||||
"""Demonstrates dynamic routing based on multiple factors."""
|
||||
|
||||
# Custom routing function
|
||||
def determine_route(task_output) -> str:
|
||||
"""Custom function to determine routing based on output."""
|
||||
# Simulate complex routing logic
|
||||
factors = task_output.raw.lower()
|
||||
|
||||
if "urgent" in factors and "complex" in factors:
|
||||
return "escalate"
|
||||
elif "simple" in factors:
|
||||
return "automate"
|
||||
elif "review" in factors:
|
||||
return "manual_review"
|
||||
else:
|
||||
return "standard"
|
||||
|
||||
# Dynamic routing task
|
||||
route_task = Task(
|
||||
name="dynamic_route",
|
||||
description="""Analyze this request and determine routing:
|
||||
- Request type: Customer complaint
|
||||
- Complexity: Moderate
|
||||
- Priority: Urgent
|
||||
- Customer tier: Premium""",
|
||||
expected_output="Routing decision with reasoning",
|
||||
agent=dynamic_router,
|
||||
task_type="decision",
|
||||
condition=determine_route # Use custom function for routing
|
||||
)
|
||||
|
||||
# Possible routes
|
||||
escalate_task = Task(
|
||||
name="escalate",
|
||||
description="Escalate to senior team",
|
||||
expected_output="Escalation complete",
|
||||
agent=processor_agent
|
||||
)
|
||||
|
||||
automate_task = Task(
|
||||
name="automate",
|
||||
description="Process automatically",
|
||||
expected_output="Automated processing complete",
|
||||
agent=processor_agent
|
||||
)
|
||||
|
||||
review_task = Task(
|
||||
name="manual_review",
|
||||
description="Send for manual review",
|
||||
expected_output="Manual review complete",
|
||||
agent=processor_agent
|
||||
)
|
||||
|
||||
standard_task = Task(
|
||||
name="standard",
|
||||
description="Standard processing",
|
||||
expected_output="Standard processing complete",
|
||||
agent=processor_agent
|
||||
)
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[dynamic_router, processor_agent],
|
||||
tasks=[route_task, escalate_task, automate_task, review_task, standard_task],
|
||||
process="workflow",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=== Conditional Routing Example ===")
|
||||
result = conditional_routing_example()
|
||||
print(f"Result: {result}\n")
|
||||
|
||||
print("=== Loop Pattern Example ===")
|
||||
result = loop_pattern_example()
|
||||
print(f"Result: {result}\n")
|
||||
|
||||
print("=== Decision Tree Example ===")
|
||||
result = decision_tree_example()
|
||||
print(f"Result: {result}\n")
|
||||
|
||||
print("=== Dynamic Routing Example ===")
|
||||
result = dynamic_routing_example()
|
||||
print(f"Result: {result}")
|
||||
@@ -0,0 +1,263 @@
|
||||
"""
|
||||
Self-Reflection Details Example
|
||||
|
||||
This example demonstrates the self-reflection capabilities in PraisonAI agents:
|
||||
- How self-reflection works
|
||||
- Configuring reflection parameters
|
||||
- Different reflection strategies
|
||||
- Impact on output quality
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from typing import Dict, Any
|
||||
import time
|
||||
|
||||
# Example 1: Basic Self-Reflection
|
||||
basic_reflection_agent = Agent(
|
||||
name="BasicReflector",
|
||||
role="Content creator with self-improvement",
|
||||
goal="Create high-quality content through iterative reflection",
|
||||
backstory="You are a perfectionist writer who reviews and improves your work multiple times.",
|
||||
instructions="""When creating content:
|
||||
1. Write your initial draft
|
||||
2. Review it critically
|
||||
3. Identify areas for improvement
|
||||
4. Revise and enhance
|
||||
5. Repeat until satisfied""",
|
||||
self_reflect=True, # Enable self-reflection
|
||||
min_reflect=1, # Minimum 1 reflection iteration
|
||||
max_reflect=3 # Maximum 3 reflection iterations
|
||||
)
|
||||
|
||||
# Example 2: Advanced Reflection with Different Strategies
|
||||
quality_focused_agent = Agent(
|
||||
name="QualityFocused",
|
||||
role="Quality-obsessed analyst",
|
||||
goal="Produce extremely high-quality analysis through deep reflection",
|
||||
backstory="You never settle for mediocre work and always strive for excellence.",
|
||||
instructions="""Your reflection process should focus on:
|
||||
- Accuracy and correctness
|
||||
- Completeness of analysis
|
||||
- Clarity of presentation
|
||||
- Logical flow
|
||||
- Supporting evidence""",
|
||||
self_reflect=True,
|
||||
min_reflect=3, # Higher minimum for quality
|
||||
max_reflect=5 # Allow more iterations
|
||||
)
|
||||
|
||||
efficiency_balanced_agent = Agent(
|
||||
name="EfficiencyBalanced",
|
||||
role="Balanced performer",
|
||||
goal="Achieve good quality with reasonable reflection time",
|
||||
backstory="You balance quality with efficiency, knowing when good enough is sufficient.",
|
||||
instructions="Create good content with 1-2 rounds of improvement.",
|
||||
self_reflect=True,
|
||||
min_reflect=1,
|
||||
max_reflect=2 # Limit iterations for efficiency
|
||||
)
|
||||
|
||||
# Example 3: No Reflection for Comparison
|
||||
no_reflection_agent = Agent(
|
||||
name="NoReflection",
|
||||
role="Quick responder",
|
||||
goal="Provide immediate responses without reflection",
|
||||
backstory="You provide quick, first-draft responses.",
|
||||
instructions="Respond immediately with your first thought.",
|
||||
self_reflect=False # Disable reflection
|
||||
)
|
||||
|
||||
# Demonstration function to show reflection in action
|
||||
def demonstrate_reflection_levels():
|
||||
"""Show how different reflection settings affect output quality."""
|
||||
|
||||
test_prompt = """Write a compelling product description for an innovative smart water bottle that:
|
||||
- Tracks hydration levels
|
||||
- Reminds users to drink water
|
||||
- Syncs with fitness apps
|
||||
- Has a 24-hour battery life"""
|
||||
|
||||
print("=== Testing Different Reflection Levels ===\n")
|
||||
|
||||
# Test without reflection
|
||||
print("1. WITHOUT REFLECTION:")
|
||||
start_time = time.time()
|
||||
result_no_reflect = no_reflection_agent.start(test_prompt)
|
||||
time_no_reflect = time.time() - start_time
|
||||
print(f"Time: {time_no_reflect:.2f}s")
|
||||
print(f"Result: {result_no_reflect}\n")
|
||||
|
||||
# Test with basic reflection
|
||||
print("2. BASIC REFLECTION (1-3 iterations):")
|
||||
start_time = time.time()
|
||||
result_basic = basic_reflection_agent.start(test_prompt)
|
||||
time_basic = time.time() - start_time
|
||||
print(f"Time: {time_basic:.2f}s")
|
||||
print(f"Result: {result_basic}\n")
|
||||
|
||||
# Test with quality-focused reflection
|
||||
print("3. QUALITY-FOCUSED REFLECTION (3-5 iterations):")
|
||||
start_time = time.time()
|
||||
result_quality = quality_focused_agent.start(test_prompt)
|
||||
time_quality = time.time() - start_time
|
||||
print(f"Time: {time_quality:.2f}s")
|
||||
print(f"Result: {result_quality}\n")
|
||||
|
||||
# Example 4: Reflection in Multi-Agent Workflows
|
||||
def reflection_workflow_example():
|
||||
"""Demonstrate how reflection works in multi-agent scenarios."""
|
||||
|
||||
# Initial creator with reflection
|
||||
creator_agent = Agent(
|
||||
name="Creator",
|
||||
role="Initial content creator",
|
||||
goal="Create first draft with self-improvement",
|
||||
backstory="You create initial drafts and refine them through reflection.",
|
||||
self_reflect=True,
|
||||
min_reflect=2,
|
||||
max_reflect=3
|
||||
)
|
||||
|
||||
# Reviewer without reflection (provides feedback)
|
||||
reviewer_agent = Agent(
|
||||
name="Reviewer",
|
||||
role="Content reviewer",
|
||||
goal="Provide constructive feedback",
|
||||
backstory="You review content and provide specific improvement suggestions.",
|
||||
self_reflect=False # No reflection needed for reviewing
|
||||
)
|
||||
|
||||
# Final polisher with reflection
|
||||
polisher_agent = Agent(
|
||||
name="Polisher",
|
||||
role="Final content polisher",
|
||||
goal="Perfect the content based on feedback",
|
||||
backstory="You take feedback and create the final, polished version.",
|
||||
self_reflect=True,
|
||||
min_reflect=1,
|
||||
max_reflect=2
|
||||
)
|
||||
|
||||
# Workflow tasks
|
||||
create_task = Task(
|
||||
name="create_content",
|
||||
description="Create a blog post about 'The Future of AI in Healthcare' (200 words)",
|
||||
expected_output="Initial blog post draft",
|
||||
agent=creator_agent
|
||||
)
|
||||
|
||||
review_task = Task(
|
||||
name="review_content",
|
||||
description="Review the blog post and provide specific feedback for improvement",
|
||||
expected_output="Detailed feedback with specific suggestions",
|
||||
agent=reviewer_agent,
|
||||
context=[create_task]
|
||||
)
|
||||
|
||||
polish_task = Task(
|
||||
name="polish_content",
|
||||
description="Create the final version incorporating all feedback",
|
||||
expected_output="Polished final blog post",
|
||||
agent=polisher_agent,
|
||||
context=[create_task, review_task]
|
||||
)
|
||||
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[creator_agent, reviewer_agent, polisher_agent],
|
||||
tasks=[create_task, review_task, polish_task],
|
||||
process="sequential",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
return workflow.start()
|
||||
|
||||
# Example 5: Custom Reflection Control
|
||||
class ReflectionController:
|
||||
"""Custom controller to demonstrate programmatic reflection control."""
|
||||
|
||||
def __init__(self):
|
||||
self.iteration_count = 0
|
||||
self.quality_threshold = 0.8
|
||||
|
||||
def should_continue_reflecting(self, current_output: str) -> bool:
|
||||
"""Custom logic to determine if more reflection is needed."""
|
||||
self.iteration_count += 1
|
||||
|
||||
# Simple quality check (in practice, this could be more sophisticated)
|
||||
quality_indicators = [
|
||||
len(current_output) > 100,
|
||||
'.' in current_output,
|
||||
any(word in current_output.lower() for word in ['innovative', 'comprehensive', 'detailed'])
|
||||
]
|
||||
|
||||
quality_score = sum(quality_indicators) / len(quality_indicators)
|
||||
|
||||
return quality_score < self.quality_threshold and self.iteration_count < 5
|
||||
|
||||
# Agent with custom reflection behavior
|
||||
custom_reflection_agent = Agent(
|
||||
name="CustomReflector",
|
||||
role="Adaptive content creator",
|
||||
goal="Create content with dynamic reflection based on quality",
|
||||
backstory="You adapt your reflection process based on content quality.",
|
||||
instructions="""Create content and reflect on it.
|
||||
Continue improving until quality standards are met or maximum iterations reached.""",
|
||||
self_reflect=True,
|
||||
min_reflect=1,
|
||||
max_reflect=5
|
||||
)
|
||||
|
||||
# Example 6: Reflection Impact Analysis
|
||||
def analyze_reflection_impact():
|
||||
"""Analyze and visualize the impact of reflection on output."""
|
||||
|
||||
test_cases = [
|
||||
"Explain quantum computing in one sentence",
|
||||
"Write a haiku about artificial intelligence",
|
||||
"Create a tagline for a sustainable energy company"
|
||||
]
|
||||
|
||||
results = []
|
||||
|
||||
for test in test_cases:
|
||||
print(f"\nTest Case: {test}")
|
||||
print("-" * 50)
|
||||
|
||||
# Without reflection
|
||||
result_no = no_reflection_agent.start(test)
|
||||
|
||||
# With reflection
|
||||
result_yes = quality_focused_agent.start(test)
|
||||
|
||||
results.append({
|
||||
'test': test,
|
||||
'without_reflection': result_no,
|
||||
'with_reflection': result_yes,
|
||||
'improvement': len(result_yes) > len(result_no) # Simple metric
|
||||
})
|
||||
|
||||
print(f"Without Reflection: {result_no}")
|
||||
print(f"With Reflection: {result_yes}")
|
||||
|
||||
return results
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Demonstrate different reflection levels
|
||||
demonstrate_reflection_levels()
|
||||
|
||||
# Show reflection in workflows
|
||||
print("\n=== Reflection in Multi-Agent Workflow ===")
|
||||
workflow_result = reflection_workflow_example()
|
||||
print(f"Workflow Result: {workflow_result}")
|
||||
|
||||
# Analyze reflection impact
|
||||
print("\n=== Reflection Impact Analysis ===")
|
||||
impact_results = analyze_reflection_impact()
|
||||
|
||||
# Summary
|
||||
print("\n=== Summary of Reflection Benefits ===")
|
||||
print("1. Improved Quality: Reflection iterations allow agents to refine their outputs")
|
||||
print("2. Error Correction: Agents can catch and fix mistakes through self-review")
|
||||
print("3. Completeness: Multiple passes ensure all requirements are addressed")
|
||||
print("4. Coherence: Reflection improves logical flow and consistency")
|
||||
print("5. Customization: Reflection parameters can be tuned for different use cases")
|
||||
@@ -0,0 +1,226 @@
|
||||
# Minimal Latency Tracking for PraisonAI MCP Server
|
||||
|
||||
This solution provides latency tracking for MCP servers without modifying any PraisonAI core files. It's implemented as a custom tool that can be used externally.
|
||||
|
||||
## Overview
|
||||
|
||||
The latency tracking solution measures three key phases:
|
||||
1. **Planning Process** - Time taken for agent planning and decision making
|
||||
2. **Tool Usage** - Time spent executing tools
|
||||
3. **LLM Answer Generation** - Time spent generating responses
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Option 1: Use as a Custom Tool
|
||||
|
||||
```python
|
||||
from latency_tracker_tool import latency_tracking_tool
|
||||
|
||||
# Add to your agent
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
role="Helper",
|
||||
tools=[latency_tracking_tool]
|
||||
)
|
||||
|
||||
# Track manually
|
||||
latency_tracking_tool("start", "planning", "request_1")
|
||||
response = agent.chat("Your query")
|
||||
latency_tracking_tool("end", "planning", "request_1")
|
||||
|
||||
# Get metrics
|
||||
metrics = latency_tracking_tool("metrics", request_id="request_1")
|
||||
```
|
||||
|
||||
### Option 2: Use Context Managers
|
||||
|
||||
```python
|
||||
from latency_tracker_tool import tracker
|
||||
|
||||
# Track with context manager
|
||||
with tracker.track("planning", "request_1"):
|
||||
response = agent.chat("Your query")
|
||||
|
||||
# Get metrics
|
||||
metrics = tracker.get_metrics("request_1")
|
||||
```
|
||||
|
||||
### Option 3: Use Wrapper Classes
|
||||
|
||||
```python
|
||||
from latency_tracker_tool import create_tracked_agent
|
||||
|
||||
# Create tracked agent class
|
||||
TrackedAgent = create_tracked_agent(Agent)
|
||||
|
||||
# Use like normal agent
|
||||
agent = TrackedAgent(
|
||||
name="Assistant",
|
||||
role="Helper",
|
||||
request_id="request_1"
|
||||
)
|
||||
|
||||
# Operations are automatically tracked
|
||||
response = agent.chat("Your query")
|
||||
```
|
||||
|
||||
## MCP Server Integration
|
||||
|
||||
### Basic MCP Tracking
|
||||
|
||||
```python
|
||||
from latency_tracker_tool import tracker
|
||||
|
||||
def handle_mcp_request(request_data):
|
||||
request_id = request_data.get('id', 'default')
|
||||
|
||||
with tracker.track("total_request", request_id):
|
||||
# Track planning
|
||||
with tracker.track("planning", request_id):
|
||||
plan = create_plan(request_data)
|
||||
|
||||
# Track tool usage
|
||||
with tracker.track("tool_usage", request_id):
|
||||
tool_results = execute_tools(plan)
|
||||
|
||||
# Track LLM generation
|
||||
with tracker.track("llm_generation", request_id):
|
||||
response = generate_response(tool_results)
|
||||
|
||||
# Include metrics in response
|
||||
metrics = tracker.get_metrics(request_id)
|
||||
return {
|
||||
"response": response,
|
||||
"latency_metrics": metrics
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced MCP Server Wrapper
|
||||
|
||||
```python
|
||||
from latency_tracker_tool import tracker
|
||||
|
||||
def add_tracking_to_mcp_server(mcp_server):
|
||||
"""Add tracking to existing MCP server."""
|
||||
original_handle = mcp_server.handle_request
|
||||
|
||||
def tracked_handle(request_data):
|
||||
request_id = request_data.get('id', 'mcp_request')
|
||||
|
||||
with tracker.track("mcp_total", request_id):
|
||||
response = original_handle(request_data)
|
||||
|
||||
return response
|
||||
|
||||
mcp_server.handle_request = tracked_handle
|
||||
return mcp_server
|
||||
```
|
||||
|
||||
## Tools with Built-in Tracking
|
||||
|
||||
Create a `tools.py` file in your project root:
|
||||
|
||||
```python
|
||||
from latency_tracker_tool import track_latency, tracker
|
||||
|
||||
@track_latency("tool_search", "current_request")
|
||||
def search_tool(query: str) -> str:
|
||||
"""Search with automatic latency tracking."""
|
||||
# Your search logic
|
||||
return results
|
||||
|
||||
def get_latency_report(request_id: str = "current_request") -> str:
|
||||
"""Get latency metrics as a tool."""
|
||||
metrics = tracker.get_metrics(request_id)
|
||||
# Format and return report
|
||||
return formatted_report
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### LatencyTracker Class
|
||||
|
||||
- `start_timer(phase, request_id)` - Start timing a phase
|
||||
- `end_timer(phase, request_id)` - End timing and return elapsed time
|
||||
- `track(phase, request_id)` - Context manager for tracking
|
||||
- `get_metrics(request_id)` - Get metrics for a request
|
||||
- `get_summary()` - Get summary of all requests
|
||||
- `clear(request_id)` - Clear tracking data
|
||||
|
||||
### Metrics Format
|
||||
|
||||
```json
|
||||
{
|
||||
"planning": {
|
||||
"count": 1,
|
||||
"total": 1.234,
|
||||
"average": 1.234,
|
||||
"min": 1.234,
|
||||
"max": 1.234,
|
||||
"latest": 1.234
|
||||
},
|
||||
"tool_usage": {
|
||||
"count": 3,
|
||||
"total": 0.567,
|
||||
"average": 0.189,
|
||||
"min": 0.150,
|
||||
"max": 0.250,
|
||||
"latest": 0.167
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
See the following example files:
|
||||
- `example_latency_tracking.py` - Basic usage examples
|
||||
- `mcp_server_latency_example.py` - MCP server integration
|
||||
- `tools_with_latency.py` - Tools with built-in tracking
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **No Core Modifications** - Works without changing PraisonAI source code
|
||||
2. **Flexible** - Multiple ways to integrate (tool, decorator, wrapper, context manager)
|
||||
3. **Thread-Safe** - Supports concurrent requests
|
||||
4. **Minimal Overhead** - Lightweight tracking with negligible performance impact
|
||||
5. **Extensible** - Easy to add custom phases and metrics
|
||||
|
||||
## Use Cases
|
||||
|
||||
1. **Performance Monitoring** - Track and optimize MCP server performance
|
||||
2. **Debugging** - Identify bottlenecks in request processing
|
||||
3. **SLA Monitoring** - Ensure response times meet requirements
|
||||
4. **Capacity Planning** - Understand resource usage patterns
|
||||
5. **A/B Testing** - Compare performance of different implementations
|
||||
|
||||
## Tips
|
||||
|
||||
1. Use unique request IDs for concurrent request tracking
|
||||
2. Clear old tracking data periodically to free memory
|
||||
3. Add tracking to critical paths only to minimize overhead
|
||||
4. Use phase names consistently across your application
|
||||
5. Consider logging metrics for long-term analysis
|
||||
|
||||
## Integration with Existing Monitoring
|
||||
|
||||
The metrics can be easily exported to monitoring systems:
|
||||
|
||||
```python
|
||||
# Export to Prometheus
|
||||
def export_to_prometheus():
|
||||
summary = tracker.get_summary()
|
||||
# Convert to Prometheus format
|
||||
|
||||
# Export to CloudWatch
|
||||
def export_to_cloudwatch():
|
||||
metrics = tracker.get_metrics()
|
||||
# Send to CloudWatch
|
||||
|
||||
# Export to custom logging
|
||||
import json
|
||||
import logging
|
||||
|
||||
def log_metrics(request_id):
|
||||
metrics = tracker.get_metrics(request_id)
|
||||
logging.info(f"Latency metrics: {json.dumps(metrics)}")
|
||||
```
|
||||
@@ -0,0 +1,195 @@
|
||||
"""
|
||||
Example: Using Latency Tracking Tool with PraisonAI
|
||||
|
||||
This example shows how to track latency without modifying core files.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
from latency_tracker_tool import (
|
||||
latency_tracking_tool,
|
||||
create_tracked_agent,
|
||||
create_tracked_llm,
|
||||
tracker,
|
||||
get_latency_metrics,
|
||||
get_latency_summary
|
||||
)
|
||||
import json
|
||||
|
||||
|
||||
# Example 1: Using the latency tracking tool directly with agents
|
||||
def example_with_tool():
|
||||
"""Example using latency_tracking_tool as a custom tool."""
|
||||
print("=== Example 1: Using Latency Tracking Tool ===\n")
|
||||
|
||||
# Create an agent with the latency tracking tool
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Information Researcher",
|
||||
goal="Research and provide information",
|
||||
tools=[latency_tracking_tool], # Add our custom tool
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
|
||||
# Start tracking manually
|
||||
latency_tracking_tool("start", "planning", "request_1")
|
||||
|
||||
# Agent performs task
|
||||
response = researcher.chat("What is the capital of France?")
|
||||
|
||||
# End tracking
|
||||
latency_tracking_tool("end", "planning", "request_1")
|
||||
|
||||
# Get metrics
|
||||
metrics_json = latency_tracking_tool("metrics", request_id="request_1")
|
||||
metrics = json.loads(metrics_json)
|
||||
|
||||
print(f"Response: {response}")
|
||||
print(f"Metrics: {json.dumps(metrics, indent=2)}")
|
||||
|
||||
|
||||
# Example 2: Using wrapper classes for automatic tracking
|
||||
def example_with_wrappers():
|
||||
"""Example using wrapper classes for automatic tracking."""
|
||||
print("\n=== Example 2: Using Wrapper Classes ===\n")
|
||||
|
||||
# Create tracked agent class
|
||||
TrackedAgent = create_tracked_agent(Agent)
|
||||
|
||||
# Create agent with tracking
|
||||
analyst = TrackedAgent(
|
||||
name="Analyst",
|
||||
role="Data Analyst",
|
||||
goal="Analyze data and provide insights",
|
||||
llm="gpt-4o-mini",
|
||||
request_id="request_2" # Unique request ID
|
||||
)
|
||||
|
||||
# Operations are automatically tracked
|
||||
response = analyst.chat("Calculate the sum of 1 to 10")
|
||||
|
||||
# Get metrics
|
||||
metrics = get_latency_metrics("request_2")
|
||||
|
||||
print(f"Response: {response}")
|
||||
print(f"Metrics: {json.dumps(metrics, indent=2)}")
|
||||
|
||||
|
||||
# Example 3: Using context manager for fine-grained tracking
|
||||
def example_with_context_manager():
|
||||
"""Example using context manager for custom phase tracking."""
|
||||
print("\n=== Example 3: Using Context Manager ===\n")
|
||||
|
||||
agent = Agent(
|
||||
name="Calculator",
|
||||
role="Math Expert",
|
||||
goal="Solve mathematical problems",
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
|
||||
request_id = "request_3"
|
||||
|
||||
# Track different phases manually
|
||||
with tracker.track("initialization", request_id):
|
||||
# Simulate initialization
|
||||
pass
|
||||
|
||||
with tracker.track("planning", request_id):
|
||||
response = agent.chat("What is 15% of 200?")
|
||||
|
||||
with tracker.track("post_processing", request_id):
|
||||
# Simulate post-processing
|
||||
result = f"Formatted result: {response}"
|
||||
|
||||
# Get comprehensive metrics
|
||||
metrics = get_latency_metrics(request_id)
|
||||
|
||||
print(f"Result: {result}")
|
||||
print(f"Metrics by phase:")
|
||||
for phase, data in metrics.items():
|
||||
print(f" {phase}: {data['total']:.3f}s")
|
||||
|
||||
|
||||
# Example 4: Tracking MCP server requests
|
||||
def example_mcp_tracking():
|
||||
"""Example for tracking MCP server operations."""
|
||||
print("\n=== Example 4: MCP Server Tracking ===\n")
|
||||
|
||||
# Simulate MCP server request handling
|
||||
request_id = "mcp_request_1"
|
||||
|
||||
# Start tracking the entire request
|
||||
with tracker.track("total_request", request_id):
|
||||
|
||||
# Track planning phase
|
||||
with tracker.track("planning", request_id):
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
role="MCP Assistant",
|
||||
goal="Handle MCP requests",
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
plan = agent.chat("Plan: Search for Python documentation")
|
||||
|
||||
# Track tool usage
|
||||
with tracker.track("tool_usage", request_id):
|
||||
# Simulate tool execution
|
||||
tool_result = "Found 5 relevant documentation pages"
|
||||
|
||||
# Track LLM generation
|
||||
with tracker.track("llm_generation", request_id):
|
||||
final_response = agent.chat(f"Based on {tool_result}, provide a summary")
|
||||
|
||||
# Get detailed metrics
|
||||
metrics = get_latency_metrics(request_id)
|
||||
|
||||
print("MCP Request Metrics:")
|
||||
print(f"Total time: {metrics['total_request']['total']:.3f}s")
|
||||
print(f"Breakdown:")
|
||||
for phase in ['planning', 'tool_usage', 'llm_generation']:
|
||||
if phase in metrics:
|
||||
print(f" - {phase}: {metrics[phase]['total']:.3f}s")
|
||||
|
||||
|
||||
# Example 5: Tracking multiple concurrent requests
|
||||
def example_concurrent_tracking():
|
||||
"""Example tracking multiple concurrent requests."""
|
||||
print("\n=== Example 5: Concurrent Request Tracking ===\n")
|
||||
|
||||
# Simulate multiple MCP requests
|
||||
for i in range(3):
|
||||
request_id = f"concurrent_{i}"
|
||||
|
||||
with tracker.track("total", request_id):
|
||||
agent = Agent(
|
||||
name=f"Agent_{i}",
|
||||
role="Concurrent Worker",
|
||||
goal="Process requests concurrently",
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
|
||||
with tracker.track("processing", request_id):
|
||||
agent.chat(f"Process request {i}")
|
||||
|
||||
# Get summary of all requests
|
||||
summary = get_latency_summary()
|
||||
|
||||
print("Summary of all requests:")
|
||||
print(json.dumps(summary, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run all examples
|
||||
example_with_tool()
|
||||
example_with_wrappers()
|
||||
example_with_context_manager()
|
||||
example_mcp_tracking()
|
||||
example_concurrent_tracking()
|
||||
|
||||
# Final summary
|
||||
print("\n=== Final Summary ===")
|
||||
final_summary = get_latency_summary()
|
||||
print(f"Total requests tracked: {len(final_summary)}")
|
||||
|
||||
# Clear all tracking data
|
||||
tracker.clear()
|
||||
print("\nAll tracking data cleared.")
|
||||
@@ -0,0 +1,210 @@
|
||||
"""
|
||||
Minimal Latency Tracking Tool for PraisonAI MCP Server
|
||||
|
||||
This tool provides latency tracking without modifying core files.
|
||||
It uses decorators and wrapper functions to track execution times
|
||||
for planning, tool usage, and LLM generation phases.
|
||||
"""
|
||||
|
||||
import time
|
||||
import json
|
||||
import threading
|
||||
from typing import Dict, Any, Callable, Optional
|
||||
from functools import wraps
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
class LatencyTracker:
|
||||
"""Minimal latency tracking tool for MCP server operations."""
|
||||
|
||||
def __init__(self):
|
||||
self._data = {}
|
||||
self._lock = threading.Lock()
|
||||
self._active_timers = {}
|
||||
|
||||
def start_timer(self, phase: str, request_id: str = "default"):
|
||||
"""Start timing a phase."""
|
||||
with self._lock:
|
||||
key = f"{request_id}_{phase}"
|
||||
self._active_timers[key] = time.time()
|
||||
|
||||
def end_timer(self, phase: str, request_id: str = "default") -> float:
|
||||
"""End timing a phase and return elapsed time."""
|
||||
with self._lock:
|
||||
key = f"{request_id}_{phase}"
|
||||
if key not in self._active_timers:
|
||||
return 0.0
|
||||
|
||||
elapsed = time.time() - self._active_timers[key]
|
||||
del self._active_timers[key]
|
||||
|
||||
# Store the timing
|
||||
if request_id not in self._data:
|
||||
self._data[request_id] = {}
|
||||
if phase not in self._data[request_id]:
|
||||
self._data[request_id][phase] = []
|
||||
self._data[request_id][phase].append(elapsed)
|
||||
|
||||
return elapsed
|
||||
|
||||
@contextmanager
|
||||
def track(self, phase: str, request_id: str = "default"):
|
||||
"""Context manager for tracking a phase."""
|
||||
self.start_timer(phase, request_id)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
self.end_timer(phase, request_id)
|
||||
|
||||
def get_metrics(self, request_id: str = "default") -> Dict[str, Any]:
|
||||
"""Get metrics for a specific request."""
|
||||
with self._lock:
|
||||
if request_id not in self._data:
|
||||
return {}
|
||||
|
||||
metrics = {}
|
||||
for phase, timings in self._data[request_id].items():
|
||||
if timings:
|
||||
metrics[phase] = {
|
||||
'count': len(timings),
|
||||
'total': sum(timings),
|
||||
'average': sum(timings) / len(timings),
|
||||
'min': min(timings),
|
||||
'max': max(timings),
|
||||
'latest': timings[-1]
|
||||
}
|
||||
return metrics
|
||||
|
||||
def get_summary(self) -> Dict[str, Any]:
|
||||
"""Get summary of all tracked requests."""
|
||||
with self._lock:
|
||||
summary = {}
|
||||
for request_id, phases in self._data.items():
|
||||
summary[request_id] = self.get_metrics(request_id)
|
||||
return summary
|
||||
|
||||
def clear(self, request_id: Optional[str] = None):
|
||||
"""Clear tracking data."""
|
||||
with self._lock:
|
||||
if request_id:
|
||||
self._data.pop(request_id, None)
|
||||
else:
|
||||
self._data.clear()
|
||||
self._active_timers.clear()
|
||||
|
||||
|
||||
# Global tracker instance
|
||||
tracker = LatencyTracker()
|
||||
|
||||
|
||||
def track_latency(phase: str, request_id: str = "default"):
|
||||
"""Decorator to track function execution latency."""
|
||||
def decorator(func: Callable) -> Callable:
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
with tracker.track(phase, request_id):
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def create_tracked_agent(agent_class):
|
||||
"""Create a wrapper class that tracks agent operations."""
|
||||
class TrackedAgent(agent_class):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._request_id = kwargs.get('request_id', 'default')
|
||||
|
||||
def chat(self, *args, **kwargs):
|
||||
"""Tracked chat method for planning phase."""
|
||||
with tracker.track('planning', self._request_id):
|
||||
return super().chat(*args, **kwargs)
|
||||
|
||||
def execute_tool(self, *args, **kwargs):
|
||||
"""Tracked execute_tool method."""
|
||||
with tracker.track('tool_usage', self._request_id):
|
||||
return super().execute_tool(*args, **kwargs)
|
||||
|
||||
return TrackedAgent
|
||||
|
||||
|
||||
def create_tracked_llm(llm_class):
|
||||
"""Create a wrapper class that tracks LLM operations."""
|
||||
class TrackedLLM(llm_class):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._request_id = kwargs.get('request_id', 'default')
|
||||
|
||||
def get_response(self, *args, **kwargs):
|
||||
"""Tracked get_response method for LLM generation."""
|
||||
with tracker.track('llm_generation', self._request_id):
|
||||
return super().get_response(*args, **kwargs)
|
||||
|
||||
return TrackedLLM
|
||||
|
||||
|
||||
# Custom tool function for manual tracking
|
||||
def latency_tracking_tool(action: str, phase: str = "", request_id: str = "default") -> str:
|
||||
"""
|
||||
Manual latency tracking tool for PraisonAI agents.
|
||||
|
||||
Args:
|
||||
action: One of 'start', 'end', 'metrics', 'summary', 'clear'
|
||||
phase: Phase name (for 'start' and 'end' actions)
|
||||
request_id: Request identifier for tracking
|
||||
|
||||
Returns:
|
||||
str: JSON string with results
|
||||
"""
|
||||
if action == "start":
|
||||
if not phase:
|
||||
return json.dumps({"error": "Phase name required for start action"})
|
||||
tracker.start_timer(phase, request_id)
|
||||
return json.dumps({"status": "started", "phase": phase, "request_id": request_id})
|
||||
|
||||
elif action == "end":
|
||||
if not phase:
|
||||
return json.dumps({"error": "Phase name required for end action"})
|
||||
elapsed = tracker.end_timer(phase, request_id)
|
||||
return json.dumps({
|
||||
"status": "ended",
|
||||
"phase": phase,
|
||||
"request_id": request_id,
|
||||
"elapsed": elapsed
|
||||
})
|
||||
|
||||
elif action == "metrics":
|
||||
metrics = tracker.get_metrics(request_id)
|
||||
return json.dumps({"request_id": request_id, "metrics": metrics})
|
||||
|
||||
elif action == "summary":
|
||||
summary = tracker.get_summary()
|
||||
return json.dumps({"summary": summary})
|
||||
|
||||
elif action == "clear":
|
||||
tracker.clear(request_id)
|
||||
return json.dumps({"status": "cleared", "request_id": request_id})
|
||||
|
||||
else:
|
||||
return json.dumps({"error": f"Unknown action: {action}"})
|
||||
|
||||
|
||||
# Convenience functions for external use
|
||||
def start_tracking(phase: str, request_id: str = "default"):
|
||||
"""Start tracking a phase."""
|
||||
tracker.start_timer(phase, request_id)
|
||||
|
||||
|
||||
def end_tracking(phase: str, request_id: str = "default") -> float:
|
||||
"""End tracking a phase and return elapsed time."""
|
||||
return tracker.end_timer(phase, request_id)
|
||||
|
||||
|
||||
def get_latency_metrics(request_id: str = "default") -> Dict[str, Any]:
|
||||
"""Get latency metrics for a request."""
|
||||
return tracker.get_metrics(request_id)
|
||||
|
||||
|
||||
def get_latency_summary() -> Dict[str, Any]:
|
||||
"""Get summary of all latency tracking."""
|
||||
return tracker.get_summary()
|
||||
@@ -0,0 +1,173 @@
|
||||
"""
|
||||
MCP Server with Latency Tracking Example
|
||||
|
||||
This shows how to add latency tracking to an MCP server
|
||||
without modifying PraisonAI core files.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
from praisonaiagents.mcp import HostedMCPServer
|
||||
from latency_tracker_tool import tracker, get_latency_metrics
|
||||
import json
|
||||
|
||||
|
||||
class LatencyTrackedMCPServer(HostedMCPServer):
|
||||
"""MCP Server with built-in latency tracking."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Import and use the original agents, not wrapped ones
|
||||
self._original_handle_request = self.handle_request
|
||||
self.handle_request = self._tracked_handle_request
|
||||
|
||||
def _tracked_handle_request(self, request_data):
|
||||
"""Wrapped request handler with latency tracking."""
|
||||
request_id = request_data.get('id', 'mcp_request')
|
||||
|
||||
# Track the entire request
|
||||
with tracker.track("mcp_total_request", request_id):
|
||||
# Call original handler
|
||||
response = self._original_handle_request(request_data)
|
||||
|
||||
# Add latency metrics to response if requested
|
||||
if request_data.get('include_latency_metrics', False):
|
||||
metrics = get_latency_metrics(request_id)
|
||||
response['latency_metrics'] = metrics
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def create_mcp_agent_with_tracking(request_id: str = "mcp_request"):
|
||||
"""Create an agent that tracks its operations."""
|
||||
|
||||
class TrackedOperationAgent(Agent):
|
||||
"""Agent that tracks planning, tool usage, and LLM calls."""
|
||||
|
||||
def chat(self, *args, **kwargs):
|
||||
with tracker.track("planning", request_id):
|
||||
return super().chat(*args, **kwargs)
|
||||
|
||||
def execute_tool(self, *args, **kwargs):
|
||||
with tracker.track("tool_usage", request_id):
|
||||
return super().execute_tool(*args, **kwargs)
|
||||
|
||||
# Create the tracked agent
|
||||
agent = TrackedOperationAgent(
|
||||
name="MCPAssistant",
|
||||
role="MCP Request Handler",
|
||||
goal="Handle MCP requests with latency tracking",
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
|
||||
return agent
|
||||
|
||||
|
||||
# Example usage for MCP server operators
|
||||
def example_mcp_with_tracking():
|
||||
"""Example showing how to use latency tracking with MCP server."""
|
||||
|
||||
print("=== MCP Server Latency Tracking Example ===\n")
|
||||
|
||||
# Simulate handling an MCP request
|
||||
request_id = "mcp_example_1"
|
||||
|
||||
# Create tracked agent
|
||||
agent = create_mcp_agent_with_tracking(request_id)
|
||||
|
||||
# Simulate the three phases mentioned in the issue
|
||||
print("1. Planning Phase:")
|
||||
with tracker.track("planning", request_id):
|
||||
planning_result = agent.chat("Plan how to search for Python async documentation")
|
||||
print(f" Plan: {planning_result[:100]}...")
|
||||
|
||||
print("\n2. Tool Usage Phase:")
|
||||
# If you have actual tools, they would be executed here
|
||||
with tracker.track("tool_usage", request_id):
|
||||
# Simulate tool execution
|
||||
import time
|
||||
time.sleep(0.1) # Simulate tool delay
|
||||
tool_result = "Found 10 documentation pages about Python async"
|
||||
print(f" Tool result: {tool_result}")
|
||||
|
||||
print("\n3. LLM Answer Generation Phase:")
|
||||
with tracker.track("llm_generation", request_id):
|
||||
final_answer = agent.chat(f"Based on finding that {tool_result}, provide a concise summary")
|
||||
print(f" Answer: {final_answer[:100]}...")
|
||||
|
||||
# Get and display metrics
|
||||
print("\n=== Latency Metrics ===")
|
||||
metrics = get_latency_metrics(request_id)
|
||||
|
||||
for phase, data in metrics.items():
|
||||
print(f"{phase}:")
|
||||
print(f" - Total time: {data['total']:.3f}s")
|
||||
print(f" - Count: {data['count']}")
|
||||
print(f" - Average: {data['average']:.3f}s")
|
||||
|
||||
# Calculate total time
|
||||
total_time = sum(data['total'] for data in metrics.values())
|
||||
print(f"\nTotal execution time: {total_time:.3f}s")
|
||||
|
||||
# Show percentage breakdown
|
||||
print("\nTime breakdown:")
|
||||
for phase, data in metrics.items():
|
||||
percentage = (data['total'] / total_time) * 100
|
||||
print(f" - {phase}: {percentage:.1f}%")
|
||||
|
||||
|
||||
# Function to wrap existing MCP server with tracking
|
||||
def add_tracking_to_mcp_server(mcp_server):
|
||||
"""Add latency tracking to an existing MCP server instance."""
|
||||
|
||||
original_handle = mcp_server.handle_request
|
||||
|
||||
def tracked_handle(request_data):
|
||||
request_id = request_data.get('id', 'mcp_request')
|
||||
|
||||
with tracker.track("mcp_request_total", request_id):
|
||||
# You can add more granular tracking here based on request type
|
||||
request_type = request_data.get('method', 'unknown')
|
||||
|
||||
with tracker.track(f"mcp_{request_type}", request_id):
|
||||
response = original_handle(request_data)
|
||||
|
||||
return response
|
||||
|
||||
mcp_server.handle_request = tracked_handle
|
||||
return mcp_server
|
||||
|
||||
|
||||
# Utility function for MCP server monitoring
|
||||
def get_mcp_latency_summary():
|
||||
"""Get a formatted summary of MCP server latency."""
|
||||
|
||||
summary = tracker.get_summary()
|
||||
|
||||
if not summary:
|
||||
return "No MCP requests tracked yet."
|
||||
|
||||
report = "MCP Server Latency Summary\n"
|
||||
report += "=" * 50 + "\n"
|
||||
|
||||
for request_id, metrics in summary.items():
|
||||
if request_id.startswith("mcp_"):
|
||||
report += f"\nRequest: {request_id}\n"
|
||||
|
||||
total_time = 0
|
||||
for phase, data in metrics.items():
|
||||
phase_time = data['total']
|
||||
total_time += phase_time
|
||||
report += f" {phase}: {phase_time:.3f}s\n"
|
||||
|
||||
report += f" Total: {total_time:.3f}s\n"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run the example
|
||||
example_mcp_with_tracking()
|
||||
|
||||
# Show overall summary
|
||||
print("\n" + "=" * 50)
|
||||
print(get_mcp_latency_summary())
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Minimal Example: Latency Tracking for MCP Server
|
||||
|
||||
This is the simplest way to add latency tracking to your MCP server
|
||||
without modifying any core PraisonAI files.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent
|
||||
from latency_tracker_tool import tracker
|
||||
import time
|
||||
|
||||
# Example: Track MCP request handling
|
||||
def handle_mcp_request(query: str, request_id: str = "mcp_1"):
|
||||
"""Simulate handling an MCP request with latency tracking."""
|
||||
|
||||
print(f"\nHandling MCP request: {request_id}")
|
||||
print(f"Query: {query}")
|
||||
|
||||
# 1. Planning Phase
|
||||
tracker.start_timer("planning", request_id)
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
role="MCP Handler",
|
||||
goal="Process requests",
|
||||
llm="gpt-4o-mini"
|
||||
)
|
||||
plan = f"I will search for information about {query}"
|
||||
time.sleep(0.1) # Simulate planning time
|
||||
planning_time = tracker.end_timer("planning", request_id)
|
||||
|
||||
# 2. Tool Usage Phase
|
||||
tracker.start_timer("tool_usage", request_id)
|
||||
# Simulate tool execution
|
||||
time.sleep(0.2) # Simulate tool execution time
|
||||
tool_result = f"Found 5 results for {query}"
|
||||
tool_time = tracker.end_timer("tool_usage", request_id)
|
||||
|
||||
# 3. LLM Generation Phase
|
||||
tracker.start_timer("llm_generation", request_id)
|
||||
# In real usage, this would be: response = agent.chat(prompt)
|
||||
time.sleep(0.15) # Simulate LLM response time
|
||||
response = f"Based on my search, here's information about {query}..."
|
||||
llm_time = tracker.end_timer("llm_generation", request_id)
|
||||
|
||||
# Get metrics
|
||||
metrics = tracker.get_metrics(request_id)
|
||||
|
||||
# Display results
|
||||
print(f"\nResponse: {response}")
|
||||
print(f"\nLatency Breakdown:")
|
||||
print(f" Planning: {planning_time:.3f}s")
|
||||
print(f" Tool Usage: {tool_time:.3f}s")
|
||||
print(f" LLM Generation: {llm_time:.3f}s")
|
||||
print(f" Total: {planning_time + tool_time + llm_time:.3f}s")
|
||||
|
||||
return response, metrics
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Simulate multiple MCP requests
|
||||
queries = [
|
||||
"Python async programming",
|
||||
"Machine learning basics",
|
||||
"Docker best practices"
|
||||
]
|
||||
|
||||
for i, query in enumerate(queries):
|
||||
handle_mcp_request(query, f"mcp_request_{i}")
|
||||
|
||||
# Show summary
|
||||
print("\n" + "="*50)
|
||||
print("OVERALL LATENCY SUMMARY")
|
||||
print("="*50)
|
||||
|
||||
summary = tracker.get_summary()
|
||||
for request_id, phases in summary.items():
|
||||
print(f"\n{request_id}:")
|
||||
total = sum(phase_data['total'] for phase_data in phases.values())
|
||||
for phase, data in phases.items():
|
||||
percentage = (data['total'] / total) * 100
|
||||
print(f" {phase}: {data['total']:.3f}s ({percentage:.1f}%)")
|
||||
@@ -0,0 +1,150 @@
|
||||
"""
|
||||
Example tools.py file with integrated latency tracking.
|
||||
|
||||
This shows how to add latency tracking to your tools without modifying core files.
|
||||
Place this as tools.py in your project root for automatic loading.
|
||||
"""
|
||||
|
||||
import time
|
||||
from typing import List, Dict
|
||||
from latency_tracker_tool import tracker, track_latency
|
||||
|
||||
# Example 1: Simple tool with manual tracking
|
||||
def search_with_tracking(query: str) -> str:
|
||||
"""
|
||||
Search tool with built-in latency tracking.
|
||||
|
||||
Args:
|
||||
query: Search query string
|
||||
|
||||
Returns:
|
||||
str: Search results
|
||||
"""
|
||||
# Manual tracking approach
|
||||
tracker.start_timer("tool_search", "current_request")
|
||||
|
||||
# Simulate search operation
|
||||
time.sleep(0.1) # Simulate API call
|
||||
result = f"Found 3 results for '{query}'"
|
||||
|
||||
elapsed = tracker.end_timer("tool_search", "current_request")
|
||||
|
||||
# Include timing in result (optional)
|
||||
return f"{result} (took {elapsed:.3f}s)"
|
||||
|
||||
|
||||
# Example 2: Tool with decorator-based tracking
|
||||
@track_latency("tool_calculation", "current_request")
|
||||
def calculate_with_tracking(expression: str) -> str:
|
||||
"""
|
||||
Calculator tool with automatic latency tracking via decorator.
|
||||
|
||||
Args:
|
||||
expression: Mathematical expression to evaluate
|
||||
|
||||
Returns:
|
||||
str: Calculation result
|
||||
"""
|
||||
# Simulate calculation
|
||||
time.sleep(0.05)
|
||||
|
||||
try:
|
||||
result = eval(expression)
|
||||
return f"Result: {result}"
|
||||
except Exception as e:
|
||||
return f"Error: {str(e)}"
|
||||
|
||||
|
||||
# Example 3: Tool with context manager tracking
|
||||
def analyze_with_tracking(data: str) -> Dict[str, any]:
|
||||
"""
|
||||
Analysis tool with fine-grained latency tracking.
|
||||
|
||||
Args:
|
||||
data: Data to analyze
|
||||
|
||||
Returns:
|
||||
dict: Analysis results with timing breakdown
|
||||
"""
|
||||
results = {}
|
||||
|
||||
# Track different phases of analysis
|
||||
with tracker.track("analysis_preprocessing", "current_request"):
|
||||
# Simulate preprocessing
|
||||
time.sleep(0.02)
|
||||
processed_data = data.lower().strip()
|
||||
|
||||
with tracker.track("analysis_main", "current_request"):
|
||||
# Simulate main analysis
|
||||
time.sleep(0.08)
|
||||
word_count = len(processed_data.split())
|
||||
char_count = len(processed_data)
|
||||
|
||||
with tracker.track("analysis_postprocessing", "current_request"):
|
||||
# Simulate postprocessing
|
||||
time.sleep(0.01)
|
||||
results = {
|
||||
"word_count": word_count,
|
||||
"char_count": char_count,
|
||||
"processed": True
|
||||
}
|
||||
|
||||
# Get metrics for this analysis
|
||||
metrics = tracker.get_metrics("current_request")
|
||||
if "analysis_preprocessing" in metrics:
|
||||
results["timing"] = {
|
||||
"preprocessing": metrics["analysis_preprocessing"]["latest"],
|
||||
"main": metrics["analysis_main"]["latest"],
|
||||
"postprocessing": metrics["analysis_postprocessing"]["latest"]
|
||||
}
|
||||
|
||||
return results
|
||||
|
||||
|
||||
# Latency reporting tool - allows agents to get latency metrics
|
||||
def get_latency_report(request_id: str = "current_request") -> str:
|
||||
"""
|
||||
Get a latency report for the current or specified request.
|
||||
|
||||
Args:
|
||||
request_id: Request identifier (default: "current_request")
|
||||
|
||||
Returns:
|
||||
str: Formatted latency report
|
||||
"""
|
||||
metrics = tracker.get_metrics(request_id)
|
||||
|
||||
if not metrics:
|
||||
return "No latency data available for this request."
|
||||
|
||||
report = f"Latency Report for {request_id}:\n"
|
||||
report += "-" * 40 + "\n"
|
||||
|
||||
total_time = 0
|
||||
for phase, data in metrics.items():
|
||||
phase_time = data['total']
|
||||
total_time += phase_time
|
||||
report += f"{phase}: {phase_time:.3f}s (avg: {data['average']:.3f}s, count: {data['count']})\n"
|
||||
|
||||
report += "-" * 40 + "\n"
|
||||
report += f"Total tracked time: {total_time:.3f}s\n"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
# Clear latency data tool
|
||||
def clear_latency_data(request_id: str = None) -> str:
|
||||
"""
|
||||
Clear latency tracking data.
|
||||
|
||||
Args:
|
||||
request_id: Specific request to clear (None clears all)
|
||||
|
||||
Returns:
|
||||
str: Confirmation message
|
||||
"""
|
||||
tracker.clear(request_id)
|
||||
if request_id:
|
||||
return f"Cleared latency data for request: {request_id}"
|
||||
else:
|
||||
return "Cleared all latency tracking data"
|
||||
@@ -0,0 +1,141 @@
|
||||
"""
|
||||
Advanced handoff example with callbacks, input types, and filters.
|
||||
|
||||
This example demonstrates advanced handoff features including:
|
||||
- Custom handoff callbacks
|
||||
- Structured input data
|
||||
- Input filters
|
||||
- Custom tool names and descriptions
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, handoff, handoff_filters, prompt_with_handoff_instructions
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
# Define structured input for escalation
|
||||
class EscalationData(BaseModel):
|
||||
reason: str
|
||||
priority: Optional[str] = "normal"
|
||||
customer_sentiment: Optional[str] = None
|
||||
|
||||
|
||||
# Callback function for logging handoffs
|
||||
def log_handoff(source_agent: Agent):
|
||||
"""Log when a handoff occurs"""
|
||||
logging.info(f"Handoff initiated from {source_agent.name}")
|
||||
|
||||
|
||||
# Callback function with input data
|
||||
def log_escalation(source_agent: Agent, input_data: EscalationData):
|
||||
"""Log escalation with structured data"""
|
||||
logging.info(f"ESCALATION from {source_agent.name}: {input_data.reason} (Priority: {input_data.priority})")
|
||||
|
||||
|
||||
# Create specialized agents
|
||||
faq_agent = Agent(
|
||||
name="FAQ Agent",
|
||||
role="FAQ Specialist",
|
||||
goal="Answer frequently asked questions using knowledge base",
|
||||
backstory="I have access to comprehensive FAQ documentation and can quickly provide accurate answers."
|
||||
)
|
||||
|
||||
escalation_agent = Agent(
|
||||
name="Escalation Agent",
|
||||
role="Senior Support Manager",
|
||||
goal="Handle escalated issues that require special attention",
|
||||
backstory="I handle complex cases that need senior-level intervention and decision-making."
|
||||
)
|
||||
|
||||
# Create support agent with custom handoffs
|
||||
support_agent = Agent(
|
||||
name="Support Agent",
|
||||
role="Customer Support Representative",
|
||||
goal="Provide first-line support and escalate when necessary",
|
||||
backstory="I help customers with their issues and know when to involve specialists.",
|
||||
instructions=prompt_with_handoff_instructions(
|
||||
"""Help customers with their requests. You should:
|
||||
1. Try to resolve issues yourself first
|
||||
2. Transfer to FAQ Agent for common questions you can't answer
|
||||
3. Escalate to senior management for complex or sensitive issues
|
||||
|
||||
When escalating, always provide a clear reason and assess the priority.""",
|
||||
None # Agent will be set later
|
||||
),
|
||||
handoffs=[
|
||||
# Simple handoff with callback
|
||||
handoff(
|
||||
faq_agent,
|
||||
on_handoff=log_handoff,
|
||||
input_filter=handoff_filters.remove_all_tools # Remove tool calls from history
|
||||
),
|
||||
# Advanced handoff with structured input
|
||||
handoff(
|
||||
escalation_agent,
|
||||
tool_name_override="escalate_to_manager",
|
||||
tool_description_override="Escalate complex or sensitive issues to senior management",
|
||||
on_handoff=log_escalation,
|
||||
input_type=EscalationData
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# Update the instructions with the agent reference
|
||||
support_agent.instructions = prompt_with_handoff_instructions(
|
||||
support_agent.instructions,
|
||||
support_agent
|
||||
)
|
||||
|
||||
|
||||
# Example with custom input filter
|
||||
def custom_filter(data):
|
||||
"""Keep only last 3 messages and remove system messages"""
|
||||
data = handoff_filters.keep_last_n_messages(3)(data)
|
||||
data = handoff_filters.remove_system_messages(data)
|
||||
return data
|
||||
|
||||
|
||||
# Agent with custom filtered handoff
|
||||
filtered_agent = Agent(
|
||||
name="Filtered Support",
|
||||
role="Support with Privacy",
|
||||
goal="Handle support while maintaining privacy",
|
||||
backstory="I ensure customer privacy by filtering sensitive conversation history.",
|
||||
handoffs=[
|
||||
handoff(
|
||||
faq_agent,
|
||||
tool_description_override="Transfer to FAQ (filtered history)",
|
||||
input_filter=custom_filter
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
print("=== Advanced Handoff Examples ===\n")
|
||||
|
||||
# Test escalation with structured data
|
||||
print("Test 1: Escalation with structured input")
|
||||
response = support_agent.chat(
|
||||
"I've been waiting for my refund for 3 weeks and I'm very frustrated! "
|
||||
"I need this resolved immediately or I'll take legal action!"
|
||||
)
|
||||
print(f"Response: {response}\n")
|
||||
|
||||
# Test FAQ handoff
|
||||
print("\nTest 2: FAQ handoff with filtering")
|
||||
response = support_agent.chat(
|
||||
"How do I reset my password? I can't find the option in settings."
|
||||
)
|
||||
print(f"Response: {response}\n")
|
||||
|
||||
# Test filtered handoff
|
||||
print("\nTest 3: Filtered handoff")
|
||||
# Add some conversation history
|
||||
filtered_agent.chat("My account number is 12345")
|
||||
filtered_agent.chat("I have a sensitive issue")
|
||||
response = filtered_agent.chat("I need help with FAQ about privacy policy")
|
||||
print(f"Response: {response}\n")
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Basic handoff example demonstrating agent-to-agent delegation.
|
||||
|
||||
This example shows how agents can hand off tasks to specialized agents.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Create specialized agents
|
||||
billing_agent = Agent(
|
||||
name="Billing Agent",
|
||||
role="Billing Specialist",
|
||||
goal="Handle all billing-related inquiries and tasks",
|
||||
backstory="I am an expert in billing systems, payment processing, and invoice management."
|
||||
)
|
||||
|
||||
refund_agent = Agent(
|
||||
name="Refund Agent",
|
||||
role="Refund Specialist",
|
||||
goal="Process refund requests and handle refund-related issues",
|
||||
backstory="I specialize in processing refunds, evaluating refund eligibility, and ensuring customer satisfaction."
|
||||
)
|
||||
|
||||
technical_support_agent = Agent(
|
||||
name="Technical Support",
|
||||
role="Technical Support Specialist",
|
||||
goal="Resolve technical issues and provide technical assistance",
|
||||
backstory="I am skilled in troubleshooting technical problems and providing solutions."
|
||||
)
|
||||
|
||||
# Create a triage agent with handoffs to specialized agents
|
||||
triage_agent = Agent(
|
||||
name="Triage Agent",
|
||||
role="Customer Service Triage",
|
||||
goal="Understand customer needs and route them to the appropriate specialist",
|
||||
backstory="I analyze customer requests and direct them to the most suitable specialist for efficient resolution.",
|
||||
instructions="""Analyze the customer's request and determine which specialist can best help:
|
||||
- For billing questions, payment issues, or invoices, transfer to the Billing Agent
|
||||
- For refund requests or refund status inquiries, transfer to the Refund Agent
|
||||
- For technical problems or product issues, transfer to Technical Support
|
||||
|
||||
Always explain why you're transferring the customer before doing so.""",
|
||||
handoffs=[billing_agent, refund_agent, technical_support_agent]
|
||||
)
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
print("=== Customer Service Triage System ===\n")
|
||||
|
||||
# Test different types of requests
|
||||
test_requests = [
|
||||
"I need a refund for my last purchase",
|
||||
"Why was I charged twice on my credit card?",
|
||||
"The app keeps crashing when I try to login"
|
||||
]
|
||||
|
||||
for request in test_requests:
|
||||
print(f"\nCustomer: {request}")
|
||||
response = triage_agent.chat(request)
|
||||
print(f"Response: {response}")
|
||||
print("-" * 50)
|
||||
@@ -0,0 +1,162 @@
|
||||
"""
|
||||
Complete customer service workflow example with handoffs.
|
||||
|
||||
This example demonstrates a realistic customer service scenario with:
|
||||
- Order status checking
|
||||
- Refund processing
|
||||
- Technical support
|
||||
- FAQ handling
|
||||
- Escalation management
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, handoff, RECOMMENDED_PROMPT_PREFIX
|
||||
import random
|
||||
|
||||
|
||||
# Mock functions for demonstration
|
||||
def check_order_status(order_id: str) -> str:
|
||||
"""Check the status of an order"""
|
||||
statuses = ["shipped", "processing", "delivered", "pending"]
|
||||
return f"Order {order_id} is {random.choice(statuses)}"
|
||||
|
||||
|
||||
def process_refund(order_id: str, reason: str) -> str:
|
||||
"""Process a refund request"""
|
||||
return f"Refund initiated for order {order_id}. Reason: {reason}. Expected in 3-5 business days."
|
||||
|
||||
|
||||
def get_faq_answer(question: str) -> str:
|
||||
"""Get answer from FAQ database"""
|
||||
faqs = {
|
||||
"shipping": "Standard shipping takes 5-7 business days. Express shipping takes 2-3 business days.",
|
||||
"returns": "You can return items within 30 days of purchase in original condition.",
|
||||
"warranty": "All products come with a 1-year manufacturer warranty.",
|
||||
"payment": "We accept credit cards, debit cards, PayPal, and Apple Pay."
|
||||
}
|
||||
for key, answer in faqs.items():
|
||||
if key in question.lower():
|
||||
return answer
|
||||
return "I'll need to check our documentation for that specific question."
|
||||
|
||||
|
||||
# Create specialized agents with tools
|
||||
order_agent = Agent(
|
||||
name="Order Specialist",
|
||||
role="Order Management Specialist",
|
||||
goal="Handle all order-related inquiries including tracking, modifications, and status updates",
|
||||
backstory="I specialize in order management and have access to the order tracking system.",
|
||||
tools=[check_order_status],
|
||||
instructions=f"""{RECOMMENDED_PROMPT_PREFIX}
|
||||
|
||||
I can help with:
|
||||
- Checking order status
|
||||
- Tracking shipments
|
||||
- Order modifications
|
||||
- Delivery issues
|
||||
|
||||
For refunds, I'll transfer you to our Refund Specialist.
|
||||
For technical issues, I'll connect you with Technical Support."""
|
||||
)
|
||||
|
||||
refund_agent = Agent(
|
||||
name="Refund Specialist",
|
||||
role="Refund and Returns Specialist",
|
||||
goal="Process refunds and handle return requests efficiently",
|
||||
backstory="I'm authorized to process refunds and handle all return-related matters.",
|
||||
tools=[process_refund],
|
||||
instructions="""I process refunds and returns. I need the order ID and reason for the refund.
|
||||
I ensure all refunds are processed according to our policy."""
|
||||
)
|
||||
|
||||
faq_agent = Agent(
|
||||
name="FAQ Assistant",
|
||||
role="Knowledge Base Specialist",
|
||||
goal="Provide quick answers to frequently asked questions",
|
||||
backstory="I have access to our comprehensive FAQ database.",
|
||||
tools=[get_faq_answer],
|
||||
instructions="I provide answers to common questions about shipping, returns, warranty, and payments."
|
||||
)
|
||||
|
||||
technical_agent = Agent(
|
||||
name="Technical Support",
|
||||
role="Technical Support Engineer",
|
||||
goal="Resolve technical issues with products and services",
|
||||
backstory="I'm trained in troubleshooting all our products and technical services.",
|
||||
instructions="""I help with:
|
||||
- Product setup and configuration
|
||||
- Troubleshooting technical issues
|
||||
- Software problems
|
||||
- Hardware diagnostics"""
|
||||
)
|
||||
|
||||
escalation_agent = Agent(
|
||||
name="Senior Manager",
|
||||
role="Customer Experience Manager",
|
||||
goal="Handle escalated issues and ensure customer satisfaction",
|
||||
backstory="I'm a senior manager with authority to make exceptions and handle complex cases.",
|
||||
instructions="""I handle:
|
||||
- Escalated complaints
|
||||
- Special requests requiring manager approval
|
||||
- Complex issues that need executive decisions
|
||||
- Customer retention situations"""
|
||||
)
|
||||
|
||||
# Create main customer service agent with handoffs
|
||||
customer_service_agent = Agent(
|
||||
name="Customer Service",
|
||||
role="Customer Service Representative",
|
||||
goal="Provide excellent customer service by understanding needs and routing to the right specialist",
|
||||
backstory="I'm your first point of contact and I'll make sure you get the help you need.",
|
||||
instructions=f"""{RECOMMENDED_PROMPT_PREFIX}
|
||||
|
||||
Welcome! I'm here to help you today. I can assist with various requests or connect you with the right specialist:
|
||||
|
||||
- For order tracking and status → Order Specialist
|
||||
- For refunds and returns → Refund Specialist
|
||||
- For common questions → FAQ Assistant
|
||||
- For technical problems → Technical Support
|
||||
- For complaints or special requests → Senior Manager
|
||||
|
||||
How can I help you today?""",
|
||||
handoffs=[
|
||||
order_agent,
|
||||
refund_agent,
|
||||
faq_agent,
|
||||
technical_agent,
|
||||
handoff(
|
||||
escalation_agent,
|
||||
tool_description_override="Escalate to senior management for complex issues or complaints"
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# Example interaction
|
||||
if __name__ == "__main__":
|
||||
print("=== Customer Service System ===")
|
||||
print("Welcome to our customer service! Type 'quit' to exit.\n")
|
||||
|
||||
# Simulated customer interactions
|
||||
test_scenarios = [
|
||||
"I need to check the status of my order #12345",
|
||||
"I want a refund for order #67890, the product was damaged",
|
||||
"What's your return policy?",
|
||||
"My device won't turn on after the update",
|
||||
"I'm very unhappy with the service and want to speak to a manager!",
|
||||
"How long does shipping usually take?"
|
||||
]
|
||||
|
||||
print("Running automated test scenarios:\n")
|
||||
for scenario in test_scenarios:
|
||||
print(f"Customer: {scenario}")
|
||||
response = customer_service_agent.chat(scenario)
|
||||
print(f"Agent: {response}")
|
||||
print("-" * 80)
|
||||
|
||||
# Interactive mode
|
||||
print("\nNow entering interactive mode. You can ask questions directly:")
|
||||
while True:
|
||||
user_input = input("\nYou: ")
|
||||
if user_input.lower() == 'quit':
|
||||
break
|
||||
response = customer_service_agent.chat(user_input)
|
||||
print(f"Agent: {response}")
|
||||
@@ -0,0 +1,167 @@
|
||||
# Agent Handoffs
|
||||
|
||||
Agent handoffs allow agents to delegate tasks to other specialized agents. This is useful when you have agents with different areas of expertise that need to collaborate.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, handoff
|
||||
|
||||
# Create specialized agents
|
||||
billing_agent = Agent(name="Billing Agent", role="Billing Specialist")
|
||||
refund_agent = Agent(name="Refund Agent", role="Refund Specialist")
|
||||
|
||||
# Create main agent with handoffs
|
||||
triage_agent = Agent(
|
||||
name="Triage Agent",
|
||||
role="Customer Service",
|
||||
handoffs=[billing_agent, refund_agent] # Can hand off to these agents
|
||||
)
|
||||
```
|
||||
|
||||
## How Handoffs Work
|
||||
|
||||
1. Handoffs are automatically converted to tools that the agent can use
|
||||
2. The agent decides when to hand off based on the conversation context
|
||||
3. When a handoff occurs, the target agent receives the conversation history
|
||||
4. The target agent's response is returned to the user
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Custom Handoff Configuration
|
||||
|
||||
Use the `handoff()` function for more control:
|
||||
|
||||
```python
|
||||
from praisonaiagents import Agent, handoff
|
||||
|
||||
agent = Agent(name="Target Agent")
|
||||
|
||||
custom_handoff = handoff(
|
||||
agent=agent,
|
||||
tool_name_override="escalate_to_specialist",
|
||||
tool_description_override="Escalate complex issues to a specialist",
|
||||
on_handoff=lambda ctx: print(f"Handoff from {ctx.name}"),
|
||||
input_filter=handoff_filters.remove_all_tools
|
||||
)
|
||||
|
||||
main_agent = Agent(
|
||||
name="Main Agent",
|
||||
handoffs=[custom_handoff]
|
||||
)
|
||||
```
|
||||
|
||||
### Handoff Callbacks
|
||||
|
||||
Execute custom logic when a handoff occurs:
|
||||
|
||||
```python
|
||||
# Create target agent
|
||||
target_agent = Agent(name="Target Agent", role="Specialist")
|
||||
|
||||
def log_handoff(source_agent):
|
||||
print(f"Handoff initiated from {source_agent.name}")
|
||||
|
||||
handoff_with_callback = handoff(
|
||||
target_agent,
|
||||
on_handoff=log_handoff
|
||||
)
|
||||
```
|
||||
|
||||
### Structured Input
|
||||
|
||||
Require specific data when handing off:
|
||||
|
||||
```python
|
||||
from pydantic import BaseModel
|
||||
|
||||
class EscalationData(BaseModel):
|
||||
reason: str
|
||||
priority: str
|
||||
|
||||
# Create escalation agent
|
||||
escalation_agent = Agent(name="Escalation Agent", role="Senior Manager")
|
||||
|
||||
def handle_escalation(source_agent, data: EscalationData):
|
||||
print(f"Escalation: {data.reason} (Priority: {data.priority})")
|
||||
|
||||
escalation_handoff = handoff(
|
||||
escalation_agent,
|
||||
on_handoff=handle_escalation,
|
||||
input_type=EscalationData
|
||||
)
|
||||
```
|
||||
|
||||
### Input Filters
|
||||
|
||||
Control what conversation history is passed to the target agent:
|
||||
|
||||
```python
|
||||
from praisonaiagents import handoff_filters
|
||||
|
||||
# Create target agent for filtering examples
|
||||
agent = Agent(name="Target Agent", role="Specialist")
|
||||
|
||||
# Remove all tool calls from history
|
||||
filtered_handoff = handoff(
|
||||
agent,
|
||||
input_filter=handoff_filters.remove_all_tools
|
||||
)
|
||||
|
||||
# Keep only last N messages
|
||||
limited_handoff = handoff(
|
||||
agent,
|
||||
input_filter=handoff_filters.keep_last_n_messages(5)
|
||||
)
|
||||
|
||||
# Remove system messages
|
||||
clean_handoff = handoff(
|
||||
agent,
|
||||
input_filter=handoff_filters.remove_system_messages
|
||||
)
|
||||
```
|
||||
|
||||
## Recommended Prompts
|
||||
|
||||
Include handoff instructions in your agent prompts:
|
||||
|
||||
```python
|
||||
from praisonaiagents import RECOMMENDED_PROMPT_PREFIX, prompt_with_handoff_instructions
|
||||
|
||||
# Create specialized agents
|
||||
billing_agent = Agent(name="Billing Agent", role="Billing Specialist")
|
||||
technical_agent = Agent(name="Technical Agent", role="Technical Support")
|
||||
|
||||
agent = Agent(
|
||||
name="Support Agent",
|
||||
handoffs=[billing_agent, technical_agent]
|
||||
)
|
||||
|
||||
# After creating the agent, update its instructions
|
||||
agent.instructions = prompt_with_handoff_instructions(
|
||||
"Help customers and transfer to specialists when needed.",
|
||||
agent # Pass the agent to auto-generate handoff info
|
||||
)
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
See the examples directory for complete working examples:
|
||||
- `examples/handoff_basic.py` - Simple handoff demonstration
|
||||
- `examples/handoff_advanced.py` - Advanced features with callbacks and filters
|
||||
- `examples/handoff_customer_service.py` - Real-world customer service workflow
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Clear Role Definition**: Give each agent a clear role and area of expertise
|
||||
2. **Handoff Instructions**: Include when to hand off in agent instructions
|
||||
3. **Context Preservation**: Use input filters carefully to maintain necessary context
|
||||
4. **Logging**: Use callbacks to track handoffs for debugging and analytics
|
||||
5. **Testing**: Test handoff paths to ensure smooth transitions
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
The handoff feature is fully backward compatible:
|
||||
- Existing agents work without modification
|
||||
- The `handoffs` parameter is optional
|
||||
- All existing agent functionality is preserved
|
||||
@@ -0,0 +1,163 @@
|
||||
"""
|
||||
Advanced Dynamic Input Example for PraisonAI
|
||||
|
||||
This example demonstrates an advanced system that dynamically creates agents and tasks
|
||||
based on user inputs, including conditional logic, custom configurations, and file output.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import duckduckgo
|
||||
import os
|
||||
from typing import Dict, List
|
||||
|
||||
class DynamicAgentSystem:
|
||||
"""Advanced system for handling dynamic user inputs"""
|
||||
|
||||
def __init__(self):
|
||||
self.user_preferences = {}
|
||||
self.llm_config = {
|
||||
"model": os.getenv("LLM_MODEL", "gpt-4o-mini"),
|
||||
"temperature": 0.7
|
||||
}
|
||||
|
||||
def collect_user_inputs(self) -> Dict[str, str]:
|
||||
"""Collect multiple user inputs"""
|
||||
inputs = {}
|
||||
inputs['topic'] = input("What topic would you like to explore? ")
|
||||
inputs['depth'] = input("Analysis depth (quick/detailed)? ").lower() or "quick"
|
||||
inputs['output_format'] = input("Output format (summary/report/bullets)? ").lower() or "summary"
|
||||
inputs['language'] = input("Language preference (en/es/fr)? ").lower() or "en"
|
||||
return inputs
|
||||
|
||||
def create_dynamic_agents(self, inputs: Dict[str, str]) -> List[Agent]:
|
||||
"""Create agents based on user inputs"""
|
||||
agents = []
|
||||
|
||||
# Research agent with dynamic configuration
|
||||
research_agent = Agent(
|
||||
name="ResearchExpert",
|
||||
role=f"{'Detailed' if inputs['depth'] == 'detailed' else 'Quick'} Research Specialist",
|
||||
goal=f"Conduct {inputs['depth']} research on {inputs['topic']} in {inputs['language']}",
|
||||
backstory=f"Multilingual expert specializing in {inputs['depth']} analysis",
|
||||
tools=[duckduckgo],
|
||||
self_reflect=inputs['depth'] == 'detailed',
|
||||
llm=self.llm_config
|
||||
)
|
||||
agents.append(research_agent)
|
||||
|
||||
# Format agent based on output preference
|
||||
format_agent = Agent(
|
||||
name="FormatExpert",
|
||||
role=f"{inputs['output_format'].title()} Formatter",
|
||||
goal=f"Format research into {inputs['output_format']} style",
|
||||
backstory=f"Expert in creating {inputs['output_format']} documents",
|
||||
llm=self.llm_config
|
||||
)
|
||||
agents.append(format_agent)
|
||||
|
||||
# Optional quality agent for detailed analysis
|
||||
if inputs['depth'] == 'detailed':
|
||||
quality_agent = Agent(
|
||||
name="QualityChecker",
|
||||
role="Quality Assurance Specialist",
|
||||
goal="Verify accuracy and completeness",
|
||||
backstory="Expert in fact-checking and quality control",
|
||||
llm=self.llm_config
|
||||
)
|
||||
agents.append(quality_agent)
|
||||
|
||||
return agents
|
||||
|
||||
def create_dynamic_tasks(self, agents: List[Agent], inputs: Dict[str, str]) -> List[Task]:
|
||||
"""Create tasks based on user inputs and agents"""
|
||||
tasks = []
|
||||
|
||||
# Research task
|
||||
research_task = Task(
|
||||
description=f"""
|
||||
Research '{inputs['topic']}' with the following requirements:
|
||||
- Depth: {inputs['depth']}
|
||||
- Language: {inputs['language']}
|
||||
- Find {'5-10' if inputs['depth'] == 'detailed' else '3-5'} key points
|
||||
- Include sources and citations
|
||||
""",
|
||||
expected_output=f"Research findings about {inputs['topic']} with sources",
|
||||
agent=agents[0], # Research agent
|
||||
name="research_phase"
|
||||
)
|
||||
tasks.append(research_task)
|
||||
|
||||
# Formatting task
|
||||
format_instructions = {
|
||||
'summary': "Create a concise paragraph summary",
|
||||
'report': "Create a structured report with sections",
|
||||
'bullets': "Create a bullet-point list of key findings"
|
||||
}
|
||||
|
||||
format_task = Task(
|
||||
description=f"""
|
||||
Format the research findings as follows:
|
||||
- Style: {format_instructions[inputs['output_format']]}
|
||||
- Language: {inputs['language']}
|
||||
- Maintain all source citations
|
||||
""",
|
||||
expected_output=f"{inputs['output_format'].title()} of {inputs['topic']}",
|
||||
agent=agents[1], # Format agent
|
||||
context=[research_task],
|
||||
name="formatting_phase"
|
||||
)
|
||||
tasks.append(format_task)
|
||||
|
||||
# Quality check task (if detailed)
|
||||
if inputs['depth'] == 'detailed' and len(agents) > 2:
|
||||
quality_task = Task(
|
||||
description="Verify all facts, check sources, and ensure completeness",
|
||||
expected_output="Quality-assured final output with verification notes",
|
||||
agent=agents[2], # Quality agent
|
||||
context=[format_task],
|
||||
name="quality_phase"
|
||||
)
|
||||
tasks.append(quality_task)
|
||||
|
||||
return tasks
|
||||
|
||||
def run(self):
|
||||
"""Main execution flow"""
|
||||
# Collect inputs
|
||||
print("🎯 PraisonAI Dynamic Input System")
|
||||
print("-" * 40)
|
||||
inputs = self.collect_user_inputs()
|
||||
|
||||
# Create dynamic agents and tasks
|
||||
agents = self.create_dynamic_agents(inputs)
|
||||
tasks = self.create_dynamic_tasks(agents, inputs)
|
||||
|
||||
# Configure process based on depth
|
||||
process = "hierarchical" if inputs['depth'] == 'detailed' else "sequential"
|
||||
|
||||
# Run the system
|
||||
print(f"\n🚀 Starting {process} analysis for '{inputs['topic']}'...")
|
||||
praison_agents = PraisonAIAgents(
|
||||
agents=agents,
|
||||
tasks=tasks,
|
||||
process=process,
|
||||
verbose=inputs['depth'] == 'detailed'
|
||||
)
|
||||
|
||||
result = praison_agents.start()
|
||||
|
||||
# Save results if detailed
|
||||
if inputs['depth'] == 'detailed':
|
||||
filename = f"{inputs['topic'].replace(' ', '_')}_{inputs['output_format']}.txt"
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
f.write(result)
|
||||
print(f"\n📄 Results saved to: {filename}")
|
||||
|
||||
return result
|
||||
|
||||
# Usage
|
||||
if __name__ == "__main__":
|
||||
system = DynamicAgentSystem()
|
||||
result = system.run()
|
||||
print("\n📊 Final Result:")
|
||||
print(result)
|
||||
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
Environment Variable Input Example for PraisonAI
|
||||
|
||||
This example demonstrates how to use environment variables combined with user input
|
||||
to create flexible agent configurations that can be pre-configured via environment.
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Set via environment or use default
|
||||
default_topic = os.getenv("RESEARCH_TOPIC", "AI trends")
|
||||
user_topic = input(f"Topic to research [{default_topic}]: ") or default_topic
|
||||
|
||||
# Get other configuration from environment
|
||||
llm_model = os.getenv("LLM_MODEL", "gpt-4o-mini")
|
||||
temperature = float(os.getenv("LLM_TEMPERATURE", "0.7"))
|
||||
max_retries = int(os.getenv("MAX_RETRIES", "3"))
|
||||
|
||||
# Create agent with environment-based configuration
|
||||
agent = Agent(
|
||||
name="Researcher",
|
||||
role="Research Assistant",
|
||||
goal=f"Research {user_topic}",
|
||||
backstory="Expert researcher with configurable capabilities",
|
||||
llm={
|
||||
"model": llm_model,
|
||||
"temperature": temperature
|
||||
},
|
||||
max_retry_limit=max_retries
|
||||
)
|
||||
|
||||
# Create task
|
||||
task = Task(
|
||||
description=f"Research and summarize: {user_topic}",
|
||||
expected_output="Comprehensive summary with key findings",
|
||||
agent=agent
|
||||
)
|
||||
|
||||
# Show configuration
|
||||
print(f"\n🔧 Configuration:")
|
||||
print(f" - Topic: {user_topic}")
|
||||
print(f" - Model: {llm_model}")
|
||||
print(f" - Temperature: {temperature}")
|
||||
print(f" - Max Retries: {max_retries}")
|
||||
print("\n" + "="*50 + "\n")
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(agents=[agent], tasks=[task])
|
||||
result = agents.start()
|
||||
|
||||
# Save to environment-specified location if provided
|
||||
output_path = os.getenv("OUTPUT_PATH")
|
||||
if output_path:
|
||||
output_file = os.path.join(output_path, f"{user_topic.replace(' ', '_')}_research.txt")
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(result)
|
||||
print(f"\n📁 Results saved to: {output_file}")
|
||||
|
||||
print("\n✅ Research completed!")
|
||||
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Medium Complexity Input Example for PraisonAI
|
||||
|
||||
This example shows how to use multiple user inputs to create a more sophisticated
|
||||
agent system with tools, multiple agents, and context passing between tasks.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import duckduckgo
|
||||
|
||||
# Get multiple inputs
|
||||
topic = input("Enter search topic: ")
|
||||
num_results = input("How many results? (default: 5): ") or "5"
|
||||
|
||||
# Create search agent with tools
|
||||
search_agent = Agent(
|
||||
name="WebSearcher",
|
||||
role="Search Specialist",
|
||||
goal=f"Find {num_results} relevant results about {topic}",
|
||||
backstory="Expert in internet research and data collection",
|
||||
tools=[duckduckgo],
|
||||
self_reflect=False
|
||||
)
|
||||
|
||||
# Create analysis agent
|
||||
analysis_agent = Agent(
|
||||
name="Analyzer",
|
||||
role="Data Analyst",
|
||||
goal="Analyze and summarize search results",
|
||||
backstory="Expert in data synthesis and reporting"
|
||||
)
|
||||
|
||||
# Create tasks with context passing
|
||||
search_task = Task(
|
||||
description=f"Search for '{topic}' and find top {num_results} results",
|
||||
expected_output=f"List of {num_results} relevant results with sources",
|
||||
agent=search_agent,
|
||||
name="search_task"
|
||||
)
|
||||
|
||||
analyze_task = Task(
|
||||
description="Analyze the search results and create a summary report",
|
||||
expected_output="Comprehensive summary with key insights",
|
||||
agent=analysis_agent,
|
||||
context=[search_task], # Receives results from search_task
|
||||
name="analysis_task"
|
||||
)
|
||||
|
||||
# Run sequential process
|
||||
agents = PraisonAIAgents(
|
||||
agents=[search_agent, analysis_agent],
|
||||
tasks=[search_task, analyze_task],
|
||||
process="sequential"
|
||||
)
|
||||
agents.start()
|
||||
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
Simple Input Example for PraisonAI
|
||||
|
||||
This example demonstrates how to use basic user input to create dynamic agents and tasks.
|
||||
The user is prompted for a search query, and the agent searches for information about it.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
|
||||
# Get user input
|
||||
user_query = input("What would you like to search for? ")
|
||||
|
||||
# Create agent
|
||||
agent = Agent(
|
||||
name="SearchAgent",
|
||||
role="Information Finder",
|
||||
goal="Find information about user's query",
|
||||
backstory="Expert researcher with web access"
|
||||
)
|
||||
|
||||
# Create task with dynamic input
|
||||
task = Task(
|
||||
description=f"Search for information about: {user_query}",
|
||||
expected_output=f"Summary of findings about {user_query}",
|
||||
agent=agent
|
||||
)
|
||||
|
||||
# Run
|
||||
agents = PraisonAIAgents(agents=[agent], tasks=[task])
|
||||
agents.start()
|
||||
@@ -0,0 +1,177 @@
|
||||
"""
|
||||
Streamlit UI Input Example for PraisonAI
|
||||
|
||||
This example demonstrates how to create a web-based UI for dynamic user input
|
||||
using Streamlit, making it easy for users to interact with PraisonAI agents.
|
||||
|
||||
To run this example:
|
||||
1. Install streamlit: pip install streamlit
|
||||
2. Run: streamlit run streamlit_ui_input.py
|
||||
"""
|
||||
|
||||
import streamlit as st
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
from praisonaiagents.tools import duckduckgo
|
||||
|
||||
# Set page configuration
|
||||
st.set_page_config(
|
||||
page_title="PraisonAI Dynamic Input",
|
||||
page_icon="🤖",
|
||||
layout="wide"
|
||||
)
|
||||
|
||||
st.title("🤖 PraisonAI Dynamic Input Interface")
|
||||
st.markdown("---")
|
||||
|
||||
# Create sidebar for configuration
|
||||
with st.sidebar:
|
||||
st.header("⚙️ Configuration")
|
||||
|
||||
# Model selection
|
||||
model = st.selectbox(
|
||||
"Select Model",
|
||||
["gpt-4o-mini", "gpt-4o", "gpt-3.5-turbo", "claude-3-opus"],
|
||||
index=0
|
||||
)
|
||||
|
||||
# Temperature slider
|
||||
temperature = st.slider(
|
||||
"Creativity Level (Temperature)",
|
||||
min_value=0.0,
|
||||
max_value=1.0,
|
||||
value=0.7,
|
||||
step=0.1
|
||||
)
|
||||
|
||||
# Process type
|
||||
process_type = st.radio(
|
||||
"Process Type",
|
||||
["sequential", "hierarchical"],
|
||||
index=0
|
||||
)
|
||||
|
||||
# Enable tools
|
||||
use_tools = st.checkbox("Enable Web Search", value=True)
|
||||
|
||||
# Main content area
|
||||
col1, col2 = st.columns([2, 1])
|
||||
|
||||
with col1:
|
||||
# User input
|
||||
user_query = st.text_area(
|
||||
"What would you like to know?",
|
||||
placeholder="Enter your question or research topic here...",
|
||||
height=100
|
||||
)
|
||||
|
||||
# Additional options
|
||||
with st.expander("Advanced Options"):
|
||||
max_search_results = st.number_input(
|
||||
"Max Search Results",
|
||||
min_value=1,
|
||||
max_value=20,
|
||||
value=5
|
||||
)
|
||||
|
||||
output_format = st.selectbox(
|
||||
"Output Format",
|
||||
["Summary", "Detailed Report", "Bullet Points"],
|
||||
index=0
|
||||
)
|
||||
|
||||
include_sources = st.checkbox("Include Sources", value=True)
|
||||
|
||||
with col2:
|
||||
st.info(
|
||||
"💡 **Tips:**\n"
|
||||
"- Be specific with your questions\n"
|
||||
"- Use higher temperature for creative tasks\n"
|
||||
"- Enable web search for current information"
|
||||
)
|
||||
|
||||
# Submit button
|
||||
if st.button("🚀 Submit", type="primary", use_container_width=True):
|
||||
if user_query:
|
||||
# Create progress container
|
||||
progress_container = st.container()
|
||||
|
||||
with progress_container:
|
||||
with st.spinner("🔄 Processing your request..."):
|
||||
try:
|
||||
# Create agent with dynamic configuration
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
role=f"{output_format} Specialist",
|
||||
goal=f"Answer: {user_query}",
|
||||
backstory="Knowledgeable assistant with configurable capabilities",
|
||||
tools=[duckduckgo] if use_tools else [],
|
||||
llm={
|
||||
"model": model,
|
||||
"temperature": temperature
|
||||
}
|
||||
)
|
||||
|
||||
# Create task with dynamic parameters
|
||||
task_description = f"Provide a {output_format.lower()} answer for: {user_query}"
|
||||
if use_tools:
|
||||
task_description += f"\nSearch for up to {max_search_results} relevant results."
|
||||
if include_sources:
|
||||
task_description += "\nInclude sources for all information."
|
||||
|
||||
task = Task(
|
||||
description=task_description,
|
||||
expected_output=f"{output_format} with clear, helpful information",
|
||||
agent=agent
|
||||
)
|
||||
|
||||
# Run agents
|
||||
agents = PraisonAIAgents(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
process=process_type
|
||||
)
|
||||
|
||||
result = agents.start()
|
||||
|
||||
# Display results
|
||||
st.success("✅ Processing complete!")
|
||||
|
||||
# Show result in a nice format
|
||||
st.markdown("### 📊 Results")
|
||||
|
||||
# Create tabs for different views
|
||||
tab1, tab2, tab3 = st.tabs(["Result", "Configuration", "Raw Output"])
|
||||
|
||||
with tab1:
|
||||
st.markdown(result)
|
||||
|
||||
with tab2:
|
||||
st.json({
|
||||
"model": model,
|
||||
"temperature": temperature,
|
||||
"process": process_type,
|
||||
"tools_enabled": use_tools,
|
||||
"output_format": output_format,
|
||||
"query": user_query
|
||||
})
|
||||
|
||||
with tab3:
|
||||
st.code(result, language="markdown")
|
||||
|
||||
# Download button
|
||||
st.download_button(
|
||||
label="📥 Download Results",
|
||||
data=result,
|
||||
file_name=f"{user_query[:30].replace(' ', '_')}_results.txt",
|
||||
mime="text/plain"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"❌ An error occurred: {str(e)}")
|
||||
st.exception(e)
|
||||
else:
|
||||
st.warning("⚠️ Please enter a question or topic to research.")
|
||||
|
||||
# Footer
|
||||
st.markdown("---")
|
||||
st.markdown("Built with ❤️ using PraisonAI and Streamlit")
|
||||
@@ -0,0 +1,34 @@
|
||||
# Example: Using Ollama with a remote host via base_url parameter
|
||||
# pip install praisonaiagents
|
||||
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Method 1: Using base_url parameter directly (NEW)
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm="ollama/llama3.2",
|
||||
base_url="http://remote-host:11434"
|
||||
)
|
||||
|
||||
response = agent.start("Why is the sky blue?")
|
||||
print(response)
|
||||
|
||||
# Method 2: Using dict configuration
|
||||
agent2 = Agent(
|
||||
instructions="You are a helpful assistant",
|
||||
llm={
|
||||
"model": "ollama/llama3.2",
|
||||
"base_url": "http://remote-host:11434"
|
||||
}
|
||||
)
|
||||
|
||||
response2 = agent2.start("What is the capital of France?")
|
||||
print(response2)
|
||||
|
||||
# Method 3: Using environment variable (existing method)
|
||||
# export OPENAI_BASE_URL=http://remote-host:11434
|
||||
# Then just:
|
||||
# agent3 = Agent(
|
||||
# instructions="You are a helpful assistant",
|
||||
# llm="ollama/llama3.2"
|
||||
# )
|
||||
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic State Management Example
|
||||
==============================
|
||||
|
||||
This example demonstrates the fundamental state management capabilities in PraisonAI.
|
||||
It shows how to set, get, update, and manage state values in a multi-agent workflow.
|
||||
|
||||
Run this example:
|
||||
python 01_basic_state_management.py
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import json
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
def display_project_status() -> str:
|
||||
"""Tool to display current project status from workflow state"""
|
||||
# Access state from the global workflow variable
|
||||
project_name = workflow.get_state("project_name", "Unknown Project")
|
||||
budget = workflow.get_state("budget", 0)
|
||||
stage = workflow.get_state("stage", "not_started")
|
||||
team_size = workflow.get_state("team_size", 0)
|
||||
features = workflow.get_state("features", [])
|
||||
|
||||
status = f"""
|
||||
Project Status Report
|
||||
====================
|
||||
Project: {project_name}
|
||||
Budget: ${budget:,}
|
||||
Stage: {stage}
|
||||
Team Size: {team_size}
|
||||
Features: {', '.join(features) if features else 'None added yet'}
|
||||
"""
|
||||
|
||||
return status
|
||||
|
||||
|
||||
def add_feature(feature_name: str) -> str:
|
||||
"""Tool to add a new feature to the project"""
|
||||
features = workflow.get_state("features", [])
|
||||
features.append(feature_name)
|
||||
workflow.set_state("features", features)
|
||||
|
||||
return f"Added feature: {feature_name}. Total features: {len(features)}"
|
||||
|
||||
|
||||
def update_project_stage(new_stage: str) -> str:
|
||||
"""Tool to update the project stage"""
|
||||
old_stage = workflow.get_state("stage", "not_started")
|
||||
workflow.set_state("stage", new_stage)
|
||||
|
||||
# Log stage transition
|
||||
transitions = workflow.get_state("stage_transitions", [])
|
||||
transitions.append({"from": old_stage, "to": new_stage})
|
||||
workflow.set_state("stage_transitions", transitions)
|
||||
|
||||
return f"Project stage updated from '{old_stage}' to '{new_stage}'"
|
||||
|
||||
|
||||
def check_budget_health() -> Dict[str, Any]:
|
||||
"""Tool to check budget health"""
|
||||
budget = workflow.get_state("budget", 0)
|
||||
spent = workflow.get_state("spent", 0)
|
||||
|
||||
if budget == 0:
|
||||
health = "undefined"
|
||||
percentage = 0
|
||||
else:
|
||||
percentage = (spent / budget) * 100
|
||||
if percentage > 90:
|
||||
health = "critical"
|
||||
elif percentage > 70:
|
||||
health = "warning"
|
||||
else:
|
||||
health = "healthy"
|
||||
|
||||
return {
|
||||
"budget": budget,
|
||||
"spent": spent,
|
||||
"remaining": budget - spent,
|
||||
"percentage_used": percentage,
|
||||
"health": health
|
||||
}
|
||||
|
||||
|
||||
# Create agents
|
||||
project_manager = Agent(
|
||||
name="ProjectManager",
|
||||
role="Manage project state and status",
|
||||
goal="Track and report project progress",
|
||||
backstory="An experienced project manager who keeps track of all project details",
|
||||
tools=[display_project_status, update_project_stage],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
developer = Agent(
|
||||
name="Developer",
|
||||
role="Add features to the project",
|
||||
goal="Implement new features and track them in state",
|
||||
backstory="A skilled developer who implements features",
|
||||
tools=[add_feature, display_project_status],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
finance_manager = Agent(
|
||||
name="FinanceManager",
|
||||
role="Monitor project budget",
|
||||
goal="Ensure project stays within budget",
|
||||
backstory="A careful finance manager who tracks spending",
|
||||
tools=[check_budget_health],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create tasks
|
||||
task1 = Task(
|
||||
name="initialize_project",
|
||||
description="Initialize the project and display initial status",
|
||||
expected_output="Initial project status report",
|
||||
agent=project_manager,
|
||||
tools=[display_project_status]
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="add_core_features",
|
||||
description="Add the following core features to the project: 'User Authentication', 'Dashboard', 'API Integration'",
|
||||
expected_output="Confirmation of added features",
|
||||
agent=developer,
|
||||
tools=[add_feature]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="update_to_development",
|
||||
description="Update the project stage to 'development' and show updated status",
|
||||
expected_output="Updated project status",
|
||||
agent=project_manager,
|
||||
tools=[update_project_stage, display_project_status]
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="check_budget",
|
||||
description="Check the current budget health and provide a financial report",
|
||||
expected_output="Budget health report",
|
||||
agent=finance_manager,
|
||||
tools=[check_budget_health]
|
||||
)
|
||||
|
||||
# Create workflow (global variable for state access in tools)
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[project_manager, developer, finance_manager],
|
||||
tasks=[task1, task2, task3, task4],
|
||||
verbose=True,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Set initial state values
|
||||
print("\n=== Setting Initial State ===")
|
||||
workflow.set_state("project_name", "AI Assistant Platform")
|
||||
workflow.set_state("budget", 100000)
|
||||
workflow.set_state("spent", 25000)
|
||||
workflow.set_state("features", [])
|
||||
|
||||
# Update multiple state values at once
|
||||
workflow.update_state({
|
||||
"stage": "planning",
|
||||
"team_size": 5,
|
||||
"project_manager": "Alice",
|
||||
"tech_stack": ["Python", "React", "PostgreSQL"]
|
||||
})
|
||||
|
||||
# Demonstrate state operations
|
||||
print("\n=== State Operations Demo ===")
|
||||
|
||||
# Check if state exists
|
||||
if workflow.has_state("budget"):
|
||||
budget = workflow.get_state("budget")
|
||||
print(f"Project budget: ${budget:,}")
|
||||
|
||||
# Get all state
|
||||
all_state = workflow.get_all_state()
|
||||
print(f"\nAll state keys: {list(all_state.keys())}")
|
||||
|
||||
# Get state with default
|
||||
priority = workflow.get_state("priority", "medium")
|
||||
print(f"Project priority: {priority}")
|
||||
|
||||
# Run the workflow
|
||||
print("\n=== Starting Workflow ===")
|
||||
result = workflow.start()
|
||||
|
||||
# Display final state
|
||||
print("\n=== Final State ===")
|
||||
final_state = workflow.get_all_state()
|
||||
print(json.dumps(final_state, indent=2))
|
||||
|
||||
# Demonstrate state deletion
|
||||
print("\n=== State Cleanup Demo ===")
|
||||
workflow.delete_state("project_manager")
|
||||
print(f"State after deletion: {list(workflow.get_all_state().keys())}")
|
||||
|
||||
# Clear all state (commented out to preserve results)
|
||||
# workflow.clear_state()
|
||||
# print(f"State after clear: {workflow.get_all_state()}")
|
||||
@@ -0,0 +1,307 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
State in Tool Functions Example
|
||||
==============================
|
||||
|
||||
This example shows how to use workflow state within tool functions.
|
||||
Tools can read and modify state to share information between agents and tasks.
|
||||
|
||||
Run this example:
|
||||
python 02_state_in_tool_functions.py
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import time
|
||||
import json
|
||||
from typing import Dict, Any
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def track_progress() -> Dict[str, Any]:
|
||||
"""Tool that tracks task progress using workflow state"""
|
||||
# Access current progress from state
|
||||
current_stage = workflow.get_state("stage", "not_started")
|
||||
completed_tasks = workflow.get_state("completed_tasks", 0)
|
||||
total_tasks = workflow.get_state("total_tasks", 10)
|
||||
|
||||
# Increment completed tasks counter
|
||||
workflow.increment_state("completed_tasks", 1)
|
||||
|
||||
# Track task completion time
|
||||
workflow.append_to_state("task_history", {
|
||||
"task_id": completed_tasks + 1,
|
||||
"stage": current_stage,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"status": "completed"
|
||||
}, max_length=10) # Keep only last 10 entries
|
||||
|
||||
# Calculate progress
|
||||
new_completed = completed_tasks + 1
|
||||
progress_percentage = (new_completed / total_tasks) * 100
|
||||
|
||||
return {
|
||||
"stage": current_stage,
|
||||
"tasks_completed": new_completed,
|
||||
"total_tasks": total_tasks,
|
||||
"progress": f"{progress_percentage:.1f}%",
|
||||
"remaining": total_tasks - new_completed
|
||||
}
|
||||
|
||||
|
||||
def log_error(error_type: str, error_message: str) -> str:
|
||||
"""Tool that logs errors to state"""
|
||||
# Increment error counter
|
||||
workflow.increment_state(f"error_count_{error_type}", 1, default=0)
|
||||
|
||||
# Append to error log with timestamp
|
||||
error_entry = {
|
||||
"type": error_type,
|
||||
"message": error_message,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
workflow.append_to_state("error_log", error_entry, max_length=50)
|
||||
|
||||
# Update last error timestamp
|
||||
workflow.set_state("last_error_time", datetime.now().isoformat())
|
||||
|
||||
# Get current error count
|
||||
error_count = workflow.get_state(f"error_count_{error_type}", 0)
|
||||
|
||||
return f"Error logged: {error_type} (Total {error_type} errors: {error_count})"
|
||||
|
||||
|
||||
def process_data_batch() -> Dict[str, Any]:
|
||||
"""Tool that processes data in batches using state for coordination"""
|
||||
# Get or initialize batch processing state
|
||||
if not workflow.has_state("batch_total"):
|
||||
workflow.set_state("batch_total", 5)
|
||||
workflow.set_state("batch_current", 0)
|
||||
workflow.set_state("batch_results", [])
|
||||
|
||||
# Get current batch info
|
||||
batch_current = workflow.get_state("batch_current")
|
||||
batch_total = workflow.get_state("batch_total")
|
||||
|
||||
# Process next batch
|
||||
batch_current += 1
|
||||
workflow.set_state("batch_current", batch_current)
|
||||
|
||||
# Simulate batch processing
|
||||
result = {
|
||||
"batch_id": batch_current,
|
||||
"records_processed": 100,
|
||||
"processing_time": 0.5,
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
# Store batch result
|
||||
workflow.append_to_state("batch_results", result)
|
||||
|
||||
# Update statistics
|
||||
workflow.increment_state("total_records_processed", 100, default=0)
|
||||
|
||||
return {
|
||||
"batch": batch_current,
|
||||
"total_batches": batch_total,
|
||||
"result": result,
|
||||
"more_batches": batch_current < batch_total
|
||||
}
|
||||
|
||||
|
||||
def generate_report() -> str:
|
||||
"""Tool that generates a report from accumulated state data"""
|
||||
# Gather all state data
|
||||
completed_tasks = workflow.get_state("completed_tasks", 0)
|
||||
total_tasks = workflow.get_state("total_tasks", 10)
|
||||
task_history = workflow.get_state("task_history", [])
|
||||
error_log = workflow.get_state("error_log", [])
|
||||
batch_results = workflow.get_state("batch_results", [])
|
||||
total_records = workflow.get_state("total_records_processed", 0)
|
||||
|
||||
# Count errors by type
|
||||
error_types = {}
|
||||
for key in workflow.get_all_state().keys():
|
||||
if key.startswith("error_count_"):
|
||||
error_type = key.replace("error_count_", "")
|
||||
error_types[error_type] = workflow.get_state(key)
|
||||
|
||||
report = f"""
|
||||
===== WORKFLOW REPORT =====
|
||||
|
||||
Task Progress:
|
||||
- Completed: {completed_tasks}/{total_tasks} ({(completed_tasks/total_tasks*100):.1f}%)
|
||||
- Recent Tasks: {len(task_history)} tracked
|
||||
|
||||
Batch Processing:
|
||||
- Batches Processed: {len(batch_results)}
|
||||
- Total Records: {total_records}
|
||||
|
||||
Errors:
|
||||
- Total Errors: {len(error_log)}
|
||||
- Error Types: {json.dumps(error_types, indent=2) if error_types else 'None'}
|
||||
|
||||
Recent Activity:
|
||||
"""
|
||||
|
||||
# Add recent task history
|
||||
if task_history:
|
||||
report += "\n Recent Tasks:\n"
|
||||
for task in task_history[-3:]: # Last 3 tasks
|
||||
report += f" - Task {task['task_id']} completed at {task['timestamp']}\n"
|
||||
|
||||
# Add recent errors
|
||||
if error_log:
|
||||
report += "\n Recent Errors:\n"
|
||||
for error in error_log[-3:]: # Last 3 errors
|
||||
report += f" - {error['type']}: {error['message']} at {error['timestamp']}\n"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
def update_configuration(key: str, value: Any) -> str:
|
||||
"""Tool that updates configuration stored in state"""
|
||||
# Get current config
|
||||
config = workflow.get_state("config", {})
|
||||
|
||||
# Store old value for audit
|
||||
old_value = config.get(key, "not_set")
|
||||
|
||||
# Update config
|
||||
config[key] = value
|
||||
workflow.set_state("config", config)
|
||||
|
||||
# Log configuration change
|
||||
workflow.append_to_state("config_changes", {
|
||||
"key": key,
|
||||
"old_value": old_value,
|
||||
"new_value": value,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}, max_length=100)
|
||||
|
||||
return f"Configuration updated: {key} = {value} (was: {old_value})"
|
||||
|
||||
|
||||
# Create agents
|
||||
progress_tracker = Agent(
|
||||
name="ProgressTracker",
|
||||
role="Track and report task progress",
|
||||
goal="Monitor workflow progress using state",
|
||||
backstory="A meticulous tracker who monitors every task",
|
||||
tools=[track_progress, generate_report],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
data_processor = Agent(
|
||||
name="DataProcessor",
|
||||
role="Process data in batches",
|
||||
goal="Efficiently process all data batches",
|
||||
backstory="A data processing specialist",
|
||||
tools=[process_data_batch],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
error_handler = Agent(
|
||||
name="ErrorHandler",
|
||||
role="Handle and log errors",
|
||||
goal="Track all errors and maintain error logs",
|
||||
backstory="An error handling expert",
|
||||
tools=[log_error],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
config_manager = Agent(
|
||||
name="ConfigManager",
|
||||
role="Manage system configuration",
|
||||
goal="Update and track configuration changes",
|
||||
backstory="A configuration management specialist",
|
||||
tools=[update_configuration],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create tasks
|
||||
task1 = Task(
|
||||
name="initialize_tracking",
|
||||
description="Initialize the workflow and track the first progress update",
|
||||
expected_output="Initial progress report",
|
||||
agent=progress_tracker,
|
||||
tools=[track_progress]
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
name="update_config",
|
||||
description="Update configuration settings: set 'batch_size' to 100 and 'retry_limit' to 3",
|
||||
expected_output="Configuration update confirmations",
|
||||
agent=config_manager,
|
||||
tools=[update_configuration]
|
||||
)
|
||||
|
||||
task3 = Task(
|
||||
name="process_all_batches",
|
||||
description="Process all data batches and track progress",
|
||||
expected_output="All batch processing results",
|
||||
agent=data_processor,
|
||||
tools=[process_data_batch]
|
||||
)
|
||||
|
||||
task4 = Task(
|
||||
name="simulate_errors",
|
||||
description="Log some sample errors: 'connection' error 'Failed to connect to database' and 'validation' error 'Invalid data format'",
|
||||
expected_output="Error logging confirmations",
|
||||
agent=error_handler,
|
||||
tools=[log_error]
|
||||
)
|
||||
|
||||
task5 = Task(
|
||||
name="track_more_progress",
|
||||
description="Track progress for 3 more tasks",
|
||||
expected_output="Progress updates",
|
||||
agent=progress_tracker,
|
||||
tools=[track_progress]
|
||||
)
|
||||
|
||||
task6 = Task(
|
||||
name="generate_final_report",
|
||||
description="Generate a comprehensive report of all activities",
|
||||
expected_output="Final workflow report",
|
||||
agent=progress_tracker,
|
||||
tools=[generate_report]
|
||||
)
|
||||
|
||||
# Create workflow (global variable for state access in tools)
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[progress_tracker, data_processor, error_handler, config_manager],
|
||||
tasks=[task1, task2, task3, task4, task5, task6],
|
||||
verbose=True,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Initialize workflow state
|
||||
print("\n=== Initializing Workflow State ===")
|
||||
workflow.set_state("stage", "processing")
|
||||
workflow.set_state("total_tasks", 10)
|
||||
workflow.set_state("completed_tasks", 0)
|
||||
|
||||
# Run the workflow
|
||||
print("\n=== Starting Workflow ===")
|
||||
result = workflow.start()
|
||||
|
||||
# Display final state summary
|
||||
print("\n=== Final State Summary ===")
|
||||
final_state = workflow.get_all_state()
|
||||
print(f"Total state keys: {len(final_state)}")
|
||||
print(f"Completed tasks: {final_state.get('completed_tasks', 0)}")
|
||||
print(f"Total errors logged: {len(final_state.get('error_log', []))}")
|
||||
print(f"Batches processed: {len(final_state.get('batch_results', []))}")
|
||||
print(f"Configuration changes: {len(final_state.get('config_changes', []))}")
|
||||
|
||||
# Show some state details
|
||||
print("\n=== State Details ===")
|
||||
print(f"Current configuration: {json.dumps(final_state.get('config', {}), indent=2)}")
|
||||
print(f"Error counts by type: ", end="")
|
||||
error_counts = {k: v for k, v in final_state.items() if k.startswith("error_count_")}
|
||||
print(json.dumps(error_counts, indent=2) if error_counts else "None")
|
||||
@@ -0,0 +1,421 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Conditional Task Execution with State Example
|
||||
============================================
|
||||
|
||||
This example demonstrates how to use state to control task flow with conditional execution.
|
||||
Tasks can make decisions based on state values to determine which tasks execute next.
|
||||
|
||||
Run this example:
|
||||
python 03_conditional_task_execution.py
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import json
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
def check_budget_status() -> str:
|
||||
"""Check budget and return decision based on spending"""
|
||||
budget = workflow.get_state("budget", 0)
|
||||
spent = workflow.get_state("spent", 0)
|
||||
|
||||
if budget == 0:
|
||||
return "no_budget"
|
||||
|
||||
percentage_spent = (spent / budget) * 100
|
||||
|
||||
# Store budget analysis in state
|
||||
workflow.set_state("budget_analysis", {
|
||||
"budget": budget,
|
||||
"spent": spent,
|
||||
"remaining": budget - spent,
|
||||
"percentage_spent": percentage_spent
|
||||
})
|
||||
|
||||
# Return decision based on budget status
|
||||
if percentage_spent >= 90:
|
||||
workflow.set_state("budget_alert", "critical")
|
||||
return "over_budget"
|
||||
elif percentage_spent >= 70:
|
||||
workflow.set_state("budget_alert", "warning")
|
||||
return "within_budget"
|
||||
else:
|
||||
workflow.set_state("budget_alert", "healthy")
|
||||
return "under_budget"
|
||||
|
||||
|
||||
def reduce_costs() -> str:
|
||||
"""Implement cost reduction measures"""
|
||||
current_spent = workflow.get_state("spent", 0)
|
||||
|
||||
# Simulate cost reduction
|
||||
savings = current_spent * 0.15 # 15% reduction
|
||||
new_spent = current_spent - savings
|
||||
workflow.set_state("spent", new_spent)
|
||||
workflow.set_state("cost_reduction_applied", True)
|
||||
workflow.set_state("savings_achieved", savings)
|
||||
|
||||
# Log action
|
||||
workflow.append_to_state("actions_taken", {
|
||||
"action": "cost_reduction",
|
||||
"savings": savings,
|
||||
"new_spent": new_spent
|
||||
})
|
||||
|
||||
return f"Cost reduction implemented. Saved ${savings:,.2f}. New spending: ${new_spent:,.2f}"
|
||||
|
||||
|
||||
def continue_development() -> str:
|
||||
"""Continue with normal development"""
|
||||
# Add new features
|
||||
features = workflow.get_state("features", [])
|
||||
new_features = ["Feature A", "Feature B"]
|
||||
features.extend(new_features)
|
||||
workflow.set_state("features", features)
|
||||
|
||||
# Update development status
|
||||
workflow.set_state("development_status", "active")
|
||||
|
||||
# Log action
|
||||
workflow.append_to_state("actions_taken", {
|
||||
"action": "continue_development",
|
||||
"features_added": new_features
|
||||
})
|
||||
|
||||
return f"Continuing development. Added features: {', '.join(new_features)}"
|
||||
|
||||
|
||||
def expand_features() -> str:
|
||||
"""Expand project with additional features"""
|
||||
# Add premium features
|
||||
features = workflow.get_state("features", [])
|
||||
premium_features = ["Premium Feature X", "Premium Feature Y", "Premium Feature Z"]
|
||||
features.extend(premium_features)
|
||||
workflow.set_state("features", features)
|
||||
|
||||
# Increase budget allocation
|
||||
additional_budget = 20000
|
||||
current_budget = workflow.get_state("budget", 0)
|
||||
workflow.set_state("budget", current_budget + additional_budget)
|
||||
|
||||
# Update status
|
||||
workflow.set_state("development_status", "expanded")
|
||||
|
||||
# Log action
|
||||
workflow.append_to_state("actions_taken", {
|
||||
"action": "expand_features",
|
||||
"premium_features_added": premium_features,
|
||||
"budget_increased": additional_budget
|
||||
})
|
||||
|
||||
return f"Expanded project scope. Added premium features and increased budget by ${additional_budget:,}"
|
||||
|
||||
|
||||
def check_performance() -> str:
|
||||
"""Check system performance and return status"""
|
||||
# Simulate performance metrics
|
||||
cpu_usage = workflow.get_state("cpu_usage", 45) # percentage
|
||||
memory_usage = workflow.get_state("memory_usage", 60) # percentage
|
||||
response_time = workflow.get_state("response_time", 200) # milliseconds
|
||||
|
||||
# Store performance metrics
|
||||
workflow.set_state("performance_metrics", {
|
||||
"cpu_usage": cpu_usage,
|
||||
"memory_usage": memory_usage,
|
||||
"response_time": response_time
|
||||
})
|
||||
|
||||
# Determine performance status
|
||||
if cpu_usage > 80 or memory_usage > 85 or response_time > 500:
|
||||
return "poor_performance"
|
||||
elif cpu_usage > 60 or memory_usage > 70 or response_time > 300:
|
||||
return "moderate_performance"
|
||||
else:
|
||||
return "good_performance"
|
||||
|
||||
|
||||
def optimize_performance() -> str:
|
||||
"""Optimize system performance"""
|
||||
# Simulate optimization
|
||||
workflow.set_state("cpu_usage", 40)
|
||||
workflow.set_state("memory_usage", 50)
|
||||
workflow.set_state("response_time", 150)
|
||||
workflow.set_state("optimization_applied", True)
|
||||
|
||||
# Log action
|
||||
workflow.append_to_state("actions_taken", {
|
||||
"action": "optimize_performance",
|
||||
"improvements": "Applied caching, code optimization, and resource cleanup"
|
||||
})
|
||||
|
||||
return "Performance optimization completed. All metrics improved."
|
||||
|
||||
|
||||
def scale_infrastructure() -> str:
|
||||
"""Scale up infrastructure"""
|
||||
# Simulate scaling
|
||||
current_servers = workflow.get_state("server_count", 2)
|
||||
new_servers = current_servers + 2
|
||||
workflow.set_state("server_count", new_servers)
|
||||
workflow.set_state("infrastructure_scaled", True)
|
||||
|
||||
# Log action
|
||||
workflow.append_to_state("actions_taken", {
|
||||
"action": "scale_infrastructure",
|
||||
"servers_added": 2,
|
||||
"total_servers": new_servers
|
||||
})
|
||||
|
||||
return f"Infrastructure scaled. Added 2 servers. Total servers: {new_servers}"
|
||||
|
||||
|
||||
def maintain_current_setup() -> str:
|
||||
"""Maintain current setup without changes"""
|
||||
workflow.set_state("system_status", "stable")
|
||||
|
||||
# Log action
|
||||
workflow.append_to_state("actions_taken", {
|
||||
"action": "maintain_current",
|
||||
"reason": "Performance is good, no changes needed"
|
||||
})
|
||||
|
||||
return "System performing well. Maintaining current setup."
|
||||
|
||||
|
||||
def generate_decision_report() -> str:
|
||||
"""Generate report on all decisions made"""
|
||||
actions = workflow.get_state("actions_taken", [])
|
||||
budget_analysis = workflow.get_state("budget_analysis", {})
|
||||
performance_metrics = workflow.get_state("performance_metrics", {})
|
||||
|
||||
report = """
|
||||
Decision Flow Report
|
||||
===================
|
||||
|
||||
Budget Analysis:
|
||||
"""
|
||||
|
||||
if budget_analysis:
|
||||
report += f"""
|
||||
- Budget: ${budget_analysis.get('budget', 0):,}
|
||||
- Spent: ${budget_analysis.get('spent', 0):,}
|
||||
- Remaining: ${budget_analysis.get('remaining', 0):,}
|
||||
- Percentage Spent: {budget_analysis.get('percentage_spent', 0):.1f}%
|
||||
- Alert Level: {workflow.get_state('budget_alert', 'unknown')}
|
||||
"""
|
||||
|
||||
report += "\n Performance Metrics:\n"
|
||||
if performance_metrics:
|
||||
report += f"""
|
||||
- CPU Usage: {performance_metrics.get('cpu_usage', 0)}%
|
||||
- Memory Usage: {performance_metrics.get('memory_usage', 0)}%
|
||||
- Response Time: {performance_metrics.get('response_time', 0)}ms
|
||||
"""
|
||||
|
||||
report += "\n Actions Taken:\n"
|
||||
for i, action in enumerate(actions, 1):
|
||||
report += f" {i}. {action['action'].replace('_', ' ').title()}\n"
|
||||
for key, value in action.items():
|
||||
if key != 'action':
|
||||
report += f" - {key}: {value}\n"
|
||||
|
||||
# Add final state summary
|
||||
report += f"""
|
||||
|
||||
Final State:
|
||||
- Features: {len(workflow.get_state('features', []))} total
|
||||
- Development Status: {workflow.get_state('development_status', 'unknown')}
|
||||
- System Status: {workflow.get_state('system_status', 'unknown')}
|
||||
"""
|
||||
|
||||
return report
|
||||
|
||||
|
||||
# Create agents
|
||||
finance_agent = Agent(
|
||||
name="FinanceAgent",
|
||||
role="Monitor budget and make financial decisions",
|
||||
goal="Ensure project stays within budget constraints",
|
||||
backstory="A financial expert who makes budget decisions",
|
||||
tools=[check_budget_status],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
cost_manager = Agent(
|
||||
name="CostManager",
|
||||
role="Implement cost reduction strategies",
|
||||
goal="Reduce costs when budget is tight",
|
||||
backstory="A cost optimization specialist",
|
||||
tools=[reduce_costs],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
development_agent = Agent(
|
||||
name="DevelopmentAgent",
|
||||
role="Manage feature development",
|
||||
goal="Develop features based on budget availability",
|
||||
backstory="A development manager who adapts to budget constraints",
|
||||
tools=[continue_development, expand_features],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
performance_agent = Agent(
|
||||
name="PerformanceAgent",
|
||||
role="Monitor and optimize system performance",
|
||||
goal="Ensure optimal system performance",
|
||||
backstory="A performance engineer",
|
||||
tools=[check_performance, optimize_performance, scale_infrastructure, maintain_current_setup],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
report_agent = Agent(
|
||||
name="ReportAgent",
|
||||
role="Generate comprehensive reports",
|
||||
goal="Document all decisions and actions taken",
|
||||
backstory="A reporting specialist",
|
||||
tools=[generate_decision_report],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create conditional tasks
|
||||
budget_decision_task = Task(
|
||||
name="budget_decision",
|
||||
description="Check current budget status and decide next action",
|
||||
expected_output="Budget status decision",
|
||||
agent=finance_agent,
|
||||
tools=[check_budget_status],
|
||||
task_type="decision",
|
||||
condition={
|
||||
"over_budget": ["cost_reduction_task"],
|
||||
"within_budget": ["continue_development_task"],
|
||||
"under_budget": ["expand_features_task"],
|
||||
"no_budget": ["report_task"] # Skip to report if no budget
|
||||
}
|
||||
)
|
||||
|
||||
cost_reduction_task = Task(
|
||||
name="cost_reduction_task",
|
||||
description="Implement cost reduction measures due to budget constraints",
|
||||
expected_output="Cost reduction confirmation",
|
||||
agent=cost_manager,
|
||||
tools=[reduce_costs],
|
||||
next_tasks=["performance_check_task"]
|
||||
)
|
||||
|
||||
continue_development_task = Task(
|
||||
name="continue_development_task",
|
||||
description="Continue with planned development",
|
||||
expected_output="Development continuation confirmation",
|
||||
agent=development_agent,
|
||||
tools=[continue_development],
|
||||
next_tasks=["performance_check_task"]
|
||||
)
|
||||
|
||||
expand_features_task = Task(
|
||||
name="expand_features_task",
|
||||
description="Expand project with additional premium features",
|
||||
expected_output="Feature expansion confirmation",
|
||||
agent=development_agent,
|
||||
tools=[expand_features],
|
||||
next_tasks=["performance_check_task"]
|
||||
)
|
||||
|
||||
performance_check_task = Task(
|
||||
name="performance_check_task",
|
||||
description="Check system performance and decide on optimization needs",
|
||||
expected_output="Performance status decision",
|
||||
agent=performance_agent,
|
||||
tools=[check_performance],
|
||||
task_type="decision",
|
||||
condition={
|
||||
"poor_performance": ["optimize_performance_task"],
|
||||
"moderate_performance": ["scale_infrastructure_task"],
|
||||
"good_performance": ["maintain_setup_task"]
|
||||
}
|
||||
)
|
||||
|
||||
optimize_performance_task = Task(
|
||||
name="optimize_performance_task",
|
||||
description="Optimize system performance due to poor metrics",
|
||||
expected_output="Performance optimization confirmation",
|
||||
agent=performance_agent,
|
||||
tools=[optimize_performance],
|
||||
next_tasks=["report_task"]
|
||||
)
|
||||
|
||||
scale_infrastructure_task = Task(
|
||||
name="scale_infrastructure_task",
|
||||
description="Scale infrastructure to handle moderate load",
|
||||
expected_output="Infrastructure scaling confirmation",
|
||||
agent=performance_agent,
|
||||
tools=[scale_infrastructure],
|
||||
next_tasks=["report_task"]
|
||||
)
|
||||
|
||||
maintain_setup_task = Task(
|
||||
name="maintain_setup_task",
|
||||
description="Maintain current setup as performance is good",
|
||||
expected_output="Setup maintenance confirmation",
|
||||
agent=performance_agent,
|
||||
tools=[maintain_current_setup],
|
||||
next_tasks=["report_task"]
|
||||
)
|
||||
|
||||
report_task = Task(
|
||||
name="report_task",
|
||||
description="Generate comprehensive report of all decisions and actions",
|
||||
expected_output="Complete decision flow report",
|
||||
agent=report_agent,
|
||||
tools=[generate_decision_report]
|
||||
)
|
||||
|
||||
# Create workflow
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[finance_agent, cost_manager, development_agent, performance_agent, report_agent],
|
||||
tasks=[
|
||||
budget_decision_task,
|
||||
cost_reduction_task,
|
||||
continue_development_task,
|
||||
expand_features_task,
|
||||
performance_check_task,
|
||||
optimize_performance_task,
|
||||
scale_infrastructure_task,
|
||||
maintain_setup_task,
|
||||
report_task
|
||||
],
|
||||
verbose=True,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Test different scenarios by changing initial state
|
||||
print("\n=== Scenario 1: Over Budget with Poor Performance ===")
|
||||
workflow.set_state("budget", 100000)
|
||||
workflow.set_state("spent", 92000) # 92% spent - over budget
|
||||
workflow.set_state("cpu_usage", 85) # High CPU - poor performance
|
||||
workflow.set_state("memory_usage", 88)
|
||||
workflow.set_state("response_time", 600)
|
||||
workflow.set_state("features", [])
|
||||
workflow.set_state("actions_taken", [])
|
||||
|
||||
# Run workflow
|
||||
result = workflow.start()
|
||||
|
||||
# To test other scenarios, uncomment and run:
|
||||
"""
|
||||
print("\n\n=== Scenario 2: Under Budget with Good Performance ===")
|
||||
workflow.clear_state()
|
||||
workflow.set_state("budget", 100000)
|
||||
workflow.set_state("spent", 40000) # 40% spent - under budget
|
||||
workflow.set_state("cpu_usage", 35) # Low usage - good performance
|
||||
workflow.set_state("memory_usage", 45)
|
||||
workflow.set_state("response_time", 150)
|
||||
workflow.set_state("features", [])
|
||||
workflow.set_state("actions_taken", [])
|
||||
result = workflow.start()
|
||||
"""
|
||||
@@ -0,0 +1,345 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Session State Persistence Example
|
||||
================================
|
||||
|
||||
This example demonstrates how to save and restore workflow state using sessions.
|
||||
This is useful for long-running workflows that may need to be paused and resumed.
|
||||
|
||||
Run this example:
|
||||
python 04_session_state_persistence.py
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents, Session
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
def process_customer_data(customer_id: str) -> Dict[str, Any]:
|
||||
"""Process customer data and update state"""
|
||||
# Track which customers have been processed
|
||||
processed_customers = workflow.get_state("processed_customers", [])
|
||||
|
||||
# Simulate data processing
|
||||
processing_result = {
|
||||
"customer_id": customer_id,
|
||||
"status": "processed",
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"records_processed": 150
|
||||
}
|
||||
|
||||
# Update state
|
||||
processed_customers.append(customer_id)
|
||||
workflow.set_state("processed_customers", processed_customers)
|
||||
|
||||
# Increment counters
|
||||
workflow.increment_state("total_customers_processed", 1, default=0)
|
||||
workflow.increment_state("total_records_processed", 150, default=0)
|
||||
|
||||
# Add to processing history
|
||||
workflow.append_to_state("processing_history", processing_result, max_length=100)
|
||||
|
||||
return processing_result
|
||||
|
||||
|
||||
def check_processing_status() -> str:
|
||||
"""Check current processing status"""
|
||||
total_customers = workflow.get_state("total_customers_processed", 0)
|
||||
total_records = workflow.get_state("total_records_processed", 0)
|
||||
processed_list = workflow.get_state("processed_customers", [])
|
||||
session_id = workflow.get_state("session_id", "unknown")
|
||||
|
||||
status = f"""
|
||||
Processing Status (Session: {session_id})
|
||||
========================================
|
||||
Total Customers Processed: {total_customers}
|
||||
Total Records Processed: {total_records}
|
||||
Customers: {', '.join(processed_list) if processed_list else 'None'}
|
||||
"""
|
||||
|
||||
# Check if we need to continue
|
||||
remaining_customers = workflow.get_state("remaining_customers", [])
|
||||
if remaining_customers:
|
||||
status += f"\nRemaining Customers: {', '.join(remaining_customers)}"
|
||||
|
||||
return status
|
||||
|
||||
|
||||
def save_checkpoint() -> str:
|
||||
"""Save current state as a checkpoint"""
|
||||
session_id = workflow.get_state("session_id", "session_001")
|
||||
|
||||
# Add checkpoint metadata
|
||||
workflow.set_state("last_checkpoint", datetime.now().isoformat())
|
||||
workflow.set_state("checkpoint_number", workflow.get_state("checkpoint_number", 0) + 1)
|
||||
|
||||
# Save session state
|
||||
workflow.save_session_state(session_id, include_memory=True)
|
||||
|
||||
checkpoint_num = workflow.get_state("checkpoint_number")
|
||||
return f"Checkpoint #{checkpoint_num} saved for session {session_id}"
|
||||
|
||||
|
||||
def simulate_long_task() -> str:
|
||||
"""Simulate a long-running task that updates progress"""
|
||||
task_name = "data_migration"
|
||||
|
||||
# Initialize or get current progress
|
||||
progress = workflow.get_state(f"{task_name}_progress", 0)
|
||||
|
||||
# Simulate work in chunks
|
||||
chunk_size = 20
|
||||
progress += chunk_size
|
||||
|
||||
# Update state
|
||||
workflow.set_state(f"{task_name}_progress", progress)
|
||||
workflow.set_state(f"{task_name}_last_update", datetime.now().isoformat())
|
||||
|
||||
# Check if complete
|
||||
if progress >= 100:
|
||||
workflow.set_state(f"{task_name}_status", "completed")
|
||||
return f"Task '{task_name}' completed!"
|
||||
else:
|
||||
workflow.set_state(f"{task_name}_status", "in_progress")
|
||||
return f"Task '{task_name}' progress: {progress}%"
|
||||
|
||||
|
||||
def generate_session_report() -> str:
|
||||
"""Generate a report for the current session"""
|
||||
session_id = workflow.get_state("session_id", "unknown")
|
||||
start_time = workflow.get_state("session_start_time", "unknown")
|
||||
checkpoints = workflow.get_state("checkpoint_number", 0)
|
||||
|
||||
# Get all task statuses
|
||||
all_state = workflow.get_all_state()
|
||||
task_statuses = {}
|
||||
for key, value in all_state.items():
|
||||
if key.endswith("_status"):
|
||||
task_name = key.replace("_status", "")
|
||||
task_statuses[task_name] = value
|
||||
|
||||
report = f"""
|
||||
Session Report
|
||||
==============
|
||||
Session ID: {session_id}
|
||||
Start Time: {start_time}
|
||||
Checkpoints: {checkpoints}
|
||||
|
||||
Processing Summary:
|
||||
- Customers Processed: {workflow.get_state('total_customers_processed', 0)}
|
||||
- Records Processed: {workflow.get_state('total_records_processed', 0)}
|
||||
|
||||
Task Statuses:
|
||||
"""
|
||||
|
||||
for task, status in task_statuses.items():
|
||||
progress = workflow.get_state(f"{task}_progress", "N/A")
|
||||
report += f" - {task}: {status} (Progress: {progress}%)\n"
|
||||
|
||||
# Add processing history summary
|
||||
history = workflow.get_state("processing_history", [])
|
||||
if history:
|
||||
report += f"\n Recent Processing ({len(history)} total):\n"
|
||||
for entry in history[-3:]: # Last 3 entries
|
||||
report += f" - {entry['customer_id']} at {entry['timestamp']}\n"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
# Create agents
|
||||
data_processor = Agent(
|
||||
name="DataProcessor",
|
||||
role="Process customer data",
|
||||
goal="Process all customer data efficiently",
|
||||
backstory="A data processing specialist",
|
||||
tools=[process_customer_data],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
status_monitor = Agent(
|
||||
name="StatusMonitor",
|
||||
role="Monitor processing status",
|
||||
goal="Track and report processing progress",
|
||||
backstory="A monitoring specialist",
|
||||
tools=[check_processing_status, save_checkpoint],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
task_runner = Agent(
|
||||
name="TaskRunner",
|
||||
role="Run long-running tasks",
|
||||
goal="Execute tasks that may span multiple sessions",
|
||||
backstory="A task execution specialist",
|
||||
tools=[simulate_long_task],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
report_generator = Agent(
|
||||
name="ReportGenerator",
|
||||
role="Generate session reports",
|
||||
goal="Create comprehensive session reports",
|
||||
backstory="A reporting specialist",
|
||||
tools=[generate_session_report],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create tasks for initial session
|
||||
initial_tasks = [
|
||||
Task(
|
||||
name="check_initial_status",
|
||||
description="Check the initial processing status",
|
||||
expected_output="Initial status report",
|
||||
agent=status_monitor,
|
||||
tools=[check_processing_status]
|
||||
),
|
||||
Task(
|
||||
name="process_customer_1",
|
||||
description="Process customer data for customer 'CUST001'",
|
||||
expected_output="Processing result for CUST001",
|
||||
agent=data_processor,
|
||||
tools=[process_customer_data]
|
||||
),
|
||||
Task(
|
||||
name="process_customer_2",
|
||||
description="Process customer data for customer 'CUST002'",
|
||||
expected_output="Processing result for CUST002",
|
||||
agent=data_processor,
|
||||
tools=[process_customer_data]
|
||||
),
|
||||
Task(
|
||||
name="run_long_task",
|
||||
description="Run the long-running data migration task",
|
||||
expected_output="Task progress update",
|
||||
agent=task_runner,
|
||||
tools=[simulate_long_task]
|
||||
),
|
||||
Task(
|
||||
name="save_checkpoint_1",
|
||||
description="Save a checkpoint of the current state",
|
||||
expected_output="Checkpoint confirmation",
|
||||
agent=status_monitor,
|
||||
tools=[save_checkpoint]
|
||||
),
|
||||
Task(
|
||||
name="generate_report_1",
|
||||
description="Generate a report for the current session",
|
||||
expected_output="Session report",
|
||||
agent=report_generator,
|
||||
tools=[generate_session_report]
|
||||
)
|
||||
]
|
||||
|
||||
# Create workflow with memory enabled
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[data_processor, status_monitor, task_runner, report_generator],
|
||||
tasks=initial_tasks,
|
||||
verbose=True,
|
||||
process="sequential",
|
||||
memory=True # Enable memory for persistence
|
||||
)
|
||||
|
||||
# Initialize session
|
||||
session_id = "project_session_001"
|
||||
print(f"\n=== Starting Session: {session_id} ===")
|
||||
|
||||
# Set initial session state
|
||||
workflow.set_state("session_id", session_id)
|
||||
workflow.set_state("session_start_time", datetime.now().isoformat())
|
||||
workflow.set_state("remaining_customers", ["CUST003", "CUST004", "CUST005"])
|
||||
|
||||
# Run initial workflow
|
||||
print("\n=== Running Initial Workflow ===")
|
||||
result = workflow.start()
|
||||
|
||||
# Save session state
|
||||
print("\n=== Saving Session State ===")
|
||||
workflow.save_session_state(session_id)
|
||||
saved_state = workflow.get_all_state()
|
||||
print(f"Saved {len(saved_state)} state keys")
|
||||
|
||||
# Simulate session interruption
|
||||
print("\n=== Simulating Session Interruption ===")
|
||||
print("Clearing current state to simulate new session...")
|
||||
workflow.clear_state()
|
||||
print(f"State after clear: {len(workflow.get_all_state())} keys")
|
||||
|
||||
# Create tasks for resumed session
|
||||
resumed_tasks = [
|
||||
Task(
|
||||
name="check_resumed_status",
|
||||
description="Check the status after resuming",
|
||||
expected_output="Resumed status report",
|
||||
agent=status_monitor,
|
||||
tools=[check_processing_status]
|
||||
),
|
||||
Task(
|
||||
name="process_remaining_customers",
|
||||
description="Process remaining customers: CUST003, CUST004",
|
||||
expected_output="Processing results for remaining customers",
|
||||
agent=data_processor,
|
||||
tools=[process_customer_data]
|
||||
),
|
||||
Task(
|
||||
name="continue_long_task",
|
||||
description="Continue the long-running data migration task",
|
||||
expected_output="Updated task progress",
|
||||
agent=task_runner,
|
||||
tools=[simulate_long_task]
|
||||
),
|
||||
Task(
|
||||
name="save_checkpoint_2",
|
||||
description="Save another checkpoint",
|
||||
expected_output="Checkpoint confirmation",
|
||||
agent=status_monitor,
|
||||
tools=[save_checkpoint]
|
||||
),
|
||||
Task(
|
||||
name="generate_final_report",
|
||||
description="Generate final session report",
|
||||
expected_output="Final session report",
|
||||
agent=report_generator,
|
||||
tools=[generate_session_report]
|
||||
)
|
||||
]
|
||||
|
||||
# Create new workflow instance for resumed session
|
||||
resumed_workflow = PraisonAIAgents(
|
||||
agents=[data_processor, status_monitor, task_runner, report_generator],
|
||||
tasks=resumed_tasks,
|
||||
verbose=True,
|
||||
process="sequential",
|
||||
memory=True
|
||||
)
|
||||
|
||||
# Make resumed_workflow available globally for tools
|
||||
workflow = resumed_workflow
|
||||
|
||||
# Restore session state
|
||||
print(f"\n=== Resuming Session: {session_id} ===")
|
||||
workflow.restore_session_state(session_id)
|
||||
restored_state = workflow.get_all_state()
|
||||
print(f"Restored {len(restored_state)} state keys")
|
||||
|
||||
# Show what was restored
|
||||
print("\nRestored state includes:")
|
||||
print(f"- Processed customers: {workflow.get_state('processed_customers', [])}")
|
||||
print(f"- Total records: {workflow.get_state('total_records_processed', 0)}")
|
||||
print(f"- Task progress: {workflow.get_state('data_migration_progress', 0)}%")
|
||||
|
||||
# Continue workflow
|
||||
print("\n=== Continuing Workflow ===")
|
||||
result = resumed_workflow.start()
|
||||
|
||||
# Final state summary
|
||||
print("\n=== Final Session Summary ===")
|
||||
final_state = workflow.get_all_state()
|
||||
print(f"Total customers processed: {workflow.get_state('total_customers_processed', 0)}")
|
||||
print(f"Total records processed: {workflow.get_state('total_records_processed', 0)}")
|
||||
print(f"Checkpoints created: {workflow.get_state('checkpoint_number', 0)}")
|
||||
print(f"Task status: {workflow.get_state('data_migration_status', 'unknown')}")
|
||||
@@ -0,0 +1,396 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Loop Control with State Example
|
||||
==============================
|
||||
|
||||
This example demonstrates how to use state to control loops and iterative processes.
|
||||
Tasks can loop based on state conditions until certain criteria are met.
|
||||
|
||||
Run this example:
|
||||
python 05_loop_control_with_state.py
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import time
|
||||
import random
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
|
||||
|
||||
def process_batch() -> str:
|
||||
"""Process data in batches using state to track progress"""
|
||||
# Initialize batch state if needed
|
||||
if not workflow.has_state("batch_total"):
|
||||
workflow.set_state("batch_total", 5)
|
||||
workflow.set_state("batch_current", 0)
|
||||
workflow.set_state("batch_start_time", datetime.now().isoformat())
|
||||
|
||||
# Get current batch info
|
||||
batch_current = workflow.get_state("batch_current")
|
||||
batch_total = workflow.get_state("batch_total")
|
||||
|
||||
# Process next batch
|
||||
batch_current += 1
|
||||
workflow.set_state("batch_current", batch_current)
|
||||
|
||||
# Simulate batch processing with random success/failure
|
||||
success = random.random() > 0.2 # 80% success rate
|
||||
records_processed = random.randint(80, 120) if success else 0
|
||||
|
||||
# Create batch result
|
||||
batch_result = {
|
||||
"batch_id": batch_current,
|
||||
"records_processed": records_processed,
|
||||
"status": "success" if success else "failed",
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
# Store batch result
|
||||
workflow.append_to_state("batch_results", batch_result)
|
||||
|
||||
# Update statistics
|
||||
if success:
|
||||
workflow.increment_state("successful_batches", 1, default=0)
|
||||
workflow.increment_state("total_records_processed", records_processed, default=0)
|
||||
else:
|
||||
workflow.increment_state("failed_batches", 1, default=0)
|
||||
# Add to retry queue
|
||||
workflow.append_to_state("retry_queue", batch_current)
|
||||
|
||||
# Determine if more batches
|
||||
if batch_current < batch_total:
|
||||
return "more_batches"
|
||||
else:
|
||||
# Check if we have retries
|
||||
retry_queue = workflow.get_state("retry_queue", [])
|
||||
if retry_queue:
|
||||
return "process_retries"
|
||||
else:
|
||||
return "all_batches_complete"
|
||||
|
||||
|
||||
def process_retry_batch() -> str:
|
||||
"""Process failed batches from retry queue"""
|
||||
retry_queue = workflow.get_state("retry_queue", [])
|
||||
|
||||
if not retry_queue:
|
||||
return "no_retries"
|
||||
|
||||
# Get next batch to retry
|
||||
batch_id = retry_queue.pop(0)
|
||||
workflow.set_state("retry_queue", retry_queue)
|
||||
|
||||
# Increment retry counter
|
||||
workflow.increment_state(f"batch_{batch_id}_retry_count", 1, default=0)
|
||||
retry_count = workflow.get_state(f"batch_{batch_id}_retry_count")
|
||||
|
||||
# Process with higher success rate on retry
|
||||
success = random.random() > 0.1 # 90% success rate on retry
|
||||
records_processed = random.randint(80, 120) if success else 0
|
||||
|
||||
# Update batch result
|
||||
retry_result = {
|
||||
"batch_id": batch_id,
|
||||
"records_processed": records_processed,
|
||||
"status": "retry_success" if success else "retry_failed",
|
||||
"retry_attempt": retry_count,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
}
|
||||
|
||||
workflow.append_to_state("retry_results", retry_result)
|
||||
|
||||
if success:
|
||||
workflow.increment_state("successful_retries", 1, default=0)
|
||||
workflow.increment_state("total_records_processed", records_processed, default=0)
|
||||
else:
|
||||
# Check retry limit
|
||||
if retry_count < 3:
|
||||
# Add back to retry queue
|
||||
retry_queue.append(batch_id)
|
||||
workflow.set_state("retry_queue", retry_queue)
|
||||
else:
|
||||
# Mark as permanently failed
|
||||
workflow.append_to_state("permanently_failed_batches", batch_id)
|
||||
|
||||
# Check if more retries needed
|
||||
retry_queue = workflow.get_state("retry_queue", [])
|
||||
if retry_queue:
|
||||
return "more_retries"
|
||||
else:
|
||||
return "retries_complete"
|
||||
|
||||
|
||||
def collect_paginated_data() -> str:
|
||||
"""Collect data from paginated API using state"""
|
||||
# Initialize pagination state
|
||||
if not workflow.has_state("current_page"):
|
||||
workflow.set_state("current_page", 1)
|
||||
workflow.set_state("total_pages", 0) # Will be set after first call
|
||||
workflow.set_state("items_collected", [])
|
||||
|
||||
current_page = workflow.get_state("current_page")
|
||||
|
||||
# Simulate API call
|
||||
if current_page == 1:
|
||||
# First call - determine total pages
|
||||
total_pages = 4
|
||||
workflow.set_state("total_pages", total_pages)
|
||||
|
||||
# Simulate collecting items
|
||||
items_per_page = random.randint(8, 12)
|
||||
new_items = [f"item_{current_page}_{i}" for i in range(items_per_page)]
|
||||
|
||||
# Add to collected items
|
||||
items = workflow.get_state("items_collected", [])
|
||||
items.extend(new_items)
|
||||
workflow.set_state("items_collected", items)
|
||||
|
||||
# Update page counter
|
||||
workflow.increment_state("current_page", 1)
|
||||
|
||||
# Log page processing
|
||||
workflow.append_to_state("page_log", {
|
||||
"page": current_page,
|
||||
"items_collected": items_per_page,
|
||||
"timestamp": datetime.now().isoformat()
|
||||
})
|
||||
|
||||
# Check if more pages
|
||||
total_pages = workflow.get_state("total_pages")
|
||||
if current_page < total_pages:
|
||||
return "more_pages"
|
||||
else:
|
||||
return "pagination_complete"
|
||||
|
||||
|
||||
def validate_collected_items() -> str:
|
||||
"""Validate all collected items"""
|
||||
items = workflow.get_state("items_collected", [])
|
||||
|
||||
# Initialize validation state
|
||||
if not workflow.has_state("validation_index"):
|
||||
workflow.set_state("validation_index", 0)
|
||||
workflow.set_state("valid_items", [])
|
||||
workflow.set_state("invalid_items", [])
|
||||
|
||||
validation_index = workflow.get_state("validation_index")
|
||||
batch_size = 5 # Validate 5 items at a time
|
||||
|
||||
# Get items to validate in this iteration
|
||||
end_index = min(validation_index + batch_size, len(items))
|
||||
items_to_validate = items[validation_index:end_index]
|
||||
|
||||
# Simulate validation
|
||||
for item in items_to_validate:
|
||||
# Random validation (90% valid)
|
||||
is_valid = random.random() > 0.1
|
||||
|
||||
if is_valid:
|
||||
workflow.append_to_state("valid_items", item)
|
||||
else:
|
||||
workflow.append_to_state("invalid_items", item)
|
||||
|
||||
# Update validation index
|
||||
workflow.set_state("validation_index", end_index)
|
||||
|
||||
# Check if more items to validate
|
||||
if end_index < len(items):
|
||||
return "more_validation"
|
||||
else:
|
||||
return "validation_complete"
|
||||
|
||||
|
||||
def generate_loop_report() -> str:
|
||||
"""Generate comprehensive report on all loop operations"""
|
||||
# Batch processing stats
|
||||
batch_total = workflow.get_state("batch_total", 0)
|
||||
successful_batches = workflow.get_state("successful_batches", 0)
|
||||
failed_batches = workflow.get_state("failed_batches", 0)
|
||||
successful_retries = workflow.get_state("successful_retries", 0)
|
||||
permanently_failed = len(workflow.get_state("permanently_failed_batches", []))
|
||||
total_records = workflow.get_state("total_records_processed", 0)
|
||||
|
||||
# Pagination stats
|
||||
total_pages = workflow.get_state("total_pages", 0)
|
||||
items_collected = len(workflow.get_state("items_collected", []))
|
||||
|
||||
# Validation stats
|
||||
valid_items = len(workflow.get_state("valid_items", []))
|
||||
invalid_items = len(workflow.get_state("invalid_items", []))
|
||||
|
||||
# Calculate timing
|
||||
start_time = workflow.get_state("batch_start_time", "unknown")
|
||||
|
||||
report = f"""
|
||||
Loop Operations Report
|
||||
=====================
|
||||
|
||||
Batch Processing:
|
||||
- Total Batches: {batch_total}
|
||||
- Successful: {successful_batches}
|
||||
- Failed Initially: {failed_batches}
|
||||
- Successful Retries: {successful_retries}
|
||||
- Permanently Failed: {permanently_failed}
|
||||
- Total Records Processed: {total_records}
|
||||
- Success Rate: {((successful_batches + successful_retries) / batch_total * 100):.1f}%
|
||||
|
||||
Pagination Collection:
|
||||
- Pages Processed: {total_pages}
|
||||
- Items Collected: {items_collected}
|
||||
- Average Items/Page: {items_collected / total_pages:.1f}
|
||||
|
||||
Validation Results:
|
||||
- Total Items: {items_collected}
|
||||
- Valid Items: {valid_items}
|
||||
- Invalid Items: {invalid_items}
|
||||
- Validation Rate: {(valid_items / items_collected * 100):.1f}%
|
||||
|
||||
Processing Started: {start_time}
|
||||
"""
|
||||
|
||||
# Add batch failure details
|
||||
retry_results = workflow.get_state("retry_results", [])
|
||||
if retry_results:
|
||||
report += "\n Retry Details:\n"
|
||||
for result in retry_results[-3:]: # Last 3 retries
|
||||
report += f" - Batch {result['batch_id']}: {result['status']} (Attempt {result['retry_attempt']})\n"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
# Create agents
|
||||
batch_processor = Agent(
|
||||
name="BatchProcessor",
|
||||
role="Process data in batches",
|
||||
goal="Process all batches successfully with retry logic",
|
||||
backstory="A batch processing expert",
|
||||
tools=[process_batch, process_retry_batch],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
data_collector = Agent(
|
||||
name="DataCollector",
|
||||
role="Collect paginated data",
|
||||
goal="Collect all data from paginated source",
|
||||
backstory="A data collection specialist",
|
||||
tools=[collect_paginated_data],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
validator = Agent(
|
||||
name="Validator",
|
||||
role="Validate collected items",
|
||||
goal="Validate all collected items in batches",
|
||||
backstory="A data validation expert",
|
||||
tools=[validate_collected_items],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
reporter = Agent(
|
||||
name="Reporter",
|
||||
role="Generate reports",
|
||||
goal="Create comprehensive reports on loop operations",
|
||||
backstory="A reporting specialist",
|
||||
tools=[generate_loop_report],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create loop tasks
|
||||
batch_loop_task = Task(
|
||||
name="process_batches",
|
||||
description="Process all data batches",
|
||||
expected_output="Batch processing status",
|
||||
agent=batch_processor,
|
||||
tools=[process_batch],
|
||||
task_type="loop",
|
||||
condition={
|
||||
"more_batches": ["process_batches"], # Loop back to itself
|
||||
"process_retries": ["retry_failed_batches"],
|
||||
"all_batches_complete": ["collect_pages"] # Go to next task
|
||||
}
|
||||
)
|
||||
|
||||
retry_loop_task = Task(
|
||||
name="retry_failed_batches",
|
||||
description="Retry processing for failed batches",
|
||||
expected_output="Retry processing status",
|
||||
agent=batch_processor,
|
||||
tools=[process_retry_batch],
|
||||
task_type="loop",
|
||||
condition={
|
||||
"more_retries": ["retry_failed_batches"], # Loop back to itself
|
||||
"retries_complete": ["collect_pages"],
|
||||
"no_retries": ["collect_pages"]
|
||||
}
|
||||
)
|
||||
|
||||
pagination_loop_task = Task(
|
||||
name="collect_pages",
|
||||
description="Collect all pages of data",
|
||||
expected_output="Page collection status",
|
||||
agent=data_collector,
|
||||
tools=[collect_paginated_data],
|
||||
task_type="loop",
|
||||
condition={
|
||||
"more_pages": ["collect_pages"], # Loop back to itself
|
||||
"pagination_complete": ["validate_items"]
|
||||
}
|
||||
)
|
||||
|
||||
validation_loop_task = Task(
|
||||
name="validate_items",
|
||||
description="Validate all collected items in batches",
|
||||
expected_output="Validation status",
|
||||
agent=validator,
|
||||
tools=[validate_collected_items],
|
||||
task_type="loop",
|
||||
condition={
|
||||
"more_validation": ["validate_items"], # Loop back to itself
|
||||
"validation_complete": ["generate_report"]
|
||||
}
|
||||
)
|
||||
|
||||
report_task = Task(
|
||||
name="generate_report",
|
||||
description="Generate final report on all loop operations",
|
||||
expected_output="Comprehensive loop operations report",
|
||||
agent=reporter,
|
||||
tools=[generate_loop_report]
|
||||
)
|
||||
|
||||
# Create workflow
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[batch_processor, data_collector, validator, reporter],
|
||||
tasks=[batch_loop_task, retry_loop_task, pagination_loop_task, validation_loop_task, report_task],
|
||||
verbose=True,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Initialize workflow
|
||||
print("\n=== Starting Loop Control Example ===")
|
||||
print("This example will demonstrate:")
|
||||
print("1. Batch processing with automatic retry on failure")
|
||||
print("2. Paginated data collection")
|
||||
print("3. Iterative validation of collected items")
|
||||
print("4. All controlled by state-based loop conditions")
|
||||
|
||||
# Run workflow
|
||||
result = workflow.start()
|
||||
|
||||
# Display loop statistics
|
||||
print("\n=== Loop Statistics ===")
|
||||
print(f"Total loop iterations:")
|
||||
print(f"- Batch processing: {workflow.get_state('batch_current', 0)} batches")
|
||||
print(f"- Retry processing: {len(workflow.get_state('retry_results', []))} retries")
|
||||
print(f"- Page collection: {workflow.get_state('current_page', 1) - 1} pages")
|
||||
print(f"- Item validation: {workflow.get_state('validation_index', 0)} items validated")
|
||||
|
||||
# Show state size
|
||||
print(f"\n=== State Management ===")
|
||||
print(f"Total state keys: {len(workflow.get_all_state())}")
|
||||
print(f"Batch results stored: {len(workflow.get_state('batch_results', []))}")
|
||||
print(f"Items collected: {len(workflow.get_state('items_collected', []))}")
|
||||
@@ -0,0 +1,600 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Advanced State Operations Example
|
||||
================================
|
||||
|
||||
This example demonstrates advanced state management techniques including:
|
||||
- Working with complex nested state
|
||||
- State transformations and calculations
|
||||
- Error handling with state
|
||||
- State-based caching
|
||||
- Concurrent state updates
|
||||
|
||||
Run this example:
|
||||
python 06_advanced_state_operations.py
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, Task, PraisonAIAgents
|
||||
import json
|
||||
import time
|
||||
import hashlib
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, Any, List, Optional
|
||||
|
||||
|
||||
def manage_nested_state() -> str:
|
||||
"""Demonstrate working with complex nested state structures"""
|
||||
# Initialize complex state structure
|
||||
if not workflow.has_state("system_config"):
|
||||
workflow.set_state("system_config", {
|
||||
"database": {
|
||||
"host": "localhost",
|
||||
"port": 5432,
|
||||
"connections": {
|
||||
"max": 100,
|
||||
"active": 0,
|
||||
"idle": 100
|
||||
}
|
||||
},
|
||||
"api": {
|
||||
"endpoints": {
|
||||
"v1": {"users": True, "products": True},
|
||||
"v2": {"users": True, "products": True, "analytics": False}
|
||||
},
|
||||
"rate_limits": {
|
||||
"global": 1000,
|
||||
"per_user": 100
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
"authentication": True,
|
||||
"caching": True,
|
||||
"monitoring": False
|
||||
}
|
||||
})
|
||||
|
||||
# Get and modify nested state
|
||||
config = workflow.get_state("system_config")
|
||||
|
||||
# Update nested values
|
||||
config["database"]["connections"]["active"] += 10
|
||||
config["database"]["connections"]["idle"] -= 10
|
||||
config["api"]["endpoints"]["v2"]["analytics"] = True
|
||||
config["features"]["monitoring"] = True
|
||||
|
||||
# Add new nested section
|
||||
config["performance"] = {
|
||||
"cache_size": "512MB",
|
||||
"worker_threads": 4,
|
||||
"optimizations": {
|
||||
"query_cache": True,
|
||||
"connection_pooling": True,
|
||||
"lazy_loading": False
|
||||
}
|
||||
}
|
||||
|
||||
# Save updated config
|
||||
workflow.set_state("system_config", config)
|
||||
|
||||
# Create a summary
|
||||
summary = f"""
|
||||
Nested State Update Complete:
|
||||
- Active DB Connections: {config['database']['connections']['active']}
|
||||
- API v2 Analytics: {'Enabled' if config['api']['endpoints']['v2']['analytics'] else 'Disabled'}
|
||||
- Monitoring: {'Enabled' if config['features']['monitoring'] else 'Disabled'}
|
||||
- New Performance Section Added
|
||||
"""
|
||||
|
||||
return summary
|
||||
|
||||
|
||||
def implement_state_cache() -> Dict[str, Any]:
|
||||
"""Implement caching mechanism using state"""
|
||||
cache_key = "api_responses"
|
||||
|
||||
# Initialize cache if not exists
|
||||
if not workflow.has_state(cache_key):
|
||||
workflow.set_state(cache_key, {})
|
||||
workflow.set_state("cache_stats", {
|
||||
"hits": 0,
|
||||
"misses": 0,
|
||||
"evictions": 0
|
||||
})
|
||||
|
||||
# Simulate API calls with caching
|
||||
api_calls = ["user_123", "product_456", "user_123", "order_789", "product_456"]
|
||||
results = []
|
||||
|
||||
cache = workflow.get_state(cache_key)
|
||||
cache_stats = workflow.get_state("cache_stats")
|
||||
max_cache_size = 3
|
||||
cache_ttl_seconds = 300 # 5 minutes
|
||||
|
||||
for call_id in api_calls:
|
||||
current_time = time.time()
|
||||
|
||||
# Check cache
|
||||
if call_id in cache:
|
||||
cached_data = cache[call_id]
|
||||
# Check if cache is still valid
|
||||
if current_time - cached_data["timestamp"] < cache_ttl_seconds:
|
||||
# Cache hit
|
||||
cache_stats["hits"] += 1
|
||||
results.append({
|
||||
"id": call_id,
|
||||
"data": cached_data["data"],
|
||||
"source": "cache",
|
||||
"age": current_time - cached_data["timestamp"]
|
||||
})
|
||||
continue
|
||||
|
||||
# Cache miss - simulate API call
|
||||
cache_stats["misses"] += 1
|
||||
api_data = f"data_for_{call_id}_{int(current_time)}"
|
||||
|
||||
# Add to cache with eviction if needed
|
||||
if len(cache) >= max_cache_size:
|
||||
# Evict oldest entry
|
||||
oldest_key = min(cache.keys(), key=lambda k: cache[k]["timestamp"])
|
||||
del cache[oldest_key]
|
||||
cache_stats["evictions"] += 1
|
||||
|
||||
cache[call_id] = {
|
||||
"data": api_data,
|
||||
"timestamp": current_time
|
||||
}
|
||||
|
||||
results.append({
|
||||
"id": call_id,
|
||||
"data": api_data,
|
||||
"source": "api",
|
||||
"age": 0
|
||||
})
|
||||
|
||||
# Update state
|
||||
workflow.set_state(cache_key, cache)
|
||||
workflow.set_state("cache_stats", cache_stats)
|
||||
|
||||
return {
|
||||
"results": results,
|
||||
"cache_stats": cache_stats,
|
||||
"cache_size": len(cache)
|
||||
}
|
||||
|
||||
|
||||
def calculate_derived_metrics() -> Dict[str, Any]:
|
||||
"""Calculate and store derived metrics from state data"""
|
||||
# Get various state values
|
||||
total_records = workflow.get_state("total_records_processed", 0)
|
||||
processing_time = workflow.get_state("total_processing_time", 0)
|
||||
error_count = workflow.get_state("total_errors", 0)
|
||||
successful_operations = workflow.get_state("successful_operations", 0)
|
||||
|
||||
# Initialize metrics state
|
||||
if not workflow.has_state("performance_metrics"):
|
||||
workflow.set_state("performance_metrics", {})
|
||||
|
||||
metrics = workflow.get_state("performance_metrics")
|
||||
|
||||
# Calculate derived metrics
|
||||
if processing_time > 0:
|
||||
throughput = total_records / processing_time
|
||||
else:
|
||||
throughput = 0
|
||||
|
||||
if successful_operations > 0:
|
||||
error_rate = (error_count / (successful_operations + error_count)) * 100
|
||||
else:
|
||||
error_rate = 0
|
||||
|
||||
# Moving averages
|
||||
if "throughput_history" not in metrics:
|
||||
metrics["throughput_history"] = []
|
||||
|
||||
metrics["throughput_history"].append(throughput)
|
||||
if len(metrics["throughput_history"]) > 10:
|
||||
metrics["throughput_history"] = metrics["throughput_history"][-10:]
|
||||
|
||||
avg_throughput = sum(metrics["throughput_history"]) / len(metrics["throughput_history"])
|
||||
|
||||
# Update metrics
|
||||
metrics.update({
|
||||
"current_throughput": throughput,
|
||||
"average_throughput": avg_throughput,
|
||||
"error_rate": error_rate,
|
||||
"efficiency": (successful_operations / (successful_operations + error_count) * 100) if (successful_operations + error_count) > 0 else 0,
|
||||
"last_calculated": datetime.now().isoformat()
|
||||
})
|
||||
|
||||
workflow.set_state("performance_metrics", metrics)
|
||||
|
||||
return metrics
|
||||
|
||||
|
||||
def handle_state_transactions() -> str:
|
||||
"""Demonstrate transaction-like state updates with rollback capability"""
|
||||
# Create transaction checkpoint
|
||||
transaction_id = f"txn_{int(time.time())}"
|
||||
|
||||
# Save current state as checkpoint
|
||||
checkpoint = {
|
||||
"balance": workflow.get_state("account_balance", 1000),
|
||||
"transactions": workflow.get_state("transaction_history", []).copy(),
|
||||
"inventory": workflow.get_state("inventory", {"item_a": 10, "item_b": 20}).copy()
|
||||
}
|
||||
|
||||
workflow.set_state(f"checkpoint_{transaction_id}", checkpoint)
|
||||
|
||||
try:
|
||||
# Perform multiple state updates (simulating a transaction)
|
||||
balance = workflow.get_state("account_balance", 1000)
|
||||
inventory = workflow.get_state("inventory", {"item_a": 10, "item_b": 20})
|
||||
|
||||
# Simulate purchase
|
||||
item_cost = 250
|
||||
if balance >= item_cost and inventory["item_a"] > 0:
|
||||
# Update balance
|
||||
workflow.set_state("account_balance", balance - item_cost)
|
||||
|
||||
# Update inventory
|
||||
inventory["item_a"] -= 1
|
||||
workflow.set_state("inventory", inventory)
|
||||
|
||||
# Add to transaction history
|
||||
workflow.append_to_state("transaction_history", {
|
||||
"id": transaction_id,
|
||||
"type": "purchase",
|
||||
"item": "item_a",
|
||||
"amount": item_cost,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"status": "completed"
|
||||
})
|
||||
|
||||
# Simulate potential failure
|
||||
if workflow.get_state("simulate_failure", False):
|
||||
raise Exception("Simulated transaction failure")
|
||||
|
||||
result = f"Transaction {transaction_id} completed successfully"
|
||||
else:
|
||||
raise Exception("Insufficient balance or inventory")
|
||||
|
||||
except Exception as e:
|
||||
# Rollback on failure
|
||||
checkpoint = workflow.get_state(f"checkpoint_{transaction_id}")
|
||||
workflow.set_state("account_balance", checkpoint["balance"])
|
||||
workflow.set_state("transaction_history", checkpoint["transactions"])
|
||||
workflow.set_state("inventory", checkpoint["inventory"])
|
||||
|
||||
# Log failed transaction
|
||||
workflow.append_to_state("failed_transactions", {
|
||||
"id": transaction_id,
|
||||
"error": str(e),
|
||||
"timestamp": datetime.now().isoformat()
|
||||
})
|
||||
|
||||
result = f"Transaction {transaction_id} failed and rolled back: {str(e)}"
|
||||
|
||||
finally:
|
||||
# Clean up checkpoint
|
||||
workflow.delete_state(f"checkpoint_{transaction_id}")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def manage_state_versioning() -> Dict[str, Any]:
|
||||
"""Implement state versioning for audit trail"""
|
||||
config_key = "application_config"
|
||||
|
||||
# Initialize versioning system
|
||||
if not workflow.has_state("state_versions"):
|
||||
workflow.set_state("state_versions", {})
|
||||
workflow.set_state("version_counter", 0)
|
||||
|
||||
# Get current config
|
||||
current_config = workflow.get_state(config_key, {
|
||||
"theme": "light",
|
||||
"language": "en",
|
||||
"notifications": True
|
||||
})
|
||||
|
||||
# Create new version before changes
|
||||
version_counter = workflow.get_state("version_counter")
|
||||
version_counter += 1
|
||||
workflow.set_state("version_counter", version_counter)
|
||||
|
||||
# Store current version
|
||||
versions = workflow.get_state("state_versions")
|
||||
version_id = f"v{version_counter}"
|
||||
versions[version_id] = {
|
||||
"config": current_config.copy(),
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"hash": hashlib.md5(json.dumps(current_config, sort_keys=True).encode()).hexdigest()
|
||||
}
|
||||
|
||||
# Make changes
|
||||
new_config = current_config.copy()
|
||||
new_config["theme"] = "dark"
|
||||
new_config["language"] = "es"
|
||||
new_config["font_size"] = 14
|
||||
|
||||
# Store new version
|
||||
workflow.set_state(config_key, new_config)
|
||||
workflow.set_state("state_versions", versions)
|
||||
|
||||
# Calculate diff
|
||||
changes = []
|
||||
for key in set(list(current_config.keys()) + list(new_config.keys())):
|
||||
old_val = current_config.get(key, "not_set")
|
||||
new_val = new_config.get(key, "not_set")
|
||||
if old_val != new_val:
|
||||
changes.append({
|
||||
"field": key,
|
||||
"old": old_val,
|
||||
"new": new_val
|
||||
})
|
||||
|
||||
return {
|
||||
"version": version_id,
|
||||
"changes": changes,
|
||||
"total_versions": len(versions),
|
||||
"config_hash": versions[version_id]["hash"]
|
||||
}
|
||||
|
||||
|
||||
def aggregate_distributed_state() -> str:
|
||||
"""Simulate aggregating state from multiple sources"""
|
||||
# Initialize distributed nodes state
|
||||
nodes = ["node_1", "node_2", "node_3"]
|
||||
|
||||
for node in nodes:
|
||||
if not workflow.has_state(f"{node}_metrics"):
|
||||
workflow.set_state(f"{node}_metrics", {
|
||||
"requests": int(time.time() % 1000),
|
||||
"errors": int(time.time() % 10),
|
||||
"latency": int(time.time() % 100),
|
||||
"uptime": 99.5 + (time.time() % 0.5)
|
||||
})
|
||||
|
||||
# Aggregate metrics
|
||||
aggregated = {
|
||||
"total_requests": 0,
|
||||
"total_errors": 0,
|
||||
"avg_latency": 0,
|
||||
"min_uptime": 100,
|
||||
"nodes_reporting": 0
|
||||
}
|
||||
|
||||
latencies = []
|
||||
|
||||
for node in nodes:
|
||||
node_metrics = workflow.get_state(f"{node}_metrics")
|
||||
if node_metrics:
|
||||
aggregated["total_requests"] += node_metrics["requests"]
|
||||
aggregated["total_errors"] += node_metrics["errors"]
|
||||
latencies.append(node_metrics["latency"])
|
||||
aggregated["min_uptime"] = min(aggregated["min_uptime"], node_metrics["uptime"])
|
||||
aggregated["nodes_reporting"] += 1
|
||||
|
||||
if latencies:
|
||||
aggregated["avg_latency"] = sum(latencies) / len(latencies)
|
||||
|
||||
# Store aggregated state with timestamp
|
||||
workflow.set_state("aggregated_metrics", {
|
||||
"data": aggregated,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"nodes": nodes
|
||||
})
|
||||
|
||||
# Create summary
|
||||
summary = f"""
|
||||
Distributed State Aggregation:
|
||||
- Nodes: {aggregated['nodes_reporting']}/{len(nodes)}
|
||||
- Total Requests: {aggregated['total_requests']}
|
||||
- Total Errors: {aggregated['total_errors']}
|
||||
- Average Latency: {aggregated['avg_latency']:.2f}ms
|
||||
- Minimum Uptime: {aggregated['min_uptime']:.2f}%
|
||||
"""
|
||||
|
||||
return summary
|
||||
|
||||
|
||||
def generate_advanced_report() -> str:
|
||||
"""Generate comprehensive report on advanced state operations"""
|
||||
system_config = workflow.get_state("system_config", {})
|
||||
cache_stats = workflow.get_state("cache_stats", {})
|
||||
performance_metrics = workflow.get_state("performance_metrics", {})
|
||||
transaction_history = workflow.get_state("transaction_history", [])
|
||||
failed_transactions = workflow.get_state("failed_transactions", [])
|
||||
versions = workflow.get_state("state_versions", {})
|
||||
aggregated_metrics = workflow.get_state("aggregated_metrics", {})
|
||||
|
||||
report = f"""
|
||||
Advanced State Operations Report
|
||||
===============================
|
||||
|
||||
System Configuration:
|
||||
- Database Connections: {system_config.get('database', {}).get('connections', {}).get('active', 0)} active
|
||||
- Features Enabled: {sum(1 for v in system_config.get('features', {}).values() if v)}
|
||||
- Performance Optimizations: {sum(1 for v in system_config.get('performance', {}).get('optimizations', {}).values() if v)}
|
||||
|
||||
Cache Performance:
|
||||
- Cache Hits: {cache_stats.get('hits', 0)}
|
||||
- Cache Misses: {cache_stats.get('misses', 0)}
|
||||
- Hit Rate: {(cache_stats.get('hits', 0) / (cache_stats.get('hits', 0) + cache_stats.get('misses', 0)) * 100):.1f}%
|
||||
- Evictions: {cache_stats.get('evictions', 0)}
|
||||
|
||||
Performance Metrics:
|
||||
- Current Throughput: {performance_metrics.get('current_throughput', 0):.2f} records/sec
|
||||
- Average Throughput: {performance_metrics.get('average_throughput', 0):.2f} records/sec
|
||||
- Error Rate: {performance_metrics.get('error_rate', 0):.2f}%
|
||||
- Efficiency: {performance_metrics.get('efficiency', 0):.2f}%
|
||||
|
||||
Transaction Management:
|
||||
- Successful Transactions: {len(transaction_history)}
|
||||
- Failed Transactions: {len(failed_transactions)}
|
||||
- Current Balance: ${workflow.get_state('account_balance', 0)}
|
||||
|
||||
State Versioning:
|
||||
- Total Versions: {len(versions)}
|
||||
- Latest Version: {max(versions.keys()) if versions else 'None'}
|
||||
|
||||
Distributed Aggregation:
|
||||
"""
|
||||
|
||||
if aggregated_metrics:
|
||||
data = aggregated_metrics.get('data', {})
|
||||
report += f"""
|
||||
- Reporting Nodes: {data.get('nodes_reporting', 0)}
|
||||
- Total Requests: {data.get('total_requests', 0)}
|
||||
- Average Latency: {data.get('avg_latency', 0):.2f}ms
|
||||
- System Uptime: {data.get('min_uptime', 0):.2f}%
|
||||
"""
|
||||
|
||||
return report
|
||||
|
||||
|
||||
# Create agents
|
||||
state_manager = Agent(
|
||||
name="StateManager",
|
||||
role="Manage complex state operations",
|
||||
goal="Demonstrate advanced state management techniques",
|
||||
backstory="An expert in state management",
|
||||
tools=[manage_nested_state, handle_state_transactions, manage_state_versioning],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
cache_manager = Agent(
|
||||
name="CacheManager",
|
||||
role="Implement and manage state-based caching",
|
||||
goal="Optimize performance with intelligent caching",
|
||||
backstory="A caching specialist",
|
||||
tools=[implement_state_cache],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
metrics_calculator = Agent(
|
||||
name="MetricsCalculator",
|
||||
role="Calculate derived metrics from state",
|
||||
goal="Provide insights through metric calculations",
|
||||
backstory="A data analytics expert",
|
||||
tools=[calculate_derived_metrics, aggregate_distributed_state],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
report_generator = Agent(
|
||||
name="ReportGenerator",
|
||||
role="Generate comprehensive reports",
|
||||
goal="Document all advanced state operations",
|
||||
backstory="A reporting specialist",
|
||||
tools=[generate_advanced_report],
|
||||
llm="gpt-4o-mini",
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Create tasks
|
||||
tasks = [
|
||||
Task(
|
||||
name="setup_nested_state",
|
||||
description="Set up and manage complex nested state structures",
|
||||
expected_output="Nested state configuration summary",
|
||||
agent=state_manager,
|
||||
tools=[manage_nested_state]
|
||||
),
|
||||
Task(
|
||||
name="implement_caching",
|
||||
description="Implement state-based caching with the API calls simulation",
|
||||
expected_output="Cache implementation results",
|
||||
agent=cache_manager,
|
||||
tools=[implement_state_cache]
|
||||
),
|
||||
Task(
|
||||
name="test_transactions",
|
||||
description="Test transaction-like state updates with rollback",
|
||||
expected_output="Transaction test results",
|
||||
agent=state_manager,
|
||||
tools=[handle_state_transactions]
|
||||
),
|
||||
Task(
|
||||
name="setup_versioning",
|
||||
description="Implement state versioning for configuration changes",
|
||||
expected_output="Versioning implementation results",
|
||||
agent=state_manager,
|
||||
tools=[manage_state_versioning]
|
||||
),
|
||||
Task(
|
||||
name="calculate_metrics",
|
||||
description="Calculate derived performance metrics from state",
|
||||
expected_output="Calculated metrics",
|
||||
agent=metrics_calculator,
|
||||
tools=[calculate_derived_metrics]
|
||||
),
|
||||
Task(
|
||||
name="aggregate_states",
|
||||
description="Aggregate state from distributed nodes",
|
||||
expected_output="Aggregation summary",
|
||||
agent=metrics_calculator,
|
||||
tools=[aggregate_distributed_state]
|
||||
),
|
||||
Task(
|
||||
name="generate_report",
|
||||
description="Generate final report on all advanced state operations",
|
||||
expected_output="Comprehensive state operations report",
|
||||
agent=report_generator,
|
||||
tools=[generate_advanced_report]
|
||||
)
|
||||
]
|
||||
|
||||
# Create workflow
|
||||
workflow = PraisonAIAgents(
|
||||
agents=[state_manager, cache_manager, metrics_calculator, report_generator],
|
||||
tasks=tasks,
|
||||
verbose=True,
|
||||
process="sequential"
|
||||
)
|
||||
|
||||
# Initialize some state for demonstrations
|
||||
print("\n=== Initializing Advanced State Operations ===")
|
||||
workflow.set_state("total_records_processed", 5000)
|
||||
workflow.set_state("total_processing_time", 120)
|
||||
workflow.set_state("total_errors", 23)
|
||||
workflow.set_state("successful_operations", 477)
|
||||
|
||||
# Run workflow
|
||||
result = workflow.start()
|
||||
|
||||
# Display final state summary
|
||||
print("\n=== Final State Summary ===")
|
||||
all_state = workflow.get_all_state()
|
||||
print(f"Total state keys: {len(all_state)}")
|
||||
print(f"State size (JSON): {len(json.dumps(all_state))} characters")
|
||||
|
||||
# Show state categories
|
||||
categories = {
|
||||
"config": 0,
|
||||
"metrics": 0,
|
||||
"cache": 0,
|
||||
"transaction": 0,
|
||||
"version": 0,
|
||||
"other": 0
|
||||
}
|
||||
|
||||
for key in all_state.keys():
|
||||
if "config" in key:
|
||||
categories["config"] += 1
|
||||
elif "metric" in key or "performance" in key:
|
||||
categories["metrics"] += 1
|
||||
elif "cache" in key:
|
||||
categories["cache"] += 1
|
||||
elif "transaction" in key or "balance" in key:
|
||||
categories["transaction"] += 1
|
||||
elif "version" in key:
|
||||
categories["version"] += 1
|
||||
else:
|
||||
categories["other"] += 1
|
||||
|
||||
print("\nState Categories:")
|
||||
for category, count in categories.items():
|
||||
print(f" - {category}: {count} keys")
|
||||
@@ -14,6 +14,7 @@ from .mcp.mcp import MCP
|
||||
from .session import Session
|
||||
from .memory.memory import Memory
|
||||
from .guardrails import GuardrailResult, LLMGuardrail
|
||||
from .agent.handoff import Handoff, handoff, handoff_filters, RECOMMENDED_PROMPT_PREFIX, prompt_with_handoff_instructions
|
||||
from .main import (
|
||||
TaskOutput,
|
||||
ReflectionOutput,
|
||||
@@ -102,6 +103,11 @@ __all__ = [
|
||||
'MCP',
|
||||
'GuardrailResult',
|
||||
'LLMGuardrail',
|
||||
'Handoff',
|
||||
'handoff',
|
||||
'handoff_filters',
|
||||
'RECOMMENDED_PROMPT_PREFIX',
|
||||
'prompt_with_handoff_instructions',
|
||||
'get_telemetry',
|
||||
'enable_telemetry',
|
||||
'disable_telemetry',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Agent module for AI agents"""
|
||||
from .agent import Agent
|
||||
from .image_agent import ImageAgent
|
||||
from .handoff import Handoff, handoff, handoff_filters, RECOMMENDED_PROMPT_PREFIX, prompt_with_handoff_instructions
|
||||
|
||||
__all__ = ['Agent', 'ImageAgent']
|
||||
__all__ = ['Agent', 'ImageAgent', 'Handoff', 'handoff', 'handoff_filters', 'RECOMMENDED_PROMPT_PREFIX', 'prompt_with_handoff_instructions']
|
||||
@@ -33,6 +33,7 @@ _shared_apps = {} # Dict of port -> FastAPI app
|
||||
if TYPE_CHECKING:
|
||||
from ..task.task import Task
|
||||
from ..main import TaskOutput
|
||||
from ..handoff import Handoff
|
||||
|
||||
@dataclass
|
||||
class ChatCompletionMessage:
|
||||
@@ -373,7 +374,10 @@ class Agent:
|
||||
user_id: Optional[str] = None,
|
||||
reasoning_steps: bool = False,
|
||||
guardrail: Optional[Union[Callable[['TaskOutput'], Tuple[bool, Any]], str]] = None,
|
||||
max_guardrail_retries: int = 3
|
||||
max_guardrail_retries: int = 3,
|
||||
handoffs: Optional[List[Union['Agent', 'Handoff']]] = None,
|
||||
base_url: Optional[str] = None,
|
||||
api_key: Optional[str] = None
|
||||
):
|
||||
"""Initialize an Agent instance.
|
||||
|
||||
@@ -457,6 +461,13 @@ class Agent:
|
||||
description string for LLM-based validation. Defaults to None.
|
||||
max_guardrail_retries (int, optional): Maximum number of retry attempts when guardrail
|
||||
validation fails before giving up. Defaults to 3.
|
||||
handoffs (Optional[List[Union['Agent', 'Handoff']]], optional): List of agents or
|
||||
handoff configurations that this agent can delegate tasks to. Enables agent-to-agent
|
||||
collaboration and task specialization. Defaults to None.
|
||||
base_url (Optional[str], optional): Base URL for custom LLM endpoints (e.g., Ollama).
|
||||
If provided, automatically creates a custom LLM instance. Defaults to None.
|
||||
api_key (Optional[str], optional): API key for LLM provider. If not provided,
|
||||
falls back to environment variables. Defaults to None.
|
||||
|
||||
Raises:
|
||||
ValueError: If all of name, role, goal, backstory, and instructions are None.
|
||||
@@ -503,10 +514,40 @@ class Agent:
|
||||
# Check for model name in environment variable if not provided
|
||||
self._using_custom_llm = False
|
||||
|
||||
# If the user passes a dictionary (for advanced configuration)
|
||||
if isinstance(llm, dict) and "model" in llm:
|
||||
# If base_url is provided, always create a custom LLM instance
|
||||
if base_url:
|
||||
try:
|
||||
from ..llm.llm import LLM
|
||||
# Handle different llm parameter types with base_url
|
||||
if isinstance(llm, dict):
|
||||
# Merge base_url and api_key into the dict
|
||||
llm_config = llm.copy()
|
||||
llm_config['base_url'] = base_url
|
||||
if api_key:
|
||||
llm_config['api_key'] = api_key
|
||||
self.llm_instance = LLM(**llm_config)
|
||||
else:
|
||||
# Create LLM with model string and base_url
|
||||
model_name = llm or os.getenv('OPENAI_MODEL_NAME', 'gpt-4o')
|
||||
self.llm_instance = LLM(
|
||||
model=model_name,
|
||||
base_url=base_url,
|
||||
api_key=api_key
|
||||
)
|
||||
self._using_custom_llm = True
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
"LLM features requested but dependencies not installed. "
|
||||
"Please install with: pip install \"praisonaiagents[llm]\""
|
||||
) from e
|
||||
# If the user passes a dictionary (for advanced configuration)
|
||||
elif isinstance(llm, dict) and "model" in llm:
|
||||
try:
|
||||
from ..llm.llm import LLM
|
||||
# Add api_key if provided and not in dict
|
||||
if api_key and 'api_key' not in llm:
|
||||
llm = llm.copy()
|
||||
llm['api_key'] = api_key
|
||||
self.llm_instance = LLM(**llm) # Pass all dict items as kwargs
|
||||
self._using_custom_llm = True
|
||||
except ImportError as e:
|
||||
@@ -519,7 +560,10 @@ class Agent:
|
||||
try:
|
||||
from ..llm.llm import LLM
|
||||
# Pass the entire string so LiteLLM can parse provider/model
|
||||
self.llm_instance = LLM(model=llm)
|
||||
llm_params = {'model': llm}
|
||||
if api_key:
|
||||
llm_params['api_key'] = api_key
|
||||
self.llm_instance = LLM(**llm_params)
|
||||
self._using_custom_llm = True
|
||||
|
||||
# Ensure tools are properly accessible when using custom LLM
|
||||
@@ -584,6 +628,10 @@ Your Goal: {self.goal}
|
||||
self._guardrail_fn = None
|
||||
self._setup_guardrail()
|
||||
|
||||
# Process handoffs and convert them to tools
|
||||
self.handoffs = handoffs if handoffs else []
|
||||
self._process_handoffs()
|
||||
|
||||
# Check if knowledge parameter has any values
|
||||
if not knowledge:
|
||||
self.knowledge = None
|
||||
@@ -657,6 +705,34 @@ Your Goal: {self.goal}
|
||||
else:
|
||||
raise ValueError("Agent guardrail must be either a callable or a string description")
|
||||
|
||||
def _process_handoffs(self):
|
||||
"""Process handoffs and convert them to tools that can be used by the agent."""
|
||||
if not self.handoffs:
|
||||
return
|
||||
|
||||
# Import here to avoid circular imports
|
||||
from .handoff import Handoff
|
||||
|
||||
for handoff_item in self.handoffs:
|
||||
try:
|
||||
if isinstance(handoff_item, Handoff):
|
||||
# Convert Handoff object to a tool function
|
||||
tool_func = handoff_item.to_tool_function(self)
|
||||
self.tools.append(tool_func)
|
||||
elif hasattr(handoff_item, 'name') and hasattr(handoff_item, 'chat'):
|
||||
# Direct agent reference - create a simple handoff
|
||||
from .handoff import handoff
|
||||
handoff_obj = handoff(handoff_item)
|
||||
tool_func = handoff_obj.to_tool_function(self)
|
||||
self.tools.append(tool_func)
|
||||
else:
|
||||
logging.warning(
|
||||
f"Invalid handoff item type: {type(handoff_item)}. "
|
||||
"Expected Agent or Handoff instance."
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to process handoff item {handoff_item}: {e}")
|
||||
|
||||
def _process_guardrail(self, task_output):
|
||||
"""Process the guardrail validation for a task output.
|
||||
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
"""
|
||||
Handoff functionality for agent-to-agent delegation.
|
||||
|
||||
This module provides handoff capabilities that allow agents to delegate tasks
|
||||
to other agents, similar to the OpenAI Agents SDK implementation.
|
||||
"""
|
||||
|
||||
from typing import Optional, Any, Callable, Dict, TYPE_CHECKING
|
||||
from dataclasses import dataclass, field
|
||||
import inspect
|
||||
import logging
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .agent import Agent
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class HandoffInputData:
|
||||
"""Data passed to a handoff target agent."""
|
||||
messages: list = field(default_factory=list)
|
||||
context: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
class Handoff:
|
||||
"""
|
||||
Represents a handoff configuration for delegating tasks to another agent.
|
||||
|
||||
Handoffs are represented as tools to the LLM, allowing agents to transfer
|
||||
control to specialized agents for specific tasks.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
agent: 'Agent',
|
||||
tool_name_override: Optional[str] = None,
|
||||
tool_description_override: Optional[str] = None,
|
||||
on_handoff: Optional[Callable] = None,
|
||||
input_type: Optional[type] = None,
|
||||
input_filter: Optional[Callable[[HandoffInputData], HandoffInputData]] = None
|
||||
):
|
||||
"""
|
||||
Initialize a Handoff configuration.
|
||||
|
||||
Args:
|
||||
agent: The target agent to hand off to
|
||||
tool_name_override: Custom tool name (defaults to transfer_to_<agent_name>)
|
||||
tool_description_override: Custom tool description
|
||||
on_handoff: Callback function executed when handoff is invoked
|
||||
input_type: Type of input expected by the handoff (for structured data)
|
||||
input_filter: Function to filter/transform input before passing to target agent
|
||||
"""
|
||||
self.agent = agent
|
||||
self.tool_name_override = tool_name_override
|
||||
self.tool_description_override = tool_description_override
|
||||
self.on_handoff = on_handoff
|
||||
self.input_type = input_type
|
||||
self.input_filter = input_filter
|
||||
|
||||
@property
|
||||
def tool_name(self) -> str:
|
||||
"""Get the tool name for this handoff."""
|
||||
if self.tool_name_override:
|
||||
return self.tool_name_override
|
||||
return self.default_tool_name()
|
||||
|
||||
@property
|
||||
def tool_description(self) -> str:
|
||||
"""Get the tool description for this handoff."""
|
||||
if self.tool_description_override:
|
||||
return self.tool_description_override
|
||||
return self.default_tool_description()
|
||||
|
||||
def default_tool_name(self) -> str:
|
||||
"""Generate default tool name based on agent name."""
|
||||
# Convert agent name to snake_case for tool name
|
||||
agent_name = self.agent.name.lower().replace(' ', '_')
|
||||
return f"transfer_to_{agent_name}"
|
||||
|
||||
def default_tool_description(self) -> str:
|
||||
"""Generate default tool description based on agent role and goal."""
|
||||
agent_desc = f"Transfer task to {self.agent.name}"
|
||||
if hasattr(self.agent, 'role') and self.agent.role:
|
||||
agent_desc += f" ({self.agent.role})"
|
||||
if hasattr(self.agent, 'goal') and self.agent.goal:
|
||||
agent_desc += f" - {self.agent.goal}"
|
||||
return agent_desc
|
||||
|
||||
def to_tool_function(self, source_agent: 'Agent') -> Callable:
|
||||
"""
|
||||
Convert this handoff to a tool function that can be called by the LLM.
|
||||
|
||||
Args:
|
||||
source_agent: The agent that will be using this handoff
|
||||
|
||||
Returns:
|
||||
A callable function that performs the handoff
|
||||
"""
|
||||
def handoff_tool(**kwargs):
|
||||
"""Execute the handoff to the target agent."""
|
||||
try:
|
||||
# Execute on_handoff callback if provided
|
||||
if self.on_handoff:
|
||||
try:
|
||||
sig = inspect.signature(self.on_handoff)
|
||||
# Get parameters excluding those with defaults and varargs/varkwargs
|
||||
required_params = [
|
||||
p for p in sig.parameters.values()
|
||||
if p.default == inspect.Parameter.empty
|
||||
and p.kind not in (p.VAR_POSITIONAL, p.VAR_KEYWORD)
|
||||
]
|
||||
num_required = len(required_params)
|
||||
|
||||
if num_required == 0:
|
||||
self.on_handoff()
|
||||
elif num_required == 1:
|
||||
self.on_handoff(source_agent)
|
||||
elif num_required == 2:
|
||||
if self.input_type and kwargs:
|
||||
try:
|
||||
input_data = self.input_type(**kwargs)
|
||||
self.on_handoff(source_agent, input_data)
|
||||
except TypeError as e:
|
||||
logger.error(f"Failed to create input_type instance: {e}")
|
||||
self.on_handoff(source_agent, kwargs)
|
||||
else:
|
||||
# No input_type or no kwargs: pass raw kwargs or empty dict
|
||||
self.on_handoff(source_agent, kwargs or {})
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Callback {self.on_handoff.__name__} requires {num_required} parameters, "
|
||||
"but only 0-2 are supported"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error invoking callback {self.on_handoff.__name__}: {e}")
|
||||
# Continue with handoff even if callback fails
|
||||
|
||||
# Prepare handoff data
|
||||
handoff_data = HandoffInputData(
|
||||
messages=getattr(source_agent, 'chat_history', []),
|
||||
context={'source_agent': source_agent.name}
|
||||
)
|
||||
|
||||
# Apply input filter if provided
|
||||
if self.input_filter:
|
||||
handoff_data = self.input_filter(handoff_data)
|
||||
|
||||
# Get the last user message or context to pass to target agent
|
||||
last_message = None
|
||||
for msg in reversed(handoff_data.messages):
|
||||
if isinstance(msg, dict) and msg.get('role') == 'user':
|
||||
last_message = msg.get('content', '')
|
||||
break
|
||||
|
||||
if not last_message and handoff_data.messages:
|
||||
# If no user message, use the last message
|
||||
last_msg = handoff_data.messages[-1]
|
||||
if isinstance(last_msg, dict):
|
||||
last_message = last_msg.get('content', '')
|
||||
else:
|
||||
last_message = str(last_msg)
|
||||
|
||||
# Prepare context information
|
||||
context_info = f"[Handoff from {source_agent.name}] "
|
||||
if kwargs and self.input_type:
|
||||
# Include structured input data in context
|
||||
context_info += f"Context: {kwargs} "
|
||||
|
||||
# Execute the target agent
|
||||
if last_message:
|
||||
prompt = context_info + last_message
|
||||
logger.info(f"Handing off to {self.agent.name} with prompt: {prompt}")
|
||||
response = self.agent.chat(prompt)
|
||||
return f"Handoff successful. {self.agent.name} response: {response}"
|
||||
return f"Handoff to {self.agent.name} completed, but no specific task was provided."
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error during handoff to {self.agent.name}: {str(e)}")
|
||||
return f"Error during handoff to {self.agent.name}: {str(e)}"
|
||||
|
||||
# Set function metadata for tool definition generation
|
||||
handoff_tool.__name__ = self.tool_name
|
||||
handoff_tool.__doc__ = self.tool_description
|
||||
|
||||
# Add input type annotations if provided
|
||||
if self.input_type and hasattr(self.input_type, '__annotations__'):
|
||||
sig_params = []
|
||||
for field_name, field_type in self.input_type.__annotations__.items():
|
||||
sig_params.append(
|
||||
inspect.Parameter(
|
||||
field_name,
|
||||
inspect.Parameter.KEYWORD_ONLY,
|
||||
annotation=field_type
|
||||
)
|
||||
)
|
||||
handoff_tool.__signature__ = inspect.Signature(sig_params)
|
||||
|
||||
return handoff_tool
|
||||
|
||||
|
||||
def handoff(
|
||||
agent: 'Agent',
|
||||
tool_name_override: Optional[str] = None,
|
||||
tool_description_override: Optional[str] = None,
|
||||
on_handoff: Optional[Callable] = None,
|
||||
input_type: Optional[type] = None,
|
||||
input_filter: Optional[Callable[[HandoffInputData], HandoffInputData]] = None
|
||||
) -> Handoff:
|
||||
"""
|
||||
Create a handoff configuration for delegating tasks to another agent.
|
||||
|
||||
This is a convenience function that creates a Handoff instance with the
|
||||
specified configuration.
|
||||
|
||||
Args:
|
||||
agent: The target agent to hand off to
|
||||
tool_name_override: Custom tool name (defaults to transfer_to_<agent_name>)
|
||||
tool_description_override: Custom tool description
|
||||
on_handoff: Callback function executed when handoff is invoked
|
||||
input_type: Type of input expected by the handoff (for structured data)
|
||||
input_filter: Function to filter/transform input before passing to target agent
|
||||
|
||||
Returns:
|
||||
A configured Handoff instance
|
||||
|
||||
Example:
|
||||
```python
|
||||
from praisonaiagents import Agent, handoff
|
||||
|
||||
billing_agent = Agent(name="Billing Agent")
|
||||
refund_agent = Agent(name="Refund Agent")
|
||||
|
||||
triage_agent = Agent(
|
||||
name="Triage Agent",
|
||||
handoffs=[billing_agent, handoff(refund_agent)]
|
||||
)
|
||||
```
|
||||
"""
|
||||
return Handoff(
|
||||
agent=agent,
|
||||
tool_name_override=tool_name_override,
|
||||
tool_description_override=tool_description_override,
|
||||
on_handoff=on_handoff,
|
||||
input_type=input_type,
|
||||
input_filter=input_filter
|
||||
)
|
||||
|
||||
|
||||
# Handoff filters - common patterns for filtering handoff data
|
||||
class handoff_filters:
|
||||
"""Common handoff input filters."""
|
||||
|
||||
@staticmethod
|
||||
def remove_all_tools(data: HandoffInputData) -> HandoffInputData:
|
||||
"""Remove all tool calls from the message history."""
|
||||
filtered_messages = []
|
||||
for msg in data.messages:
|
||||
if isinstance(msg, dict) and (msg.get('tool_calls') or msg.get('role') == 'tool'):
|
||||
# Skip messages with tool calls
|
||||
continue
|
||||
filtered_messages.append(msg)
|
||||
|
||||
data.messages = filtered_messages
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def keep_last_n_messages(n: int) -> Callable[[HandoffInputData], HandoffInputData]:
|
||||
"""Keep only the last n messages in the history."""
|
||||
def filter_func(data: HandoffInputData) -> HandoffInputData:
|
||||
data.messages = data.messages[-n:]
|
||||
return data
|
||||
return filter_func
|
||||
|
||||
@staticmethod
|
||||
def remove_system_messages(data: HandoffInputData) -> HandoffInputData:
|
||||
"""Remove all system messages from the history."""
|
||||
filtered_messages = []
|
||||
for msg in data.messages:
|
||||
if (isinstance(msg, dict) and msg.get('role') != 'system') or not isinstance(msg, dict):
|
||||
filtered_messages.append(msg)
|
||||
|
||||
data.messages = filtered_messages
|
||||
return data
|
||||
|
||||
|
||||
# Recommended prompt prefix for agents that use handoffs
|
||||
RECOMMENDED_PROMPT_PREFIX = """You have the ability to transfer tasks to specialized agents when appropriate.
|
||||
When you determine that a task would be better handled by another agent with specific expertise,
|
||||
use the transfer tool to hand off the task. The receiving agent will have the full context of
|
||||
the conversation and will continue helping the user."""
|
||||
|
||||
|
||||
def prompt_with_handoff_instructions(base_prompt: str, agent: 'Agent') -> str:
|
||||
"""
|
||||
Add handoff instructions to an agent's prompt.
|
||||
|
||||
Args:
|
||||
base_prompt: The original prompt/instructions
|
||||
agent: The agent that will use handoffs
|
||||
|
||||
Returns:
|
||||
Updated prompt with handoff instructions
|
||||
"""
|
||||
if not hasattr(agent, 'handoffs') or not agent.handoffs:
|
||||
return base_prompt
|
||||
|
||||
handoff_info = "\n\nAvailable handoff agents:\n"
|
||||
for h in agent.handoffs:
|
||||
if isinstance(h, Handoff):
|
||||
handoff_info += f"- {h.agent.name}: {h.tool_description}\n"
|
||||
else:
|
||||
# Direct agent reference - create a temporary Handoff to get the default description
|
||||
temp_handoff = Handoff(agent=h)
|
||||
handoff_info += f"- {h.name}: {temp_handoff.tool_description}\n"
|
||||
|
||||
return RECOMMENDED_PROMPT_PREFIX + handoff_info + "\n\n" + base_prompt
|
||||
@@ -276,6 +276,41 @@ class LLM:
|
||||
]
|
||||
|
||||
return self.model in legacy_o1_models
|
||||
|
||||
def _supports_streaming_tools(self) -> bool:
|
||||
"""
|
||||
Check if the current provider supports streaming with tools.
|
||||
|
||||
Most providers that support tool calling also support streaming with tools,
|
||||
but some providers (like Ollama and certain local models) require non-streaming
|
||||
calls when tools are involved.
|
||||
|
||||
Returns:
|
||||
bool: True if provider supports streaming with tools, False otherwise
|
||||
"""
|
||||
if not self.model:
|
||||
return False
|
||||
|
||||
# Ollama doesn't reliably support streaming with tools
|
||||
if self._is_ollama_provider():
|
||||
return False
|
||||
|
||||
# OpenAI models support streaming with tools
|
||||
if any(self.model.startswith(prefix) for prefix in ["gpt-", "o1-", "o3-"]):
|
||||
return True
|
||||
|
||||
# Anthropic Claude models support streaming with tools
|
||||
if self.model.startswith("claude-"):
|
||||
return True
|
||||
|
||||
# Google Gemini models support streaming with tools
|
||||
if any(self.model.startswith(prefix) for prefix in ["gemini-", "gemini/"]):
|
||||
return True
|
||||
|
||||
# For other providers, default to False to be safe
|
||||
# This ensures we make a single non-streaming call rather than risk
|
||||
# missing tool calls or making duplicate calls
|
||||
return False
|
||||
|
||||
def get_response(
|
||||
self,
|
||||
@@ -480,49 +515,110 @@ class LLM:
|
||||
|
||||
# Otherwise do the existing streaming approach
|
||||
else:
|
||||
if verbose:
|
||||
with Live(display_generating("", current_time), console=console, refresh_per_second=4) as live:
|
||||
response_text = ""
|
||||
# Determine if we should use streaming based on tool support
|
||||
use_streaming = stream
|
||||
if formatted_tools and not self._supports_streaming_tools():
|
||||
# Provider doesn't support streaming with tools, use non-streaming
|
||||
use_streaming = False
|
||||
|
||||
if use_streaming:
|
||||
# Streaming approach (with or without tools)
|
||||
tool_calls = []
|
||||
response_text = ""
|
||||
|
||||
if verbose:
|
||||
with Live(display_generating("", current_time), console=console, refresh_per_second=4) as live:
|
||||
for chunk in litellm.completion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
tools=formatted_tools,
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
**kwargs
|
||||
)
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta:
|
||||
delta = chunk.choices[0].delta
|
||||
if delta.content:
|
||||
response_text += delta.content
|
||||
live.update(display_generating(response_text, current_time))
|
||||
|
||||
# Capture tool calls from streaming chunks if provider supports it
|
||||
if formatted_tools and self._supports_streaming_tools() and hasattr(delta, 'tool_calls') and delta.tool_calls:
|
||||
for tc in delta.tool_calls:
|
||||
if tc.index >= len(tool_calls):
|
||||
tool_calls.append({
|
||||
"id": tc.id,
|
||||
"type": "function",
|
||||
"function": {"name": "", "arguments": ""}
|
||||
})
|
||||
if tc.function.name:
|
||||
tool_calls[tc.index]["function"]["name"] = tc.function.name
|
||||
if tc.function.arguments:
|
||||
tool_calls[tc.index]["function"]["arguments"] += tc.function.arguments
|
||||
else:
|
||||
# Non-verbose streaming
|
||||
for chunk in litellm.completion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
tools=formatted_tools,
|
||||
temperature=temperature,
|
||||
stream=stream,
|
||||
stream=True,
|
||||
**kwargs
|
||||
)
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta.content:
|
||||
content = chunk.choices[0].delta.content
|
||||
response_text += content
|
||||
live.update(display_generating(response_text, current_time))
|
||||
if chunk and chunk.choices and chunk.choices[0].delta:
|
||||
delta = chunk.choices[0].delta
|
||||
if delta.content:
|
||||
response_text += delta.content
|
||||
|
||||
# Capture tool calls from streaming chunks if provider supports it
|
||||
if formatted_tools and self._supports_streaming_tools() and hasattr(delta, 'tool_calls') and delta.tool_calls:
|
||||
for tc in delta.tool_calls:
|
||||
if tc.index >= len(tool_calls):
|
||||
tool_calls.append({
|
||||
"id": tc.id,
|
||||
"type": "function",
|
||||
"function": {"name": "", "arguments": ""}
|
||||
})
|
||||
if tc.function.name:
|
||||
tool_calls[tc.index]["function"]["name"] = tc.function.name
|
||||
if tc.function.arguments:
|
||||
tool_calls[tc.index]["function"]["arguments"] += tc.function.arguments
|
||||
|
||||
response_text = response_text.strip()
|
||||
|
||||
# Create a mock final_response with the captured data
|
||||
final_response = {
|
||||
"choices": [{
|
||||
"message": {
|
||||
"content": response_text,
|
||||
"tool_calls": tool_calls if tool_calls else None
|
||||
}
|
||||
}]
|
||||
}
|
||||
else:
|
||||
# Non-verbose mode, just collect the response
|
||||
response_text = ""
|
||||
for chunk in litellm.completion(
|
||||
# Non-streaming approach (when tools require it or streaming is disabled)
|
||||
final_response = litellm.completion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
tools=formatted_tools,
|
||||
temperature=temperature,
|
||||
stream=stream,
|
||||
stream=False,
|
||||
**kwargs
|
||||
)
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta.content:
|
||||
response_text += chunk.choices[0].delta.content
|
||||
|
||||
response_text = response_text.strip()
|
||||
|
||||
# Get final completion to check for tool calls
|
||||
final_response = litellm.completion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
tools=formatted_tools,
|
||||
temperature=temperature,
|
||||
stream=False, # No streaming for tool call check
|
||||
**kwargs
|
||||
)
|
||||
)
|
||||
response_text = final_response["choices"][0]["message"]["content"]
|
||||
|
||||
if verbose:
|
||||
# Display the complete response at once
|
||||
display_interaction(
|
||||
original_prompt,
|
||||
response_text,
|
||||
markdown=markdown,
|
||||
generation_time=time.time() - current_time,
|
||||
console=console
|
||||
)
|
||||
|
||||
tool_calls = final_response["choices"][0]["message"].get("tool_calls")
|
||||
|
||||
@@ -1198,53 +1294,106 @@ Output MUST be JSON with 'reflection' and 'satisfactory'.
|
||||
console=console
|
||||
)
|
||||
else:
|
||||
if verbose:
|
||||
# ----------------------------------------------------
|
||||
# 1) Make the streaming call WITHOUT tools
|
||||
# ----------------------------------------------------
|
||||
async for chunk in await litellm.acompletion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=stream,
|
||||
**kwargs
|
||||
)
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta.content:
|
||||
response_text += chunk.choices[0].delta.content
|
||||
print("\033[K", end="\r")
|
||||
print(f"Generating... {time.time() - start_time:.1f}s", end="\r")
|
||||
# Determine if we should use streaming based on tool support
|
||||
use_streaming = stream
|
||||
if formatted_tools and not self._supports_streaming_tools():
|
||||
# Provider doesn't support streaming with tools, use non-streaming
|
||||
use_streaming = False
|
||||
|
||||
if use_streaming:
|
||||
# Streaming approach (with or without tools)
|
||||
tool_calls = []
|
||||
|
||||
if verbose:
|
||||
async for chunk in await litellm.acompletion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
tools=formatted_tools,
|
||||
**kwargs
|
||||
)
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta:
|
||||
delta = chunk.choices[0].delta
|
||||
if delta.content:
|
||||
response_text += delta.content
|
||||
print("\033[K", end="\r")
|
||||
print(f"Generating... {time.time() - start_time:.1f}s", end="\r")
|
||||
|
||||
# Capture tool calls from streaming chunks if provider supports it
|
||||
if formatted_tools and self._supports_streaming_tools() and hasattr(delta, 'tool_calls') and delta.tool_calls:
|
||||
for tc in delta.tool_calls:
|
||||
if tc.index >= len(tool_calls):
|
||||
tool_calls.append({
|
||||
"id": tc.id,
|
||||
"type": "function",
|
||||
"function": {"name": "", "arguments": ""}
|
||||
})
|
||||
if tc.function.name:
|
||||
tool_calls[tc.index]["function"]["name"] = tc.function.name
|
||||
if tc.function.arguments:
|
||||
tool_calls[tc.index]["function"]["arguments"] += tc.function.arguments
|
||||
else:
|
||||
# Non-verbose streaming
|
||||
async for chunk in await litellm.acompletion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=True,
|
||||
tools=formatted_tools,
|
||||
**kwargs
|
||||
)
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta:
|
||||
delta = chunk.choices[0].delta
|
||||
if delta.content:
|
||||
response_text += delta.content
|
||||
|
||||
# Capture tool calls from streaming chunks if provider supports it
|
||||
if formatted_tools and self._supports_streaming_tools() and hasattr(delta, 'tool_calls') and delta.tool_calls:
|
||||
for tc in delta.tool_calls:
|
||||
if tc.index >= len(tool_calls):
|
||||
tool_calls.append({
|
||||
"id": tc.id,
|
||||
"type": "function",
|
||||
"function": {"name": "", "arguments": ""}
|
||||
})
|
||||
if tc.function.name:
|
||||
tool_calls[tc.index]["function"]["name"] = tc.function.name
|
||||
if tc.function.arguments:
|
||||
tool_calls[tc.index]["function"]["arguments"] += tc.function.arguments
|
||||
|
||||
response_text = response_text.strip()
|
||||
|
||||
# We already have tool_calls from streaming if supported
|
||||
# No need for a second API call!
|
||||
else:
|
||||
# Non-verbose streaming call, still no tools
|
||||
async for chunk in await litellm.acompletion(
|
||||
# Non-streaming approach (when tools require it or streaming is disabled)
|
||||
tool_response = await litellm.acompletion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=stream,
|
||||
**kwargs
|
||||
stream=False,
|
||||
tools=formatted_tools,
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
):
|
||||
if chunk and chunk.choices and chunk.choices[0].delta.content:
|
||||
response_text += chunk.choices[0].delta.content
|
||||
|
||||
response_text = response_text.strip()
|
||||
|
||||
# ----------------------------------------------------
|
||||
# 2) If tool calls are needed, do a non-streaming call
|
||||
# ----------------------------------------------------
|
||||
if tools and execute_tool_fn:
|
||||
# Next call with tools if needed
|
||||
tool_response = await litellm.acompletion(
|
||||
**self._build_completion_params(
|
||||
messages=messages,
|
||||
temperature=temperature,
|
||||
stream=False,
|
||||
tools=formatted_tools, # We safely pass tools here
|
||||
**{k:v for k,v in kwargs.items() if k != 'reasoning_steps'}
|
||||
)
|
||||
)
|
||||
# handle tool_calls from tool_response as usual...
|
||||
tool_calls = tool_response.choices[0].message.get("tool_calls")
|
||||
response_text = tool_response.choices[0].message.get("content", "")
|
||||
tool_calls = tool_response.choices[0].message.get("tool_calls", [])
|
||||
|
||||
if verbose:
|
||||
# Display the complete response at once
|
||||
display_interaction(
|
||||
original_prompt,
|
||||
response_text,
|
||||
markdown=markdown,
|
||||
generation_time=time.time() - start_time,
|
||||
console=console
|
||||
)
|
||||
|
||||
# Now handle tools if we have them (either from streaming or non-streaming)
|
||||
if tools and execute_tool_fn and tool_calls:
|
||||
|
||||
if tool_calls:
|
||||
# Convert tool_calls to a serializable format for all providers
|
||||
|
||||
@@ -7,6 +7,7 @@ import shlex
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import platform
|
||||
from typing import Any, List, Optional, Callable, Iterable, Union
|
||||
from functools import wraps, partial
|
||||
|
||||
@@ -199,7 +200,13 @@ class MCP:
|
||||
# Handle the single string format for stdio client
|
||||
if isinstance(command_or_string, str) and args is None:
|
||||
# Split the string into command and args using shell-like parsing
|
||||
parts = shlex.split(command_or_string)
|
||||
if platform.system() == 'Windows':
|
||||
# Use shlex with posix=False for Windows to handle quotes and paths with spaces
|
||||
parts = shlex.split(command_or_string, posix=False)
|
||||
# Remove quotes from parts if present (Windows shlex keeps them)
|
||||
parts = [part.strip('"') for part in parts]
|
||||
else:
|
||||
parts = shlex.split(command_or_string)
|
||||
if not parts:
|
||||
raise ValueError("Empty command string")
|
||||
|
||||
@@ -217,11 +224,17 @@ class MCP:
|
||||
env = kwargs.get('env', {})
|
||||
if not env:
|
||||
env = os.environ.copy()
|
||||
env.update({
|
||||
'PYTHONIOENCODING': 'utf-8',
|
||||
'LC_ALL': 'C.UTF-8',
|
||||
'LANG': 'C.UTF-8'
|
||||
})
|
||||
|
||||
# Always set Python encoding
|
||||
env['PYTHONIOENCODING'] = 'utf-8'
|
||||
|
||||
# Only set locale variables on Unix systems
|
||||
if platform.system() != 'Windows':
|
||||
env.update({
|
||||
'LC_ALL': 'C.UTF-8',
|
||||
'LANG': 'C.UTF-8'
|
||||
})
|
||||
|
||||
kwargs['env'] = env
|
||||
|
||||
self.server_params = StdioServerParameters(
|
||||
@@ -236,7 +249,14 @@ class MCP:
|
||||
print(f"Warning: MCP initialization timed out after {self.timeout} seconds")
|
||||
|
||||
# Automatically detect if this is an NPX command
|
||||
self.is_npx = cmd == 'npx' or (isinstance(cmd, str) and os.path.basename(cmd) == 'npx')
|
||||
base_cmd = os.path.basename(cmd) if isinstance(cmd, str) else cmd
|
||||
# Check for npx with or without Windows extensions
|
||||
npx_variants = ['npx', 'npx.cmd', 'npx.exe']
|
||||
if platform.system() == 'Windows' and isinstance(base_cmd, str):
|
||||
# Case-insensitive comparison on Windows
|
||||
self.is_npx = base_cmd.lower() in [v.lower() for v in npx_variants]
|
||||
else:
|
||||
self.is_npx = base_cmd in npx_variants
|
||||
|
||||
# For NPX-based MCP servers, use a different approach
|
||||
if self.is_npx:
|
||||
|
||||
@@ -741,6 +741,54 @@ class Memory:
|
||||
filtered.append(h)
|
||||
return filtered[:limit]
|
||||
|
||||
def search(self, query: str, user_id: Optional[str] = None, agent_id: Optional[str] = None,
|
||||
run_id: Optional[str] = None, limit: int = 5, rerank: bool = False, **kwargs) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Generic search method that delegates to appropriate specific search methods.
|
||||
Provides compatibility with mem0.Memory interface.
|
||||
|
||||
Args:
|
||||
query: The search query string
|
||||
user_id: Optional user ID for user-specific search
|
||||
agent_id: Optional agent ID for agent-specific search
|
||||
run_id: Optional run ID for run-specific search
|
||||
limit: Maximum number of results to return
|
||||
rerank: Whether to use advanced reranking
|
||||
**kwargs: Additional search parameters
|
||||
|
||||
Returns:
|
||||
List of search results
|
||||
"""
|
||||
# If using mem0, pass all parameters directly
|
||||
if self.use_mem0 and hasattr(self, "mem0_client"):
|
||||
search_params = {
|
||||
"query": query,
|
||||
"limit": limit,
|
||||
"rerank": rerank
|
||||
}
|
||||
|
||||
# Add optional parameters if provided
|
||||
if user_id is not None:
|
||||
search_params["user_id"] = user_id
|
||||
if agent_id is not None:
|
||||
search_params["agent_id"] = agent_id
|
||||
if run_id is not None:
|
||||
search_params["run_id"] = run_id
|
||||
|
||||
# Include any additional kwargs
|
||||
search_params.update(kwargs)
|
||||
|
||||
return self.mem0_client.search(**search_params)
|
||||
|
||||
# For local memory, use specific search methods
|
||||
if user_id:
|
||||
# Use user-specific search
|
||||
return self.search_user_memory(user_id, query, limit=limit, rerank=rerank, **kwargs)
|
||||
else:
|
||||
# Default to long-term memory search
|
||||
# Note: agent_id and run_id filtering could be added to metadata filtering in the future
|
||||
return self.search_long_term(query, limit=limit, rerank=rerank, **kwargs)
|
||||
|
||||
def reset_user_memory(self):
|
||||
"""
|
||||
Clear all user-based info. For simplicity, we do a full LTM reset.
|
||||
|
||||
@@ -13,6 +13,7 @@ import logging
|
||||
from typing import List, Dict, Any, Optional, Union, TYPE_CHECKING
|
||||
from importlib import util
|
||||
import json
|
||||
import re
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import duckdb
|
||||
@@ -29,6 +30,25 @@ class DuckDBTools:
|
||||
"""
|
||||
self.database = database
|
||||
self._conn = None
|
||||
|
||||
def _validate_identifier(self, identifier: str) -> str:
|
||||
"""Validate and quote a SQL identifier to prevent injection.
|
||||
|
||||
Args:
|
||||
identifier: Table or column name to validate
|
||||
|
||||
Returns:
|
||||
Quoted identifier safe for SQL
|
||||
|
||||
Raises:
|
||||
ValueError: If identifier contains invalid characters
|
||||
"""
|
||||
# Only allow alphanumeric characters, underscores, and dots
|
||||
if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)?$', identifier):
|
||||
raise ValueError(f"Invalid identifier: {identifier}")
|
||||
|
||||
# Quote the identifier to handle reserved words
|
||||
return f'"{identifier}"'
|
||||
|
||||
def _get_duckdb(self) -> Optional['duckdb']:
|
||||
"""Get duckdb module, installing if needed"""
|
||||
@@ -125,39 +145,50 @@ class DuckDBTools:
|
||||
if conn is None:
|
||||
return False
|
||||
|
||||
# Check if table exists
|
||||
exists = conn.execute(f"""
|
||||
# Check if table exists using parameterized query
|
||||
exists = conn.execute("""
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='{table_name}'
|
||||
""").fetchone() is not None
|
||||
WHERE type='table' AND name=?
|
||||
""", [table_name]).fetchone() is not None
|
||||
|
||||
if exists:
|
||||
if if_exists == 'fail':
|
||||
raise ValueError(f"Table {table_name} already exists")
|
||||
elif if_exists == 'replace':
|
||||
conn.execute(f"DROP TABLE IF EXISTS {table_name}")
|
||||
# Validate and quote table name to prevent injection
|
||||
safe_table = self._validate_identifier(table_name)
|
||||
conn.execute(f"DROP TABLE IF EXISTS {safe_table}")
|
||||
elif if_exists != 'append':
|
||||
raise ValueError("if_exists must be 'fail', 'replace', or 'append'")
|
||||
|
||||
# Create table if needed
|
||||
if not exists or if_exists == 'replace':
|
||||
safe_table = self._validate_identifier(table_name)
|
||||
if schema:
|
||||
# Create table with schema
|
||||
columns = ', '.join(f"{k} {v}" for k, v in schema.items())
|
||||
conn.execute(f"CREATE TABLE {table_name} ({columns})")
|
||||
# Create table with schema - validate column names
|
||||
column_defs = []
|
||||
for col_name, col_type in schema.items():
|
||||
safe_col = self._validate_identifier(col_name)
|
||||
# Validate column type to prevent injection
|
||||
if not re.match(r'^[A-Z][A-Z0-9_]*(\([0-9,]+\))?$', col_type.upper()):
|
||||
raise ValueError(f"Invalid column type: {col_type}")
|
||||
column_defs.append(f"{safe_col} {col_type}")
|
||||
columns = ', '.join(column_defs)
|
||||
conn.execute(f"CREATE TABLE {safe_table} ({columns})")
|
||||
else:
|
||||
# Infer schema from CSV
|
||||
# Infer schema from CSV - use parameterized query for filepath
|
||||
conn.execute(f"""
|
||||
CREATE TABLE {table_name} AS
|
||||
SELECT * FROM read_csv_auto('{filepath}')
|
||||
CREATE TABLE {safe_table} AS
|
||||
SELECT * FROM read_csv_auto(?)
|
||||
WHERE 1=0
|
||||
""")
|
||||
""", [filepath])
|
||||
|
||||
# Load data
|
||||
# Load data - use validated table name and parameterized filepath
|
||||
safe_table = self._validate_identifier(table_name)
|
||||
conn.execute(f"""
|
||||
INSERT INTO {table_name}
|
||||
SELECT * FROM read_csv_auto('{filepath}')
|
||||
""")
|
||||
INSERT INTO {safe_table}
|
||||
SELECT * FROM read_csv_auto(?)
|
||||
""", [filepath])
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -21,6 +21,32 @@ from ..approval import require_approval
|
||||
class FileTools:
|
||||
"""Tools for file operations including read, write, list, and information."""
|
||||
|
||||
@staticmethod
|
||||
def _validate_path(filepath: str) -> str:
|
||||
"""
|
||||
Validate and normalize a file path to prevent path traversal attacks.
|
||||
|
||||
Args:
|
||||
filepath: Path to validate
|
||||
|
||||
Returns:
|
||||
str: Normalized absolute path
|
||||
|
||||
Raises:
|
||||
ValueError: If path contains suspicious patterns
|
||||
"""
|
||||
# Normalize the path
|
||||
normalized = os.path.normpath(filepath)
|
||||
absolute = os.path.abspath(normalized)
|
||||
|
||||
# Check for suspicious patterns
|
||||
if '..' in filepath or filepath.startswith('~'):
|
||||
raise ValueError(f"Suspicious path pattern detected: {filepath}")
|
||||
|
||||
# Additional check: ensure the resolved path doesn't escape expected boundaries
|
||||
# This is a basic check - in production, you'd want to define allowed directories
|
||||
return absolute
|
||||
|
||||
@staticmethod
|
||||
def read_file(filepath: str, encoding: str = 'utf-8') -> str:
|
||||
"""
|
||||
@@ -34,7 +60,9 @@ class FileTools:
|
||||
str: Content of the file
|
||||
"""
|
||||
try:
|
||||
with open(filepath, 'r', encoding=encoding) as f:
|
||||
# Validate path to prevent traversal attacks
|
||||
safe_path = FileTools._validate_path(filepath)
|
||||
with open(safe_path, 'r', encoding=encoding) as f:
|
||||
return f.read()
|
||||
except Exception as e:
|
||||
error_msg = f"Error reading file {filepath}: {str(e)}"
|
||||
@@ -56,9 +84,11 @@ class FileTools:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Validate path to prevent traversal attacks
|
||||
safe_path = FileTools._validate_path(filepath)
|
||||
# Create directory if it doesn't exist
|
||||
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
||||
with open(filepath, 'w', encoding=encoding) as f:
|
||||
os.makedirs(os.path.dirname(safe_path), exist_ok=True)
|
||||
with open(safe_path, 'w', encoding=encoding) as f:
|
||||
f.write(content)
|
||||
return True
|
||||
except Exception as e:
|
||||
@@ -79,7 +109,9 @@ class FileTools:
|
||||
List[Dict]: List of file information dictionaries
|
||||
"""
|
||||
try:
|
||||
path = Path(directory)
|
||||
# Validate directory path
|
||||
safe_dir = FileTools._validate_path(directory)
|
||||
path = Path(safe_dir)
|
||||
if pattern:
|
||||
files = path.glob(pattern)
|
||||
else:
|
||||
@@ -114,7 +146,9 @@ class FileTools:
|
||||
Dict: File information including size, dates, etc.
|
||||
"""
|
||||
try:
|
||||
path = Path(filepath)
|
||||
# Validate file path
|
||||
safe_path = FileTools._validate_path(filepath)
|
||||
path = Path(safe_path)
|
||||
if not path.exists():
|
||||
return {'error': f'File not found: {filepath}'}
|
||||
|
||||
@@ -149,9 +183,12 @@ class FileTools:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Validate paths to prevent traversal attacks
|
||||
safe_src = FileTools._validate_path(src)
|
||||
safe_dst = FileTools._validate_path(dst)
|
||||
# Create destination directory if it doesn't exist
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
shutil.copy2(src, dst)
|
||||
os.makedirs(os.path.dirname(safe_dst), exist_ok=True)
|
||||
shutil.copy2(safe_src, safe_dst)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error copying file from {src} to {dst}: {str(e)}"
|
||||
@@ -172,9 +209,12 @@ class FileTools:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Validate paths to prevent traversal attacks
|
||||
safe_src = FileTools._validate_path(src)
|
||||
safe_dst = FileTools._validate_path(dst)
|
||||
# Create destination directory if it doesn't exist
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
shutil.move(src, dst)
|
||||
os.makedirs(os.path.dirname(safe_dst), exist_ok=True)
|
||||
shutil.move(safe_src, safe_dst)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error moving file from {src} to {dst}: {str(e)}"
|
||||
@@ -194,7 +234,9 @@ class FileTools:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
os.remove(filepath)
|
||||
# Validate path to prevent traversal attacks
|
||||
safe_path = FileTools._validate_path(filepath)
|
||||
os.remove(safe_path)
|
||||
return True
|
||||
except Exception as e:
|
||||
error_msg = f"Error deleting file {filepath}: {str(e)}"
|
||||
|
||||
@@ -46,20 +46,100 @@ class PythonTools:
|
||||
timeout: int = 30,
|
||||
max_output_size: int = 10000
|
||||
) -> Dict[str, Any]:
|
||||
"""Execute Python code safely."""
|
||||
"""Execute Python code safely with restricted builtins."""
|
||||
try:
|
||||
# Set up execution environment
|
||||
# Create safe builtins - restricted set of functions
|
||||
safe_builtins = {
|
||||
# Basic functions
|
||||
'print': print,
|
||||
'len': len,
|
||||
'range': range,
|
||||
'enumerate': enumerate,
|
||||
'zip': zip,
|
||||
'map': map,
|
||||
'filter': filter,
|
||||
'sum': sum,
|
||||
'min': min,
|
||||
'max': max,
|
||||
'abs': abs,
|
||||
'round': round,
|
||||
'sorted': sorted,
|
||||
'reversed': reversed,
|
||||
'any': any,
|
||||
'all': all,
|
||||
# Type constructors
|
||||
'int': int,
|
||||
'float': float,
|
||||
'str': str,
|
||||
'bool': bool,
|
||||
'list': list,
|
||||
'tuple': tuple,
|
||||
'dict': dict,
|
||||
'set': set,
|
||||
# Math functions
|
||||
'pow': pow,
|
||||
'divmod': divmod,
|
||||
# Exceptions
|
||||
'Exception': Exception,
|
||||
'ValueError': ValueError,
|
||||
'TypeError': TypeError,
|
||||
'KeyError': KeyError,
|
||||
'IndexError': IndexError,
|
||||
'RuntimeError': RuntimeError,
|
||||
# Other safe functions
|
||||
'isinstance': isinstance,
|
||||
'type': type,
|
||||
'hasattr': hasattr,
|
||||
'getattr': getattr,
|
||||
'setattr': setattr,
|
||||
'dir': dir,
|
||||
'help': help,
|
||||
# Disable dangerous functions
|
||||
'__import__': None,
|
||||
'eval': None,
|
||||
'exec': None,
|
||||
'compile': None,
|
||||
'open': None,
|
||||
'input': None,
|
||||
'globals': None,
|
||||
'locals': None,
|
||||
'vars': None,
|
||||
}
|
||||
|
||||
# Set up execution environment with safe builtins
|
||||
if globals_dict is None:
|
||||
globals_dict = {'__builtins__': __builtins__}
|
||||
globals_dict = {'__builtins__': safe_builtins}
|
||||
else:
|
||||
# Override builtins in provided globals
|
||||
globals_dict['__builtins__'] = safe_builtins
|
||||
|
||||
if locals_dict is None:
|
||||
locals_dict = {}
|
||||
|
||||
# Security check: validate code doesn't contain dangerous patterns
|
||||
dangerous_patterns = [
|
||||
'__import__', 'import ', 'from ', 'exec', 'eval',
|
||||
'compile', 'open(', 'file(', 'input(', 'raw_input',
|
||||
'__subclasses__', '__bases__', '__globals__', '__code__',
|
||||
'__class__', 'globals(', 'locals(', 'vars('
|
||||
]
|
||||
|
||||
code_lower = code.lower()
|
||||
for pattern in dangerous_patterns:
|
||||
if pattern.lower() in code_lower:
|
||||
return {
|
||||
'result': None,
|
||||
'stdout': '',
|
||||
'stderr': f'Security Error: Code contains restricted pattern: {pattern}',
|
||||
'success': False
|
||||
}
|
||||
|
||||
# Capture output
|
||||
stdout_buffer = io.StringIO()
|
||||
stderr_buffer = io.StringIO()
|
||||
|
||||
try:
|
||||
# Compile code
|
||||
# Compile code with restricted mode
|
||||
compiled_code = compile(code, '<string>', 'exec')
|
||||
|
||||
# Execute with output capture
|
||||
|
||||
@@ -12,6 +12,8 @@ import shlex
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import platform
|
||||
import psutil
|
||||
from typing import Dict, List, Optional, Union
|
||||
from ..approval import require_approval
|
||||
|
||||
@@ -38,7 +40,6 @@ class ShellTools:
|
||||
command: str,
|
||||
cwd: Optional[str] = None,
|
||||
timeout: int = 30,
|
||||
shell: bool = False,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
max_output_size: int = 10000
|
||||
) -> Dict[str, Union[str, int, bool]]:
|
||||
@@ -48,7 +49,6 @@ class ShellTools:
|
||||
command: Command to execute
|
||||
cwd: Working directory
|
||||
timeout: Maximum execution time in seconds
|
||||
shell: Whether to run command in shell
|
||||
env: Environment variables
|
||||
max_output_size: Maximum output size in bytes
|
||||
|
||||
@@ -56,8 +56,12 @@ class ShellTools:
|
||||
Dictionary with execution results
|
||||
"""
|
||||
try:
|
||||
# Split command if not using shell
|
||||
if not shell:
|
||||
# Always split command for safety (no shell execution)
|
||||
# Use shlex.split with appropriate posix flag
|
||||
if platform.system() == 'Windows':
|
||||
# Use shlex with posix=False for Windows to handle quotes properly
|
||||
command = shlex.split(command, posix=False)
|
||||
else:
|
||||
command = shlex.split(command)
|
||||
|
||||
# Set up process environment
|
||||
@@ -72,7 +76,7 @@ class ShellTools:
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
cwd=cwd,
|
||||
shell=shell,
|
||||
shell=False, # Always use shell=False for security
|
||||
env=process_env,
|
||||
text=True
|
||||
)
|
||||
@@ -201,7 +205,9 @@ class ShellTools:
|
||||
try:
|
||||
cpu_percent = psutil.cpu_percent(interval=1)
|
||||
memory = psutil.virtual_memory()
|
||||
disk = psutil.disk_usage('/')
|
||||
# Use appropriate root path for the OS
|
||||
root_path = os.path.abspath(os.sep)
|
||||
disk = psutil.disk_usage(root_path)
|
||||
|
||||
return {
|
||||
'cpu': {
|
||||
@@ -223,7 +229,7 @@ class ShellTools:
|
||||
'percent': disk.percent
|
||||
},
|
||||
'boot_time': psutil.boot_time(),
|
||||
'platform': os.uname().sysname
|
||||
'platform': platform.system()
|
||||
}
|
||||
except Exception as e:
|
||||
error_msg = f"Error getting system info: {str(e)}"
|
||||
@@ -246,7 +252,11 @@ if __name__ == "__main__":
|
||||
# 1. Execute command
|
||||
print("1. Command Execution")
|
||||
print("------------------------------")
|
||||
result = execute_command("ls -la")
|
||||
# Cross-platform directory listing
|
||||
if platform.system() == 'Windows':
|
||||
result = execute_command("dir")
|
||||
else:
|
||||
result = execute_command("ls -la")
|
||||
print(f"Success: {result['success']}")
|
||||
print(f"Output:\n{result['stdout']}")
|
||||
if result['stderr']:
|
||||
|
||||
@@ -27,6 +27,57 @@ class SpiderTools:
|
||||
"""Initialize SpiderTools and check for required packages."""
|
||||
self._session = None
|
||||
|
||||
def _validate_url(self, url: str) -> bool:
|
||||
"""
|
||||
Validate URL to prevent SSRF attacks.
|
||||
|
||||
Args:
|
||||
url: URL to validate
|
||||
|
||||
Returns:
|
||||
bool: True if URL is safe, False otherwise
|
||||
"""
|
||||
try:
|
||||
parsed = urlparse(url)
|
||||
|
||||
# Only allow http/https protocols
|
||||
if parsed.scheme not in ['http', 'https']:
|
||||
return False
|
||||
|
||||
# Reject URLs with no hostname
|
||||
if not parsed.hostname:
|
||||
return False
|
||||
|
||||
# Reject local/internal addresses
|
||||
hostname = parsed.hostname.lower()
|
||||
|
||||
# Block localhost and loopback
|
||||
if hostname in ['localhost', '127.0.0.1', '0.0.0.0', '::1']:
|
||||
return False
|
||||
|
||||
# Block private IP ranges
|
||||
import ipaddress
|
||||
try:
|
||||
ip = ipaddress.ip_address(hostname)
|
||||
if ip.is_private or ip.is_reserved or ip.is_loopback or ip.is_link_local:
|
||||
return False
|
||||
except ValueError:
|
||||
# Not an IP address, continue with domain validation
|
||||
pass
|
||||
|
||||
# Block common internal domains
|
||||
if any(hostname.endswith(domain) for domain in ['.local', '.internal', '.localdomain']):
|
||||
return False
|
||||
|
||||
# Block metadata service endpoints
|
||||
if hostname in ['169.254.169.254', 'metadata.google.internal']:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def _get_session(self):
|
||||
"""Get or create requests session with common headers."""
|
||||
if util.find_spec('requests') is None:
|
||||
@@ -70,6 +121,10 @@ class SpiderTools:
|
||||
Dict: Scraped content or error dict
|
||||
"""
|
||||
try:
|
||||
# Validate URL to prevent SSRF
|
||||
if not self._validate_url(url):
|
||||
return {"error": f"Invalid or potentially dangerous URL: {url}"}
|
||||
|
||||
session = self._get_session()
|
||||
if session is None:
|
||||
return {"error": "requests package not available"}
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.0.108"
|
||||
version = "0.0.110"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
requires-python = ">=3.10"
|
||||
authors = [
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
"""
|
||||
Test backward compatibility for handoff feature.
|
||||
|
||||
This test ensures that:
|
||||
1. Existing agent code works without handoffs
|
||||
2. Agents can be created with all existing parameters
|
||||
3. Tools work as before
|
||||
4. No breaking changes were introduced
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, handoff, handoff_filters
|
||||
|
||||
|
||||
def test_agent_without_handoffs():
|
||||
"""Test that agents work without handoffs (backward compatibility)"""
|
||||
# Create agent without handoffs - should work as before
|
||||
agent = Agent(
|
||||
name="Test Agent",
|
||||
role="Tester",
|
||||
goal="Test functionality",
|
||||
backstory="I test things",
|
||||
instructions="Just a test agent"
|
||||
)
|
||||
|
||||
assert agent.name == "Test Agent"
|
||||
assert agent.handoffs == []
|
||||
assert hasattr(agent, 'tools')
|
||||
|
||||
|
||||
def test_agent_with_existing_tools():
|
||||
"""Test that existing tool functionality still works"""
|
||||
def test_tool(input: str) -> str:
|
||||
"""A test tool"""
|
||||
return f"Processed: {input}"
|
||||
|
||||
agent = Agent(
|
||||
name="Tool Agent",
|
||||
tools=[test_tool]
|
||||
)
|
||||
|
||||
assert len(agent.tools) == 1
|
||||
assert agent.tools[0] == test_tool
|
||||
|
||||
|
||||
def test_agent_with_handoffs():
|
||||
"""Test agent creation with handoffs"""
|
||||
target_agent = Agent(name="Target Agent")
|
||||
|
||||
agent = Agent(
|
||||
name="Source Agent",
|
||||
handoffs=[target_agent]
|
||||
)
|
||||
|
||||
# Check handoffs were stored
|
||||
assert len(agent.handoffs) == 1
|
||||
assert agent.handoffs[0] == target_agent
|
||||
|
||||
# Check handoff was converted to tool
|
||||
assert len(agent.tools) == 1
|
||||
assert callable(agent.tools[0])
|
||||
assert agent.tools[0].__name__ == "transfer_to_target_agent"
|
||||
|
||||
|
||||
def test_handoff_with_tools():
|
||||
"""Test that handoffs and regular tools work together"""
|
||||
def my_tool():
|
||||
"""Test tool"""
|
||||
return "tool result"
|
||||
|
||||
target_agent = Agent(name="Target")
|
||||
|
||||
agent = Agent(
|
||||
name="Source",
|
||||
tools=[my_tool],
|
||||
handoffs=[target_agent]
|
||||
)
|
||||
|
||||
# Should have both the regular tool and the handoff tool
|
||||
assert len(agent.tools) == 2
|
||||
tool_names = [t.__name__ for t in agent.tools]
|
||||
assert "my_tool" in tool_names
|
||||
assert "transfer_to_target" in tool_names
|
||||
|
||||
|
||||
def test_handoff_object():
|
||||
"""Test using Handoff objects"""
|
||||
target = Agent(name="Target")
|
||||
|
||||
handoff_obj = handoff(
|
||||
target,
|
||||
tool_name_override="custom_transfer",
|
||||
tool_description_override="Custom description"
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="Source",
|
||||
handoffs=[handoff_obj]
|
||||
)
|
||||
|
||||
assert len(agent.tools) == 1
|
||||
assert agent.tools[0].__name__ == "custom_transfer"
|
||||
assert agent.tools[0].__doc__ == "Custom description"
|
||||
|
||||
|
||||
def test_mixed_handoffs():
|
||||
"""Test mixing direct agent references and Handoff objects"""
|
||||
agent1 = Agent(name="Agent One")
|
||||
agent2 = Agent(name="Agent Two")
|
||||
|
||||
source = Agent(
|
||||
name="Source",
|
||||
handoffs=[
|
||||
agent1, # Direct reference
|
||||
handoff(agent2, tool_name_override="special_transfer") # Handoff object
|
||||
]
|
||||
)
|
||||
|
||||
assert len(source.handoffs) == 2
|
||||
assert len(source.tools) == 2
|
||||
|
||||
tool_names = [t.__name__ for t in source.tools]
|
||||
assert "transfer_to_agent_one" in tool_names
|
||||
assert "special_transfer" in tool_names
|
||||
|
||||
|
||||
def test_handoff_filters():
|
||||
"""Test handoff filter functions"""
|
||||
from praisonaiagents.agent.handoff import HandoffInputData
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": "System prompt"},
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistant", "content": "Hi", "tool_calls": [{"name": "test"}]},
|
||||
{"role": "tool", "content": "result"},
|
||||
{"role": "user", "content": "Thanks"}
|
||||
]
|
||||
|
||||
# Test remove_all_tools filter
|
||||
data = HandoffInputData(messages=list(messages))
|
||||
filtered = handoff_filters.remove_all_tools(data)
|
||||
assert len(filtered.messages) == 3
|
||||
assert all(msg.get("role") not in ["tool"] and "tool_calls" not in msg
|
||||
for msg in filtered.messages if isinstance(msg, dict))
|
||||
|
||||
# Test keep_last_n_messages filter
|
||||
data = HandoffInputData(messages=list(messages))
|
||||
filtered = handoff_filters.keep_last_n_messages(3)(data)
|
||||
assert len(filtered.messages) == 3
|
||||
assert filtered.messages[0]['role'] == 'assistant'
|
||||
|
||||
# Test remove_system_messages filter
|
||||
data = HandoffInputData(messages=list(messages))
|
||||
filtered = handoff_filters.remove_system_messages(data)
|
||||
assert len(filtered.messages) == 4
|
||||
assert all(msg.get("role") != "system" for msg in filtered.messages if isinstance(msg, dict))
|
||||
|
||||
|
||||
def test_all_agent_parameters():
|
||||
"""Test that all agent parameters still work"""
|
||||
agent = Agent(
|
||||
name="Full Agent",
|
||||
role="Test Role",
|
||||
goal="Test Goal",
|
||||
backstory="Test Backstory",
|
||||
instructions="Test Instructions",
|
||||
llm="gpt-4",
|
||||
tools=[],
|
||||
function_calling_llm=None,
|
||||
max_iter=10,
|
||||
max_rpm=100,
|
||||
max_execution_time=300,
|
||||
memory=None,
|
||||
verbose=False,
|
||||
allow_delegation=True,
|
||||
step_callback=None,
|
||||
cache=False,
|
||||
system_template="Test template",
|
||||
prompt_template="Test prompt",
|
||||
response_template="Test response",
|
||||
allow_code_execution=True,
|
||||
max_retry_limit=5,
|
||||
respect_context_window=False,
|
||||
code_execution_mode="unsafe",
|
||||
embedder_config={"test": "config"},
|
||||
knowledge=None,
|
||||
knowledge_config={"test": "knowledge"},
|
||||
use_system_prompt=False,
|
||||
markdown=False,
|
||||
stream=False,
|
||||
self_reflect=True,
|
||||
max_reflect=5,
|
||||
min_reflect=2,
|
||||
reflect_llm="gpt-3.5-turbo",
|
||||
reflect_prompt="Reflect on this",
|
||||
user_id="test_user",
|
||||
reasoning_steps=True,
|
||||
guardrail=None,
|
||||
max_guardrail_retries=5,
|
||||
handoffs=[] # New parameter
|
||||
)
|
||||
|
||||
# Verify all parameters were set correctly
|
||||
assert agent.name == "Full Agent"
|
||||
assert agent.role == "Test Role"
|
||||
assert agent.max_iter == 10
|
||||
assert not agent.verbose
|
||||
assert agent.handoffs == []
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Run basic tests
|
||||
print("Testing backward compatibility...")
|
||||
|
||||
test_agent_without_handoffs()
|
||||
print("✓ Agents work without handoffs")
|
||||
|
||||
test_agent_with_existing_tools()
|
||||
print("✓ Existing tools still work")
|
||||
|
||||
test_agent_with_handoffs()
|
||||
print("✓ Agents work with handoffs")
|
||||
|
||||
test_handoff_with_tools()
|
||||
print("✓ Handoffs and tools work together")
|
||||
|
||||
test_handoff_object()
|
||||
print("✓ Handoff objects work correctly")
|
||||
|
||||
test_mixed_handoffs()
|
||||
print("✓ Mixed handoff types work")
|
||||
|
||||
test_handoff_filters()
|
||||
print("✓ Handoff filters work")
|
||||
|
||||
test_all_agent_parameters()
|
||||
print("✓ All agent parameters preserved")
|
||||
|
||||
print("\nAll backward compatibility tests passed! ✨")
|
||||
Generated
+2052
-2050
File diff suppressed because it is too large.
Load diff
@@ -3,8 +3,8 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.35.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.35.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.37.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.37.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -170,6 +170,25 @@ class PraisonAI:
|
||||
pass
|
||||
return None
|
||||
|
||||
def read_file_if_provided(self, file_path):
|
||||
"""
|
||||
Read content from a file if the file path is provided.
|
||||
Returns the file content or None if file cannot be read.
|
||||
"""
|
||||
if not file_path:
|
||||
return None
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
file_content = f.read().strip()
|
||||
return file_content if file_content else None
|
||||
except FileNotFoundError:
|
||||
print(f"[red]ERROR: File not found: {file_path}[/red]")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"[red]ERROR: Failed to read file: {e}[/red]")
|
||||
sys.exit(1)
|
||||
|
||||
def main(self):
|
||||
"""
|
||||
The main function of the PraisonAI object. It parses the command-line arguments,
|
||||
@@ -189,15 +208,24 @@ class PraisonAI:
|
||||
|
||||
# Check for piped input from stdin
|
||||
stdin_input = self.read_stdin_if_available()
|
||||
|
||||
# Check for file input if --file is provided
|
||||
file_input = self.read_file_if_provided(getattr(args, 'file', None))
|
||||
|
||||
if args.command:
|
||||
if args.command.startswith("tests.test") or args.command.startswith("tests/test"): # Argument used for testing purposes
|
||||
print("test")
|
||||
return "test"
|
||||
else:
|
||||
# If stdin input is available, append it to the command
|
||||
# Combine command with any available inputs (stdin and/or file)
|
||||
combined_inputs = []
|
||||
if stdin_input:
|
||||
combined_prompt = f"{args.command} {stdin_input}"
|
||||
combined_inputs.append(stdin_input)
|
||||
if file_input:
|
||||
combined_inputs.append(file_input)
|
||||
|
||||
if combined_inputs:
|
||||
combined_prompt = f"{args.command} {' '.join(combined_inputs)}"
|
||||
result = self.handle_direct_prompt(combined_prompt)
|
||||
print(result)
|
||||
return result
|
||||
@@ -206,20 +234,30 @@ class PraisonAI:
|
||||
elif hasattr(args, 'direct_prompt') and args.direct_prompt:
|
||||
# Only handle direct prompt if agent_file wasn't explicitly set in constructor
|
||||
if original_agent_file == "agents.yaml": # Default value, so safe to use direct prompt
|
||||
# If stdin input is available, append it to the direct prompt
|
||||
prompt = args.direct_prompt
|
||||
# Combine direct prompt with any available inputs (stdin and/or file)
|
||||
prompt_parts = [args.direct_prompt]
|
||||
if stdin_input:
|
||||
prompt = f"{args.direct_prompt} {stdin_input}"
|
||||
prompt_parts.append(stdin_input)
|
||||
if file_input:
|
||||
prompt_parts.append(file_input)
|
||||
prompt = ' '.join(prompt_parts)
|
||||
result = self.handle_direct_prompt(prompt)
|
||||
print(result)
|
||||
return result
|
||||
else:
|
||||
# Agent file was explicitly set, ignore direct prompt and use the file
|
||||
pass
|
||||
elif stdin_input:
|
||||
# If only stdin input is provided (no command), use it as direct prompt
|
||||
if original_agent_file == "agents.yaml": # Default value, so safe to use stdin as prompt
|
||||
result = self.handle_direct_prompt(stdin_input)
|
||||
elif stdin_input or file_input:
|
||||
# If only stdin/file input is provided (no command), use it as direct prompt
|
||||
if original_agent_file == "agents.yaml": # Default value, so safe to use input as prompt
|
||||
# Combine any available inputs
|
||||
inputs = []
|
||||
if stdin_input:
|
||||
inputs.append(stdin_input)
|
||||
if file_input:
|
||||
inputs.append(file_input)
|
||||
combined_input = ' '.join(inputs)
|
||||
result = self.handle_direct_prompt(combined_input)
|
||||
print(result)
|
||||
return result
|
||||
# If no command or direct_prompt, preserve agent_file from constructor (don't overwrite)
|
||||
@@ -530,6 +568,7 @@ class PraisonAI:
|
||||
parser.add_argument("--public", action="store_true", help="Use ngrok to expose the server publicly (only with --call)")
|
||||
parser.add_argument("--merge", action="store_true", help="Merge existing agents.yaml with auto-generated agents instead of overwriting")
|
||||
parser.add_argument("--claudecode", action="store_true", help="Enable Claude Code integration for file modifications and coding tasks")
|
||||
parser.add_argument("--file", "-f", type=str, help="Read input from a file and append it to the prompt")
|
||||
|
||||
# If we're in a test environment, parse with empty args to avoid pytest interference
|
||||
if in_test_env:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import subprocess
|
||||
import os
|
||||
import platform
|
||||
from dotenv import load_dotenv
|
||||
|
||||
class CloudDeployer:
|
||||
@@ -56,7 +57,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.2.35 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.2.37 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
@@ -116,20 +117,66 @@ class CloudDeployer:
|
||||
self.create_api_file()
|
||||
self.create_dockerfile()
|
||||
"""Runs a sequence of shell commands for deployment, continues on error."""
|
||||
|
||||
# Get project ID upfront for Windows compatibility
|
||||
try:
|
||||
result = subprocess.run(['gcloud', 'config', 'get-value', 'project'],
|
||||
capture_output=True, text=True, check=True)
|
||||
project_id = result.stdout.strip()
|
||||
except subprocess.CalledProcessError:
|
||||
print("ERROR: Failed to get GCP project ID. Ensure gcloud is configured.")
|
||||
return
|
||||
|
||||
# Get environment variables
|
||||
openai_model = os.environ.get('OPENAI_MODEL_NAME', 'gpt-4o')
|
||||
openai_key = os.environ.get('OPENAI_API_KEY', 'Enter your API key')
|
||||
openai_base = os.environ.get('OPENAI_API_BASE', 'https://api.openai.com/v1')
|
||||
|
||||
# Build commands with actual values
|
||||
commands = [
|
||||
"yes | gcloud auth configure-docker us-central1-docker.pkg.dev",
|
||||
"gcloud artifacts repositories create praisonai-repository --repository-format=docker --location=us-central1",
|
||||
"docker build --platform linux/amd64 -t gcr.io/$(gcloud config get-value project)/praisonai-app:latest .",
|
||||
"docker tag gcr.io/$(gcloud config get-value project)/praisonai-app:latest us-central1-docker.pkg.dev/$(gcloud config get-value project)/praisonai-repository/praisonai-app:latest",
|
||||
"docker push us-central1-docker.pkg.dev/$(gcloud config get-value project)/praisonai-repository/praisonai-app:latest",
|
||||
"gcloud run deploy praisonai-service --image us-central1-docker.pkg.dev/$(gcloud config get-value project)/praisonai-repository/praisonai-app:latest --platform managed --region us-central1 --allow-unauthenticated --set-env-vars OPENAI_MODEL_NAME=${OPENAI_MODEL_NAME},OPENAI_API_KEY=${OPENAI_API_KEY},OPENAI_API_BASE=${OPENAI_API_BASE}"
|
||||
['gcloud', 'auth', 'configure-docker', 'us-central1-docker.pkg.dev'],
|
||||
['gcloud', 'artifacts', 'repositories', 'create', 'praisonai-repository',
|
||||
'--repository-format=docker', '--location=us-central1'],
|
||||
['docker', 'build', '--platform', 'linux/amd64', '-t',
|
||||
f'gcr.io/{project_id}/praisonai-app:latest', '.'],
|
||||
['docker', 'tag', f'gcr.io/{project_id}/praisonai-app:latest',
|
||||
f'us-central1-docker.pkg.dev/{project_id}/praisonai-repository/praisonai-app:latest'],
|
||||
['docker', 'push',
|
||||
f'us-central1-docker.pkg.dev/{project_id}/praisonai-repository/praisonai-app:latest'],
|
||||
['gcloud', 'run', 'deploy', 'praisonai-service',
|
||||
'--image', f'us-central1-docker.pkg.dev/{project_id}/praisonai-repository/praisonai-app:latest',
|
||||
'--platform', 'managed', '--region', 'us-central1', '--allow-unauthenticated',
|
||||
'--set-env-vars', f'OPENAI_MODEL_NAME={openai_model},OPENAI_API_KEY={openai_key},OPENAI_API_BASE={openai_base}']
|
||||
]
|
||||
|
||||
for cmd in commands:
|
||||
|
||||
# Run commands with appropriate handling for each platform
|
||||
for i, cmd in enumerate(commands):
|
||||
try:
|
||||
subprocess.run(cmd, shell=True, check=True)
|
||||
if i == 0: # First command (gcloud auth configure-docker)
|
||||
if platform.system() != 'Windows':
|
||||
# On Unix, pipe 'yes' to auto-confirm
|
||||
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
|
||||
proc.communicate(input=b'Y\n')
|
||||
if proc.returncode != 0:
|
||||
raise subprocess.CalledProcessError(proc.returncode, cmd)
|
||||
else:
|
||||
# On Windows, try with --quiet flag to avoid prompts
|
||||
cmd_with_quiet = cmd + ['--quiet']
|
||||
try:
|
||||
subprocess.run(cmd_with_quiet, check=True)
|
||||
except subprocess.CalledProcessError:
|
||||
# If --quiet fails, try without it
|
||||
print("Note: You may need to manually confirm the authentication prompt")
|
||||
subprocess.run(cmd, check=True)
|
||||
else:
|
||||
# Run other commands normally
|
||||
subprocess.run(cmd, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"ERROR: Command '{e.cmd}' failed with exit status {e.returncode}")
|
||||
print(f"ERROR: Command failed with exit status {e.returncode}")
|
||||
# Commands 2 (build) and 4 (push) and 5 (deploy) are critical
|
||||
if i in [2, 4, 5]:
|
||||
print("Critical command failed. Aborting deployment.")
|
||||
return
|
||||
print(f"Continuing with the next command...")
|
||||
|
||||
# Usage
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PraisonAI"
|
||||
version = "2.2.35"
|
||||
version = "2.2.37"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
|
||||
readme = "README.md"
|
||||
license = ""
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.0.108",
|
||||
"praisonaiagents>=0.0.110",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
@@ -95,7 +95,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.15", "crewai"]
|
||||
|
||||
[tool.poetry]
|
||||
name = "PraisonAI"
|
||||
version = "2.2.35"
|
||||
version = "2.2.37"
|
||||
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
|
||||
authors = ["Mervin Praison"]
|
||||
license = ""
|
||||
@@ -113,7 +113,7 @@ python = ">=3.10,<3.13"
|
||||
rich = ">=13.7"
|
||||
markdown = ">=3.5"
|
||||
pyparsing = ">=3.0.0"
|
||||
praisonaiagents = ">=0.0.108"
|
||||
praisonaiagents = ">=0.0.110"
|
||||
python-dotenv = ">=0.19.0"
|
||||
instructor = ">=1.3.3"
|
||||
PyYAML = ">=6.0"
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to verify the double API call fix in PraisonAI LLM implementation.
|
||||
|
||||
This script demonstrates that the LLM wrapper now makes only one API call
|
||||
when using tools, instead of two separate calls (one for streaming, one for tools).
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
# Add the path to access the LLM module
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src/praisonai-agents'))
|
||||
|
||||
from praisonaiagents.llm import LLM
|
||||
|
||||
# Sample tool function for testing
|
||||
def get_weather(location: str, unit: str = "celsius") -> str:
|
||||
"""Get the weather for a specific location."""
|
||||
return f"The weather in {location} is 22°{unit[0].upper()}"
|
||||
|
||||
def test_streaming_with_tools():
|
||||
"""Test that streaming with tools makes only one API call."""
|
||||
|
||||
# Initialize LLM
|
||||
llm = LLM(model="gpt-4o", verbose=True)
|
||||
|
||||
# Track API calls
|
||||
api_call_count = 0
|
||||
original_completion = None
|
||||
|
||||
def mock_completion(*args, **kwargs):
|
||||
nonlocal api_call_count
|
||||
api_call_count += 1
|
||||
print(f"\n🔍 API Call #{api_call_count}")
|
||||
print(f" Stream: {kwargs.get('stream', False)}")
|
||||
print(f" Tools: {'Yes' if kwargs.get('tools') else 'No'}")
|
||||
|
||||
# Mock response
|
||||
if kwargs.get('stream', False):
|
||||
# Streaming response
|
||||
def stream_generator():
|
||||
# Simulate streaming chunks
|
||||
chunks = ["The ", "weather ", "looks ", "nice ", "today."]
|
||||
for i, chunk in enumerate(chunks):
|
||||
yield MagicMock(
|
||||
choices=[MagicMock(
|
||||
delta=MagicMock(
|
||||
content=chunk,
|
||||
tool_calls=None
|
||||
)
|
||||
)]
|
||||
)
|
||||
return stream_generator()
|
||||
else:
|
||||
# Non-streaming response
|
||||
return {
|
||||
"choices": [{
|
||||
"message": {
|
||||
"content": "The weather looks nice today.",
|
||||
"tool_calls": None
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
# Patch litellm.completion
|
||||
with patch('litellm.completion', side_effect=mock_completion):
|
||||
print("=" * 60)
|
||||
print("Testing LLM with tools and streaming enabled")
|
||||
print("=" * 60)
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
# Call LLM with tools
|
||||
response = llm.get_response(
|
||||
prompt="What's the weather in Paris?",
|
||||
tools=[get_weather],
|
||||
execute_tool_fn=lambda name, args: get_weather(**args),
|
||||
verbose=False, # Set to False to avoid display functions
|
||||
stream=True
|
||||
)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
|
||||
print(f"\nResponse: {response}")
|
||||
print(f"Time taken: {elapsed_time:.2f}s")
|
||||
print(f"Total API calls: {api_call_count}")
|
||||
|
||||
# Verify only one API call was made
|
||||
if api_call_count == 1:
|
||||
print("\n✅ SUCCESS: Only 1 API call made (optimized!)")
|
||||
print(" Previously this would have made 2 calls:")
|
||||
print(" 1. Streaming call without tools")
|
||||
print(" 2. Non-streaming call with tools")
|
||||
else:
|
||||
print(f"\n❌ FAILED: Made {api_call_count} API calls (expected 1)")
|
||||
|
||||
def test_non_streaming_with_tools():
|
||||
"""Test non-streaming mode with tools."""
|
||||
|
||||
llm = LLM(model="gpt-4o", verbose=False)
|
||||
|
||||
api_call_count = 0
|
||||
|
||||
def mock_completion(*args, **kwargs):
|
||||
nonlocal api_call_count
|
||||
api_call_count += 1
|
||||
|
||||
return {
|
||||
"choices": [{
|
||||
"message": {
|
||||
"content": "I'll check the weather for you.",
|
||||
"tool_calls": [{
|
||||
"id": "call_123",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"arguments": '{"location": "London", "unit": "fahrenheit"}'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
with patch('litellm.completion', side_effect=mock_completion):
|
||||
print("\n" + "=" * 60)
|
||||
print("Testing LLM with tools and streaming disabled")
|
||||
print("=" * 60)
|
||||
|
||||
response = llm.get_response(
|
||||
prompt="What's the weather in London in fahrenheit?",
|
||||
tools=[get_weather],
|
||||
execute_tool_fn=lambda name, args: get_weather(**args),
|
||||
stream=False
|
||||
)
|
||||
|
||||
print(f"\nTotal API calls: {api_call_count}")
|
||||
|
||||
if api_call_count == 1:
|
||||
print("✅ SUCCESS: Only 1 API call made")
|
||||
else:
|
||||
print(f"❌ FAILED: Made {api_call_count} API calls (expected 1)")
|
||||
|
||||
def test_provider_detection():
|
||||
"""Test the new _supports_streaming_tools method."""
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Testing provider streaming tool support detection")
|
||||
print("=" * 60)
|
||||
|
||||
# Test different providers
|
||||
providers_to_test = [
|
||||
("gpt-4o", True, "OpenAI GPT-4o"),
|
||||
("gpt-3.5-turbo", True, "OpenAI GPT-3.5"),
|
||||
("claude-3-5-sonnet", True, "Anthropic Claude"),
|
||||
("gemini-2.0-flash", True, "Google Gemini"),
|
||||
("ollama/llama2", False, "Ollama (local)"),
|
||||
("groq/mixtral-8x7b", False, "Groq"),
|
||||
("custom-model", False, "Unknown provider")
|
||||
]
|
||||
|
||||
for model, expected, description in providers_to_test:
|
||||
llm = LLM(model=model)
|
||||
supports_streaming = llm._supports_streaming_tools()
|
||||
|
||||
status = "✅" if supports_streaming == expected else "❌"
|
||||
print(f"{status} {description}: {model}")
|
||||
print(f" Supports streaming with tools: {supports_streaming}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Testing double API call fix in PraisonAI LLM")
|
||||
print("=" * 60)
|
||||
|
||||
# Run tests
|
||||
test_streaming_with_tools()
|
||||
test_non_streaming_with_tools()
|
||||
test_provider_detection()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Test complete!")
|
||||
print("\nKey improvement: When using tools with streaming-capable providers,")
|
||||
print("the LLM now makes only 1 API call instead of 2, reducing:")
|
||||
print("- API costs by 50%")
|
||||
print("- Response latency by 1-3 seconds")
|
||||
print("- Complexity in the codebase")
|
||||
Generated
+2582
-2584
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user