Skip to content

Commit c5c3674

Browse files
committed
implement DevExpress AI
1 parent 30f9846 commit c5c3674

16 files changed

Lines changed: 675 additions & 241 deletions

CS/BusinessObjects/AzureAILanguageHelper.cs

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

CS/BusinessObjects/AzureAITranslationHelper.cs

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

CS/BusinessObjects/FileFormat.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public enum RichEditFormat
1818
Dot = 15,
1919
}
2020

21+
public enum RichEditDocumentPart
22+
{
23+
WholeDocument = 1,
24+
FirstPage = 2,
25+
FirstSection = 3,
26+
}
27+
2128
public enum SpreadsheetFormat
2229
{
2330
Xls = 1,
@@ -32,4 +39,31 @@ public enum SpreadsheetFormat
3239
Pdf = 13,
3340
}
3441

42+
public enum PresentationFormat
43+
{
44+
Pptx = 1,
45+
Ppt = 2,
46+
Pdf = 3,
47+
}
48+
49+
public enum PresentationPart
50+
{
51+
WholePresentation = 1,
52+
FirstSlide = 2,
53+
}
54+
55+
public enum PdfPart
56+
{
57+
WholeDocument = 1,
58+
FirstPage = 2,
59+
}
60+
public enum TranslationLang
61+
{
62+
English = 1,
63+
Spanish = 2,
64+
French = 3,
65+
German = 4,
66+
67+
}
68+
3569
}

CS/BusinessObjects/Helpers.cs

Lines changed: 114 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,44 @@
1-
using DevExpress.Spreadsheet;
1+
using DevExpress.Docs.Presentation;
2+
using DevExpress.Drawing;
3+
using DevExpress.Pdf;
4+
using DevExpress.Spreadsheet;
25
using DevExpress.XtraRichEdit;
6+
using System.Drawing;
7+
using System.Globalization;
8+
using PresentationDocumentFormat = DevExpress.Docs.Presentation.DocumentFormat;
39
using RichEditDocumentFormat = DevExpress.XtraRichEdit.DocumentFormat;
410
using RichEditEncryptionSettings = DevExpress.XtraRichEdit.API.Native.EncryptionSettings;
511
using SpreadsheetDocumentFormat = DevExpress.Spreadsheet.DocumentFormat;
612
using SpreadsheetEncryptionSettings = DevExpress.Spreadsheet.EncryptionSettings;
713

814
namespace RichEditOpenAIWebApi.BusinessObjects
915
{
16+
17+
public static class SharedHelper
18+
{
19+
public static CultureInfo GetTranslationLanguage(TranslationLang translationLanguage)
20+
{
21+
return translationLanguage switch
22+
{
23+
TranslationLang.English => new CultureInfo("en-US"),
24+
TranslationLang.Spanish => new CultureInfo("es-ES"),
25+
TranslationLang.French => new CultureInfo("fr-FR"),
26+
TranslationLang.German => new CultureInfo("de-DE"),
27+
_ => throw new NotSupportedException($"Translation language '{translationLanguage}' is not supported.")
28+
};
29+
}
30+
31+
public static async Task<string> FileToBase64String(IFormFile file)
32+
{
33+
using (var stream = new MemoryStream())
34+
{
35+
await file.CopyToAsync(stream);
36+
stream.Seek(0, SeekOrigin.Begin);
37+
byte[] imageBytes = stream.ToArray();
38+
return Convert.ToBase64String(imageBytes);
39+
}
40+
}
41+
}
1042
public static class RichEditHelper
1143
{
1244
public static async Task LoadFile(RichEditDocumentServer server, IFormFile file)
@@ -66,16 +98,7 @@ public static string GetContentType(RichEditFormat documentFormat)
6698
default: return string.Empty;
6799
}
68100
}
69-
public static async Task<string> FileToBase64String(IFormFile file)
70-
{
71-
using (var stream = new MemoryStream())
72-
{
73-
await file.CopyToAsync(stream);
74-
stream.Seek(0, SeekOrigin.Begin);
75-
byte[] imageBytes = stream.ToArray();
76-
return Convert.ToBase64String(imageBytes);
77-
}
78-
}
101+
79102
}
80103
public static class SpreadsheetHelper
81104
{
@@ -130,7 +153,86 @@ public static string GetContentType(SpreadsheetFormat documentFormat)
130153
default: return string.Empty;
131154
}
132155

