pycoze 0.1.316__py3-none-any.whl → 0.1.334__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.
pycoze/bot/chat.py CHANGED
@@ -17,11 +17,11 @@ async def check_interrupt_file(interval, interrupt_file, chat_task):
17
17
  break
18
18
 
19
19
 
20
- async def run_with_interrupt_check(conversation_history, user_input, cwd: str, abilities, bot_setting, interrupt_file):
20
+ async def run_with_interrupt_check(conversation_history, user_input, cwd: str, abilities, bot_setting, has_any_tool, interrupt_file):
21
21
  clear_chat_data()
22
22
  try:
23
23
  chat_task = asyncio.create_task(
24
- handle_user_inputs(conversation_history, user_input, cwd, abilities, bot_setting)
24
+ handle_user_inputs(conversation_history, user_input, cwd, abilities, bot_setting, has_any_tool)
25
25
  )
26
26
  check_task = asyncio.create_task(
27
27
  check_interrupt_file(0.5, interrupt_file, chat_task)
@@ -52,10 +52,11 @@ def chat(bot_setting_file: str):
52
52
  bot_setting = json.load(f)
53
53
  abilities = get_abilities(bot_setting)
54
54
  cwd = tempfile.mkdtemp()
55
+ system_prompt, has_any_tool = get_system_prompt(abilities, bot_setting)
55
56
  conversation_history = [
56
57
  {
57
58
  "role": "system",
58
- "content": get_system_prompt(abilities, bot_setting),
59
+ "content": system_prompt,
59
60
  }
60
61
  ]
61
62
  while True:
@@ -69,12 +70,12 @@ def chat(bot_setting_file: str):
69
70
  if "interruptFile" in params:
70
71
  asyncio.run(
71
72
  run_with_interrupt_check(
72
- conversation_history, user_input, cwd, abilities, bot_setting, params["interruptFile"]
73
+ conversation_history, user_input, cwd, abilities, bot_setting, has_any_tool, params["interruptFile"]
73
74
  )
74
75
  )
75
76
  else:
76
77
  asyncio.run(
77
- handle_user_inputs(conversation_history, user_input, cwd, abilities, bot_setting)
78
+ handle_user_inputs(conversation_history, user_input, cwd, abilities, bot_setting, has_any_tool)
78
79
  )
79
80
 
80
81
  output("assistant", CHAT_DATA["info"])
pycoze/bot/chat_base.py CHANGED
@@ -145,7 +145,7 @@ async def stream_openai_response(conversation_history, start_new_stream):
145
145
  yield ("text", text_content.strip())
146
146
 
147
147
 
148
- async def handle_user_inputs(conversation_history, user_input, cwd, abilities, bot_setting):
148
+ async def handle_user_inputs(conversation_history, user_input, cwd, abilities, bot_setting, has_any_tool):
149
149
  no_exit_if_incomplete = bot_setting["systemAbility"]['no_exit_if_incomplete']
150
150
  programmer_mode = bot_setting["systemAbility"]['programmer_mode']
151
151
 
@@ -174,7 +174,7 @@ async def handle_user_inputs(conversation_history, user_input, cwd, abilities, b
174
174
  conversation_history, start_new_stream
175
175
  ):
176
176
  if len(response) == 2:
177
- if response[0] == "text" and response[1].strip() != "":
177
+ if response[0] == "text" and response[1].strip() != "" or (response[0] == "json" and not has_any_tool):
178
178
  conversation_history.append(
179
179
  {"role": "assistant", "content": response[1]}
180
180
  )
pycoze/bot/lib.py CHANGED
@@ -68,28 +68,38 @@ def get_system_prompt(abilities, bot_setting):
68
68
 
69
69
 
70
70
  abilities_str = "\n".join([function_to_string(a) for a in abilities])
71
+
71
72
  context = {
72
73
  "prompt": bot_setting["prompt"],
73
74
  "system": system,
74
75
  "cd_prompt": cd_prompt,
75
76
  "abilities_str": abilities_str,
76
- "programmer_mode": True,
77
- "no_exit_if_incomplete": True,
78
- "allow_read_file": True,
79
- "allow_read_multiple_files": True,
80
- "allow_execute_command": True,
81
- "allow_write_or_overwrite_file": True,
82
- "allow_replace_part_of_a_file": True,
83
- "allow_search_files": True,
84
- "allow_list_files": True,
85
- "allow_access_webpage": True,
86
-
77
+ "programmer_mode": False,
78
+ "no_exit_if_incomplete": False,
79
+ "allow_read_file": False,
80
+ "allow_read_multiple_files": False,
81
+ "allow_execute_command": False,
82
+ "allow_write_or_overwrite_file": False,
83
+ "allow_replace_part_of_a_file": False,
84
+ "allow_search_files": False,
85
+ "allow_list_files": False,
86
+ "allow_access_webpage": False,
87
87
  }
88
88
 
89
89
  context.update(bot_setting["systemAbility"])
90
+
91
+ has_any_tool = False
92
+ if len(abilities) > 0:
93
+ has_any_tool = True
94
+ for key in bot_setting["systemAbility"]:
95
+ if key != "programmer_mode" and bot_setting["systemAbility"][key] == True:
96
+ has_any_tool = True
97
+ break
98
+
99
+ context["has_any_tool"] = has_any_tool
90
100
  system_prompt = template.render(context)
91
101
 
92
- return system_prompt
102
+ return system_prompt, has_any_tool
93
103
 
94
104
 
95
105
  def resolve_relative_path(cwd:str, path_str: str) -> str:
pycoze/bot/prompt.md CHANGED
@@ -1,5 +1,6 @@
1
1
  {{ prompt }}
2
2
 
3
+ {% if has_any_tool %}
3
4
  ==== Tool Usage
4
5
  You have access to a set of tools running on the {{ system }} system that are executed upon user approval. Only one tool can be used per message, and you will receive the result of the tool's execution in the user's response. You progressively use these tools to accomplish tasks, with each tool's usage being based on the outcome of the previous tool.
5
6
 
@@ -17,6 +18,7 @@ Here's the translation in English:
17
18
  }
