Skip to content

Commit d08d98c

Browse files
committed
Release v3.9.24
1 parent 2c9e8b4 commit d08d98c

32 files changed

+2088
-64
lines changed

docker/Dockerfile.chat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=3.9.23" \
19+
"praisonai>=3.9.24" \
2020
"praisonai[chat]" \
2121
"embedchain[github,youtube]"
2222

docker/Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
2020
# Install Python packages (using latest versions)
2121
RUN pip install --no-cache-dir \
2222
praisonai_tools \
23-
"praisonai>=3.9.23" \
23+
"praisonai>=3.9.24" \
2424
"praisonai[ui]" \
2525
"praisonai[chat]" \
2626
"praisonai[realtime]" \

docker/Dockerfile.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=3.9.23" \
19+
"praisonai>=3.9.24" \
2020
"praisonai[ui]" \
2121
"praisonai[crewai]"
2222

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
Basic Context Management Example
3+
4+
Demonstrates enabling context management with ContextConfig.
5+
This manages token budgets, auto-compaction, and prevents context overflow.
6+
"""
7+
8+
from praisonaiagents import Agent
9+
from praisonaiagents.context import ContextConfig, OptimizerStrategy
10+
11+
# Example 1: Enable context with defaults
12+
agent_basic = Agent(
13+
name="Assistant",
14+
instructions="You are a helpful assistant",
15+
context=True # Auto-compact at 80% utilization
16+
)
17+
18+
# Example 2: Custom configuration
19+
agent_custom = Agent(
20+
name="CustomAgent",
21+
instructions="You are a helpful assistant with custom context settings",
22+
context=ContextConfig(
23+
auto_compact=True,
24+
compact_threshold=0.8, # Trigger at 80% utilization
25+
strategy=OptimizerStrategy.SMART,
26+
output_reserve=8000, # Reserve tokens for output
27+
keep_recent_turns=5, # Always keep last 5 turns
28+
tool_output_max=10000, # Max tokens per tool output
29+
)
30+
)
31+
32+
# Example 3: Sliding window strategy
33+
agent_sliding = Agent(
34+
name="SlidingAgent",
35+
instructions="You are a helpful assistant using sliding window",
36+
context=ContextConfig(
37+
strategy=OptimizerStrategy.SLIDING_WINDOW,
38+
keep_recent_turns=10, # Keep last 10 turns
39+
)
40+
)
41+
42+
if __name__ == "__main__":
43+
print("=== Basic Context Example ===")
44+
print("Context management is automatically enabled.")
45+
print()
46+
47+
# Test basic agent
48+
result = agent_basic.chat("Hello! What is 2 + 2?")
49+
print(f"Response: {result}")
50+
print()
51+
52+
# Show context config
53+
print("=== Context Configuration ===")
54+
config = ContextConfig(
55+
auto_compact=True,
56+
compact_threshold=0.8,
57+
strategy=OptimizerStrategy.SMART,
58+
)
59+
print(f"Config: {config.to_dict()}")
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Session Tracking Example
3+
4+
Demonstrates tracking conversation state (goal, plan, progress) across turns.
5+
Inspired by Agno's SessionContextStore pattern.
6+
"""
7+
8+
from praisonaiagents.context import SessionContextTracker
9+
10+
# Create session tracker
11+
tracker = SessionContextTracker(
12+
session_id="user123",
13+
track_summary=True,
14+
track_goal=True,
15+
track_plan=True,
16+
track_progress=True,
17+
)
18+
19+
# Set the user's goal
20+
tracker.update_goal("Build a Python web application with Flask")
21+
22+
# Define the plan
23+
tracker.update_plan([
24+
"Create Flask project structure",
25+
"Add routes for API endpoints",
26+
"Implement database models",
27+
"Add authentication",
28+
"Write tests",
29+
"Deploy to cloud"
30+
])
31+
32+
# Mark completed steps
33+
tracker.add_progress("Created Flask project structure")
34+
tracker.add_progress("Added routes for API endpoints")
35+
36+
# Update summary
37+
tracker.update_summary(
38+
"User is building a Flask web app. Completed project setup and API routes. "
39+
"Next: implement database models."
40+
)
41+
42+
if __name__ == "__main__":
43+
print("=== Session Tracking Example ===")
44+
print()
45+
46+
# Show current state
47+
print(f"Session ID: {tracker.session_id}")
48+
print(f"Goal: {tracker.goal}")
49+
print(f"Plan: {tracker.plan}")
50+
print(f"Progress: {tracker.progress}")
51+
print()
52+
53+
# Get context string (simple format)
54+
print("=== Context String ===")
55+
print(tracker.to_context_string())
56+
print()
57+
58+
# Get system prompt section (XML format with guidelines)
59+
print("=== System Prompt Section ===")
60+
print(tracker.to_system_prompt_section())
61+
print()
62+
63+
# Export to dict for persistence
64+
print("=== Export as Dict ===")
65+
data = tracker.to_dict()
66+
print(f"Exported: {data.keys()}")
67+
print()
68+
69+
# Recreate from dict
70+
new_tracker = SessionContextTracker.from_dict(data)
71+
print(f"Restored goal: {new_tracker.goal}")
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""
2+
Multi-Memory Aggregation Example
3+
4+
Demonstrates concurrent fetching from multiple context sources.
5+
Inspired by CrewAI's ContextualMemory pattern.
6+
"""
7+
8+
import asyncio
9+
from praisonaiagents.context import ContextAggregator, create_aggregator_from_config
10+
11+
# Example 1: Basic aggregator with mock sources
12+
def mock_memory_search(query: str) -> str:
13+
"""Mock memory search - returns recent conversation context."""
14+
return f"[Memory] User previously asked about: {query}. They prefer Python."
15+
16+
def mock_knowledge_search(query: str) -> str:
17+
"""Mock knowledge search - returns facts from knowledge base."""
18+
return f"[Knowledge] Relevant facts: Python is a high-level programming language."
19+
20+
def mock_rag_retrieve(query: str) -> str:
21+
"""Mock RAG retrieval - returns document chunks."""
22+
return f"[RAG] Retrieved: Documentation about {query} from the codebase."
23+
24+
# Create aggregator
25+
aggregator = ContextAggregator(
26+
max_tokens=4000,
27+
separator="\n\n---\n\n",
28+
include_source_labels=True
29+
)
30+
31+
# Register sources with priorities (lower = higher priority)
32+
aggregator.register_source("memory", mock_memory_search, priority=10)
33+
aggregator.register_source("knowledge", mock_knowledge_search, priority=20)
34+
aggregator.register_source("rag", mock_rag_retrieve, priority=30)
35+
36+
async def demo_async():
37+
"""Demo async aggregation."""
38+
print("=== Async Aggregation ===")
39+
result = await aggregator.aggregate("Python web development")
40+
print(f"Sources used: {result.sources_used}")
41+
print(f"Tokens used: {result.tokens_used}")
42+
print(f"Fetch times: {result.fetch_times}")
43+
print()
44+
print("Context:")
45+
print(result.context)
46+
return result
47+
48+
def demo_sync():
49+
"""Demo sync aggregation."""
50+
print("=== Sync Aggregation ===")
51+
result = aggregator.aggregate_sync("Flask API development")
52+
print(f"Sources used: {result.sources_used}")
53+
print(f"Tokens used: {result.tokens_used}")
54+
print()
55+
print("Context:")
56+
print(result.context)
57+
return result
58+
59+
if __name__ == "__main__":
60+
print("=== Multi-Memory Aggregation Example ===")
61+
print()
62+
63+
# Show registered sources
64+
print(f"Registered sources: {aggregator.sources}")
65+
print()
66+
67+
# Demo sync aggregation
68+
demo_sync()
69+
print()
70+
71+
# Demo async aggregation
72+
asyncio.run(demo_async())
73+
print()
74+
75+
# Demo selective sources
76+
print("=== Selective Sources ===")
77+
result = aggregator.aggregate_sync(
78+
"Find database info",
79+
sources=["memory", "knowledge"] # Only use these
80+
)
81+
print(f"Sources used: {result.sources_used}")
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""
2+
Compaction Strategies Example
3+
4+
Demonstrates different context compaction strategies.
5+
"""
6+
7+
from praisonaiagents import Agent
8+
from praisonaiagents.context import ContextConfig, OptimizerStrategy
9+
10+
# Strategy 1: TRUNCATE - Fast, removes oldest messages
11+
agent_truncate = Agent(
12+
name="TruncateAgent",
13+
instructions="You are a helpful assistant",
14+
context=ContextConfig(
15+
strategy=OptimizerStrategy.TRUNCATE,
16+
compact_threshold=0.8,
17+
)
18+
)
19+
20+
# Strategy 2: SLIDING_WINDOW - Keeps recent N turns
21+
agent_sliding = Agent(
22+
name="SlidingAgent",
23+
instructions="You are a helpful assistant",
24+
context=ContextConfig(
25+
strategy=OptimizerStrategy.SLIDING_WINDOW,
26+
keep_recent_turns=10,
27+
)
28+
)
29+
30+
# Strategy 3: SMART - Importance-based (default)
31+
agent_smart = Agent(
32+
name="SmartAgent",
33+
instructions="You are a helpful assistant",
34+
context=ContextConfig(
35+
strategy=OptimizerStrategy.SMART, # Default
36+
compact_threshold=0.8,
37+
)
38+
)
39+
40+
# Strategy 4: PRUNE_TOOLS - Truncate old tool outputs
41+
agent_prune = Agent(
42+
name="PruneAgent",
43+
instructions="You are a helpful assistant with tools",
44+
context=ContextConfig(
45+
strategy=OptimizerStrategy.PRUNE_TOOLS,
46+
tool_output_max=5000, # Max tokens per tool output
47+
)
48+
)
49+
50+
# Strategy 5: NON_DESTRUCTIVE - Only prune tools, keep all history
51+
agent_safe = Agent(
52+
name="SafeAgent",
53+
instructions="You are a helpful assistant (safety-critical)",
54+
context=ContextConfig(
55+
strategy=OptimizerStrategy.NON_DESTRUCTIVE,
56+
)
57+
)
58+
59+
if __name__ == "__main__":
60+
print("=== Compaction Strategies Example ===")
61+
print()
62+
63+
strategies = [
64+
("TRUNCATE", OptimizerStrategy.TRUNCATE, "Remove oldest messages"),
65+
("SLIDING_WINDOW", OptimizerStrategy.SLIDING_WINDOW, "Keep last N turns"),
66+
("SMART", OptimizerStrategy.SMART, "Importance-based (default)"),
67+
("PRUNE_TOOLS", OptimizerStrategy.PRUNE_TOOLS, "Truncate tool outputs"),
68+
("NON_DESTRUCTIVE", OptimizerStrategy.NON_DESTRUCTIVE, "Only prune tools"),
69+
]
70+
71+
for name, strategy, description in strategies:
72+
print(f" {name:20} - {description}")
73+
74+
print()
75+
print("Usage:")
76+
print(" context=ContextConfig(strategy=OptimizerStrategy.SLIDING_WINDOW)")

0 commit comments

Comments
 (0)