mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-09 17:31:52 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d65840e092 |
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>=2.3.75" \
|
||||
"praisonai>=2.3.76" \
|
||||
"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.75" \
|
||||
"praisonai>=2.3.76" \
|
||||
"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.75" \
|
||||
"praisonai>=2.3.76" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import sys
|
||||
warnings.filterwarnings("ignore", message=".*There is no current event loop.*", category=DeprecationWarning)
|
||||
warnings.filterwarnings("ignore", message=".*Pydantic serializer warnings.*")
|
||||
warnings.filterwarnings("ignore", message=".*PydanticSerializationUnexpectedValue.*")
|
||||
warnings.filterwarnings("ignore", message=".*Expected 9 fields but got.*")
|
||||
warnings.filterwarnings("ignore", message=".*Expected \\d+ fields but got.*")
|
||||
warnings.filterwarnings("ignore", message=".*Expected `StreamingChoices` but got.*")
|
||||
warnings.filterwarnings("ignore", message=".*serialized value may not be as expected.*")
|
||||
warnings.filterwarnings("ignore", message=".*Use 'content=<...>' to upload raw bytes/text content.*")
|
||||
@@ -28,7 +28,7 @@ SUPPRESSED_PATTERNS = [
|
||||
"The `dict` method is deprecated; use `model_dump` instead",
|
||||
"Pydantic serializer warnings",
|
||||
"PydanticSerializationUnexpectedValue",
|
||||
"Expected 9 fields but got 5 for type `Message`",
|
||||
"Expected", # Catches all "Expected N fields but got M" patterns
|
||||
"Expected `StreamingChoices` but got `Choices`",
|
||||
"serialized value may not be as expected",
|
||||
"Mixing V1 models and V2 models",
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
Generated
+1
-1
@@ -2422,7 +2422,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
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/v2.3.75.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.3.75.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.3.76.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.3.76.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -45,8 +45,10 @@ class AutoMemoryHandler(FlagHandler):
|
||||
def _get_auto_memory(self, user_id: str = None):
|
||||
"""Get AutoMemory instance lazily."""
|
||||
try:
|
||||
from praisonaiagents.memory import AutoMemory
|
||||
return AutoMemory(user_id=user_id or "default")
|
||||
from praisonaiagents.memory import AutoMemory, FileMemory
|
||||
# AutoMemory requires a FileMemory instance
|
||||
memory = FileMemory(user_id=user_id or "default")
|
||||
return AutoMemory(memory=memory)
|
||||
except ImportError:
|
||||
self.print_status(
|
||||
"AutoMemory requires praisonaiagents. Install with: pip install praisonaiagents",
|
||||
@@ -71,33 +73,36 @@ class AutoMemoryHandler(FlagHandler):
|
||||
config['auto_memory_user_id'] = flag_value.get('user_id', 'default')
|
||||
return config
|
||||
|
||||
def extract_memories(self, text: str, user_id: str = None) -> Dict[str, Any]:
|
||||
def extract_memories(self, text: str, user_id: str = None, user_message: str = None) -> list:
|
||||
"""
|
||||
Extract memories from text.
|
||||
Extract and store memories from text.
|
||||
|
||||
Args:
|
||||
text: Text to extract memories from
|
||||
text: Assistant response text to extract memories from
|
||||
user_id: User ID for memory isolation
|
||||
user_message: Original user message (for context)
|
||||
|
||||
Returns:
|
||||
Dictionary of extracted memories
|
||||
List of extracted memories
|
||||
"""
|
||||
auto_memory = self._get_auto_memory(user_id)
|
||||
if not auto_memory:
|
||||
return {}
|
||||
return []
|
||||
|
||||
try:
|
||||
if hasattr(auto_memory, 'extract'):
|
||||
memories = auto_memory.extract(text)
|
||||
self.print_status(f"🧠 Extracted {len(memories)} memories", "success")
|
||||
return memories
|
||||
elif hasattr(auto_memory, 'process'):
|
||||
result = auto_memory.process(text)
|
||||
return result
|
||||
# Use process_interaction which extracts AND stores memories
|
||||
memories = auto_memory.process_interaction(
|
||||
user_message=user_message or text,
|
||||
assistant_response=text if user_message else None,
|
||||
store=True # Store the memories
|
||||
)
|
||||
if memories:
|
||||
self.print_status(f"🧠 Extracted and stored {len(memories)} memories", "success")
|
||||
return memories
|
||||
except Exception as e:
|
||||
self.log(f"Memory extraction failed: {e}", "error")
|
||||
|
||||
return {}
|
||||
return []
|
||||
|
||||
def store_memory(self, content: str, user_id: str = None, importance: float = 0.5) -> bool:
|
||||
"""
|
||||
@@ -127,13 +132,14 @@ class AutoMemoryHandler(FlagHandler):
|
||||
self.log(f"Memory storage failed: {e}", "error")
|
||||
return False
|
||||
|
||||
def post_process_result(self, result: Any, flag_value: Any) -> Any:
|
||||
def post_process_result(self, result: Any, flag_value: Any, user_message: str = None) -> Any:
|
||||
"""
|
||||
Post-process result to extract and store memories.
|
||||
|
||||
Args:
|
||||
result: Agent output
|
||||
flag_value: Boolean or dict with configuration
|
||||
user_message: Original user message for context
|
||||
|
||||
Returns:
|
||||
Original result (memories are stored)
|
||||
@@ -144,15 +150,18 @@ class AutoMemoryHandler(FlagHandler):
|
||||
user_id = None
|
||||
if isinstance(flag_value, dict):
|
||||
user_id = flag_value.get('user_id')
|
||||
user_message = flag_value.get('user_message', user_message)
|
||||
|
||||
# Extract memories from result
|
||||
# Extract and store memories from result
|
||||
text = str(result)
|
||||
memories = self.extract_memories(text, user_id)
|
||||
memories = self.extract_memories(text, user_id, user_message=user_message)
|
||||
|
||||
if memories:
|
||||
self.print_status("\n🧠 Auto-extracted Memories:", "info")
|
||||
for key, value in memories.items():
|
||||
self.print_status(f" • {key}: {value[:50]}...", "info")
|
||||
for mem in memories:
|
||||
mem_type = mem.get('type', 'unknown')
|
||||
content = mem.get('content', str(mem))[:50]
|
||||
self.print_status(f" • {mem_type}: {content}...", "info")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -5,6 +5,42 @@ import argparse
|
||||
import warnings
|
||||
import os
|
||||
|
||||
# Suppress Pydantic serialization warnings from LiteLLM BEFORE any imports
|
||||
# These warnings occur when LiteLLM's response objects have field mismatches
|
||||
# Using both filterwarnings AND patching warnings.warn for complete suppression
|
||||
|
||||
warnings.filterwarnings("ignore", message=".*Pydantic serializer warnings.*")
|
||||
warnings.filterwarnings("ignore", message=".*PydanticSerializationUnexpectedValue.*")
|
||||
warnings.filterwarnings("ignore", message=".*Expected \\d+ fields but got.*")
|
||||
warnings.filterwarnings("ignore", message=".*Expected `StreamingChoices`.*")
|
||||
warnings.filterwarnings("ignore", message=".*Expected `Message`.*")
|
||||
warnings.filterwarnings("ignore", message=".*serialized value may not be as expected.*")
|
||||
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic.*")
|
||||
|
||||
# Patch warnings.showwarning to intercept ALL warnings including those from crewai's patched warn
|
||||
# This is the final output function that actually displays warnings
|
||||
_SUPPRESSED_PATTERNS = [
|
||||
"Pydantic serializer warnings",
|
||||
"PydanticSerializationUnexpectedValue",
|
||||
"Expected", # Catches "Expected N fields but got M"
|
||||
"StreamingChoices",
|
||||
"serialized value may not be as expected",
|
||||
"duckduckgo_search", # Suppress duckduckgo rename warning
|
||||
]
|
||||
|
||||
_original_showwarning = warnings.showwarning
|
||||
|
||||
def _patched_showwarning(message, category, filename, lineno, file=None, line=None):
|
||||
msg_str = str(message)
|
||||
for pattern in _SUPPRESSED_PATTERNS:
|
||||
if pattern in msg_str:
|
||||
return
|
||||
if category is UserWarning and "pydantic" in filename.lower():
|
||||
return
|
||||
_original_showwarning(message, category, filename, lineno, file, line)
|
||||
|
||||
warnings.showwarning = _patched_showwarning
|
||||
|
||||
# Suppress crewai RuntimeWarning about module loading order (only in non-debug mode)
|
||||
# This warning is harmless and occurs when running as `python -m praisonai.cli.main`
|
||||
if os.environ.get('LOGLEVEL', 'INFO').upper() != 'DEBUG':
|
||||
@@ -1342,12 +1378,47 @@ class PraisonAI:
|
||||
|
||||
console.print(table)
|
||||
|
||||
# Show recent memories
|
||||
# Show recent short-term memories
|
||||
print("\n[bold]Recent Short-term Memories:[/bold]")
|
||||
short_term = memory.get_short_term(limit=5)
|
||||
for i, item in enumerate(short_term, 1):
|
||||
content = item.get('content', str(item))[:100]
|
||||
print(f" {i}. {content}")
|
||||
if short_term:
|
||||
for i, item in enumerate(short_term, 1):
|
||||
content = item.get('content', str(item))[:100]
|
||||
print(f" {i}. {content}")
|
||||
else:
|
||||
print(" [dim]No short-term memories[/dim]")
|
||||
|
||||
# Show long-term memories
|
||||
print("\n[bold]Long-term Memories:[/bold]")
|
||||
long_term = memory.get_long_term(limit=10)
|
||||
if long_term:
|
||||
for i, item in enumerate(long_term, 1):
|
||||
# Handle both dict and MemoryItem objects
|
||||
if hasattr(item, 'content'):
|
||||
content = str(item.content)[:100]
|
||||
importance = getattr(item, 'importance', 0)
|
||||
else:
|
||||
content = item.get('content', str(item))[:100]
|
||||
importance = item.get('importance', 0)
|
||||
print(f" {i}. [{importance:.1f}] {content}")
|
||||
else:
|
||||
print(" [dim]No long-term memories[/dim]")
|
||||
|
||||
# Show entities
|
||||
print("\n[bold]Entities:[/bold]")
|
||||
entities = memory.get_all_entities()
|
||||
if entities:
|
||||
for entity in entities[:10]:
|
||||
# Handle both dict and Entity objects
|
||||
if hasattr(entity, 'name'):
|
||||
name = entity.name
|
||||
entity_type = getattr(entity, 'entity_type', 'unknown')
|
||||
else:
|
||||
name = entity.get('name', 'Unknown')
|
||||
entity_type = entity.get('entity_type', 'unknown')
|
||||
print(f" • {name} ({entity_type})")
|
||||
else:
|
||||
print(" [dim]No entities[/dim]")
|
||||
|
||||
elif action == 'add':
|
||||
if not action_args:
|
||||
@@ -3118,9 +3189,8 @@ Provide ONLY the commit message, no explanations."""
|
||||
telemetry = TelemetryHandler(verbose=getattr(self.args, 'verbose', False))
|
||||
telemetry.enable()
|
||||
|
||||
# Auto Memory - Automatic memory extraction
|
||||
# Auto Memory - Automatic memory extraction (handled post-processing, not as Agent param)
|
||||
if getattr(self.args, 'auto_memory', False):
|
||||
agent_config["auto_memory"] = True
|
||||
print("[bold cyan]Auto Memory enabled - will extract and store memories[/bold cyan]")
|
||||
|
||||
# MCP - Model Context Protocol tools
|
||||
@@ -3266,7 +3336,10 @@ Provide ONLY the commit message, no explanations."""
|
||||
if hasattr(self, 'args') and getattr(self.args, 'auto_memory', False):
|
||||
from .features.auto_memory import AutoMemoryHandler
|
||||
auto_mem = AutoMemoryHandler(verbose=getattr(self.args, 'verbose', False))
|
||||
auto_mem.post_process_result(result, {'user_id': getattr(self.args, 'user_id', None)})
|
||||
auto_mem.post_process_result(
|
||||
result,
|
||||
{'user_id': getattr(self.args, 'user_id', None), 'user_message': prompt}
|
||||
)
|
||||
|
||||
# Todo - Generate todo list from response
|
||||
if hasattr(self, 'args') and getattr(self.args, 'todo', False):
|
||||
|
||||
@@ -57,7 +57,7 @@ class CloudDeployer:
|
||||
file.write("FROM python:3.11-slim\n")
|
||||
file.write("WORKDIR /app\n")
|
||||
file.write("COPY . .\n")
|
||||
file.write("RUN pip install flask praisonai==2.3.75 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.3.76 gunicorn markdown\n")
|
||||
file.write("EXPOSE 8080\n")
|
||||
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "2.3.75"
|
||||
__version__ = "2.3.76"
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.1.23",
|
||||
"praisonaiagents>=0.1.24",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
|
||||
Generated
+4
-4
@@ -4197,7 +4197,7 @@ requires-dist = [
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.0.22" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'autogen-v4'", specifier = ">=0.0.22" },
|
||||
{ name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.0.22" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.1.23" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.1.24" },
|
||||
{ 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" },
|
||||
@@ -4252,7 +4252,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
@@ -4261,9 +4261,9 @@ dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "rich" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/79/5e/563a931f0d79f6c64fa8f891ad6eb88cacbbd3f26af5efe52c07a31f11b4/praisonaiagents-0.1.23.tar.gz", hash = "sha256:7a840172892c67feb68e04167db827017d5df8a0e496eb91e309d0e272db60c9", size = 678076, upload-time = "2025-12-22T17:00:28.27Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/31/3e/9dec08dd8107b963cdb3ea3a77b5530e7f68b239c38c80f713be27920f1b/praisonaiagents-0.1.24.tar.gz", hash = "sha256:8a6d17c2df22f2171df11b44b44b817e72a6f34f1f5b4e389691bedbbff06621", size = 678110, upload-time = "2025-12-23T05:39:18.104Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/b3/bf02847078595ab1cf109dfd3c7282eaece21f7b879fe96a3ae0d23e8571/praisonaiagents-0.1.23-py3-none-any.whl", hash = "sha256:a455c8fd04fdbd7dd7bf9755c24f19c9c496c404ef60a4fdfc4d4a51decb2e60", size = 616785, upload-time = "2025-12-22T17:00:26.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/33/3b45e341433a01408f59ced6eb39da3ecb17067f0ff3c954fa38e07aaffb/praisonaiagents-0.1.24-py3-none-any.whl", hash = "sha256:03a1c476bb5287ad9e519b85a17a93c42ce11b01db87009fcde17a1901e4828a", size = 616792, upload-time = "2025-12-23T05:39:16.12Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in new issue
Block a user