Skip to content

feat: add opt-in verbose_logs to surface GEval judge criteria, steps,… - #301

Open
x86girl wants to merge 1 commit into
lightspeed-core:mainfrom
x86girl:prgutier/g-eval/rubrics
Open

feat: add opt-in verbose_logs to surface GEval judge criteria, steps,…#301
x86girl wants to merge 1 commit into
lightspeed-core:mainfrom
x86girl:prgutier/g-eval/rubrics

Conversation

@x86girl

@x86girl x86girl commented Jul 29, 2026

Copy link
Copy Markdown

Currently, lightspeed-evaluation does not report when creating rubrics using a Judge (LLM).
For correctness or consistency, for example, it asks the judge to define the steps to get this rubric, and lightspeed-evaluation is
not reporting anywhere how it has been done.
This PR create a new opt-in verbose_logs arg to surface GEval judge criteria, steps, and rubrics.

Summary by CodeRabbit

  • New Features

    • Added optional verbose logging for GEval evaluations.
    • Verbose logs can be enabled in metric configuration and are included in evaluation results and CSV/JSON exports.
    • Verbose logs are supported for both turn-level and conversation-level evaluations.
  • Tests

    • Added coverage for configuration, capture, reset behavior, result propagation, and serialization of verbose logs.

… and rubrics

GEval metrics ask the judge LLM to generate evaluation steps and rubrics
internally, but these were never exposed in the output — making it hard
to understand how a score was derived. This adds a `verbose: true` flag
to any GEval metric config that captures the judge's criteria, evaluation
steps, and rubric from DeepEval's verbose_logs and propagates them
through the full pipeline to the JSON/CSV output.

Changes:
- GEvalConfig: new `verbose` bool field (default False), parsed from metadata
- GEvalHandler: capture `metric.verbose_logs` at turn and conversation level
- DeepEvalMetrics: propagate last_verbose_logs from the GEval handler
- MetricResult: new `verbose_logs` optional field, inherited by EvaluationResult
- MetricsEvaluator: read handler verbose_logs after evaluation, attach to result
- Serializer: include verbose_logs in JSON output only when non-None
- constants: add verbose_logs to SUPPORTED_CSV_COLUMNS
- system.yaml: document the verbose option in metrics_metadata example

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

GEval verbose log propagation

