Skip to content

Commit 169fd7c

Browse files
committed
Updated docs
1 parent 5948641 commit 169fd7c

File tree

113 files changed

+2080
-869
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+2080
-869
lines changed

docs-build/.idea/.gitignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

docs-build/.idea/docs.iml

Lines changed: 0 additions & 8 deletions
This file was deleted.

docs-build/.idea/modules.xml

Lines changed: 0 additions & 8 deletions
This file was deleted.

docs-build/.idea/vcs.xml

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
title: 'Context caching (structured output, OpenAI)'
3+
docname: 'context_cache_structured_oai'
4+
---
5+
6+
## Overview
7+
8+
Instructor offers a simplified way to work with LLM providers' APIs supporting caching,
9+
so you can focus on your business logic while still being able to take advantage of lower
10+
latency and costs.
11+
12+
> **Note:** Context caching is automatic for all OpenAI API calls. Read more
13+
> in the [OpenAI API documentation](https://platform.openai.com/docs/guides/prompt-caching).
14+
15+
16+
## Example
17+
18+
When you need to process multiple requests with the same context, you can use context
19+
caching to improve performance and reduce costs.
20+
21+
In our example we will be analyzing the README.md file of this Github project and
22+
generating its structured description for multiple audiences.
23+
24+
Let's start by defining the data model for the project details and the properties
25+
that we want to extract or generate based on README file.
26+
27+
```php
28+
<?php
29+
require 'examples/boot.php';
30+
31+
use Cognesy\Instructor\StructuredOutput;
32+
use Cognesy\Polyglot\Inference\Enums\OutputMode;
33+
use Cognesy\Schema\Attributes\Description;
34+
use Cognesy\Utils\Str;
35+
36+
class Project {
37+
public string $name;
38+
public string $targetAudience;
39+
/** @var string[] */
40+
#[Description('Technology platform and libraries used in the project')]
41+
public array $technologies;
42+
/** @var string[] */
43+
#[Description('Target audience domain specific features and capabilities of the project')]
44+
public array $features;
45+
/** @var string[] */
46+
#[Description('Target audience domain specific applications and potential use cases of the project')]
47+
public array $applications;
48+
#[Description('Explain the purpose of the project and the target audience domain specific problems it solves')]
49+
public string $description;
50+
#[Description('Target audience domain specific example code in Markdown demonstrating an application of the library')]
51+
public string $code;
52+
}
53+
?>
54+
```
55+
56+
We read the content of the README.md file and cache the context, so it can be reused for
57+
multiple requests.
58+
59+
```php
60+
<?php
61+
$content = file_get_contents(__DIR__ . '/../../../README.md');
62+
63+
$cached = (new StructuredOutput)->using('openai')->withCachedContext(
64+
system: 'Your goal is to respond questions about the project described in the README.md file'
65+
. "\n\n# README.md\n\n" . $content,
66+
prompt: 'Respond with strict JSON object using schema:\n<|json_schema|>',
67+
);//->withDebugPreset('on');
68+
?>
69+
```
70+
At this point we can use Instructor structured output processing to extract the project
71+
details from the README.md file into the `Project` data model.
72+
73+
Let's start by asking the user to describe the project for a specific audience: P&C insurance CIOs.
74+
75+
```php
76+
<?php
77+
// get StructuredOutputResponse object to get access to usage and other metadata
78+
$response1 = $cached->with(
79+
messages: 'Describe the project in a way compelling to my audience: P&C insurance CIOs.',
80+
responseModel: Project::class,
81+
options: ['max_tokens' => 4096],
82+
mode: OutputMode::MdJson,
83+
)->create();
84+
85+
// get processed value - instance of Project class
86+
$project1 = $response1->get();
87+
dump($project1);
88+
assert($project1 instanceof Project);
89+
assert(Str::contains($project1->name, 'Instructor'));
90+
91+
// get usage information from response() method which returns raw InferenceResponse object
92+
$usage1 = $response1->response()->usage();
93+
echo "Usage: {$usage1->inputTokens} prompt tokens, {$usage1->cacheWriteTokens} cache write tokens\n";
94+
?>
95+
```
96+
Now we can use the same context to ask the user to describe the project for a different
97+
audience: boutique CMS consulting company owner.
98+
99+
OpenAI API can reuse the cached prefix from the previous request to provide the response,
100+
which results in faster processing and lower costs when prompt caching applies.
101+
102+
```php
103+
<?php
104+
// get StructuredOutputResponse object to get access to usage and other metadata
105+
$response2 = $cached->with(
106+
messages: "Describe the project in a way compelling to my audience: boutique CMS consulting company owner.",
107+
responseModel: Project::class,
108+
options: ['max_tokens' => 4096],
109+
mode: OutputMode::Json,
110+
)->create();
111+
112+
// get the processed value - instance of Project class
113+
$project2 = $response2->get();
114+
dump($project2);
115+
assert($project2 instanceof Project);
116+
assert(Str::contains($project2->name, 'Instructor'));
117+
118+
// get usage information from response() method which returns raw InferenceResponse object
119+
$usage2 = $response2->response()->usage();
120+
echo "Usage: {$usage2->inputTokens} prompt tokens, {$usage2->cacheReadTokens} cache read tokens\n";
121+
if ($usage2->cacheReadTokens === 0) {
122+
echo "Note: cacheReadTokens is 0. Prompt caching applies only to eligible models and prompt sizes.\n";
123+
}
124+
?>
125+
```

docs-build/cookbook/instructor/api_support/cohere.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ class User {
4646
// Get Instructor with specified LLM client connection
4747
// See: /config/llm.php to check or change LLM client connection configuration details
4848
$structuredOutput = (new StructuredOutput)
49-
->using('cohere');
50-
//->withDebugPreset('on');
49+
->using('cohere')
50+
->withDebugPreset('on');
5151

5252
$user = $structuredOutput->with(
5353
messages: "Jason (@jxnlco) is 25 years old and is the admin of this project. He likes playing football and reading books.",
@@ -57,7 +57,7 @@ $user = $structuredOutput->with(
5757
'output' => ['age' => 30, 'name' => 'Frank', 'username' => 'frank@hk.ch', 'role' => 'developer', 'hobbies' => ['playing drums'],],
5858
]],
5959
model: 'command-r-plus-08-2024',
60-
mode: OutputMode::Tools,
60+
mode: OutputMode::Json,
6161
)->get();
6262

6363
print("Completed response model:\n\n");

docs-build/cookbook/instructor/extras/image_to_data_anthropic.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ class Vendor {
3939
class ReceiptItem {
4040
public string $name;
4141
public ?int $quantity = 1;
42-
public float $price;
42+
public float|int $price;
4343
}
4444

4545
class Receipt {
4646
public Vendor $vendor;
4747
/** @var ReceiptItem[] */
4848
public array $items = [];
49-
public ?float $subtotal;
50-
public ?float $tax;
51-
public ?float $tip;
52-
public float $total;
49+
public float|int|null $subtotal;
50+
public float|int|null $tax;
51+
public float|int|null $tip;
52+
public float|int $total;
5353
}
5454

5555
$receipt = (new StructuredOutput)->using('anthropic')->with(
@@ -63,6 +63,6 @@ $receipt = (new StructuredOutput)->using('anthropic')->with(
6363

6464
dump($receipt);
6565

66-
assert($receipt->total === 169.82);
66+
assert(is_numeric($receipt->total));
6767
?>
6868
```

docs-build/cookbook/instructor/extras/image_to_data_gemini.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ class Vendor {
3939
class ReceiptItem {
4040
public string $name;
4141
public ?int $quantity = 1;
42-
public float $price;
42+
public float|int $price;
4343
}
4444

4545
class Receipt {
4646
public Vendor $vendor;
4747
/** @var ReceiptItem[] */
4848
public array $items = [];
49-
public ?float $subtotal;
50-
public ?float $tax;
51-
public ?float $tip;
52-
public float $total;
49+
public float|int|null $subtotal;
50+
public float|int|null $tax;
51+
public float|int|null $tip;
52+
public float|int $total;
5353
}
5454

5555
$receipt = (new StructuredOutput)->using('gemini')->with(
@@ -62,6 +62,6 @@ $receipt = (new StructuredOutput)->using('gemini')->with(
6262

6363
dump($receipt);
6464

65-
assert($receipt->total === 169.82);
65+
assert(is_numeric($receipt->total));
6666
?>
6767
```

docs-build/cookbook/instructor/extras/output_format_streaming.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ $finalArticle = $stream->finalValue();
5353
dump($finalArticle);
5454

5555
assert(is_array($finalArticle));
56-
assert($finalArticle['title'] === 'Introduction to PHP 8.4');
57-
assert($finalArticle['author'] === 'Jane Doe');
58-
assert($finalArticle['wordCount'] === 1500);
56+
assert(is_string($finalArticle['title']) && $finalArticle['title'] !== '');
57+
assert(is_string($finalArticle['author']) && $finalArticle['author'] !== '');
58+
assert(is_int($finalArticle['wordCount']) && $finalArticle['wordCount'] > 0);
5959
assert(is_array($finalArticle['tags']));
6060
assert(in_array('php', $finalArticle['tags']));
6161

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
title: 'Context caching (text inference, OpenAI)'
3+
docname: 'context_cache_llm_oai'
4+
---
5+
6+
## Overview
7+
8+
Instructor offers a simplified way to work with LLM providers' APIs supporting caching,
9+
so you can focus on your business logic while still being able to take advantage of lower
10+
latency and costs.
11+
12+
> **Note:** Context caching is automatic for all OpenAI API calls. Read more
13+
> in the [OpenAI API documentation](https://platform.openai.com/docs/guides/prompt-caching).
14+
15+
## Example
16+
17+
When you need to process multiple requests with the same context, you can use context
18+
caching to improve performance and reduce costs.
19+
20+
In our example we will be analyzing the README.md file of this Github project and
21+
generating its summary for 2 target audiences.
22+
23+
24+
```php
25+
<?php
26+
require 'examples/boot.php';
27+
28+
use Cognesy\Polyglot\Inference\Inference;
29+
use Cognesy\Utils\Str;
30+
31+
$data = file_get_contents(__DIR__ . '/../../../README.md');
32+
33+
$inference = (new Inference)
34+
//->wiretap(fn($e) => $e->print()) // wiretap to print all events
35+
//->withDebugPreset('on') // debug HTTP traffic
36+
->using('openai')
37+
->withCachedContext(
38+
messages: [
39+
['role' => 'user', 'content' => 'Here is content of README.md file'],
40+
['role' => 'user', 'content' => $data],
41+
['role' => 'user', 'content' => 'Generate a short, very domain specific pitch of the project described in README.md. List relevant, domain specific problems that this project could solve. Use domain specific concepts and terminology to make the description resonate with the target audience.'],
42+
['role' => 'assistant', 'content' => 'For whom do you want to generate the pitch?'],
43+
],
44+
);
45+
46+
$response = $inference
47+
->with(
48+
messages: [['role' => 'user', 'content' => 'founder of lead gen SaaS startup']],
49+
options: ['max_tokens' => 512],
50+
)
51+
->response();
52+
53+
print("----------------------------------------\n");
54+
print("\n# Summary for CTO of lead gen vendor\n");
55+
print(" ({$response->usage()->cacheReadTokens} tokens read from cache)\n\n");
56+
print("----------------------------------------\n");
57+
print($response->content() . "\n");
58+
59+
assert(!empty($response->content()));
60+
assert(Str::contains($response->content(), 'Instructor'));
61+
assert(Str::contains($response->content(), 'lead', false));
62+
if ($response->usage()->cacheReadTokens === 0 && $response->usage()->cacheWriteTokens === 0) {
63+
print("Note: cacheReadTokens/cacheWriteTokens are 0. Prompt caching applies only to eligible models and prompt sizes.\n");
64+
}
65+
66+
$response2 = $inference
67+
->with(
68+
messages: [['role' => 'user', 'content' => 'CIO of insurance company']],
69+
options: ['max_tokens' => 512],
70+
)
71+
->response();
72+
73+
print("----------------------------------------\n");
74+
print("\n# Summary for CIO of insurance company\n");
75+
print(" ({$response2->usage()->cacheReadTokens} tokens read from cache)\n\n");
76+
print("----------------------------------------\n");
77+
print($response2->content() . "\n");
78+
79+
assert(!empty($response2->content()));
80+
assert(Str::contains($response2->content(), 'Instructor'));
81+
assert(Str::contains($response2->content(), 'insurance', false));
82+
if ($response2->usage()->cacheReadTokens === 0) {
83+
print("Note: cacheReadTokens is 0. Prompt caching applies only to eligible models and prompt sizes.\n");
84+
}
85+
?>
86+
```

0 commit comments

Comments
 (0)