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.
@@ -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,3 @@
1
+ from hyperpocket_anthropic.pocket_anthropic import PocketAnthropic
2
+
3
+ __all__ = ["PocketAnthropic"]
@@ -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,3 @@
1
+ from hyperpocket_anthropic.util.tool_to_anthropic_spec import tool_to_anthropic_spec
2
+
3
+ __all__ = ["tool_to_anthropic_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"