Usage
Basic Usage¶
Instructor extracts structured data from text using LLM inference. You define a PHP class that describes the shape of the data you want, and Instructor takes care of building the prompt, calling the model, and deserializing the response into a typed object.
use Cognesy\Instructor\StructuredOutput;
class Person {
public string $name;
public int $age;
}
$person = (new StructuredOutput)
->with(
messages: 'Jason is 28 years old.',
responseModel: Person::class,
)
->get();
echo $person->name; // Jason
echo $person->age; // 28
By default, Instructor looks for the
OPENAI_API_KEYenvironment variable. You can also choose a provider explicitly withStructuredOutput::using('openai')or by passing a runtime configured withLLMConfig.
Building The Request¶
The with() method covers the common path. It accepts all the parameters you typically need
in a single call:
$person = (new StructuredOutput)
->with(
messages: 'Jason is 28 years old.',
responseModel: Person::class,
system: 'Extract accurate data.',
prompt: 'Identify the person mentioned.',
model: 'gpt-4o',
)
->get();
When you prefer a more explicit, step-by-step style, use the fluent API:
$person = (new StructuredOutput)
->withMessages('Jason is 28 years old.')
->withResponseModel(Person::class)
->withSystem('Extract accurate data.')
->withPrompt('Identify the person mentioned.')
->withModel('gpt-4o')
->get();
Both approaches produce identical requests. Use whichever reads better in your code.
Request Methods¶
| Method | Purpose |
|---|---|
withMessages(...) |
Set the chat messages |
withInput(...) |
Set input from a string, array, or object (converted to messages) |
withResponseModel(...) |
Set the response model (class string, instance, or schema array) |
withResponseClass(...) |
Set the response model from a class name |
withResponseObject(...) |
Set the response model from an object instance |
withResponseJsonSchema(...) |
Set the response model from a JSON Schema array |
withSystem(...) |
Set the system prompt (string\|\Stringable) |
withPrompt(...) |
Set additional prompt text (string\|\Stringable) |
withExamples(...) |
Provide few-shot examples |
withModel(...) |
Override the model name |
withOptions(...) |
Pass provider-specific options |
withOption(...) |
Set a single provider option |
withStreaming(...) |
Enable or disable streaming |
withCachedContext(...) |
Set cached context for providers that support prompt caching |
Reading The Result¶
Instructor provides several ways to consume the response depending on your needs.
get() - The Parsed Value¶
The most common method. Returns the deserialized, validated object (or scalar when using
the Scalar adapter):
$person = (new StructuredOutput)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->get();
response() - The Full Response Envelope¶
Returns a StructuredOutputResponse that wraps both the parsed value and the raw LLM
response, giving you access to usage metadata, finish reason, and more:
$response = (new StructuredOutput)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->response();
$person = $response->value();
$usage = $response->usage();
inferenceResponse() - The Underlying Inference Response¶
Returns the low-level InferenceResponse from the Polyglot layer, useful when you need
direct access to HTTP response data or provider-specific details:
$raw = (new StructuredOutput)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->inferenceResponse();
stream() - Streaming Partial Results¶
Returns a StructuredOutputStream for real-time processing. Streaming is enabled
automatically when you call stream():
$stream = (new StructuredOutput)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->stream();
foreach ($stream->partials() as $partial) {
echo $partial->name ?? '...';
}
$person = $stream->lastUpdate();
create() - Lazy Execution¶
Returns a PendingStructuredOutput handle without triggering the LLM call. Nothing
executes until you read from it:
$pending = (new StructuredOutput)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->create();
// execution happens here
$person = $pending->get();
PendingStructuredOutput exposes the same reading methods as StructuredOutput plus
a few utility helpers:
| Method | Return type |
|---|---|
get() |
The parsed value |
response() |
StructuredOutputResponse |
inferenceResponse() |
InferenceResponse |
stream() |
StructuredOutputStream |
toJson() |
JSON string of the extracted data |
toArray() |
Associative array of the extracted data |
toJsonObject() |
Json object |
Typed Convenience Methods¶
When working with Scalar responses or any result where you know the expected PHP type,
you can skip get() and call a typed accessor directly:
$age = (new StructuredOutput)
->with(messages: 'Jason is 28.', responseModel: Scalar::integer('age'))
->getInt();
Available typed methods: getString(), getInt(), getFloat(), getBoolean(),
getObject(), getArray().
String As Input¶
You can pass a plain string anywhere messages are expected. Instructor wraps it into a user message automatically:
$person = (new StructuredOutput)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->get();
This is equivalent to passing [['role' => 'user', 'content' => 'Jason is 28 years old.']].
Structured-To-Structured Processing¶
The input parameter accepts objects, arrays, or strings. This lets you transform one
structured representation into another:
class Email {
public function __construct(
public string $address = '',
public string $subject = '',
public string $body = '',
) {}
}
$email = new Email(
address: 'joe@gmail.com',
subject: 'Status update',
body: 'Your account has been updated.',
);
$translated = (new StructuredOutput)
->withInput($email)
->with(
responseModel: Email::class,
prompt: 'Translate the text fields to Spanish. Keep other fields unchanged.',
)
->get();
Output Formats¶
By default, Instructor returns an instance of your response model class. You can change this with the output format methods:
// Return as an associative array instead of an object
$data = (new StructuredOutput)
->withResponseClass(User::class)
->intoArray()
->with(messages: 'John Doe, 30 years old')
->get();
// ['name' => 'John Doe', 'age' => 30]
// Use one class for the schema but hydrate into a different class
$dto = (new StructuredOutput)
->withResponseClass(UserProfile::class)
->intoInstanceOf(UserDTO::class)
->with(messages: 'Extract user data')
->get();
Three output format methods are available:
| Method | Effect |
|---|---|
intoArray() |
Skip deserialization, return a raw associative array |
intoInstanceOf($class) |
Use the schema from the response model but hydrate into a different class |
intoObject($obj) |
Pass a self-deserializing object that implements CanDeserializeSelf |
Using A Runtime¶
For applications that share provider configuration and behavior across many requests,
create a StructuredOutputRuntime once and reuse it:
use Cognesy\Instructor\StructuredOutput;
use Cognesy\Instructor\StructuredOutputRuntime;
use Cognesy\Polyglot\Inference\Config\LLMConfig;
$runtime = StructuredOutputRuntime::fromConfig(
LLMConfig::fromPreset('openai')
)->withMaxRetries(2);
$person = (new StructuredOutput)
->withRuntime($runtime)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->get();
The runtime holds settings like retries, output mode, validators, transformers, and deserializers. Individual requests stay lightweight and focused on content.
You can also use the static shorthand to pick a provider without building a full runtime:
$person = StructuredOutput::using('anthropic')
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->get();
Streaming Support¶
Instructor supports streaming of partial results, allowing you to process data as it arrives from the model:
$stream = (new StructuredOutput)
->with(messages: 'Jason is 28 years old.', responseModel: Person::class)
->stream();
foreach ($stream->partials() as $partialPerson) {
echo "Name: " . ($partialPerson->name ?? '...');
echo "Age: " . ($partialPerson->age ?? '...');
}
// After the stream completes, retrieve the final validated object
$person = $stream->lastUpdate();
The StructuredOutputStream provides several iteration methods:
| Method | Yields |
|---|---|
partials() |
Partially filled objects as they arrive |
sequence() |
Completed items when using Sequence as the response model |
responses() |
Full StructuredOutputResponse snapshots |
finalValue() |
Drains the stream and returns the final parsed value |
finalResponse() |
Drains the stream and returns the final StructuredOutputResponse |