move controller service logics into a service
This commit is contained in:
@@ -5,101 +5,72 @@ declare(strict_types=1);
|
|||||||
namespace App\Controller\Admin;
|
namespace App\Controller\Admin;
|
||||||
|
|
||||||
use App\Entity\ModelGenerationConfig;
|
use App\Entity\ModelGenerationConfig;
|
||||||
use App\Knowledge\Retrieval\NdjsonHybridRetriever;
|
use App\Service\Admin\ModelGenerationConfigAdminService;
|
||||||
use App\Repository\ModelGenerationConfigRepository;
|
|
||||||
use App\Service\ModelGenerationConfigManager;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
|
||||||
#[Route('/admin/model-config')]
|
#[Route('/admin/model-config')]
|
||||||
class ModelGenerationConfigController extends AbstractController
|
final class ModelGenerationConfigController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/', name: 'admin_model_config_list')]
|
#[Route('/', name: 'admin_model_config_list')]
|
||||||
public function list(ModelGenerationConfigRepository $repository): Response
|
public function list(ModelGenerationConfigAdminService $svc): Response
|
||||||
{
|
{
|
||||||
$this->denyAccessUnlessGranted('ROLE_KNOWLEDGE_ADMIN');
|
$this->denyAccessUnlessGranted('ROLE_KNOWLEDGE_ADMIN');
|
||||||
|
|
||||||
$configs = $repository->findBy(
|
|
||||||
[],
|
|
||||||
['active' => 'DESC', 'modelName' => 'ASC', 'version' => 'DESC']
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->render('admin/model_config/list.html.twig', [
|
return $this->render('admin/model_config/list.html.twig', [
|
||||||
'configs' => $configs,
|
'configs' => $svc->list(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/create', name: 'admin_model_config_create')]
|
#[Route('/create', name: 'admin_model_config_create', methods: ['GET', 'POST'])]
|
||||||
public function create(
|
public function create(
|
||||||
Request $request,
|
Request $request,
|
||||||
EntityManagerInterface $em,
|
ModelGenerationConfigAdminService $svc
|
||||||
ModelGenerationConfigRepository $repository
|
|
||||||
): Response {
|
): Response {
|
||||||
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
||||||
|
|
||||||
if ($request->isMethod('POST')) {
|
if ($request->isMethod('POST')) {
|
||||||
|
try {
|
||||||
$modelName = (string) $request->request->get('model_name');
|
$svc->create($request->request->all());
|
||||||
$version = $repository->findNextVersion($modelName);
|
$this->addFlash('success', 'Konfiguration erstellt.');
|
||||||
|
|
||||||
$retrievalMaxChunks = (int) $request->request->get('retrieval_max_chunks', 25);
|
|
||||||
$retrievalVectorTopK = (int) $request->request->get('retrieval_vector_top_k', 25);
|
|
||||||
|
|
||||||
$config = new ModelGenerationConfig(
|
|
||||||
modelName: $modelName,
|
|
||||||
version: $version,
|
|
||||||
stream: (bool) $request->request->get('stream'),
|
|
||||||
temperature: (float) $request->request->get('temperature'),
|
|
||||||
topK: (int) $request->request->get('top_k'),
|
|
||||||
topP: (float) $request->request->get('top_p'),
|
|
||||||
repeatPenalty: (float) $request->request->get('repeat_penalty'),
|
|
||||||
numCtx: (int) $request->request->get('num_ctx'),
|
|
||||||
active: false,
|
|
||||||
retrievalMaxChunks: $retrievalMaxChunks,
|
|
||||||
retrievalVectorTopK: $retrievalVectorTopK
|
|
||||||
);
|
|
||||||
|
|
||||||
$em->persist($config);
|
|
||||||
$em->flush();
|
|
||||||
|
|
||||||
return $this->redirectToRoute('admin_model_config_list');
|
return $this->redirectToRoute('admin_model_config_list');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->addFlash('danger', $e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('admin/model_config/create.html.twig');
|
return $this->render('admin/model_config/create.html.twig');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}/activate', name: 'admin_model_config_activate')]
|
#[Route('/{id}/activate', name: 'admin_model_config_activate', methods: ['POST'])]
|
||||||
public function activate(
|
public function activate(
|
||||||
ModelGenerationConfig $config,
|
ModelGenerationConfig $config,
|
||||||
ModelGenerationConfigManager $manager
|
ModelGenerationConfigAdminService $svc
|
||||||
): Response {
|
): Response {
|
||||||
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
||||||
|
|
||||||
$manager->activate($config);
|
$svc->activate($config);
|
||||||
|
|
||||||
return $this->redirectToRoute('admin_model_config_list');
|
return $this->redirectToRoute('admin_model_config_list');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}/test-retrieval', name: 'admin_model_config_test_retrieval')]
|
#[Route('/{id}/test-retrieval', name: 'admin_model_config_test_retrieval', methods: ['GET', 'POST'])]
|
||||||
public function testRetrieval(
|
public function testRetrieval(
|
||||||
ModelGenerationConfig $config,
|
ModelGenerationConfig $config,
|
||||||
Request $request,
|
Request $request,
|
||||||
NdjsonHybridRetriever $retriever
|
ModelGenerationConfigAdminService $svc
|
||||||
): Response {
|
): Response {
|
||||||
$this->denyAccessUnlessGranted('ROLE_KNOWLEDGE_ADMIN');
|
$this->denyAccessUnlessGranted('ROLE_KNOWLEDGE_ADMIN');
|
||||||
|
|
||||||
$results = [];
|
|
||||||
$prompt = '';
|
$prompt = '';
|
||||||
|
$results = [];
|
||||||
|
|
||||||
if ($request->isMethod('POST')) {
|
if ($request->isMethod('POST')) {
|
||||||
$prompt = trim((string)$request->request->get('prompt'));
|
$prompt = trim((string)$request->request->get('prompt'));
|
||||||
|
$results = $svc->testRetrieval($config, $prompt);
|
||||||
if ($prompt !== '') {
|
|
||||||
$results = $retriever->retrieveInternal($prompt, $config);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->render('admin/model_config/test_retrieval.html.twig', [
|
return $this->render('admin/model_config/test_retrieval.html.twig', [
|
||||||
@@ -113,23 +84,23 @@ class ModelGenerationConfigController extends AbstractController
|
|||||||
public function delete(
|
public function delete(
|
||||||
ModelGenerationConfig $config,
|
ModelGenerationConfig $config,
|
||||||
Request $request,
|
Request $request,
|
||||||
EntityManagerInterface $em
|
ModelGenerationConfigAdminService $svc
|
||||||
): Response {
|
): Response {
|
||||||
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
$this->denyAccessUnlessGranted('ROLE_SUPER_ADMIN');
|
||||||
|
|
||||||
if ($config->isActive()) {
|
if (!$this->isCsrfTokenValid(
|
||||||
$this->addFlash('danger', 'Aktive Konfiguration kann nicht gelöscht werden.');
|
'delete_model_config_'.$config->getId(),
|
||||||
return $this->redirectToRoute('admin_model_config_list');
|
$request->request->get('_token')
|
||||||
|
)) {
|
||||||
|
throw $this->createAccessDeniedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->isCsrfTokenValid('delete_model_config_'.$config->getId(), $request->request->get('_token'))) {
|
try {
|
||||||
throw $this->createAccessDeniedException('Invalid CSRF token.');
|
$svc->delete($config);
|
||||||
}
|
|
||||||
|
|
||||||
$em->remove($config);
|
|
||||||
$em->flush();
|
|
||||||
|
|
||||||
$this->addFlash('success', 'Konfiguration gelöscht.');
|
$this->addFlash('success', 'Konfiguration gelöscht.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->addFlash('danger', $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
return $this->redirectToRoute('admin_model_config_list');
|
return $this->redirectToRoute('admin_model_config_list');
|
||||||
}
|
}
|
||||||
|
|||||||
87
src/Service/Admin/ModelGenerationConfigAdminService.php
Normal file
87
src/Service/Admin/ModelGenerationConfigAdminService.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service\Admin;
|
||||||
|
|
||||||
|
use App\Entity\ModelGenerationConfig;
|
||||||
|
use App\Knowledge\Retrieval\NdjsonHybridRetriever;
|
||||||
|
use App\Repository\ModelGenerationConfigRepository;
|
||||||
|
use App\Service\ModelGenerationConfigManager;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
final class ModelGenerationConfigAdminService
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly ModelGenerationConfigRepository $repository,
|
||||||
|
private readonly EntityManagerInterface $em,
|
||||||
|
private readonly ModelGenerationConfigManager $manager,
|
||||||
|
private readonly NdjsonHybridRetriever $retriever,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function list(): array
|
||||||
|
{
|
||||||
|
return $this->repository->findBy(
|
||||||
|
[],
|
||||||
|
['active' => 'DESC', 'modelName' => 'ASC', 'version' => 'DESC']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(array $data): ModelGenerationConfig
|
||||||
|
{
|
||||||
|
$modelName = $this->requireString($data['model_name'] ?? null, 'model_name');
|
||||||
|
|
||||||
|
$version = $this->repository->findNextVersion($modelName);
|
||||||
|
|
||||||
|
$config = new ModelGenerationConfig(
|
||||||
|
modelName: $modelName,
|
||||||
|
version: $version,
|
||||||
|
stream: (bool)($data['stream'] ?? false),
|
||||||
|
temperature: (float)($data['temperature'] ?? 0.7),
|
||||||
|
topK: (int)($data['top_k'] ?? 40),
|
||||||
|
topP: (float)($data['top_p'] ?? 0.9),
|
||||||
|
repeatPenalty: (float)($data['repeat_penalty'] ?? 1.1),
|
||||||
|
numCtx: (int)($data['num_ctx'] ?? 4096),
|
||||||
|
active: false,
|
||||||
|
retrievalMaxChunks: (int)($data['retrieval_max_chunks'] ?? 25),
|
||||||
|
retrievalVectorTopK: (int)($data['retrieval_vector_top_k'] ?? 25),
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->em->persist($config);
|
||||||
|
$this->em->flush();
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function activate(ModelGenerationConfig $config): void
|
||||||
|
{
|
||||||
|
$this->manager->activate($config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(ModelGenerationConfig $config): void
|
||||||
|
{
|
||||||
|
if ($config->isActive()) {
|
||||||
|
throw new \RuntimeException('Aktive Konfiguration kann nicht gelöscht werden.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->em->remove($config);
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRetrieval(ModelGenerationConfig $config, string $prompt): array
|
||||||
|
{
|
||||||
|
if (trim($prompt) === '') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->retriever->retrieveInternal($prompt, $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function requireString(mixed $value, string $field): string
|
||||||
|
{
|
||||||
|
if (!is_string($value) || trim($value) === '') {
|
||||||
|
throw new \InvalidArgumentException("Invalid value for {$field}");
|
||||||
|
}
|
||||||
|
return trim($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user