"user", "content" => ChartPromptTemplate::generatePrompt( datasetJson: json_encode($request->chartData ?? []), userQuery: $request->userMessage ?? '', convertTime: $request->convertTime ?? true, ), ] ]; try { $response = $this->callLLMApi($contents); if (!$response['success']) { return response()->json([ 'error' => 'Failed to get AI response', 'details' => $response['error'] ], 500); } // Clean and format the markdown response $cleanedMarkdown = $this->cleanMarkdownResponse($response['text']); return response()->json([ 'success' => true, 'markdown' => $cleanedMarkdown, 'raw_text' => $response['text'] // Optional: for debugging ]); } catch (\Exception $e) { Log::error('ChatController error:', [ 'message' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return response()->json([ 'error' => 'Internal server error', 'message' => 'Unable to process your request' ], 500); } } private function callLLMApi(array $contents): string|array { $apiKey = env('VITE_GROQ_API_KEY'); if (!$apiKey) { throw new \Exception('API key not configured'); } $url = "https://api.groq.com/openai/v1/chat/completions"; $model = "deepseek-r1-distill-llama-70b"; $response = Http::withHeaders([ 'Authorization' => "Bearer {$apiKey}", 'Content-Type' => 'application/json', ])->post($url, [ 'model' => $model, 'messages' => $contents, 'temperature' => 0.5, 'max_tokens' => 8000, ]); if ($response->failed()) { return [ 'success' => false, 'error' => 'API request failed: ' . $response->status() . ' - ' . $response->body() ]; } $responseData = $response->json(); if (!isset($responseData['choices'][0]['message']['content'])) { return [ 'success' => false, 'error' => 'Invalid API response format' ]; } return [ 'success' => true, 'text' => $this->removeThinkingSteps($responseData['choices'][0]['message']['content']), ]; } private function cleanMarkdownResponse(string $text): string { // Remove any leading/trailing whitespace $text = trim($text); // Remove markdown code block wrappers if present $text = preg_replace('/^```(?:markdown)?\s*\n/', '', $text); $text = preg_replace('/\n```\s*$/', '', $text); // Ensure proper spacing after headings $text = preg_replace('/^(#{1,4}\s+.*?)$/m', '$1' . "\n", $text); // Clean up excessive line breaks (more than 2 in a row) $text = preg_replace('/\n{3,}/', "\n\n", $text); return trim($text); } protected function removeThinkingSteps($content): string { // Remove common thinking patterns $patterns = [ '/^.*?<\/thinking>\s*/s', '/^.*?<\/think>\s*/s', '/^Let me think.*?\n\n/s', '/^I need to.*?\n\n/s', '/^First, let me.*?\n\n/s', '/^To answer this.*?\n\n/s', ]; foreach ($patterns as $pattern) { $content = preg_replace($pattern, '', $content); } return trim($content); } } ?>