beswarm 0.2.54__py3-none-any.whl → 0.2.55__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.
beswarm/agents/planact.py CHANGED
@@ -95,15 +95,17 @@ class InstructionAgent(BaseAgent):
95
95
  conversation_history[0]["content"].append({"type": "text", "text": extracted_content})
96
96
 
97
97
  for message in conversation_history:
98
- if message.get("content") and isinstance(message["content"], str) \
99
- and "<knowledge_graph_tree>" in message["content"] and self.graph_tree:
100
- message["content"] = replace_xml_content(message["content"], "knowledge_graph_tree", self.graph_tree)
98
+ if message.get("content") and isinstance(message["content"], str):
99
+ if "<knowledge_graph_tree>" in message["content"] and self.graph_tree:
100
+ message["content"] = replace_xml_content(message["content"], "knowledge_graph_tree", self.graph_tree)
101
101
 
102
102
  for index, message in enumerate(raw_conversation_history):
103
- if message.get("content") and isinstance(message["content"], str) \
104
- and "<knowledge_graph_tree>" in message["content"] and self.graph_tree:
105
- message["content"] = replace_xml_content(message["content"], "knowledge_graph_tree", self.graph_tree)
106
- raw_conversation_history[index] = message
103
+ if message.get("content") and isinstance(message["content"], str):
104
+ if "<knowledge_graph_tree>" in message["content"] and self.graph_tree:
105
+ message["content"] = replace_xml_content(message["content"], "knowledge_graph_tree", self.graph_tree)
106
+ raw_conversation_history[index] = message
107
+ if "\n\nYour message **must** end with [done] to signify the end of your output." in message["content"]:
108
+ message["content"] = message["content"].replace("\n\nYour message **must** end with [done] to signify the end of your output.", "")
107
109
 
108
110
  return conversation_history
109
111
 
@@ -166,7 +168,7 @@ class InstructionAgent(BaseAgent):
166
168
  "现在开始执行第一步:\n"
167
169
  f"{instruction}"
168
170
  )
169
- self.broker.publish({"instruction": instruction, "conversation": message["conversation"]}, self.publish_topic)
171
+ self.broker.publish({"instruction": instruction + "\n\nYour message **must** end with [done] to signify the end of your output.", "conversation": message["conversation"]}, self.publish_topic)
170
172
  self.last_instruction = None
171
173
  else:
172
174
  self.logger.error("\n❌ 指令智能体生成的指令不符合要求,正在重新生成。")
@@ -301,7 +303,8 @@ class BrokerWorker:
301
303
  shell=os.getenv('SHELL', 'Unknown'), current_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
302
304
  tools_list=self.tools_json
303
305
  ),
304
- "print_log": True, "temperature": 0.5, "function_call_max_loop": 100, "logger": self.logger
306
+ "print_log": True, "temperature": 0.5, "function_call_max_loop": 100, "logger": self.logger,
307
+ "check_done": True
305
308
  }
306
309
 
307
310
  instruction_agent = InstructionAgent(
@@ -27,8 +27,6 @@ from .utils import (
27
27
  gemini_max_token_65k_models = ["gemini-2.5-pro", "gemini-2.0-pro", "gemini-2.0-flash-thinking", "gemini-2.5-flash"]
28
28
 
29
29
  async def get_gemini_payload(request, engine, provider, api_key=None):
30
- import re
31
-
32
30
  headers = {
33
31
  'Content-Type': 'application/json'
34
32
  }
@@ -176,6 +174,24 @@ async def get_gemini_payload(request, engine, provider, api_key=None):
176
174
  ]
177
175
  generation_config = {}
178
176
 
177
+ def process_tool_parameters(data):
178
+ if isinstance(data, dict):
179
+ # 移除 Gemini 不支持的 'additionalProperties'
180
+ data.pop("additionalProperties", None)
181
+
182
+ # 将 'default' 值移入 'description'
183
+ if "default" in data:
184
+ default_value = data.pop("default")
185
+ description = data.get("description", "")
186
+ data["description"] = f"{description}\nDefault: {default_value}"
187
+
188
+ # 递归处理
189
+ for value in data.values():
190
+ process_tool_parameters(value)
191
+ elif isinstance(data, list):
192
+ for item in data:
193
+ process_tool_parameters(item)
194
+
179
195
  for field, value in request.model_dump(exclude_unset=True).items():
180
196
  if field not in miss_fields and value is not None:
181
197
  if field == "tools" and "gemini-2.0-flash-thinking" in original_model:
@@ -185,22 +201,9 @@ async def get_gemini_payload(request, engine, provider, api_key=None):
185
201
  processed_tools = []
186
202
  for tool in value:
187
203
  function_def = tool["function"]
188
- # gemini不支持parameters里面的additionalProperties字段,需要删除
189
- if safe_get(function_def, "parameters", "additionalProperties", default=None) is not None:
190
- del function_def["parameters"]["additionalProperties"]
191
-
192
- # 处理 parameters.properties 中的 default 字段
193
- if safe_get(function_def, "parameters", "properties", default=None):
194
- for prop_value in function_def["parameters"]["properties"].values():
195
- if "additionalProperties" in prop_value:
196
- del prop_value["additionalProperties"]
197
- if "default" in prop_value:
198
- # 将 default 值添加到 description 中
199
- default_value = prop_value["default"]
200
- description = prop_value.get("description", "")
201
- prop_value["description"] = f"{description}\nDefault: {default_value}"
202
- # 删除 default 字段
203
- del prop_value["default"]
204
+ if "parameters" in function_def:
205
+ process_tool_parameters(function_def["parameters"])
206
+
204
207
  if function_def["name"] != "googleSearch" and function_def["name"] != "googleSearch":
205
208
  processed_tools.append({"function": function_def})
206
209
 
@@ -67,6 +67,7 @@ class chatgpt(BaseLLM):
67
67
  cut_history_by_function_name: str = "",
68
68
  cache_messages: list = None,
69
69
  logger: logging.Logger = None,
70
+ check_done: bool = False,
70
71
  ) -> None:
