mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-25 08:08:14 +00:00
Merge branch 'bugfix/restrict-python-version-compatibility' of https://github.com/joaomdmoura/crewAI into bugfix/restrict-python-version-compatibility
This commit is contained in:
@@ -122,7 +122,6 @@ crewai reset-memories --knowledge
|
|||||||
|
|
||||||
This is useful when you've updated your knowledge sources and want to ensure that the agents are using the most recent information.
|
This is useful when you've updated your knowledge sources and want to ensure that the agents are using the most recent information.
|
||||||
|
|
||||||
|
|
||||||
## Custom Knowledge Sources
|
## Custom Knowledge Sources
|
||||||
|
|
||||||
CrewAI allows you to create custom knowledge sources for any type of data by extending the `BaseKnowledgeSource` class. Let's create a practical example that fetches and processes space news articles.
|
CrewAI allows you to create custom knowledge sources for any type of data by extending the `BaseKnowledgeSource` class. Let's create a practical example that fetches and processes space news articles.
|
||||||
@@ -220,6 +219,7 @@ result = crew.kickoff(
|
|||||||
inputs={"user_question": "What are the latest developments in space exploration?"}
|
inputs={"user_question": "What are the latest developments in space exploration?"}
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
```output Output
|
```output Output
|
||||||
# Agent: Space News Analyst
|
# Agent: Space News Analyst
|
||||||
## Task: Answer this question about space news: What are the latest developments in space exploration?
|
## Task: Answer this question about space news: What are the latest developments in space exploration?
|
||||||
@@ -243,10 +243,12 @@ The latest developments in space exploration, based on recent space news article
|
|||||||
|
|
||||||
7. The Center for AEroSpace Autonomy Research (CAESAR) at Stanford University is focusing on spacecraft autonomy. The center held a kickoff event on May 22, 2024, to highlight the industry, academia, and government collaboration it seeks to foster. This could lead to significant advancements in autonomous spacecraft technology. [Source: SpaceNews](https://spacenews.com/stanford-center-focuses-on-spacecraft-autonomy/)
|
7. The Center for AEroSpace Autonomy Research (CAESAR) at Stanford University is focusing on spacecraft autonomy. The center held a kickoff event on May 22, 2024, to highlight the industry, academia, and government collaboration it seeks to foster. This could lead to significant advancements in autonomous spacecraft technology. [Source: SpaceNews](https://spacenews.com/stanford-center-focuses-on-spacecraft-autonomy/)
|
||||||
```
|
```
|
||||||
|
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
#### Key Components Explained
|
#### Key Components Explained
|
||||||
|
|
||||||
1. **Custom Knowledge Source (`SpaceNewsKnowledgeSource`)**:
|
1. **Custom Knowledge Source (`SpaceNewsKnowledgeSource`)**:
|
||||||
|
|
||||||
- Extends `BaseKnowledgeSource` for integration with CrewAI
|
- Extends `BaseKnowledgeSource` for integration with CrewAI
|
||||||
- Configurable API endpoint and article limit
|
- Configurable API endpoint and article limit
|
||||||
- Implements three key methods:
|
- Implements three key methods:
|
||||||
@@ -255,10 +257,12 @@ The latest developments in space exploration, based on recent space news article
|
|||||||
- `add()`: Processes and stores the content
|
- `add()`: Processes and stores the content
|
||||||
|
|
||||||
2. **Agent Configuration**:
|
2. **Agent Configuration**:
|
||||||
|
|
||||||
- Specialized role as a Space News Analyst
|
- Specialized role as a Space News Analyst
|
||||||
- Uses the knowledge source to access space news
|
- Uses the knowledge source to access space news
|
||||||
|
|
||||||
3. **Task Setup**:
|
3. **Task Setup**:
|
||||||
|
|
||||||
- Takes a user question as input through `{user_question}`
|
- Takes a user question as input through `{user_question}`
|
||||||
- Designed to provide detailed answers based on the knowledge source
|
- Designed to provide detailed answers based on the knowledge source
|
||||||
|
|
||||||
@@ -267,6 +271,7 @@ The latest developments in space exploration, based on recent space news article
|
|||||||
- Handles input/output through the kickoff method
|
- Handles input/output through the kickoff method
|
||||||
|
|
||||||
This example demonstrates how to:
|
This example demonstrates how to:
|
||||||
|
|
||||||
- Create a custom knowledge source that fetches real-time data
|
- Create a custom knowledge source that fetches real-time data
|
||||||
- Process and format external data for AI consumption
|
- Process and format external data for AI consumption
|
||||||
- Use the knowledge source to answer specific user questions
|
- Use the knowledge source to answer specific user questions
|
||||||
@@ -274,13 +279,15 @@ This example demonstrates how to:
|
|||||||
|
|
||||||
#### About the Spaceflight News API
|
#### About the Spaceflight News API
|
||||||
|
|
||||||
The example uses the [Spaceflight News API](https://api.spaceflightnewsapi.net/v4/documentation), which:
|
The example uses the [Spaceflight News API](https://api.spaceflightnewsapi.net/v4/docs/), which:
|
||||||
|
|
||||||
- Provides free access to space-related news articles
|
- Provides free access to space-related news articles
|
||||||
- Requires no authentication
|
- Requires no authentication
|
||||||
- Returns structured data about space news
|
- Returns structured data about space news
|
||||||
- Supports pagination and filtering
|
- Supports pagination and filtering
|
||||||
|
|
||||||
You can customize the API query by modifying the endpoint URL:
|
You can customize the API query by modifying the endpoint URL:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# Fetch more articles
|
# Fetch more articles
|
||||||
recent_news = SpaceNewsKnowledgeSource(
|
recent_news = SpaceNewsKnowledgeSource(
|
||||||
|
|||||||
@@ -172,6 +172,48 @@ def my_tool(question: str) -> str:
|
|||||||
return "Result from your custom tool"
|
return "Result from your custom tool"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Structured Tools
|
||||||
|
|
||||||
|
The `StructuredTool` class wraps functions as tools, providing flexibility and validation while reducing boilerplate. It supports custom schemas and dynamic logic for seamless integration of complex functionalities.
|
||||||
|
|
||||||
|
#### Example:
|
||||||
|
Using `StructuredTool.from_function`, you can wrap a function that interacts with an external API or system, providing a structured interface. This enables robust validation and consistent execution, making it easier to integrate complex functionalities into your applications as demonstrated in the following example:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from crewai.tools.structured_tool import CrewStructuredTool
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
# Define the schema for the tool's input using Pydantic
|
||||||
|
class APICallInput(BaseModel):
|
||||||
|
endpoint: str
|
||||||
|
parameters: dict
|
||||||
|
|
||||||
|
# Wrapper function to execute the API call
|
||||||
|
def tool_wrapper(*args, **kwargs):
|
||||||
|
# Here, you would typically call the API using the parameters
|
||||||
|
# For demonstration, we'll return a placeholder string
|
||||||
|
return f"Call the API at {kwargs['endpoint']} with parameters {kwargs['parameters']}"
|
||||||
|
|
||||||
|
# Create and return the structured tool
|
||||||
|
def create_structured_tool():
|
||||||
|
return CrewStructuredTool.from_function(
|
||||||
|
name='Wrapper API',
|
||||||
|
description="A tool to wrap API calls with structured input.",
|
||||||
|
args_schema=APICallInput,
|
||||||
|
func=tool_wrapper,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Example usage
|
||||||
|
structured_tool = create_structured_tool()
|
||||||
|
|
||||||
|
# Execute the tool with structured input
|
||||||
|
result = structured_tool._run(**{
|
||||||
|
"endpoint": "https://example.com/api",
|
||||||
|
"parameters": {"key1": "value1", "key2": "value2"}
|
||||||
|
})
|
||||||
|
print(result) # Output: Call the API at https://example.com/api with parameters {'key1': 'value1', 'key2': 'value2'}
|
||||||
|
```
|
||||||
|
|
||||||
### Custom Caching Mechanism
|
### Custom Caching Mechanism
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
|
|||||||
@@ -143,6 +143,9 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
|||||||
tool_result = self._execute_tool_and_check_finality(
|
tool_result = self._execute_tool_and_check_finality(
|
||||||
formatted_answer
|
formatted_answer
|
||||||
)
|
)
|
||||||
|
if self.step_callback:
|
||||||
|
self.step_callback(tool_result)
|
||||||
|
|
||||||
formatted_answer.text += f"\nObservation: {tool_result.result}"
|
formatted_answer.text += f"\nObservation: {tool_result.result}"
|
||||||
formatted_answer.result = tool_result.result
|
formatted_answer.result = tool_result.result
|
||||||
if tool_result.result_as_answer:
|
if tool_result.result_as_answer:
|
||||||
@@ -299,7 +302,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
|
|||||||
self._i18n.slice("summarizer_system_message"), role="system"
|
self._i18n.slice("summarizer_system_message"), role="system"
|
||||||
),
|
),
|
||||||
self._format_msg(
|
self._format_msg(
|
||||||
self._i18n.slice("sumamrize_instruction").format(group=group),
|
self._i18n.slice("summarize_instruction").format(group=group),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
callbacks=self.callbacks,
|
callbacks=self.callbacks,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import hashlib
|
|||||||
import io
|
import io
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
from typing import Any, Dict, List, Optional, Union, cast
|
from typing import Any, Dict, List, Optional, Union, cast
|
||||||
|
|
||||||
import chromadb
|
import chromadb
|
||||||
@@ -15,6 +16,7 @@ from crewai.knowledge.storage.base_knowledge_storage import BaseKnowledgeStorage
|
|||||||
from crewai.utilities import EmbeddingConfigurator
|
from crewai.utilities import EmbeddingConfigurator
|
||||||
from crewai.utilities.logger import Logger
|
from crewai.utilities.logger import Logger
|
||||||
from crewai.utilities.paths import db_storage_path
|
from crewai.utilities.paths import db_storage_path
|
||||||
|
from crewai.utilities.constants import KNOWLEDGE_DIRECTORY
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@@ -105,15 +107,17 @@ class KnowledgeStorage(BaseKnowledgeStorage):
|
|||||||
raise Exception("Failed to create or get collection")
|
raise Exception("Failed to create or get collection")
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
if self.app:
|
base_path = os.path.join(db_storage_path(), KNOWLEDGE_DIRECTORY)
|
||||||
self.app.reset()
|
if not self.app:
|
||||||
else:
|
|
||||||
base_path = os.path.join(db_storage_path(), "knowledge")
|
|
||||||
self.app = chromadb.PersistentClient(
|
self.app = chromadb.PersistentClient(
|
||||||
path=base_path,
|
path=base_path,
|
||||||
settings=Settings(allow_reset=True),
|
settings=Settings(allow_reset=True),
|
||||||
)
|
)
|
||||||
self.app.reset()
|
|
||||||
|
self.app.reset()
|
||||||
|
shutil.rmtree(base_path)
|
||||||
|
self.app = None
|
||||||
|
self.collection = None
|
||||||
|
|
||||||
def save(
|
def save(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -150,9 +150,11 @@ class RAGStorage(BaseRAGStorage):
|
|||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> None:
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(f"{db_storage_path()}/{self.type}")
|
|
||||||
if self.app:
|
if self.app:
|
||||||
self.app.reset()
|
self.app.reset()
|
||||||
|
shutil.rmtree(f"{db_storage_path()}/{self.type}")
|
||||||
|
self.app = None
|
||||||
|
self.collection = None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "attempt to write a readonly database" in str(e):
|
if "attempt to write a readonly database" in str(e):
|
||||||
# Ignore this specific error
|
# Ignore this specific error
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class UserMemory(Memory):
|
|||||||
limit: int = 3,
|
limit: int = 3,
|
||||||
score_threshold: float = 0.35,
|
score_threshold: float = 0.35,
|
||||||
):
|
):
|
||||||
results = super().search(
|
results = self.storage.search(
|
||||||
query=query,
|
query=query,
|
||||||
limit=limit,
|
limit=limit,
|
||||||
score_threshold=score_threshold,
|
score_threshold=score_threshold,
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ def cache_handler(func):
|
|||||||
|
|
||||||
|
|
||||||
def crew(func) -> Callable[..., Crew]:
|
def crew(func) -> Callable[..., Crew]:
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
def wrapper(self, *args, **kwargs) -> Crew:
|
def wrapper(self, *args, **kwargs) -> Crew:
|
||||||
instantiated_tasks = []
|
instantiated_tasks = []
|
||||||
instantiated_agents = []
|
instantiated_agents = []
|
||||||
|
|||||||
@@ -213,4 +213,8 @@ def CrewBase(cls: T) -> T:
|
|||||||
callback_functions[callback]() for callback in callbacks
|
callback_functions[callback]() for callback in callbacks
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Include base class (qual)name in the wrapper class (qual)name.
|
||||||
|
WrappedClass.__name__ = CrewBase.__name__ + "(" + cls.__name__ + ")"
|
||||||
|
WrappedClass.__qualname__ = CrewBase.__qualname__ + "(" + cls.__name__ + ")"
|
||||||
|
|
||||||
return cast(T, WrappedClass)
|
return cast(T, WrappedClass)
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
|
from functools import wraps
|
||||||
|
|
||||||
def memoize(func):
|
def memoize(func):
|
||||||
cache = {}
|
cache = {}
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
def memoized_func(*args, **kwargs):
|
def memoized_func(*args, **kwargs):
|
||||||
key = (args, tuple(kwargs.items()))
|
key = (args, tuple(kwargs.items()))
|
||||||
if key not in cache:
|
if key not in cache:
|
||||||
cache[key] = func(*args, **kwargs)
|
cache[key] = func(*args, **kwargs)
|
||||||
return cache[key]
|
return cache[key]
|
||||||
|
|
||||||
memoized_func.__dict__.update(func.__dict__)
|
|
||||||
return memoized_func
|
return memoized_func
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"human_feedback": "You got human feedback on your work, re-evaluate it and give a new Final Answer when ready.\n {human_feedback}",
|
"human_feedback": "You got human feedback on your work, re-evaluate it and give a new Final Answer when ready.\n {human_feedback}",
|
||||||
"getting_input": "This is the agent's final answer: {final_answer}\n\n",
|
"getting_input": "This is the agent's final answer: {final_answer}\n\n",
|
||||||
"summarizer_system_message": "You are a helpful assistant that summarizes text.",
|
"summarizer_system_message": "You are a helpful assistant that summarizes text.",
|
||||||
"sumamrize_instruction": "Summarize the following text, make sure to include all the important information: {group}",
|
"summarize_instruction": "Summarize the following text, make sure to include all the important information: {group}",
|
||||||
"summary": "This is a summary of our conversation so far:\n{merged_summary}",
|
"summary": "This is a summary of our conversation so far:\n{merged_summary}",
|
||||||
"manager_request": "Your best answer to your coworker asking you this, accounting for the context shared.",
|
"manager_request": "Your best answer to your coworker asking you this, accounting for the context shared.",
|
||||||
"formatted_task_instructions": "Ensure your final answer contains only the content in the following format: {output_format}\n\nEnsure the final output does not include any code block markers like ```json or ```python.",
|
"formatted_task_instructions": "Ensure your final answer contains only the content in the following format: {output_format}\n\nEnsure the final output does not include any code block markers like ```json or ```python.",
|
||||||
|
|||||||
Reference in New Issue
Block a user