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

Feature/answer explainability #96

Open
wants to merge 82 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
9b0815f
working app version
annalimm Feb 25, 2025
8b63f91
mocked answer
annalimm Feb 25, 2025
441728b
working app version with added modules and Displayed in app mocked RA…
annalimm Feb 27, 2025
4dfe8f7
working app version w/ mocked answer, pdf, working explanation proces…
annalimm Feb 27, 2025
2bf541c
version with properly highlighted ideas in a RAG answer
annalimm Feb 27, 2025
15e7ab7
getting rid of mocked answer ideas, first steps in fixing pages metadata
annalimm Feb 28, 2025
81cc50c
cleaned unnecessary for testing funcs in App.tsx
annalimm Feb 28, 2025
a82c5f5
cleaned preproc. module; correctly rewritten response highlighting (i…
annalimm Mar 3, 2025
4b9c31b
correct version for ChatWindow (to the previous commit)
annalimm Mar 3, 2025
425ca99
multiple consise highlighted ideas in response
annalimm Mar 3, 2025
cd13f8c
improved prompt for llm splitting response by ideas
annalimm Mar 3, 2025
90c156a
smaller file for testing
annalimm Mar 3, 2025
3693c6f
cleaned ideas coloring logic
annalimm Mar 4, 2025
fa22f3d
cleaning response info
annalimm Mar 4, 2025
43b3279
minor changes and unnecessary files cleanup
annalimm Mar 4, 2025
d787b73
added activeSourceId,fixed dissapearing of the source file after proc…
annalimm Mar 4, 2025
40031c1
saving (pages) metadata during processing now works!
annalimm Mar 4, 2025
990b1b4
minor logging changes
annalimm Mar 5, 2025
e52a6ea
first working steps for pdf/source highlighting
annalimm Mar 5, 2025
e9da80b
handling chunks existing on a few pages -> improved highlighting
annalimm Mar 5, 2025
839f148
console issues are fixed
annalimm Mar 5, 2025
d1d2a87
resolve merge
dani2112 Mar 10, 2025
836daf4
add citations
dani2112 Mar 10, 2025
895d2eb
placeholder
dani2112 Mar 10, 2025
2b59f35
updated package
annalimm Mar 11, 2025
a0843c7
citations are added
annalimm Mar 11, 2025
395b37d
implemented to lexio working version of idea highlighting
annalimm Mar 11, 2025
90904e4
handling types carefully
annalimm Mar 12, 2025
0cb2963
cleaning unnecessary message objects
annalimm Mar 12, 2025
f294c54
minor cleanup changes
annalimm Mar 12, 2025
3be274d
removed per-page color indicators in retrieved-source window
annalimm Mar 12, 2025
cb697c0
cleaning types
annalimm Mar 12, 2025
d12c85f
new module for message highlighting
annalimm Mar 12, 2025
e6a793a
removed the highlight count display
annalimm Mar 12, 2025
6ac3dbc
Merge branch 'main' into feature/answer_explainability
annalimm Mar 12, 2025
f0203f1
updated packacge lock file
annalimm Mar 12, 2025
c91513f
sbd package type definition
annalimm Mar 12, 2025
76f5874
add missing color field in PDFHighlight tests
annalimm Mar 12, 2025
e6018d5
generic names
annalimm Mar 13, 2025
fdb6957
separate AssistantMarkdownContent into distinct module avoiding circu…
annalimm Mar 13, 2025
3024618
replaced DOM-based highlighting with React components
annalimm Mar 17, 2025
bfa7059
reverted to restricted SourcesDisplay root styles
annalimm Mar 17, 2025
40689d1
text highlighting using character positions instead of regex matching
annalimm Mar 17, 2025
d6f4c48
redundant code cleanup in SourceDisplay
annalimm Mar 17, 2025
5278ee8
streamline highlight color handling and remove redundant color genera…
annalimm Mar 17, 2025
31664c2
minor changes
annalimm Mar 17, 2025
91c3609
original version of rag-state file
annalimm Mar 17, 2025
5676d55
Citation structure refactoring
annalimm Mar 17, 2025
0d43e0f
minor changes
annalimm Mar 17, 2025
040ccd5
reduced redundancy in a StremChunk
annalimm Mar 18, 2025
5be5434
package file minor cleanup
annalimm Mar 18, 2025
da29aa2
minor files cleanup
annalimm Mar 18, 2025
e776029
types module documentation minor changes
annalimm Mar 18, 2025
1b18783
test types interface definitions changes
annalimm Mar 18, 2025
22f2c5b
citationGenerator generic component
annalimm Mar 18, 2025
5449dd3
implemented Citation linking mechanism
annalimm Mar 19, 2025
5c09b4e
cleaner matching implementation
annalimm Mar 19, 2025
03c7dc9
minor changes
annalimm Mar 19, 2025
22688b6
minor cleanup
annalimm Mar 19, 2025
ff54599
minor format change
annalimm Mar 24, 2025
a52c515
simplify setSelectedSource and handle page updates directly in compon…
annalimm Mar 24, 2025
a709170
passing the page number instead of embedding it in a metadata object
annalimm Mar 24, 2025
43e9082
minor changes
annalimm Mar 25, 2025
6a86c60
PdfViewer cleaner version
annalimm Mar 25, 2025
254ae4a
metadata handling before data handling
annalimm Mar 25, 2025
283c635
formatting changes
annalimm Mar 25, 2025
04f50cc
formatting
annalimm Mar 25, 2025
78e96ff
formatting
annalimm Mar 25, 2025
1205b01
MessageHighlight type constraint
annalimm Mar 25, 2025
efe09ab
citations is now able to be returned asynchronously
annalimm Mar 25, 2025
a33c2a9
formatting minor changes
annalimm Mar 25, 2025
7b9fb00
removed the text property from messageHighlights
annalimm Mar 25, 2025
0c409ba
citations w/ both types of highlights inputs (chars/ text)
annalimm Mar 25, 2025
71dd65a
soft dependency approach for the explainability-related libraries
annalimm Mar 26, 2025
6fed05a
sbd lib soft dependency
annalimm Mar 26, 2025
8ff5ed6
openai lib soft dependency
annalimm Mar 26, 2025
e7eb40b
fixed TypeScript errors
annalimm Mar 26, 2025
05faf64
REST API for explanation features
annalimm Mar 26, 2025
a30e843
vite_config file reverting changes
annalimm Mar 26, 2025
543b5d1
minor cleanup
annalimm Mar 26, 2025
14196a0
minor types change
annalimm Mar 26, 2025
cb35948
rag-state cleanup
annalimm Mar 26, 2025
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ dummy-package/

.vscode/

examples/llama-index/frontend/rag-ui/
examples/llama-index/frontend/rag-ui/
6 changes: 6 additions & 0 deletions lexio/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
# Coverage Reports
coverage

# Environment Variables
.env.local

# PDF Files
pdfs/

# Logs
logs
*.log
Expand Down
111 changes: 111 additions & 0 deletions lexio/lib/components/ChatWindow/AssistantMarkdownContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import React from "react";
import {ChatWindowStyles} from "./ChatWindow";
import Markdown from "react-markdown";
import {Light as SyntaxHighlighter} from "react-syntax-highlighter";
import {docco} from "react-syntax-highlighter/dist/esm/styles/hljs";
import remarkGfm from "remark-gfm";
import {ClipboardIcon, ClipboardDocumentIcon} from "@heroicons/react/24/outline";

/**
* Props for the AssistantMarkdownContent component.
* @typedef {Object} AssistantMarkdownContentProps
* @property {string} content - The markdown content to render.
* @property {ChatWindowStyles} style - Styling options for the chat window.
*/
interface AssistantMarkdownContentProps {
content: string;
style: ChatWindowStyles;
}

/**
* Renders markdown content with enhanced features such as syntax highlighting and copy functionality.
*
* @param {AssistantMarkdownContentProps} props - The props for the component.
* @returns {JSX.Element} The rendered markdown content.
*
* @internal
*/
export const AssistantMarkdownContent: React.FC<AssistantMarkdownContentProps> = ({content, style}) => {
return (
<Markdown
components={{
/**
* Custom renderer for code blocks to include syntax highlighting and a copy button.
*
* @param {Object} props - Properties passed to the code component.
* @param {Object} props.node - The AST node.
* @param {string} props.className - The class name for the code block.
* @param {React.ReactNode} props.children - The code content.
* @returns {JSX.Element} The customized code block.
*/
code({node, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '');
const language = match ? match[1] : 'plaintext';
const [copied, setCopied] = React.useState(false);

/**
* Handles copying the code content to the clipboard.
*/
const handleCopy = () => {
navigator.clipboard.writeText(String(children));
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 3000); // Reset copied state after 3 seconds
}

// Block code (triple ```)
return (
<div style={{
position: 'relative',
marginBottom: '1rem'
}} {...(props as React.HTMLProps<HTMLDivElement>)}>
{match && (
<div
style={{
marginLeft: '0.33rem',
fontSize: 'var(--font-size-small)',
fontWeight: 'bold',
background: '#f5f5f5',
padding: '0 8px',
borderTopLeftRadius: '5px',
borderTopRightRadius: '5px',
borderBottom: '1px solid #ccc',
display: 'inline-block',
}}
>
{language}
</div>
)}
<div className="relative">
<SyntaxHighlighter
style={docco}
language={language}
PreTag="div"
wrapLongLine={true}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>

<div
className="absolute top-1 right-1 px-1.5 pt-0.5 text-sm rounded-md hover:shadow-md "
style={{
backgroundColor: style.messageBackgroundColor,
}}
>
<button
onClick={handleCopy}
>
{copied ? <ClipboardDocumentIcon className={"w-5 h-5"} /> : <ClipboardIcon className={"w-5 h-5"} />}
</button>
</div>
</div>
</div>
);
},
}}
remarkPlugins={[remarkGfm]}>
{content}
</Markdown>
);
}
2 changes: 2 additions & 0 deletions lexio/lib/components/ChatWindow/ChatWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
markdown={markdown}
showCopy={showCopy}
showFeedback={showFeedback}
highlights={msg.highlights || []}
/>
)}
</React.Fragment>
Expand All @@ -214,6 +215,7 @@ const ChatWindow: React.FC<ChatWindowProps> = ({
icon={assistantIcon || undefined}
markdown={markdown}
isStreaming={true}
highlights={currentStream.highlights || []}
/>
)}
<div ref={chatEndRef}/>
Expand Down
136 changes: 18 additions & 118 deletions lexio/lib/components/ChatWindow/ChatWindowAssistantMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,121 +1,17 @@
import React, {ReactNode, useMemo, useState} from "react";
import {ChatWindowStyles} from "./ChatWindow.tsx";
import Markdown from "react-markdown";
import {Light as SyntaxHighlighter} from "react-syntax-highlighter";
import {docco} from "react-syntax-highlighter/dist/esm/styles/hljs";
import remarkGfm from "remark-gfm";
import "./AssistantMarkdownContent.css";
import {ClipboardIcon, ClipboardDocumentIcon} from "@heroicons/react/24/outline";
import {scaleFontSize} from "../../utils/scaleFontSize.tsx";
import { MessageFeedback } from "./MessageFeedback.tsx";
/**
* Props for the AssistantMarkdownContent component.
* @typedef {Object} AssistantMarkdownContentProps
* @property {string} content - The markdown content to render.
* @property {ChatWindowStyles} style - Styling options for the chat window.
*/
interface AssistantMarkdownContentProps {
content: string;
style: ChatWindowStyles;
}

