-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'PSL-US-7770-UnitTest' of https://github.com/microsoft/B…
…uild-your-own-copilot-Solution-Accelerator into PSL-US-7770-UnitTest
- Loading branch information
Showing
13 changed files
with
1,553 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,5 @@ frontend/node_modules | |
__pycache__/ | ||
.ipynb_checkpoints/ | ||
static | ||
venv | ||
venv | ||
frontend/coverage |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
...ssistant/App/frontend/src/components/ChatMessageContainer/ChatMessageContainer.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
.chatMessageUser { | ||
display: flex; | ||
justify-content: flex-end; | ||
margin-bottom: 12px; | ||
} | ||
|
||
.chatMessageUserMessage { | ||
padding: 20px; | ||
background: #edf5fd; | ||
border-radius: 8px; | ||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.14), 0px 0px 2px rgba(0, 0, 0, 0.12); | ||
font-style: normal; | ||
font-weight: 400; | ||
font-size: 14px; | ||
line-height: 22px; | ||
color: #242424; | ||
flex: none; | ||
order: 0; | ||
flex-grow: 0; | ||
white-space: pre-wrap; | ||
word-wrap: break-word; | ||
max-width: 800px; | ||
} | ||
|
||
.chatMessageGpt { | ||
margin-bottom: 12px; | ||
max-width: 80%; | ||
display: flex; | ||
} | ||
|
||
.chatMessageError { | ||
padding: 20px; | ||
border-radius: 8px; | ||
box-shadow: rgba(182, 52, 67, 1) 1px 1px 2px, rgba(182, 52, 67, 1) 0px 0px 1px; | ||
color: #242424; | ||
flex: none; | ||
order: 0; | ||
flex-grow: 0; | ||
max-width: 800px; | ||
margin-bottom: 12px; | ||
} | ||
|
||
.chatMessageErrorContent { | ||
font-family: "Segoe UI"; | ||
font-style: normal; | ||
font-weight: 400; | ||
font-size: 14px; | ||
line-height: 22px; | ||
white-space: pre-wrap; | ||
word-wrap: break-word; | ||
gap: 12px; | ||
align-items: center; | ||
} | ||
|
||
@media screen and (-ms-high-contrast: active), (forced-colors: active) { | ||
.chatMessageUserMessage { | ||
border: 2px solid WindowText; | ||
padding: 10px; | ||
background-color: Window; | ||
color: WindowText; | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
ResearchAssistant/App/frontend/src/components/ChatMessageContainer/ChatMessageContainer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { Fragment } from "react"; | ||
import { Stack } from "@fluentui/react"; | ||
import { ToolMessageContent, type ChatMessage, type Citation } from "../../api"; | ||
import styles from "./ChatMessageContainer.module.css"; | ||
import { Answer } from "../Answer/Answer"; | ||
import { ErrorCircleRegular } from "@fluentui/react-icons"; | ||
|
||
type ChatMessageContainerProps = { | ||
messages: ChatMessage[]; | ||
onShowCitation: (citation: Citation) => void; | ||
showLoadingMessage: boolean; | ||
}; | ||
|
||
const parseCitationFromMessage = (message: ChatMessage) => { | ||
if (message?.role && message?.role === "tool") { | ||
try { | ||
const toolMessage = JSON.parse(message.content) as ToolMessageContent; | ||
return toolMessage.citations; | ||
} catch { | ||
return []; | ||
} | ||
} | ||
return []; | ||
}; | ||
|
||
const ChatMessageContainer = (props: ChatMessageContainerProps): JSX.Element => { | ||
const [ASSISTANT, TOOL, ERROR, USER] = ["assistant", "tool", "error", "user"]; | ||
const { messages, onShowCitation , showLoadingMessage} = props; | ||
return ( | ||
<Fragment> | ||
{messages.map((answer, index) => ( | ||
<Fragment key={answer.role + index}> | ||
{answer.role === USER ? ( | ||
<div className={styles.chatMessageUser} tabIndex={0}> | ||
<div className={styles.chatMessageUserMessage}> | ||
{answer.content} | ||
</div> | ||
</div> | ||
) : answer.role === ASSISTANT ? ( | ||
<div className={styles.chatMessageGpt}> | ||
<Answer | ||
answer={{ | ||
answer: answer.content, | ||
citations: parseCitationFromMessage(messages[index - 1]), | ||
}} | ||
onCitationClicked={(c) => onShowCitation(c)} | ||
/> | ||
</div> | ||
) : answer.role === ERROR ? ( | ||
<div className={styles.chatMessageError}> | ||
<Stack horizontal className={styles.chatMessageErrorContent}> | ||
<ErrorCircleRegular | ||
className={styles.errorIcon} | ||
style={{ color: "rgba(182, 52, 67, 1)" }} | ||
/> | ||
<span>Error</span> | ||
</Stack> | ||
<span className={styles.chatMessageErrorContent}> | ||
{answer.content} | ||
</span> | ||
</div> | ||
) : null} | ||
</Fragment> | ||
))} | ||
{showLoadingMessage && ( | ||
<> | ||
<div className={styles.chatMessageGpt}> | ||
<Answer | ||
answer={{ | ||
answer: "Generating answer...", | ||
citations: [], | ||
}} | ||
onCitationClicked={() => null} | ||
/> | ||
</div> | ||
</> | ||
)} | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export default ChatMessageContainer; |
80 changes: 80 additions & 0 deletions
80
ResearchAssistant/App/frontend/src/components/CitationPanel/CitationPanel.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
.citationPanel { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-start; | ||
padding: 16px 16px; | ||
gap: 8px; | ||
background: #ffffff; | ||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.14), 0px 0px 2px rgba(0, 0, 0, 0.12); | ||
border-radius: 8px; | ||
flex: auto; | ||
order: 0; | ||
align-self: stretch; | ||
flex-grow: 0.3; | ||
max-width: 30%; | ||
overflow-y: scroll; | ||
max-height: calc(100vh - 100px); | ||
} | ||
|
||
.citationPanelHeaderContainer { | ||
width: 100%; | ||
} | ||
|
||
.citationPanelHeader { | ||
font-style: normal; | ||
font-weight: 600; | ||
font-size: 18px; | ||
line-height: 24px; | ||
color: #000000; | ||
flex: none; | ||
order: 0; | ||
flex-grow: 0; | ||
} | ||
|
||
.citationPanelDismiss { | ||
width: 18px; | ||
height: 18px; | ||
color: #424242; | ||
} | ||
|
||
.citationPanelDismiss:hover { | ||
background-color: #d1d1d1; | ||
cursor: pointer; | ||
} | ||
|
||
.citationPanelTitle { | ||
font-style: normal; | ||
font-weight: 600; | ||
font-size: 16px; | ||
line-height: 22px; | ||
color: #323130; | ||
margin-top: 12px; | ||
margin-bottom: 12px; | ||
} | ||
|
||
.citationPanelTitle:hover { | ||
text-decoration: underline; | ||
cursor: pointer; | ||
} | ||
|
||
.citationPanelContent { | ||
font-style: normal; | ||
font-weight: 400; | ||
font-size: 14px; | ||
line-height: 20px; | ||
color: #000000; | ||
flex: none; | ||
order: 1; | ||
align-self: stretch; | ||
flex-grow: 0; | ||
} | ||
|
||
/* high constrat */ | ||
@media screen and (-ms-high-contrast: active), (forced-colors: active) { | ||
.citationPanel { | ||
border: 2px solid WindowText; | ||
padding: 10px; | ||
background-color: Window; | ||
color: WindowText; | ||
} | ||
} |
89 changes: 89 additions & 0 deletions
89
ResearchAssistant/App/frontend/src/components/CitationPanel/CitationPanel.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { IconButton, Stack } from "@fluentui/react"; | ||
import { PrimaryButton } from "@fluentui/react/lib/Button"; | ||
import ReactMarkdown from "react-markdown"; | ||
import remarkGfm from "remark-gfm"; | ||
import rehypeRaw from "rehype-raw"; | ||
import { type Citation } from "../../api"; | ||
|
||
import styles from "./CitationPanel.module.css"; | ||
|
||
type citationPanelProps = { | ||
activeCitation: Citation | undefined; | ||
setIsCitationPanelOpen: (flag: boolean) => void; | ||
onViewSource: (citation: Citation | undefined) => void; | ||
onClickAddFavorite: () => void; | ||
}; | ||
|
||
const CitationPanel = (props: citationPanelProps): JSX.Element => { | ||
const { | ||
activeCitation, | ||
setIsCitationPanelOpen, | ||
onViewSource, | ||
onClickAddFavorite, | ||
} = props; | ||
|
||
const title = !activeCitation?.url?.includes("blob.core") | ||
? activeCitation?.url ?? "" | ||
: activeCitation?.title ?? ""; | ||
return ( | ||
<Stack.Item | ||
className={styles.citationPanel} | ||
tabIndex={0} | ||
role="tabpanel" | ||
aria-label="Citations Panel" | ||
> | ||
<Stack | ||
aria-label="Citations Panel Header Container" | ||
horizontal | ||
className={styles.citationPanelHeaderContainer} | ||
horizontalAlign="space-between" | ||
verticalAlign="center" | ||
> | ||
<Stack horizontal verticalAlign="center"> | ||
<span aria-label="Citations" className={styles.citationPanelHeader}> | ||
References | ||
</span> | ||
</Stack> | ||
<IconButton | ||
iconProps={{ iconName: "Cancel", style: { color: "#424242" } }} | ||
aria-label="Close citations panel" | ||
onClick={() => { | ||
setIsCitationPanelOpen(false); | ||
}} | ||
/> | ||
</Stack> | ||
<h5 | ||
className={styles.citationPanelTitle} | ||
tabIndex={0} | ||
title={title} | ||
onClick={() => onViewSource(activeCitation)} | ||
> | ||
{activeCitation?.title || ""} | ||
</h5> | ||
<PrimaryButton | ||
iconProps={{ iconName: "CirclePlus", style: { color: "white" } }} // Set icon color to white | ||
onClick={onClickAddFavorite} | ||
styles={{ | ||
root: { | ||
borderRadius: "4px", | ||
marginTop: "10px", | ||
padding: "12px 24px", | ||
}, | ||
}} | ||
> | ||
Favorite | ||
</PrimaryButton> | ||
<div tabIndex={0}> | ||
<ReactMarkdown | ||
linkTarget="_blank" | ||
className={styles.citationPanelContent} | ||
children={activeCitation?.content || ""} | ||
remarkPlugins={[remarkGfm]} | ||
rehypePlugins={[rehypeRaw]} | ||
/> | ||
</div> | ||
</Stack.Item> | ||
); | ||
}; | ||
|
||
export default CitationPanel; |
Oops, something went wrong.