Skip to content

Commit debb1fd

Browse files
nitbossNithin Bose
andauthored
Add collapsible user input display for long messages (#471)
* Add collapsible user input display for long messages - Implement smart headline generation that extracts email subjects or truncates text intelligently - Add collapsible UI for messages over 150 characters to preserve screen space for answers - Maintain original large text styling for short messages (backward compatible) - Use existing Radix UI Collapsible components with smooth expand/collapse animations - Include visual indicators (chevron icons) for interaction state Fixes issue where long user inputs dominated the results page with oversized text. * Fix deprecated LangChain imports and update GitHub Actions versions - Update deprecated import paths to use langchain_core and provider-specific packages - Update GitHub Actions from v3 to v4 for better compatibility - Fixes failing eval workflow in CI * Fix import sorting and module import issues from commit 4450b89 - Fix I001 import sorting errors in evaluation scripts by moving provider-specific imports after langchain.* imports - Fix ModuleNotFoundError by correcting import path from langchain_core.chat_models to langchain.chat_models in backend/utils.py - Apply code formatting fixes using ruff and prettier - Addresses failing tests and linting issues in CI --------- Co-authored-by: Nithin Bose <[email protected]>
1 parent 2c63f20 commit debb1fd

File tree

9 files changed

+96
-10
lines changed

9 files changed

+96
-10
lines changed

.github/actions/poetry_setup/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ runs:
2828
with:
2929
python-version: ${{ inputs.python-version }}
3030

31-
- uses: actions/cache@v3
31+
- uses: actions/cache@v4
3232
id: cache-bin-poetry
3333
name: Cache Poetry binary - Python ${{ inputs.python-version }}
3434
env:
@@ -75,7 +75,7 @@ runs:
7575
run: pipx install "poetry==$POETRY_VERSION" --python '${{ steps.setup-python.outputs.python-path }}' --verbose
7676

7777
- name: Restore pip and poetry cached dependencies
78-
uses: actions/cache@v3
78+
uses: actions/cache@v4
7979
env:
8080
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "4"
8181
with:

.github/workflows/eval.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
environment: Evaluation
2020
steps:
2121
- name: Checkout repository
22-
uses: actions/checkout@v3
22+
uses: actions/checkout@v4
2323

2424
- name: Set up Python + Poetry
2525
uses: "./.github/actions/poetry_setup"

_scripts/clear_index.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Clear Weaviate index."""
2+
23
import logging
34
import os
45

_scripts/evaluate_chains.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77

88
import weaviate
99
from langchain import load as langchain_load
10-
from langchain.chat_models import ChatAnthropic, ChatOpenAI
1110
from langchain.embeddings import OpenAIEmbeddings
1211
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder, PromptTemplate
1312
from langchain.schema.output_parser import StrOutputParser
1413
from langchain.schema.retriever import BaseRetriever
1514
from langchain.schema.runnable import Runnable, RunnableMap
1615
from langchain.smith import RunEvalConfig
1716
from langchain.vectorstores import Weaviate
17+
from langchain_anthropic import ChatAnthropic
18+
from langchain_openai import ChatOpenAI
1819
from langsmith import Client, RunEvaluator
1920
from langsmith.evaluation.evaluator import EvaluationResult
2021
from langsmith.schemas import Example, Run

_scripts/evaluate_chains_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
AgentTokenBufferMemory,
1111
)
1212
from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent
13-
from langchain.chat_models import ChatOpenAI
1413
from langchain.embeddings import OpenAIEmbeddings
1514
from langchain.prompts import MessagesPlaceholder
1615
from langchain.schema.messages import SystemMessage
1716
from langchain.smith import RunEvalConfig, run_on_dataset
1817
from langchain.vectorstores import Weaviate
18+
from langchain_openai import ChatOpenAI
1919
from langsmith import Client, RunEvaluator
2020
from langsmith.evaluation.evaluator import EvaluationResult
2121
from langsmith.schemas import Example, Run

_scripts/evaluate_chains_improved_chain.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import weaviate
99
from langchain import load as langchain_load
10-
from langchain.chat_models import ChatAnthropic, ChatOpenAI
1110
from langchain.embeddings import OpenAIEmbeddings
1211
from langchain.output_parsers import CommaSeparatedListOutputParser
1312
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder, PromptTemplate
@@ -16,6 +15,8 @@
1615
from langchain.schema.runnable import Runnable, RunnableMap
1716
from langchain.smith import RunEvalConfig
1817
from langchain.vectorstores import Weaviate
18+
from langchain_anthropic import ChatAnthropic
19+
from langchain_openai import ChatOpenAI
1920
from langsmith import Client, RunEvaluator
2021
from langsmith.evaluation.evaluator import EvaluationResult
2122
from langsmith.schemas import Example, Run

_scripts/evaluate_chat_langchain.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
# This is ugly
33
import argparse
44

5-
from langchain.chat_models import ChatAnthropic, ChatOpenAI
65
from langchain.smith import RunEvalConfig
6+
from langchain_anthropic import ChatAnthropic
7+
from langchain_openai import ChatOpenAI
78
from langsmith import Client
89

910
# Ugly. Requires PYTHONATH=$(PWD) to run

backend/ingest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Load html from files, clean up, split, ingest into Weaviate."""
2+
23
import logging
34
import os
45
import re

frontend/app/components/chat-interface/messages.tsx

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,100 @@ import {
66
useThreadRuntime,
77
} from "@assistant-ui/react";
88
import { useState, type FC } from "react";
9+
import { ChevronDownIcon, ChevronRightIcon } from "lucide-react";
910

1011
import { MarkdownText } from "../ui/assistant-ui/markdown-text";
1112
import { useGraphContext } from "@/app/contexts/GraphContext";
1213
import { useRuns } from "@/app/hooks/useRuns";
1314
import { TooltipIconButton } from "../ui/assistant-ui/tooltip-icon-button";
1415
import { ThumbsDownIcon, ThumbsUpIcon } from "lucide-react";
16+
import {
17+
Collapsible,
18+
CollapsibleTrigger,
19+
CollapsibleContent,
20+
} from "../ui/collapsible";
21+
22+
// Helper function to generate a brief headline from long text
23+
function generateHeadline(text: string, maxLength: number = 60): string {
24+
if (text.length <= maxLength) return text;
25+
26+
// Try to find the first sentence or logical break
27+
const firstSentence = text.match(/^[^.!?]*[.!?]/);
28+
if (firstSentence && firstSentence[0].length <= maxLength) {
29+
return firstSentence[0].trim();
30+
}
31+
32+
// Try to find subject line if it looks like an email
33+
const subjectMatch = text.match(/^Subject:\s*([^\n\r]+)/i);
34+
if (subjectMatch && subjectMatch[1].length <= maxLength) {
35+
return subjectMatch[1].trim();
36+
}
37+
38+
// Fallback to truncated text at word boundary
39+
const truncated = text.substring(0, maxLength);
40+
const lastSpace = truncated.lastIndexOf(" ");
41+
return lastSpace > maxLength * 0.7
42+
? truncated.substring(0, lastSpace) + "..."
43+
: truncated + "...";
44+
}
1545

1646
export const UserMessage: FC = () => {
47+
const message = useMessage();
48+
const [isExpanded, setIsExpanded] = useState(false);
49+
50+
// Get the text content from the message
51+
const textContent =
52+
message.content?.[0]?.type === "text" ? message.content[0].text : "";
53+
const isLongText = textContent.length > 150; // Threshold for collapsible behavior
54+
55+
if (!isLongText) {
56+
// For short text, use the original styling
57+
return (
58+
<MessagePrimitive.Root className="pt-2 sm:pt-4 flex w-full md:max-w-4xl md:mx-0 mx-auto max-w-[95%] md:py-4 py-2">
59+
<div className="bg-inherit text-white break-words rounded-2xl sm:rounded-3xl pt-2 md:pt-2.5 mb-[-15px] sm:mb-[-25px] text-2xl sm:text-4xl font-light">
60+
<MessagePrimitive.Content />
61+
</div>
62+
</MessagePrimitive.Root>
63+
);
64+
}
65+
66+
const headline = generateHeadline(textContent);
67+
1768
return (
1869
<MessagePrimitive.Root className="pt-2 sm:pt-4 flex w-full md:max-w-4xl md:mx-0 mx-auto max-w-[95%] md:py-4 py-2">
19-
<div className="bg-inherit text-white break-words rounded-2xl sm:rounded-3xl pt-2 md:pt-2.5 mb-[-15px] sm:mb-[-25px] text-2xl sm:text-4xl font-light">
20-
<MessagePrimitive.Content />
21-
</div>
70+
<Collapsible
71+
open={isExpanded}
72+
onOpenChange={setIsExpanded}
73+
className="w-full"
74+
>
75+
<CollapsibleTrigger className="w-full text-left group hover:opacity-80 transition-opacity">
76+
<div className="bg-inherit text-white break-words rounded-2xl sm:rounded-3xl pt-2 md:pt-2.5 mb-[-15px] sm:mb-[-25px] flex items-start gap-2">
77+
<div className="text-2xl sm:text-4xl font-light flex-1">
78+
{headline}
79+
</div>
80+
<div className="flex items-center mt-1 text-gray-400 group-hover:text-white transition-colors">
81+
{isExpanded ? (
82+
<ChevronDownIcon className="w-5 h-5 sm:w-6 sm:h-6" />
83+
) : (
84+
<ChevronRightIcon className="w-5 h-5 sm:w-6 sm:h-6" />
85+
)}
86+
</div>
87+
</div>
88+
</CollapsibleTrigger>
89+
90+
<CollapsibleContent className="overflow-hidden">
91+
<div className="pt-4 pb-2">
92+
<div className="bg-gray-800/50 text-gray-200 text-sm sm:text-base rounded-lg p-3 sm:p-4 border border-gray-700/50">
93+
<div className="font-medium text-gray-300 mb-2 text-xs sm:text-sm uppercase tracking-wide">
94+
Full Message
95+
</div>
96+
<div className="whitespace-pre-wrap break-words leading-relaxed">
97+
{textContent}
98+
</div>
99+
</div>
100+
</div>
101+
</CollapsibleContent>
102+
</Collapsible>
22103
</MessagePrimitive.Root>
23104
);
24105
};

0 commit comments

Comments
 (0)