Layer / File(s) Summary
Verbose logging contracts
src/lightspeed_evaluation/core/models/llm.py, src/lightspeed_evaluation/core/models/data.py, src/lightspeed_evaluation/core/constants.py, config/system.yaml, tests/unit/core/models/*
Adds the GEvalConfig.verbose option, MetricResult.verbose_logs, the CSV column, example metadata, and model/configuration tests.
GEval log capture
src/lightspeed_evaluation/core/metrics/geval.py, src/lightspeed_evaluation/core/metrics/deepeval.py, tests/unit/core/metrics/test_geval.py
Captures turn-level and conversation-level GEval verbose logs, resets them between evaluations, and exposes them through the DeepEval metrics path.
Result propagation and serialization
src/lightspeed_evaluation/pipeline/evaluation/evaluator.py, src/lightspeed_evaluation/core/output/serializers.py, tests/unit/pipeline/evaluation/test_evaluator.py, tests/unit/core/output/test_final_coverage.py
Copies supported handler logs into evaluation results and conditionally includes non-null logs in serialized output.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GEvalConfig
  participant GEvalHandler
  participant MetricsEvaluator
  participant MetricResult
  participant result_to_json_dict
  GEvalConfig->>GEvalHandler: provide verbose configuration
  GEvalHandler->>GEvalHandler: capture verbose_logs
  GEvalHandler->>MetricsEvaluator: expose last_verbose_logs
  MetricsEvaluator->>MetricResult: assign verbose_logs
  result_to_json_dict->>MetricResult: read verbose_logs
  result_to_json_dict->>result_to_json_dict: include non-null logs
Loading

Suggested reviewers: xmican10

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main change: adding opt-in GEval verbose logs surfaced in outputs.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lightspeed_evaluation/pipeline/evaluation/evaluator.py`:
- Around line 230-236: Update the GEval/DeepEval verbose-log propagation in the
evaluator to use logs from the handlers created by _create_handler_for_judge
rather than self.handlers[framework]. Carry the selected or aggregated panel
logs through JudgeOrchestrator and assign them to MetricResult for the
corresponding panel run, avoiding stale primary-handler state. Add a test
covering verbose-log propagation from a panel-created handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 51c7c3aa-fd25-42c7-8778-aa22a8d6ec65

📥 Commits

Reviewing files that changed from the base of the PR and between 590f807 and 84eff7c.

📒 Files selected for processing (13)
  • config/system.yaml
  • src/lightspeed_evaluation/core/constants.py
  • src/lightspeed_evaluation/core/metrics/deepeval.py
  • src/lightspeed_evaluation/core/metrics/geval.py
  • src/lightspeed_evaluation/core/models/data.py
  • src/lightspeed_evaluation/core/models/llm.py
  • src/lightspeed_evaluation/core/output/serializers.py
  • src/lightspeed_evaluation/pipeline/evaluation/evaluator.py
  • tests/unit/core/metrics/test_geval.py
  • tests/unit/core/models/test_data.py
  • tests/unit/core/models/test_system.py
  • tests/unit/core/output/test_final_coverage.py
  • tests/unit/pipeline/evaluation/test_evaluator.py

Comment on lines +230 to +236
# Capture verbose_logs from GEval handler if enabled
if framework in ("geval", "deepeval"):
handler = self.handlers.get(framework)
if handler is not None:
verbose_logs = getattr(handler, "last_verbose_logs", None)
if isinstance(verbose_logs, str):
metric_result.verbose_logs = verbose_logs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Propagate verbose logs from panel-created handlers.

Panel GEval runs use DeepEvalMetrics instances created by _create_handler_for_judge, not necessarily self.handlers[framework]. This reads the primary handler’s state after orchestration, so panel verbose logs are dropped (or stale logs can be attached). Carry the selected/aggregated panel logs through JudgeOrchestrator into MetricResult, and add a panel-path test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lightspeed_evaluation/pipeline/evaluation/evaluator.py` around lines 230
- 236, Update the GEval/DeepEval verbose-log propagation in the evaluator to use
logs from the handlers created by _create_handler_for_judge rather than
self.handlers[framework]. Carry the selected or aggregated panel logs through
JudgeOrchestrator and assign them to MetricResult for the corresponding panel
run, avoiding stale primary-handler state. Add a test covering verbose-log
propagation from a panel-created handler.

@asamal4 asamal4 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks !!
Please address coderabbit's comment. and PTAL my comments..

Thread safety — shared mutable state between write and read
Judge panel path — verbose logs not captured
Only GEval — but verbose logs are available on all DeepEval metrics
Only file backends — missing from SQL, MLflow, Langfuse
Inconsistent JSON schema — conditionally omitted unlike other optional fields

"""
self.deepeval_llm_manager = deepeval_llm_manager
self.metric_manager = metric_manager
self.last_verbose_logs: str | None = None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last_verbose_logs is mutable instance state on a shared object. Handlers are created once and shared by all ThreadPoolExecutor threads. Between the write here and the read at evaluator.py, another thread can reset or overwrite the value. Same issue exists on deepeval.py.


# Capture verbose_logs from GEval handler if enabled
if framework in ("geval", "deepeval"):
handler = self.handlers.get(framework)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the judge panel path is used, fresh DeepEvalMetrics instances per judge are created. But this line reads from self.handlers.get(framework); the primary handler, not the panel handler. Panel verbose_logs are never captured.

default=None,
description="Per-judge scores when using judge panel (for transparency)",
)
verbose_logs: Optional[str] = Field(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field is added to MetricResult and flows to CSV/JSON, but EvaluationResultDB has no verbose_logs column for other storage. Data is silently dropped on any non-file storage backend.

"agent_latency": r.agent_latency,
"tokens_per_second": r.tokens_per_second,
}
if r.verbose_logs is not None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every other optional field in this dict (judge_scores, time_to_first_token, etc.) is always present, set to None when absent.

turn_data=scope.turn_data,
is_conversation=scope.is_conversation,
)
self.last_verbose_logs = self.geval_handler.last_verbose_logs

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a DeepEval-wide feature, this code limit it to geval only, standard deepeval metric wont capture the verbose log.

Comment thread config/system.yaml
# expected_outcome: "Technically correct and follows best practices."
threshold: 0.7
description: "General technical accuracy of provided commands, code, or technical information"
# verbose: true # optional: include verbose logs (criteria, evaluation steps, rubric) in output

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does verbose need to be an individual metric property? either we would want the log for all deepeval metrics or none at all..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants