import replicate
from pydantic import create_model
import inspect, json, re
from inspect import Parameter
from fastcore.foundation import L
from functools import partial
from pprint import pprint
Llama-3 Func Calling
An example of how to use the Llama-3 model to call functions with prompting only.
Inference code with prompt is located here.
Setup
The following collapsible element contains helper functions for the Replicate inference API and parsing the response:
def parse(text):
"""Use regular expressions to find content within the tags."""
= re.search(r"<function-call>\s*(.*?)\s*</function-call>", text, re.DOTALL)
function_call_search = re.search(r"<answer>\s*(.*?)\s*</answer>", text, re.DOTALL)
answer_search = function_call_search.group(1).strip() if function_call_search else None
function_call = answer_search.group(1).strip() if answer_search else None
answer
if function_call and function_call != "None": return {"type": "function-call", "content": function_call}
elif answer: return {"type": "text", "content": answer}
else: return {"type": "text", "content": text}
def run(prompt:str, tools:str=None):
= {"prompt": f"{prompt}", "temperature": 0}
inp if tools: inp['tools'] = tools
= replicate.run(
output "hamelsmu/llama-3-70b-instruct-awq-with-tools:b6042c085a7927a3d87e065a9f51fb7238ef6870c7a2ab7b03caa3c0e9413e19",
input=inp
)= ''.join(output)
txt return parse(txt)
A helper to help turn functions into a schema from fastai/llm-hackers
def schema(f):
= {n:(o.annotation, ... if o.default==Parameter.empty else o.default)
kw for n,o in inspect.signature(f).parameters.items()}
= create_model(f'Input for `{f.__name__}`', **kw).schema()
s return dict(name=f.__name__, description=f.__doc__, parameters=s)
Lets define two tools:
def get_exchange_rate(base_currency:str, target_currency:str):
"""
Get the exchange rate between two currencies.
Parameters:
- base_currency (str): The currency to convert from.
- target_currency (str): The currency to convert to.
Returns:
float: The exchange rate from base_currency to target_currency.
"""
...
def create_contact(name:str, email:str):
"""
Create a new contact.
Parameters:
- name (str): The name of the contact.
- email (str): The email address of the contact.
Returns:
dict: Confirmation of the created contact.
"""
...
= json.dumps(list(L([get_exchange_rate, create_contact]).map(schema))) tools
The Demo
Scenario 1A: No tool required to answer question
even though tool is provided
= run(prompt="Write a very short sentence about SEO.",
o1a =tools)
tools pprint(o1a)
{'content': 'Search Engine Optimization (SEO) is crucial for online '
'visibility.',
'type': 'text'}
Scenario 1B: No tool required to answer question
no tools are provided
= run(prompt="Write a very short sentence about SEO.",
o1b =None)
tools pprint(o1b)
{'content': 'Here is a very short sentence about SEO:\n'
'\n'
'"Optimizing website content with relevant keywords improves '
'search engine rankings."',
'type': 'text'}
Scenario 2: Tool is reqiured to answer question
= run(prompt="How many Japenese Yen are there in 1000 USD?",
o2 =tools)
tools pprint(o2)
{'content': 'get_exchange_rate(base_currency="USD", target_currency="JPY")',
'type': 'function-call'}
Scenario 3A: Tool reqiured but not enough info in the prompt for the params
= run(prompt="Can you help me add a Hamel Husain to my address book?",
o3a =tools)
tools pprint(o3a)
{'content': "I'd be happy to help you add Hamel Husain to your address book! "
'However, I need more information from you. Could you please '
"provide Hamel's email address? Once I have that, I can assist you "
'in adding the contact.',
'type': 'text'}
Scenario 3B: Tool required, there is enough info in the prompt
= run(prompt="Can you help me add a Hamel Husain to my address book?\
o3b His email address is h@fmail.com",
=tools)
tools pprint(o3b)
{'content': 'create_contact(name="Hamel Husain", email="h@fmail.com")',
'type': 'function-call'}