From 4e6e6b8054df7b3a6c20093a28ec60240c55034f Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:06:32 -0400 Subject: [PATCH 1/2] Remove infer_parent by improving attribute defaults --- src/controlflow/planning/plan.py | 1 - src/controlflow/settings.py | 2 +- src/controlflow/tasks/task.py | 25 +++++++++---------------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/controlflow/planning/plan.py b/src/controlflow/planning/plan.py index 32d738b7..fe717a99 100644 --- a/src/controlflow/planning/plan.py +++ b/src/controlflow/planning/plan.py @@ -87,7 +87,6 @@ def create_plan( or {}, agents=[planning_agent] if planning_agent else None, result_type=list[PlanTask], - infer_parent=False, ) # create a new flow to avoid polluting the main flow's history diff --git a/src/controlflow/settings.py b/src/controlflow/settings.py index 3554262d..e957e74b 100644 --- a/src/controlflow/settings.py +++ b/src/controlflow/settings.py @@ -69,7 +69,7 @@ class Settings(ControlFlowSettings): llm_model: str = Field( default="openai/gpt-4o", - description="The LLM model to use.", + description="The default LLM model for agents.", ) llm_temperature: float = Field(0.7, description="The temperature for LLM sampling.") max_input_tokens: int = Field( diff --git a/src/controlflow/tasks/task.py b/src/controlflow/tasks/task.py index 52564976..a2f59bce 100644 --- a/src/controlflow/tasks/task.py +++ b/src/controlflow/tasks/task.py @@ -86,7 +86,7 @@ class Task(ControlFlowModel): "context, they are automatically added as `depends_on`", ) parent: Optional["Task"] = Field( - None, + NOTSET, description="The parent task of this task. Subtasks are considered" " upstream dependencies of their parents.", validate_default=True, @@ -100,7 +100,7 @@ class Task(ControlFlowModel): status: TaskStatus = TaskStatus.PENDING result: Optional[Union[T, str]] = None result_type: Union[type[T], GenericAlias, _AnnotatedAlias, tuple, None] = Field( - str, + NOTSET, description="The expected type of the result. This should be a type" ", generic alias, BaseModel subclass, or list of choices. " "Can be None if no result is expected or the agent should communicate internally.", @@ -133,7 +133,6 @@ def __init__( self, objective: str = None, result_type: Any = NOTSET, - infer_parent: bool = True, user_access: bool = None, **kwargs, ): @@ -143,19 +142,13 @@ def __init__( Args: objective (str, optional): The objective of the task. Defaults to None. result_type (Any, optional): The type of the result. Defaults to NOTSET. - infer_parent (bool, optional): Whether to infer the parent task. Defaults to True. - agents (Optional[list[Agent]], optional): The list of agents - associated with the task. Defaults to None. + user_access (bool, optional): Whether the task is interactive. Defaults to None. **kwargs: Additional keyword arguments. """ # allow certain args to be provided as a positional args - if result_type is not NOTSET: - kwargs["result_type"] = result_type if objective is not None: kwargs["objective"] = objective - # if parent is None and infer parent is False, set parent to NOTSET - if not infer_parent and kwargs.get("parent") is None: - kwargs["parent"] = NOTSET + if additional_instructions := get_instructions(): kwargs["instructions"] = ( kwargs.get("instructions") @@ -230,17 +223,17 @@ def _validate_agents(cls, v): raise ValueError("Agents must be `None` or a non-empty list of agents.") return v - @field_validator("parent") + @field_validator("parent", mode="before") def _default_parent(cls, v): - if v is None: + if v is NOTSET: parent_tasks = ctx.get("tasks", []) v = parent_tasks[-1] if parent_tasks else None - elif v is NOTSET: - v = None return v - @field_validator("result_type") + @field_validator("result_type", mode="before") def _ensure_result_type_is_list_if_literal(cls, v): + if v is NOTSET: + v = str if isinstance(v, _LiteralGenericAlias): v = v.__args__ if isinstance(v, (list, tuple, set)): From 521f7c6f0f6d3632370f35c44124f85baaf35cab Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:33:13 -0400 Subject: [PATCH 2/2] Update task.py --- src/controlflow/tasks/task.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/controlflow/tasks/task.py b/src/controlflow/tasks/task.py index edf9cfd0..e81faf44 100644 --- a/src/controlflow/tasks/task.py +++ b/src/controlflow/tasks/task.py @@ -104,6 +104,7 @@ class Task(ControlFlowModel): description="The expected type of the result. This should be a type" ", generic alias, BaseModel subclass, or list of choices. " "Can be None if no result is expected or the agent should communicate internally.", + validate_default=True, ) result_validator: Optional[Callable] = Field( None, @@ -132,7 +133,6 @@ class Task(ControlFlowModel): def __init__( self, objective: str = None, - result_type: Any = NOTSET, user_access: bool = None, **kwargs, ): @@ -225,14 +225,14 @@ def _validate_agents(cls, v): @field_validator("parent", mode="before") def _default_parent(cls, v): - if v is NOTSET: + if v == NOTSET: parent_tasks = ctx.get("tasks", []) v = parent_tasks[-1] if parent_tasks else None return v @field_validator("result_type", mode="before") - def _ensure_result_type_is_list_if_literal(cls, v): - if v is NOTSET: + def _validate_result_type(cls, v): + if v == NOTSET: v = str if isinstance(v, _LiteralGenericAlias): v = v.__args__