Skip to content

Commit

Permalink
Fixed Gemini tool streaming defect, code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ddebowczyk committed Oct 8, 2024
1 parent 0dacba8 commit f8bb110
Show file tree
Hide file tree
Showing 294 changed files with 852 additions and 862 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -662,9 +662,9 @@ For more information see [Structures](docs/structures.md) section.
You can specify model and other options that will be passed to OpenAI / LLM endpoint.

```php
use Cognesy\Instructor\Features\LLM\Data\LLMConfig;
use Cognesy\Instructor\Features\LLM\Drivers\OpenAIDriver;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Extras\LLM\Data\LLMConfig;
use Cognesy\Instructor\Extras\LLM\Drivers\OpenAIDriver;

// OpenAI auth params
$yourApiKey = Env::get('OPENAI_API_KEY'); // use your own API key
Expand Down Expand Up @@ -743,7 +743,7 @@ class Skill {
You can use ValidationMixin trait to add ability of easy, custom data object validation.

```php
use Cognesy\Instructor\Validation\Traits\ValidationMixin;
use Cognesy\Instructor\Features\Validation\Traits\ValidationMixin;

class User {
use ValidationMixin;
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"Cognesy\\Experimental\\": "experimental/"
},
"files": [
"tests/Examples/Call/test_functions.php"
]
},
"authors": [
Expand Down Expand Up @@ -54,7 +55,8 @@
"psr/http-factory-implementation": "*",
"symfony/psr-http-message-bridge": "^7.1",
"nyholm/psr7": "^1.8",
"guzzlehttp/psr7": "^2.7"
"guzzlehttp/psr7": "^2.7",
"twig/twig": "^3.0"
},
"config": {
"allow-plugins": {
Expand Down
2 changes: 1 addition & 1 deletion config/embed.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

use Cognesy\Instructor\Extras\LLM\Enums\LLMProviderType;
use Cognesy\Instructor\Features\LLM\Enums\LLMProviderType;
use Cognesy\Instructor\Utils\Env;

return [
Expand Down
2 changes: 1 addition & 1 deletion config/http.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

use Cognesy\Instructor\Extras\Http\Enums\HttpClientType;
use Cognesy\Instructor\Features\Http\Enums\HttpClientType;

return [
'defaultClient' => 'guzzle',
Expand Down
2 changes: 1 addition & 1 deletion config/llm.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

use Cognesy\Instructor\Extras\LLM\Enums\LLMProviderType;
use Cognesy\Instructor\Features\LLM\Enums\LLMProviderType;
use Cognesy\Instructor\Utils\Env;

return [
Expand Down
4 changes: 2 additions & 2 deletions docs/advanced/model_options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ You can pass a custom configured instance of client to the Instructor. This allo

```php
<?php
use Cognesy\Instructor\Features\LLM\Data\LLMConfig;
use Cognesy\Instructor\Features\LLM\Drivers\OpenAIDriver;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Extras\LLM\Data\LLMConfig;
use Cognesy\Instructor\Extras\LLM\Drivers\OpenAIDriver;

// Create instance of OpenAI client initialized with custom parameters
$driver = new OpenAIDriver(new LLMConfig(
Expand Down
5 changes: 1 addition & 4 deletions docs/cookbook/examples/advanced/context_cache.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ that we want to extract or generate based on README file.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Description;
use Cognesy\Instructor\Utils\Str;
use Cognesy\Instructor\Features\Schema\Attributes\Description;

class Project {
public string $name;
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/advanced/context_cache_llm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ generating its summary for 2 target audiences.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Features\LLM\Inference;
use Cognesy\Instructor\Utils\Str;

$content = file_get_contents(__DIR__ . '/../../../README.md');
Expand Down
4 changes: 2 additions & 2 deletions docs/cookbook/examples/advanced/custom_client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\LLM\Data\LLMConfig;
use Cognesy\Instructor\Extras\LLM\Drivers\OpenAIDriver;
use Cognesy\Instructor\Features\LLM\Data\LLMConfig;
use Cognesy\Instructor\Features\LLM\Drivers\OpenAIDriver;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Utils\Env;

Expand Down
4 changes: 3 additions & 1 deletion docs/cookbook/examples/advanced/custom_prompts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ customize how LLM is instructed to process the input.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;
use Cognesy\Instructor\Instructor;

class User {
public int $age;
Expand Down
5 changes: 4 additions & 1 deletion docs/cookbook/examples/advanced/demonstrations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ is expected to be a JSON object.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Data\Example;use Cognesy\Instructor\Enums\Mode;use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Data\Example;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;
use Cognesy\Instructor\Instructor;

class User {
public int $age;
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/api_support/azure_openai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class User {
$instructor = (new Instructor)->withConnection('azure');

// Call with your model name and preferred execution mode
$user = $instructor->withDebug()->respond(
$user = $instructor->respond(
messages: "Jason (@jxnlco) is 25 years old and is the admin of this project. He likes playing football and reading books.",
responseModel: User::class,
examples: [[
Expand Down
2 changes: 0 additions & 2 deletions docs/cookbook/examples/api_support/ollama.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\Debug\Debug;
use Cognesy\Instructor\Instructor;

enum UserType : string {
Expand All @@ -44,7 +43,6 @@ class User {
// See: /config/llm.php to check or change LLM client connection configuration details
$instructor = (new Instructor)->withConnection('ollama');

//Debug::enable();
$user = $instructor->respond(
messages: "Jason (@jxnlco) is 25 years old and is the admin of this project. He likes playing football and reading books.",
responseModel: User::class,
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/api_support/openrouter.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class User {
// See: /config/llm.php to check or change LLM client connection configuration details
$instructor = (new Instructor)->withConnection('openrouter');

$user = $instructor->withDebug()->respond(
$user = $instructor->respond(
messages: "Jason (@jxnlco) is 25 years old. He is the admin of this project. He likes playing football and reading books.",
responseModel: User::class,
prompt: 'Parse the user data to JSON, respond using following JSON Schema: <|json_schema|>',
Expand Down
4 changes: 2 additions & 2 deletions docs/cookbook/examples/basics/attributes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ context to the language model or to provide additional instructions to the model
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Features\Schema\Attributes\Description;
use Cognesy\Instructor\Features\Schema\Attributes\Instructions;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Description;
use Cognesy\Instructor\Schema\Attributes\Instructions;

// Step 1: Define a class that represents the structure and semantics
// of the data you want to extract
Expand Down
7 changes: 6 additions & 1 deletion docs/cookbook/examples/basics/self_correction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ until results meet the requirements or maxRetries is reached.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__.'../../src/');

use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;use Cognesy\Instructor\Events\Response\ResponseValidated;use Cognesy\Instructor\Events\Response\ResponseValidationAttempt;use Cognesy\Instructor\Events\Response\ResponseValidationFailed;use Cognesy\Instructor\Instructor;use Symfony\Component\Validator\Constraints as Assert;
use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;
use Cognesy\Instructor\Events\Response\ResponseValidated;
use Cognesy\Instructor\Events\Response\ResponseValidationAttempt;
use Cognesy\Instructor\Events\Response\ResponseValidationFailed;
use Cognesy\Instructor\Instructor;
use Symfony\Component\Validator\Constraints as Assert;

class UserDetails
{
Expand Down
4 changes: 2 additions & 2 deletions docs/cookbook/examples/basics/validation_multifield.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ is `1010` instead of `2010`) and respond with correct graduation year.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__.'../../src/');

use Cognesy\Instructor\Features\Validation\Traits\ValidationMixin;
use Cognesy\Instructor\Features\Validation\ValidationResult;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Validation\Traits\ValidationMixin;
use Cognesy\Instructor\Validation\ValidationResult;

class UserDetails
{
Expand Down
6 changes: 3 additions & 3 deletions docs/cookbook/examples/basics/validation_with_llm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ $loader->add('Cognesy\\Instructor\\', __DIR__.'../../src/');
use Cognesy\Instructor\Events\Event;
use Cognesy\Instructor\Extras\Scalar\Scalar;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Description;
use Cognesy\Instructor\Features\Schema\Attributes\Description;
use Cognesy\Instructor\Utils\Str;
use Cognesy\Instructor\Validation\Traits\ValidationMixin;
use Cognesy\Instructor\Validation\ValidationResult;
use Cognesy\Instructor\Features\Validation\Traits\ValidationMixin;
use Cognesy\Instructor\Features\Validation\ValidationResult;

class UserDetails
{
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/extras/image_car_damage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Extras\Image\Image;
use Cognesy\Instructor\Features\Schema\Attributes\Description;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Description;

enum DamageSeverity : string {
case Minor = 'minor';
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/extras/llm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ LLM providers access details can be found and modified via
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Features\LLM\Inference;
use Cognesy\Instructor\Utils\Str;


Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/extras/llm_json.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Features\LLM\Inference;

$data = (new Inference)
->withConnection('openai') // optional, default is set in /config/llm.php
Expand Down
3 changes: 2 additions & 1 deletion docs/cookbook/examples/extras/llm_json_schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ supported by all language model providers.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Features\LLM\Inference;

$data = (new Inference)
->withConnection('openai')
Expand Down
3 changes: 2 additions & 1 deletion docs/cookbook/examples/extras/llm_md_json.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ to guide the model in generating the correct response.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Features\LLM\Inference;

$data = (new Inference)
->withConnection('openai')
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/extras/llm_tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Features\LLM\Inference;

$data = (new Inference)
->withConnection('openai')
Expand Down
5 changes: 3 additions & 2 deletions docs/cookbook/examples/extras/schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ the JSON Schema manually, which can be error-prone and time-consuming.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Schema\Factories\SchemaFactory;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Features\LLM\Inference;
use Cognesy\Instructor\Features\Schema\Factories\SchemaFactory;

class City {
public string $name;
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/extras/schema_dynamic.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Extras\Structure\Field;
use Cognesy\Instructor\Extras\Structure\Structure;
use Cognesy\Instructor\Features\LLM\Inference;

$city = Structure::define('city', [
Field::string('name', 'City name')->required(),
Expand Down
4 changes: 2 additions & 2 deletions docs/cookbook/examples/extras/translate_ui_fields.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Extras\Scalar\Scalar;
use Cognesy\Instructor\Features\Validation\Contracts\CanValidateObject;
use Cognesy\Instructor\Features\Validation\ValidationResult;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Validation\Contracts\CanValidateObject;
use Cognesy\Instructor\Validation\ValidationResult;

class TextElementModel
{
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/examples/extras/web_to_objects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ $loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\Web\Webpage;
use Cognesy\Instructor\Features\Schema\Attributes\Instructions;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Instructions;

class Company {
public string $name = '';
Expand Down
4 changes: 2 additions & 2 deletions docs/cookbook/examples/troubleshooting/debugging.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ This is useful for debugging the request and response when you are not getting t
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Extras\LLM\Data\LLMConfig;
use Cognesy\Instructor\Extras\LLM\Drivers\OpenAIDriver;
use Cognesy\Instructor\Features\LLM\Data\LLMConfig;
use Cognesy\Instructor\Features\LLM\Drivers\OpenAIDriver;
use Cognesy\Instructor\Instructor;

class User {
Expand Down
5 changes: 4 additions & 1 deletion docs/cookbook/examples/troubleshooting/on_event.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ and their properties.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Events\Event;use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;use Cognesy\Instructor\Events\HttpClient\ResponseReceivedFromLLM;use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Events\Event;
use Cognesy\Instructor\Events\HttpClient\RequestSentToLLM;
use Cognesy\Instructor\Events\HttpClient\ResponseReceivedFromLLM;
use Cognesy\Instructor\Instructor;

class User
{
Expand Down
4 changes: 2 additions & 2 deletions docs/cookbook/examples/troubleshooting/token_usage_events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ $loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Events\Inference\LLMResponseReceived;
use Cognesy\Instructor\Events\Inference\PartialLLMResponseReceived;
use Cognesy\Instructor\Extras\LLM\Data\LLMResponse;
use Cognesy\Instructor\Extras\LLM\Data\PartialLLMResponse;
use Cognesy\Instructor\Features\LLM\Data\LLMResponse;
use Cognesy\Instructor\Features\LLM\Data\PartialLLMResponse;
use Cognesy\Instructor\Instructor;

class User {
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/prompting/misc/chain_of_thought.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ self-explain approach to generating the response.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__.'../../src/');

use Cognesy\Instructor\Features\Schema\Attributes\Instructions;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Instructions;

class Employee {
#[Instructions('Think step by step to determine the correct year of employment.')]
Expand Down
4 changes: 2 additions & 2 deletions docs/cookbook/prompting/misc/limiting_lists.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ a manageable set of properties.
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__.'../../src/');

use Cognesy\Instructor\Features\Validation\Traits\ValidationMixin;
use Cognesy\Instructor\Features\Validation\ValidationResult;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Validation\Traits\ValidationMixin;
use Cognesy\Instructor\Validation\ValidationResult;

class Property
{
Expand Down
6 changes: 3 additions & 3 deletions docs/cookbook/prompting/misc/reflection_prompting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__.'../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Features\Schema\Attributes\Instructions;
use Cognesy\Instructor\Features\Validation\Contracts\CanValidateSelf;
use Cognesy\Instructor\Features\Validation\ValidationResult;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Instructions;
use Cognesy\Instructor\Validation\Contracts\CanValidateSelf;
use Cognesy\Instructor\Validation\ValidationResult;

class ReflectiveResponse implements CanValidateSelf {
#[Instructions('Is problem solvable and what domain expertise it requires')]
Expand Down
2 changes: 1 addition & 1 deletion docs/cookbook/prompting/zero_shot/auto_refine.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ $loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__.'../../src/');

use Cognesy\Instructor\Extras\Scalar\Scalar;
use Cognesy\Instructor\Features\Schema\Attributes\Description;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Schema\Attributes\Description;

class RewrittenTask {
#[Description("Relevant context")]
Expand Down
Loading

0 comments on commit f8bb110

Please sign in to comment.