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 pprintLlama-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."""
function_call_search = re.search(r"<function-call>\s*(.*?)\s*</function-call>", text, re.DOTALL)
answer_search = re.search(r"<answer>\s*(.*?)\s*</answer>", text, re.DOTALL)
function_call = function_call_search.group(1).strip() if function_call_search else None
answer = answer_search.group(1).strip() if answer_search else None
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):
inp = {"prompt": f"{prompt}", "temperature": 0}
if tools: inp['tools'] = tools
output = replicate.run(
"hamelsmu/llama-3-70b-instruct-awq-with-tools:b6042c085a7927a3d87e065a9f51fb7238ef6870c7a2ab7b03caa3c0e9413e19",
input=inp
)
txt = ''.join(output)
return parse(txt) A helper to help turn functions into a schema from fastai/llm-hackers
def schema(f):
kw = {n:(o.annotation, ... if o.default==Parameter.empty else o.default)
for n,o in inspect.signature(f).parameters.items()}
s = create_model(f'Input for `{f.__name__}`', **kw).schema()
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.
"""
...
tools = json.dumps(list(L([get_exchange_rate, create_contact]).map(schema)))The Demo
Scenario 1A: No tool required to answer question
even though tool is provided
o1a = run(prompt="Write a very short sentence about SEO.",
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
o1b = run(prompt="Write a very short sentence about SEO.",
tools=None)
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
o2 = run(prompt="How many Japenese Yen are there in 1000 USD?",
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
o3a = run(prompt="Can you help me add a Hamel Husain to my address book?",
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
o3b = run(prompt="Can you help me add a Hamel Husain to my address book?\
His email address is h@fmail.com",
tools=tools)
pprint(o3b){'content': 'create_contact(name="Hamel Husain", email="h@fmail.com")',
'type': 'function-call'}