Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: HuggingFaceLocalChatGenerator unified support for tools #8827

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

vblagoje
Copy link
Member

@vblagoje vblagoje commented Feb 6, 2025

Why:

Adds universal tools support to HuggingFaceLocalChatGenerator

What:

  • Introduced support for tool calls, allowing the generation model to prepare and parse tool interactions.
  • Implemented a tool call parsing method that utilizes regex patterns or callables.

How can it be used:

The addition allows for parsing tool calls from generated text, identified by tool names and their arguments. This can be set up during initialization:

import torch

from haystack.dataclasses import ChatMessage
from haystack.tools import Tool
from haystack.components.generators.chat import HuggingFaceLocalChatGenerator
from haystack.utils import Secret

def weather(city: str):
    return f'The weather in {city} is sunny and 32°C'

# Define tool parameters
tool_parameters = {
    "type": "object",
    "properties": {"city": {"type": "string"}},
    "required": ["city"]
}

# Create weather tool
weather_tool = Tool(
    name="weather",
    description="useful to determine the weather in a given location",
    parameters=tool_parameters,
    function=weather
)
# Initialize generator with tool
client = HuggingFaceLocalChatGenerator(
    model="NousResearch/Hermes-2-Pro-Llama-3-8B",
    token=Secret.from_env_var("HF_TOKEN"),
    tools=[weather_tool],
    huggingface_pipeline_kwargs={"torch_dtype":torch.bfloat16, "device_map": "auto"}
)
client.warm_up()

# Run initial query
messages = [ChatMessage.from_user("What's the weather like in Paris?")]
results = client.run(messages=messages)

# Get tool call from response
tool_message = next(msg for msg in results["replies"] if msg.tool_call)
tool_call = tool_message.tool_call

# Execute tool and send result back
weather_result = weather(**tool_call.arguments)
new_messages = [
    messages[0],
    tool_message,
    ChatMessage.from_tool(tool_result=weather_result, origin=tool_call)
]

# Get final response
final_result = client.run(new_messages)
print(final_result["replies"][0].text)

>>> The weather in Paris is sunny and 32°C. Enjoy your day!

How did you test it:

  • Added unit tests that mock generator run with specified tool patterns and tool lists
  • Real test notebook

Notes for the reviewer:

  • See https://huggingface.co/blog/unified-tool-use for more details about HF and tools
  • Validate the regex pattern for tool call extraction.
  • Ensure comprehensive testing of different tool call scenarios to guarantee robustness.

@github-actions github-actions bot added the type:documentation Improvements on the docs label Feb 6, 2025
@coveralls
Copy link
Collaborator

coveralls commented Feb 6, 2025

Pull Request Test Coverage Report for Build 13200235309

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 23 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.07%) to 92.58%

Files with Coverage Reduction New Missed Lines %
components/generators/chat/hugging_face_local.py 23 84.46%
Totals Coverage Status
Change from base Build 13183889468: -0.07%
Covered Lines: 9058
Relevant Lines: 9784

💛 - Coveralls

@vblagoje vblagoje marked this pull request as ready for review February 7, 2025 09:00
@vblagoje vblagoje requested review from a team as code owners February 7, 2025 09:00
@vblagoje vblagoje requested review from dfokina, davidsbatista and anakin87 and removed request for a team and davidsbatista February 7, 2025 09:00
@vblagoje
Copy link
Member Author

vblagoje commented Feb 7, 2025

@davidsbatista asking @anakin87 for review here as he knows this code intimately 🙏

Copy link
Member

@anakin87 anakin87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! I particularly appreciated the notebook...

I left some comments about points we can improve.

@vblagoje
Copy link
Member Author

vblagoje commented Feb 7, 2025

Have a look at the updated run of the notebook as well @anakin87 🙏

@vblagoje vblagoje requested a review from anakin87 February 7, 2025 13:05
Copy link
Member

@anakin87 anakin87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a small comment to address.

Plus, "feat!:" in the PR title indicates a breaking change, and this does not seem breaking.
If I am right, let's simply change this to "feat:"

Feel free to merge once these small aspects are fixed.

Good work!

generator = HuggingFaceLocalChatGenerator(
model="meta-llama/Llama-2-13b-chat-hf", tools=tools, tool_parsing_function=custom_tool_parser
)
generator.pipeline = Mock(return_value=[{"generated_text": "Let me check the weather for you"}])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this generated_text is confusing. Please use something like "mock response. We don't use it"

Uses DEFAULT_TOOL_PATTERN to extract tool calls.
:param text: The text to parse for tool calls.
:returns: A list containing a single ToolCall if a valid tool call is found, None otherwise.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are only extracting a single tool call, but this is clearly explained.
We can improve this in future if there are requests from the community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic:tests type:documentation Improvements on the docs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants