LightAgent 0.2.5__tar.gz → 0.2.8__tar.gz

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.
@@ -14,10 +14,11 @@ import importlib
14
14
 
15
15
  # 全局工具注册表
16
16
  _FUNCTION_MAPPINGS = {} # 工具名称 -> 工具函数
17
+ _FUNCTION_INFO = {} # 工具名称 -> 工具info信息
17
18
  _OPENAI_FUNCTION_SCHEMAS = [] # OpenAI 格式的工具描述
18
19
  _PROMPT_FUNCTION_SCHEMAS = [] # prompt 格式的工具描述
19
20
 
20
- __version__ = "0.2.1" # 你可以根据需要设置版本号
21
+ __version__ = "0.2.8" # 你可以根据需要设置版本号
21
22
 
22
23
 
23
24
  def register_tool_manually(tools: List[Union[str, Callable]]) -> bool:
@@ -32,6 +33,9 @@ def register_tool_manually(tools: List[Union[str, Callable]]) -> bool:
32
33
 
33
34
  tool_info = func.tool_info
34
35
  tool_name = tool_info["tool_name"]
36
+
37
+ # 注册到全局字典
38
+ _FUNCTION_INFO[tool_name] = tool_info
35
39
  _FUNCTION_MAPPINGS[tool_name] = func # 注册工具
36
40
 
37
41
  # 构建 OpenAI 格式的工具描述
@@ -159,11 +163,14 @@ class LightAgent:
159
163
  instructions: Optional[str] = None, # 代理指令
160
164
  role: Optional[str] = None,
161
165
  model: str,
162
- api_key: str,
166
+ api_key: str | None = None,
163
167
  base_url: str | httpx.URL | None = None,
164
168
  websocket_base_url: str | httpx.URL | None = None,
165
169
  memory=None, # 支持外部传入记忆模块
166
170
  tree_of_thought: bool = False, # 是否启用链式思考
171
+ tot_model: str | None = None,
172
+ tot_api_key: str | None = None,
173
+ tot_base_url: str | httpx.URL | None = None,
167
174
  self_learning: bool = False, # 是否启用agent自我学习
168
175
  tools: List[Union[str, Callable]] = None, # 支持混合输入
169
176
  debug: bool = False, # 是否启用调试模式
@@ -182,6 +189,9 @@ class LightAgent:
182
189
  :param websocket_base_url: WebSocket 的基础 URL。
183
190
  :param memory: 外部传入的记忆模块,需实现 `retrieve` 和 `store` 方法。
184
191
  :param tree_of_thought: 是否启用思维链功能。
192
+ :param tot_model: 使用的模型名称。
193
+ :param tot_api_key: API 密钥。
194
+ :param tot_base_url: API 的基础 URL。
185
195
  :param tools: 工具列表,支持函数名称(字符串)或函数对象。
186
196
  :param debug: 是否启用调试模式。
187
197
  :param log_level: 日志级别(INFO, DEBUG, ERROR)。
@@ -236,9 +246,21 @@ class LightAgent:
236
246
  base_url = f"https://api.openai.com/v1"
237
247
 
238
248
  self.client = OpenAI(
239
- base_url=base_url,
240
- api_key=self.api_key
249
+ base_url = base_url,
250
+ api_key = self.api_key
241
251
  )
252
+ if self.tree_of_thought:
253
+ if tot_api_key is None:
254
+ tot_api_key = api_key
255
+ if tot_base_url is None:
256
+ tot_base_url = base_url
257
+ if not tot_model:
258
+ tot_model = "deepseek-r1" # 默认思维推理模型为deepseek-r1
259
+ self.tot_model = tot_model
260
+ self.tot_client = OpenAI(
261
+ base_url = tot_base_url,
262
+ api_key = tot_api_key
263
+ )
242
264
 
243
265
  def get_tool(self, tool_name: str) -> Callable:
