Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add start/end date ability for query history as CSV endpoint #3211

Merged
merged 1 commit into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 4 additions & 2 deletions backend/ee/danswer/server/query_history/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,12 +427,14 @@ def get_chat_session_admin(
@router.get("/admin/query-history-csv")
def get_query_history_as_csv(
_: User | None = Depends(current_admin_user),
start: datetime | None = None,
end: datetime | None = None,
db_session: Session = Depends(get_session),
) -> StreamingResponse:
complete_chat_session_history = fetch_and_process_chat_session_history(
db_session=db_session,
start=datetime.fromtimestamp(0, tz=timezone.utc),
end=datetime.now(tz=timezone.utc),
start=start or datetime.fromtimestamp(0, tz=timezone.utc),
end=end or datetime.now(tz=timezone.utc),
feedback_type=None,
limit=None,
)
Expand Down
9 changes: 4 additions & 5 deletions backend/tests/integration/common_utils/managers/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def get_chat_history(
user_performing_action: DATestUser | None = None,
) -> list[DATestChatMessage]:
response = requests.get(
f"{API_SERVER_URL}/chat/history/{chat_session.id}",
f"{API_SERVER_URL}/chat/get-chat-session/{chat_session.id}",
headers=user_performing_action.headers
if user_performing_action
else GENERAL_HEADERS,
Expand All @@ -151,11 +151,10 @@ def get_chat_history(

return [
DATestChatMessage(
id=msg["id"],
id=msg["message_id"],
chat_session_id=chat_session.id,
parent_message_id=msg.get("parent_message_id"),
parent_message_id=msg.get("parent_message"),
message=msg["message"],
response=msg.get("response", ""),
)
for msg in response.json()
for msg in response.json()["messages"]
]
5 changes: 2 additions & 3 deletions backend/tests/integration/common_utils/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,10 @@ class DATestChatSession(BaseModel):


class DATestChatMessage(BaseModel):
id: str | None = None
id: int
chat_session_id: UUID
parent_message_id: str | None
parent_message_id: int | None
message: str
response: str


class StreamedResponse(BaseModel):
Expand Down
89 changes: 71 additions & 18 deletions backend/tests/integration/tests/query-history/test_query_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import timedelta
from datetime import timezone

import pytest
import requests

from danswer.configs.constants import QAFeedbackType
Expand All @@ -16,7 +17,8 @@
from tests.integration.common_utils.test_models import DATestUser


def test_query_history_endpoints(reset: None) -> None:
@pytest.fixture
def setup_chat_session(reset: None) -> tuple[DATestUser, str]:
# Create admin user and required resources
admin_user: DATestUser = UserManager.create(name="admin_user")
cc_pair = CCPairManager.create_from_scratch(user_performing_action=admin_user)
Expand Down Expand Up @@ -46,16 +48,29 @@ def test_query_history_endpoints(reset: None) -> None:
user_performing_action=admin_user,
)

# Test get chat session history endpoint
end_time = datetime.now(tz=timezone.utc)
start_time = end_time - timedelta(days=1)
messages = ChatSessionManager.get_chat_history(
chat_session=chat_session,
user_performing_action=admin_user,
)

# Add another message to the chat session
ChatSessionManager.send_message(
chat_session_id=chat_session.id,
message="What about Q2 revenue?",
user_performing_action=admin_user,
parent_message_id=messages[-1].id,
)

return admin_user, str(chat_session.id)


def test_chat_history_endpoints(
reset: None, setup_chat_session: tuple[DATestUser, str]
) -> None:
admin_user, first_chat_id = setup_chat_session

response = requests.get(
f"{API_SERVER_URL}/admin/chat-session-history",
params={
"start": start_time.isoformat(),
"end": end_time.isoformat(),
},
headers=admin_user.headers,
)
assert response.status_code == 200
Expand All @@ -66,15 +81,29 @@ def test_query_history_endpoints(reset: None) -> None:

# Verify the first chat session details
first_session = history_response[0]
first_chat_id = first_session["id"]
assert first_session["user_email"] == admin_user.email
assert first_session["name"] == "Test chat session"
assert first_session["first_user_message"] == "What was the Q1 revenue?"
assert first_session["first_ai_message"] is not None
assert first_session["assistant_id"] == 0
assert first_session["feedback_type"] is None
assert first_session["flow_type"] == SessionType.CHAT.value
assert first_session["conversation_length"] == 2 # User message + AI response
assert first_session["conversation_length"] == 4 # 2 User messages + 2 AI responses

# Test date filtering - should return no results
past_end = datetime.now(tz=timezone.utc) - timedelta(days=1)
past_start = past_end - timedelta(days=1)
response = requests.get(
f"{API_SERVER_URL}/admin/chat-session-history",
params={
"start": past_start.isoformat(),
"end": past_end.isoformat(),
},
headers=admin_user.headers,
)
assert response.status_code == 200
history_response = response.json()
assert len(history_response) == 0

# Test get specific chat session endpoint
response = requests.get(
Expand All @@ -89,7 +118,25 @@ def test_query_history_endpoints(reset: None) -> None:
assert len(session_details["messages"]) > 0
assert session_details["flow_type"] == SessionType.CHAT.value

# Test CSV export endpoint
# Test filtering by feedback
response = requests.get(
f"{API_SERVER_URL}/admin/chat-session-history",
params={
"feedback_type": QAFeedbackType.LIKE.value,
},
headers=admin_user.headers,
)
assert response.status_code == 200
history_response = response.json()
assert len(history_response) == 0


def test_chat_history_csv_export(
reset: None, setup_chat_session: tuple[DATestUser, str]
) -> None:
admin_user, _ = setup_chat_session

# Test CSV export endpoint with date filtering
response = requests.get(
f"{API_SERVER_URL}/admin/query-history-csv",
headers=admin_user.headers,
Expand All @@ -100,20 +147,26 @@ def test_query_history_endpoints(reset: None) -> None:

# Verify CSV content
csv_content = response.content.decode()
csv_lines = csv_content.strip().split("\n")
assert len(csv_lines) == 3 # Header + 2 QA pairs
assert "chat_session_id" in csv_content
assert "user_message" in csv_content
assert "ai_response" in csv_content
assert "What was the Q1 revenue?" in csv_content
assert "What about Q2 revenue?" in csv_content

# Test filtering by feedback
# Test CSV export with date filtering - should return no results
past_end = datetime.now(tz=timezone.utc) - timedelta(days=1)
past_start = past_end - timedelta(days=1)
response = requests.get(
f"{API_SERVER_URL}/admin/chat-session-history",
f"{API_SERVER_URL}/admin/query-history-csv",
params={
"feedback_type": QAFeedbackType.LIKE.value,
"start": start_time.isoformat(),
"end": end_time.isoformat(),
"start": past_start.isoformat(),
"end": past_end.isoformat(),
},
headers=admin_user.headers,
)
assert response.status_code == 200
history_response = response.json()
assert len(history_response) == 0
csv_content = response.content.decode()
csv_lines = csv_content.strip().split("\n")
assert len(csv_lines) == 1 # Only header, no data rows
Loading