move controller service logics into a service

This commit is contained in:
team2
2026-02-27 20:19:03 +01:00
parent 8096ac0de9
commit bd3dd6e659
2 changed files with 119 additions and 61 deletions

View File

@@ -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');
} }

View 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);
}
}