mirror of
https://github.com/symfony/ai-models-dev-platform.git
synced 2026-03-24 04:42:07 +01:00
134 lines
4.0 KiB
PHP
134 lines
4.0 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\AI\Platform\Bridge\ModelsDev;
|
|
|
|
use Composer\InstalledVersions;
|
|
use Symfony\AI\Platform\Exception\RuntimeException;
|
|
|
|
/**
|
|
* Loads and caches models.dev data.
|
|
*
|
|
* @internal
|
|
*
|
|
* @author Fabien Potencier <fabien@symfony.com>
|
|
*/
|
|
final class DataLoader
|
|
{
|
|
/**
|
|
* @var array<string, array<string, mixed>>|null
|
|
*/
|
|
private static ?array $cachedData = null;
|
|
|
|
private static ?string $cachedPath = null;
|
|
|
|
/**
|
|
* @return array<string, array<string, mixed>>
|
|
*/
|
|
public static function load(?string $dataPath = null): array
|
|
{
|
|
$dataPath ??= self::resolveDefaultPath();
|
|
|
|
// Return cached data if path matches
|
|
if (null !== self::$cachedData && self::$cachedPath === $dataPath) {
|
|
return self::$cachedData;
|
|
}
|
|
|
|
if (!file_exists($dataPath)) {
|
|
throw new RuntimeException(\sprintf('The models.dev data file "%s" does not exist.', $dataPath));
|
|
}
|
|
|
|
$json = file_get_contents($dataPath);
|
|
if (false === $json) {
|
|
throw new RuntimeException(\sprintf('Failed to read the models.dev data file "%s".', $dataPath));
|
|
}
|
|
|
|
$data = json_decode($json, true, flags: \JSON_THROW_ON_ERROR);
|
|
if (!\is_array($data)) {
|
|
throw new RuntimeException('Invalid models.dev API data.');
|
|
}
|
|
|
|
// Sort providers alphabetically and sort models within each provider by release date
|
|
$sortedData = self::sortData($data);
|
|
|
|
self::$cachedData = $sortedData;
|
|
self::$cachedPath = $dataPath;
|
|
|
|
return $sortedData;
|
|
}
|
|
|
|
/**
|
|
* Clear cached data (useful for testing).
|
|
*
|
|
* @internal
|
|
*/
|
|
public static function clearCache(): void
|
|
{
|
|
self::$cachedData = null;
|
|
self::$cachedPath = null;
|
|
}
|
|
|
|
/**
|
|
* Resolves the default path to the models.dev JSON file.
|
|
*
|
|
* Looks for the "symfony/models-dev" Composer package and returns
|
|
* the path to its "models-dev.json" file.
|
|
*
|
|
* @throws RuntimeException if the package is not installed
|
|
*/
|
|
private static function resolveDefaultPath(): string
|
|
{
|
|
if (class_exists(InstalledVersions::class) && InstalledVersions::isInstalled('symfony/models-dev')) {
|
|
$installPath = InstalledVersions::getInstallPath('symfony/models-dev');
|
|
|
|
if (null !== $installPath) {
|
|
return $installPath.'/models-dev.json';
|
|
}
|
|
}
|
|
|
|
throw new RuntimeException('The "models.dev" data file could not be found; either pass an explicit JSON file path or run "composer require symfony/models-dev".');
|
|
}
|
|
|
|
/**
|
|
* Sort providers alphabetically and models by release date (newest first).
|
|
*
|
|
* @param array<string, array<string, mixed>> $data
|
|
*
|
|
* @return array<string, array<string, mixed>>
|
|
*/
|
|
private static function sortData(array $data): array
|
|
{
|
|
// Sort providers alphabetically
|
|
ksort($data);
|
|
|
|
// Sort models within each provider by release date (newest first)
|
|
foreach ($data as $providerId => &$provider) {
|
|
if (isset($provider['models']) && \is_array($provider['models'])) {
|
|
// Convert models to array with keys preserved
|
|
$models = $provider['models'];
|
|
|
|
// Sort models by release_date descending
|
|
uasort($models, static function ($a, $b) {
|
|
$dateA = $a['release_date'] ?? '1970-01-01';
|
|
$dateB = $b['release_date'] ?? '1970-01-01';
|
|
|
|
// Compare dates in descending order (newer dates first)
|
|
return strcmp($dateB, $dateA);
|
|
});
|
|
|
|
$provider['models'] = $models;
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
}
|