/**
* Renders markdown content with enhanced features such as syntax highlighting and copy functionality.
*
* @param {AssistantMarkdownContentProps} props - The props for the component.
* @returns {JSX.Element} The rendered markdown content.
*
* @internal
*/
const AssistantMarkdownContent: React.FC<AssistantMarkdownContentProps> = ({content, style}) => {
return (
<Markdown
components={{
/**
* Custom renderer for code blocks to include syntax highlighting and a copy button.
*
* @param {Object} props - Properties passed to the code component.
* @param {Object} props.node - The AST node.
* @param {string} props.className - The class name for the code block.
* @param {React.ReactNode} props.children - The code content.
* @returns {JSX.Element} The customized code block.
*/
code({node, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '');
const language = match ? match[1] : 'plaintext';
const [copied, setCopied] = React.useState(false);

/**
* Handles copying the code content to the clipboard.
*/
const handleCopy = () => {
navigator.clipboard.writeText(String(children));
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 3000); // Reset copied state after 3 seconds
}

// Block code (triple ```)
return (
<div style={{
position: 'relative',
marginBottom: '1rem'
}} {...(props as React.HTMLProps<HTMLDivElement>)}>
{match && (
<div
style={{
marginLeft: '0.33rem',
fontSize: 'var(--font-size-small)',
fontWeight: 'bold',
background: '#f5f5f5',
padding: '0 8px',
borderTopLeftRadius: '5px',
borderTopRightRadius: '5px',
borderBottom: '1px solid #ccc',
display: 'inline-block',
}}
>
{language}
</div>
)}
<div className="relative">
<SyntaxHighlighter
style={docco}
language={language}
PreTag="div"
wrapLongLine={true}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>

<div
className="absolute top-1 right-1 px-1.5 pt-0.5 text-sm rounded-md hover:shadow-md "
style={{
backgroundColor: style.messageBackgroundColor,
}}
>
<button
onClick={handleCopy}
>
{copied ? <ClipboardDocumentIcon className={"w-5 h-5"} /> : <ClipboardIcon className={"w-5 h-5"} />}
</button>
</div>
</div>
</div>
);
},
}}
remarkPlugins={[remarkGfm]}>
{content}
</Markdown>
);
}
import {MessageFeedback} from "./MessageFeedback.tsx";
import {MessageHighlight} from '../../types';
import {renderHighlightedContent} from './MessageHighlighting';