156+
}
157+
}
158+
public static class PresentationHelper
159+
{
160+
public static async Task<Presentation> LoadPresentation(IFormFile file)
161+
{
162+
using (var stream = new MemoryStream())
163+
{
164+
await file.CopyToAsync(stream);
165+
stream.Seek(0, SeekOrigin.Begin);
166+
var presentation = new Presentation(stream);
167+
return presentation;
168+
}
169+
}
170+
171+
public static string GetContentType(PresentationFormat documentFormat)
172+
{
173+
switch (documentFormat)
174+
{
175+
case PresentationFormat.Ppt:
176+
case PresentationFormat.Pptx:
177+
return "application/vnd.ms-powerpoint";
178+
default: return string.Empty;
179+
}
180+
}
181+
182+
public static Stream SaveDocument(Presentation presentation, PresentationFormat outputFormat)
183+
{
184+
MemoryStream resultStream = new MemoryStream();
185+
if (outputFormat == PresentationFormat.Pdf)
186+
presentation.ExportToPdf(resultStream);
187+
else
188+
{
189+
PresentationDocumentFormat documentFormat = new PresentationDocumentFormat((int)outputFormat);
190+
presentation.SaveDocument(resultStream, documentFormat);
191+
}
192+
resultStream.Seek(0, SeekOrigin.Begin);
193+
return resultStream;
194+
}
133195

196+
}
197+
public static class PdfHelper
198+
{
199+
200+
public static async Task LoadPdfDocument(PdfDocumentProcessor processor, IFormFile file)
201+
{
202+
using (var stream = new MemoryStream())
203+
{
204+
await file.CopyToAsync(stream);
205+
stream.Seek(0, SeekOrigin.Begin);
206+
processor.LoadDocument(stream, true);
207+
}
208+
}
209+
210+
public static void AddContentToPage(PdfDocumentProcessor pdfDocumentProcessor, PdfPage page, PdfRectangle pageSize, string text)
211+
{
212+
using (PdfGraphics graphics = pdfDocumentProcessor.CreateGraphicsWorldSystem())
213+
{
214+
using (var textBrush = new DXSolidBrush(Color.FromArgb(255, Color.DarkOrange)))
215+
{
216+
DXFont font = new DXFont("Segoe UI", 12, DXFontStyle.Regular);
217+
218+
// Calculate text size
219+
SizeF textSize = graphics.MeasureString(
220+
text,
221+
font,
222+
new PdfStringFormat());
223+
224+
// Calculate an area to draw the text
225+
PointF textPoint = new PointF(0, (float)(pageSize.Height - 10));
226+
RectangleF rectangle = new RectangleF(
227+
0, 10,
228+
(float)pageSize.Width,
229+
(float)(pageSize.Height / 2));
230+
231+
// Draw text at the calculated area
232+
graphics.DrawString(text, font, textBrush, rectangle);
233+
graphics.AddToPageForeground(page);
234+
}
235+
}
134236
}
135237
}
136-
}
238+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using DevExpress.AIIntegration;
2+
using DevExpress.AIIntegration.Extensions;
3+
using Microsoft.Extensions.AI;
4+
using OpenAI.Chat;
5+
using System.ClientModel;
6+
7+
namespace RichEditOpenAIWebApi.BusinessObjects
8+
{
9+
10+
namespace RichEditOpenAIWebApi.BusinessObjects
11+
{
12+
public class HyperlinkHelper
13+
{
14+
private readonly IChatClient _chatClient;
15+
private readonly AIExtensionsContainerDefault defaultAIExtensionContainer;
16+
17+
public HyperlinkHelper(IChatClient chatClient)
18+
{
19+
_chatClient = chatClient;
20+
defaultAIExtensionContainer = AIExtensionsContainerConsole.CreateDefaultAIExtensionContainer(chatClient);
21+
}
22+
23+
public async Task<string> DescribeHyperlinkAsync(string link, CancellationToken cancellationToken = default)
24+
{
25+
if (string.IsNullOrWhiteSpace(link))
26+
return string.Empty;
27+
var request = new CustomPromptRequest("You describe hyperlinks for accessibility. Describe this hyperlink in 10–20 words:", link);
28+
string response = await defaultAIExtensionContainer.CustomPromptAsync(request, cancellationToken);
29+
30+
return response.Trim();
31+
}
32+
}
33+
}
34+
35+
}

CS/BusinessObjects/ImageHelper.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Azure;
2+
using Azure.AI.OpenAI;
3+
using DevExpress.AIIntegration;
4+
using DevExpress.AIIntegration.Docs;
5+
using DevExpress.AIIntegration.Extensions;
6+
using DevExpress.Drawing;
7+
using DevExpress.Office.Utils;
8+
using Microsoft.Extensions.AI;
9+
10+
namespace RichEditOpenAIWebApi.BusinessObjects {
11+
class ImageHelper {
12+
13+
private readonly IChatClient _chatClient;
14+
private readonly AIExtensionsContainerDefault defaultAIExtensionContainer;
15+
16+
internal ImageHelper(IChatClient chatClient) {
17+
_chatClient = chatClient;
18+
defaultAIExtensionContainer = AIExtensionsContainerConsole.CreateDefaultAIExtensionContainer(chatClient);
19+
}
20+
string ConvertDXImageToBase64String(DXImage image) {
21+
using (MemoryStream stream = new MemoryStream()) {
22+
image.Save(stream, DXImageFormat.Png);
23+
byte[] imageBytes = stream.ToArray();
24+
return Convert.ToBase64String(imageBytes);
25+
}
26+
}
27+
internal async Task<string> DescribeImageAsync(OfficeImage image) {
28+
29+
var imageByteString = ConvertDXImageToBase64String(image.DXImage);
30+
31+
var request = new GenerateImageDescriptionRequest(imageByteString);
32+
var response = await defaultAIExtensionContainer.GenerateImageDescriptionAsync(request);
33+
return response;
34+
}
35+
}
36+
}

CS/BusinessObjects/OpenAIClientHyperlinkHelper.cs

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

CS/BusinessObjects/OpenAIClientImageHelper.cs

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

0 commit comments

Comments
 (0)