jupyter-agent 2025.6.103__py3-none-any.whl → 2025.6.105__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.
Files changed (41) hide show
  1. jupyter_agent/bot_actions.py +270 -0
  2. jupyter_agent/bot_agents/__init__.py +0 -42
  3. jupyter_agent/bot_agents/base.py +85 -45
  4. jupyter_agent/bot_agents/master_planner.py +2 -0
  5. jupyter_agent/bot_agents/output_task_result.py +6 -7
  6. jupyter_agent/bot_agents/request_user_supply.py +186 -0
  7. jupyter_agent/bot_agents/task_planner_v3.py +12 -13
  8. jupyter_agent/bot_agents/task_reasoner.py +2 -2
  9. jupyter_agent/bot_agents/task_structrue_reasoner.py +19 -12
  10. jupyter_agent/bot_agents/task_structrue_summarier.py +19 -18
  11. jupyter_agent/bot_agents/task_summarier.py +2 -2
  12. jupyter_agent/bot_agents/task_verifier.py +1 -1
  13. jupyter_agent/bot_agents/task_verify_summarier.py +5 -6
  14. jupyter_agent/bot_chat.py +2 -2
  15. jupyter_agent/bot_contexts.py +28 -23
  16. jupyter_agent/bot_evaluation.py +325 -0
  17. jupyter_agent/bot_evaluators/__init__.py +0 -0
  18. jupyter_agent/bot_evaluators/base.py +42 -0
  19. jupyter_agent/bot_evaluators/dummy_flow.py +20 -0
  20. jupyter_agent/bot_evaluators/dummy_global.py +20 -0
  21. jupyter_agent/bot_evaluators/dummy_task.py +20 -0
  22. jupyter_agent/bot_evaluators/flow_global_planning.py +88 -0
  23. jupyter_agent/bot_evaluators/flow_task_executor.py +152 -0
  24. jupyter_agent/bot_flows/__init__.py +0 -4
  25. jupyter_agent/bot_flows/base.py +114 -10
  26. jupyter_agent/bot_flows/master_planner.py +7 -2
  27. jupyter_agent/bot_flows/task_executor_v3.py +45 -20
  28. jupyter_agent/bot_magics.py +108 -53
  29. jupyter_agent/bot_outputs.py +56 -3
  30. jupyter_agent/utils.py +20 -31
  31. {jupyter_agent-2025.6.103.dist-info → jupyter_agent-2025.6.105.dist-info}/METADATA +39 -8
  32. jupyter_agent-2025.6.105.dist-info/RECORD +40 -0
  33. jupyter_agent-2025.6.105.dist-info/entry_points.txt +2 -0
  34. jupyter_agent/bot_agents/task_planner_v1.py +0 -158
  35. jupyter_agent/bot_agents/task_planner_v2.py +0 -172
  36. jupyter_agent/bot_flows/task_executor_v1.py +0 -86
  37. jupyter_agent/bot_flows/task_executor_v2.py +0 -84
  38. jupyter_agent-2025.6.103.dist-info/RECORD +0 -33
  39. {jupyter_agent-2025.6.103.dist-info → jupyter_agent-2025.6.105.dist-info}/WHEEL +0 -0
  40. {jupyter_agent-2025.6.103.dist-info → jupyter_agent-2025.6.105.dist-info}/licenses/LICENSE +0 -0
  41. {jupyter_agent-2025.6.103.dist-info → jupyter_agent-2025.6.105.dist-info}/top_level.txt +0 -0
@@ -11,7 +11,11 @@ import datetime
11
11
  import jinja2
12
12
 
13
13
  from enum import Enum
14
+ from typing import Optional, Dict, List, Tuple, Any, Type
15
+ from pydantic import BaseModel, Field
14
16
  from IPython.display import display, Markdown
17
+ from .bot_evaluation import BaseEvaluationRecord
18
+ from .bot_actions import ActionBase
15
19
  from .utils import no_indent, no_wrap
16
20
 
17
21
  STAGE_SWITCHER_SCRIPT = no_wrap(
@@ -187,12 +191,15 @@ class AgentOutput:
187
191
  )
188
192
  self.template = self.jinja_env.from_string(AGENT_OUTPUT_TEMPLEATE)
189
193
  self.handler = None
