Why use Instructor?
Key capabilities of Instructor
Our library introduces three key enhancements:
- Response Model: Specify a data model to be returned by LLM to simplify your code.
- Validation: Automatically validate response generated by LLM before you start using it.
- Max Retries: Automated retry attempts for invalid responses.
A Glimpse into Instructor’s Capabilities
With Instructor, your code becomes more efficient and readable. Here’s a quick peek.
Understanding the workflow
Let’s see how we can leverage it to make use of instructor
Step 1: Define the data model
Create a data model to define the structure of the data you want to extract. This model will map directly to the information in the prompt.
<?php
class UserDetail {
public string $name;
public int $age;
}
Step 2: Extract
Use the Instructor::respond()
method to send a prompt and extract the data into the target object. The responseModel
parameter specifies the model to use for extraction.
/** @var UserDetail */
$user = (new Instructor)->respond(
messages: [["role": "user", "content": "Extract Jason is 25 years old"]],
responseModel: UserDetail::class,
model: "gpt-3.5-turbo",
);
assert($user->name == "Jason")
assert($user->age == 25)
It’s helpful to annotate the variable with the type of the response model, which will help your IDE provide autocomplete and spell check.
Understanding Validation
Validation can also be plugged into the same data model. If the response triggers any validation rules Instructor will raise a validation error.
Self Correcting on Validation Error
Here, the LeadReport
model is passed as the $responseModel
, and $maxRetries
is set to 2. It means that if the extracted data does not match the model, Instructor will re-ask the model 2 times before giving up.
use Cognesy\Instructor\Instructor;
use Symfony\Component\Validator\Constraints as Assert;
class UserDetails
{
public string $name;
#[Assert\Email]
public string $email;
}
$user = (new Instructor)->respond(
messages: [['role' => 'user', 'content' => "you can reply to me via jason@gmailcom -- Jason"]],
responseModel: UserDetails::class,
maxRetries: 2
);
assert($user->email === "jason@gmail.com");
!!! note “More about Validation”
Check out Jason’s blog post Good LLM validation is just good validation
Custom Validators
Instructor uses Symfony validation component to validate extracted data. You can use #[Assert/Callback] annotation to build fully customized validation logic.
See Symfony docs for more details on how to use Callback constraint.
use Cognesy\Instructor\Instructor;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
class UserDetails
{
public string $name;
public int $age;
#[Assert\Callback]
public function validateName(ExecutionContextInterface $context, mixed $payload) {
if ($this->name !== strtoupper($this->name)) {
$context->buildViolation("Name must be in uppercase.")
->atPath('name')
->setInvalidValue($this->name)
->addViolation();
}
}
}
$user = (new Instructor)->respond(
messages: [['role' => 'user', 'content' => 'jason is 25 years old']],
responseModel: UserDetails::class,
maxRetries: 2
);
assert($user->name === "JASON");