Skip to content

Commit

Permalink
Example of token consumption counting using events
Browse files Browse the repository at this point in the history
  • Loading branch information
ddebowczyk committed Aug 26, 2024
1 parent 45a0458 commit 091dcf2
Show file tree
Hide file tree
Showing 38 changed files with 403 additions and 203 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ Here's a simple CLI demo app using Instructor to extract structured data from te
- OpenRouter support - access to 100+ language models
- Use local models with Ollama

### Other capabilities

- Developer friendly LLM context caching for reduced costs and faster inference (for Anthropic models)
- Developer friendly image processing (for OpenAI, Anthropic and Gemini models)

### Documentation and examples

- Learn more from growing documentation and 50+ cookbooks
Expand Down
70 changes: 0 additions & 70 deletions docs/cookbook/examples/api_support/caching.mdx

This file was deleted.

2 changes: 1 addition & 1 deletion docs/cookbook/examples/basics/complex_extraction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ $events = $instructor
->request(
messages: $report,
responseModel: Sequence::of(ProjectEvent::class),
model: 'openai:gpt-4o-mini',
model: 'gpt-4o-mini',
mode: Mode::Json,
options: [
'max_tokens' => 2048,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Clients\Anthropic\AnthropicClient;
use Cognesy\Instructor\Clients\OpenRouter\OpenRouterClient;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\Sequence\Sequence;
use Cognesy\Instructor\Instructor;
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/techniques/image_to_data.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: 'Image to data'
title: 'Image to data (OpenAI)'
docname: 'image_to_data'
---

Expand Down
74 changes: 74 additions & 0 deletions docs/cookbook/examples/techniques/image_to_data_anthropic.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: 'Image to data (Anthropic)'
docname: 'image_to_data_anthropic'
---

## Overview

This is an example of how to extract structured data from an image using
Instructor. The image is loaded from a file and converted to base64 format
before sending it to OpenAI API.

The response model is a PHP class that represents the structured receipt
information with data of vendor, items, subtotal, tax, tip, and total.


## Scanned image

Here's the image we're going to extract data from.

![Receipt](images/receipt.png)


## Example

```php
<?php
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Clients\Anthropic\AnthropicClient;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\Image\Image;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Utils\Env;

class Vendor {
public ?string $name = '';
public ?string $address = '';
public ?string $phone = '';
}

class ReceiptItem {
public string $name;
public ?int $quantity = 1;
public float $price;
}

class Receipt {
public Vendor $vendor;
/** @var ReceiptItem[] */
public array $items = [];
public ?float $subtotal;
public ?float $tax;
public ?float $tip;
public float $total;
}

$client = new AnthropicClient(
apiKey: Env::get('ANTHROPIC_API_KEY'),
);

$receipt = (new Instructor)->withClient($client)->respond(
input: Image::fromFile(__DIR__ . '/receipt.png'),
responseModel: Receipt::class,
prompt: 'Extract structured data from the receipt. Return result as JSON following this schema: <|json_schema|>',
mode: Mode::Json,
options: ['max_tokens' => 4096]
);

dump($receipt);

assert($receipt->total === 169.82);
?>
```
94 changes: 94 additions & 0 deletions docs/cookbook/examples/troubleshooting/token_usage_events.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: 'Tracking token usage via events'
docname: 'token_usage_events'
---

## Overview

Some use cases require tracking the token usage of the API responses.
Currently, this can be done by listening to the `ApiResponseReceived`
and `PartialApiResponseReceived` events and summing the token usage
of the responses.

Code below demonstrates how it can be implemented using Instructor
event listeners.

> Note: OpenAI API requires `stream_options` to be set to
> `['include_usage' => true]` to include token usage in the streamed
> responses.
## Example

```php
<?php
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\ApiClient\Responses\ApiResponse;
use Cognesy\Instructor\ApiClient\Responses\PartialApiResponse;
use Cognesy\Instructor\ApiClient\Traits\PartialApiResponseReceived;
use Cognesy\Instructor\Events\ApiClient\ApiResponseReceived;
use Cognesy\Instructor\Instructor;

class User {
public int $age;
public string $name;
}

class TokenCounter {
private int $input = 0;
private int $output = 0;
private int $cacheCreation = 0;
private int $cacheRead = 0;

public function add(ApiResponse|PartialApiResponse $response) {
$this->input += $response->inputTokens;
$this->output += $response->outputTokens;
$this->cacheCreation += $response->cacheCreationTokens;
$this->cacheRead += $response->cacheReadTokens;
}

public function reset() {
$this->input = 0;
$this->output = 0;
$this->cacheCreation = 0;
$this->cacheRead = 0;
}

public function print() {
echo "Input tokens: $this->input\n";
echo "Output tokens: $this->output\n";
echo "Cache creation tokens: $this->cacheCreation\n";
echo "Cache read tokens: $this->cacheRead\n";
}
}

$counter = new TokenCounter();

echo "COUNTING TOKENS FOR SYNC RESPONSE\n";
$text = "Jason is 25 years old and works as an engineer.";
$instructor = (new Instructor)
->onEvent(ApiResponseReceived::class, fn($e) => $counter->add($e->apiResponse))
->respond(
messages: $text,
responseModel: User::class,
);
echo "\nTEXT: $text\n";
$counter->print();
$counter->reset();

echo "\n\nCOUNTING TOKENS FOR STREAMED RESPONSE\n";
$text = "Anna is 19 years old.";
$instructor = (new Instructor)
->onEvent(PartialApiResponseReceived::class, fn($e) => $counter->add($e->partialApiResponse))
->respond(
messages: $text,
responseModel: User::class,
options: ['stream' => true, 'stream_options' => ['include_usage' => true]],
);
echo "\nTEXT: $text\n";
$counter->print();
$counter->reset();

?>
```
3 changes: 2 additions & 1 deletion docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
"cookbook/examples/techniques/entity_relationships",
"cookbook/examples/techniques/handling_errors",
"cookbook/examples/techniques/image_to_data",
"cookbook/examples/techniques/image_to_data",
"cookbook/examples/techniques/image_to_data_anthropic",
"cookbook/examples/techniques/image_to_data",
"cookbook/examples/techniques/limiting_lists",
"cookbook/examples/techniques/restate_instructions",
Expand All @@ -174,6 +174,7 @@
"cookbook/examples/troubleshooting/debugging",
"cookbook/examples/troubleshooting/on_error",
"cookbook/examples/troubleshooting/on_event",
"cookbook/examples/troubleshooting/token_usage_events",
"cookbook/examples/troubleshooting/wiretap"
]
},
Expand Down
2 changes: 1 addition & 1 deletion examples/01_Basics/ComplexExtraction/run.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ enum StakeholderRole: string {
->request(
messages: $report,
responseModel: Sequence::of(ProjectEvent::class),
model: 'openai:gpt-4o-mini',
model: 'gpt-4o-mini',
mode: Mode::Json,
options: [
'max_tokens' => 2048,
Expand Down
2 changes: 1 addition & 1 deletion examples/03_Techniques/ImageToData/run.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: 'Image to data'
title: 'Image to data (OpenAI)'
docname: 'image_to_data'
---

Expand Down
4 changes: 2 additions & 2 deletions examples/03_Techniques/ImageToDataAnthropic/run.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'Image to data'
docname: 'image_to_data'
title: 'Image to data (Anthropic)'
docname: 'image_to_data_anthropic'
---

## Overview
Expand Down
Loading

0 comments on commit 091dcf2

Please sign in to comment.