-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Toolkit Task Improvements #1268
Changes from all commits
0187bbd
c82da88
ffa8726
1977f9c
ace7596
d99b7cc
b5025d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -217,14 +217,18 @@ def __init_from_prompt(self, value: str) -> None: | |
actions_matches = re.findall(self.ACTIONS_PATTERN, value, re.DOTALL) | ||
answer_matches = re.findall(self.ANSWER_PATTERN, value, re.MULTILINE) | ||
|
||
if self.thought is None and thought_matches: | ||
self.thought = thought_matches[-1] | ||
self.actions = self.__parse_actions(actions_matches) | ||
|
||
self.__parse_actions(actions_matches) | ||
if thought_matches: | ||
self.thought = thought_matches[-1] | ||
|
||
# If there are no actions to take but an answer is provided, set the answer as the output. | ||
if len(self.actions) == 0 and self.output is None and answer_matches: | ||
self.output = TextArtifact(answer_matches[-1]) | ||
if not self.actions and self.output is None: | ||
if answer_matches: | ||
# A direct answer is provided, set it as the output. | ||
self.output = TextArtifact(answer_matches[-1]) | ||
else: | ||
# The LLM failed to follow the ReAct prompt, set the LLM's raw response as the output. | ||
self.output = TextArtifact(value) | ||
|
||
def __init_from_artifacts(self, artifacts: ListArtifact) -> None: | ||
"""Parses the input Artifacts to extract the thought and actions. | ||
|
@@ -243,23 +247,30 @@ def __init_from_artifacts(self, artifacts: ListArtifact) -> None: | |
if isinstance(artifact, ActionArtifact) | ||
] | ||
|
||
thoughts = [artifact.value for artifact in artifacts.value if isinstance(artifact, TextArtifact)] | ||
if thoughts: | ||
self.thought = thoughts[0] | ||
# When parsing from Artifacts we can't determine the thought unless there are also Actions | ||
if self.actions: | ||
thoughts = [artifact.value for artifact in artifacts.value if isinstance(artifact, TextArtifact)] | ||
if thoughts: | ||
self.thought = thoughts[0] | ||
else: | ||
if self.output is None: | ||
self.output = TextArtifact(artifacts.to_text()) | ||
|
||
def __parse_actions(self, actions_matches: list[str]) -> None: | ||
def __parse_actions(self, actions_matches: list[str]) -> list[ToolAction]: | ||
if len(actions_matches) == 0: | ||
return | ||
return [] | ||
try: | ||
data = actions_matches[-1] | ||
actions_list: list[dict] = json.loads(data, strict=False) | ||
|
||
self.actions = [self.__process_action_object(action_object) for action_object in actions_list] | ||
return [self.__process_action_object(action_object) for action_object in actions_list] | ||
except json.JSONDecodeError as e: | ||
logger.exception("Subtask %s\nInvalid actions JSON: %s", self.origin_task.id, e) | ||
|
||
self.output = ErrorArtifact(f"Actions JSON decoding error: {e}", exception=e) | ||
|
||
return [] | ||
|
||
Comment on lines
-250
to
+273
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fewer side effects, more consistent with native tool calling action parsing. |
||
def __process_action_object(self, action_object: dict) -> ToolAction: | ||
# Load action tag; throw exception if the key is not present | ||
action_tag = action_object["tag"] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -180,9 +180,6 @@ def run(self) -> BaseArtifact: | |
if subtask.output is None: | ||
if len(self.subtasks) >= self.max_subtasks: | ||
subtask.output = ErrorArtifact(f"Exceeded tool limit of {self.max_subtasks} subtasks per task") | ||
elif not subtask.actions: | ||
# handle case when the LLM failed to follow the ReAct prompt and didn't return a proper action | ||
subtask.output = subtask.input | ||
Comment on lines
-183
to
-185
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to handle this slightly differently depending on whether we're using native tool calling or not. Moved this logic to |
||
else: | ||
subtask.before_run() | ||
subtask.run() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,16 +8,14 @@ Actions: <JSON array of actions that MUST follow this schema: {{ actions_schema | |
{{ stop_sequence }}: <action outputs> | ||
"Thought", "Actions", "{{ stop_sequence }}" must always start on a new line. | ||
|
||
You must use the following format when providing your final answer: | ||
Answer: <final answer> | ||
{% endif %} | ||
Repeat executing actions as many times as you need. | ||
If an action's output contains an error, you MUST ALWAYS try to fix the error by executing another action. | ||
You must use the following format when providing your final answer: | ||
Answer: <final answer> | ||
|
||
Be truthful. ALWAYS be proactive and NEVER ask the user for more information input. Keep using actions until you have your final answer. | ||
NEVER make up actions, action names, or action paths. NEVER make up facts. NEVER reference tags in other action input values. | ||
|
||
Actions might store their output in memory as artifacts (with `memory_name` and `artifact_namespace`). If action output is stored in memory, ALWAYS try to pass it to another action. NEVER make up memory names or artifact namespaces. | ||
Comment on lines
-19
to
-20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was causing the LLM to hallucinate these keys into the Tool schema. The Tool schema is descriptive enough, we don't need to mention them here. |
||
{% if meta_memory %} | ||
|
||
{{ meta_memory }} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically this is still true for non native tool calling, but that feels edge case enough where it's not worth mentioning.