mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-10 08:38:30 +00:00
fix: Respect use_system_prompt in Converter regeneration
Fixes #2571 Co-authored-by: Devin AI <devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
@@ -4,4 +4,6 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: ["--fix"]
|
args: ["--fix"]
|
||||||
|
exclude: ^src/crewai/cli/templates/
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
|
exclude: ^src/crewai/cli/templates/
|
||||||
|
|||||||
@@ -367,8 +367,12 @@ class Agent(BaseAgent):
|
|||||||
"info", "Coding tools not available. Install crewai_tools. "
|
"info", "Coding tools not available. Install crewai_tools. "
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_output_converter(self, llm, text, model, instructions):
|
def get_output_converter(
|
||||||
return Converter(llm=llm, text=text, model=model, instructions=instructions)
|
self, agent, llm, text, model, instructions
|
||||||
|
): # Add agent parameter
|
||||||
|
return Converter(
|
||||||
|
agent=agent, llm=llm, text=text, model=model, instructions=instructions
|
||||||
|
)
|
||||||
|
|
||||||
def _training_handler(self, task_prompt: str) -> str:
|
def _training_handler(self, task_prompt: str) -> str:
|
||||||
"""Handle training data for the agent task prompt to improve output on Training."""
|
"""Handle training data for the agent task prompt to improve output on Training."""
|
||||||
|
|||||||
@@ -153,8 +153,12 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
|||||||
login_response_json = login_response.json()
|
login_response_json = login_response.json()
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
settings.tool_repository_username = login_response_json["credential"]["username"]
|
settings.tool_repository_username = login_response_json["credential"][
|
||||||
settings.tool_repository_password = login_response_json["credential"]["password"]
|
"username"
|
||||||
|
]
|
||||||
|
settings.tool_repository_password = login_response_json["credential"][
|
||||||
|
"password"
|
||||||
|
]
|
||||||
settings.dump()
|
settings.dump()
|
||||||
|
|
||||||
console.print(
|
console.print(
|
||||||
@@ -179,7 +183,7 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
|||||||
capture_output=False,
|
capture_output=False,
|
||||||
env=self._build_env_with_credentials(repository_handle),
|
env=self._build_env_with_credentials(repository_handle),
|
||||||
text=True,
|
text=True,
|
||||||
check=True
|
check=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
if add_package_result.stderr:
|
if add_package_result.stderr:
|
||||||
@@ -204,7 +208,11 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
|||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env[f"UV_INDEX_{repository_handle}_USERNAME"] = str(settings.tool_repository_username or "")
|
env[f"UV_INDEX_{repository_handle}_USERNAME"] = str(
|
||||||
env[f"UV_INDEX_{repository_handle}_PASSWORD"] = str(settings.tool_repository_password or "")
|
settings.tool_repository_username or ""
|
||||||
|
)
|
||||||
|
env[f"UV_INDEX_{repository_handle}_PASSWORD"] = str(
|
||||||
|
settings.tool_repository_password or ""
|
||||||
|
)
|
||||||
|
|
||||||
return env
|
return env
|
||||||
|
|||||||
@@ -297,9 +297,7 @@ class Crew(BaseModel):
|
|||||||
)
|
)
|
||||||
self._external_memory = (
|
self._external_memory = (
|
||||||
# External memory doesn’t support a default value since it was designed to be managed entirely externally
|
# External memory doesn’t support a default value since it was designed to be managed entirely externally
|
||||||
self.external_memory.set_crew(self)
|
self.external_memory.set_crew(self) if self.external_memory else None
|
||||||
if self.external_memory
|
|
||||||
else None
|
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
self.memory_config
|
self.memory_config
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ class FlowPlot:
|
|||||||
ValueError
|
ValueError
|
||||||
If flow object is invalid or missing required attributes.
|
If flow object is invalid or missing required attributes.
|
||||||
"""
|
"""
|
||||||
if not hasattr(flow, '_methods'):
|
if not hasattr(flow, "_methods"):
|
||||||
raise ValueError("Invalid flow object: missing '_methods' attribute")
|
raise ValueError("Invalid flow object: missing '_methods' attribute")
|
||||||
if not hasattr(flow, '_listeners'):
|
if not hasattr(flow, "_listeners"):
|
||||||
raise ValueError("Invalid flow object: missing '_listeners' attribute")
|
raise ValueError("Invalid flow object: missing '_listeners' attribute")
|
||||||
if not hasattr(flow, '_start_methods'):
|
if not hasattr(flow, "_start_methods"):
|
||||||
raise ValueError("Invalid flow object: missing '_start_methods' attribute")
|
raise ValueError("Invalid flow object: missing '_start_methods' attribute")
|
||||||
|
|
||||||
self.flow = flow
|
self.flow = flow
|
||||||
self.colors = COLORS
|
self.colors = COLORS
|
||||||
self.node_styles = NODE_STYLES
|
self.node_styles = NODE_STYLES
|
||||||
@@ -65,7 +65,7 @@ class FlowPlot:
|
|||||||
"""
|
"""
|
||||||
if not filename or not isinstance(filename, str):
|
if not filename or not isinstance(filename, str):
|
||||||
raise ValueError("Filename must be a non-empty string")
|
raise ValueError("Filename must be a non-empty string")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Initialize network
|
# Initialize network
|
||||||
net = Network(
|
net = Network(
|
||||||
@@ -121,7 +121,9 @@ class FlowPlot:
|
|||||||
network_html = net.generate_html()
|
network_html = net.generate_html()
|
||||||
final_html_content = self._generate_final_html(network_html)
|
final_html_content = self._generate_final_html(network_html)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(f"Failed to generate network visualization: {str(e)}")
|
raise RuntimeError(
|
||||||
|
f"Failed to generate network visualization: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
# Save the final HTML content to the file
|
# Save the final HTML content to the file
|
||||||
try:
|
try:
|
||||||
@@ -129,7 +131,9 @@ class FlowPlot:
|
|||||||
f.write(final_html_content)
|
f.write(final_html_content)
|
||||||
print(f"Plot saved as {filename}.html")
|
print(f"Plot saved as {filename}.html")
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise IOError(f"Failed to save flow visualization to {filename}.html: {str(e)}")
|
raise IOError(
|
||||||
|
f"Failed to save flow visualization to {filename}.html: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
except (ValueError, RuntimeError, IOError) as e:
|
except (ValueError, RuntimeError, IOError) as e:
|
||||||
raise e
|
raise e
|
||||||
@@ -165,7 +169,9 @@ class FlowPlot:
|
|||||||
try:
|
try:
|
||||||
# Extract just the body content from the generated HTML
|
# Extract just the body content from the generated HTML
|
||||||
current_dir = os.path.dirname(__file__)
|
current_dir = os.path.dirname(__file__)
|
||||||
template_path = safe_path_join("assets", "crewai_flow_visual_template.html", root=current_dir)
|
template_path = safe_path_join(
|
||||||
|
"assets", "crewai_flow_visual_template.html", root=current_dir
|
||||||
|
)
|
||||||
logo_path = safe_path_join("assets", "crewai_logo.svg", root=current_dir)
|
logo_path = safe_path_join("assets", "crewai_logo.svg", root=current_dir)
|
||||||
|
|
||||||
if not os.path.exists(template_path):
|
if not os.path.exists(template_path):
|
||||||
@@ -197,6 +203,7 @@ class FlowPlot:
|
|||||||
lib_folder = safe_path_join("lib", root=os.getcwd())
|
lib_folder = safe_path_join("lib", root=os.getcwd())
|
||||||
if os.path.exists(lib_folder) and os.path.isdir(lib_folder):
|
if os.path.exists(lib_folder) and os.path.isdir(lib_folder):
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
shutil.rmtree(lib_folder)
|
shutil.rmtree(lib_folder)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(f"Error validating lib folder path: {e}")
|
print(f"Error validating lib folder path: {e}")
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
def get_legend_items(colors):
|
def get_legend_items(colors):
|
||||||
return [
|
return [
|
||||||
{"label": "Start Method", "color": colors["start"]},
|
{"label": "Start Method", "color": colors["start"]},
|
||||||
|
|||||||
@@ -43,18 +43,18 @@ def safe_path_join(*parts: str, root: Union[str, Path, None] = None) -> str:
|
|||||||
|
|
||||||
# Establish root directory
|
# Establish root directory
|
||||||
root_path = Path(root).resolve() if root else Path.cwd()
|
root_path = Path(root).resolve() if root else Path.cwd()
|
||||||
|
|
||||||
# Join and resolve the full path
|
# Join and resolve the full path
|
||||||
full_path = Path(root_path, *clean_parts).resolve()
|
full_path = Path(root_path, *clean_parts).resolve()
|
||||||
|
|
||||||
# Check if the resolved path is within root
|
# Check if the resolved path is within root
|
||||||
if not str(full_path).startswith(str(root_path)):
|
if not str(full_path).startswith(str(root_path)):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Invalid path: Potential directory traversal. Path must be within {root_path}"
|
f"Invalid path: Potential directory traversal. Path must be within {root_path}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return str(full_path)
|
return str(full_path)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(e, ValueError):
|
if isinstance(e, ValueError):
|
||||||
raise
|
raise
|
||||||
@@ -84,17 +84,17 @@ def validate_path_exists(path: Union[str, Path], file_type: str = "file") -> str
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
path_obj = Path(path).resolve()
|
path_obj = Path(path).resolve()
|
||||||
|
|
||||||
if not path_obj.exists():
|
if not path_obj.exists():
|
||||||
raise ValueError(f"Path does not exist: {path}")
|
raise ValueError(f"Path does not exist: {path}")
|
||||||
|
|
||||||
if file_type == "file" and not path_obj.is_file():
|
if file_type == "file" and not path_obj.is_file():
|
||||||
raise ValueError(f"Path is not a file: {path}")
|
raise ValueError(f"Path is not a file: {path}")
|
||||||
elif file_type == "directory" and not path_obj.is_dir():
|
elif file_type == "directory" and not path_obj.is_dir():
|
||||||
raise ValueError(f"Path is not a directory: {path}")
|
raise ValueError(f"Path is not a directory: {path}")
|
||||||
|
|
||||||
return str(path_obj)
|
return str(path_obj)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(e, ValueError):
|
if isinstance(e, ValueError):
|
||||||
raise
|
raise
|
||||||
@@ -126,9 +126,9 @@ def list_files(directory: Union[str, Path], pattern: str = "*") -> List[str]:
|
|||||||
dir_path = Path(directory).resolve()
|
dir_path = Path(directory).resolve()
|
||||||
if not dir_path.is_dir():
|
if not dir_path.is_dir():
|
||||||
raise ValueError(f"Not a directory: {directory}")
|
raise ValueError(f"Not a directory: {directory}")
|
||||||
|
|
||||||
return [str(p) for p in dir_path.glob(pattern) if p.is_file()]
|
return [str(p) for p in dir_path.glob(pattern) if p.is_file()]
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(e, ValueError):
|
if isinstance(e, ValueError):
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -8,45 +8,45 @@ from pydantic import BaseModel
|
|||||||
|
|
||||||
class FlowPersistence(abc.ABC):
|
class FlowPersistence(abc.ABC):
|
||||||
"""Abstract base class for flow state persistence.
|
"""Abstract base class for flow state persistence.
|
||||||
|
|
||||||
This class defines the interface that all persistence implementations must follow.
|
This class defines the interface that all persistence implementations must follow.
|
||||||
It supports both structured (Pydantic BaseModel) and unstructured (dict) states.
|
It supports both structured (Pydantic BaseModel) and unstructured (dict) states.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def init_db(self) -> None:
|
def init_db(self) -> None:
|
||||||
"""Initialize the persistence backend.
|
"""Initialize the persistence backend.
|
||||||
|
|
||||||
This method should handle any necessary setup, such as:
|
This method should handle any necessary setup, such as:
|
||||||
- Creating tables
|
- Creating tables
|
||||||
- Establishing connections
|
- Establishing connections
|
||||||
- Setting up indexes
|
- Setting up indexes
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def save_state(
|
def save_state(
|
||||||
self,
|
self,
|
||||||
flow_uuid: str,
|
flow_uuid: str,
|
||||||
method_name: str,
|
method_name: str,
|
||||||
state_data: Union[Dict[str, Any], BaseModel]
|
state_data: Union[Dict[str, Any], BaseModel],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Persist the flow state after method completion.
|
"""Persist the flow state after method completion.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
flow_uuid: Unique identifier for the flow instance
|
flow_uuid: Unique identifier for the flow instance
|
||||||
method_name: Name of the method that just completed
|
method_name: Name of the method that just completed
|
||||||
state_data: Current state data (either dict or Pydantic model)
|
state_data: Current state data (either dict or Pydantic model)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def load_state(self, flow_uuid: str) -> Optional[Dict[str, Any]]:
|
def load_state(self, flow_uuid: str) -> Optional[Dict[str, Any]]:
|
||||||
"""Load the most recent state for a given flow UUID.
|
"""Load the most recent state for a given flow UUID.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
flow_uuid: Unique identifier for the flow instance
|
flow_uuid: Unique identifier for the flow instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The most recent state as a dictionary, or None if no state exists
|
The most recent state as a dictionary, or None if no state exists
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ LOG_MESSAGES = {
|
|||||||
"save_state": "Saving flow state to memory for ID: {}",
|
"save_state": "Saving flow state to memory for ID: {}",
|
||||||
"save_error": "Failed to persist state for method {}: {}",
|
"save_error": "Failed to persist state for method {}: {}",
|
||||||
"state_missing": "Flow instance has no state",
|
"state_missing": "Flow instance has no state",
|
||||||
"id_missing": "Flow state must have an 'id' field for persistence"
|
"id_missing": "Flow state must have an 'id' field for persistence",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -58,7 +58,13 @@ class PersistenceDecorator:
|
|||||||
_printer = Printer() # Class-level printer instance
|
_printer = Printer() # Class-level printer instance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def persist_state(cls, flow_instance: Any, method_name: str, persistence_instance: FlowPersistence, verbose: bool = False) -> None:
|
def persist_state(
|
||||||
|
cls,
|
||||||
|
flow_instance: Any,
|
||||||
|
method_name: str,
|
||||||
|
persistence_instance: FlowPersistence,
|
||||||
|
verbose: bool = False,
|
||||||
|
) -> None:
|
||||||
"""Persist flow state with proper error handling and logging.
|
"""Persist flow state with proper error handling and logging.
|
||||||
|
|
||||||
This method handles the persistence of flow state data, including proper
|
This method handles the persistence of flow state data, including proper
|
||||||
@@ -76,22 +82,24 @@ class PersistenceDecorator:
|
|||||||
AttributeError: If flow instance lacks required state attributes
|
AttributeError: If flow instance lacks required state attributes
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
state = getattr(flow_instance, 'state', None)
|
state = getattr(flow_instance, "state", None)
|
||||||
if state is None:
|
if state is None:
|
||||||
raise ValueError("Flow instance has no state")
|
raise ValueError("Flow instance has no state")
|
||||||
|
|
||||||
flow_uuid: Optional[str] = None
|
flow_uuid: Optional[str] = None
|
||||||
if isinstance(state, dict):
|
if isinstance(state, dict):
|
||||||
flow_uuid = state.get('id')
|
flow_uuid = state.get("id")
|
||||||
elif isinstance(state, BaseModel):
|
elif isinstance(state, BaseModel):
|
||||||
flow_uuid = getattr(state, 'id', None)
|
flow_uuid = getattr(state, "id", None)
|
||||||
|
|
||||||
if not flow_uuid:
|
if not flow_uuid:
|
||||||
raise ValueError("Flow state must have an 'id' field for persistence")
|
raise ValueError("Flow state must have an 'id' field for persistence")
|
||||||
|
|
||||||
# Log state saving only if verbose is True
|
# Log state saving only if verbose is True
|
||||||
if verbose:
|
if verbose:
|
||||||
cls._printer.print(LOG_MESSAGES["save_state"].format(flow_uuid), color="cyan")
|
cls._printer.print(
|
||||||
|
LOG_MESSAGES["save_state"].format(flow_uuid), color="cyan"
|
||||||
|
)
|
||||||
logger.info(LOG_MESSAGES["save_state"].format(flow_uuid))
|
logger.info(LOG_MESSAGES["save_state"].format(flow_uuid))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -144,7 +152,10 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
|||||||
def begin(self):
|
def begin(self):
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
def decorator(target: Union[Type, Callable[..., T]]) -> Union[Type, Callable[..., T]]:
|
|
||||||
|
def decorator(
|
||||||
|
target: Union[Type, Callable[..., T]],
|
||||||
|
) -> Union[Type, Callable[..., T]]:
|
||||||
"""Decorator that handles both class and method decoration."""
|
"""Decorator that handles both class and method decoration."""
|
||||||
actual_persistence = persistence or SQLiteFlowPersistence()
|
actual_persistence = persistence or SQLiteFlowPersistence()
|
||||||
|
|
||||||
@@ -154,8 +165,8 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
|||||||
|
|
||||||
@functools.wraps(original_init)
|
@functools.wraps(original_init)
|
||||||
def new_init(self: Any, *args: Any, **kwargs: Any) -> None:
|
def new_init(self: Any, *args: Any, **kwargs: Any) -> None:
|
||||||
if 'persistence' not in kwargs:
|
if "persistence" not in kwargs:
|
||||||
kwargs['persistence'] = actual_persistence
|
kwargs["persistence"] = actual_persistence
|
||||||
original_init(self, *args, **kwargs)
|
original_init(self, *args, **kwargs)
|
||||||
|
|
||||||
setattr(target, "__init__", new_init)
|
setattr(target, "__init__", new_init)
|
||||||
@@ -165,11 +176,11 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
|||||||
|
|
||||||
for name, method in target.__dict__.items():
|
for name, method in target.__dict__.items():
|
||||||
if callable(method) and (
|
if callable(method) and (
|
||||||
hasattr(method, "__is_start_method__") or
|
hasattr(method, "__is_start_method__")
|
||||||
hasattr(method, "__trigger_methods__") or
|
or hasattr(method, "__trigger_methods__")
|
||||||
hasattr(method, "__condition_type__") or
|
or hasattr(method, "__condition_type__")
|
||||||
hasattr(method, "__is_flow_method__") or
|
or hasattr(method, "__is_flow_method__")
|
||||||
hasattr(method, "__is_router__")
|
or hasattr(method, "__is_router__")
|
||||||
):
|
):
|
||||||
original_methods[name] = method
|
original_methods[name] = method
|
||||||
|
|
||||||
@@ -177,18 +188,30 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
|||||||
for name, method in original_methods.items():
|
for name, method in original_methods.items():
|
||||||
if asyncio.iscoroutinefunction(method):
|
if asyncio.iscoroutinefunction(method):
|
||||||
# Create a closure to capture the current name and method
|
# Create a closure to capture the current name and method
|
||||||
def create_async_wrapper(method_name: str, original_method: Callable):
|
def create_async_wrapper(
|
||||||
|
method_name: str, original_method: Callable
|
||||||
|
):
|
||||||
@functools.wraps(original_method)
|
@functools.wraps(original_method)
|
||||||
async def method_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
async def method_wrapper(
|
||||||
|
self: Any, *args: Any, **kwargs: Any
|
||||||
|
) -> Any:
|
||||||
result = await original_method(self, *args, **kwargs)
|
result = await original_method(self, *args, **kwargs)
|
||||||
PersistenceDecorator.persist_state(self, method_name, actual_persistence, verbose)
|
PersistenceDecorator.persist_state(
|
||||||
|
self, method_name, actual_persistence, verbose
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return method_wrapper
|
return method_wrapper
|
||||||
|
|
||||||
wrapped = create_async_wrapper(name, method)
|
wrapped = create_async_wrapper(name, method)
|
||||||
|
|
||||||
# Preserve all original decorators and attributes
|
# Preserve all original decorators and attributes
|
||||||
for attr in ["__is_start_method__", "__trigger_methods__", "__condition_type__", "__is_router__"]:
|
for attr in [
|
||||||
|
"__is_start_method__",
|
||||||
|
"__trigger_methods__",
|
||||||
|
"__condition_type__",
|
||||||
|
"__is_router__",
|
||||||
|
]:
|
||||||
if hasattr(method, attr):
|
if hasattr(method, attr):
|
||||||
setattr(wrapped, attr, getattr(method, attr))
|
setattr(wrapped, attr, getattr(method, attr))
|
||||||
setattr(wrapped, "__is_flow_method__", True)
|
setattr(wrapped, "__is_flow_method__", True)
|
||||||
@@ -197,18 +220,28 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
|||||||
setattr(target, name, wrapped)
|
setattr(target, name, wrapped)
|
||||||
else:
|
else:
|
||||||
# Create a closure to capture the current name and method
|
# Create a closure to capture the current name and method
|
||||||
def create_sync_wrapper(method_name: str, original_method: Callable):
|
def create_sync_wrapper(
|
||||||
|
method_name: str, original_method: Callable
|
||||||
|
):
|
||||||
@functools.wraps(original_method)
|
@functools.wraps(original_method)
|
||||||
def method_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
def method_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
||||||
result = original_method(self, *args, **kwargs)
|
result = original_method(self, *args, **kwargs)
|
||||||
PersistenceDecorator.persist_state(self, method_name, actual_persistence, verbose)
|
PersistenceDecorator.persist_state(
|
||||||
|
self, method_name, actual_persistence, verbose
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return method_wrapper
|
return method_wrapper
|
||||||
|
|
||||||
wrapped = create_sync_wrapper(name, method)
|
wrapped = create_sync_wrapper(name, method)
|
||||||
|
|
||||||
# Preserve all original decorators and attributes
|
# Preserve all original decorators and attributes
|
||||||
for attr in ["__is_start_method__", "__trigger_methods__", "__condition_type__", "__is_router__"]:
|
for attr in [
|
||||||
|
"__is_start_method__",
|
||||||
|
"__trigger_methods__",
|
||||||
|
"__condition_type__",
|
||||||
|
"__is_router__",
|
||||||
|
]:
|
||||||
if hasattr(method, attr):
|
if hasattr(method, attr):
|
||||||
setattr(wrapped, attr, getattr(method, attr))
|
setattr(wrapped, attr, getattr(method, attr))
|
||||||
setattr(wrapped, "__is_flow_method__", True)
|
setattr(wrapped, "__is_flow_method__", True)
|
||||||
@@ -223,29 +256,49 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
|||||||
setattr(method, "__is_flow_method__", True)
|
setattr(method, "__is_flow_method__", True)
|
||||||
|
|
||||||
if asyncio.iscoroutinefunction(method):
|
if asyncio.iscoroutinefunction(method):
|
||||||
|
|
||||||
@functools.wraps(method)
|
@functools.wraps(method)
|
||||||
async def method_async_wrapper(flow_instance: Any, *args: Any, **kwargs: Any) -> T:
|
async def method_async_wrapper(
|
||||||
|
flow_instance: Any, *args: Any, **kwargs: Any
|
||||||
|
) -> T:
|
||||||
method_coro = method(flow_instance, *args, **kwargs)
|
method_coro = method(flow_instance, *args, **kwargs)
|
||||||
if asyncio.iscoroutine(method_coro):
|
if asyncio.iscoroutine(method_coro):
|
||||||
result = await method_coro
|
result = await method_coro
|
||||||
else:
|
else:
|
||||||
result = method_coro
|
result = method_coro
|
||||||
PersistenceDecorator.persist_state(flow_instance, method.__name__, actual_persistence, verbose)
|
PersistenceDecorator.persist_state(
|
||||||
|
flow_instance, method.__name__, actual_persistence, verbose
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
for attr in ["__is_start_method__", "__trigger_methods__", "__condition_type__", "__is_router__"]:
|
for attr in [
|
||||||
|
"__is_start_method__",
|
||||||
|
"__trigger_methods__",
|
||||||
|
"__condition_type__",
|
||||||
|
"__is_router__",
|
||||||
|
]:
|
||||||
if hasattr(method, attr):
|
if hasattr(method, attr):
|
||||||
setattr(method_async_wrapper, attr, getattr(method, attr))
|
setattr(method_async_wrapper, attr, getattr(method, attr))
|
||||||
setattr(method_async_wrapper, "__is_flow_method__", True)
|
setattr(method_async_wrapper, "__is_flow_method__", True)
|
||||||
return cast(Callable[..., T], method_async_wrapper)
|
return cast(Callable[..., T], method_async_wrapper)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@functools.wraps(method)
|
@functools.wraps(method)
|
||||||
def method_sync_wrapper(flow_instance: Any, *args: Any, **kwargs: Any) -> T:
|
def method_sync_wrapper(
|
||||||
|
flow_instance: Any, *args: Any, **kwargs: Any
|
||||||
|
) -> T:
|
||||||
result = method(flow_instance, *args, **kwargs)
|
result = method(flow_instance, *args, **kwargs)
|
||||||
PersistenceDecorator.persist_state(flow_instance, method.__name__, actual_persistence, verbose)
|
PersistenceDecorator.persist_state(
|
||||||
|
flow_instance, method.__name__, actual_persistence, verbose
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
for attr in ["__is_start_method__", "__trigger_methods__", "__condition_type__", "__is_router__"]:
|
for attr in [
|
||||||
|
"__is_start_method__",
|
||||||
|
"__trigger_methods__",
|
||||||
|
"__condition_type__",
|
||||||
|
"__is_router__",
|
||||||
|
]:
|
||||||
if hasattr(method, attr):
|
if hasattr(method, attr):
|
||||||
setattr(method_sync_wrapper, attr, getattr(method, attr))
|
setattr(method_sync_wrapper, attr, getattr(method, attr))
|
||||||
setattr(method_sync_wrapper, "__is_flow_method__", True)
|
setattr(method_sync_wrapper, "__is_flow_method__", True)
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ def method_calls_crew(method: Any) -> bool:
|
|||||||
|
|
||||||
class CrewCallVisitor(ast.NodeVisitor):
|
class CrewCallVisitor(ast.NodeVisitor):
|
||||||
"""AST visitor to detect .crew() method calls."""
|
"""AST visitor to detect .crew() method calls."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.found = False
|
self.found = False
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ def add_nodes_to_network(
|
|||||||
net: Any,
|
net: Any,
|
||||||
flow: Any,
|
flow: Any,
|
||||||
node_positions: Dict[str, Tuple[float, float]],
|
node_positions: Dict[str, Tuple[float, float]],
|
||||||
node_styles: Dict[str, Dict[str, Any]]
|
node_styles: Dict[str, Dict[str, Any]],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Add nodes to the network visualization with appropriate styling.
|
Add nodes to the network visualization with appropriate styling.
|
||||||
@@ -98,6 +99,7 @@ def add_nodes_to_network(
|
|||||||
- Crew methods
|
- Crew methods
|
||||||
- Regular methods
|
- Regular methods
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def human_friendly_label(method_name):
|
def human_friendly_label(method_name):
|
||||||
return method_name.replace("_", " ").title()
|
return method_name.replace("_", " ").title()
|
||||||
|
|
||||||
@@ -140,7 +142,7 @@ def compute_positions(
|
|||||||
flow: Any,
|
flow: Any,
|
||||||
node_levels: Dict[str, int],
|
node_levels: Dict[str, int],
|
||||||
y_spacing: float = 150,
|
y_spacing: float = 150,
|
||||||
x_spacing: float = 150
|
x_spacing: float = 150,
|
||||||
) -> Dict[str, Tuple[float, float]]:
|
) -> Dict[str, Tuple[float, float]]:
|
||||||
"""
|
"""
|
||||||
Compute the (x, y) positions for each node in the flow graph.
|
Compute the (x, y) positions for each node in the flow graph.
|
||||||
@@ -181,7 +183,7 @@ def add_edges(
|
|||||||
net: Any,
|
net: Any,
|
||||||
flow: Any,
|
flow: Any,
|
||||||
node_positions: Dict[str, Tuple[float, float]],
|
node_positions: Dict[str, Tuple[float, float]],
|
||||||
colors: Dict[str, str]
|
colors: Dict[str, str],
|
||||||
) -> None:
|
) -> None:
|
||||||
edge_smooth: Dict[str, Union[str, float]] = {"type": "continuous"} # Default value
|
edge_smooth: Dict[str, Union[str, float]] = {"type": "continuous"} # Default value
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ class KickoffTaskOutputsSQLiteStorage:
|
|||||||
An updated SQLite storage class for kickoff task outputs storage.
|
An updated SQLite storage class for kickoff task outputs storage.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, db_path: Optional[str] = None) -> None:
|
||||||
self, db_path: Optional[str] = None
|
|
||||||
) -> None:
|
|
||||||
if db_path is None:
|
if db_path is None:
|
||||||
# Get the parent directory of the default db path and create our db file there
|
# Get the parent directory of the default db path and create our db file there
|
||||||
db_path = str(Path(db_storage_path()) / "latest_kickoff_task_outputs.db")
|
db_path = str(Path(db_storage_path()) / "latest_kickoff_task_outputs.db")
|
||||||
@@ -146,7 +144,9 @@ class KickoffTaskOutputsSQLiteStorage:
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
if cursor.rowcount == 0:
|
if cursor.rowcount == 0:
|
||||||
logger.warning(f"No row found with task_index {task_index}. No update performed.")
|
logger.warning(
|
||||||
|
f"No row found with task_index {task_index}. No update performed."
|
||||||
|
)
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
error_msg = DatabaseError.format_error(DatabaseError.UPDATE_ERROR, e)
|
error_msg = DatabaseError.format_error(DatabaseError.UPDATE_ERROR, e)
|
||||||
logger.error(error_msg)
|
logger.error(error_msg)
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ class LTMSQLiteStorage:
|
|||||||
An updated SQLite storage class for LTM data storage.
|
An updated SQLite storage class for LTM data storage.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, db_path: Optional[str] = None) -> None:
|
||||||
self, db_path: Optional[str] = None
|
|
||||||
) -> None:
|
|
||||||
if db_path is None:
|
if db_path is None:
|
||||||
# Get the parent directory of the default db path and create our db file there
|
# Get the parent directory of the default db path and create our db file there
|
||||||
db_path = str(Path(db_storage_path()) / "long_term_memory_storage.db")
|
db_path = str(Path(db_storage_path()) / "long_term_memory_storage.db")
|
||||||
|
|||||||
@@ -170,9 +170,13 @@ def CrewBase(cls: T) -> T:
|
|||||||
|
|
||||||
if function_calling_llm := agent_info.get("function_calling_llm"):
|
if function_calling_llm := agent_info.get("function_calling_llm"):
|
||||||
try:
|
try:
|
||||||
self.agents_config[agent_name]["function_calling_llm"] = llms[function_calling_llm]()
|
self.agents_config[agent_name]["function_calling_llm"] = llms[
|
||||||
|
function_calling_llm
|
||||||
|
]()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.agents_config[agent_name]["function_calling_llm"] = function_calling_llm
|
self.agents_config[agent_name]["function_calling_llm"] = (
|
||||||
|
function_calling_llm
|
||||||
|
)
|
||||||
|
|
||||||
if step_callback := agent_info.get("step_callback"):
|
if step_callback := agent_info.get("step_callback"):
|
||||||
self.agents_config[agent_name]["step_callback"] = callbacks[
|
self.agents_config[agent_name]["step_callback"] = callbacks[
|
||||||
|
|||||||
@@ -26,46 +26,55 @@ class Fingerprint(BaseModel):
|
|||||||
metadata (Dict[str, Any]): Additional metadata associated with this fingerprint
|
metadata (Dict[str, Any]): Additional metadata associated with this fingerprint
|
||||||
"""
|
"""
|
||||||
|
|
||||||
uuid_str: str = Field(default_factory=lambda: str(uuid.uuid4()), description="String representation of the UUID")
|
uuid_str: str = Field(
|
||||||
created_at: datetime = Field(default_factory=datetime.now, description="When this fingerprint was created")
|
default_factory=lambda: str(uuid.uuid4()),
|
||||||
metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata for this fingerprint")
|
description="String representation of the UUID",
|
||||||
|
)
|
||||||
|
created_at: datetime = Field(
|
||||||
|
default_factory=datetime.now, description="When this fingerprint was created"
|
||||||
|
)
|
||||||
|
metadata: Dict[str, Any] = Field(
|
||||||
|
default_factory=dict, description="Additional metadata for this fingerprint"
|
||||||
|
)
|
||||||
|
|
||||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||||
|
|
||||||
@field_validator('metadata')
|
@field_validator("metadata")
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_metadata(cls, v):
|
def validate_metadata(cls, v):
|
||||||
"""Validate that metadata is a dictionary with string keys and valid values."""
|
"""Validate that metadata is a dictionary with string keys and valid values."""
|
||||||
if not isinstance(v, dict):
|
if not isinstance(v, dict):
|
||||||
raise ValueError("Metadata must be a dictionary")
|
raise ValueError("Metadata must be a dictionary")
|
||||||
|
|
||||||
# Validate that all keys are strings
|
# Validate that all keys are strings
|
||||||
for key, value in v.items():
|
for key, value in v.items():
|
||||||
if not isinstance(key, str):
|
if not isinstance(key, str):
|
||||||
raise ValueError(f"Metadata keys must be strings, got {type(key)}")
|
raise ValueError(f"Metadata keys must be strings, got {type(key)}")
|
||||||
|
|
||||||
# Validate nested dictionaries (prevent deeply nested structures)
|
# Validate nested dictionaries (prevent deeply nested structures)
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
# Check for nested dictionaries (limit depth to 1)
|
# Check for nested dictionaries (limit depth to 1)
|
||||||
for nested_key, nested_value in value.items():
|
for nested_key, nested_value in value.items():
|
||||||
if not isinstance(nested_key, str):
|
if not isinstance(nested_key, str):
|
||||||
raise ValueError(f"Nested metadata keys must be strings, got {type(nested_key)}")
|
raise ValueError(
|
||||||
|
f"Nested metadata keys must be strings, got {type(nested_key)}"
|
||||||
|
)
|
||||||
if isinstance(nested_value, dict):
|
if isinstance(nested_value, dict):
|
||||||
raise ValueError("Metadata can only be nested one level deep")
|
raise ValueError("Metadata can only be nested one level deep")
|
||||||
|
|
||||||
# Check for maximum metadata size (prevent DoS)
|
# Check for maximum metadata size (prevent DoS)
|
||||||
if len(str(v)) > 10000: # Limit metadata size to 10KB
|
if len(str(v)) > 10000: # Limit metadata size to 10KB
|
||||||
raise ValueError("Metadata size exceeds maximum allowed (10KB)")
|
raise ValueError("Metadata size exceeds maximum allowed (10KB)")
|
||||||
|
|
||||||
return v
|
return v
|
||||||
|
|
||||||
def __init__(self, **data):
|
def __init__(self, **data):
|
||||||
"""Initialize a Fingerprint with auto-generated uuid_str and created_at."""
|
"""Initialize a Fingerprint with auto-generated uuid_str and created_at."""
|
||||||
# Remove uuid_str and created_at from data to ensure they're auto-generated
|
# Remove uuid_str and created_at from data to ensure they're auto-generated
|
||||||
if 'uuid_str' in data:
|
if "uuid_str" in data:
|
||||||
data.pop('uuid_str')
|
data.pop("uuid_str")
|
||||||
if 'created_at' in data:
|
if "created_at" in data:
|
||||||
data.pop('created_at')
|
data.pop("created_at")
|
||||||
|
|
||||||
# Call the parent constructor with the modified data
|
# Call the parent constructor with the modified data
|
||||||
super().__init__(**data)
|
super().__init__(**data)
|
||||||
@@ -88,19 +97,21 @@ class Fingerprint(BaseModel):
|
|||||||
"""
|
"""
|
||||||
if not isinstance(seed, str):
|
if not isinstance(seed, str):
|
||||||
raise ValueError("Seed must be a string")
|
raise ValueError("Seed must be a string")
|
||||||
|
|
||||||
if not seed.strip():
|
if not seed.strip():
|
||||||
raise ValueError("Seed cannot be empty or whitespace")
|
raise ValueError("Seed cannot be empty or whitespace")
|
||||||
|
|
||||||
# Create a deterministic UUID using v5 (SHA-1)
|
# Create a deterministic UUID using v5 (SHA-1)
|
||||||
# Custom namespace for CrewAI to enhance security
|
# Custom namespace for CrewAI to enhance security
|
||||||
|
|
||||||
# Using a unique namespace specific to CrewAI to reduce collision risks
|
# Using a unique namespace specific to CrewAI to reduce collision risks
|
||||||
CREW_AI_NAMESPACE = uuid.UUID('f47ac10b-58cc-4372-a567-0e02b2c3d479')
|
CREW_AI_NAMESPACE = uuid.UUID("f47ac10b-58cc-4372-a567-0e02b2c3d479")
|
||||||
return str(uuid.uuid5(CREW_AI_NAMESPACE, seed))
|
return str(uuid.uuid5(CREW_AI_NAMESPACE, seed))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate(cls, seed: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> 'Fingerprint':
|
def generate(
|
||||||
|
cls, seed: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None
|
||||||
|
) -> "Fingerprint":
|
||||||
"""
|
"""
|
||||||
Static factory method to create a new Fingerprint.
|
Static factory method to create a new Fingerprint.
|
||||||
|
|
||||||
@@ -115,7 +126,7 @@ class Fingerprint(BaseModel):
|
|||||||
fingerprint = cls(metadata=metadata or {})
|
fingerprint = cls(metadata=metadata or {})
|
||||||
if seed:
|
if seed:
|
||||||
# For seed-based generation, we need to manually set the uuid_str after creation
|
# For seed-based generation, we need to manually set the uuid_str after creation
|
||||||
object.__setattr__(fingerprint, 'uuid_str', cls._generate_uuid(seed))
|
object.__setattr__(fingerprint, "uuid_str", cls._generate_uuid(seed))
|
||||||
return fingerprint
|
return fingerprint
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
@@ -142,11 +153,11 @@ class Fingerprint(BaseModel):
|
|||||||
return {
|
return {
|
||||||
"uuid_str": self.uuid_str,
|
"uuid_str": self.uuid_str,
|
||||||
"created_at": self.created_at.isoformat(),
|
"created_at": self.created_at.isoformat(),
|
||||||
"metadata": self.metadata
|
"metadata": self.metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, data: Dict[str, Any]) -> 'Fingerprint':
|
def from_dict(cls, data: Dict[str, Any]) -> "Fingerprint":
|
||||||
"""
|
"""
|
||||||
Create a Fingerprint from a dictionary representation.
|
Create a Fingerprint from a dictionary representation.
|
||||||
|
|
||||||
@@ -163,8 +174,10 @@ class Fingerprint(BaseModel):
|
|||||||
|
|
||||||
# For consistency with existing stored fingerprints, we need to manually set these
|
# For consistency with existing stored fingerprints, we need to manually set these
|
||||||
if "uuid_str" in data:
|
if "uuid_str" in data:
|
||||||
object.__setattr__(fingerprint, 'uuid_str', data["uuid_str"])
|
object.__setattr__(fingerprint, "uuid_str", data["uuid_str"])
|
||||||
if "created_at" in data and isinstance(data["created_at"], str):
|
if "created_at" in data and isinstance(data["created_at"], str):
|
||||||
object.__setattr__(fingerprint, 'created_at', datetime.fromisoformat(data["created_at"]))
|
object.__setattr__(
|
||||||
|
fingerprint, "created_at", datetime.fromisoformat(data["created_at"])
|
||||||
|
)
|
||||||
|
|
||||||
return fingerprint
|
return fingerprint
|
||||||
|
|||||||
@@ -38,29 +38,27 @@ class SecurityConfig(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
version: str = Field(
|
version: str = Field(
|
||||||
default="1.0.0",
|
default="1.0.0", description="Version of the security configuration"
|
||||||
description="Version of the security configuration"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fingerprint: Fingerprint = Field(
|
fingerprint: Fingerprint = Field(
|
||||||
default_factory=Fingerprint,
|
default_factory=Fingerprint, description="Unique identifier for the component"
|
||||||
description="Unique identifier for the component"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_compatible(self, min_version: str) -> bool:
|
def is_compatible(self, min_version: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if this security configuration is compatible with the minimum required version.
|
Check if this security configuration is compatible with the minimum required version.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
min_version (str): Minimum required version in semver format (e.g., "1.0.0")
|
min_version (str): Minimum required version in semver format (e.g., "1.0.0")
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if this configuration is compatible, False otherwise
|
bool: True if this configuration is compatible, False otherwise
|
||||||
"""
|
"""
|
||||||
# Simple version comparison (can be enhanced with packaging.version if needed)
|
# Simple version comparison (can be enhanced with packaging.version if needed)
|
||||||
current = [int(x) for x in self.version.split(".")]
|
current = [int(x) for x in self.version.split(".")]
|
||||||
minimum = [int(x) for x in min_version.split(".")]
|
minimum = [int(x) for x in min_version.split(".")]
|
||||||
|
|
||||||
# Compare major, minor, patch versions
|
# Compare major, minor, patch versions
|
||||||
for c, m in zip(current, minimum):
|
for c, m in zip(current, minimum):
|
||||||
if c > m:
|
if c > m:
|
||||||
@@ -69,19 +67,19 @@ class SecurityConfig(BaseModel):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@model_validator(mode='before')
|
@model_validator(mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_fingerprint(cls, values):
|
def validate_fingerprint(cls, values):
|
||||||
"""Ensure fingerprint is properly initialized."""
|
"""Ensure fingerprint is properly initialized."""
|
||||||
if isinstance(values, dict):
|
if isinstance(values, dict):
|
||||||
# Handle case where fingerprint is not provided or is None
|
# Handle case where fingerprint is not provided or is None
|
||||||
if 'fingerprint' not in values or values['fingerprint'] is None:
|
if "fingerprint" not in values or values["fingerprint"] is None:
|
||||||
values['fingerprint'] = Fingerprint()
|
values["fingerprint"] = Fingerprint()
|
||||||
# Handle case where fingerprint is a string (seed)
|
# Handle case where fingerprint is a string (seed)
|
||||||
elif isinstance(values['fingerprint'], str):
|
elif isinstance(values["fingerprint"], str):
|
||||||
if not values['fingerprint'].strip():
|
if not values["fingerprint"].strip():
|
||||||
raise ValueError("Fingerprint seed cannot be empty")
|
raise ValueError("Fingerprint seed cannot be empty")
|
||||||
values['fingerprint'] = Fingerprint.generate(seed=values['fingerprint'])
|
values["fingerprint"] = Fingerprint.generate(seed=values["fingerprint"])
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, Any]:
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
@@ -91,13 +89,11 @@ class SecurityConfig(BaseModel):
|
|||||||
Returns:
|
Returns:
|
||||||
Dict[str, Any]: Dictionary representation of the security config
|
Dict[str, Any]: Dictionary representation of the security config
|
||||||
"""
|
"""
|
||||||
result = {
|
result = {"fingerprint": self.fingerprint.to_dict()}
|
||||||
"fingerprint": self.fingerprint.to_dict()
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, data: Dict[str, Any]) -> 'SecurityConfig':
|
def from_dict(cls, data: Dict[str, Any]) -> "SecurityConfig":
|
||||||
"""
|
"""
|
||||||
Create a SecurityConfig from a dictionary.
|
Create a SecurityConfig from a dictionary.
|
||||||
|
|
||||||
@@ -111,6 +107,10 @@ class SecurityConfig(BaseModel):
|
|||||||
data_copy = data.copy()
|
data_copy = data.copy()
|
||||||
|
|
||||||
fingerprint_data = data_copy.pop("fingerprint", None)
|
fingerprint_data = data_copy.pop("fingerprint", None)
|
||||||
fingerprint = Fingerprint.from_dict(fingerprint_data) if fingerprint_data else Fingerprint()
|
fingerprint = (
|
||||||
|
Fingerprint.from_dict(fingerprint_data)
|
||||||
|
if fingerprint_data
|
||||||
|
else Fingerprint()
|
||||||
|
)
|
||||||
|
|
||||||
return cls(fingerprint=fingerprint)
|
return cls(fingerprint=fingerprint)
|
||||||
|
|||||||
@@ -193,7 +193,6 @@ class Task(BaseModel):
|
|||||||
# Check return annotation if present, but don't require it
|
# Check return annotation if present, but don't require it
|
||||||
return_annotation = sig.return_annotation
|
return_annotation = sig.return_annotation
|
||||||
if return_annotation != inspect.Signature.empty:
|
if return_annotation != inspect.Signature.empty:
|
||||||
|
|
||||||
return_annotation_args = get_args(return_annotation)
|
return_annotation_args = get_args(return_annotation)
|
||||||
if not (
|
if not (
|
||||||
get_origin(return_annotation) is tuple
|
get_origin(return_annotation) is tuple
|
||||||
@@ -464,7 +463,9 @@ class Task(BaseModel):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
self._save_file(content)
|
self._save_file(content)
|
||||||
crewai_event_bus.emit(self, TaskCompletedEvent(output=task_output, task=self))
|
crewai_event_bus.emit(
|
||||||
|
self, TaskCompletedEvent(output=task_output, task=self)
|
||||||
|
)
|
||||||
return task_output
|
return task_output
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.end_time = datetime.datetime.now()
|
self.end_time = datetime.datetime.now()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class GuardrailResult(BaseModel):
|
|||||||
result (Any, optional): The validated/transformed result if successful
|
result (Any, optional): The validated/transformed result if successful
|
||||||
error (str, optional): Error message if validation failed
|
error (str, optional): Error message if validation failed
|
||||||
"""
|
"""
|
||||||
|
|
||||||
success: bool
|
success: bool
|
||||||
result: Optional[Any] = None
|
result: Optional[Any] = None
|
||||||
error: Optional[str] = None
|
error: Optional[str] = None
|
||||||
@@ -32,9 +33,13 @@ class GuardrailResult(BaseModel):
|
|||||||
values = info.data
|
values = info.data
|
||||||
if "success" in values:
|
if "success" in values:
|
||||||
if values["success"] and v and "error" in values and values["error"]:
|
if values["success"] and v and "error" in values and values["error"]:
|
||||||
raise ValueError("Cannot have both result and error when success is True")
|
raise ValueError(
|
||||||
|
"Cannot have both result and error when success is True"
|
||||||
|
)
|
||||||
if not values["success"] and v and "result" in values and values["result"]:
|
if not values["success"] and v and "result" in values and values["result"]:
|
||||||
raise ValueError("Cannot have both result and error when success is False")
|
raise ValueError(
|
||||||
|
"Cannot have both result and error when success is False"
|
||||||
|
)
|
||||||
return v
|
return v
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -52,5 +57,5 @@ class GuardrailResult(BaseModel):
|
|||||||
return cls(
|
return cls(
|
||||||
success=success,
|
success=success,
|
||||||
result=data if success else None,
|
result=data if success else None,
|
||||||
error=data if not success else None
|
error=data if not success else None,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -75,12 +75,12 @@ class Telemetry:
|
|||||||
):
|
):
|
||||||
raise # Re-raise the exception to not interfere with system signals
|
raise # Re-raise the exception to not interfere with system signals
|
||||||
self.ready = False
|
self.ready = False
|
||||||
|
|
||||||
def _is_telemetry_disabled(self) -> bool:
|
def _is_telemetry_disabled(self) -> bool:
|
||||||
"""Check if telemetry should be disabled based on environment variables."""
|
"""Check if telemetry should be disabled based on environment variables."""
|
||||||
return (
|
return (
|
||||||
os.getenv("OTEL_SDK_DISABLED", "false").lower() == "true" or
|
os.getenv("OTEL_SDK_DISABLED", "false").lower() == "true"
|
||||||
os.getenv("CREWAI_DISABLE_TELEMETRY", "false").lower() == "true"
|
or os.getenv("CREWAI_DISABLE_TELEMETRY", "false").lower() == "true"
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_tracer(self):
|
def set_tracer(self):
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ class AddImageTool(BaseTool):
|
|||||||
"""Tool for adding images to the content"""
|
"""Tool for adding images to the content"""
|
||||||
|
|
||||||
name: str = Field(default_factory=lambda: i18n.tools("add_image")["name"]) # type: ignore
|
name: str = Field(default_factory=lambda: i18n.tools("add_image")["name"]) # type: ignore
|
||||||
description: str = Field(default_factory=lambda: i18n.tools("add_image")["description"]) # type: ignore
|
description: str = Field(
|
||||||
|
default_factory=lambda: i18n.tools("add_image")["description"]
|
||||||
|
) # type: ignore
|
||||||
args_schema: type[BaseModel] = AddImageToolSchema
|
args_schema: type[BaseModel] = AddImageToolSchema
|
||||||
|
|
||||||
def _run(
|
def _run(
|
||||||
|
|||||||
@@ -47,10 +47,7 @@ class BaseAgentTool(BaseTool):
|
|||||||
return coworker
|
return coworker
|
||||||
|
|
||||||
def _execute(
|
def _execute(
|
||||||
self,
|
self, agent_name: Optional[str], task: str, context: Optional[str] = None
|
||||||
agent_name: Optional[str],
|
|
||||||
task: str,
|
|
||||||
context: Optional[str] = None
|
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Execute delegation to an agent with case-insensitive and whitespace-tolerant matching.
|
Execute delegation to an agent with case-insensitive and whitespace-tolerant matching.
|
||||||
@@ -77,7 +74,9 @@ class BaseAgentTool(BaseTool):
|
|||||||
# when it should look like this:
|
# when it should look like this:
|
||||||
# {"task": "....", "coworker": "...."}
|
# {"task": "....", "coworker": "...."}
|
||||||
sanitized_name = self.sanitize_agent_name(agent_name)
|
sanitized_name = self.sanitize_agent_name(agent_name)
|
||||||
logger.debug(f"Sanitized agent name from '{agent_name}' to '{sanitized_name}'")
|
logger.debug(
|
||||||
|
f"Sanitized agent name from '{agent_name}' to '{sanitized_name}'"
|
||||||
|
)
|
||||||
|
|
||||||
available_agents = [agent.role for agent in self.agents]
|
available_agents = [agent.role for agent in self.agents]
|
||||||
logger.debug(f"Available agents: {available_agents}")
|
logger.debug(f"Available agents: {available_agents}")
|
||||||
@@ -87,23 +86,31 @@ class BaseAgentTool(BaseTool):
|
|||||||
for available_agent in self.agents
|
for available_agent in self.agents
|
||||||
if self.sanitize_agent_name(available_agent.role) == sanitized_name
|
if self.sanitize_agent_name(available_agent.role) == sanitized_name
|
||||||
]
|
]
|
||||||
logger.debug(f"Found {len(agent)} matching agents for role '{sanitized_name}'")
|
logger.debug(
|
||||||
|
f"Found {len(agent)} matching agents for role '{sanitized_name}'"
|
||||||
|
)
|
||||||
except (AttributeError, ValueError) as e:
|
except (AttributeError, ValueError) as e:
|
||||||
# Handle specific exceptions that might occur during role name processing
|
# Handle specific exceptions that might occur during role name processing
|
||||||
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
||||||
coworkers="\n".join(
|
coworkers="\n".join(
|
||||||
[f"- {self.sanitize_agent_name(agent.role)}" for agent in self.agents]
|
[
|
||||||
|
f"- {self.sanitize_agent_name(agent.role)}"
|
||||||
|
for agent in self.agents
|
||||||
|
]
|
||||||
),
|
),
|
||||||
error=str(e)
|
error=str(e),
|
||||||
)
|
)
|
||||||
|
|
||||||
if not agent:
|
if not agent:
|
||||||
# No matching agent found after sanitization
|
# No matching agent found after sanitization
|
||||||
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
||||||
coworkers="\n".join(
|
coworkers="\n".join(
|
||||||
[f"- {self.sanitize_agent_name(agent.role)}" for agent in self.agents]
|
[
|
||||||
|
f"- {self.sanitize_agent_name(agent.role)}"
|
||||||
|
for agent in self.agents
|
||||||
|
]
|
||||||
),
|
),
|
||||||
error=f"No agent found with role '{sanitized_name}'"
|
error=f"No agent found with role '{sanitized_name}'",
|
||||||
)
|
)
|
||||||
|
|
||||||
agent = agent[0]
|
agent = agent[0]
|
||||||
@@ -114,11 +121,12 @@ class BaseAgentTool(BaseTool):
|
|||||||
expected_output=agent.i18n.slice("manager_request"),
|
expected_output=agent.i18n.slice("manager_request"),
|
||||||
i18n=agent.i18n,
|
i18n=agent.i18n,
|
||||||
)
|
)
|
||||||
logger.debug(f"Created task for agent '{self.sanitize_agent_name(agent.role)}': {task}")
|
logger.debug(
|
||||||
|
f"Created task for agent '{self.sanitize_agent_name(agent.role)}': {task}"
|
||||||
|
)
|
||||||
return agent.execute_task(task_with_assigned_agent, context)
|
return agent.execute_task(task_with_assigned_agent, context)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Handle task creation or execution errors
|
# Handle task creation or execution errors
|
||||||
return self.i18n.errors("agent_tool_execution_error").format(
|
return self.i18n.errors("agent_tool_execution_error").format(
|
||||||
agent_role=self.sanitize_agent_name(agent.role),
|
agent_role=self.sanitize_agent_name(agent.role), error=str(e)
|
||||||
error=str(e)
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ def to_langchain(
|
|||||||
def tool(*args, result_as_answer=False):
|
def tool(*args, result_as_answer=False):
|
||||||
"""
|
"""
|
||||||
Decorator to create a tool from a function.
|
Decorator to create a tool from a function.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args: Positional arguments, either the function to decorate or the tool name.
|
*args: Positional arguments, either the function to decorate or the tool name.
|
||||||
result_as_answer: Flag to indicate if the tool result should be used as the final agent answer.
|
result_as_answer: Flag to indicate if the tool result should be used as the final agent answer.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import json
|
|||||||
import re
|
import re
|
||||||
from typing import Any, Optional, Type, Union, get_args, get_origin
|
from typing import Any, Optional, Type, Union, get_args, get_origin
|
||||||
|
|
||||||
from pydantic import BaseModel, ValidationError
|
from pydantic import BaseModel, Field, ValidationError
|
||||||
|
|
||||||
from crewai.agents.agent_builder.utilities.base_output_converter import OutputConverter
|
from crewai.agents.agent_builder.utilities.base_output_converter import OutputConverter
|
||||||
from crewai.utilities.printer import Printer
|
from crewai.utilities.printer import Printer
|
||||||
@@ -20,18 +20,27 @@ class ConverterError(Exception):
|
|||||||
class Converter(OutputConverter):
|
class Converter(OutputConverter):
|
||||||
"""Class that converts text into either pydantic or json."""
|
"""Class that converts text into either pydantic or json."""
|
||||||
|
|
||||||
|
agent: Any = Field(description="The agent instance associated with this converter.")
|
||||||
|
|
||||||
def to_pydantic(self, current_attempt=1) -> BaseModel:
|
def to_pydantic(self, current_attempt=1) -> BaseModel:
|
||||||
"""Convert text to pydantic."""
|
"""Convert text to pydantic."""
|
||||||
try:
|
try:
|
||||||
if self.llm.supports_function_calling():
|
if self.llm.supports_function_calling():
|
||||||
result = self._create_instructor().to_pydantic()
|
result = self._create_instructor().to_pydantic()
|
||||||
else:
|
else:
|
||||||
response = self.llm.call(
|
messages = []
|
||||||
[
|
if self.agent and getattr(self.agent, "use_system_prompt", True):
|
||||||
{"role": "system", "content": self.instructions},
|
messages.append({"role": "system", "content": self.instructions})
|
||||||
{"role": "user", "content": self.text},
|
messages.append({"role": "user", "content": self.text})
|
||||||
]
|
else:
|
||||||
)
|
messages.append(
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": f"{self.instructions}\n\n{self.text}",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.llm.call(messages) # Assign the result to 'response'
|
||||||
try:
|
try:
|
||||||
# Try to directly validate the response JSON
|
# Try to directly validate the response JSON
|
||||||
result = self.model.model_validate_json(response)
|
result = self.model.model_validate_json(response)
|
||||||
@@ -74,14 +83,20 @@ class Converter(OutputConverter):
|
|||||||
if self.llm.supports_function_calling():
|
if self.llm.supports_function_calling():
|
||||||
return self._create_instructor().to_json()
|
return self._create_instructor().to_json()
|
||||||
else:
|
else:
|
||||||
return json.dumps(
|
messages = []
|
||||||
self.llm.call(
|
if self.agent and getattr(self.agent, "use_system_prompt", True):
|
||||||
[
|
messages.append({"role": "system", "content": self.instructions})
|
||||||
{"role": "system", "content": self.instructions},
|
messages.append({"role": "user", "content": self.text})
|
||||||
{"role": "user", "content": self.text},
|
else:
|
||||||
]
|
messages.append(
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": f"{self.instructions}\n\n{self.text}",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
llm_result = self.llm.call(messages)
|
||||||
|
return json.dumps(llm_result)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if current_attempt < self.max_attempts:
|
if current_attempt < self.max_attempts:
|
||||||
return self.to_json(current_attempt + 1)
|
return self.to_json(current_attempt + 1)
|
||||||
@@ -239,11 +254,11 @@ def create_converter(
|
|||||||
) -> Converter:
|
) -> Converter:
|
||||||
if agent and not converter_cls:
|
if agent and not converter_cls:
|
||||||
if hasattr(agent, "get_output_converter"):
|
if hasattr(agent, "get_output_converter"):
|
||||||
converter = agent.get_output_converter(*args, **kwargs)
|
converter = agent.get_output_converter(agent=agent, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
raise AttributeError("Agent does not have a 'get_output_converter' method")
|
raise AttributeError("Agent does not have a 'get_output_converter' method")
|
||||||
elif converter_cls:
|
elif converter_cls:
|
||||||
converter = converter_cls(*args, **kwargs)
|
converter = converter_cls(agent=agent, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Either agent or converter_cls must be provided")
|
raise ValueError("Either agent or converter_cls must be provided")
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from pydantic import BaseModel
|
|||||||
|
|
||||||
class CrewJSONEncoder(json.JSONEncoder):
|
class CrewJSONEncoder(json.JSONEncoder):
|
||||||
"""Custom JSON encoder for CrewAI objects and special types."""
|
"""Custom JSON encoder for CrewAI objects and special types."""
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from crewai.agents.parser import OutputParserException
|
|||||||
|
|
||||||
"""Parser for converting text outputs into Pydantic models."""
|
"""Parser for converting text outputs into Pydantic models."""
|
||||||
|
|
||||||
|
|
||||||
class CrewPydanticOutputParser:
|
class CrewPydanticOutputParser:
|
||||||
"""Parses text outputs into specified Pydantic models."""
|
"""Parses text outputs into specified Pydantic models."""
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
"""Error message definitions for CrewAI database operations."""
|
"""Error message definitions for CrewAI database operations."""
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,27 +7,33 @@ from typing import Union
|
|||||||
|
|
||||||
class FileHandler:
|
class FileHandler:
|
||||||
"""Handler for file operations supporting both JSON and text-based logging.
|
"""Handler for file operations supporting both JSON and text-based logging.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path (Union[bool, str]): Path to the log file or boolean flag
|
file_path (Union[bool, str]): Path to the log file or boolean flag
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, file_path: Union[bool, str]):
|
def __init__(self, file_path: Union[bool, str]):
|
||||||
self._initialize_path(file_path)
|
self._initialize_path(file_path)
|
||||||
|
|
||||||
def _initialize_path(self, file_path: Union[bool, str]):
|
def _initialize_path(self, file_path: Union[bool, str]):
|
||||||
if file_path is True: # File path is boolean True
|
if file_path is True: # File path is boolean True
|
||||||
self._path = os.path.join(os.curdir, "logs.txt")
|
self._path = os.path.join(os.curdir, "logs.txt")
|
||||||
|
|
||||||
elif isinstance(file_path, str): # File path is a string
|
elif isinstance(file_path, str): # File path is a string
|
||||||
if file_path.endswith((".json", ".txt")):
|
if file_path.endswith((".json", ".txt")):
|
||||||
self._path = file_path # No modification if the file ends with .json or .txt
|
self._path = (
|
||||||
|
file_path # No modification if the file ends with .json or .txt
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self._path = file_path + ".txt" # Append .txt if the file doesn't end with .json or .txt
|
self._path = (
|
||||||
|
file_path + ".txt"
|
||||||
|
) # Append .txt if the file doesn't end with .json or .txt
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("file_path must be a string or boolean.") # Handle the case where file_path isn't valid
|
raise ValueError(
|
||||||
|
"file_path must be a string or boolean."
|
||||||
|
) # Handle the case where file_path isn't valid
|
||||||
|
|
||||||
def log(self, **kwargs):
|
def log(self, **kwargs):
|
||||||
try:
|
try:
|
||||||
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
@@ -45,20 +51,25 @@ class FileHandler:
|
|||||||
except (json.JSONDecodeError, FileNotFoundError):
|
except (json.JSONDecodeError, FileNotFoundError):
|
||||||
# If no valid JSON or file doesn't exist, start with an empty list
|
# If no valid JSON or file doesn't exist, start with an empty list
|
||||||
existing_data = [log_entry]
|
existing_data = [log_entry]
|
||||||
|
|
||||||
with open(self._path, "w", encoding="utf-8") as write_file:
|
with open(self._path, "w", encoding="utf-8") as write_file:
|
||||||
json.dump(existing_data, write_file, indent=4)
|
json.dump(existing_data, write_file, indent=4)
|
||||||
write_file.write("\n")
|
write_file.write("\n")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Append log in plain text format
|
# Append log in plain text format
|
||||||
message = f"{now}: " + ", ".join([f"{key}=\"{value}\"" for key, value in kwargs.items()]) + "\n"
|
message = (
|
||||||
|
f"{now}: "
|
||||||
|
+ ", ".join([f'{key}="{value}"' for key, value in kwargs.items()])
|
||||||
|
+ "\n"
|
||||||
|
)
|
||||||
with open(self._path, "a", encoding="utf-8") as file:
|
with open(self._path, "a", encoding="utf-8") as file:
|
||||||
file.write(message)
|
file.write(message)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(f"Failed to log message: {str(e)}")
|
raise ValueError(f"Failed to log message: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
class PickleHandler:
|
class PickleHandler:
|
||||||
def __init__(self, file_name: str) -> None:
|
def __init__(self, file_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ from pydantic import BaseModel, Field, PrivateAttr, model_validator
|
|||||||
|
|
||||||
"""Internationalization support for CrewAI prompts and messages."""
|
"""Internationalization support for CrewAI prompts and messages."""
|
||||||
|
|
||||||
|
|
||||||
class I18N(BaseModel):
|
class I18N(BaseModel):
|
||||||
"""Handles loading and retrieving internationalized prompts."""
|
"""Handles loading and retrieving internationalized prompts."""
|
||||||
|
|
||||||
_prompts: Dict[str, Dict[str, str]] = PrivateAttr()
|
_prompts: Dict[str, Dict[str, str]] = PrivateAttr()
|
||||||
prompt_file: Optional[str] = Field(
|
prompt_file: Optional[str] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import appdirs
|
|||||||
|
|
||||||
"""Path management utilities for CrewAI storage and configuration."""
|
"""Path management utilities for CrewAI storage and configuration."""
|
||||||
|
|
||||||
|
|
||||||
def db_storage_path() -> str:
|
def db_storage_path() -> str:
|
||||||
"""Returns the path for SQLite database storage.
|
"""Returns the path for SQLite database storage.
|
||||||
|
|
||||||
@@ -28,4 +29,4 @@ def get_project_directory_name():
|
|||||||
else:
|
else:
|
||||||
cwd = Path.cwd()
|
cwd = Path.cwd()
|
||||||
project_directory_name = cwd.name
|
project_directory_name = cwd.name
|
||||||
return project_directory_name
|
return project_directory_name
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ from crewai.task import Task
|
|||||||
"""Handles planning and coordination of crew tasks."""
|
"""Handles planning and coordination of crew tasks."""
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PlanPerTask(BaseModel):
|
class PlanPerTask(BaseModel):
|
||||||
"""Represents a plan for a specific task."""
|
"""Represents a plan for a specific task."""
|
||||||
|
|
||||||
task: str = Field(..., description="The task for which the plan is created")
|
task: str = Field(..., description="The task for which the plan is created")
|
||||||
plan: str = Field(
|
plan: str = Field(
|
||||||
...,
|
...,
|
||||||
@@ -20,6 +22,7 @@ class PlanPerTask(BaseModel):
|
|||||||
|
|
||||||
class PlannerTaskPydanticOutput(BaseModel):
|
class PlannerTaskPydanticOutput(BaseModel):
|
||||||
"""Output format for task planning results."""
|
"""Output format for task planning results."""
|
||||||
|
|
||||||
list_of_plans_per_task: List[PlanPerTask] = Field(
|
list_of_plans_per_task: List[PlanPerTask] = Field(
|
||||||
...,
|
...,
|
||||||
description="Step by step plan on how the agents can execute their tasks using the available tools with mastery",
|
description="Step by step plan on how the agents can execute their tasks using the available tools with mastery",
|
||||||
@@ -28,6 +31,7 @@ class PlannerTaskPydanticOutput(BaseModel):
|
|||||||
|
|
||||||
class CrewPlanner:
|
class CrewPlanner:
|
||||||
"""Plans and coordinates the execution of crew tasks."""
|
"""Plans and coordinates the execution of crew tasks."""
|
||||||
|
|
||||||
def __init__(self, tasks: List[Task], planning_agent_llm: Optional[Any] = None):
|
def __init__(self, tasks: List[Task], planning_agent_llm: Optional[Any] = None):
|
||||||
self.tasks = tasks
|
self.tasks = tasks
|
||||||
|
|
||||||
@@ -97,8 +101,12 @@ class CrewPlanner:
|
|||||||
for idx, task in enumerate(self.tasks):
|
for idx, task in enumerate(self.tasks):
|
||||||
knowledge_list = self._get_agent_knowledge(task)
|
knowledge_list = self._get_agent_knowledge(task)
|
||||||
agent_tools = (
|
agent_tools = (
|
||||||
f"[{', '.join(str(tool) for tool in task.agent.tools)}]" if task.agent and task.agent.tools else '"agent has no tools"',
|
f"[{', '.join(str(tool) for tool in task.agent.tools)}]"
|
||||||
f',\n "agent_knowledge": "[\\"{knowledge_list[0]}\\"]"' if knowledge_list and str(knowledge_list) != "None" else ""
|
if task.agent and task.agent.tools
|
||||||
|
else '"agent has no tools"',
|
||||||
|
f',\n "agent_knowledge": "[\\"{knowledge_list[0]}\\"]"'
|
||||||
|
if knowledge_list and str(knowledge_list) != "None"
|
||||||
|
else "",
|
||||||
)
|
)
|
||||||
task_summary = f"""
|
task_summary = f"""
|
||||||
Task Number {idx + 1} - {task.description}
|
Task Number {idx + 1} - {task.description}
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ from crewai.task import Task
|
|||||||
|
|
||||||
"""Handles storage and retrieval of task execution outputs."""
|
"""Handles storage and retrieval of task execution outputs."""
|
||||||
|
|
||||||
|
|
||||||
class ExecutionLog(BaseModel):
|
class ExecutionLog(BaseModel):
|
||||||
"""Represents a log entry for task execution."""
|
"""Represents a log entry for task execution."""
|
||||||
|
|
||||||
task_id: str
|
task_id: str
|
||||||
expected_output: Optional[str] = None
|
expected_output: Optional[str] = None
|
||||||
output: Dict[str, Any]
|
output: Dict[str, Any]
|
||||||
@@ -26,6 +28,7 @@ class ExecutionLog(BaseModel):
|
|||||||
|
|
||||||
"""Manages storage and retrieval of task outputs."""
|
"""Manages storage and retrieval of task outputs."""
|
||||||
|
|
||||||
|
|
||||||
class TaskOutputStorageHandler:
|
class TaskOutputStorageHandler:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.storage = KickoffTaskOutputsSQLiteStorage()
|
self.storage = KickoffTaskOutputsSQLiteStorage()
|
||||||
|
|||||||
@@ -259,7 +259,9 @@ def test_cache_hitting():
|
|||||||
def handle_tool_end(source, event):
|
def handle_tool_end(source, event):
|
||||||
received_events.append(event)
|
received_events.append(event)
|
||||||
|
|
||||||
with (patch.object(CacheHandler, "read") as read,):
|
with (
|
||||||
|
patch.object(CacheHandler, "read") as read,
|
||||||
|
):
|
||||||
read.return_value = "0"
|
read.return_value = "0"
|
||||||
task = Task(
|
task = Task(
|
||||||
description="What is 2 times 6? Ignore correctness and just return the result of the multiplication tool, you must use the tool.",
|
description="What is 2 times 6? Ignore correctness and just return the result of the multiplication tool, you must use the tool.",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from dotenv import load_dotenv
|
|||||||
|
|
||||||
load_result = load_dotenv(override=True)
|
load_result = load_dotenv(override=True)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def setup_test_environment():
|
def setup_test_environment():
|
||||||
"""Set up test environment with a temporary directory for SQLite storage."""
|
"""Set up test environment with a temporary directory for SQLite storage."""
|
||||||
@@ -15,11 +16,13 @@ def setup_test_environment():
|
|||||||
# Create the directory with proper permissions
|
# Create the directory with proper permissions
|
||||||
storage_dir = Path(temp_dir) / "crewai_test_storage"
|
storage_dir = Path(temp_dir) / "crewai_test_storage"
|
||||||
storage_dir.mkdir(parents=True, exist_ok=True)
|
storage_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Validate that the directory was created successfully
|
# Validate that the directory was created successfully
|
||||||
if not storage_dir.exists() or not storage_dir.is_dir():
|
if not storage_dir.exists() or not storage_dir.is_dir():
|
||||||
raise RuntimeError(f"Failed to create test storage directory: {storage_dir}")
|
raise RuntimeError(
|
||||||
|
f"Failed to create test storage directory: {storage_dir}"
|
||||||
|
)
|
||||||
|
|
||||||
# Verify directory permissions
|
# Verify directory permissions
|
||||||
try:
|
try:
|
||||||
# Try to create a test file to verify write permissions
|
# Try to create a test file to verify write permissions
|
||||||
@@ -27,11 +30,13 @@ def setup_test_environment():
|
|||||||
test_file.touch()
|
test_file.touch()
|
||||||
test_file.unlink()
|
test_file.unlink()
|
||||||
except (OSError, IOError) as e:
|
except (OSError, IOError) as e:
|
||||||
raise RuntimeError(f"Test storage directory {storage_dir} is not writable: {e}")
|
raise RuntimeError(
|
||||||
|
f"Test storage directory {storage_dir} is not writable: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
# Set environment variable to point to the test storage directory
|
# Set environment variable to point to the test storage directory
|
||||||
os.environ["CREWAI_STORAGE_DIR"] = str(storage_dir)
|
os.environ["CREWAI_STORAGE_DIR"] = str(storage_dir)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
# Cleanup is handled automatically when tempfile context exits
|
# Cleanup is handled automatically when tempfile context exits
|
||||||
|
|||||||
@@ -2157,7 +2157,6 @@ def test_tools_with_custom_caching():
|
|||||||
with patch.object(
|
with patch.object(
|
||||||
CacheHandler, "add", wraps=crew._cache_handler.add
|
CacheHandler, "add", wraps=crew._cache_handler.add
|
||||||
) as add_to_cache:
|
) as add_to_cache:
|
||||||
|
|
||||||
result = crew.kickoff()
|
result = crew.kickoff()
|
||||||
|
|
||||||
# Check that add_to_cache was called exactly twice
|
# Check that add_to_cache was called exactly twice
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
def test_task_output_import():
|
def test_task_output_import():
|
||||||
"""Test that TaskOutput can be imported from crewai."""
|
"""Test that TaskOutput can be imported from crewai."""
|
||||||
from crewai import TaskOutput
|
from crewai import TaskOutput
|
||||||
|
|
||||||
assert TaskOutput is not None
|
assert TaskOutput is not None
|
||||||
|
|
||||||
|
|
||||||
def test_crew_output_import():
|
def test_crew_output_import():
|
||||||
"""Test that CrewOutput can be imported from crewai."""
|
"""Test that CrewOutput can be imported from crewai."""
|
||||||
from crewai import CrewOutput
|
from crewai import CrewOutput
|
||||||
|
|
||||||
assert CrewOutput is not None
|
assert CrewOutput is not None
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@@ -12,6 +11,7 @@ class MockCrew:
|
|||||||
def __init__(self, memory_config):
|
def __init__(self, memory_config):
|
||||||
self.memory_config = memory_config
|
self.memory_config = memory_config
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def user_memory():
|
def user_memory():
|
||||||
"""Fixture to create a UserMemory instance"""
|
"""Fixture to create a UserMemory instance"""
|
||||||
@@ -19,17 +19,18 @@ def user_memory():
|
|||||||
memory_config={
|
memory_config={
|
||||||
"provider": "mem0",
|
"provider": "mem0",
|
||||||
"config": {"user_id": "john"},
|
"config": {"user_id": "john"},
|
||||||
"user_memory" : {}
|
"user_memory": {},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
user_memory = MagicMock(spec=UserMemory)
|
user_memory = MagicMock(spec=UserMemory)
|
||||||
|
|
||||||
with patch.object(Memory,'__new__',return_value=user_memory):
|
with patch.object(Memory, "__new__", return_value=user_memory):
|
||||||
user_memory_instance = UserMemory(crew=crew)
|
user_memory_instance = UserMemory(crew=crew)
|
||||||
|
|
||||||
return user_memory_instance
|
return user_memory_instance
|
||||||
|
|
||||||
|
|
||||||
def test_save_and_search(user_memory):
|
def test_save_and_search(user_memory):
|
||||||
memory = UserMemoryItem(
|
memory = UserMemoryItem(
|
||||||
data="""test value test value test value test value test value test value
|
data="""test value test value test value test value test value test value
|
||||||
@@ -40,16 +41,10 @@ def test_save_and_search(user_memory):
|
|||||||
)
|
)
|
||||||
|
|
||||||
with patch.object(UserMemory, "save") as mock_save:
|
with patch.object(UserMemory, "save") as mock_save:
|
||||||
user_memory.save(
|
user_memory.save(value=memory.data, metadata=memory.metadata, user=memory.user)
|
||||||
value=memory.data,
|
|
||||||
metadata=memory.metadata,
|
|
||||||
user=memory.user
|
|
||||||
)
|
|
||||||
|
|
||||||
mock_save.assert_called_once_with(
|
mock_save.assert_called_once_with(
|
||||||
value=memory.data,
|
value=memory.data, metadata=memory.metadata, user=memory.user
|
||||||
metadata=memory.metadata,
|
|
||||||
user=memory.user
|
|
||||||
)
|
)
|
||||||
|
|
||||||
expected_result = [
|
expected_result = [
|
||||||
@@ -62,7 +57,9 @@ def test_save_and_search(user_memory):
|
|||||||
expected_result = ["mocked_result"]
|
expected_result = ["mocked_result"]
|
||||||
|
|
||||||
# Use patch.object to mock UserMemory's search method
|
# Use patch.object to mock UserMemory's search method
|
||||||
with patch.object(UserMemory, 'search', return_value=expected_result) as mock_search:
|
with patch.object(
|
||||||
|
UserMemory, "search", return_value=expected_result
|
||||||
|
) as mock_search:
|
||||||
find = UserMemory.search("test value", score_threshold=0.01)[0]
|
find = UserMemory.search("test value", score_threshold=0.01)[0]
|
||||||
mock_search.assert_called_once_with("test value", score_threshold=0.01)
|
mock_search.assert_called_once_with("test value", score_threshold=0.01)
|
||||||
assert find == expected_result[0]
|
assert find == expected_result[0]
|
||||||
|
|||||||
@@ -43,9 +43,10 @@ class InternalCrew:
|
|||||||
@llm
|
@llm
|
||||||
def local_llm(self):
|
def local_llm(self):
|
||||||
return LLM(
|
return LLM(
|
||||||
model='openai/model_name',
|
model="openai/model_name",
|
||||||
api_key="None",
|
api_key="None",
|
||||||
base_url="http://xxx.xxx.xxx.xxx:8000/v1")
|
base_url="http://xxx.xxx.xxx.xxx:8000/v1",
|
||||||
|
)
|
||||||
|
|
||||||
@agent
|
@agent
|
||||||
def researcher(self):
|
def researcher(self):
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ def test_agent_with_deterministic_fingerprint():
|
|||||||
role="Researcher",
|
role="Researcher",
|
||||||
goal="Research quantum computing",
|
goal="Research quantum computing",
|
||||||
backstory="Expert in quantum physics",
|
backstory="Expert in quantum physics",
|
||||||
security_config=security_config
|
security_config=security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create another agent with the same security config
|
# Create another agent with the same security config
|
||||||
@@ -62,7 +62,7 @@ def test_agent_with_deterministic_fingerprint():
|
|||||||
role="Completely different role",
|
role="Completely different role",
|
||||||
goal="Different goal",
|
goal="Different goal",
|
||||||
backstory="Different backstory",
|
backstory="Different backstory",
|
||||||
security_config=security_config
|
security_config=security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Both agents should have the same fingerprint UUID
|
# Both agents should have the same fingerprint UUID
|
||||||
@@ -84,9 +84,7 @@ def test_task_with_deterministic_fingerprint():
|
|||||||
|
|
||||||
# Create an agent first (required for tasks)
|
# Create an agent first (required for tasks)
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
role="Assistant",
|
role="Assistant", goal="Help with tasks", backstory="Helpful AI assistant"
|
||||||
goal="Help with tasks",
|
|
||||||
backstory="Helpful AI assistant"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a task with the deterministic fingerprint
|
# Create a task with the deterministic fingerprint
|
||||||
@@ -94,7 +92,7 @@ def test_task_with_deterministic_fingerprint():
|
|||||||
description="Analyze data",
|
description="Analyze data",
|
||||||
expected_output="Data analysis report",
|
expected_output="Data analysis report",
|
||||||
agent=agent,
|
agent=agent,
|
||||||
security_config=security_config
|
security_config=security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create another task with the same security config
|
# Create another task with the same security config
|
||||||
@@ -102,7 +100,7 @@ def test_task_with_deterministic_fingerprint():
|
|||||||
description="Different task description",
|
description="Different task description",
|
||||||
expected_output="Different expected output",
|
expected_output="Different expected output",
|
||||||
agent=agent,
|
agent=agent,
|
||||||
security_config=security_config
|
security_config=security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Both tasks should have the same fingerprint UUID
|
# Both tasks should have the same fingerprint UUID
|
||||||
@@ -119,36 +117,18 @@ def test_crew_with_deterministic_fingerprint():
|
|||||||
|
|
||||||
# Create agents for the crew
|
# Create agents for the crew
|
||||||
agent1 = Agent(
|
agent1 = Agent(
|
||||||
role="Researcher",
|
role="Researcher", goal="Research information", backstory="Expert researcher"
|
||||||
goal="Research information",
|
|
||||||
backstory="Expert researcher"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
agent2 = Agent(
|
agent2 = Agent(role="Writer", goal="Write reports", backstory="Expert writer")
|
||||||
role="Writer",
|
|
||||||
goal="Write reports",
|
|
||||||
backstory="Expert writer"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create a crew with the deterministic fingerprint
|
# Create a crew with the deterministic fingerprint
|
||||||
crew1 = Crew(
|
crew1 = Crew(agents=[agent1, agent2], tasks=[], security_config=security_config)
|
||||||
agents=[agent1, agent2],
|
|
||||||
tasks=[],
|
|
||||||
security_config=security_config
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create another crew with the same security config but different agents
|
# Create another crew with the same security config but different agents
|
||||||
agent3 = Agent(
|
agent3 = Agent(role="Analyst", goal="Analyze data", backstory="Expert analyst")
|
||||||
role="Analyst",
|
|
||||||
goal="Analyze data",
|
|
||||||
backstory="Expert analyst"
|
|
||||||
)
|
|
||||||
|
|
||||||
crew2 = Crew(
|
crew2 = Crew(agents=[agent3], tasks=[], security_config=security_config)
|
||||||
agents=[agent3],
|
|
||||||
tasks=[],
|
|
||||||
security_config=security_config
|
|
||||||
)
|
|
||||||
|
|
||||||
# Both crews should have the same fingerprint UUID
|
# Both crews should have the same fingerprint UUID
|
||||||
assert crew1.fingerprint.uuid_str == crew2.fingerprint.uuid_str
|
assert crew1.fingerprint.uuid_str == crew2.fingerprint.uuid_str
|
||||||
@@ -168,7 +148,7 @@ def test_recreating_components_with_same_seed():
|
|||||||
role="Researcher",
|
role="Researcher",
|
||||||
goal="Research topic",
|
goal="Research topic",
|
||||||
backstory="Expert researcher",
|
backstory="Expert researcher",
|
||||||
security_config=security_config1
|
security_config=security_config1,
|
||||||
)
|
)
|
||||||
|
|
||||||
uuid_from_first_session = agent1.fingerprint.uuid_str
|
uuid_from_first_session = agent1.fingerprint.uuid_str
|
||||||
@@ -181,7 +161,7 @@ def test_recreating_components_with_same_seed():
|
|||||||
role="Researcher",
|
role="Researcher",
|
||||||
goal="Research topic",
|
goal="Research topic",
|
||||||
backstory="Expert researcher",
|
backstory="Expert researcher",
|
||||||
security_config=security_config2
|
security_config=security_config2,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Should have same UUID across sessions
|
# Should have same UUID across sessions
|
||||||
@@ -209,7 +189,7 @@ def test_security_config_with_seed_string():
|
|||||||
role="Tester",
|
role="Tester",
|
||||||
goal="Test fingerprints",
|
goal="Test fingerprints",
|
||||||
backstory="Expert tester",
|
backstory="Expert tester",
|
||||||
security_config=security_config
|
security_config=security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Agent should have the same fingerprint UUID
|
# Agent should have the same fingerprint UUID
|
||||||
@@ -236,7 +216,7 @@ def test_complex_component_hierarchy_with_deterministic_fingerprints():
|
|||||||
role="Complex Test Agent",
|
role="Complex Test Agent",
|
||||||
goal="Test complex fingerprint scenarios",
|
goal="Test complex fingerprint scenarios",
|
||||||
backstory="Expert in testing",
|
backstory="Expert in testing",
|
||||||
security_config=agent_config
|
security_config=agent_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a task
|
# Create a task
|
||||||
@@ -244,15 +224,11 @@ def test_complex_component_hierarchy_with_deterministic_fingerprints():
|
|||||||
description="Test complex fingerprinting",
|
description="Test complex fingerprinting",
|
||||||
expected_output="Verification of fingerprint stability",
|
expected_output="Verification of fingerprint stability",
|
||||||
agent=agent,
|
agent=agent,
|
||||||
security_config=task_config
|
security_config=task_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a crew
|
# Create a crew
|
||||||
crew = Crew(
|
crew = Crew(agents=[agent], tasks=[task], security_config=crew_config)
|
||||||
agents=[agent],
|
|
||||||
tasks=[task],
|
|
||||||
security_config=crew_config
|
|
||||||
)
|
|
||||||
|
|
||||||
# Each component should have its own deterministic fingerprint
|
# Each component should have its own deterministic fingerprint
|
||||||
assert agent.fingerprint.uuid_str == agent_fingerprint.uuid_str
|
assert agent.fingerprint.uuid_str == agent_fingerprint.uuid_str
|
||||||
@@ -271,4 +247,4 @@ def test_complex_component_hierarchy_with_deterministic_fingerprints():
|
|||||||
|
|
||||||
assert agent_fingerprint.uuid_str == agent_fingerprint2.uuid_str
|
assert agent_fingerprint.uuid_str == agent_fingerprint2.uuid_str
|
||||||
assert task_fingerprint.uuid_str == task_fingerprint2.uuid_str
|
assert task_fingerprint.uuid_str == task_fingerprint2.uuid_str
|
||||||
assert crew_fingerprint.uuid_str == crew_fingerprint2.uuid_str
|
assert crew_fingerprint.uuid_str == crew_fingerprint2.uuid_str
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ def test_fingerprint_from_dict():
|
|||||||
fingerprint_dict = {
|
fingerprint_dict = {
|
||||||
"uuid_str": uuid_str,
|
"uuid_str": uuid_str,
|
||||||
"created_at": created_at_iso,
|
"created_at": created_at_iso,
|
||||||
"metadata": metadata
|
"metadata": metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
fingerprint = Fingerprint.from_dict(fingerprint_dict)
|
fingerprint = Fingerprint.from_dict(fingerprint_dict)
|
||||||
@@ -207,11 +207,7 @@ def test_invalid_uuid_str():
|
|||||||
uuid_str = "not-a-valid-uuid"
|
uuid_str = "not-a-valid-uuid"
|
||||||
created_at = datetime.now().isoformat()
|
created_at = datetime.now().isoformat()
|
||||||
|
|
||||||
fingerprint_dict = {
|
fingerprint_dict = {"uuid_str": uuid_str, "created_at": created_at, "metadata": {}}
|
||||||
"uuid_str": uuid_str,
|
|
||||||
"created_at": created_at,
|
|
||||||
"metadata": {}
|
|
||||||
}
|
|
||||||
|
|
||||||
# The Fingerprint.from_dict method accepts even invalid UUIDs
|
# The Fingerprint.from_dict method accepts even invalid UUIDs
|
||||||
# This seems to be the current behavior
|
# This seems to be the current behavior
|
||||||
@@ -243,7 +239,7 @@ def test_fingerprint_metadata_mutation():
|
|||||||
expected_metadata = {
|
expected_metadata = {
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"status": "published",
|
"status": "published",
|
||||||
"author": "Test Author"
|
"author": "Test Author",
|
||||||
}
|
}
|
||||||
assert fingerprint.metadata == expected_metadata
|
assert fingerprint.metadata == expected_metadata
|
||||||
|
|
||||||
@@ -260,4 +256,4 @@ def test_fingerprint_metadata_mutation():
|
|||||||
|
|
||||||
# Ensure immutable fields remain unchanged
|
# Ensure immutable fields remain unchanged
|
||||||
assert fingerprint.uuid_str == uuid_str
|
assert fingerprint.uuid_str == uuid_str
|
||||||
assert fingerprint.created_at == created_at
|
assert fingerprint.created_at == created_at
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ def test_agent_with_security_config():
|
|||||||
role="Tester",
|
role="Tester",
|
||||||
goal="Test fingerprinting",
|
goal="Test fingerprinting",
|
||||||
backstory="Testing fingerprinting",
|
backstory="Testing fingerprinting",
|
||||||
security_config=security_config
|
security_config=security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert agent.security_config is not None
|
assert agent.security_config is not None
|
||||||
@@ -28,9 +28,7 @@ def test_agent_fingerprint_property():
|
|||||||
"""Test the fingerprint property on Agent."""
|
"""Test the fingerprint property on Agent."""
|
||||||
# Create agent without security_config
|
# Create agent without security_config
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
role="Tester",
|
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Fingerprint should be automatically generated
|
# Fingerprint should be automatically generated
|
||||||
@@ -45,21 +43,14 @@ def test_crew_with_security_config():
|
|||||||
security_config = SecurityConfig()
|
security_config = SecurityConfig()
|
||||||
|
|
||||||
agent1 = Agent(
|
agent1 = Agent(
|
||||||
role="Tester1",
|
role="Tester1", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
agent2 = Agent(
|
agent2 = Agent(
|
||||||
role="Tester2",
|
role="Tester2", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
crew = Crew(
|
crew = Crew(agents=[agent1, agent2], security_config=security_config)
|
||||||
agents=[agent1, agent2],
|
|
||||||
security_config=security_config
|
|
||||||
)
|
|
||||||
|
|
||||||
assert crew.security_config is not None
|
assert crew.security_config is not None
|
||||||
assert crew.security_config == security_config
|
assert crew.security_config == security_config
|
||||||
@@ -71,15 +62,11 @@ def test_crew_fingerprint_property():
|
|||||||
"""Test the fingerprint property on Crew."""
|
"""Test the fingerprint property on Crew."""
|
||||||
# Create crew without security_config
|
# Create crew without security_config
|
||||||
agent1 = Agent(
|
agent1 = Agent(
|
||||||
role="Tester1",
|
role="Tester1", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
agent2 = Agent(
|
agent2 = Agent(
|
||||||
role="Tester2",
|
role="Tester2", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
crew = Crew(agents=[agent1, agent2])
|
crew = Crew(agents=[agent1, agent2])
|
||||||
@@ -96,16 +83,14 @@ def test_task_with_security_config():
|
|||||||
security_config = SecurityConfig()
|
security_config = SecurityConfig()
|
||||||
|
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
role="Tester",
|
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
task = Task(
|
task = Task(
|
||||||
description="Test task",
|
description="Test task",
|
||||||
expected_output="Testing output",
|
expected_output="Testing output",
|
||||||
agent=agent,
|
agent=agent,
|
||||||
security_config=security_config
|
security_config=security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert task.security_config is not None
|
assert task.security_config is not None
|
||||||
@@ -118,16 +103,10 @@ def test_task_fingerprint_property():
|
|||||||
"""Test the fingerprint property on Task."""
|
"""Test the fingerprint property on Task."""
|
||||||
# Create task without security_config
|
# Create task without security_config
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
role="Tester",
|
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
task = Task(
|
task = Task(description="Test task", expected_output="Testing output", agent=agent)
|
||||||
description="Test task",
|
|
||||||
expected_output="Testing output",
|
|
||||||
agent=agent
|
|
||||||
)
|
|
||||||
|
|
||||||
# Fingerprint should be automatically generated
|
# Fingerprint should be automatically generated
|
||||||
assert task.fingerprint is not None
|
assert task.fingerprint is not None
|
||||||
@@ -139,33 +118,20 @@ def test_end_to_end_fingerprinting():
|
|||||||
"""Test end-to-end fingerprinting across Agent, Crew, and Task."""
|
"""Test end-to-end fingerprinting across Agent, Crew, and Task."""
|
||||||
# Create components with auto-generated fingerprints
|
# Create components with auto-generated fingerprints
|
||||||
agent1 = Agent(
|
agent1 = Agent(
|
||||||
role="Researcher",
|
role="Researcher", goal="Research information", backstory="Expert researcher"
|
||||||
goal="Research information",
|
|
||||||
backstory="Expert researcher"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
agent2 = Agent(
|
agent2 = Agent(role="Writer", goal="Write content", backstory="Expert writer")
|
||||||
role="Writer",
|
|
||||||
goal="Write content",
|
|
||||||
backstory="Expert writer"
|
|
||||||
)
|
|
||||||
|
|
||||||
task1 = Task(
|
task1 = Task(
|
||||||
description="Research topic",
|
description="Research topic", expected_output="Research findings", agent=agent1
|
||||||
expected_output="Research findings",
|
|
||||||
agent=agent1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
task2 = Task(
|
task2 = Task(
|
||||||
description="Write article",
|
description="Write article", expected_output="Written article", agent=agent2
|
||||||
expected_output="Written article",
|
|
||||||
agent=agent2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
crew = Crew(
|
crew = Crew(agents=[agent1, agent2], tasks=[task1, task2])
|
||||||
agents=[agent1, agent2],
|
|
||||||
tasks=[task1, task2]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify all fingerprints were automatically generated
|
# Verify all fingerprints were automatically generated
|
||||||
assert agent1.fingerprint is not None
|
assert agent1.fingerprint is not None
|
||||||
@@ -180,18 +146,18 @@ def test_end_to_end_fingerprinting():
|
|||||||
agent2.fingerprint.uuid_str,
|
agent2.fingerprint.uuid_str,
|
||||||
task1.fingerprint.uuid_str,
|
task1.fingerprint.uuid_str,
|
||||||
task2.fingerprint.uuid_str,
|
task2.fingerprint.uuid_str,
|
||||||
crew.fingerprint.uuid_str
|
crew.fingerprint.uuid_str,
|
||||||
]
|
]
|
||||||
assert len(fingerprints) == len(set(fingerprints)), "All fingerprints should be unique"
|
assert len(fingerprints) == len(
|
||||||
|
set(fingerprints)
|
||||||
|
), "All fingerprints should be unique"
|
||||||
|
|
||||||
|
|
||||||
def test_fingerprint_persistence():
|
def test_fingerprint_persistence():
|
||||||
"""Test that fingerprints persist and don't change."""
|
"""Test that fingerprints persist and don't change."""
|
||||||
# Create an agent and check its fingerprint
|
# Create an agent and check its fingerprint
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
role="Tester",
|
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||||
goal="Test fingerprinting",
|
|
||||||
backstory="Testing fingerprinting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get initial fingerprint
|
# Get initial fingerprint
|
||||||
@@ -201,11 +167,7 @@ def test_fingerprint_persistence():
|
|||||||
assert agent.fingerprint.uuid_str == initial_fingerprint
|
assert agent.fingerprint.uuid_str == initial_fingerprint
|
||||||
|
|
||||||
# Create a task with the agent
|
# Create a task with the agent
|
||||||
task = Task(
|
task = Task(description="Test task", expected_output="Testing output", agent=agent)
|
||||||
description="Test task",
|
|
||||||
expected_output="Testing output",
|
|
||||||
agent=agent
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check that task has its own unique fingerprint
|
# Check that task has its own unique fingerprint
|
||||||
assert task.fingerprint is not None
|
assert task.fingerprint is not None
|
||||||
@@ -223,27 +185,25 @@ def test_shared_security_config_fingerprints():
|
|||||||
role="Researcher",
|
role="Researcher",
|
||||||
goal="Research information",
|
goal="Research information",
|
||||||
backstory="Expert researcher",
|
backstory="Expert researcher",
|
||||||
security_config=shared_security_config
|
security_config=shared_security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
agent2 = Agent(
|
agent2 = Agent(
|
||||||
role="Writer",
|
role="Writer",
|
||||||
goal="Write content",
|
goal="Write content",
|
||||||
backstory="Expert writer",
|
backstory="Expert writer",
|
||||||
security_config=shared_security_config
|
security_config=shared_security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
task = Task(
|
task = Task(
|
||||||
description="Write article",
|
description="Write article",
|
||||||
expected_output="Written article",
|
expected_output="Written article",
|
||||||
agent=agent1,
|
agent=agent1,
|
||||||
security_config=shared_security_config
|
security_config=shared_security_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
crew = Crew(
|
crew = Crew(
|
||||||
agents=[agent1, agent2],
|
agents=[agent1, agent2], tasks=[task], security_config=shared_security_config
|
||||||
tasks=[task],
|
|
||||||
security_config=shared_security_config
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify all components have the same fingerprint UUID
|
# Verify all components have the same fingerprint UUID
|
||||||
@@ -256,4 +216,4 @@ def test_shared_security_config_fingerprints():
|
|||||||
assert agent1.fingerprint is shared_security_config.fingerprint
|
assert agent1.fingerprint is shared_security_config.fingerprint
|
||||||
assert agent2.fingerprint is shared_security_config.fingerprint
|
assert agent2.fingerprint is shared_security_config.fingerprint
|
||||||
assert task.fingerprint is shared_security_config.fingerprint
|
assert task.fingerprint is shared_security_config.fingerprint
|
||||||
assert crew.fingerprint is shared_security_config.fingerprint
|
assert crew.fingerprint is shared_security_config.fingerprint
|
||||||
|
|||||||
@@ -63,13 +63,11 @@ def test_security_config_from_dict():
|
|||||||
fingerprint_dict = {
|
fingerprint_dict = {
|
||||||
"uuid_str": "b723c6ff-95de-5e87-860b-467b72282bd8",
|
"uuid_str": "b723c6ff-95de-5e87-860b-467b72282bd8",
|
||||||
"created_at": datetime.now().isoformat(),
|
"created_at": datetime.now().isoformat(),
|
||||||
"metadata": {"version": "1.0"}
|
"metadata": {"version": "1.0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a config dict with just the fingerprint
|
# Create a config dict with just the fingerprint
|
||||||
config_dict = {
|
config_dict = {"fingerprint": fingerprint_dict}
|
||||||
"fingerprint": fingerprint_dict
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create config manually since from_dict has a specific implementation
|
# Create config manually since from_dict has a specific implementation
|
||||||
config = SecurityConfig()
|
config = SecurityConfig()
|
||||||
@@ -115,4 +113,4 @@ def test_security_config_json_serialization():
|
|||||||
new_config.fingerprint = new_fingerprint
|
new_config.fingerprint = new_fingerprint
|
||||||
|
|
||||||
# Check the new config has the same fingerprint metadata
|
# Check the new config has the same fingerprint metadata
|
||||||
assert new_config.fingerprint.metadata == {"version": "1.0"}
|
assert new_config.fingerprint.metadata == {"version": "1.0"}
|
||||||
|
|||||||
@@ -6,14 +6,17 @@ import pytest
|
|||||||
from crewai.telemetry import Telemetry
|
from crewai.telemetry import Telemetry
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("env_var,value,expected_ready", [
|
@pytest.mark.parametrize(
|
||||||
("OTEL_SDK_DISABLED", "true", False),
|
"env_var,value,expected_ready",
|
||||||
("OTEL_SDK_DISABLED", "TRUE", False),
|
[
|
||||||
("CREWAI_DISABLE_TELEMETRY", "true", False),
|
("OTEL_SDK_DISABLED", "true", False),
|
||||||
("CREWAI_DISABLE_TELEMETRY", "TRUE", False),
|
("OTEL_SDK_DISABLED", "TRUE", False),
|
||||||
("OTEL_SDK_DISABLED", "false", True),
|
("CREWAI_DISABLE_TELEMETRY", "true", False),
|
||||||
("CREWAI_DISABLE_TELEMETRY", "false", True),
|
("CREWAI_DISABLE_TELEMETRY", "TRUE", False),
|
||||||
])
|
("OTEL_SDK_DISABLED", "false", True),
|
||||||
|
("CREWAI_DISABLE_TELEMETRY", "false", True),
|
||||||
|
],
|
||||||
|
)
|
||||||
def test_telemetry_environment_variables(env_var, value, expected_ready):
|
def test_telemetry_environment_variables(env_var, value, expected_ready):
|
||||||
"""Test telemetry state with different environment variable configurations."""
|
"""Test telemetry state with different environment variable configurations."""
|
||||||
with patch.dict(os.environ, {env_var: value}):
|
with patch.dict(os.environ, {env_var: value}):
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from crewai.flow.persistence import persist
|
|||||||
|
|
||||||
class PoemState(FlowState):
|
class PoemState(FlowState):
|
||||||
"""Test state model with default values that should be overridden."""
|
"""Test state model with default values that should be overridden."""
|
||||||
|
|
||||||
sentence_count: int = 1000 # Default that should be overridden
|
sentence_count: int = 1000 # Default that should be overridden
|
||||||
has_set_count: bool = False # Track whether we've set the count
|
has_set_count: bool = False # Track whether we've set the count
|
||||||
poem_type: str = ""
|
poem_type: str = ""
|
||||||
@@ -46,11 +47,13 @@ def test_default_value_override():
|
|||||||
|
|
||||||
# Fourth run - explicit override should work
|
# Fourth run - explicit override should work
|
||||||
flow3 = PoemFlow()
|
flow3 = PoemFlow()
|
||||||
flow3.kickoff(inputs={
|
flow3.kickoff(
|
||||||
"id": original_uuid,
|
inputs={
|
||||||
"has_set_count": True,
|
"id": original_uuid,
|
||||||
"sentence_count": 5, # Override persisted value
|
"has_set_count": True,
|
||||||
})
|
"sentence_count": 5, # Override persisted value
|
||||||
|
}
|
||||||
|
)
|
||||||
assert flow3.state.sentence_count == 5 # Should use override value
|
assert flow3.state.sentence_count == 5 # Should use override value
|
||||||
|
|
||||||
# Third run - should not load sentence_count=2 instead of default 1000
|
# Third run - should not load sentence_count=2 instead of default 1000
|
||||||
@@ -96,17 +99,12 @@ def test_multi_step_default_override():
|
|||||||
|
|
||||||
# Second run - should load persisted state and update poem type
|
# Second run - should load persisted state and update poem type
|
||||||
flow2 = MultiStepPoemFlow()
|
flow2 = MultiStepPoemFlow()
|
||||||
flow2.kickoff(inputs={
|
flow2.kickoff(inputs={"id": original_uuid, "sentence_count": 5})
|
||||||
"id": original_uuid,
|
|
||||||
"sentence_count": 5
|
|
||||||
})
|
|
||||||
assert flow2.state.sentence_count == 5
|
assert flow2.state.sentence_count == 5
|
||||||
assert flow2.state.poem_type == "limerick"
|
assert flow2.state.poem_type == "limerick"
|
||||||
|
|
||||||
# Third run - new flow without persisted state should use defaults
|
# Third run - new flow without persisted state should use defaults
|
||||||
flow3 = MultiStepPoemFlow()
|
flow3 = MultiStepPoemFlow()
|
||||||
flow3.kickoff(inputs={
|
flow3.kickoff(inputs={"id": original_uuid})
|
||||||
"id": original_uuid
|
|
||||||
})
|
|
||||||
assert flow3.state.sentence_count == 5
|
assert flow3.state.sentence_count == 5
|
||||||
assert flow3.state.poem_type == "limerick"
|
assert flow3.state.poem_type == "limerick"
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ def test_multimodal_agent_with_image_url():
|
|||||||
llm = LLM(
|
llm = LLM(
|
||||||
model="openai/gpt-4o", # model with vision capabilities
|
model="openai/gpt-4o", # model with vision capabilities
|
||||||
api_key=OPENAI_API_KEY,
|
api_key=OPENAI_API_KEY,
|
||||||
temperature=0.7
|
temperature=0.7,
|
||||||
)
|
)
|
||||||
|
|
||||||
expert_analyst = Agent(
|
expert_analyst = Agent(
|
||||||
@@ -28,7 +28,7 @@ def test_multimodal_agent_with_image_url():
|
|||||||
llm=llm,
|
llm=llm,
|
||||||
verbose=True,
|
verbose=True,
|
||||||
allow_delegation=False,
|
allow_delegation=False,
|
||||||
multimodal=True
|
multimodal=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
inspection_task = Task(
|
inspection_task = Task(
|
||||||
@@ -40,7 +40,7 @@ def test_multimodal_agent_with_image_url():
|
|||||||
Provide a detailed report highlighting any issues found.
|
Provide a detailed report highlighting any issues found.
|
||||||
""",
|
""",
|
||||||
expected_output="A detailed report highlighting any issues found",
|
expected_output="A detailed report highlighting any issues found",
|
||||||
agent=expert_analyst
|
agent=expert_analyst,
|
||||||
)
|
)
|
||||||
|
|
||||||
crew = Crew(agents=[expert_analyst], tasks=[inspection_task])
|
crew = Crew(agents=[expert_analyst], tasks=[inspection_task])
|
||||||
|
|||||||
@@ -107,18 +107,18 @@ def test_result_as_answer_in_tool_decorator():
|
|||||||
def my_tool_with_result_as_answer(question: str) -> str:
|
def my_tool_with_result_as_answer(question: str) -> str:
|
||||||
"""This tool will return its result as the final answer."""
|
"""This tool will return its result as the final answer."""
|
||||||
return question
|
return question
|
||||||
|
|
||||||
assert my_tool_with_result_as_answer.result_as_answer is True
|
assert my_tool_with_result_as_answer.result_as_answer is True
|
||||||
|
|
||||||
converted_tool = my_tool_with_result_as_answer.to_structured_tool()
|
converted_tool = my_tool_with_result_as_answer.to_structured_tool()
|
||||||
assert converted_tool.result_as_answer is True
|
assert converted_tool.result_as_answer is True
|
||||||
|
|
||||||
@tool("Tool with default result_as_answer")
|
@tool("Tool with default result_as_answer")
|
||||||
def my_tool_with_default(question: str) -> str:
|
def my_tool_with_default(question: str) -> str:
|
||||||
"""This tool uses the default result_as_answer value."""
|
"""This tool uses the default result_as_answer value."""
|
||||||
return question
|
return question
|
||||||
|
|
||||||
assert my_tool_with_default.result_as_answer is False
|
assert my_tool_with_default.result_as_answer is False
|
||||||
|
|
||||||
converted_tool = my_tool_with_default.to_structured_tool()
|
converted_tool = my_tool_with_default.to_structured_tool()
|
||||||
assert converted_tool.result_as_answer is False
|
assert converted_tool.result_as_answer is False
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,864 +0,0 @@
|
|||||||
interactions:
|
|
||||||
- request:
|
|
||||||
body: '{"model": "llama3.2:3b", "prompt": "### System:\nPlease convert the following
|
|
||||||
text into valid JSON.\n\nOutput ONLY the valid JSON and nothing else.\n\nThe
|
|
||||||
JSON must follow this format exactly:\n{\n \"name\": str,\n \"age\": int\n}\n\n###
|
|
||||||
User:\nName: Alice Llama, Age: 30\n\n", "options": {"stop": []}, "stream": false}'
|
|
||||||
headers:
|
|
||||||
accept:
|
|
||||||
- '*/*'
|
|
||||||
accept-encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
connection:
|
|
||||||
- keep-alive
|
|
||||||
content-length:
|
|
||||||
- '321'
|
|
||||||
host:
|
|
||||||
- localhost:11434
|
|
||||||
user-agent:
|
|
||||||
- litellm/1.60.2
|
|
||||||
method: POST
|
|
||||||
uri: http://localhost:11434/api/generate
|
|
||||||
response:
|
|
||||||
content: '{"model":"llama3.2:3b","created_at":"2025-02-21T02:57:55.059392Z","response":"{\"name\":
|
|
||||||
\"Alice Llama\", \"age\": 30}","done":true,"done_reason":"stop","context":[128006,9125,128007,271,38766,1303,33025,2696,25,6790,220,2366,18,271,128009,128006,882,128007,271,14711,744,512,5618,5625,279,2768,1495,1139,2764,4823,382,5207,27785,279,2764,4823,323,4400,775,382,791,4823,2011,1833,420,3645,7041,512,517,220,330,609,794,610,345,220,330,425,794,528,198,633,14711,2724,512,678,25,30505,445,81101,11,13381,25,220,966,271,128009,128006,78191,128007,271,5018,609,794,330,62786,445,81101,498,330,425,794,220,966,92],"total_duration":4675906000,"load_duration":836091458,"prompt_eval_count":82,"prompt_eval_duration":3561000000,"eval_count":15,"eval_duration":275000000}'
|
|
||||||
headers:
|
|
||||||
Content-Length:
|
|
||||||
- '761'
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Date:
|
|
||||||
- Fri, 21 Feb 2025 02:57:55 GMT
|
|
||||||
http_version: HTTP/1.1
|
|
||||||
status_code: 200
|
|
||||||
- request:
|
|
||||||
body: '{"name": "llama3.2:3b"}'
|
|
||||||
headers:
|
|
||||||
accept:
|
|
||||||
- '*/*'
|
|
||||||
accept-encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
connection:
|
|
||||||
- keep-alive
|
|
||||||
content-length:
|
|
||||||
- '23'
|
|
||||||
content-type:
|
|
||||||
- application/json
|
|
||||||
host:
|
|
||||||
- localhost:11434
|
|
||||||
user-agent:
|
|
||||||
- litellm/1.60.2
|
|
||||||
method: POST
|
|
||||||
uri: http://localhost:11434/api/show
|
|
||||||
response:
|
|
||||||
content: "{\"license\":\"LLAMA 3.2 COMMUNITY LICENSE AGREEMENT\\nLlama 3.2 Version
|
|
||||||
Release Date: September 25, 2024\\n\\n\u201CAgreement\u201D means the terms
|
|
||||||
and conditions for use, reproduction, distribution \\nand modification of the
|
|
||||||
Llama Materials set forth herein.\\n\\n\u201CDocumentation\u201D means the specifications,
|
|
||||||
manuals and documentation accompanying Llama 3.2\\ndistributed by Meta at https://llama.meta.com/doc/overview.\\n\\n\u201CLicensee\u201D
|
|
||||||
or \u201Cyou\u201D means you, or your employer or any other person or entity
|
|
||||||
(if you are \\nentering into this Agreement on such person or entity\u2019s
|
|
||||||
behalf), of the age required under\\napplicable laws, rules or regulations to
|
|
||||||
provide legal consent and that has legal authority\\nto bind your employer or
|
|
||||||
such other person or entity if you are entering in this Agreement\\non their
|
|
||||||
behalf.\\n\\n\u201CLlama 3.2\u201D means the foundational large language models
|
|
||||||
and software and algorithms, including\\nmachine-learning model code, trained
|
|
||||||
model weights, inference-enabling code, training-enabling code,\\nfine-tuning
|
|
||||||
enabling code and other elements of the foregoing distributed by Meta at \\nhttps://www.llama.com/llama-downloads.\\n\\n\u201CLlama
|
|
||||||
Materials\u201D means, collectively, Meta\u2019s proprietary Llama 3.2 and Documentation
|
|
||||||
(and \\nany portion thereof) made available under this Agreement.\\n\\n\u201CMeta\u201D
|
|
||||||
or \u201Cwe\u201D means Meta Platforms Ireland Limited (if you are located in
|
|
||||||
or, \\nif you are an entity, your principal place of business is in the EEA
|
|
||||||
or Switzerland) \\nand Meta Platforms, Inc. (if you are located outside of the
|
|
||||||
EEA or Switzerland). \\n\\n\\nBy clicking \u201CI Accept\u201D below or by using
|
|
||||||
or distributing any portion or element of the Llama Materials,\\nyou agree to
|
|
||||||
be bound by this Agreement.\\n\\n\\n1. License Rights and Redistribution.\\n\\n
|
|
||||||
\ a. Grant of Rights. You are granted a non-exclusive, worldwide, \\nnon-transferable
|
|
||||||
and royalty-free limited license under Meta\u2019s intellectual property or
|
|
||||||
other rights \\nowned by Meta embodied in the Llama Materials to use, reproduce,
|
|
||||||
distribute, copy, create derivative works \\nof, and make modifications to the
|
|
||||||
Llama Materials. \\n\\n b. Redistribution and Use. \\n\\n i. If
|
|
||||||
you distribute or make available the Llama Materials (or any derivative works
|
|
||||||
thereof), \\nor a product or service (including another AI model) that contains
|
|
||||||
any of them, you shall (A) provide\\na copy of this Agreement with any such
|
|
||||||
Llama Materials; and (B) prominently display \u201CBuilt with Llama\u201D\\non
|
|
||||||
a related website, user interface, blogpost, about page, or product documentation.
|
|
||||||
If you use the\\nLlama Materials or any outputs or results of the Llama Materials
|
|
||||||
to create, train, fine tune, or\\notherwise improve an AI model, which is distributed
|
|
||||||
or made available, you shall also include \u201CLlama\u201D\\nat the beginning
|
|
||||||
of any such AI model name.\\n\\n ii. If you receive Llama Materials,
|
|
||||||
or any derivative works thereof, from a Licensee as part\\nof an integrated
|
|
||||||
end user product, then Section 2 of this Agreement will not apply to you. \\n\\n
|
|
||||||
\ iii. You must retain in all copies of the Llama Materials that you distribute
|
|
||||||
the \\nfollowing attribution notice within a \u201CNotice\u201D text file distributed
|
|
||||||
as a part of such copies: \\n\u201CLlama 3.2 is licensed under the Llama 3.2
|
|
||||||
Community License, Copyright \xA9 Meta Platforms,\\nInc. All Rights Reserved.\u201D\\n\\n
|
|
||||||
\ iv. Your use of the Llama Materials must comply with applicable laws
|
|
||||||
and regulations\\n(including trade compliance laws and regulations) and adhere
|
|
||||||
to the Acceptable Use Policy for\\nthe Llama Materials (available at https://www.llama.com/llama3_2/use-policy),
|
|
||||||
which is hereby \\nincorporated by reference into this Agreement.\\n \\n2.
|
|
||||||
Additional Commercial Terms. If, on the Llama 3.2 version release date, the
|
|
||||||
monthly active users\\nof the products or services made available by or for
|
|
||||||
Licensee, or Licensee\u2019s affiliates, \\nis greater than 700 million monthly
|
|
||||||
active users in the preceding calendar month, you must request \\na license
|
|
||||||
from Meta, which Meta may grant to you in its sole discretion, and you are not
|
|
||||||
authorized to\\nexercise any of the rights under this Agreement unless or until
|
|
||||||
Meta otherwise expressly grants you such rights.\\n\\n3. Disclaimer of Warranty.
|
|
||||||
UNLESS REQUIRED BY APPLICABLE LAW, THE LLAMA MATERIALS AND ANY OUTPUT AND \\nRESULTS
|
|
||||||
THEREFROM ARE PROVIDED ON AN \u201CAS IS\u201D BASIS, WITHOUT WARRANTIES OF
|
|
||||||
ANY KIND, AND META DISCLAIMS\\nALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND
|
|
||||||
IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES\\nOF TITLE, NON-INFRINGEMENT,
|
|
||||||
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE\\nFOR
|
|
||||||
DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE LLAMA MATERIALS
|
|
||||||
AND ASSUME ANY RISKS ASSOCIATED\\nWITH YOUR USE OF THE LLAMA MATERIALS AND ANY
|
|
||||||
OUTPUT AND RESULTS.\\n\\n4. Limitation of Liability. IN NO EVENT WILL META OR
|
|
||||||
ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, \\nWHETHER IN CONTRACT,
|
|
||||||
TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT,
|
|
||||||
\\nFOR ANY LOST PROFITS OR ANY INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL,
|
|
||||||
EXEMPLARY OR PUNITIVE DAMAGES, EVEN \\nIF META OR ITS AFFILIATES HAVE BEEN ADVISED
|
|
||||||
OF THE POSSIBILITY OF ANY OF THE FOREGOING.\\n\\n5. Intellectual Property.\\n\\n
|
|
||||||
\ a. No trademark licenses are granted under this Agreement, and in connection
|
|
||||||
with the Llama Materials, \\nneither Meta nor Licensee may use any name or mark
|
|
||||||
owned by or associated with the other or any of its affiliates, \\nexcept as
|
|
||||||
required for reasonable and customary use in describing and redistributing the
|
|
||||||
Llama Materials or as \\nset forth in this Section 5(a). Meta hereby grants
|
|
||||||
you a license to use \u201CLlama\u201D (the \u201CMark\u201D) solely as required
|
|
||||||
\\nto comply with the last sentence of Section 1.b.i. You will comply with Meta\u2019s
|
|
||||||
brand guidelines (currently accessible \\nat https://about.meta.com/brand/resources/meta/company-brand/).
|
|
||||||
All goodwill arising out of your use of the Mark \\nwill inure to the benefit
|
|
||||||
of Meta.\\n\\n b. Subject to Meta\u2019s ownership of Llama Materials and
|
|
||||||
derivatives made by or for Meta, with respect to any\\n derivative works
|
|
||||||
and modifications of the Llama Materials that are made by you, as between you
|
|
||||||
and Meta,\\n you are and will be the owner of such derivative works and modifications.\\n\\n
|
|
||||||
\ c. If you institute litigation or other proceedings against Meta or any
|
|
||||||
entity (including a cross-claim or\\n counterclaim in a lawsuit) alleging
|
|
||||||
that the Llama Materials or Llama 3.2 outputs or results, or any portion\\n
|
|
||||||
\ of any of the foregoing, constitutes infringement of intellectual property
|
|
||||||
or other rights owned or licensable\\n by you, then any licenses granted
|
|
||||||
to you under this Agreement shall terminate as of the date such litigation or\\n
|
|
||||||
\ claim is filed or instituted. You will indemnify and hold harmless Meta
|
|
||||||
from and against any claim by any third\\n party arising out of or related
|
|
||||||
to your use or distribution of the Llama Materials.\\n\\n6. Term and Termination.
|
|
||||||
The term of this Agreement will commence upon your acceptance of this Agreement
|
|
||||||
or access\\nto the Llama Materials and will continue in full force and effect
|
|
||||||
until terminated in accordance with the terms\\nand conditions herein. Meta
|
|
||||||
may terminate this Agreement if you are in breach of any term or condition of
|
|
||||||
this\\nAgreement. Upon termination of this Agreement, you shall delete and cease
|
|
||||||
use of the Llama Materials. Sections 3,\\n4 and 7 shall survive the termination
|
|
||||||
of this Agreement. \\n\\n7. Governing Law and Jurisdiction. This Agreement will
|
|
||||||
be governed and construed under the laws of the State of \\nCalifornia without
|
|
||||||
regard to choice of law principles, and the UN Convention on Contracts for the
|
|
||||||
International\\nSale of Goods does not apply to this Agreement. The courts of
|
|
||||||
California shall have exclusive jurisdiction of\\nany dispute arising out of
|
|
||||||
this Agreement.\\n**Llama 3.2** **Acceptable Use Policy**\\n\\nMeta is committed
|
|
||||||
to promoting safe and fair use of its tools and features, including Llama 3.2.
|
|
||||||
If you access or use Llama 3.2, you agree to this Acceptable Use Policy (\u201C**Policy**\u201D).
|
|
||||||
The most recent copy of this policy can be found at [https://www.llama.com/llama3_2/use-policy](https://www.llama.com/llama3_2/use-policy).\\n\\n**Prohibited
|
|
||||||
Uses**\\n\\nWe want everyone to use Llama 3.2 safely and responsibly. You agree
|
|
||||||
you will not use, or allow others to use, Llama 3.2 to:\\n\\n\\n\\n1. Violate
|
|
||||||
the law or others\u2019 rights, including to:\\n 1. Engage in, promote, generate,
|
|
||||||
contribute to, encourage, plan, incite, or further illegal or unlawful activity
|
|
||||||
or content, such as:\\n 1. Violence or terrorism\\n 2. Exploitation
|
|
||||||
or harm to children, including the solicitation, creation, acquisition, or dissemination
|
|
||||||
of child exploitative content or failure to report Child Sexual Abuse Material\\n
|
|
||||||
\ 3. Human trafficking, exploitation, and sexual violence\\n 4.
|
|
||||||
The illegal distribution of information or materials to minors, including obscene
|
|
||||||
materials, or failure to employ legally required age-gating in connection with
|
|
||||||
such information or materials.\\n 5. Sexual solicitation\\n 6.
|
|
||||||
Any other criminal activity\\n 1. Engage in, promote, incite, or facilitate
|
|
||||||
the harassment, abuse, threatening, or bullying of individuals or groups of
|
|
||||||
individuals\\n 2. Engage in, promote, incite, or facilitate discrimination
|
|
||||||
or other unlawful or harmful conduct in the provision of employment, employment
|
|
||||||
benefits, credit, housing, other economic benefits, or other essential goods
|
|
||||||
and services\\n 3. Engage in the unauthorized or unlicensed practice of any
|
|
||||||
profession including, but not limited to, financial, legal, medical/health,
|
|
||||||
or related professional practices\\n 4. Collect, process, disclose, generate,
|
|
||||||
or infer private or sensitive information about individuals, including information
|
|
||||||
about individuals\u2019 identity, health, or demographic information, unless
|
|
||||||
you have obtained the right to do so in accordance with applicable law\\n 5.
|
|
||||||
Engage in or facilitate any action or generate any content that infringes, misappropriates,
|
|
||||||
or otherwise violates any third-party rights, including the outputs or results
|
|
||||||
of any products or services using the Llama Materials\\n 6. Create, generate,
|
|
||||||
or facilitate the creation of malicious code, malware, computer viruses or do
|
|
||||||
anything else that could disable, overburden, interfere with or impair the proper
|
|
||||||
working, integrity, operation or appearance of a website or computer system\\n
|
|
||||||
\ 7. Engage in any action, or facilitate any action, to intentionally circumvent
|
|
||||||
or remove usage restrictions or other safety measures, or to enable functionality
|
|
||||||
disabled by Meta\\n2. Engage in, promote, incite, facilitate, or assist in the
|
|
||||||
planning or development of activities that present a risk of death or bodily
|
|
||||||
harm to individuals, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 8. Military, warfare, nuclear industries or applications, espionage, use
|
|
||||||
for materials or activities that are subject to the International Traffic Arms
|
|
||||||
Regulations (ITAR) maintained by the United States Department of State or to
|
|
||||||
the U.S. Biological Weapons Anti-Terrorism Act of 1989 or the Chemical Weapons
|
|
||||||
Convention Implementation Act of 1997\\n 9. Guns and illegal weapons (including
|
|
||||||
weapon development)\\n 10. Illegal drugs and regulated/controlled substances\\n
|
|
||||||
\ 11. Operation of critical infrastructure, transportation technologies, or
|
|
||||||
heavy machinery\\n 12. Self-harm or harm to others, including suicide, cutting,
|
|
||||||
and eating disorders\\n 13. Any content intended to incite or promote violence,
|
|
||||||
abuse, or any infliction of bodily harm to an individual\\n3. Intentionally
|
|
||||||
deceive or mislead others, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 14. Generating, promoting, or furthering fraud or the creation or promotion
|
|
||||||
of disinformation\\n 15. Generating, promoting, or furthering defamatory
|
|
||||||
content, including the creation of defamatory statements, images, or other content\\n
|
|
||||||
\ 16. Generating, promoting, or further distributing spam\\n 17. Impersonating
|
|
||||||
another individual without consent, authorization, or legal right\\n 18.
|
|
||||||
Representing that the use of Llama 3.2 or outputs are human-generated\\n 19.
|
|
||||||
Generating or facilitating false online engagement, including fake reviews and
|
|
||||||
other means of fake online engagement\\n4. Fail to appropriately disclose to
|
|
||||||
end users any known dangers of your AI system\\n5. Interact with third party
|
|
||||||
tools, models, or software designed to generate unlawful content or engage in
|
|
||||||
unlawful or harmful conduct and/or represent that the outputs of such tools,
|
|
||||||
models, or software are associated with Meta or Llama 3.2\\n\\nWith respect
|
|
||||||
to any multimodal models included in Llama 3.2, the rights granted under Section
|
|
||||||
1(a) of the Llama 3.2 Community License Agreement are not being granted to you
|
|
||||||
if you are an individual domiciled in, or a company with a principal place of
|
|
||||||
business in, the European Union. This restriction does not apply to end users
|
|
||||||
of a product or service that incorporates any such multimodal models.\\n\\nPlease
|
|
||||||
report any violation of this Policy, software \u201Cbug,\u201D or other problems
|
|
||||||
that could lead to a violation of this Policy through one of the following means:\\n\\n\\n\\n*
|
|
||||||
Reporting issues with the model: [https://github.com/meta-llama/llama-models/issues](https://l.workplace.com/l.php?u=https%3A%2F%2Fgithub.com%2Fmeta-llama%2Fllama-models%2Fissues\\u0026h=AT0qV8W9BFT6NwihiOHRuKYQM_UnkzN_NmHMy91OT55gkLpgi4kQupHUl0ssR4dQsIQ8n3tfd0vtkobvsEvt1l4Ic6GXI2EeuHV8N08OG2WnbAmm0FL4ObkazC6G_256vN0lN9DsykCvCqGZ)\\n*
|
|
||||||
Reporting risky content generated by the model: [developers.facebook.com/llama_output_feedback](http://developers.facebook.com/llama_output_feedback)\\n*
|
|
||||||
Reporting bugs and security concerns: [facebook.com/whitehat/info](http://facebook.com/whitehat/info)\\n*
|
|
||||||
Reporting violations of the Acceptable Use Policy or unlicensed uses of Llama
|
|
||||||
3.2: LlamaUseReport@meta.com\",\"modelfile\":\"# Modelfile generated by \\\"ollama
|
|
||||||
show\\\"\\n# To build a new Modelfile based on this, replace FROM with:\\n#
|
|
||||||
FROM llama3.2:3b\\n\\nFROM /Users/joaomoura/.ollama/models/blobs/sha256-dde5aa3fc5ffc17176b5e8bdc82f587b24b2678c6c66101bf7da77af9f7ccdff\\nTEMPLATE
|
|
||||||
\\\"\\\"\\\"\\u003c|start_header_id|\\u003esystem\\u003c|end_header_id|\\u003e\\n\\nCutting
|
|
||||||
Knowledge Date: December 2023\\n\\n{{ if .System }}{{ .System }}\\n{{- end }}\\n{{-
|
|
||||||
if .Tools }}When you receive a tool call response, use the output to format
|
|
||||||
an answer to the orginal user question.\\n\\nYou are a helpful assistant with
|
|
||||||
tool calling capabilities.\\n{{- end }}\\u003c|eot_id|\\u003e\\n{{- range $i,
|
|
||||||
$_ := .Messages }}\\n{{- $last := eq (len (slice $.Messages $i)) 1 }}\\n{{-
|
|
||||||
if eq .Role \\\"user\\\" }}\\u003c|start_header_id|\\u003euser\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if and $.Tools $last }}\\n\\nGiven the following functions, please respond with
|
|
||||||
a JSON for a function call with its proper arguments that best answers the given
|
|
||||||
prompt.\\n\\nRespond in the format {\\\"name\\\": function name, \\\"parameters\\\":
|
|
||||||
dictionary of argument name and its value}. Do not use variables.\\n\\n{{ range
|
|
||||||
$.Tools }}\\n{{- . }}\\n{{ end }}\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{-
|
|
||||||
else }}\\n\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{- end }}{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- else if eq .Role \\\"assistant\\\" }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if .ToolCalls }}\\n{{ range .ToolCalls }}\\n{\\\"name\\\": \\\"{{ .Function.Name
|
|
||||||
}}\\\", \\\"parameters\\\": {{ .Function.Arguments }}}{{ end }}\\n{{- else }}\\n\\n{{
|
|
||||||
.Content }}\\n{{- end }}{{ if not $last }}\\u003c|eot_id|\\u003e{{ end }}\\n{{-
|
|
||||||
else if eq .Role \\\"tool\\\" }}\\u003c|start_header_id|\\u003eipython\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
.Content }}\\u003c|eot_id|\\u003e{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- end }}\\n{{- end }}\\\"\\\"\\\"\\nPARAMETER stop \\u003c|start_header_id|\\u003e\\nPARAMETER
|
|
||||||
stop \\u003c|end_header_id|\\u003e\\nPARAMETER stop \\u003c|eot_id|\\u003e\\nLICENSE
|
|
||||||
\\\"LLAMA 3.2 COMMUNITY LICENSE AGREEMENT\\nLlama 3.2 Version Release Date:
|
|
||||||
September 25, 2024\\n\\n\u201CAgreement\u201D means the terms and conditions
|
|
||||||
for use, reproduction, distribution \\nand modification of the Llama Materials
|
|
||||||
set forth herein.\\n\\n\u201CDocumentation\u201D means the specifications, manuals
|
|
||||||
and documentation accompanying Llama 3.2\\ndistributed by Meta at https://llama.meta.com/doc/overview.\\n\\n\u201CLicensee\u201D
|
|
||||||
or \u201Cyou\u201D means you, or your employer or any other person or entity
|
|
||||||
(if you are \\nentering into this Agreement on such person or entity\u2019s
|
|
||||||
behalf), of the age required under\\napplicable laws, rules or regulations to
|
|
||||||
provide legal consent and that has legal authority\\nto bind your employer or
|
|
||||||
such other person or entity if you are entering in this Agreement\\non their
|
|
||||||
behalf.\\n\\n\u201CLlama 3.2\u201D means the foundational large language models
|
|
||||||
and software and algorithms, including\\nmachine-learning model code, trained
|
|
||||||
model weights, inference-enabling code, training-enabling code,\\nfine-tuning
|
|
||||||
enabling code and other elements of the foregoing distributed by Meta at \\nhttps://www.llama.com/llama-downloads.\\n\\n\u201CLlama
|
|
||||||
Materials\u201D means, collectively, Meta\u2019s proprietary Llama 3.2 and Documentation
|
|
||||||
(and \\nany portion thereof) made available under this Agreement.\\n\\n\u201CMeta\u201D
|
|
||||||
or \u201Cwe\u201D means Meta Platforms Ireland Limited (if you are located in
|
|
||||||
or, \\nif you are an entity, your principal place of business is in the EEA
|
|
||||||
or Switzerland) \\nand Meta Platforms, Inc. (if you are located outside of the
|
|
||||||
EEA or Switzerland). \\n\\n\\nBy clicking \u201CI Accept\u201D below or by using
|
|
||||||
or distributing any portion or element of the Llama Materials,\\nyou agree to
|
|
||||||
be bound by this Agreement.\\n\\n\\n1. License Rights and Redistribution.\\n\\n
|
|
||||||
\ a. Grant of Rights. You are granted a non-exclusive, worldwide, \\nnon-transferable
|
|
||||||
and royalty-free limited license under Meta\u2019s intellectual property or
|
|
||||||
other rights \\nowned by Meta embodied in the Llama Materials to use, reproduce,
|
|
||||||
distribute, copy, create derivative works \\nof, and make modifications to the
|
|
||||||
Llama Materials. \\n\\n b. Redistribution and Use. \\n\\n i. If
|
|
||||||
you distribute or make available the Llama Materials (or any derivative works
|
|
||||||
thereof), \\nor a product or service (including another AI model) that contains
|
|
||||||
any of them, you shall (A) provide\\na copy of this Agreement with any such
|
|
||||||
Llama Materials; and (B) prominently display \u201CBuilt with Llama\u201D\\non
|
|
||||||
a related website, user interface, blogpost, about page, or product documentation.
|
|
||||||
If you use the\\nLlama Materials or any outputs or results of the Llama Materials
|
|
||||||
to create, train, fine tune, or\\notherwise improve an AI model, which is distributed
|
|
||||||
or made available, you shall also include \u201CLlama\u201D\\nat the beginning
|
|
||||||
of any such AI model name.\\n\\n ii. If you receive Llama Materials,
|
|
||||||
or any derivative works thereof, from a Licensee as part\\nof an integrated
|
|
||||||
end user product, then Section 2 of this Agreement will not apply to you. \\n\\n
|
|
||||||
\ iii. You must retain in all copies of the Llama Materials that you distribute
|
|
||||||
the \\nfollowing attribution notice within a \u201CNotice\u201D text file distributed
|
|
||||||
as a part of such copies: \\n\u201CLlama 3.2 is licensed under the Llama 3.2
|
|
||||||
Community License, Copyright \xA9 Meta Platforms,\\nInc. All Rights Reserved.\u201D\\n\\n
|
|
||||||
\ iv. Your use of the Llama Materials must comply with applicable laws
|
|
||||||
and regulations\\n(including trade compliance laws and regulations) and adhere
|
|
||||||
to the Acceptable Use Policy for\\nthe Llama Materials (available at https://www.llama.com/llama3_2/use-policy),
|
|
||||||
which is hereby \\nincorporated by reference into this Agreement.\\n \\n2.
|
|
||||||
Additional Commercial Terms. If, on the Llama 3.2 version release date, the
|
|
||||||
monthly active users\\nof the products or services made available by or for
|
|
||||||
Licensee, or Licensee\u2019s affiliates, \\nis greater than 700 million monthly
|
|
||||||
active users in the preceding calendar month, you must request \\na license
|
|
||||||
from Meta, which Meta may grant to you in its sole discretion, and you are not
|
|
||||||
authorized to\\nexercise any of the rights under this Agreement unless or until
|
|
||||||
Meta otherwise expressly grants you such rights.\\n\\n3. Disclaimer of Warranty.
|
|
||||||
UNLESS REQUIRED BY APPLICABLE LAW, THE LLAMA MATERIALS AND ANY OUTPUT AND \\nRESULTS
|
|
||||||
THEREFROM ARE PROVIDED ON AN \u201CAS IS\u201D BASIS, WITHOUT WARRANTIES OF
|
|
||||||
ANY KIND, AND META DISCLAIMS\\nALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND
|
|
||||||
IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES\\nOF TITLE, NON-INFRINGEMENT,
|
|
||||||
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE\\nFOR
|
|
||||||
DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE LLAMA MATERIALS
|
|
||||||
AND ASSUME ANY RISKS ASSOCIATED\\nWITH YOUR USE OF THE LLAMA MATERIALS AND ANY
|
|
||||||
OUTPUT AND RESULTS.\\n\\n4. Limitation of Liability. IN NO EVENT WILL META OR
|
|
||||||
ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, \\nWHETHER IN CONTRACT,
|
|
||||||
TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT,
|
|
||||||
\\nFOR ANY LOST PROFITS OR ANY INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL,
|
|
||||||
EXEMPLARY OR PUNITIVE DAMAGES, EVEN \\nIF META OR ITS AFFILIATES HAVE BEEN ADVISED
|
|
||||||
OF THE POSSIBILITY OF ANY OF THE FOREGOING.\\n\\n5. Intellectual Property.\\n\\n
|
|
||||||
\ a. No trademark licenses are granted under this Agreement, and in connection
|
|
||||||
with the Llama Materials, \\nneither Meta nor Licensee may use any name or mark
|
|
||||||
owned by or associated with the other or any of its affiliates, \\nexcept as
|
|
||||||
required for reasonable and customary use in describing and redistributing the
|
|
||||||
Llama Materials or as \\nset forth in this Section 5(a). Meta hereby grants
|
|
||||||
you a license to use \u201CLlama\u201D (the \u201CMark\u201D) solely as required
|
|
||||||
\\nto comply with the last sentence of Section 1.b.i. You will comply with Meta\u2019s
|
|
||||||
brand guidelines (currently accessible \\nat https://about.meta.com/brand/resources/meta/company-brand/).
|
|
||||||
All goodwill arising out of your use of the Mark \\nwill inure to the benefit
|
|
||||||
of Meta.\\n\\n b. Subject to Meta\u2019s ownership of Llama Materials and
|
|
||||||
derivatives made by or for Meta, with respect to any\\n derivative works
|
|
||||||
and modifications of the Llama Materials that are made by you, as between you
|
|
||||||
and Meta,\\n you are and will be the owner of such derivative works and modifications.\\n\\n
|
|
||||||
\ c. If you institute litigation or other proceedings against Meta or any
|
|
||||||
entity (including a cross-claim or\\n counterclaim in a lawsuit) alleging
|
|
||||||
that the Llama Materials or Llama 3.2 outputs or results, or any portion\\n
|
|
||||||
\ of any of the foregoing, constitutes infringement of intellectual property
|
|
||||||
or other rights owned or licensable\\n by you, then any licenses granted
|
|
||||||
to you under this Agreement shall terminate as of the date such litigation or\\n
|
|
||||||
\ claim is filed or instituted. You will indemnify and hold harmless Meta
|
|
||||||
from and against any claim by any third\\n party arising out of or related
|
|
||||||
to your use or distribution of the Llama Materials.\\n\\n6. Term and Termination.
|
|
||||||
The term of this Agreement will commence upon your acceptance of this Agreement
|
|
||||||
or access\\nto the Llama Materials and will continue in full force and effect
|
|
||||||
until terminated in accordance with the terms\\nand conditions herein. Meta
|
|
||||||
may terminate this Agreement if you are in breach of any term or condition of
|
|
||||||
this\\nAgreement. Upon termination of this Agreement, you shall delete and cease
|
|
||||||
use of the Llama Materials. Sections 3,\\n4 and 7 shall survive the termination
|
|
||||||
of this Agreement. \\n\\n7. Governing Law and Jurisdiction. This Agreement will
|
|
||||||
be governed and construed under the laws of the State of \\nCalifornia without
|
|
||||||
regard to choice of law principles, and the UN Convention on Contracts for the
|
|
||||||
International\\nSale of Goods does not apply to this Agreement. The courts of
|
|
||||||
California shall have exclusive jurisdiction of\\nany dispute arising out of
|
|
||||||
this Agreement.\\\"\\nLICENSE \\\"**Llama 3.2** **Acceptable Use Policy**\\n\\nMeta
|
|
||||||
is committed to promoting safe and fair use of its tools and features, including
|
|
||||||
Llama 3.2. If you access or use Llama 3.2, you agree to this Acceptable Use
|
|
||||||
Policy (\u201C**Policy**\u201D). The most recent copy of this policy can be
|
|
||||||
found at [https://www.llama.com/llama3_2/use-policy](https://www.llama.com/llama3_2/use-policy).\\n\\n**Prohibited
|
|
||||||
Uses**\\n\\nWe want everyone to use Llama 3.2 safely and responsibly. You agree
|
|
||||||
you will not use, or allow others to use, Llama 3.2 to:\\n\\n\\n\\n1. Violate
|
|
||||||
the law or others\u2019 rights, including to:\\n 1. Engage in, promote, generate,
|
|
||||||
contribute to, encourage, plan, incite, or further illegal or unlawful activity
|
|
||||||
or content, such as:\\n 1. Violence or terrorism\\n 2. Exploitation
|
|
||||||
or harm to children, including the solicitation, creation, acquisition, or dissemination
|
|
||||||
of child exploitative content or failure to report Child Sexual Abuse Material\\n
|
|
||||||
\ 3. Human trafficking, exploitation, and sexual violence\\n 4.
|
|
||||||
The illegal distribution of information or materials to minors, including obscene
|
|
||||||
materials, or failure to employ legally required age-gating in connection with
|
|
||||||
such information or materials.\\n 5. Sexual solicitation\\n 6.
|
|
||||||
Any other criminal activity\\n 1. Engage in, promote, incite, or facilitate
|
|
||||||
the harassment, abuse, threatening, or bullying of individuals or groups of
|
|
||||||
individuals\\n 2. Engage in, promote, incite, or facilitate discrimination
|
|
||||||
or other unlawful or harmful conduct in the provision of employment, employment
|
|
||||||
benefits, credit, housing, other economic benefits, or other essential goods
|
|
||||||
and services\\n 3. Engage in the unauthorized or unlicensed practice of any
|
|
||||||
profession including, but not limited to, financial, legal, medical/health,
|
|
||||||
or related professional practices\\n 4. Collect, process, disclose, generate,
|
|
||||||
or infer private or sensitive information about individuals, including information
|
|
||||||
about individuals\u2019 identity, health, or demographic information, unless
|
|
||||||
you have obtained the right to do so in accordance with applicable law\\n 5.
|
|
||||||
Engage in or facilitate any action or generate any content that infringes, misappropriates,
|
|
||||||
or otherwise violates any third-party rights, including the outputs or results
|
|
||||||
of any products or services using the Llama Materials\\n 6. Create, generate,
|
|
||||||
or facilitate the creation of malicious code, malware, computer viruses or do
|
|
||||||
anything else that could disable, overburden, interfere with or impair the proper
|
|
||||||
working, integrity, operation or appearance of a website or computer system\\n
|
|
||||||
\ 7. Engage in any action, or facilitate any action, to intentionally circumvent
|
|
||||||
or remove usage restrictions or other safety measures, or to enable functionality
|
|
||||||
disabled by Meta\\n2. Engage in, promote, incite, facilitate, or assist in the
|
|
||||||
planning or development of activities that present a risk of death or bodily
|
|
||||||
harm to individuals, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 8. Military, warfare, nuclear industries or applications, espionage, use
|
|
||||||
for materials or activities that are subject to the International Traffic Arms
|
|
||||||
Regulations (ITAR) maintained by the United States Department of State or to
|
|
||||||
the U.S. Biological Weapons Anti-Terrorism Act of 1989 or the Chemical Weapons
|
|
||||||
Convention Implementation Act of 1997\\n 9. Guns and illegal weapons (including
|
|
||||||
weapon development)\\n 10. Illegal drugs and regulated/controlled substances\\n
|
|
||||||
\ 11. Operation of critical infrastructure, transportation technologies, or
|
|
||||||
heavy machinery\\n 12. Self-harm or harm to others, including suicide, cutting,
|
|
||||||
and eating disorders\\n 13. Any content intended to incite or promote violence,
|
|
||||||
abuse, or any infliction of bodily harm to an individual\\n3. Intentionally
|
|
||||||
deceive or mislead others, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 14. Generating, promoting, or furthering fraud or the creation or promotion
|
|
||||||
of disinformation\\n 15. Generating, promoting, or furthering defamatory
|
|
||||||
content, including the creation of defamatory statements, images, or other content\\n
|
|
||||||
\ 16. Generating, promoting, or further distributing spam\\n 17. Impersonating
|
|
||||||
another individual without consent, authorization, or legal right\\n 18.
|
|
||||||
Representing that the use of Llama 3.2 or outputs are human-generated\\n 19.
|
|
||||||
Generating or facilitating false online engagement, including fake reviews and
|
|
||||||
other means of fake online engagement\\n4. Fail to appropriately disclose to
|
|
||||||
end users any known dangers of your AI system\\n5. Interact with third party
|
|
||||||
tools, models, or software designed to generate unlawful content or engage in
|
|
||||||
unlawful or harmful conduct and/or represent that the outputs of such tools,
|
|
||||||
models, or software are associated with Meta or Llama 3.2\\n\\nWith respect
|
|
||||||
to any multimodal models included in Llama 3.2, the rights granted under Section
|
|
||||||
1(a) of the Llama 3.2 Community License Agreement are not being granted to you
|
|
||||||
if you are an individual domiciled in, or a company with a principal place of
|
|
||||||
business in, the European Union. This restriction does not apply to end users
|
|
||||||
of a product or service that incorporates any such multimodal models.\\n\\nPlease
|
|
||||||
report any violation of this Policy, software \u201Cbug,\u201D or other problems
|
|
||||||
that could lead to a violation of this Policy through one of the following means:\\n\\n\\n\\n*
|
|
||||||
Reporting issues with the model: [https://github.com/meta-llama/llama-models/issues](https://l.workplace.com/l.php?u=https%3A%2F%2Fgithub.com%2Fmeta-llama%2Fllama-models%2Fissues\\u0026h=AT0qV8W9BFT6NwihiOHRuKYQM_UnkzN_NmHMy91OT55gkLpgi4kQupHUl0ssR4dQsIQ8n3tfd0vtkobvsEvt1l4Ic6GXI2EeuHV8N08OG2WnbAmm0FL4ObkazC6G_256vN0lN9DsykCvCqGZ)\\n*
|
|
||||||
Reporting risky content generated by the model: [developers.facebook.com/llama_output_feedback](http://developers.facebook.com/llama_output_feedback)\\n*
|
|
||||||
Reporting bugs and security concerns: [facebook.com/whitehat/info](http://facebook.com/whitehat/info)\\n*
|
|
||||||
Reporting violations of the Acceptable Use Policy or unlicensed uses of Llama
|
|
||||||
3.2: LlamaUseReport@meta.com\\\"\\n\",\"parameters\":\"stop \\\"\\u003c|start_header_id|\\u003e\\\"\\nstop
|
|
||||||
\ \\\"\\u003c|end_header_id|\\u003e\\\"\\nstop \\\"\\u003c|eot_id|\\u003e\\\"\",\"template\":\"\\u003c|start_header_id|\\u003esystem\\u003c|end_header_id|\\u003e\\n\\nCutting
|
|
||||||
Knowledge Date: December 2023\\n\\n{{ if .System }}{{ .System }}\\n{{- end }}\\n{{-
|
|
||||||
if .Tools }}When you receive a tool call response, use the output to format
|
|
||||||
an answer to the orginal user question.\\n\\nYou are a helpful assistant with
|
|
||||||
tool calling capabilities.\\n{{- end }}\\u003c|eot_id|\\u003e\\n{{- range $i,
|
|
||||||
$_ := .Messages }}\\n{{- $last := eq (len (slice $.Messages $i)) 1 }}\\n{{-
|
|
||||||
if eq .Role \\\"user\\\" }}\\u003c|start_header_id|\\u003euser\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if and $.Tools $last }}\\n\\nGiven the following functions, please respond with
|
|
||||||
a JSON for a function call with its proper arguments that best answers the given
|
|
||||||
prompt.\\n\\nRespond in the format {\\\"name\\\": function name, \\\"parameters\\\":
|
|
||||||
dictionary of argument name and its value}. Do not use variables.\\n\\n{{ range
|
|
||||||
$.Tools }}\\n{{- . }}\\n{{ end }}\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{-
|
|
||||||
else }}\\n\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{- end }}{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- else if eq .Role \\\"assistant\\\" }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if .ToolCalls }}\\n{{ range .ToolCalls }}\\n{\\\"name\\\": \\\"{{ .Function.Name
|
|
||||||
}}\\\", \\\"parameters\\\": {{ .Function.Arguments }}}{{ end }}\\n{{- else }}\\n\\n{{
|
|
||||||
.Content }}\\n{{- end }}{{ if not $last }}\\u003c|eot_id|\\u003e{{ end }}\\n{{-
|
|
||||||
else if eq .Role \\\"tool\\\" }}\\u003c|start_header_id|\\u003eipython\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
.Content }}\\u003c|eot_id|\\u003e{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- end }}\\n{{- end }}\",\"details\":{\"parent_model\":\"\",\"format\":\"gguf\",\"family\":\"llama\",\"families\":[\"llama\"],\"parameter_size\":\"3.2B\",\"quantization_level\":\"Q4_K_M\"},\"model_info\":{\"general.architecture\":\"llama\",\"general.basename\":\"Llama-3.2\",\"general.file_type\":15,\"general.finetune\":\"Instruct\",\"general.languages\":[\"en\",\"de\",\"fr\",\"it\",\"pt\",\"hi\",\"es\",\"th\"],\"general.parameter_count\":3212749888,\"general.quantization_version\":2,\"general.size_label\":\"3B\",\"general.tags\":[\"facebook\",\"meta\",\"pytorch\",\"llama\",\"llama-3\",\"text-generation\"],\"general.type\":\"model\",\"llama.attention.head_count\":24,\"llama.attention.head_count_kv\":8,\"llama.attention.key_length\":128,\"llama.attention.layer_norm_rms_epsilon\":0.00001,\"llama.attention.value_length\":128,\"llama.block_count\":28,\"llama.context_length\":131072,\"llama.embedding_length\":3072,\"llama.feed_forward_length\":8192,\"llama.rope.dimension_count\":128,\"llama.rope.freq_base\":500000,\"llama.vocab_size\":128256,\"tokenizer.ggml.bos_token_id\":128000,\"tokenizer.ggml.eos_token_id\":128009,\"tokenizer.ggml.merges\":null,\"tokenizer.ggml.model\":\"gpt2\",\"tokenizer.ggml.pre\":\"llama-bpe\",\"tokenizer.ggml.token_type\":null,\"tokenizer.ggml.tokens\":null},\"modified_at\":\"2025-02-20T18:55:09.150577031-08:00\"}"
|
|
||||||
headers:
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Date:
|
|
||||||
- Fri, 21 Feb 2025 02:57:55 GMT
|
|
||||||
Transfer-Encoding:
|
|
||||||
- chunked
|
|
||||||
http_version: HTTP/1.1
|
|
||||||
status_code: 200
|
|
||||||
- request:
|
|
||||||
body: '{"name": "llama3.2:3b"}'
|
|
||||||
headers:
|
|
||||||
accept:
|
|
||||||
- '*/*'
|
|
||||||
accept-encoding:
|
|
||||||
- gzip, deflate
|
|
||||||
connection:
|
|
||||||
- keep-alive
|
|
||||||
content-length:
|
|
||||||
- '23'
|
|
||||||
content-type:
|
|
||||||
- application/json
|
|
||||||
host:
|
|
||||||
- localhost:11434
|
|
||||||
user-agent:
|
|
||||||
- litellm/1.60.2
|
|
||||||
method: POST
|
|
||||||
uri: http://localhost:11434/api/show
|
|
||||||
response:
|
|
||||||
content: "{\"license\":\"LLAMA 3.2 COMMUNITY LICENSE AGREEMENT\\nLlama 3.2 Version
|
|
||||||
Release Date: September 25, 2024\\n\\n\u201CAgreement\u201D means the terms
|
|
||||||
and conditions for use, reproduction, distribution \\nand modification of the
|
|
||||||
Llama Materials set forth herein.\\n\\n\u201CDocumentation\u201D means the specifications,
|
|
||||||
manuals and documentation accompanying Llama 3.2\\ndistributed by Meta at https://llama.meta.com/doc/overview.\\n\\n\u201CLicensee\u201D
|
|
||||||
or \u201Cyou\u201D means you, or your employer or any other person or entity
|
|
||||||
(if you are \\nentering into this Agreement on such person or entity\u2019s
|
|
||||||
behalf), of the age required under\\napplicable laws, rules or regulations to
|
|
||||||
provide legal consent and that has legal authority\\nto bind your employer or
|
|
||||||
such other person or entity if you are entering in this Agreement\\non their
|
|
||||||
behalf.\\n\\n\u201CLlama 3.2\u201D means the foundational large language models
|
|
||||||
and software and algorithms, including\\nmachine-learning model code, trained
|
|
||||||
model weights, inference-enabling code, training-enabling code,\\nfine-tuning
|
|
||||||
enabling code and other elements of the foregoing distributed by Meta at \\nhttps://www.llama.com/llama-downloads.\\n\\n\u201CLlama
|
|
||||||
Materials\u201D means, collectively, Meta\u2019s proprietary Llama 3.2 and Documentation
|
|
||||||
(and \\nany portion thereof) made available under this Agreement.\\n\\n\u201CMeta\u201D
|
|
||||||
or \u201Cwe\u201D means Meta Platforms Ireland Limited (if you are located in
|
|
||||||
or, \\nif you are an entity, your principal place of business is in the EEA
|
|
||||||
or Switzerland) \\nand Meta Platforms, Inc. (if you are located outside of the
|
|
||||||
EEA or Switzerland). \\n\\n\\nBy clicking \u201CI Accept\u201D below or by using
|
|
||||||
or distributing any portion or element of the Llama Materials,\\nyou agree to
|
|
||||||
be bound by this Agreement.\\n\\n\\n1. License Rights and Redistribution.\\n\\n
|
|
||||||
\ a. Grant of Rights. You are granted a non-exclusive, worldwide, \\nnon-transferable
|
|
||||||
and royalty-free limited license under Meta\u2019s intellectual property or
|
|
||||||
other rights \\nowned by Meta embodied in the Llama Materials to use, reproduce,
|
|
||||||
distribute, copy, create derivative works \\nof, and make modifications to the
|
|
||||||
Llama Materials. \\n\\n b. Redistribution and Use. \\n\\n i. If
|
|
||||||
you distribute or make available the Llama Materials (or any derivative works
|
|
||||||
thereof), \\nor a product or service (including another AI model) that contains
|
|
||||||
any of them, you shall (A) provide\\na copy of this Agreement with any such
|
|
||||||
Llama Materials; and (B) prominently display \u201CBuilt with Llama\u201D\\non
|
|
||||||
a related website, user interface, blogpost, about page, or product documentation.
|
|
||||||
If you use the\\nLlama Materials or any outputs or results of the Llama Materials
|
|
||||||
to create, train, fine tune, or\\notherwise improve an AI model, which is distributed
|
|
||||||
or made available, you shall also include \u201CLlama\u201D\\nat the beginning
|
|
||||||
of any such AI model name.\\n\\n ii. If you receive Llama Materials,
|
|
||||||
or any derivative works thereof, from a Licensee as part\\nof an integrated
|
|
||||||
end user product, then Section 2 of this Agreement will not apply to you. \\n\\n
|
|
||||||
\ iii. You must retain in all copies of the Llama Materials that you distribute
|
|
||||||
the \\nfollowing attribution notice within a \u201CNotice\u201D text file distributed
|
|
||||||
as a part of such copies: \\n\u201CLlama 3.2 is licensed under the Llama 3.2
|
|
||||||
Community License, Copyright \xA9 Meta Platforms,\\nInc. All Rights Reserved.\u201D\\n\\n
|
|
||||||
\ iv. Your use of the Llama Materials must comply with applicable laws
|
|
||||||
and regulations\\n(including trade compliance laws and regulations) and adhere
|
|
||||||
to the Acceptable Use Policy for\\nthe Llama Materials (available at https://www.llama.com/llama3_2/use-policy),
|
|
||||||
which is hereby \\nincorporated by reference into this Agreement.\\n \\n2.
|
|
||||||
Additional Commercial Terms. If, on the Llama 3.2 version release date, the
|
|
||||||
monthly active users\\nof the products or services made available by or for
|
|
||||||
Licensee, or Licensee\u2019s affiliates, \\nis greater than 700 million monthly
|
|
||||||
active users in the preceding calendar month, you must request \\na license
|
|
||||||
from Meta, which Meta may grant to you in its sole discretion, and you are not
|
|
||||||
authorized to\\nexercise any of the rights under this Agreement unless or until
|
|
||||||
Meta otherwise expressly grants you such rights.\\n\\n3. Disclaimer of Warranty.
|
|
||||||
UNLESS REQUIRED BY APPLICABLE LAW, THE LLAMA MATERIALS AND ANY OUTPUT AND \\nRESULTS
|
|
||||||
THEREFROM ARE PROVIDED ON AN \u201CAS IS\u201D BASIS, WITHOUT WARRANTIES OF
|
|
||||||
ANY KIND, AND META DISCLAIMS\\nALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND
|
|
||||||
IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES\\nOF TITLE, NON-INFRINGEMENT,
|
|
||||||
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE\\nFOR
|
|
||||||
DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE LLAMA MATERIALS
|
|
||||||
AND ASSUME ANY RISKS ASSOCIATED\\nWITH YOUR USE OF THE LLAMA MATERIALS AND ANY
|
|
||||||
OUTPUT AND RESULTS.\\n\\n4. Limitation of Liability. IN NO EVENT WILL META OR
|
|
||||||
ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, \\nWHETHER IN CONTRACT,
|
|
||||||
TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT,
|
|
||||||
\\nFOR ANY LOST PROFITS OR ANY INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL,
|
|
||||||
EXEMPLARY OR PUNITIVE DAMAGES, EVEN \\nIF META OR ITS AFFILIATES HAVE BEEN ADVISED
|
|
||||||
OF THE POSSIBILITY OF ANY OF THE FOREGOING.\\n\\n5. Intellectual Property.\\n\\n
|
|
||||||
\ a. No trademark licenses are granted under this Agreement, and in connection
|
|
||||||
with the Llama Materials, \\nneither Meta nor Licensee may use any name or mark
|
|
||||||
owned by or associated with the other or any of its affiliates, \\nexcept as
|
|
||||||
required for reasonable and customary use in describing and redistributing the
|
|
||||||
Llama Materials or as \\nset forth in this Section 5(a). Meta hereby grants
|
|
||||||
you a license to use \u201CLlama\u201D (the \u201CMark\u201D) solely as required
|
|
||||||
\\nto comply with the last sentence of Section 1.b.i. You will comply with Meta\u2019s
|
|
||||||
brand guidelines (currently accessible \\nat https://about.meta.com/brand/resources/meta/company-brand/).
|
|
||||||
All goodwill arising out of your use of the Mark \\nwill inure to the benefit
|
|
||||||
of Meta.\\n\\n b. Subject to Meta\u2019s ownership of Llama Materials and
|
|
||||||
derivatives made by or for Meta, with respect to any\\n derivative works
|
|
||||||
and modifications of the Llama Materials that are made by you, as between you
|
|
||||||
and Meta,\\n you are and will be the owner of such derivative works and modifications.\\n\\n
|
|
||||||
\ c. If you institute litigation or other proceedings against Meta or any
|
|
||||||
entity (including a cross-claim or\\n counterclaim in a lawsuit) alleging
|
|
||||||
that the Llama Materials or Llama 3.2 outputs or results, or any portion\\n
|
|
||||||
\ of any of the foregoing, constitutes infringement of intellectual property
|
|
||||||
or other rights owned or licensable\\n by you, then any licenses granted
|
|
||||||
to you under this Agreement shall terminate as of the date such litigation or\\n
|
|
||||||
\ claim is filed or instituted. You will indemnify and hold harmless Meta
|
|
||||||
from and against any claim by any third\\n party arising out of or related
|
|
||||||
to your use or distribution of the Llama Materials.\\n\\n6. Term and Termination.
|
|
||||||
The term of this Agreement will commence upon your acceptance of this Agreement
|
|
||||||
or access\\nto the Llama Materials and will continue in full force and effect
|
|
||||||
until terminated in accordance with the terms\\nand conditions herein. Meta
|
|
||||||
may terminate this Agreement if you are in breach of any term or condition of
|
|
||||||
this\\nAgreement. Upon termination of this Agreement, you shall delete and cease
|
|
||||||
use of the Llama Materials. Sections 3,\\n4 and 7 shall survive the termination
|
|
||||||
of this Agreement. \\n\\n7. Governing Law and Jurisdiction. This Agreement will
|
|
||||||
be governed and construed under the laws of the State of \\nCalifornia without
|
|
||||||
regard to choice of law principles, and the UN Convention on Contracts for the
|
|
||||||
International\\nSale of Goods does not apply to this Agreement. The courts of
|
|
||||||
California shall have exclusive jurisdiction of\\nany dispute arising out of
|
|
||||||
this Agreement.\\n**Llama 3.2** **Acceptable Use Policy**\\n\\nMeta is committed
|
|
||||||
to promoting safe and fair use of its tools and features, including Llama 3.2.
|
|
||||||
If you access or use Llama 3.2, you agree to this Acceptable Use Policy (\u201C**Policy**\u201D).
|
|
||||||
The most recent copy of this policy can be found at [https://www.llama.com/llama3_2/use-policy](https://www.llama.com/llama3_2/use-policy).\\n\\n**Prohibited
|
|
||||||
Uses**\\n\\nWe want everyone to use Llama 3.2 safely and responsibly. You agree
|
|
||||||
you will not use, or allow others to use, Llama 3.2 to:\\n\\n\\n\\n1. Violate
|
|
||||||
the law or others\u2019 rights, including to:\\n 1. Engage in, promote, generate,
|
|
||||||
contribute to, encourage, plan, incite, or further illegal or unlawful activity
|
|
||||||
or content, such as:\\n 1. Violence or terrorism\\n 2. Exploitation
|
|
||||||
or harm to children, including the solicitation, creation, acquisition, or dissemination
|
|
||||||
of child exploitative content or failure to report Child Sexual Abuse Material\\n
|
|
||||||
\ 3. Human trafficking, exploitation, and sexual violence\\n 4.
|
|
||||||
The illegal distribution of information or materials to minors, including obscene
|
|
||||||
materials, or failure to employ legally required age-gating in connection with
|
|
||||||
such information or materials.\\n 5. Sexual solicitation\\n 6.
|
|
||||||
Any other criminal activity\\n 1. Engage in, promote, incite, or facilitate
|
|
||||||
the harassment, abuse, threatening, or bullying of individuals or groups of
|
|
||||||
individuals\\n 2. Engage in, promote, incite, or facilitate discrimination
|
|
||||||
or other unlawful or harmful conduct in the provision of employment, employment
|
|
||||||
benefits, credit, housing, other economic benefits, or other essential goods
|
|
||||||
and services\\n 3. Engage in the unauthorized or unlicensed practice of any
|
|
||||||
profession including, but not limited to, financial, legal, medical/health,
|
|
||||||
or related professional practices\\n 4. Collect, process, disclose, generate,
|
|
||||||
or infer private or sensitive information about individuals, including information
|
|
||||||
about individuals\u2019 identity, health, or demographic information, unless
|
|
||||||
you have obtained the right to do so in accordance with applicable law\\n 5.
|
|
||||||
Engage in or facilitate any action or generate any content that infringes, misappropriates,
|
|
||||||
or otherwise violates any third-party rights, including the outputs or results
|
|
||||||
of any products or services using the Llama Materials\\n 6. Create, generate,
|
|
||||||
or facilitate the creation of malicious code, malware, computer viruses or do
|
|
||||||
anything else that could disable, overburden, interfere with or impair the proper
|
|
||||||
working, integrity, operation or appearance of a website or computer system\\n
|
|
||||||
\ 7. Engage in any action, or facilitate any action, to intentionally circumvent
|
|
||||||
or remove usage restrictions or other safety measures, or to enable functionality
|
|
||||||
disabled by Meta\\n2. Engage in, promote, incite, facilitate, or assist in the
|
|
||||||
planning or development of activities that present a risk of death or bodily
|
|
||||||
harm to individuals, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 8. Military, warfare, nuclear industries or applications, espionage, use
|
|
||||||
for materials or activities that are subject to the International Traffic Arms
|
|
||||||
Regulations (ITAR) maintained by the United States Department of State or to
|
|
||||||
the U.S. Biological Weapons Anti-Terrorism Act of 1989 or the Chemical Weapons
|
|
||||||
Convention Implementation Act of 1997\\n 9. Guns and illegal weapons (including
|
|
||||||
weapon development)\\n 10. Illegal drugs and regulated/controlled substances\\n
|
|
||||||
\ 11. Operation of critical infrastructure, transportation technologies, or
|
|
||||||
heavy machinery\\n 12. Self-harm or harm to others, including suicide, cutting,
|
|
||||||
and eating disorders\\n 13. Any content intended to incite or promote violence,
|
|
||||||
abuse, or any infliction of bodily harm to an individual\\n3. Intentionally
|
|
||||||
deceive or mislead others, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 14. Generating, promoting, or furthering fraud or the creation or promotion
|
|
||||||
of disinformation\\n 15. Generating, promoting, or furthering defamatory
|
|
||||||
content, including the creation of defamatory statements, images, or other content\\n
|
|
||||||
\ 16. Generating, promoting, or further distributing spam\\n 17. Impersonating
|
|
||||||
another individual without consent, authorization, or legal right\\n 18.
|
|
||||||
Representing that the use of Llama 3.2 or outputs are human-generated\\n 19.
|
|
||||||
Generating or facilitating false online engagement, including fake reviews and
|
|
||||||
other means of fake online engagement\\n4. Fail to appropriately disclose to
|
|
||||||
end users any known dangers of your AI system\\n5. Interact with third party
|
|
||||||
tools, models, or software designed to generate unlawful content or engage in
|
|
||||||
unlawful or harmful conduct and/or represent that the outputs of such tools,
|
|
||||||
models, or software are associated with Meta or Llama 3.2\\n\\nWith respect
|
|
||||||
to any multimodal models included in Llama 3.2, the rights granted under Section
|
|
||||||
1(a) of the Llama 3.2 Community License Agreement are not being granted to you
|
|
||||||
if you are an individual domiciled in, or a company with a principal place of
|
|
||||||
business in, the European Union. This restriction does not apply to end users
|
|
||||||
of a product or service that incorporates any such multimodal models.\\n\\nPlease
|
|
||||||
report any violation of this Policy, software \u201Cbug,\u201D or other problems
|
|
||||||
that could lead to a violation of this Policy through one of the following means:\\n\\n\\n\\n*
|
|
||||||
Reporting issues with the model: [https://github.com/meta-llama/llama-models/issues](https://l.workplace.com/l.php?u=https%3A%2F%2Fgithub.com%2Fmeta-llama%2Fllama-models%2Fissues\\u0026h=AT0qV8W9BFT6NwihiOHRuKYQM_UnkzN_NmHMy91OT55gkLpgi4kQupHUl0ssR4dQsIQ8n3tfd0vtkobvsEvt1l4Ic6GXI2EeuHV8N08OG2WnbAmm0FL4ObkazC6G_256vN0lN9DsykCvCqGZ)\\n*
|
|
||||||
Reporting risky content generated by the model: [developers.facebook.com/llama_output_feedback](http://developers.facebook.com/llama_output_feedback)\\n*
|
|
||||||
Reporting bugs and security concerns: [facebook.com/whitehat/info](http://facebook.com/whitehat/info)\\n*
|
|
||||||
Reporting violations of the Acceptable Use Policy or unlicensed uses of Llama
|
|
||||||
3.2: LlamaUseReport@meta.com\",\"modelfile\":\"# Modelfile generated by \\\"ollama
|
|
||||||
show\\\"\\n# To build a new Modelfile based on this, replace FROM with:\\n#
|
|
||||||
FROM llama3.2:3b\\n\\nFROM /Users/joaomoura/.ollama/models/blobs/sha256-dde5aa3fc5ffc17176b5e8bdc82f587b24b2678c6c66101bf7da77af9f7ccdff\\nTEMPLATE
|
|
||||||
\\\"\\\"\\\"\\u003c|start_header_id|\\u003esystem\\u003c|end_header_id|\\u003e\\n\\nCutting
|
|
||||||
Knowledge Date: December 2023\\n\\n{{ if .System }}{{ .System }}\\n{{- end }}\\n{{-
|
|
||||||
if .Tools }}When you receive a tool call response, use the output to format
|
|
||||||
an answer to the orginal user question.\\n\\nYou are a helpful assistant with
|
|
||||||
tool calling capabilities.\\n{{- end }}\\u003c|eot_id|\\u003e\\n{{- range $i,
|
|
||||||
$_ := .Messages }}\\n{{- $last := eq (len (slice $.Messages $i)) 1 }}\\n{{-
|
|
||||||
if eq .Role \\\"user\\\" }}\\u003c|start_header_id|\\u003euser\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if and $.Tools $last }}\\n\\nGiven the following functions, please respond with
|
|
||||||
a JSON for a function call with its proper arguments that best answers the given
|
|
||||||
prompt.\\n\\nRespond in the format {\\\"name\\\": function name, \\\"parameters\\\":
|
|
||||||
dictionary of argument name and its value}. Do not use variables.\\n\\n{{ range
|
|
||||||
$.Tools }}\\n{{- . }}\\n{{ end }}\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{-
|
|
||||||
else }}\\n\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{- end }}{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- else if eq .Role \\\"assistant\\\" }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if .ToolCalls }}\\n{{ range .ToolCalls }}\\n{\\\"name\\\": \\\"{{ .Function.Name
|
|
||||||
}}\\\", \\\"parameters\\\": {{ .Function.Arguments }}}{{ end }}\\n{{- else }}\\n\\n{{
|
|
||||||
.Content }}\\n{{- end }}{{ if not $last }}\\u003c|eot_id|\\u003e{{ end }}\\n{{-
|
|
||||||
else if eq .Role \\\"tool\\\" }}\\u003c|start_header_id|\\u003eipython\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
.Content }}\\u003c|eot_id|\\u003e{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- end }}\\n{{- end }}\\\"\\\"\\\"\\nPARAMETER stop \\u003c|start_header_id|\\u003e\\nPARAMETER
|
|
||||||
stop \\u003c|end_header_id|\\u003e\\nPARAMETER stop \\u003c|eot_id|\\u003e\\nLICENSE
|
|
||||||
\\\"LLAMA 3.2 COMMUNITY LICENSE AGREEMENT\\nLlama 3.2 Version Release Date:
|
|
||||||
September 25, 2024\\n\\n\u201CAgreement\u201D means the terms and conditions
|
|
||||||
for use, reproduction, distribution \\nand modification of the Llama Materials
|
|
||||||
set forth herein.\\n\\n\u201CDocumentation\u201D means the specifications, manuals
|
|
||||||
and documentation accompanying Llama 3.2\\ndistributed by Meta at https://llama.meta.com/doc/overview.\\n\\n\u201CLicensee\u201D
|
|
||||||
or \u201Cyou\u201D means you, or your employer or any other person or entity
|
|
||||||
(if you are \\nentering into this Agreement on such person or entity\u2019s
|
|
||||||
behalf), of the age required under\\napplicable laws, rules or regulations to
|
|
||||||
provide legal consent and that has legal authority\\nto bind your employer or
|
|
||||||
such other person or entity if you are entering in this Agreement\\non their
|
|
||||||
behalf.\\n\\n\u201CLlama 3.2\u201D means the foundational large language models
|
|
||||||
and software and algorithms, including\\nmachine-learning model code, trained
|
|
||||||
model weights, inference-enabling code, training-enabling code,\\nfine-tuning
|
|
||||||
enabling code and other elements of the foregoing distributed by Meta at \\nhttps://www.llama.com/llama-downloads.\\n\\n\u201CLlama
|
|
||||||
Materials\u201D means, collectively, Meta\u2019s proprietary Llama 3.2 and Documentation
|
|
||||||
(and \\nany portion thereof) made available under this Agreement.\\n\\n\u201CMeta\u201D
|
|
||||||
or \u201Cwe\u201D means Meta Platforms Ireland Limited (if you are located in
|
|
||||||
or, \\nif you are an entity, your principal place of business is in the EEA
|
|
||||||
or Switzerland) \\nand Meta Platforms, Inc. (if you are located outside of the
|
|
||||||
EEA or Switzerland). \\n\\n\\nBy clicking \u201CI Accept\u201D below or by using
|
|
||||||
or distributing any portion or element of the Llama Materials,\\nyou agree to
|
|
||||||
be bound by this Agreement.\\n\\n\\n1. License Rights and Redistribution.\\n\\n
|
|
||||||
\ a. Grant of Rights. You are granted a non-exclusive, worldwide, \\nnon-transferable
|
|
||||||
and royalty-free limited license under Meta\u2019s intellectual property or
|
|
||||||
other rights \\nowned by Meta embodied in the Llama Materials to use, reproduce,
|
|
||||||
distribute, copy, create derivative works \\nof, and make modifications to the
|
|
||||||
Llama Materials. \\n\\n b. Redistribution and Use. \\n\\n i. If
|
|
||||||
you distribute or make available the Llama Materials (or any derivative works
|
|
||||||
thereof), \\nor a product or service (including another AI model) that contains
|
|
||||||
any of them, you shall (A) provide\\na copy of this Agreement with any such
|
|
||||||
Llama Materials; and (B) prominently display \u201CBuilt with Llama\u201D\\non
|
|
||||||
a related website, user interface, blogpost, about page, or product documentation.
|
|
||||||
If you use the\\nLlama Materials or any outputs or results of the Llama Materials
|
|
||||||
to create, train, fine tune, or\\notherwise improve an AI model, which is distributed
|
|
||||||
or made available, you shall also include \u201CLlama\u201D\\nat the beginning
|
|
||||||
of any such AI model name.\\n\\n ii. If you receive Llama Materials,
|
|
||||||
or any derivative works thereof, from a Licensee as part\\nof an integrated
|
|
||||||
end user product, then Section 2 of this Agreement will not apply to you. \\n\\n
|
|
||||||
\ iii. You must retain in all copies of the Llama Materials that you distribute
|
|
||||||
the \\nfollowing attribution notice within a \u201CNotice\u201D text file distributed
|
|
||||||
as a part of such copies: \\n\u201CLlama 3.2 is licensed under the Llama 3.2
|
|
||||||
Community License, Copyright \xA9 Meta Platforms,\\nInc. All Rights Reserved.\u201D\\n\\n
|
|
||||||
\ iv. Your use of the Llama Materials must comply with applicable laws
|
|
||||||
and regulations\\n(including trade compliance laws and regulations) and adhere
|
|
||||||
to the Acceptable Use Policy for\\nthe Llama Materials (available at https://www.llama.com/llama3_2/use-policy),
|
|
||||||
which is hereby \\nincorporated by reference into this Agreement.\\n \\n2.
|
|
||||||
Additional Commercial Terms. If, on the Llama 3.2 version release date, the
|
|
||||||
monthly active users\\nof the products or services made available by or for
|
|
||||||
Licensee, or Licensee\u2019s affiliates, \\nis greater than 700 million monthly
|
|
||||||
active users in the preceding calendar month, you must request \\na license
|
|
||||||
from Meta, which Meta may grant to you in its sole discretion, and you are not
|
|
||||||
authorized to\\nexercise any of the rights under this Agreement unless or until
|
|
||||||
Meta otherwise expressly grants you such rights.\\n\\n3. Disclaimer of Warranty.
|
|
||||||
UNLESS REQUIRED BY APPLICABLE LAW, THE LLAMA MATERIALS AND ANY OUTPUT AND \\nRESULTS
|
|
||||||
THEREFROM ARE PROVIDED ON AN \u201CAS IS\u201D BASIS, WITHOUT WARRANTIES OF
|
|
||||||
ANY KIND, AND META DISCLAIMS\\nALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND
|
|
||||||
IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES\\nOF TITLE, NON-INFRINGEMENT,
|
|
||||||
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE\\nFOR
|
|
||||||
DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE LLAMA MATERIALS
|
|
||||||
AND ASSUME ANY RISKS ASSOCIATED\\nWITH YOUR USE OF THE LLAMA MATERIALS AND ANY
|
|
||||||
OUTPUT AND RESULTS.\\n\\n4. Limitation of Liability. IN NO EVENT WILL META OR
|
|
||||||
ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, \\nWHETHER IN CONTRACT,
|
|
||||||
TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT,
|
|
||||||
\\nFOR ANY LOST PROFITS OR ANY INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL,
|
|
||||||
EXEMPLARY OR PUNITIVE DAMAGES, EVEN \\nIF META OR ITS AFFILIATES HAVE BEEN ADVISED
|
|
||||||
OF THE POSSIBILITY OF ANY OF THE FOREGOING.\\n\\n5. Intellectual Property.\\n\\n
|
|
||||||
\ a. No trademark licenses are granted under this Agreement, and in connection
|
|
||||||
with the Llama Materials, \\nneither Meta nor Licensee may use any name or mark
|
|
||||||
owned by or associated with the other or any of its affiliates, \\nexcept as
|
|
||||||
required for reasonable and customary use in describing and redistributing the
|
|
||||||
Llama Materials or as \\nset forth in this Section 5(a). Meta hereby grants
|
|
||||||
you a license to use \u201CLlama\u201D (the \u201CMark\u201D) solely as required
|
|
||||||
\\nto comply with the last sentence of Section 1.b.i. You will comply with Meta\u2019s
|
|
||||||
brand guidelines (currently accessible \\nat https://about.meta.com/brand/resources/meta/company-brand/).
|
|
||||||
All goodwill arising out of your use of the Mark \\nwill inure to the benefit
|
|
||||||
of Meta.\\n\\n b. Subject to Meta\u2019s ownership of Llama Materials and
|
|
||||||
derivatives made by or for Meta, with respect to any\\n derivative works
|
|
||||||
and modifications of the Llama Materials that are made by you, as between you
|
|
||||||
and Meta,\\n you are and will be the owner of such derivative works and modifications.\\n\\n
|
|
||||||
\ c. If you institute litigation or other proceedings against Meta or any
|
|
||||||
entity (including a cross-claim or\\n counterclaim in a lawsuit) alleging
|
|
||||||
that the Llama Materials or Llama 3.2 outputs or results, or any portion\\n
|
|
||||||
\ of any of the foregoing, constitutes infringement of intellectual property
|
|
||||||
or other rights owned or licensable\\n by you, then any licenses granted
|
|
||||||
to you under this Agreement shall terminate as of the date such litigation or\\n
|
|
||||||
\ claim is filed or instituted. You will indemnify and hold harmless Meta
|
|
||||||
from and against any claim by any third\\n party arising out of or related
|
|
||||||
to your use or distribution of the Llama Materials.\\n\\n6. Term and Termination.
|
|
||||||
The term of this Agreement will commence upon your acceptance of this Agreement
|
|
||||||
or access\\nto the Llama Materials and will continue in full force and effect
|
|
||||||
until terminated in accordance with the terms\\nand conditions herein. Meta
|
|
||||||
may terminate this Agreement if you are in breach of any term or condition of
|
|
||||||
this\\nAgreement. Upon termination of this Agreement, you shall delete and cease
|
|
||||||
use of the Llama Materials. Sections 3,\\n4 and 7 shall survive the termination
|
|
||||||
of this Agreement. \\n\\n7. Governing Law and Jurisdiction. This Agreement will
|
|
||||||
be governed and construed under the laws of the State of \\nCalifornia without
|
|
||||||
regard to choice of law principles, and the UN Convention on Contracts for the
|
|
||||||
International\\nSale of Goods does not apply to this Agreement. The courts of
|
|
||||||
California shall have exclusive jurisdiction of\\nany dispute arising out of
|
|
||||||
this Agreement.\\\"\\nLICENSE \\\"**Llama 3.2** **Acceptable Use Policy**\\n\\nMeta
|
|
||||||
is committed to promoting safe and fair use of its tools and features, including
|
|
||||||
Llama 3.2. If you access or use Llama 3.2, you agree to this Acceptable Use
|
|
||||||
Policy (\u201C**Policy**\u201D). The most recent copy of this policy can be
|
|
||||||
found at [https://www.llama.com/llama3_2/use-policy](https://www.llama.com/llama3_2/use-policy).\\n\\n**Prohibited
|
|
||||||
Uses**\\n\\nWe want everyone to use Llama 3.2 safely and responsibly. You agree
|
|
||||||
you will not use, or allow others to use, Llama 3.2 to:\\n\\n\\n\\n1. Violate
|
|
||||||
the law or others\u2019 rights, including to:\\n 1. Engage in, promote, generate,
|
|
||||||
contribute to, encourage, plan, incite, or further illegal or unlawful activity
|
|
||||||
or content, such as:\\n 1. Violence or terrorism\\n 2. Exploitation
|
|
||||||
or harm to children, including the solicitation, creation, acquisition, or dissemination
|
|
||||||
of child exploitative content or failure to report Child Sexual Abuse Material\\n
|
|
||||||
\ 3. Human trafficking, exploitation, and sexual violence\\n 4.
|
|
||||||
The illegal distribution of information or materials to minors, including obscene
|
|
||||||
materials, or failure to employ legally required age-gating in connection with
|
|
||||||
such information or materials.\\n 5. Sexual solicitation\\n 6.
|
|
||||||
Any other criminal activity\\n 1. Engage in, promote, incite, or facilitate
|
|
||||||
the harassment, abuse, threatening, or bullying of individuals or groups of
|
|
||||||
individuals\\n 2. Engage in, promote, incite, or facilitate discrimination
|
|
||||||
or other unlawful or harmful conduct in the provision of employment, employment
|
|
||||||
benefits, credit, housing, other economic benefits, or other essential goods
|
|
||||||
and services\\n 3. Engage in the unauthorized or unlicensed practice of any
|
|
||||||
profession including, but not limited to, financial, legal, medical/health,
|
|
||||||
or related professional practices\\n 4. Collect, process, disclose, generate,
|
|
||||||
or infer private or sensitive information about individuals, including information
|
|
||||||
about individuals\u2019 identity, health, or demographic information, unless
|
|
||||||
you have obtained the right to do so in accordance with applicable law\\n 5.
|
|
||||||
Engage in or facilitate any action or generate any content that infringes, misappropriates,
|
|
||||||
or otherwise violates any third-party rights, including the outputs or results
|
|
||||||
of any products or services using the Llama Materials\\n 6. Create, generate,
|
|
||||||
or facilitate the creation of malicious code, malware, computer viruses or do
|
|
||||||
anything else that could disable, overburden, interfere with or impair the proper
|
|
||||||
working, integrity, operation or appearance of a website or computer system\\n
|
|
||||||
\ 7. Engage in any action, or facilitate any action, to intentionally circumvent
|
|
||||||
or remove usage restrictions or other safety measures, or to enable functionality
|
|
||||||
disabled by Meta\\n2. Engage in, promote, incite, facilitate, or assist in the
|
|
||||||
planning or development of activities that present a risk of death or bodily
|
|
||||||
harm to individuals, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 8. Military, warfare, nuclear industries or applications, espionage, use
|
|
||||||
for materials or activities that are subject to the International Traffic Arms
|
|
||||||
Regulations (ITAR) maintained by the United States Department of State or to
|
|
||||||
the U.S. Biological Weapons Anti-Terrorism Act of 1989 or the Chemical Weapons
|
|
||||||
Convention Implementation Act of 1997\\n 9. Guns and illegal weapons (including
|
|
||||||
weapon development)\\n 10. Illegal drugs and regulated/controlled substances\\n
|
|
||||||
\ 11. Operation of critical infrastructure, transportation technologies, or
|
|
||||||
heavy machinery\\n 12. Self-harm or harm to others, including suicide, cutting,
|
|
||||||
and eating disorders\\n 13. Any content intended to incite or promote violence,
|
|
||||||
abuse, or any infliction of bodily harm to an individual\\n3. Intentionally
|
|
||||||
deceive or mislead others, including use of Llama 3.2 related to the following:\\n
|
|
||||||
\ 14. Generating, promoting, or furthering fraud or the creation or promotion
|
|
||||||
of disinformation\\n 15. Generating, promoting, or furthering defamatory
|
|
||||||
content, including the creation of defamatory statements, images, or other content\\n
|
|
||||||
\ 16. Generating, promoting, or further distributing spam\\n 17. Impersonating
|
|
||||||
another individual without consent, authorization, or legal right\\n 18.
|
|
||||||
Representing that the use of Llama 3.2 or outputs are human-generated\\n 19.
|
|
||||||
Generating or facilitating false online engagement, including fake reviews and
|
|
||||||
other means of fake online engagement\\n4. Fail to appropriately disclose to
|
|
||||||
end users any known dangers of your AI system\\n5. Interact with third party
|
|
||||||
tools, models, or software designed to generate unlawful content or engage in
|
|
||||||
unlawful or harmful conduct and/or represent that the outputs of such tools,
|
|
||||||
models, or software are associated with Meta or Llama 3.2\\n\\nWith respect
|
|
||||||
to any multimodal models included in Llama 3.2, the rights granted under Section
|
|
||||||
1(a) of the Llama 3.2 Community License Agreement are not being granted to you
|
|
||||||
if you are an individual domiciled in, or a company with a principal place of
|
|
||||||
business in, the European Union. This restriction does not apply to end users
|
|
||||||
of a product or service that incorporates any such multimodal models.\\n\\nPlease
|
|
||||||
report any violation of this Policy, software \u201Cbug,\u201D or other problems
|
|
||||||
that could lead to a violation of this Policy through one of the following means:\\n\\n\\n\\n*
|
|
||||||
Reporting issues with the model: [https://github.com/meta-llama/llama-models/issues](https://l.workplace.com/l.php?u=https%3A%2F%2Fgithub.com%2Fmeta-llama%2Fllama-models%2Fissues\\u0026h=AT0qV8W9BFT6NwihiOHRuKYQM_UnkzN_NmHMy91OT55gkLpgi4kQupHUl0ssR4dQsIQ8n3tfd0vtkobvsEvt1l4Ic6GXI2EeuHV8N08OG2WnbAmm0FL4ObkazC6G_256vN0lN9DsykCvCqGZ)\\n*
|
|
||||||
Reporting risky content generated by the model: [developers.facebook.com/llama_output_feedback](http://developers.facebook.com/llama_output_feedback)\\n*
|
|
||||||
Reporting bugs and security concerns: [facebook.com/whitehat/info](http://facebook.com/whitehat/info)\\n*
|
|
||||||
Reporting violations of the Acceptable Use Policy or unlicensed uses of Llama
|
|
||||||
3.2: LlamaUseReport@meta.com\\\"\\n\",\"parameters\":\"stop \\\"\\u003c|start_header_id|\\u003e\\\"\\nstop
|
|
||||||
\ \\\"\\u003c|end_header_id|\\u003e\\\"\\nstop \\\"\\u003c|eot_id|\\u003e\\\"\",\"template\":\"\\u003c|start_header_id|\\u003esystem\\u003c|end_header_id|\\u003e\\n\\nCutting
|
|
||||||
Knowledge Date: December 2023\\n\\n{{ if .System }}{{ .System }}\\n{{- end }}\\n{{-
|
|
||||||
if .Tools }}When you receive a tool call response, use the output to format
|
|
||||||
an answer to the orginal user question.\\n\\nYou are a helpful assistant with
|
|
||||||
tool calling capabilities.\\n{{- end }}\\u003c|eot_id|\\u003e\\n{{- range $i,
|
|
||||||
$_ := .Messages }}\\n{{- $last := eq (len (slice $.Messages $i)) 1 }}\\n{{-
|
|
||||||
if eq .Role \\\"user\\\" }}\\u003c|start_header_id|\\u003euser\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if and $.Tools $last }}\\n\\nGiven the following functions, please respond with
|
|
||||||
a JSON for a function call with its proper arguments that best answers the given
|
|
||||||
prompt.\\n\\nRespond in the format {\\\"name\\\": function name, \\\"parameters\\\":
|
|
||||||
dictionary of argument name and its value}. Do not use variables.\\n\\n{{ range
|
|
||||||
$.Tools }}\\n{{- . }}\\n{{ end }}\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{-
|
|
||||||
else }}\\n\\n{{ .Content }}\\u003c|eot_id|\\u003e\\n{{- end }}{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- else if eq .Role \\\"assistant\\\" }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n{{-
|
|
||||||
if .ToolCalls }}\\n{{ range .ToolCalls }}\\n{\\\"name\\\": \\\"{{ .Function.Name
|
|
||||||
}}\\\", \\\"parameters\\\": {{ .Function.Arguments }}}{{ end }}\\n{{- else }}\\n\\n{{
|
|
||||||
.Content }}\\n{{- end }}{{ if not $last }}\\u003c|eot_id|\\u003e{{ end }}\\n{{-
|
|
||||||
else if eq .Role \\\"tool\\\" }}\\u003c|start_header_id|\\u003eipython\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
.Content }}\\u003c|eot_id|\\u003e{{ if $last }}\\u003c|start_header_id|\\u003eassistant\\u003c|end_header_id|\\u003e\\n\\n{{
|
|
||||||
end }}\\n{{- end }}\\n{{- end }}\",\"details\":{\"parent_model\":\"\",\"format\":\"gguf\",\"family\":\"llama\",\"families\":[\"llama\"],\"parameter_size\":\"3.2B\",\"quantization_level\":\"Q4_K_M\"},\"model_info\":{\"general.architecture\":\"llama\",\"general.basename\":\"Llama-3.2\",\"general.file_type\":15,\"general.finetune\":\"Instruct\",\"general.languages\":[\"en\",\"de\",\"fr\",\"it\",\"pt\",\"hi\",\"es\",\"th\"],\"general.parameter_count\":3212749888,\"general.quantization_version\":2,\"general.size_label\":\"3B\",\"general.tags\":[\"facebook\",\"meta\",\"pytorch\",\"llama\",\"llama-3\",\"text-generation\"],\"general.type\":\"model\",\"llama.attention.head_count\":24,\"llama.attention.head_count_kv\":8,\"llama.attention.key_length\":128,\"llama.attention.layer_norm_rms_epsilon\":0.00001,\"llama.attention.value_length\":128,\"llama.block_count\":28,\"llama.context_length\":131072,\"llama.embedding_length\":3072,\"llama.feed_forward_length\":8192,\"llama.rope.dimension_count\":128,\"llama.rope.freq_base\":500000,\"llama.vocab_size\":128256,\"tokenizer.ggml.bos_token_id\":128000,\"tokenizer.ggml.eos_token_id\":128009,\"tokenizer.ggml.merges\":null,\"tokenizer.ggml.model\":\"gpt2\",\"tokenizer.ggml.pre\":\"llama-bpe\",\"tokenizer.ggml.token_type\":null,\"tokenizer.ggml.tokens\":null},\"modified_at\":\"2025-02-20T18:55:09.150577031-08:00\"}"
|
|
||||||
headers:
|
|
||||||
Content-Type:
|
|
||||||
- application/json; charset=utf-8
|
|
||||||
Date:
|
|
||||||
- Fri, 21 Feb 2025 02:57:55 GMT
|
|
||||||
Transfer-Encoding:
|
|
||||||
- chunked
|
|
||||||
http_version: HTTP/1.1
|
|
||||||
status_code: 200
|
|
||||||
version: 1
|
|
||||||
@@ -197,6 +197,101 @@ def test_convert_with_instructions_success(
|
|||||||
assert output.age == 50
|
assert output.age == 50
|
||||||
|
|
||||||
|
|
||||||
|
@patch("crewai.utilities.converter.get_conversion_instructions")
|
||||||
|
@patch("crewai.utilities.converter.create_converter")
|
||||||
|
def test_convert_with_instructions_respects_use_system_prompt_false(
|
||||||
|
mock_create_converter, mock_get_instructions, mock_agent
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Test that convert_with_instructions does not use a system prompt
|
||||||
|
when agent.use_system_prompt is False and the LLM doesn't support function calling.
|
||||||
|
"""
|
||||||
|
mock_agent.use_system_prompt = False
|
||||||
|
mock_llm = MagicMock()
|
||||||
|
mock_llm.supports_function_calling.return_value = False
|
||||||
|
mock_agent.llm = mock_llm
|
||||||
|
mock_agent.function_calling_llm = None # Ensure fallback to agent.llm
|
||||||
|
|
||||||
|
mock_get_instructions.return_value = "Test Instructions"
|
||||||
|
|
||||||
|
mock_converter_instance = MagicMock(spec=Converter)
|
||||||
|
mock_converter_instance.agent = mock_agent # Set the agent on the mock converter
|
||||||
|
mock_converter_instance.llm = mock_llm
|
||||||
|
mock_converter_instance.instructions = "Test Instructions"
|
||||||
|
mock_converter_instance.text = "Some text"
|
||||||
|
mock_converter_instance.model = SimpleModel
|
||||||
|
|
||||||
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
|
llm=mock_llm,
|
||||||
|
text="Some text",
|
||||||
|
model=SimpleModel,
|
||||||
|
instructions="Test Instructions",
|
||||||
|
)
|
||||||
|
mock_create_converter.return_value = (
|
||||||
|
converter # This instance will be used by convert_with_instructions
|
||||||
|
)
|
||||||
|
|
||||||
|
converter.llm.call = MagicMock(return_value='{"name": "Mock Name", "age": 99}')
|
||||||
|
|
||||||
|
convert_with_instructions("Some text", SimpleModel, False, mock_agent)
|
||||||
|
|
||||||
|
converter.llm.call.assert_called_once()
|
||||||
|
call_args = converter.llm.call.call_args[0][0] # Get the 'messages' list argument
|
||||||
|
|
||||||
|
assert not any(msg.get("role") == "system" for msg in call_args)
|
||||||
|
user_message = next((msg for msg in call_args if msg.get("role") == "user"), None)
|
||||||
|
assert user_message is not None
|
||||||
|
assert "Test Instructions" in user_message["content"]
|
||||||
|
assert "Some text" in user_message["content"]
|
||||||
|
assert user_message["content"].startswith("Test Instructions\n\n")
|
||||||
|
|
||||||
|
|
||||||
|
@patch("crewai.utilities.converter.get_conversion_instructions")
|
||||||
|
@patch("crewai.utilities.converter.create_converter")
|
||||||
|
def test_convert_with_instructions_respects_use_system_prompt_true(
|
||||||
|
mock_create_converter, mock_get_instructions, mock_agent
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Test that convert_with_instructions uses a system prompt
|
||||||
|
when agent.use_system_prompt is True and the LLM doesn't support function calling.
|
||||||
|
"""
|
||||||
|
mock_agent.use_system_prompt = True # Explicitly True
|
||||||
|
mock_llm = MagicMock()
|
||||||
|
mock_llm.supports_function_calling.return_value = False
|
||||||
|
mock_agent.llm = mock_llm
|
||||||
|
mock_agent.function_calling_llm = None
|
||||||
|
|
||||||
|
mock_get_instructions.return_value = "Test Instructions"
|
||||||
|
|
||||||
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
|
llm=mock_llm,
|
||||||
|
text="Some text",
|
||||||
|
model=SimpleModel,
|
||||||
|
instructions="Test Instructions",
|
||||||
|
)
|
||||||
|
mock_create_converter.return_value = (
|
||||||
|
converter # This instance will be used by convert_with_instructions
|
||||||
|
)
|
||||||
|
|
||||||
|
converter.llm.call = MagicMock(return_value='{"name": "Mock Name", "age": 99}')
|
||||||
|
|
||||||
|
convert_with_instructions("Some text", SimpleModel, False, mock_agent)
|
||||||
|
|
||||||
|
converter.llm.call.assert_called_once()
|
||||||
|
call_args = converter.llm.call.call_args[0][0]
|
||||||
|
|
||||||
|
system_message = next(
|
||||||
|
(msg for msg in call_args if msg.get("role") == "system"), None
|
||||||
|
)
|
||||||
|
assert system_message is not None
|
||||||
|
assert system_message["content"] == "Test Instructions"
|
||||||
|
user_message = next((msg for msg in call_args if msg.get("role") == "user"), None)
|
||||||
|
assert user_message is not None
|
||||||
|
assert user_message["content"] == "Some text"
|
||||||
|
|
||||||
|
|
||||||
@patch("crewai.utilities.converter.create_converter")
|
@patch("crewai.utilities.converter.create_converter")
|
||||||
@patch("crewai.utilities.converter.get_conversion_instructions")
|
@patch("crewai.utilities.converter.get_conversion_instructions")
|
||||||
def test_convert_with_instructions_failure(
|
def test_convert_with_instructions_failure(
|
||||||
@@ -334,7 +429,10 @@ def test_convert_with_instructions():
|
|||||||
sample_text = "Name: Alice, Age: 30"
|
sample_text = "Name: Alice, Age: 30"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||||
|
mock_agent = Mock() # Add mock agent if not available
|
||||||
|
mock_agent.use_system_prompt = True # Default or set as needed
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent, # Add agent argument
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=SimpleModel,
|
model=SimpleModel,
|
||||||
@@ -362,7 +460,10 @@ def test_converter_with_llama3_2_model():
|
|||||||
llm = LLM(model="ollama/llama3.2:3b", base_url="http://localhost:11434")
|
llm = LLM(model="ollama/llama3.2:3b", base_url="http://localhost:11434")
|
||||||
sample_text = "Name: Alice Llama, Age: 30"
|
sample_text = "Name: Alice Llama, Age: 30"
|
||||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||||
|
mock_agent = Mock() # Add mock agent if not available
|
||||||
|
mock_agent.use_system_prompt = True # Default or set as needed
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent, # Add agent argument
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=SimpleModel,
|
model=SimpleModel,
|
||||||
@@ -380,7 +481,10 @@ def test_converter_with_llama3_1_model():
|
|||||||
llm = LLM(model="ollama/llama3.1", base_url="http://localhost:11434")
|
llm = LLM(model="ollama/llama3.1", base_url="http://localhost:11434")
|
||||||
sample_text = "Name: Alice Llama, Age: 30"
|
sample_text = "Name: Alice Llama, Age: 30"
|
||||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||||
|
mock_agent = Mock() # Add mock agent if not available
|
||||||
|
mock_agent.use_system_prompt = True # Default or set as needed
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent, # Add agent argument
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=SimpleModel,
|
model=SimpleModel,
|
||||||
@@ -405,7 +509,11 @@ def test_converter_with_nested_model():
|
|||||||
sample_text = "Name: John Doe\nAge: 30\nAddress: 123 Main St, Anytown, 12345"
|
sample_text = "Name: John Doe\nAge: 30\nAddress: 123 Main St, Anytown, 12345"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(Person, llm)
|
instructions = get_conversion_instructions(Person, llm)
|
||||||
|
mock_agent = Mock()
|
||||||
|
mock_agent.use_system_prompt = True
|
||||||
|
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=Person,
|
model=Person,
|
||||||
@@ -431,7 +539,10 @@ def test_converter_error_handling():
|
|||||||
sample_text = "Name: Alice, Age: 30"
|
sample_text = "Name: Alice, Age: 30"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||||
|
mock_agent = Mock() # Add mock agent if not available
|
||||||
|
mock_agent.use_system_prompt = True # Default or set as needed
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent, # Add agent argument
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=SimpleModel,
|
model=SimpleModel,
|
||||||
@@ -456,7 +567,11 @@ def test_converter_retry_logic():
|
|||||||
sample_text = "Name: Retry Alice, Age: 30"
|
sample_text = "Name: Retry Alice, Age: 30"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||||
|
mock_agent = Mock()
|
||||||
|
mock_agent.use_system_prompt = True
|
||||||
|
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=SimpleModel,
|
model=SimpleModel,
|
||||||
@@ -485,7 +600,11 @@ def test_converter_with_optional_fields():
|
|||||||
sample_text = "Name: Bob, age: None"
|
sample_text = "Name: Bob, age: None"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(OptionalModel, llm)
|
instructions = get_conversion_instructions(OptionalModel, llm)
|
||||||
|
mock_agent = Mock()
|
||||||
|
mock_agent.use_system_prompt = True
|
||||||
|
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=OptionalModel,
|
model=OptionalModel,
|
||||||
@@ -510,7 +629,11 @@ def test_converter_with_list_field():
|
|||||||
sample_text = "Items: 1, 2, 3"
|
sample_text = "Items: 1, 2, 3"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(ListModel, llm)
|
instructions = get_conversion_instructions(ListModel, llm)
|
||||||
|
mock_agent = Mock()
|
||||||
|
mock_agent.use_system_prompt = True
|
||||||
|
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=ListModel,
|
model=ListModel,
|
||||||
@@ -543,7 +666,11 @@ def test_converter_with_enum():
|
|||||||
sample_text = "Name: Alice, Color: Red"
|
sample_text = "Name: Alice, Color: Red"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(EnumModel, llm)
|
instructions = get_conversion_instructions(EnumModel, llm)
|
||||||
|
mock_agent = Mock()
|
||||||
|
mock_agent.use_system_prompt = True
|
||||||
|
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=EnumModel,
|
model=EnumModel,
|
||||||
@@ -565,7 +692,11 @@ def test_converter_with_ambiguous_input():
|
|||||||
sample_text = "Charlie is thirty years old"
|
sample_text = "Charlie is thirty years old"
|
||||||
|
|
||||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||||
|
mock_agent = Mock()
|
||||||
|
mock_agent.use_system_prompt = True
|
||||||
|
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text=sample_text,
|
text=sample_text,
|
||||||
model=SimpleModel,
|
model=SimpleModel,
|
||||||
@@ -586,7 +717,11 @@ def test_converter_with_function_calling():
|
|||||||
instructor = Mock()
|
instructor = Mock()
|
||||||
instructor.to_pydantic.return_value = SimpleModel(name="Eve", age=35)
|
instructor.to_pydantic.return_value = SimpleModel(name="Eve", age=35)
|
||||||
|
|
||||||
|
mock_agent = Mock()
|
||||||
|
mock_agent.use_system_prompt = True
|
||||||
|
|
||||||
converter = Converter(
|
converter = Converter(
|
||||||
|
agent=mock_agent,
|
||||||
llm=llm,
|
llm=llm,
|
||||||
text="Name: Eve, Age: 35",
|
text="Name: Eve, Age: 35",
|
||||||
model=SimpleModel,
|
model=SimpleModel,
|
||||||
|
|||||||
@@ -29,13 +29,14 @@ def mock_knowledge_source():
|
|||||||
"""
|
"""
|
||||||
return StringKnowledgeSource(content=content)
|
return StringKnowledgeSource(content=content)
|
||||||
|
|
||||||
@patch('crewai.knowledge.storage.knowledge_storage.chromadb')
|
|
||||||
|
@patch("crewai.knowledge.storage.knowledge_storage.chromadb")
|
||||||
def test_knowledge_included_in_planning(mock_chroma):
|
def test_knowledge_included_in_planning(mock_chroma):
|
||||||
"""Test that verifies knowledge sources are properly included in planning."""
|
"""Test that verifies knowledge sources are properly included in planning."""
|
||||||
# Mock ChromaDB collection
|
# Mock ChromaDB collection
|
||||||
mock_collection = mock_chroma.return_value.get_or_create_collection.return_value
|
mock_collection = mock_chroma.return_value.get_or_create_collection.return_value
|
||||||
mock_collection.add.return_value = None
|
mock_collection.add.return_value = None
|
||||||
|
|
||||||
# Create an agent with knowledge
|
# Create an agent with knowledge
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
role="AI Researcher",
|
role="AI Researcher",
|
||||||
@@ -45,14 +46,14 @@ def test_knowledge_included_in_planning(mock_chroma):
|
|||||||
StringKnowledgeSource(
|
StringKnowledgeSource(
|
||||||
content="AI systems require careful training and validation."
|
content="AI systems require careful training and validation."
|
||||||
)
|
)
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a task for the agent
|
# Create a task for the agent
|
||||||
task = Task(
|
task = Task(
|
||||||
description="Explain the basics of AI systems",
|
description="Explain the basics of AI systems",
|
||||||
expected_output="A clear explanation of AI fundamentals",
|
expected_output="A clear explanation of AI fundamentals",
|
||||||
agent=agent
|
agent=agent,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a crew planner
|
# Create a crew planner
|
||||||
@@ -62,23 +63,29 @@ def test_knowledge_included_in_planning(mock_chroma):
|
|||||||
task_summary = planner._create_tasks_summary()
|
task_summary = planner._create_tasks_summary()
|
||||||
|
|
||||||
# Verify that knowledge is included in planning when present
|
# Verify that knowledge is included in planning when present
|
||||||
assert "AI systems require careful training" in task_summary, \
|
assert (
|
||||||
"Knowledge content should be present in task summary when knowledge exists"
|
"AI systems require careful training" in task_summary
|
||||||
assert '"agent_knowledge"' in task_summary, \
|
), "Knowledge content should be present in task summary when knowledge exists"
|
||||||
"agent_knowledge field should be present in task summary when knowledge exists"
|
assert (
|
||||||
|
'"agent_knowledge"' in task_summary
|
||||||
|
), "agent_knowledge field should be present in task summary when knowledge exists"
|
||||||
|
|
||||||
# Verify that knowledge is properly formatted
|
# Verify that knowledge is properly formatted
|
||||||
assert isinstance(task.agent.knowledge_sources, list), \
|
assert isinstance(
|
||||||
"Knowledge sources should be stored in a list"
|
task.agent.knowledge_sources, list
|
||||||
assert len(task.agent.knowledge_sources) > 0, \
|
), "Knowledge sources should be stored in a list"
|
||||||
"At least one knowledge source should be present"
|
assert (
|
||||||
assert task.agent.knowledge_sources[0].content in task_summary, \
|
len(task.agent.knowledge_sources) > 0
|
||||||
"Knowledge source content should be included in task summary"
|
), "At least one knowledge source should be present"
|
||||||
|
assert (
|
||||||
|
task.agent.knowledge_sources[0].content in task_summary
|
||||||
|
), "Knowledge source content should be included in task summary"
|
||||||
|
|
||||||
# Verify that other expected components are still present
|
# Verify that other expected components are still present
|
||||||
assert task.description in task_summary, \
|
assert (
|
||||||
"Task description should be present in task summary"
|
task.description in task_summary
|
||||||
assert task.expected_output in task_summary, \
|
), "Task description should be present in task summary"
|
||||||
"Expected output should be present in task summary"
|
assert (
|
||||||
assert agent.role in task_summary, \
|
task.expected_output in task_summary
|
||||||
"Agent role should be present in task summary"
|
), "Expected output should be present in task summary"
|
||||||
|
assert agent.role in task_summary, "Agent role should be present in task summary"
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class InternalCrewPlanner:
|
|||||||
# Knowledge field should not be present when empty
|
# Knowledge field should not be present when empty
|
||||||
assert '"agent_knowledge"' not in tasks_summary
|
assert '"agent_knowledge"' not in tasks_summary
|
||||||
|
|
||||||
@patch('crewai.knowledge.storage.knowledge_storage.chromadb')
|
@patch("crewai.knowledge.storage.knowledge_storage.chromadb")
|
||||||
def test_create_tasks_summary_with_knowledge_and_tools(self, mock_chroma):
|
def test_create_tasks_summary_with_knowledge_and_tools(self, mock_chroma):
|
||||||
"""Test task summary generation with both knowledge and tools present."""
|
"""Test task summary generation with both knowledge and tools present."""
|
||||||
# Mock ChromaDB collection
|
# Mock ChromaDB collection
|
||||||
@@ -146,8 +146,8 @@ class InternalCrewPlanner:
|
|||||||
tools=[tool1, tool2],
|
tools=[tool1, tool2],
|
||||||
knowledge_sources=[
|
knowledge_sources=[
|
||||||
StringKnowledgeSource(content="Test knowledge content")
|
StringKnowledgeSource(content="Test knowledge content")
|
||||||
]
|
],
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create planner with the new task
|
# Create planner with the new task
|
||||||
|
|||||||
Reference in New Issue
Block a user