Skip to content

Commit 0ec177a

Browse files
feat: add PSR-3 logging support
1 parent bf080f7 commit 0ec177a

30 files changed

+322
-181
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ Transformers::setup()
136136
->setRemotePathTemplate('...') // Set the remote path template for downloading models. Defaults to `{model}/resolve/{revision}/{file}`
137137
->setAuthToken('...') // Set the auth token for downloading models. Defaults to `null`
138138
->setUserAgent('...') // Set the user agent for downloading models. Defaults to `transformers-php/{version}`
139-
->setImageDriver('...') // Set the image driver for processing images. Defaults to `IMAGICK'
139+
->setImageDriver('...') // Set the image driver for processing images. Defaults to `VIPS`
140+
->setLogger($logger) // Set a PSR-3 compatible logger. Defaults to `NullLogger` if not set
140141
->apply(); // Apply the configuration
141142
```
142143

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"codewithkyrian/jinja-php": "^1.0",
1919
"codewithkyrian/platform-package-installer": "^1.0",
2020
"imagine/imagine": "^1.3",
21+
"psr/log": "^1.1 || ^2.0 || ^3.0",
2122
"rindow/rindow-math-matrix": "^2.1",
2223
"rindow/rindow-matlib-ffi": "^1.1",
2324
"rindow/rindow-openblas-ffi": "^1.0",
@@ -77,4 +78,4 @@
7778
"windows-x86_64": "https://github.com/codewithkyrian/transformers-php/releases/download/{version}/dist-windows-x86_64.zip"
7879
}
7980
}
80-
}
81+
}

docs/configuration.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ models, and the remote path template. These settings allow you to tailor how and
1515
```php
1616
use Codewithkyrian\Transformers\Transformers;
1717
use Codewithkyrian\Transformers\Utils\ImageDriver;
18+
use Psr\Log\LoggerInterface;
1819

1920
Transformers::setup()
2021
->setCacheDir('/path/to/models')
2122
->setRemoteHost('https://yourmodelshost.com')
2223
->setRemotePathTemplate('custom/path/{model}/{file}')
2324
->setAuthToken('your-token')
2425
->setUserAgent('your-user-agent')
25-
->setImageDriver(ImageDriver::IMAGICK);
26+
->setImageDriver(ImageDriver::IMAGICK)
27+
->setLogger($logger);
2628
```
2729

2830
::: tip
@@ -94,8 +96,7 @@ Transformers::setup()->setUserAgent('your-user-agent');
9496
### `setImageDriver(ImageDriver $imageDriver)`
9597

9698
This setting allows you to specify the image backend to use for image processing tasks. By default, the image driver is
97-
not set and an error will be thrown if you try to perform any image related task. You can change this to `IMAGICK`, `GD`
98-
or `VIPS` if you prefer, just make sure to have the required extensions installed.
99+
set to `VIPS`. You can change this to `IMAGICK`, `GD` or `VIPS` if you prefer, just make sure to have the required extensions installed.
99100

100101
```php
101102
use Codewithkyrian\Transformers\Utils\ImageDriver;
@@ -105,6 +106,24 @@ Transformers::setup()
105106
->apply();
106107
```
107108

109+
### `setLogger(LoggerInterface $logger)`
110+
111+
This setting allows you to specify a PSR-3 compatible logger for TransformersPHP. The library will log various events such as model loading, generation progress, warnings, and errors. If no logger is set, a `NullLogger` will be used by default, which discards all log messages.
112+
113+
```php
114+
use Psr\Log\LoggerInterface;
115+
use Monolog\Logger;
116+
use Monolog\Handler\StreamHandler;
117+
118+
// Create a logger instance (example using Monolog)
119+
$logger = new Logger('transformers');
120+
$logger->pushHandler(new StreamHandler('logs/transformers.log', Logger::INFO));
121+
122+
Transformers::setup()
123+
->setLogger($logger)
124+
->apply();
125+
```
126+
108127
## Standalone PHP Projects
109128

110129
In a standalone PHP project, the best place to add global configuration is in your project's bootstrap or initialization
@@ -138,6 +157,7 @@ set the cache directory to the subdirectory of the `storage` directory, as it's
138157

139158
```php [AppServiceProvider.php]
140159
use Codewithkyrian\Transformers\Transformers;
160+
use Illuminate\Support\Facades\Log;
141161

142162
public function boot()
143163
{
@@ -147,6 +167,7 @@ public function boot()
147167
->setRemotePathTemplate('custom/path/{model}/{file}')
148168
->setAuthToken('your-token')
149169
->setUserAgent('your-user-agent')
170+
->setLogger(Log::getLogger())
150171
->apply();
151172
}
152173
```
@@ -162,15 +183,20 @@ services, making it a good place to set up global configurations.
162183

163184
```php [Kernel.php]
164185
use Codewithkyrian\Transformers\Transformers;
186+
use Psr\Log\LoggerInterface;
165187