194
+ self._is_dirty = True
190
195
  self._latest_display_tm = 0
191
196
  self._contents = {}
192
197
  self._active_stage = None
193
198
  self._agent_data_timestamp = None
194
199
  self._agent_data = {}
195
200
  self._logging_records = []
201
+ self._evaluation_records = []
202
+ self._action_records = []
196
203
 
197
204
  @property
198
205
  def content(self):
@@ -226,11 +233,18 @@ class AgentOutput:
226
233
  "jupyter-agent-data": self._agent_data,
227
234
  }
228
235
  )
236
+ if self._evaluation_records:
237
+ metadata["jupyter-agent-evaluation-records"] = [record.model_dump() for record in self._evaluation_records]
238
+ if self._action_records:
239
+ metadata["jupyter-agent-action-records"] = [record.model_dump() for record in self._action_records]
229
240
  return metadata
230
241
 
231
242
  def display(self, stage=None, force=False, wait=True):
232
- if stage is not None:
243
+ if stage is not None and stage != self._active_stage:
233
244
  self._active_stage = stage
245
+ self._is_dirty = True
246
+ if not self._is_dirty and not force:
247
+ return
234
248
  if not force and time.time() - self._latest_display_tm < 1:
235
249
  if wait:
236
250
  time.sleep(1 - (time.time() - self._latest_display_tm))
@@ -241,6 +255,7 @@ class AgentOutput:
241
255
  else:
242
256
  self.handler.update(Markdown(self.content), metadata=self.metadata)
243
257
  self._latest_display_tm = time.time()
258
+ self._is_dirty = False
244
259
 
245
260
  def clear(self, stage=None, clear_metadata=False):
246
261
  if stage is None:
@@ -249,6 +264,7 @@ class AgentOutput:
249
264
  self._contents[stage] = []
250
265
  if clear_metadata:
251
266
  self._agent_data = {}
267
+ self._is_dirty = True
252
268
  self.display(force=False, wait=False)
253
269
 
254
270
  def output_block(
@@ -268,6 +284,7 @@ class AgentOutput:
268
284
  "code_language": code_language,
269
285
  }
270
286
  )
287
+ self._is_dirty = True
271
288
  self.display(stage, force=False, wait=False)
272
289
 
273
290
  def output_text(self, content, stage=None, code_language="python"):
@@ -283,6 +300,7 @@ class AgentOutput:
283
300
  self._contents[stage][-1]["content"] += "\n" + content
284
301
  else:
285
302
  self._contents[stage].append({"type": "text", "content": content, "code_language": code_language})
303
+ self._is_dirty = True
286
304
  self.display(stage, force=False, wait=False)
287
305
 
288
306
  def output_markdown(self, content, stage=None):
@@ -291,12 +309,14 @@ class AgentOutput:
291
309
  if stage not in self._contents:
292
310
  self._contents[stage] = []
293
311
  self._contents[stage].append({"type": "markdown", "content": content})
312
+ self._is_dirty = True
294
313
  self.display(stage, force=False, wait=False)
295
314
 
296
315
  def output_agent_data(self, **kwargs):
297
316
  self.log(f"output agent data {kwargs}", level="DEBUG")
298
317
  self._agent_data.update(kwargs)
299
- self._agent_data_timestamp = int(time.time() * 1000)
318
+ self._agent_data_timestamp = time.time()
319
+ self._is_dirty = True
300
320
  self.display(force=False, wait=False)
301
321
 
302
322
  def log(self, msg, level="INFO"):
@@ -318,6 +338,31 @@ class AgentOutput:
318
338
  "content": content,
319
339
  }
320
340
  )
341
+ self._is_dirty = True
342
+ self.display(force=False, wait=False)
343
+
344
+ def log_evaluation(self, record: BaseEvaluationRecord):
345
+ assert isinstance(
346
+ record, BaseEvaluationRecord
347
+ ), "record must be an instance of BaseEvalutionRecord or its subclass"
348
+ if record.timestamp == 0:
349
+ record.timestamp = time.time()
350
+ self._evaluation_records.append(record)
351
+ self.log(
352
+ f"Evaluation: {record.eval_type}[{record.cell_index}] duration: {record.execution_duration:.2f}s "
353
+ f"success: {record.is_success} correct: {record.correct_score:.2f}",
354
+ level="INFO",
355
+ )
356
+ self._is_dirty = True
357
+ self.display(force=False, wait=False)
358
+
359
+ def log_action(self, record: ActionBase):
360
+ assert isinstance(record, ActionBase), "record must be an instance of BaseActionRecord or its subclass"
361
+ if record.timestamp == 0:
362
+ record.timestamp = time.time()
363
+ self._action_records.append(record)
364
+ self.log(f"Action: {record.action} from {record.source}", level="INFO")
365
+ self._is_dirty = True
321
366
  self.display(force=False, wait=False)
