hyperpocket-langgraph 0.1.9__py3-none-any.whl → 0.2.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- hyperpocket_langgraph/__init__.py +1 -1
- hyperpocket_langgraph/pocket_langgraph.py +84 -43
- {hyperpocket_langgraph-0.1.9.dist-info → hyperpocket_langgraph-0.2.0.dist-info}/METADATA +14 -16
- hyperpocket_langgraph-0.2.0.dist-info/RECORD +5 -0
- hyperpocket_langgraph-0.1.9.dist-info/RECORD +0 -5
- {hyperpocket_langgraph-0.1.9.dist-info → hyperpocket_langgraph-0.2.0.dist-info}/WHEEL +0 -0
@@ -1,26 +1,21 @@
|
|
1
1
|
import copy
|
2
2
|
from typing import Optional
|
3
3
|
|
4
|
+
from hyperpocket.config import pocket_logger
|
4
5
|
from langchain_core.runnables import RunnableConfig
|
5
6
|
from langgraph.errors import NodeInterrupt
|
6
7
|
from pydantic import BaseModel
|
7
8
|
|
8
|
-
from hyperpocket.config import pocket_logger
|
9
|
-
|
10
9
|
try:
|
11
10
|
from langchain_core.messages import ToolMessage
|
12
11
|
from langchain_core.tools import BaseTool, StructuredTool
|
13
12
|
except ImportError:
|
14
|
-
raise ImportError(
|
15
|
-
"You need to install langchain to use pocket langgraph."
|
16
|
-
)
|
13
|
+
raise ImportError("You need to install langchain to use pocket langgraph.")
|
17
14
|
|
18
15
|
try:
|
19
16
|
from langgraph.graph import MessagesState
|
20
17
|
except ImportError:
|
21
|
-
raise ImportError(
|
22
|
-
"You need to install langgraph to use pocket langgraph"
|
23
|
-
)
|
18
|
+
raise ImportError("You need to install langgraph to use pocket langgraph")
|
24
19
|
|
25
20
|
from hyperpocket import Pocket
|
26
21
|
from hyperpocket.tool import Tool as PocketTool
|
@@ -34,16 +29,22 @@ class PocketLanggraph(Pocket):
|
|
34
29
|
def get_tools(self, use_profile: Optional[bool] = None):
|
35
30
|
if use_profile is not None:
|
36
31
|
self.use_profile = use_profile
|
37
|
-
return [
|
38
|
-
|
39
|
-
|
40
|
-
|
32
|
+
return [
|
33
|
+
self._get_langgraph_tool(tool_impl)
|
34
|
+
for tool_impl in self.core.tools.values()
|
35
|
+
]
|
36
|
+
|
37
|
+
def get_tool_node(
|
38
|
+
self, should_interrupt: bool = False, use_profile: Optional[bool] = None
|
39
|
+
):
|
41
40
|
if use_profile is not None:
|
42
41
|
self.use_profile = use_profile
|
43
42
|
|
44
|
-
async def _tool_node(
|
43
|
+
async def _tool_node(
|
44
|
+
state: PocketLanggraphBaseState, config: RunnableConfig
|
45
|
+
) -> dict:
|
45
46
|
thread_id = config.get("configurable", {}).get("thread_id", "default")
|
46
|
-
last_message = state[
|
47
|
+
last_message = state["messages"][-1]
|
47
48
|
tool_calls = last_message.tool_calls
|
48
49
|
|
49
50
|
# 01. prepare
|
@@ -54,9 +55,9 @@ class PocketLanggraph(Pocket):
|
|
54
55
|
pocket_logger.debug(f"prepare tool {tool_call}")
|
55
56
|
_tool_call = copy.deepcopy(tool_call)
|
56
57
|
|
57
|
-
tool_call_id = _tool_call[
|
58
|
-
tool_name = _tool_call[
|
59
|
-
tool_args = _tool_call[
|
58
|
+
tool_call_id = _tool_call["id"]
|
59
|
+
tool_name = _tool_call["name"]
|
60
|
+
tool_args = _tool_call["args"]
|
60
61
|
|
61
62
|
if self.use_profile:
|
62
63
|
body = tool_args.pop("body")
|
@@ -68,27 +69,42 @@ class PocketLanggraph(Pocket):
|
|
68
69
|
if isinstance(body, BaseModel):
|
69
70
|
body = body.model_dump()
|
70
71
|
|
71
|
-
prepare = await self.prepare_in_subprocess(
|
72
|
-
|
72
|
+
prepare = await self.prepare_in_subprocess(
|
73
|
+
tool_name, body=body, thread_id=thread_id, profile=profile
|
74
|
+
)
|
73
75
|
need_prepare |= True if prepare else False
|
74
76
|
|
75
77
|
if prepare is None:
|
76
|
-
prepare_done_list.append(
|
78
|
+
prepare_done_list.append(
|
79
|
+
ToolMessage(content="prepare done", tool_call_id=tool_call_id)
|
80
|
+
)
|
77
81
|
else:
|
78
|
-
prepare_list.append(
|
82
|
+
prepare_list.append(
|
83
|
+
ToolMessage(content=prepare, tool_call_id=tool_call_id)
|
84
|
+
)
|
79
85
|
|
80
86
|
if need_prepare:
|
81
87
|
pocket_logger.debug(f"need prepare : {prepare_list}")
|
82
88
|
if should_interrupt: # interrupt
|
83
|
-
pocket_logger.debug(
|
84
|
-
|
85
|
-
|
89
|
+
pocket_logger.debug(
|
90
|
+
f"{last_message.name}({last_message.id}) is interrupt."
|
91
|
+
)
|
92
|
+
result = "\n\t" + "\n\t".join(
|
93
|
+
set(msg.content for msg in prepare_list)
|
94
|
+
)
|
95
|
+
raise NodeInterrupt(
|
96
|
+
f"{result}\n\nThe tool execution interrupted. Please talk to me to resume."
|
97
|
+
)
|
86
98
|
|
87
99
|
else: # multi turn
|
88
|
-
pocket_logger.debug(
|
100
|
+
pocket_logger.debug(
|
101
|
+
f"{last_message.name}({last_message.id}) is multi-turn"
|
102
|
+
)
|
89
103
|
return {"messages": prepare_done_list + prepare_list}
|
90
104
|
|
91
|
-
pocket_logger.debug(
|
105
|
+
pocket_logger.debug(
|
106
|
+
f"no need prepare {last_message.name}({last_message.id})"
|
107
|
+
)
|
92
108
|
|
93
109
|
# 02. authenticate and tool call
|
94
110
|
tool_messages = []
|
@@ -96,9 +112,9 @@ class PocketLanggraph(Pocket):
|
|
96
112
|
pocket_logger.debug(f"authenticate and call {tool_call}")
|
97
113
|
_tool_call = copy.deepcopy(tool_call)
|
98
114
|
|
99
|
-
tool_call_id = _tool_call[
|
100
|
-
tool_name = _tool_call[
|
101
|
-
tool_args = _tool_call[
|
115
|
+
tool_call_id = _tool_call["id"]
|
116
|
+
tool_name = _tool_call["name"]
|
117
|
+
tool_args = _tool_call["args"]
|
102
118
|
if self.use_profile:
|
103
119
|
body = tool_args.pop("body")
|
104
120
|
profile = tool_args.pop("profile", "default")
|
@@ -111,27 +127,48 @@ class PocketLanggraph(Pocket):
|
|
111
127
|
|
112
128
|
try:
|
113
129
|
auth = await self.authenticate_in_subprocess(
|
114
|
-
tool_name, body=body, thread_id=thread_id, profile=profile
|
130
|
+
tool_name, body=body, thread_id=thread_id, profile=profile
|
131
|
+
)
|
115
132
|
except Exception as e:
|
116
|
-
pocket_logger.error(
|
133
|
+
pocket_logger.error(
|
134
|
+
f"occur exception during authenticate. error : {e}"
|
135
|
+
)
|
117
136
|
tool_messages.append(
|
118
|
-
ToolMessage(
|
119
|
-
|
137
|
+
ToolMessage(
|
138
|
+
content=f"occur exception during authenticate. error : {e}",
|
139
|
+
tool_name=tool_name,
|
140
|
+
tool_call_id=tool_call_id,
|
141
|
+
)
|
142
|
+
)
|
120
143
|
continue
|
121
144
|
|
122
145
|
try:
|
123
146
|
result = await self.tool_call_in_subprocess(
|
124
|
-
tool_name,
|
125
|
-
|
147
|
+
tool_name,
|
148
|
+
body=body,
|
149
|
+
envs=auth,
|
150
|
+
thread_id=thread_id,
|
151
|
+
profile=tool_args.get("profile", "default"),
|
152
|
+
)
|
126
153
|
except Exception as e:
|
127
|
-
pocket_logger.error(
|
154
|
+
pocket_logger.error(
|
155
|
+
f"occur exception during tool calling. error : {e}"
|
156
|
+
)
|
128
157
|
tool_messages.append(
|
129
|
-
ToolMessage(
|
130
|
-
|
158
|
+
ToolMessage(
|
159
|
+
content=f"occur exception during tool calling. error : {e}",
|
160
|
+
tool_name=tool_name,
|
161
|
+
tool_call_id=tool_call_id,
|
162
|
+
)
|
163
|
+
)
|
131
164
|
continue
|
132
165
|
|
133
166
|
pocket_logger.debug(f"{tool_name} tool result : {result}")
|
134
|
-
tool_messages.append(
|
167
|
+
tool_messages.append(
|
168
|
+
ToolMessage(
|
169
|
+
content=result, tool_name=tool_name, tool_call_id=tool_call_id
|
170
|
+
)
|
171
|
+
)
|
135
172
|
|
136
173
|
return {"messages": tool_messages}
|
137
174
|
|
@@ -151,10 +188,12 @@ class PocketLanggraph(Pocket):
|
|
151
188
|
if isinstance(body, BaseModel):
|
152
189
|
body = body.model_dump()
|
153
190
|
|
154
|
-
result, interrupted = self.invoke_with_state(
|
191
|
+
result, interrupted = self.invoke_with_state(
|
192
|
+
pocket_tool.name, body, thread_id, profile, **kwargs
|
193
|
+
)
|
155
194
|
say = result
|
156
195
|
if interrupted:
|
157
|
-
say = f
|
196
|
+
say = f"{say}\n\nThe tool execution interrupted. Please talk to me to resume."
|
158
197
|
return say
|
159
198
|
|
160
199
|
async def _ainvoke(**kwargs) -> str:
|
@@ -170,10 +209,12 @@ class PocketLanggraph(Pocket):
|
|
170
209
|
if isinstance(body, BaseModel):
|
171
210
|
body = body.model_dump()
|
172
211
|
|
173
|
-
result, interrupted = await self.ainvoke_with_state(
|
212
|
+
result, interrupted = await self.ainvoke_with_state(
|
213
|
+
pocket_tool.name, body, thread_id, profile, **kwargs
|
214
|
+
)
|
174
215
|
say = result
|
175
216
|
if interrupted:
|
176
|
-
say = f
|
217
|
+
say = f"{say}\n\nThe tool execution interrupted. Please talk to me to resume."
|
177
218
|
return say
|
178
219
|
|
179
220
|
return StructuredTool.from_function(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: hyperpocket-langgraph
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.0
|
4
4
|
Author-email: Hyperpocket Team <hyperpocket@vessl.ai>
|
5
5
|
Requires-Python: >=3.10
|
6
6
|
Requires-Dist: hyperpocket>=0.0.3
|
@@ -17,13 +17,13 @@ Description-Content-Type: text/markdown
|
|
17
17
|
## Get Pocket Subgraph
|
18
18
|
|
19
19
|
```python
|
20
|
-
|
20
|
+
|
21
21
|
|
22
22
|
from hyperpocket_langgraph import PocketLanggraph
|
23
23
|
|
24
24
|
pocket = PocketLanggraph(tools=[
|
25
|
-
|
26
|
-
|
25
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
|
26
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
|
27
27
|
"https://github.com/my-org/some-awesome-tool",
|
28
28
|
])
|
29
29
|
|
@@ -36,14 +36,13 @@ pocket_node = pocket.get_tool_node()
|
|
36
36
|
```python
|
37
37
|
import os
|
38
38
|
|
39
|
-
from hyperpocket.tool import from_git
|
40
39
|
from langchain_openai import ChatOpenAI
|
41
40
|
|
42
41
|
from hyperpocket_langgraph import PocketLanggraph
|
43
42
|
|
44
43
|
pocket = PocketLanggraph(tools=[
|
45
|
-
|
46
|
-
|
44
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
|
45
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
|
47
46
|
])
|
48
47
|
|
49
48
|
# get tools from pocket to bind llm
|
@@ -60,7 +59,6 @@ llm_with_tools = llm.bind_tools(tools)
|
|
60
59
|
import os
|
61
60
|
from typing import Annotated
|
62
61
|
|
63
|
-
from hyperpocket.tool import from_git
|
64
62
|
from langchain_core.runnables import RunnableConfig
|
65
63
|
from langchain_openai import ChatOpenAI
|
66
64
|
from langgraph.checkpoint.memory import MemorySaver
|
@@ -73,8 +71,8 @@ from hyperpocket_langgraph import PocketLanggraph
|
|
73
71
|
|
74
72
|
# Define pocket tools
|
75
73
|
pocket = PocketLanggraph(tools=[
|
76
|
-
|
77
|
-
|
74
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
|
75
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
|
78
76
|
])
|
79
77
|
|
80
78
|
# Get Pocket ToolNode
|
@@ -131,14 +129,14 @@ by setting the `should_interrupt` flag when calling `get_tool_node`
|
|
131
129
|
Perform authentication in a multi-turn way
|
132
130
|
|
133
131
|
```python
|
134
|
-
|
132
|
+
|
135
133
|
|
136
134
|
from hyperpocket_langgraph import PocketLanggraph
|
137
135
|
|
138
136
|
# Define pocket tools
|
139
137
|
pocket = PocketLanggraph(tools=[
|
140
|
-
|
141
|
-
|
138
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
|
139
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
|
142
140
|
])
|
143
141
|
|
144
142
|
# Get Pocket ToolNode
|
@@ -148,14 +146,14 @@ pocket_node = pocket.get_tool_node(should_interrupt=False) # multi turn
|
|
148
146
|
### Human-in-the-loop Auth
|
149
147
|
|
150
148
|
```python
|
151
|
-
|
149
|
+
|
152
150
|
|
153
151
|
from hyperpocket_langgraph import PocketLanggraph
|
154
152
|
|
155
153
|
# Define pocket tools
|
156
154
|
pocket = PocketLanggraph(tools=[
|
157
|
-
|
158
|
-
|
155
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/get-message",
|
156
|
+
"https://github.com/vessl-ai/hyperpocket/tree/main/tools/slack/post-message",
|
159
157
|
])
|
160
158
|
|
161
159
|
# Get Pocket ToolNode
|
@@ -0,0 +1,5 @@
|
|
1
|
+
hyperpocket_langgraph/__init__.py,sha256=Zqzel_ezEkzYOwVuzYWTQr4SJ737dd9hALXrIpMywEo,98
|
2
|
+
hyperpocket_langgraph/pocket_langgraph.py,sha256=Y1kj27T0NR7PFsO9NwQsZxBK9In-yQkwXTp_yDlPv80,8393
|
3
|
+
hyperpocket_langgraph-0.2.0.dist-info/METADATA,sha256=zmKuKzy8eSMrKaDaiCi3bkkTM92OtX1NSyqyFBAZLmc,5409
|
4
|
+
hyperpocket_langgraph-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
5
|
+
hyperpocket_langgraph-0.2.0.dist-info/RECORD,,
|
@@ -1,5 +0,0 @@
|
|
1
|
-
hyperpocket_langgraph/__init__.py,sha256=0Az6FKsAvohOk8G4kUE99g6kyWz-Nf7dUuCuN3_pViY,97
|
2
|
-
hyperpocket_langgraph/pocket_langgraph.py,sha256=y8GT64UrcriVr36gAf5NbTSFfnefl3NrcGnzFKqz6qY,7540
|
3
|
-
hyperpocket_langgraph-0.1.9.dist-info/METADATA,sha256=mYL-Xfo7WLAqXv6tGz4C0tr5-FrGFR076Wzvckhqzk0,5846
|
4
|
-
hyperpocket_langgraph-0.1.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
5
|
-
hyperpocket_langgraph-0.1.9.dist-info/RECORD,,
|
File without changes
|