71
72
  """
72
73
  Initialize Chatbot with API key (from https://platform.openai.com/account/api-keys)
@@ -86,6 +87,7 @@ class chatgpt(BaseLLM):
86
87
  self.function_call_max_loop = function_call_max_loop
87
88
  self.cut_history_by_function_name = cut_history_by_function_name
88
89
  self.latest_file_content = {}
90
+ self.check_done = check_done
89
91
 
90
92
  if logger:
91
93
  self.logger = logger
@@ -465,6 +467,12 @@ class chatgpt(BaseLLM):
465
467
  missing_required_params = []
466
468
 
467
469
  if self.use_plugins == True:
470
+ if self.check_done:
471
+ # self.logger.info(f"worker Response: {full_response}")
472
+ if not full_response.strip().endswith('[done]'):
473
+ raise Exception(f"Response is not ended with [done]: {full_response}")
474
+ else:
475
+ full_response = full_response.strip().rstrip('[done]')
468
476
  full_response = full_response.replace("<tool_code>", "").replace("</tool_code>", "")
469
477
  function_parameter = parse_function_xml(full_response)
470
478
  if function_parameter:
@@ -711,7 +719,7 @@ class chatgpt(BaseLLM):
711
719
  self.logger.info(f"api_key: {kwargs.get('api_key', self.api_key)}")
712
720
 
713
721
  # 发送请求并处理响应
714
- for i in range(3):
722
+ for i in range(10):
715
723
  if self.print_log:
716
724
  replaced_text = json.loads(re.sub(r';base64,([A-Za-z0-9+/=]+)', ';base64,***', json.dumps(json_post)))
717
725
  replaced_text_str = json.dumps(replaced_text, indent=4, ensure_ascii=False)
@@ -763,6 +771,9 @@ class chatgpt(BaseLLM):
763
771
  except httpx.RemoteProtocolError:
764
772
  continue
765
773
  except Exception as e:
774
+ if "Response is not ended with [done]:" in str(e):
775
+ self.logger.error(f"Response is not ended with [done]: {e}")
776
+ continue
766
777
  self.logger.error(f"发生了未预料的错误:{e}")
767
778
  import traceback
768
779
  self.logger.error(traceback.format_exc())
@@ -770,7 +781,7 @@ class chatgpt(BaseLLM):
770
781
  e = "您输入了无效的API URL,请使用正确的URL并使用`/start`命令重新设置API URL。具体错误如下:\n\n" + str(e)
771
782
  raise Exception(f"{e}")
772
783
  # 最后一次重试失败,向上抛出异常
773
- if i == 2:
784
+ if i == 11:
774
785
  raise Exception(f"{e}")
775
786
 
776
787
  def ask_stream(
beswarm/prompt.py CHANGED
@@ -1,10 +1,11 @@
1
1
  worker_system_prompt = """
2
2
  <communication>
3
3
  1. Format your responses in markdown. Use backticks to format file, directory, function, and class names.
