Compare commits

..

3 Commits

Author SHA1 Message Date
Brandon Hancock (bhancock_ai)
d9d9fc0103 Merge branch 'main' into bugfix/drop-pkg-resources 2024-12-12 12:39:44 -05:00
Brandon Hancock (bhancock_ai)
e9ab010fab Merge branch 'main' into bugfix/drop-pkg-resources 2024-12-12 12:19:01 -05:00
Brandon Hancock
934043d234 remove pkg_resources which was causing issues 2024-12-12 12:17:17 -05:00
21 changed files with 11153 additions and 594 deletions

View File

@@ -44,7 +44,7 @@ To get started with CrewAI, follow these simple steps:
### 1. Installation ### 1. Installation
Ensure you have Python >=3.10 <3.13 installed on your system. CrewAI uses [UV](https://docs.astral.sh/uv/) for dependency management and package handling, offering a seamless setup and execution experience. Ensure you have Python >=3.10 <=3.12 installed on your system. CrewAI uses [UV](https://docs.astral.sh/uv/) for dependency management and package handling, offering a seamless setup and execution experience.
First, install CrewAI: First, install CrewAI:

View File

@@ -7,7 +7,7 @@ icon: wrench
<Note> <Note>
**Python Version Requirements** **Python Version Requirements**
CrewAI requires `Python >=3.10 and <3.13`. Here's how to check your version: CrewAI requires `Python >=3.10 and <=3.12`. Here's how to check your version:
```bash ```bash
python3 --version python3 --version
``` ```

View File

@@ -3,7 +3,7 @@ name = "crewai"
version = "0.86.0" version = "0.86.0"
description = "Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks." description = "Cutting-edge framework for orchestrating role-playing, autonomous AI agents. By fostering collaborative intelligence, CrewAI empowers agents to work together seamlessly, tackling complex tasks."
readme = "README.md" readme = "README.md"
requires-python = ">=3.10,<3.13" requires-python = ">=3.10,<=3.12"
authors = [ authors = [
{ name = "Joao Moura", email = "joao@crewai.com" } { name = "Joao Moura", email = "joao@crewai.com" }
] ]
@@ -26,7 +26,7 @@ dependencies = [
"uv>=0.4.25", "uv>=0.4.25",
"tomli-w>=1.1.0", "tomli-w>=1.1.0",
"tomli>=2.0.2", "tomli>=2.0.2",
"chromadb>=0.5.23", "chromadb>=0.5.18",
"pdfplumber>=0.11.4", "pdfplumber>=0.11.4",
"openpyxl>=3.1.5", "openpyxl>=3.1.5",
"blinker>=1.9.0", "blinker>=1.9.0",
@@ -38,7 +38,7 @@ Documentation = "https://docs.crewai.com"
Repository = "https://github.com/crewAIInc/crewAI" Repository = "https://github.com/crewAIInc/crewAI"
[project.optional-dependencies] [project.optional-dependencies]
tools = ["crewai-tools>=0.17.0"] tools = ["crewai-tools>=0.14.0"]
agentops = ["agentops>=0.3.0"] agentops = ["agentops>=0.3.0"]
fastembed = ["fastembed>=0.4.1"] fastembed = ["fastembed>=0.4.1"]
pdfplumber = [ pdfplumber = [
@@ -64,7 +64,7 @@ dev-dependencies = [
"mkdocs-material-extensions>=1.3.1", "mkdocs-material-extensions>=1.3.1",
"pillow>=10.2.0", "pillow>=10.2.0",
"cairosvg>=2.7.1", "cairosvg>=2.7.1",
"crewai-tools>=0.17.0", "crewai-tools>=0.14.0",
"pytest>=8.0.0", "pytest>=8.0.0",
"pytest-vcr>=1.0.2", "pytest-vcr>=1.0.2",
"python-dotenv>=1.0.0", "python-dotenv>=1.0.0",

View File

@@ -23,19 +23,27 @@ from crewai.utilities.converter import generate_model_description
from crewai.utilities.token_counter_callback import TokenCalcHandler from crewai.utilities.token_counter_callback import TokenCalcHandler
from crewai.utilities.training_handler import CrewTrainingHandler from crewai.utilities.training_handler import CrewTrainingHandler
agentops = None
try: def mock_agent_ops_provider():
import agentops # type: ignore # Name "agentops" is already defined def track_agent(*args, **kwargs):
from agentops import track_agent # type: ignore
except ImportError:
def track_agent():
def noop(f): def noop(f):
return f return f
return noop return noop
return track_agent
agentops = None
if os.environ.get("AGENTOPS_API_KEY"):
try:
from agentops import track_agent
except ImportError:
track_agent = mock_agent_ops_provider()
else:
track_agent = mock_agent_ops_provider()
@track_agent() @track_agent()
class Agent(BaseAgent): class Agent(BaseAgent):

View File

@@ -4,7 +4,7 @@ Welcome to the {{crew_name}} Crew project, powered by [crewAI](https://crewai.co
## Installation ## Installation
Ensure you have Python >=3.10 <3.13 installed on your system. This project uses [UV](https://docs.astral.sh/uv/) for dependency management and package handling, offering a seamless setup and execution experience. Ensure you have Python >=3.10 <=3.12 installed on your system. This project uses [UV](https://docs.astral.sh/uv/) for dependency management and package handling, offering a seamless setup and execution experience.
First, if you haven't already, install uv: First, if you haven't already, install uv:

View File

@@ -3,7 +3,7 @@ name = "{{folder_name}}"
version = "0.1.0" version = "0.1.0"
description = "{{name}} using crewAI" description = "{{name}} using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }] authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<3.13" requires-python = ">=3.10,<=3.12"
dependencies = [ dependencies = [
"crewai[tools]>=0.86.0,<1.0.0" "crewai[tools]>=0.86.0,<1.0.0"
] ]

View File

@@ -4,7 +4,7 @@ Welcome to the {{crew_name}} Crew project, powered by [crewAI](https://crewai.co
## Installation ## Installation
Ensure you have Python >=3.10 <3.13 installed on your system. This project uses [UV](https://docs.astral.sh/uv/) for dependency management and package handling, offering a seamless setup and execution experience. Ensure you have Python >=3.10 <=3.12 installed on your system. This project uses [UV](https://docs.astral.sh/uv/) for dependency management and package handling, offering a seamless setup and execution experience.
First, if you haven't already, install uv: First, if you haven't already, install uv:

View File

@@ -3,7 +3,7 @@ name = "{{folder_name}}"
version = "0.1.0" version = "0.1.0"
description = "{{name}} using crewAI" description = "{{name}} using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }] authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<3.13" requires-python = ">=3.10,<=3.12"
dependencies = [ dependencies = [
"crewai[tools]>=0.86.0,<1.0.0", "crewai[tools]>=0.86.0,<1.0.0",
] ]

View File

@@ -5,7 +5,7 @@ custom tools to power up your crews.
## Installing ## Installing
Ensure you have Python >=3.10 <3.13 installed on your system. This project Ensure you have Python >=3.10 <=3.12 installed on your system. This project
uses [UV](https://docs.astral.sh/uv/) for dependency management and package uses [UV](https://docs.astral.sh/uv/) for dependency management and package
handling, offering a seamless setup and execution experience. handling, offering a seamless setup and execution experience.

View File

@@ -3,7 +3,7 @@ name = "{{folder_name}}"
version = "0.1.0" version = "0.1.0"
description = "Power up your crews with {{folder_name}}" description = "Power up your crews with {{folder_name}}"
readme = "README.md" readme = "README.md"
requires-python = ">=3.10,<3.13" requires-python = ">=3.10,<=3.12"
dependencies = [ dependencies = [
"crewai[tools]>=0.86.0" "crewai[tools]>=0.86.0"
] ]

View File

@@ -1,5 +1,6 @@
import asyncio import asyncio
import json import json
import os
import uuid import uuid
import warnings import warnings
from concurrent.futures import Future from concurrent.futures import Future
@@ -48,10 +49,12 @@ from crewai.utilities.planning_handler import CrewPlanner
from crewai.utilities.task_output_storage_handler import TaskOutputStorageHandler from crewai.utilities.task_output_storage_handler import TaskOutputStorageHandler
from crewai.utilities.training_handler import CrewTrainingHandler from crewai.utilities.training_handler import CrewTrainingHandler
agentops = None
if os.environ.get("AGENTOPS_API_KEY"):
try: try:
import agentops # type: ignore import agentops # type: ignore
except ImportError: except ImportError:
agentops = None pass
warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd") warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")

View File

@@ -124,44 +124,23 @@ class KnowledgeStorage(BaseKnowledgeStorage):
documents: List[str], documents: List[str],
metadata: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None, metadata: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None,
): ):
if not self.collection: if self.collection:
raise Exception("Collection not initialized")
try: try:
# Create a dictionary to store unique documents if metadata is None:
unique_docs = {} metadatas: Optional[OneOrMany[chromadb.Metadata]] = None
elif isinstance(metadata, list):
# Generate IDs and create a mapping of id -> (document, metadata) metadatas = [cast(chromadb.Metadata, m) for m in metadata]
for idx, doc in enumerate(documents):
doc_id = hashlib.sha256(doc.encode("utf-8")).hexdigest()
doc_metadata = None
if metadata is not None:
if isinstance(metadata, list):
doc_metadata = metadata[idx]
else: else:
doc_metadata = metadata metadatas = cast(chromadb.Metadata, metadata)
unique_docs[doc_id] = (doc, doc_metadata)
# Prepare filtered lists for ChromaDB ids = [
filtered_docs = [] hashlib.sha256(doc.encode("utf-8")).hexdigest() for doc in documents
filtered_metadata = [] ]
filtered_ids = []
# Build the filtered lists
for doc_id, (doc, meta) in unique_docs.items():
filtered_docs.append(doc)
filtered_metadata.append(meta)
filtered_ids.append(doc_id)
# If we have no metadata at all, set it to None
final_metadata: Optional[OneOrMany[chromadb.Metadata]] = (
None if all(m is None for m in filtered_metadata) else filtered_metadata
)
self.collection.upsert( self.collection.upsert(
documents=filtered_docs, documents=documents,
metadatas=final_metadata, metadatas=metadatas,
ids=filtered_ids, ids=ids,
) )
except chromadb.errors.InvalidDimensionException as e: except chromadb.errors.InvalidDimensionException as e:
Logger(verbose=True).log( Logger(verbose=True).log(
@@ -175,8 +154,12 @@ class KnowledgeStorage(BaseKnowledgeStorage):
"Try resetting the collection using `crewai reset-memories -a`" "Try resetting the collection using `crewai reset-memories -a`"
) from e ) from e
except Exception as e: except Exception as e:
Logger(verbose=True).log("error", f"Failed to upsert documents: {e}", "red") Logger(verbose=True).log(
"error", f"Failed to upsert documents: {e}", "red"
)
raise raise
else:
raise Exception("Collection not initialized")
def _create_default_embedding_function(self): def _create_default_embedding_function(self):
from chromadb.utils.embedding_functions.openai_embedding_function import ( from chromadb.utils.embedding_functions.openai_embedding_function import (

View File

@@ -1,5 +1,6 @@
import ast import ast
import datetime import datetime
import os
import time import time
from difflib import SequenceMatcher from difflib import SequenceMatcher
from textwrap import dedent from textwrap import dedent
@@ -14,10 +15,12 @@ from crewai.tools.tool_calling import InstructorToolCalling, ToolCalling
from crewai.tools.tool_usage_events import ToolUsageError, ToolUsageFinished from crewai.tools.tool_usage_events import ToolUsageError, ToolUsageFinished
from crewai.utilities import I18N, Converter, ConverterError, Printer from crewai.utilities import I18N, Converter, ConverterError, Printer
agentops = None
if os.environ.get("AGENTOPS_API_KEY"):
try: try:
import agentops # type: ignore import agentops # type: ignore
except ImportError: except ImportError:
agentops = None pass
OPENAI_BIGGER_MODELS = ["gpt-4", "gpt-4o", "o1-preview", "o1-mini"] OPENAI_BIGGER_MODELS = ["gpt-4", "gpt-4o", "o1-preview", "o1-mini"]
@@ -419,10 +422,9 @@ class ToolUsage:
elif value.lower() in [ elif value.lower() in [
"true", "true",
"false", "false",
"null",
]: # Check for boolean and null values ]: # Check for boolean and null values
value = value.lower().capitalize() value = value.lower()
elif value.lower() == "null":
value = "None"
else: else:
# Assume the value is a string and needs quotes # Assume the value is a string and needs quotes
value = '"' + value.replace('"', '\\"') + '"' value = '"' + value.replace('"', '\\"') + '"'

View File

@@ -1,7 +1,6 @@
import json import json
from datetime import date, datetime from datetime import date, datetime
from decimal import Decimal from decimal import Decimal
from enum import Enum
from uuid import UUID from uuid import UUID
from pydantic import BaseModel from pydantic import BaseModel
@@ -11,7 +10,7 @@ class CrewJSONEncoder(json.JSONEncoder):
def default(self, obj): def default(self, obj):
if isinstance(obj, BaseModel): if isinstance(obj, BaseModel):
return self._handle_pydantic_model(obj) return self._handle_pydantic_model(obj)
elif isinstance(obj, UUID) or isinstance(obj, Decimal) or isinstance(obj, Enum): elif isinstance(obj, UUID) or isinstance(obj, Decimal):
return str(obj) return str(obj)
elif isinstance(obj, datetime) or isinstance(obj, date): elif isinstance(obj, datetime) or isinstance(obj, date):

View File

@@ -1,3 +1,4 @@
import os
from typing import List from typing import List
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@@ -5,17 +6,27 @@ from pydantic import BaseModel, Field
from crewai.utilities import Converter from crewai.utilities import Converter
from crewai.utilities.pydantic_schema_parser import PydanticSchemaParser from crewai.utilities.pydantic_schema_parser import PydanticSchemaParser
agentops = None
try:
from agentops import track_agent # type: ignore
except ImportError:
def track_agent(name): def mock_agent_ops_provider():
def track_agent(*args, **kwargs):
def noop(f): def noop(f):
return f return f
return noop return noop
return track_agent
agentops = None
if os.environ.get("AGENTOPS_API_KEY"):
try:
from agentops import track_agent
except ImportError:
track_agent = mock_agent_ops_provider()
else:
track_agent = mock_agent_ops_provider()
class Entity(BaseModel): class Entity(BaseModel):
name: str = Field(description="The name of the entity.") name: str = Field(description="The name of the entity.")

View File

@@ -1595,15 +1595,19 @@ def test_agent_execute_task_with_ollama():
@pytest.mark.vcr(filter_headers=["authorization"]) @pytest.mark.vcr(filter_headers=["authorization"])
def test_agent_with_knowledge_sources(): def test_agent_with_knowledge_sources():
# Create a knowledge source with some content # Create a knowledge source with some content
content = "Brandon's favorite color is red and he likes Mexican food." content = "Brandon's favorite color is blue and he likes Mexican food."
string_source = StringKnowledgeSource(content=content) string_source = StringKnowledgeSource(
content=content, metadata={"preference": "personal"}
)
with patch( with patch(
"crewai.knowledge.storage.knowledge_storage.KnowledgeStorage" "crewai.knowledge.storage.knowledge_storage.KnowledgeStorage"
) as MockKnowledge: ) as MockKnowledge:
mock_knowledge_instance = MockKnowledge.return_value mock_knowledge_instance = MockKnowledge.return_value
mock_knowledge_instance.sources = [string_source] mock_knowledge_instance.sources = [string_source]
mock_knowledge_instance.query.return_value = [{"content": content}] mock_knowledge_instance.query.return_value = [
{"content": content, "metadata": {"preference": "personal"}}
]
agent = Agent( agent = Agent(
role="Information Agent", role="Information Agent",
@@ -1624,4 +1628,4 @@ def test_agent_with_knowledge_sources():
result = crew.kickoff() result = crew.kickoff()
# Assert that the agent provides the correct information # Assert that the agent provides the correct information
assert "red" in result.raw.lower() assert "blue" in result.raw.lower()

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -231,7 +231,7 @@ class TestDeployCommand(unittest.TestCase):
[project] [project]
name = "test_project" name = "test_project"
version = "0.1.0" version = "0.1.0"
requires-python = ">=3.10,<3.13" requires-python = ">=3.10,<=3.12"
dependencies = ["crewai"] dependencies = ["crewai"]
""", """,
) )
@@ -250,7 +250,7 @@ class TestDeployCommand(unittest.TestCase):
[project] [project]
name = "test_project" name = "test_project"
version = "0.1.0" version = "0.1.0"
requires-python = ">=3.10,<3.13" requires-python = ">=3.10,<=3.12"
dependencies = ["crewai"] dependencies = ["crewai"]
""", """,
) )

View File

@@ -686,7 +686,7 @@ def test_increment_tool_errors():
with patch.object(Task, "increment_tools_errors") as increment_tools_errors: with patch.object(Task, "increment_tools_errors") as increment_tools_errors:
increment_tools_errors.return_value = None increment_tools_errors.return_value = None
crew.kickoff() crew.kickoff()
assert len(increment_tools_errors.mock_calls) > 0 assert len(increment_tools_errors.mock_calls) == 12
def test_task_definition_based_on_dict(): def test_task_definition_based_on_dict():

17
uv.lock generated
View File

@@ -1,10 +1,9 @@
version = 1 version = 1
requires-python = ">=3.10, <3.13" requires-python = ">=3.10, <=3.12"
resolution-markers = [ resolution-markers = [
"python_full_version < '3.11'", "python_full_version < '3.11'",
"python_full_version == '3.11.*'", "python_full_version == '3.11.*'",
"python_full_version >= '3.12' and python_full_version < '3.12.4'", "python_full_version >= '3.12'",
"python_full_version >= '3.12.4'",
] ]
[[package]] [[package]]
@@ -480,7 +479,7 @@ wheels = [
[[package]] [[package]]
name = "chromadb" name = "chromadb"
version = "0.5.23" version = "0.5.18"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "bcrypt" }, { name = "bcrypt" },
@@ -512,9 +511,9 @@ dependencies = [
{ name = "typing-extensions" }, { name = "typing-extensions" },
{ name = "uvicorn", extra = ["standard"] }, { name = "uvicorn", extra = ["standard"] },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/42/64/28daa773f784bcd18de944fe26ed301de844d6ee17188e26a9d6b4baf122/chromadb-0.5.23.tar.gz", hash = "sha256:360a12b9795c5a33cb1f839d14410ccbde662ef1accd36153b0ae22312edabd1", size = 33700455 } sdist = { url = "https://files.pythonhosted.org/packages/15/95/d1a3f14c864e37d009606b82bd837090902b5e5a8e892fcab07eeaec0438/chromadb-0.5.18.tar.gz", hash = "sha256:cfbb3e5aeeb1dd532b47d80ed9185e8a9886c09af41c8e6123edf94395d76aec", size = 33620708 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/92/8c/a9eb95a28e6c35a0122417976a9d435eeaceb53f596a8973e33b3dd4cfac/chromadb-0.5.23-py3-none-any.whl", hash = "sha256:ffe5bdd7276d12cb682df0d38a13aa37573e6a3678e71889ac45f539ae05ad7e", size = 628347 }, { url = "https://files.pythonhosted.org/packages/82/85/4d2f8b9202153105ad4514ae09e9fe6f3b353a45e44e0ef7eca03dd8b9dc/chromadb-0.5.18-py3-none-any.whl", hash = "sha256:9dd3827b5e04b4ff0a5ea0df28a78bac88a09f45be37fcd7fe20f879b57c43cf", size = 615499 },
] ]
[[package]] [[package]]
@@ -649,9 +648,9 @@ requires-dist = [
{ name = "appdirs", specifier = ">=1.4.4" }, { name = "appdirs", specifier = ">=1.4.4" },
{ name = "auth0-python", specifier = ">=4.7.1" }, { name = "auth0-python", specifier = ">=4.7.1" },
{ name = "blinker", specifier = ">=1.9.0" }, { name = "blinker", specifier = ">=1.9.0" },
{ name = "chromadb", specifier = ">=0.5.23" }, { name = "chromadb", specifier = ">=0.5.18" },
{ name = "click", specifier = ">=8.1.7" }, { name = "click", specifier = ">=8.1.7" },
{ name = "crewai-tools", marker = "extra == 'tools'", specifier = ">=0.17.0" }, { name = "crewai-tools", marker = "extra == 'tools'", specifier = ">=0.14.0" },
{ name = "fastembed", marker = "extra == 'fastembed'", specifier = ">=0.4.1" }, { name = "fastembed", marker = "extra == 'fastembed'", specifier = ">=0.4.1" },
{ name = "instructor", specifier = ">=1.3.3" }, { name = "instructor", specifier = ">=1.3.3" },
{ name = "json-repair", specifier = ">=0.25.2" }, { name = "json-repair", specifier = ">=0.25.2" },
@@ -679,7 +678,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "cairosvg", specifier = ">=2.7.1" }, { name = "cairosvg", specifier = ">=2.7.1" },
{ name = "crewai-tools", specifier = ">=0.17.0" }, { name = "crewai-tools", specifier = ">=0.14.0" },
{ name = "mkdocs", specifier = ">=1.4.3" }, { name = "mkdocs", specifier = ">=1.4.3" },
{ name = "mkdocs-material", specifier = ">=9.5.7" }, { name = "mkdocs-material", specifier = ">=9.5.7" },
{ name = "mkdocs-material-extensions", specifier = ">=1.3.1" }, { name = "mkdocs-material-extensions", specifier = ">=1.3.1" },