322
367
 
323
368
 
@@ -363,6 +408,14 @@ def output_agent_data(**kwargs):
363
408
  get_output().output_agent_data(**kwargs)
364
409
 
365
410
 
411
+ def output_evaluation(record: BaseEvaluationRecord):
412
+ get_output().log_evaluation(record)
413
+
414
+
415
+ def output_action(record: ActionBase):
416
+ get_output().log_action(record)
417
+
418
+
366
419
  def clear_output(stage=None, clear_metadata=False):
367
420
  get_output().clear(stage, clear_metadata)
368
421
 
@@ -475,6 +528,6 @@ _A = output_agent_data
475
528
  _L = log
476
529
  _D = lambda msg: log(msg, level="DEBUG")
477
530
  _I = lambda msg: log(msg, level="INFO")
478
- _W = lambda msg: log(msg, level="WARNING")
531
+ _W = lambda msg: log(msg, level="WARN")
479
532
  _E = lambda msg: log(msg, level="ERROR")
480
533
  _F = lambda msg: log(msg, level="FATAL")
jupyter_agent/utils.py CHANGED
@@ -91,37 +91,6 @@ class TeeOutputCapture(capture_output):
91
91
  return CapturedIO(stdout, stderr, outputs)
92
92
 
93
93
 
94
- class RequestUserPrompt(BaseModel):
95
- prompt: str = Field(
96
- description="需要用户补充详细信息的Prompt",
97
- examples=["请补充与...相关的详细的信息", "请确认...是否...", "请提供..."],
98
- )
99
- example: Optional[str] = Field(None, description="示例", examples=["..."])
100
-
101
-
102
- class UserPromptResponse(BaseModel):
103
- prompt: str = Field(description="需要用户补充详细信息的Prompt", examples=["..."])
104
- response: str = Field(description="用户补充的详细信息", examples=["..."])
105
-
106
-
107
- def request_user_response(prompts: list[RequestUserPrompt]) -> list[UserPromptResponse]:
108
- responses = []
109
- for prompt in prompts:
110
- response = input(f"{prompt.prompt} (例如: {prompt.example})")
111
- responses.append(UserPromptResponse(prompt=prompt.prompt, response=response))
112
- return responses
113
-
114
-
115
- def format_user_prompts(prompts: list[RequestUserPrompt], title="用户补充详细信息") -> str:
116
- result = "```markdown\n"
117
- result += f"### {title}\n\n"
118
- result += "\n".join(
119
- [f"- **Issue**: {prompt.prompt} (例如: {prompt.example})\n- **Reply**: " for prompt in prompts]
120
- )
121
- result += "\n```\n"
122
- return result
123
-
124
-
125
94
  def no_indent(text: str) -> str:
126
95
  return re.sub(r"^\s+", "", text, flags=re.MULTILINE)
127
96
 
@@ -136,3 +105,23 @@ def no_newline(text: str) -> str:
136
105
 
137
106
  def no_space(text: str) -> str:
138
107
  return re.sub(r"\s+", "", text, flags=re.MULTILINE)
108
+
109
+
110
+ class EnvironmentCapbilities(BaseModel):
111
+ save_metadata: bool = False
112
+ user_confirm: bool = False
113
+ user_supply_info: bool = False
114
+ set_cell_content: bool = False
115
+
116
+
117
+ __env_capbilities = EnvironmentCapbilities()
118
+
119
+
120
+ def get_env_capbilities() -> EnvironmentCapbilities:
121
+ return __env_capbilities
122
+
123
+
124
+ def set_env_capbilities(env_capbilities: EnvironmentCapbilities):
125
+ global __env_capbilities
126
+
127
+ __env_capbilities = env_capbilities
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jupyter-agent
3
- Version: 2025.6.103
3
+ Version: 2025.6.105
4
4
  Summary: 调用LLM实现Jupyter代码的自动生成、执行、调试等功能
