mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-07 17:33:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2d181dd74 | ||
|
|
7411fdbb52 | ||
|
|
e7a8ce8eb7 | ||
|
|
61fb094306 | ||
|
|
018e8c78ab | ||
|
|
f0f0f653fe | ||
|
|
98a4ff8450 | ||
|
|
d6333aaf33 | ||
|
|
8005094267 | ||
|
|
08b21dabe3 | ||
|
|
8c70d840df | ||
|
|
d8e944c1d3 | ||
|
|
79b2b88f72 | ||
|
|
f5dfbd5670 | ||
|
|
aa6aa5933d | ||
|
|
ff3a4f2016 | ||
|
|
0d5444fc23 | ||
|
|
d7d5dab17b | ||
|
|
05678394e6 | ||
|
|
54cddc09b4 | ||
|
|
9cbab01785 | ||
|
|
de9d4bd3c6 | ||
|
|
aba2265e5e | ||
|
|
ebb9b24bff | ||
|
|
759ef2c655 | ||
|
|
cb4318f6e8 | ||
|
|
d9bb869d5e | ||
|
|
34b6aeb76b | ||
|
|
078b7801e1 | ||
|
|
a970e849b4 | ||
|
|
8e68f4e71c | ||
|
|
308758cdc2 | ||
|
|
f8fa61b082 | ||
|
|
955d236924 | ||
|
|
d9d63c3a13 | ||
|
|
5bee6eb470 | ||
|
|
7cb1676b7c | ||
|
|
e2e9c3f9ee | ||
|
|
cbe8beeca6 | ||
|
|
f7b66a52b7 | ||
|
|
6dbf194312 | ||
|
|
335e8d7e47 | ||
|
|
d65840e092 | ||
|
|
5a13571fdd | ||
|
|
e3b48c2526 | ||
|
|
8d32238b4c | ||
|
|
c17b1298bb | ||
|
|
ec6c150315 | ||
|
|
3d26cedd5d | ||
|
|
8c735a60b2 | ||
|
|
2f5f2f1c13 | ||
|
|
0253073c68 | ||
|
|
7f0e334e8c | ||
|
|
cacf1097ef | ||
|
|
09f01919d2 | ||
|
|
92397615f8 | ||
|
|
4b21943a53 | ||
|
|
af56a753bd | ||
|
|
15c2559a3c | ||
|
|
3215bdc0a6 | ||
|
|
0ff0d83744 | ||
|
|
8f956f91dd | ||
|
|
954f6ac33d | ||
|
|
264d11d8d9 | ||
|
|
88da2bdd7b | ||
|
|
b84e6c2460 | ||
|
|
0434b23ada | ||
|
|
a9951e0694 |
No files matched your search
+3
-1
@@ -80,4 +80,6 @@ CopilotKit*
|
||||
issue_details.json
|
||||
|
||||
# MCP Registry tokens
|
||||
.mcpregistry_*
|
||||
.mcpregistry_*
|
||||
|
||||
*.log
|
||||
@@ -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.3.56" \
|
||||
"praisonai>=2.6.2" \
|
||||
"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.3.56" \
|
||||
"praisonai>=2.6.2" \
|
||||
"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.3.56" \
|
||||
"praisonai>=2.6.2" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
Async Runs Examples
|
||||
===================
|
||||
|
||||
This directory contains examples for the PraisonAI Async Jobs API.
|
||||
|
||||
Examples:
|
||||
---------
|
||||
1. sdk_submit_poll_result.py - Python SDK example for submit/poll/result
|
||||
2. cli_submit_poll_result.sh - Bash/curl example for submit/poll/result
|
||||
3. idempotency.sh - Demonstrates idempotency key usage
|
||||
4. cancel.sh - Demonstrates job cancellation
|
||||
5. sse_stream.sh - Demonstrates SSE streaming
|
||||
|
||||
Prerequisites:
|
||||
--------------
|
||||
1. Set OPENAI_API_KEY environment variable
|
||||
2. Start the jobs server:
|
||||
|
||||
cd /path/to/praisonai-package/src/praisonai
|
||||
python -m uvicorn praisonai.jobs.server:create_app --port 8005 --factory
|
||||
|
||||
3. Run examples:
|
||||
|
||||
python sdk_submit_poll_result.py
|
||||
bash cli_submit_poll_result.sh
|
||||
bash idempotency.sh
|
||||
bash cancel.sh
|
||||
bash sse_stream.sh
|
||||
|
||||
Environment Variables:
|
||||
----------------------
|
||||
- OPENAI_API_KEY: Required for agent execution
|
||||
- PRAISONAI_BASE_URL: API server URL (default: http://127.0.0.1:8005)
|
||||
"""
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# CLI Example: Cancel a Running Job
|
||||
#
|
||||
# This example demonstrates how to cancel a running job.
|
||||
#
|
||||
# Requirements:
|
||||
# - Jobs server running on http://127.0.0.1:8005
|
||||
#
|
||||
# Usage:
|
||||
# bash cancel.sh
|
||||
|
||||
set -e
|
||||
|
||||
API_URL="${PRAISONAI_BASE_URL:-http://127.0.0.1:8005}"
|
||||
|
||||
echo "============================================================"
|
||||
echo "PraisonAI Job Cancellation Example"
|
||||
echo "============================================================"
|
||||
|
||||
# Submit a long-running job
|
||||
echo ""
|
||||
echo "1. Submitting a job..."
|
||||
RESPONSE=$(curl -s -X POST "$API_URL/api/v1/runs" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"prompt": "Write a detailed essay about the history of computing."}')
|
||||
|
||||
JOB_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['job_id'])")
|
||||
echo " Job ID: $JOB_ID"
|
||||
|
||||
# Wait briefly
|
||||
echo ""
|
||||
echo "2. Waiting 1 second..."
|
||||
sleep 1
|
||||
|
||||
# Cancel the job
|
||||
echo ""
|
||||
echo "3. Cancelling job..."
|
||||
CANCEL_RESPONSE=$(curl -s -X POST "$API_URL/api/v1/runs/$JOB_ID/cancel")
|
||||
STATUS=$(echo "$CANCEL_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
|
||||
echo " Status after cancel: $STATUS"
|
||||
|
||||
# Verify cancellation
|
||||
echo ""
|
||||
echo "4. Verification:"
|
||||
if [ "$STATUS" = "cancelled" ]; then
|
||||
echo " ✓ SUCCESS: Job was cancelled"
|
||||
else
|
||||
echo " ℹ Job status: $STATUS (may have completed before cancel)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo "Cancellation example completed!"
|
||||
echo "============================================================"
|
||||
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
# CLI Example: Submit, Poll, and Get Result for Async Jobs
|
||||
#
|
||||
# This example demonstrates how to use the PraisonAI CLI to:
|
||||
# 1. Submit an async job
|
||||
# 2. Check job status
|
||||
# 3. Get the result
|
||||
#
|
||||
# Requirements:
|
||||
# - OPENAI_API_KEY environment variable set
|
||||
# - Jobs server running on http://127.0.0.1:8005
|
||||
#
|
||||
# Usage:
|
||||
# bash cli_submit_poll_result.sh
|
||||
|
||||
set -e
|
||||
|
||||
API_URL="${PRAISONAI_BASE_URL:-http://127.0.0.1:8005}"
|
||||
|
||||
echo "============================================================"
|
||||
echo "PraisonAI Async Jobs CLI Example"
|
||||
echo "============================================================"
|
||||
|
||||
# Check if server is running
|
||||
echo ""
|
||||
echo "Checking server health..."
|
||||
if ! curl -s "$API_URL/health" > /dev/null 2>&1; then
|
||||
echo "✗ Server not available at $API_URL"
|
||||
echo " Start the server with: python -m uvicorn praisonai.jobs.server:create_app --port 8005 --factory"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Server is healthy"
|
||||
|
||||
# 1. Submit a job
|
||||
echo ""
|
||||
echo "1. Submitting job..."
|
||||
RESPONSE=$(curl -s -X POST "$API_URL/api/v1/runs" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"prompt": "What is 2+2? Answer with just the number."}')
|
||||
|
||||
JOB_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['job_id'])")
|
||||
echo " Job ID: $JOB_ID"
|
||||
|
||||
# 2. Poll for status
|
||||
echo ""
|
||||
echo "2. Polling for status..."
|
||||
while true; do
|
||||
STATUS_RESPONSE=$(curl -s "$API_URL/api/v1/runs/$JOB_ID")
|
||||
STATUS=$(echo "$STATUS_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
|
||||
PROGRESS=$(echo "$STATUS_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['progress']['percentage'])")
|
||||
|
||||
echo " Status: $STATUS | Progress: ${PROGRESS}%"
|
||||
|
||||
if [ "$STATUS" = "succeeded" ] || [ "$STATUS" = "failed" ] || [ "$STATUS" = "cancelled" ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 3. Get result
|
||||
echo ""
|
||||
echo "3. Getting result..."
|
||||
if [ "$STATUS" = "succeeded" ]; then
|
||||
RESULT=$(curl -s "$API_URL/api/v1/runs/$JOB_ID/result")
|
||||
echo " Result: $(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['result'])")"
|
||||
echo " Duration: $(echo "$RESULT" | python3 -c "import sys,json; print(f\"{json.load(sys.stdin)['duration_seconds']:.2f}s\")")"
|
||||
else
|
||||
echo " Job did not succeed: $STATUS"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo "Example completed!"
|
||||
echo "============================================================"
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# CLI Example: Idempotency Key Usage
|
||||
#
|
||||
# This example demonstrates how idempotency keys prevent duplicate job submissions.
|
||||
# Submitting the same request with the same idempotency key returns the existing job.
|
||||
#
|
||||
# Requirements:
|
||||
# - Jobs server running on http://127.0.0.1:8005
|
||||
#
|
||||
# Usage:
|
||||
# bash idempotency.sh
|
||||
|
||||
set -e
|
||||
|
||||
API_URL="${PRAISONAI_BASE_URL:-http://127.0.0.1:8005}"
|
||||
IDEM_KEY="example-idem-key-$(date +%s)"
|
||||
|
||||
echo "============================================================"
|
||||
echo "PraisonAI Idempotency Key Example"
|
||||
echo "============================================================"
|
||||
|
||||
# First submission
|
||||
echo ""
|
||||
echo "1. First submission with Idempotency-Key: $IDEM_KEY"
|
||||
RESPONSE1=$(curl -s -X POST "$API_URL/api/v1/runs" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Idempotency-Key: $IDEM_KEY" \
|
||||
-d '{"prompt": "What is 1+1?"}')
|
||||
|
||||
JOB_ID1=$(echo "$RESPONSE1" | python3 -c "import sys,json; print(json.load(sys.stdin)['job_id'])")
|
||||
echo " Job ID: $JOB_ID1"
|
||||
|
||||
# Second submission with same key
|
||||
echo ""
|
||||
echo "2. Second submission with SAME Idempotency-Key: $IDEM_KEY"
|
||||
RESPONSE2=$(curl -s -X POST "$API_URL/api/v1/runs" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Idempotency-Key: $IDEM_KEY" \
|
||||
-d '{"prompt": "Different prompt but same key"}')
|
||||
|
||||
JOB_ID2=$(echo "$RESPONSE2" | python3 -c "import sys,json; print(json.load(sys.stdin)['job_id'])")
|
||||
echo " Job ID: $JOB_ID2"
|
||||
|
||||
# Verify same job ID
|
||||
echo ""
|
||||
echo "3. Verification:"
|
||||
if [ "$JOB_ID1" = "$JOB_ID2" ]; then
|
||||
echo " ✓ SUCCESS: Same job ID returned (no duplicate created)"
|
||||
else
|
||||
echo " ✗ FAILURE: Different job IDs returned"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo "Idempotency example completed!"
|
||||
echo "============================================================"
|
||||
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
SDK Example: Submit, Poll, and Get Result for Async Jobs
|
||||
|
||||
This example demonstrates how to use the PraisonAI Jobs SDK to:
|
||||
1. Submit an async job
|
||||
2. Poll for status
|
||||
3. Get the result
|
||||
|
||||
Requirements:
|
||||
- OPENAI_API_KEY environment variable set
|
||||
- Jobs server running on http://127.0.0.1:8005
|
||||
|
||||
Usage:
|
||||
python sdk_submit_poll_result.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import httpx
|
||||
|
||||
# Configuration
|
||||
API_URL = os.getenv("PRAISONAI_BASE_URL", "http://127.0.0.1:8005")
|
||||
POLL_INTERVAL = 2 # seconds
|
||||
|
||||
|
||||
def submit_job(prompt: str, idempotency_key: str = None) -> dict:
|
||||
"""Submit a job and return the response."""
|
||||
headers = {}
|
||||
if idempotency_key:
|
||||
headers["Idempotency-Key"] = idempotency_key
|
||||
|
||||
with httpx.Client(timeout=30.0) as client:
|
||||
response = client.post(
|
||||
f"{API_URL}/api/v1/runs",
|
||||
json={"prompt": prompt},
|
||||
headers=headers if headers else None
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
|
||||
def get_status(job_id: str) -> dict:
|
||||
"""Get job status."""
|
||||
with httpx.Client(timeout=30.0) as client:
|
||||
response = client.get(f"{API_URL}/api/v1/runs/{job_id}")
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
|
||||
def get_result(job_id: str) -> dict:
|
||||
"""Get job result."""
|
||||
with httpx.Client(timeout=30.0) as client:
|
||||
response = client.get(f"{API_URL}/api/v1/runs/{job_id}/result")
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
|
||||
def wait_for_completion(job_id: str, max_wait: int = 120) -> dict:
|
||||
"""Poll until job completes."""
|
||||
start = time.time()
|
||||
while time.time() - start < max_wait:
|
||||
status = get_status(job_id)
|
||||
print(f" Status: {status['status']} | Progress: {status['progress']['percentage']:.0f}%")
|
||||
|
||||
if status["status"] in ("succeeded", "failed", "cancelled"):
|
||||
return status
|
||||
|
||||
# Honor retry_after if present
|
||||
wait_time = status.get("retry_after") or POLL_INTERVAL
|
||||
time.sleep(wait_time)
|
||||
|
||||
raise TimeoutError(f"Job {job_id} did not complete within {max_wait}s")
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("PraisonAI Async Jobs SDK Example")
|
||||
print("=" * 60)
|
||||
|
||||
# Check if server is running
|
||||
try:
|
||||
with httpx.Client(timeout=5.0) as client:
|
||||
health = client.get(f"{API_URL}/health")
|
||||
health.raise_for_status()
|
||||
print(f"✓ Server healthy: {health.json()['status']}")
|
||||
except Exception as e:
|
||||
print(f"✗ Server not available at {API_URL}: {e}")
|
||||
print(" Start the server with: python -m uvicorn praisonai.jobs.server:create_app --port 8005 --factory")
|
||||
return
|
||||
|
||||
# 1. Submit a job
|
||||
print("\n1. Submitting job...")
|
||||
prompt = "What is the capital of France? Answer in one word."
|
||||
result = submit_job(prompt)
|
||||
job_id = result["job_id"]
|
||||
print(f" Job ID: {job_id}")
|
||||
print(f" Status: {result['status']}")
|
||||
print(f" Poll URL: {result['poll_url']}")
|
||||
|
||||
# 2. Wait for completion
|
||||
print("\n2. Waiting for completion...")
|
||||
final_status = wait_for_completion(job_id)
|
||||
print(f" Final status: {final_status['status']}")
|
||||
|
||||
# 3. Get result
|
||||
if final_status["status"] == "succeeded":
|
||||
print("\n3. Getting result...")
|
||||
result = get_result(job_id)
|
||||
print(f" Result: {result['result']}")
|
||||
print(f" Duration: {result['duration_seconds']:.2f}s")
|
||||
else:
|
||||
print(f"\n3. Job did not succeed: {final_status.get('error', 'Unknown error')}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Example completed successfully!")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/bin/bash
|
||||
# CLI Example: SSE Streaming
|
||||
#
|
||||
# This example demonstrates how to stream job progress via Server-Sent Events.
|
||||
#
|
||||
# Requirements:
|
||||
# - Jobs server running on http://127.0.0.1:8005
|
||||
#
|
||||
# Usage:
|
||||
# bash sse_stream.sh
|
||||
|
||||
set -e
|
||||
|
||||
API_URL="${PRAISONAI_BASE_URL:-http://127.0.0.1:8005}"
|
||||
|
||||
echo "============================================================"
|
||||
echo "PraisonAI SSE Streaming Example"
|
||||
echo "============================================================"
|
||||
|
||||
# Submit a job
|
||||
echo ""
|
||||
echo "1. Submitting job..."
|
||||
RESPONSE=$(curl -s -X POST "$API_URL/api/v1/runs" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"prompt": "Count from 1 to 5."}')
|
||||
|
||||
JOB_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['job_id'])")
|
||||
echo " Job ID: $JOB_ID"
|
||||
|
||||
# Stream progress
|
||||
echo ""
|
||||
echo "2. Streaming progress (Ctrl+C to stop)..."
|
||||
echo " Connecting to: $API_URL/api/v1/runs/$JOB_ID/stream"
|
||||
echo ""
|
||||
|
||||
# Use curl to stream SSE events (timeout after 60s)
|
||||
curl -s -N --max-time 60 "$API_URL/api/v1/runs/$JOB_ID/stream" | while read -r line; do
|
||||
if [[ "$line" == data:* ]]; then
|
||||
data="${line#data: }"
|
||||
if [ "$data" = "[DONE]" ]; then
|
||||
echo " Stream completed"
|
||||
break
|
||||
fi
|
||||
echo " Event: $data"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "============================================================"
|
||||
echo "Streaming example completed!"
|
||||
echo "============================================================"
|
||||
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic Background Tasks Example for PraisonAI Agents.
|
||||
|
||||
This example demonstrates how to use the background task system to:
|
||||
1. Run tasks asynchronously
|
||||
2. Track task progress
|
||||
3. Cancel running tasks
|
||||
4. Handle task completion
|
||||
|
||||
Usage:
|
||||
python basic_background.py
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
from praisonaiagents.background import BackgroundRunner, BackgroundConfig, TaskStatus
|
||||
|
||||
|
||||
async def main():
|
||||
print("=" * 60)
|
||||
print("Background Tasks Demo")
|
||||
print("=" * 60)
|
||||
|
||||
# Create a background runner with config
|
||||
config = BackgroundConfig(max_concurrent_tasks=3)
|
||||
runner = BackgroundRunner(config=config)
|
||||
|
||||
# Define some example tasks
|
||||
def slow_task(duration: float, name: str) -> str:
|
||||
"""A slow task that simulates work."""
|
||||
print(f" 🔄 Task '{name}' starting (will take {duration}s)")
|
||||
time.sleep(duration)
|
||||
return f"Task '{name}' completed after {duration}s"
|
||||
|
||||
async def async_task(duration: float, name: str) -> str:
|
||||
"""An async task that simulates work."""
|
||||
print(f" 🔄 Async task '{name}' starting (will take {duration}s)")
|
||||
await asyncio.sleep(duration)
|
||||
return f"Async task '{name}' completed after {duration}s"
|
||||
|
||||
# Submit tasks
|
||||
print("\n--- Submitting Tasks ---")
|
||||
|
||||
task1 = await runner.submit(slow_task, args=(1.0, "quick-job"), name="task1")
|
||||
print(f"✅ Submitted task 1: {task1.id[:8]}")
|
||||
|
||||
task2 = await runner.submit(slow_task, args=(2.0, "medium-job"), name="task2")
|
||||
print(f"✅ Submitted task 2: {task2.id[:8]}")
|
||||
|
||||
task3 = await runner.submit(async_task, args=(1.5, "async-job"), name="task3")
|
||||
print(f"✅ Submitted async task 3: {task3.id[:8]}")
|
||||
|
||||
# List all tasks
|
||||
print("\n--- Task Status ---")
|
||||
for task in runner.tasks:
|
||||
print(f" [{task.id[:8]}] {task.status.value}")
|
||||
|
||||
# Wait for task 1 to complete
|
||||
print("\n--- Waiting for Task 1 ---")
|
||||
await task1.wait(timeout=5.0)
|
||||
print(f"✅ Task 1 result: {task1.result}")
|
||||
|
||||
# Check status of all tasks
|
||||
print("\n--- Updated Task Status ---")
|
||||
for task in [task1, task2, task3]:
|
||||
status = "✅" if task.status == TaskStatus.COMPLETED else "🔄"
|
||||
print(f" {status} [{task.id[:8]}] {task.status.value}")
|
||||
|
||||
# Wait for all remaining tasks
|
||||
print("\n--- Waiting for All Tasks ---")
|
||||
await task2.wait(timeout=10.0)
|
||||
await task3.wait(timeout=10.0)
|
||||
|
||||
# Final status
|
||||
print("\n--- Final Results ---")
|
||||
for task in [task1, task2, task3]:
|
||||
if task.result:
|
||||
print(f" ✅ {task.result}")
|
||||
|
||||
# Cleanup
|
||||
runner.clear_completed()
|
||||
print("\n✅ Cleared completed tasks")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Demo Complete!")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic Checkpoints Example for PraisonAI Agents.
|
||||
|
||||
This example demonstrates how to use the shadow git checkpointing system to:
|
||||
1. Save checkpoints before making changes
|
||||
2. List available checkpoints
|
||||
3. View diffs between checkpoints
|
||||
4. Restore to a previous checkpoint
|
||||
|
||||
Usage:
|
||||
python basic_checkpoints.py
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
from praisonaiagents.checkpoints import CheckpointService
|
||||
|
||||
|
||||
async def main():
|
||||
# Create a temporary workspace for demonstration
|
||||
with tempfile.TemporaryDirectory() as workspace:
|
||||
print("=" * 60)
|
||||
print("Shadow Git Checkpointing Demo")
|
||||
print("=" * 60)
|
||||
print(f"\nWorkspace: {workspace}")
|
||||
|
||||
# Create some initial files
|
||||
test_file = Path(workspace) / "example.py"
|
||||
test_file.write_text("# Initial content\nprint('Hello, World!')\n")
|
||||
print(f"\n✅ Created initial file: {test_file.name}")
|
||||
|
||||
# Initialize the checkpoint service
|
||||
service = CheckpointService(workspace_dir=workspace)
|
||||
|
||||
try:
|
||||
# Initialize the shadow git repository
|
||||
print("\n--- Initializing Checkpoint Service ---")
|
||||
await service.initialize()
|
||||
print("✅ Shadow git repository initialized")
|
||||
|
||||
# Save first checkpoint
|
||||
print("\n--- Saving Checkpoint 1: Initial State ---")
|
||||
result1 = await service.save("Initial state")
|
||||
print(f"✅ Checkpoint saved: {result1.checkpoint.id[:8]}")
|
||||
print(f" Message: {result1.checkpoint.message}")
|
||||
|
||||
# Make some changes
|
||||
print("\n--- Making Changes ---")
|
||||
test_file.write_text("# Modified content\nprint('Hello, PraisonAI!')\nprint('Checkpoints are awesome!')\n")
|
||||
print("✅ Modified example.py")
|
||||
|
||||
# Create a new file
|
||||
new_file = Path(workspace) / "utils.py"
|
||||
new_file.write_text("def helper():\n return 'I help!'\n")
|
||||
print("✅ Created utils.py")
|
||||
|
||||
# Save second checkpoint
|
||||
print("\n--- Saving Checkpoint 2: After Changes ---")
|
||||
result2 = await service.save("Added features")
|
||||
print(f"✅ Checkpoint saved: {result2.checkpoint.id[:8]}")
|
||||
|
||||
# List all checkpoints
|
||||
print("\n--- Listing All Checkpoints ---")
|
||||
checkpoints = await service.list_checkpoints()
|
||||
for i, cp in enumerate(checkpoints, 1):
|
||||
print(f" {i}. [{cp.id[:8]}] {cp.message} ({cp.timestamp})")
|
||||
|
||||
# Show diff
|
||||
print("\n--- Current Diff (uncommitted changes) ---")
|
||||
diff = await service.diff()
|
||||
if diff.files:
|
||||
for f in diff.files:
|
||||
print(f" {f.status}: {f.path}")
|
||||
else:
|
||||
print(" No uncommitted changes")
|
||||
|
||||
# Make more changes to show diff
|
||||
test_file.write_text("# Even more changes\nprint('This will be reverted')\n")
|
||||
print("\n✅ Made more changes to example.py")
|
||||
|
||||
diff = await service.diff()
|
||||
print("\n--- New Diff ---")
|
||||
if diff.files:
|
||||
for f in diff.files:
|
||||
print(f" {f.status}: {f.path}")
|
||||
|
||||
# Restore to checkpoint 2
|
||||
print(f"\n--- Restoring to Checkpoint: {result2.checkpoint.id[:8]} ---")
|
||||
await service.restore(result2.checkpoint.id)
|
||||
print("✅ Restored successfully!")
|
||||
|
||||
# Verify restoration
|
||||
content = test_file.read_text()
|
||||
print(f"\n--- Verified Content After Restore ---")
|
||||
print(content)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error: {e}")
|
||||
raise
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Demo Complete!")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,93 @@
|
||||
# Persistence CLI Commands
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
# Check database connectivity
|
||||
praisonai persistence doctor \
|
||||
--conversation-url postgresql://localhost:5432/praisonai \
|
||||
--state-url redis://localhost:6379
|
||||
|
||||
# Run agent with persistence
|
||||
praisonai persistence run \
|
||||
--conversation-url postgresql://localhost:5432/praisonai \
|
||||
--session-id my-session
|
||||
|
||||
# Resume a session
|
||||
praisonai persistence resume \
|
||||
--conversation-url postgresql://localhost:5432/praisonai \
|
||||
--session-id my-session
|
||||
|
||||
# Export session to file
|
||||
praisonai persistence export \
|
||||
--conversation-url postgresql://localhost:5432/praisonai \
|
||||
--session-id my-session \
|
||||
--output session_backup.jsonl
|
||||
|
||||
# Import session from file
|
||||
praisonai persistence import \
|
||||
--conversation-url postgresql://localhost:5432/praisonai \
|
||||
--file session_backup.jsonl
|
||||
|
||||
# Check schema status
|
||||
praisonai persistence status \
|
||||
--conversation-url postgresql://localhost:5432/praisonai \
|
||||
--state-url redis://localhost:6379
|
||||
|
||||
# Apply migrations
|
||||
praisonai persistence migrate \
|
||||
--conversation-url postgresql://localhost:5432/praisonai \
|
||||
--state-url redis://localhost:6379
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Instead of CLI flags, you can use environment variables:
|
||||
|
||||
```bash
|
||||
export PRAISON_CONVERSATION_URL=postgresql://localhost:5432/praisonai
|
||||
export PRAISON_STATE_URL=redis://localhost:6379
|
||||
export PRAISON_KNOWLEDGE_URL=http://localhost:6333
|
||||
|
||||
# Then run without URL flags
|
||||
praisonai persistence doctor
|
||||
praisonai persistence status
|
||||
```
|
||||
|
||||
## Docker Setup
|
||||
|
||||
```bash
|
||||
# Start all services
|
||||
docker run -d --name praison-postgres \
|
||||
-e POSTGRES_PASSWORD=praison123 \
|
||||
-e POSTGRES_DB=praisonai \
|
||||
-p 5432:5432 postgres:16
|
||||
|
||||
docker run -d --name praison-redis \
|
||||
-p 6379:6379 redis:7
|
||||
|
||||
docker run -d --name praison-qdrant \
|
||||
-p 6333:6333 -p 6334:6334 qdrant/qdrant
|
||||
|
||||
# Verify
|
||||
docker ps
|
||||
```
|
||||
|
||||
## Example Workflow
|
||||
|
||||
```bash
|
||||
# 1. Start services
|
||||
docker-compose up -d
|
||||
|
||||
# 2. Check connectivity
|
||||
praisonai persistence doctor
|
||||
|
||||
# 3. Run agent
|
||||
praisonai persistence run --session-id demo-session
|
||||
|
||||
# 4. Export for backup
|
||||
praisonai persistence export --session-id demo-session --output backup.jsonl
|
||||
|
||||
# 5. Import to another environment
|
||||
praisonai persistence import --file backup.jsonl
|
||||
```
|
||||
@@ -0,0 +1,124 @@
|
||||
# PraisonAI Persistence CLI - End-to-End Guide
|
||||
|
||||
This guide demonstrates the CLI commands for database persistence.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
```bash
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
# Start Docker containers
|
||||
docker run -d --name praison-postgres -p 5432:5432 \
|
||||
-e POSTGRES_PASSWORD=praison123 \
|
||||
-e POSTGRES_DB=praisonai \
|
||||
postgres:16
|
||||
|
||||
docker run -d --name praison-qdrant -p 6333:6333 qdrant/qdrant
|
||||
docker run -d --name praison-redis -p 6379:6379 redis:7
|
||||
```
|
||||
|
||||
## 1. Doctor Command - Validate Connectivity
|
||||
|
||||
```bash
|
||||
# Check all stores
|
||||
praisonai persistence doctor \
|
||||
--conversation-url "postgresql://postgres:praison123@localhost:5432/praisonai" \
|
||||
--knowledge-url "http://localhost:6333" \
|
||||
--state-url "redis://localhost:6379"
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
```
|
||||
==================================================
|
||||
PraisonAI Persistence Doctor
|
||||
==================================================
|
||||
|
||||
[Conversation Store] Testing: postgresql://postgres:****@localhost:5432/praisonai
|
||||
✅ Connected (postgres)
|
||||
|
||||
[Knowledge Store] Testing: http://localhost:6333
|
||||
✅ Connected (qdrant)
|
||||
|
||||
[State Store] Testing: redis://localhost:6379
|
||||
✅ Connected (redis)
|
||||
|
||||
==================================================
|
||||
Results: 3/3 stores connected successfully
|
||||
==================================================
|
||||
```
|
||||
|
||||
## 2. Run Command - Execute Agent with Persistence
|
||||
|
||||
```bash
|
||||
# Run agent with persistence (dry-run first)
|
||||
praisonai persistence run \
|
||||
--session-id "cli-demo-001" \
|
||||
--conversation-url "postgresql://postgres:praison123@localhost:5432/praisonai" \
|
||||
--dry-run \
|
||||
"Hello, my name is Bob"
|
||||
|
||||
# Actually run it
|
||||
praisonai persistence run \
|
||||
--session-id "cli-demo-001" \
|
||||
--conversation-url "postgresql://postgres:praison123@localhost:5432/praisonai" \
|
||||
"Hello, my name is Bob"
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
```
|
||||
[Session: cli-demo-001]
|
||||
Agent: Hello Bob! Nice to meet you. How can I help you today?
|
||||
```
|
||||
|
||||
## 3. Resume Command - Continue a Session
|
||||
|
||||
```bash
|
||||
# Show history
|
||||
praisonai persistence resume \
|
||||
--session-id "cli-demo-001" \
|
||||
--conversation-url "postgresql://postgres:praison123@localhost:5432/praisonai" \
|
||||
--show-history
|
||||
|
||||
# Continue conversation
|
||||
praisonai persistence resume \
|
||||
--session-id "cli-demo-001" \
|
||||
--conversation-url "postgresql://postgres:praison123@localhost:5432/praisonai" \
|
||||
--continue "What's my name?"
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
```
|
||||
[Session: cli-demo-001]
|
||||
Messages in history: 2
|
||||
|
||||
--- Conversation History ---
|
||||
[USER] Hello, my name is Bob
|
||||
[ASSISTANT] Hello Bob! Nice to meet you...
|
||||
--- End History ---
|
||||
|
||||
Agent: Your name is Bob!
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Instead of passing URLs on command line, use environment variables:
|
||||
|
||||
```bash
|
||||
export PRAISON_CONVERSATION_URL="postgresql://postgres:praison123@localhost:5432/praisonai"
|
||||
export PRAISON_KNOWLEDGE_URL="http://localhost:6333"
|
||||
export PRAISON_STATE_URL="redis://localhost:6379"
|
||||
export OPENAI_API_KEY="your-key"
|
||||
|
||||
# Now commands are simpler
|
||||
praisonai persistence doctor --all
|
||||
praisonai persistence run --session-id "my-session" "Hello!"
|
||||
```
|
||||
|
||||
## Full CLI Reference
|
||||
|
||||
```
|
||||
praisonai persistence --help
|
||||
praisonai persistence doctor --help
|
||||
praisonai persistence run --help
|
||||
praisonai persistence resume --help
|
||||
```
|
||||
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic Context Compaction Example for PraisonAI Agents.
|
||||
|
||||
This example demonstrates how to use context compaction to:
|
||||
1. Manage conversation context length
|
||||
2. Use different compaction strategies
|
||||
3. Track compaction results
|
||||
4. Preserve important messages
|
||||
|
||||
Usage:
|
||||
python basic_compaction.py
|
||||
"""
|
||||
|
||||
from praisonaiagents.compaction import (
|
||||
ContextCompactor, CompactionConfig, CompactionStrategy, CompactionResult
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("Context Compaction Demo")
|
||||
print("=" * 60)
|
||||
|
||||
# ==========================================================================
|
||||
# Sample Messages
|
||||
# ==========================================================================
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a helpful AI assistant."},
|
||||
{"role": "user", "content": "Hello! Can you help me with Python?"},
|
||||
{"role": "assistant", "content": "Of course! I'd be happy to help you with Python. What would you like to know?"},
|
||||
{"role": "user", "content": "How do I read a file in Python?"},
|
||||
{"role": "assistant", "content": "To read a file in Python, you can use the built-in open() function. Here's an example:\n\nwith open('filename.txt', 'r') as f:\n content = f.read()\n\nThis opens the file, reads its content, and automatically closes it."},
|
||||
{"role": "user", "content": "What about writing to a file?"},
|
||||
{"role": "assistant", "content": "To write to a file, use the 'w' mode:\n\nwith open('filename.txt', 'w') as f:\n f.write('Hello, World!')\n\nUse 'a' mode to append instead of overwriting."},
|
||||
{"role": "user", "content": "Can you explain list comprehensions?"},
|
||||
{"role": "assistant", "content": "List comprehensions are a concise way to create lists. Instead of:\n\nresult = []\nfor x in range(10):\n result.append(x * 2)\n\nYou can write:\n\nresult = [x * 2 for x in range(10)]"},
|
||||
]
|
||||
|
||||
print(f"\n--- Original Messages ---")
|
||||
print(f" Message count: {len(messages)}")
|
||||
|
||||
# ==========================================================================
|
||||
# Basic Compaction
|
||||
# ==========================================================================
|
||||
print("\n--- Basic Compaction (Truncate Strategy) ---")
|
||||
|
||||
compactor = ContextCompactor(
|
||||
max_tokens=50, # Low limit to trigger compaction
|
||||
strategy=CompactionStrategy.TRUNCATE,
|
||||
preserve_system=True,
|
||||
preserve_recent=2
|
||||
)
|
||||
|
||||
# Check stats before
|
||||
stats = compactor.get_stats(messages)
|
||||
print(f" Total tokens: {stats['total_tokens']}")
|
||||
print(f" Max tokens: {stats['max_tokens']}")
|
||||
print(f" Needs compaction: {stats['needs_compaction']}")
|
||||
|
||||
# Compact
|
||||
compacted, result = compactor.compact(messages)
|
||||
|
||||
print(f"\n After compaction:")
|
||||
print(f" Messages: {len(messages)} -> {len(compacted)}")
|
||||
print(f" Tokens: {result.original_tokens} -> {result.compacted_tokens}")
|
||||
print(f" Saved: {result.tokens_saved} tokens")
|
||||
print(f" Compression: {result.compression_ratio:.1%}")
|
||||
|
||||
# ==========================================================================
|
||||
# Sliding Window Strategy
|
||||
# ==========================================================================
|
||||
print("\n--- Sliding Window Strategy ---")
|
||||
|
||||
compactor = ContextCompactor(
|
||||
max_tokens=50,
|
||||
strategy=CompactionStrategy.SLIDING,
|
||||
preserve_system=True,
|
||||
preserve_recent=3
|
||||
)
|
||||
|
||||
compacted, result = compactor.compact(messages)
|
||||
|
||||
print(f" Messages kept: {result.messages_kept}")
|
||||
print(f" Messages removed: {result.messages_removed}")
|
||||
print(f" Strategy: {result.strategy_used.value}")
|
||||
|
||||
# ==========================================================================
|
||||
# Summarize Strategy
|
||||
# ==========================================================================
|
||||
print("\n--- Summarize Strategy ---")
|
||||
|
||||
compactor = ContextCompactor(
|
||||
max_tokens=50,
|
||||
strategy=CompactionStrategy.SUMMARIZE,
|
||||
preserve_system=True,
|
||||
preserve_recent=2
|
||||
)
|
||||
|
||||
compacted, result = compactor.compact(messages)
|
||||
|
||||
print(f" Messages kept: {result.messages_kept}")
|
||||
print(f" Strategy: {result.strategy_used.value}")
|
||||
|
||||
# Show what messages remain
|
||||
print(f"\n Remaining message roles:")
|
||||
for msg in compacted:
|
||||
role = msg.get("role", "unknown")
|
||||
content_preview = msg.get("content", "")[:50]
|
||||
print(f" [{role}] {content_preview}...")
|
||||
|
||||
# ==========================================================================
|
||||
# No Compaction Needed
|
||||
# ==========================================================================
|
||||
print("\n--- No Compaction Needed ---")
|
||||
|
||||
compactor = ContextCompactor(
|
||||
max_tokens=10000, # High limit
|
||||
strategy=CompactionStrategy.TRUNCATE
|
||||
)
|
||||
|
||||
compacted, result = compactor.compact(messages)
|
||||
|
||||
print(f" Was compacted: {result.was_compacted}")
|
||||
print(f" Messages unchanged: {len(compacted) == len(messages)}")
|
||||
|
||||
# ==========================================================================
|
||||
# Result Serialization
|
||||
# ==========================================================================
|
||||
print("\n--- Result Serialization ---")
|
||||
|
||||
compactor = ContextCompactor(max_tokens=50)
|
||||
_, result = compactor.compact(messages)
|
||||
|
||||
data = result.to_dict()
|
||||
print(f" Original tokens: {data['original_tokens']}")
|
||||
print(f" Compacted tokens: {data['compacted_tokens']}")
|
||||
print(f" Compression ratio: {data['compression_ratio']:.2f}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Demo Complete!")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,85 @@
|
||||
"""
|
||||
CLI Compare Example - Advanced Usage
|
||||
|
||||
This example demonstrates advanced comparison features including
|
||||
custom mode configurations and result analysis.
|
||||
"""
|
||||
|
||||
from praisonai.cli.features.compare import (
|
||||
CompareHandler,
|
||||
CompareResult,
|
||||
ModeResult,
|
||||
get_mode_config,
|
||||
save_compare_result,
|
||||
format_comparison_table,
|
||||
)
|
||||
|
||||
# Create custom mode configurations
|
||||
custom_modes = {
|
||||
"fast": {"llm": "gpt-4o-mini"},
|
||||
"accurate": {"llm": "gpt-4o", "planning": True},
|
||||
"research": {"research": True, "web_search": True},
|
||||
}
|
||||
|
||||
# Create handler with verbose output
|
||||
handler = CompareHandler(verbose=True)
|
||||
|
||||
# Example: Manually create comparison results for analysis
|
||||
# (useful for testing without API calls)
|
||||
mock_result = CompareResult(
|
||||
query="What are the latest AI trends?",
|
||||
comparisons=[
|
||||
ModeResult(
|
||||
mode="basic",
|
||||
output="AI trends include LLMs, multimodal models, and agents.",
|
||||
execution_time_ms=1234.5,
|
||||
model_used="gpt-4o-mini",
|
||||
tools_used=[]
|
||||
),
|
||||
ModeResult(
|
||||
mode="tools",
|
||||
output="Based on recent search results, AI trends in 2024 include...",
|
||||
execution_time_ms=2567.8,
|
||||
model_used="gpt-4o-mini",
|
||||
tools_used=["internet_search"]
|
||||
),
|
||||
ModeResult(
|
||||
mode="research",
|
||||
output="Comprehensive research shows that AI trends...",
|
||||
execution_time_ms=5432.1,
|
||||
model_used="gpt-4o-mini",
|
||||
tools_used=["internet_search", "web_scraper"]
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
# Get summary statistics
|
||||
summary = mock_result.get_summary()
|
||||
print("Comparison Summary:")
|
||||
print(f" Fastest mode: {summary['fastest']} ({summary['fastest_time_ms']:.1f}ms)")
|
||||
print(f" Slowest mode: {summary['slowest']} ({summary['slowest_time_ms']:.1f}ms)")
|
||||
|
||||
# Format as table
|
||||
print("\n" + format_comparison_table(mock_result))
|
||||
|
||||
# Convert to JSON for storage
|
||||
print("\nJSON Output:")
|
||||
print(mock_result.to_json())
|
||||
|
||||
# Save to file
|
||||
# save_compare_result(mock_result, "advanced_comparison.json")
|
||||
|
||||
print("\n--- CLI Usage Examples ---")
|
||||
print("""
|
||||
# Basic comparison
|
||||
praisonai "What is AI?" --compare "basic,tools"
|
||||
|
||||
# Compare with specific model
|
||||
praisonai "Explain quantum computing" --compare "basic,planning,research" --model gpt-4o
|
||||
|
||||
# Save results to file
|
||||
praisonai "Latest tech news" --compare "basic,tools,web_search" --compare-output results.json
|
||||
|
||||
# Verbose output
|
||||
praisonai "Write a poem" --compare "basic,planning" --verbose
|
||||
""")
|
||||
@@ -0,0 +1,45 @@
|
||||
"""
|
||||
CLI Compare Example - Basic Usage
|
||||
|
||||
This example demonstrates how to compare different CLI modes programmatically.
|
||||
"""
|
||||
|
||||
from praisonai.cli.features.compare import (
|
||||
CompareHandler,
|
||||
get_mode_config,
|
||||
list_available_modes,
|
||||
parse_modes,
|
||||
)
|
||||
|
||||
# List all available comparison modes
|
||||
print("Available modes:")
|
||||
for mode in list_available_modes():
|
||||
config = get_mode_config(mode)
|
||||
print(f" - {mode}: {config}")
|
||||
|
||||
# Parse modes from comma-separated string
|
||||
modes = parse_modes("basic,tools,planning")
|
||||
print(f"\nParsed modes: {modes}")
|
||||
|
||||
# Create compare handler
|
||||
handler = CompareHandler(verbose=True)
|
||||
|
||||
# Compare modes (this will run actual agent calls)
|
||||
# Uncomment to run:
|
||||
# result = handler.compare(
|
||||
# query="What is artificial intelligence?",
|
||||
# modes=["basic", "tools"],
|
||||
# model="gpt-4o-mini"
|
||||
# )
|
||||
# handler.print_result(result)
|
||||
|
||||
# Save results to file
|
||||
# result = handler.execute(
|
||||
# query="Explain machine learning",
|
||||
# modes_str="basic,planning",
|
||||
# output_path="comparison_results.json"
|
||||
# )
|
||||
|
||||
print("\nTo run comparison via CLI:")
|
||||
print(' praisonai "What is AI?" --compare "basic,tools,planning"')
|
||||
print(' praisonai "What is AI?" --compare "basic,research" --compare-output results.json')
|
||||
@@ -0,0 +1,23 @@
|
||||
# Example: Data Collection Agent with 30-minute Schedule
|
||||
# Collects and analyzes data every 30 minutes
|
||||
|
||||
framework: praisonai
|
||||
|
||||
agents:
|
||||
- name: "Data Collector"
|
||||
role: "Data Analysis Specialist"
|
||||
goal: "Collect and analyze market data at regular intervals"
|
||||
instructions: |
|
||||
You are a data analysis specialist focused on collecting and analyzing
|
||||
market trends and metrics. Provide actionable insights from the data.
|
||||
tools:
|
||||
- search_tool
|
||||
verbose: false
|
||||
|
||||
task: "Collect latest market data and identify key trends"
|
||||
|
||||
# Schedule: Every 30 minutes with immediate execution
|
||||
schedule:
|
||||
interval: "*/30m"
|
||||
max_retries: 5
|
||||
run_immediately: true
|
||||
@@ -0,0 +1,53 @@
|
||||
# Example: 24/7 AI News Monitor with Scheduler
|
||||
# This agent runs continuously at regular intervals to monitor AI news
|
||||
|
||||
framework: praisonai
|
||||
|
||||
agents:
|
||||
- name: "AI News Monitor"
|
||||
role: "Technology News Analyst"
|
||||
goal: "Monitor and summarize the latest AI developments"
|
||||
instructions: |
|
||||
You are an expert technology news analyst specializing in AI and machine learning.
|
||||
Your job is to search for the latest AI news, identify the most important developments,
|
||||
and provide clear, concise summaries with sources.
|
||||
|
||||
Focus on:
|
||||
- Major AI product launches
|
||||
- Research breakthroughs
|
||||
- Industry trends
|
||||
- Policy and regulation updates
|
||||
tools:
|
||||
- search_tool
|
||||
verbose: true
|
||||
|
||||
# Task to execute on each scheduled run
|
||||
task: |
|
||||
Search for the latest AI news from the past 24 hours.
|
||||
Provide the top 3 most important stories with:
|
||||
1. Headline
|
||||
2. Brief summary (2-3 sentences)
|
||||
3. Source URL
|
||||
4. Why it's significant
|
||||
|
||||
# Schedule configuration
|
||||
schedule:
|
||||
# Interval options:
|
||||
# - "hourly" - Every hour
|
||||
# - "daily" - Every 24 hours
|
||||
# - "*/30m" - Every 30 minutes
|
||||
# - "*/6h" - Every 6 hours
|
||||
# - "3600" - Custom seconds
|
||||
interval: "hourly"
|
||||
|
||||
# Maximum retry attempts if execution fails
|
||||
max_retries: 3
|
||||
|
||||
# Run immediately when scheduler starts (before first scheduled interval)
|
||||
run_immediately: true
|
||||
|
||||
# Optional: Variables for customization
|
||||
variables:
|
||||
news_category: "AI and Machine Learning"
|
||||
region: "Global"
|
||||
time_range: "24 hours"
|
||||
@@ -0,0 +1,69 @@
|
||||
"""
|
||||
Accuracy Evaluation Example
|
||||
|
||||
This example demonstrates how to evaluate agent output accuracy
|
||||
by comparing against expected outputs using LLM-as-judge.
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.eval import AccuracyEvaluator
|
||||
|
||||
# Check if we have an API key
|
||||
has_api_key = os.getenv("OPENAI_API_KEY") is not None
|
||||
|
||||
if has_api_key:
|
||||
# Create a simple math tutor agent
|
||||
agent = Agent(
|
||||
instructions="You are a math tutor. Answer math questions concisely with just the number."
|
||||
)
|
||||
|
||||
# Create accuracy evaluator
|
||||
evaluator = AccuracyEvaluator(
|
||||
agent=agent,
|
||||
input_text="What is 2 + 2?",
|
||||
expected_output="4",
|
||||
num_iterations=3, # Run 3 times for statistical significance
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Run evaluation
|
||||
result = evaluator.run(print_summary=True)
|
||||
|
||||
# Check results
|
||||
print(f"\nAverage Score: {result.avg_score}/10")
|
||||
print(f"Passed: {result.passed}")
|
||||
else:
|
||||
print("⚠️ No OPENAI_API_KEY found. Using mock evaluation...")
|
||||
|
||||
# Create evaluator without agent for mock testing
|
||||
evaluator = AccuracyEvaluator(
|
||||
func=lambda x: "4", # Mock function
|
||||
input_text="What is 2 + 2?",
|
||||
expected_output="4",
|
||||
num_iterations=1,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Test with mock output
|
||||
try:
|
||||
result = evaluator.run(print_summary=True)
|
||||
print(f"\nMock Average Score: {result.avg_score}/10")
|
||||
print(f"Mock Passed: {result.passed}")
|
||||
except Exception as e:
|
||||
print(f"Mock evaluation failed: {e}")
|
||||
print("This is expected without an API key")
|
||||
|
||||
# You can also evaluate pre-generated outputs
|
||||
print("\n--- Testing pre-generated output evaluation ---")
|
||||
output = "The answer is 4"
|
||||
|
||||
if has_api_key:
|
||||
try:
|
||||
result2 = evaluator.evaluate_output(output, print_summary=True)
|
||||
print(f"Pre-generated output score: {result2.avg_score}/10")
|
||||
except Exception as e:
|
||||
print(f"Pre-generated evaluation failed: {e}")
|
||||
else:
|
||||
print("⚠️ Skipping pre-generated evaluation (no API key)")
|
||||
print("To run full evaluation, set OPENAI_API_KEY environment variable")
|
||||
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Batch Evaluation Example
|
||||
|
||||
This example demonstrates how to run batch evaluations
|
||||
from a JSON test file.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import tempfile
|
||||
from praisonaiagents.eval import AccuracyEvaluator
|
||||
|
||||
# Check if we have an API key
|
||||
has_api_key = os.getenv("OPENAI_API_KEY") is not None
|
||||
|
||||
# Create a test file with multiple test cases
|
||||
test_cases = [
|
||||
{
|
||||
"input": "What is 2 + 2?",
|
||||
"expected": "4"
|
||||
},
|
||||
{
|
||||
"input": "What is the capital of France?",
|
||||
"expected": "Paris"
|
||||
},
|
||||
{
|
||||
"input": "What color is the sky?",
|
||||
"expected": "Blue"
|
||||
}
|
||||
]
|
||||
|
||||
# Save test cases to a temporary file
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
|
||||
json.dump(test_cases, f)
|
||||
test_file = f.name
|
||||
|
||||
print(f"Test file created: {test_file}")
|
||||
print(f"Running {len(test_cases)} test cases...")
|
||||
|
||||
if has_api_key:
|
||||
# You can use the CLI for batch evaluation:
|
||||
# praisonai eval batch --agent agents.yaml --test-file tests.json --batch-type accuracy
|
||||
|
||||
# Or programmatically:
|
||||
from praisonaiagents import Agent
|
||||
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant. Answer questions concisely."
|
||||
)
|
||||
|
||||
results = []
|
||||
for i, test_case in enumerate(test_cases):
|
||||
print(f"\nTest {i + 1}: {test_case['input']}")
|
||||
|
||||
evaluator = AccuracyEvaluator(
|
||||
agent=agent,
|
||||
input_text=test_case["input"],
|
||||
expected_output=test_case["expected"],
|
||||
num_iterations=1
|
||||
)
|
||||
|
||||
result = evaluator.run()
|
||||
results.append({
|
||||
"input": test_case["input"],
|
||||
"expected": test_case["expected"],
|
||||
"score": result.avg_score,
|
||||
"passed": result.passed
|
||||
})
|
||||
|
||||
print(f" Score: {result.avg_score}/10")
|
||||
print(f" Passed: {result.passed}")
|
||||
|
||||
# Summary
|
||||
passed = sum(1 for r in results if r["passed"])
|
||||
print(f"\n{'='*50}")
|
||||
print(f"Summary: {passed}/{len(results)} tests passed")
|
||||
print(f"Pass Rate: {passed/len(results):.1%}")
|
||||
else:
|
||||
print("⚠️ No OPENAI_API_KEY found. Running mock batch evaluation...")
|
||||
|
||||
# Mock evaluation without API key
|
||||
results = []
|
||||
for i, test_case in enumerate(test_cases):
|
||||
print(f"\nTest {i + 1}: {test_case['input']}")
|
||||
|
||||
# Mock result (all would fail without API key)
|
||||
mock_score = 0.0
|
||||
mock_passed = False
|
||||
|
||||
results.append({
|
||||
"input": test_case["input"],
|
||||
"expected": test_case["expected"],
|
||||
"score": mock_score,
|
||||
"passed": mock_passed
|
||||
})
|
||||
|
||||
print(f" Score: {mock_score}/10 (mock)")
|
||||
print(f" Passed: {mock_passed} (expected without API key)")
|
||||
|
||||
# Summary
|
||||
passed = sum(1 for r in results if r["passed"])
|
||||
print(f"\n{'='*50}")
|
||||
print(f"Summary: {passed}/{len(results)} tests passed (mock evaluation)")
|
||||
print(f"Pass Rate: {passed/len(results):.1%}")
|
||||
print("\nTo run real batch evaluation, set OPENAI_API_KEY environment variable")
|
||||
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
Criteria Evaluation Example
|
||||
|
||||
This example demonstrates how to evaluate agent outputs
|
||||
against custom criteria using LLM-as-judge.
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.eval import CriteriaEvaluator
|
||||
|
||||
# Check if we have an API key
|
||||
has_api_key = os.getenv("OPENAI_API_KEY") is not None
|
||||
|
||||
if has_api_key:
|
||||
print("--- Testing Criteria Evaluation with Agent ---")
|
||||
# Create a customer service agent
|
||||
agent = Agent(
|
||||
instructions="You are a friendly customer service agent. Be helpful and empathetic."
|
||||
)
|
||||
|
||||
# Create criteria evaluator with numeric scoring
|
||||
evaluator = CriteriaEvaluator(
|
||||
criteria="Response is helpful, empathetic, and provides a clear solution",
|
||||
agent=agent,
|
||||
input_text="I'm frustrated because my order hasn't arrived yet.",
|
||||
scoring_type="numeric", # Score 1-10
|
||||
threshold=7.0, # Pass if score >= 7
|
||||
num_iterations=2,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Run evaluation
|
||||
result = evaluator.run(print_summary=True)
|
||||
|
||||
print("\nNumeric Scoring Results:")
|
||||
print(f" Average Score: {result.avg_score}/10")
|
||||
print(f" Pass Rate: {result.pass_rate:.1%}")
|
||||
print(f" Passed: {result.passed}")
|
||||
|
||||
# Binary scoring example (pass/fail)
|
||||
print("\n--- Testing Binary Scoring ---")
|
||||
binary_evaluator = CriteriaEvaluator(
|
||||
criteria="Response does not contain any offensive language",
|
||||
agent=agent,
|
||||
input_text="Tell me a joke",
|
||||
scoring_type="binary", # Pass or Fail
|
||||
verbose=True
|
||||
)
|
||||
|
||||
binary_result = binary_evaluator.run(print_summary=True)
|
||||
|
||||
# With on_fail callback
|
||||
print("\n--- Testing Failure Callback ---")
|
||||
def handle_failure(score):
|
||||
print(f"ALERT: Evaluation failed with score {score.score}")
|
||||
print(f"Reasoning: {score.reasoning}")
|
||||
|
||||
callback_evaluator = CriteriaEvaluator(
|
||||
criteria="Response is professional and helpful",
|
||||
agent=agent,
|
||||
input_text="Help me",
|
||||
on_fail=handle_failure,
|
||||
threshold=8.0
|
||||
)
|
||||
|
||||
callback_evaluator.run()
|
||||
else:
|
||||
print("⚠️ No OPENAI_API_KEY found. Skipping agent-based criteria evaluation...")
|
||||
|
||||
# Test pre-generated output evaluation (doesn't need agent)
|
||||
print("\n--- Testing Pre-generated Output Evaluation ---")
|
||||
if has_api_key:
|
||||
output = "I understand your frustration. Let me check on your order right away."
|
||||
try:
|
||||
result2 = evaluator.evaluate_output(output, print_summary=True)
|
||||
print(f"Pre-generated output score: {result2.avg_score}/10")
|
||||
except Exception as e:
|
||||
print(f"Pre-generated evaluation failed: {e}")
|
||||
else:
|
||||
print("⚠️ Skipping pre-generated evaluation (no API key)")
|
||||
print("To run full evaluation, set OPENAI_API_KEY environment variable")
|
||||
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
Performance Evaluation Example
|
||||
|
||||
This example demonstrates how to benchmark agent performance
|
||||
by measuring runtime and memory usage across multiple iterations.
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.eval import PerformanceEvaluator
|
||||
|
||||
# Check if we have an API key
|
||||
has_api_key = os.getenv("OPENAI_API_KEY") is not None
|
||||
|
||||
if has_api_key:
|
||||
print("--- Testing Agent Performance ---")
|
||||
# Create a simple agent
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant. Answer questions briefly."
|
||||
)
|
||||
|
||||
# Create performance evaluator
|
||||
evaluator = PerformanceEvaluator(
|
||||
agent=agent,
|
||||
input_text="What is the capital of France?",
|
||||
num_iterations=10, # Run 10 benchmark iterations
|
||||
warmup_runs=2, # 2 warmup runs before measurement
|
||||
track_memory=True, # Track memory usage
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Run evaluation
|
||||
result = evaluator.run(print_summary=True)
|
||||
|
||||
# Access detailed metrics
|
||||
print("\nAgent Performance Results:")
|
||||
print(f" Average Time: {result.avg_run_time:.4f}s")
|
||||
print(f" Min Time: {result.min_run_time:.4f}s")
|
||||
print(f" Max Time: {result.max_run_time:.4f}s")
|
||||
print(f" Median Time: {result.median_run_time:.4f}s")
|
||||
print(f" P95 Time: {result.p95_run_time:.4f}s")
|
||||
print(f" Avg Memory: {result.avg_memory:.2f} MB")
|
||||
else:
|
||||
print("⚠️ No OPENAI_API_KEY found. Skipping agent performance test...")
|
||||
|
||||
# You can also benchmark any function
|
||||
def my_function():
|
||||
import time
|
||||
time.sleep(0.1)
|
||||
return "done"
|
||||
|
||||
func_evaluator = PerformanceEvaluator(
|
||||
func=my_function,
|
||||
num_iterations=5,
|
||||
warmup_runs=1,
|
||||
track_memory=False
|
||||
)
|
||||
|
||||
func_result = func_evaluator.run(print_summary=True)
|
||||
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
Reliability Evaluation Example
|
||||
|
||||
This example demonstrates how to verify that agents call
|
||||
the expected tools during execution.
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.eval import ReliabilityEvaluator
|
||||
|
||||
|
||||
def search_web(query: str) -> str:
|
||||
"""Search the web for information."""
|
||||
return f"Search results for: {query}"
|
||||
|
||||
|
||||
def calculate(expression: str) -> str:
|
||||
"""Calculate a math expression."""
|
||||
return str(eval(expression))
|
||||
|
||||
|
||||
# Check if we have an API key
|
||||
has_api_key = os.getenv("OPENAI_API_KEY") is not None
|
||||
|
||||
if has_api_key:
|
||||
print("--- Testing Agent Tool Call Reliability ---")
|
||||
# Create an agent with tools
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant with access to search and calculator tools.",
|
||||
tools=[search_web, calculate]
|
||||
)
|
||||
|
||||
# Create reliability evaluator
|
||||
evaluator = ReliabilityEvaluator(
|
||||
agent=agent,
|
||||
input_text="Search for the weather in Paris and calculate 25 * 4",
|
||||
expected_tools=["search_web", "calculate"], # Tools that should be called
|
||||
forbidden_tools=["delete_file"], # Tools that should NOT be called
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Run evaluation
|
||||
result = evaluator.run(print_summary=True)
|
||||
|
||||
# Check results
|
||||
print("\nAgent Reliability Results:")
|
||||
print(f" Passed: {result.passed}")
|
||||
print(f" Pass Rate: {result.pass_rate:.1%}")
|
||||
else:
|
||||
print("⚠️ No OPENAI_API_KEY found. Skipping agent reliability test...")
|
||||
print("Agent would fail to call tools without API key (expected behavior)")
|
||||
|
||||
# You can also evaluate pre-recorded tool calls (doesn't need API key)
|
||||
print("\n--- Testing Pre-recorded Tool Call Evaluation ---")
|
||||
# Create a mock agent for tool call evaluation
|
||||
mock_agent = Agent(instructions="Mock agent")
|
||||
evaluator = ReliabilityEvaluator(
|
||||
agent=mock_agent,
|
||||
expected_tools=["search_web", "calculate"], # Tools that should be called
|
||||
forbidden_tools=["delete_file"], # Tools that should NOT be called
|
||||
verbose=True
|
||||
)
|
||||
|
||||
result2 = evaluator.evaluate_tool_calls(
|
||||
actual_tools=["search_web", "calculate"],
|
||||
print_summary=True
|
||||
)
|
||||
|
||||
print("\nPre-recorded Tool Call Results:")
|
||||
print(f" Passed: {result2.passed}")
|
||||
print(f" Pass Rate: {result2.pass_rate:.1%}")
|
||||
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic Hooks Example for PraisonAI Agents.
|
||||
|
||||
This example demonstrates how to use the hooks system to:
|
||||
1. Log tool calls before execution
|
||||
2. Block dangerous operations
|
||||
3. Add context to agent responses
|
||||
4. Monitor session lifecycle
|
||||
|
||||
Usage:
|
||||
python basic_hooks.py
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.hooks import (
|
||||
HookRegistry, HookRunner, HookEvent, HookResult,
|
||||
BeforeToolInput, AfterToolInput
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
# Create a hook registry
|
||||
registry = HookRegistry()
|
||||
|
||||
# ==========================================================================
|
||||
# Hook 1: Log all tool calls
|
||||
# ==========================================================================
|
||||
@registry.on(HookEvent.BEFORE_TOOL)
|
||||
def log_tool_calls(event_data: BeforeToolInput) -> HookResult:
|
||||
"""Log every tool call before execution."""
|
||||
print(f"\n📝 [LOG] Tool: {event_data.tool_name}")
|
||||
print(f" Input: {event_data.tool_input}")
|
||||
return HookResult.allow()
|
||||
|
||||
# ==========================================================================
|
||||
# Hook 2: Block dangerous file operations (using function logic)
|
||||
# ==========================================================================
|
||||
@registry.on(HookEvent.BEFORE_TOOL)
|
||||
def block_delete_operations(event_data: BeforeToolInput) -> HookResult:
|
||||
"""Block any delete or remove operations."""
|
||||
dangerous_keywords = ['delete', 'remove', 'rm', 'unlink']
|
||||
tool_lower = event_data.tool_name.lower()
|
||||
|
||||
if any(kw in tool_lower for kw in dangerous_keywords):
|
||||
print(f"\n🚫 [BLOCKED] Dangerous operation: {event_data.tool_name}")
|
||||
return HookResult.deny(
|
||||
f"Operation '{event_data.tool_name}' is blocked by security policy"
|
||||
)
|
||||
return HookResult.allow()
|
||||
|
||||
# ==========================================================================
|
||||
# Hook 3: Require confirmation for write operations
|
||||
# ==========================================================================
|
||||
@registry.on(HookEvent.BEFORE_TOOL)
|
||||
def confirm_write_operations(event_data: BeforeToolInput) -> HookResult:
|
||||
"""Request confirmation for write operations."""
|
||||
write_keywords = ['write', 'save', 'create', 'update']
|
||||
tool_lower = event_data.tool_name.lower()
|
||||
|
||||
if any(kw in tool_lower for kw in write_keywords):
|
||||
print(f"\n⚠️ [CONFIRM] Write operation: {event_data.tool_name}")
|
||||
# In a real scenario, you might prompt the user here
|
||||
# For this example, we'll auto-approve
|
||||
return HookResult.allow("Auto-approved for demo")
|
||||
return HookResult.allow()
|
||||
|
||||
# ==========================================================================
|
||||
# Hook 4: Add timing information after tool execution
|
||||
# ==========================================================================
|
||||
@registry.on(HookEvent.AFTER_TOOL)
|
||||
def log_tool_completion(event_data: AfterToolInput) -> HookResult:
|
||||
"""Log tool completion with timing."""
|
||||
print(f"\n✅ [DONE] Tool: {event_data.tool_name}")
|
||||
print(f" Duration: {event_data.execution_time_ms:.2f}ms")
|
||||
if event_data.tool_error:
|
||||
print(f" Error: {event_data.tool_error}")
|
||||
return HookResult.allow()
|
||||
|
||||
# ==========================================================================
|
||||
# Test the hooks
|
||||
# ==========================================================================
|
||||
print("=" * 60)
|
||||
print("Testing Hooks System")
|
||||
print("=" * 60)
|
||||
|
||||
runner = HookRunner(registry)
|
||||
|
||||
# Test 1: Normal tool call (should be logged and allowed)
|
||||
print("\n--- Test 1: Normal read operation ---")
|
||||
input1 = BeforeToolInput(
|
||||
session_id="test",
|
||||
cwd="/tmp",
|
||||
event_name="before_tool",
|
||||
timestamp="2024-01-01T00:00:00",
|
||||
tool_name="read_file",
|
||||
tool_input={"path": "/tmp/test.txt"}
|
||||
)
|
||||
results = asyncio.run(runner.execute(HookEvent.BEFORE_TOOL, input1))
|
||||
print(f"Result: {'ALLOWED' if not HookRunner.is_blocked(results) else 'BLOCKED'}")
|
||||
|
||||
# Test 2: Delete operation (should be blocked)
|
||||
print("\n--- Test 2: Delete operation ---")
|
||||
input2 = BeforeToolInput(
|
||||
session_id="test",
|
||||
cwd="/tmp",
|
||||
event_name="before_tool",
|
||||
timestamp="2024-01-01T00:00:00",
|
||||
tool_name="delete_file",
|
||||
tool_input={"path": "/important/data.txt"}
|
||||
)
|
||||
results = asyncio.run(runner.execute(HookEvent.BEFORE_TOOL, input2))
|
||||
print(f"Result: {'ALLOWED' if not HookRunner.is_blocked(results) else 'BLOCKED'}")
|
||||
if HookRunner.is_blocked(results):
|
||||
print(f"Reason: {HookRunner.get_blocking_reason(results)}")
|
||||
|
||||
# Test 3: Write operation (should be confirmed)
|
||||
print("\n--- Test 3: Write operation ---")
|
||||
input3 = BeforeToolInput(
|
||||
session_id="test",
|
||||
cwd="/tmp",
|
||||
event_name="before_tool",
|
||||
timestamp="2024-01-01T00:00:00",
|
||||
tool_name="write_file",
|
||||
tool_input={"path": "/tmp/output.txt", "content": "Hello"}
|
||||
)
|
||||
results = asyncio.run(runner.execute(HookEvent.BEFORE_TOOL, input3))
|
||||
print(f"Result: {'ALLOWED' if not HookRunner.is_blocked(results) else 'BLOCKED'}")
|
||||
|
||||
# Show registered hooks
|
||||
print("\n" + "=" * 60)
|
||||
print("Registered Hooks:")
|
||||
print("=" * 60)
|
||||
for event, hooks in registry.list_hooks().items():
|
||||
print(f"\n{event}:")
|
||||
for hook in hooks:
|
||||
print(f" - {hook['name']} (matcher: {hook['matcher'] or '*'})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Basic Agent Example
|
||||
* Demonstrates simple agent usage with OpenAI
|
||||
*/
|
||||
|
||||
import { Agent } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
const agent = new Agent({
|
||||
name: 'Assistant',
|
||||
instructions: 'You are a helpful assistant. Be concise and informative.',
|
||||
llm: 'openai/gpt-4o-mini'
|
||||
});
|
||||
|
||||
const response = await agent.chat('What is TypeScript?');
|
||||
console.log('Response:', response.text);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Context Agent Example
|
||||
* Demonstrates RAG-enabled agent with knowledge base
|
||||
*/
|
||||
|
||||
import { ContextAgent, createContextAgent, KnowledgeBase } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create knowledge base
|
||||
const kb = new KnowledgeBase();
|
||||
|
||||
// Add documents
|
||||
await kb.add({
|
||||
id: 'doc1',
|
||||
content: 'TypeScript is a strongly typed programming language that builds on JavaScript.',
|
||||
metadata: { topic: 'typescript' }
|
||||
});
|
||||
|
||||
await kb.add({
|
||||
id: 'doc2',
|
||||
content: 'TypeScript adds optional static typing and class-based object-oriented programming.',
|
||||
metadata: { topic: 'typescript' }
|
||||
});
|
||||
|
||||
await kb.add({
|
||||
id: 'doc3',
|
||||
content: 'PraisonAI is a framework for building AI agents in TypeScript and Python.',
|
||||
metadata: { topic: 'praisonai' }
|
||||
});
|
||||
|
||||
// Create context agent with knowledge base
|
||||
const agent = createContextAgent({
|
||||
name: 'KnowledgeAgent',
|
||||
llm: 'openai/gpt-4o-mini',
|
||||
knowledgeBase: kb,
|
||||
maxContextDocs: 3
|
||||
});
|
||||
|
||||
// Query with context
|
||||
const response = await agent.chat('What is TypeScript?');
|
||||
console.log('Response:', response.text);
|
||||
|
||||
// Check conversation history
|
||||
console.log('\nConversation history:', agent.getHistory().length, 'messages');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Image Agent Example
|
||||
* Demonstrates image analysis capabilities
|
||||
*/
|
||||
|
||||
import { ImageAgent, createImageAgent } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
const agent = createImageAgent({
|
||||
name: 'VisionAgent',
|
||||
llm: 'openai/gpt-4o-mini',
|
||||
verbose: true
|
||||
});
|
||||
|
||||
console.log('Image Agent created:', agent.name);
|
||||
|
||||
// Note: For actual image analysis, provide a real image URL
|
||||
// const analysis = await agent.analyze({
|
||||
// imageUrl: 'https://example.com/image.jpg',
|
||||
// prompt: 'Describe this image in detail'
|
||||
// });
|
||||
// console.log('Analysis:', analysis);
|
||||
|
||||
// Chat without image
|
||||
const response = await agent.chat('What types of images can you analyze?');
|
||||
console.log('Response:', response);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Multi-Agent Example
|
||||
* Demonstrates multiple agents working together
|
||||
*/
|
||||
|
||||
import { Agent, PraisonAIAgents, Task } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create specialized agents
|
||||
const researcher = new Agent({
|
||||
name: 'Researcher',
|
||||
role: 'Research Specialist',
|
||||
goal: 'Find accurate information on topics',
|
||||
instructions: 'You research topics thoroughly and provide factual information.'
|
||||
});
|
||||
|
||||
const writer = new Agent({
|
||||
name: 'Writer',
|
||||
role: 'Content Writer',
|
||||
goal: 'Create engaging content from research',
|
||||
instructions: 'You write clear, engaging content based on provided research.'
|
||||
});
|
||||
|
||||
// Create tasks
|
||||
const researchTask = new Task({
|
||||
description: 'Research the benefits of TypeScript over JavaScript',
|
||||
expectedOutput: 'A list of key benefits with explanations',
|
||||
agent: researcher
|
||||
});
|
||||
|
||||
const writeTask = new Task({
|
||||
description: 'Write a short article about TypeScript benefits',
|
||||
expectedOutput: 'A 200-word article',
|
||||
agent: writer
|
||||
});
|
||||
|
||||
// Run agents
|
||||
const agents = new PraisonAIAgents({
|
||||
agents: [researcher, writer],
|
||||
tasks: [researchTask, writeTask],
|
||||
process: 'sequential'
|
||||
});
|
||||
|
||||
const result = await agents.start();
|
||||
console.log('Result:', result);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Deep Research Agent Example
|
||||
* Demonstrates comprehensive research with citations
|
||||
*/
|
||||
|
||||
import { DeepResearchAgent, createDeepResearchAgent } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
const agent = createDeepResearchAgent({
|
||||
name: 'Scholar',
|
||||
llm: 'openai/gpt-4o-mini',
|
||||
maxIterations: 5,
|
||||
verbose: true
|
||||
});
|
||||
|
||||
console.log('Research Agent:', agent.name);
|
||||
|
||||
// Conduct research
|
||||
const result = await agent.research('What are the key benefits of TypeScript?');
|
||||
|
||||
console.log('\n=== Research Results ===');
|
||||
console.log('Answer:', result.answer.substring(0, 500) + '...');
|
||||
console.log('\nConfidence:', result.confidence);
|
||||
console.log('Reasoning steps:', result.reasoning.length);
|
||||
|
||||
// Show reasoning
|
||||
console.log('\n=== Reasoning Process ===');
|
||||
result.reasoning.forEach(step => {
|
||||
console.log(`Step ${step.step}: ${step.thought}`);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Router Agent Example
|
||||
* Demonstrates routing requests to specialized agents
|
||||
*/
|
||||
|
||||
import { RouterAgent, createRouter, routeConditions, Agent } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create specialized agents
|
||||
const mathAgent = {
|
||||
name: 'MathAgent',
|
||||
chat: async (input: string) => ({ text: `Math answer for: ${input}` })
|
||||
} as any;
|
||||
|
||||
const codeAgent = {
|
||||
name: 'CodeAgent',
|
||||
chat: async (input: string) => ({ text: `Code solution for: ${input}` })
|
||||
} as any;
|
||||
|
||||
const generalAgent = {
|
||||
name: 'GeneralAgent',
|
||||
chat: async (input: string) => ({ text: `General response: ${input}` })
|
||||
} as any;
|
||||
|
||||
// Create router with conditions
|
||||
const router = createRouter({
|
||||
name: 'SmartRouter',
|
||||
routes: [
|
||||
{
|
||||
agent: mathAgent,
|
||||
condition: routeConditions.keywords(['math', 'calculate', 'number', 'equation']),
|
||||
priority: 10
|
||||
},
|
||||
{
|
||||
agent: codeAgent,
|
||||
condition: routeConditions.keywords(['code', 'program', 'function', 'javascript']),
|
||||
priority: 10
|
||||
}
|
||||
],
|
||||
defaultAgent: generalAgent
|
||||
});
|
||||
|
||||
// Test routing
|
||||
const queries = [
|
||||
'Calculate 2 + 2',
|
||||
'Write a function to sort an array',
|
||||
'What is the weather today?'
|
||||
];
|
||||
|
||||
for (const query of queries) {
|
||||
const result = await router.route(query);
|
||||
console.log(`Query: "${query}"`);
|
||||
console.log(`Routed to: ${result?.agent.name || 'default'}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* AutoAgents Example
|
||||
* Demonstrates automatic agent generation from task descriptions
|
||||
*/
|
||||
|
||||
import { AutoAgents, createAutoAgents } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
const auto = createAutoAgents({
|
||||
pattern: 'sequential',
|
||||
verbose: true
|
||||
});
|
||||
|
||||
// Analyze task complexity
|
||||
console.log('=== Complexity Analysis ===');
|
||||
const tasks = [
|
||||
'Write a hello world function',
|
||||
'Build a web scraper that extracts product data',
|
||||
'Create a multi-step data pipeline with validation, transformation, and multiple output formats'
|
||||
];
|
||||
|
||||
tasks.forEach(task => {
|
||||
const complexity = auto.analyzeComplexity(task);
|
||||
console.log(`"${task.substring(0, 40)}..." -> ${complexity}`);
|
||||
});
|
||||
|
||||
// Recommend patterns
|
||||
console.log('\n=== Pattern Recommendations ===');
|
||||
const patternTasks = [
|
||||
'Process items in parallel',
|
||||
'Route requests to different handlers',
|
||||
'Orchestrate multiple workers',
|
||||
'Evaluate and optimize results'
|
||||
];
|
||||
|
||||
patternTasks.forEach(task => {
|
||||
const pattern = auto.recommendPattern(task);
|
||||
console.log(`"${task}" -> ${pattern}`);
|
||||
});
|
||||
|
||||
// Generate agent configuration
|
||||
console.log('\n=== Generate Agent Config ===');
|
||||
console.log('Generating agents for: "Build a web scraper"');
|
||||
|
||||
const team = await auto.generate('Build a web scraper that extracts product prices from e-commerce sites');
|
||||
|
||||
console.log('\nGenerated Team:');
|
||||
console.log('Pattern:', team.pattern);
|
||||
console.log('Agents:', team.agents.length);
|
||||
team.agents.forEach(agent => {
|
||||
console.log(` - ${agent.name}: ${agent.role}`);
|
||||
});
|
||||
console.log('Tasks:', team.tasks.length);
|
||||
team.tasks.forEach(task => {
|
||||
console.log(` - ${task.description.substring(0, 50)}...`);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Redis Database Example
|
||||
*/
|
||||
|
||||
import { createMemoryRedis } from '../../../src/praisonai-ts/src';
|
||||
|
||||
async function main() {
|
||||
// Use in-memory Redis for this example
|
||||
const redis = createMemoryRedis();
|
||||
await redis.connect();
|
||||
|
||||
console.log('Connected to Redis');
|
||||
|
||||
// Basic get/set
|
||||
await redis.set('user:123', { name: 'John', role: 'admin' });
|
||||
const user = await redis.get('user:123');
|
||||
console.log('User:', user);
|
||||
|
||||
// Set with TTL
|
||||
await redis.set('session:abc', { token: 'xyz' }, 60);
|
||||
const ttl = await redis.ttl('session:abc');
|
||||
console.log('Session TTL:', ttl, 'seconds');
|
||||
|
||||
// Hash operations
|
||||
await redis.hset('profile:123', 'email', '[email protected]');
|
||||
await redis.hset('profile:123', 'phone', '555-1234');
|
||||
const profile = await redis.hgetall('profile:123');
|
||||
console.log('Profile:', profile);
|
||||
|
||||
// List operations
|
||||
await redis.rpush('queue:tasks', { id: 1, type: 'process' });
|
||||
await redis.rpush('queue:tasks', { id: 2, type: 'notify' });
|
||||
const tasks = await redis.lrange('queue:tasks', 0, -1);
|
||||
console.log('Tasks:', tasks);
|
||||
|
||||
// Pub/Sub (memory only)
|
||||
await redis.subscribe('events', (message) => {
|
||||
console.log('Received event:', message);
|
||||
});
|
||||
await redis.publish('events', JSON.stringify({ type: 'user_joined' }));
|
||||
|
||||
// Cleanup
|
||||
await redis.disconnect();
|
||||
console.log('Done!');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Evaluation Framework Example
|
||||
* Demonstrates accuracy, performance, and reliability evaluation
|
||||
*/
|
||||
|
||||
import { accuracyEval, performanceEval, reliabilityEval, EvalSuite } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
console.log('=== Accuracy Evaluation ===');
|
||||
const accuracyResult = await accuracyEval({
|
||||
input: 'What is 2 + 2?',
|
||||
expectedOutput: '4',
|
||||
actualOutput: 'The answer is 4'
|
||||
});
|
||||
console.log('Passed:', accuracyResult.passed);
|
||||
console.log('Score:', accuracyResult.score);
|
||||
console.log('Duration:', accuracyResult.duration, 'ms');
|
||||
|
||||
console.log('\n=== Performance Evaluation ===');
|
||||
const perfResult = await performanceEval({
|
||||
func: async () => {
|
||||
// Simulate some work
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
return 'done';
|
||||
},
|
||||
iterations: 5,
|
||||
warmupRuns: 1
|
||||
});
|
||||
console.log('Iterations:', perfResult.times.length);
|
||||
console.log('Avg time:', perfResult.avgTime.toFixed(2), 'ms');
|
||||
console.log('Min time:', perfResult.minTime.toFixed(2), 'ms');
|
||||
console.log('Max time:', perfResult.maxTime.toFixed(2), 'ms');
|
||||
|
||||
console.log('\n=== Reliability Evaluation ===');
|
||||
const reliabilityResult = await reliabilityEval({
|
||||
expectedToolCalls: ['search', 'calculate'],
|
||||
actualToolCalls: ['search', 'calculate']
|
||||
});
|
||||
console.log('Passed:', reliabilityResult.passed);
|
||||
console.log('Score:', reliabilityResult.score);
|
||||
|
||||
console.log('\n=== Eval Suite ===');
|
||||
const suite = new EvalSuite();
|
||||
|
||||
await suite.runAccuracy('test1', {
|
||||
input: 'Hello',
|
||||
expectedOutput: 'Hi',
|
||||
actualOutput: 'Hi there!'
|
||||
});
|
||||
|
||||
await suite.runAccuracy('test2', {
|
||||
input: 'Goodbye',
|
||||
expectedOutput: 'Bye',
|
||||
actualOutput: 'Bye!'
|
||||
});
|
||||
|
||||
const summary = suite.getSummary();
|
||||
console.log('Total tests:', summary.total);
|
||||
console.log('Passed:', summary.passed);
|
||||
console.log('Failed:', summary.failed);
|
||||
console.log('Pass rate:', (summary.passRate * 100).toFixed(1) + '%');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Content Guardrails Example
|
||||
* Demonstrates input/output validation
|
||||
*/
|
||||
|
||||
import { guardrail, GuardrailManager, builtinGuardrails, LLMGuardrail } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create custom guardrail
|
||||
const noSpamGuardrail = guardrail({
|
||||
name: 'no_spam',
|
||||
check: (content) => {
|
||||
const spamWords = ['buy now', 'free money', 'click here'];
|
||||
const hasSpam = spamWords.some(word =>
|
||||
content.toLowerCase().includes(word)
|
||||
);
|
||||
return {
|
||||
status: hasSpam ? 'failed' : 'passed',
|
||||
message: hasSpam ? 'Content contains spam' : undefined
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Use built-in guardrails
|
||||
const maxLength = builtinGuardrails.maxLength(500);
|
||||
const minLength = builtinGuardrails.minLength(10);
|
||||
const blockedWords = builtinGuardrails.blockedWords(['badword1', 'badword2']);
|
||||
|
||||
// Create manager
|
||||
const manager = new GuardrailManager();
|
||||
manager.add(noSpamGuardrail);
|
||||
manager.add(maxLength);
|
||||
manager.add(minLength);
|
||||
manager.add(blockedWords);
|
||||
|
||||
// Test content
|
||||
const testCases = [
|
||||
'This is a normal, helpful response about programming.',
|
||||
'BUY NOW! Free money if you click here!',
|
||||
'Short',
|
||||
'This is a valid response that provides useful information about TypeScript and its benefits for developers.'
|
||||
];
|
||||
|
||||
console.log('=== Guardrail Tests ===\n');
|
||||
|
||||
for (const content of testCases) {
|
||||
console.log(`Content: "${content.substring(0, 40)}..."`);
|
||||
const result = await manager.runAll(content);
|
||||
console.log(` Passed: ${result.passed}`);
|
||||
if (!result.passed) {
|
||||
result.results
|
||||
.filter(r => r.status === 'failed')
|
||||
.forEach(r => console.log(` Failed: ${r.message}`));
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
// LLM Guardrail example
|
||||
console.log('=== LLM Guardrail ===');
|
||||
const llmGuard = new LLMGuardrail({
|
||||
name: 'quality_check',
|
||||
criteria: 'Content must be helpful and professional'
|
||||
});
|
||||
console.log('LLM Guardrail created:', llmGuard.name);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Knowledge Base (RAG) Example
|
||||
* Demonstrates retrieval-augmented generation
|
||||
*/
|
||||
|
||||
import { KnowledgeBase, createKnowledgeBase, Chunking } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create knowledge base
|
||||
const kb = createKnowledgeBase();
|
||||
|
||||
// Add documents
|
||||
const documents = [
|
||||
{
|
||||
id: 'ts-intro',
|
||||
content: 'TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.',
|
||||
metadata: { category: 'introduction', language: 'typescript' }
|
||||
},
|
||||
{
|
||||
id: 'ts-types',
|
||||
content: 'TypeScript adds optional static typing and class-based object-oriented programming to the language.',
|
||||
metadata: { category: 'features', language: 'typescript' }
|
||||
},
|
||||
{
|
||||
id: 'ts-benefits',
|
||||
content: 'Benefits of TypeScript include catching errors early, better IDE support, and improved code maintainability.',
|
||||
metadata: { category: 'benefits', language: 'typescript' }
|
||||
},
|
||||
{
|
||||
id: 'js-intro',
|
||||
content: 'JavaScript is a lightweight, interpreted programming language with first-class functions.',
|
||||
metadata: { category: 'introduction', language: 'javascript' }
|
||||
}
|
||||
];
|
||||
|
||||
for (const doc of documents) {
|
||||
await kb.add(doc);
|
||||
}
|
||||
|
||||
console.log('Documents added:', kb.size);
|
||||
|
||||
// Search
|
||||
console.log('\n=== Search: "TypeScript benefits" ===');
|
||||
const results = await kb.search('TypeScript benefits', 3);
|
||||
results.forEach(r => {
|
||||
console.log(`Score: ${r.score.toFixed(2)} - ${r.document.content.substring(0, 50)}...`);
|
||||
});
|
||||
|
||||
// Build context
|
||||
console.log('\n=== Context for LLM ===');
|
||||
const context = kb.buildContext(results);
|
||||
console.log(context);
|
||||
|
||||
// Chunking example
|
||||
console.log('\n=== Chunking Example ===');
|
||||
const chunker = new Chunking({ chunkSize: 100, overlap: 20 });
|
||||
const longText = 'This is a long document. '.repeat(20);
|
||||
const chunks = chunker.chunk(longText);
|
||||
console.log(`Chunked into ${chunks.length} pieces`);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Conversation Memory Example
|
||||
* Demonstrates memory management for conversations
|
||||
*/
|
||||
|
||||
import { Memory, createMemory } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
const memory = createMemory({
|
||||
maxEntries: 100,
|
||||
maxTokens: 10000
|
||||
});
|
||||
|
||||
// Simulate a conversation
|
||||
await memory.add('What is TypeScript?', 'user');
|
||||
await memory.add('TypeScript is a strongly typed programming language that builds on JavaScript.', 'assistant');
|
||||
await memory.add('What are its main benefits?', 'user');
|
||||
await memory.add('Key benefits include type safety, better IDE support, and easier refactoring.', 'assistant');
|
||||
await memory.add('Can you give an example?', 'user');
|
||||
|
||||
console.log('Memory size:', memory.size, 'entries\n');
|
||||
|
||||
// Get recent messages
|
||||
console.log('=== Recent Messages ===');
|
||||
const recent = memory.getRecent(3);
|
||||
recent.forEach(entry => {
|
||||
console.log(`[${entry.role}]: ${entry.content.substring(0, 50)}...`);
|
||||
});
|
||||
|
||||
// Search memory
|
||||
console.log('\n=== Search Results for "TypeScript" ===');
|
||||
const results = await memory.search('TypeScript');
|
||||
results.forEach(r => {
|
||||
console.log(`Score: ${r.score.toFixed(2)} - ${r.entry.content.substring(0, 40)}...`);
|
||||
});
|
||||
|
||||
// Build context
|
||||
console.log('\n=== Full Context ===');
|
||||
console.log(memory.buildContext());
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Observability Example
|
||||
* Demonstrates tracing and monitoring
|
||||
*/
|
||||
|
||||
import { MemoryObservabilityAdapter, ConsoleObservabilityAdapter } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Memory adapter - stores traces in memory
|
||||
const memoryAdapter = new MemoryObservabilityAdapter();
|
||||
|
||||
// Start a trace
|
||||
const trace = memoryAdapter.startTrace('agent-execution');
|
||||
console.log('Trace started:', trace.traceId);
|
||||
|
||||
// Create spans for different operations
|
||||
const llmSpan = trace.startSpan('llm-call', 'llm');
|
||||
llmSpan.setAttribute('model', 'gpt-4o-mini');
|
||||
llmSpan.setAttribute('tokens', 150);
|
||||
await new Promise(r => setTimeout(r, 100)); // Simulate work
|
||||
llmSpan.end();
|
||||
|
||||
const toolSpan = trace.startSpan('tool-execution', 'tool');
|
||||
toolSpan.setAttribute('tool', 'calculator');
|
||||
toolSpan.addEvent('tool-started', { input: '2+2' });
|
||||
await new Promise(r => setTimeout(r, 50)); // Simulate work
|
||||
toolSpan.addEvent('tool-completed', { output: '4' });
|
||||
toolSpan.end();
|
||||
|
||||
// End trace
|
||||
trace.end();
|
||||
|
||||
// Retrieve trace data
|
||||
const traceData = memoryAdapter.getTrace(trace.traceId);
|
||||
console.log('\n=== Trace Data ===');
|
||||
console.log('Trace ID:', traceData?.traceId);
|
||||
console.log('Spans:', traceData?.spans.length);
|
||||
console.log('Duration:', traceData?.endTime! - traceData?.startTime!, 'ms');
|
||||
|
||||
// Show spans
|
||||
console.log('\n=== Spans ===');
|
||||
traceData?.spans.forEach(span => {
|
||||
console.log(`- ${span.name} (${span.kind}): ${span.endTime! - span.startTime}ms`);
|
||||
if (span.attributes) {
|
||||
Object.entries(span.attributes).forEach(([k, v]) => {
|
||||
console.log(` ${k}: ${v}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Console adapter example
|
||||
console.log('\n=== Console Adapter ===');
|
||||
const consoleAdapter = new ConsoleObservabilityAdapter();
|
||||
const trace2 = consoleAdapter.startTrace('demo-trace');
|
||||
const span = trace2.startSpan('demo-span', 'custom');
|
||||
span.end();
|
||||
trace2.end();
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Planning System Example
|
||||
* Demonstrates plans, steps, and todo lists
|
||||
*/
|
||||
|
||||
import { Plan, PlanStep, TodoList, TodoItem, PlanStorage, createPlan, createTodoList } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create a project plan
|
||||
console.log('=== Project Plan ===');
|
||||
const plan = createPlan({
|
||||
name: 'Build AI Agent',
|
||||
description: 'Create a fully functional AI agent'
|
||||
});
|
||||
|
||||
plan.addStep(new PlanStep({ description: 'Design agent architecture' }));
|
||||
plan.addStep(new PlanStep({ description: 'Implement core functionality' }));
|
||||
plan.addStep(new PlanStep({ description: 'Add tool support' }));
|
||||
plan.addStep(new PlanStep({ description: 'Write tests' }));
|
||||
plan.addStep(new PlanStep({ description: 'Deploy to production' }));
|
||||
|
||||
console.log('Plan:', plan.name);
|
||||
console.log('Steps:', plan.steps.length);
|
||||
|
||||
// Execute steps
|
||||
plan.start();
|
||||
plan.steps[0].start();
|
||||
plan.steps[0].complete();
|
||||
plan.steps[1].start();
|
||||
plan.steps[1].complete();
|
||||
|
||||
const progress = plan.getProgress();
|
||||
console.log(`Progress: ${progress.completed}/${progress.total} (${progress.percentage}%)`);
|
||||
|
||||
// Create todo list
|
||||
console.log('\n=== Todo List ===');
|
||||
const todos = createTodoList('Sprint Tasks');
|
||||
|
||||
todos.add(new TodoItem({ content: 'Review PR #123', priority: 'high' }));
|
||||
todos.add(new TodoItem({ content: 'Fix bug in router', priority: 'high' }));
|
||||
todos.add(new TodoItem({ content: 'Update documentation', priority: 'medium' }));
|
||||
todos.add(new TodoItem({ content: 'Refactor tests', priority: 'low' }));
|
||||
|
||||
console.log('Total items:', todos.items.length);
|
||||
console.log('High priority:', todos.getByPriority('high').length);
|
||||
|
||||
// Complete some items
|
||||
todos.items[0].complete();
|
||||
todos.items[1].start();
|
||||
|
||||
console.log('Pending:', todos.getPending().length);
|
||||
console.log('Completed:', todos.getCompleted().length);
|
||||
|
||||
const todoProgress = todos.getProgress();
|
||||
console.log(`Progress: ${todoProgress.completed}/${todoProgress.total} (${todoProgress.percentage}%)`);
|
||||
|
||||
// Use storage
|
||||
console.log('\n=== Plan Storage ===');
|
||||
const storage = new PlanStorage();
|
||||
storage.savePlan(plan);
|
||||
storage.saveTodoList(todos);
|
||||
|
||||
console.log('Saved plans:', storage.listPlans().length);
|
||||
console.log('Saved todo lists:', storage.listTodoLists().length);
|
||||
|
||||
// Retrieve
|
||||
const retrieved = storage.getPlan(plan.id);
|
||||
console.log('Retrieved plan:', retrieved?.name);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Skills System Example
|
||||
* Demonstrates skill management and parsing
|
||||
*/
|
||||
|
||||
import { SkillManager, parseSkillFile, createSkillManager } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Parse a skill file
|
||||
const skillContent = `---
|
||||
name: code-review
|
||||
description: Reviews code for best practices and potential issues
|
||||
license: MIT
|
||||
metadata:
|
||||
author: praisonai
|
||||
version: "1.0"
|
||||
allowed-tools: Read Grep
|
||||
---
|
||||
|
||||
# Code Review Skill
|
||||
|
||||
When reviewing code:
|
||||
1. Check for syntax errors
|
||||
2. Look for security vulnerabilities
|
||||
3. Suggest performance improvements
|
||||
4. Ensure proper error handling
|
||||
`;
|
||||
|
||||
console.log('=== Parse Skill File ===');
|
||||
const skill = parseSkillFile(skillContent);
|
||||
console.log('Name:', skill.metadata.name);
|
||||
console.log('Description:', skill.metadata.description);
|
||||
console.log('License:', skill.metadata.license);
|
||||
console.log('Instructions preview:', skill.instructions.substring(0, 100) + '...');
|
||||
|
||||
// Create skill manager
|
||||
console.log('\n=== Skill Manager ===');
|
||||
const manager = createSkillManager({ paths: [] });
|
||||
|
||||
// Register skills manually
|
||||
manager.register({
|
||||
metadata: {
|
||||
name: 'typescript-expert',
|
||||
description: 'Expert knowledge in TypeScript development'
|
||||
},
|
||||
instructions: 'You are a TypeScript expert. Help with type definitions, generics, and best practices.'
|
||||
});
|
||||
|
||||
manager.register({
|
||||
metadata: {
|
||||
name: 'api-designer',
|
||||
description: 'Designs RESTful APIs following best practices'
|
||||
},
|
||||
instructions: 'You design clean, RESTful APIs with proper versioning and documentation.'
|
||||
});
|
||||
|
||||
// List skills
|
||||
console.log('Registered skills:');
|
||||
manager.list().forEach(s => {
|
||||
console.log(`- ${s.metadata.name}: ${s.metadata.description}`);
|
||||
});
|
||||
|
||||
// Get specific skill
|
||||
const tsSkill = manager.get('typescript-expert');
|
||||
console.log('\n=== TypeScript Expert Skill ===');
|
||||
console.log('Instructions:', tsSkill?.instructions);
|
||||
|
||||
// Generate prompt
|
||||
console.log('\n=== Generated Prompt ===');
|
||||
const prompt = manager.generatePrompt(['typescript-expert']);
|
||||
console.log(prompt.substring(0, 200) + '...');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Basic Tools Example
|
||||
* Demonstrates tool creation and usage
|
||||
*/
|
||||
|
||||
import { tool, ToolRegistry, getRegistry } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create tools
|
||||
const calculator = tool({
|
||||
name: 'calculator',
|
||||
description: 'Perform basic math calculations',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
expression: { type: 'string', description: 'Math expression to evaluate' }
|
||||
},
|
||||
required: ['expression']
|
||||
},
|
||||
execute: async ({ expression }) => {
|
||||
try {
|
||||
const result = eval(expression);
|
||||
return `Result: ${result}`;
|
||||
} catch (e) {
|
||||
return 'Error: Invalid expression';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const greeter = tool({
|
||||
name: 'greeter',
|
||||
description: 'Generate a greeting',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Name to greet' }
|
||||
},
|
||||
required: ['name']
|
||||
},
|
||||
execute: async ({ name }) => `Hello, ${name}! Welcome to PraisonAI.`
|
||||
});
|
||||
|
||||
// Create registry and register tools
|
||||
const registry = new ToolRegistry();
|
||||
registry.register(calculator);
|
||||
registry.register(greeter);
|
||||
|
||||
console.log('Registered tools:', registry.list().map(t => t.name));
|
||||
|
||||
// Execute tools
|
||||
const calcResult = await calculator.execute({ expression: '10 * 5 + 2' });
|
||||
console.log('\nCalculator:', calcResult);
|
||||
|
||||
const greetResult = await greeter.execute({ name: 'Developer' });
|
||||
console.log('Greeter:', greetResult);
|
||||
|
||||
// Get OpenAI format
|
||||
console.log('\nOpenAI tool format:', JSON.stringify(calculator.toOpenAITool(), null, 2));
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Custom Tool Example
|
||||
* Demonstrates creating custom tools using BaseTool class (plugin pattern)
|
||||
*/
|
||||
|
||||
import { BaseTool, createTool, tool, ToolRegistry } from 'praisonai';
|
||||
|
||||
// Method 1: Extend BaseTool class (recommended for complex tools)
|
||||
class WeatherTool extends BaseTool<{ location: string; units?: string }, { temp: number; condition: string }> {
|
||||
name = 'get_weather';
|
||||
description = 'Get current weather for a location';
|
||||
parameters = {
|
||||
type: 'object' as const,
|
||||
properties: {
|
||||
location: { type: 'string', description: 'City name' },
|
||||
units: { type: 'string', description: 'celsius or fahrenheit', default: 'celsius' }
|
||||
},
|
||||
required: ['location']
|
||||
};
|
||||
|
||||
async run(params: { location: string; units?: string }): Promise<{ temp: number; condition: string }> {
|
||||
// Simulate API call
|
||||
console.log(`Getting weather for ${params.location} in ${params.units || 'celsius'}`);
|
||||
return { temp: 22, condition: 'sunny' };
|
||||
}
|
||||
}
|
||||
|
||||
// Method 2: Use createTool function (quick inline tools)
|
||||
const calculatorTool = createTool({
|
||||
name: 'calculator',
|
||||
description: 'Evaluate a math expression',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
expression: { type: 'string', description: 'Math expression to evaluate' }
|
||||
},
|
||||
required: ['expression']
|
||||
},
|
||||
run: (params: { expression: string }) => {
|
||||
try {
|
||||
return eval(params.expression);
|
||||
} catch {
|
||||
return 'Error: Invalid expression';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Method 3: Use tool() function with config object
|
||||
const greeterTool = tool({
|
||||
name: 'greeter',
|
||||
description: 'Generate a personalized greeting',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Name to greet' },
|
||||
style: { type: 'string', description: 'Greeting style: formal or casual' }
|
||||
},
|
||||
required: ['name']
|
||||
},
|
||||
execute: async (params: { name: string; style?: string }) => {
|
||||
if (params.style === 'formal') {
|
||||
return `Good day, ${params.name}. How may I assist you?`;
|
||||
}
|
||||
return `Hey ${params.name}! What's up?`;
|
||||
}
|
||||
});
|
||||
|
||||
async function main() {
|
||||
console.log('=== Custom Tool Examples ===\n');
|
||||
|
||||
// Test WeatherTool (class-based)
|
||||
console.log('--- WeatherTool (class-based) ---');
|
||||
const weather = new WeatherTool();
|
||||
console.log('Name:', weather.name);
|
||||
console.log('Description:', weather.description);
|
||||
|
||||
const weatherResult = await weather.run({ location: 'New York' });
|
||||
console.log('Result:', weatherResult);
|
||||
|
||||
// Safe execution with error handling
|
||||
const safeResult = await weather.safeRun({ location: 'London' });
|
||||
console.log('Safe result:', safeResult);
|
||||
|
||||
// Get OpenAI schema
|
||||
console.log('OpenAI Schema:', JSON.stringify(weather.getSchema(), null, 2));
|
||||
|
||||
// Test calculatorTool (createTool)
|
||||
console.log('\n--- Calculator Tool (createTool) ---');
|
||||
const calcResult = await calculatorTool.run({ expression: '10 * 5 + 2' });
|
||||
console.log('10 * 5 + 2 =', calcResult);
|
||||
|
||||
// Test greeterTool (tool function)
|
||||
console.log('\n--- Greeter Tool (tool function) ---');
|
||||
const greeting1 = await greeterTool.execute({ name: 'Alice' });
|
||||
console.log('Casual:', greeting1);
|
||||
|
||||
const greeting2 = await greeterTool.execute({ name: 'Mr. Smith', style: 'formal' });
|
||||
console.log('Formal:', greeting2);
|
||||
|
||||
// Register tools in registry
|
||||
console.log('\n--- Tool Registry ---');
|
||||
const registry = new ToolRegistry();
|
||||
registry.register(greeterTool);
|
||||
|
||||
console.log('Registered tools:', registry.list().map(t => t.name));
|
||||
console.log('OpenAI tools format:', registry.toOpenAITools().length, 'tools');
|
||||
|
||||
// Validate tool
|
||||
console.log('\n--- Validation ---');
|
||||
console.log('WeatherTool valid:', weather.validate());
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Pinecone Vector Store Example
|
||||
*/
|
||||
|
||||
import { createPineconeStore } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
const pinecone = createPineconeStore({
|
||||
apiKey: process.env.PINECONE_API_KEY!
|
||||
});
|
||||
|
||||
const indexName = 'test-index';
|
||||
|
||||
// Create index
|
||||
console.log('Creating index...');
|
||||
await pinecone.createIndex({
|
||||
indexName,
|
||||
dimension: 3,
|
||||
metric: 'cosine'
|
||||
});
|
||||
|
||||
// List indexes
|
||||
const indexes = await pinecone.listIndexes();
|
||||
console.log('Indexes:', indexes);
|
||||
|
||||
// Upsert vectors
|
||||
console.log('Upserting vectors...');
|
||||
await pinecone.upsert({
|
||||
indexName,
|
||||
vectors: [
|
||||
{ id: 'vec-1', vector: [0.1, 0.2, 0.3], metadata: { category: 'A' } },
|
||||
{ id: 'vec-2', vector: [0.4, 0.5, 0.6], metadata: { category: 'B' } },
|
||||
{ id: 'vec-3', vector: [0.7, 0.8, 0.9], metadata: { category: 'A' } }
|
||||
]
|
||||
});
|
||||
|
||||
// Query
|
||||
console.log('Querying...');
|
||||
const results = await pinecone.query({
|
||||
indexName,
|
||||
vector: [0.1, 0.2, 0.3],
|
||||
topK: 2,
|
||||
includeMetadata: true
|
||||
});
|
||||
|
||||
console.log('Results:');
|
||||
for (const r of results) {
|
||||
console.log(` ${r.id}: score=${r.score.toFixed(4)}, metadata=${JSON.stringify(r.metadata)}`);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
console.log('Deleting index...');
|
||||
await pinecone.deleteIndex(indexName);
|
||||
console.log('Done!');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Voice/TTS Example
|
||||
*/
|
||||
|
||||
import { createOpenAIVoice } from '../../../src/praisonai-ts/src';
|
||||
import { writeFileSync } from 'fs';
|
||||
|
||||
async function main() {
|
||||
const voice = createOpenAIVoice({
|
||||
apiKey: process.env.OPENAI_API_KEY
|
||||
});
|
||||
|
||||
// Check available voices
|
||||
const speakers = await voice.getSpeakers();
|
||||
console.log('Available voices:', speakers.map(s => s.name).join(', '));
|
||||
|
||||
// Generate speech
|
||||
console.log('Generating speech...');
|
||||
const audio = await voice.speak('Hello! Welcome to PraisonAI TypeScript SDK.', {
|
||||
voice: 'nova',
|
||||
speed: 1.0,
|
||||
format: 'mp3'
|
||||
});
|
||||
|
||||
// Save to file
|
||||
writeFileSync('output.mp3', audio);
|
||||
console.log('Audio saved to output.mp3');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Basic Workflow Example
|
||||
* Demonstrates sequential workflow execution
|
||||
*/
|
||||
|
||||
import { Workflow, parallel, route, loop } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
// Create a simple workflow
|
||||
const workflow = new Workflow<string, string>('DataProcessor')
|
||||
.step('validate', async (input) => {
|
||||
console.log('Step 1: Validating input...');
|
||||
return input.trim();
|
||||
})
|
||||
.step('transform', async (input) => {
|
||||
console.log('Step 2: Transforming...');
|
||||
return input.toUpperCase();
|
||||
})
|
||||
.step('format', async (input) => {
|
||||
console.log('Step 3: Formatting...');
|
||||
return `[PROCESSED] ${input}`;
|
||||
});
|
||||
|
||||
const result = await workflow.run(' hello world ');
|
||||
console.log('\nFinal output:', result.output);
|
||||
console.log('Steps executed:', result.steps.length);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Conditional Workflow Example
|
||||
* Demonstrates routing based on conditions
|
||||
*/
|
||||
|
||||
import { route } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
const processRequest = async (type: string) => {
|
||||
console.log(`Processing request type: ${type}`);
|
||||
|
||||
const result = await route([
|
||||
{
|
||||
condition: () => type === 'urgent',
|
||||
execute: async () => {
|
||||
console.log(' -> Urgent handler activated');
|
||||
return 'Processed urgently';
|
||||
}
|
||||
},
|
||||
{
|
||||
condition: () => type === 'normal',
|
||||
execute: async () => {
|
||||
console.log(' -> Normal handler activated');
|
||||
return 'Processed normally';
|
||||
}
|
||||
},
|
||||
{
|
||||
condition: () => true, // Default
|
||||
execute: async () => {
|
||||
console.log(' -> Default handler activated');
|
||||
return 'Processed with default handler';
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// Test different request types
|
||||
const types = ['urgent', 'normal', 'unknown'];
|
||||
|
||||
for (const type of types) {
|
||||
const result = await processRequest(type);
|
||||
console.log(`Result: ${result}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Parallel Workflow Example
|
||||
* Demonstrates parallel execution of tasks
|
||||
*/
|
||||
|
||||
import { parallel } from 'praisonai';
|
||||
|
||||
async function main() {
|
||||
console.log('Starting parallel tasks...\n');
|
||||
|
||||
const results = await parallel([
|
||||
async () => {
|
||||
console.log('Task 1: Starting...');
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
console.log('Task 1: Complete');
|
||||
return 'Result 1';
|
||||
},
|
||||
async () => {
|
||||
console.log('Task 2: Starting...');
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
console.log('Task 2: Complete');
|
||||
return 'Result 2';
|
||||
},
|
||||
async () => {
|
||||
console.log('Task 3: Starting...');
|
||||
await new Promise(r => setTimeout(r, 750));
|
||||
console.log('Task 3: Complete');
|
||||
return 'Result 3';
|
||||
}
|
||||
]);
|
||||
|
||||
console.log('\nAll tasks complete!');
|
||||
console.log('Results:', results);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Basic Middleware Example - PraisonAI Agents
|
||||
|
||||
Demonstrates before/after hooks and wrap decorators for model and tool calls.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, tool
|
||||
from praisonaiagents.hooks import (
|
||||
before_model, after_model, wrap_model_call,
|
||||
before_tool, after_tool, wrap_tool_call,
|
||||
InvocationContext, ModelRequest, ModelResponse
|
||||
)
|
||||
|
||||
# Simple tool for demonstration
|
||||
@tool
|
||||
def get_weather(city: str) -> str:
|
||||
"""Get weather for a city."""
|
||||
return f"Sunny, 22°C in {city}"
|
||||
|
||||
# Before model hook - adds context
|
||||
@before_model
|
||||
def add_context(request: ModelRequest) -> ModelRequest:
|
||||
print(f"[before_model] Adding context to request")
|
||||
return request
|
||||
|
||||
# After model hook - logs response
|
||||
@after_model
|
||||
def log_response(response: ModelResponse) -> ModelResponse:
|
||||
print(f"[after_model] Response received")
|
||||
return response
|
||||
|
||||
# Wrap tool call - retry on error
|
||||
@wrap_tool_call
|
||||
def retry_on_error(tool_call, call_next):
|
||||
print(f"[wrap_tool_call] Executing tool")
|
||||
try:
|
||||
return call_next(tool_call)
|
||||
except Exception as e:
|
||||
print(f"[wrap_tool_call] Retrying after error: {e}")
|
||||
return call_next(tool_call)
|
||||
|
||||
# Create agent with hooks
|
||||
agent = Agent(
|
||||
name="WeatherBot",
|
||||
instructions="You help with weather queries.",
|
||||
tools=[get_weather],
|
||||
hooks=[add_context, log_response, retry_on_error]
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Test the tool directly
|
||||
result = get_weather("London")
|
||||
print(f"Weather: {result}")
|
||||
|
||||
print("\n✓ Middleware example complete")
|
||||
@@ -0,0 +1,31 @@
|
||||
"""
|
||||
Configurable Model Example - PraisonAI Agents
|
||||
|
||||
Demonstrates runtime model switching without recreating the agent.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Create agent with configurable model enabled
|
||||
agent = Agent(
|
||||
name="FlexBot",
|
||||
instructions="You are a helpful assistant.",
|
||||
llm="gpt-4o-mini",
|
||||
llm_config={"configurable": True}
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Default model call
|
||||
print("Using default model (gpt-4o-mini)...")
|
||||
# response = agent.chat("Say hello in 5 words")
|
||||
|
||||
# Override model per-call
|
||||
print("\nOverriding to different model...")
|
||||
# response = agent.chat("Say hello in 5 words", config={"model": "gpt-4o"})
|
||||
|
||||
# Override temperature
|
||||
print("\nOverriding temperature...")
|
||||
# response = agent.chat("Say hello creatively", config={"temperature": 0.9})
|
||||
|
||||
print("\n✓ Configurable model example complete")
|
||||
print("Note: Uncomment agent.chat() calls to run with API key")
|
||||
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
Injected State Example - PraisonAI Agents
|
||||
|
||||
Demonstrates injecting agent state into tools without exposing it in the schema.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, tool
|
||||
from praisonaiagents.tools import Injected
|
||||
from praisonaiagents.tools.injected import AgentState, with_injection_context
|
||||
|
||||
# Tool with injected state - state param is NOT in the public schema
|
||||
@tool
|
||||
def show_context(query: str, state: Injected[dict]) -> str:
|
||||
"""Show the current agent context."""
|
||||
session_id = state.get('session_id', 'unknown')
|
||||
agent_id = state.get('agent_id', 'unknown')
|
||||
return f"Query: {query}, Session: {session_id}, Agent: {agent_id}"
|
||||
|
||||
# Create agent with the tool
|
||||
agent = Agent(
|
||||
name="ContextBot",
|
||||
instructions="You help show context information.",
|
||||
tools=[show_context],
|
||||
session_id="my-session-123"
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Verify injected param is not in schema
|
||||
schema = show_context.get_schema()
|
||||
params = schema['function']['parameters']['properties']
|
||||
print(f"Schema params: {list(params.keys())}")
|
||||
assert 'state' not in params, "state should NOT be in schema"
|
||||
print("✓ 'state' correctly excluded from schema")
|
||||
|
||||
# Test with manual injection context
|
||||
mock_state = AgentState(
|
||||
agent_id="test-agent",
|
||||
run_id="run-1",
|
||||
session_id="session-abc"
|
||||
)
|
||||
|
||||
with with_injection_context(mock_state):
|
||||
result = show_context(query="hello")
|
||||
print(f"Result: {result}")
|
||||
|
||||
# Test via agent.execute_tool
|
||||
result = agent.execute_tool("show_context", {"query": "test"})
|
||||
print(f"Agent result: {result}")
|
||||
|
||||
print("\n✓ Injected state example complete")
|
||||
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Rate Limiter Example - PraisonAI Agents
|
||||
|
||||
Demonstrates token bucket rate limiting for LLM API calls.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent
|
||||
from praisonaiagents.llm import RateLimiter
|
||||
|
||||
# Create rate limiter: 60 requests per minute
|
||||
limiter = RateLimiter(requests_per_minute=60, burst=5)
|
||||
|
||||
# Create agent with rate limiter
|
||||
agent = Agent(
|
||||
name="RateLimitedBot",
|
||||
instructions="You are a helpful assistant.",
|
||||
rate_limiter=limiter
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"Rate limiter: {limiter}")
|
||||
print(f"Available tokens: {limiter.available_tokens}")
|
||||
|
||||
# Demonstrate rate limiting
|
||||
for i in range(3):
|
||||
limiter.acquire()
|
||||
print(f"Request {i+1} acquired, tokens left: {limiter.available_tokens:.1f}")
|
||||
|
||||
print("\n✓ Rate limiter example complete")
|
||||
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
Multi-Agent Persistence Example
|
||||
|
||||
Demonstrates how multiple agents can share or isolate conversation
|
||||
history using the persistence layer.
|
||||
"""
|
||||
|
||||
from praisonai.persistence.factory import create_conversation_store, create_state_store
|
||||
from praisonai.persistence.conversation.base import ConversationSession, ConversationMessage
|
||||
import uuid
|
||||
|
||||
|
||||
def main():
|
||||
# Create stores
|
||||
conv_store = create_conversation_store("sqlite", path=":memory:")
|
||||
state_store = create_state_store("memory")
|
||||
|
||||
print("=== Multi-Agent Persistence Demo ===\n")
|
||||
|
||||
# Scenario 1: Shared session (agents collaborate)
|
||||
print("--- Scenario 1: Shared Session ---")
|
||||
shared_session_id = f"shared-{uuid.uuid4().hex[:8]}"
|
||||
|
||||
session = ConversationSession(
|
||||
session_id=shared_session_id,
|
||||
user_id="user-123",
|
||||
name="Shared Conversation"
|
||||
)
|
||||
conv_store.create_session(session)
|
||||
|
||||
# Agent 1 (Researcher) adds context
|
||||
conv_store.add_message(shared_session_id, ConversationMessage(
|
||||
role="assistant",
|
||||
content="[Researcher] I found relevant information about the topic.",
|
||||
metadata={"agent_id": "researcher", "agent_role": "research"}
|
||||
))
|
||||
|
||||
# Agent 2 (Writer) uses the context
|
||||
conv_store.add_message(shared_session_id, ConversationMessage(
|
||||
role="assistant",
|
||||
content="[Writer] Based on the research, here's a summary...",
|
||||
metadata={"agent_id": "writer", "agent_role": "writing"}
|
||||
))
|
||||
|
||||
# Agent 3 (Editor) reviews
|
||||
conv_store.add_message(shared_session_id, ConversationMessage(
|
||||
role="assistant",
|
||||
content="[Editor] I've reviewed and polished the content.",
|
||||
metadata={"agent_id": "editor", "agent_role": "editing"}
|
||||
))
|
||||
|
||||
messages = conv_store.get_messages(shared_session_id)
|
||||
print(f"Shared session has {len(messages)} messages from different agents")
|
||||
for msg in messages:
|
||||
agent = msg.metadata.get("agent_id", "unknown") if msg.metadata else "unknown"
|
||||
print(f" - {agent}: {msg.content[:50]}...")
|
||||
|
||||
# Scenario 2: Isolated sessions (agents work independently)
|
||||
print("\n--- Scenario 2: Isolated Sessions ---")
|
||||
|
||||
agent_sessions = {}
|
||||
for agent_name in ["planner", "executor", "validator"]:
|
||||
session_id = f"{agent_name}-{uuid.uuid4().hex[:8]}"
|
||||
agent_sessions[agent_name] = session_id
|
||||
|
||||
conv_store.create_session(ConversationSession(
|
||||
session_id=session_id,
|
||||
agent_id=agent_name,
|
||||
name=f"{agent_name.title()} Session"
|
||||
))
|
||||
|
||||
# Each agent has its own conversation
|
||||
conv_store.add_message(session_id, ConversationMessage(
|
||||
role="user",
|
||||
content=f"Task for {agent_name}"
|
||||
))
|
||||
conv_store.add_message(session_id, ConversationMessage(
|
||||
role="assistant",
|
||||
content=f"[{agent_name.title()}] Processing task..."
|
||||
))
|
||||
|
||||
print("Created isolated sessions for each agent:")
|
||||
for agent, sid in agent_sessions.items():
|
||||
msgs = conv_store.get_messages(sid)
|
||||
print(f" - {agent}: {len(msgs)} messages")
|
||||
|
||||
# Scenario 3: Shared state across agents
|
||||
print("\n--- Scenario 3: Shared State ---")
|
||||
|
||||
# Agents share state for coordination
|
||||
state_store.set("workflow:status", {"phase": "research", "progress": 0})
|
||||
state_store.set("workflow:context", {"topic": "AI Agents", "deadline": "2024-12-31"})
|
||||
|
||||
# Agent 1 updates progress
|
||||
state = state_store.get("workflow:status")
|
||||
state["progress"] = 33
|
||||
state["phase"] = "writing"
|
||||
state_store.set("workflow:status", state)
|
||||
print(f"Agent 1 updated state: {state}")
|
||||
|
||||
# Agent 2 reads and updates
|
||||
state = state_store.get("workflow:status")
|
||||
state["progress"] = 66
|
||||
state["phase"] = "editing"
|
||||
state_store.set("workflow:status", state)
|
||||
print(f"Agent 2 updated state: {state}")
|
||||
|
||||
# Agent 3 completes
|
||||
state = state_store.get("workflow:status")
|
||||
state["progress"] = 100
|
||||
state["phase"] = "complete"
|
||||
state_store.set("workflow:status", state)
|
||||
print(f"Agent 3 completed: {state}")
|
||||
|
||||
# Cleanup
|
||||
conv_store.close()
|
||||
state_store.close()
|
||||
print("\n✅ Multi-agent persistence demo complete!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,40 @@
|
||||
"""Multi-Agent Shared Session - DB Persistence Test"""
|
||||
import sys
|
||||
sys.path.insert(0, 'src/praisonai')
|
||||
from praisonai.persistence import create_conversation_store
|
||||
from praisonai.persistence.conversation.base import ConversationSession, ConversationMessage
|
||||
|
||||
# Create shared session for multiple agents
|
||||
store = create_conversation_store("sqlite", path="/tmp/multi_agent.db")
|
||||
session_id = "shared-session-123"
|
||||
|
||||
# Create session
|
||||
session = ConversationSession(session_id=session_id, agent_id="multi")
|
||||
try:
|
||||
store.create_session(session)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Agent 1 writes
|
||||
msg1 = ConversationMessage(session_id=session_id, role="user", content="Agent1: Hello")
|
||||
store.add_message(session_id, msg1)
|
||||
msg2 = ConversationMessage(session_id=session_id, role="assistant", content="Agent1: Hi there!")
|
||||
store.add_message(session_id, msg2)
|
||||
|
||||
# Agent 2 writes to same session
|
||||
msg3 = ConversationMessage(session_id=session_id, role="user", content="Agent2: What did Agent1 say?")
|
||||
store.add_message(session_id, msg3)
|
||||
msg4 = ConversationMessage(session_id=session_id, role="assistant", content="Agent2: Agent1 said Hello")
|
||||
store.add_message(session_id, msg4)
|
||||
|
||||
# Verify both agents' messages are in session
|
||||
messages = store.get_messages(session_id)
|
||||
print(f"Total messages in shared session: {len(messages)}")
|
||||
assert len(messages) >= 4, "Should have messages from both agents"
|
||||
|
||||
# Verify content
|
||||
contents = [m.content for m in messages]
|
||||
assert any("Agent1" in c for c in contents), "Should have Agent1 messages"
|
||||
assert any("Agent2" in c for c in contents), "Should have Agent2 messages"
|
||||
|
||||
print("PASSED: Multi-agent shared session persistence")
|
||||
@@ -0,0 +1,16 @@
|
||||
"""Multi-Agent Shared Session Demo"""
|
||||
from praisonaiagents import Agent
|
||||
from praisonai.persistence import create_conversation_store
|
||||
|
||||
store = create_conversation_store("sqlite", path="/tmp/multi_agent.db")
|
||||
|
||||
agent1 = Agent(name="Researcher", llm="gpt-4o-mini", db=store, session_id="shared-session")
|
||||
agent2 = Agent(name="Writer", llm="gpt-4o-mini", db=store, session_id="shared-session")
|
||||
|
||||
r1 = agent1.chat("Research topic: AI in healthcare. Key finding: reduces diagnosis time by 50%")
|
||||
print(f"Researcher: {r1[:50]}...")
|
||||
|
||||
r2 = agent2.chat("Based on the research, what was the key finding?")
|
||||
print(f"Writer: {r2[:50]}...")
|
||||
assert "50" in r2 or "diagnosis" in r2.lower(), "Writer should see Researcher's context"
|
||||
print("PASSED: Multi-agent shared session works")
|
||||
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
Basic Observability Usage Example
|
||||
|
||||
This example demonstrates how to use the observability module
|
||||
with PraisonAI agents.
|
||||
|
||||
Usage:
|
||||
# Set your provider's API key first
|
||||
export LANGFUSE_PUBLIC_KEY=pk-lf-xxx
|
||||
export LANGFUSE_SECRET_KEY=sk-lf-xxx
|
||||
|
||||
python basic_usage.py
|
||||
"""
|
||||
|
||||
from praisonai_tools.observability import obs
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Initialize observability (auto-detects provider from env vars)
|
||||
obs.init()
|
||||
|
||||
# Or specify a provider explicitly
|
||||
# obs.init(provider="langfuse", project_name="my-project")
|
||||
|
||||
# Create an agent
|
||||
agent = Agent(
|
||||
instructions="You are a helpful assistant.",
|
||||
model="gpt-4o-mini",
|
||||
)
|
||||
|
||||
# Use trace context manager for complete workflow tracing
|
||||
with obs.trace("chat-session", session_id="user-123"):
|
||||
# Use span context manager for individual operations
|
||||
with obs.span("user-query", kind=obs.SpanKind.AGENT):
|
||||
response = agent.chat("What is the capital of France?")
|
||||
print(response)
|
||||
|
||||
# Log LLM calls manually if needed
|
||||
obs.log_llm_call(
|
||||
model="gpt-4o-mini",
|
||||
input_messages="What is 2+2?",
|
||||
output="4",
|
||||
input_tokens=10,
|
||||
output_tokens=1,
|
||||
)
|
||||
|
||||
# Check diagnostics
|
||||
print("\nDiagnostics:")
|
||||
print(obs.doctor())
|
||||
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
Langfuse Integration Example
|
||||
|
||||
This example shows how to use Langfuse for LLM observability.
|
||||
|
||||
Setup:
|
||||
1. Sign up at https://langfuse.com/
|
||||
2. Get your API keys from the project settings
|
||||
3. Set environment variables:
|
||||
export LANGFUSE_PUBLIC_KEY=pk-lf-xxx
|
||||
export LANGFUSE_SECRET_KEY=sk-lf-xxx
|
||||
4. Install dependencies:
|
||||
pip install opentelemetry-sdk opentelemetry-exporter-otlp
|
||||
|
||||
Usage:
|
||||
python langfuse_example.py
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonai_tools.observability import obs
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Initialize Langfuse
|
||||
success = obs.init(
|
||||
provider="langfuse",
|
||||
project_name="praisonai-demo",
|
||||
)
|
||||
|
||||
if not success:
|
||||
print("Failed to initialize Langfuse. Check your API keys.")
|
||||
print("Required: LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY")
|
||||
exit(1)
|
||||
|
||||
print("Langfuse initialized successfully!")
|
||||
print(f"View traces at: https://cloud.langfuse.com/")
|
||||
|
||||
# Create agent
|
||||
agent = Agent(
|
||||
instructions="You are a helpful coding assistant.",
|
||||
model="gpt-4o-mini",
|
||||
)
|
||||
|
||||
# Run with tracing
|
||||
with obs.trace("coding-session", user_id="developer-1"):
|
||||
response = agent.chat("Write a Python function to calculate fibonacci numbers")
|
||||
print(response)
|
||||
|
||||
print("\nCheck Langfuse dashboard for traces!")
|
||||
@@ -0,0 +1,22 @@
|
||||
"""MLflow Local Observability Demo (no API key needed)"""
|
||||
import mlflow
|
||||
import time
|
||||
|
||||
mlflow.set_tracking_uri("file:///tmp/mlflow_demo")
|
||||
mlflow.set_experiment("praisonai-demo")
|
||||
|
||||
with mlflow.start_run(run_name="agent-trace"):
|
||||
mlflow.log_param("agent_name", "Assistant")
|
||||
mlflow.log_param("model", "gpt-4o-mini")
|
||||
|
||||
# Simulate agent work
|
||||
start = time.time()
|
||||
time.sleep(0.1)
|
||||
latency = time.time() - start
|
||||
|
||||
mlflow.log_metric("latency_ms", latency * 1000)
|
||||
mlflow.log_metric("tokens_used", 150)
|
||||
|
||||
print(f"Logged run to MLflow: latency={latency*1000:.1f}ms")
|
||||
|
||||
print("PASSED: MLflow local observability works")
|
||||
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
Multi-Agent Tracing Example
|
||||
|
||||
This example shows how to trace multi-agent workflows with
|
||||
parent/child span relationships.
|
||||
|
||||
Usage:
|
||||
# Set your provider's API key
|
||||
export LANGFUSE_PUBLIC_KEY=pk-lf-xxx
|
||||
export LANGFUSE_SECRET_KEY=sk-lf-xxx
|
||||
|
||||
python multi_agent_tracing.py
|
||||
"""
|
||||
|
||||
from praisonai_tools.observability import obs
|
||||
from praisonai_tools.observability.base import SpanKind
|
||||
from praisonaiagents import Agent, PraisonAIAgents
|
||||
|
||||
# Initialize observability
|
||||
obs.init()
|
||||
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
instructions="You research topics and provide detailed information.",
|
||||
model="gpt-4o-mini",
|
||||
)
|
||||
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
instructions="You write clear, engaging content based on research.",
|
||||
model="gpt-4o-mini",
|
||||
)
|
||||
|
||||
# Trace the multi-agent workflow
|
||||
with obs.trace("content-creation", metadata={"workflow": "research-write"}):
|
||||
|
||||
# Research phase
|
||||
with obs.span("research-phase", kind=SpanKind.AGENT) as research_span:
|
||||
research_span.attributes["agent"] = "Researcher"
|
||||
research_result = researcher.chat("Research the benefits of AI in healthcare")
|
||||
|
||||
# Writing phase
|
||||
with obs.span("writing-phase", kind=SpanKind.AGENT) as write_span:
|
||||
write_span.attributes["agent"] = "Writer"
|
||||
write_span.attributes["input_length"] = len(str(research_result))
|
||||
final_content = writer.chat(f"Write a blog post based on: {research_result}")
|
||||
|
||||
print("Final Content:")
|
||||
print(final_content)
|
||||
|
||||
# Check trace info
|
||||
print("\nDiagnostics:", obs.doctor())
|
||||
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
Qdrant Knowledge Store - Agent-First Example
|
||||
|
||||
Demonstrates using Qdrant for knowledge-based RAG with an Agent.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Docker Setup:
|
||||
docker run -d --name praison-qdrant -p 6333:6333 qdrant/qdrant
|
||||
|
||||
Run:
|
||||
python knowledge_qdrant.py
|
||||
|
||||
Expected Output:
|
||||
Agent responds using knowledge from documents
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent
|
||||
import tempfile
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Create sample knowledge document
|
||||
sample_doc = """
|
||||
# AI and Programming Guide
|
||||
|
||||
## Python Programming
|
||||
Python is a versatile programming language used for web development, data science, and AI.
|
||||
It has a simple syntax and extensive libraries.
|
||||
|
||||
## Machine Learning
|
||||
Machine learning enables computers to learn patterns from data without explicit programming.
|
||||
Common frameworks include TensorFlow, PyTorch, and scikit-learn.
|
||||
|
||||
## Databases
|
||||
PostgreSQL is a powerful open-source relational database system.
|
||||
It supports both SQL and JSON data types.
|
||||
"""
|
||||
|
||||
# Save to temp file
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
doc_path = os.path.join(temp_dir, "guide.txt")
|
||||
with open(doc_path, "w") as f:
|
||||
f.write(sample_doc)
|
||||
|
||||
print("=== Qdrant Knowledge Store Demo (Agent-First) ===")
|
||||
|
||||
# Agent-first approach: use knowledge parameter with Qdrant
|
||||
agent = Agent(
|
||||
name="KnowledgeAssistant",
|
||||
instructions="You are a helpful assistant with access to technical documentation.",
|
||||
knowledge=[doc_path],
|
||||
knowledge_config={
|
||||
"vector_store": "qdrant",
|
||||
"url": "http://localhost:6333"
|
||||
}
|
||||
)
|
||||
|
||||
# Chat - agent uses knowledge for RAG
|
||||
response = agent.chat("What programming language is good for AI?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Cleanup
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
print("\n=== Demo Complete ===")
|
||||
|
||||
# --- Advanced: Direct Store Usage ---
|
||||
# from praisonai.persistence.factory import create_knowledge_store
|
||||
# store = create_knowledge_store("qdrant", url="http://localhost:6333")
|
||||
@@ -0,0 +1,43 @@
|
||||
"""
|
||||
Minimal Agent with Database Persistence
|
||||
|
||||
This is the simplest way to add persistence to your agent.
|
||||
Messages, runs, and traces are automatically saved.
|
||||
|
||||
Run:
|
||||
python minimal_agent_db.py
|
||||
|
||||
Expected output:
|
||||
- Agent responds to your question
|
||||
- Data is persisted to PostgreSQL
|
||||
- Session can be resumed later with same session_id
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, db
|
||||
|
||||
# Create database connection (PostgreSQL + Redis)
|
||||
my_db = db(
|
||||
database_url="postgresql://postgres:praison123@localhost:5432/praisonai",
|
||||
state_url="redis://localhost:6379" # Optional: for state/tracing
|
||||
)
|
||||
|
||||
# Create agent with persistence
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant. Be concise.",
|
||||
db=my_db,
|
||||
# session_id is optional - defaults to per-hour ID (YYYYMMDDHH-hash)
|
||||
# Set explicitly for session continuity across runs:
|
||||
session_id="my-persistent-session"
|
||||
)
|
||||
|
||||
# Chat - messages are automatically persisted
|
||||
response = agent.chat("What is the capital of France?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Verify persistence
|
||||
data = my_db.export_session("my-persistent-session")
|
||||
print(f"\nMessages stored: {len(data.get('messages', []))}")
|
||||
|
||||
# Clean up
|
||||
my_db.close()
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
PostgreSQL with Runs and Traces
|
||||
|
||||
Demonstrates full persistence with run tracking and tracing.
|
||||
|
||||
Run:
|
||||
python postgres_runs_traces.py
|
||||
|
||||
Expected output:
|
||||
- Agent responds with tool usage
|
||||
- Runs and traces are persisted
|
||||
- Export shows full session data
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, db
|
||||
|
||||
def get_weather(city: str) -> str:
|
||||
"""Get weather for a city."""
|
||||
return f"Weather in {city}: Sunny, 72°F"
|
||||
|
||||
# Create database with PostgreSQL + Redis
|
||||
my_db = db(
|
||||
database_url="postgresql://postgres:praison123@localhost:5432/praisonai",
|
||||
state_url="redis://localhost:6379"
|
||||
)
|
||||
|
||||
# Create agent with tools
|
||||
agent = Agent(
|
||||
name="WeatherBot",
|
||||
instructions="You help with weather. Use the get_weather tool when asked.",
|
||||
tools=[get_weather],
|
||||
db=my_db,
|
||||
session_id="weather-session-001"
|
||||
)
|
||||
|
||||
# First chat - triggers run tracking
|
||||
print("=== First Question ===")
|
||||
response1 = agent.chat("What's the weather in Tokyo?")
|
||||
print(f"Response: {response1}\n")
|
||||
|
||||
# Second chat - same session, new run
|
||||
print("=== Second Question ===")
|
||||
response2 = agent.chat("How about New York?")
|
||||
print(f"Response: {response2}\n")
|
||||
|
||||
# Export session data
|
||||
print("=== Session Data ===")
|
||||
data = my_db.export_session("weather-session-001")
|
||||
print(f"Session ID: {data.get('session_id')}")
|
||||
print(f"Messages: {len(data.get('messages', []))}")
|
||||
print(f"Agent: {data.get('agent_name')}")
|
||||
|
||||
# Show messages
|
||||
print("\n=== Messages ===")
|
||||
for msg in data.get('messages', []):
|
||||
role = msg.get('role', 'unknown')
|
||||
content = msg.get('content', '')[:60]
|
||||
print(f" [{role}] {content}...")
|
||||
|
||||
my_db.close()
|
||||
print("\n✅ Done")
|
||||
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Redis State Store - Agent-First Example
|
||||
|
||||
Use Redis for state management with an Agent.
|
||||
|
||||
Docker Setup:
|
||||
docker run -d --name redis -p 6379:6379 redis:7
|
||||
|
||||
Run:
|
||||
python redis_state.py
|
||||
|
||||
Expected output:
|
||||
Agent responds with state persisted to Redis
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, db
|
||||
|
||||
print("=== Redis State Store (Agent-First) ===")
|
||||
|
||||
# Agent-first approach: use db parameter with Redis state store
|
||||
my_db = db(
|
||||
database_url="sqlite:///conversations.db", # Conversations
|
||||
state_url="redis://localhost:6379" # State/tracing
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant.",
|
||||
db=my_db,
|
||||
session_id="redis-state-session"
|
||||
)
|
||||
|
||||
# Chat - state is automatically managed via Redis
|
||||
response = agent.chat("Hello! Remember my name is Alice.")
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Second message to test state
|
||||
response2 = agent.chat("What is my name?")
|
||||
print(f"Response: {response2}")
|
||||
|
||||
my_db.close()
|
||||
print("\n✅ Done")
|
||||
|
||||
# --- Advanced: Direct Store Usage ---
|
||||
# from praisonaiagents import db
|
||||
# redis_db = db.RedisDB(host="localhost", port=6379)
|
||||
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
Session Resume Example
|
||||
|
||||
Demonstrates how to resume a conversation from a previous session.
|
||||
|
||||
Run:
|
||||
python session_resume.py
|
||||
|
||||
Expected output:
|
||||
- First run: Creates new session
|
||||
- Second run: Resumes with history
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, db
|
||||
|
||||
# Create database
|
||||
my_db = db(
|
||||
database_url="postgresql://postgres:praison123@localhost:5432/praisonai",
|
||||
state_url="redis://localhost:6379"
|
||||
)
|
||||
|
||||
SESSION_ID = "resume-demo-session"
|
||||
|
||||
# Create agent with explicit session_id
|
||||
agent = Agent(
|
||||
name="MemoryBot",
|
||||
instructions="You remember our conversation. Be helpful and concise.",
|
||||
db=my_db,
|
||||
session_id=SESSION_ID
|
||||
)
|
||||
|
||||
# Check if this is a new or resumed session
|
||||
data = my_db.export_session(SESSION_ID)
|
||||
existing_messages = len(data.get('messages', []))
|
||||
|
||||
if existing_messages == 0:
|
||||
print("=== NEW SESSION ===")
|
||||
print("This is a new conversation.\n")
|
||||
|
||||
response = agent.chat("My name is Alice and I love Python programming.")
|
||||
print(f"Response: {response}\n")
|
||||
|
||||
response = agent.chat("What's my favorite programming language?")
|
||||
print(f"Response: {response}\n")
|
||||
else:
|
||||
print(f"=== RESUMED SESSION ({existing_messages} previous messages) ===")
|
||||
print("Continuing previous conversation.\n")
|
||||
|
||||
# Show previous messages
|
||||
print("Previous messages:")
|
||||
for msg in data.get('messages', [])[:4]:
|
||||
role = msg.get('role', 'unknown')
|
||||
content = msg.get('content', '')[:60]
|
||||
print(f" [{role}] {content}...")
|
||||
print()
|
||||
|
||||
# Continue conversation
|
||||
response = agent.chat("What's my name and what do I like?")
|
||||
print(f"Response: {response}\n")
|
||||
|
||||
# Show final state
|
||||
final_data = my_db.export_session(SESSION_ID)
|
||||
print(f"Total messages now: {len(final_data.get('messages', []))}")
|
||||
|
||||
my_db.close()
|
||||
print("✅ Done")
|
||||
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
Simple Database Persistence Example for PraisonAI Agents.
|
||||
|
||||
This example shows how to enable automatic conversation persistence
|
||||
with just 2 lines of code.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Docker Setup:
|
||||
docker run -d --name praison-postgres -p 5432:5432 \
|
||||
-e POSTGRES_PASSWORD=praison123 \
|
||||
-e POSTGRES_DB=praisonai \
|
||||
postgres:16
|
||||
|
||||
Environment:
|
||||
export OPENAI_API_KEY=your-key
|
||||
|
||||
Run:
|
||||
python simple_agent_postgres.py
|
||||
|
||||
Expected Output:
|
||||
=== First Run ===
|
||||
Agent: Nice to meet you, Alice! Python is a great choice...
|
||||
Session ID: demo-session-001
|
||||
Messages persisted: 2
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, db
|
||||
|
||||
# Create database adapter (simplified import)
|
||||
db_instance = db(
|
||||
database_url="postgresql://postgres:praison123@localhost:5432/praisonai"
|
||||
)
|
||||
|
||||
# Create agent with persistence enabled
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant. Keep responses brief.",
|
||||
db=db_instance,
|
||||
session_id="demo-session-001", # Same session_id = resume conversation
|
||||
verbose=False
|
||||
)
|
||||
|
||||
# Chat with persistence
|
||||
print("=== First Run ===")
|
||||
response = agent.chat("My name is Alice and I love Python programming.")
|
||||
print(f"Agent: {response}\n")
|
||||
|
||||
# Show session info
|
||||
print(f"Session ID: {agent.session_id}")
|
||||
print(f"Messages in history: {len(agent.chat_history)}")
|
||||
|
||||
# Close DB connection
|
||||
db_instance.close()
|
||||
|
||||
print("\n=== Session persisted! ===")
|
||||
print("Run again with same session_id to resume.")
|
||||
@@ -0,0 +1,41 @@
|
||||
"""
|
||||
SQLite Local Database
|
||||
|
||||
Use SQLite for simple local persistence without external services.
|
||||
|
||||
Run:
|
||||
python sqlite_local.py
|
||||
|
||||
Expected output:
|
||||
- Agent responds
|
||||
- Data persisted to local SQLite file
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, db
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
# Create SQLite database (local file)
|
||||
db_path = os.path.join(tempfile.gettempdir(), "my_agent.db")
|
||||
my_db = db.SQLiteDB(path=db_path)
|
||||
|
||||
print(f"Database: {db_path}")
|
||||
|
||||
# Create agent
|
||||
agent = Agent(
|
||||
name="LocalBot",
|
||||
instructions="You are a helpful assistant.",
|
||||
db=my_db,
|
||||
session_id="local-session"
|
||||
)
|
||||
|
||||
# Chat
|
||||
response = agent.chat("Hello! What can you help me with?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Verify
|
||||
data = my_db.export_session("local-session")
|
||||
print(f"\nMessages stored: {len(data.get('messages', []))}")
|
||||
|
||||
my_db.close()
|
||||
print("✅ Done")
|
||||
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Redis State Store - Agent-First Example
|
||||
|
||||
Use Redis for state management with an Agent.
|
||||
|
||||
Docker Setup:
|
||||
docker run -d --name praison-redis -p 6379:6379 redis:7
|
||||
|
||||
Run:
|
||||
python state_redis.py
|
||||
|
||||
Expected Output:
|
||||
Agent responds with state persisted to Redis
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, db
|
||||
|
||||
print("=== Redis State Store (Agent-First) ===")
|
||||
|
||||
# Agent-first approach: use db parameter with Redis state store
|
||||
my_db = db(
|
||||
database_url="sqlite:///conversations.db", # Conversations
|
||||
state_url="redis://localhost:6379" # State/tracing
|
||||
)
|
||||
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant.",
|
||||
db=my_db,
|
||||
session_id="redis-state-example"
|
||||
)
|
||||
|
||||
# Chat - state is automatically managed via Redis
|
||||
response = agent.chat("Hello! Remember my favorite color is blue.")
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Second message to test state
|
||||
response2 = agent.chat("What is my favorite color?")
|
||||
print(f"Response: {response2}")
|
||||
|
||||
my_db.close()
|
||||
print("\n=== Demo Complete ===")
|
||||
|
||||
# --- Advanced: Direct Store Usage ---
|
||||
# from praisonai.persistence.factory import create_state_store
|
||||
# store = create_state_store("redis", url="redis://localhost:6379")
|
||||
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic Policy Engine Example for PraisonAI Agents.
|
||||
|
||||
This example demonstrates how to use the policy engine to:
|
||||
1. Create policies with rules
|
||||
2. Check if actions are allowed
|
||||
3. Block dangerous operations
|
||||
4. Use convenience policy creators
|
||||
|
||||
Usage:
|
||||
python basic_policy.py
|
||||
"""
|
||||
|
||||
from praisonaiagents.policy import (
|
||||
PolicyEngine, Policy, PolicyRule, PolicyAction, PolicyConfig,
|
||||
create_deny_tools_policy, create_read_only_policy
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("Policy Engine Demo")
|
||||
print("=" * 60)
|
||||
|
||||
# Create a policy engine
|
||||
engine = PolicyEngine()
|
||||
|
||||
# ==========================================================================
|
||||
# Policy 1: Block dangerous tools
|
||||
# ==========================================================================
|
||||
print("\n--- Creating Policies ---")
|
||||
|
||||
dangerous_tools_policy = Policy(
|
||||
name="block_dangerous",
|
||||
description="Block dangerous file operations",
|
||||
rules=[
|
||||
PolicyRule(
|
||||
action=PolicyAction.DENY,
|
||||
resource="tool:delete_*",
|
||||
reason="Delete operations are blocked",
|
||||
name="deny_delete"
|
||||
),
|
||||
PolicyRule(
|
||||
action=PolicyAction.DENY,
|
||||
resource="tool:rm_*",
|
||||
reason="Remove operations are blocked",
|
||||
name="deny_rm"
|
||||
),
|
||||
],
|
||||
priority=100
|
||||
)
|
||||
engine.add_policy(dangerous_tools_policy)
|
||||
print(f"✅ Added policy: {dangerous_tools_policy.name}")
|
||||
|
||||
# ==========================================================================
|
||||
# Policy 2: Allow read operations
|
||||
# ==========================================================================
|
||||
read_policy = Policy(
|
||||
name="allow_read",
|
||||
description="Allow read operations",
|
||||
rules=[
|
||||
PolicyRule(
|
||||
action=PolicyAction.ALLOW,
|
||||
resource="tool:read_*",
|
||||
name="allow_read"
|
||||
),
|
||||
PolicyRule(
|
||||
action=PolicyAction.ALLOW,
|
||||
resource="tool:list_*",
|
||||
name="allow_list"
|
||||
),
|
||||
]
|
||||
)
|
||||
engine.add_policy(read_policy)
|
||||
print(f"✅ Added policy: {read_policy.name}")
|
||||
|
||||
# ==========================================================================
|
||||
# Test policy checks
|
||||
# ==========================================================================
|
||||
print("\n--- Testing Policy Checks ---")
|
||||
|
||||
test_cases = [
|
||||
("tool:read_file", "Reading a file"),
|
||||
("tool:list_directory", "Listing directory"),
|
||||
("tool:delete_file", "Deleting a file"),
|
||||
("tool:rm_directory", "Removing directory"),
|
||||
("tool:write_file", "Writing a file"),
|
||||
]
|
||||
|
||||
for resource, description in test_cases:
|
||||
result = engine.check(resource, {})
|
||||
status = "✅ ALLOWED" if result.allowed else "🚫 DENIED"
|
||||
reason = f" ({result.reason})" if result.reason else ""
|
||||
print(f" {status}: {description}{reason}")
|
||||
|
||||
# ==========================================================================
|
||||
# Using convenience functions
|
||||
# ==========================================================================
|
||||
print("\n--- Using Convenience Functions ---")
|
||||
|
||||
# Create a read-only policy
|
||||
read_only = create_read_only_policy()
|
||||
print(f"✅ Created read-only policy with {len(read_only.rules)} rules")
|
||||
|
||||
# Create a deny tools policy
|
||||
deny_tools = create_deny_tools_policy(
|
||||
["execute_*", "shell_*", "system_*"],
|
||||
reason="System commands are blocked"
|
||||
)
|
||||
print(f"✅ Created deny-tools policy with {len(deny_tools.rules)} rules")
|
||||
|
||||
# ==========================================================================
|
||||
# Strict mode example
|
||||
# ==========================================================================
|
||||
print("\n--- Strict Mode Example ---")
|
||||
|
||||
strict_engine = PolicyEngine(PolicyConfig(strict_mode=True))
|
||||
|
||||
# In strict mode, unknown resources are denied
|
||||
result = strict_engine.check("tool:unknown_operation", {})
|
||||
print(f" Unknown operation in strict mode: {'DENIED' if not result.allowed else 'ALLOWED'}")
|
||||
|
||||
# ==========================================================================
|
||||
# Policy serialization
|
||||
# ==========================================================================
|
||||
print("\n--- Policy Serialization ---")
|
||||
|
||||
policy_dict = dangerous_tools_policy.to_dict()
|
||||
print(f" Serialized policy: {policy_dict['name']} with {len(policy_dict['rules'])} rules")
|
||||
|
||||
# Recreate from dict
|
||||
restored = Policy.from_dict(policy_dict)
|
||||
print(f" Restored policy: {restored.name}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Demo Complete!")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -15,6 +15,7 @@ Features demonstrated:
|
||||
from praisonaiagents import Agent
|
||||
import tempfile
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Create a sample knowledge document for demonstration
|
||||
sample_document = """
|
||||
@@ -91,38 +92,15 @@ doc_path = os.path.join(temp_dir, "ai_healthcare_guide.txt")
|
||||
with open(doc_path, "w") as f:
|
||||
f.write(sample_document)
|
||||
|
||||
# Create an agent with advanced knowledge management configuration
|
||||
# Create an agent with knowledge management
|
||||
knowledge_agent = Agent(
|
||||
name="AdvancedKnowledgeAgent",
|
||||
role="Healthcare AI Knowledge Expert",
|
||||
goal="Provide comprehensive answers about AI in healthcare using advanced knowledge retrieval",
|
||||
backstory="You are an expert in healthcare AI with access to comprehensive knowledge bases and advanced retrieval capabilities.",
|
||||
|
||||
# Advanced knowledge configuration
|
||||
# Knowledge configuration - simple and working
|
||||
knowledge=[doc_path],
|
||||
knowledge_config={
|
||||
"vector_store": {
|
||||
"provider": "chroma",
|
||||
"collection_name": "healthcare_ai_knowledge"
|
||||
},
|
||||
"chunking": {
|
||||
"strategy": "semantic", # Advanced semantic chunking
|
||||
"chunk_size": 500, # Optimal chunk size for retrieval
|
||||
"chunk_overlap": 50, # Overlap for context preservation
|
||||
"separators": ["\n\n", "\n", ".", "!", "?"] # Smart separators
|
||||
},
|
||||
"retrieval": {
|
||||
"search_type": "similarity",
|
||||
"k": 5, # Retrieve top 5 most relevant chunks
|
||||
"score_threshold": 0.7, # Minimum relevance score
|
||||
"rerank": True # Enable reranking for better results
|
||||
},
|
||||
"embedding": {
|
||||
"provider": "openai",
|
||||
"model": "text-embedding-3-small", # Efficient embedding model
|
||||
"dimensions": 1536
|
||||
}
|
||||
},
|
||||
|
||||
instructions="""You are an expert in healthcare AI. Use the knowledge base to provide
|
||||
comprehensive, accurate answers. Always cite specific information from the documents
|
||||
@@ -180,7 +158,6 @@ relationship_result = knowledge_agent.start(
|
||||
print(f"Relationship analysis result:\n{relationship_result}\n")
|
||||
|
||||
# Clean up temporary files
|
||||
import shutil
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
print("="*80)
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
24/7 News Checker Agent Example
|
||||
|
||||
This example demonstrates how to create a continuously running agent
|
||||
that checks for AI news every hour and prints the results.
|
||||
|
||||
Usage:
|
||||
python news_checker_agent.py
|
||||
|
||||
The agent will:
|
||||
1. Run immediately on start
|
||||
2. Check for latest AI news every 1 hour
|
||||
3. Print results to console
|
||||
4. Continue running until stopped (Ctrl+C)
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Add parent directory to path for imports
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../..'))
|
||||
|
||||
from praisonaiagents import Agent
|
||||
from praisonai.agent_scheduler import AgentScheduler
|
||||
from tools import search_tool
|
||||
|
||||
|
||||
def on_success(result):
|
||||
"""Callback function called when agent execution succeeds."""
|
||||
print("\n" + "="*80)
|
||||
print(f"✅ SUCCESS - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("="*80)
|
||||
print(result)
|
||||
print("="*80 + "\n")
|
||||
|
||||
|
||||
def on_failure(error):
|
||||
"""Callback function called when agent execution fails."""
|
||||
print("\n" + "="*80)
|
||||
print(f"❌ FAILURE - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("="*80)
|
||||
print(f"Error: {error}")
|
||||
print("="*80 + "\n")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to set up and run the scheduled news checker agent."""
|
||||
|
||||
print("\n🤖 Starting 24/7 News Checker Agent")
|
||||
print("="*80)
|
||||
|
||||
# Create the agent with web search capability
|
||||
agent = Agent(
|
||||
name="NewsChecker",
|
||||
role="AI News Monitor",
|
||||
goal="Monitor and summarize the latest AI and technology news",
|
||||
backstory="""You are an expert AI news analyst who stays up-to-date
|
||||
with the latest developments in artificial intelligence, machine learning,
|
||||
and technology. You provide concise, accurate summaries of important news.""",
|
||||
tools=[search_tool],
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# Define the task
|
||||
task = """Search for the latest AI news from today.
|
||||
Focus on major developments, breakthroughs, or announcements.
|
||||
Provide a summary of the top 3-5 most important news items.
|
||||
Include the source and key details for each item."""
|
||||
|
||||
# Create scheduler with callbacks
|
||||
scheduler = AgentScheduler(
|
||||
agent=agent,
|
||||
task=task,
|
||||
on_success=on_success,
|
||||
on_failure=on_failure
|
||||
)
|
||||
|
||||
print(f"Agent: {agent.name}")
|
||||
print(f"Task: {task}")
|
||||
print(f"Schedule: Every 1 hour")
|
||||
print("="*80)
|
||||
print("\n⏰ Starting scheduler... (Press Ctrl+C to stop)\n")
|
||||
|
||||
# Start the scheduler
|
||||
# - "hourly" or "*/1h" = every 1 hour
|
||||
# - run_immediately=True = run once before starting the schedule
|
||||
scheduler.start(
|
||||
schedule_expr="hourly", # Run every hour
|
||||
max_retries=3, # Retry up to 3 times on failure
|
||||
run_immediately=True # Run immediately on start
|
||||
)
|
||||
|
||||
try:
|
||||
# Keep the main thread alive
|
||||
while scheduler.is_running:
|
||||
import time
|
||||
time.sleep(1)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n🛑 Stopping scheduler...")
|
||||
scheduler.stop()
|
||||
|
||||
# Print final statistics
|
||||
stats = scheduler.get_stats()
|
||||
print("\n📊 Final Statistics:")
|
||||
print(f" Total Executions: {stats['total_executions']}")
|
||||
print(f" Successful: {stats['successful_executions']}")
|
||||
print(f" Failed: {stats['failed_executions']}")
|
||||
print(f" Success Rate: {stats['success_rate']:.1f}%")
|
||||
print("\n✅ Agent stopped successfully\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,143 @@
|
||||
"""
|
||||
Live News Checker Agent - 24/7 Scheduled Agent
|
||||
|
||||
This example demonstrates a real working agent that checks AI news
|
||||
every hour using the AgentScheduler with actual API calls.
|
||||
|
||||
Requirements:
|
||||
- OPENAI_API_KEY environment variable set
|
||||
- praisonaiagents package installed
|
||||
|
||||
Usage:
|
||||
python news_checker_live.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../..'))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../../..'))
|
||||
|
||||
from praisonaiagents import Agent
|
||||
from praisonai.scheduler import AgentScheduler
|
||||
|
||||
# Import search_tool from root tools.py
|
||||
try:
|
||||
from tools import search_tool
|
||||
except ImportError:
|
||||
# Fallback: create inline search tool
|
||||
from duckduckgo_search import DDGS
|
||||
|
||||
def search_tool(query: str) -> list:
|
||||
"""Search the web using DuckDuckGo."""
|
||||
try:
|
||||
results = []
|
||||
ddgs = DDGS()
|
||||
for result in ddgs.text(keywords=query, max_results=5):
|
||||
results.append({
|
||||
"title": result.get("title", ""),
|
||||
"url": result.get("href", ""),
|
||||
"snippet": result.get("body", ""),
|
||||
})
|
||||
return results
|
||||
except Exception as e:
|
||||
print(f"Search error: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def on_success(result):
|
||||
"""Callback when agent execution succeeds."""
|
||||
print("\n" + "="*80)
|
||||
print(f"✅ SUCCESS - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("="*80)
|
||||
print(result)
|
||||
print("="*80 + "\n")
|
||||
|
||||
|
||||
def on_failure(error):
|
||||
"""Callback when agent execution fails."""
|
||||
print("\n" + "="*80)
|
||||
print(f"❌ FAILURE - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print("="*80)
|
||||
print(f"Error: {error}")
|
||||
print("="*80 + "\n")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to run the scheduled news checker."""
|
||||
|
||||
# Check for API key
|
||||
if not os.getenv("OPENAI_API_KEY"):
|
||||
print("❌ Error: OPENAI_API_KEY environment variable not set")
|
||||
print("Please set it with: export OPENAI_API_KEY=your_key_here")
|
||||
sys.exit(1)
|
||||
|
||||
print("\n🤖 Starting 24/7 AI News Checker Agent")
|
||||
print("="*80)
|
||||
|
||||
# Create the agent with web search capability
|
||||
agent = Agent(
|
||||
name="AI News Monitor",
|
||||
role="Technology News Analyst",
|
||||
goal="Monitor and summarize the latest AI and technology news",
|
||||
backstory="""You are an expert AI news analyst who stays up-to-date
|
||||
with the latest developments in artificial intelligence, machine learning,
|
||||
and technology. You provide concise, accurate summaries of important news.""",
|
||||
tools=[search_tool],
|
||||
verbose=True,
|
||||
self_reflect=False # Disable reflection for faster execution
|
||||
)
|
||||
|
||||
# Define the task
|
||||
task = """Search for the latest AI news from today.
|
||||
Focus on major developments, breakthroughs, or announcements.
|
||||
Provide a summary of the top 3 most important news items.
|
||||
Include the source and key details for each item."""
|
||||
|
||||
# Create scheduler with callbacks
|
||||
scheduler = AgentScheduler(
|
||||
agent=agent,
|
||||
task=task,
|
||||
on_success=on_success,
|
||||
on_failure=on_failure
|
||||
)
|
||||
|
||||
print(f"Agent: {agent.name}")
|
||||
print(f"Task: {task}")
|
||||
print(f"Schedule: Every 1 hour")
|
||||
print("="*80)
|
||||
print("\n⏰ Starting scheduler... (Press Ctrl+C to stop)\n")
|
||||
|
||||
# Start the scheduler
|
||||
# For testing: use "*/2m" (every 2 minutes) instead of "hourly"
|
||||
# For production: use "hourly"
|
||||
scheduler.start(
|
||||
schedule_expr="*/2m", # Every 2 minutes for testing
|
||||
max_retries=3,
|
||||
run_immediately=True # Run once immediately
|
||||
)
|
||||
|
||||
try:
|
||||
# Keep the main thread alive
|
||||
while scheduler.is_running:
|
||||
import time
|
||||
time.sleep(1)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n🛑 Stopping scheduler...")
|
||||
scheduler.stop()
|
||||
|
||||
# Print final statistics
|
||||
stats = scheduler.get_stats()
|
||||
print("\n📊 Final Statistics:")
|
||||
print(f" Total Executions: {stats['total_executions']}")
|
||||
print(f" Successful: {stats['successful_executions']}")
|
||||
print(f" Failed: {stats['failed_executions']}")
|
||||
print(f" Success Rate: {stats['success_rate']:.1f}%")
|
||||
print("\n✅ Agent stopped successfully\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Simple test script for 24/7 Agent Scheduler
|
||||
|
||||
This script demonstrates the basic usage of AgentScheduler
|
||||
for running agents periodically.
|
||||
|
||||
Usage:
|
||||
python simple_test.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../..'))
|
||||
|
||||
from unittest.mock import Mock
|
||||
from praisonai.scheduler import AgentScheduler
|
||||
|
||||
# Create a mock agent for testing
|
||||
mock_agent = Mock()
|
||||
mock_agent.name = "TestAgent"
|
||||
mock_agent.start = Mock(return_value="Test execution successful!")
|
||||
|
||||
# Create scheduler
|
||||
scheduler = AgentScheduler(
|
||||
agent=mock_agent,
|
||||
task="Test task execution"
|
||||
)
|
||||
|
||||
print("🤖 Testing AgentScheduler")
|
||||
print("=" * 60)
|
||||
|
||||
# Test 1: Execute once
|
||||
print("\n✅ Test 1: Execute once")
|
||||
result = scheduler.execute_once()
|
||||
print(f"Result: {result}")
|
||||
|
||||
# Test 2: Get stats
|
||||
print("\n✅ Test 2: Get statistics")
|
||||
stats = scheduler.get_stats()
|
||||
print(f"Stats: {stats}")
|
||||
|
||||
# Test 3: Start scheduler (will run every 5 seconds)
|
||||
print("\n✅ Test 3: Start scheduler (*/5s)")
|
||||
scheduler.start("*/5s", run_immediately=True)
|
||||
|
||||
import time
|
||||
print("Running for 12 seconds...")
|
||||
time.sleep(12)
|
||||
|
||||
# Stop scheduler
|
||||
print("\n✅ Test 4: Stop scheduler")
|
||||
scheduler.stop()
|
||||
|
||||
# Final stats
|
||||
print("\n📊 Final Statistics:")
|
||||
final_stats = scheduler.get_stats()
|
||||
for key, value in final_stats.items():
|
||||
print(f" {key}: {value}")
|
||||
|
||||
print("\n✅ All tests passed!")
|
||||
print("=" * 60)
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run all examples and collect PASS/SKIP/FAIL results."""
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
EXAMPLES_DIR = Path(__file__).parent
|
||||
RESULTS = []
|
||||
|
||||
def run_example(path: Path) -> tuple:
|
||||
"""Run an example and return (name, status, reason)."""
|
||||
name = f"{path.parent.name}/{path.name}"
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[sys.executable, str(path)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=60,
|
||||
env={**os.environ, "PYTHONPATH": str(EXAMPLES_DIR.parent / "src")}
|
||||
)
|
||||
output = result.stdout + result.stderr
|
||||
if "PASSED" in output:
|
||||
return (name, "PASS", "")
|
||||
elif "SKIPPED" in output:
|
||||
return (name, "SKIP", output.split("SKIPPED:")[-1].strip()[:50])
|
||||
elif result.returncode != 0:
|
||||
error = output.strip().split("\n")[-1][:80]
|
||||
return (name, "FAIL", error)
|
||||
else:
|
||||
return (name, "PASS", "")
|
||||
except subprocess.TimeoutExpired:
|
||||
return (name, "FAIL", "Timeout")
|
||||
except Exception as e:
|
||||
return (name, "FAIL", str(e)[:50])
|
||||
|
||||
def main():
|
||||
print("=" * 70)
|
||||
print("EXAMPLE RUNNER - PASS/SKIP/FAIL SUMMARY")
|
||||
print("=" * 70)
|
||||
|
||||
# Find all example files
|
||||
examples = []
|
||||
for subdir in ["db", "vector", "observability", "multi_agent", "workflows"]:
|
||||
subpath = EXAMPLES_DIR / subdir
|
||||
if subpath.exists():
|
||||
examples.extend(sorted(subpath.glob("*_wow.py")))
|
||||
|
||||
print(f"\nFound {len(examples)} examples to run\n")
|
||||
|
||||
for ex in examples:
|
||||
name, status, reason = run_example(ex)
|
||||
RESULTS.append((name, status, reason))
|
||||
icon = {"PASS": "✅", "SKIP": "⏭️", "FAIL": "❌"}.get(status, "?")
|
||||
reason_str = f" ({reason})" if reason else ""
|
||||
print(f"{icon} {status:4} | {name:45} {reason_str}")
|
||||
|
||||
# Summary
|
||||
print("\n" + "=" * 70)
|
||||
passed = sum(1 for _, s, _ in RESULTS if s == "PASS")
|
||||
skipped = sum(1 for _, s, _ in RESULTS if s == "SKIP")
|
||||
failed = sum(1 for _, s, _ in RESULTS if s == "FAIL")
|
||||
print(f"SUMMARY: {passed} PASS | {skipped} SKIP | {failed} FAIL | {len(RESULTS)} TOTAL")
|
||||
print("=" * 70)
|
||||
|
||||
return 0 if failed == 0 else 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,14 @@
|
||||
framework: praisonai
|
||||
|
||||
agents:
|
||||
- name: "5 Second Timer"
|
||||
role: "Timer Agent"
|
||||
instructions: "Display the current time"
|
||||
verbose: true
|
||||
|
||||
task: "Show current time"
|
||||
|
||||
schedule:
|
||||
interval: "*/5s"
|
||||
max_retries: 3
|
||||
run_immediately: true
|
||||
@@ -0,0 +1,14 @@
|
||||
framework: praisonai
|
||||
|
||||
agents:
|
||||
- name: "Counter Agent"
|
||||
role: "Counter"
|
||||
instructions: "Count from 1 to 5, incrementing by 1 each time. Just output the numbers clearly."
|
||||
verbose: true
|
||||
|
||||
task: "Print numbers 1, 2, 3, 4, 5 (one number per line)"
|
||||
|
||||
schedule:
|
||||
interval: "*/5s"
|
||||
max_retries: 3
|
||||
run_immediately: true
|
||||
@@ -0,0 +1,16 @@
|
||||
framework: praisonai
|
||||
|
||||
agents:
|
||||
- name: "Counter Agent with Limits"
|
||||
role: "Counter"
|
||||
instructions: "Count from 1 to 5, incrementing by 1 each time. Just output the numbers clearly."
|
||||
verbose: true
|
||||
|
||||
task: "Print numbers 1, 2, 3, 4, 5 (one number per line)"
|
||||
|
||||
schedule:
|
||||
interval: "*/5s" # Run every 5 seconds
|
||||
max_retries: 3 # Retry up to 3 times on failure
|
||||
run_immediately: true # Run once immediately on start
|
||||
timeout: 30 # Max 30 seconds per execution
|
||||
max_cost: 0.01 # Stop after spending $0.01 USD
|
||||
@@ -0,0 +1,15 @@
|
||||
framework: praisonai
|
||||
|
||||
agents:
|
||||
- name: "Budget Test Agent"
|
||||
role: "Tester"
|
||||
instructions: "Count from 1 to 3"
|
||||
verbose: true
|
||||
|
||||
task: "Print numbers 1, 2, 3"
|
||||
|
||||
schedule:
|
||||
interval: "*/3s"
|
||||
max_retries: 2
|
||||
run_immediately: true
|
||||
# No max_cost specified - should default to $1.00
|
||||
@@ -0,0 +1,73 @@
|
||||
"""
|
||||
Basic Agent Skills Usage Example
|
||||
|
||||
This example demonstrates how to use Agent Skills with PraisonAI Agents.
|
||||
Skills are modular capabilities that can be loaded and used by agents.
|
||||
"""
|
||||
|
||||
from praisonaiagents import Agent, SkillManager
|
||||
|
||||
# Example 1: Using SkillManager directly
|
||||
print("=" * 50)
|
||||
print("Example 1: Using SkillManager directly")
|
||||
print("=" * 50)
|
||||
|
||||
# Create a skill manager
|
||||
manager = SkillManager()
|
||||
|
||||
# Discover skills from a directory
|
||||
# This scans the directory for subdirectories containing SKILL.md files
|
||||
skill_count = manager.discover(["./pdf-processing"], include_defaults=False)
|
||||
print(f"Discovered {skill_count} skill(s)")
|
||||
|
||||
# List available skills
|
||||
for skill in manager:
|
||||
print(f" - {skill.properties.name}: {skill.properties.description[:50]}...")
|
||||
|
||||
# Generate prompt XML for system prompt injection
|
||||
prompt_xml = manager.to_prompt()
|
||||
print("\nGenerated prompt XML:")
|
||||
print(prompt_xml)
|
||||
|
||||
# Example 2: Using skills with an Agent
|
||||
print("\n" + "=" * 50)
|
||||
print("Example 2: Using skills with an Agent")
|
||||
print("=" * 50)
|
||||
|
||||
# Create an agent with skills
|
||||
# Skills are lazy-loaded only when accessed
|
||||
agent = Agent(
|
||||
name="PDF Assistant",
|
||||
instructions="You are a helpful assistant that can process PDF documents.",
|
||||
skills=["./pdf-processing"], # Direct skill paths
|
||||
)
|
||||
|
||||
# Access the skill manager through the agent
|
||||
if agent.skill_manager:
|
||||
print(f"Agent has {len(agent.skill_manager)} skill(s) loaded")
|
||||
|
||||
# Get the skills prompt for system prompt injection
|
||||
skills_prompt = agent.get_skills_prompt()
|
||||
print("\nAgent skills prompt:")
|
||||
print(skills_prompt)
|
||||
|
||||
# Example 3: Discovering skills from multiple directories
|
||||
print("\n" + "=" * 50)
|
||||
print("Example 3: Using skills_dirs for discovery")
|
||||
print("=" * 50)
|
||||
|
||||
# Create an agent that discovers skills from directories
|
||||
agent_with_discovery = Agent(
|
||||
name="Multi-Skill Agent",
|
||||
instructions="You are a versatile assistant with multiple skills.",
|
||||
skills_dirs=["./"], # Scan current directory for skill subdirectories
|
||||
)
|
||||
|
||||
if agent_with_discovery.skill_manager:
|
||||
print(f"Discovered {len(agent_with_discovery.skill_manager)} skill(s)")
|
||||
for name in agent_with_discovery.skill_manager.skill_names:
|
||||
print(f" - {name}")
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
print("Examples complete!")
|
||||
print("=" * 50)
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Example: Creating Skills with PraisonAI CLI
|
||||
|
||||
This example demonstrates how to create Agent Skills using the CLI.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import tempfile
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def example_create_skill_with_template():
|
||||
"""Create a skill using template mode (no API key required)."""
|
||||
print("=" * 60)
|
||||
print("Example 1: Create skill with template")
|
||||
print("=" * 60)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
result = subprocess.run([
|
||||
"praisonai", "skills", "create",
|
||||
"--name", "my-template-skill",
|
||||
"--description", "A skill for processing text files",
|
||||
"--author", "example-team",
|
||||
"--license", "MIT",
|
||||
"--template",
|
||||
"--output-dir", tmpdir
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
if result.returncode == 0:
|
||||
skill_md = Path(tmpdir) / "my-template-skill" / "SKILL.md"
|
||||
print(f"\nGenerated SKILL.md:\n{skill_md.read_text()[:500]}...")
|
||||
else:
|
||||
print(f"Error: {result.stderr}")
|
||||
|
||||
|
||||
def example_create_skill_with_ai():
|
||||
"""Create a skill using AI generation (requires API key)."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 2: Create skill with AI generation")
|
||||
print("=" * 60)
|
||||
|
||||
if not os.environ.get("OPENAI_API_KEY"):
|
||||
print("Skipping: OPENAI_API_KEY not set")
|
||||
return
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
result = subprocess.run([
|
||||
"praisonai", "skills", "create",
|
||||
"--name", "csv-analyzer",
|
||||
"--description", "Analyze CSV files and generate statistical reports",
|
||||
"--output-dir", tmpdir
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
if result.returncode == 0:
|
||||
skill_md = Path(tmpdir) / "csv-analyzer" / "SKILL.md"
|
||||
print(f"\nGenerated SKILL.md:\n{skill_md.read_text()[:800]}...")
|
||||
|
||||
# Check if script was generated
|
||||
script_path = Path(tmpdir) / "csv-analyzer" / "scripts" / "skill.py"
|
||||
if script_path.exists():
|
||||
print(f"\nGenerated skill.py:\n{script_path.read_text()[:500]}...")
|
||||
|
||||
|
||||
def example_create_skill_with_script():
|
||||
"""Create a skill with auto-generated Python script."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 3: Create skill with script")
|
||||
print("=" * 60)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
result = subprocess.run([
|
||||
"praisonai", "skills", "create",
|
||||
"--name", "data-processor",
|
||||
"--description", "Process and transform data files",
|
||||
"--template",
|
||||
"--script",
|
||||
"--output-dir", tmpdir
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
if result.returncode == 0:
|
||||
script_path = Path(tmpdir) / "data-processor" / "scripts" / "skill.py"
|
||||
if script_path.exists():
|
||||
print(f"\nGenerated skill.py:\n{script_path.read_text()}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
example_create_skill_with_template()
|
||||
example_create_skill_with_ai()
|
||||
example_create_skill_with_script()
|
||||
@@ -0,0 +1,163 @@
|
||||
"""
|
||||
Custom Skill Creation Example
|
||||
|
||||
This example demonstrates how to programmatically create and validate
|
||||
custom Agent Skills using PraisonAI Agents.
|
||||
"""
|
||||
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
from praisonaiagents.skills import (
|
||||
SkillManager,
|
||||
SkillLoader,
|
||||
validate,
|
||||
read_properties,
|
||||
)
|
||||
|
||||
|
||||
def create_custom_skill(
|
||||
name: str,
|
||||
description: str,
|
||||
instructions: str,
|
||||
base_dir: str = None
|
||||
) -> Path:
|
||||
"""Create a custom skill programmatically.
|
||||
|
||||
Args:
|
||||
name: Skill name (kebab-case)
|
||||
description: What the skill does
|
||||
instructions: Markdown instructions for the skill
|
||||
base_dir: Directory to create skill in (default: temp dir)
|
||||
|
||||
Returns:
|
||||
Path to the created skill directory
|
||||
"""
|
||||
if base_dir is None:
|
||||
base_dir = tempfile.mkdtemp()
|
||||
|
||||
skill_dir = Path(base_dir) / name
|
||||
skill_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Create SKILL.md
|
||||
skill_md_content = f"""---
|
||||
name: {name}
|
||||
description: {description}
|
||||
license: Apache-2.0
|
||||
metadata:
|
||||
author: custom
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
{instructions}
|
||||
"""
|
||||
(skill_dir / "SKILL.md").write_text(skill_md_content)
|
||||
|
||||
# Create optional directories
|
||||
(skill_dir / "scripts").mkdir(exist_ok=True)
|
||||
(skill_dir / "references").mkdir(exist_ok=True)
|
||||
(skill_dir / "assets").mkdir(exist_ok=True)
|
||||
|
||||
return skill_dir
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("Custom Skill Creation Example")
|
||||
print("=" * 60)
|
||||
|
||||
# Create a custom skill
|
||||
print("\n1. Creating a custom skill...")
|
||||
|
||||
skill_path = create_custom_skill(
|
||||
name="code-review",
|
||||
description="Review code for best practices, bugs, and improvements. Use when asked to review or analyze code quality.",
|
||||
instructions="""
|
||||
# Code Review Skill
|
||||
|
||||
## Overview
|
||||
This skill enables thorough code review with focus on:
|
||||
- Code quality and readability
|
||||
- Potential bugs and edge cases
|
||||
- Performance considerations
|
||||
- Security vulnerabilities
|
||||
- Best practices adherence
|
||||
|
||||
## Instructions
|
||||
|
||||
When reviewing code:
|
||||
|
||||
1. **Read the code carefully** - Understand the purpose and flow
|
||||
2. **Check for bugs** - Look for null checks, edge cases, error handling
|
||||
3. **Evaluate readability** - Variable names, comments, structure
|
||||
4. **Consider performance** - Time/space complexity, unnecessary operations
|
||||
5. **Security review** - Input validation, injection risks, data exposure
|
||||
6. **Suggest improvements** - Provide actionable recommendations
|
||||
|
||||
## Output Format
|
||||
|
||||
Structure your review as:
|
||||
- Summary: Brief overview of the code
|
||||
- Issues: List of problems found (severity: high/medium/low)
|
||||
- Suggestions: Recommended improvements
|
||||
- Positive aspects: What's done well
|
||||
"""
|
||||
)
|
||||
|
||||
print(f" Created skill at: {skill_path}")
|
||||
|
||||
# Validate the skill
|
||||
print("\n2. Validating the skill...")
|
||||
errors = validate(skill_path)
|
||||
|
||||
if errors:
|
||||
print(" Validation errors:")
|
||||
for error in errors:
|
||||
print(f" - {error}")
|
||||
else:
|
||||
print(" ✓ Skill is valid!")
|
||||
|
||||
# Load and inspect the skill
|
||||
print("\n3. Loading skill properties...")
|
||||
props = read_properties(skill_path)
|
||||
print(f" Name: {props.name}")
|
||||
print(f" Description: {props.description[:60]}...")
|
||||
print(f" License: {props.license}")
|
||||
|
||||
# Use with SkillLoader for progressive loading
|
||||
print("\n4. Using SkillLoader for progressive disclosure...")
|
||||
loader = SkillLoader()
|
||||
|
||||
# Level 1: Load metadata only
|
||||
skill = loader.load_metadata(str(skill_path))
|
||||
print(f" Level 1 - Metadata loaded: {skill.properties.name}")
|
||||
print(f" Instructions loaded: {skill.is_activated}")
|
||||
|
||||
# Level 2: Activate (load instructions)
|
||||
loader.activate(skill)
|
||||
print(f" Level 2 - Activated: {skill.is_activated}")
|
||||
print(f" Instructions preview: {skill.instructions[:100]}...")
|
||||
|
||||
# Use with SkillManager
|
||||
print("\n5. Using with SkillManager...")
|
||||
manager = SkillManager()
|
||||
manager.add_skill(str(skill_path))
|
||||
|
||||
# Generate prompt XML
|
||||
prompt = manager.to_prompt()
|
||||
print(" Generated prompt XML:")
|
||||
print(prompt)
|
||||
|
||||
# Clean up
|
||||
print("\n6. Cleanup...")
|
||||
import shutil
|
||||
shutil.rmtree(skill_path.parent)
|
||||
print(" Temporary files removed.")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Example complete!")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Example: Multi-Agent CLI Usage
|
||||
|
||||
This example demonstrates how to use the praisonai agents command
|
||||
to define and run multiple agents from the command line.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
|
||||
def example_single_agent():
|
||||
"""Run a single agent with a simple task."""
|
||||
print("=" * 60)
|
||||
print("Example 1: Single Agent")
|
||||
print("=" * 60)
|
||||
|
||||
result = subprocess.run([
|
||||
"praisonai", "agents", "run",
|
||||
"--agent", "assistant:Helper",
|
||||
"--task", "What is the capital of France?"
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
if result.returncode != 0:
|
||||
print(f"Error: {result.stderr}")
|
||||
|
||||
|
||||
def example_agent_with_tools():
|
||||
"""Run an agent with tools."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 2: Agent with Tools")
|
||||
print("=" * 60)
|
||||
|
||||
result = subprocess.run([
|
||||
"praisonai", "agents", "run",
|
||||
"--agent", "researcher:Research Analyst:internet_search",
|
||||
"--task", "Find the latest news about renewable energy"
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
|
||||
def example_multiple_agents_sequential():
|
||||
"""Run multiple agents in sequential mode."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 3: Multiple Agents (Sequential)")
|
||||
print("=" * 60)
|
||||
|
||||
result = subprocess.run([
|
||||
"praisonai", "agents", "run",
|
||||
"--agent", "researcher:Research Analyst:internet_search",
|
||||
"--agent", "writer:Content Writer:write_file",
|
||||
"--task", "Research AI trends and write a brief summary"
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
|
||||
def example_multiple_agents_parallel():
|
||||
"""Run multiple agents in parallel mode."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 4: Multiple Agents (Parallel)")
|
||||
print("=" * 60)
|
||||
|
||||
result = subprocess.run([
|
||||
"praisonai", "agents", "run",
|
||||
"--agent", "analyst1:Market Analyst",
|
||||
"--agent", "analyst2:Tech Analyst",
|
||||
"--process", "parallel",
|
||||
"--task", "Analyze the current state of AI industry"
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
|
||||
def example_with_custom_llm():
|
||||
"""Run agents with a custom LLM model."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 5: Custom LLM Model")
|
||||
print("=" * 60)
|
||||
|
||||
result = subprocess.run([
|
||||
"praisonai", "agents", "run",
|
||||
"--agent", "coder:Developer:execute_command",
|
||||
"--llm", "gpt-4o-mini",
|
||||
"--task", "Write a simple hello world Python script"
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
|
||||
def example_with_instructions():
|
||||
"""Run agents with additional instructions."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 6: With Additional Instructions")
|
||||
print("=" * 60)
|
||||
|
||||
result = subprocess.run([
|
||||
"praisonai", "agents", "run",
|
||||
"--agent", "analyst:Data Analyst",
|
||||
"--instructions", "Be concise and provide only key insights",
|
||||
"--task", "Explain the benefits of using AI in healthcare"
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
|
||||
def example_list_tools():
|
||||
"""List available tools for agents."""
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 7: List Available Tools")
|
||||
print("=" * 60)
|
||||
|
||||
result = subprocess.run([
|
||||
"praisonai", "agents", "list"
|
||||
], capture_output=True, text=True)
|
||||
|
||||
print(result.stdout)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Check for API key
|
||||
if not os.environ.get("OPENAI_API_KEY"):
|
||||
print("Warning: OPENAI_API_KEY not set. Some examples may fail.")
|
||||
print()
|
||||
|
||||
# Run examples
|
||||
example_list_tools()
|
||||
example_single_agent()
|
||||
# Uncomment to run more examples:
|
||||
# example_agent_with_tools()
|
||||
# example_multiple_agents_sequential()
|
||||
# example_multiple_agents_parallel()
|
||||
# example_with_custom_llm()
|
||||
# example_with_instructions()
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: pdf-processing
|
||||
description: Process and extract information from PDF documents. Use this skill when the user asks to read, analyze, or extract data from PDF files.
|
||||
license: Apache-2.0
|
||||
compatibility: Works with PraisonAI Agents
|
||||
metadata:
|
||||
author: praisonai
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
# PDF Processing Skill
|
||||
|
||||
## Overview
|
||||
|
||||
This skill enables agents to process PDF documents, extract text content, and analyze the information within them.
|
||||
|
||||
## When to Use
|
||||
|
||||
Activate this skill when:
|
||||
- User asks to read or analyze a PDF file
|
||||
- User needs to extract text from a PDF
|
||||
- User wants to summarize a PDF document
|
||||
- User needs to search for information within a PDF
|
||||
|
||||
## Instructions
|
||||
|
||||
1. First, verify the PDF file exists at the specified path
|
||||
2. Use appropriate tools to read the PDF content
|
||||
3. Extract text while preserving structure where possible
|
||||
4. For large PDFs, process in chunks to manage context
|
||||
5. Summarize or analyze based on user's specific request
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Always confirm the file path before processing
|
||||
- Handle encrypted PDFs gracefully with appropriate error messages
|
||||
- For scanned PDFs, note that OCR may be required
|
||||
- Preserve important formatting like tables and lists
|
||||
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Basic Thinking Budgets Example for PraisonAI Agents.
|
||||
|
||||
This example demonstrates how to use thinking budgets to:
|
||||
1. Configure token budgets for extended thinking
|
||||
2. Use predefined budget levels
|
||||
3. Track thinking usage
|
||||
4. Adapt budgets based on complexity
|
||||
|
||||
Usage:
|
||||
python basic_thinking.py
|
||||
"""
|
||||
|
||||
from praisonaiagents.thinking import (
|
||||
ThinkingBudget, ThinkingConfig, ThinkingUsage, ThinkingTracker
|
||||
)
|
||||
from praisonaiagents.thinking.budget import BudgetLevel
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("Thinking Budgets Demo")
|
||||
print("=" * 60)
|
||||
|
||||
# ==========================================================================
|
||||
# Budget Levels
|
||||
# ==========================================================================
|
||||
print("\n--- Budget Levels ---")
|
||||
|
||||
levels = [
|
||||
("Minimal", ThinkingBudget.minimal()),
|
||||
("Low", ThinkingBudget.low()),
|
||||
("Medium", ThinkingBudget.medium()),
|
||||
("High", ThinkingBudget.high()),
|
||||
("Maximum", ThinkingBudget.maximum()),
|
||||
]
|
||||
|
||||
for name, budget in levels:
|
||||
print(f" {name}: {budget.max_tokens:,} tokens")
|
||||
|
||||
# ==========================================================================
|
||||
# Custom Budget
|
||||
# ==========================================================================
|
||||
print("\n--- Custom Budget ---")
|
||||
|
||||
custom_budget = ThinkingBudget(
|
||||
max_tokens=12000,
|
||||
min_tokens=2000,
|
||||
adaptive=True,
|
||||
max_time_seconds=120.0
|
||||
)
|
||||
print(f" Max tokens: {custom_budget.max_tokens:,}")
|
||||
print(f" Min tokens: {custom_budget.min_tokens:,}")
|
||||
print(f" Adaptive: {custom_budget.adaptive}")
|
||||
print(f" Time limit: {custom_budget.max_time_seconds}s")
|
||||
|
||||
# ==========================================================================
|
||||
# Complexity-Based Scaling
|
||||
# ==========================================================================
|
||||
print("\n--- Complexity-Based Token Allocation ---")
|
||||
|
||||
budget = ThinkingBudget(
|
||||
max_tokens=16000,
|
||||
min_tokens=2000,
|
||||
adaptive=True
|
||||
)
|
||||
|
||||
complexities = [0.0, 0.25, 0.5, 0.75, 1.0]
|
||||
for complexity in complexities:
|
||||
tokens = budget.get_tokens_for_complexity(complexity)
|
||||
bar = "█" * int(tokens / 1000)
|
||||
print(f" Complexity {complexity:.2f}: {tokens:,} tokens {bar}")
|
||||
|
||||
# ==========================================================================
|
||||
# Usage Tracking
|
||||
# ==========================================================================
|
||||
print("\n--- Usage Tracking ---")
|
||||
|
||||
usage = ThinkingUsage(
|
||||
budget_tokens=8000,
|
||||
tokens_used=5000,
|
||||
time_seconds=30.0,
|
||||
budget_time=60.0
|
||||
)
|
||||
|
||||
print(f" Tokens used: {usage.tokens_used:,} / {usage.budget_tokens:,}")
|
||||
print(f" Tokens remaining: {usage.tokens_remaining:,}")
|
||||
print(f" Utilization: {usage.token_utilization:.1%}")
|
||||
print(f" Over budget: {usage.is_over_budget}")
|
||||
print(f" Time remaining: {usage.time_remaining}s")
|
||||
|
||||
# ==========================================================================
|
||||
# Session Tracking
|
||||
# ==========================================================================
|
||||
print("\n--- Session Tracking ---")
|
||||
|
||||
tracker = ThinkingTracker()
|
||||
|
||||
# Simulate multiple thinking sessions
|
||||
sessions = [
|
||||
(8000, 4000, 20.0),
|
||||
(8000, 6000, 35.0),
|
||||
(16000, 12000, 60.0),
|
||||
(8000, 9000, 45.0), # Over budget
|
||||
]
|
||||
|
||||
for budget_tokens, tokens_used, time_seconds in sessions:
|
||||
session = tracker.start_session(budget_tokens=budget_tokens)
|
||||
tracker.end_session(session, tokens_used=tokens_used, time_seconds=time_seconds)
|
||||
|
||||
summary = tracker.get_summary()
|
||||
print(f" Total sessions: {summary['session_count']}")
|
||||
print(f" Total tokens used: {summary['total_tokens_used']:,}")
|
||||
print(f" Average tokens/session: {summary['average_tokens_per_session']:,.0f}")
|
||||
print(f" Average utilization: {summary['average_utilization']:.1%}")
|
||||
print(f" Over-budget sessions: {summary['over_budget_count']}")
|
||||
|
||||
# ==========================================================================
|
||||
# Serialization
|
||||
# ==========================================================================
|
||||
print("\n--- Serialization ---")
|
||||
|
||||
budget = ThinkingBudget.from_level(BudgetLevel.HIGH)
|
||||
data = budget.to_dict()
|
||||
print(f" Serialized: level={data['level']}, max_tokens={data['max_tokens']}")
|
||||
|
||||
restored = ThinkingBudget.from_dict(data)
|
||||
print(f" Restored: {restored.max_tokens:,} tokens")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Demo Complete!")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
"""ArXiv Tool Example.
|
||||
|
||||
This example demonstrates how to use the ArXiv tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
|
||||
Note: No API key required!
|
||||
"""
|
||||
|
||||
from praisonai_tools import ArxivTool
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize ArXiv tool (no API key needed)
|
||||
arxiv = ArxivTool()
|
||||
|
||||
# Example 1: Search ArXiv
|
||||
print("=" * 60)
|
||||
print("Example 1: Search ArXiv")
|
||||
print("=" * 60)
|
||||
|
||||
results = arxiv.search("transformer neural networks", max_results=3)
|
||||
|
||||
if results and "error" in results[0]:
|
||||
print(f"Error: {results[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(results)} papers:")
|
||||
for paper in results:
|
||||
print(f"\n Title: {paper.get('title', 'N/A')[:60]}...")
|
||||
authors = paper.get('authors', [])
|
||||
if authors:
|
||||
print(f" Authors: {', '.join(authors[:2])}...")
|
||||
print(f" Published: {paper.get('published', 'N/A')}")
|
||||
print(f" PDF: {paper.get('pdf_url', 'N/A')}")
|
||||
|
||||
print("\n✅ ArXiv tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
"""Calculator Tool Example.
|
||||
|
||||
This example demonstrates how to use the Calculator tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
|
||||
Note: No API key required!
|
||||
"""
|
||||
|
||||
from praisonai_tools import CalculatorTool
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize Calculator tool
|
||||
calc = CalculatorTool()
|
||||
|
||||
# Example 1: Basic arithmetic
|
||||
print("=" * 60)
|
||||
print("Example 1: Basic Arithmetic")
|
||||
print("=" * 60)
|
||||
|
||||
expressions = [
|
||||
"2 + 2",
|
||||
"10 * 5",
|
||||
"100 / 4",
|
||||
"2 ** 10",
|
||||
"(10 + 5) * 2 - 3"
|
||||
]
|
||||
|
||||
for expr in expressions:
|
||||
result = calc.evaluate(expr)
|
||||
print(f" {expr} = {result.get('result', result)}")
|
||||
|
||||
# Example 2: Percentage calculation
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 2: Percentage Calculation")
|
||||
print("=" * 60)
|
||||
|
||||
result = calc.evaluate("250 * 0.15")
|
||||
print(f" 15% of 250 = {result.get('result', result)}")
|
||||
|
||||
result = calc.evaluate("1000 * (1 + 0.05) ** 3")
|
||||
print(f" $1000 at 5% for 3 years = ${result.get('result', 0):.2f}")
|
||||
|
||||
print("\n✅ Calculator tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
"""DuckDuckGo Search Tool Example.
|
||||
|
||||
This example demonstrates how to use the DuckDuckGo search tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
|
||||
Note: No API key required!
|
||||
"""
|
||||
|
||||
from praisonai_tools import DuckDuckGoTool
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize DuckDuckGo tool (no API key needed)
|
||||
ddg = DuckDuckGoTool()
|
||||
|
||||
# Example 1: Web search
|
||||
print("=" * 60)
|
||||
print("Example 1: Web Search")
|
||||
print("=" * 60)
|
||||
|
||||
results = ddg.search("Python programming best practices", max_results=3)
|
||||
|
||||
if results and "error" in results[0]:
|
||||
print(f"Error: {results[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(results)} results:")
|
||||
for r in results:
|
||||
print(f" - {r['title']}")
|
||||
print(f" URL: {r['url']}")
|
||||
print(f" Snippet: {r['snippet'][:100]}...")
|
||||
print()
|
||||
|
||||
# Example 2: News search
|
||||
print("=" * 60)
|
||||
print("Example 2: News Search")
|
||||
print("=" * 60)
|
||||
|
||||
news = ddg.news("artificial intelligence", max_results=3)
|
||||
|
||||
if news and "error" in news[0]:
|
||||
print(f"Error: {news[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(news)} news articles:")
|
||||
for n in news:
|
||||
print(f" - {n['title']}")
|
||||
print(f" Source: {n.get('source', 'N/A')}")
|
||||
print(f" Date: {n.get('date', 'N/A')}")
|
||||
print()
|
||||
|
||||
# Example 3: Image search
|
||||
print("=" * 60)
|
||||
print("Example 3: Image Search")
|
||||
print("=" * 60)
|
||||
|
||||
images = ddg.images("sunset landscape", max_results=3)
|
||||
|
||||
if images and "error" in images[0]:
|
||||
print(f"Error: {images[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(images)} images:")
|
||||
for img in images:
|
||||
print(f" - {img['title']}")
|
||||
print(f" Image URL: {img['image_url'][:60]}...")
|
||||
print()
|
||||
|
||||
print("✅ DuckDuckGo tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
"""Exa Search Tool Example.
|
||||
|
||||
This example demonstrates how to use the Exa search tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
export EXA_API_KEY=your_api_key
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonai_tools import ExaTool
|
||||
|
||||
|
||||
def main():
|
||||
# Check for API key
|
||||
if not os.getenv("EXA_API_KEY"):
|
||||
print("Error: EXA_API_KEY environment variable not set")
|
||||
print("Get your API key from https://exa.ai/")
|
||||
return
|
||||
|
||||
# Initialize Exa tool
|
||||
exa = ExaTool()
|
||||
|
||||
# Example 1: Neural search
|
||||
print("=" * 60)
|
||||
print("Example 1: Neural Search")
|
||||
print("=" * 60)
|
||||
|
||||
results = exa.search("best practices for Python development", num_results=3)
|
||||
|
||||
if results and "error" in results[0]:
|
||||
print(f"Error: {results[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(results)} results:")
|
||||
for r in results:
|
||||
print(f" - {r.get('title', 'N/A')[:50]}...")
|
||||
print(f" URL: {r.get('url', 'N/A')[:60]}...")
|
||||
print(f" Score: {r.get('score', 'N/A')}")
|
||||
print()
|
||||
|
||||
print("✅ Exa tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
"""Firecrawl Tool Example.
|
||||
|
||||
This example demonstrates how to use the Firecrawl tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
export FIRECRAWL_API_KEY=your_api_key
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonai_tools import FirecrawlTool
|
||||
|
||||
|
||||
def main():
|
||||
# Check for API key
|
||||
if not os.getenv("FIRECRAWL_API_KEY"):
|
||||
print("Error: FIRECRAWL_API_KEY environment variable not set")
|
||||
print("Get your API key from https://firecrawl.dev/")
|
||||
return
|
||||
|
||||
# Initialize Firecrawl tool
|
||||
firecrawl = FirecrawlTool()
|
||||
|
||||
# Example 1: Scrape a page
|
||||
print("=" * 60)
|
||||
print("Example 1: Scrape a Page")
|
||||
print("=" * 60)
|
||||
|
||||
result = firecrawl.scrape("https://example.com")
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
else:
|
||||
print(f"URL: {result.get('url', 'N/A')}")
|
||||
markdown = result.get('markdown', '')
|
||||
print(f"Content preview: {markdown[:300]}...")
|
||||
|
||||
print("\n✅ Firecrawl tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
"""Hacker News Tool Example.
|
||||
|
||||
This example demonstrates how to use the Hacker News tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
|
||||
Note: No API key required!
|
||||
"""
|
||||
|
||||
from praisonai_tools import HackerNewsTool
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize Hacker News tool
|
||||
hn = HackerNewsTool()
|
||||
|
||||
# Example 1: Get top stories
|
||||
print("=" * 60)
|
||||
print("Example 1: Top Stories")
|
||||
print("=" * 60)
|
||||
|
||||
stories = hn.get_top_stories(limit=5)
|
||||
|
||||
if stories and "error" in stories[0]:
|
||||
print(f"Error: {stories[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(stories)} top stories:")
|
||||
for story in stories:
|
||||
print(f" - {story.get('title', 'N/A')[:50]}...")
|
||||
print(f" Score: {story.get('score', 'N/A')} | Comments: {story.get('descendants', 'N/A')}")
|
||||
print(f" URL: {story.get('url', 'N/A')[:60]}...")
|
||||
print()
|
||||
|
||||
print("✅ Hacker News tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
"""Jina Reader Tool Example.
|
||||
|
||||
This example demonstrates how to use the Jina Reader tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
|
||||
Note: Works without API key (with rate limits)
|
||||
"""
|
||||
|
||||
from praisonai_tools import JinaTool
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize Jina tool (works without API key)
|
||||
jina = JinaTool()
|
||||
|
||||
# Example 1: Read a URL
|
||||
print("=" * 60)
|
||||
print("Example 1: Read URL Content")
|
||||
print("=" * 60)
|
||||
|
||||
result = jina.read("https://example.com")
|
||||
|
||||
if "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
else:
|
||||
print(f"URL: {result.get('url', 'N/A')}")
|
||||
print(f"Title: {result.get('title', 'N/A')}")
|
||||
content = result.get('content', '')
|
||||
print(f"Content preview: {content[:300]}...")
|
||||
|
||||
print("\n✅ Jina tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"""PostgreSQL Tool Example.
|
||||
|
||||
This example demonstrates how to use the PostgreSQL tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
Docker: docker run -d --name postgres -e POSTGRES_PASSWORD=praison123 -e POSTGRES_DB=praisonai -p 5432:5432 postgres:16
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
"""
|
||||
|
||||
from praisonai_tools import PostgresTool
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize PostgreSQL tool
|
||||
pg = PostgresTool(
|
||||
host="localhost",
|
||||
port=5432,
|
||||
database="praisonai",
|
||||
user="postgres",
|
||||
password="praison123"
|
||||
)
|
||||
|
||||
# Example 1: List tables
|
||||
print("=" * 60)
|
||||
print("Example 1: List Tables")
|
||||
print("=" * 60)
|
||||
|
||||
tables = pg.list_tables()
|
||||
|
||||
if isinstance(tables, dict) and "error" in tables:
|
||||
print(f"Error: {tables['error']}")
|
||||
else:
|
||||
print(f"Found {len(tables)} tables:")
|
||||
for t in tables[:10]:
|
||||
print(f" - {t.get('table_name', t)}")
|
||||
|
||||
# Example 2: Query
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 2: Execute Query")
|
||||
print("=" * 60)
|
||||
|
||||
result = pg.query("SELECT version()")
|
||||
|
||||
if isinstance(result, dict) and "error" in result:
|
||||
print(f"Error: {result['error']}")
|
||||
else:
|
||||
print(f"PostgreSQL version: {result}")
|
||||
|
||||
print("\n✅ PostgreSQL tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
"""Serper Tool Example.
|
||||
|
||||
This example demonstrates how to use the Serper (Google Search) tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
export SERPER_API_KEY=your_api_key
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonai_tools import SerperTool
|
||||
|
||||
|
||||
def main():
|
||||
# Check for API key
|
||||
if not os.getenv("SERPER_API_KEY"):
|
||||
print("Error: SERPER_API_KEY environment variable not set")
|
||||
print("Get your API key from https://serper.dev/")
|
||||
return
|
||||
|
||||
# Initialize Serper tool
|
||||
serper = SerperTool()
|
||||
|
||||
# Example 1: Web search
|
||||
print("=" * 60)
|
||||
print("Example 1: Google Web Search")
|
||||
print("=" * 60)
|
||||
|
||||
results = serper.search("Python programming tutorials", max_results=3)
|
||||
|
||||
if results and "error" in results[0]:
|
||||
print(f"Error: {results[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(results)} results:")
|
||||
for r in results:
|
||||
print(f" - {r.get('title', 'N/A')[:50]}...")
|
||||
print(f" URL: {r.get('link', 'N/A')[:60]}...")
|
||||
print()
|
||||
|
||||
print("✅ Serper tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
"""Tavily Search Tool Example.
|
||||
|
||||
This example demonstrates how to use the Tavily search tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
export TAVILY_API_KEY=your_api_key
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
"""
|
||||
|
||||
import os
|
||||
from praisonai_tools import TavilyTool
|
||||
|
||||
def main():
|
||||
# Check for API key
|
||||
if not os.getenv("TAVILY_API_KEY"):
|
||||
print("Error: TAVILY_API_KEY environment variable not set")
|
||||
print("Get your API key from https://tavily.com/")
|
||||
return
|
||||
|
||||
# Initialize Tavily tool
|
||||
tavily = TavilyTool()
|
||||
|
||||
# Example 1: Basic search
|
||||
print("=" * 60)
|
||||
print("Example 1: Basic Search")
|
||||
print("=" * 60)
|
||||
|
||||
results = tavily.search("What is quantum computing?", max_results=3)
|
||||
|
||||
if "error" in results:
|
||||
print(f"Error: {results['error']}")
|
||||
else:
|
||||
print(f"Query: {results.get('query')}")
|
||||
if "answer" in results:
|
||||
print(f"\nAI Answer: {results['answer'][:200]}...")
|
||||
print(f"\nResults ({len(results.get('results', []))}):")
|
||||
for r in results.get("results", []):
|
||||
print(f" - {r['title']}")
|
||||
print(f" URL: {r['url']}")
|
||||
print(f" Score: {r.get('score', 'N/A')}")
|
||||
|
||||
# Example 2: Search context for RAG
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 2: Search Context (for RAG)")
|
||||
print("=" * 60)
|
||||
|
||||
context = tavily.search_context("Python best practices 2024")
|
||||
print(f"Context (first 300 chars): {context[:300]}...")
|
||||
|
||||
print("\n✅ Tavily tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
"""Wikipedia Tool Example.
|
||||
|
||||
This example demonstrates how to use the Wikipedia tool with PraisonAI agents.
|
||||
|
||||
Requirements:
|
||||
pip install "praisonai[tools]"
|
||||
|
||||
Usage:
|
||||
python tool.py
|
||||
|
||||
Note: No API key required!
|
||||
"""
|
||||
|
||||
from praisonai_tools import WikipediaTool
|
||||
|
||||
|
||||
def main():
|
||||
# Initialize Wikipedia tool (no API key needed)
|
||||
wiki = WikipediaTool()
|
||||
|
||||
# Example 1: Search Wikipedia
|
||||
print("=" * 60)
|
||||
print("Example 1: Search Wikipedia")
|
||||
print("=" * 60)
|
||||
|
||||
results = wiki.search("Python programming", max_results=5)
|
||||
|
||||
if results and "error" in results[0]:
|
||||
print(f"Error: {results[0]['error']}")
|
||||
else:
|
||||
print(f"Found {len(results)} results:")
|
||||
for r in results:
|
||||
print(f" - {r['title']}")
|
||||
|
||||
# Example 2: Get page summary
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 2: Get Page Summary")
|
||||
print("=" * 60)
|
||||
|
||||
summary = wiki.summary("Artificial intelligence", sentences=3)
|
||||
|
||||
if "error" in summary:
|
||||
print(f"Error: {summary['error']}")
|
||||
else:
|
||||
print(f"Title: {summary['title']}")
|
||||
print(f"Summary: {summary['summary'][:300]}...")
|
||||
|
||||
# Example 3: Get full page
|
||||
print("\n" + "=" * 60)
|
||||
print("Example 3: Get Full Page")
|
||||
print("=" * 60)
|
||||
|
||||
page = wiki.get_page("Machine learning")
|
||||
|
||||
if "error" in page:
|
||||
print(f"Error: {page['error']}")
|
||||
if "options" in page:
|
||||
print(f"Options: {page['options'][:5]}")
|
||||
else:
|
||||
print(f"Title: {page['title']}")
|
||||
print(f"URL: {page['url']}")
|
||||
print(f"Categories: {page['categories'][:3]}")
|
||||
print(f"Content preview: {page['content'][:200]}...")
|
||||
|
||||
print("\n✅ Wikipedia tool working correctly!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,23 @@
|
||||
"""ChromaDB Vector Store - Agent-First Example"""
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Agent-first approach: use knowledge parameter with ChromaDB
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant with access to documents.",
|
||||
knowledge=["./docs/guide.pdf"], # Add your documents here
|
||||
knowledge_config={
|
||||
"vector_store": "chroma",
|
||||
"path": "/tmp/chroma_demo"
|
||||
}
|
||||
)
|
||||
|
||||
# Chat - agent uses knowledge for RAG
|
||||
response = agent.chat("What information do you have?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
print("PASSED: ChromaDB with Agent")
|
||||
|
||||
# --- Advanced: Direct Store Usage ---
|
||||
# from praisonai.persistence import create_knowledge_store
|
||||
# store = create_knowledge_store("chroma", path="/tmp/chroma_demo")
|
||||
@@ -0,0 +1,25 @@
|
||||
"""LanceDB Vector Store - Agent-First Example"""
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Agent-first approach: use knowledge parameter with LanceDB
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant with access to documents.",
|
||||
knowledge=["./docs/guide.pdf"], # Add your documents here
|
||||
knowledge_config={
|
||||
"vector_store": "lancedb",
|
||||
"path": "/tmp/lancedb_test"
|
||||
}
|
||||
)
|
||||
|
||||
# Chat - agent uses knowledge for RAG
|
||||
response = agent.chat("What information do you have?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
print("PASSED: LanceDB with Agent")
|
||||
|
||||
# --- Advanced: Direct LanceDB Usage ---
|
||||
# import lancedb
|
||||
# db = lancedb.connect("/tmp/lancedb_test")
|
||||
# data = [{"id": "1", "text": "ML is AI", "vector": [0.1] * 128}]
|
||||
# table = db.create_table("demo", data)
|
||||
@@ -0,0 +1,23 @@
|
||||
"""LanceDB Vector Store - Agent-First Example"""
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Agent-first approach: use knowledge parameter with LanceDB
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant with access to documents.",
|
||||
knowledge=["./docs/guide.pdf"], # Add your documents here
|
||||
knowledge_config={
|
||||
"vector_store": "lancedb",
|
||||
"path": "/tmp/lancedb_demo"
|
||||
}
|
||||
)
|
||||
|
||||
# Chat - agent uses knowledge for RAG
|
||||
response = agent.chat("What information do you have?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
print("PASSED: LanceDB with Agent")
|
||||
|
||||
# --- Advanced: Direct Store Usage ---
|
||||
# from praisonai.persistence import create_knowledge_store
|
||||
# store = create_knowledge_store("lancedb", path="/tmp/lancedb_demo")
|
||||
@@ -0,0 +1,31 @@
|
||||
"""PGVector Vector Store - Agent-First Example
|
||||
|
||||
Docker: docker run -d --name pgvector -e POSTGRES_PASSWORD=postgres -p 5433:5432 pgvector/pgvector:pg16
|
||||
"""
|
||||
import os
|
||||
from praisonaiagents import Agent
|
||||
|
||||
url = os.getenv("PGVECTOR_URL", "postgresql://postgres:postgres@localhost:5433/postgres")
|
||||
|
||||
# Agent-first approach: use knowledge parameter with PGVector
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant with access to documents.",
|
||||
knowledge=["./docs/guide.pdf"], # Add your documents here
|
||||
knowledge_config={
|
||||
"vector_store": "pgvector",
|
||||
"url": url
|
||||
}
|
||||
)
|
||||
|
||||
# Chat - agent uses knowledge for RAG
|
||||
response = agent.chat("What information do you have?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
print("PASSED: PGVector with Agent")
|
||||
|
||||
# --- Advanced: Direct PGVector Usage ---
|
||||
# import psycopg2
|
||||
# conn = psycopg2.connect(url)
|
||||
# cur = conn.cursor()
|
||||
# cur.execute("CREATE EXTENSION IF NOT EXISTS vector")
|
||||
@@ -0,0 +1,29 @@
|
||||
"""PGVector Knowledge Store - Agent-First Example (requires Docker)
|
||||
|
||||
Docker: docker run -d --name pgvector -e POSTGRES_PASSWORD=postgres -p 5433:5432 pgvector/pgvector:pg16
|
||||
"""
|
||||
import os
|
||||
from praisonaiagents import Agent
|
||||
|
||||
url = os.getenv("PGVECTOR_URL", "postgresql://postgres:postgres@localhost:5433/postgres")
|
||||
|
||||
# Agent-first approach: use knowledge parameter with PGVector
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant with access to documents.",
|
||||
knowledge=["./docs/guide.pdf"], # Add your documents here
|
||||
knowledge_config={
|
||||
"vector_store": "pgvector",
|
||||
"url": url
|
||||
}
|
||||
)
|
||||
|
||||
# Chat - agent uses knowledge for RAG
|
||||
response = agent.chat("What information do you have?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
print("PASSED: PGVector with Agent")
|
||||
|
||||
# --- Advanced: Direct Store Usage ---
|
||||
# from praisonai.persistence import create_knowledge_store
|
||||
# store = create_knowledge_store("pgvector", url=url)
|
||||
@@ -0,0 +1,34 @@
|
||||
"""Pinecone Vector Store - Agent-First Example
|
||||
|
||||
Requires: export PINECONE_API_KEY=...
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from praisonaiagents import Agent
|
||||
|
||||
api_key = os.getenv("PINECONE_API_KEY")
|
||||
if not api_key:
|
||||
print("SKIPPED: Pinecone - PINECONE_API_KEY not set")
|
||||
sys.exit(0)
|
||||
|
||||
# Agent-first approach: use knowledge parameter with Pinecone
|
||||
agent = Agent(
|
||||
name="Assistant",
|
||||
instructions="You are a helpful assistant with access to documents.",
|
||||
knowledge=["./docs/guide.pdf"], # Add your documents here
|
||||
knowledge_config={
|
||||
"vector_store": "pinecone",
|
||||
"api_key": api_key,
|
||||
"environment": "us-east-1"
|
||||
}
|
||||
)
|
||||
|
||||
# Chat - agent uses knowledge for RAG
|
||||
response = agent.chat("What information do you have?")
|
||||
print(f"Response: {response}")
|
||||
|
||||
print("PASSED: Pinecone with Agent")
|
||||
|
||||
# --- Advanced: Direct Store Usage ---
|
||||
# from pinecone import Pinecone
|
||||
# pc = Pinecone(api_key=api_key)
|
||||
Loaded 100 of 579 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user