- Created `quick-replies.blade.php` for managing quick replies. - Added `settings.blade.php` for admin settings management. - Implemented `ticket-show.blade.php` to display ticket details. - Introduced `timeline-card.blade.php` component for displaying timeline information. Enhance quick reply management functionality - Developed `quick-reply-manager.blade.php` for creating and editing quick replies. - Integrated Livewire for dynamic interaction and validation. Implement settings page for AI configuration - Created `settings-page.blade.php` for managing AI settings, including prompts and provider instances. - Added functionality for managing models and embeddings. Add ticket show functionality with real-time updates - Implemented ticket details view with processing status and tool call logs. - Added support for displaying article suggestions and error messages. Create unit tests for AI classifier and domain info tool - Added `AIClassifierServiceTest.php` to validate AI classifier functionality. - Implemented `DomainInfoToolTest.php` for domain parameter validation. - Created `OxxaClientTest.php` to test API interactions and password hashing.
82 lines
2.1 KiB
PHP
82 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
class LlmModelCatalogService
|
|
{
|
|
public function modelsFor(array $instance, bool $refresh = false): array
|
|
{
|
|
$cacheKey = 'llm_models_'.sha1(json_encode([
|
|
'type' => $instance['type'] ?? '',
|
|
'base_url' => $instance['base_url'] ?? '',
|
|
]));
|
|
|
|
if ($refresh) {
|
|
Cache::forget($cacheKey);
|
|
}
|
|
|
|
return Cache::remember($cacheKey, now()->addMinutes(5), fn () => $this->fetchModels($instance));
|
|
}
|
|
|
|
public function cachedUntil(array $instance): ?string
|
|
{
|
|
$models = $this->modelsFor($instance);
|
|
|
|
return $models === [] ? null : now()->addMinutes(5)->format('H:i:s');
|
|
}
|
|
|
|
private function fetchModels(array $instance): array
|
|
{
|
|
$type = (string) ($instance['type'] ?? '');
|
|
$baseUrl = rtrim((string) ($instance['base_url'] ?? ''), '/');
|
|
|
|
if ($baseUrl === '') {
|
|
return [];
|
|
}
|
|
|
|
return match ($type) {
|
|
'lmstudio' => $this->fetchLmStudioModels($baseUrl),
|
|
'ollama' => $this->fetchOllamaModels($baseUrl),
|
|
default => [],
|
|
};
|
|
}
|
|
|
|
private function fetchLmStudioModels(string $baseUrl): array
|
|
{
|
|
$response = Http::connectTimeout(2)
|
|
->timeout(5)
|
|
->get($baseUrl.'/v1/models')
|
|
->throw()
|
|
->json();
|
|
|
|
return collect($response['data'] ?? [])
|
|
->pluck('id')
|
|
->filter()
|
|
->map(fn ($model) => (string) $model)
|
|
->unique()
|
|
->sort()
|
|
->values()
|
|
->all();
|
|
}
|
|
|
|
private function fetchOllamaModels(string $baseUrl): array
|
|
{
|
|
$response = Http::connectTimeout(2)
|
|
->timeout(5)
|
|
->get($baseUrl.'/api/tags')
|
|
->throw()
|
|
->json();
|
|
|
|
return collect($response['models'] ?? [])
|
|
->map(fn ($model) => (string) ($model['name'] ?? $model['model'] ?? ''))
|
|
->filter()
|
|
->unique()
|
|
->sort()
|
|
->values()
|
|
->all();
|
|
}
|
|
}
|