Skip to content

Commit 8b669d1

Browse files
authored
Merge pull request #7 from SyncfusionExamples/947961
947961 : Integrate AIAssistView in the PdfViewer AI summarizer
2 parents 96d2fd6 + 20612a6 commit 8b669d1

File tree

8 files changed

+285
-383
lines changed

8 files changed

+285
-383
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
using Syncfusion.UI.Xaml.Chat;
2+
using Syncfusion.Windows.PdfViewer;
3+
using System.Collections.ObjectModel;
4+
using System.ComponentModel;
5+
using System.Text;
6+
7+
namespace Smart_Summarize
8+
{
9+
internal class AIAssitViewModel : INotifyPropertyChanged
10+
{
11+
#region Fields
12+
private ObservableCollection<object> chats;
13+
private ObservableCollection<string> suggestion;
14+
private Author currentUser;
15+
private PdfViewerControl pdfViewer;
16+
MicrosoftAIExtension microsoftAIExtension;
17+
StringBuilder processedText = new StringBuilder();
18+
public event PropertyChangedEventHandler PropertyChanged;
19+
#endregion
20+
21+
#region Properties
22+
/// <summary>
23+
/// Gets or sets the collection of chat messages.
24+
/// </summary>
25+
public ObservableCollection<object> Chats
26+
{
27+
get
28+
{
29+
return chats;
30+
}
31+
set
32+
{
33+
chats = value;
34+
RaisePropertyChanged("Messages");
35+
}
36+
}
37+
/// <summary>
38+
/// Gets or sets the collection of chat suggestions.
39+
/// </summary>
40+
public ObservableCollection<string> Suggestion
41+
{
42+
get
43+
{
44+
return suggestion;
45+
}
46+
set
47+
{
48+
suggestion = value;
49+
RaisePropertyChanged("Suggestion");
50+
}
51+
}
52+
/// <summary>
53+
/// Gets or sets the current user of the chat.
54+
/// </summary>
55+
public Author CurrentUser
56+
{
57+
get
58+
{
59+
return currentUser;
60+
}
61+
set
62+
{
63+
currentUser = value;
64+
RaisePropertyChanged("CurrentUser");
65+
}
66+
}
67+
/// <summary>
68+
/// Raises the PropertyChanged event to notify the UI of property changes.
69+
/// </summary>
70+
/// <param name="propName">The name of the property that changed.</param>
71+
public void RaisePropertyChanged(string propName)
72+
{
73+
if (PropertyChanged != null)
74+
{
75+
PropertyChanged(this, new PropertyChangedEventArgs(propName));
76+
}
77+
}
78+
#endregion
79+
#region constructor
80+
public AIAssitViewModel(PdfViewerControl viewer)
81+
{
82+
pdfViewer = viewer;
83+
Chats = new ObservableCollection<object>();
84+
suggestion = new ObservableCollection<string>();
85+
CurrentUser = new Author() { Name = pdfViewer.CurrentUser };
86+
microsoftAIExtension = new MicrosoftAIExtension("Your-AI-Key");
87+
Chats.CollectionChanged += Chats_CollectionChanged;
88+
}
89+
#endregion
90+
91+
#region Methods
92+
/// <summary>
93+
/// Generates chat messages by summarizing the PDF document.
94+
/// </summary>
95+
public async Task GenerateMessages()
96+
{
97+
Chats.Add(new TextMessage
98+
{
99+
Author = currentUser,
100+
DateTime = DateTime.Now,
101+
Text = "Summarizing the PDF document..."
102+
});
103+
104+
// Execute the following asynchronously
105+
await ExtractDetailsFromPDF();
106+
107+
string summaryText = await SummarizePDF();
108+
109+
// Update chats on the UI thread
110+
Chats.Add(new TextMessage
111+
{
112+
Author = new Author { Name = "AIAssistant" },
113+
DateTime = DateTime.Now,
114+
Text = summaryText
115+
});
116+
await AddSuggestions(summaryText);
117+
}
118+
/// <summary>
119+
/// Generate suggestion from the answers
120+
/// </summary>
121+
private async Task AddSuggestions(String text)
122+
{
123+
string suggestions = await microsoftAIExtension.GetAnswerFromGPT("You are a helpful assistant. Your task is to analyze the answer and ask 3 short one-line suggestion questions that user asks.", text);
124+
125+
var suggestionList = suggestions.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
126+
foreach (var suggestion in suggestionList)
127+
{
128+
Suggestion.Add(suggestion);
129+
}
130+
}
131+
/// <summary>
132+
/// Extracts text from each page of the PDF document.
133+
/// </summary>
134+
private async Task<string> ExtractDetailsFromPDF()
135+
{
136+
StringBuilder extractedText = new StringBuilder();
137+
Syncfusion.Pdf.TextLines textLines = new Syncfusion.Pdf.TextLines();
138+
//Extract the text from the PDF document
139+
for (int pageIndex = 0; pageIndex < pdfViewer.PageCount; pageIndex++)
140+
{
141+
string text = $"... Page {pageIndex + 1} ...\n";
142+
text += pdfViewer.ExtractText(pageIndex, out textLines);
143+
extractedText.AppendLine(text);
144+
}
145+
return ProcessExtractedText(extractedText.ToString());
146+
}
147+
/// <summary>
148+
/// Processes the extracted full text from a document by splitting it into pages.
149+
/// </summary>
150+
/// <param name="fullText">The complete extracted text from the document.</param>
151+
/// <returns>A formatted string containing the processed text.</returns>
152+
private string ProcessExtractedText(string fullText)
153+
{
154+
string[] pages = fullText.Split(new string[] { "\f", "\n\nPage " }, StringSplitOptions.RemoveEmptyEntries);
155+
for (int i = 0; i < pages.Length; i++)
156+
{
157+
processedText.AppendLine($"... Page {i + 1} ...");
158+
string[] lines = pages[i].Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
159+
int maxLines = Math.Min(1000, lines.Length);
160+
161+
for (int j = 0; j < maxLines; j++)
162+
{
163+
processedText.AppendLine(lines[j]);
164+
}
165+
processedText.AppendLine();
166+
}
167+
return processedText.ToString();
168+
}
169+
/// <summary>
170+
/// Summarizes the extracted text from the PDF using Extension AI.
171+
/// </summary>
172+
private async Task<string> SummarizePDF()
173+
{
174+
//Summarize the text using the Semantic Kernel AI
175+
string summary = await microsoftAIExtension.GetAnswerFromGPT(processedText.ToString());
176+
return summary;
177+
}
178+
/// <summary>
179+
/// Handles the event when the chat collection changes.
180+
/// </summary>
181+
/// <param name="sender">The source of the event.</param>
182+
/// <param name="e">The event data containing information about the collection change.</param>
183+
private async void Chats_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
184+
{
185+
if (e.NewItems != null && e.NewItems.Count > 0)
186+
{
187+
var item = e.NewItems[0] as ITextMessage;
188+
if (item != null)
189+
{
190+
if (item.Text != "Summarizing the PDF document...")
191+
{
192+
if (item.Author.Name == currentUser.Name)
193+
{
194+
string answer = await microsoftAIExtension.GetAnswerFromGPT("You are a helpful assistant. Your task is to analyze the provided question and answer the question based on the pdf", item.Text);
195+
Chats.Add(new TextMessage
196+
{
197+
Author = new Author { Name = "AIAssistant" },
198+
DateTime = DateTime.Now,
199+
Text = answer
200+
});
201+
Suggestion.Clear();
202+
await AddSuggestions(answer);
203+
}
204+
205+
}
206+
207+
}
208+
}
209+
}
210+
#endregion
211+
}
212+
}

