hyperpocket-anthropic 0.1.3__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|