Skip to content

Decouple response generation from bias assessment: add SelfEval class for user-provided responses (no LangChain dependency) #239

Description

@mohitcek

Is your feature request related to a problem? Please describe.
AutoEval couples response generation to metric computation: it requires a LangChain chat model (langchain_llm) and calls it internally to generate responses and counterfactual responses. This is frustrating when:

  • The generation stack isn't LangChain (direct provider SDKs, internal API gateways, batch/offline pipelines) — using AutoEval means wrapping that stack in a LangChain-compatible object just to reuse the orchestration.
  • Responses already exist (e.g., collected from production). AutoEval accepts responses=, but still needs a live LLM whenever prompts contain protected attribute words, because the counterfactual responses cannot be supplied through the public API.
  • Generation and evaluation happen in different environments (e.g., generation behind a governed gateway, evaluation on a separate machine), and there is no clean hand-off between the two steps.

The underlying metric classes (ToxicityMetrics, StereotypeMetrics, CounterfactualMetrics) are already LLM-free — only the convenience orchestration forces the LangChain dependency.

Describe the solution you'd like
A SelfEval class in langfair.auto that splits the AutoEval workflow into two explicit phases, with generation delegated to the user:

  1. Prompt preparation (no LLM): the user provides prompts; on construction, SelfEval runs the fairness-through-unawareness (FTU) check and creates counterfactual prompt variants for any protected attribute (gender, race) found. get_prompts() returns a flat, ordered list of every prompt requiring a response — each prompt repeated count times (default 25), originals first, then one block per counterfactual group. A prompt_manifest property documents the segment layout.
  2. Generation (user-side): the user generates exactly one response per element of get_prompts(), in order, with any stack, inserting "Unable to get response" for failed generations.
  3. Metric computation (no LLM): evaluate(responses=...) — synchronous, no await — validates the length/order contract (with a per-segment breakdown on mismatch) and computes the same toxicity, stereotype, and counterfactual metrics as AutoEval.evaluate, including print_results() / export_results().

Pre-existing responses should also be supported at construction (parity with AutoEval's responses= parameter), in which case get_prompts() returns only the counterfactual variants still requiring generation.

To keep the two classes in sync, the shared logic (FTU check, metric steps, results assembly, print/export) should be factored into a common base class, leaving AutoEval's public API unchanged. A demo notebook should illustrate the file-based hand-off (prompts.jsonrequired_prompts.json → user-generated responses.json → metrics).

Describe alternatives you've considered

  • Wrapping a custom stack in a LangChain BaseChatModel to satisfy AutoEval: forces a LangChain dependency and async plumbing on users whose stacks are not LangChain-based, just to reuse orchestration.
  • Using AutoEval(responses=...): avoids generation for original prompts only; the counterfactual generation step still requires a live LLM whenever FTU is not satisfied.
  • Calling the metric classes and CounterfactualGenerator.parse_texts/create_prompts directly: possible today, but users must reimplement AutoEval's orchestration themselves (FTU handling, count expansion, group pairing, failure filtering, results assembly), which is error-prone and duplicated across teams.

Additional context

  • Metric computation in AutoEval is already fully LLM-free; the LLM is only needed for generation, so there is a clean seam for this separation.
  • The count=25 default follows the established convention for toxicity evaluation (DecodingTrust, https://arxiv.org/abs/2306.11698; Gehman et al., 2020, https://aclanthology.org/2020.findings-emnlp.301/).
  • An implementation of this proposal is available on branch mc/selfeval (PR to follow).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions