Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,57 @@ foreach (AiClient::defaultRegistry()->findModelsMetadataForSupport($requirements
}
```

See the [`PromptBuilder` class](https://github.com/WordPress/php-ai-client/blob/trunk/src/Builders/PromptBuilder.php) and the [`EmbeddingBuilder` class](https://github.com/WordPress/php-ai-client/blob/trunk/src/Builders/EmbeddingBuilder.php) and their public methods for all the ways you can configure generation.
### Classification using any compatible model

Classification models answer typed questions about the state you give them rather than generating content. There are three types of question:

* A `binary` question asks whether a statement is true, and is answered with the probability that it is.
* A `choice` question lists named options, each with a description of when it applies, and is answered with the key of the chosen option.
* A `score` question lists the levels of a scale from lowest to highest, and is answered with a position on that scale, from `0` for the lowest level to one less than the number of levels. The position may fall between two levels.

Answers to `choice` and `score` questions may also carry the model's confidence and a probability for each option or level, depending on what the model reports. Every answer is checked against its question, so an answer of the wrong type, an option the question does not have, or a position outside the scale raises a `RuntimeException`.

As with content generation, a suitable model is discovered if you do not name one. Classification requires a registered provider with at least one model that supports it. If there is none, `classifyResult()` throws an `InvalidArgumentException`, and `isSupported()` returns `false`.

```php
use WordPress\AiClient\AiClient;
use WordPress\AiClient\Providers\Models\Classification\DTO\ClassificationQuestion;
use WordPress\AiClient\Providers\Models\Classification\Enums\ClassificationQuestionTypeEnum;

$result = AiClient::classify(['comment' => $commentText])
->withQuestion(
'spam',
new ClassificationQuestion(ClassificationQuestionTypeEnum::binary(), 'Is this comment spam?')
)
->withQuestion(
'route',
new ClassificationQuestion(
ClassificationQuestionTypeEnum::choice(),
'How should a moderator handle it?',
[
'approve' => 'The comment is fine to publish.',
'hold' => 'The comment needs a closer look.',
'trash' => 'The comment should be removed.',
]
)
)
->withQuestion(
'tone',
new ClassificationQuestion(
ClassificationQuestionTypeEnum::score(),
'How civil is the comment?',
['Hostile.', 'Neutral.', 'Friendly.']
)
)
->classifyResult();

$spamProbability = $result->getAnswer('spam')->getProbability(); // e.g. 0.03
$route = $result->getAnswer('route')->getChoice(); // e.g. 'approve'
$confidence = $result->getAnswer('route')->getConfidence(); // e.g. 0.91, or null if not reported
$tone = $result->getAnswer('tone')->getScore(); // e.g. 1.7, between 'Neutral.' and 'Friendly.'
```

See the [`PromptBuilder` class](https://github.com/WordPress/php-ai-client/blob/trunk/src/Builders/PromptBuilder.php), the [`EmbeddingBuilder` class](https://github.com/WordPress/php-ai-client/blob/trunk/src/Builders/EmbeddingBuilder.php), and the [`ClassificationBuilder` class](https://github.com/WordPress/php-ai-client/blob/trunk/src/Builders/ClassificationBuilder.php) and their public methods for all the ways you can configure generation.

**More documentation is coming soon.**

Expand All @@ -175,6 +225,8 @@ The AI Client supports PSR-14 event dispatching for prompt lifecycle events. Thi
- `AfterGenerateResultEvent` - Dispatched after a result is received from the model
- `BeforeGenerateEmbeddingEvent` - Dispatched before embedding inputs are sent to the model
- `AfterGenerateEmbeddingEvent` - Dispatched after an embedding result is received from the model
- `BeforeClassifyEvent` - Dispatched before classification state and questions are sent to the model
- `AfterClassifyEvent` - Dispatched after the model's answers have been received and checked against the questions

**Important:** Event listeners should not return a value, as they will be ignored. In order to modify data that is passed with the event object, you need to rely on setters on the event object. Any event data for which there are no setters on the event object is meant to be immutable or, in other words, read-only for the event listener.

Expand Down
2 changes: 2 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ The two builders differ fundamentally in how they arrive at a model:

Both builders accumulate model configuration through the shared `ModelConfigurationTrait`, which provides `usingModelConfig()`.

Classification uses a third builder, `ClassificationBuilder`, because classification models take state and typed questions rather than a prompt, and answer each question with a probability, an option, or a position on a scale instead of generating content. Like `PromptBuilder`, it **resolves** a model through the `ModelResolutionTrait`, since answers are not tied to the model that produced them.

### Code examples

The following examples indicate how this SDK could eventually be used.
Expand Down
23 changes: 23 additions & 0 deletions src/AiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\SimpleCache\CacheInterface;
use WordPress\AiClient\Builders\ClassificationBuilder;
use WordPress\AiClient\Builders\EmbeddingBuilder;
use WordPress\AiClient\Builders\PromptBuilder;
use WordPress\AiClient\Common\Exception\InvalidArgumentException;
Expand Down Expand Up @@ -271,6 +272,28 @@ public static function input($input = null, ?ProviderRegistry $registry = null):
);
}

/**
* Creates a classification builder for fluent classification.
*
* Classification answers typed questions about the given state rather than generating content. Add
* questions via withQuestion() on the returned builder, then chain classifyResult() to get one answer
* per question.
*
* @since n.e.x.t
*
* @param array<string, mixed>|null $state Optional initial state to classify.
* @param ProviderRegistry|null $registry Optional custom registry. If null, uses default.
* @return ClassificationBuilder The classification builder instance.
*/
public static function classify(?array $state = null, ?ProviderRegistry $registry = null): ClassificationBuilder
{
return new ClassificationBuilder(
$registry ?? self::defaultRegistry(),
$state,
self::$eventDispatcher
);
}

/**
* Generates content using a unified API that automatically detects model capabilities.
*
Expand Down
Loading
Loading