v1.16.0
Release Notes - v1.16.0
New Features
OutputFormat API
Control output format independently from schema:
// Get raw arrays instead of objects
$data = StructuredOutput::with(...)
->intoArray()
->get();
// Deserialize to different class than schema
$user = StructuredOutput::with(...)
->intoInstanceOf(User::class)
->get();
// Self-deserializing objects
$obj = StructuredOutput::with(...)
->intoObject($customObject)
->get();Pluggable Extraction
Custom JSON extraction strategies:
class CustomExtractor implements CanExtractContent {
public function extract(string $content): string {
// custom extraction logic
}
}
StructuredOutput::with(...)
->withExtractor(new ResponseExtractor([
new CustomExtractor(),
new ResilientJsonExtractor(),
]))
->get();Built-in extractors:
DirectJsonExtractor- Parse as-isResilientJsonExtractor- Handle malformed JSONMarkdownBlockExtractor- Extract from code blocksBracketMatchingExtractor- Find first{to last}SmartBraceExtractor- Handle escaped quotes
Extraction Events
Track extraction lifecycle:
ExtractionStartedExtractionStrategyAttemptedExtractionStrategySucceededExtractionStrategyFailedExtractionCompletedExtractionFailed
Manual Schema Support
JSON schemas no longer require x-php-class:
$schema = [
'type' => 'object',
'properties' => [
'name' => ['type' => 'string'],
],
];
// Returns raw array when no class specified
$data = StructuredOutput::with(
messages: 'John',
responseModel: $schema
)->get();Response Caching
use Cognesy\Polyglot\Inference\Enums\ResponseCachePolicy;
// Cache responses in memory
$response = Inference::with(...)
->withCachePolicy(ResponseCachePolicy::Memory)
->get();Improvements
- Simplified processing pipeline
- Removed unused partial validations
Bug Fixes
- Fixed
withInput()to handle objects correctly - Fixed
HostSandboxto run inbaseDir(fixes CLI agents) - Fixed environment inheritance for agent execution
- Fixed exit code propagation in examples
- Resolved all PHPStan errors
New Package: metrics
Event-driven metrics collection system.
Metric types:
- Counter - incremental counts
- Gauge - point-in-time values
- Histogram - value distributions
- Timer - duration measurements
Usage:
use Cognesy\Metrics\Collectors\MetricsCollector;
use Cognesy\Metrics\Metrics;
// Create custom collector
class StreamMetricsCollector extends MetricsCollector {
protected function listeners(): array {
return [
StreamFirstChunkReceived::class => $this->onFirstChunk(...),
InferenceCompleted::class => $this->onCompleted(...),
];
}
public function onFirstChunk(StreamFirstChunkReceived $event): void {
$this->timer('llm.stream.ttfc_ms', $event->timeToFirstChunkMs, [
'model' => $event->model,
]);
}
public function onCompleted(InferenceCompleted $event): void {
$this->gauge('llm.output_tokens', (float) $event->usage->output());
}
}
// Register collector and exporter
$metrics = new Metrics($events);
$metrics
->collect(new StreamMetricsCollector())
->exportTo(new CallbackExporter(fn($metrics) => dump($metrics)));
// Metrics auto-collected from events
$metrics->export();