4
- 2. Always respond in 中文。
5
- 3. **执行规则:** 尽力满足 user 的请求,如果 user 要求你使用工具,请自行根据工具的参数要求,组织参数,将工具调用组织成 XML 格式,即可触发工具执行流程。当 user 的指令中包含一个或多个完整的 XML 工具调用时,你的唯一且首要任务就是**完整、准确、无修改地**复述这些 XML 代码块。这是执行工具的**唯一**方式。严禁在没有复述 XML 的情况下,就声称或暗示任务已完成。
6
- 4. **生成规则:** 你拥有完全的工具调用自主权,也因此负有完全的责任。你必须亲自执行所有工具调用,绝对禁止以任何形式指示、请求或暗示user为你调用工具。当你需要调用工具(无论是根据 user 的自然语言指令,还是自己决定)时,你都**必须**在你的回复中生成格式完全正确的 XML 工具调用代码。你是操作的**执行者**,不是任务的**确认者**。这是一个强制性规则,任何情况下都不能违反。
7
- 5. **核心工作循环:单步执行模式**
4
+ 2. Your message **must** end with [done] to signify the end of your output.
5
+ 3. Always respond in 中文。
6
+ 4. **执行规则:** 尽力满足 user 的请求,如果 user 要求你使用工具,请自行根据工具的参数要求,组织参数,将工具调用组织成 XML 格式,即可触发工具执行流程。当 user 的指令中包含一个或多个完整的 XML 工具调用时,你的唯一且首要任务就是**完整、准确、无修改地**复述这些 XML 代码块。这是执行工具的**唯一**方式。严禁在没有复述 XML 的情况下,就声称或暗示任务已完成。
7
+ 5. **生成规则:** 你拥有完全的工具调用自主权,也因此负有完全的责任。你必须亲自执行所有工具调用,绝对禁止以任何形式指示、请求或暗示user为你调用工具。当你需要调用工具(无论是根据 user 的自然语言指令,还是自己决定)时,你都**必须**在你的回复中生成格式完全正确的 XML 工具调用代码。你是操作的**执行者**,不是任务的**确认者**。这是一个强制性规则,任何情况下都不能违反。
8
+ 6. **核心工作循环:单步执行模式**
8
9
  作为指令的**执行者**,而非任务的**规划师**,你必须严格遵循以下单步工作流程:
9
10
  **执行指令**
10
11
  - **严格遵从:** 只执行 user 当前下达的明确指令。在 user 明确给出下一步指令前,绝不擅自行动或推测、执行任何未明确要求的后续步骤。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beswarm
3
- Version: 0.2.54
3
+ Version: 0.2.55
4
4
  Summary: MAS
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -2,16 +2,16 @@ beswarm/__init__.py,sha256=HZjUOJtZR5QhMuDbq-wukQQn1VrBusNWai_ysGo-VVI,20
2
2
  beswarm/broker.py,sha256=64Y-djrKYaZfBQ8obwHOmr921QgZeu9BtScZWaYLfDo,9887
3
3
  beswarm/core.py,sha256=htssaaeIBZ_yOqvX9VtANoVWaZHt_7oWcxyDI1z0paQ,310
4
4
  beswarm/knowledge_graph.py,sha256=oiOMknAJzGrOHc2AyQgvrCcZAkGLhFnsnvSBdfFBWMw,14831
5
- beswarm/prompt.py,sha256=n0a1a6NThIxAYSkisg1sEKjvz2w0tozpKL4BIplaAkI,32286
5
+ beswarm/prompt.py,sha256=INVRWQZP6lysvGUcPOYI_er5-bi1gGe_qa6BTov7PmY,32362
6
6
  beswarm/taskmanager.py,sha256=ErgZa9_aBeWdmt5neRw6sDVdwSWewxip458gAjeQhS4,12188
7
7
  beswarm/utils.py,sha256=0J-b38P5QGT-A_38co7FjzaUNJykaskI7mbbcQ4w_68,8215
8
8
  beswarm/agents/chatgroup.py,sha256=PzrmRcDKAbB7cxL16nMod_CzPosDV6bfTmXxQVuv-AQ,12012
9
- beswarm/agents/planact.py,sha256=jadkGp8uzjjzh5cq0l4IMF2gn1hN6Gx94ICAzabHWpQ,19524
9
+ beswarm/agents/planact.py,sha256=xi259X0y1Sd2HBM42pp0JtCtGE3glhO12l5u5F0SvOU,19926
10
10
  beswarm/aient/aient/__init__.py,sha256=SRfF7oDVlOOAi6nGKiJIUK6B_arqYLO9iSMp-2IZZps,21
