pycoze 0.1.90__py3-none-any.whl → 0.1.94__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/access/tool_for_bot.py +29 -31
- pycoze/bot/agent/agent_types/openai_func_call_agent.py +48 -46
- pycoze/bot/bot.py +3 -2
- {pycoze-0.1.90.dist-info → pycoze-0.1.94.dist-info}/METADATA +2 -2
- {pycoze-0.1.90.dist-info → pycoze-0.1.94.dist-info}/RECORD +8 -8
- {pycoze-0.1.90.dist-info → pycoze-0.1.94.dist-info}/LICENSE +0 -0
- {pycoze-0.1.90.dist-info → pycoze-0.1.94.dist-info}/WHEEL +0 -0
- {pycoze-0.1.90.dist-info → pycoze-0.1.94.dist-info}/top_level.txt +0 -0
pycoze/access/tool_for_bot.py
CHANGED
@@ -6,16 +6,22 @@ import types
|
|
6
6
|
import langchain_core
|
7
7
|
|
8
8
|
|
9
|
-
|
10
|
-
"""
|
11
|
-
sys.path.insert(0, module_path)
|
12
|
-
os.chdir(module_path)
|
9
|
+
class ChangeDirectoryAndPath:
|
10
|
+
"""Context manager to change the current working directory and sys.path."""
|
13
11
|
|
12
|
+
def __init__(self, module_path):
|
13
|
+
self.module_path = module_path
|
14
|
+
self.old_path = None
|
14
15
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def __enter__(self):
|
17
|
+
self.old_path = os.getcwd()
|
18
|
+
sys.path.insert(0, self.module_path)
|
19
|
+
os.chdir(self.module_path)
|
20
|
+
return self
|
21
|
+
|
22
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
23
|
+
sys.path.remove(self.module_path)
|
24
|
+
os.chdir(self.old_path)
|
19
25
|
|
20
26
|
|
21
27
|
def wrapped_tool(tool, module_path):
|
@@ -24,12 +30,8 @@ def wrapped_tool(tool, module_path):
|
|
24
30
|
|
25
31
|
def _wrapped_tool(*args, **kwargs):
|
26
32
|
print(f"调用了{tool.name}")
|
27
|
-
|
28
|
-
try:
|
29
|
-
change_directory_and_path(module_path)
|
33
|
+
with ChangeDirectoryAndPath(module_path):
|
30
34
|
result = original_tool_function(*args, **kwargs)
|
31
|
-
finally:
|
32
|
-
restore_directory_and_path(module_path, old_path)
|
33
35
|
print(f"{tool.name}调用完毕,结果为:", result)
|
34
36
|
return result
|
35
37
|
|
@@ -39,7 +41,6 @@ def wrapped_tool(tool, module_path):
|
|
39
41
|
def import_tools(tool_id):
|
40
42
|
"""Import tools from a specified tool_id."""
|
41
43
|
tool_base_path = "../../tool"
|
42
|
-
old_path = os.getcwd()
|
43
44
|
module_path = os.path.join(tool_base_path, tool_id)
|
44
45
|
module_path = os.path.normpath(os.path.abspath(module_path))
|
45
46
|
|
@@ -51,23 +52,22 @@ def import_tools(tool_id):
|
|
51
52
|
original_modules = sys.modules.copy()
|
52
53
|
|
53
54
|
try:
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
55
|
+
with ChangeDirectoryAndPath(module_path):
|
56
|
+
module = importlib.import_module("tool")
|
57
|
+
export_tools = getattr(module, "export_tools")
|
58
|
+
valid_tools = []
|
59
|
+
for tool in export_tools:
|
60
|
+
assert isinstance(tool, langchain_core.tools.StructuredTool) or isinstance(
|
61
|
+
tool, types.FunctionType
|
62
|
+
), f"Tool is not a StructuredTool or function: {tool}"
|
63
|
+
if isinstance(tool, types.FunctionType) and not isinstance(
|
64
|
+
tool, langchain_core.tools.StructuredTool
|
65
|
+
):
|
66
|
+
valid_tools.append(_tool(tool))
|
67
|
+
export_tools = valid_tools
|
67
68
|
|
68
69
|
except Exception as e:
|
69
70
|
print(f"Error loading tool {tool_id}: {e}")
|
70
|
-
restore_directory_and_path(module_path, old_path)
|
71
71
|
return []
|
72
72
|
|
73
73
|
# Unload modules and restore sys.modules state
|
@@ -76,9 +76,7 @@ def import_tools(tool_id):
|
|
76
76
|
if key not in original_modules:
|
77
77
|
del sys.modules[key]
|
78
78
|
|
79
|
-
restore_directory_and_path(module_path, old_path)
|
80
|
-
|
81
79
|
for tool in export_tools:
|
82
80
|
tool.func = wrapped_tool(tool, module_path)
|
83
81
|
|
84
|
-
return export_tools
|
82
|
+
return export_tools
|
@@ -30,40 +30,11 @@ def get_all_markdown_json(content):
|
|
30
30
|
return json_list
|
31
31
|
|
32
32
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
system_message: str,
|
37
|
-
tool_compatibility_mode: str,
|
38
|
-
**kwargs
|
39
|
-
):
|
40
|
-
|
41
|
-
async def _get_messages(messages):
|
42
|
-
msgs = []
|
43
|
-
for m in messages:
|
44
|
-
if isinstance(m, ToolMessage):
|
45
|
-
_dict = m.dict()
|
46
|
-
_dict["content"] = str(_dict["content"])
|
47
|
-
m_c = ToolMessage(**_dict)
|
48
|
-
msgs.append(m_c)
|
49
|
-
else:
|
50
|
-
msgs.append(m)
|
51
|
-
|
52
|
-
return [SystemMessage(content=system_message)] + msgs
|
53
|
-
|
54
|
-
if tools:
|
55
|
-
llm_with_tools = llm.bind(tools=[convert_to_openai_tool(t) for t in tools])
|
33
|
+
def get_tools(last_message):
|
34
|
+
if "tool_calls" in last_message.additional_kwargs:
|
35
|
+
return last_message.additional_kwargs["tool_calls"]
|
56
36
|
else:
|
57
|
-
|
58
|
-
agent = _get_messages | llm_with_tools
|
59
|
-
tool_executor = ToolExecutor(tools)
|
60
|
-
|
61
|
-
# Define the function that determines whether to continue or not
|
62
|
-
def should_continue(messages):
|
63
|
-
# If there is no FuncCall, then we finish
|
64
|
-
last_message = messages[-1]
|
65
|
-
if last_message.content.strip().endswith("```"):
|
66
|
-
last_message.content = last_message.content + "\n\n" # 避免影响阅读
|
37
|
+
tool_calls = None
|
67
38
|
if '"name"' in last_message.content and '"parameters":' in last_message.content:
|
68
39
|
print("name 和 paremeters 模式")
|
69
40
|
all_json = get_all_markdown_json(last_message.content)
|
@@ -79,9 +50,6 @@ def create_openai_func_call_agent_executor(
|
|
79
50
|
"id": random.randint(0, 1000000),
|
80
51
|
}
|
81
52
|
)
|
82
|
-
last_message.tool_calls = tool_calls
|
83
|
-
last_message.additional_kwargs["tool_calls"] = tool_calls
|
84
|
-
return "continue"
|
85
53
|
if "<|tool▁sep|>" in last_message.content:
|
86
54
|
print("deepseek的bug: <|tool▁sep|> 模式")
|
87
55
|
name = (
|
@@ -100,15 +68,49 @@ def create_openai_func_call_agent_executor(
|
|
100
68
|
}
|
101
69
|
)
|
102
70
|
|
103
|
-
|
104
|
-
|
105
|
-
|
71
|
+
return tool_calls
|
72
|
+
|
73
|
+
|
74
|
+
def create_openai_func_call_agent_executor(
|
75
|
+
tools: list[BaseTool],
|
76
|
+
llm: LanguageModelLike,
|
77
|
+
system_message: str,
|
78
|
+
tool_compatibility_mode: str,
|
79
|
+
**kwargs
|
80
|
+
):
|
81
|
+
|
82
|
+
async def _get_messages(messages):
|
83
|
+
msgs = []
|
84
|
+
for m in messages:
|
85
|
+
if isinstance(m, ToolMessage):
|
86
|
+
_dict = m.dict()
|
87
|
+
_dict["content"] = str(_dict["content"])
|
88
|
+
m_c = ToolMessage(**_dict)
|
89
|
+
msgs.append(m_c)
|
90
|
+
else:
|
91
|
+
msgs.append(m)
|
92
|
+
|
93
|
+
return [SystemMessage(content=system_message)] + msgs
|
94
|
+
|
95
|
+
if tools:
|
96
|
+
llm_with_tools = llm.bind(tools=[convert_to_openai_tool(t) for t in tools])
|
97
|
+
else:
|
98
|
+
llm_with_tools = llm
|
99
|
+
agent = _get_messages | llm_with_tools
|
100
|
+
tool_executor = ToolExecutor(tools)
|
101
|
+
|
102
|
+
# Define the function that determines whether to continue or not
|
103
|
+
def should_continue(messages):
|
104
|
+
# If there is no FuncCall, then we finish
|
105
|
+
last_message = messages[-1]
|
106
|
+
if last_message.content.strip().endswith("```"):
|
107
|
+
last_message.content = last_message.content + "\n\n" # 避免影响阅读
|
108
|
+
tools = get_tools(last_message)
|
109
|
+
if last_message.tool_calls or tools:
|
110
|
+
return 'continue'
|
111
|
+
return 'end'
|
106
112
|
|
107
|
-
|
108
|
-
return "end"
|
109
|
-
# Otherwise if there is, we continue
|
110
|
-
else:
|
111
|
-
return "continue"
|
113
|
+
|
112
114
|
|
113
115
|
# Define the function to execute tools
|
114
116
|
async def call_tool(messages):
|
@@ -116,7 +118,7 @@ def create_openai_func_call_agent_executor(
|
|
116
118
|
# Based on the continue condition
|
117
119
|
# we know the last message involves a FuncCall
|
118
120
|
last_message = messages[-1]
|
119
|
-
for tool_call in last_message
|
121
|
+
for tool_call in get_tools(last_message):
|
120
122
|
function = tool_call["function"]
|
121
123
|
function_name = function["name"]
|
122
124
|
if function_name == "a_delay_function":
|
@@ -141,7 +143,7 @@ def create_openai_func_call_agent_executor(
|
|
141
143
|
# We use the response to create a ToolMessage
|
142
144
|
tool_messages = []
|
143
145
|
for tool_call, response in zip(
|
144
|
-
last_message
|
146
|
+
get_tools(last_message), responses
|
145
147
|
):
|
146
148
|
if not isinstance(response, (str, int, float, bool, list, tuple)):
|
147
149
|
response = repr(
|
pycoze/bot/bot.py
CHANGED
@@ -53,8 +53,9 @@ def agent_chat(bot_setting_file, history):
|
|
53
53
|
and len(tools) > 0
|
54
54
|
):
|
55
55
|
prompt += """
|
56
|
-
|
57
|
-
|
56
|
+
作为一个AI,你如果不确定结果,请务必使用工具查询。
|
57
|
+
你可以通过下面的方式使用工具,并耐心等待工具返回结果。
|
58
|
+
如果你需要调用工具,请使用以正确markdown中的json代码格式进行结尾(务必保证json格式正确,不要出现反斜杠未转义等问题):
|
58
59
|
```json
|
59
60
|
{"name": 函数名, "parameters": 参数词典}
|
60
61
|
```
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pycoze
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.94
|
4
4
|
Summary: Package for pycoze only!
|
5
5
|
Author: Yuan Jie Xiong
|
6
6
|
Author-email: aiqqqqqqq@qq.com
|
@@ -18,7 +18,7 @@ Package for pycoze only!
|
|
18
18
|
|
19
19
|
|
20
20
|
<!-- For author only -->
|
21
|
-
<!-- pip install twine -->
|
21
|
+
<!-- pip install twine wheel -->
|
22
22
|
|
23
23
|
<!-- 递增setup.py的版本 -->
|
24
24
|
<!-- 删除build和dist和pycoze.egg-info文件夹 -->
|
@@ -1,17 +1,17 @@
|
|
1
1
|
pycoze/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
pycoze/module.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
pycoze/access/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
pycoze/access/tool_for_bot.py,sha256=
|
4
|
+
pycoze/access/tool_for_bot.py,sha256=SbAyQJ9BtuLquVrXnmHJl8t_cdID-AYvdwXQvY67u-Y,2608
|
5
5
|
pycoze/ai/__init__.py,sha256=odM2lgYSnApxw4AzLV_5AyaxL5_MLfydOSB1VmLGFyA,75
|
6
6
|
pycoze/ai/vram_reserve.py,sha256=QbqaA8qv87cnEpOVDMygi0BNMxuhLYwj1UKfR_D5BD4,4340
|
7
7
|
pycoze/bot/__init__.py,sha256=6HHMxDQVOyZM9dtSjQm9tjGnhj4h7CixD0JOvEwTi48,41
|
8
|
-
pycoze/bot/bot.py,sha256=
|
8
|
+
pycoze/bot/bot.py,sha256=HV2N6Cfuvv5eCCh8bG8Lv6DpDJZ1FrSVrVk8H-zcyCE,3146
|
9
9
|
pycoze/bot/agent/__init__.py,sha256=YR9vpkEQn1e4937r_xFPJXUCPBEJ0SFzEQDBe2x3-YA,157
|
10
10
|
pycoze/bot/agent/agent.py,sha256=XMTO6s8OJpaOnymT8ZUuJxXx2ICZ3r7Ck0pHJqPPFIs,3346
|
11
11
|
pycoze/bot/agent/assistant.py,sha256=XI4w-rFfbk3qYE0tWcWoya8dz-3cA-QZ0Sanhl3DbKE,1112
|
12
12
|
pycoze/bot/agent/chat.py,sha256=kc0qgcrBSXdiMy49JwThZTV-0PAvzAhiUvbI5ILiSnU,571
|
13
13
|
pycoze/bot/agent/agent_types/__init__.py,sha256=XNvKWq9REE5Wzjm0OZi3CKIQF2UZ9PZkeUuxgFJbrfc,128
|
14
|
-
pycoze/bot/agent/agent_types/openai_func_call_agent.py,sha256=
|
14
|
+
pycoze/bot/agent/agent_types/openai_func_call_agent.py,sha256=klMFym4FVDClpYZPh3AYXkihBVyRkpdWBpZ56IHohZo,6736
|
15
15
|
pycoze/ui/__init__.py,sha256=7xAfL2lfG7-jllPJEZUJO89xUE9sNzvo1y0WmBswjBI,458
|
16
16
|
pycoze/ui/base.py,sha256=SCXVDK7PpMaBv6ovvabHcfRq_d2AWM0BRyxpNhuJN5A,1285
|
17
17
|
pycoze/ui/color.py,sha256=cT9Ib8uNzkOKxyW0IwVj46o4LwdB1xgNCj1_Rou9d_4,854
|
@@ -20,8 +20,8 @@ pycoze/ui/ui_def.py,sha256=UhhU_yB3GV9ISbvTWT48hsHPHI250BhMILh6bu5Uioo,4206
|
|
20
20
|
pycoze/utils/__init__.py,sha256=TNJhFfY7JYdLlzuP9GvgxfNXUtbgH_NUUJSqHXCxJn4,78
|
21
21
|
pycoze/utils/arg.py,sha256=kA3KBQzXc2WlH5XbF8kfikfpqljiKaW7oY_GE4Qyffc,753
|
22
22
|
pycoze/utils/text_or_file.py,sha256=gpxZVWt2DW6YiEg_MnMuwg36VNf3TX383QD_1oZNB0Y,551
|
23
|
-
pycoze-0.1.
|
24
|
-
pycoze-0.1.
|
25
|
-
pycoze-0.1.
|
26
|
-
pycoze-0.1.
|
27
|
-
pycoze-0.1.
|
23
|
+
pycoze-0.1.94.dist-info/LICENSE,sha256=QStd_Qsd0-kAam_-sOesCIp_uKrGWeoKwt9M49NVkNU,1090
|
24
|
+
pycoze-0.1.94.dist-info/METADATA,sha256=jjabhgJm9ZlQmWh0-Y0Xoh9t3BDCBvYRpif09RLi5Vs,725
|
25
|
+
pycoze-0.1.94.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
26
|
+
pycoze-0.1.94.dist-info/top_level.txt,sha256=76dPeDhKvOCleL3ZC5gl1-y4vdS1tT_U1hxWVAn7sFo,7
|
27
|
+
pycoze-0.1.94.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|