18
19
  }
19
20
  ```
21
+ {% endif %}
20
22
 
21
23
  {% if allow_read_file %}
22
24
  For example:
pycoze/bot/tools.py CHANGED
@@ -10,6 +10,7 @@ from pycoze.api import window, web
10
10
  import traceback
11
11
 
12
12
 
13
+
13
14
  class InvalidToolError(Exception):
14
15
  """无效工具错误"""
15
16
 
@@ -45,7 +46,7 @@ class ExecuteCommandTool(Tool):
45
46
  "confirm",
46
47
  f"Do you want to execute the command{self.params['command']}? ",
47
48
  )
48
- if approve.strip().lower().startswith("n"):
49
+ if not approve:
49
50
  return "User does not wish to run the command."
50
51
  result = subprocess.run(
51
52
  self.params["command"],
@@ -267,6 +268,7 @@ class ToolExecutor:
267
268
  try:
268
269
  result = func(**params)
269
270
  except Exception as e:
271
+ print("Execute tool error:", traceback.format_exc())
270
272
  return False, traceback.format_exc()
271
273
  return True, str(result)
272
274
  else:
pycoze/reference/lib.py CHANGED
@@ -1,10 +1,42 @@
1
1
  import os
2
2
  import sys
3
3
  import importlib
4
- import types
5
4
  import functools
5
+ import inspect
6
+ import asyncio
7
+ import nest_asyncio
6
8
 
9
+ # 应用 nest_asyncio 补丁,以允许在已经运行的事件循环中再次运行事件循环
10
+ nest_asyncio.apply()
7
11
 
12
+ def call_func(func, args=None, kwargs=None):
13
+ if args is None:
14
+ args = ()
15
+ if kwargs is None:
16
+ kwargs = {}
17
+
18
+ if inspect.isgeneratorfunction(func):
19
+ return list(func(*args, **kwargs))
20
+ elif inspect.iscoroutinefunction(func):
21
+ coro = func(*args, **kwargs) if inspect.iscoroutinefunction(func) else func
22
+ try:
23
+ # 尝试获取当前运行的事件循环
24
+ loop = asyncio.get_running_loop()
25
+ except RuntimeError:
26
+ # 如果没有运行的事件循环,使用 asyncio.run()
27
+ return asyncio.run(coro)
28
+ else:
29
+ # 如果事件循环已经在运行,直接调度协程并等待结果
30
+ async def run_coro():
31
+ return await coro
32
+ # 在当前事件循环中调度任务并等待完成
33
+ future = asyncio.ensure_future(run_coro())
34
+ while not future.done():
35
+ loop.run_until_complete(asyncio.sleep(0.1)) # 避免阻塞
36
+ return future.result()
37
+ else:
38
+ return func(*args, **kwargs)
39
+
8
40
  class ChangeDirectoryAndPath:
9
41
  """Context manager to change the current working directory and sys.path."""
10
42
 
@@ -19,7 +51,8 @@ class ChangeDirectoryAndPath:
19
51
  return self
20
52
 
21
53
  def __exit__(self, exc_type, exc_value, traceback):
22
- sys.path.remove(self.module_path)
54
+ if self.module_path in sys.path:
55
+ sys.path.remove(self.module_path)
23
56
  os.chdir(self.old_path)
24
57
 
25
58
 
@@ -57,16 +90,16 @@ def wrapped_func(func, module_path):
57
90
  except:
58
91
  print(f"called unknown")
59
92
  with ChangeDirectoryAndPath(module_path):
60
- result = func(*args, **kwargs)
61
- try:
62
- if isinstance(result, types.GeneratorType):
63
- result = list(result)
64
- print(f"{func.__name__} 调用完毕,结果为:", result)
65
- except:
66
- pass
93
+ try:
94
+ result = call_func(func, args, kwargs)
95
+ except Exception as e:
96
+ print(f"调用 {func.__name__} 时发生错误: {str(e)}")
97
+ raise
98
+
99
+ print(f"{func.__name__} 调用完毕,结果为:", result)
100
+
67
101
  return result
68
102
 
69
103
  wrapped_function = functools.wraps(func)(_wrapped)
70
104
  return wrapped_function
71
105
 
72
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pycoze
3
- Version: 0.1.316
3
+ Version: 0.1.334
4
4
  Summary: Package for pycoze only!
5
5
  Author: Yuan Jie Xiong
6
6
  Author-email: aiqqqqqqq@qq.com
@@ -12,15 +12,15 @@ pycoze/api/lib/view.py,sha256=_PIpTfeuTPPlMDKshMGsqFQYMq7ZiO4Hg5XwHwDoU60,7357
12
12
  pycoze/api/lib/web.py,sha256=GWgtiTJOolKOX2drXcwuyqTcbo5FQVxa1NuBGcNyjyc,223
13
13
  pycoze/api/lib/window.py,sha256=bTkQCzQZ7i3pYXB70bUSTBNJ9C4TW_X3yMae1VkquGk,1944
14
14
  pycoze/bot/__init__.py,sha256=rL3Q-ycczRpSFfKn84fg3QBl5k22WpyeIU5qOEjEby8,79
15
- pycoze/bot/chat.py,sha256=cYMXFe0hgN0CTcI5BiUtte2eTZwgYLKq1vBDQ-eqB5c,3246
16
- pycoze/bot/chat_base.py,sha256=czmOKUum3Rwo4lAOJtfslxaF8RKauWzj26s_WMmQa48,9180
17
- pycoze/bot/lib.py,sha256=IIihXPODCbM29TlxS0lhm2Fw3GWm2MzUeAn9LGa86lg,6889
15
+ pycoze/bot/chat.py,sha256=ts2Qr7IZGyTFlnIccG8m04H7c8Yr1xtjPgzmjeQUzo4,3351
16
+ pycoze/bot/chat_base.py,sha256=H6zLxblMbyDLsf5T13YYCoEfLl__axw67PbfM0vnYbg,9242
17
+ pycoze/bot/lib.py,sha256=smigeWuhl8esHE-Y5l_9bpjJkEJ5OqrxTyPcO8JIubM,7224
18
18
  pycoze/bot/message.py,sha256=Zq-_k8HztBMOUIs3hbOvWvwHBNopn4UJJBliCROIGcc,718
19
- pycoze/bot/prompt.md,sha256=ehjdvZ-se9NaH0OSiDEvrFE9kvdj9MTZlWZUTxPY780,15743
20
- pycoze/bot/tools.py,sha256=987hUTy-kZfTwUUd3WStPhNUPkOIGCVm-JWL3Qh70pg,9648
19
+ pycoze/bot/prompt.md,sha256=XHP8EdtzmnlMbM0xTe5GKnjAIFq7KauUARiNly2atz4,15777
20
+ pycoze/bot/tools.py,sha256=j8l0sXEPn_yjTllHcmYEr_auVDuOicXdDco4bhZVIIA,9694
21
21
  pycoze/reference/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  pycoze/reference/bot.py,sha256=pxHVYo0G3P3YZ--vBYbMEiEyBoxxPwaO5dMTf9WFMSc,2014
23
- pycoze/reference/lib.py,sha256=6jvowP2LqjyV21ppRhmtxHxnQJHCbHmlpbj9btV2RQ4,2191
23
+ pycoze/reference/lib.py,sha256=ixiexCA6XWAda_G2ZVDSbFqTJmbkTvYLN47-nc5zyFU,3530
24
24
  pycoze/reference/tool.py,sha256=h7G3KSoZYWq5IJu6E0-shIQ3XiJeJsgSM85GxEnhF98,1107
25
25
  pycoze/reference/workflow.py,sha256=whQtw_FAxvlSbjow1oNFLdytPjjRs_pDBbQmNjaX6zc,1340
26
26
  pycoze/ui/__init__.py,sha256=uaXet23wUk64TcZjpBX8qOx4aUhwA_ucrmcxy7Q4Qr4,929
@@ -33,8 +33,8 @@ pycoze/utils/arg.py,sha256=jop1tBfe5hYkHW1NSpCeaZBEznkgguBscj_7M2dWfrs,503
33
33
  pycoze/utils/env.py,sha256=5pWlXfM1F5ZU9hhv1rHlDEanjEW5wf0nbyez9bNRqqA,559
34
34
  pycoze/utils/socket.py,sha256=bZbFFRH4mfThzRqt55BAAGQ6eICx_ja4x8UGGrUdAm8,2428
35
35
  pycoze/utils/text_or_file.py,sha256=gpxZVWt2DW6YiEg_MnMuwg36VNf3TX383QD_1oZNB0Y,551
36
- pycoze-0.1.316.dist-info/LICENSE,sha256=QStd_Qsd0-kAam_-sOesCIp_uKrGWeoKwt9M49NVkNU,1090
37
- pycoze-0.1.316.dist-info/METADATA,sha256=-Shyz80jC19pUcPlpYDC8TkkDYCmsYeOnQpNYxnEp7U,854
38
- pycoze-0.1.316.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
39
- pycoze-0.1.316.dist-info/top_level.txt,sha256=76dPeDhKvOCleL3ZC5gl1-y4vdS1tT_U1hxWVAn7sFo,7
40
- pycoze-0.1.316.dist-info/RECORD,,
36
+ pycoze-0.1.334.dist-info/LICENSE,sha256=QStd_Qsd0-kAam_-sOesCIp_uKrGWeoKwt9M49NVkNU,1090
37
+ pycoze-0.1.334.dist-info/METADATA,sha256=3ILPNMNEHtM9bWi3C9mmZvzCxaa0kxmz3_QGewzOUbk,854
38
+ pycoze-0.1.334.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
39
+ pycoze-0.1.334.dist-info/top_level.txt,sha256=76dPeDhKvOCleL3ZC5gl1-y4vdS1tT_U1hxWVAn7sFo,7
40
+ pycoze-0.1.334.dist-info/RECORD,,