---
title: Why use Instructor?
description: '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
<?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.

```php
/** @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.

```php
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](https://jxnl.github.io/instructor/blog/2023/10/23/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](https://symfony.com/doc/current/reference/constraints/Callback.html) for more details on how to use Callback constraint.

```php
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");
```
