Skip to content

Commit

Permalink
Add Recepta Role for CoT in Planner [Ready] (#455)
Browse files Browse the repository at this point in the history
Co-authored-by: Shilin HE <[email protected]>
  • Loading branch information
liqul and ShilinHe authored Jan 20, 2025
1 parent 8978d5d commit 724c37a
Show file tree
Hide file tree
Showing 12 changed files with 731 additions and 20 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Unlike many agent frameworks that only track the chat history with LLMs in text,


## 🆕 News
- 📅2025-01-16: TaskWeaver has been enhanced with an experimental role called [Recepta](https://microsoft.github.io/TaskWeaver/blog/reasoning) for its reasoning power.🧠
- 📅2024-12-23: TaskWeaver has been integrated with the [AgentOps](https://microsoft.github.io/TaskWeaver/docs/observability) for better observability and monitoring.🔍
- 📅2024-09-13: We introduce the shared memory to store information that is shared between the roles in TaskWeaver. Please check the [memory](https://microsoft.github.io/TaskWeaver/docs/memory) for more details.🧠
- 📅2024-09-13: We have enhanced the experience feature by allowing static and dynamic experience selection. Please check the [experience](https://microsoft.github.io/TaskWeaver/blog/experience) for more details.📚
Expand All @@ -31,7 +32,7 @@ Unlike many agent frameworks that only track the chat history with LLMs in text,
- 📅2024-03-28: TaskWeaver now offers all-in-one Docker image, providing a convenient one-stop experience for users. Please check the [docker](https://microsoft.github.io/TaskWeaver/docs/usage/docker) for more details.🐳
- 📅2024-03-27: TaskWeaver now switches to `container` mode by default for code execution. Please check the [code execution](https://microsoft.github.io/TaskWeaver/docs/code_execution) for more details.🐳
- 📅2024-03-07: TaskWeaver now supports configuration of different LLMs for various components, such as the Planner and CodeInterpreter. Please check the [multi-llm](https://microsoft.github.io/TaskWeaver/docs/llms/multi-llm) for more details.🔗
- 📅2024-03-04: TaskWeaver now supports a [container](https://microsoft.github.io/TaskWeaver/docs/code_execution) mode, which provides a more secure environment for code execution.🐳
<!-- - 📅2024-03-04: TaskWeaver now supports a [container](https://microsoft.github.io/TaskWeaver/docs/code_execution) mode, which provides a more secure environment for code execution.🐳 -->
<!-- - 📅2024-02-28: TaskWeaver now offers a [CLI-only](https://microsoft.github.io/TaskWeaver/docs/advanced/cli_only) mode, enabling users to interact seamlessly with the Command Line Interface (CLI) using natural language.📟 -->
<!-- - 📅2024-02-01: TaskWeaver now has a plugin [document_retriever](https://github.com/microsoft/TaskWeaver/blob/main/project/plugins/README.md#document_retriever) for RAG based on a knowledge base.📚 -->
<!-- - 📅2024-01-30: TaskWeaver introduces a new plugin-only mode that securely generates calls to specified plugins without producing extraneous code.🪡 -->
Expand All @@ -54,7 +55,7 @@ Unlike many agent frameworks that only track the chat history with LLMs in text,
- [x] **Code verification** - TaskWeaver is designed to verify the generated code before execution. It can detect potential issues in the generated code and provide suggestions to fix them.
- [x] **Easy to use** - TaskWeaver is easy to use with sample plugins, examples and tutorials to help you get started. TaskWeaver offers an open-box experience, allowing users to run it immediately after installation.
- [x] **Easy to debug** - TaskWeaver is easy to debug with detailed and transparent logs to help you understand the entire process, including LLM prompts, the code generation, and execution process.
- [x] **Security consideration** - TaskWeaver supports a basic session management to keep different users' data separate. The code execution is separated into different processes to avoid mutal interference.
- [x] **Security consideration** - TaskWeaver supports a basic session management to keep different users' data separate. The code execution is separated into different processes to avoid mutual interference.
- [x] **Easy extension** - TaskWeaver is easy to extend to accomplish more complex tasks with multiple agents as the plugins.

## ✨ Quick Start
Expand Down
6 changes: 4 additions & 2 deletions project/examples/planner_examples/example-planner-2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ rounds:
send_from: Planner
send_to: User
attachment_list:
- type: reasoning
- type: plan_reasoning
content: |-
The user greets the Planner
- type: init_plan
Expand All @@ -21,4 +21,6 @@ rounds:
content: |-
1. Respond to the user's greeting
- type: current_plan_step
content: 1. Respond to the user's greeting
content: 1. Respond to the user's greeting
- type: stop
content: Completed
9 changes: 6 additions & 3 deletions project/examples/planner_examples/example-planner-echo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ rounds:
send_from: Planner
send_to: Echo
attachment_list:
- type: reasoning
- type: plan_reasoning
content: |-
The user wants to echo the input 'Hello World'
- type: init_plan
Expand All @@ -22,6 +22,8 @@ rounds:
1. Ask Echo to echo the user's input, 'Hello World'
- type: current_plan_step
content: 1. Ask Echo to echo the user's input, 'Hello World'
- type: stop
content: InProcess
- message: Hello World
send_from: Echo
send_to: Planner
Expand All @@ -30,7 +32,7 @@ rounds:
send_from: Planner
send_to: User
attachment_list:
- type: reasoning
- type: plan_reasoning
content: |-
The user query is successfully answered
- type: init_plan
Expand All @@ -41,4 +43,5 @@ rounds:
1. Ask Echo to echo the user's input, 'Hello World'
- type: current_plan_step
content: 1. Ask Echo to echo the user's input, 'Hello World'

- type: stop
content: Completed
137 changes: 137 additions & 0 deletions project/examples/planner_examples/example-planner-recepta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
enabled: True
rounds:
- user_query: echo 'Generate Employee Report'
state: created
post_list:
- message: |-
please follow the instructions below to complete the task:
# Task Instructions
## Step 1: Extract Employee Data
Extract the following information from the employee summary:
- `Employee ID`
- `Department`
- `Project Code`
- `Role`
- `Manager`
- `Location`

### Employee Summary
On April 10, 2025, a review was conducted for an employee with ID `E12345`. The employee is part of the `Development` department and is currently assigned to project code `"X987"`. The role held is `"Software Engineer"` under the supervision of manager `"J. Doe."` The primary work location is `"Remote."`

## Step 2: Validate the Role
- Confirm if the role is recognized among the following: Software Engineer, Data Analyst, Project Manager, DevOps Specialist, QA Tester.
- Check if the role is one of the recognized roles.

## Step 3: Construct SQL Query
Prepare and print the SQL query using the extracted details:
```sql
SELECT EmployeeID, Department, ProjectCode, Role, Manager, Location
FROM EmployeeRecords
WHERE EmployeeID = '{EmployeeID}'
AND Department = '{Department}'
AND ProjectCode = '{ProjectCode}'
AND Role = '{Role}'
AND Manager = '{Manager}'
AND Location = '{Location}'
ORDER BY EmployeeID;
```
send_from: User
send_to: Planner
attachment_list:
- message: |-
Thought: I can read and comprehend the employee summary to extract the required information.
Result: the `Employee ID` is `E12345`, the `Department` is `Development`, the `Project Code` is `X987`, the `Role` is `Software Engineer`, the `Manager` is `J. Doe`, and the `Location` is `Remote`.
send_from: Planner
send_to: Recepta
attachment_list:
- type: plan_reasoning
content: |-
The first step is to extract the following information from the employee summary: `Employee ID`, `Department`, `Project Code`, `Role`, `Manager`, `Location`.
- type: init_plan
content: |-
1. extract the following information from the employee summary: `Employee ID`, `Department`, `Project Code`, `Role`, `Manager`, `Location`
2. validate the role <interactively depends on 1>
3. construct and print the SQL query using the extracted details <interactively depends on 1>
4. check the execution result and report the result to the user <interactively depends on 1 and 3>
- type: plan
content: |-
1. extract information from the employee summary
2. validate the role
3. construct SQL query using the extracted details
4. report the result to the user
- type: current_plan_step
content: 1. extract information from the employee summary
- type: stop
content: InProcess
- message: Got it! Please go ahead.
send_from: Recepta
send_to: Planner
attachment_list:
- message: |-
Thought: I can verify if the role is one of the recognized roles with my pattern matching capability.
Thought: The recognized roles are `Software Engineer, Data Analyst, Project Manager, DevOps Specialist, QA Tester`.
Result: The role is `Software Engineer`, which is recognized.
send_from: Planner
send_to: Recepta
attachment_list:
- type: plan_reasoning
content: |-
I have extracted the information from the employee summary. The next step is to verify if the role is one of the recognized roles.
- type: init_plan
content: |-
1. extract the following information from the employee summary: `Employee ID`, `Department`, `Project Code`, `Role`, `Manager`, `Location`
2. validate the role <interactively depends on 1>
3. construct and print the SQL query using the extracted details <interactively depends on 1>
4. check the execution result and report the result to the user <interactively depends on 1 and 3>
- type: plan
content: |-
1. extract information from the employee summary
2. validate the role
3. construct SQL query using the extracted details
4. report the result to the user
- type: current_plan_step
content: 2. validate the role
- type: stop
content: InProcess
- message: Got it! Please go ahead.
send_from: Recepta
send_to: Planner
attachment_list:
- message: |-
The role is `Software Engineer`, which is recognized.
Here is the SQL query using the extracted details:
```sql
SELECT EmployeeID, Department, ProjectCode, Role, Manager, Location
FROM EmployeeRecords
WHERE EmployeeID = 'E12345'
AND Department = 'Development'
AND ProjectCode = 'X987'
AND Role = 'Software Engineer'
AND Manager = 'J. Doe'
AND Location = 'Remote'
ORDER BY EmployeeID;
```
send_from: Planner
send_to: User
attachment_list:
- type: plan_reasoning
content: |-
I can prepare and print the SQL query using the extracted details to the User.
- type: init_plan
content: |-
1. extract the following information from the employee summary: `Employee ID`, `Department`, `Project Code`, `Role`, `Manager`, `Location`
2. validate the role <interactively depends on 1>
3. construct and print the SQL query using the extracted details <interactively depends on 1>
4. check the execution result and report the result to the user <interactively depends on 1 and 3>
- type: plan
content: |-
1. extract information from the employee summary
2. validate the role
3. construct SQL query using the extracted details
4. report the result to the user
- type: current_plan_step
content: 3. construct and print the SQL query using the extracted details and report the result to the user
- type: stop
content: Completed
8 changes: 6 additions & 2 deletions project/examples/planner_examples/example-planner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ rounds:
send_from: Planner
send_to: CodeInterpreter
attachment_list:
- type: reasoning
- type: plan_reasoning
content: |-
The user wants to count the rows of the data file /home/data.csv. The first step is to load the data file and count the rows of the loaded data.
- type: init_plan
Expand All @@ -25,6 +25,8 @@ rounds:
2. Check the execution result and report the result to the user if it is correct
- type: current_plan_step
content: 1. Instruct CodeInterpreter to load the data file and count the rows of the loaded data
- type: stop
content: InProcess
- message: Load the data file /home/data.csv successfully and there are 100 rows in the data file
send_from: CodeInterpreter
send_to: Planner
Expand All @@ -33,7 +35,7 @@ rounds:
send_from: Planner
send_to: User
attachment_list:
- type: reasoning
- type: plan_reasoning
content: |-
The data file /home/data.csv is loaded and there are 100 rows in the data file
The execution result is correct
Expand All @@ -49,3 +51,5 @@ rounds:
2. Check the execution result and report the result to the user if it is correct
- type: current_plan_step
content: 2. report the result to the user
- type: stop
content: Completed
3 changes: 2 additions & 1 deletion taskweaver/ces/runtime/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ def load_lib(self, local_ns: Dict[str, Any]):
# customize pandas display options
pd.set_option("display.html.table_schema", False)
pd.set_option("display.notebook_repr_html", False)
pd.set_option("display.max_rows", 4)
pd.set_option("display.max_rows", 5)
pd.set_option("display.expand_frame_repr", False)
pd.set_option("display.max_colwidth", None)
local_ns["pd"] = pd
except ImportError:
self.log(
Expand Down
Empty file.
44 changes: 44 additions & 0 deletions taskweaver/ext_role/recepta/recepta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from injector import inject

from taskweaver.logging import TelemetryLogger
from taskweaver.memory import Memory, Post
from taskweaver.module.event_emitter import SessionEventEmitter
from taskweaver.module.tracing import Tracing
from taskweaver.role import Role
from taskweaver.role.role import RoleConfig, RoleEntry


class ReceptaConfig(RoleConfig):
def _configure(self):
self.decorator = self._get_str("decorator", "")


class Recepta(Role):
@inject
def __init__(
self,
config: ReceptaConfig,
logger: TelemetryLogger,
tracing: Tracing,
event_emitter: SessionEventEmitter,
role_entry: RoleEntry,
):
super().__init__(config, logger, tracing, event_emitter, role_entry)

def reply(self, memory: Memory, **kwargs: ...) -> Post:
rounds = memory.get_role_rounds(
role=self.alias,
include_failure_rounds=False,
)

# obtain the query from the last round
last_post = rounds[-1].post_list[-1]

post_proxy = self.event_emitter.create_post_proxy(self.alias)

post_proxy.update_send_to(last_post.send_from)
post_proxy.update_message(
"Got it. Now, please go ahead!",
)

return post_proxy.end()
7 changes: 7 additions & 0 deletions taskweaver/ext_role/recepta/recepta.role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
alias: Recepta
module: taskweaver.ext_role.recepta.recepta.Recepta
intro : |-
- Recepta is responsible for helping the Planner to record the reasoning process.
- When the Planner is reasoning and do not involve any Workers, it must send a message to Recepta to record the reasoning process.
- When Planner needs to reason in the middle of the task and is not ready to talk to the User, it can send a message to `Recepta` to record the reasoning process and result. The message should be formatted as "Thought 1: reasoning...\nThought 2: reasoning...\n...Result: result...".
- The reasoning result should be insights or conclusion derived for the task step, NOT a plan or a set of instructions for further action.
3 changes: 2 additions & 1 deletion taskweaver/memory/attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class AttachmentType(Enum):
init_plan = "init_plan"
plan = "plan"
current_plan_step = "current_plan_step"
reasoning = "reasoning"
plan_reasoning = "plan_reasoning"
stop = "stop"

# CodeInterpreter - generate code
thought = "thought"
Expand Down
Loading

0 comments on commit 724c37a

Please sign in to comment.