5
5
  Author: viewstar000
6
6
  License: MIT
@@ -10,14 +10,16 @@ Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >=3.12
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
+ Requires-Dist: bottle
14
+ Requires-Dist: ipynbname
13
15
  Requires-Dist: ipython
16
+ Requires-Dist: jinja2
17
+ Requires-Dist: nbclient
14
18
  Requires-Dist: nbformat
15
- Requires-Dist: ipynbname
16
19
  Requires-Dist: openai
17
- Requires-Dist: traitlets
18
- Requires-Dist: pyyaml
19
- Requires-Dist: jinja2
20
20
  Requires-Dist: pydantic
21
+ Requires-Dist: pyyaml
22
+ Requires-Dist: traitlets
21
23
  Dynamic: license-file
22
24
 
23
25
  # jupyter-agent
@@ -94,15 +96,21 @@ pip install /path/to/jupyter-agent/dist/jupyter_agent-xxxx-py3-none-any.whl
94
96
  # 设置当前Notebook的路径,当无法自动获取时需要手工指定,以Vscode中的Notebook为例
95
97
  %config BotMagics.notebook_path = globals()["__vsc_ipynb_file__"]
96
98
 
97
- # 设置是否保存任务数据到Metadata,只有Vscode中安装了jupyter-agent-extension后才支持
99
+ # 设置运行环境是否保存任务数据到Metadata,默认为False,仅在Vscode中安装jupyter-agent-extension后或在评估模式下支持
98
100
  %config BotMagics.support_save_meta = True
101
+ # 设置运行环境是否设置单元格内容,默认为False,权在Vscode中安装jupyter-agent-extension后或在评估模式下支持
102
+ %config BotMagics.support_set_cell_content = True
99
103
 
100
104
  # 设置日志级别,可选值为DEBUG、INFO、WARN、ERROR、FATAL,默认为INFO
101
105
  %config BotMagics.logging_level = 'DEBUG'
102
106
 
107
+ # 开启自动评估功能,默认为False,调用LLM对当前结果进行打分,目前仅实现了对子任务的整体打分
108
+ %config BotMagics.enable_evaluating = True
109
+ # 开启模拟用户补充信息功能,默认为False,调用LLM模拟对Agent的提问进行补充,用于自动评估
110
+ %config BotMagics.enable_supply_mocking = True
111
+
103
112
  # 设置是否显示思考过程,默认为True
104
113
  %config BotMagics.display_think = True
105
-
106
114
  # 设置是否显示发送给出LLM的消息和LLM的回答,默认为False
107
115
  %config BotMagics.display_message = True
108
116
  %config BotMagics.display_response = True
@@ -150,6 +158,14 @@ pip install /path/to/jupyter-agent/dist/jupyter_agent-xxxx-py3-none-any.whl
150
158
 
