mirror of
https://github.com/MervinPraison/PraisonAI.git
synced 2026-11-08 17:31:00 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79b2b88f72 | ||
|
|
f5dfbd5670 | ||
|
|
aa6aa5933d |
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.5.2" \
|
||||
"praisonai>=2.5.3" \
|
||||
"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.5.2" \
|
||||
"praisonai>=2.5.3" \
|
||||
"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.5.2" \
|
||||
"praisonai>=2.5.3" \
|
||||
"praisonai[ui]" \
|
||||
"praisonai[crewai]"
|
||||
|
||||
|
||||
@@ -500,6 +500,33 @@ class Knowledge:
|
||||
base_config["graph_store"] = self._config["graph_store"]
|
||||
return base_config
|
||||
|
||||
def _prepare_mem0_config(self, config):
|
||||
"""Prepare config for mem0 by removing PraisonAI-specific fields.
|
||||
|
||||
mem0's RerankerConfig only accepts 'provider' and 'config' fields.
|
||||
PraisonAI adds 'enabled' and 'default_rerank' for internal use.
|
||||
"""
|
||||
mem0_config = config.copy()
|
||||
|
||||
# Strip PraisonAI-specific reranker fields that mem0 doesn't accept
|
||||
if "reranker" in mem0_config:
|
||||
reranker = mem0_config["reranker"]
|
||||
if isinstance(reranker, dict):
|
||||
# Keep only mem0-compatible fields: provider, config
|
||||
mem0_reranker = {}
|
||||
if "provider" in reranker:
|
||||
mem0_reranker["provider"] = reranker["provider"]
|
||||
if "config" in reranker:
|
||||
mem0_reranker["config"] = reranker["config"]
|
||||
|
||||
# If no valid mem0 fields, remove reranker entirely
|
||||
if mem0_reranker:
|
||||
mem0_config["reranker"] = mem0_reranker
|
||||
else:
|
||||
del mem0_config["reranker"]
|
||||
|
||||
return mem0_config
|
||||
|
||||
@cached_property
|
||||
def memory(self):
|
||||
# Check if MongoDB provider is specified
|
||||
@@ -511,19 +538,22 @@ class Knowledge:
|
||||
# Fall back to default memory
|
||||
pass
|
||||
|
||||
# Prepare config for mem0 (strip PraisonAI-specific fields)
|
||||
mem0_config = self._prepare_mem0_config(self.config)
|
||||
|
||||
# Default Mem0 memory
|
||||
try:
|
||||
return CustomMemory.from_config(self.config)
|
||||
return CustomMemory.from_config(mem0_config)
|
||||
except (NotImplementedError, ValueError) as e:
|
||||
if "list_collections" in str(e) or "Extra fields not allowed" in str(e):
|
||||
# Keep only allowed fields
|
||||
vector_store_config = {
|
||||
"collection_name": self.config["vector_store"]["config"]["collection_name"],
|
||||
"path": self.config["vector_store"]["config"]["path"]
|
||||
"collection_name": mem0_config["vector_store"]["config"]["collection_name"],
|
||||
"path": mem0_config["vector_store"]["config"]["path"]
|
||||
}
|
||||
self.config["vector_store"]["config"] = vector_store_config
|
||||
mem0_config["vector_store"]["config"] = vector_store_config
|
||||
from mem0 import Memory
|
||||
return Memory.from_config(self.config)
|
||||
return Memory.from_config(mem0_config)
|
||||
raise
|
||||
|
||||
@cached_property
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "praisonaiagents"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
@@ -1189,16 +1189,16 @@ class TestWorkflowConfiguration:
|
||||
"""Test that workflow planning setting is stored."""
|
||||
def step1(ctx): return StepResult(output="Done")
|
||||
|
||||
workflow = Workflow(steps=[step1], planning=True, planning_llm="gpt-4o")
|
||||
workflow = Workflow(steps=[step1], planning=True, planning_llm="gpt-5-nano")
|
||||
assert workflow.planning == True
|
||||
assert workflow.planning_llm == "gpt-4o"
|
||||
assert workflow.planning_llm == "gpt-5-nano"
|
||||
|
||||
def test_workflow_default_llm(self):
|
||||
"""Test default LLM setting."""
|
||||
def step1(ctx): return StepResult(output="Done")
|
||||
|
||||
workflow = Workflow(steps=[step1], default_llm="gpt-4o-mini")
|
||||
assert workflow.default_llm == "gpt-4o-mini"
|
||||
workflow = Workflow(steps=[step1], default_llm="gpt-5-nano")
|
||||
assert workflow.default_llm == "gpt-5-nano"
|
||||
|
||||
def test_workflow_default_agent_config(self):
|
||||
"""Test default agent config."""
|
||||
@@ -1393,10 +1393,10 @@ class TestPlanningAndReasoning:
|
||||
workflow = Workflow(
|
||||
steps=[lambda ctx: StepResult(output="test")],
|
||||
planning=True,
|
||||
planning_llm="gpt-4o"
|
||||
planning_llm="gpt-5-nano"
|
||||
)
|
||||
assert workflow.planning == True
|
||||
assert workflow.planning_llm == "gpt-4o"
|
||||
assert workflow.planning_llm == "gpt-5-nano"
|
||||
|
||||
def test_workflow_reasoning_parameter_exists(self):
|
||||
"""Test that Workflow accepts reasoning parameter."""
|
||||
|
||||
Generated
+1
-1
@@ -2422,7 +2422,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "praisonaiagents"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
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.5.2.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.5.2.tar.gz | shasum -a 256`.split.first
|
||||
url "https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.5.3.tar.gz"
|
||||
sha256 `curl -sL https://github.com/MervinPraison/PraisonAI/archive/refs/tags/v2.5.3.tar.gz | shasum -a 256`.split.first
|
||||
license "MIT"
|
||||
|
||||
depends_on "[email protected]"
|
||||
|
||||
@@ -131,18 +131,34 @@ Document: {document[:1000]}
|
||||
|
||||
Relevance score (0-10):"""
|
||||
|
||||
if hasattr(client, 'chat'):
|
||||
# PraisonAI Agent or similar
|
||||
# Check if client has a callable 'chat' method (PraisonAI Agent)
|
||||
# Note: OpenAI client has 'chat' attribute but it's a namespace, not callable
|
||||
if hasattr(client, 'chat') and callable(getattr(client, 'chat', None)):
|
||||
# PraisonAI Agent or similar with callable chat method
|
||||
response = client.chat(prompt)
|
||||
else:
|
||||
# OpenAI client
|
||||
response = client.chat.completions.create(
|
||||
model=self.model,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
max_tokens=10,
|
||||
temperature=0
|
||||
)
|
||||
response = response.choices[0].message.content
|
||||
# OpenAI client - use chat.completions.create
|
||||
# Try max_completion_tokens first (newer models), then max_tokens (older)
|
||||
# Note: Some models (e.g., gpt-5-nano) don't support temperature=0
|
||||
api_error = None
|
||||
for token_param in [{"max_completion_tokens": 10}, {"max_tokens": 10}]:
|
||||
try:
|
||||
response = client.chat.completions.create(
|
||||
model=self.model,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
**token_param
|
||||
)
|
||||
response = response.choices[0].message.content
|
||||
api_error = None
|
||||
break
|
||||
except Exception as e:
|
||||
api_error = e
|
||||
err_str = str(e).lower()
|
||||
if "max_completion_tokens" not in err_str and "max_tokens" not in err_str:
|
||||
raise # Re-raise if not a token param error
|
||||
continue
|
||||
if api_error:
|
||||
raise api_error
|
||||
|
||||
# Parse score
|
||||
if response:
|
||||
|
||||
@@ -107,7 +107,17 @@ class ChromaVectorStore:
|
||||
) -> List[str]:
|
||||
"""Add vectors to ChromaDB."""
|
||||
ids = ids or [str(uuid_module.uuid4()) for _ in texts]
|
||||
metadatas = metadatas or [{} for _ in texts]
|
||||
|
||||
# ChromaDB requires non-empty metadata dicts
|
||||
# Ensure each metadata dict has at least one key
|
||||
if metadatas is None:
|
||||
metadatas = [{"_source": "praisonai"} for _ in texts]
|
||||
else:
|
||||
# Ensure no empty dicts - add placeholder if empty
|
||||
metadatas = [
|
||||
m if m else {"_source": "praisonai"}
|
||||
for m in metadatas
|
||||
]
|
||||
|
||||
# Use different collection if namespace specified
|
||||
if namespace and namespace != self.namespace:
|
||||
|
||||
@@ -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.5.2 gunicorn markdown\n")
|
||||
file.write("RUN pip install flask praisonai==2.5.3 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.5.2"
|
||||
__version__ = "2.5.3"
|
||||
@@ -12,7 +12,7 @@ dependencies = [
|
||||
"rich>=13.7",
|
||||
"markdown>=3.5",
|
||||
"pyparsing>=3.0.0",
|
||||
"praisonaiagents>=0.3.2",
|
||||
"praisonaiagents>=0.3.3",
|
||||
"python-dotenv>=0.19.0",
|
||||
"instructor>=1.3.3",
|
||||
"PyYAML>=6.0",
|
||||
|
||||
@@ -59,12 +59,12 @@ class TestKnowledgeIntegration:
|
||||
}
|
||||
})
|
||||
|
||||
# Add document
|
||||
result = knowledge.add(test_file)
|
||||
# Add document (mem0 requires user_id, agent_id, or run_id)
|
||||
result = knowledge.add(test_file, user_id="test_user")
|
||||
assert result is not None
|
||||
|
||||
# Search
|
||||
results = knowledge.search("Who created Python?")
|
||||
results = knowledge.search("Who created Python?", user_id="test_user")
|
||||
assert len(results) > 0
|
||||
|
||||
@requires_openai
|
||||
@@ -83,15 +83,17 @@ class TestKnowledgeIntegration:
|
||||
}
|
||||
})
|
||||
|
||||
# Store text
|
||||
knowledge.store("The capital of France is Paris.")
|
||||
knowledge.store("The capital of Germany is Berlin.")
|
||||
# Store text (mem0 requires user_id, agent_id, or run_id)
|
||||
knowledge.store("The capital of France is Paris.", user_id="test_user")
|
||||
knowledge.store("The capital of Germany is Berlin.", user_id="test_user")
|
||||
|
||||
# Search
|
||||
results = knowledge.search("What is the capital of France?")
|
||||
assert len(results) > 0
|
||||
results = knowledge.search("What is the capital of France?", user_id="test_user")
|
||||
# Results is a dict with 'results' key containing list of memories
|
||||
result_list = results.get("results", results) if isinstance(results, dict) else results
|
||||
assert len(result_list) > 0
|
||||
# Check that Paris is mentioned in results
|
||||
result_text = str(results[0]).lower()
|
||||
result_text = str(result_list[0]).lower()
|
||||
assert "paris" in result_text or "france" in result_text
|
||||
|
||||
|
||||
@@ -187,7 +189,7 @@ class TestRerankerIntegration:
|
||||
except ImportError:
|
||||
pytest.skip("Reranker not available")
|
||||
|
||||
reranker = LLMReranker(model="gpt-5-nano")
|
||||
reranker = LLMReranker(model="gpt-4o-mini")
|
||||
|
||||
documents = [
|
||||
"Python is a programming language.",
|
||||
|
||||
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.3.2" },
|
||||
{ name = "praisonaiagents", specifier = ">=0.3.3" },
|
||||
{ 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.3.2"
|
||||
version = "0.3.3"
|
||||
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/30/8a/a33381c4f69e4ca1b639ad6b32d516c1adcd1d521ed78c8cdb2a947249fc/praisonaiagents-0.3.2.tar.gz", hash = "sha256:569fed4d865491cb67e7f3b6e2a603902f15bbeea1e104eb1691f634280b3155", size = 757144, upload-time = "2025-12-26T05:20:13.557Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/85/c2/04d0415e75c53a066ef42861c4699c0502885ab41aebe70e02f098075a83/praisonaiagents-0.3.3.tar.gz", hash = "sha256:82a6941e4bb7178ced495e4e0ae595a86e5e808b0998a96c89ebc45ce25d68db", size = 757530, upload-time = "2025-12-26T05:53:45.798Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/30/57526915881e5a9d1c3c24f6369c055df93613e4e5f64db6a3fc32579ce2/praisonaiagents-0.3.2-py3-none-any.whl", hash = "sha256:50f7b6aa0a825b16f001e7a09b7eb120b89f36b010743eca6b1ec6322d9662ca", size = 707842, upload-time = "2025-12-26T05:20:11.181Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/90/d9c035ebfcd341aef2f47dbc393feb902f817dd781333f5436da38449087/praisonaiagents-0.3.3-py3-none-any.whl", hash = "sha256:4dd787c9b77d159b13a2fd9043ddf21c8b16e69a708ea315e42c21e998a0d921", size = 708130, upload-time = "2025-12-26T05:53:43.826Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in new issue
Block a user