Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions apps/evaluations/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import importlib
from collections import defaultdict
from collections import OrderedDict, defaultdict
from functools import cached_property
from typing import TYPE_CHECKING, Literal

Expand Down Expand Up @@ -350,24 +350,28 @@ def get_table_data(self, include_ids: bool = False):
for key, value in result.message_context.items()
if key != "current_datetime"
}
if include_ids is True:
table_by_message[result.message.id].update({"id": result.message.id})

table_by_message[result.message.id].update(
{
"Dataset Input": result.input_message,
"Dataset Output": result.output_message,
"Generated Response": result.output.get("generated_response", ""),
**{
f"{key} ({result.evaluator.name})": value
for key, value in result.output.get("result", {}).items()
},
**context_columns,
"session": result.session.external_id if result.session_id else "",
}
# Build row data in order
row_data = OrderedDict()
row_data["session"] = result.session.external_id if result.session_id else ""
row_data["message_id"] = result.message.id
row_data["Dataset Input"] = result.input_message
row_data["Dataset Output"] = result.output_message
row_data["Generated Response"] = result.output.get("generated_response", "")

row_data.update(
{f"{key} ({result.evaluator.name})": value for key, value in result.output.get("result", {}).items()}
)

row_data.update(context_columns)

if result.output.get("error"):
table_by_message[result.message.id]["error"] = result.output.get("error")
row_data["error"] = result.output.get("error")

if include_ids is True:
row_data["id"] = result.message.id

table_by_message[result.message.id] = row_data

return [{"#": index, **row} for index, row in enumerate(table_by_message.values())]


Expand Down
5 changes: 4 additions & 1 deletion apps/evaluations/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ class DatasetMessagesTable(tables.Table):
]
)

def __init__(self, *args, highlight_message_id=None, **kwargs):
super().__init__(*args, **kwargs)
self.highlight_message_id = highlight_message_id

class Meta:
model = EvaluationMessage
fields = (
Expand All @@ -351,6 +355,5 @@ class Meta:
"session_state",
"actions",
)
row_attrs = settings.DJANGO_TABLES2_ROW_ATTRS
orderable = False
empty_text = "No messages in this dataset yet."
Comment on lines 366 to 374

This comment was marked as outdated.

19 changes: 18 additions & 1 deletion apps/evaluations/views/dataset_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ class DatasetMessagesTableView(LoginAndTeamRequiredMixin, SingleTableView, Permi
model = EvaluationMessage
table_class = DatasetMessagesTable
table_pagination = {"per_page": 10}
template_name = "table/single_table.html"
template_name = "evaluations/dataset_messages_table.html"
permission_required = "evaluations.view_evaluationdataset"

def get_queryset(self):
Expand All @@ -295,6 +295,23 @@ def get_queryset(self):
evaluationdataset__id=dataset_id, evaluationdataset__team=self.request.team
).order_by("id")

def get_highlight_message_id(self):
"""Extract and validate the message_id query parameter for highlighting."""
try:
return int(self.request.GET.get("message_id"))
except (ValueError, TypeError):
return None

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["highlight_message_id"] = self.get_highlight_message_id()
return context

def get_table_kwargs(self):
kwargs = super().get_table_kwargs()
kwargs["highlight_message_id"] = self.get_highlight_message_id()
return kwargs


@login_and_team_required
@require_POST
Comment on lines +324 to 334

This comment was marked as outdated.

Expand Down
22 changes: 22 additions & 0 deletions apps/evaluations/views/evaluation_config_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.utils import timezone
from django.utils.safestring import mark_safe
from django.views.decorators.http import require_http_methods, require_POST
from django.views.generic import CreateView, TemplateView, UpdateView
from django_tables2 import SingleTableView, columns, tables
Expand Down Expand Up @@ -271,6 +272,18 @@ def session_enabled_condition(_, record):
# Check if session value exists (not empty string)
return bool(record.get("session"))

def dataset_url_factory(_, __, record, value):
if not value:
return "#"
dataset_id = self.evaluation_run.config.dataset_id
message_id = record.get("message_id")

url = reverse("evaluations:dataset_edit", args=[self.kwargs["team_slug"], dataset_id])
return f"{url}?message_id={message_id}"

def dataset_enabled_condition(_, record):
return bool(record.get("message_id"))

header = key.replace("_", " ").title()
match key:
case "session":
Expand All @@ -282,9 +295,18 @@ def session_enabled_condition(_, record):
url_factory=session_url_factory,
enabled_condition=session_enabled_condition,
),
actions.chip_action(
label=mark_safe('<i class="fa-solid fa-external-link"></i>'),
url_factory=dataset_url_factory,
enabled_condition=dataset_enabled_condition,
open_url_in_new_tab=True,
),
],
align="right",
)
case "message_id":
# Skip rendering message_id as a separate column since it's now in session column
return None
return columns.Column(verbose_name=header)


Expand Down
2 changes: 1 addition & 1 deletion templates/evaluations/dataset_edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ <h3 class="font-bold">{% translate "Dataset Creation Failed" %}</h3>
{% endif %}
<h2 class="pg-subtitle">{% translate "Dataset Messages" %}</h2>
<div id="dataset-messages-table"
hx-get="{% url 'evaluations:dataset_messages_table' request.team.slug object.id %}"
hx-get="{% url 'evaluations:dataset_messages_table' request.team.slug object.id %}{% if request.GET.message_id %}?message_id={{ request.GET.message_id }}{% endif %}"
hx-trigger="load, refreshTable from:body"
hx-target="this"
hx-swap="innerHTML">
Expand Down
28 changes: 28 additions & 0 deletions templates/evaluations/dataset_messages_table.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% load static %}
{% load render_table from django_tables2 %}

{% render_table table "evaluations/dataset_messages_table_render.html" %}

{% if highlight_message_id %}
<script>
function scrollToMessage() {
const messageId = "{{ highlight_message_id }}";
const selectedRow = document.querySelector(`tr[data-message-id="${messageId}"]`);
if (selectedRow) {
selectedRow.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
}
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', scrollToMessage);
} else {
scrollToMessage();
}
</script>
{% endif %}

{% block modal %}
{% endblock modal %}
22 changes: 22 additions & 0 deletions templates/evaluations/dataset_messages_table_render.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "table/tailwind_js_pagination.html" %}
{% load django_tables2 %}

{% block table.tbody %}
<tbody {{ table.attrs.tbody.as_html }}>
{% for record in table.page.object_list|default:table.data %}
<tr class="{% if table.highlight_message_id == record.record.id %}bg-yellow-100 dark:bg-yellow-900/20{% endif %}"
{% if table.highlight_message_id == record.record.id %}id="message-{{ record.record.id }}"{% endif %}
data-message-id="{{ record.record.id }}">
{% for column, cell in record.items %}
{% if column.visible %}
<td {{ column.attrs.td.as_html }}>{{ cell }}</td>
{% endif %}
{% endfor %}
</tr>
{% empty %}
{% if table.empty_text %}
<tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
{% endif %}
{% endfor %}
</tbody>
{% endblock table.tbody %}
Loading