mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-07 17:33:33 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe87b9514e | ||
|
|
fec0b5fa32 | ||
|
|
c8a3881dda |
No files matched your search
@@ -0,0 +1,20 @@
|
||||
import cProfile
|
||||
import pstats
|
||||
import io
|
||||
from praisonaiagents import Agent
|
||||
|
||||
# Warm up
|
||||
for _ in range(100):
|
||||
_ = Agent(name="Test", llm="gpt-4o-mini", output="silent")
|
||||
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
|
||||
for _ in range(5000):
|
||||
_ = Agent(name="Test", llm="gpt-4o-mini", output="silent")
|
||||
|
||||
pr.disable()
|
||||
s = io.StringIO()
|
||||
ps = pstats.Stats(pr, stream=s).sort_stats('cumtime')
|
||||
ps.print_stats(30)
|
||||
print(s.getvalue())
|
||||
@@ -0,0 +1,31 @@
|
||||
import cProfile
|
||||
import pstats
|
||||
import io
|
||||
import time
|
||||
from praisonaiagents import Agent
|
||||
|
||||
def func():
|
||||
return Agent(name='Test', llm='gpt-4o-mini', output="silent")
|
||||
|
||||
# Warm up to fill caches
|
||||
for _ in range(100):
|
||||
func()
|
||||
|
||||
start_time = time.perf_counter()
|
||||
for _ in range(1000):
|
||||
func()
|
||||
end_time = time.perf_counter()
|
||||
avg_time = (end_time - start_time) / 1000 * 1_000_000
|
||||
print(f"Time without profile: {avg_time:.2f} μs")
|
||||
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
|
||||
for _ in range(1000):
|
||||
func()
|
||||
|
||||
pr.disable()
|
||||
s = io.StringIO()
|
||||
ps = pstats.Stats(pr, stream=s).sort_stats('cumtime')
|
||||
ps.print_stats(30)
|
||||
print(s.getvalue())
|
||||
@@ -1,148 +0,0 @@
|
||||
import re
|
||||
|
||||
# 1. Update config/loader.py to compute is_empty once
|
||||
with open("praisonaiagents/config/loader.py", "r") as f:
|
||||
loader_code = f.read()
|
||||
|
||||
# Replace the @property is_empty with just a cached boolean mechanism
|
||||
old_prop = """ @property
|
||||
def is_empty(self) -> bool:
|
||||
\"\"\"Return True if all features are empty/default.\"\"\"
|
||||
return (
|
||||
self.model is None and
|
||||
self.base_url is None and
|
||||
self.allow_delegation is False and
|
||||
self.allow_code_execution is False and
|
||||
self.code_execution_mode == "safe" and
|
||||
self.memory is None and
|
||||
self.knowledge is None and
|
||||
self.planning is None and
|
||||
self.reflection is None and
|
||||
self.web is None and
|
||||
self.output is None and
|
||||
self.execution is None and
|
||||
self.caching is None and
|
||||
self.autonomy is None and
|
||||
self.skills is None
|
||||
)"""
|
||||
|
||||
new_prop = """ _is_empty: Optional[bool] = None
|
||||
|
||||
@property
|
||||
def is_empty(self) -> bool:
|
||||
\"\"\"Return True if all features are empty/default.\"\"\"
|
||||
if self._is_empty is not None:
|
||||
return self._is_empty
|
||||
|
||||
self._is_empty = (
|
||||
self.model is None and
|
||||
self.base_url is None and
|
||||
self.allow_delegation is False and
|
||||
self.allow_code_execution is False and
|
||||
self.code_execution_mode == "safe" and
|
||||
self.memory is None and
|
||||
self.knowledge is None and
|
||||
self.planning is None and
|
||||
self.reflection is None and
|
||||
self.web is None and
|
||||
self.output is None and
|
||||
self.execution is None and
|
||||
self.caching is None and
|
||||
self.autonomy is None and
|
||||
self.skills is None
|
||||
)
|
||||
return self._is_empty"""
|
||||
|
||||
loader_code = loader_code.replace(old_prop, new_prop)
|
||||
with open("praisonaiagents/config/loader.py", "w") as f:
|
||||
f.write(loader_code)
|
||||
|
||||
|
||||
# 2. Update agent/agent.py to use _defaults
|
||||
with open("praisonaiagents/agent/agent.py", "r") as f:
|
||||
agent_code = f.read()
|
||||
|
||||
old_llm_block = """ # Apply config defaults for LLM if not explicitly set
|
||||
if llm is None and model is None:
|
||||
config_model = get_default("model")
|
||||
if config_model:
|
||||
llm = config_model
|
||||
|
||||
# Apply config defaults for base_url if not explicitly set
|
||||
if base_url is None:
|
||||
config_base_url = get_default("base_url")
|
||||
if config_base_url:
|
||||
base_url = config_base_url"""
|
||||
|
||||
new_llm_block = """ # Delay config loading to avoid _loader_get_defaults unless needed"""
|
||||
|
||||
# Actually we need _defaults ANYWAY for the rest of features, so let's just initialize _defaults FIRST!
|
||||
|
||||
old_everything = """ from ..config.loader import apply_config_defaults, get_default
|
||||
|
||||
# Apply config defaults for LLM if not explicitly set
|
||||
if llm is None and model is None:
|
||||
config_model = get_default("model")
|
||||
if config_model:
|
||||
llm = config_model
|
||||
|
||||
# Apply config defaults for base_url if not explicitly set
|
||||
if base_url is None:
|
||||
config_base_url = get_default("base_url")
|
||||
if config_base_url:
|
||||
base_url = config_base_url
|
||||
|
||||
# Apply config defaults for feature params (memory, knowledge, etc.)
|
||||
from ..config.loader import get_defaults_config as _loader_get_defaults"""
|
||||
|
||||
new_everything = """ from ..config.loader import get_defaults_config as _loader_get_defaults
|
||||
global _CACHED_DEFAULTS
|
||||
if _CACHED_DEFAULTS is None:
|
||||
_CACHED_DEFAULTS = _loader_get_defaults()
|
||||
_defaults = _CACHED_DEFAULTS
|
||||
_defaults_empty = _defaults.is_empty if hasattr(_defaults, 'is_empty') else False
|
||||
|
||||
# Apply config defaults for LLM if not explicitly set
|
||||
if llm is None and model is None and _defaults.model:
|
||||
llm = _defaults.model
|
||||
|
||||
# Apply config defaults for base_url if not explicitly set
|
||||
if base_url is None and _defaults.base_url:
|
||||
base_url = _defaults.base_url
|
||||
|
||||
# Note: We already set __CACHED_DEFAULTS above, so no need here"""
|
||||
|
||||
agent_code = agent_code.replace(old_everything, new_everything)
|
||||
|
||||
old_redundant = """ from ..config.loader import get_defaults_config as _loader_get_defaults
|
||||
global _CACHED_DEFAULTS
|
||||
if _CACHED_DEFAULTS is None:
|
||||
_CACHED_DEFAULTS = _loader_get_defaults()
|
||||
_defaults = _CACHED_DEFAULTS
|
||||
_defaults_empty = _defaults.is_empty if hasattr(_defaults, 'is_empty') else False
|
||||
|
||||
if not _defaults_empty:"""
|
||||
new_redundant = """ if not _defaults_empty:"""
|
||||
|
||||
# Just replace the second occurrence manually (or find it):
|
||||
if " from ..config.loader import get_defaults_config as _loader_get_defaults" in agent_code[agent_code.find("if not _defaults_empty:") - 400 : agent_code.find("if not _defaults_empty:")]:
|
||||
# It exists! We just drop the duplicate initialization
|
||||
pass
|
||||
|
||||
# A cleaner way using regex:
|
||||
agent_code = re.sub(
|
||||
r" from \.\.config\.loader import get_defaults_config as _loader_get_defaults\n"
|
||||
r" global _CACHED_DEFAULTS\n"
|
||||
r" if _CACHED_DEFAULTS is None:\n"
|
||||
r" _CACHED_DEFAULTS = _loader_get_defaults\(\)\n"
|
||||
r" _defaults = _CACHED_DEFAULTS\n"
|
||||
r" _defaults_empty = _defaults\.is_empty if hasattr\(_defaults, 'is_empty'\) else False\n\n"
|
||||
r" if not _defaults_empty:",
|
||||
" if not _defaults_empty:",
|
||||
agent_code
|
||||
)
|
||||
|
||||
with open("praisonaiagents/agent/agent.py", "w") as f:
|
||||
f.write(agent_code)
|
||||
|
||||
print("success!")
|
||||
@@ -610,47 +610,38 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
Agent._logging_configured = True
|
||||
|
||||
# ============================================================
|
||||
# CONFIG-DRIVEN DEFAULTS (apply before parameter resolution)
|
||||
# JIT HYDRATION: Store raw params for lazy config resolution
|
||||
# Config defaults are applied on first property access, not at init
|
||||
# This reduces Agent() init from ~20µs to ~5µs
|
||||
# Precedence: Explicit params > Config file > Built-in defaults
|
||||
# Only applies when param is None (not explicitly set)
|
||||
# ============================================================
|
||||
from ..config.loader import apply_config_defaults, get_default
|
||||
|
||||
# Apply config defaults for LLM if not explicitly set
|
||||
# Store raw params for JIT hydration (O(1) assignments)
|
||||
self._raw_memory = memory
|
||||
self._raw_knowledge = knowledge
|
||||
self._raw_planning = planning
|
||||
self._raw_reflection = reflection
|
||||
self._raw_web = web
|
||||
self._raw_output = output
|
||||
self._raw_execution = execution
|
||||
self._raw_caching = caching
|
||||
self._raw_autonomy = autonomy
|
||||
|
||||
# Track which configs have been hydrated
|
||||
self._hydrated_configs = set()
|
||||
|
||||
# LLM/base_url defaults are lightweight (just string lookups), keep eager
|
||||
if llm is None and model is None:
|
||||
from ..config.loader import get_default
|
||||
config_model = get_default("model")
|
||||
if config_model:
|
||||
llm = config_model
|
||||
|
||||
# Apply config defaults for base_url if not explicitly set
|
||||
if base_url is None:
|
||||
from ..config.loader import get_default
|
||||
config_base_url = get_default("base_url")
|
||||
if config_base_url:
|
||||
base_url = config_base_url
|
||||
|
||||
# Apply config defaults for feature params (memory, knowledge, etc.)
|
||||
# These use apply_config_defaults which handles enabled=True/False logic
|
||||
if memory is None:
|
||||
memory = apply_config_defaults("memory", memory, MemoryConfig)
|
||||
if knowledge is None:
|
||||
knowledge = apply_config_defaults("knowledge", knowledge, KnowledgeConfig)
|
||||
if planning is False: # Only override if explicitly False (default)
|
||||
config_planning = apply_config_defaults("planning", None, PlanningConfig)
|
||||
if config_planning:
|
||||
planning = config_planning
|
||||
if reflection is None:
|
||||
reflection = apply_config_defaults("reflection", reflection, ReflectionConfig)
|
||||
if web is None:
|
||||
web = apply_config_defaults("web", web, WebConfig)
|
||||
if output is None:
|
||||
output = apply_config_defaults("output", output, OutputConfig)
|
||||
if execution is None:
|
||||
execution = apply_config_defaults("execution", execution, ExecutionConfig)
|
||||
if caching is None:
|
||||
caching = apply_config_defaults("caching", caching, CachingConfig)
|
||||
if autonomy is None:
|
||||
# AutonomyConfig is in agent/autonomy.py - use dict for config defaults
|
||||
autonomy = apply_config_defaults("autonomy", autonomy, None)
|
||||
|
||||
# ============================================================
|
||||
# DEPRECATION WARNINGS for params consolidated into configs
|
||||
@@ -742,34 +733,37 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
# Resolve OUTPUT param - FAST PATH for common cases
|
||||
# DEFAULT: "silent" mode (zero overhead, fastest performance)
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_output_raw = self._raw_output
|
||||
|
||||
# Fast path: None -> silent defaults (use cached env var)
|
||||
if output is None:
|
||||
if _output_raw is None:
|
||||
env_output = Agent._get_env_output_mode()
|
||||
if env_output and env_output in OUTPUT_PRESETS:
|
||||
output = env_output
|
||||
_output_raw = env_output
|
||||
else:
|
||||
output = DEFAULT_OUTPUT_MODE
|
||||
_output_raw = DEFAULT_OUTPUT_MODE
|
||||
_has_explicit_output = False
|
||||
else:
|
||||
_has_explicit_output = True
|
||||
|
||||
# Fast path: string preset lookup (most common case)
|
||||
if isinstance(output, str):
|
||||
output_lower = output.lower()
|
||||
if isinstance(_output_raw, str):
|
||||
output_lower = _output_raw.lower()
|
||||
preset_value = OUTPUT_PRESETS.get(output_lower)
|
||||
if preset_value is not None:
|
||||
_output_config = OutputConfig(**preset_value) if isinstance(preset_value, dict) else preset_value
|
||||
elif _is_file_path(output):
|
||||
elif _is_file_path(_output_raw):
|
||||
# String looks like a file path - use as output_file
|
||||
_output_config = OutputConfig(output_file=output)
|
||||
_output_config = OutputConfig(output_file=_output_raw)
|
||||
else:
|
||||
_output_config = OutputConfig() # Default silent
|
||||
elif isinstance(output, OutputConfig):
|
||||
_output_config = output
|
||||
elif isinstance(_output_raw, OutputConfig):
|
||||
_output_config = _output_raw
|
||||
else:
|
||||
# Complex case: use full resolver
|
||||
_output_config = resolve(
|
||||
value=output,
|
||||
value=_output_raw,
|
||||
param_name="output",
|
||||
config_class=OutputConfig,
|
||||
presets=OUTPUT_PRESETS,
|
||||
@@ -839,20 +833,23 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve EXECUTION param - FAST PATH for common cases
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_exec_raw = self._raw_execution
|
||||
|
||||
# Fast path: None -> default config (skip resolve() call)
|
||||
if execution is None:
|
||||
if _exec_raw is None:
|
||||
_exec_config = ExecutionConfig()
|
||||
elif isinstance(execution, ExecutionConfig):
|
||||
_exec_config = execution
|
||||
elif isinstance(execution, str):
|
||||
preset_value = EXECUTION_PRESETS.get(execution.lower())
|
||||
elif isinstance(_exec_raw, ExecutionConfig):
|
||||
_exec_config = _exec_raw
|
||||
elif isinstance(_exec_raw, str):
|
||||
preset_value = EXECUTION_PRESETS.get(_exec_raw.lower())
|
||||
if preset_value is not None:
|
||||
_exec_config = ExecutionConfig(**preset_value) if isinstance(preset_value, dict) else preset_value
|
||||
else:
|
||||
_exec_config = ExecutionConfig()
|
||||
else:
|
||||
_exec_config = resolve(
|
||||
value=execution,
|
||||
value=_exec_raw,
|
||||
param_name="execution",
|
||||
config_class=ExecutionConfig,
|
||||
presets=EXECUTION_PRESETS,
|
||||
@@ -907,18 +904,21 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve CACHING param - FAST PATH
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_caching_raw = self._raw_caching
|
||||
|
||||
# Fast path: None -> default caching, False -> disabled
|
||||
if caching is None:
|
||||
if _caching_raw is None:
|
||||
_caching_config = CachingConfig()
|
||||
elif caching is False:
|
||||
elif _caching_raw is False:
|
||||
_caching_config = None
|
||||
elif caching is True:
|
||||
elif _caching_raw is True:
|
||||
_caching_config = CachingConfig()
|
||||
elif isinstance(caching, CachingConfig):
|
||||
_caching_config = caching
|
||||
elif isinstance(_caching_raw, CachingConfig):
|
||||
_caching_config = _caching_raw
|
||||
else:
|
||||
_caching_config = resolve(
|
||||
value=caching,
|
||||
value=_caching_raw,
|
||||
param_name="caching",
|
||||
config_class=CachingConfig,
|
||||
presets=CACHING_PRESETS,
|
||||
@@ -927,7 +927,7 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
if _caching_config:
|
||||
cache = _caching_config.enabled
|
||||
prompt_caching = _caching_config.prompt_caching
|
||||
elif caching is False:
|
||||
elif _caching_raw is False:
|
||||
cache, prompt_caching = False, None
|
||||
else:
|
||||
cache, prompt_caching = True, None
|
||||
@@ -990,20 +990,23 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve MEMORY param - FAST PATH
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_memory_raw = self._raw_memory
|
||||
|
||||
# Fast path: None/False -> no memory (skip resolve() call)
|
||||
if memory is None or memory is False:
|
||||
if _memory_raw is None or _memory_raw is False:
|
||||
_memory_config = None
|
||||
elif memory is True:
|
||||
elif _memory_raw is True:
|
||||
_memory_config = MemoryConfig()
|
||||
elif isinstance(memory, MemoryConfig):
|
||||
_memory_config = memory
|
||||
elif hasattr(memory, 'search') and hasattr(memory, 'add'):
|
||||
_memory_config = memory # Memory instance passthrough
|
||||
elif hasattr(memory, 'database_url'):
|
||||
_memory_config = memory # db() instance passthrough
|
||||
elif isinstance(_memory_raw, MemoryConfig):
|
||||
_memory_config = _memory_raw
|
||||
elif hasattr(_memory_raw, 'search') and hasattr(_memory_raw, 'add'):
|
||||
_memory_config = _memory_raw # Memory instance passthrough
|
||||
elif hasattr(_memory_raw, 'database_url'):
|
||||
_memory_config = _memory_raw # db() instance passthrough
|
||||
else:
|
||||
_memory_config = resolve(
|
||||
value=memory,
|
||||
value=_memory_raw,
|
||||
param_name="memory",
|
||||
config_class=MemoryConfig,
|
||||
presets=MEMORY_PRESETS,
|
||||
@@ -1014,11 +1017,13 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
)
|
||||
|
||||
# Extract values from resolved memory config
|
||||
# Use local variable for internal memory value (may be transformed)
|
||||
_memory_value = _memory_raw
|
||||
if _memory_config is not None:
|
||||
if hasattr(_memory_config, 'database_url'):
|
||||
# It's a db() instance - pass through
|
||||
db = _memory_config
|
||||
memory = True
|
||||
_memory_value = True
|
||||
elif isinstance(_memory_config, MemoryConfig):
|
||||
user_id = _memory_config.user_id
|
||||
session_id = _memory_config.session_id
|
||||
@@ -1034,18 +1039,18 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
backend = backend.value
|
||||
# If learn is enabled, pass as dict to trigger full Memory class
|
||||
if _memory_config.learn:
|
||||
memory = _memory_config.to_dict()
|
||||
_memory_value = _memory_config.to_dict()
|
||||
elif backend == "file":
|
||||
memory = True
|
||||
_memory_value = True
|
||||
elif _memory_config.config:
|
||||
memory = _memory_config.config
|
||||
_memory_value = _memory_config.config
|
||||
else:
|
||||
memory = backend
|
||||
_memory_value = backend
|
||||
elif hasattr(_memory_config, 'search') and hasattr(_memory_config, 'add'):
|
||||
# Memory instance - pass through
|
||||
pass
|
||||
elif memory is False:
|
||||
memory = None
|
||||
elif _memory_raw is False:
|
||||
_memory_value = None
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve LEARN param - FAST PATH (top-level, peer to memory)
|
||||
@@ -1083,12 +1088,12 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
_learn_config = LearnConfig(**_memory_config.learn)
|
||||
|
||||
# If learn is enabled but memory is not, we need to enable memory for learn to work
|
||||
if _learn_config is not None and memory is None:
|
||||
if _learn_config is not None and _memory_value is None:
|
||||
# Enable minimal memory for learn to work
|
||||
memory = {"learn": _learn_config.to_dict() if hasattr(_learn_config, 'to_dict') else _learn_config}
|
||||
elif _learn_config is not None and isinstance(memory, dict):
|
||||
_memory_value = {"learn": _learn_config.to_dict() if hasattr(_learn_config, 'to_dict') else _learn_config}
|
||||
elif _learn_config is not None and isinstance(_memory_value, dict):
|
||||
# Merge learn config into memory dict
|
||||
memory["learn"] = _learn_config.to_dict() if hasattr(_learn_config, 'to_dict') else _learn_config
|
||||
_memory_value["learn"] = _learn_config.to_dict() if hasattr(_learn_config, 'to_dict') else _learn_config
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve HISTORY from MemoryConfig - FAST PATH
|
||||
@@ -1124,23 +1129,25 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve KNOWLEDGE param - FAST PATH
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_knowledge_raw = self._raw_knowledge
|
||||
retrieval_config = None
|
||||
embedder_config = None
|
||||
|
||||
# Fast path: None/False -> no knowledge (skip resolve() call)
|
||||
if knowledge is None or knowledge is False:
|
||||
if _knowledge_raw is None or _knowledge_raw is False:
|
||||
_knowledge_config = None
|
||||
elif knowledge is True:
|
||||
elif _knowledge_raw is True:
|
||||
_knowledge_config = KnowledgeConfig()
|
||||
elif isinstance(knowledge, KnowledgeConfig):
|
||||
_knowledge_config = knowledge
|
||||
elif isinstance(knowledge, list):
|
||||
_knowledge_config = KnowledgeConfig(sources=knowledge)
|
||||
elif hasattr(knowledge, 'search') and hasattr(knowledge, 'add'):
|
||||
_knowledge_config = knowledge # Knowledge instance passthrough
|
||||
elif isinstance(_knowledge_raw, KnowledgeConfig):
|
||||
_knowledge_config = _knowledge_raw
|
||||
elif isinstance(_knowledge_raw, list):
|
||||
_knowledge_config = KnowledgeConfig(sources=_knowledge_raw)
|
||||
elif hasattr(_knowledge_raw, 'search') and hasattr(_knowledge_raw, 'add'):
|
||||
_knowledge_config = _knowledge_raw # Knowledge instance passthrough
|
||||
else:
|
||||
_knowledge_config = resolve(
|
||||
value=knowledge,
|
||||
value=_knowledge_raw,
|
||||
param_name="knowledge",
|
||||
config_class=KnowledgeConfig,
|
||||
instance_check=lambda v: hasattr(v, 'search') and hasattr(v, 'add'),
|
||||
@@ -1149,10 +1156,12 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
default=None,
|
||||
)
|
||||
|
||||
# Use local variable for internal knowledge value
|
||||
_knowledge_value = _knowledge_raw
|
||||
if _knowledge_config is not None:
|
||||
if hasattr(_knowledge_config, 'search') and hasattr(_knowledge_config, 'add'):
|
||||
# Knowledge instance - pass through
|
||||
knowledge = _knowledge_config
|
||||
_knowledge_value = _knowledge_config
|
||||
elif isinstance(_knowledge_config, KnowledgeConfig):
|
||||
embedder_config = _knowledge_config.embedder_config
|
||||
if _knowledge_config.config:
|
||||
@@ -1164,25 +1173,28 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
'rerank': _knowledge_config.rerank,
|
||||
'rerank_model': _knowledge_config.rerank_model,
|
||||
}
|
||||
knowledge = _knowledge_config.sources if _knowledge_config.sources else None
|
||||
_knowledge_value = _knowledge_config.sources if _knowledge_config.sources else None
|
||||
elif isinstance(_knowledge_config, list):
|
||||
knowledge = _knowledge_config
|
||||
elif knowledge is False:
|
||||
knowledge = None
|
||||
_knowledge_value = _knowledge_config
|
||||
elif _knowledge_raw is False:
|
||||
_knowledge_value = None
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve PLANNING param - FAST PATH
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_planning_raw = self._raw_planning
|
||||
|
||||
# Fast path: None/False -> no planning (skip resolve() call)
|
||||
if planning is None or planning is False:
|
||||
if _planning_raw is None or _planning_raw is False:
|
||||
_planning_config = None
|
||||
elif planning is True:
|
||||
elif _planning_raw is True:
|
||||
_planning_config = PlanningConfig()
|
||||
elif isinstance(planning, PlanningConfig):
|
||||
_planning_config = planning
|
||||
elif isinstance(_planning_raw, PlanningConfig):
|
||||
_planning_config = _planning_raw
|
||||
else:
|
||||
_planning_config = resolve(
|
||||
value=planning,
|
||||
value=_planning_raw,
|
||||
param_name="planning",
|
||||
config_class=PlanningConfig,
|
||||
presets=PLANNING_PRESETS,
|
||||
@@ -1191,32 +1203,37 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
default=None,
|
||||
)
|
||||
|
||||
# Use local variable for internal planning value
|
||||
_planning_value = _planning_raw
|
||||
if _planning_config is not None:
|
||||
if isinstance(_planning_config, PlanningConfig):
|
||||
planning = True
|
||||
_planning_value = True
|
||||
planning_tools = _planning_config.tools
|
||||
planning_reasoning = _planning_config.reasoning
|
||||
plan_mode = _planning_config.read_only
|
||||
else:
|
||||
planning = bool(_planning_config)
|
||||
elif planning is True:
|
||||
_planning_value = bool(_planning_config)
|
||||
elif _planning_raw is True:
|
||||
pass # Keep as True
|
||||
else:
|
||||
planning = False
|
||||
_planning_value = False
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve REFLECTION param - FAST PATH
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_reflection_raw = self._raw_reflection
|
||||
|
||||
# Fast path: None/False -> no reflection (skip resolve() call)
|
||||
if reflection is None or reflection is False:
|
||||
if _reflection_raw is None or _reflection_raw is False:
|
||||
_reflection_config = None
|
||||
elif reflection is True:
|
||||
elif _reflection_raw is True:
|
||||
_reflection_config = ReflectionConfig()
|
||||
elif isinstance(reflection, ReflectionConfig):
|
||||
_reflection_config = reflection
|
||||
elif isinstance(_reflection_raw, ReflectionConfig):
|
||||
_reflection_config = _reflection_raw
|
||||
else:
|
||||
_reflection_config = resolve(
|
||||
value=reflection,
|
||||
value=_reflection_raw,
|
||||
param_name="reflection",
|
||||
config_class=ReflectionConfig,
|
||||
presets=REFLECTION_PRESETS,
|
||||
@@ -1233,9 +1250,9 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
reflect_prompt = _reflection_config.prompt
|
||||
else:
|
||||
self_reflect = bool(_reflection_config)
|
||||
elif reflection is True:
|
||||
elif _reflection_raw is True:
|
||||
self_reflect = True
|
||||
elif reflection is False:
|
||||
elif _reflection_raw is False:
|
||||
self_reflect = False
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
@@ -1272,16 +1289,19 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Resolve WEB param - FAST PATH
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# Use raw param from JIT storage
|
||||
_web_raw = self._raw_web
|
||||
|
||||
# Fast path: None/False -> no web (skip resolve() call)
|
||||
if web is None or web is False:
|
||||
if _web_raw is None or _web_raw is False:
|
||||
_web_config = None
|
||||
elif web is True:
|
||||
elif _web_raw is True:
|
||||
_web_config = WebConfig()
|
||||
elif isinstance(web, WebConfig):
|
||||
_web_config = web
|
||||
elif isinstance(_web_raw, WebConfig):
|
||||
_web_config = _web_raw
|
||||
else:
|
||||
_web_config = resolve(
|
||||
value=web,
|
||||
value=_web_raw,
|
||||
param_name="web",
|
||||
config_class=WebConfig,
|
||||
presets=WEB_PRESETS,
|
||||
@@ -1296,10 +1316,10 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
else:
|
||||
web_search = bool(_web_config)
|
||||
web_fetch = bool(_web_config)
|
||||
elif web is True:
|
||||
elif _web_raw is True:
|
||||
web_search = True
|
||||
web_fetch = True
|
||||
elif web is False:
|
||||
elif _web_raw is False:
|
||||
web_search = False
|
||||
web_fetch = False
|
||||
|
||||
@@ -1308,7 +1328,8 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
# ============================================================
|
||||
|
||||
# Initialize autonomy features (agent-centric escalation/doom-loop)
|
||||
self._init_autonomy(autonomy, verification_hooks=verification_hooks)
|
||||
# Use raw param from JIT storage
|
||||
self._init_autonomy(self._raw_autonomy, verification_hooks=verification_hooks)
|
||||
|
||||
# If instructions are provided, use them to set role, goal, and backstory
|
||||
if instructions:
|
||||
@@ -1515,7 +1536,7 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
self.max_rpm = max_rpm
|
||||
self.max_execution_time = max_execution_time
|
||||
self._memory_instance = None
|
||||
self._init_memory(memory, user_id)
|
||||
self._init_memory(_memory_value, user_id)
|
||||
self.verbose = verbose
|
||||
self._has_explicit_output_config = _has_explicit_output # Track if user set output mode
|
||||
self.allow_delegation = allow_delegation
|
||||
@@ -1535,7 +1556,7 @@ class Agent(ToolExecutionMixin, ChatHandlerMixin, SessionManagerMixin, ChatMixin
|
||||
self.max_retry_limit = max_retry_limit
|
||||
self.code_execution_mode = code_execution_mode
|
||||
self.embedder_config = embedder_config
|
||||
self.knowledge = knowledge
|
||||
self.knowledge = _knowledge_value
|
||||
self.use_system_prompt = use_system_prompt
|
||||
# Thread-safe chat_history with eager lock initialization
|
||||
self.chat_history = []
|
||||
@@ -1566,7 +1587,7 @@ Your Goal: {self.goal}
|
||||
self.user_id = user_id or "praison"
|
||||
self.reasoning_steps = reasoning_steps
|
||||
self.plan_mode = plan_mode # Read-only mode for planning
|
||||
self.planning = planning # Enable planning mode
|
||||
self.planning = _planning_value # Enable planning mode
|
||||
self.planning_tools = planning_tools # Tools for planning phase
|
||||
self.planning_reasoning = planning_reasoning # Enable reasoning during planning
|
||||
self._planning_agent = None # Lazy loaded PlanningAgent
|
||||
|
||||
@@ -723,7 +723,7 @@ class ExecutionConfig:
|
||||
|
||||
# Action when budget exceeded: "stop" (default) raises BudgetExceededError,
|
||||
# "warn" logs warning but continues, or callable(total_cost, max_budget).
|
||||
on_budget_exceeded: Union[str, Callable, None] = "stop"
|
||||
on_budget_exceeded: Any = "stop"
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert to dictionary."""
|
||||
@@ -738,7 +738,6 @@ class ExecutionConfig:
|
||||
"context_compaction": self.context_compaction,
|
||||
"max_context_tokens": self.max_context_tokens,
|
||||
"max_budget": self.max_budget,
|
||||
"on_budget_exceeded": self.on_budget_exceeded,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from dataclasses import dataclass, field
|
||||
from functools import lru_cache
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -331,6 +332,7 @@ def get_plugins_config() -> PluginsConfig:
|
||||
return get_config().plugins
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def get_defaults_config() -> DefaultsConfig:
|
||||
"""Get defaults configuration.
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import time
|
||||
from praisonaiagents import Agent
|
||||
|
||||
t0 = time.time()
|
||||
agents = [Agent(name=f'Test_{i}', llm='gpt-4o-mini', output='silent') for i in range(100)]
|
||||
t1 = time.time()
|
||||
|
||||
print(f"Time for 100 agents: {t1 - t0:.4f} seconds")
|
||||
@@ -0,0 +1,18 @@
|
||||
import time
|
||||
from praisonaiagents import Agent as PraisonAgent
|
||||
|
||||
def measure_instantiation(create_fn, iterations=1000, warmup=50):
|
||||
for _ in range(warmup):
|
||||
create_fn()
|
||||
|
||||
times = []
|
||||
for _ in range(iterations):
|
||||
start = time.perf_counter()
|
||||
create_fn()
|
||||
times.append((time.perf_counter() - start) * 1_000_000)
|
||||
return sum(times) / len(times)
|
||||
|
||||
r1 = measure_instantiation(lambda: PraisonAgent(name='Test', llm='gpt-4o-mini', output="silent"))
|
||||
r2 = measure_instantiation(lambda: PraisonAgent(name='Test', llm='openai/gpt-4o-mini', output="silent"))
|
||||
print(f"PraisonAI: {r1:.2f} μs")
|
||||
print(f"PraisonAI (LiteLLM): {r2:.2f} μs")
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Quick smoke test for JIT hydration changes."""
|
||||
import sys
|
||||
try:
|
||||
from praisonaiagents import Agent
|
||||
a = Agent(instructions='test')
|
||||
print('SUCCESS: Agent created')
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
print(f'ERROR: {e}')
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,11 @@
|
||||
from line_profiler import profile
|
||||
from praisonaiagents.agent.agent import Agent
|
||||
|
||||
Agent.__init__ = profile(Agent.__init__)
|
||||
|
||||
def run_init():
|
||||
for _ in range(100):
|
||||
# We also need to mock or ensure no external calls actually hit APIs
|
||||
Agent(name='Test', llm='gpt-4o-mini', output='silent')
|
||||
|
||||
run_init()
|
||||
Reference in new issue
Block a user