import os
from utils import get_together_api_key
L3: Retry-based Structured Output
⏳ Note (Kernel Starting)
: This notebook takes about 30 seconds to be ready to use. You may start and watch the video while you wait.
import instructor
from openai import OpenAI
# Instantiate the client
= OpenAI(
together_client =f"{os.getenv('DLAI_TOGETHER_API_BASE', 'https://api.together.xyz')}/v1",
base_url=get_together_api_key(),
api_key )
đź’» Â Access requirements.txt
and helper.py
files: 1) click on the “File” option on the top menu of the notebook and then 2) click on “Open”.
⬇  Download Notebooks: 1) click on the “File” option on the top menu of the notebook and then 2) click on “Download as” and select “Notebook (.ipynb)”.
📒  For more help, please see the “Appendix – Tips, Help, and Download” Lesson.
= together_client.chat.completions.create(
response ="meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
model=[{"role": "user", "content": "sup"}],
messages
)
0].message.content response.choices[
"Sup back at you. How's your day going so far?"
Adding Instructor
# Wrap together with the instructor client
= instructor.from_openai(together_client) instructor_client
from pydantic import BaseModel
class Greeting(BaseModel):
str hello:
= instructor_client.chat.completions.create(
response ="meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
model=[{"role": "user", "content": "sup"}],
messages# Note: OpenAI uses response_format, instructor
# uses response_model!
=Greeting,
response_model
)
response
Greeting(hello='sup')
Defining a calendar event
from pydantic import Field
from datetime import date
from typing import List
# Person only has a name, but we can easily extend it with other fields
class Person(BaseModel):
str
name:
class CalendarEvent(BaseModel):
str
name:
# not supported by OpenAI. We want a format like 2025-01-30
date: date
participants: List[Person]
str
address_number: str
street_name: str
city_name:
# Inline regex patterns not supported by OpenAI restrict state code
# to be two capital letters (OpenAI does not support pattern fields)
str = Field(pattern=r"[A-Z]{2}")
state_code:
# Zip code must be five digits
str = Field(pattern=r"\d{6}") zip_code:
= """
event_description Rahul and Priya are going to a science fair on Friday, January 2024.
The science fair is hosted at the auditorium of National Public School, Indiranagar at 12th Main Road, HAL 2nd Stage in Bangalore, Karnataka.
"""
def generate(
response_model,
user_prompt,="You are a helpful assistant.",
system_prompt="meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo",
model# Can use 70b for a higher-quality model
# model="meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo",
=3,
max_retries
):= instructor_client.chat.completions.create(
event =model,
model=[
messages"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
{
],=response_model,
response_model=max_retries,
max_retries
)
return event
= """
system_prompt Make a calendar event. Respond in JSON with
the event name, date, list of participants,
and the address.
"""
= "Event description: " + event_description
user_prompt
= generate(CalendarEvent, user_prompt, system_prompt=system_prompt) event
event
CalendarEvent(name='Science Fair', date=datetime.date(2024, 1, 5), participants=[Person(name='Rahul'), Person(name='Priya')], address_number='12th Main Road', street_name='HAL 2nd Stage', city_name='Bangalore', state_code='KA', zip_code='560038')
event.model_dump()
{'name': 'Science Fair',
'date': datetime.date(2024, 1, 5),
'participants': [{'name': 'Rahul'}, {'name': 'Priya'}],
'address_number': '12th Main Road',
'street_name': 'HAL 2nd Stage',
'city_name': 'Bangalore',
'state_code': 'KA',
'zip_code': '560038'}
Retries
from utils import UsageTracker
# Clear any completion response hooks -- prevents
# duplicate writes to the usage tracker.
"completion:response")
instructor_client.clear(
# Create a new tracker
= UsageTracker()
tracker
# Define a custom instructor hook and update the
# tracker when a new completion runs.
def log_completion_kwargs(*args, **kwargs):
= args[0].usage
usage
tracker.track(usage)
# Assign the hook to instructor -- this will make the hook
# run each time the server returns a chat completion to us.
"completion:response", log_completion_kwargs) instructor_client.on(
# Clear the tracker before we run the completion
# so we arent' tracking multiple jobs.
tracker.clear()
= generate(
event
CalendarEvent,
user_prompt,=system_prompt,
system_prompt=4,
max_retries
)
event
CalendarEvent(name='Science Fair', date=datetime.date(2024, 1, 5), participants=[Person(name='Rahul'), Person(name='Priya')], address_number='12th Main Road', street_name='HAL 2nd Stage', city_name='Bangalore', state_code='KA', zip_code='560038')
print("Input tokens: ", tracker.input_tokens)
print("Output tokens: ", tracker.output_tokens)
print("Total tokens: ", sum(tracker.total_tokens))
print("Num retries: ", len(tracker.output_tokens))
Input tokens: [572]
Output tokens: [126]
Total tokens: 698
Num retries: 1
When retry methods fail
from typing import Literal
class Complicated(BaseModel):
# a must be cat, dog, or hat
"cat", "dog", "hat"]
a: Literal[int
b: bool c:
# Clear the tracker before we run the completion
# so we arent' tracking multiple jobs.
tracker.clear()
try:
= generate(
event
Complicated,"Write me a short essay on Dolly Parton.",
="Don't give me what I want.",
system_prompt=3,
max_retries
)
# Show the event
print(event)
except instructor.exceptions.InstructorRetryException:
print("We failed to parse!")
except e:
raise e
We failed to parse!
print("Input tokens: ", tracker.input_tokens)
print("Output tokens: ", tracker.output_tokens)
print("Total tokens: ", sum(tracker.total_tokens))
print("Num retries: ", len(tracker.output_tokens))
Input tokens: [277, 277, 277]
Output tokens: [16, 17, 16]
Total tokens: 880
Num retries: 3
You try!
# Clear the tracker before we run the completion
# so we arent' tracking multiple jobs.
tracker.clear()
try:
= generate(
event
Complicated,"Give me a, b, and c.",
="Give me what I want.",
system_prompt=3,
max_retries
)print(event)
except instructor.exceptions.InstructorRetryException:
print("We failed to parse!")
except e:
raise e
a='cat' b=1 c=True
print("Input tokens: ", tracker.input_tokens)
print("Output tokens: ", tracker.output_tokens)
print("Total tokens: ", sum(tracker.total_tokens))
print("Num retries: ", len(tracker.output_tokens))
Input tokens: [273, 421, 569]
Output tokens: [29, 29, 28]
Total tokens: 1349
Num retries: 3
event
Complicated(a='cat', b=1, c=True)