tools inventory

#2
by lucyknada - opened

assembling the end to end example from the readme below and guessing at what the inventory should look like.
now my question is: are the example_tools in the wrong format?
would appreciate a simple example that does it "right", thanks!

<|im_start|>user
What is the capital of france?<|im_end|>
<|im_start|>assistant
<tool_call>[{"name": "get_weather", "arguments": {"city": "Paris", "country": "France"}}]</tool_call><|im_end|>
import json
import re
from typing import Optional

from jinja2 import Template
import torch 
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.utils import get_json_schema

example_tools = {
    "calculate_price": {
        "description": "Calculate total price including tax",
        "parameters": {
            "type": "object",
            "properties": {
                "base_price": {"type": "number"},
                "tax_rate": {"type": "number"}
            },
            "required": ["base_price", "tax_rate"]
        }
    },
    "get_weather": {
        "description": "Get weather information for a location",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string"},
                "country": {"type": "string"}
            },
            "required": ["city"]
        }
    }
}

system_prompt = Template("""You are an expert in composing functions. You are given a question and a set of possible functions. 
Based on the question, you will need to make one or more function/tool calls to achieve the purpose. 
If none of the functions can be used, point it out and refuse to answer. 
If the given question lacks the parameters required by the function, also point it out.

You have access to the following tools:
<tools>{{ tools }}</tools>

The output MUST strictly adhere to the following format, and NO other text MUST be included.
The example format is as follows. Please make sure the parameter type is correct. If no function call is needed, please make the tool calls an empty list '[]'.
<tool_call>[
{"name": "func_name1", "arguments": {"argument1": "value1", "argument2": "value2"}},

(more tool calls as required)
]</tool_call>""")


def prepare_messages(
    query: str,
    tools: Optional[dict[str, any]] = None,
    history: Optional[list[dict[str, str]]] = None
) -> list[dict[str, str]]:
    """Prepare the system and user messages for the given query and tools.
    
    Args:
        query: The query to be answered.
        tools: The tools available to the user. Defaults to None, in which case if a
            list without content will be passed to the model.
        history: Exchange of messages, including the system_prompt from
            the first query. Defaults to None, the first message in a conversation.
    """
    if tools is None:
        tools = []
    if history:
        messages = history.copy()
        messages.append({"role": "user", "content": query})
    else:
        messages = [
            {"role": "system", "content": system_prompt.render(tools=json.dumps(tools))},
            {"role": "user", "content": query}
        ]
    return messages


def parse_response(text: str) -> str | dict[str, any]:
    """Parses a response from the model, returning either the
    parsed list with the tool calls parsed, or the
    model thought or response if couldn't generate one.

    Args:
        text: Response from the model.
    """
    pattern = r"<tool_call>(.*?)</tool_call>"
    matches = re.findall(pattern, text, re.DOTALL)
    if matches:
        return json.loads(matches[0])
    return text
    
checkpoint = "HuggingFaceTB/SmolLM2-1.7B-Instruct"
device = "cuda" # for GPU usage or "cpu" for CPU usage
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
# for multiple GPUs install accelerate and do `model = AutoModelForCausalLM.from_pretrained(checkpoint, device_map="auto")`
model = AutoModelForCausalLM.from_pretrained(checkpoint).to(device)

messages = prepare_messages("What is the capital of france?", example_tools)
input_text=tokenizer.apply_chat_template(messages, tokenize=False)
inputs = tokenizer.encode(input_text, return_tensors="pt").to(device)
outputs = model.generate(inputs, max_new_tokens=50, temperature=0.2, top_p=0.9, do_sample=True)
print(tokenizer.decode(outputs[0]))
Hugging Face TB Research org

Hi, sorry this was missing from the model card, it's updated now and you can find more details here: https://huggingface.co/HuggingFaceTB/SmolLM2-1.7B-Instruct/blob/main/instructions_function_calling.md

Can it create functions on its own? It failed when I tried to ask it to create and use simple python function to calculate 2+2, though I loaded model in 4bit using bitsandbytes config.

Hugging Face TB Research org
edited 16 days ago

Yes! The model is trained on code data, I just tried in the inference widget and it works fine, so maybe a quantization issue
image.png

that worked thanks!

lucyknada changed discussion status to closed

No. I am not talking about simply coding, I am talking about creating an agent that could create python functions and knows when to call what function. Of course it is good enough for smaller coding questions. My use case is as follows:

I got a coder instruct model running on localhost:8080 (through llamacpp) and this model should be able to call it and ask to code and then execute the code and respond with answer. (This is simplest case). How should I approach it?

Sign up or log in to comment