151
159
  更详细用法可参考[示例Notebook](https://github.com/viewstar000/jupyter-agent/blob/main/examples/data_loader.ipynb)
152
160
 
161
+ ### 评估模式
162
+
163
+ 工具提供了`bot_eval`命令用于在评估模式下执行notebook。在评估模式下,工具会顺序执行所有有单元格,直到例全局目标完成。
164
+
165
+ ```bash
166
+ bot_eval [-o output_eval.ipynb] [-e output_eval.jsonl] input.ipynb
167
+ ```
168
+
153
169
  ## 贡献
154
170
 
155
171
  欢迎提交 issue 或 pull request 参与贡献。
@@ -236,12 +252,19 @@ Advanced Configuration:
236
252
  # Set the current notebook path, when it is not automatically obtained, it needs to be manually specified, for example, in Vscode Notebook
237
253
  %config BotMagics.notebook_path = globals()["__vsc_ipynb_file__"]
238
254
 
239
- # Set whether to save task data to Metadata, only Vscode installed with jupyter-agent-extension supports
255
+ # Set whether to save task data to Metadata, only Vscode installed with jupyter-agent-extension or evaluation mode supports this.
240
256
  %config BotMagics.support_save_meta = True
257
+ # Set whether to set cell content, only Vscode installed with jupyter-agent-extension or evaluation mode supports this.
258
+ %config BotMagics.support_set_cell_content = True
241
259
 
242
260
  # Set the log level, available values are DEBUG、INFO、WARN、ERROR、FATAL, default is INFO
243
261
  %config BotMagics.logging_level = 'DEBUG'
244
262
 
263
+ # Enable automatic evaluation, default is False, call LLM to evaluate the overall result of the subtask
264
+ %config BotMagics.enable_evaluating = True
265
+ # Enable the simulation of user filling in information, default is False, call LLM to simulate the question of the agent to fill in
266
+ %config BotMagics.enable_supply_mocking = True
267
+
245
268
  # Set whether to display thinking process, default is True
246
269
  %config BotMagics.display_think = True
247
270
 
@@ -289,6 +312,14 @@ After generating code for a subtask, the tool will call the corresponding agent
289
312
 
290
313
  For more details, please refer to [example notebook](https://github.com/viewstar000/jupyter-agent/blob/main/examples/data_loader.ipynb)
291
314
 
315
+ ### Evaluation mode
316
+
317
+ Use `bot_eval` command to evaluate the code generated by the agent in evaluation mode. The evaluation mode will execute all cells in order and stop when the global goal is completed.
318
+
319
+ ```python
320
+ bot_eval [-o output_eval.ipynb] [-e output_eval.jsonl] input.ipynb
321
+ ```
322
+
292
323
  ## Contributing
293
324
 
294
325
  Welcome to submit issues or pull requests to participate in contributions.
@@ -0,0 +1,40 @@
1
+ jupyter_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ jupyter_agent/bot_actions.py,sha256=Zq9_nfh4SJdMxkjqcTyQzS0RY4RwofaRkGq_4aexO2o,8453
3
+ jupyter_agent/bot_chat.py,sha256=4zjkHtyOabT1bvGO-n4ZTMw0XREU_XDlgfLCI5gpxsw,8834
4
+ jupyter_agent/bot_contexts.py,sha256=f9PmrA8dTH8v4WLdNL_ZSMJUzMVLuRldLWYwL4vXQ6c,19489
5
+ jupyter_agent/bot_evaluation.py,sha256=t4SH6Gq4BmSyyRMozyQ2623XNGmgtCi9CTNRvOqzuRM,14266
6
+ jupyter_agent/bot_magics.py,sha256=fOStbhYwg60hUbuZwqYIbMrn_TBg0JfTwFT92pysUFw,9869
7
+ jupyter_agent/bot_outputs.py,sha256=QDzReXLqZsU7RAPR4F9JEotxAtIe9YA3ZklCJ9U_jVg,16239
8
+ jupyter_agent/utils.py,sha256=8XKXXZB1EgCwIJEqYJigA8C84FzVTc2xdcF-y5kO3kY,3634
9
+ jupyter_agent/bot_agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ jupyter_agent/bot_agents/base.py,sha256=FwCl1Z9E-nIL99qheGEcKO0H_PEd0I9OzEXd23cmQrg,12308
11
+ jupyter_agent/bot_agents/master_planner.py,sha256=aXXgtyarBmDFNAypdEbpQoxzgGkU-botX7bE9q9w3sM,1392
12
+ jupyter_agent/bot_agents/output_task_result.py,sha256=4DeAmDzjUI_0yfb26f5sLIwa74aJRzEQXbMRSyYMv1g,761
13
+ jupyter_agent/bot_agents/request_user_supply.py,sha256=wL_DyIWPd5-Jdq0boTCAhF-nxf_gPmzXgSPM6jOBFFU,6128
14
+ jupyter_agent/bot_agents/task_code_executor.py,sha256=M3oeEBlmsNz89f-yk3_nzsWKGH2C0o7AH059D_J94D8,2206
15
+ jupyter_agent/bot_agents/task_coder.py,sha256=7fXq9nk1yH3F_mJfCMZBktHmxGfgmpuChMQbpEuL0w4,1783
16
+ jupyter_agent/bot_agents/task_debuger.py,sha256=77pa_Awgvzxm3XkFA1oZsGr8SPJkjApKMtkmoySShmI,1367
17
+ jupyter_agent/bot_agents/task_planner_v3.py,sha256=qrvgfsgWs-tD8L1NWzyv9-fwamNTEm6etJYBy-Ipz28,8487
18
+ jupyter_agent/bot_agents/task_reasoner.py,sha256=OHYzPEb1e4eOGdKfo9655tTEdZRqz-s-Vdgp-2G0Jxc,1425
19
+ jupyter_agent/bot_agents/task_structrue_reasoner.py,sha256=NQ0V9uY4UelRH5Glw3PwS9HiN4I74A9FxNPcMC5P0lg,3792
20
+ jupyter_agent/bot_agents/task_structrue_summarier.py,sha256=bMrNlb_Xrs4FNosuTBPmMmmHIoPyCIjSUVR_0j7aZZ8,3898
21
+ jupyter_agent/bot_agents/task_summarier.py,sha256=85pW9mSqI-9nfuKr2n-h36OpD3QLA0WPJ1T7eWyww-A,1747
22
+ jupyter_agent/bot_agents/task_verifier.py,sha256=z45jo38c9U4FnS87-AnI4PGki14uuCRhyWVPtAbkl70,2478
23
+ jupyter_agent/bot_agents/task_verify_summarier.py,sha256=usW7RDE8-XAZXAgyHkWU1ZmY-kwi-_ePVXBngYFtb_M,4899
24
+ jupyter_agent/bot_evaluators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ jupyter_agent/bot_evaluators/base.py,sha256=yMmeFCNrQRhO9Y4s1OeRAXgxD_m-20a14hM1XFvmN-I,1374
26
+ jupyter_agent/bot_evaluators/dummy_flow.py,sha256=W0BWJKMgXIilZY0i8eP_SNVgqTUd1CT_uqMBs5aygVA,473
27
+ jupyter_agent/bot_evaluators/dummy_global.py,sha256=yZ8fo2xfVN8gZTpBfs8EJ4dcv2t4ls6aXxn3Mo7bNSk,483
28
+ jupyter_agent/bot_evaluators/dummy_task.py,sha256=owh6g6ItPXXYjesplzNMxVcKAU_kktWtuJhqRzZ05V4,475
29
+ jupyter_agent/bot_evaluators/flow_global_planning.py,sha256=kOLd0dCoqrMi6zbe5chXrwxmdahtt8QqX3UnAZgk3AQ,2419
30
+ jupyter_agent/bot_evaluators/flow_task_executor.py,sha256=gzHlKkP9K5fICYgUY5BKAzjwqn3xScxklohqoUCJaZk,4450
31
+ jupyter_agent/bot_flows/__init__.py,sha256=Xe7EbC6bt04Nc4Yr0e--FVvBJCxkZCZkwYL9oahMBtI,338
32
+ jupyter_agent/bot_flows/base.py,sha256=ADNs_-F4XLvEthRyjjBgGkv4KOOYIJRIdaRgjQXHq_k,14116
33
+ jupyter_agent/bot_flows/master_planner.py,sha256=DAsMLXzrKCZaCNoEuPK3A5yWY_PxIcN3bwzYrlpx0pU,794
34
+ jupyter_agent/bot_flows/task_executor_v3.py,sha256=_K6FOM2ZnMZAa8B_Rt1HXDVB20eCQl4Eew2KyfDPyEU,4685
35
+ jupyter_agent-2025.6.105.dist-info/licenses/LICENSE,sha256=nWMmSIg7OepTIDX_OPP0-T9ImeCBBoog7eJxm5awtcM,1068
36
+ jupyter_agent-2025.6.105.dist-info/METADATA,sha256=QqX2ahmch7Ofn_l8GHRjW5BpA1pvlm9kpOTbc5QpnIM,11699
37
+ jupyter_agent-2025.6.105.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ jupyter_agent-2025.6.105.dist-info/entry_points.txt,sha256=063AB86wSrC_V-iiEEqxTlR4uz-T7VH_YagIpmKFQC0,63
39
+ jupyter_agent-2025.6.105.dist-info/top_level.txt,sha256=c3USTBZ7DZGuvLKlEW-QfGIx0tzn98iCEn3bpdYnDtE,14
40
+ jupyter_agent-2025.6.105.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ bot_eval = jupyter_agent.bot_evaluation:main
@@ -1,158 +0,0 @@
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}")