merge: Merge main branch into task-guardrails branch

Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
Devin AI
2024-12-22 03:46:27 +00:00
33 changed files with 660 additions and 11206 deletions

View File

@@ -1,5 +1,10 @@
name: Mark stale issues and pull requests
permissions:
contents: write
issues: write
pull-requests: write
on:
schedule:
- cron: '10 12 * * *'
@@ -8,9 +13,6 @@ on:
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:

View File

@@ -44,7 +44,7 @@ To get started with CrewAI, follow these simple steps:
### 1. Installation
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.
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.
First, install CrewAI:

View File

@@ -29,7 +29,7 @@ Large Language Models (LLMs) are the core intelligence behind CrewAI agents. The
## Available Models and Their Capabilities
Here's a detailed breakdown of supported models and their capabilities, you can compare performance at [lmarena.ai](https://lmarena.ai/):
Here's a detailed breakdown of supported models and their capabilities, you can compare performance at [lmarena.ai](https://lmarena.ai/?leaderboard) and [artificialanalysis.ai](https://artificialanalysis.ai/):
<Tabs>
<Tab title="OpenAI">
@@ -121,12 +121,18 @@ Here's a detailed breakdown of supported models and their capabilities, you can
<Tab title="Gemini">
| Model | Context Window | Best For |
|-------|---------------|-----------|
| Gemini 1.5 Flash | 1M tokens | Balanced multimodal model, good for most tasks |
| Gemini 1.5 Flash 8B | 1M tokens | Fastest, most cost-efficient, good for high-frequency tasks |
| Gemini 1.5 Pro | 2M tokens | Best performing, wide variety of reasoning tasks including logical reasoning, coding, and creative collaboration |
| gemini-2.0-flash-exp | 1M tokens | Higher quality at faster speed, multimodal model, good for most tasks |
| gemini-1.5-flash | 1M tokens | Balanced multimodal model, good for most tasks |
| gemini-1.5-flash-8B | 1M tokens | Fastest, most cost-efficient, good for high-frequency tasks |
| gemini-1.5-pro | 2M tokens | Best performing, wide variety of reasoning tasks including logical reasoning, coding, and creative collaboration |
<Tip>
Google's Gemini models are all multimodal, supporting audio, images, video and text, supporting context caching, json schema, function calling, etc.
These models are available via API_KEY from
[The Gemini API](https://ai.google.dev/gemini-api/docs) and also from
[Google Cloud Vertex](https://cloud.google.com/vertex-ai/generative-ai/docs/migrate/migrate-google-ai) as part of the
[Model Garden](https://cloud.google.com/vertex-ai/generative-ai/docs/model-garden/explore-models).
</Tip>
</Tab>
<Tab title="Groq">
@@ -135,7 +141,6 @@ Here's a detailed breakdown of supported models and their capabilities, you can
| Llama 3.1 70B/8B | 131,072 tokens | High-performance, large context tasks |
| Llama 3.2 Series | 8,192 tokens | General-purpose tasks |
| Mixtral 8x7B | 32,768 tokens | Balanced performance and context |
| Gemma Series | 8,192 tokens | Efficient, smaller-scale tasks |
<Tip>
Groq is known for its fast inference speeds, making it suitable for real-time applications.
@@ -146,7 +151,7 @@ Here's a detailed breakdown of supported models and their capabilities, you can
|----------|---------------|--------------|
| Deepseek Chat | 128,000 tokens | Specialized in technical discussions |
| Claude 3 | Up to 200K tokens | Strong reasoning, code understanding |
| Gemini | Varies by model | Multimodal capabilities |
| Gemma Series | 8,192 tokens | Efficient, smaller-scale tasks |
<Info>
Provider selection should consider factors like:

View File

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

View File

@@ -3,7 +3,7 @@ name = "crewai"
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."
readme = "README.md"
requires-python = ">=3.10,<=3.12"
requires-python = ">=3.10,<3.13"
authors = [
{ name = "Joao Moura", email = "joao@crewai.com" }
]
@@ -26,7 +26,7 @@ dependencies = [
"uv>=0.4.25",
"tomli-w>=1.1.0",
"tomli>=2.0.2",
"chromadb>=0.5.18",
"chromadb>=0.5.23",
"pdfplumber>=0.11.4",
"openpyxl>=3.1.5",
"blinker>=1.9.0",
@@ -38,7 +38,7 @@ Documentation = "https://docs.crewai.com"
Repository = "https://github.com/crewAIInc/crewAI"
[project.optional-dependencies]
tools = ["crewai-tools>=0.14.0"]
tools = ["crewai-tools>=0.17.0"]
agentops = ["agentops>=0.3.0"]
fastembed = ["fastembed>=0.4.1"]
pdfplumber = [
@@ -64,7 +64,7 @@ dev-dependencies = [
"mkdocs-material-extensions>=1.3.1",
"pillow>=10.2.0",
"cairosvg>=2.7.1",
"crewai-tools>=0.14.0",
"crewai-tools>=0.17.0",
"pytest>=8.0.0",
"pytest-vcr>=1.0.2",
"python-dotenv>=1.0.0",

View File

@@ -23,27 +23,19 @@ from crewai.utilities.converter import generate_model_description
from crewai.utilities.token_counter_callback import TokenCalcHandler
from crewai.utilities.training_handler import CrewTrainingHandler
agentops = None
def mock_agent_ops_provider():
def track_agent(*args, **kwargs):
try:
import agentops # type: ignore # Name "agentops" is already defined
from agentops import track_agent # type: ignore
except ImportError:
def track_agent():
def noop(f):
return f
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()
class Agent(BaseAgent):

View File

@@ -1,7 +1,7 @@
from importlib.metadata import version as get_version
from typing import Optional
import click
import pkg_resources
from crewai.cli.add_crew_to_flow import add_crew_to_flow
from crewai.cli.create_crew import create_crew
@@ -25,7 +25,7 @@ from .update_crew import update_crew
@click.group()
@click.version_option(pkg_resources.get_distribution("crewai").version)
@click.version_option(get_version("crewai"))
def crewai():
"""Top-level command group for crewai."""
@@ -52,16 +52,16 @@ def create(type, name, provider, skip_provider=False):
def version(tools):
"""Show the installed version of crewai."""
try:
crewai_version = pkg_resources.get_distribution("crewai").version
crewai_version = get_version("crewai")
except Exception:
crewai_version = "unknown version"
click.echo(f"crewai version: {crewai_version}")
if tools:
try:
tools_version = pkg_resources.get_distribution("crewai-tools").version
tools_version = get_version("crewai")
click.echo(f"crewai tools version: {tools_version}")
except pkg_resources.DistributionNotFound:
except Exception:
click.echo("crewai tools not installed")

View File

@@ -4,7 +4,7 @@ Welcome to the {{crew_name}} Crew project, powered by [crewAI](https://crewai.co
## Installation
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.
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.
First, if you haven't already, install uv:

View File

@@ -3,7 +3,7 @@ name = "{{folder_name}}"
version = "0.1.0"
description = "{{name}} using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<=3.12"
requires-python = ">=3.10,<3.13"
dependencies = [
"crewai[tools]>=0.86.0,<1.0.0"
]
@@ -18,3 +18,6 @@ test = "{{folder_name}}.main:test"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.crewai]
type = "crew"

View File

@@ -10,7 +10,7 @@ class MyCustomToolInput(BaseModel):
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = (
"Clear description for what this tool is useful for, you agent will need this information to use it."
"Clear description for what this tool is useful for, your agent will need this information to use it."
)
args_schema: Type[BaseModel] = MyCustomToolInput

View File

@@ -4,7 +4,7 @@ Welcome to the {{crew_name}} Crew project, powered by [crewAI](https://crewai.co
## Installation
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.
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.
First, if you haven't already, install uv:

View File

@@ -5,7 +5,7 @@ from pydantic import BaseModel
from crewai.flow.flow import Flow, listen, start
from .crews.poem_crew.poem_crew import PoemCrew
from {{folder_name}}.crews.poem_crew.poem_crew import PoemCrew
class PoemState(BaseModel):

View File

@@ -3,7 +3,7 @@ name = "{{folder_name}}"
version = "0.1.0"
description = "{{name}} using crewAI"
authors = [{ name = "Your Name", email = "you@example.com" }]
requires-python = ">=3.10,<=3.12"
requires-python = ">=3.10,<3.13"
dependencies = [
"crewai[tools]>=0.86.0,<1.0.0",
]
@@ -15,3 +15,6 @@ plot = "{{folder_name}}.main:plot"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.crewai]
type = "flow"

View File

@@ -13,7 +13,7 @@ class MyCustomToolInput(BaseModel):
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = (
"Clear description for what this tool is useful for, you agent will need this information to use it."
"Clear description for what this tool is useful for, your agent will need this information to use it."
)
args_schema: Type[BaseModel] = MyCustomToolInput

View File

@@ -5,7 +5,7 @@ custom tools to power up your crews.
## Installing
Ensure you have Python >=3.10 <=3.12 installed on your system. This project
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.

View File

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

View File

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

View File

@@ -124,43 +124,60 @@ class KnowledgeStorage(BaseKnowledgeStorage):
documents: List[str],
metadata: Optional[Union[Dict[str, Any], List[Dict[str, Any]]]] = None,
):
if self.collection:
try:
if metadata is None:
metadatas: Optional[OneOrMany[chromadb.Metadata]] = None
elif isinstance(metadata, list):
metadatas = [cast(chromadb.Metadata, m) for m in metadata]
else:
metadatas = cast(chromadb.Metadata, metadata)
ids = [
hashlib.sha256(doc.encode("utf-8")).hexdigest() for doc in documents
]
self.collection.upsert(
documents=documents,
metadatas=metadatas,
ids=ids,
)
except chromadb.errors.InvalidDimensionException as e:
Logger(verbose=True).log(
"error",
"Embedding dimension mismatch. This usually happens when mixing different embedding models. Try resetting the collection using `crewai reset-memories -a`",
"red",
)
raise ValueError(
"Embedding dimension mismatch. Make sure you're using the same embedding model "
"across all operations with this collection."
"Try resetting the collection using `crewai reset-memories -a`"
) from e
except Exception as e:
Logger(verbose=True).log(
"error", f"Failed to upsert documents: {e}", "red"
)
raise
else:
if not self.collection:
raise Exception("Collection not initialized")
try:
# Create a dictionary to store unique documents
unique_docs = {}
# Generate IDs and create a mapping of id -> (document, 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:
doc_metadata = metadata
unique_docs[doc_id] = (doc, doc_metadata)
# Prepare filtered lists for ChromaDB
filtered_docs = []
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(
documents=filtered_docs,
metadatas=final_metadata,
ids=filtered_ids,
)
except chromadb.errors.InvalidDimensionException as e:
Logger(verbose=True).log(
"error",
"Embedding dimension mismatch. This usually happens when mixing different embedding models. Try resetting the collection using `crewai reset-memories -a`",
"red",
)
raise ValueError(
"Embedding dimension mismatch. Make sure you're using the same embedding model "
"across all operations with this collection."
"Try resetting the collection using `crewai reset-memories -a`"
) from e
except Exception as e:
Logger(verbose=True).log("error", f"Failed to upsert documents: {e}", "red")
raise
def _create_default_embedding_function(self):
from chromadb.utils.embedding_functions.openai_embedding_function import (
OpenAIEmbeddingFunction,

View File

@@ -44,6 +44,7 @@ LLM_CONTEXT_WINDOW_SIZES = {
"o1-preview": 128000,
"o1-mini": 128000,
# gemini
"gemini-2.0-flash": 1048576,
"gemini-1.5-pro": 2097152,
"gemini-1.5-flash": 1048576,
"gemini-1.5-flash-8b": 1048576,

View File

@@ -6,6 +6,7 @@ import os
import platform
import warnings
from contextlib import contextmanager
from importlib.metadata import version
from typing import TYPE_CHECKING, Any, Optional
@@ -16,10 +17,6 @@ def suppress_warnings():
yield
with suppress_warnings():
import pkg_resources
from opentelemetry import trace # noqa: E402
from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
OTLPSpanExporter, # noqa: E402
@@ -106,7 +103,7 @@ class Telemetry:
self._add_attribute(
span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
self._add_attribute(span, "python_version", platform.python_version())
self._add_attribute(span, "crew_key", crew.key)
@@ -308,7 +305,7 @@ class Telemetry:
self._add_attribute(
span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
self._add_attribute(span, "tool_name", tool_name)
self._add_attribute(span, "attempts", attempts)
@@ -328,7 +325,7 @@ class Telemetry:
self._add_attribute(
span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
self._add_attribute(span, "tool_name", tool_name)
self._add_attribute(span, "attempts", attempts)
@@ -348,7 +345,7 @@ class Telemetry:
self._add_attribute(
span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
if llm:
self._add_attribute(span, "llm", llm.model)
@@ -367,7 +364,7 @@ class Telemetry:
self._add_attribute(
span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
self._add_attribute(span, "crew_key", crew.key)
self._add_attribute(span, "crew_id", str(crew.id))
@@ -393,7 +390,7 @@ class Telemetry:
self._add_attribute(
span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
self._add_attribute(span, "crew_key", crew.key)
self._add_attribute(span, "crew_id", str(crew.id))
@@ -474,7 +471,7 @@ class Telemetry:
self._add_attribute(
span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
self._add_attribute(span, "crew_key", crew.key)
self._add_attribute(span, "crew_id", str(crew.id))
@@ -543,7 +540,7 @@ class Telemetry:
self._add_attribute(
crew._execution_span,
"crewai_version",
pkg_resources.get_distribution("crewai").version,
version("crewai"),
)
self._add_attribute(
crew._execution_span, "crew_output", final_string_output

View File

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

View File

@@ -12,7 +12,7 @@
"tools": "\nYou ONLY have access to the following tools, and should NEVER make up tools that are not listed here:\n\n{tools}\n\nUse the following format:\n\nThought: you should always think about what to do\nAction: the action to take, only one name of [{tool_names}], just the name, exactly as it's written.\nAction Input: the input to the action, just a simple python dictionary, enclosed in curly braces, using \" to wrap keys and values.\nObservation: the result of the action\n\nOnce all necessary information is gathered:\n\nThought: I now know the final answer\nFinal Answer: the final answer to the original input question\n",
"no_tools": "\nTo give my best complete final answer to the task use the exact following format:\n\nThought: I now can give a great answer\nFinal Answer: Your final answer must be the great and the most complete as possible, it must be outcome described.\n\nI MUST use these formats, my job depends on it!",
"format": "I MUST either use a tool (use one at time) OR give my best final answer not both at the same time. To Use the following format:\n\nThought: you should always think about what to do\nAction: the action to take, should be one of [{tool_names}]\nAction Input: the input to the action, dictionary enclosed in curly braces\nObservation: the result of the action\n... (this Thought/Action/Action Input/Result can repeat N times)\nThought: I now can give a great answer\nFinal Answer: Your final answer must be the great and the most complete as possible, it must be outcome described\n\n",
"final_answer_format": "If you don't need to use any more tools, you must give your best complete final answer, make sure it satisfy the expect criteria, use the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer: my best complete final answer to the task.\n\n",
"final_answer_format": "If you don't need to use any more tools, you must give your best complete final answer, make sure it satisfies the expected criteria, use the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer: my best complete final answer to the task.\n\n",
"format_without_tools": "\nSorry, I didn't use the right format. I MUST either use a tool (among the available ones), OR give my best final answer.\nI just remembered the expected format I must follow:\n\nQuestion: the input question you must answer\nThought: you should always think about what to do\nAction: the action to take, should be one of [{tool_names}]\nAction Input: the input to the action\nObservation: the result of the action\n... (this Thought/Action/Action Input/Result can repeat N times)\nThought: I now can give a great answer\nFinal Answer: Your final answer must be the great and the most complete as possible, it must be outcome described\n\n",
"task_with_context": "{task}\n\nThis is the context you're working with:\n{context}",
"expected_output": "\nThis is the expect criteria for your final answer: {expected_output}\nyou MUST return the actual complete content as the final answer, not a summary.",

View File

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

View File

@@ -1,4 +1,3 @@
import os
from typing import List
from pydantic import BaseModel, Field
@@ -6,27 +5,17 @@ from pydantic import BaseModel, Field
from crewai.utilities import Converter
from crewai.utilities.pydantic_schema_parser import PydanticSchemaParser
agentops = None
try:
from agentops import track_agent # type: ignore
except ImportError:
def mock_agent_ops_provider():
def track_agent(*args, **kwargs):
def track_agent(name):
def noop(f):
return f
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):
name: str = Field(description="The name of the entity.")

View File

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

View File

@@ -26237,7 +26237,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}], "model": "gpt-4o"}'
headers:
@@ -26590,7 +26590,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -26941,7 +26941,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -27292,7 +27292,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -27647,7 +27647,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -28005,7 +28005,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -28364,7 +28364,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -28718,7 +28718,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -29082,7 +29082,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -29441,7 +29441,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -29802,7 +29802,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -30170,7 +30170,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -30533,7 +30533,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -30907,7 +30907,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -31273,7 +31273,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -31644,7 +31644,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the
@@ -32015,7 +32015,7 @@ interactions:
answer."}, {"role": "user", "content": "I did it wrong. Invalid Format: I missed
the ''Action:'' after ''Thought:''. I will do right next, and don''t use a tool
I have already used.\n\nIf you don''t need to use any more tools, you must give
your best complete final answer, make sure it satisfy the expect criteria, use
your best complete final answer, make sure it satisfies the expected criteria, use
the EXACT format below:\n\nThought: I now can give a great answer\nFinal Answer:
my best complete final answer to the task.\n\n"}, {"role": "user", "content":
"I did it wrong. Tried to both perform Action and give a Final Answer at the

View File

@@ -247,7 +247,7 @@ interactions:
{"role": "user", "content": "I did it wrong. Invalid Format: I missed the ''Action:''
after ''Thought:''. I will do right next, and don''t use a tool I have already
used.\n\nIf you don''t need to use any more tools, you must give your best complete
final answer, make sure it satisfy the expect criteria, use the EXACT format
final answer, make sure it satisfies the expected criteria, use the EXACT format
below:\n\nThought: I now can give a great answer\nFinal Answer: my best complete
final answer to the task.\n\n"}], "model": "o1-preview"}'
headers:

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

View File

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

View File

@@ -6,14 +6,14 @@ from crewai.tools import BaseTool, tool
def test_creating_a_tool_using_annotation():
@tool("Name of my tool")
def my_tool(question: str) -> str:
"""Clear description for what this tool is useful for, you agent will need this information to use it."""
"""Clear description for what this tool is useful for, your agent will need this information to use it."""
return question
# Assert all the right attributes were defined
assert my_tool.name == "Name of my tool"
assert (
my_tool.description
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, you agent will need this information to use it."
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert my_tool.args_schema.schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
@@ -27,7 +27,7 @@ def test_creating_a_tool_using_annotation():
assert (
converted_tool.description
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, you agent will need this information to use it."
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert converted_tool.args_schema.schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
@@ -41,7 +41,7 @@ def test_creating_a_tool_using_annotation():
def test_creating_a_tool_using_baseclass():
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "Clear description for what this tool is useful for, you agent will need this information to use it."
description: str = "Clear description for what this tool is useful for, your agent will need this information to use it."
def _run(self, question: str) -> str:
return question
@@ -52,7 +52,7 @@ def test_creating_a_tool_using_baseclass():
assert (
my_tool.description
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, you agent will need this information to use it."
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert my_tool.args_schema.schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
@@ -64,7 +64,7 @@ def test_creating_a_tool_using_baseclass():
assert (
converted_tool.description
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, you agent will need this information to use it."
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert converted_tool.args_schema.schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
@@ -78,7 +78,7 @@ def test_creating_a_tool_using_baseclass():
def test_setting_cache_function():
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "Clear description for what this tool is useful for, you agent will need this information to use it."
description: str = "Clear description for what this tool is useful for, your agent will need this information to use it."
cache_function: Callable = lambda: False
def _run(self, question: str) -> str:
@@ -92,7 +92,7 @@ def test_setting_cache_function():
def test_default_cache_function_is_true():
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "Clear description for what this tool is useful for, you agent will need this information to use it."
description: str = "Clear description for what this tool is useful for, your agent will need this information to use it."
def _run(self, question: str) -> str:
return question

17
uv.lock generated
View File

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