Skip to content

Conversational Flow Rate

The Conversational Flow Rate metric grades how natural and coherent a multi-turn dialogue is. It penalizes unnecessary clarifications, redundant questions, ignored user signals, and irrelevant tangents.

How It Works

A single holistic LLM call grades the dialogue as a whole against a few-shot rubric and returns one verdict on the 5-level scale (fully/mostly/partial/minor/none).

Flow is judged as a property of the entire sequence, not an average of per-turn scores. A single severely broken turn that derails the rest of the conversation pulls the verdict down even if other turns are fine. Later turns are weighted more heavily than earlier ones when they diverge — the end state matters most.

The rubric explicitly considers whether the assistant:

  • directly addresses user signals,
  • avoids redundant clarifications,
  • stays coherent with prior turns,
  • and avoids irrelevant tangents.

The verdict maps to a score:

Verdict Score
fully 1.0
mostly 0.9
partial 0.7
minor 0.3
none 0.0

Parameters

Parameter Type Default Description
model str required LLM model ("gpt-4o", "anthropic:claude-3-5-sonnet-latest", "google:gemini-2.0-flash", "ollama:llama3", or CustomLLMClient)
threshold float 0.7 Minimum score to pass
verbose bool False Enable colored console output

Required Fields

Works only with ConversationalEvalTestCase.

Field Required
turns (each with input and actual_output) Yes

Usage

from eval_lib import (
    ConversationalFlowRateMetric,
    ConversationalEvalTestCase,
    EvalTestCase,
    evaluate_conversations,
)
import asyncio

metric = ConversationalFlowRateMetric(model="gpt-4o", threshold=0.7)

conversation = ConversationalEvalTestCase(
    turns=[
        EvalTestCase(
            input="I need to reset my password",
            actual_output="I can help. Please confirm the email associated with your account.",
        ),
        EvalTestCase(
            input="user@example.com",
            actual_output="Password reset link sent to user@example.com. Check your inbox.",
        ),
    ]
)

results = asyncio.run(evaluate_conversations([conversation], [metric]))

Cost

1 LLM API call per evaluation.

Tips

  • Pair with Repetitive Pattern Detection to catch loops that also count as broken flow, but for different reasons.
  • Inspect evaluation_log["key_issues"] — the holistic verdict comes with a list of the main problems the LLM identified, which is usually where you should start fixing the agent.
  • Because the verdict is holistic, a single severely broken turn is enough to drop the score to none; use this metric when you want to catch catastrophic flow breakdowns rather than measure average turn quality.