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