Skip to content

Commit 626732c

Browse files
authored
Merge pull request #3 from toolhouseai/bug/anthropic_stream_issue
2 parents d111a47 + 7593d30 commit 626732c

9 files changed

+215
-11
lines changed

examples/sample_run_local_tools.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@
3535

3636
@th.register_local_tool("hello")
3737
def hello_tool(city: str):
38-
"""Return Local Time"""
38+
"""Return a Hello message from a specific city."""
3939
return f"Hello from {city}!!!"
4040

4141

4242
messages: List = [{
4343
"role": "user",
4444
"content":
45-
"Can I get an hello from Rome?"
45+
"Can I get a hello from Rome?"
4646
}]
4747

4848
response = client.messages.create(

examples/sample_run_local_tools_groq.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030

3131

3232
@th.register_local_tool("hello")
33-
def hello(city: str):
34-
"""Return Local Time"""
33+
def hello_tool(city: str):
34+
"""Return a Hello message from a specific city."""
3535
return f"Hello from {city}!!!"
3636

3737

@@ -40,7 +40,7 @@ def hello(city: str):
4040
messages: List = [{
4141
"role": "user",
4242
"content":
43-
"Can I get an hello from Rome?"
43+
"Can I get a hello from Rome?"
4444
}]
4545

4646
response = client.chat.completions.create(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""Groq Sample"""
2+
import os
3+
from typing import List
4+
from dotenv import load_dotenv
5+
from groq import Groq
6+
from toolhouse import Toolhouse
7+
from toolhouse.models.OpenAIStream import OpenAIStream
8+
9+
load_dotenv()
10+
11+
TOKEN = os.getenv("GROQCLOUD_API_KEY")
12+
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
13+
14+
client = Groq(api_key=TOKEN)
15+
16+
local_tools = [
17+
{'type': 'function',
18+
'function':
19+
{
20+
'name': 'hello',
21+
'description': 'The user receives a customized hello message from a city and returns it to the user.',
22+
'parameters': {
23+
'type': 'object',
24+
'properties': {
25+
'city': {'type': 'string', 'description': 'The city where you are from'}
26+
}},
27+
'required': ['city']
28+
}}]
29+
30+
th = Toolhouse(access_token=TH_TOKEN, provider="openai")
31+
th.set_metadata("id", "fabio")
32+
th.set_metadata("timezone", 5)
33+
34+
35+
@th.register_local_tool("hello")
36+
def hello_tool(city: str):
37+
"""Return a Hello message from a specific city."""
38+
return f"Hello from {city}!!!"
39+
40+
41+
messages: List = [{
42+
"role": "user",
43+
"content":
44+
"Can I get a hello from Rome?"
45+
}]
46+
47+
48+
stream = client.chat.completions.create(
49+
model='gpt-4o',
50+
messages=messages,
51+
tools=th.get_tools() + local_tools,
52+
stream=True
53+
)
54+
55+
# Use the stream and save blocks
56+
stream_storage = OpenAIStream()
57+
for block in stream: # pylint: disable=E1133
58+
print(block)
59+
stream_storage.add(block)
60+
61+
messages += th.run_tools(stream_storage, stream=True)
62+
63+
response = client.chat.completions.create(
64+
model="gpt-4o",
65+
messages=messages,
66+
tools=th.get_tools() + local_tools
67+
)
68+
print(response.choices[0].message.content)

examples/sample_run_local_tools_openai.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030

3131

3232
@th.register_local_tool("hello")
33-
def whatever(city: str):
34-
"""Return Local Time"""
33+
def hello_tool(city: str):
34+
"""Return a Hello message from a specific city."""
3535
return f"Hello from {city}!!!"
3636

3737

@@ -40,7 +40,7 @@ def whatever(city: str):
4040
messages: List = [{
4141
"role": "user",
4242
"content":
43-
"Can I get an hello from Rome?"
43+
"Can I get a hello from Rome?"
4444
}]
4545

4646
response = client.chat.completions.create(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""OpenAI Sample"""
2+
import os
3+
from typing import List
4+
from dotenv import load_dotenv
5+
from openai import OpenAI
6+
from toolhouse import Toolhouse
7+
from toolhouse.models.OpenAIStream import OpenAIStream
8+
9+
load_dotenv()
10+
11+
TOKEN = os.getenv("OPENAI_KEY")
12+
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
13+
14+
client = OpenAI(api_key=TOKEN)
15+
16+
local_tools = [
17+
{'type': 'function',
18+
'function':
19+
{
20+
'name': 'hello',
21+
'description': 'The user receives a customized hello message from a city and returns it to the user.',
22+
'parameters': {
23+
'type': 'object',
24+
'properties': {
25+
'city': {'type': 'string', 'description': 'The city where you are from'}
26+
}},
27+
'required': ['city']
28+
}}]
29+
30+
th = Toolhouse(access_token=TH_TOKEN, provider="openai")
31+
th.set_metadata("id", "fabio")
32+
th.set_metadata("timezone", 5)
33+
34+
35+
@th.register_local_tool("hello")
36+
def hello_tool(city: str):
37+
"""Return a Hello message from a specific city."""
38+
return f"Hello from {city}!!!"
39+
40+
41+
messages: List = [{
42+
"role": "user",
43+
"content":
44+
"Can I get a hello from Rome?"
45+
}]
46+
47+
48+
stream = client.chat.completions.create(
49+
model='gpt-4o',
50+
messages=messages,
51+
tools=th.get_tools() + local_tools,
52+
stream=True
53+
)
54+
55+
# Use the stream and save blocks
56+
stream_storage = OpenAIStream()
57+
for block in stream: # pylint: disable=E1133
58+
print(block)
59+
stream_storage.add(block)
60+
61+
messages += th.run_tools(stream_storage, stream=True)
62+
63+
response = client.chat.completions.create(
64+
model="gpt-4o",
65+
messages=messages,
66+
tools=th.get_tools() + local_tools
67+
)
68+
print(response.choices[0].message.content)
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""Antropic Sample"""
2+
import os
3+
from typing import List
4+
5+
from dotenv import load_dotenv
6+
from anthropic import Anthropic, MessageStopEvent, TextEvent
7+
from toolhouse import Toolhouse, Provider
8+
9+
load_dotenv()
10+
11+
TOKEN = os.getenv("ANTHROPIC_KEY")
12+
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
13+
14+
local_tools = [
15+
{
16+
'name': 'hello',
17+
'description': 'The user receives a customized hello message from a city and returns it to the user.',
18+
'input_schema': {
19+
'type': 'object',
20+
'properties': {
21+
'city': {'type': 'string', 'description': 'The city where you are from'}
22+
},
23+
'required': ['city']
24+
}
25+
}
26+
]
27+
28+
client = Anthropic(api_key=TOKEN)
29+
30+
th = Toolhouse(access_token=TH_TOKEN, provider=Provider.ANTHROPIC)
31+
th.set_metadata("id", "fabio")
32+
th.set_metadata("timezone", 5)
33+
34+
35+
@th.register_local_tool("hello")
36+
def hello_tool(city: str):
37+
"""Return a Hello message from a specific city."""
38+
return f"Hello from {city}!!!"
39+
40+
41+
messages: List = [{
42+
"role": "user",
43+
"content":
44+
"Can I get a hello from Rome?"
45+
}]
46+
47+
with client.messages.stream(
48+
model="claude-3-5-sonnet-20240620",
49+
max_tokens=1024,
50+
tools=th.get_tools() + local_tools,
51+
messages=messages
52+
) as stream:
53+
for block in stream:
54+
if isinstance(block, MessageStopEvent):
55+
messages += th.run_tools(block.message, stream=True)
56+
elif isinstance(block, TextEvent):
57+
print(block.text, end="", flush=True)
58+
59+
60+
with client.messages.stream(
61+
model="claude-3-5-sonnet-20240620",
62+
max_tokens=1024,
63+
tools=th.get_tools() + local_tools,
64+
messages=messages
65+
) as stream:
66+
for text in stream.text_stream:
67+
print(text, end="", flush=True)

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
66

77
[project]
88
name = "toolhouse"
9-
version = "1.1.1"
9+
version = "1.1.2"
1010
license = {file = "LICENSE"}
1111
authors = [
1212
{ name = "Toolhouse Technologies", email = "[email protected]" },

src/toolhouse/net/utils.py

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import io
1111
from enum import Enum
12+
from pydantic import BaseModel
1213

1314

1415
def to_serialize(obj):
@@ -25,6 +26,8 @@ def to_serialize(obj):
2526
obj, (io.TextIOWrapper, io.BufferedIOBase)
2627
):
2728
return obj
29+
if isinstance(obj, BaseModel):
30+
return obj.model_dump()
2831
iter_obj = obj.__dict__.items() if hasattr(obj, "__dict__") else obj.items()
2932
for key, value in iter_obj:
3033
if isinstance(value, (io.TextIOWrapper, io.BufferedIOBase)):

src/toolhouse/sdk.py

-2
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,6 @@ def run_tools(self, response, append: bool = True, stream=False) -> List:
181181
message: dict = {'role': 'user', 'content': []}
182182
for tool in response.content:
183183
if tool.type == "tool_use":
184-
if stream:
185-
tool = tool.model_dump()
186184
if tool.name in self.local_tools.get_registered_tools():
187185
result = self.local_tools.run_tools(tool)
188186
message['content'].append(result.model_dump())

0 commit comments

Comments
 (0)