Skip to content

Commit

Permalink
Upload documents in parallel + truncate text for long document names (m…
Browse files Browse the repository at this point in the history
…icrosoft#83)

### Motivation and Context

<!-- Thank you for your contribution to the copilot-chat repo!
Please help reviewers and future users, providing the following
information:
  1. Why is this change required?
  2. What problem does it solve?
  3. What scenario does it contribute to?
  4. If it fixes an open issue, please link to the issue here.
-->
resolves microsoft#49.

### Description 

<!-- Describe your changes, the overall approach, the underlying design.
These notes will help understanding how your code works. Thanks! -->
- `DocumentImportController`: changed to use `Task.WhenAll` when
importing documents.
- all other files: changed to show overflow text on hover and to
truncate long document names (shown below).
<img width="184" alt="image"
src="https://github.com/microsoft/chat-copilot/assets/52973358/a000834d-ead1-4462-9f09-c54aaa392ceb">
<img width="391" alt="image"
src="https://github.com/microsoft/chat-copilot/assets/52973358/ae95f4c3-f9c2-4239-9cc9-ec4909087a44">
<img width="208" alt="image"
src="https://github.com/microsoft/chat-copilot/assets/52973358/80f01453-3a93-4982-b552-1a2d05fe900e">



### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [x] The code builds clean without any errors or warnings
- [x] The PR follows the [Contribution
Guidelines](https://github.com/microsoft/copilot-chat/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/copilot-chat/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [x] All unit tests pass, and I have added new tests where possible
- [x] I didn't break anyone 😄
  • Loading branch information
dehoward authored Aug 7, 2023
1 parent 10c5ee9 commit 03359da
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 44 deletions.
27 changes: 15 additions & 12 deletions webapi/CopilotChat/Controllers/DocumentImportController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,21 @@ public async Task<IActionResult> ImportDocumentsAsync(

this._logger.LogInformation("Importing {0} document(s)...", documentImportForm.FormFiles.Count());

// TODO: [Issue #49] Perform the import in parallel.
DocumentMessageContent documentMessageContent = new();
IEnumerable<ImportResult> importResults = new List<ImportResult>();
foreach (var formFile in documentImportForm.FormFiles)
{
var importResult = await this.ImportDocumentHelperAsync(kernel, formFile, documentImportForm);
documentMessageContent.AddDocument(
formFile.FileName,
this.GetReadableByteString(formFile.Length),
importResult.IsSuccessful);
importResults = importResults.Append(importResult);
}
await Task.WhenAll(documentImportForm.FormFiles.Select(formFile =>
this.ImportDocumentHelperAsync(kernel, formFile, documentImportForm).ContinueWith(task =>
{
var importResult = task.Result;
if (importResult != null)
{
documentMessageContent.AddDocument(
formFile.FileName,
this.GetReadableByteString(formFile.Length),
importResult.IsSuccessful);
importResults = importResults.Append(importResult);
}
}, TaskScheduler.Default)));

// Broadcast the document uploaded event to other users.
if (documentImportForm.DocumentScope == DocumentImportForm.DocumentScopes.Chat)
Expand Down Expand Up @@ -323,7 +326,7 @@ private async Task<ImportResult> ImportDocumentHelperAsync(IKernel kernel, IForm
this._logger.LogInformation("Importing document {0}", formFile.FileName);

// Create memory source
var memorySource = this.CreateMemorySourceAsync(formFile, documentImportForm);
var memorySource = this.CreateMemorySource(formFile, documentImportForm);

// Parse document content to memory
ImportResult importResult = ImportResult.Fail();
Expand Down Expand Up @@ -361,7 +364,7 @@ private async Task<ImportResult> ImportDocumentHelperAsync(IKernel kernel, IForm
/// <param name="formFile">The file to be uploaded</param>
/// <param name="documentImportForm">The document upload form that contains additional necessary info</param>
/// <returns>A MemorySource object.</returns>
private MemorySource CreateMemorySourceAsync(
private MemorySource CreateMemorySource(
IFormFile formFile,
DocumentImportForm documentImportForm)
{
Expand Down
19 changes: 8 additions & 11 deletions webapp/src/components/chat/chat-history/ChatHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,14 @@ export const ChatHistory: React.FC<ChatHistoryProps> = ({ messages, onGetRespons

return (
<div className={classes.root}>
{messages
.slice()
.sort((a, b) => a.timestamp - b.timestamp)
.map((message, index) => (
<ChatHistoryItem
key={message.timestamp}
message={message}
getResponse={onGetResponse}
messageIndex={index}
/>
))}
{messages.map((message, index) => (
<ChatHistoryItem
key={message.timestamp}
message={message}
getResponse={onGetResponse}
messageIndex={index}
/>
))}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ import {
makeStyles,
mergeClasses,
shorthands,
tokens
tokens,
} from '@fluentui/react-components';
import React from 'react';
import { IChatMessage } from '../../../libs/models/ChatMessage';
import { SharedStyles } from '../../../styles';
import { getFileIconByFileExtension } from '../tabs/DocumentsTab';

const useClasses = makeStyles({
root: {
display: 'flex',
flexDirection: 'column',
...shorthands.margin(tokens.spacingVerticalM, 0),
...shorthands.margin(tokens.spacingVerticalM, 0),
},
card: {
height: 'fit-content',
Expand All @@ -39,6 +40,9 @@ const useClasses = makeStyles({
fontSize: 'small',
fontWeight: '500',
},
cardHeaderTextContainer: {
...SharedStyles.overflowEllipsis,
},
footer: {
float: 'right',
fontSize: 'small',
Expand Down Expand Up @@ -81,23 +85,30 @@ export const ChatHistoryDocumentContent: React.FC<ChatHistoryDocumentContentProp

return (
<>
{documents.map((document, index) => (
{documents.map(({ name, size, isUploaded }, index) => (
<div className={classes.root} key={`${message.id ?? 'unknown-message-id'}-document-${index}`}>
<Card appearance="filled-alternative" className={classes.card}>
<CardHeader
className={classes.cardHeader}
image={getFileIconByFileExtension(document.name, { className: classes.icon })}
header={<Text className={classes.cardHeaderText}>{document.name}</Text>}
image={getFileIconByFileExtension(name, { className: classes.icon })}
header={{
className: classes.cardHeaderTextContainer,
children: (
<Text className={classes.cardHeaderText} title={name}>
{name}
</Text>
),
}}
description={
<Caption1 block className={classes.cardCaption}>
{document.size}
{size}
</Caption1>
}
/>
<ProgressBar thickness="large" color={document.isUploaded ? "success" : "error"} value={1} />
<ProgressBar thickness="large" color={isUploaded ? 'success' : 'error'} value={1} />
</Card>
<span className={isMe ? classes.footer : mergeClasses(classes.footer, classes.floatLeft)}>
{document.isUploaded ? "Success: memory established" : "Failed: memory not established"}
{isUploaded ? 'Success: memory established' : 'Failed: memory not established'}
</span>
</div>
))}
Expand Down
25 changes: 14 additions & 11 deletions webapp/src/components/chat/chat-list/ChatListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { useAppDispatch, useAppSelector } from '../../../redux/app/hooks';
import { RootState } from '../../../redux/app/store';
import { FeatureKeys } from '../../../redux/features/app/AppState';
import { setSelectedConversation } from '../../../redux/features/conversations/conversationsSlice';
import { Breakpoints } from '../../../styles';
import { Breakpoints, SharedStyles } from '../../../styles';
import { timestampToDateString } from '../../utils/TextUtils';
import { EditChatName } from '../shared/EditChatName';
import { ListItemActions } from './ListItemActions';
Expand Down Expand Up @@ -55,12 +55,9 @@ const useClasses = makeStyles({
justifyContent: 'space-between',
},
title: {
...shorthands.overflow('hidden'),
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
...SharedStyles.overflowEllipsis,
fontSize: tokens.fontSizeBase300,
color: tokens.colorNeutralForeground1,
lineHeight: tokens.lineHeightBase200,
},
timestamp: {
flexShrink: 0,
Expand All @@ -70,12 +67,10 @@ const useClasses = makeStyles({
lineHeight: tokens.lineHeightBase200,
},
previewText: {
...SharedStyles.overflowEllipsis,
display: 'block',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
lineHeight: tokens.lineHeightBase100,
color: tokens.colorNeutralForeground2,
...shorthands.overflow('hidden'),
},
popoverSurface: {
display: 'none',
Expand Down Expand Up @@ -143,12 +138,18 @@ export const ChatListItem: FC<IChatListItemProps> = ({
}
/>
{editingTitle ? (
<EditChatName name={header} chatId={id} exitEdits={() => { setEditingTitle(false) }} />
<EditChatName
name={header}
chatId={id}
exitEdits={() => {
setEditingTitle(false);
}}
/>
) : (
<>
<div className={classes.body}>
<div className={classes.header}>
<Text className={classes.title}>
<Text className={classes.title} title={header}>
{header}
{features[FeatureKeys.AzureContentSafety].enabled && (
<ShieldTask16Regular className={classes.protectedIcon} />
Expand Down Expand Up @@ -178,7 +179,9 @@ export const ChatListItem: FC<IChatListItemProps> = ({
<ListItemActions
chatId={id}
chatName={header}
onEditTitleClick={() => { setEditingTitle(true); }}
onEditTitleClick={() => {
setEditingTitle(true);
}}
/>
)}
</>
Expand Down
6 changes: 4 additions & 2 deletions webapp/src/components/chat/tabs/DocumentsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,10 @@ function useTable(resources: ChatMemorySource[]) {
),
renderCell: (item) => (
<TableCell key={item.id}>
<TableCellLayout media={item.name.icon}>
<a href={item.name.url}>{item.name.label}</a>
<TableCellLayout media={item.name.icon} truncate>
<a href={item.name.url} title={item.name.label}>
{item.name.label}
</a>
</TableCellLayout>
</TableCell>
),
Expand Down
6 changes: 6 additions & 0 deletions webapp/src/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
createDarkTheme,
createLightTheme,
makeStyles,
shorthands,
themeToTokensObject,
tokens,
} from '@fluentui/react-components';
Expand Down Expand Up @@ -66,6 +67,11 @@ export const SharedStyles: Record<string, GriffelStyle> = {
height: '100%',
...ScrollBarStyles,
},
overflowEllipsis: {
...shorthands.overflow('hidden'),
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
};

export const useDialogClasses = makeStyles({
Expand Down

0 comments on commit 03359da

Please sign in to comment.