jupyter-agent 2025.6.100__py3-none-any.whl → 2025.6.101__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jupyter_agent/__init__.py +0 -0
- jupyter_agent/bot_agents/__init__.py +42 -0
- jupyter_agent/bot_agents/base.py +324 -0
- jupyter_agent/bot_agents/master_planner.py +45 -0
- jupyter_agent/bot_agents/output_task_result.py +29 -0
- jupyter_agent/bot_agents/task_code_executor.py +53 -0
- jupyter_agent/bot_agents/task_coder.py +71 -0
- jupyter_agent/bot_agents/task_debuger.py +69 -0
- jupyter_agent/bot_agents/task_planner_v1.py +158 -0
- jupyter_agent/bot_agents/task_planner_v2.py +172 -0
- jupyter_agent/bot_agents/task_planner_v3.py +189 -0
- jupyter_agent/bot_agents/task_reasoner.py +61 -0
- jupyter_agent/bot_agents/task_structrue_reasoner.py +106 -0
- jupyter_agent/bot_agents/task_structrue_summarier.py +123 -0
- jupyter_agent/bot_agents/task_summarier.py +76 -0
- jupyter_agent/bot_agents/task_verifier.py +99 -0
- jupyter_agent/bot_agents/task_verify_summarier.py +134 -0
- jupyter_agent/bot_chat.py +218 -0
- jupyter_agent/bot_contexts.py +466 -0
- jupyter_agent/bot_flows/__init__.py +20 -0
- jupyter_agent/bot_flows/base.py +209 -0
- jupyter_agent/bot_flows/master_planner.py +16 -0
- jupyter_agent/bot_flows/task_executor_v1.py +86 -0
- jupyter_agent/bot_flows/task_executor_v2.py +84 -0
- jupyter_agent/bot_flows/task_executor_v3.py +89 -0
- jupyter_agent/bot_magics.py +127 -0
- jupyter_agent/bot_outputs.py +480 -0
- jupyter_agent/utils.py +138 -0
- {jupyter_agent-2025.6.100.dist-info → jupyter_agent-2025.6.101.dist-info}/METADATA +13 -7
- jupyter_agent-2025.6.101.dist-info/RECORD +33 -0
- jupyter_agent-2025.6.101.dist-info/top_level.txt +1 -0
- jupyter_agent-2025.6.100.dist-info/RECORD +0 -5
- jupyter_agent-2025.6.100.dist-info/top_level.txt +0 -1
- {jupyter_agent-2025.6.100.dist-info → jupyter_agent-2025.6.101.dist-info}/WHEEL +0 -0
- {jupyter_agent-2025.6.100.dist-info → jupyter_agent-2025.6.101.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
"""
|
2
|
+
Copyright (c) 2025 viewstar000
|
3
|
+
|
4
|
+
This software is released under the MIT License.
|
5
|
+
https://opensource.org/licenses/MIT
|
6
|
+
"""
|
7
|
+
|
8
|
+
from enum import Enum
|
9
|
+
from pydantic import BaseModel, Field
|
10
|
+
from IPython.display import Markdown
|
11
|
+
from .base import BaseChatAgent, AgentOutputFormat, AgentModelType
|
12
|
+
from ..bot_outputs import _D, _I, _W, _E, _F, _M, _B, _C, _O
|
13
|
+
from ..bot_outputs import ReplyType
|
14
|
+
|
15
|
+
|
16
|
+
TASK_PLANNER_PROMPT = """\
|
17
|
+
**角色定义**:
|
18
|
+
|
19
|
+
你是一名任务调度专家,负责根据全局分析规划,逐步推进并协调各子任务的执行。
|
20
|
+
|
21
|
+
**任务要求**:
|
22
|
+
|
23
|
+
- 审查全局目标与已完成的子任务结果,判断是否已实现整体目标:
|
24
|
+
- 若目标已达成,终止流程并输出最终结果。
|
25
|
+
- 若目标未达成,请根据目标规划说明和已完成子任务,制定下一个**子任务**的执行计划
|
26
|
+
- 子任务的划分应严格遵守全局目标规划说明的要求
|
27
|
+
- 协调代码生成Agent、结果验证Agent、结果总结Agent共同完成当前子任务
|
28
|
+
- 子任务的执行计划具体包括:
|
29
|
+
1. 子任务工作描述:
|
30
|
+
- 简明阐述子任务目标、输入与输出约束
|
31
|
+
2. 子任务代码生成Prompt:
|
32
|
+
- 需生成的代码类型(如数据处理、建模、可视化等)
|
33
|
+
- 具体输入(数据、变量、参数等)
|
34
|
+
- 预期输出形式(变量名、图表、文本等)
|
35
|
+
3. 子任务结果验证Prompt:
|
36
|
+
- 检测子任务代码执行结果是否符合当前子任务的要求
|
37
|
+
- 检测条件只考虑当前子任务的要求,不要考虑全局目标
|
38
|
+
4. 子任务结果总结Prompt:
|
39
|
+
- 说明本子任务结果总结的要点和输出要素,以便后续子任务使用
|
40
|
+
- 若需要用户提供更多的信息,给出详细的提示信息
|
41
|
+
|
42
|
+
{% include "TASK_OUTPUT_FORMAT" %}
|
43
|
+
|
44
|
+
---
|
45
|
+
|
46
|
+
{% include "TASK_CONTEXTS" %}
|
47
|
+
|
48
|
+
---
|
49
|
+
|
50
|
+
{% include "CODE_CONTEXTS" %}
|
51
|
+
|
52
|
+
---
|
53
|
+
|
54
|
+
{% if task.subject and task.issue %}
|
55
|
+
**当前子任务信息**:
|
56
|
+
|
57
|
+
### 当前子任务目标:
|
58
|
+
{{ task.subject }}
|
59
|
+
|
60
|
+
### 当前子任务代码:
|
61
|
+
```python
|
62
|
+
{{ task.source }}
|
63
|
+
```
|
64
|
+
|
65
|
+
### 当前子任务输出:
|
66
|
+
{{ task.output }}
|
67
|
+
|
68
|
+
### 当前子任务存在的问题:
|
69
|
+
{{ task.issue }}
|
70
|
+
|
71
|
+
---
|
72
|
+
|
73
|
+
请参考上述信息重新规划当前子任务:
|
74
|
+
{% else %}
|
75
|
+
请按要求规划下一个子任务:
|
76
|
+
{% endif %}
|
77
|
+
|
78
|
+
"""
|
79
|
+
|
80
|
+
|
81
|
+
class TaskPlannerState(Enum):
|
82
|
+
PLANNED = "planned" # 任务规划完成
|
83
|
+
REQUEST_INFO = "request_info" # 需要用户补充更详细的信息
|
84
|
+
GLOBAL_FINISHED = "global_finished" # 全局目标已达成
|
85
|
+
|
86
|
+
|
87
|
+
class TaskPlannerOutput(BaseModel):
|
88
|
+
state: TaskPlannerState = Field(
|
89
|
+
description=(
|
90
|
+
"任务规划状态: "
|
91
|
+
f"{TaskPlannerState.PLANNED}, 完成规划, 可以开始执行下一步; "
|
92
|
+
f"{TaskPlannerState.REQUEST_INFO}, 需要用户补充更详细的信息; "
|
93
|
+
f"{TaskPlannerState.GLOBAL_FINISHED}, 全局目标是否已达成, 无需继续规划; "
|
94
|
+
),
|
95
|
+
examples=[TaskPlannerState.PLANNED.value],
|
96
|
+
)
|
97
|
+
subtask_subject: str = Field(
|
98
|
+
"",
|
99
|
+
description='子任务简要描述, 在 state="planned" 时必填',
|
100
|
+
examples=["对...进行...处理,输出..."],
|
101
|
+
)
|
102
|
+
subtask_coding_prompt: str = Field(
|
103
|
+
"",
|
104
|
+
description='子任务代码生成Prompt, 在 state="planned" 时必填',
|
105
|
+
examples=["请基于...,计算...,并保存结果为..."],
|
106
|
+
)
|
107
|
+
subtask_verify_prompt: str = Field(
|
108
|
+
"",
|
109
|
+
description='子任务结果验证Prompt, 在 state="planned" 时必填',
|
110
|
+
examples=["请验证当前任务结果是否符合以下条件:..."],
|
111
|
+
)
|
112
|
+
subtask_summary_prompt: str = Field(
|
113
|
+
"",
|
114
|
+
description='子任务结果总结Prompt, 在 state="planned" 时必填',
|
115
|
+
examples=["请对当前任务的结果进行总结,输出以下要素:..."],
|
116
|
+
)
|
117
|
+
request_info_prompt: str = Field(
|
118
|
+
"",
|
119
|
+
description='需要用户补充更详细的信息的 Prompt, 在 state="request_info" 时必填',
|
120
|
+
examples=["请补充与...相关的详细的信息"],
|
121
|
+
)
|
122
|
+
|
123
|
+
|
124
|
+
class TaskPlannerAgentV1(BaseChatAgent):
|
125
|
+
"""任务规划器代理类"""
|
126
|
+
|
127
|
+
PROMPT = TASK_PLANNER_PROMPT
|
128
|
+
OUTPUT_FORMAT = AgentOutputFormat.JSON
|
129
|
+
OUTPUT_JSON_SCHEMA = TaskPlannerOutput
|
130
|
+
MODEL_TYPE = AgentModelType.PLANNER
|
131
|
+
|
132
|
+
def on_reply(self, reply: TaskPlannerOutput):
|
133
|
+
"""执行规划逻辑"""
|
134
|
+
if reply.state == TaskPlannerState.GLOBAL_FINISHED:
|
135
|
+
_C(Markdown("全局目标已达成,任务完成!"), reply_type=ReplyType.TASK_RESULT)
|
136
|
+
return False, reply.state
|
137
|
+
elif reply.state == TaskPlannerState.REQUEST_INFO:
|
138
|
+
assert reply.request_info_prompt, "Request info prompt is empty"
|
139
|
+
_O(Markdown(f"### 需要补充更详细的信息\n\n{reply.request_info_prompt}"), reply_type=ReplyType.TASK_ISSUE)
|
140
|
+
return True, reply.state
|
141
|
+
elif reply.state == TaskPlannerState.PLANNED:
|
142
|
+
assert reply.subtask_subject, "Subtask subject is empty"
|
143
|
+
assert reply.subtask_coding_prompt, "Subtask coding prompt is empty"
|
144
|
+
assert reply.subtask_verify_prompt, "Subtask verify prompt is empty"
|
145
|
+
assert reply.subtask_summary_prompt, "Subtask summary prompt is empty"
|
146
|
+
_M(
|
147
|
+
f"### 子任务: {reply.subtask_subject}\n"
|
148
|
+
f"- Coding: {reply.subtask_coding_prompt}\n"
|
149
|
+
f"- Verify: {reply.subtask_verify_prompt}\n"
|
150
|
+
f"- Summary: {reply.subtask_summary_prompt}\n"
|
151
|
+
)
|
152
|
+
self.task.set_data("subject", reply.subtask_subject)
|
153
|
+
self.task.set_data("coding_prompt", reply.subtask_coding_prompt)
|
154
|
+
self.task.set_data("verify_prompt", reply.subtask_verify_prompt)
|
155
|
+
self.task.set_data("summary_prompt", reply.subtask_summary_prompt)
|
156
|
+
return False, reply.state
|
157
|
+
else:
|
158
|
+
raise ValueError(f"Unknown task planner state: {reply.state}")
|
@@ -0,0 +1,172 @@
|
|
1
|
+
"""
|
2
|
+
Copyright (c) 2025 viewstar000
|
3
|
+
|
4
|
+
This software is released under the MIT License.
|
5
|
+
https://opensource.org/licenses/MIT
|
6
|
+
"""
|
7
|
+
|
8
|
+
from enum import Enum
|
9
|
+
from pydantic import BaseModel, Field
|
10
|
+
from IPython.display import Markdown
|
11
|
+
from .base import BaseChatAgent, AgentOutputFormat, AgentModelType
|
12
|
+
from ..bot_outputs import _D, _I, _W, _E, _F, _M, _B, _C, _O
|
13
|
+
from ..bot_outputs import ReplyType
|
14
|
+
|
15
|
+
|
16
|
+
TASK_PLANNER_PROMPT = """\
|
17
|
+
**角色定义**:
|
18
|
+
|
19
|
+
你是一个任务规划专家,负责根据全局目标规划,需要将一个复杂的Jupyter Notebook编程任务分解成若干步骤(Cell子任务),
|
20
|
+
并逐步推进子任务的执行。
|
21
|
+
|
22
|
+
**任务要求**:
|
23
|
+
|
24
|
+
- 审查全局目标与已完成的cell子任务的结果,判断是否已实现整体目标,若全局目标已达成,终止流程并输出最终结果。
|
25
|
+
- 若全局目标未达成,请根据全局目标规划和已完成的cell子任务,制定下一个**Cell子任务**的执行计划,包括:
|
26
|
+
- 首先拆解出Cell子任务的工作描述,包括子任务目标、输入与输出约束等
|
27
|
+
- 然后跟据子任务目标的特点,选择合适的子任务执行方式
|
28
|
+
- LLM直接推理模式:
|
29
|
+
- 若子任务的目标可以直接通过推理实现,则直接能过推理分析完成子任务,输出任务结果后结束当前子任务的执行
|
30
|
+
- 该模式通常适用于简单数据的比对、数据模型设计、数据模型比对、策略生成、报告生成等任务场景
|
31
|
+
- 代码执行+LLM分析总结模式:
|
32
|
+
- 若子任务的目标需要通过执行代码并对执行结果进行推理分析总结的方式实现,则协调代码生成Agent、LLM分析总结Agent共同完成当前子任务
|
33
|
+
- 该模式通常适用于数据加截、预览、清洗、统计、可视化、复杂算法等任务场景
|
34
|
+
- 此时应结合代码执行Agent与LLM分析总结agent的能力的优劣,进行合理的分工并生成相应的Prompt
|
35
|
+
- 代码生成Prompt,提供给代码生成Agent的Prompt包括:
|
36
|
+
- 需生成的代码类型(如数据处理、建模、可视化等)
|
37
|
+
- 具体输入(数据、变量、参数等)
|
38
|
+
- 预期输出形式(变量名、图表、文本等)
|
39
|
+
- 代码执行的结果仅在当前子任务中可见,不会记录在全局上下文中
|
40
|
+
- 分析总结Prompt,提供给LLM分析总结Agent的Prompt包括:
|
41
|
+
- 说明本子任务结果分析总结的要点和输出要素,以便后续子任务使用
|
42
|
+
- 验证总结的结果会记录在全局上下文中
|
43
|
+
- 若需要用户提供更多的信息才能完成子任务,给出详细的提示信息
|
44
|
+
- 子任务的划分应严格遵守全局目标规划说明的要求
|
45
|
+
- 子任务代码执行的结果不会记录在全局上下文中,只有LLM直接推理或LLM分析总结的结果会记录在全局上下文中以支持后续子任务的执行
|
46
|
+
|
47
|
+
|
48
|
+
{% include "TASK_OUTPUT_FORMAT" %}
|
49
|
+
|
50
|
+
---
|
51
|
+
|
52
|
+
{% include "TASK_CONTEXTS" %}
|
53
|
+
|
54
|
+
---
|
55
|
+
|
56
|
+
{% include "CODE_CONTEXTS" %}
|
57
|
+
|
58
|
+
---
|
59
|
+
|
60
|
+
{% if task.subject and task.issue %}
|
61
|
+
**当前子任务信息**:
|
62
|
+
|
63
|
+
### 当前子任务目标:
|
64
|
+
{{ task.subject }}
|
65
|
+
|
66
|
+
### 当前子任务代码:
|
67
|
+
```python
|
68
|
+
{{ task.source }}
|
69
|
+
```
|
70
|
+
|
71
|
+
### 当前子任务输出:
|
72
|
+
{{ task.output }}
|
73
|
+
|
74
|
+
### 当前子任务存在的问题:
|
75
|
+
{{ task.issue }}
|
76
|
+
|
77
|
+
---
|
78
|
+
|
79
|
+
请参考上述信息重新规划当前子任务:
|
80
|
+
{% else %}
|
81
|
+
请按要求规划下一个子任务:
|
82
|
+
{% endif %}
|
83
|
+
|
84
|
+
"""
|
85
|
+
|
86
|
+
|
87
|
+
class TaskPlannerState(Enum):
|
88
|
+
CODING_PLANNED = "coding_planned" # 任务规划完成
|
89
|
+
REASONING_PLANNED = "reasoning_planned" # 任务规划完成
|
90
|
+
REQUEST_INFO = "request_info" # 需要用户补充更详细的信息
|
91
|
+
GLOBAL_FINISHED = "global_finished" # 全局目标已达成
|
92
|
+
|
93
|
+
|
94
|
+
class TaskPlannerOutput(BaseModel):
|
95
|
+
state: TaskPlannerState = Field(
|
96
|
+
description=(
|
97
|
+
"任务规划状态: "
|
98
|
+
f"{TaskPlannerState.CODING_PLANNED}, 完成规划, 使用代码执行+LLM分析总结模式; "
|
99
|
+
f"{TaskPlannerState.REASONING_PLANNED}, 完成规划, 使用LLM直接推理模式; "
|
100
|
+
f"{TaskPlannerState.REQUEST_INFO}, 需要用户补充更详细的信息; "
|
101
|
+
f"{TaskPlannerState.GLOBAL_FINISHED}, 全局目标是否已达成, 无需继续规划; "
|
102
|
+
),
|
103
|
+
examples=[TaskPlannerState.CODING_PLANNED.value],
|
104
|
+
)
|
105
|
+
subtask_subject: str = Field(
|
106
|
+
"",
|
107
|
+
description=(
|
108
|
+
f'子任务工作描述, 在 state="{TaskPlannerState.CODING_PLANNED}"'
|
109
|
+
f'或state="{TaskPlannerState.REASONING_PLANNED}" 时必填'
|
110
|
+
),
|
111
|
+
examples=["对...进行...处理,输出..."],
|
112
|
+
)
|
113
|
+
subtask_coding_prompt: str = Field(
|
114
|
+
"",
|
115
|
+
description=f'代码生成Prompt, 在 state="{TaskPlannerState.CODING_PLANNED}" 时必填',
|
116
|
+
examples=["请基于...,计算...,并保存结果为..."],
|
117
|
+
)
|
118
|
+
subtask_summary_prompt: str = Field(
|
119
|
+
"",
|
120
|
+
description=(
|
121
|
+
f'结果总结Prompt, 在 state="{TaskPlannerState.CODING_PLANNED}"'
|
122
|
+
f'或state="{TaskPlannerState.REASONING_PLANNED}" 时必填'
|
123
|
+
),
|
124
|
+
examples=["请对当前任务的结果进行总结,输出以下要素:..."],
|
125
|
+
)
|
126
|
+
request_info_prompt: str = Field(
|
127
|
+
"",
|
128
|
+
description=f'需要用户补充更详细的信息的 Prompt, 在 state="{TaskPlannerState.REQUEST_INFO}" 时必填',
|
129
|
+
examples=["请补充与...相关的详细的信息"],
|
130
|
+
)
|
131
|
+
|
132
|
+
|
133
|
+
class TaskPlannerAgentV2(BaseChatAgent):
|
134
|
+
"""任务规划器代理类"""
|
135
|
+
|
136
|
+
PROMPT = TASK_PLANNER_PROMPT
|
137
|
+
OUTPUT_FORMAT = AgentOutputFormat.JSON
|
138
|
+
OUTPUT_JSON_SCHEMA = TaskPlannerOutput
|
139
|
+
MODEL_TYPE = AgentModelType.PLANNER
|
140
|
+
|
141
|
+
def on_reply(self, reply: TaskPlannerOutput):
|
142
|
+
"""执行规划逻辑"""
|
143
|
+
if reply.state == TaskPlannerState.GLOBAL_FINISHED:
|
144
|
+
_C(Markdown("全局目标已达成,任务完成!"), reply_type=ReplyType.TASK_RESULT)
|
145
|
+
return False, reply.state
|
146
|
+
elif reply.state == TaskPlannerState.REQUEST_INFO:
|
147
|
+
assert reply.request_info_prompt, "Request info prompt is empty"
|
148
|
+
_O(Markdown(f"### 需要补充更详细的信息\n\n{reply.request_info_prompt}"), reply_type=ReplyType.TASK_ISSUE)
|
149
|
+
return True, reply.state
|
150
|
+
elif reply.state == TaskPlannerState.CODING_PLANNED:
|
151
|
+
assert reply.subtask_subject, "Subtask subject is empty"
|
152
|
+
assert reply.subtask_coding_prompt, "Subtask coding prompt is empty"
|
153
|
+
assert reply.subtask_summary_prompt, "Subtask summary prompt is empty"
|
154
|
+
_M(
|
155
|
+
f"### 子任务: {reply.subtask_subject}\n"
|
156
|
+
f"- Coding: {reply.subtask_coding_prompt}\n"
|
157
|
+
f"- Summary: {reply.subtask_summary_prompt}\n"
|
158
|
+
)
|
159
|
+
|
160
|
+
self.task.set_data("subject", reply.subtask_subject)
|
161
|
+
self.task.set_data("coding_prompt", reply.subtask_coding_prompt)
|
162
|
+
self.task.set_data("summary_prompt", reply.subtask_summary_prompt)
|
163
|
+
return False, reply.state
|
164
|
+
elif reply.state == TaskPlannerState.REASONING_PLANNED:
|
165
|
+
assert reply.subtask_subject, "Subtask subject is empty"
|
166
|
+
assert reply.subtask_summary_prompt, "Subtask summary prompt is empty"
|
167
|
+
_M(f"### 子任务: {reply.subtask_subject}\n" f"- Summary: {reply.subtask_summary_prompt}\n")
|
168
|
+
self.task.set_data("subject", reply.subtask_subject)
|
169
|
+
self.task.set_data("summary_prompt", reply.subtask_summary_prompt)
|
170
|
+
return False, reply.state
|
171
|
+
else:
|
172
|
+
raise ValueError(f"Unknown task planner state: {reply.state}")
|
@@ -0,0 +1,189 @@
|
|
1
|
+
"""
|
2
|
+
Copyright (c) 2025 viewstar000
|
3
|
+
|
4
|
+
This software is released under the MIT License.
|
5
|
+
https://opensource.org/licenses/MIT
|
6
|
+
"""
|
7
|
+
|
8
|
+
from enum import Enum
|
9
|
+
from typing import Optional, List
|
10
|
+
from pydantic import BaseModel, Field
|
11
|
+
from IPython.display import Markdown
|
12
|
+
from .base import BaseChatAgent, AgentOutputFormat, AgentModelType
|
13
|
+
from ..bot_outputs import ReplyType, _D, _I, _W, _E, _F, _A, _O, _C, _M, _B
|
14
|
+
from ..utils import RequestUserPrompt, format_user_prompts
|
15
|
+
|
16
|
+
|
17
|
+
TASK_PLANNER_PROMPT = """\
|
18
|
+
**角色定义**:
|
19
|
+
|
20
|
+
你是一个任务规划专家,负责根据全局目标规划,需要将一个复杂的Jupyter Notebook编程任务分解成若干步骤(Cell子任务),
|
21
|
+
并逐步推进子任务的执行。
|
22
|
+
|
23
|
+
**任务要求**:
|
24
|
+
|
25
|
+
- 审查全局目标与已完成的cell子任务的结果,判断是否已实现整体目标,若全局目标已达成,终止流程并输出最终结果。
|
26
|
+
- 若全局目标未达成,请根据全局目标规划和已完成的cell子任务,制定下一个**Cell子任务**的执行计划,包括:
|
27
|
+
- 首先拆解出Cell子任务的工作描述,包括子任务目标、输入与输出约束等
|
28
|
+
- 然后跟据子任务目标的特点,选择合适的子任务执行方式
|
29
|
+
- LLM直接推理模式:
|
30
|
+
- 若子任务的目标可以直接通过推理实现,则直接能过推理分析完成子任务,输出任务结果后结束当前子任务的执行
|
31
|
+
- 该模式通常适用于简单数据的比对、数据模型设计、数据模型比对、策略生成、报告生成等任务场景
|
32
|
+
- 代码执行+LLM分析总结模式:
|
33
|
+
- 若子任务的目标需要通过执行代码并对执行结果进行推理分析总结的方式实现,则协调代码生成Agent、LLM分析总结Agent共同完成当前子任务
|
34
|
+
- 该模式通常适用于数据加截、预览、清洗、统计、可视化、复杂算法等任务场景
|
35
|
+
- 此时应结合代码执行Agent与LLM分析总结agent的能力的优劣,进行合理的分工并生成相应的Prompt
|
36
|
+
- 代码生成Prompt,提供给代码生成Agent的Prompt包括:
|
37
|
+
- 需生成的代码类型(如数据处理、建模、可视化等)
|
38
|
+
- 具体输入(数据、变量、参数等)
|
39
|
+
- 预期输出形式(变量名、图表、文本等)
|
40
|
+
- 代码执行的结果仅在当前子任务中可见,不会记录在全局上下文中
|
41
|
+
- 分析总结Prompt,提供给LLM分析总结Agent的Prompt包括:
|
42
|
+
- 说明本子任务结果分析总结的要点和输出要素,以便后续子任务使用
|
43
|
+
- 验证总结的结果会记录在全局上下文中
|
44
|
+
- 若需要用户提供更多的信息才能完成子任务,给出详细的提示信息
|
45
|
+
- 子任务的划分应严格遵守全局目标规划说明的要求
|
46
|
+
- 在引用已完成的子任务的结果时,特别是important_infos中的信息,要保证准确、清晰、完整,不要出现任何误导信息
|
47
|
+
- 子任务代码执行的结果不会记录在全局上下文中,只有LLM直接推理或LLM分析总结的结果会记录在全局上下文中以支持后续子任务的执行
|
48
|
+
|
49
|
+
|
50
|
+
{% include "TASK_OUTPUT_FORMAT" %}
|
51
|
+
|
52
|
+
---
|
53
|
+
|
54
|
+
{% include "TASK_CONTEXTS" %}
|
55
|
+
|
56
|
+
---
|
57
|
+
|
58
|
+
{% include "CODE_CONTEXTS" %}
|
59
|
+
|
60
|
+
---
|
61
|
+
|
62
|
+
{% if task.subject and task.issue %}
|
63
|
+
**当前子任务信息**:
|
64
|
+
|
65
|
+
### 当前子任务目标:
|
66
|
+
{{ task.subject }}
|
67
|
+
|
68
|
+
### 当前子任务代码:
|
69
|
+
```python
|
70
|
+
{{ task.source }}
|
71
|
+
```
|
72
|
+
|
73
|
+
### 当前子任务输出:
|
74
|
+
{{ task.output }}
|
75
|
+
|
76
|
+
### 当前子任务存在的问题:
|
77
|
+
{{ task.issue }}
|
78
|
+
|
79
|
+
---
|
80
|
+
|
81
|
+
请参考上述信息重新规划当前子任务:
|
82
|
+
{% else %}
|
83
|
+
请按要求规划下一个子任务:
|
84
|
+
{% endif %}
|
85
|
+
|
86
|
+
"""
|
87
|
+
|
88
|
+
|
89
|
+
class TaskPlannerState(Enum):
|
90
|
+
CODING_PLANNED = "coding_planned" # 任务规划完成
|
91
|
+
REASONING_PLANNED = "reasoning_planned" # 任务规划完成
|
92
|
+
REQUEST_INFO = "request_info" # 需要用户补充更详细的信息
|
93
|
+
GLOBAL_FINISHED = "global_finished" # 全局目标已达成
|
94
|
+
|
95
|
+
|
96
|
+
class TaskPlannerOutput(BaseModel):
|
97
|
+
state: TaskPlannerState = Field(
|
98
|
+
description=(
|
99
|
+
"任务规划状态: "
|
100
|
+
f"{TaskPlannerState.CODING_PLANNED}, 完成规划, 使用代码执行+LLM分析总结模式; "
|
101
|
+
f"{TaskPlannerState.REASONING_PLANNED}, 完成规划, 使用LLM直接推理模式; "
|
102
|
+
f"{TaskPlannerState.REQUEST_INFO}, 需要用户补充更详细的信息; "
|
103
|
+
f"{TaskPlannerState.GLOBAL_FINISHED}, 全局目标是否已达成, 无需继续规划; "
|
104
|
+
),
|
105
|
+
examples=[TaskPlannerState.CODING_PLANNED.value],
|
106
|
+
)
|
107
|
+
subtask_id: str = Field(
|
108
|
+
"",
|
109
|
+
description=f'子任务全局唯一ID,在 state="{TaskPlannerState.CODING_PLANNED}" '
|
110
|
+
f'或state="{TaskPlannerState.REASONING_PLANNED}" 时必填',
|
111
|
+
examples=["task-xxx"],
|
112
|
+
)
|
113
|
+
subtask_subject: str = Field(
|
114
|
+
"",
|
115
|
+
description=(
|
116
|
+
f'子任务工作描述, 在 state="{TaskPlannerState.CODING_PLANNED}"'
|
117
|
+
f'或state="{TaskPlannerState.REASONING_PLANNED}" 时必填'
|
118
|
+
),
|
119
|
+
examples=["对...进行...处理,输出..."],
|
120
|
+
)
|
121
|
+
subtask_coding_prompt: str = Field(
|
122
|
+
"",
|
123
|
+
description=f'代码生成Prompt, 在 state="{TaskPlannerState.CODING_PLANNED}" 时必填',
|
124
|
+
examples=["请基于...,计算...,并保存结果为..."],
|
125
|
+
)
|
126
|
+
subtask_summary_prompt: str = Field(
|
127
|
+
"",
|
128
|
+
description=(
|
129
|
+
f'结果总结Prompt, 在 state="{TaskPlannerState.CODING_PLANNED}"'
|
130
|
+
f'或state="{TaskPlannerState.REASONING_PLANNED}" 时必填'
|
131
|
+
),
|
132
|
+
examples=["请对当前任务的结果进行总结,输出以下要素:..."],
|
133
|
+
)
|
134
|
+
request_supply_infos: Optional[List[RequestUserPrompt]] = Field(
|
135
|
+
None, description=f'需要用户补充更详细的信息的 Prompt, 在 state="{TaskPlannerState.REQUEST_INFO}" 时必填'
|
136
|
+
)
|
137
|
+
|
138
|
+
|
139
|
+
class TaskPlannerAgentV3(BaseChatAgent):
|
140
|
+
"""任务规划器代理类"""
|
141
|
+
|
142
|
+
PROMPT = TASK_PLANNER_PROMPT
|
143
|
+
OUTPUT_FORMAT = AgentOutputFormat.JSON
|
144
|
+
OUTPUT_JSON_SCHEMA = TaskPlannerOutput
|
145
|
+
MODEL_TYPE = AgentModelType.PLANNER
|
146
|
+
|
147
|
+
def on_reply(self, reply: TaskPlannerOutput):
|
148
|
+
"""执行规划逻辑"""
|
149
|
+
if reply.state == TaskPlannerState.GLOBAL_FINISHED:
|
150
|
+
_C(Markdown("全局目标已达成,任务完成!"), reply_type=ReplyType.TASK_RESULT)
|
151
|
+
return False, reply.state
|
152
|
+
elif reply.state == TaskPlannerState.REQUEST_INFO:
|
153
|
+
assert reply.request_supply_infos, "Request info prompt is empty"
|
154
|
+
_O(Markdown(f"### 需要补充更详细的信息\n"))
|
155
|
+
_O(Markdown(format_user_prompts(reply.request_supply_infos)))
|
156
|
+
return True, reply.state
|
157
|
+
elif reply.state == TaskPlannerState.CODING_PLANNED:
|
158
|
+
assert reply.subtask_id, "Subtask id is empty"
|
159
|
+
assert reply.subtask_subject, "Subtask subject is empty"
|
160
|
+
assert reply.subtask_coding_prompt, "Subtask coding prompt is empty"
|
161
|
+
assert reply.subtask_summary_prompt, "Subtask summary prompt is empty"
|
162
|
+
_M(
|
163
|
+
f"### 子任务: {reply.subtask_subject}\n"
|
164
|
+
f"- ID: {reply.subtask_id}\n"
|
165
|
+
f"- Coding: {reply.subtask_coding_prompt}\n"
|
166
|
+
f"- Summary: {reply.subtask_summary_prompt}\n"
|
167
|
+
)
|
168
|
+
self.task.set_data("task_id", reply.subtask_id)
|
169
|
+
self.task.set_data("subject", reply.subtask_subject)
|
170
|
+
self.task.set_data("coding_prompt", reply.subtask_coding_prompt)
|
171
|
+
self.task.set_data("summary_prompt", reply.subtask_summary_prompt)
|
172
|
+
self.task.set_data("result", "")
|
173
|
+
return False, reply.state
|
174
|
+
elif reply.state == TaskPlannerState.REASONING_PLANNED:
|
175
|
+
assert reply.subtask_id, "Subtask id is empty"
|
176
|
+
assert reply.subtask_subject, "Subtask subject is empty"
|
177
|
+
assert reply.subtask_summary_prompt, "Subtask summary prompt is empty"
|
178
|
+
_M(
|
179
|
+
f"### 子任务: {reply.subtask_subject}\n"
|
180
|
+
f"- ID: {reply.subtask_id}\n"
|
181
|
+
f"- Reasoning: {reply.subtask_summary_prompt}\n"
|
182
|
+
)
|
183
|
+
self.task.set_data("task_id", reply.subtask_id)
|
184
|
+
self.task.set_data("subject", reply.subtask_subject)
|
185
|
+
self.task.set_data("summary_prompt", reply.subtask_summary_prompt)
|
186
|
+
self.task.set_data("result", "")
|
187
|
+
return False, reply.state
|
188
|
+
else:
|
189
|
+
raise ValueError(f"Unknown task planner state: {reply.state}")
|
@@ -0,0 +1,61 @@
|
|
1
|
+
"""
|
2
|
+
Copyright (c) 2025 viewstar000
|
3
|
+
|
4
|
+
This software is released under the MIT License.
|
5
|
+
https://opensource.org/licenses/MIT
|
6
|
+
"""
|
7
|
+
|
8
|
+
from IPython.display import Markdown
|
9
|
+
from .base import BaseChatAgent, AgentOutputFormat
|
10
|
+
from ..bot_outputs import _D, _I, _W, _E, _F, _M, _B, _C, _O
|
11
|
+
from ..bot_outputs import ReplyType
|
12
|
+
|
13
|
+
TASK_REASONER_PROMPT = """\
|
14
|
+
**角色定义**:
|
15
|
+
|
16
|
+
你是一个推理分析与信息提炼专家,能够从已有的数据、结果中推理分析并提取出关键结论。
|
17
|
+
|
18
|
+
**任务要求**:
|
19
|
+
|
20
|
+
- 在已有的数据、结果中进行推理分析,按需提取关键结论,并将结论输出为**人类可读的总结**
|
21
|
+
- 包含以下内容:
|
22
|
+
1. 核心发现(如"Electronics类别月均增长12%")
|
23
|
+
2. 数据支撑(引用关键数值或图表)
|
24
|
+
3. 其它建议(如新子任务Prompt等)
|
25
|
+
|
26
|
+
{% include "TASK_OUTPUT_FORMAT" %}
|
27
|
+
|
28
|
+
---
|
29
|
+
|
30
|
+
{% include "TASK_CONTEXTS" %}
|
31
|
+
|
32
|
+
---
|
33
|
+
|
34
|
+
{% include "CODE_CONTEXTS" %}
|
35
|
+
|
36
|
+
---
|
37
|
+
|
38
|
+
**当前子任务信息**:
|
39
|
+
|
40
|
+
### 当前子任务目标:
|
41
|
+
{{ task.subject }}
|
42
|
+
|
43
|
+
### 当前任务分析总结要求:
|
44
|
+
{{ task.summary_prompt }}
|
45
|
+
|
46
|
+
---
|
47
|
+
|
48
|
+
请按要求输出任务结论:
|
49
|
+
"""
|
50
|
+
|
51
|
+
|
52
|
+
class TaskReasoningAgent(BaseChatAgent):
|
53
|
+
|
54
|
+
PROMPT = TASK_REASONER_PROMPT
|
55
|
+
OUTPUT_FORMAT = AgentOutputFormat.TEXT
|
56
|
+
DISPLAY_REPLY = False
|
57
|
+
|
58
|
+
def on_reply(self, reply: str):
|
59
|
+
_C(Markdown("### 任务总结\n" + reply), reply_type=ReplyType.TASK_RESULT)
|
60
|
+
assert reply, "Reply is empty"
|
61
|
+
self.task.set_data("result", reply)
|
@@ -0,0 +1,106 @@
|
|
1
|
+
"""
|
2
|
+
Copyright (c) 2025 viewstar000
|
3
|
+
|
4
|
+
This software is released under the MIT License.
|
5
|
+
https://opensource.org/licenses/MIT
|
6
|
+
"""
|
7
|
+
|
8
|
+
import json
|
9
|
+
|
10
|
+
from enum import Enum
|
11
|
+
from typing import List, Optional, Dict, Any
|
12
|
+
from pydantic import BaseModel, Field
|
13
|
+
from IPython.display import Markdown
|
14
|
+
from .base import BaseChatAgent, AgentOutputFormat
|
15
|
+
from ..bot_outputs import ReplyType, _D, _I, _W, _E, _F, _M, _B, _C, _O, markdown_block
|
16
|
+
from ..utils import RequestUserPrompt, format_user_prompts
|
17
|
+
|
18
|
+
TASK_REASONER_PROMPT = """\
|
19
|
+
**角色定义**:
|
20
|
+
|
21
|
+
你是一个推理分析与信息提炼专家,能够从已有的数据、结果中推理分析并提取出关键结论。
|
22
|
+
|
23
|
+
**任务要求**:
|
24
|
+
|
25
|
+
- 在已有的数据、结果中进行推理分析,按需提取关键结论,并将结论输出为**人类可读的总结**
|
26
|
+
- 包含以下内容:
|
27
|
+
1. 核心发现(如"Electronics类别月均增长12%")
|
28
|
+
2. 数据支撑(引用关键数值或图表)
|
29
|
+
3. 其它建议(如新子任务Prompt等)
|
30
|
+
- 在引用其它已完成的子任务的结果时,特别是其important_infos中的信息,要保证准确、清晰、完整,不要出现任何误导信息
|
31
|
+
|
32
|
+
注:任务代码执行的结果不会记录在全局上下文中,只有任务总结的结果会记录在全局上下文中,
|
33
|
+
因此任务总结中应包含对代码执行结果的简要说明,以便后续子任务使用。
|
34
|
+
|
35
|
+
{% include "TASK_OUTPUT_FORMAT" %}
|
36
|
+
|
37
|
+
---
|
38
|
+
|
39
|
+
{% include "TASK_CONTEXTS" %}
|
40
|
+
|
41
|
+
---
|
42
|
+
|
43
|
+
{% include "CODE_CONTEXTS" %}
|
44
|
+
|
45
|
+
---
|
46
|
+
|
47
|
+
**当前子任务信息**:
|
48
|
+
|
49
|
+
### 当前子任务目标:
|
50
|
+
{{ task.subject }}
|
51
|
+
|
52
|
+
### 当前任务总结要求:
|
53
|
+
{{ task.summary_prompt }}
|
54
|
+
|
55
|
+
---
|
56
|
+
|
57
|
+
请按要求输出任务结论:
|
58
|
+
"""
|
59
|
+
|
60
|
+
|
61
|
+
class TaskStructureReasonOutput(BaseModel):
|
62
|
+
|
63
|
+
summary: str = Field(description=f"任务总结的详细描述", examples=["..."])
|
64
|
+
important_infos: Optional[Dict[str, Any]] = Field(
|
65
|
+
None,
|
66
|
+
description="任务总结中的重要信息,特别是需要后续子任务重点关注的信息。"
|
67
|
+
"注意:该字段仅支持结构化信息,不能使用代码、长文本等非结构化信息",
|
68
|
+
examples=[
|
69
|
+
{
|
70
|
+
"..._constraint": "...",
|
71
|
+
"..._expression": "...",
|
72
|
+
"..._patterns": ["...", "..."],
|
73
|
+
"..._execution_strategies": ["...", "..."],
|
74
|
+
"..._features": {"...": "...", "...": "..."},
|
75
|
+
"..._mapping_rules": {"...": "...", "...": "..."},
|
76
|
+
"...": "...",
|
77
|
+
}
|
78
|
+
],
|
79
|
+
)
|
80
|
+
request_confirm_infos: Optional[List[RequestUserPrompt]] = Field(
|
81
|
+
None, description="需要用户补充确认的信息,问题应尽量简单,只需要用户回答是/否或在备选项中选择即可"
|
82
|
+
)
|
83
|
+
|
84
|
+
|
85
|
+
class TaskStructureReasoningAgent(BaseChatAgent):
|
86
|
+
|
87
|
+
PROMPT = TASK_REASONER_PROMPT
|
88
|
+
OUTPUT_FORMAT = AgentOutputFormat.JSON
|
89
|
+
OUTPUT_JSON_SCHEMA = TaskStructureReasonOutput
|
90
|
+
DISPLAY_REPLY = True
|
91
|
+
|
92
|
+
def on_reply(self, reply: TaskStructureReasonOutput):
|
93
|
+
assert reply.summary, "Reply is empty"
|
94
|
+
_C(Markdown("### 任务总结\n\n" + reply.summary), reply_type=ReplyType.TASK_RESULT)
|
95
|
+
self.task.set_data("result", reply.summary)
|
96
|
+
if reply.important_infos:
|
97
|
+
self.task.set_data("important_infos", reply.important_infos)
|
98
|
+
_O(
|
99
|
+
markdown_block(
|
100
|
+
f"```json\n{json.dumps(reply.important_infos, indent=4, ensure_ascii=False)}\n```",
|
101
|
+
title="重要信息",
|
102
|
+
)
|
103
|
+
)
|
104
|
+
if reply.request_confirm_infos:
|
105
|
+
_O(Markdown(f"### 需要补充确认的信息\n"))
|
106
|
+
_O(Markdown(format_user_prompts(reply.request_confirm_infos, title="用户补充确认信息")))
|