/**
* Props for the ChatWindowAssistantMessage component.
* @typedef {Object} ChatWindowAssistantMessageProps
* @property {string} message - The assistant message content.
* @property {string | null} messageId - ID of the message, null for streaming messages
* @property {ChatWindowStyles} style - Styling options for the chat window / assistant message
* @property {string} roleLabel - Label indicating the role of the assistant.
* @property {boolean} showRoleIndicator - Flag to show or hide the role indicator.
Expand All @@ -124,6 +20,7 @@ const AssistantMarkdownContent: React.FC<AssistantMarkdownContentProps> = ({cont
* @property {boolean} [isStreaming] - Flag indicating if the message is being streamed.
* @property {boolean} [showCopy] - Flag to show or hide the copy button.
* @property {boolean} [showFeedback] - Flag to show or hide the feedback buttons.
* @property {MessageHighlight[]} [highlights] - Highlights to highlight in the message, used for completed messages
*/
interface ChatWindowAssistantMessageProps {
message: string;
Expand All @@ -136,6 +33,7 @@ interface ChatWindowAssistantMessageProps {
isStreaming?: boolean;
showCopy?: boolean;
showFeedback?: boolean;
highlights?: MessageHighlight[];
}

/**
Expand All @@ -155,13 +53,16 @@ const ChatWindowAssistantMessage: React.FC<ChatWindowAssistantMessageProps> = ({
isStreaming,
showCopy,
showFeedback,
highlights
}) => {
const [copied, setCopied] = useState(false);
// show icon if showRoleIndicator is true and icon is not null
const showIcon = showRoleIndicator && !!icon;
// show label if showRoleIndicator is true and roleLabel is not null and icon is not shown
const showLabel = showRoleIndicator && !!roleLabel && !showIcon;

const highlightedContentRef = React.useRef<HTMLDivElement>(null);

/**
* Handles copying the message content to the clipboard.
*/
Expand Down Expand Up @@ -210,16 +111,15 @@ const ChatWindowAssistantMessage: React.FC<ChatWindowAssistantMessageProps> = ({
borderRadius: style.messageBorderRadius,
fontSize: style.messageFontSize,
}}>
{markdown ? (
<div className={"assistant-markdown-content"}
style={assistantMarkdownContentStyling}>
<AssistantMarkdownContent content={message} style={style}/>
</div>
) : (
<div className="inline whitespace-pre-wrap">
{message}
</div>
)}
<div ref={highlightedContentRef}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

seems to diable current renderer. consider checking if current renderer can still be used when having highlights. either by making the renderer have clickable highlights natively or having some overlay mechanism that overlays certain content in the existing renderd content.

Copy link
Collaborator

Choose a reason for hiding this comment

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

still an issue. you render either highlighted contnet or markdown content. can we render highlighted markdown content? see idea with overlay mechanism? could be lightweight addition to current renderer.

{renderHighlightedContent(
message,
highlights,
markdown || false,
style,
assistantMarkdownContentStyling
)}
</div>
</div>
{messageId && !isStreaming && (
<div
Expand Down
Loading