<?php
namespace App\AI\SymfonyAiExtend\Processor; use Symfony\AI\Agent\Input; use Symfony\AI\Agent\InputProcessorInterface; use Symfony\AI\Agent\Output; use Symfony\AI\Agent\OutputProcessorInterface; use App\AI\SymfonyAiExtend\Claude\ModelCatalog as ClaudeModelCatalog; use App\AI\SymfonyAiExtend\Gemini\ModelCatalog as GeminiModelCatalog; use App\AI\SymfonyAiExtend\OpenAi\ModelCatalog as OpenAiModelCatalog; class DatabaseProcessor implements InputProcessorInterface, OutputProcessorInterface { private $idRequest; private $requestStartTime; public function __construct( private readonly int $idTopic, private readonly string $usermessage, private readonly string $type = 'main', ) { } public function processInput(Input $input): void { $options = $input->getOptions(); $bodyStr = json_encode($options, JSON_PRETTY_PRINT); \DB::startTransaction(); if ($this->type=='router' && $this->idTopic) { $msgEnt = \Entity\AiChatMessage::insert(); $msgEnt->idTopic = $this->idTopic; $msgEnt->message = $this->usermessage; $msgEnt->role = 'user'; $msgEnt->save(); } $reqEnt = \Entity\AiChatRequest::insert(); if (APP_VERSION_BUILD>=5688) { if (str_starts_with($input->getModel(), 'gpt-')) { $reqEnt->platform = 'openai'; } elseif (str_starts_with($input->getModel(), 'claude-')) { $reqEnt->platform = 'anthropic'; } elseif (str_starts_with($input->getModel(), 'gemini-')) { $reqEnt->platform = 'gemini'; } $reqEnt->model = $input->getModel(); } $reqEnt->idTopic = $this->idTopic; $reqEnt->request = $bodyStr; $reqEnt->type = $this->type; $reqEnt->save(); \DB::commitTransaction(); $this->idRequest = $reqEnt->getId(); $this->requestStartTime = microtime(true); } public function processOutput(Output $output): void { $response = $output->getResult()->getRawResult()->getData(); $bodyStr = json_encode($response, JSON_PRETTY_PRINT); $userResponses = []; $inputTokens = $cachedTokens = $outputTokens = 0; if (str_starts_with($output->getModel(), 'gpt-')) { if ($response && $response['output']) { foreach ($response['output'] as $message) { if ($message['type'] == 'message') { foreach ($message['content'] as $content) { if ($content['type']=='output_text' && $content['text']) { $userResponses[] = $content['text']; } } } } } $inputTokens = (int)$response['usage']['input_tokens']; $cachedTokens = (int)$response['usage']['input_tokens_details']['cached_tokens']; $outputTokens = (int)$response['usage']['output_tokens']; $cost = OpenAiModelCatalog::calculateCost($output->getModel(), $inputTokens-$cachedTokens, $outputTokens, $cachedTokens); } elseif (str_starts_with($output->getModel(), 'claude-')) { if ($response && $response['type']=='message' && $response['content']) { foreach ($response['content'] as $content) { if ($content['type']=='text' && $content['text']) { $userResponses[] = $content['text']; } } } $inputTokens = (int)$response['usage']['input_tokens'] + (int)$response['usage']['cache_creation_input_tokens'] + (int)$response['usage']['cache_read_input_tokens']; $cachedTokens = (int)$response['usage']['cache_creation_input_tokens'] + (int)$response['usage']['cache_read_input_tokens']; $outputTokens = (int)$response['usage']['output_tokens']; $cost = ClaudeModelCatalog::calculateCost($output->getModel(), $inputTokens-$cachedTokens, $outputTokens, $cachedTokens); } elseif (str_starts_with($output->getModel(), 'gemini-')) { if ($response && $response['status']=='completed' && $response['steps']) { foreach ($response['steps'] as $step) { if ($step['type'] == 'model_output') { foreach ($step['content'] as $content) { if ($content['type']=='text' && $content['text']) { $userResponses[] = $content['text']; } } } } } $inputTokens = (int)$response['usage']['total_input_tokens']; $cachedTokens = (int)$response['usage']['total_cached_tokens']; $outputTokens = (int)$response['usage']['total_output_tokens']; $cost = GeminiModelCatalog::calculateCost($output->getModel(), $inputTokens-$cachedTokens, $outputTokens, $cachedTokens); } \DB::startTransaction(); $respEnt = \Entity\AiChatRequest::update($this->idRequest); $respEnt->response = $bodyStr; $respEnt->duration = microtime(true) - $this->requestStartTime; if (!$response['error']) { $respEnt->inputTokens = $inputTokens; $respEnt->outputTokens = $outputTokens; if (APP_VERSION_BUILD>=5688) { $respEnt->cachedTokens = $cachedTokens; } if (APP_VERSION_BUILD>=5688) { } } $respEnt->save(); if ($this->type=='main' && $this->idTopic) { foreach ($userResponses as $text) { $msgEnt = \Entity\AiChatMessage::insert(); $msgEnt->idTopic = $this->idTopic; $msgEnt->role = 'assistant'; $msgEnt->message = $text; $msgEnt->save(); } } \DB::commitTransaction(); } }