166188
public function boot()
167189
{
190+
// Get the logger from the container
191+
$logger = $this->getContainer()->get(LoggerInterface::class);
192+
168193
Transformers::setup()
169194
->setCacheDir('/path/to/models')
170195
->setRemoteHost('https://yourmodelshost.com')
171196
->setRemotePathTemplate('custom/path/{model}/{file}')
172197
->setAuthToken('your-token')
173198
->setUserAgent('your-user-agent')
199+
->setLogger($logger)
174200
->apply();
175201
}
176202
```

examples/bootstrap.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,26 @@
44

55
use Codewithkyrian\Transformers\Transformers;
66
use Codewithkyrian\Transformers\Utils\ImageDriver;
7+
use Psr\Log\AbstractLogger;
78

89
require_once './vendor/autoload.php';
910

1011
$cacheDir = '/Volumes/KYRIAN SSD/Transformers';
1112

13+
class FileLogger extends AbstractLogger
14+
{
15+
public function __construct(protected string $filename) {}
16+
17+
public function log($level, $message, array $context = []): void
18+
{
19+
$line = sprintf("[%s][%s] %s %s\n", date('Y-m-d H:i:s'), strtoupper($level), $message, empty($context) ? '' : json_encode($context));
20+
file_put_contents($this->filename, $line, FILE_APPEND);
21+
}
22+
}
23+
24+
$logger = new FileLogger(__DIR__ . '/transformers.log');
25+
1226
Transformers::setup()
1327
->setCacheDir($cacheDir)
28+
->setLogger($logger)
1429
->setImageDriver(ImageDriver::VIPS);

examples/transformers.log

Whitespace-only changes.

src/Configs/PretrainedConfig.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use ArrayAccess;
88
use Codewithkyrian\Transformers\Utils\Hub;
99
use function Codewithkyrian\Transformers\Utils\array_pick;
10+
use Codewithkyrian\Transformers\Transformers;
1011

1112
/**
1213
* The base class that implements the common methods for loading a configuration either from a local file or directory,
@@ -40,8 +41,7 @@ public static function fromPretrained(
4041
?string $cacheDir = null,
4142
string $revision = 'main',
4243
?callable $onProgress = null
43-
): self
44-
{
44+
): self {
4545
$config ??= Hub::getJson(
4646
$modelNameOrPath,
4747
fileName: 'config.json',
@@ -50,7 +50,10 @@ public static function fromPretrained(
5050
fatal: false,
5151
onProgress: $onProgress
5252
);
53-
53+
if ($config === null) {
54+
$logger = Transformers::getLogger();
55+
$logger->warning('Config loading returned null, using fallback/defaults');
56+
}
5457
return new self($config);
5558
}
5659

src/Decoders/Decoder.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
namespace Codewithkyrian\Transformers\Decoders;
77

88
use Codewithkyrian\Transformers\Tokenizers\AddedToken;
9+
use Codewithkyrian\Transformers\Transformers;
910

1011
/**
1112
* The base class for token decoders.
@@ -35,9 +36,11 @@ public function __construct(protected array $config)
3536
*/
3637
public static function fromConfig(?array $config): ?self
3738
{
39+
$logger = Transformers::getLogger();
3840
if ($config === null) {
3941
return null;
4042
}
43+
$logger->debug('Creating decoder', ['type' => $config['type'] ?? 'unknown']);
4144

4245
return match ($config['type']) {
4346
'WordPiece' => new WordPieceDecoder($config),
@@ -83,6 +86,4 @@ public function __invoke(array $tokens): string
8386
{
8487
return $this->decode($tokens);
8588
}
86-
87-
88-
}
89+
}

src/FeatureExtractors/WhisperFeatureExtractor.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use Codewithkyrian\Transformers\Tensor\Tensor;
99
use Codewithkyrian\Transformers\Utils\Audio;
10-
use function Codewithkyrian\Transformers\Utils\timeUsage;
10+
use Codewithkyrian\Transformers\Transformers;
1111

1212
class WhisperFeatureExtractor extends FeatureExtractor
1313
{
@@ -38,9 +38,10 @@ public function __construct(array $config)
3838
public function __invoke(Tensor $waveform): array
3939
{
4040
if ($waveform->size() > $this->config['n_samples']) {
41-
trigger_error('Attempting to extract features for audio longer than 30 seconds.' .
41+
$logger = Transformers::getLogger();
42+
$logger->warning('Attempting to extract features for audio longer than 30 seconds.' .
4243
'If using a pipeline to extract transcript from a long audio clip,' .
43-
'remember to specify `chunkLengthSecs` and/or `strideLengthSecs` in the pipeline options.', E_USER_WARNING);
44+
'remember to specify `chunkLengthSecs` and/or `strideLengthSecs` in the pipeline options.');
4445

4546
$waveform = $waveform->sliceWithBounds([0], [$this->config['n_samples']]);
4647
} else if ($waveform->size() < $this->config['n_samples']) {
@@ -71,4 +72,4 @@ public function __invoke(Tensor $waveform): array
7172
'input_features' => $features->unsqueeze(0)
7273
];
7374
}
74-
}
75+
}

src/Generation/LogitsProcessors/LogitsProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ abstract class LogitsProcessor
1717
* @return Tensor The processed logits.
1818
*/
1919
abstract public function __invoke(array $inputIds, Tensor $logits): Tensor;
20-
}
20+
}

src/Generation/StoppingCriteria/MaxLengthCriteria.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,18 @@ public function __construct(protected int $maxLength, protected ?int $maxPositio
3030
*/
3131
public function __invoke(array $inputIds, array $scores): array
3232
{
33-
// return array_map(fn ($ids) => count($ids) >= $this->maxLength, $inputIds);
3433
$results = [];
3534
foreach ($inputIds as $ids) {
3635
$currentLength = count($ids);
3736
$isDone = $currentLength >= $this->maxLength;
3837

3938
if ($this->maxPositionEmbeddings !== null && !$isDone && $currentLength >= $this->maxPositionEmbeddings) {
40-
echo
39+
$logger = Transformers::getLogger();
40+
$logger->warning(
4141
"This is a friendly reminder - the current text generation call will exceed the model's predefined " .
42-
"maximum length ({$this->maxPositionEmbeddings}). Depending on the model, you may observe " .
43-
"exceptions, performance degradation, or nothing at all."
44-
;
42+
"maximum length ({$this->maxPositionEmbeddings}). Depending on the model, you may observe " .
43+
"exceptions, performance degradation, or nothing at all."
44+
);
4545
}
4646

4747
$results[] = $isDone;

0 commit comments

Comments
 (0)