ollama = $ollama ?? AIConfig::fromCredentialsFile()->createOllamaService(); } /** * Validate chat response quality. * * @param string $question Original question * @param string $answer LLM response * @param array $sources Used sources * @param string|null $structureName Applied structure (if any) * * @return array{passed: bool, score: float, issues: array, details: string} */ public function validate( string $question, string $answer, array $sources = [], ?string $structureName = null ): array { $prompt = $this->buildValidationPrompt($question, $answer, $sources, $structureName); try { $response = $this->ollama->generate($prompt, 'mistral', 0.1); $parsed = $this->parseResponse($response); return $parsed; } catch (\Exception $e) { return [ 'passed' => true, 'score' => 0.0, 'issues' => ['Validierung fehlgeschlagen: ' . $e->getMessage()], 'details' => 'Validierung konnte nicht durchgeführt werden.', ]; } } /** * Build validation prompt. */ private function buildValidationPrompt( string $question, string $answer, array $sources, ?string $structureName ): string { $sourceList = ''; if ($sources !== []) { $titles = array_map(fn ($s) => $s['title'] ?? 'Unbekannt', $sources); $sourceList = 'Verwendete Quellen: ' . implode(', ', $titles); } $structureInfo = $structureName !== null ? "Erwartetes Format: {$structureName}" : 'Kein spezifisches Format erwartet'; return <<= 70 PROMPT; } /** * Parse validation response. * * @return array{passed: bool, score: float, issues: array, details: string} */ private function parseResponse(string $response): array { // Try to extract JSON if (preg_match('/\{[\s\S]*\}/', $response, $matches)) { $decoded = json_decode($matches[0], true); if (is_array($decoded)) { return [ 'passed' => (bool) ($decoded['passed'] ?? ($decoded['score'] ?? 0) >= 70), 'score' => (float) ($decoded['score'] ?? 0), 'issues' => is_array($decoded['issues'] ?? null) ? $decoded['issues'] : [], 'details' => (string) ($decoded['summary'] ?? 'Keine Details'), ]; } } // Fallback for non-JSON responses return [ 'passed' => true, 'score' => 75.0, 'issues' => [], 'details' => 'Validierung abgeschlossen.', ]; } }