244
266
  """
@@ -272,6 +294,7 @@ class LightAgent:
272
294
  # 注册工具函数
273
295
  if hasattr(tool_func, "tool_info"):
274
296
  tool_info = tool_func.tool_info
297
+ _FUNCTION_INFO[tool_name] = tool_info # 注册工具info信息
275
298
  _FUNCTION_MAPPINGS[tool_name] = tool_func
276
299
 
277
300
  # 构建 OpenAI 格式的工具描述
@@ -358,7 +381,7 @@ class LightAgent:
358
381
  query: str,
359
382
  light_swarm=None,
360
383
  stream: bool = False,
361
- max_retry: int = 5,
384
+ max_retry: int = 10,
362
385
  user_id: str = "default_user",
363
386
  history: list = None,
364
387
  metadata: Optional[Dict] = None,
@@ -398,7 +421,6 @@ class LightAgent:
398
421
  return result
399
422
 
400
423
  # 2. 正常处理任务
401
-
402
424
  now = datetime.now()
403
425
  current_date = now.strftime("%Y-%m-%d")
404
426
  current_time = now.strftime("%H:%M:%S")
@@ -435,7 +457,7 @@ class LightAgent:
435
457
  params["messages"] = [{"role": "system", "content": system_prompt}]
436
458
  # 将历史对话添加到消息列表中
437
459
  for item in history:
438
- params["messages"].append({"role": item["role"], "content": item["input"]})
460
+ params["messages"].append({"role": item["role"], "content": item["content"]})
439
461
  # 最后添加当前用户的查询信息
440
462
  params["messages"].append({"role": "user", "content": query})
441
463
  response = self.client.chat.completions.create(**params)
@@ -483,10 +505,28 @@ class LightAgent:
483
505
  combined_response += chunk # 将每个 chunk 叠加
484
506
  if combined_response == "":
485
507
  combined_response = "".join(tool_response)
508
+
509
+ # 将 combined_response 解析为 JSON 对象(如果它是 JSON 字符串)
510
+ try:
511
+ combined_response = json.loads(combined_response) # 解析 JSON
512
+ except json.JSONDecodeError:
513
+ pass # 如果不是 JSON 字符串,保持原样
514
+
515
+ # 将 JSON 对象中的 Unicode 编码转换为中文字符
516
+ if isinstance(combined_response, dict):
517
+ combined_response = json.dumps(combined_response, ensure_ascii=False) # 确保中文字符不转义
518
+
486
519
  tool_responses.append(combined_response) # 将叠加后的完整响应添加到列表
487
520
  else:
488
521
  # print(f"Non-streaming response from tool: {function_call.name}")
489
522
  combined_response = tool_response
523
+ # 如果是 JSON 字符串,解析并转换为中文
524
+ if isinstance(combined_response, str):
525
+ try:
526
+ combined_response = json.loads(combined_response) # 解析 JSON
527
+ combined_response = json.dumps(combined_response, ensure_ascii=False) # 转换为中文
528
+ except json.JSONDecodeError:
529
+ pass # 如果不是 JSON 字符串,保持原样
490
530
  tool_responses.append(combined_response) # 直接添加普通响应
491
531
 
492
532
  self.log("INFO", "tool_response", {"tool_response": combined_response})
@@ -520,6 +560,7 @@ class LightAgent:
520
560
  # 更新响应
521
561
  if function_call_name == 'finish':
522
562
  return # 如果最后调用了finish工具,则结束生成器
563
+ # print(params)
523
564
  response = self.client.chat.completions.create(**params)
524
565
 
525
566
  # 重试次数用尽
@@ -583,6 +624,7 @@ class LightAgent:
583
624
  if tool_call["name"]: # 确保工具调用有名称
584
625
  function_call = {
585
626
  "name": tool_call["name"],
627
+ "title": _FUNCTION_INFO.get(tool_call["name"], {}).get('tool_title') or '',
586
628
  "arguments": tool_call["arguments"],
587
629
  }
588
630
  self.log("INFO", "tool_call", {"function_call": function_call})
@@ -610,7 +652,16 @@ class LightAgent:
610
652
  # print(f"Streaming response from tool: {function_call['name']}")
611
653
  combined_response = ""
612
654
  for chunk in tool_response:
613
- yield chunk
655
+ # 将工具返回的数据继续流出
656
+ tool_output = {
657
+ "name": tool_call["name"],
658
+ "title": _FUNCTION_INFO.get(tool_call["name"], {}).get(
659
+ 'tool_title') or '',
660
+ "output": chunk,
661
+ }
662
+ self.log("INFO", "tool_call", {"tool_output": tool_output})
663
+ yield tool_output
664
+ # 将工具的调用信息推送给开发者
614
665
  if function_call_name == 'finish':
615
666
  content = chunk.choices[0].delta.content or ""
616
667
  combined_response += content # 将每个 chunk 叠加
@@ -788,18 +839,21 @@ class LightAgent:
788
839
 
789
840
  def run_thought(self, query: str, stream=False, tools=None):
790
841
  """使用思维树的方式 让大模型先根据get_tools_str生成一个解答用户query的工具使用计划"""
791
- tot_model = "deepseek-chat" # self.model
842
+ tot_model = self.tot_model # self.model
792
843
  tools = get_tools_str()
793
844
  if not isinstance(tools, str):
794
845
  tools = str(tools) # 确保 tools 是字符串
795
- system_prompt = f"""你是一个智能助手,请根据用户输入的问题,结合工具使用计划,生成一个思维树,并按照思维树依次调用工具步骤,最终生成一个最终回答。/n 工具列表: {tools}"""
846
+ now = datetime.now()
847
+ current_date = now.strftime("%Y-%m-%d")
848
+ current_time = now.strftime("%H:%M:%S")
849
+ system_prompt = f"""你是一个智能助手,请根据用户输入的问题,结合工具使用计划,生成一个思维树,并按照思维树依次调用工具步骤,最终生成一个最终回答。/n 今日的日期: {current_date} 当前时间: {current_time} /n 工具列表: {tools}"""
796
850
  self.log("DEBUG", "run_thought", {"system_prompt": system_prompt})
797
851
 
798
852
  # 第一次请求,生成初始的工具使用计划
799
853
  params = dict(model=tot_model,
800
854
  messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": query}],
801
855
  stream=False)
802
- response = self.client.chat.completions.create(**params)
856
+ response = self.tot_client.chat.completions.create(**params)
803
857
  initial_content = response.choices[0].message.content
804
858
  self.log("DEBUG", "initial_response", {"response": initial_content})
805
859
 
@@ -812,7 +866,7 @@ class LightAgent:
812
866
  ], stream=False)
813
867
  self.log("DEBUG", "reflection_params", {"params": reflection_params})
814
868
 
815
- reflection_response = self.client.chat.completions.create(**reflection_params)
869
+ reflection_response = self.tot_client.chat.completions.create(**reflection_params)
816
870
  refined_content = reflection_response.choices[0].message.content
817
871
  self.log("DEBUG", "refined_response", {"response": refined_content})
818
872
  return refined_content