mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-10 17:29:39 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57b637948f |
No files matched your search
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
|
||||
# Install Python packages (using latest versions)
|
||||
RUN pip install --no-cache-dir \
|
||||
praisonai_tools \
|
||||
"praisonai>=3.3.0" \
|
||||
"praisonai>=3.3.1" \
|
||||
"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>=3.3.0" \
|
||||
"praisonai>=3.3.1" \
|
||||
"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>=3.3.0" \
|
||||
"praisonai>=3.3.1" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
@@ -128,6 +128,78 @@ def main():
|
||||
budget_dict = budgeter.to_dict()
|
||||
print(f"Budget as dict: {budget_dict}")
|
||||
|
||||
# Example 6: Overflow handling strategies overview
|
||||
print("\n6. Overflow Handling Strategies")
|
||||
print("-" * 40)
|
||||
strategies = [
|
||||
("truncate", "Remove oldest messages first", "Fast, simple", "Loses early context"),
|
||||
("sliding_window", "Keep N most recent messages", "Preserves recent", "Loses early context"),
|
||||
("prune_tools", "Truncate old tool outputs", "Keeps messages", "May lose tool details"),
|
||||
("summarize", "Replace old messages with summary", "Preserves meaning", "Slower, uses API"),
|
||||
("smart", "Combine strategies intelligently", "Best balance", "More complex"),
|
||||
]
|
||||
print(f"{'Strategy':<15} | {'Description':<30} | {'Pros':<18} | {'Cons'}")
|
||||
print("-" * 90)
|
||||
for name, desc, pros, cons in strategies:
|
||||
print(f"{name:<15} | {desc:<30} | {pros:<18} | {cons}")
|
||||
|
||||
# Example 7: Simulated overflow playbook
|
||||
print("\n7. Overflow Playbook (Thresholds → Actions)")
|
||||
print("-" * 40)
|
||||
playbook = [
|
||||
(0.70, "INFO", "Monitor usage, no action needed"),
|
||||
(0.80, "NOTICE", "Consider optimization soon"),
|
||||
(0.90, "WARNING", "Trigger auto-compact if enabled"),
|
||||
(0.95, "CRITICAL", "Aggressive optimization required"),
|
||||
(1.00, "OVERFLOW", "Immediate truncation to prevent API error"),
|
||||
]
|
||||
print(f"{'Usage':<8} | {'Level':<10} | {'Action'}")
|
||||
print("-" * 60)
|
||||
for threshold, level, action in playbook:
|
||||
print(f"{threshold:>6.0%} | {level:<10} | {action}")
|
||||
|
||||
# Example 8: Strategy comparison table
|
||||
print("\n8. Strategy Comparison")
|
||||
print("-" * 40)
|
||||
print("Strategy | Preserves | Loses | Best For")
|
||||
print("-" * 70)
|
||||
print("truncate | Recent msgs | Old msgs | Simple chats")
|
||||
print("sliding_window | Last N msgs | Earlier msgs | Long conversations")
|
||||
print("prune_tools | All messages | Tool details | Tool-heavy agents")
|
||||
print("summarize | Context meaning| Exact wording | Important history")
|
||||
print("smart | Balanced | Minimal | Production use")
|
||||
|
||||
# Example 9: Default strategy for interactive mode
|
||||
print("\n9. Default Strategy: Interactive Mode")
|
||||
print("-" * 40)
|
||||
print("Interactive mode default: context=False (zero overhead)")
|
||||
print("To enable context management in interactive mode:")
|
||||
print(" praisonai chat --context # Enable with defaults")
|
||||
print(" Or in code:")
|
||||
print(" agent = Agent(instructions='...', context=True)")
|
||||
print("")
|
||||
print("When enabled, defaults are:")
|
||||
print(" - auto_compact: True")
|
||||
print(" - compact_threshold: 0.8 (80% usage)")
|
||||
print(" - strategy: smart")
|
||||
print(" - output_reserve: model-specific (8K-16K)")
|
||||
|
||||
# Example 10: Default strategy for auto-agents mode
|
||||
print("\n10. Default Strategy: Auto-Agents Mode")
|
||||
print("-" * 40)
|
||||
print("Auto-agents mode default: context=False (zero overhead)")
|
||||
print("To enable for multi-agent workflows:")
|
||||
print(" from praisonaiagents import PraisonAIAgents")
|
||||
print(" agents = PraisonAIAgents(agents=[...], context=True)")
|
||||
print("")
|
||||
print("Recommended config for long tasks:")
|
||||
print(" context=ManagerConfig(")
|
||||
print(" auto_compact=True,")
|
||||
print(" compact_threshold=0.7, # Earlier trigger for safety")
|
||||
print(" strategy='smart',")
|
||||
print(" output_reserve=16384, # Larger reserve for complex outputs")
|
||||
print(" )")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✓ Context budgeting examples complete!")
|
||||
print("=" * 60)
|
||||
|
||||
@@ -13,10 +13,10 @@ from praisonaiagents import Agent
|
||||
from praisonaiagents.context import (
|
||||
ContextBudgeter,
|
||||
ContextLedgerManager,
|
||||
ContextMonitor,
|
||||
get_optimizer,
|
||||
OptimizerStrategy,
|
||||
estimate_messages_tokens,
|
||||
format_percent,
|
||||
)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ def main():
|
||||
|
||||
# Get budget info
|
||||
budget = budgeter.allocate()
|
||||
print(f"\nModel: gpt-4o-mini")
|
||||
print("\nModel: gpt-4o-mini")
|
||||
print(f"Context budget: {budget.usable:,} tokens")
|
||||
print(f"Output reserve: {budget.output_reserve:,} tokens")
|
||||
|
||||
@@ -76,7 +76,7 @@ def main():
|
||||
current_tokens = ledger.get_total()
|
||||
utilization = budgeter.get_utilization(current_tokens)
|
||||
|
||||
print(f"[Context: {current_tokens} tokens, {utilization:.1%} used]")
|
||||
print(f"[Context: {current_tokens} tokens, {format_percent(utilization)} used]")
|
||||
|
||||
# Check if optimization needed
|
||||
if utilization > 0.8:
|
||||
@@ -101,7 +101,7 @@ def main():
|
||||
final_utilization = budgeter.get_utilization(final_tokens)
|
||||
|
||||
print(f"Total tokens used: {final_tokens:,}")
|
||||
print(f"Context utilization: {final_utilization:.1%}")
|
||||
print(f"Context utilization: {format_percent(final_utilization)}")
|
||||
print(f"Messages in conversation: {len(conversation)}")
|
||||
print(f"Remaining capacity: {budgeter.get_remaining(final_tokens):,} tokens")
|
||||
|
||||
|
||||
@@ -41,7 +41,32 @@ Usage:
|
||||
monitor.snapshot(ledger=result.ledger, budget=budget, messages=result.messages)
|
||||
"""
|
||||
|
||||
def format_percent(value: float) -> str:
|
||||
"""
|
||||
Smart percentage formatting for context utilization display.
|
||||
|
||||
- For values < 0.1%: shows "<0.1%"
|
||||
- For values < 1%: shows 2 decimal places (e.g., "0.02%")
|
||||
- For values >= 1%: shows 1 decimal place (e.g., "5.3%")
|
||||
|
||||
Args:
|
||||
value: A ratio (0.0 to 1.0+), NOT already multiplied by 100
|
||||
|
||||
Returns:
|
||||
Formatted percentage string
|
||||
"""
|
||||
pct = value * 100
|
||||
if pct < 0.1 and pct > 0:
|
||||
return "<0.1%"
|
||||
elif pct < 1.0:
|
||||
return f"{pct:.2f}%"
|
||||
else:
|
||||
return f"{pct:.1f}%"
|
||||
|
||||
|
||||
__all__ = [
|
||||
# Utilities
|
||||
"format_percent",
|
||||
# Models
|
||||
"ContextSegment",
|
||||
"ContextLedger",
|
||||
|
||||
@@ -15,6 +15,16 @@ from .models import (
|
||||
)
|
||||
|
||||
|
||||
def _format_pct(value: float) -> str:
|
||||
"""Smart percentage formatting: <0.1% for tiny, 2 decimals for <1%, 1 decimal otherwise."""
|
||||
if value < 0.1 and value > 0:
|
||||
return "<0.1%"
|
||||
elif value < 1.0:
|
||||
return f"{value:.2f}%"
|
||||
else:
|
||||
return f"{value:.1f}%"
|
||||
|
||||
|
||||
# Sensitive patterns for redaction
|
||||
SENSITIVE_PATTERNS = [
|
||||
# OpenAI API keys
|
||||
@@ -258,10 +268,10 @@ def format_human_snapshot(snapshot: ContextSnapshot, redact: bool = True) -> str
|
||||
tokens = snapshot.ledger.get_segment(seg)
|
||||
budget = snapshot.budget.get_segment_budget(seg)
|
||||
pct = (tokens / budget * 100) if budget > 0 else 0
|
||||
lines.append(f"{name:<20} | {tokens:>10,} | {budget:>10,} | {pct:>7.1f}%")
|
||||
lines.append(f"{name:<20} | {tokens:>10,} | {budget:>10,} | {_format_pct(pct):>8}")
|
||||
|
||||
lines.append("-" * 20 + "-+-" + "-" * 10 + "-+-" + "-" * 10 + "-+-" + "-" * 8)
|
||||
lines.append(f"{'TOTAL':<20} | {snapshot.ledger.total:>10,} | {snapshot.budget.usable:>10,} | {snapshot.utilization * 100:>7.1f}%")
|
||||
lines.append(f"{'TOTAL':<20} | {snapshot.ledger.total:>10,} | {snapshot.budget.usable:>10,} | {_format_pct(snapshot.utilization * 100):>8}")
|
||||
|
||||
lines.append("")
|
||||
|
||||
@@ -528,17 +538,17 @@ class ContextMonitor:
|
||||
utilization = ledger.total / budget.usable if budget.usable > 0 else 0
|
||||
|
||||
if utilization >= 1.0:
|
||||
warnings.append(f"CRITICAL: Context overflow! {utilization*100:.1f}% of usable budget")
|
||||
warnings.append(f"CRITICAL: Context overflow! {_format_pct(utilization*100)} of usable budget")
|
||||
elif utilization >= 0.9:
|
||||
warnings.append(f"WARNING: Context at {utilization*100:.1f}% of usable budget")
|
||||
warnings.append(f"WARNING: Context at {_format_pct(utilization*100)} of usable budget")
|
||||
elif utilization >= 0.8:
|
||||
warnings.append(f"NOTICE: Context at {utilization*100:.1f}% of usable budget")
|
||||
warnings.append(f"NOTICE: Context at {_format_pct(utilization*100)} of usable budget")
|
||||
|
||||
# Check individual segments
|
||||
if budget.tool_outputs > 0:
|
||||
tool_util = ledger.tool_outputs / budget.tool_outputs
|
||||
if tool_util >= 0.9:
|
||||
warnings.append(f"Tool outputs at {tool_util*100:.1f}% of budget")
|
||||
warnings.append(f"Tool outputs at {_format_pct(tool_util*100)} of budget")
|
||||
|
||||
return warnings
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
@@ -182,3 +182,43 @@ class TestTokenEstimationAccuracy:
|
||||
long_tokens = estimate_tokens_heuristic(long)
|
||||
|
||||
assert long_tokens > short_tokens * 50
|
||||
|
||||
|
||||
class TestFormatPercent:
|
||||
"""Tests for format_percent utility function."""
|
||||
|
||||
def test_format_percent_zero(self):
|
||||
"""Test zero value."""
|
||||
from praisonaiagents.context import format_percent
|
||||
assert format_percent(0) == "0.00%"
|
||||
|
||||
def test_format_percent_tiny(self):
|
||||
"""Test tiny values show <0.1%."""
|
||||
from praisonaiagents.context import format_percent
|
||||
# 0.0002 = 0.02% which is < 0.1%
|
||||
assert format_percent(0.0002) == "<0.1%"
|
||||
assert format_percent(0.0005) == "<0.1%"
|
||||
assert format_percent(0.0009) == "<0.1%"
|
||||
|
||||
def test_format_percent_small(self):
|
||||
"""Test small values show 2 decimals."""
|
||||
from praisonaiagents.context import format_percent
|
||||
# 0.002 = 0.2% which is < 1%
|
||||
assert format_percent(0.002) == "0.20%"
|
||||
assert format_percent(0.005) == "0.50%"
|
||||
assert format_percent(0.009) == "0.90%"
|
||||
|
||||
def test_format_percent_normal(self):
|
||||
"""Test normal values show 1 decimal."""
|
||||
from praisonaiagents.context import format_percent
|
||||
# 0.05 = 5%
|
||||
assert format_percent(0.05) == "5.0%"
|
||||
assert format_percent(0.5) == "50.0%"
|
||||
assert format_percent(0.8) == "80.0%"
|
||||
assert format_percent(1.0) == "100.0%"
|
||||
|
||||
def test_format_percent_overflow(self):
|
||||
"""Test overflow values."""
|
||||
from praisonaiagents.context import format_percent
|
||||
assert format_percent(1.1) == "110.0%"
|
||||
assert format_percent(1.5) == "150.0%"
|
||||
Generated
+1
-1
@@ -2422,7 +2422,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
|
||||
@@ -3,8 +3,8 @@ class Praisonai < Formula
|
||||
|
||||
desc "AI tools for various AI applications"
|
||||
homepage "https://github.com/MervinPraison/PraisonAI"
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.3.0.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.3.0.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.3.1.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v3.3.1.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -57,7 +57,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==3.3.0 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==3.3.1 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "3.3.0"
|
||||
__version__ = "3.3.1"
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.8.0",
|
||||
"praisonaiagents>=0.8.1",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
|
||||
Generated
+4
-4
@@ -4276,7 +4276,7 @@ requires-dist = [
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.1.0" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen-v4'", specifier = ">=0.1.0" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.1.0" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.8.0" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.8.1" },
|
||||
{ name = "pyautogen", marker = "extra == 'autogen'", specifier = "==0.2.29" },
|
||||
{ name = "pydantic", marker = "extra == 'chat'", specifier = "<=2.10.1" },
|
||||
{ name = "pydantic", marker = "extra == 'code'", specifier = "<=2.10.1" },
|
||||
@@ -4324,7 +4324,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
@@ -4333,9 +4333,9 @@ dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "rich" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0c/09/2a1f1c007c96e03397d86c8f5edfbdca9f805897c8c471248524f95044c4/praisonaiagents-0.8.0.tar.gz", hash = "sha256:3863036e57837404587906d7845d4bb25a3b5510d716519f193259bd548e5927", size = 897274, upload-time = "2026-01-08T10:29:21.003Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d1/a1/3577e22f24fd64c870d1b5e0cb56f7addd88c45d0c2fbb649a63cbf509d5/praisonaiagents-0.8.1.tar.gz", hash = "sha256:f17f6e8bdecdebb7c0c234ebc7103070c4546b31d41e878572208c75e6ef19ef", size = 897661, upload-time = "2026-01-08T12:24:08.607Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/a4/efaca47ec2daf0fe357739a1bec9430ce789d8331688271f76528bb1bd0e/praisonaiagents-0.8.0-py3-none-any.whl", hash = "sha256:451af1179f6b2bc465388a65c7431cbf0428726b3a16c7f8664496f464fa1a7d", size = 865862, upload-time = "2026-01-08T10:29:18.372Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/01/d0afaf98e78da1d1293f6f1a53e6b2f7b14c8ba1908b70eed16e5b138427/praisonaiagents-0.8.1-py3-none-any.whl", hash = "sha256:b898f8f1f38ae8d010dfba69f443f146faa2d685c997aa5a4992e786dc115654", size = 866252, upload-time = "2026-01-08T12:24:05.975Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in new issue
Block a user