mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-16 04:18:35 +00:00
Compare commits
3 Commits
1.6.1
...
devin/1744
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
031c2d165a | ||
|
|
2e5f0509bf | ||
|
|
44abceffaa |
@@ -4,4 +4,6 @@ repos:
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix"]
|
||||
exclude: ^src/crewai/cli/templates/
|
||||
- id: ruff-format
|
||||
exclude: ^src/crewai/cli/templates/
|
||||
|
||||
@@ -367,8 +367,12 @@ class Agent(BaseAgent):
|
||||
"info", "Coding tools not available. Install crewai_tools. "
|
||||
)
|
||||
|
||||
def get_output_converter(self, llm, text, model, instructions):
|
||||
return Converter(llm=llm, text=text, model=model, instructions=instructions)
|
||||
def get_output_converter(
|
||||
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:
|
||||
"""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()
|
||||
|
||||
settings = Settings()
|
||||
settings.tool_repository_username = login_response_json["credential"]["username"]
|
||||
settings.tool_repository_password = login_response_json["credential"]["password"]
|
||||
settings.tool_repository_username = login_response_json["credential"][
|
||||
"username"
|
||||
]
|
||||
settings.tool_repository_password = login_response_json["credential"][
|
||||
"password"
|
||||
]
|
||||
settings.dump()
|
||||
|
||||
console.print(
|
||||
@@ -179,7 +183,7 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
||||
capture_output=False,
|
||||
env=self._build_env_with_credentials(repository_handle),
|
||||
text=True,
|
||||
check=True
|
||||
check=True,
|
||||
)
|
||||
|
||||
if add_package_result.stderr:
|
||||
@@ -204,7 +208,11 @@ class ToolCommand(BaseCommand, PlusAPIMixin):
|
||||
settings = Settings()
|
||||
|
||||
env = os.environ.copy()
|
||||
env[f"UV_INDEX_{repository_handle}_USERNAME"] = str(settings.tool_repository_username or "")
|
||||
env[f"UV_INDEX_{repository_handle}_PASSWORD"] = str(settings.tool_repository_password or "")
|
||||
env[f"UV_INDEX_{repository_handle}_USERNAME"] = str(
|
||||
settings.tool_repository_username or ""
|
||||
)
|
||||
env[f"UV_INDEX_{repository_handle}_PASSWORD"] = str(
|
||||
settings.tool_repository_password or ""
|
||||
)
|
||||
|
||||
return env
|
||||
|
||||
@@ -297,9 +297,7 @@ class Crew(BaseModel):
|
||||
)
|
||||
self._external_memory = (
|
||||
# External memory doesn’t support a default value since it was designed to be managed entirely externally
|
||||
self.external_memory.set_crew(self)
|
||||
if self.external_memory
|
||||
else None
|
||||
self.external_memory.set_crew(self) if self.external_memory else None
|
||||
)
|
||||
if (
|
||||
self.memory_config
|
||||
|
||||
@@ -34,13 +34,13 @@ class FlowPlot:
|
||||
ValueError
|
||||
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")
|
||||
if not hasattr(flow, '_listeners'):
|
||||
if not hasattr(flow, "_listeners"):
|
||||
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")
|
||||
|
||||
|
||||
self.flow = flow
|
||||
self.colors = COLORS
|
||||
self.node_styles = NODE_STYLES
|
||||
@@ -65,7 +65,7 @@ class FlowPlot:
|
||||
"""
|
||||
if not filename or not isinstance(filename, str):
|
||||
raise ValueError("Filename must be a non-empty string")
|
||||
|
||||
|
||||
try:
|
||||
# Initialize network
|
||||
net = Network(
|
||||
@@ -121,7 +121,9 @@ class FlowPlot:
|
||||
network_html = net.generate_html()
|
||||
final_html_content = self._generate_final_html(network_html)
|
||||
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
|
||||
try:
|
||||
@@ -129,7 +131,9 @@ class FlowPlot:
|
||||
f.write(final_html_content)
|
||||
print(f"Plot saved as {filename}.html")
|
||||
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:
|
||||
raise e
|
||||
@@ -165,7 +169,9 @@ class FlowPlot:
|
||||
try:
|
||||
# Extract just the body content from the generated HTML
|
||||
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)
|
||||
|
||||
if not os.path.exists(template_path):
|
||||
@@ -197,6 +203,7 @@ class FlowPlot:
|
||||
lib_folder = safe_path_join("lib", root=os.getcwd())
|
||||
if os.path.exists(lib_folder) and os.path.isdir(lib_folder):
|
||||
import shutil
|
||||
|
||||
shutil.rmtree(lib_folder)
|
||||
except ValueError as e:
|
||||
print(f"Error validating lib folder path: {e}")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
def get_legend_items(colors):
|
||||
return [
|
||||
{"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
|
||||
root_path = Path(root).resolve() if root else Path.cwd()
|
||||
|
||||
|
||||
# Join and resolve the full path
|
||||
full_path = Path(root_path, *clean_parts).resolve()
|
||||
|
||||
|
||||
# Check if the resolved path is within root
|
||||
if not str(full_path).startswith(str(root_path)):
|
||||
raise ValueError(
|
||||
f"Invalid path: Potential directory traversal. Path must be within {root_path}"
|
||||
)
|
||||
|
||||
|
||||
return str(full_path)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
if isinstance(e, ValueError):
|
||||
raise
|
||||
@@ -84,17 +84,17 @@ def validate_path_exists(path: Union[str, Path], file_type: str = "file") -> str
|
||||
"""
|
||||
try:
|
||||
path_obj = Path(path).resolve()
|
||||
|
||||
|
||||
if not path_obj.exists():
|
||||
raise ValueError(f"Path does not exist: {path}")
|
||||
|
||||
|
||||
if file_type == "file" and not path_obj.is_file():
|
||||
raise ValueError(f"Path is not a file: {path}")
|
||||
elif file_type == "directory" and not path_obj.is_dir():
|
||||
raise ValueError(f"Path is not a directory: {path}")
|
||||
|
||||
|
||||
return str(path_obj)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
if isinstance(e, ValueError):
|
||||
raise
|
||||
@@ -126,9 +126,9 @@ def list_files(directory: Union[str, Path], pattern: str = "*") -> List[str]:
|
||||
dir_path = Path(directory).resolve()
|
||||
if not dir_path.is_dir():
|
||||
raise ValueError(f"Not a directory: {directory}")
|
||||
|
||||
|
||||
return [str(p) for p in dir_path.glob(pattern) if p.is_file()]
|
||||
|
||||
|
||||
except Exception as e:
|
||||
if isinstance(e, ValueError):
|
||||
raise
|
||||
|
||||
@@ -8,45 +8,45 @@ from pydantic import BaseModel
|
||||
|
||||
class FlowPersistence(abc.ABC):
|
||||
"""Abstract base class for flow state persistence.
|
||||
|
||||
|
||||
This class defines the interface that all persistence implementations must follow.
|
||||
It supports both structured (Pydantic BaseModel) and unstructured (dict) states.
|
||||
"""
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def init_db(self) -> None:
|
||||
"""Initialize the persistence backend.
|
||||
|
||||
|
||||
This method should handle any necessary setup, such as:
|
||||
- Creating tables
|
||||
- Establishing connections
|
||||
- Setting up indexes
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def save_state(
|
||||
self,
|
||||
flow_uuid: str,
|
||||
method_name: str,
|
||||
state_data: Union[Dict[str, Any], BaseModel]
|
||||
state_data: Union[Dict[str, Any], BaseModel],
|
||||
) -> None:
|
||||
"""Persist the flow state after method completion.
|
||||
|
||||
|
||||
Args:
|
||||
flow_uuid: Unique identifier for the flow instance
|
||||
method_name: Name of the method that just completed
|
||||
state_data: Current state data (either dict or Pydantic model)
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def load_state(self, flow_uuid: str) -> Optional[Dict[str, Any]]:
|
||||
"""Load the most recent state for a given flow UUID.
|
||||
|
||||
|
||||
Args:
|
||||
flow_uuid: Unique identifier for the flow instance
|
||||
|
||||
|
||||
Returns:
|
||||
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_error": "Failed to persist state for method {}: {}",
|
||||
"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
|
||||
|
||||
@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.
|
||||
|
||||
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
|
||||
"""
|
||||
try:
|
||||
state = getattr(flow_instance, 'state', None)
|
||||
state = getattr(flow_instance, "state", None)
|
||||
if state is None:
|
||||
raise ValueError("Flow instance has no state")
|
||||
|
||||
flow_uuid: Optional[str] = None
|
||||
if isinstance(state, dict):
|
||||
flow_uuid = state.get('id')
|
||||
flow_uuid = state.get("id")
|
||||
elif isinstance(state, BaseModel):
|
||||
flow_uuid = getattr(state, 'id', None)
|
||||
flow_uuid = getattr(state, "id", None)
|
||||
|
||||
if not flow_uuid:
|
||||
raise ValueError("Flow state must have an 'id' field for persistence")
|
||||
|
||||
# Log state saving only if verbose is True
|
||||
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))
|
||||
|
||||
try:
|
||||
@@ -144,7 +152,10 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
||||
def begin(self):
|
||||
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."""
|
||||
actual_persistence = persistence or SQLiteFlowPersistence()
|
||||
|
||||
@@ -154,8 +165,8 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
||||
|
||||
@functools.wraps(original_init)
|
||||
def new_init(self: Any, *args: Any, **kwargs: Any) -> None:
|
||||
if 'persistence' not in kwargs:
|
||||
kwargs['persistence'] = actual_persistence
|
||||
if "persistence" not in kwargs:
|
||||
kwargs["persistence"] = actual_persistence
|
||||
original_init(self, *args, **kwargs)
|
||||
|
||||
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():
|
||||
if callable(method) and (
|
||||
hasattr(method, "__is_start_method__") or
|
||||
hasattr(method, "__trigger_methods__") or
|
||||
hasattr(method, "__condition_type__") or
|
||||
hasattr(method, "__is_flow_method__") or
|
||||
hasattr(method, "__is_router__")
|
||||
hasattr(method, "__is_start_method__")
|
||||
or hasattr(method, "__trigger_methods__")
|
||||
or hasattr(method, "__condition_type__")
|
||||
or hasattr(method, "__is_flow_method__")
|
||||
or hasattr(method, "__is_router__")
|
||||
):
|
||||
original_methods[name] = method
|
||||
|
||||
@@ -177,18 +188,30 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
||||
for name, method in original_methods.items():
|
||||
if asyncio.iscoroutinefunction(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)
|
||||
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)
|
||||
PersistenceDecorator.persist_state(self, method_name, actual_persistence, verbose)
|
||||
PersistenceDecorator.persist_state(
|
||||
self, method_name, actual_persistence, verbose
|
||||
)
|
||||
return result
|
||||
|
||||
return method_wrapper
|
||||
|
||||
wrapped = create_async_wrapper(name, method)
|
||||
|
||||
# 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):
|
||||
setattr(wrapped, attr, getattr(method, attr))
|
||||
setattr(wrapped, "__is_flow_method__", True)
|
||||
@@ -197,18 +220,28 @@ def persist(persistence: Optional[FlowPersistence] = None, verbose: bool = False
|
||||
setattr(target, name, wrapped)
|
||||
else:
|
||||
# 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)
|
||||
def method_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
|
||||
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 method_wrapper
|
||||
|
||||
wrapped = create_sync_wrapper(name, method)
|
||||
|
||||
# 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):
|
||||
setattr(wrapped, attr, getattr(method, attr))
|
||||
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)
|
||||
|
||||
if asyncio.iscoroutinefunction(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)
|
||||
if asyncio.iscoroutine(method_coro):
|
||||
result = await method_coro
|
||||
else:
|
||||
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
|
||||
|
||||
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):
|
||||
setattr(method_async_wrapper, attr, getattr(method, attr))
|
||||
setattr(method_async_wrapper, "__is_flow_method__", True)
|
||||
return cast(Callable[..., T], method_async_wrapper)
|
||||
else:
|
||||
|
||||
@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)
|
||||
PersistenceDecorator.persist_state(flow_instance, method.__name__, actual_persistence, verbose)
|
||||
PersistenceDecorator.persist_state(
|
||||
flow_instance, method.__name__, actual_persistence, verbose
|
||||
)
|
||||
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):
|
||||
setattr(method_sync_wrapper, attr, getattr(method, attr))
|
||||
setattr(method_sync_wrapper, "__is_flow_method__", True)
|
||||
|
||||
@@ -56,6 +56,7 @@ def method_calls_crew(method: Any) -> bool:
|
||||
|
||||
class CrewCallVisitor(ast.NodeVisitor):
|
||||
"""AST visitor to detect .crew() method calls."""
|
||||
|
||||
def __init__(self):
|
||||
self.found = False
|
||||
|
||||
@@ -74,7 +75,7 @@ def add_nodes_to_network(
|
||||
net: Any,
|
||||
flow: Any,
|
||||
node_positions: Dict[str, Tuple[float, float]],
|
||||
node_styles: Dict[str, Dict[str, Any]]
|
||||
node_styles: Dict[str, Dict[str, Any]],
|
||||
) -> None:
|
||||
"""
|
||||
Add nodes to the network visualization with appropriate styling.
|
||||
@@ -98,6 +99,7 @@ def add_nodes_to_network(
|
||||
- Crew methods
|
||||
- Regular methods
|
||||
"""
|
||||
|
||||
def human_friendly_label(method_name):
|
||||
return method_name.replace("_", " ").title()
|
||||
|
||||
@@ -140,7 +142,7 @@ def compute_positions(
|
||||
flow: Any,
|
||||
node_levels: Dict[str, int],
|
||||
y_spacing: float = 150,
|
||||
x_spacing: float = 150
|
||||
x_spacing: float = 150,
|
||||
) -> Dict[str, Tuple[float, float]]:
|
||||
"""
|
||||
Compute the (x, y) positions for each node in the flow graph.
|
||||
@@ -181,7 +183,7 @@ def add_edges(
|
||||
net: Any,
|
||||
flow: Any,
|
||||
node_positions: Dict[str, Tuple[float, float]],
|
||||
colors: Dict[str, str]
|
||||
colors: Dict[str, str],
|
||||
) -> None:
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, db_path: Optional[str] = None
|
||||
) -> None:
|
||||
def __init__(self, db_path: Optional[str] = None) -> None:
|
||||
if db_path is None:
|
||||
# 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")
|
||||
@@ -146,7 +144,9 @@ class KickoffTaskOutputsSQLiteStorage:
|
||||
conn.commit()
|
||||
|
||||
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:
|
||||
error_msg = DatabaseError.format_error(DatabaseError.UPDATE_ERROR, e)
|
||||
logger.error(error_msg)
|
||||
|
||||
@@ -12,9 +12,7 @@ class LTMSQLiteStorage:
|
||||
An updated SQLite storage class for LTM data storage.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, db_path: Optional[str] = None
|
||||
) -> None:
|
||||
def __init__(self, db_path: Optional[str] = None) -> None:
|
||||
if db_path is None:
|
||||
# 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")
|
||||
|
||||
@@ -170,9 +170,13 @@ def CrewBase(cls: T) -> T:
|
||||
|
||||
if function_calling_llm := agent_info.get("function_calling_llm"):
|
||||
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:
|
||||
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"):
|
||||
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
|
||||
"""
|
||||
|
||||
uuid_str: str = Field(default_factory=lambda: str(uuid.uuid4()), 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")
|
||||
uuid_str: str = Field(
|
||||
default_factory=lambda: str(uuid.uuid4()),
|
||||
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)
|
||||
|
||||
@field_validator('metadata')
|
||||
|
||||
@field_validator("metadata")
|
||||
@classmethod
|
||||
def validate_metadata(cls, v):
|
||||
"""Validate that metadata is a dictionary with string keys and valid values."""
|
||||
if not isinstance(v, dict):
|
||||
raise ValueError("Metadata must be a dictionary")
|
||||
|
||||
|
||||
# Validate that all keys are strings
|
||||
for key, value in v.items():
|
||||
if not isinstance(key, str):
|
||||
raise ValueError(f"Metadata keys must be strings, got {type(key)}")
|
||||
|
||||
|
||||
# Validate nested dictionaries (prevent deeply nested structures)
|
||||
if isinstance(value, dict):
|
||||
# Check for nested dictionaries (limit depth to 1)
|
||||
for nested_key, nested_value in value.items():
|
||||
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):
|
||||
raise ValueError("Metadata can only be nested one level deep")
|
||||
|
||||
|
||||
# Check for maximum metadata size (prevent DoS)
|
||||
if len(str(v)) > 10000: # Limit metadata size to 10KB
|
||||
raise ValueError("Metadata size exceeds maximum allowed (10KB)")
|
||||
|
||||
|
||||
return v
|
||||
|
||||
def __init__(self, **data):
|
||||
"""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
|
||||
if 'uuid_str' in data:
|
||||
data.pop('uuid_str')
|
||||
if 'created_at' in data:
|
||||
data.pop('created_at')
|
||||
if "uuid_str" in data:
|
||||
data.pop("uuid_str")
|
||||
if "created_at" in data:
|
||||
data.pop("created_at")
|
||||
|
||||
# Call the parent constructor with the modified data
|
||||
super().__init__(**data)
|
||||
@@ -88,19 +97,21 @@ class Fingerprint(BaseModel):
|
||||
"""
|
||||
if not isinstance(seed, str):
|
||||
raise ValueError("Seed must be a string")
|
||||
|
||||
|
||||
if not seed.strip():
|
||||
raise ValueError("Seed cannot be empty or whitespace")
|
||||
|
||||
|
||||
# Create a deterministic UUID using v5 (SHA-1)
|
||||
# Custom namespace for CrewAI to enhance security
|
||||
|
||||
# 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))
|
||||
|
||||
@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.
|
||||
|
||||
@@ -115,7 +126,7 @@ class Fingerprint(BaseModel):
|
||||
fingerprint = cls(metadata=metadata or {})
|
||||
if seed:
|
||||
# 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
|
||||
|
||||
def __str__(self) -> str:
|
||||
@@ -142,11 +153,11 @@ class Fingerprint(BaseModel):
|
||||
return {
|
||||
"uuid_str": self.uuid_str,
|
||||
"created_at": self.created_at.isoformat(),
|
||||
"metadata": self.metadata
|
||||
"metadata": self.metadata,
|
||||
}
|
||||
|
||||
@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.
|
||||
|
||||
@@ -163,8 +174,10 @@ class Fingerprint(BaseModel):
|
||||
|
||||
# For consistency with existing stored fingerprints, we need to manually set these
|
||||
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):
|
||||
object.__setattr__(fingerprint, 'created_at', datetime.fromisoformat(data["created_at"]))
|
||||
object.__setattr__(
|
||||
fingerprint, "created_at", datetime.fromisoformat(data["created_at"])
|
||||
)
|
||||
|
||||
return fingerprint
|
||||
|
||||
@@ -38,29 +38,27 @@ class SecurityConfig(BaseModel):
|
||||
)
|
||||
|
||||
version: str = Field(
|
||||
default="1.0.0",
|
||||
description="Version of the security configuration"
|
||||
default="1.0.0", description="Version of the security configuration"
|
||||
)
|
||||
|
||||
fingerprint: Fingerprint = Field(
|
||||
default_factory=Fingerprint,
|
||||
description="Unique identifier for the component"
|
||||
default_factory=Fingerprint, description="Unique identifier for the component"
|
||||
)
|
||||
|
||||
|
||||
def is_compatible(self, min_version: str) -> bool:
|
||||
"""
|
||||
Check if this security configuration is compatible with the minimum required version.
|
||||
|
||||
|
||||
Args:
|
||||
min_version (str): Minimum required version in semver format (e.g., "1.0.0")
|
||||
|
||||
|
||||
Returns:
|
||||
bool: True if this configuration is compatible, False otherwise
|
||||
"""
|
||||
# Simple version comparison (can be enhanced with packaging.version if needed)
|
||||
current = [int(x) for x in self.version.split(".")]
|
||||
minimum = [int(x) for x in min_version.split(".")]
|
||||
|
||||
|
||||
# Compare major, minor, patch versions
|
||||
for c, m in zip(current, minimum):
|
||||
if c > m:
|
||||
@@ -69,19 +67,19 @@ class SecurityConfig(BaseModel):
|
||||
return False
|
||||
return True
|
||||
|
||||
@model_validator(mode='before')
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def validate_fingerprint(cls, values):
|
||||
"""Ensure fingerprint is properly initialized."""
|
||||
if isinstance(values, dict):
|
||||
# Handle case where fingerprint is not provided or is None
|
||||
if 'fingerprint' not in values or values['fingerprint'] is None:
|
||||
values['fingerprint'] = Fingerprint()
|
||||
if "fingerprint" not in values or values["fingerprint"] is None:
|
||||
values["fingerprint"] = Fingerprint()
|
||||
# Handle case where fingerprint is a string (seed)
|
||||
elif isinstance(values['fingerprint'], str):
|
||||
if not values['fingerprint'].strip():
|
||||
elif isinstance(values["fingerprint"], str):
|
||||
if not values["fingerprint"].strip():
|
||||
raise ValueError("Fingerprint seed cannot be empty")
|
||||
values['fingerprint'] = Fingerprint.generate(seed=values['fingerprint'])
|
||||
values["fingerprint"] = Fingerprint.generate(seed=values["fingerprint"])
|
||||
return values
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
@@ -91,13 +89,11 @@ class SecurityConfig(BaseModel):
|
||||
Returns:
|
||||
Dict[str, Any]: Dictionary representation of the security config
|
||||
"""
|
||||
result = {
|
||||
"fingerprint": self.fingerprint.to_dict()
|
||||
}
|
||||
result = {"fingerprint": self.fingerprint.to_dict()}
|
||||
return result
|
||||
|
||||
@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.
|
||||
|
||||
@@ -111,6 +107,10 @@ class SecurityConfig(BaseModel):
|
||||
data_copy = data.copy()
|
||||
|
||||
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)
|
||||
|
||||
@@ -193,7 +193,6 @@ class Task(BaseModel):
|
||||
# Check return annotation if present, but don't require it
|
||||
return_annotation = sig.return_annotation
|
||||
if return_annotation != inspect.Signature.empty:
|
||||
|
||||
return_annotation_args = get_args(return_annotation)
|
||||
if not (
|
||||
get_origin(return_annotation) is tuple
|
||||
@@ -464,7 +463,9 @@ class Task(BaseModel):
|
||||
)
|
||||
)
|
||||
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
|
||||
except Exception as e:
|
||||
self.end_time = datetime.datetime.now()
|
||||
|
||||
@@ -22,6 +22,7 @@ class GuardrailResult(BaseModel):
|
||||
result (Any, optional): The validated/transformed result if successful
|
||||
error (str, optional): Error message if validation failed
|
||||
"""
|
||||
|
||||
success: bool
|
||||
result: Optional[Any] = None
|
||||
error: Optional[str] = None
|
||||
@@ -32,9 +33,13 @@ class GuardrailResult(BaseModel):
|
||||
values = info.data
|
||||
if "success" in values:
|
||||
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"]:
|
||||
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
|
||||
|
||||
@classmethod
|
||||
@@ -52,5 +57,5 @@ class GuardrailResult(BaseModel):
|
||||
return cls(
|
||||
success=success,
|
||||
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
|
||||
self.ready = False
|
||||
|
||||
|
||||
def _is_telemetry_disabled(self) -> bool:
|
||||
"""Check if telemetry should be disabled based on environment variables."""
|
||||
return (
|
||||
os.getenv("OTEL_SDK_DISABLED", "false").lower() == "true" or
|
||||
os.getenv("CREWAI_DISABLE_TELEMETRY", "false").lower() == "true"
|
||||
os.getenv("OTEL_SDK_DISABLED", "false").lower() == "true"
|
||||
or os.getenv("CREWAI_DISABLE_TELEMETRY", "false").lower() == "true"
|
||||
)
|
||||
|
||||
def set_tracer(self):
|
||||
|
||||
@@ -7,6 +7,19 @@ from crewai.utilities import I18N
|
||||
|
||||
i18n = I18N()
|
||||
|
||||
def _get_add_image_tool_name() -> str:
|
||||
"""Safely get the tool name from i18n."""
|
||||
tool_info = i18n.tools("add_image")
|
||||
if isinstance(tool_info, dict):
|
||||
return tool_info.get("name", "Add Image")
|
||||
return "Add Image" # Default name if not a dict
|
||||
|
||||
def _get_add_image_tool_description() -> str:
|
||||
"""Safely get the tool description from i18n."""
|
||||
tool_info = i18n.tools("add_image")
|
||||
if isinstance(tool_info, dict):
|
||||
return tool_info.get("description", "Tool for adding images to the content")
|
||||
return "Tool for adding images to the content" # Default description if not a dict
|
||||
|
||||
class AddImageToolSchema(BaseModel):
|
||||
image_url: str = Field(..., description="The URL or path of the image to add")
|
||||
@@ -18,8 +31,8 @@ class AddImageToolSchema(BaseModel):
|
||||
class AddImageTool(BaseTool):
|
||||
"""Tool for adding images to the content"""
|
||||
|
||||
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
|
||||
name: str = Field(default_factory=_get_add_image_tool_name)
|
||||
description: str = Field(default_factory=_get_add_image_tool_description)
|
||||
args_schema: type[BaseModel] = AddImageToolSchema
|
||||
|
||||
def _run(
|
||||
|
||||
@@ -47,10 +47,7 @@ class BaseAgentTool(BaseTool):
|
||||
return coworker
|
||||
|
||||
def _execute(
|
||||
self,
|
||||
agent_name: Optional[str],
|
||||
task: str,
|
||||
context: Optional[str] = None
|
||||
self, agent_name: Optional[str], task: str, context: Optional[str] = None
|
||||
) -> str:
|
||||
"""
|
||||
Execute delegation to an agent with case-insensitive and whitespace-tolerant matching.
|
||||
@@ -77,36 +74,46 @@ class BaseAgentTool(BaseTool):
|
||||
# when it should look like this:
|
||||
# {"task": "....", "coworker": "...."}
|
||||
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]
|
||||
logger.debug(f"Available agents: {available_agents}")
|
||||
|
||||
agent = [ # type: ignore # Incompatible types in assignment (expression has type "list[BaseAgent]", variable has type "str | None")
|
||||
matching_agents = [
|
||||
available_agent
|
||||
for available_agent in self.agents
|
||||
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(matching_agents)} matching agents for role '{sanitized_name}'"
|
||||
)
|
||||
except (AttributeError, ValueError) as e:
|
||||
# Handle specific exceptions that might occur during role name processing
|
||||
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
||||
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 matching_agents:
|
||||
# No matching agent found after sanitization
|
||||
return self.i18n.errors("agent_tool_unexisting_coworker").format(
|
||||
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: BaseAgent = matching_agents[0]
|
||||
try:
|
||||
task_with_assigned_agent = Task(
|
||||
description=task,
|
||||
@@ -114,11 +121,12 @@ class BaseAgentTool(BaseTool):
|
||||
expected_output=agent.i18n.slice("manager_request"),
|
||||
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)
|
||||
except Exception as e:
|
||||
# Handle task creation or execution errors
|
||||
return self.i18n.errors("agent_tool_execution_error").format(
|
||||
agent_role=self.sanitize_agent_name(agent.role),
|
||||
error=str(e)
|
||||
agent_role=self.sanitize_agent_name(agent.role), error=str(e)
|
||||
)
|
||||
|
||||
@@ -247,7 +247,7 @@ def to_langchain(
|
||||
def tool(*args, result_as_answer=False):
|
||||
"""
|
||||
Decorator to create a tool from a function.
|
||||
|
||||
|
||||
Args:
|
||||
*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.
|
||||
|
||||
@@ -380,6 +380,7 @@ class ToolUsage:
|
||||
else ToolCalling
|
||||
)
|
||||
converter = Converter(
|
||||
agent=None, # Agent not needed here as function calling is supported/used
|
||||
text=f"Only tools available:\n###\n{self._render()}\n\nReturn a valid schema for the tool, the tool name must be exactly equal one of the options, use this text to inform the valid output schema:\n\n### TEXT \n{tool_string}",
|
||||
llm=self.function_calling_llm,
|
||||
model=model,
|
||||
|
||||
@@ -2,7 +2,7 @@ import json
|
||||
import re
|
||||
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.utilities.printer import Printer
|
||||
@@ -20,18 +20,27 @@ class ConverterError(Exception):
|
||||
class Converter(OutputConverter):
|
||||
"""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:
|
||||
"""Convert text to pydantic."""
|
||||
try:
|
||||
if self.llm.supports_function_calling():
|
||||
result = self._create_instructor().to_pydantic()
|
||||
else:
|
||||
response = self.llm.call(
|
||||
[
|
||||
{"role": "system", "content": self.instructions},
|
||||
{"role": "user", "content": self.text},
|
||||
]
|
||||
)
|
||||
messages = []
|
||||
if self.agent and getattr(self.agent, "use_system_prompt", True):
|
||||
messages.append({"role": "system", "content": self.instructions})
|
||||
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 to directly validate the response JSON
|
||||
result = self.model.model_validate_json(response)
|
||||
@@ -74,14 +83,20 @@ class Converter(OutputConverter):
|
||||
if self.llm.supports_function_calling():
|
||||
return self._create_instructor().to_json()
|
||||
else:
|
||||
return json.dumps(
|
||||
self.llm.call(
|
||||
[
|
||||
{"role": "system", "content": self.instructions},
|
||||
{"role": "user", "content": self.text},
|
||||
]
|
||||
messages = []
|
||||
if self.agent and getattr(self.agent, "use_system_prompt", True):
|
||||
messages.append({"role": "system", "content": self.instructions})
|
||||
messages.append({"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:
|
||||
if current_attempt < self.max_attempts:
|
||||
return self.to_json(current_attempt + 1)
|
||||
@@ -239,11 +254,11 @@ def create_converter(
|
||||
) -> Converter:
|
||||
if agent and not converter_cls:
|
||||
if hasattr(agent, "get_output_converter"):
|
||||
converter = agent.get_output_converter(*args, **kwargs)
|
||||
converter = agent.get_output_converter(agent=agent, *args, **kwargs)
|
||||
else:
|
||||
raise AttributeError("Agent does not have a 'get_output_converter' method")
|
||||
elif converter_cls:
|
||||
converter = converter_cls(*args, **kwargs)
|
||||
converter = converter_cls(agent=agent, *args, **kwargs)
|
||||
else:
|
||||
raise ValueError("Either agent or converter_cls must be provided")
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from pydantic import BaseModel
|
||||
|
||||
class CrewJSONEncoder(json.JSONEncoder):
|
||||
"""Custom JSON encoder for CrewAI objects and special types."""
|
||||
|
||||
def default(self, obj):
|
||||
if isinstance(obj, BaseModel):
|
||||
return self._handle_pydantic_model(obj)
|
||||
|
||||
@@ -8,6 +8,7 @@ from crewai.agents.parser import OutputParserException
|
||||
|
||||
"""Parser for converting text outputs into Pydantic models."""
|
||||
|
||||
|
||||
class CrewPydanticOutputParser:
|
||||
"""Parses text outputs into specified Pydantic models."""
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Error message definitions for CrewAI database operations."""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
|
||||
@@ -65,13 +65,18 @@ class TaskEvaluator:
|
||||
instructions = f"{instructions}\n\nReturn only valid JSON with the following schema:\n```json\n{model_schema}\n```"
|
||||
|
||||
converter = Converter(
|
||||
agent=self.original_agent, # Pass agent
|
||||
llm=self.llm,
|
||||
text=evaluation_query,
|
||||
model=TaskEvaluation,
|
||||
instructions=instructions,
|
||||
)
|
||||
|
||||
return converter.to_pydantic()
|
||||
result = converter.to_pydantic()
|
||||
if isinstance(result, TaskEvaluation):
|
||||
return result
|
||||
else:
|
||||
raise TypeError(f"Expected TaskEvaluation, got {type(result)}")
|
||||
|
||||
def evaluate_training_data(
|
||||
self, training_data: dict, agent_id: str
|
||||
@@ -134,6 +139,7 @@ class TaskEvaluator:
|
||||
instructions = f"{instructions}\n\nThe json should have the following structure, with the following keys:\n{model_schema}"
|
||||
|
||||
converter = Converter(
|
||||
agent=self.original_agent, # Pass agent
|
||||
llm=self.llm,
|
||||
text=evaluation_query,
|
||||
model=TrainingTaskEvaluation,
|
||||
@@ -141,4 +147,7 @@ class TaskEvaluator:
|
||||
)
|
||||
|
||||
pydantic_result = converter.to_pydantic()
|
||||
return pydantic_result
|
||||
if isinstance(pydantic_result, TrainingTaskEvaluation):
|
||||
return pydantic_result
|
||||
else:
|
||||
raise TypeError(f"Expected TrainingTaskEvaluation, got {type(pydantic_result)}")
|
||||
|
||||
@@ -7,27 +7,33 @@ from typing import Union
|
||||
|
||||
class FileHandler:
|
||||
"""Handler for file operations supporting both JSON and text-based logging.
|
||||
|
||||
|
||||
Args:
|
||||
file_path (Union[bool, str]): Path to the log file or boolean flag
|
||||
"""
|
||||
|
||||
def __init__(self, file_path: Union[bool, str]):
|
||||
self._initialize_path(file_path)
|
||||
|
||||
|
||||
def _initialize_path(self, file_path: Union[bool, str]):
|
||||
if file_path is True: # File path is boolean True
|
||||
self._path = os.path.join(os.curdir, "logs.txt")
|
||||
|
||||
|
||||
elif isinstance(file_path, str): # File path is a string
|
||||
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:
|
||||
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:
|
||||
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):
|
||||
try:
|
||||
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
@@ -45,20 +51,25 @@ class FileHandler:
|
||||
except (json.JSONDecodeError, FileNotFoundError):
|
||||
# If no valid JSON or file doesn't exist, start with an empty list
|
||||
existing_data = [log_entry]
|
||||
|
||||
|
||||
with open(self._path, "w", encoding="utf-8") as write_file:
|
||||
json.dump(existing_data, write_file, indent=4)
|
||||
write_file.write("\n")
|
||||
|
||||
|
||||
else:
|
||||
# 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:
|
||||
file.write(message)
|
||||
|
||||
except Exception as e:
|
||||
raise ValueError(f"Failed to log message: {str(e)}")
|
||||
|
||||
|
||||
|
||||
class PickleHandler:
|
||||
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."""
|
||||
|
||||
|
||||
class I18N(BaseModel):
|
||||
"""Handles loading and retrieving internationalized prompts."""
|
||||
|
||||
_prompts: Dict[str, Dict[str, str]] = PrivateAttr()
|
||||
prompt_file: Optional[str] = Field(
|
||||
default=None,
|
||||
|
||||
@@ -5,6 +5,7 @@ import appdirs
|
||||
|
||||
"""Path management utilities for CrewAI storage and configuration."""
|
||||
|
||||
|
||||
def db_storage_path() -> str:
|
||||
"""Returns the path for SQLite database storage.
|
||||
|
||||
@@ -28,4 +29,4 @@ def get_project_directory_name():
|
||||
else:
|
||||
cwd = Path.cwd()
|
||||
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."""
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PlanPerTask(BaseModel):
|
||||
"""Represents a plan for a specific task."""
|
||||
|
||||
task: str = Field(..., description="The task for which the plan is created")
|
||||
plan: str = Field(
|
||||
...,
|
||||
@@ -20,6 +22,7 @@ class PlanPerTask(BaseModel):
|
||||
|
||||
class PlannerTaskPydanticOutput(BaseModel):
|
||||
"""Output format for task planning results."""
|
||||
|
||||
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",
|
||||
@@ -28,6 +31,7 @@ class PlannerTaskPydanticOutput(BaseModel):
|
||||
|
||||
class CrewPlanner:
|
||||
"""Plans and coordinates the execution of crew tasks."""
|
||||
|
||||
def __init__(self, tasks: List[Task], planning_agent_llm: Optional[Any] = None):
|
||||
self.tasks = tasks
|
||||
|
||||
@@ -97,8 +101,12 @@ class CrewPlanner:
|
||||
for idx, task in enumerate(self.tasks):
|
||||
knowledge_list = self._get_agent_knowledge(task)
|
||||
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',\n "agent_knowledge": "[\\"{knowledge_list[0]}\\"]"' if knowledge_list and str(knowledge_list) != "None" else ""
|
||||
f"[{', '.join(str(tool) for tool in task.agent.tools)}]"
|
||||
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 Number {idx + 1} - {task.description}
|
||||
|
||||
@@ -10,8 +10,10 @@ from crewai.task import Task
|
||||
|
||||
"""Handles storage and retrieval of task execution outputs."""
|
||||
|
||||
|
||||
class ExecutionLog(BaseModel):
|
||||
"""Represents a log entry for task execution."""
|
||||
|
||||
task_id: str
|
||||
expected_output: Optional[str] = None
|
||||
output: Dict[str, Any]
|
||||
@@ -26,6 +28,7 @@ class ExecutionLog(BaseModel):
|
||||
|
||||
"""Manages storage and retrieval of task outputs."""
|
||||
|
||||
|
||||
class TaskOutputStorageHandler:
|
||||
def __init__(self) -> None:
|
||||
self.storage = KickoffTaskOutputsSQLiteStorage()
|
||||
|
||||
@@ -259,7 +259,9 @@ def test_cache_hitting():
|
||||
def handle_tool_end(source, event):
|
||||
received_events.append(event)
|
||||
|
||||
with (patch.object(CacheHandler, "read") as read,):
|
||||
with (
|
||||
patch.object(CacheHandler, "read") as read,
|
||||
):
|
||||
read.return_value = "0"
|
||||
task = Task(
|
||||
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)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_test_environment():
|
||||
"""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
|
||||
storage_dir = Path(temp_dir) / "crewai_test_storage"
|
||||
storage_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
# Validate that the directory was created successfully
|
||||
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
|
||||
try:
|
||||
# Try to create a test file to verify write permissions
|
||||
@@ -27,11 +30,13 @@ def setup_test_environment():
|
||||
test_file.touch()
|
||||
test_file.unlink()
|
||||
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
|
||||
os.environ["CREWAI_STORAGE_DIR"] = str(storage_dir)
|
||||
|
||||
|
||||
yield
|
||||
|
||||
|
||||
# Cleanup is handled automatically when tempfile context exits
|
||||
|
||||
@@ -2157,7 +2157,6 @@ def test_tools_with_custom_caching():
|
||||
with patch.object(
|
||||
CacheHandler, "add", wraps=crew._cache_handler.add
|
||||
) as add_to_cache:
|
||||
|
||||
result = crew.kickoff()
|
||||
|
||||
# Check that add_to_cache was called exactly twice
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
def test_task_output_import():
|
||||
"""Test that TaskOutput can be imported from crewai."""
|
||||
from crewai import TaskOutput
|
||||
|
||||
|
||||
assert TaskOutput is not None
|
||||
|
||||
|
||||
|
||||
|
||||
def test_crew_output_import():
|
||||
"""Test that CrewOutput can be imported from crewai."""
|
||||
from crewai import CrewOutput
|
||||
|
||||
|
||||
assert CrewOutput is not None
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
@@ -12,6 +11,7 @@ class MockCrew:
|
||||
def __init__(self, memory_config):
|
||||
self.memory_config = memory_config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_memory():
|
||||
"""Fixture to create a UserMemory instance"""
|
||||
@@ -19,17 +19,18 @@ def user_memory():
|
||||
memory_config={
|
||||
"provider": "mem0",
|
||||
"config": {"user_id": "john"},
|
||||
"user_memory" : {}
|
||||
"user_memory": {},
|
||||
}
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
return user_memory_instance
|
||||
|
||||
|
||||
def test_save_and_search(user_memory):
|
||||
memory = UserMemoryItem(
|
||||
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:
|
||||
user_memory.save(
|
||||
value=memory.data,
|
||||
metadata=memory.metadata,
|
||||
user=memory.user
|
||||
)
|
||||
user_memory.save(value=memory.data, metadata=memory.metadata, user=memory.user)
|
||||
|
||||
mock_save.assert_called_once_with(
|
||||
value=memory.data,
|
||||
metadata=memory.metadata,
|
||||
user=memory.user
|
||||
value=memory.data, metadata=memory.metadata, user=memory.user
|
||||
)
|
||||
|
||||
expected_result = [
|
||||
@@ -62,7 +57,9 @@ def test_save_and_search(user_memory):
|
||||
expected_result = ["mocked_result"]
|
||||
|
||||
# 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]
|
||||
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
|
||||
def local_llm(self):
|
||||
return LLM(
|
||||
model='openai/model_name',
|
||||
model="openai/model_name",
|
||||
api_key="None",
|
||||
base_url="http://xxx.xxx.xxx.xxx:8000/v1")
|
||||
base_url="http://xxx.xxx.xxx.xxx:8000/v1",
|
||||
)
|
||||
|
||||
@agent
|
||||
def researcher(self):
|
||||
|
||||
@@ -54,7 +54,7 @@ def test_agent_with_deterministic_fingerprint():
|
||||
role="Researcher",
|
||||
goal="Research quantum computing",
|
||||
backstory="Expert in quantum physics",
|
||||
security_config=security_config
|
||||
security_config=security_config,
|
||||
)
|
||||
|
||||
# Create another agent with the same security config
|
||||
@@ -62,7 +62,7 @@ def test_agent_with_deterministic_fingerprint():
|
||||
role="Completely different role",
|
||||
goal="Different goal",
|
||||
backstory="Different backstory",
|
||||
security_config=security_config
|
||||
security_config=security_config,
|
||||
)
|
||||
|
||||
# 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)
|
||||
agent = Agent(
|
||||
role="Assistant",
|
||||
goal="Help with tasks",
|
||||
backstory="Helpful AI assistant"
|
||||
role="Assistant", goal="Help with tasks", backstory="Helpful AI assistant"
|
||||
)
|
||||
|
||||
# Create a task with the deterministic fingerprint
|
||||
@@ -94,7 +92,7 @@ def test_task_with_deterministic_fingerprint():
|
||||
description="Analyze data",
|
||||
expected_output="Data analysis report",
|
||||
agent=agent,
|
||||
security_config=security_config
|
||||
security_config=security_config,
|
||||
)
|
||||
|
||||
# Create another task with the same security config
|
||||
@@ -102,7 +100,7 @@ def test_task_with_deterministic_fingerprint():
|
||||
description="Different task description",
|
||||
expected_output="Different expected output",
|
||||
agent=agent,
|
||||
security_config=security_config
|
||||
security_config=security_config,
|
||||
)
|
||||
|
||||
# Both tasks should have the same fingerprint UUID
|
||||
@@ -119,36 +117,18 @@ def test_crew_with_deterministic_fingerprint():
|
||||
|
||||
# Create agents for the crew
|
||||
agent1 = Agent(
|
||||
role="Researcher",
|
||||
goal="Research information",
|
||||
backstory="Expert researcher"
|
||||
role="Researcher", goal="Research information", backstory="Expert researcher"
|
||||
)
|
||||
|
||||
agent2 = Agent(
|
||||
role="Writer",
|
||||
goal="Write reports",
|
||||
backstory="Expert writer"
|
||||
)
|
||||
agent2 = Agent(role="Writer", goal="Write reports", backstory="Expert writer")
|
||||
|
||||
# Create a crew with the deterministic fingerprint
|
||||
crew1 = Crew(
|
||||
agents=[agent1, agent2],
|
||||
tasks=[],
|
||||
security_config=security_config
|
||||
)
|
||||
crew1 = Crew(agents=[agent1, agent2], tasks=[], security_config=security_config)
|
||||
|
||||
# Create another crew with the same security config but different agents
|
||||
agent3 = Agent(
|
||||
role="Analyst",
|
||||
goal="Analyze data",
|
||||
backstory="Expert analyst"
|
||||
)
|
||||
agent3 = Agent(role="Analyst", goal="Analyze data", backstory="Expert analyst")
|
||||
|
||||
crew2 = Crew(
|
||||
agents=[agent3],
|
||||
tasks=[],
|
||||
security_config=security_config
|
||||
)
|
||||
crew2 = Crew(agents=[agent3], tasks=[], security_config=security_config)
|
||||
|
||||
# Both crews should have the same fingerprint UUID
|
||||
assert crew1.fingerprint.uuid_str == crew2.fingerprint.uuid_str
|
||||
@@ -168,7 +148,7 @@ def test_recreating_components_with_same_seed():
|
||||
role="Researcher",
|
||||
goal="Research topic",
|
||||
backstory="Expert researcher",
|
||||
security_config=security_config1
|
||||
security_config=security_config1,
|
||||
)
|
||||
|
||||
uuid_from_first_session = agent1.fingerprint.uuid_str
|
||||
@@ -181,7 +161,7 @@ def test_recreating_components_with_same_seed():
|
||||
role="Researcher",
|
||||
goal="Research topic",
|
||||
backstory="Expert researcher",
|
||||
security_config=security_config2
|
||||
security_config=security_config2,
|
||||
)
|
||||
|
||||
# Should have same UUID across sessions
|
||||
@@ -209,7 +189,7 @@ def test_security_config_with_seed_string():
|
||||
role="Tester",
|
||||
goal="Test fingerprints",
|
||||
backstory="Expert tester",
|
||||
security_config=security_config
|
||||
security_config=security_config,
|
||||
)
|
||||
|
||||
# Agent should have the same fingerprint UUID
|
||||
@@ -236,7 +216,7 @@ def test_complex_component_hierarchy_with_deterministic_fingerprints():
|
||||
role="Complex Test Agent",
|
||||
goal="Test complex fingerprint scenarios",
|
||||
backstory="Expert in testing",
|
||||
security_config=agent_config
|
||||
security_config=agent_config,
|
||||
)
|
||||
|
||||
# Create a task
|
||||
@@ -244,15 +224,11 @@ def test_complex_component_hierarchy_with_deterministic_fingerprints():
|
||||
description="Test complex fingerprinting",
|
||||
expected_output="Verification of fingerprint stability",
|
||||
agent=agent,
|
||||
security_config=task_config
|
||||
security_config=task_config,
|
||||
)
|
||||
|
||||
# Create a crew
|
||||
crew = Crew(
|
||||
agents=[agent],
|
||||
tasks=[task],
|
||||
security_config=crew_config
|
||||
)
|
||||
crew = Crew(agents=[agent], tasks=[task], security_config=crew_config)
|
||||
|
||||
# Each component should have its own deterministic fingerprint
|
||||
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 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 = {
|
||||
"uuid_str": uuid_str,
|
||||
"created_at": created_at_iso,
|
||||
"metadata": metadata
|
||||
"metadata": metadata,
|
||||
}
|
||||
|
||||
fingerprint = Fingerprint.from_dict(fingerprint_dict)
|
||||
@@ -207,11 +207,7 @@ def test_invalid_uuid_str():
|
||||
uuid_str = "not-a-valid-uuid"
|
||||
created_at = datetime.now().isoformat()
|
||||
|
||||
fingerprint_dict = {
|
||||
"uuid_str": uuid_str,
|
||||
"created_at": created_at,
|
||||
"metadata": {}
|
||||
}
|
||||
fingerprint_dict = {"uuid_str": uuid_str, "created_at": created_at, "metadata": {}}
|
||||
|
||||
# The Fingerprint.from_dict method accepts even invalid UUIDs
|
||||
# This seems to be the current behavior
|
||||
@@ -243,7 +239,7 @@ def test_fingerprint_metadata_mutation():
|
||||
expected_metadata = {
|
||||
"version": "1.0",
|
||||
"status": "published",
|
||||
"author": "Test Author"
|
||||
"author": "Test Author",
|
||||
}
|
||||
assert fingerprint.metadata == expected_metadata
|
||||
|
||||
@@ -260,4 +256,4 @@ def test_fingerprint_metadata_mutation():
|
||||
|
||||
# Ensure immutable fields remain unchanged
|
||||
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",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting",
|
||||
security_config=security_config
|
||||
security_config=security_config,
|
||||
)
|
||||
|
||||
assert agent.security_config is not None
|
||||
@@ -28,9 +28,7 @@ def test_agent_fingerprint_property():
|
||||
"""Test the fingerprint property on Agent."""
|
||||
# Create agent without security_config
|
||||
agent = Agent(
|
||||
role="Tester",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
# Fingerprint should be automatically generated
|
||||
@@ -45,21 +43,14 @@ def test_crew_with_security_config():
|
||||
security_config = SecurityConfig()
|
||||
|
||||
agent1 = Agent(
|
||||
role="Tester1",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester1", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
agent2 = Agent(
|
||||
role="Tester2",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester2", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[agent1, agent2],
|
||||
security_config=security_config
|
||||
)
|
||||
crew = Crew(agents=[agent1, agent2], security_config=security_config)
|
||||
|
||||
assert crew.security_config is not None
|
||||
assert crew.security_config == security_config
|
||||
@@ -71,15 +62,11 @@ def test_crew_fingerprint_property():
|
||||
"""Test the fingerprint property on Crew."""
|
||||
# Create crew without security_config
|
||||
agent1 = Agent(
|
||||
role="Tester1",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester1", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
agent2 = Agent(
|
||||
role="Tester2",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester2", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
crew = Crew(agents=[agent1, agent2])
|
||||
@@ -96,16 +83,14 @@ def test_task_with_security_config():
|
||||
security_config = SecurityConfig()
|
||||
|
||||
agent = Agent(
|
||||
role="Tester",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description="Test task",
|
||||
expected_output="Testing output",
|
||||
agent=agent,
|
||||
security_config=security_config
|
||||
security_config=security_config,
|
||||
)
|
||||
|
||||
assert task.security_config is not None
|
||||
@@ -118,16 +103,10 @@ def test_task_fingerprint_property():
|
||||
"""Test the fingerprint property on Task."""
|
||||
# Create task without security_config
|
||||
agent = Agent(
|
||||
role="Tester",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description="Test task",
|
||||
expected_output="Testing output",
|
||||
agent=agent
|
||||
)
|
||||
task = Task(description="Test task", expected_output="Testing output", agent=agent)
|
||||
|
||||
# Fingerprint should be automatically generated
|
||||
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."""
|
||||
# Create components with auto-generated fingerprints
|
||||
agent1 = Agent(
|
||||
role="Researcher",
|
||||
goal="Research information",
|
||||
backstory="Expert researcher"
|
||||
role="Researcher", goal="Research information", backstory="Expert researcher"
|
||||
)
|
||||
|
||||
agent2 = Agent(
|
||||
role="Writer",
|
||||
goal="Write content",
|
||||
backstory="Expert writer"
|
||||
)
|
||||
agent2 = Agent(role="Writer", goal="Write content", backstory="Expert writer")
|
||||
|
||||
task1 = Task(
|
||||
description="Research topic",
|
||||
expected_output="Research findings",
|
||||
agent=agent1
|
||||
description="Research topic", expected_output="Research findings", agent=agent1
|
||||
)
|
||||
|
||||
task2 = Task(
|
||||
description="Write article",
|
||||
expected_output="Written article",
|
||||
agent=agent2
|
||||
description="Write article", expected_output="Written article", agent=agent2
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[agent1, agent2],
|
||||
tasks=[task1, task2]
|
||||
)
|
||||
crew = Crew(agents=[agent1, agent2], tasks=[task1, task2])
|
||||
|
||||
# Verify all fingerprints were automatically generated
|
||||
assert agent1.fingerprint is not None
|
||||
@@ -180,18 +146,18 @@ def test_end_to_end_fingerprinting():
|
||||
agent2.fingerprint.uuid_str,
|
||||
task1.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():
|
||||
"""Test that fingerprints persist and don't change."""
|
||||
# Create an agent and check its fingerprint
|
||||
agent = Agent(
|
||||
role="Tester",
|
||||
goal="Test fingerprinting",
|
||||
backstory="Testing fingerprinting"
|
||||
role="Tester", goal="Test fingerprinting", backstory="Testing fingerprinting"
|
||||
)
|
||||
|
||||
# Get initial fingerprint
|
||||
@@ -201,11 +167,7 @@ def test_fingerprint_persistence():
|
||||
assert agent.fingerprint.uuid_str == initial_fingerprint
|
||||
|
||||
# Create a task with the agent
|
||||
task = Task(
|
||||
description="Test task",
|
||||
expected_output="Testing output",
|
||||
agent=agent
|
||||
)
|
||||
task = Task(description="Test task", expected_output="Testing output", agent=agent)
|
||||
|
||||
# Check that task has its own unique fingerprint
|
||||
assert task.fingerprint is not None
|
||||
@@ -223,27 +185,25 @@ def test_shared_security_config_fingerprints():
|
||||
role="Researcher",
|
||||
goal="Research information",
|
||||
backstory="Expert researcher",
|
||||
security_config=shared_security_config
|
||||
security_config=shared_security_config,
|
||||
)
|
||||
|
||||
agent2 = Agent(
|
||||
role="Writer",
|
||||
goal="Write content",
|
||||
backstory="Expert writer",
|
||||
security_config=shared_security_config
|
||||
security_config=shared_security_config,
|
||||
)
|
||||
|
||||
task = Task(
|
||||
description="Write article",
|
||||
expected_output="Written article",
|
||||
agent=agent1,
|
||||
security_config=shared_security_config
|
||||
security_config=shared_security_config,
|
||||
)
|
||||
|
||||
crew = Crew(
|
||||
agents=[agent1, agent2],
|
||||
tasks=[task],
|
||||
security_config=shared_security_config
|
||||
agents=[agent1, agent2], tasks=[task], security_config=shared_security_config
|
||||
)
|
||||
|
||||
# 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 agent2.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 = {
|
||||
"uuid_str": "b723c6ff-95de-5e87-860b-467b72282bd8",
|
||||
"created_at": datetime.now().isoformat(),
|
||||
"metadata": {"version": "1.0"}
|
||||
"metadata": {"version": "1.0"},
|
||||
}
|
||||
|
||||
# Create a config dict with just the fingerprint
|
||||
config_dict = {
|
||||
"fingerprint": fingerprint_dict
|
||||
}
|
||||
config_dict = {"fingerprint": fingerprint_dict}
|
||||
|
||||
# Create config manually since from_dict has a specific implementation
|
||||
config = SecurityConfig()
|
||||
@@ -115,4 +113,4 @@ def test_security_config_json_serialization():
|
||||
new_config.fingerprint = new_fingerprint
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
@pytest.mark.parametrize("env_var,value,expected_ready", [
|
||||
("OTEL_SDK_DISABLED", "true", False),
|
||||
("OTEL_SDK_DISABLED", "TRUE", False),
|
||||
("CREWAI_DISABLE_TELEMETRY", "true", False),
|
||||
("CREWAI_DISABLE_TELEMETRY", "TRUE", False),
|
||||
("OTEL_SDK_DISABLED", "false", True),
|
||||
("CREWAI_DISABLE_TELEMETRY", "false", True),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"env_var,value,expected_ready",
|
||||
[
|
||||
("OTEL_SDK_DISABLED", "true", False),
|
||||
("OTEL_SDK_DISABLED", "TRUE", False),
|
||||
("CREWAI_DISABLE_TELEMETRY", "true", False),
|
||||
("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):
|
||||
"""Test telemetry state with different environment variable configurations."""
|
||||
with patch.dict(os.environ, {env_var: value}):
|
||||
|
||||
@@ -6,6 +6,7 @@ from crewai.flow.persistence import persist
|
||||
|
||||
class PoemState(FlowState):
|
||||
"""Test state model with default values 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
|
||||
poem_type: str = ""
|
||||
@@ -46,11 +47,13 @@ def test_default_value_override():
|
||||
|
||||
# Fourth run - explicit override should work
|
||||
flow3 = PoemFlow()
|
||||
flow3.kickoff(inputs={
|
||||
"id": original_uuid,
|
||||
"has_set_count": True,
|
||||
"sentence_count": 5, # Override persisted value
|
||||
})
|
||||
flow3.kickoff(
|
||||
inputs={
|
||||
"id": original_uuid,
|
||||
"has_set_count": True,
|
||||
"sentence_count": 5, # Override persisted value
|
||||
}
|
||||
)
|
||||
assert flow3.state.sentence_count == 5 # Should use override value
|
||||
|
||||
# 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
|
||||
flow2 = MultiStepPoemFlow()
|
||||
flow2.kickoff(inputs={
|
||||
"id": original_uuid,
|
||||
"sentence_count": 5
|
||||
})
|
||||
flow2.kickoff(inputs={"id": original_uuid, "sentence_count": 5})
|
||||
assert flow2.state.sentence_count == 5
|
||||
assert flow2.state.poem_type == "limerick"
|
||||
|
||||
# Third run - new flow without persisted state should use defaults
|
||||
flow3 = MultiStepPoemFlow()
|
||||
flow3.kickoff(inputs={
|
||||
"id": original_uuid
|
||||
})
|
||||
flow3.kickoff(inputs={"id": original_uuid})
|
||||
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(
|
||||
model="openai/gpt-4o", # model with vision capabilities
|
||||
api_key=OPENAI_API_KEY,
|
||||
temperature=0.7
|
||||
temperature=0.7,
|
||||
)
|
||||
|
||||
expert_analyst = Agent(
|
||||
@@ -28,7 +28,7 @@ def test_multimodal_agent_with_image_url():
|
||||
llm=llm,
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
multimodal=True
|
||||
multimodal=True,
|
||||
)
|
||||
|
||||
inspection_task = Task(
|
||||
@@ -40,7 +40,7 @@ def test_multimodal_agent_with_image_url():
|
||||
Provide 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])
|
||||
|
||||
@@ -107,18 +107,18 @@ def test_result_as_answer_in_tool_decorator():
|
||||
def my_tool_with_result_as_answer(question: str) -> str:
|
||||
"""This tool will return its result as the final answer."""
|
||||
return question
|
||||
|
||||
|
||||
assert my_tool_with_result_as_answer.result_as_answer is True
|
||||
|
||||
|
||||
converted_tool = my_tool_with_result_as_answer.to_structured_tool()
|
||||
assert converted_tool.result_as_answer is True
|
||||
|
||||
|
||||
@tool("Tool with default result_as_answer")
|
||||
def my_tool_with_default(question: str) -> str:
|
||||
"""This tool uses the default result_as_answer value."""
|
||||
return question
|
||||
|
||||
|
||||
assert my_tool_with_default.result_as_answer is False
|
||||
|
||||
|
||||
converted_tool = my_tool_with_default.to_structured_tool()
|
||||
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
|
||||
@@ -46,6 +46,7 @@ def test_evaluate_training_data(converter_mock):
|
||||
converter_mock.assert_has_calls(
|
||||
[
|
||||
mock.call(
|
||||
agent=original_agent, # Add agent argument
|
||||
llm=original_agent.llm,
|
||||
text="Assess the quality of the training data based on the llm output, human feedback , and llm "
|
||||
"output improved result.\n\nIteration: data1\nInitial Output:\nInitial output 1\n\nHuman Feedback:\nHuman feedback "
|
||||
|
||||
@@ -197,6 +197,101 @@ def test_convert_with_instructions_success(
|
||||
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.get_conversion_instructions")
|
||||
def test_convert_with_instructions_failure(
|
||||
@@ -334,7 +429,10 @@ def test_convert_with_instructions():
|
||||
sample_text = "Name: Alice, Age: 30"
|
||||
|
||||
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(
|
||||
agent=mock_agent, # Add agent argument
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
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")
|
||||
sample_text = "Name: Alice Llama, Age: 30"
|
||||
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(
|
||||
agent=mock_agent, # Add agent argument
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=SimpleModel,
|
||||
@@ -380,7 +481,10 @@ def test_converter_with_llama3_1_model():
|
||||
llm = LLM(model="ollama/llama3.1", base_url="http://localhost:11434")
|
||||
sample_text = "Name: Alice Llama, Age: 30"
|
||||
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(
|
||||
agent=mock_agent, # Add agent argument
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
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"
|
||||
|
||||
instructions = get_conversion_instructions(Person, llm)
|
||||
mock_agent = Mock()
|
||||
mock_agent.use_system_prompt = True
|
||||
|
||||
converter = Converter(
|
||||
agent=mock_agent,
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=Person,
|
||||
@@ -431,7 +539,10 @@ def test_converter_error_handling():
|
||||
sample_text = "Name: Alice, Age: 30"
|
||||
|
||||
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(
|
||||
agent=mock_agent, # Add agent argument
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=SimpleModel,
|
||||
@@ -456,7 +567,11 @@ def test_converter_retry_logic():
|
||||
sample_text = "Name: Retry Alice, Age: 30"
|
||||
|
||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||
mock_agent = Mock()
|
||||
mock_agent.use_system_prompt = True
|
||||
|
||||
converter = Converter(
|
||||
agent=mock_agent,
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=SimpleModel,
|
||||
@@ -485,7 +600,11 @@ def test_converter_with_optional_fields():
|
||||
sample_text = "Name: Bob, age: None"
|
||||
|
||||
instructions = get_conversion_instructions(OptionalModel, llm)
|
||||
mock_agent = Mock()
|
||||
mock_agent.use_system_prompt = True
|
||||
|
||||
converter = Converter(
|
||||
agent=mock_agent,
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=OptionalModel,
|
||||
@@ -510,7 +629,11 @@ def test_converter_with_list_field():
|
||||
sample_text = "Items: 1, 2, 3"
|
||||
|
||||
instructions = get_conversion_instructions(ListModel, llm)
|
||||
mock_agent = Mock()
|
||||
mock_agent.use_system_prompt = True
|
||||
|
||||
converter = Converter(
|
||||
agent=mock_agent,
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=ListModel,
|
||||
@@ -543,7 +666,11 @@ def test_converter_with_enum():
|
||||
sample_text = "Name: Alice, Color: Red"
|
||||
|
||||
instructions = get_conversion_instructions(EnumModel, llm)
|
||||
mock_agent = Mock()
|
||||
mock_agent.use_system_prompt = True
|
||||
|
||||
converter = Converter(
|
||||
agent=mock_agent,
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=EnumModel,
|
||||
@@ -565,7 +692,11 @@ def test_converter_with_ambiguous_input():
|
||||
sample_text = "Charlie is thirty years old"
|
||||
|
||||
instructions = get_conversion_instructions(SimpleModel, llm)
|
||||
mock_agent = Mock()
|
||||
mock_agent.use_system_prompt = True
|
||||
|
||||
converter = Converter(
|
||||
agent=mock_agent,
|
||||
llm=llm,
|
||||
text=sample_text,
|
||||
model=SimpleModel,
|
||||
@@ -586,7 +717,11 @@ def test_converter_with_function_calling():
|
||||
instructor = Mock()
|
||||
instructor.to_pydantic.return_value = SimpleModel(name="Eve", age=35)
|
||||
|
||||
mock_agent = Mock()
|
||||
mock_agent.use_system_prompt = True
|
||||
|
||||
converter = Converter(
|
||||
agent=mock_agent,
|
||||
llm=llm,
|
||||
text="Name: Eve, Age: 35",
|
||||
model=SimpleModel,
|
||||
|
||||
@@ -29,13 +29,14 @@ def mock_knowledge_source():
|
||||
"""
|
||||
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):
|
||||
"""Test that verifies knowledge sources are properly included in planning."""
|
||||
# Mock ChromaDB collection
|
||||
mock_collection = mock_chroma.return_value.get_or_create_collection.return_value
|
||||
mock_collection.add.return_value = None
|
||||
|
||||
|
||||
# Create an agent with knowledge
|
||||
agent = Agent(
|
||||
role="AI Researcher",
|
||||
@@ -45,14 +46,14 @@ def test_knowledge_included_in_planning(mock_chroma):
|
||||
StringKnowledgeSource(
|
||||
content="AI systems require careful training and validation."
|
||||
)
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
# Create a task for the agent
|
||||
task = Task(
|
||||
description="Explain the basics of AI systems",
|
||||
expected_output="A clear explanation of AI fundamentals",
|
||||
agent=agent
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
# Create a crew planner
|
||||
@@ -62,23 +63,29 @@ def test_knowledge_included_in_planning(mock_chroma):
|
||||
task_summary = planner._create_tasks_summary()
|
||||
|
||||
# Verify that knowledge is included in planning when present
|
||||
assert "AI systems require careful training" in task_summary, \
|
||||
"Knowledge content 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"
|
||||
assert (
|
||||
"AI systems require careful training" in task_summary
|
||||
), "Knowledge content 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
|
||||
assert isinstance(task.agent.knowledge_sources, list), \
|
||||
"Knowledge sources should be stored in a list"
|
||||
assert len(task.agent.knowledge_sources) > 0, \
|
||||
"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"
|
||||
assert isinstance(
|
||||
task.agent.knowledge_sources, list
|
||||
), "Knowledge sources should be stored in a list"
|
||||
assert (
|
||||
len(task.agent.knowledge_sources) > 0
|
||||
), "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
|
||||
assert task.description in task_summary, \
|
||||
"Task description should be present in task summary"
|
||||
assert task.expected_output 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"
|
||||
assert (
|
||||
task.description in task_summary
|
||||
), "Task description should be present in task summary"
|
||||
assert (
|
||||
task.expected_output 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
|
||||
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):
|
||||
"""Test task summary generation with both knowledge and tools present."""
|
||||
# Mock ChromaDB collection
|
||||
@@ -146,8 +146,8 @@ class InternalCrewPlanner:
|
||||
tools=[tool1, tool2],
|
||||
knowledge_sources=[
|
||||
StringKnowledgeSource(content="Test knowledge content")
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
# Create planner with the new task
|
||||
|
||||
Reference in New Issue
Block a user