LightAgent 0.3.2__tar.gz → 0.3.3__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.
- {lightagent-0.3.2 → lightagent-0.3.3}/LightAgent/la_core.py +71 -22
- {lightagent-0.3.2 → lightagent-0.3.3}/PKG-INFO +302 -103
- {lightagent-0.3.2 → lightagent-0.3.3}/README.de.md +20 -9
- {lightagent-0.3.2 → lightagent-0.3.3}/README.es.md +21 -12
- {lightagent-0.3.2 → lightagent-0.3.3}/README.fr.md +20 -10
- {lightagent-0.3.2 → lightagent-0.3.3}/README.ja.md +21 -11
- {lightagent-0.3.2 → lightagent-0.3.3}/README.ko.md +18 -11
- {lightagent-0.3.2 → lightagent-0.3.3}/README.md +65 -17
- {lightagent-0.3.2 → lightagent-0.3.3}/README.pt.md +18 -9
- {lightagent-0.3.2 → lightagent-0.3.3}/README.ru.md +40 -11
- {lightagent-0.3.2 → lightagent-0.3.3}/README.zh-CN.md +76 -12
- {lightagent-0.3.2 → lightagent-0.3.3}/pyproject.toml +4 -2
- {lightagent-0.3.2 → lightagent-0.3.3}/LICENSE +0 -0
- {lightagent-0.3.2 → lightagent-0.3.3}/LightAgent/__init__.py +0 -0
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
"""
|
|
5
5
|
作者: [weego/WXAI-Team]
|
|
6
|
-
版本: 0.3.
|
|
7
|
-
最后更新: 2025-
|
|
6
|
+
版本: 0.3.3
|
|
7
|
+
最后更新: 2025-05-05
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import asyncio
|
|
@@ -22,12 +22,12 @@ from copy import deepcopy
|
|
|
22
22
|
from datetime import datetime
|
|
23
23
|
from functools import partial
|
|
24
24
|
from typing import List, Dict, Any, Callable, Union, Optional, Generator, AsyncGenerator
|
|
25
|
+
from uuid import uuid4
|
|
25
26
|
|
|
26
27
|
import httpx
|
|
27
28
|
from mcp import ClientSession, StdioServerParameters
|
|
28
29
|
from mcp.client.sse import sse_client
|
|
29
30
|
from mcp.client.stdio import stdio_client
|
|
30
|
-
from openai import OpenAI
|
|
31
31
|
from openai.types.chat import ChatCompletionChunk
|
|
32
32
|
|
|
33
33
|
# 全局工具注册表
|
|
@@ -36,7 +36,10 @@ _FUNCTION_INFO = {} # 工具名称 -> 工具info信息
|
|
|
36
36
|
_OPENAI_FUNCTION_SCHEMAS = [] # OpenAI 格式的工具描述
|
|
37
37
|
_PROMPT_FUNCTION_SCHEMAS = [] # prompt 格式的工具描述
|
|
38
38
|
|
|
39
|
-
__version__ = "0.3.
|
|
39
|
+
__version__ = "0.3.3" # 你可以根据需要设置版本号
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# openai.langfuse_auth_check()
|
|
40
43
|
|
|
41
44
|
|
|
42
45
|
def register_tool_manually(tools: List[Union[str, Callable]]) -> bool:
|
|
@@ -186,7 +189,10 @@ def filter_tools_schemas(refined_content: str) -> json:
|
|
|
186
189
|
:param refined_content: 包含工具列表的JSON字符串
|
|
187
190
|
"""
|
|
188
191
|
# global _OPENAI_FUNCTION_SCHEMAS # 声明操作全局变量
|
|
189
|
-
|
|
192
|
+
"""安全解析可能包含 Markdown 代码块的 JSON"""
|
|
193
|
+
refined_content = refined_content.strip()
|
|
194
|
+
if refined_content.startswith('```json') and refined_content.endswith('```'):
|
|
195
|
+
refined_content = refined_content[7:-3].strip() # 去除 ```json 和 ```
|
|
190
196
|
try:
|
|
191
197
|
# 解析工具列表
|
|
192
198
|
parsed_data: Dict[str, List[Dict]] = json.loads(refined_content)
|
|
@@ -413,7 +419,7 @@ class MCPClientManager:
|
|
|
413
419
|
|
|
414
420
|
|
|
415
421
|
class LightAgent:
|
|
416
|
-
__version__ = "0.3.
|
|
422
|
+
__version__ = "0.3.3" # 将版本号放在类中
|
|
417
423
|
|
|
418
424
|
def __init__(
|
|
419
425
|
self,
|
|
@@ -425,16 +431,18 @@ class LightAgent:
|
|
|
425
431
|
api_key: str | None = None, # 模型 api key
|
|
426
432
|
base_url: str | httpx.URL | None = None, # 模型 base url
|
|
427
433
|
websocket_base_url: str | httpx.URL | None = None, # 模型 websocket base url
|
|
428
|
-
memory=None, # 支持外部传入记忆模块
|
|
434
|
+
memory: str | None = None, # 支持外部传入记忆模块
|
|
429
435
|
tree_of_thought: bool = False, # 是否启用链式思考
|
|
430
436
|
tot_model: str | None = None, # 链式思考模型
|
|
431
437
|
tot_api_key: str | None = None, # 链式思考模型API密钥
|
|
432
438
|
tot_base_url: str | httpx.URL | None = None, # 链式思考模型base_url
|
|
439
|
+
filter_tools: bool = True, # 是否启用工具过滤
|
|
433
440
|
self_learning: bool = False, # 是否启用agent自我学习
|
|
434
441
|
tools: List[Union[str, Callable]] = None, # 支持工具混合输入
|
|
435
442
|
debug: bool = False, # 是否启用调试模式
|
|
436
443
|
log_level: str = "INFO", # 日志级别(INFO, DEBUG, ERROR)
|
|
437
|
-
log_file: Optional[str] = None # 日志文件路径
|
|
444
|
+
log_file: Optional[str] = None, # 日志文件路径
|
|
445
|
+
tracetools: Optional[dict] = None, # log跟踪工具
|
|
438
446
|
) -> None:
|
|
439
447
|
"""
|
|
440
448
|
初始化 LightAgent。
|
|
@@ -451,10 +459,12 @@ class LightAgent:
|
|
|
451
459
|
:param tot_model: 使用的模型名称。
|
|
452
460
|
:param tot_api_key: API 密钥。
|
|
453
461
|
:param tot_base_url: API 的基础 URL。
|
|
462
|
+
:param filter_tools: 是否启用工具过滤。
|
|
454
463
|
:param tools: 工具列表,支持函数名称(字符串)或函数对象。
|
|
455
464
|
:param debug: 是否启用调试模式。
|
|
456
465
|
:param log_level: 日志级别(INFO, DEBUG, ERROR)。
|
|
457
466
|
:param log_file: 日志文件路径。
|
|
467
|
+
:param tracetools: log跟踪工具。
|
|
458
468
|
"""
|
|
459
469
|
self.mcp_setting = None
|
|
460
470
|
self.mcp_client = None
|
|
@@ -477,9 +487,11 @@ class LightAgent:
|
|
|
477
487
|
self.memory = memory
|
|
478
488
|
self.tree_of_thought = tree_of_thought
|
|
479
489
|
self.self_learning = self_learning
|
|
490
|
+
self.filter_tools = filter_tools
|
|
480
491
|
|
|
481
492
|
self.debug = debug
|
|
482
493
|
self.log_level = log_level.upper()
|
|
494
|
+
self.traceid = "" # 用于存储 traceid
|
|
483
495
|
# 确保 log 目录存在
|
|
484
496
|
log_dir = 'logs'
|
|
485
497
|
if not os.path.exists(log_dir):
|
|
@@ -507,10 +519,6 @@ class LightAgent:
|
|
|
507
519
|
if base_url is None:
|
|
508
520
|
base_url = f"https://api.openai.com/v1"
|
|
509
521
|
|
|
510
|
-
self.client = OpenAI(
|
|
511
|
-
base_url=base_url,
|
|
512
|
-
api_key=self.api_key
|
|
513
|
-
)
|
|
514
522
|
if self.tree_of_thought:
|
|
515
523
|
if tot_api_key is None:
|
|
516
524
|
tot_api_key = api_key
|
|
@@ -519,10 +527,36 @@ class LightAgent:
|
|
|
519
527
|
if not tot_model:
|
|
520
528
|
tot_model = "deepseek-r1" # 默认思维推理模型为deepseek-r1
|
|
521
529
|
self.tot_model = tot_model
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
530
|
+
|
|
531
|
+
if tracetools is None:
|
|
532
|
+
self.tracetools = []
|
|
533
|
+
if tracetools:
|
|
534
|
+
self.tracetools = tracetools
|
|
535
|
+
# 初始化工具列表
|
|
536
|
+
from langfuse.openai import openai as la_openai
|
|
537
|
+
la_openai.langfuse_public_key = self.tracetools['TraceToolConfig']['langfuse_public_key']
|
|
538
|
+
la_openai.langfuse_secret_key = self.tracetools['TraceToolConfig']['langfuse_secret_key']
|
|
539
|
+
la_openai.langfuse_enabled = self.tracetools['TraceToolConfig'][
|
|
540
|
+
'langfuse_enabled'] # Default is True, set to False to disable Langfuse
|
|
541
|
+
la_openai.langfuse_host = self.tracetools['TraceToolConfig']['langfuse_host'] # 🇪🇺 EU region
|
|
542
|
+
la_openai.base_url = base_url
|
|
543
|
+
la_openai.api_key = self.api_key
|
|
544
|
+
self.client = la_openai
|
|
545
|
+
if self.tree_of_thought:
|
|
546
|
+
la_openai.base_url = tot_base_url
|
|
547
|
+
la_openai.api_key = tot_api_key
|
|
548
|
+
self.tot_client = la_openai
|
|
549
|
+
else:
|
|
550
|
+
from openai import OpenAI as la_openai
|
|
551
|
+
self.client = la_openai(
|
|
552
|
+
base_url=base_url,
|
|
553
|
+
api_key=self.api_key
|
|
525
554
|
)
|
|
555
|
+
if self.tree_of_thought:
|
|
556
|
+
self.tot_client = la_openai(
|
|
557
|
+
base_url=tot_base_url,
|
|
558
|
+
api_key=tot_api_key
|
|
559
|
+
)
|
|
526
560
|
|
|
527
561
|
def get_tool(self, tool_name: str) -> Callable:
|
|
528
562
|
"""
|
|
@@ -629,7 +663,10 @@ class LightAgent:
|
|
|
629
663
|
"""
|
|
630
664
|
if not self.debug:
|
|
631
665
|
return
|
|
632
|
-
|
|
666
|
+
if self.traceid is not None:
|
|
667
|
+
log_message = f"[TraceID: {self.traceid}] {action}: {data}"
|
|
668
|
+
else:
|
|
669
|
+
log_message = f"{action}: {data}"
|
|
633
670
|
if level == "DEBUG":
|
|
634
671
|
self.logger.debug(log_message)
|
|
635
672
|
elif level == "INFO":
|
|
@@ -671,6 +708,7 @@ class LightAgent:
|
|
|
671
708
|
:param metadata: 元数据。
|
|
672
709
|
:return: 代理的回复。
|
|
673
710
|
"""
|
|
711
|
+
self.traceid = uuid4().hex
|
|
674
712
|
self.log("INFO", "run", {"query": query, "user_id": user_id, "light_swarm": light_swarm, "stream": stream})
|
|
675
713
|
if history is None:
|
|
676
714
|
history = []
|
|
@@ -687,19 +725,25 @@ class LightAgent:
|
|
|
687
725
|
# self._transfer_to_agent(light_swarm.agents[target_agent_name], query, stream=stream)
|
|
688
726
|
# return # 立即结束当前生成器
|
|
689
727
|
|
|
690
|
-
#
|
|
728
|
+
# 0. 判断是否需要转移任务
|
|
691
729
|
if light_swarm:
|
|
692
730
|
result = self._handle_task_transfer(query, light_swarm, stream)
|
|
693
731
|
if result is not None:
|
|
694
732
|
return result
|
|
695
733
|
|
|
696
|
-
#
|
|
734
|
+
# 1. 正常处理任务
|
|
697
735
|
now = datetime.now()
|
|
698
736
|
current_date = now.strftime("%Y-%m-%d")
|
|
699
737
|
current_time = now.strftime("%H:%M:%S")
|
|
700
738
|
system_prompt = f"##代理名称:{self.name} ##代理指令 /n{self.instructions} ##身份 /n {self.role} /n 请一步一步思考来完成用户的要求。尽可能完成用户的回答,如果有补充信息,请参考补充信息来调用工具,直到获取所有满足用户的提问所需的答案。 /n 今日的日期: {current_date} 当前时间: {current_time}"
|
|
701
739
|
params = dict(model=self.model, stream=stream)
|
|
702
740
|
memory = ''
|
|
741
|
+
|
|
742
|
+
# 2.添加langfuse的session
|
|
743
|
+
if self.tracetools:
|
|
744
|
+
params["session_id"] = self.traceid
|
|
745
|
+
self.log("DEBUG", "Query Trace ID", {"query": query})
|
|
746
|
+
|
|
703
747
|
# 3. 从记忆中检索相关内容&保存记忆
|
|
704
748
|
if self.memory:
|
|
705
749
|
related_memories = self.memory.retrieve(query=query, user_id=user_id)
|
|
@@ -743,6 +787,7 @@ class LightAgent:
|
|
|
743
787
|
params["messages"].append({"role": item["role"], "content": item["content"]})
|
|
744
788
|
# 最后添加当前用户的查询信息
|
|
745
789
|
params["messages"].append({"role": "user", "content": query})
|
|
790
|
+
|
|
746
791
|
response = self.client.chat.completions.create(**params)
|
|
747
792
|
|
|
748
793
|
result = self._core_run_logic(response, params, stream, max_retry)
|
|
@@ -1160,7 +1205,7 @@ class LightAgent:
|
|
|
1160
1205
|
self.log("DEBUG", "run_thought", {"system_prompt": system_prompt})
|
|
1161
1206
|
|
|
1162
1207
|
try:
|
|
1163
|
-
# 第一次请求,生成初始的工具使用计划
|
|
1208
|
+
# 1. 第一次请求,生成初始的工具使用计划
|
|
1164
1209
|
params = dict(model=tot_model,
|
|
1165
1210
|
messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": query}],
|
|
1166
1211
|
stream=False)
|
|
@@ -1168,7 +1213,7 @@ class LightAgent:
|
|
|
1168
1213
|
initial_content = response.choices[0].message.content
|
|
1169
1214
|
self.log("DEBUG", "initial_response", {"response": initial_content})
|
|
1170
1215
|
|
|
1171
|
-
# 第二次请求,请求大模型反思并生成新的工具使用规划
|
|
1216
|
+
# 2. 第二次请求,请求大模型反思并生成新的工具使用规划
|
|
1172
1217
|
reflection_prompt = "请反思你的回答,请严格按照<工具列表>中的工具来规划,不可以创造其他新的工具。请输出新的任务规划,不要输出其他分析和回答。"
|
|
1173
1218
|
reflection_params = dict(model=tot_model, messages=[
|
|
1174
1219
|
{"role": "user", "content": f"{system_prompt} /n 开始思考问题: {query}"},
|
|
@@ -1204,8 +1249,12 @@ class LightAgent:
|
|
|
1204
1249
|
tool_reflection_response = self.tot_client.chat.completions.create(**tool_reflection_params)
|
|
1205
1250
|
tool_reflection_result = tool_reflection_response.choices[0].message.content
|
|
1206
1251
|
self.log("DEBUG", "tool_reflection_result", {"result": tool_reflection_result})
|
|
1207
|
-
|
|
1208
|
-
|
|
1252
|
+
|
|
1253
|
+
# 3.执行自适应工具过滤
|
|
1254
|
+
current_tools = []
|
|
1255
|
+
if self.filter_tools:
|
|
1256
|
+
current_tools = filter_tools_schemas(tool_reflection_result)
|
|
1257
|
+
self.log("DEBUG", "current_tools", {"get_tools": current_tools})
|
|
1209
1258
|
|
|
1210
1259
|
return refined_content, current_tools
|
|
1211
1260
|
|