Source code for agentscope.plan._plan_model

# -*- coding: utf-8 -*-
"""The models used in the plan module."""
from typing import Literal

import shortuuid
from pydantic import BaseModel, Field

from .._utils._common import _get_timestamp


[docs] class SubTask(BaseModel): """The subtask model used in the plan module.""" name: str = Field( description=( "The subtask name, should be concise, descriptive and not" "exceed 10 words." ), ) description: str = Field( description=( "The subtask description, including the constraints, target and " "outcome to be achieved. The description should be clear, " "specific and concise, and all the constraints, target and " "outcome should be specific and measurable." ), ) expected_outcome: str = Field( description=( "The expected outcome of the subtask, which should be specific, " "concrete and measurable." ), ) outcome: str | None = Field( description="The actual outcome of the subtask.", exclude=True, default=None, ) state: Literal["todo", "in_progress", "done", "abandoned"] = Field( description="The state of the subtask.", default="todo", exclude=True, ) created_at: str = Field( description="The time the subtask was created.", default_factory=_get_timestamp, ) # Result related fields finished_at: str | None = Field( description="The time the subtask was finished.", default=None, exclude=True, )
[docs] def finish(self, outcome: str) -> None: """Finish the subtask with the actual outcome.""" self.state = "done" self.outcome = outcome self.finished_at = _get_timestamp()
[docs] def to_oneline_markdown(self) -> str: """Convert the subtask to MarkDown format.""" status_map = { "todo": "- []", "in_progress": "- [][WIP]", "done": "- [x]", "abandoned": "- [][Abandoned]", } return f"{status_map[self.state]} {self.name}"
[docs] def to_markdown(self, detailed: bool = False) -> str: """Convert the subtask to MarkDown format. Args: detailed (`bool`, defaults to `False`): Whether to include detailed information about the subtask. """ status_map = { "todo": "- [ ] ", "in_progress": "- [ ] [WIP]", "done": "- [x] ", "abandoned": "- [ ] [Abandoned]", } if detailed: markdown_strs = [ f"{status_map[self.state]}{self.name}", f"\t- Created At: {self.created_at}", f"\t- Description: {self.description}", f"\t- Expected Outcome: {self.expected_outcome}", f"\t- State: {self.state}", ] if self.state == "done": markdown_strs.extend( [ f"\t- Finished At: {self.finished_at}", f"\t- Actual Outcome: {self.outcome}", ], ) return "\n".join(markdown_strs) return f"{status_map[self.state]}{self.name}"
[docs] class Plan(BaseModel): """The plan model used in the plan module, contains a list of subtasks.""" id: str = Field(exclude=True, default_factory=shortuuid.uuid) name: str = Field( description=( "The plan name, should be concise, descriptive and not exceed 10 " "words." ), ) description: str = Field( description=( "The plan description, including the constraints, target and " "outcome to be achieved. The description should be clear, " "specific and concise, and all the constraints, target and " "outcome should be specific and measurable." ), ) expected_outcome: str = Field( description=( "The expected outcome of the plan, which should be specific, " "concrete and measurable." ), ) subtasks: list[SubTask] = Field( description=("A list of subtasks that make up the plan."), ) created_at: str = Field( description="The time the plan was created.", default_factory=_get_timestamp, exclude=True, ) state: Literal["todo", "in_progress", "done", "abandoned"] = Field( description="The state of the plan.", default="todo", exclude=True, ) finished_at: str | None = Field( description="The time the plan was finished.", default=None, exclude=True, ) outcome: str | None = Field( description="The actual outcome of the plan.", default=None, exclude=True, )
[docs] def finish( self, state: Literal["done", "abandoned"], outcome: str, ) -> None: """Finish the plan.""" self.state = state self.outcome = outcome self.finished_at = _get_timestamp()
[docs] def to_markdown(self, detailed: bool = False) -> str: """Convert the plan to MarkDown format.""" subtasks_markdown = "\n".join( [ subtask.to_markdown( detailed=detailed, ) for subtask in self.subtasks ], ) return "\n".join( [ f"# {self.name}", f"**Description**: {self.description}", f"**Expected Outcome**: {self.expected_outcome}", f"**State**: {self.state}", f"**Created At**: {self.created_at}", "## Subtasks", subtasks_markdown, ], )