Skip to content

Commit d111a47

Browse files
authored
feat: Added support to run local tools with Groq Client (#2)
* feat: Added support to run local tools with Groq Client
1 parent 64b4ec0 commit d111a47

10 files changed

+97
-21
lines changed

examples/sample_groq.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,15 @@
22
import os
33
from typing import List
44
from dotenv import load_dotenv
5-
from openai import OpenAI
5+
from groq import Groq
66
from toolhouse import Toolhouse
77

88
load_dotenv()
99

1010
TOKEN = os.getenv("GROQCLOUD_API_KEY")
1111
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
1212

13-
client = OpenAI(
14-
api_key=os.environ.get('GROQCLOUD_API_KEY'),
15-
base_url="https://api.groq.com/openai/v1",
16-
)
13+
client = Groq(api_key=TOKEN)
1714

1815
th = Toolhouse(access_token=TH_TOKEN, provider="openai")
1916

examples/sample_groq_openai_client.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
import os
33
from typing import List
44
from dotenv import load_dotenv
5-
from groq import Groq
5+
from openai import OpenAI
66
from toolhouse import Toolhouse
77

88
load_dotenv()
99

1010
TOKEN = os.getenv("GROQCLOUD_API_KEY")
1111
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
1212

13-
client = Groq(
14-
api_key=os.environ.get('GROQCLOUD_API_KEY')
13+
client = OpenAI(
14+
api_key=TOKEN,
15+
base_url="https://api.groq.com/openai/v1"
1516
)
1617

1718
th = Toolhouse(access_token=TH_TOKEN, provider="openai")

examples/sample_groq_openai_client_stream.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
1313

1414
client = OpenAI(
15-
api_key=os.environ.get('GROQCLOUD_API_KEY'),
15+
api_key=TOKEN,
1616
base_url="https://api.groq.com/openai/v1",
1717
)
1818

examples/sample_groq_stream.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111
TOKEN = os.getenv("GROQCLOUD_API_KEY")
1212
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
1313

14-
client = Groq(
15-
api_key=os.environ.get('GROQCLOUD_API_KEY')
16-
)
14+
client = Groq(api_key=TOKEN)
1715

1816
th = Toolhouse(access_token=TH_TOKEN, provider="openai")
1917

examples/sample_run_local_tools.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
local_tools = [
1616
{
1717
'name': 'hello',
18-
'description': 'The user receive a customized hello message from a city and return it to the user',
18+
'description': 'The user receives a customized hello message from a city and returns it to the user.',
1919
'input_schema': {
2020
'type': 'object',
2121
'properties': {
@@ -34,7 +34,7 @@
3434

3535

3636
@th.register_local_tool("hello")
37-
def whatever(city: str):
37+
def hello_tool(city: str):
3838
"""Return Local Time"""
3939
return f"Hello from {city}!!!"
4040

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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+
load_dotenv()
8+
9+
TOKEN = os.getenv("GROQCLOUD_API_KEY")
10+
TH_TOKEN = os.getenv("TOOLHOUSE_BEARER_TOKEN")
11+
12+
13+
local_tools = [
14+
{'type': 'function',
15+
'function':
16+
{
17+
'name': 'hello',
18+
'description': 'The user receives a customized hello message from a city and returns it to the user.',
19+
'parameters': {
20+
'type': 'object',
21+
'properties': {
22+
'city': {'type': 'string', 'description': 'The city where you are from'}
23+
}},
24+
'required': ['city']
25+
}}]
26+
27+
th = Toolhouse(access_token=TH_TOKEN, provider="openai")
28+
th.set_metadata("id", "fabio")
29+
th.set_metadata("timezone", 5)
30+
31+
32+
@th.register_local_tool("hello")
33+
def hello(city: str):
34+
"""Return Local Time"""
35+
return f"Hello from {city}!!!"
36+
37+
38+
client = Groq(api_key=TOKEN)
39+
40+
messages: List = [{
41+
"role": "user",
42+
"content":
43+
"Can I get an hello from Rome?"
44+
}]
45+
46+
response = client.chat.completions.create(
47+
model='llama3-groq-70b-8192-tool-use-preview',
48+
messages=messages,
49+
tools=th.get_tools() + local_tools
50+
)
51+
52+
messages += th.run_tools(response)
53+
54+
response = client.chat.completions.create(
55+
model='llama3-groq-70b-8192-tool-use-preview',
56+
messages=messages,
57+
tools=th.get_tools() + local_tools
58+
)
59+
60+
print(response.choices[0].message.content)

examples/sample_run_local_tools_openai.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Antropic Sample"""
1+
"""OpenAI Sample"""
22
import os
33
from typing import List
44
from dotenv import load_dotenv
@@ -15,7 +15,7 @@
1515
'function':
1616
{
1717
'name': 'hello',
18-
'description': 'The user receive a customized hello message from a city and return it to the user',
18+
'description': 'The user receives a customized hello message from a city and returns it to the user.',
1919
'parameters': {
2020
'type': 'object',
2121
'properties': {

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.0"
9+
version = "1.1.1"
1010
license = {file = "LICENSE"}
1111
authors = [
1212
{ name = "Toolhouse Technologies", email = "[email protected]" },

src/toolhouse/services/local_tools.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@
33
import json
44
from anthropic.types import ToolUseBlock
55
from openai.types.chat import ChatCompletionMessageToolCall
6+
from groq.types.chat import ChatCompletionMessageToolCall as GroqChatCompletionMessageToolCall
67
from ..models.RunLocalTools import AnthropicToolResponse, OpenAIToolResponse
78

9+
SupportedTools = Union[
10+
ChatCompletionMessageToolCall,
11+
GroqChatCompletionMessageToolCall,
12+
ToolUseBlock]
13+
814

915
class LocalTools():
1016
"""Local Runner"""
1117
def __init__(self):
1218
self.local_tools = {}
13-
19+
1420
def get_registered_tools(self) -> List[str]:
1521
"""Get List of registered tools"""
1622
return self.local_tools.keys()
17-
23+
1824
def register_local_tool(self, local_tool):
1925
"""Register a new local tool runner"""
2026
def decorator(func):
@@ -39,7 +45,7 @@ def _run_local_tools(self, local_tool, *args, **kwargs) -> str:
3945
f"Make sure that you have a function that can handle this tool and decorate it with @register_local_tool(\"{local_tool}\")."
4046
)
4147

42-
def run_tools(self, tool: Union[ChatCompletionMessageToolCall, ToolUseBlock]) -> Union[AnthropicToolResponse, OpenAIToolResponse]:
48+
def run_tools(self, tool: SupportedTools) -> Union[AnthropicToolResponse, OpenAIToolResponse]:
4349
"""_summary_
4450
4551
Args:
@@ -53,7 +59,7 @@ def run_tools(self, tool: Union[ChatCompletionMessageToolCall, ToolUseBlock]) ->
5359
tool_input = tool.input if isinstance(tool.input, dict) else {}
5460
content = self._run_local_tools(local_tool=tool.name, **tool_input)
5561
return AnthropicToolResponse(type="tool_result", content=content, tool_use_id=tool.id)
56-
elif isinstance(tool, ChatCompletionMessageToolCall):
62+
elif isinstance(tool, ChatCompletionMessageToolCall) or isinstance(tool, GroqChatCompletionMessageToolCall):
5763
content = self._run_local_tools(tool.function.name, **json.loads(tool.function.arguments))
5864
return OpenAIToolResponse(tool_call_id=tool.id, name=tool.function.name, content=content, role="tool")
5965
else:

test/services/test_local_runner.py

+14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import unittest
33
from anthropic.types import ToolUseBlock
44
from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall, Function
5+
from groq.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall as ChatCompletionMessageToolCallGroq, Function as FunctionGroq
56
from toolhouse.services.local_tools import LocalTools
67

78

@@ -45,6 +46,19 @@ def add(a, b):
4546
# Test the 'add' function
4647
result = self.runner.run_tools(tool)
4748
self.assertEqual(result.content, "8", "The add function did not return the expected result")
49+
50+
def test_register_and_run_local_tool_groq(self):
51+
"""Test registering and running a local tool groq"""
52+
53+
@self.runner.register_local_tool("add")
54+
def add(a, b):
55+
return str(a + b)
56+
57+
func = FunctionGroq(arguments=json.dumps({'a': 3, 'b': 5}), name="add")
58+
tool = ChatCompletionMessageToolCallGroq(id="id", function=func, type="function")
59+
# Test the 'add' function
60+
result = self.runner.run_tools(tool)
61+
self.assertEqual(result.content, "8", "The add function did not return the expected result")
4862

4963
def test_run_nonexistent_local_tool(self):
5064
"""Test running a local tool that does not exist."""

0 commit comments

Comments
 (0)