def generate_score_and_reasons(
        self,
        system_prompt: str,
        user_prompt: Optional[str] = None,
        min_score_val: int = 0,
        max_score_val: int = 10,
        temperature: float = 0.0,
    ) -> Tuple[float, Dict]:
        """
        Base method to generate a score and reason, used for evaluation.

        Args:
            system_prompt: A pre-formatted system prompt.

            user_prompt: An optional user prompt. Defaults to None.

            min_score_val: The minimum score value.

            max_score_val: The maximum score value.

            temperature: The temperature for the LLM response.

        Returns:
            The score on a 0-1 scale.

            Reason metadata if returned by the LLM.
        """
        assert self.endpoint is not None, "Endpoint is not set."
        assert (
            max_score_val > min_score_val
        ), "Max score must be greater than min score."

        llm_messages = [{"role": "system", "content": system_prompt}]
        if user_prompt is not None:
            llm_messages.append({"role": "user", "content": user_prompt})
        response = self.endpoint.run_in_pace(
            func=self._create_chat_completion,
            messages=llm_messages,
            temperature=temperature,
        )
        if "Supporting Evidence" in response:
            score = -1
            supporting_evidence = None
            criteria = None
            lines = response.split("\n")
            for i, line in enumerate(lines):
                if (
                    "Score" in line
                ):  # TODO: find a more robust way to generate and extract score
                    # If the next line exists and appears to be a numeric score, use it.
                    if (
                        i + 1 < len(lines)
                        and lines[i + 1].strip().replace(".", "", 1).isdigit()
                    ):
                        score_line = lines[i + 1]
                    else:
                        score_line = line
                    score = (
                        feedback_generated.re_configured_rating(
                            score_line,
                            min_score_val=min_score_val,
                            max_score_val=max_score_val,
                        )
                        - min_score_val
                    ) / (max_score_val - min_score_val)
                criteria_lines = []
                supporting_evidence_lines = []
                collecting_criteria = False
                collecting_evidence = False

                for line in response.split("\n"):
                    if "Criteria:" in line:
                        criteria_lines.append(
                            line.split("Criteria:", 1)[1].strip()
                        )
                        collecting_criteria = True
                        collecting_evidence = False
                    elif "Supporting Evidence:" in line:
                        supporting_evidence_lines.append(
                            line.split("Supporting Evidence:", 1)[1].strip()
                        )
                        collecting_evidence = True
                        collecting_criteria = False
                    elif collecting_criteria:
                        if "Supporting Evidence:" not in line:
                            criteria_lines.append(line.strip())
                        else:
                            collecting_criteria = False
                    elif collecting_evidence:
                        if "Criteria:" not in line:
                            supporting_evidence_lines.append(line.strip())
                        else:
                            collecting_evidence = False

                criteria = "\n".join(criteria_lines).strip()
                supporting_evidence = "\n".join(
                    supporting_evidence_lines
                ).strip()
            reasons = {
                "reason": (
                    f"{'Criteria: ' + str(criteria)}\n"
                    f"{'Supporting Evidence: ' + str(supporting_evidence)}"
                )
            }
            return score, reasons

        else:
            score = (
                feedback_generated.re_configured_rating(
                    response,
                    min_score_val=min_score_val,
                    max_score_val=max_score_val,
                )
                - min_score_val
            ) / (max_score_val - min_score_val)
            warnings.warn(
                "No supporting evidence provided. Returning score only.",
                UserWarning,
            )
            return score, {}

        Base method to generate a score and reason, used for evaluation.

        Args:
            system_prompt: A pre-formatted system prompt.

            user_prompt: An optional user prompt. Defaults to None.

            min_score_val: The minimum score value.

            max_score_val: The maximum score value.

            temperature: The temperature for the LLM response.

        Returns:
            The score on a 0-1 scale.

            Reason metadata if returned by the LLM.
        
src/feedback/trulens/feedback/llm_provider.py