11
11
  beswarm/aient/aient/core/__init__.py,sha256=NxjebTlku35S4Dzr16rdSqSTWUvvwEeACe8KvHJnjPg,34
12
12
  beswarm/aient/aient/core/log_config.py,sha256=kz2_yJv1p-o3lUQOwA3qh-LSc3wMHv13iCQclw44W9c,274
13
13
  beswarm/aient/aient/core/models.py,sha256=d4MISNezTSe0ls0-fjuToI2SoT-sk5fWqAJuKVinIlo,7502
14
- beswarm/aient/aient/core/request.py,sha256=M1AfroPgFDG7oTLE2gisvR4BdkUeWqoTwfpxl_nxYB8,76923
14
+ beswarm/aient/aient/core/request.py,sha256=4FFCwQ7h7b6bqtrA8qw-DPJVXZTj2i1CkYccFeEwUPw,76552
15
15
  beswarm/aient/aient/core/response.py,sha256=sPcNV9qLosj3lIXElezUZEjIyglspdkBg-EsIUhr9bQ,33203
16
16
  beswarm/aient/aient/core/utils.py,sha256=D98d5Cy1h4ejKtuxS0EEDtL4YqpaZLB5tuXoVP0IBWQ,28462
17
17
  beswarm/aient/aient/core/test/test_base_api.py,sha256=pWnycRJbuPSXKKU9AQjWrMAX1wiLC_014Qc9hh5C2Pw,524
@@ -21,7 +21,7 @@ beswarm/aient/aient/core/test/test_payload.py,sha256=8jBiJY1uidm1jzL-EiK0s6UGmW9
21
21
  beswarm/aient/aient/models/__init__.py,sha256=ZTiZgbfBPTjIPSKURE7t6hlFBVLRS9lluGbmqc1WjxQ,43
22
22
  beswarm/aient/aient/models/audio.py,sha256=kRd-8-WXzv4vwvsTGwnstK-WR8--vr9CdfCZzu8y9LA,1934
23
23
  beswarm/aient/aient/models/base.py,sha256=-nnihYnx-vHZMqeVO9ljjt3k4FcD3n-iMk4tT-10nRQ,7232
24
- beswarm/aient/aient/models/chatgpt.py,sha256=t9P0PsMsjnqjv3MrUKNKC1-gy7Pf9tOb8BhBPcnbhMw,48741
24
+ beswarm/aient/aient/models/chatgpt.py,sha256=LnbWADil5oNmdBaAtXb1XcQwoaERqanO7Or9wzsg82w,49348
25
25
  beswarm/aient/aient/plugins/__init__.py,sha256=p3KO6Aa3Lupos4i2SjzLQw1hzQTigOAfEHngsldrsyk,986
26
26
  beswarm/aient/aient/plugins/arXiv.py,sha256=yHjb6PS3GUWazpOYRMKMzghKJlxnZ5TX8z9F6UtUVow,1461
27
27
  beswarm/aient/aient/plugins/config.py,sha256=2DXH-LP9KGl_P4467chJu3q4AAbX5nSn4DIkdI0aYH8,7105
@@ -116,7 +116,7 @@ beswarm/tools/search_web.py,sha256=NYrb5KL_WUGPm-fOKT8Cyjon04lxBU-gaLdrVjeYgGo,1
116
116
  beswarm/tools/subtasks.py,sha256=mIjA2QrRy9Fos4rYm8fCfu2QrsE_MGnQI9IR8dOxsGs,9885
117
117
  beswarm/tools/worker.py,sha256=_cSkRUKRJMAiZiTfnBze_e9Kc7k7KvbB5hdxdvp4FW4,2009
118
118
  beswarm/tools/write_csv.py,sha256=u0Hq18Ksfheb52MVtyLNCnSDHibITpsYBPs2ub7USYA,1466
119
- beswarm-0.2.54.dist-info/METADATA,sha256=JmhKRLbetJWjNWxQObaFQcw1EOZjZgRQm9PzwBkHjaE,3878
120
- beswarm-0.2.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
121
- beswarm-0.2.54.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
122
- beswarm-0.2.54.dist-info/RECORD,,
119
+ beswarm-0.2.55.dist-info/METADATA,sha256=iUHDB2olCdaPgC5J8ppmSdqdH6NXChIfnDsclhikhpY,3878
120
+ beswarm-0.2.55.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
121
+ beswarm-0.2.55.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
122
+ beswarm-0.2.55.dist-info/RECORD,,