Smart_Summarize/AIResultChatBox.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

Smart_Summarize/ChatTextBlock.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

Smart_Summarize/MainWindow.xaml

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
xmlns:local="clr-namespace:Smart_Summarize"
77
xmlns:PdfViewer="clr-namespace:Syncfusion.Windows.PdfViewer;assembly=Syncfusion.PdfViewer.WPF"
88
xmlns:Notification="clr-namespace:Syncfusion.Windows.Controls.Notification;assembly=Syncfusion.SfBusyIndicator.WPF"
9-
xmlns:syncfusionskin ="clr-namespace:Syncfusion.SfSkinManager;assembly=Syncfusion.SfSkinManager.WPF"
9+
xmlns:syncfusionskin ="clr-namespace:Syncfusion.SfSkinManager;assembly=Syncfusion.SfSkinManager.WPF" xmlns:syncfusion="clr-namespace:Syncfusion.UI.Xaml.Chat;assembly=Syncfusion.SfChat.Wpf"
1010
mc:Ignorable="d"
1111
Title="MainWindow" Height="450" Width="800" WindowState="Maximized"
1212
syncfusionskin:SfSkinManager.Theme="{syncfusionskin:SkinManagerExtension ThemeName=Windows11Light}">
@@ -15,7 +15,10 @@
1515
<ColumnDefinition Width="7*"/>
1616
<ColumnDefinition Width="auto"/>
1717
</Grid.ColumnDefinitions>
18-
<PdfViewer:PdfViewerControl x:Name="pdfViewer" Grid.Column="0" Loaded="pdfViewer_Loaded" DocumentLoaded="pdfViewer_DocumentLoaded"/>
18+
19+
<PdfViewer:PdfViewerControl x:Name="pdfViewer" Grid.Column="0"
20+
Loaded="pdfViewer_Loaded"
21+
DocumentLoaded="pdfViewer_DocumentLoaded"/>
1922
<Grid x:Name="summarizeGrid" Grid.Column="1" Visibility="Collapsed">
2023
<Grid.RowDefinitions>
2124
<RowDefinition Height="41"/>
@@ -27,29 +30,30 @@
2730
</Grid.ColumnDefinitions>
2831
<Border x:Name="seperator" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="1,0,0,0"/>
2932
<Label x:Name="aI_Title" Grid.Row="0" Grid.Column="1" FontSize="14" Padding="6,12,0,0" Content="AI Assist" Width="350" HorizontalAlignment="Left"/>
30-
<Grid x:Name="chatGrid" Grid.Row="1" Grid.Column="1">
31-
<Grid.RowDefinitions>
32-
<RowDefinition/>
33-
<RowDefinition Height="Auto"/>
34-
</Grid.RowDefinitions>
35-
<ScrollViewer Grid.Row="0" x:Name="ChatViewer" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" >
36-
<StackPanel x:Name="chatStack" Orientation="Vertical" >
37-
</StackPanel>
38-
</ScrollViewer>
39-
<StackPanel x:Name="inputStack" Grid.Row="1" Orientation="Horizontal">
40-
<Grid>
41-
<TextBox x:Name="inputText" Width="340" Padding="0,10,35,10" MinHeight="40" VerticalContentAlignment="Top" AcceptsReturn="True" MaxHeight="90" Margin="5,10" TextWrapping="Wrap" GotFocus="inputText_GotFocus" LostFocus="inputText_LostFocus"/>
42-
<Button x:Name="sendButton" Margin="5,10,6,15" Height="25" Width="25" VerticalAlignment="Bottom" HorizontalAlignment="Right" Click="sendButton_Click">
43-
<Button.Content>
44-
<Path Data="M0.175518 0.119595C0.324511 -0.00749701 0.533985 -0.0359071 0.711447 0.0469087L15.7114 7.04691C15.8875 7.12906 16 7.30574 16 7.5C16 7.69426 15.8875 7.87094 15.7114 7.95309L0.711447 14.9531C0.533985 15.0359 0.324511 15.0075 0.175518 14.8804C0.0265241 14.7533 -0.0345577 14.5509 0.0192423 14.3626L1.98 7.5L0.0192423 0.637361C-0.0345577 0.449061 0.0265241 0.246686 0.175518 0.119595ZM2.87716 8L1.28191 13.5833L14.3177 7.5L1.28191 1.41666L2.87716 7H9.5C9.77615 7 10 7.22386 10 7.5C10 7.77614 9.77615 8 9.5 8H2.87716Z"
45-
Height="14" Width="16" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"/>
46-
</Button.Content>
47-
</Button>
48-
</Grid>
49-
</StackPanel>
50-
</Grid>
51-
<Canvas x:Name="loadingCanvas" Grid.Row="1" Grid.Column="1" Background="White" Opacity="0.5" Visibility="Collapsed"/>
52-
<Notification:SfBusyIndicator x:Name="loadingIndicator" Grid.Row="1" Grid.Column="1" Visibility="Collapsed" IsBusy="True" AnimationType="DotCircle" ViewboxHeight="75" ViewboxWidth="150"/>
33+
<syncfusion:SfAIAssistView
34+
x:Name="aiAssistView" Visibility="Collapsed"
35+
Grid.Row="1" Grid.Column="1" Width="350" Height="Auto" CurrentUser="{Binding CurrentUser}"
36+
Messages="{Binding Chats}"
37+
SuggestionSelected="chat_SuggestionSelected"
38+
Suggestions="{Binding Suggestion}">
39+
<syncfusion:SfAIAssistView.BannerTemplate>
40+
<DataTemplate>
41+
<StackPanel
42+
Orientation="Vertical"
43+
VerticalAlignment="Bottom"
44+
Margin="0,10,0,0">
45+
<Viewbox Height="32" Width="32">
46+
<Path
47+
Margin="4"
48+
Data="M12.7393 0.396994C12.6915 0.170186 12.4942 0.00592917 12.2625 0.000156701C12.0307 -0.00561577 11.8255 0.14861 11.7665 0.372759L11.6317 0.88471C11.4712 1.49477 10.9948 1.97121 10.3847 2.13174L9.87276 2.26646C9.66167 2.32201 9.51101 2.50807 9.50058 2.72609C9.49014 2.94412 9.62234 3.14371 9.82715 3.21917L10.5469 3.48434C11.0663 3.67572 11.4646 4.10158 11.6208 4.63266L11.7703 5.14108C11.8343 5.35877 12.0369 5.50605 12.2637 5.49981C12.4906 5.49358 12.6847 5.3354 12.7367 5.11453L12.8292 4.72158C12.9661 4.1398 13.3904 3.66811 13.9545 3.47067L14.6652 3.22193C14.8737 3.14895 15.0096 2.94777 14.9995 2.72708C14.9894 2.50639 14.8356 2.31851 14.6213 2.26493L14.1122 2.13768C13.4624 1.97521 12.9622 1.45598 12.8242 0.800453L12.7393 0.396994ZM11.3796 2.78214C11.7234 2.57072 12.0165 2.28608 12.2378 1.94927C12.458 2.28452 12.7496 2.56851 13.0919 2.77995C12.7482 2.99134 12.4564 3.27526 12.2359 3.60987C12.015 3.2757 11.7229 2.99268 11.3796 2.78214ZM4.85357 10.4744C4.91635 10.6878 5.11235 10.8336 5.33379 10.8333L5.34711 10.8331C5.57393 10.8269 5.76811 10.6687 5.82009 10.4478L5.98446 9.74927C6.25825 8.5857 7.10693 7.64233 8.23516 7.24744L9.49856 6.80524C9.7035 6.73351 9.83872 6.53772 9.83322 6.32066C9.82772 6.1036 9.68277 5.9149 9.47446 5.85363L8.57059 5.58779C7.50843 5.2754 6.65671 4.47887 6.27396 3.43999L5.80255 2.16046C5.72974 1.96284 5.54135 1.83282 5.33236 1.83331C5.10615 1.83366 4.90757 1.98624 4.84972 2.20607L4.61022 3.11621C4.28914 4.33632 3.33626 5.2892 2.11615 5.61027L1.20601 5.84978C0.994926 5.90532 0.844266 6.09138 0.833828 6.3094C0.82339 6.52743 0.955587 6.72703 1.1604 6.80249L2.43993 7.2739C3.47881 7.65665 4.27534 8.50837 4.58773 9.57053L4.85357 10.4744ZM7.68415 6.38731C6.62743 6.82043 5.78274 7.636 5.309 8.65736C4.83249 7.63465 3.985 6.82144 2.92852 6.39092C3.98451 5.95938 4.83592 5.14232 5.31175 4.11073C5.78498 5.13721 6.63136 5.95377 7.68415 6.38731ZM11.9893 7.39699C11.9415 7.17019 11.7442 7.00593 11.5125 7.00016C11.2807 6.99438 11.0755 7.14861 11.0165 7.37276L10.8368 8.05536C10.6075 8.92687 9.92687 9.6075 9.05536 9.83684L8.37276 10.0165C8.16167 10.072 8.01101 10.2581 8.00058 10.4761C7.99014 10.6941 8.12233 10.8937 8.32715 10.9692L9.2868 11.3227C10.0289 11.5961 10.5978 12.2045 10.8209 12.9632L11.0203 13.6411C11.0843 13.8588 11.2869 14.006 11.5137 13.9998C11.7406 13.9936 11.9347 13.8354 11.9867 13.6145L12.11 13.0906C12.3056 12.2595 12.9118 11.5856 13.7176 11.3036L14.6652 10.9719C14.8737 10.8989 15.0096 10.6978 14.9995 10.4771C14.9894 10.2564 14.8356 10.0685 14.6213 10.0149L13.9426 9.84526C13.0141 9.61316 12.2997 8.87141 12.1025 7.93494L11.9893 7.39699ZM9.99771 10.543C10.6264 10.2254 11.1444 9.72499 11.4838 9.10985C11.8215 9.72215 12.3367 10.2219 12.9632 10.5402C12.3344 10.8584 11.8194 11.3576 11.4815 11.9678C11.1422 11.3576 10.6262 10.8597 9.99771 10.543Z"
49+
Fill="Black">
50+
</Path>
51+
</Viewbox>
52+
<TextBlock Text="AI Assistant" HorizontalAlignment="Center" FontSize="16" />
53+
</StackPanel>
54+
</DataTemplate>
55+
</syncfusion:SfAIAssistView.BannerTemplate>
56+
</syncfusion:SfAIAssistView>
5357
</Grid>
5458
</Grid>
5559
</Window>

0 commit comments

Comments
 (0)