import { MetadataMode } from "../Node.js";
import { llmFromSettingsOrContext } from "../Settings.js";
import { extractText } from "../llm/utils.js";
import { PromptMixin } from "../prompts/Mixin.js";
import { defaultCorrectnessSystemPrompt, defaultUserPrompt } from "./prompts.js";
import { defaultEvaluationParser } from "./utils.js";
/** Correctness Evaluator */ export class CorrectnessEvaluator extends PromptMixin {
    scoreThreshold;
    parserFunction;
    llm;
    correctnessPrompt = defaultCorrectnessSystemPrompt;
    constructor(params){
        super();
        this.llm = llmFromSettingsOrContext(params?.serviceContext);
        this.correctnessPrompt = defaultCorrectnessSystemPrompt;
        this.scoreThreshold = params?.scoreThreshold ?? 4.0;
        this.parserFunction = params?.parserFunction ?? defaultEvaluationParser;
    }
    _updatePrompts(prompts) {
        if ("correctnessPrompt" in prompts) {
            this.correctnessPrompt = prompts["correctnessPrompt"];
        }
    }
    /**
   *
   * @param query Query to evaluate
   * @param response  Response to evaluate
   * @param contexts Array of contexts
   * @param reference  Reference response
   */ async evaluate({ query, response, contexts, reference }) {
        if (query === null || response === null) {
            throw new Error("query, and response must be provided");
        }
        const messages = [
            {
                role: "system",
                content: this.correctnessPrompt()
            },
            {
                role: "user",
                content: defaultUserPrompt({
                    query,
                    generatedAnswer: response,
                    referenceAnswer: reference || "(NO REFERENCE ANSWER SUPPLIED)"
                })
            }
        ];
        const evalResponse = await this.llm.chat({
            messages
        });
        const [score, reasoning] = this.parserFunction(extractText(evalResponse.message.content));
        return {
            query: query,
            response: response,
            passing: score >= this.scoreThreshold || score === null,
            score: score,
            feedback: reasoning
        };
    }
    /**
   * @param query Query to evaluate
   * @param response  Response to evaluate
   */ async evaluateResponse({ query, response }) {
        const responseStr = response?.response;
        const contexts = [];
        if (response) {
            for (const node of response.sourceNodes || []){
                contexts.push(node.node.getContent(MetadataMode.ALL));
            }
        }
        return this.evaluate({
            query,
            response: responseStr,
            contexts
        });
    }
}
