103 lines
3.2 KiB
PHP
103 lines
3.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Constants\ErrorCode;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Services\LlmService;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class LlmController extends Controller
|
|
{
|
|
/**
|
|
* @var LlmService
|
|
*/
|
|
private readonly LlmService $llmService;
|
|
|
|
public function __construct(LlmService $llmService)
|
|
{
|
|
$this->llmService = $llmService;
|
|
}
|
|
|
|
/**
|
|
* 發送 LLM 請求
|
|
*
|
|
* @param Request $request
|
|
* @return JsonResponse
|
|
* @throws ValidationException|\RuntimeException
|
|
*/
|
|
public function request(Request $request): JsonResponse
|
|
{
|
|
try {
|
|
if (!$request->client) {
|
|
throw new \RuntimeException('客戶信息未找到。');
|
|
}
|
|
|
|
/** @var array{
|
|
* prompt: string,
|
|
* max_tokens?: int,
|
|
* temperature?: float,
|
|
* top_p?: float,
|
|
* frequency_penalty?: float,
|
|
* presence_penalty?: float
|
|
* } $validated */
|
|
$validated = $request->validate([
|
|
'prompt' => 'required|string|max:4000',
|
|
'max_tokens' => 'nullable|integer|min:1|max:4000',
|
|
'temperature' => 'nullable|numeric|min:0|max:2',
|
|
'top_p' => 'nullable|numeric|min:0|max:1',
|
|
'frequency_penalty' => 'nullable|numeric|min:-2|max:2',
|
|
'presence_penalty' => 'nullable|numeric|min:-2|max:2',
|
|
]);
|
|
|
|
/** @var array{response: string} $result */
|
|
$result = $this->llmService->sendRequest(
|
|
$request->client,
|
|
$validated['prompt'],
|
|
array_filter($validated, fn($key) => $key !== 'prompt', ARRAY_FILTER_USE_KEY)
|
|
);
|
|
|
|
if (!isset($result['response'])) {
|
|
throw new \RuntimeException('LLM 提供商返回的響應格式無效。');
|
|
}
|
|
|
|
return $this->success([
|
|
'response' => $result['response'],
|
|
]);
|
|
|
|
} catch (ValidationException $e) {
|
|
return $this->error(
|
|
ErrorCode::VALIDATION_ERROR,
|
|
ErrorCode::getMessage(ErrorCode::VALIDATION_ERROR),
|
|
$e->errors()
|
|
);
|
|
} catch (\InvalidArgumentException $e) {
|
|
return $this->error(
|
|
ErrorCode::INVALID_REQUEST_FORMAT,
|
|
$e->getMessage()
|
|
);
|
|
} catch (\RuntimeException $e) {
|
|
return $this->error(
|
|
ErrorCode::PROVIDER_ERROR,
|
|
$e->getMessage()
|
|
);
|
|
} catch (\Exception $e) {
|
|
Log::error('Error processing LLM request', [
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
'client_id' => $request->client->id,
|
|
'request_data' => $request->except(['prompt']),
|
|
]);
|
|
|
|
return $this->error(
|
|
ErrorCode::SERVER_ERROR,
|
|
ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
|
|
);
|
|
}
|
|
}
|
|
}
|