mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-08 01:08:39 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cd838f691 | ||
|
|
319944e012 | ||
|
|
b53162aa9e | ||
|
|
52c249fde0 | ||
|
|
7607df753f | ||
|
|
8fa181bc55 | ||
|
|
ccbf0ebebb | ||
|
|
6995a446e1 | ||
|
|
72c70ce050 |
No files matched your search
+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.64" \
|
||||
"praisonai>=2.2.65" \
|
||||
"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.64" \
|
||||
"praisonai>=2.2.65" \
|
||||
"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.64" \
|
||||
"praisonai>=2.2.65" \
|
||||
"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.64" \
|
||||
"praisonai>=2.2.65" \
|
||||
"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.64`
|
||||
- PraisonAI: `>=2.2.65`
|
||||
- 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.64" "praisonaiagents==0.0.92"
|
||||
RUN pip install "praisonai==2.2.65" "praisonaiagents==0.0.92"
|
||||
```
|
||||
|
||||
## 🌐 Production Deployment
|
||||
|
||||
+343
-343
@@ -1,355 +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": [
|
||||
"cells": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"True"
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "_T4g3t5sLoag"
|
||||
},
|
||||
"source": [
|
||||
"# ZeroScript: AI-Powered Browser Test Automation using PraisonAI Agent & OpenAI"
|
||||
]
|
||||
},
|
||||
"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"
|
||||
"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'\ud83e\ude93 killing pid={self.browser_pid}...' if (self.browser_pid and owns_browser) else '\u2620\ufe0f'\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": [
|
||||
"\u2705 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.model_dump() if hasattr(result_obj, \"model_dump\") 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\"\u2705 Report saved to {report}\")\n",
|
||||
"\n",
|
||||
"await main()\n"
|
||||
]
|
||||
},
|
||||
"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": {
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
"provenance": []
|
||||
},
|
||||
"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"
|
||||
]
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"✅ Report saved to data/reports/report_20250630_092319.json\n"
|
||||
]
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -440,7 +440,7 @@ async def generate_research(
|
||||
"message": "Report generation queued",
|
||||
"created_at": datetime.now().isoformat(),
|
||||
"updated_at": datetime.now().isoformat(),
|
||||
"config": request.dict()
|
||||
"config": request.model_dump()
|
||||
}
|
||||
|
||||
# Create config object
|
||||
|
||||
@@ -31,7 +31,7 @@ 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)
|
||||
json.dump(chain.model_dump(), f, indent=2)
|
||||
return f"Reasoning chain saved to {filename}"
|
||||
|
||||
# Example 1: Chain of Thought Agent
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script to fix the deprecated .dict() usage in Jupyter notebook
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
def fix_notebook():
|
||||
notebook_path = "examples/cookbooks/Programming_Code_Analysis_Agents/ZeroScript_AI_TestExecutor.ipynb"
|
||||
|
||||
try:
|
||||
# Read the notebook
|
||||
with open(notebook_path, 'r') as f:
|
||||
notebook = json.load(f)
|
||||
|
||||
# Find and fix the cell with .dict() usage
|
||||
for cell in notebook.get('cells', []):
|
||||
if cell.get('cell_type') == 'code':
|
||||
source = cell.get('source', [])
|
||||
# Convert source to string if it's a list
|
||||
source_str = ''.join(source) if isinstance(source, list) else source
|
||||
|
||||
# Check if this cell contains the problematic .dict() usage or hasattr check
|
||||
if 'result_obj.dict()' in source_str or 'hasattr(result_obj, "dict")' in source_str:
|
||||
print(f"Found cell with .dict() usage, fixing...")
|
||||
# Replace .dict() with .model_dump() and fix hasattr check for backward compatibility
|
||||
fixed_source = source_str.replace('result_obj.dict()', 'result_obj.model_dump()').replace('hasattr(result_obj, "dict")', 'hasattr(result_obj, "model_dump")')
|
||||
|
||||
# Convert back to list format if needed
|
||||
if isinstance(source, list):
|
||||
cell['source'] = fixed_source.splitlines(True)
|
||||
else:
|
||||
cell['source'] = fixed_source
|
||||
|
||||
print("Fixed .dict() usage")
|
||||
break
|
||||
|
||||
# Write the fixed notebook back
|
||||
with open(notebook_path, 'w') as f:
|
||||
json.dump(notebook, f, indent=2)
|
||||
|
||||
print(f"Successfully updated {notebook_path}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error fixing notebook: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = fix_notebook()
|
||||
sys.exit(0 if success else 1)
|
||||
@@ -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.64.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.64.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.65.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.2.65.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -14,10 +14,13 @@ import importlib
|
||||
import importlib.util
|
||||
import os
|
||||
import logging
|
||||
import re
|
||||
import keyword
|
||||
|
||||
# Framework-specific imports with availability checks
|
||||
CREWAI_AVAILABLE = False
|
||||
AUTOGEN_AVAILABLE = False
|
||||
AUTOGEN_V4_AVAILABLE = False
|
||||
PRAISONAI_TOOLS_AVAILABLE = False
|
||||
AGENTOPS_AVAILABLE = False
|
||||
PRAISONAI_AVAILABLE = False
|
||||
@@ -41,6 +44,17 @@ try:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
from autogen_agentchat.agents import AssistantAgent as AutoGenV4AssistantAgent
|
||||
from autogen_ext.models.openai import OpenAIChatCompletionClient
|
||||
from autogen_agentchat.teams import RoundRobinGroupChat
|
||||
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
|
||||
from autogen_agentchat.messages import TextMessage
|
||||
from autogen_core import CancellationToken
|
||||
AUTOGEN_V4_AVAILABLE = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import agentops
|
||||
AGENTOPS_AVAILABLE = True
|
||||
@@ -70,6 +84,40 @@ os.environ["OTEL_SDK_DISABLED"] = "true"
|
||||
def noop(*args, **kwargs):
|
||||
pass
|
||||
|
||||
def sanitize_agent_name_for_autogen_v4(name):
|
||||
"""
|
||||
Sanitize agent name to be a valid Python identifier for AutoGen v0.4.
|
||||
|
||||
Args:
|
||||
name (str): The original agent name
|
||||
|
||||
Returns:
|
||||
str: A valid Python identifier
|
||||
"""
|
||||
# Convert to string and replace invalid characters with underscores
|
||||
sanitized = re.sub(r'[^a-zA-Z0-9_]', '_', str(name))
|
||||
|
||||
# Collapse only very excessive underscores (5 or more) to reduce extreme cases
|
||||
sanitized = re.sub(r'_{5,}', '_', sanitized)
|
||||
|
||||
# Remove trailing underscores only if not part of a dunder pattern and only if singular
|
||||
if sanitized.endswith('_') and not sanitized.endswith('__') and sanitized != '_':
|
||||
sanitized = sanitized.rstrip('_')
|
||||
|
||||
# Ensure it starts with a letter or underscore (not a digit)
|
||||
if sanitized and sanitized[0].isdigit():
|
||||
sanitized = 'agent_' + sanitized
|
||||
|
||||
# Handle empty string or only invalid characters (including single underscore from all invalid chars)
|
||||
if not sanitized or sanitized == '_':
|
||||
sanitized = 'agent'
|
||||
|
||||
# Check if it's a Python keyword and append underscore if so
|
||||
if keyword.iskeyword(sanitized):
|
||||
sanitized += '_'
|
||||
|
||||
return sanitized
|
||||
|
||||
def disable_crewai_telemetry():
|
||||
if CREWAI_AVAILABLE:
|
||||
for attr in dir(Telemetry):
|
||||
@@ -123,8 +171,8 @@ class AgentsGenerator:
|
||||
# Validate framework availability
|
||||
if framework == "crewai" and not CREWAI_AVAILABLE:
|
||||
raise ImportError("CrewAI is not installed. Please install it with 'pip install praisonai[crewai]'")
|
||||
elif framework == "autogen" and not AUTOGEN_AVAILABLE:
|
||||
raise ImportError("AutoGen is not installed. Please install it with 'pip install praisonai[autogen]'")
|
||||
elif framework == "autogen" and not (AUTOGEN_AVAILABLE or AUTOGEN_V4_AVAILABLE):
|
||||
raise ImportError("AutoGen is not installed. Please install it with 'pip install praisonai[autogen]' for v0.2 or 'pip install praisonai[autogen-v4]' for v0.4")
|
||||
elif framework == "praisonai" and not PRAISONAI_AVAILABLE:
|
||||
raise ImportError("PraisonAI is not installed. Please install it with 'pip install praisonaiagents'")
|
||||
|
||||
@@ -316,11 +364,35 @@ class AgentsGenerator:
|
||||
framework = self.framework or config.get('framework')
|
||||
|
||||
if framework == "autogen":
|
||||
if not AUTOGEN_AVAILABLE:
|
||||
raise ImportError("AutoGen is not installed. Please install it with 'pip install praisonai[autogen]'")
|
||||
if not (AUTOGEN_AVAILABLE or AUTOGEN_V4_AVAILABLE):
|
||||
raise ImportError("AutoGen is not installed. Please install it with 'pip install praisonai[autogen]' for v0.2 or 'pip install praisonai[autogen-v4]' for v0.4")
|
||||
|
||||
# Choose autogen version based on availability and environment preference
|
||||
# AUTOGEN_VERSION can be set to "v0.2" or "v0.4" to force a specific version
|
||||
autogen_version = os.environ.get("AUTOGEN_VERSION", "auto").lower()
|
||||
|
||||
use_v4 = False
|
||||
if autogen_version == "v0.4" and AUTOGEN_V4_AVAILABLE:
|
||||
use_v4 = True
|
||||
elif autogen_version == "v0.2" and AUTOGEN_AVAILABLE:
|
||||
use_v4 = False
|
||||
elif autogen_version == "auto":
|
||||
# Default preference: use v0.4 if available, fallback to v0.2
|
||||
use_v4 = AUTOGEN_V4_AVAILABLE
|
||||
else:
|
||||
# Fallback to whatever is available
|
||||
use_v4 = AUTOGEN_V4_AVAILABLE and not AUTOGEN_AVAILABLE
|
||||
|
||||
if AGENTOPS_AVAILABLE:
|
||||
agentops.init(os.environ.get("AGENTOPS_API_KEY"), default_tags=["autogen"])
|
||||
return self._run_autogen(config, topic, tools_dict)
|
||||
version_tag = "autogen-v4" if use_v4 else "autogen-v2"
|
||||
agentops.init(os.environ.get("AGENTOPS_API_KEY"), default_tags=[version_tag])
|
||||
|
||||
if use_v4:
|
||||
self.logger.info("Using AutoGen v0.4")
|
||||
return self._run_autogen_v4(config, topic, tools_dict)
|
||||
else:
|
||||
self.logger.info("Using AutoGen v0.2")
|
||||
return self._run_autogen(config, topic, tools_dict)
|
||||
elif framework == "praisonai":
|
||||
if not PRAISONAI_AVAILABLE:
|
||||
raise ImportError("PraisonAI is not installed. Please install it with 'pip install praisonaiagents'")
|
||||
@@ -407,6 +479,113 @@ class AgentsGenerator:
|
||||
|
||||
return result
|
||||
|
||||
def _run_autogen_v4(self, config, topic, tools_dict):
|
||||
"""
|
||||
Run agents using the AutoGen v0.4 framework with async, event-driven architecture.
|
||||
|
||||
Args:
|
||||
config (dict): Configuration dictionary
|
||||
topic (str): The topic to process
|
||||
tools_dict (dict): Dictionary of available tools
|
||||
|
||||
Returns:
|
||||
str: Result of the agent interactions
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
async def run_autogen_v4_async():
|
||||
# Create model client for v0.4
|
||||
model_config = self.config_list[0] if self.config_list else {}
|
||||
model_client = OpenAIChatCompletionClient(
|
||||
model=model_config.get('model', 'gpt-4o'),
|
||||
api_key=model_config.get('api_key', os.environ.get("OPENAI_API_KEY")),
|
||||
base_url=model_config.get('base_url', "https://api.openai.com/v1")
|
||||
)
|
||||
|
||||
agents = []
|
||||
combined_tasks = []
|
||||
|
||||
# Create agents from config
|
||||
for role, details in config['roles'].items():
|
||||
# For AutoGen v0.4, ensure agent name is a valid Python identifier
|
||||
agent_name = details['role'].format(topic=topic).replace("{topic}", topic)
|
||||
agent_name = sanitize_agent_name_for_autogen_v4(agent_name)
|
||||
backstory = details['backstory'].format(topic=topic)
|
||||
|
||||
# Convert tools for v0.4 - simplified tool passing
|
||||
agent_tools = []
|
||||
for tool_name in details.get('tools', []):
|
||||
if tool_name in tools_dict:
|
||||
tool_instance = tools_dict[tool_name]
|
||||
# For v0.4, we can pass the tool's run method directly if it's callable
|
||||
if hasattr(tool_instance, 'run') and callable(tool_instance.run):
|
||||
agent_tools.append(tool_instance.run)
|
||||
|
||||
# Create v0.4 AssistantAgent
|
||||
assistant = AutoGenV4AssistantAgent(
|
||||
name=agent_name,
|
||||
system_message=backstory + ". Must reply with 'TERMINATE' when the task is complete.",
|
||||
model_client=model_client,
|
||||
tools=agent_tools,
|
||||
reflect_on_tool_use=True
|
||||
)
|
||||
|
||||
agents.append(assistant)
|
||||
|
||||
# Collect all task descriptions for sequential execution
|
||||
for task_name, task_details in details.get('tasks', {}).items():
|
||||
description_filled = task_details['description'].format(topic=topic)
|
||||
combined_tasks.append(description_filled)
|
||||
|
||||
if not agents:
|
||||
return "No agents created from configuration"
|
||||
|
||||
# Create termination conditions
|
||||
text_termination = TextMentionTermination("TERMINATE")
|
||||
max_messages_termination = MaxMessageTermination(max_messages=20)
|
||||
termination_condition = text_termination | max_messages_termination
|
||||
|
||||
# Create RoundRobinGroupChat for parallel/sequential execution
|
||||
group_chat = RoundRobinGroupChat(
|
||||
agents,
|
||||
termination_condition=termination_condition,
|
||||
max_turns=len(agents) * 3 # Allow multiple rounds
|
||||
)
|
||||
|
||||
# Combine all tasks into a single task description
|
||||
task_description = f"Topic: {topic}\n\nTasks to complete:\n" + "\n".join(
|
||||
f"{i+1}. {task}" for i, task in enumerate(combined_tasks)
|
||||
)
|
||||
|
||||
# Run the group chat
|
||||
try:
|
||||
result = await group_chat.run(task=task_description)
|
||||
|
||||
# Extract the final message content
|
||||
if result.messages:
|
||||
final_message = result.messages[-1]
|
||||
if hasattr(final_message, 'content'):
|
||||
return f"### AutoGen v0.4 Output ###\n{final_message.content}"
|
||||
else:
|
||||
return f"### AutoGen v0.4 Output ###\n{str(final_message)}"
|
||||
else:
|
||||
return "### AutoGen v0.4 Output ###\nNo messages generated"
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error in AutoGen v0.4 execution: {str(e)}")
|
||||
return f"### AutoGen v0.4 Error ###\n{str(e)}"
|
||||
|
||||
finally:
|
||||
# Close the model client
|
||||
await model_client.close()
|
||||
|
||||
# Run the async function
|
||||
try:
|
||||
return asyncio.run(run_autogen_v4_async())
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error running AutoGen v0.4: {str(e)}")
|
||||
return f"### AutoGen v0.4 Error ###\n{str(e)}"
|
||||
|
||||
def _run_crewai(self, config, topic, tools_dict):
|
||||
"""
|
||||
Run agents using the CrewAI framework.
|
||||
|
||||
@@ -32,6 +32,13 @@ try:
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
from autogen_agentchat.agents import AssistantAgent
|
||||
from autogen_ext.models.openai import OpenAIChatCompletionClient
|
||||
AUTOGEN_V4_AVAILABLE = True
|
||||
except ImportError:
|
||||
AUTOGEN_V4_AVAILABLE = False
|
||||
|
||||
try:
|
||||
from praisonai_tools import (
|
||||
CodeDocsSearchTool, CSVSearchTool, DirectorySearchTool, DOCXSearchTool,
|
||||
@@ -73,10 +80,11 @@ class AutoGenerator:
|
||||
CrewAI is not installed. Please install with:
|
||||
pip install "praisonai[crewai]"
|
||||
""")
|
||||
elif framework == "autogen" and not AUTOGEN_AVAILABLE:
|
||||
elif framework == "autogen" and not (AUTOGEN_AVAILABLE or AUTOGEN_V4_AVAILABLE):
|
||||
raise ImportError("""
|
||||
AutoGen is not installed. Please install with:
|
||||
pip install "praisonai[autogen]"
|
||||
pip install "praisonai[autogen]" for v0.2
|
||||
pip install "praisonai[autogen-v4]" for v0.4
|
||||
""")
|
||||
elif framework == "praisonai" and not PRAISONAI_AVAILABLE:
|
||||
raise ImportError("""
|
||||
@@ -86,7 +94,14 @@ Praisonai is not installed. Please install with:
|
||||
|
||||
# Only show tools message if using a framework and tools are needed
|
||||
if (framework in ["crewai", "autogen"]) and not PRAISONAI_TOOLS_AVAILABLE:
|
||||
logging.warning(f"""
|
||||
if framework == "autogen":
|
||||
logging.warning("""
|
||||
Tools are not available for autogen. To use tools, install:
|
||||
pip install "praisonai[autogen]" for v0.2
|
||||
pip install "praisonai[autogen-v4]" for v0.4
|
||||
""")
|
||||
else:
|
||||
logging.warning(f"""
|
||||
Tools are not available for {framework}. To use tools, install:
|
||||
pip install "praisonai[{framework}]"
|
||||
""")
|
||||
|
||||
@@ -57,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.64 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.2.65 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "PraisonAI"
|
||||
version = "2.2.64"
|
||||
version = "2.2.65"
|
||||
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 = ""
|
||||
@@ -92,10 +92,17 @@ call = [
|
||||
train = []
|
||||
crewai = ["crewai>=0.32.0", "praisonai-tools>=0.0.22"]
|
||||
autogen = ["pyautogen==0.2.29", "praisonai-tools>=0.0.22", "crewai"]
|
||||
autogen-v4 = [
|
||||
"autogen-agentchat>=0.4.0",
|
||||
"autogen-ext[openai]>=0.4.0",
|
||||
"autogen-core>=0.4.0",
|
||||
"praisonai-tools>=0.0.22",
|
||||
"crewai"
|
||||
]
|
||||
|
||||
[tool.poetry]
|
||||
name = "PraisonAI"
|
||||
version = "2.2.64"
|
||||
version = "2.2.65"
|
||||
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 = ""
|
||||
@@ -119,6 +126,9 @@ instructor = ">=1.3.3"
|
||||
PyYAML = ">=6.0"
|
||||
mcp = ">=1.6.0"
|
||||
pyautogen = {version = "==0.2.29", optional = true}
|
||||
autogen-agentchat = {version = ">=0.4.0", optional = true}
|
||||
autogen-ext = {version = ">=0.4.0", optional = true}
|
||||
autogen-core = {version = ">=0.4.0", optional = true}
|
||||
crewai = {version = ">=0.32.0", optional = true}
|
||||
praisonai-tools = {version = ">=0.0.22", optional = true}
|
||||
chainlit = {version = "==2.5.5", optional = true}
|
||||
@@ -277,6 +287,7 @@ call = [
|
||||
]
|
||||
crewai = ["crewai", "praisonai-tools"]
|
||||
autogen = ["pyautogen", "praisonai-tools", "crewai"]
|
||||
autogen-v4 = ["autogen-agentchat", "autogen-ext", "autogen-core", "praisonai-tools", "crewai"]
|
||||
|
||||
[tool.poetry-dynamic-versioning]
|
||||
enable = true
|
||||
|
||||
Generated
+88
-25
@@ -335,6 +335,54 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/d1/800ab8dfe15f00836b8d1ea41f68f5e4731a96e8fc19548993996f3b5728/auth0_python-4.9.0-py3-none-any.whl", hash = "sha256:6440c7f74dfd669d9f5cdfe9bb44c4c3b230ce98a82353f55a387e90241fbf5b", size = 135349, upload-time = "2025-04-01T09:31:35.538Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autogen-agentchat"
|
||||
version = "0.6.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "autogen-core" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/9a/89e3b4456ba543593aef37e2ed38b52b374d0b43db87a3494490e20aa29e/autogen_agentchat-0.6.4.tar.gz", hash = "sha256:a50ba1a97f3881693084677807756714f237da89fd481207e6d139c930b2b3f8", size = 137817, upload-time = "2025-07-09T17:48:32.868Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/92/bc/3cc970d370d3dff4e83cf4008062e129c997b879cf721efce5a381cbb953/autogen_agentchat-0.6.4-py3-none-any.whl", hash = "sha256:441f884af0eb9edb953451b0ec06077ac782a7d60d591ce7ea57d94fefad2098", size = 114245, upload-time = "2025-07-09T17:48:31.48Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autogen-core"
|
||||
version = "0.6.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "jsonref" },
|
||||
{ name = "opentelemetry-api" },
|
||||
{ name = "pillow" },
|
||||
{ name = "protobuf" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9b/9c/36411364e8d02b292d4ff79823c0e15ebca9e055b1f9e57169562763f6c3/autogen_core-0.6.4.tar.gz", hash = "sha256:0c0ea2aa2794d5ec28e55eb2385480761e591f07c34dbd814feb71a21407aa0d", size = 99761, upload-time = "2025-07-09T17:48:57.136Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/75/40/7621973ad47912186f165ad02290d446b0e1a001ea79b5d3874eef8486cf/autogen_core-0.6.4-py3-none-any.whl", hash = "sha256:49bce7e2fb24aee5e577e5e32faa6e440dfcdd472f653e5eaa5a640eb908dd35", size = 101394, upload-time = "2025-07-09T17:48:55.246Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autogen-ext"
|
||||
version = "0.6.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "autogen-core" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/45/87/8872f3fbaea54cac11114935a2e497213ff40333b79cc1c9856e4b1de0c5/autogen_ext-0.6.4.tar.gz", hash = "sha256:ed153aa896723186ca9c5db42b3ec998d010cba503fee21d70548efb7bf9f0bb", size = 368319, upload-time = "2025-07-09T17:48:54.886Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/49/8d5a78e0072530151f4347743a231634e4af8f1772b17b767f3070de8ba6/autogen_ext-0.6.4-py3-none-any.whl", hash = "sha256:9a1a74bb671b791a5c2e3bf3038ba7c6d0d4825d98bd393b3e0a980ae83db893", size = 317109, upload-time = "2025-07-09T17:48:53.361Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
openai = [
|
||||
{ name = "aiofiles" },
|
||||
{ name = "openai" },
|
||||
{ name = "tiktoken" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backoff"
|
||||
version = "2.2.1"
|
||||
@@ -4000,7 +4048,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonai"
|
||||
version = "2.2.64"
|
||||
version = "2.2.65"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "instructor" },
|
||||
@@ -4030,6 +4078,13 @@ autogen = [
|
||||
{ name = "praisonai-tools" },
|
||||
{ name = "pyautogen" },
|
||||
]
|
||||
autogen-v4 = [
|
||||
{ name = "autogen-agentchat" },
|
||||
{ name = "autogen-core" },
|
||||
{ name = "autogen-ext", extra = ["openai"] },
|
||||
{ name = "crewai" },
|
||||
{ name = "praisonai-tools" },
|
||||
]
|
||||
call = [
|
||||
{ name = "fastapi" },
|
||||
{ name = "flaml", extra = ["automl"] },
|
||||
@@ -4107,6 +4162,9 @@ requires-dist = [
|
||||
{ name = "aiosqlite", marker = "extra == 'code'", specifier = ">=0.20.0" },
|
||||
{ name = "aiosqlite", marker = "extra == 'realtime'", specifier = ">=0.20.0" },
|
||||
{ name = "aiosqlite", marker = "extra == 'ui'", specifier = ">=0.20.0" },
|
||||
{ name = "autogen-agentchat", marker = "extra == 'autogen-v4'", specifier = ">=0.4.0" },
|
||||
{ name = "autogen-core", marker = "extra == 'autogen-v4'", specifier = ">=0.4.0" },
|
||||
{ name = "autogen-ext", extras = ["openai"], marker = "extra == 'autogen-v4'", specifier = ">=0.4.0" },
|
||||
{ name = "chainlit", marker = "extra == 'chat'", specifier = "==2.5.5" },
|
||||
{ name = "chainlit", marker = "extra == 'code'", specifier = "==2.5.5" },
|
||||
{ name = "chainlit", marker = "extra == 'realtime'", specifier = "==2.5.5" },
|
||||
@@ -4115,6 +4173,7 @@ requires-dist = [
|
||||
{ name = "crawl4ai", marker = "extra == 'code'", specifier = ">=0.6.0" },
|
||||
{ name = "crawl4ai", marker = "extra == 'realtime'", specifier = ">=0.6.0" },
|
||||
{ name = "crewai", marker = "extra == 'autogen'" },
|
||||
{ name = "crewai", marker = "extra == 'autogen-v4'" },
|
||||
{ name = "crewai", marker = "extra == 'crewai'", specifier = ">=0.32.0" },
|
||||
{ name = "duckduckgo-search", marker = "extra == 'realtime'", specifier = ">=6.3.0" },
|
||||
{ name = "fastapi", marker = "extra == 'api'", specifier = ">=0.115.0" },
|
||||
@@ -4141,6 +4200,7 @@ requires-dist = [
|
||||
{ name = "playwright", marker = "extra == 'code'", specifier = ">=1.47.0" },
|
||||
{ name = "plotly", marker = "extra == 'realtime'", specifier = ">=5.24.0" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.0.22" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen-v4'", specifier = ">=0.0.22" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.0.22" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.0.136" },
|
||||
{ name = "pyautogen", marker = "extra == 'autogen'", specifier = "==0.2.29" },
|
||||
@@ -4168,7 +4228,7 @@ requires-dist = [
|
||||
{ name = "websockets", marker = "extra == 'realtime'", specifier = ">=12.0" },
|
||||
{ name = "yfinance", marker = "extra == 'realtime'", specifier = ">=0.2.44" },
|
||||
]
|
||||
provides-extras = ["ui", "gradio", "api", "agentops", "google", "openai", "anthropic", "cohere", "chat", "code", "realtime", "call", "train", "crewai", "autogen"]
|
||||
provides-extras = ["ui", "gradio", "api", "agentops", "google", "openai", "anthropic", "cohere", "chat", "code", "realtime", "call", "train", "crewai", "autogen", "autogen-v4"]
|
||||
|
||||
[[package]]
|
||||
name = "praisonai-tools"
|
||||
@@ -5676,35 +5736,38 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "tiktoken"
|
||||
version = "0.7.0"
|
||||
version = "0.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "regex" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c4/4a/abaec53e93e3ef37224a4dd9e2fc6bb871e7a538c2b6b9d2a6397271daf4/tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6", size = 33437, upload-time = "2024-05-13T18:03:28.793Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ea/cf/756fedf6981e82897f2d570dd25fa597eb3f4459068ae0572d7e888cfd6f/tiktoken-0.9.0.tar.gz", hash = "sha256:d02a5ca6a938e0490e1ff957bc48c8b078c88cb83977be1625b1fd8aac792c5d", size = 35991, upload-time = "2025-02-14T06:03:01.003Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/96/10/28d59d43d72a0ebd4211371d0bf10c935cdecbb62b812ae04c58bfc37d96/tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f", size = 961465, upload-time = "2024-05-13T18:02:31.978Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/0c/d4125348dedd1f8f38e3f85245e7fc38858ffc77c9b7edfb762a8191ba0b/tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225", size = 906849, upload-time = "2024-05-13T18:02:33.535Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/ab/f9c7675747f259d133d66065106cf732a7c2bef6043062fbca8e011f7f4d/tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590", size = 1048795, upload-time = "2024-05-13T18:02:35.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/8c/7d1007557b343d5cf18349802e94d3a14397121e9105b4661f8cd753f9bf/tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c", size = 1080866, upload-time = "2024-05-13T18:02:37.583Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/40/61d6354cb64a563fce475a2907039be9fe809ca5f801213856353b01a35b/tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311", size = 1092776, upload-time = "2024-05-13T18:02:39.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/6c/83ca40527d072739f0704b9f59b325786c444ca63672a77cb69adc8181f7/tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5", size = 1142591, upload-time = "2024-05-13T18:02:40.793Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/1f/a5d72755118e9e1b62cdf3ef9138eb83d49088f3cb37a9540025c81c0e75/tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702", size = 798864, upload-time = "2024-05-13T18:02:42.567Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/eb/57492b2568eea1d546da5cc1ae7559d924275280db80ba07e6f9b89a914b/tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f", size = 961468, upload-time = "2024-05-13T18:02:43.788Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/ef/e07dbfcb2f85c84abaa1b035a9279575a8da0236305491dc22ae099327f7/tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f", size = 907005, upload-time = "2024-05-13T18:02:45.327Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/9b/f36db825b1e9904c3a2646439cb9923fc1e09208e2e071c6d9dd64ead131/tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b", size = 1049183, upload-time = "2024-05-13T18:02:46.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/b4/b80d1fe33015e782074e96bbbf4108ccd283b8deea86fb43c15d18b7c351/tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992", size = 1080830, upload-time = "2024-05-13T18:02:48.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/40/c66ff3a21af6d62a7e0ff428d12002c4e0389f776d3ff96dcaa0bb354eee/tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1", size = 1092967, upload-time = "2024-05-13T18:02:50.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/80/f4c9e255ff236e6a69ce44b927629cefc1b63d3a00e2d1c9ed540c9492d2/tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89", size = 1142682, upload-time = "2024-05-13T18:02:51.814Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/10/c04b4ff592a5f46b28ebf4c2353f735c02ae7f0ce1b165d00748ced6467e/tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb", size = 799009, upload-time = "2024-05-13T18:02:53.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/46/4cdda4186ce900608f522da34acf442363346688c71b938a90a52d7b84cc/tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908", size = 960446, upload-time = "2024-05-13T18:02:54.409Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/30/09ced367d280072d7a3e21f34263dfbbf6378661e7a0f6414e7c18971083/tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410", size = 906652, upload-time = "2024-05-13T18:02:56.25Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/7b/c949e4954441a879a67626963dff69096e3c774758b9f2bb0853f7b4e1e7/tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704", size = 1047904, upload-time = "2024-05-13T18:02:57.707Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/81/1842a22f15586072280364c2ab1e40835adaf64e42fe80e52aff921ee021/tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350", size = 1079836, upload-time = "2024-05-13T18:02:59.009Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/87/51a133a3d5307cf7ae3754249b0faaa91d3414b85c3d36f80b54d6817aa6/tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4", size = 1092472, upload-time = "2024-05-13T18:03:00.597Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/1f/c93517dc6d3b2c9e988b8e24f87a8b2d4a4ab28920a3a3f3ea338397ae0c/tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97", size = 1141881, upload-time = "2024-05-13T18:03:02.743Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/4b/48ca098cb580c099b5058bf62c4cb5e90ca6130fa43ef4df27088536245b/tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f", size = 799281, upload-time = "2024-05-13T18:03:04.036Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/f3/50ec5709fad61641e4411eb1b9ac55b99801d71f1993c29853f256c726c9/tiktoken-0.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:586c16358138b96ea804c034b8acf3f5d3f0258bd2bc3b0227af4af5d622e382", size = 1065770, upload-time = "2025-02-14T06:02:01.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/f8/5a9560a422cf1755b6e0a9a436e14090eeb878d8ec0f80e0cd3d45b78bf4/tiktoken-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9c59ccc528c6c5dd51820b3474402f69d9a9e1d656226848ad68a8d5b2e5108", size = 1009314, upload-time = "2025-02-14T06:02:02.869Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/20/3ed4cfff8f809cb902900ae686069e029db74567ee10d017cb254df1d598/tiktoken-0.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0968d5beeafbca2a72c595e8385a1a1f8af58feaebb02b227229b69ca5357fd", size = 1143140, upload-time = "2025-02-14T06:02:04.165Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/95/cc2c6d79df8f113bdc6c99cdec985a878768120d87d839a34da4bd3ff90a/tiktoken-0.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92a5fb085a6a3b7350b8fc838baf493317ca0e17bd95e8642f95fc69ecfed1de", size = 1197860, upload-time = "2025-02-14T06:02:06.268Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/6c/9c1a4cc51573e8867c9381db1814223c09ebb4716779c7f845d48688b9c8/tiktoken-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:15a2752dea63d93b0332fb0ddb05dd909371ededa145fe6a3242f46724fa7990", size = 1259661, upload-time = "2025-02-14T06:02:08.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/4c/22eb8e9856a2b1808d0a002d171e534eac03f96dbe1161978d7389a59498/tiktoken-0.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:26113fec3bd7a352e4b33dbaf1bd8948de2507e30bd95a44e2b1156647bc01b4", size = 894026, upload-time = "2025-02-14T06:02:12.841Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/ae/4613a59a2a48e761c5161237fc850eb470b4bb93696db89da51b79a871f1/tiktoken-0.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f32cc56168eac4851109e9b5d327637f15fd662aa30dd79f964b7c39fbadd26e", size = 1065987, upload-time = "2025-02-14T06:02:14.174Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/86/55d9d1f5b5a7e1164d0f1538a85529b5fcba2b105f92db3622e5d7de6522/tiktoken-0.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:45556bc41241e5294063508caf901bf92ba52d8ef9222023f83d2483a3055348", size = 1009155, upload-time = "2025-02-14T06:02:15.384Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/58/01fb6240df083b7c1916d1dcb024e2b761213c95d576e9f780dfb5625a76/tiktoken-0.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03935988a91d6d3216e2ec7c645afbb3d870b37bcb67ada1943ec48678e7ee33", size = 1142898, upload-time = "2025-02-14T06:02:16.666Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/73/41591c525680cd460a6becf56c9b17468d3711b1df242c53d2c7b2183d16/tiktoken-0.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b3d80aad8d2c6b9238fc1a5524542087c52b860b10cbf952429ffb714bc1136", size = 1197535, upload-time = "2025-02-14T06:02:18.595Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/7c/1069f25521c8f01a1a182f362e5c8e0337907fae91b368b7da9c3e39b810/tiktoken-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b2a21133be05dc116b1d0372af051cd2c6aa1d2188250c9b553f9fa49301b336", size = 1259548, upload-time = "2025-02-14T06:02:20.729Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/07/c67ad1724b8e14e2b4c8cca04b15da158733ac60136879131db05dda7c30/tiktoken-0.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:11a20e67fdf58b0e2dea7b8654a288e481bb4fc0289d3ad21291f8d0849915fb", size = 893895, upload-time = "2025-02-14T06:02:22.67Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/e5/21ff33ecfa2101c1bb0f9b6df750553bd873b7fb532ce2cb276ff40b197f/tiktoken-0.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e88f121c1c22b726649ce67c089b90ddda8b9662545a8aeb03cfef15967ddd03", size = 1065073, upload-time = "2025-02-14T06:02:24.768Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/03/a95e7b4863ee9ceec1c55983e4cc9558bcfd8f4f80e19c4f8a99642f697d/tiktoken-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a6600660f2f72369acb13a57fb3e212434ed38b045fd8cc6cdd74947b4b5d210", size = 1008075, upload-time = "2025-02-14T06:02:26.92Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/10/1305bb02a561595088235a513ec73e50b32e74364fef4de519da69bc8010/tiktoken-0.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95e811743b5dfa74f4b227927ed86cbc57cad4df859cb3b643be797914e41794", size = 1140754, upload-time = "2025-02-14T06:02:28.124Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/40/da42522018ca496432ffd02793c3a72a739ac04c3794a4914570c9bb2925/tiktoken-0.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99376e1370d59bcf6935c933cb9ba64adc29033b7e73f5f7569f3aad86552b22", size = 1196678, upload-time = "2025-02-14T06:02:29.845Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/41/1e59dddaae270ba20187ceb8aa52c75b24ffc09f547233991d5fd822838b/tiktoken-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:badb947c32739fb6ddde173e14885fb3de4d32ab9d8c591cbd013c22b4c31dd2", size = 1259283, upload-time = "2025-02-14T06:02:33.838Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/64/b16003419a1d7728d0d8c0d56a4c24325e7b10a21a9dd1fc0f7115c02f0a/tiktoken-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:5a62d7a25225bafed786a524c1b9f0910a1128f4232615bf3f8257a73aaa3b16", size = 894897, upload-time = "2025-02-14T06:02:36.265Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/11/09d936d37f49f4f494ffe660af44acd2d99eb2429d60a57c71318af214e0/tiktoken-0.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b0e8e05a26eda1249e824156d537015480af7ae222ccb798e5234ae0285dbdb", size = 1064919, upload-time = "2025-02-14T06:02:37.494Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/0e/f38ba35713edb8d4197ae602e80837d574244ced7fb1b6070b31c29816e0/tiktoken-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:27d457f096f87685195eea0165a1807fae87b97b2161fe8c9b1df5bd74ca6f63", size = 1007877, upload-time = "2025-02-14T06:02:39.516Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/82/9197f77421e2a01373e27a79dd36efdd99e6b4115746ecc553318ecafbf0/tiktoken-0.9.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cf8ded49cddf825390e36dd1ad35cd49589e8161fdcb52aa25f0583e90a3e01", size = 1140095, upload-time = "2025-02-14T06:02:41.791Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/bb/4513da71cac187383541facd0291c4572b03ec23c561de5811781bbd988f/tiktoken-0.9.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc156cb314119a8bb9748257a2eaebd5cc0753b6cb491d26694ed42fc7cb3139", size = 1195649, upload-time = "2025-02-14T06:02:43Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/5c/74e4c137530dd8504e97e3a41729b1103a4ac29036cbfd3250b11fd29451/tiktoken-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cd69372e8c9dd761f0ab873112aba55a0e3e506332dd9f7522ca466e817b1b7a", size = 1258465, upload-time = "2025-02-14T06:02:45.046Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/a8/8f499c179ec900783ffe133e9aab10044481679bb9aad78436d239eee716/tiktoken-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:5ea0edb6f83dc56d794723286215918c1cde03712cbbafa0348b33448faf5b95", size = 894669, upload-time = "2025-02-14T06:02:47.341Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test the backward compatibility fix for Pydantic .dict() → .model_dump() migration
|
||||
"""
|
||||
|
||||
class MockPydanticV1:
|
||||
"""Mock Pydantic v1 model that has .dict() but not .model_dump()"""
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def dict(self):
|
||||
return self.data
|
||||
|
||||
def __str__(self):
|
||||
return str(self.data)
|
||||
|
||||
class MockPydanticV2:
|
||||
"""Mock Pydantic v2 model that has both .dict() and .model_dump()"""
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def dict(self):
|
||||
return self.data
|
||||
|
||||
def model_dump(self):
|
||||
return self.data
|
||||
|
||||
def __str__(self):
|
||||
return str(self.data)
|
||||
|
||||
class MockNonPydantic:
|
||||
"""Mock non-Pydantic object"""
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def __str__(self):
|
||||
return str(self.data)
|
||||
|
||||
def test_notebook_backward_compatibility():
|
||||
"""Test the fixed notebook logic with different object types"""
|
||||
|
||||
print("Testing notebook backward compatibility fix...")
|
||||
|
||||
# Test cases
|
||||
test_objects = [
|
||||
("Pydantic v1 mock", MockPydanticV1({"test": "data1"})),
|
||||
("Pydantic v2 mock", MockPydanticV2({"test": "data2"})),
|
||||
("Non-Pydantic object", MockNonPydantic({"test": "data3"})),
|
||||
("String object", "just a string"),
|
||||
("None object", None),
|
||||
]
|
||||
|
||||
for name, result_obj in test_objects:
|
||||
print(f"\nTesting {name}:")
|
||||
|
||||
# This is the fixed logic from the notebook
|
||||
try:
|
||||
result = result_obj.model_dump() if hasattr(result_obj, "model_dump") else str(result_obj)
|
||||
print(f" ✅ Success: {result}")
|
||||
except Exception as e:
|
||||
print(f" ❌ Failed: {e}")
|
||||
return False
|
||||
|
||||
print("\n✅ All backward compatibility tests passed!")
|
||||
return True
|
||||
|
||||
def test_api_files_syntax():
|
||||
"""Test that the API files have valid syntax"""
|
||||
|
||||
print("\nTesting API files syntax...")
|
||||
|
||||
files_to_check = [
|
||||
"examples/python/concepts/reasoning-extraction.py",
|
||||
"examples/python/api/secondary-market-research-api.py"
|
||||
]
|
||||
|
||||
for file_path in files_to_check:
|
||||
try:
|
||||
print(f" Checking {file_path}...")
|
||||
with open(file_path, 'r') as f:
|
||||
code = f.read()
|
||||
|
||||
# Check that .model_dump() is used instead of .dict()
|
||||
if '.dict()' in code and 'result_obj.dict()' in code:
|
||||
print(f" ❌ Found remaining .dict() usage in {file_path}")
|
||||
return False
|
||||
|
||||
# Compile the code to check syntax
|
||||
compile(code, file_path, 'exec')
|
||||
print(f" ✅ {file_path} has valid syntax")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Error checking {file_path}: {e}")
|
||||
return False
|
||||
|
||||
print("✅ All API files have valid syntax!")
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("TESTING BACKWARD COMPATIBILITY FIXES")
|
||||
print("=" * 60)
|
||||
|
||||
success = True
|
||||
success &= test_notebook_backward_compatibility()
|
||||
success &= test_api_files_syntax()
|
||||
|
||||
if success:
|
||||
print("\n🎉 All backward compatibility tests passed!")
|
||||
print("The fixes ensure compatibility with both Pydantic v1 and v2")
|
||||
else:
|
||||
print("\n❌ Some tests failed")
|
||||
exit(1)
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Simple test to check if the fixed files work correctly
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
def test_fixed_files():
|
||||
"""Test the files that had .dict() usage to ensure they work with .model_dump()"""
|
||||
print("Testing fixed files...")
|
||||
|
||||
try:
|
||||
# Test 1: Import and test the reasoning extraction functionality
|
||||
print("Testing reasoning-extraction.py imports...")
|
||||
import json
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Create a dummy ChainOfThought class to test our fix
|
||||
class ChainOfThought(BaseModel):
|
||||
problem: str
|
||||
reasoning_steps: list = []
|
||||
solution: str = ""
|
||||
|
||||
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.model_dump(), f, indent=2) # This was the fix
|
||||
return f"Reasoning chain saved to {filename}"
|
||||
|
||||
# Test the fixed function
|
||||
test_chain = ChainOfThought(
|
||||
problem="Test problem for validation",
|
||||
reasoning_steps=["Step 1", "Step 2"],
|
||||
solution="Test solution"
|
||||
)
|
||||
result = save_reasoning_chain(test_chain)
|
||||
print(f"✅ reasoning-extraction.py fix works: {result}")
|
||||
|
||||
# Test 2: Test the API fix (MarketResearchRequest simulation)
|
||||
print("Testing secondary-market-research-api.py fix...")
|
||||
|
||||
class MarketResearchRequest(BaseModel):
|
||||
company: str
|
||||
geography: str
|
||||
market_segment: str = "general"
|
||||
|
||||
def test_api_serialization(request: MarketResearchRequest):
|
||||
"""Test the fixed API serialization"""
|
||||
from datetime import datetime
|
||||
job_status = {
|
||||
"status": "queued",
|
||||
"progress": 0,
|
||||
"message": "Report generation queued",
|
||||
"created_at": datetime.now().isoformat(),
|
||||
"updated_at": datetime.now().isoformat(),
|
||||
"config": request.model_dump() # This was the fix
|
||||
}
|
||||
return job_status
|
||||
|
||||
test_request = MarketResearchRequest(
|
||||
company="Test Company",
|
||||
geography="Global",
|
||||
market_segment="tech"
|
||||
)
|
||||
api_result = test_api_serialization(test_request)
|
||||
print(f"✅ secondary-market-research-api.py fix works: {api_result['config']}")
|
||||
|
||||
print("\n✅ All Pydantic .dict() → .model_dump() fixes are working correctly!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error testing fixes: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def test_import_praisonaiagents():
|
||||
"""Test basic PraisonAI Agents import"""
|
||||
try:
|
||||
print("Testing PraisonAI Agents import...")
|
||||
from praisonaiagents import Agent
|
||||
print("✅ Successfully imported PraisonAI Agents")
|
||||
|
||||
# Try to create an agent without LLM call
|
||||
agent = Agent(
|
||||
instructions="Test agent for validation",
|
||||
tools=[]
|
||||
)
|
||||
print("✅ Successfully created agent instance")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Error importing or creating agent: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
def test_litellm_deprecation():
|
||||
"""Test for litellm deprecation warnings"""
|
||||
try:
|
||||
# Capture warnings to see if we've reduced them
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
|
||||
# Try to import litellm
|
||||
import litellm
|
||||
print("✅ LiteLLM imported successfully")
|
||||
|
||||
# Check for any deprecation warnings caught
|
||||
pydantic_warnings = [warning for warning in w if 'pydantic' in str(warning.message).lower() and 'dict' in str(warning.message).lower()]
|
||||
|
||||
if pydantic_warnings:
|
||||
print(f"⚠️ Found {len(pydantic_warnings)} Pydantic dict() deprecation warnings:")
|
||||
for warning in pydantic_warnings:
|
||||
print(f" - {warning.message}")
|
||||
else:
|
||||
print("✅ No Pydantic dict() deprecation warnings detected during import")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error testing litellm: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("TESTING DEPRECATION WARNING FIXES")
|
||||
print("=" * 60)
|
||||
|
||||
success = True
|
||||
|
||||
# Test our fixed files
|
||||
success &= test_fixed_files()
|
||||
print()
|
||||
|
||||
# Test basic imports
|
||||
success &= test_import_praisonaiagents()
|
||||
print()
|
||||
|
||||
# Test for remaining warnings
|
||||
success &= test_litellm_deprecation()
|
||||
print()
|
||||
|
||||
if success:
|
||||
print("✅ All tests passed! Deprecation warnings should be resolved.")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("❌ Some tests failed. Please check the output above.")
|
||||
sys.exit(1)
|
||||
Reference in new issue
Block a user