hyperpocket-anthropic 0.1.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.
- hyperpocket_anthropic-0.1.3/PKG-INFO +194 -0
- hyperpocket_anthropic-0.1.3/README.md +179 -0
- hyperpocket_anthropic-0.1.3/hyperpocket_anthropic/__init__.py +3 -0
- hyperpocket_anthropic-0.1.3/hyperpocket_anthropic/pocket_anthropic.py +77 -0
- hyperpocket_anthropic-0.1.3/hyperpocket_anthropic/util/__init__.py +3 -0
- hyperpocket_anthropic-0.1.3/hyperpocket_anthropic/util/tool_to_anthropic_spec.py +22 -0
- hyperpocket_anthropic-0.1.3/pyproject.toml +16 -0
@@ -0,0 +1,194 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: hyperpocket-anthropic
|
3
|
+
Version: 0.1.3
|
4
|
+
Summary:
|
5
|
+
Author: moon
|
6
|
+
Author-email: moon@vessl.ai
|
7
|
+
Requires-Python: >=3.11,<4.0
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
12
|
+
Requires-Dist: anthropic (>=0.40.0,<0.41.0)
|
13
|
+
Requires-Dist: hyperpocket (>=0.0.1,<0.0.2)
|
14
|
+
Description-Content-Type: text/markdown
|
15
|
+
|
16
|
+
## Anthropic extensions
|
17
|
+
|
18
|
+
### Get Pocket Anthropic Tool Spec
|
19
|
+
|
20
|
+
```python
|
21
|
+
import hyperpocket as pk
|
22
|
+
from pocket_anthropic import PocketAnthropic
|
23
|
+
|
24
|
+
pocket = PocketAnthropic(tools=[
|
25
|
+
*pk.curated_tools.SLACK, # SLACK = [slack_get_message, slack_post_message, ..]
|
26
|
+
*pk.curated_tools.LINEAR,
|
27
|
+
"https://github.com/my-org/some-awesome-tool"]
|
28
|
+
)
|
29
|
+
|
30
|
+
# get anthropic compatible tool specs from pocket
|
31
|
+
tool_specs = pocket.get_anthropic_tool_specs()
|
32
|
+
```
|
33
|
+
|
34
|
+
|
35
|
+
### Tool Injection
|
36
|
+
|
37
|
+
```python
|
38
|
+
import os
|
39
|
+
|
40
|
+
from anthropic import Anthropic
|
41
|
+
|
42
|
+
messages = [
|
43
|
+
{
|
44
|
+
"role": "user",
|
45
|
+
"content": "get slack message",
|
46
|
+
}
|
47
|
+
]
|
48
|
+
|
49
|
+
llm = Anthropic()
|
50
|
+
response = llm.messages.create(
|
51
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
52
|
+
max_tokens=500,
|
53
|
+
messages=messages,
|
54
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
55
|
+
)
|
56
|
+
```
|
57
|
+
|
58
|
+
|
59
|
+
### Tool Call
|
60
|
+
|
61
|
+
```python
|
62
|
+
response = llm.messages.create(
|
63
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
64
|
+
max_tokens=500,
|
65
|
+
messages=messages,
|
66
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
67
|
+
)
|
68
|
+
|
69
|
+
tool_result_blocks = []
|
70
|
+
for block in response.content:
|
71
|
+
if block.type == "tool_use":
|
72
|
+
tool_result_block = pocket.invoke(block)
|
73
|
+
tool_result_blocks.append(tool_result_block)
|
74
|
+
|
75
|
+
messages.append({"role": "user", "content": tool_result_blocks})
|
76
|
+
|
77
|
+
response_after_tool_call = llm.messages.create(
|
78
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
79
|
+
max_tokens=500,
|
80
|
+
messages=messages,
|
81
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
82
|
+
)
|
83
|
+
|
84
|
+
# ...
|
85
|
+
```
|
86
|
+
|
87
|
+
### Full Code
|
88
|
+
|
89
|
+
```python
|
90
|
+
import os
|
91
|
+
|
92
|
+
from anthropic import Anthropic
|
93
|
+
|
94
|
+
import hyperpocket as pk
|
95
|
+
from pocket_anthropic import PocketAnthropic
|
96
|
+
|
97
|
+
pocket = PocketAnthropic(tools=[
|
98
|
+
*pk.curated_tools.SLACK, # SLACK = [slack_get_message, slack_post_message, ..]
|
99
|
+
*pk.curated_tools.LINEAR,
|
100
|
+
"https://github.com/my-org/some-awesome-tool"]
|
101
|
+
)
|
102
|
+
|
103
|
+
# get anthropic compatible tool specs from pocket
|
104
|
+
tool_specs = pocket.get_anthropic_tool_specs()
|
105
|
+
messages = [
|
106
|
+
{
|
107
|
+
"role": "user",
|
108
|
+
"content": "get slack message",
|
109
|
+
}
|
110
|
+
]
|
111
|
+
|
112
|
+
llm = Anthropic()
|
113
|
+
response = llm.messages.create(
|
114
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
115
|
+
max_tokens=500,
|
116
|
+
messages=messages,
|
117
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
118
|
+
)
|
119
|
+
|
120
|
+
tool_result_blocks = []
|
121
|
+
for block in response.content:
|
122
|
+
if block.type == "tool_use":
|
123
|
+
tool_result_block = pocket.invoke(block) # tool call by pocket
|
124
|
+
tool_result_blocks.append(tool_result_block)
|
125
|
+
|
126
|
+
messages.append({"role": "user", "content": tool_result_blocks})
|
127
|
+
|
128
|
+
response_after_tool_call = llm.messages.create(
|
129
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
130
|
+
max_tokens=500,
|
131
|
+
messages=messages,
|
132
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
133
|
+
)
|
134
|
+
|
135
|
+
```
|
136
|
+
|
137
|
+
|
138
|
+
### Examples
|
139
|
+
|
140
|
+
```python
|
141
|
+
import os
|
142
|
+
|
143
|
+
from anthropic import Anthropic
|
144
|
+
|
145
|
+
import hyperpocket as pk
|
146
|
+
from pocket_anthropic import PocketAnthropic
|
147
|
+
|
148
|
+
client = Anthropic()
|
149
|
+
pocket = PocketAnthropic(
|
150
|
+
tools=[
|
151
|
+
*pk.curated_tools.SLACK, # SLACK = [slack_get_message, slack_post_message, ..]
|
152
|
+
*pk.curated_tools.LINEAR,
|
153
|
+
"https://github.com/my-org/some-awesome-tool"]
|
154
|
+
)
|
155
|
+
|
156
|
+
tool_specs = pocket.get_anthropic_tool_specs()
|
157
|
+
|
158
|
+
messages = []
|
159
|
+
while True:
|
160
|
+
print("user(q to quit) : ", end="")
|
161
|
+
user_input = input()
|
162
|
+
if user_input == "q":
|
163
|
+
break
|
164
|
+
if user_input == "":
|
165
|
+
continue
|
166
|
+
|
167
|
+
messages.append({"role": "user", "content": user_input})
|
168
|
+
|
169
|
+
while True:
|
170
|
+
response = client.messages.create(
|
171
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
172
|
+
max_tokens=500,
|
173
|
+
messages=messages,
|
174
|
+
tools=tool_specs,
|
175
|
+
)
|
176
|
+
|
177
|
+
messages.append({"role": "assistant", "content": response.content})
|
178
|
+
|
179
|
+
tool_result_blocks = []
|
180
|
+
for block in response.content:
|
181
|
+
if block.type == "text":
|
182
|
+
print("[ai] response : ", block.text)
|
183
|
+
|
184
|
+
elif block.type == "tool_use":
|
185
|
+
tool_result_block = pocket.invoke(block)
|
186
|
+
tool_result_blocks.append(tool_result_block)
|
187
|
+
|
188
|
+
print("[tool] response : ", tool_result_block["content"])
|
189
|
+
|
190
|
+
messages.append({"role": "user", "content": tool_result_blocks})
|
191
|
+
|
192
|
+
if response.stop_reason != "tool_use":
|
193
|
+
break
|
194
|
+
```
|
@@ -0,0 +1,179 @@
|
|
1
|
+
## Anthropic extensions
|
2
|
+
|
3
|
+
### Get Pocket Anthropic Tool Spec
|
4
|
+
|
5
|
+
```python
|
6
|
+
import hyperpocket as pk
|
7
|
+
from pocket_anthropic import PocketAnthropic
|
8
|
+
|
9
|
+
pocket = PocketAnthropic(tools=[
|
10
|
+
*pk.curated_tools.SLACK, # SLACK = [slack_get_message, slack_post_message, ..]
|
11
|
+
*pk.curated_tools.LINEAR,
|
12
|
+
"https://github.com/my-org/some-awesome-tool"]
|
13
|
+
)
|
14
|
+
|
15
|
+
# get anthropic compatible tool specs from pocket
|
16
|
+
tool_specs = pocket.get_anthropic_tool_specs()
|
17
|
+
```
|
18
|
+
|
19
|
+
|
20
|
+
### Tool Injection
|
21
|
+
|
22
|
+
```python
|
23
|
+
import os
|
24
|
+
|
25
|
+
from anthropic import Anthropic
|
26
|
+
|
27
|
+
messages = [
|
28
|
+
{
|
29
|
+
"role": "user",
|
30
|
+
"content": "get slack message",
|
31
|
+
}
|
32
|
+
]
|
33
|
+
|
34
|
+
llm = Anthropic()
|
35
|
+
response = llm.messages.create(
|
36
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
37
|
+
max_tokens=500,
|
38
|
+
messages=messages,
|
39
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
40
|
+
)
|
41
|
+
```
|
42
|
+
|
43
|
+
|
44
|
+
### Tool Call
|
45
|
+
|
46
|
+
```python
|
47
|
+
response = llm.messages.create(
|
48
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
49
|
+
max_tokens=500,
|
50
|
+
messages=messages,
|
51
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
52
|
+
)
|
53
|
+
|
54
|
+
tool_result_blocks = []
|
55
|
+
for block in response.content:
|
56
|
+
if block.type == "tool_use":
|
57
|
+
tool_result_block = pocket.invoke(block)
|
58
|
+
tool_result_blocks.append(tool_result_block)
|
59
|
+
|
60
|
+
messages.append({"role": "user", "content": tool_result_blocks})
|
61
|
+
|
62
|
+
response_after_tool_call = llm.messages.create(
|
63
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
64
|
+
max_tokens=500,
|
65
|
+
messages=messages,
|
66
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
67
|
+
)
|
68
|
+
|
69
|
+
# ...
|
70
|
+
```
|
71
|
+
|
72
|
+
### Full Code
|
73
|
+
|
74
|
+
```python
|
75
|
+
import os
|
76
|
+
|
77
|
+
from anthropic import Anthropic
|
78
|
+
|
79
|
+
import hyperpocket as pk
|
80
|
+
from pocket_anthropic import PocketAnthropic
|
81
|
+
|
82
|
+
pocket = PocketAnthropic(tools=[
|
83
|
+
*pk.curated_tools.SLACK, # SLACK = [slack_get_message, slack_post_message, ..]
|
84
|
+
*pk.curated_tools.LINEAR,
|
85
|
+
"https://github.com/my-org/some-awesome-tool"]
|
86
|
+
)
|
87
|
+
|
88
|
+
# get anthropic compatible tool specs from pocket
|
89
|
+
tool_specs = pocket.get_anthropic_tool_specs()
|
90
|
+
messages = [
|
91
|
+
{
|
92
|
+
"role": "user",
|
93
|
+
"content": "get slack message",
|
94
|
+
}
|
95
|
+
]
|
96
|
+
|
97
|
+
llm = Anthropic()
|
98
|
+
response = llm.messages.create(
|
99
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
100
|
+
max_tokens=500,
|
101
|
+
messages=messages,
|
102
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
103
|
+
)
|
104
|
+
|
105
|
+
tool_result_blocks = []
|
106
|
+
for block in response.content:
|
107
|
+
if block.type == "tool_use":
|
108
|
+
tool_result_block = pocket.invoke(block) # tool call by pocket
|
109
|
+
tool_result_blocks.append(tool_result_block)
|
110
|
+
|
111
|
+
messages.append({"role": "user", "content": tool_result_blocks})
|
112
|
+
|
113
|
+
response_after_tool_call = llm.messages.create(
|
114
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
115
|
+
max_tokens=500,
|
116
|
+
messages=messages,
|
117
|
+
tools=tool_specs, # pass the tool specs as an tools argument
|
118
|
+
)
|
119
|
+
|
120
|
+
```
|
121
|
+
|
122
|
+
|
123
|
+
### Examples
|
124
|
+
|
125
|
+
```python
|
126
|
+
import os
|
127
|
+
|
128
|
+
from anthropic import Anthropic
|
129
|
+
|
130
|
+
import hyperpocket as pk
|
131
|
+
from pocket_anthropic import PocketAnthropic
|
132
|
+
|
133
|
+
client = Anthropic()
|
134
|
+
pocket = PocketAnthropic(
|
135
|
+
tools=[
|
136
|
+
*pk.curated_tools.SLACK, # SLACK = [slack_get_message, slack_post_message, ..]
|
137
|
+
*pk.curated_tools.LINEAR,
|
138
|
+
"https://github.com/my-org/some-awesome-tool"]
|
139
|
+
)
|
140
|
+
|
141
|
+
tool_specs = pocket.get_anthropic_tool_specs()
|
142
|
+
|
143
|
+
messages = []
|
144
|
+
while True:
|
145
|
+
print("user(q to quit) : ", end="")
|
146
|
+
user_input = input()
|
147
|
+
if user_input == "q":
|
148
|
+
break
|
149
|
+
if user_input == "":
|
150
|
+
continue
|
151
|
+
|
152
|
+
messages.append({"role": "user", "content": user_input})
|
153
|
+
|
154
|
+
while True:
|
155
|
+
response = client.messages.create(
|
156
|
+
model=os.getenv("ANTHROPIC_MODEL_NAME"),
|
157
|
+
max_tokens=500,
|
158
|
+
messages=messages,
|
159
|
+
tools=tool_specs,
|
160
|
+
)
|
161
|
+
|
162
|
+
messages.append({"role": "assistant", "content": response.content})
|
163
|
+
|
164
|
+
tool_result_blocks = []
|
165
|
+
for block in response.content:
|
166
|
+
if block.type == "text":
|
167
|
+
print("[ai] response : ", block.text)
|
168
|
+
|
169
|
+
elif block.type == "tool_use":
|
170
|
+
tool_result_block = pocket.invoke(block)
|
171
|
+
tool_result_blocks.append(tool_result_block)
|
172
|
+
|
173
|
+
print("[tool] response : ", tool_result_block["content"])
|
174
|
+
|
175
|
+
messages.append({"role": "user", "content": tool_result_blocks})
|
176
|
+
|
177
|
+
if response.stop_reason != "tool_use":
|
178
|
+
break
|
179
|
+
```
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import json
|
2
|
+
from typing import List
|
3
|
+
|
4
|
+
try:
|
5
|
+
from anthropic.types import ToolResultBlockParam, ToolUseBlock
|
6
|
+
except ImportError:
|
7
|
+
raise ImportError("You need to install anthropic to use pocket anthropic.")
|
8
|
+
|
9
|
+
from hyperpocket import Pocket
|
10
|
+
from hyperpocket.tool import Tool
|
11
|
+
|
12
|
+
from hyperpocket_anthropic.util import tool_to_anthropic_spec
|
13
|
+
|
14
|
+
|
15
|
+
class PocketAnthropic(Pocket):
|
16
|
+
def invoke(self, tool_use_block: ToolUseBlock, **kwargs) -> ToolResultBlockParam:
|
17
|
+
body = self.parse_input(tool_use_block)
|
18
|
+
result, interrupted = self.invoke_with_state(
|
19
|
+
tool_use_block.name, body=body, **kwargs
|
20
|
+
)
|
21
|
+
say = result
|
22
|
+
if interrupted:
|
23
|
+
say = (
|
24
|
+
f"{say}\n\nThe tool execution interrupted. Please talk to me to resume."
|
25
|
+
)
|
26
|
+
|
27
|
+
tool_result_block = ToolResultBlockParam(
|
28
|
+
tool_use_id=tool_use_block.id, type="tool_result", content=say
|
29
|
+
)
|
30
|
+
|
31
|
+
return tool_result_block
|
32
|
+
|
33
|
+
async def ainvoke(
|
34
|
+
self, tool_use_block: ToolUseBlock, **kwargs
|
35
|
+
) -> ToolResultBlockParam:
|
36
|
+
body = self.parse_input(tool_use_block)
|
37
|
+
result, interrupted = await self.ainvoke_with_state(
|
38
|
+
tool_use_block.name, body=body, **kwargs
|
39
|
+
)
|
40
|
+
say = result
|
41
|
+
|
42
|
+
if interrupted:
|
43
|
+
say = (
|
44
|
+
f"{say}\n\nThe tool execution interrupted. Please talk to me to resume."
|
45
|
+
)
|
46
|
+
|
47
|
+
tool_result_block = ToolResultBlockParam(
|
48
|
+
tool_use_id=tool_use_block.id, type="tool_result", content=say
|
49
|
+
)
|
50
|
+
|
51
|
+
return tool_result_block
|
52
|
+
|
53
|
+
@staticmethod
|
54
|
+
def parse_input(tool_use_block):
|
55
|
+
if isinstance(tool_use_block.input, str):
|
56
|
+
arg = json.loads(tool_use_block.input)
|
57
|
+
body = arg["body"]
|
58
|
+
else:
|
59
|
+
arg = tool_use_block.input
|
60
|
+
body = arg["body"]
|
61
|
+
|
62
|
+
if isinstance(body, str):
|
63
|
+
body = json.loads(body)
|
64
|
+
|
65
|
+
return body
|
66
|
+
|
67
|
+
def get_anthropic_tool_specs(self) -> List[dict]:
|
68
|
+
specs = []
|
69
|
+
for tool in self.tools.values():
|
70
|
+
spec = self.get_anthropic_tool_spec(tool)
|
71
|
+
specs.append(spec)
|
72
|
+
return specs
|
73
|
+
|
74
|
+
@staticmethod
|
75
|
+
def get_anthropic_tool_spec(tool: Tool) -> dict:
|
76
|
+
spec = tool_to_anthropic_spec(tool)
|
77
|
+
return spec
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from hyperpocket.tool import Tool
|
2
|
+
from hyperpocket.util.flatten_json_schema import flatten_json_schema
|
3
|
+
|
4
|
+
|
5
|
+
def tool_to_anthropic_spec(tool: Tool) -> dict:
|
6
|
+
name = tool.name
|
7
|
+
description = tool.description
|
8
|
+
arg_schema = tool.schema_model()
|
9
|
+
json_schema = flatten_json_schema(arg_schema.model_json_schema())
|
10
|
+
|
11
|
+
anthropic_spec = {
|
12
|
+
"name": name,
|
13
|
+
"description": description.strip(),
|
14
|
+
"input_schema": {
|
15
|
+
"type": json_schema["type"],
|
16
|
+
"properties": json_schema["properties"],
|
17
|
+
"required": json_schema.get("required", []),
|
18
|
+
"title": json_schema.get("title", ""),
|
19
|
+
},
|
20
|
+
}
|
21
|
+
|
22
|
+
return anthropic_spec
|
@@ -0,0 +1,16 @@
|
|
1
|
+
[tool.poetry]
|
2
|
+
name = "hyperpocket-anthropic"
|
3
|
+
version = "0.1.3"
|
4
|
+
description = ""
|
5
|
+
authors = ["moon <moon@vessl.ai>"]
|
6
|
+
readme = "README.md"
|
7
|
+
|
8
|
+
[tool.poetry.dependencies]
|
9
|
+
python = "^3.11"
|
10
|
+
anthropic = "^0.40.0"
|
11
|
+
hyperpocket = "^0.0.1"
|
12
|
+
|
13
|
+
|
14
|
+
[build-system]
|
15
|
+
requires = ["poetry-core"]
|
16
|
+
build-backend = "poetry.core.masonry.api"
|