officefileapi-405645-ai-powered-extensions.md
The DevExpress Office File API includes AI-powered extensions that integrate with language models through Microsoft.Extensions.AI (IChatClient). Extensions are available for the Word Processing Document API, PDF Document API, and Presentation API Library.
The IChatClient interface serves as the central mechanism for language model interaction. Supported AI providers include:
IChatClient implementation for unsupported providers or private language models The Microsoft.Extensions.AI framework allows developers to integrate support for AI language models and services without modifying the core library. This means you can leverage third-party libraries for new AI providers or create your own custom implementation for in-house language models.Note
DevExpress AI-powered extensions operate on a “bring your own key” (BYOK) model. We do not provide a proprietary REST API or bundled language models (LLMs/SLMs).
You can either deploy a self-hosted model or connect to a cloud AI provider and obtain necessary connection parameters (endpoint, API key, language model identifier, and so on). These parameters must be configured at application startup to register an AI client and enable extension functionality.
This topic explains how to register and use available AI extensions.
View Example: Office File API – Integrate DevExpress AI-powered Extensions
For details on prerequisites, see AI Integration.
To access DevExpress packages, you need to have an active Universal Subscription or Office File API Subscription.
.NET 8 SDK or .NET Framework v4.7.2
OpenAI
Azure OpenAI
Semantic Kernel
Ollama (self-hosted models)
Foundry Local (on-device AI models)
ONNX Runtime (local ONNX models)
DevExpress AI-powered extensions run inside an AIExtensionsContainer that manages registered AI clients. Use the AIExtensionsContainerConsole.CreateDefaultAIExtensionContainer method to create a container and register a chat client in a .NET console application.
Call AIDocProcessingExtensions.CreateAIDocProcessingService to create a document-processing service instance.
The following code snippet registers an Azure Open AI client and creates and extension service:
using DevExpress.AIIntegration;
using Microsoft.Extensions.AI;
using System.Globalization;
// Configure Azure OpenAI endpoint and API key via environment variables.
Environment.SetEnvironmentVariable(
"AZURE_OPENAI_ENDPOINT",
"<YOUR_AZURE_OPENAI_ENDPOINT>");
Environment.SetEnvironmentVariable(
"AZURE_OPENAI_APIKEY",
"<YOUR_AZURE_OPENAI_KEY>");
var modelName = "gpt-4o-mini";
// Register an Azure OpenAI client and obtain the
// default AI extensions container.
AIExtensionsContainerDefault defaultAIExtensionsContainer =
RegisterAzureOpenAIClient(
Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"),
Environment.GetEnvironmentVariable("AZURE_OPENAI_APIKEY"));
// Create a document processing service instance
// from the AI extensions container.
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService();
// Helper method that creates and configures an Azure OpenAI chat client
// and wraps it in a default AI extensions container.
AIExtensionsContainerDefault RegisterAzureOpenAIClient(
string azureOpenAIEndpoint,
string azureOpenAIKey)
{
IChatClient client =
new Azure.AI.OpenAI.AzureOpenAIClient(
new Uri(azureOpenAIEndpoint),
new System.ClientModel.ApiKeyCredential(azureOpenAIKey))
.GetChatClient(modelName)
.AsIChatClient();
return AIExtensionsContainerConsole.CreateDefaultAIExtensionContainer(client);
}
Imports DevExpress.AIIntegration
Imports Microsoft.Extensions.AI
Imports System.Globalization
Imports System
' Configure Azure OpenAI endpoint and API key via environment variables.
Environment.SetEnvironmentVariable(
"AZURE_OPENAI_ENDPOINT",
"<YOUR_AZURE_OPENAI_ENDPOINT>")
Environment.SetEnvironmentVariable(
"AZURE_OPENAI_APIKEY",
"<YOUR_AZURE_OPENAI_KEY>")
Dim modelName = "gpt-4o-mini"
' Register an Azure OpenAI client and obtain the
' default AI extensions container.
Dim defaultAIExtensionsContainer As AIExtensionsContainerDefault = _
RegisterAzureOpenAIClient(
Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"), _
Environment.GetEnvironmentVariable("AZURE_OPENAI_APIKEY"))
' Create a document processing service instance
' from the AI extensions container.
Dim docProcessingService = _
defaultAIExtensionsContainer.CreateAIDocProcessingService()
' Helper method that creates and configures an Azure OpenAI chat client
' and wraps it in a default AI extensions container.
Private Function RegisterAzureOpenAIClient(
azureOpenAIEndpoint As String,
azureOpenAIKey As String) As AIExtensionsContainerDefault
Dim client As IChatClient = New Azure.AI.OpenAI.AzureOpenAIClient( _
New Uri(azureOpenAIEndpoint), _
New System.ClientModel.ApiKeyCredential(azureOpenAIKey)) _
.GetChatClient("gpt-4o-mini") _
.AsIChatClient()
Return AIExtensionsContainerConsole.CreateDefaultAIExtensionContainer(client)
End Function
You can also instantiate the AIDocProcessingService class (the IAIDocProcessingService implementation) directly instead of the CreateAIDocProcessingService method call.
Call the RegisterAIDocProcessingService(AIExtensionsContainerSettings) method to register document-processing AI extensions in your dependency injection container:
using System.Globalization;
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using Microsoft.Extensions.AI;
var azureOpenAIEndpoint = "<YOUR_AZURE_OPENAI_ENDPOINT>";
var azureOpenAIKey = "<YOUR_AZURE_OPENAI_API_KEY>";
var modelName = "<YOUR_MODEL_NAME>";
var builder = WebApplication.CreateBuilder(args);
// Create an Azure OpenAI client with endpoint and API key from helper.
var azureOpenAIClient = new Azure.AI.OpenAI.AzureOpenAIClient(
new Uri(azureOpenAIEndpoint),
new System.ClientModel.ApiKeyCredential(azureOpenAIKey));
// Get a model-specific chat client and adapt it to IChatClient.
IChatClient chatClient = azureOpenAIClient
.GetChatClient(modelName)
.AsIChatClient();
// Register the chat client as a singleton in the dependency injection container.
builder.Services.AddSingleton(chatClient);
// Add DevExpress AI services and register the document-processing extensions.
builder.Services.AddDevExpressAIConsole((config) => {
config.RegisterAIDocProcessingService();
});
// Build the configured web application instance.
var app = builder.Build();
| Extension | Supported Products | Description | Registration Method |
|---|---|---|---|
| Proofread | Word Processing Document API | ||
| Presentation API Library | Reviews text (grammar, spelling, style) in real time. | ||
| Available for an entire document/presentation or selected parts (slides, ranges, areas). | ProofreadAsync | ||
| Translate | Word Processing Document API | ||
| PDF Document API | |||
| Presentation API Library | Translates full document/presentation content or selected parts (slides, ranges, areas). Preserves formatting. | TranslateAsync | |
| Summarize | Word Processing Document API | ||
| PDF Document API | |||
| Presentation API Library | Produces a concise summary for an entire document/presentation or selected parts (slides, ranges, areas). | SummarizeAsync | |
| Contextual Q&A (Ask AI) | Word Processing Document API | ||
| PDF Document API | |||
| Presentation API Library | Answers contextual questions about document content. | ||
| Uses retrieval‑augmented generation (RAG). | AskAIAsync |
Use ProofreadAsync to review a document or presentation and apply AI-generated corrections.
The following code snippet proofreads an entire document. Code to proofread only the second paragraph is included as commented code.
using DevExpress.AIIntegration.Docs;
using DevExpress.XtraRichEdit;
using DevExpress.XtraRichEdit.API.Native;
using System.Diagnostics;
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService();
using (var wordProcessor = new RichEditDocumentServer())
{
// Load source document (ensure file exists in relative Documents folder)
wordProcessor.LoadDocument("Documents/FirstLookShortened.docx");
// Proofread entire document (culture en-US)
await docProcessingService.ProofreadAsync(wordProcessor, new System.Globalization.CultureInfo("en-US"));
// Proofread a single paragraph
// Paragraph paragraph = wordProcessor.Document.Paragraphs[1];
// await docProcessingService.ProofreadAsync(paragraph.Range, new System.Globalization.CultureInfo("en-US"));
// Prepare output directory & file path
string targetDir = @"C:\Test Documents";
Directory.CreateDirectory(targetDir); // Safe if already exists
string outputPath = Path.Combine(targetDir, "Proofread.docx");
// Save the proofread document
using (FileStream outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
{
wordProcessor.SaveDocument(outputStream, DocumentFormat.OpenXml);
}
}
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.XtraRichEdit
Imports DevExpress.XtraRichEdit.API.Native
Imports System.Globalization
Imports System.IO
Dim docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService()
Using wordProcessor As New RichEditDocumentServer()
' Load source document (ensure file exists in relative Documents folder)
wordProcessor.LoadDocument("Documents/FirstLookShortened.docx")
' Proofread entire document (culture en-US)
Await docProcessingService.ProofreadAsync(wordProcessor, New CultureInfo("en-US"))
' Proofread a single paragraph
' Dim paragraph As Paragraph = wordProcessor.Document.Paragraphs(1)
' Await docProcessingService.ProofreadAsync(paragraph.Range, New CultureInfo("en-US"))
' Prepare output directory & file path
Dim targetDir As String = "C:\Test Documents"
Directory.CreateDirectory(targetDir) ' Safe if already exists
Dim outputPath As String = Path.Combine(targetDir, "Proofread.docx")
' Save the proofread document
Using outputStream As New FileStream(outputPath, FileMode.Create, FileAccess.Write)
wordProcessor.SaveDocument(outputStream, DocumentFormat.OpenXml)
End Using
End Using
The following code snippet proofreads an entire presentation. Code to proofread only the second slide is included as commented code.
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.Docs.Presentation;
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService();
using (var presentation = new Presentation(File.ReadAllBytes("Documents/Presentation.pptx")))
{
// Proofread entire document (culture en-US)
await docProcessingService.ProofreadAsync(presentation, new System.Globalization.CultureInfo("en-US"));
// Proofread a single slide (e.g., slide 2)
// Slide slide = presentation.Slides[1];
// await docProcessingService.ProofreadAsync(slide, new System.Globalization.CultureInfo("en-US"));
// Prepare output directory & file path
string targetDir = @"C:\Test Documents";
Directory.CreateDirectory(targetDir); // Safe if already exists
string outputPath = Path.Combine(targetDir, "Proofread.pptx");
// Save the proofread presentation
using (FileStream outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
{
presentation.SaveDocument(outputStream, DocumentFormat.Pptx);
}
}
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.Docs.Presentation
Imports System.Globalization
Imports System.IO
Imports System.Threading.Tasks
Dim docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService()
Using presentation = New Presentation(File.ReadAllBytes("Documents/Presentation.pptx"))
' Proofread entire document (culture en-US)
Await docProcessingService.ProofreadAsync(presentation, New CultureInfo("en-US"))
' Proofread a single slide (e.g., slide 2)
' Dim slide As Slide = presentation.Slides(1)
' Await docProcessingService.ProofreadAsync(slide, New CultureInfo("en-US"))
' Prepare output directory & file path
Dim targetDir As String = "C:\Test Documents"
Directory.CreateDirectory(targetDir) ' Safe if already exists
Dim outputPath As String = Path.Combine(targetDir, "Proofread.pptx")
' Save the proofread presentation
Using outputStream As New FileStream(outputPath, FileMode.Create, FileAccess.Write)
presentation.SaveDocument(outputStream, DocumentFormat.Pptx)
End Using
End Using
Use TranslateAsync to translate entire documents/presentations or specified ranges. Formatting is preserved.
Note
TranslateAsync method overloads that use PdfDocumentProcessor as a parameter return translated content instead of replacing original content in the PDF file on the fly.
The following code snippet translates the second paragraph in a Word document:
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.XtraRichEdit;
using DevExpress.XtraRichEdit.API.Native;
using Microsoft.Extensions.AI;
// See "Register AI extension service" section for implementation code
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService();
using (var wordProcessor = new RichEditDocumentServer()) {
FileStream fs = File.OpenRead(
Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Documents/FirstLookShortened.docx"));
wordProcessor.LoadDocument(fs);
fs.Close();
Paragraph paragraph = wordProcessor.Document.Paragraphs[1];
await docProcessingService.TranslateAsync(
paragraph.Range,
new System.Globalization.CultureInfo("DE-DE"));
// Save the modified document
string outputFilePath =
Path.Combine(Environment.CurrentDirectory, $"Document1_translated.docx");
wordProcessor.SaveDocument(outputFilePath, DocumentFormat.Docx);
}
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.XtraRichEdit
Imports DevExpress.XtraRichEdit.API.Native
Imports Microsoft.Extensions.AI
Imports System.Globalization
Imports System.IO
Imports System.Threading.Tasks
Module Module1
Async Function Main() As Task
' See "Register AI extension service" section for implementation code
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService()
Using wordProcessor As New RichEditDocumentServer()
Dim fs As FileStream = File.OpenRead(
Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"Documents/FirstLookShortened.docx"))
wordProcessor.LoadDocument(fs)
fs.Close()
Dim paragraph As Paragraph = wordProcessor.Document.Paragraphs(1)
Await docProcessingService.TranslateAsync(
paragraph.Range,
New CultureInfo("DE-DE"))
' Save the modified document
Dim outputFilePath As String = Path.Combine(Environment.CurrentDirectory, "Document1_translated.docx")
wordProcessor.SaveDocument(outputFilePath, DocumentFormat.Docx)
End Using
End Function
End Module
The following code snippet translates the first page in a PDF document and appends the translation as a new page:
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.Drawing;
using DevExpress.Pdf;
using Microsoft.Extensions.AI;
using System.Drawing;
// Check "Register Service" section for implementation code
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService();
using var pdfDocumentProcessor = new PdfDocumentProcessor();
pdfDocumentProcessor.LoadDocument("Documents/FirstLookExported.pdf");
// Obtain the first page area
var pageBox = pdfDocumentProcessor.Document.Pages[0].CropBox;
PdfDocumentPosition pagePosition1 = new PdfDocumentPosition(1, pageBox.TopLeft);
PdfDocumentPosition pagePosition2 = new PdfDocumentPosition(1, pageBox.BottomRight);
var pageContentArea = PdfDocumentArea.Create(pagePosition1, pagePosition2);
// Translate the page content to Spanish
string translation = await docProcessingService.TranslateAsync(
pdfDocumentProcessor,
pageContentArea,
new System.Globalization.CultureInfo("es-ES"));
// Insert a new page and add the translated text
PdfPage page = pdfDocumentProcessor.InsertNewPage(1, PdfPaperSize.Letter);
PdfRectangle pageSize = page.CropBox;
AddContentToPage(pdfDocumentProcessor, page, pageSize, translation);
// Save the modified document
pdfDocumentProcessor.SaveDocument("result.pdf");
// This method draws text on the inserted page
void AddContentToPage(
PdfDocumentProcessor pdfDocumentProcessor,
PdfPage page,
PdfRectangle pageSize,
string text)
{
using (PdfGraphics graphics = pdfDocumentProcessor.CreateGraphicsWorldSystem())
{
using (var textBrush = new DXSolidBrush(Color.FromArgb(255, Color.DarkOrange)))
{
DXFont font = new DXFont("Segoe UI", 12, DXFontStyle.Regular);
// Calculate text size
SizeF textSize = graphics.MeasureString(
text,
font,
new PdfStringFormat());
// Calculate an area to draw the text
PointF textPoint = new PointF(0, (float)(pageSize.Height - 10));
RectangleF rectangle = new RectangleF(
0, 10,
(float)pageSize.Width,
(float)(pageSize.Height / 2));
// Draw text at the calculated area
graphics.DrawString(text, font, textBrush, rectangle);
graphics.AddToPageForeground(page);
}
}
}
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.Drawing
Imports DevExpress.Pdf
Imports Microsoft.Extensions.AI
Imports System.Drawing
Imports System.Globalization
' Check "Register Service" section for implementation code
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService()
Using pdfDocumentProcessor As New PdfDocumentProcessor()
pdfDocumentProcessor.LoadDocument("Documents/FirstLookExported.pdf")
' Obtain the first page area
Dim pageBox = pdfDocumentProcessor.Document.Pages(0).CropBox
Dim pagePosition1 As New PdfDocumentPosition(1, pageBox.TopLeft)
Dim pagePosition2 As New PdfDocumentPosition(1, pageBox.BottomRight)
Dim pageContentArea = PdfDocumentArea.Create(pagePosition1, pagePosition2)
' Translate the page content to Spanish
Dim translation As String = Await docProcessingService.TranslateAsync(
pdfDocumentProcessor,
pageContentArea,
New CultureInfo("es-ES"))
' Insert a new page and add the translated text
Dim page As PdfPage = pdfDocumentProcessor.InsertNewPage(1, PdfPaperSize.Letter)
Dim pageSize As PdfRectangle = page.CropBox
AddContentToPage(pdfDocumentProcessor, page, pageSize, translation)
' Save the modified document
pdfDocumentProcessor.SaveDocument("result.pdf")
End Using
' This method draws text on the inserted page
Private Sub AddContentToPage(
pdfDocumentProcessor As PdfDocumentProcessor,
page As PdfPage,
pageSize As PdfRectangle,
text As String)
Using graphics As PdfGraphics = pdfDocumentProcessor.CreateGraphicsWorldSystem()
Using textBrush As New DXSolidBrush(Color.FromArgb(255, Color.DarkOrange))
Dim font As New DXFont("Segoe UI", 12, DXFontStyle.Regular)
' Calculate text size
Dim textSize As SizeF = graphics.MeasureString(
text,
font,
New PdfStringFormat())
' Calculate an area to draw the text
Dim textPoint As New PointF(0, CSng(pageSize.Height - 10))
Dim rectangle As New RectangleF(
0,
10,
CSng(pageSize.Width),
CSng(pageSize.Height / 2))
' Draw text at the calculated area
graphics.DrawString(text, font, textBrush, rectangle)
graphics.AddToPageForeground(page)
End Using
End Using
End Sub
The following code snippet translates the first slide in a presentation:
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.Docs.Presentation;
using Microsoft.Extensions.AI;
// See "Register AI extension service" section for implementation code
docProcessingService docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService();
var presentation =
new Presentation(File.ReadAllBytes("Documents/Presentation.pptx"));
await docProcessingService.TranslateAsync(
presentation.Slides[0],
new System.Globalization.CultureInfo("DE-DE"));
// Save the modified document
FileStream outputStream = File.OpenWrite(
Path.Combine(
Path.Combine(
Environment.CurrentDirectory,
$"presentation_translated.pptx")));
presentation.SaveDocument(outputStream, DocumentFormat.Pptx);
outputStream.Close();
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.Docs.Presentation
Imports Microsoft.Extensions.AI
Imports System.Globalization
Imports System.IO
' See "Register AI extension service" section for implementation code
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService()
Dim presentation As New Presentation(File.ReadAllBytes("Documents/Presentation.pptx"))
Await docProcessingService.TranslateAsync(
presentation.Slides(0),
New CultureInfo("DE-DE"))
' Save the modified document
Dim outputStream As FileStream = File.OpenWrite(Path.Combine(Environment.CurrentDirectory, "presentation_translated.pptx"))
presentation.SaveDocument(outputStream, DocumentFormat.Pptx)
outputStream.Close()
Call SummarizeAsync to obtain a short summary (entire document/presentation or selected part). The following summarization modes are available:
Abstractive Summarization Understands original text context and rephrases it in a new, concise form. The AI “writes” a new summary based on its understanding and generates new sentences (instead of reusing the original wording). Extractive Summarization Selects and extracts key sentences/phrases from the original text. The AI identifies the most important content parts and combines them into a summary without altering the original wording.
The following code snippet obtains an AI-generated summary of a Word document and inserts it at the start:
using DevExpress.AIIntegration.Docs;
using DevExpress.XtraRichEdit;
using DevExpress.XtraRichEdit.API.Native;
// See "Register AI extension service" section for implementation code
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService();
var wordProcessor = new RichEditDocumentServer();
wordProcessor.LoadDocument("Documents/FirstLookShortened.docx");
string summary = await docProcessingService.SummarizeAsync(
wordProcessor,
SummarizationMode.Extractive,
CancellationToken.None);
wordProcessor.Document.Paragraphs.Insert(wordProcessor.Document.Paragraphs[0].Range.Start);
Paragraph summaryParagraph = wordProcessor.Document.Paragraphs[0];
// This method resets formatting for the inserted paragraph
ClearFormatting(summaryParagraph);
wordProcessor.Document.InsertText(
summaryParagraph.Range.Start,
"Document Summary:\n" + summary);
wordProcessor.SaveDocument("Documents/SummarizationResult.docx", DocumentFormat.Docx);
void ClearFormatting(Paragraph paragraph)
{
CharacterProperties cp = wordProcessor.Document.BeginUpdateCharacters(paragraph.Range);
cp.Reset();
cp.Style = wordProcessor.Document.CharacterStyles["Normal"];
wordProcessor.Document.EndUpdateCharacters(cp);
ParagraphProperties pp = wordProcessor.Document.BeginUpdateParagraphs(paragraph.Range);
pp.Reset();
pp.Style = wordProcessor.Document.ParagraphStyles["Normal"];
wordProcessor.Document.EndUpdateParagraphs(pp);
}
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.XtraRichEdit
Imports DevExpress.XtraRichEdit.API.Native
Imports System.Threading.Tasks
Imports System.Threading
Async Function Main() As Task
' See "Register AI extension service" section for implementation code
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService()
Dim wordProcessor As New RichEditDocumentServer()
wordProcessor.LoadDocument("Documents/FirstLookShortened.docx")
Dim summary As String = Await docProcessingService.SummarizeAsync( _
wordProcessor, _
SummarizationMode.Extractive, _
CancellationToken.None)
wordProcessor.Document.Paragraphs.Insert(wordProcessor.Document.Paragraphs(0).Range.Start)
Dim summaryParagraph As Paragraph = wordProcessor.Document.Paragraphs(0)
' This method resets formatting of the obtained paragraph
ClearFormatting(wordProcessor, summaryParagraph)
wordProcessor.Document.InsertText( _
summaryParagraph.Range.Start, _
"Document Summary:" & vbLf & summary)
wordProcessor.SaveDocument("Documents/SummarizationResult.docx", DocumentFormat.Docx)
End Function
Sub ClearFormatting(wordProcessor As RichEditDocumentServer, paragraph As Paragraph)
Dim cp As CharacterProperties = wordProcessor.Document.BeginUpdateCharacters(paragraph.Range)
cp.Reset()
cp.Style = wordProcessor.Document.CharacterStyles("Normal")
wordProcessor.Document.EndUpdateCharacters(cp)
Dim pp As ParagraphProperties = wordProcessor.Document.BeginUpdateParagraphs(paragraph.Range)
pp.Reset()
pp.Style = wordProcessor.Document.ParagraphStyles("Normal")
wordProcessor.Document.EndUpdateParagraphs(pp)
End Sub
The following code snippet retrieves a summary and inserts it into a newly added first page:
using DevExpress.AIIntegration.Docs;
using DevExpress.Drawing;
using DevExpress.Pdf;
using System.Drawing;
// See "Register AI extension service" section for implementation code
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService();
using var pdfDocumentProcessor = new PdfDocumentProcessor();
pdfDocumentProcessor.LoadDocument("Documents/FirstLookExported.pdf");
string summary = await docProcessingService.SummarizeAsync(
pdfDocumentProcessor,
SummarizationMode.Extractive,
CancellationToken.None);
PdfPage page = pdfDocumentProcessor.InsertNewPage(1, PdfPaperSize.Letter);
PdfRectangle pageSize = page.CropBox;
AddContentToPage(pdfDocumentProcessor, page, pageSize, summary);
pdfDocumentProcessor.SaveDocument("result.pdf");
// This method draws text on the inserted page
void AddContentToPage(PdfDocumentProcessor pdfDocumentProcessor, PdfPage page,
PdfRectangle pageSize, string text) {
using (PdfGraphics graphics = pdfDocumentProcessor.CreateGraphicsWorldSystem())
{
using (var textBrush = new DXSolidBrush(Color.FromArgb(255, Color.DarkOrange)))
{
DXFont font = new DXFont("Segoe UI", 12, DXFontStyle.Regular);
// Calculate text size
SizeF textSize = graphics.MeasureString(text, font, new PdfStringFormat());
// Calculate an area to draw the text
PointF textPoint = new PointF(0, (float)(pageSize.Height - 10));
RectangleF rectangle = new RectangleF(
0, 10,
(float)pageSize.Width,
(float)(pageSize.Height / 2));
// Draw text at the calculated area
graphics.DrawString(text, font, textBrush, rectangle);
graphics.AddToPageForeground(page);
}
}
}
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.Drawing
Imports DevExpress.Pdf
Imports System.Drawing
Async Function Main() As Task
' See "Register AI extension service" section for implementation code
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService()
Using pdfDocumentProcessor As New PdfDocumentProcessor()
pdfDocumentProcessor.LoadDocument("Documents/FirstLookExported.pdf")
Dim summary As String = Await docProcessingService.SummarizeAsync( _
pdfDocumentProcessor, _
SummarizationMode.Extractive, _
CancellationToken.None)
Dim page As PdfPage = pdfDocumentProcessor.InsertNewPage(1, PdfPaperSize.Letter)
Dim pageSize As PdfRectangle = page.CropBox
AddContentToPage(pdfDocumentProcessor, page, pageSize, summary)
pdfDocumentProcessor.SaveDocument("result.pdf")
End Using
End Function
' This method draws text on the inserted page
Private Sub AddContentToPage(pdfDocumentProcessor As PdfDocumentProcessor, page As PdfPage, pageSize As PdfRectangle, text As String)
Using graphics As PdfGraphics = pdfDocumentProcessor.CreateGraphicsWorldSystem()
Using textBrush As New DXSolidBrush(Color.FromArgb(255, Color.DarkOrange))
Dim font As New DXFont("Segoe UI", 12, DXFontStyle.Regular)
' Calculate text size
Dim textSize As SizeF = graphics.MeasureString(text, font, New PdfStringFormat())
' Calculate an area to draw the text
Dim textPoint As New PointF(0, CSng(pageSize.Height - 10))
Dim rectangle As New RectangleF( _
0, 10, _
CSng(pageSize.Width), _
CSng(pageSize.Height / 2))
' Draw text at the calculated area
graphics.DrawString(text, font, textBrush, rectangle)
graphics.AddToPageForeground(page)
End Using
End Using
End Sub
The following code snippet obtains an AI-generated summary and adds it to the first slide:
using DevExpress.AIIntegration.Docs;
using DevExpress.Docs.Presentation;
using System.Drawing;
// See "Register AI extension service" section for implementation code
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService();
var presentation = new Presentation(File.ReadAllBytes("Documents/Presentation.pptx"));
string summary = await docProcessingService.SummarizeAsync(
presentation,
SummarizationMode.Extractive,
CancellationToken.None);
Slide slide = new Slide(new SlideLayout(layoutType: SlideLayoutType.Blank, name: "slide"));
AddTextToSlide(slide, summary);
presentation.Slides.Insert(0, slide);
string targetDir = @"C:\Test Documents";
Directory.CreateDirectory(targetDir); // Safe if already exists
string outputPath = Path.Combine(targetDir, "presentation.pptx");
using (FileStream outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
{
presentation.SaveDocument(outputStream, DocumentFormat.Pptx);
}
void AddTextToSlide(Slide slide, string text)
{
Shape shape = new Shape(ShapeType.Rectangle);
shape.X = 0; shape.Y = 0;
shape.Width = presentation.SlideSize.Width;
shape.Height = presentation.SlideSize.Height;
shape.TextArea = new TextArea
{
Text = $"Summary by DevExpress AI Extensions:\r\n{text}",
ParagraphProperties = new ParagraphProperties
{
TextProperties = new TextProperties {
Fill = new SolidFill(Color.FromArgb(168, 177, 184)),
FontSize = 24
}
},
Properties = new TextAreaProperties
{
AutoFit = TextAutoSize.Shape
}
};
shape.Fill = new SolidFill(Color.FromArgb(21, 25, 28));
shape.Outline = new LineStyle { Fill = new SolidFill(Color.FromArgb(21, 25, 28)) };
slide.Shapes.Add(shape);
}
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.Docs.Presentation
Imports System.Drawing
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
' See "Register AI extension service" section for implementation code
var docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService()
Async Function Main() As Task
Dim presentation = New Presentation(File.ReadAllBytes("Documents/Presentation.pptx"))
Dim summary As String = Await docProcessingService.SummarizeAsync( _
presentation, _
SummarizationMode.Extractive, _
CancellationToken.None)
Dim slide As New Slide(New SlideLayout(layoutType:=SlideLayoutType.Blank, name:="slide"))
AddTextToSlide(slide, summary, presentation)
presentation.Slides.Insert(0, slide)
Dim targetDir As String = "C:\Test Documents"
Directory.CreateDirectory(targetDir) ' Safe if already exists
Dim outputPath As String = Path.Combine(targetDir, "presentation.pptx")
Using outputStream As New FileStream(outputPath, FileMode.Create, FileAccess.Write)
presentation.SaveDocument(outputStream, DocumentFormat.Pptx)
End Using
End Function
Sub AddTextToSlide(slide As Slide, text As String, presentation As Presentation)
Dim shape As New Shape(ShapeType.Rectangle)
shape.X = 0
shape.Y = 0
shape.Width = presentation.SlideSize.Width
shape.Height = presentation.SlideSize.Height
shape.TextArea = New TextArea With {
.Text = $"Summary by DevExpress AI Extensions:{vbCrLf}{text}",
.ParagraphProperties = New ParagraphProperties With {
.TextProperties = New TextProperties With {
.Fill = New SolidFill(Color.FromArgb(168, 177, 184)),
.FontSize = 24
}
},
.Properties = New TextAreaProperties With {
.AutoFit = TextAutoSize.Shape
}
}
shape.Fill = New SolidFill(Color.FromArgb(21, 25, 28))
shape.Outline = New LineStyle With {
.Fill = New SolidFill(Color.FromArgb(21, 25, 28))
}
slide.Shapes.Add(shape)
End Sub
Use AskAIAsync to submit a natural language question about the loaded document or presentation.
The Ask AI extension retrieves relevant content chunks (RAG) and generates a grounded response. Use the RagOptions settings to fine-tune response generation. You can pass this RagOptions object as the AskAIAsync method parameter. The following options are available:
| Property | Description | Default Value |
|---|---|---|
| ChunkSize | Sets the maximum number of characters in each content chunk. | 1000 |
| AugmentationChunkCount | Sets the number of most relevant chunks. | 5 |
| RebuildEmbeddings | Specifies whether to regenerate vector embeddings for document chunks. | |
| Regeneration may be required if the document content was changed. | true | |
| VectorDimensions | Sets the dimensionality of vector embeddings. | 1536 |
| VectorCollectionName | Sets the logical name of the vector collection (index) that stores embeddings. | "default_collection" |
Register an embedding generator and a vector store before using a specific vector collection. You can use any vector store that implements the IVectorStore interface to store embeddings. Refer to the following topics for more information: Available vector database solutions
The following code snippet registers an embedding generator and a vector store in the AI container. This code snippet uses API from the Microsoft.SemanticKernel.Connectors.InMemory NuGet package.
using Azure.AI.OpenAI;
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;
string openAiKey = "<AZURE_OPENAI_API_KEY>";
string openAiEndpoint = "<YOUR_AZURE_OPENAI_ENDPOINT>";
var clientModel = "gpt-4o-mini";
var embeddingClientName = "text-embedding-3-small";
AIIntegration.ChunkMaxLength = 6000;
var azureClient = new AzureOpenAIClient(
new Uri(openAiEndpoint),
new System.ClientModel.ApiKeyCredential(openAiKey));
var chatClient = azureClient.GetChatClient(clientModel).AsIChatClient();
// Create an in-memory vector store.
VectorStore store = new InMemoryVectorStore();
// Get the embedding client for the specified model
// and wrap it as an IEmbeddingGenerator.
var embeddingClient = azureClient.GetEmbeddingClient(embeddingClientName).AsIEmbeddingGenerator();
// Configure the dependency injection container.
var serviceProvider = new ServiceCollection()
// Register the chat client, embedding generator
// and a vector store as a singleton.
.AddSingleton(chatClient)
.AddSingleton<IEmbeddingGenerator>(embeddingClient)
.AddSingleton(store)
.AddDevExpressAIConsole() // Add DevExpress AI Console services.
.BuildServiceProvider(); // Build the service provider.
vbnet
Imports Azure.AI.OpenAI
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports Microsoft.Extensions.AI
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.Extensions.VectorData
Imports Microsoft.SemanticKernel.Connectors.InMemory
Imports System
Sub Main()
Dim openAiKey As String = "<AZURE_OPENAI_API_KEY>"
Dim openAiEndpoint As String = "<YOUR_AZURE_OPENAI_ENDPOINT>"
Dim clientModel As String = "gpt-4o-mini"
Dim embeddingClientName As String = "text-embedding-3-small"
AIIntegration.ChunkMaxLength = 6000
Dim azureClient = New AzureOpenAIClient(
New Uri(openAiEndpoint),
New System.ClientModel.ApiKeyCredential(openAiKey))
Dim chatClient = azureClient.GetChatClient(clientModel).AsIChatClient()
' Create an in-memory vector store.
Dim store As VectorStore = New InMemoryVectorStore()
' Get the embedding client for the specified model
' and wrap it as an IEmbeddingGenerator.
Dim embeddingClient = azureClient.GetEmbeddingClient(embeddingClientName).AsIEmbeddingGenerator()
' Configure the dependency injection container.
Dim serviceProvider = New ServiceCollection() _
.AddSingleton(chatClient) _
.AddSingleton(Of IEmbeddingGenerator)(embeddingClient) _
.AddSingleton(store) _
.AddDevExpressAIConsole() _
.BuildServiceProvider()
End Sub
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.XtraRichEdit;
using Microsoft.Extensions.AI;
using Microsoft.SemanticKernel.Connectors.InMemory;
AIIntegration.ChunkMaxLength = 6000;
string openAiKey = "<AZURE_OPENAI_API_KEY>";
string openAiEndpoint = "<YOUR_AZURE_OPENAI_ENDPOINT>";
var clientModel = "gpt-4o-mini";
var embeddingClientName = "text-embedding-3-small";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var azureOpenAIClient = new Azure.AI.OpenAI.AzureOpenAIClient(
new Uri(openAiEndpoint), new System.ClientModel.ApiKeyCredential(openAiKey));
IChatClient chatClient = azureOpenAIClient.GetChatClient(clientModel).AsIChatClient();
builder.Services.AddSingleton(chatClient);
// Get the embedding client for the specified model
// and wrap it as an IEmbeddingGenerator.
IEmbeddingGenerator embeddingClient = azureOpenAIClient
.GetEmbeddingClient(embeddingClientName)
.AsIEmbeddingGenerator();
// Register the embedding generator
// and a vector store as a singleton.
builder.Services.AddSingleton(embeddingClient);
builder.Services.AddSingleton<Microsoft.Extensions.VectorData.VectorStore>(new InMemoryVectorStore());
var app = builder.Build();
The following code snippet asks a question about the document content, configures RAG options (chunk size, collection name, chunk count), and inserts the AI‑generated answer as a comment about the first paragraph:
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.XtraRichEdit;
using Microsoft.Extensions.AI;
// See "Register AI extension service" section for implementation code
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService();
var options = new RagOptions {
VectorCollectionName = "document_embeddings",
ChunkSize = 800,
AugmentationChunkCount = 8
};
using (var wordProcessor = new RichEditDocumentServer()) {
wordProcessor.LoadDocument(@"Documents/Document1.docx");
string answer = await docProcessingService.AskAIAsync(
wordProcessor,
"Does this document contain any confidential information?",
options
);
wordProcessor.Document.Comments.Create(
wordProcessor.Document.Paragraphs[0].Range,
"AI Summary:\n" + answer);
wordProcessor.SaveDocument("Documents/Document_commented.docx", DocumentFormat.Docx);
}
vbnet
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.XtraRichEdit
Imports Microsoft.Extensions.AI
' See "Register AI extension service" section for implementation code
Dim docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService()
Dim options As New RagOptions With {
.VectorCollectionName = "document_embeddings",
.ChunkSize = 800,
.AugmentationChunkCount = 8
}
Using wordProcessor As New RichEditDocumentServer()
wordProcessor.LoadDocument("Documents/Document1.docx")
Dim answer As String = Await docProcessingService.AskAIAsync(
wordProcessor,
"Does this document contain any confidential information?",
options
)
wordProcessor.Document.Comments.Create(
wordProcessor.Document.Paragraphs(0).Range,
"AI Summary:" & vbLf & answer)
wordProcessor.SaveDocument("Documents/Document_commented.docx", DocumentFormat.Docx)
End Using
The following code snippet asks a contextual question about the PDF file, configures RAG options (chunk size, collection name, chunk count), and adds the answer as a sticky note annotation:
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.Pdf;
using Microsoft.Extensions.AI;
// See "Register AI extension service" section for implementation code
var docProcessingService =
defaultAIExtensionsContainer.CreateAIDocProcessingService();
var options = new RagOptions {
VectorCollectionName = "knowledge_base_vectors",
ChunkSize = 600,
AugmentationChunkCount = 7
};
using (var pdfDocumentProcessor = new PdfDocumentProcessor()) {
FileStream fs = File.OpenRead(
Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
@"Documents/Document1.pdf"));
pdfDocumentProcessor.LoadDocument(fs, true);
fs.Close();
string result =
await docProcessingService.AskAIAsync(
pdfDocumentProcessor,
"What terms does this document contain?",
options);
// Access the first page properties
PdfPageFacade page = pdfDocumentProcessor.DocumentFacade.Pages[0];
// Add sticky note at the specified point
PdfTextAnnotationFacade textAnnotation =
page.AddTextAnnotation(
new PdfPoint(64, 65),
PdfTextAnnotationIconName.Comment);
// Specify annotation parameters
textAnnotation.Author = "AI-Generated";
textAnnotation.Color = new PdfRGBColor(0.8, 0.2, 0.1);
textAnnotation.Contents = result;
// Save the modified document
string outputFilePath =
Path.Combine(Environment.CurrentDirectory, $"Document1_Annotated.pdf");
pdfDocumentProcessor.SaveDocument(outputFilePath);
}
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.Pdf
Imports Microsoft.Extensions.AI
Imports System.IO
' See "Register AI extension service" section for implementation code
Dim docProcessingService = defaultAIExtensionsContainer.CreateAIDocProcessingService()
Dim options As New RagOptions With {
.VectorCollectionName = "knowledge_base_vectors",
.ChunkSize = 600,
.AugmentationChunkCount = 7
}
Using pdfDocumentProcessor As New PdfDocumentProcessor()
Dim fs As FileStream = File.OpenRead(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Documents\Document1.pdf"))
pdfDocumentProcessor.LoadDocument(fs, True)
fs.Close()
Dim result As String = Await docProcessingService.AskAIAsync(pdfDocumentProcessor, "What terms does this document contain?", options)
' Access the first page properties
Dim page As PdfPageFacade = pdfDocumentProcessor.DocumentFacade.Pages(0)
' Add sticky note at the specified point
Dim textAnnotation As PdfTextAnnotationFacade = page.AddTextAnnotation(New PdfPoint(64, 65), PdfTextAnnotationIconName.Comment)
' Specify annotation parameters
textAnnotation.Author = "AI-Generated"
textAnnotation.Color = New PdfRGBColor(0.8, 0.2, 0.1)
textAnnotation.Contents = result
' Save the modified document
Dim outputFilePath As String = Path.Combine(Environment.CurrentDirectory, "Document1_Annotated.pdf")
pdfDocumentProcessor.SaveDocument(outputFilePath)
End Using
The following code snippet asks a question about the document content, configures RAG options (chunk size, collection name, chunk count), and inserts the AI‑generated answer as content in the first slide:
using DevExpress.AIIntegration;
using DevExpress.AIIntegration.Docs;
using DevExpress.Docs.Presentation;
using Microsoft.Extensions.AI;
// Create a document processing service instance
// from the AI extensions container.
var docProcessingService = new AIDocProcessingService(defaultAIExtensionsContainer);
var options = new RagOptions
{
VectorCollectionName = "document_embeddings",
ChunkSize = 800,
AugmentationChunkCount = 8
};
var presentation = new Presentation(File.ReadAllBytes("Documents/Presentation.pptx"));
string summary = await docProcessingService.AskAIAsync(
presentation,
"Does this document contain any confidential information?",
options);
Slide slide = new Slide(new SlideLayout(layoutType: SlideLayoutType.Blank, name: "slide"));
AddTextToSlide(slide, summary);
presentation.Slides.Insert(0, slide);
string targetDir = @"C:\Test Documents";
Directory.CreateDirectory(targetDir);
string outputPath = Path.Combine(targetDir, "presentation.pptx");
using (FileStream outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
{
presentation.SaveDocument(outputStream, DocumentFormat.Pptx);
}
void AddTextToSlide(Slide slide, string text)
{
Shape shape = new Shape(ShapeType.Rectangle);
shape.X = 0; shape.Y = 0;
shape.Width = presentation.SlideSize.Width;
shape.Height = presentation.SlideSize.Height;
shape.TextArea = new TextArea
{
Text = $"Summary by DevExpress AI Extensions:\r\n{text}",
ParagraphProperties = new ParagraphProperties
{
TextProperties = new TextProperties
{
Fill = new SolidFill(Color.FromArgb(168, 177, 184)),
FontSize = 24
}
},
Properties = new TextAreaProperties
{
AutoFit = TextAutoSize.Shape
}
};
shape.Fill = new SolidFill(Color.FromArgb(21, 25, 28));
shape.Outline = new LineStyle { Fill = new SolidFill(Color.FromArgb(21, 25, 28)) };
slide.Shapes.Add(shape);
}
Imports DevExpress.AIIntegration
Imports DevExpress.AIIntegration.Docs
Imports DevExpress.Docs.Presentation
Imports Microsoft.Extensions.AI
Imports System.IO
Imports System.Drawing
' Create a document processing service instance
' from the AI extensions container.
Dim docProcessingService As New AIDocProcessingService(defaultAIExtensionsContainer)
Dim options As New RagOptions With {
.VectorCollectionName = "document_embeddings",
.ChunkSize = 800,
.AugmentationChunkCount = 8
}
Dim presentation As New Presentation(File.ReadAllBytes("Documents/Presentation.pptx"))
Dim summary As String = Await docProcessingService.AskAIAsync(
presentation,
"Does this document contain any confidential information?",
options)
Dim slide As New Slide(New SlideLayout(layoutType:=SlideLayoutType.Blank, name:="slide"))
AddTextToSlide(slide, summary)
presentation.Slides.Insert(0, slide)
Dim targetDir As String = "C:\Test Documents"
Directory.CreateDirectory(targetDir)
Dim outputPath As String = Path.Combine(targetDir, "presentation.pptx")
Using outputStream As New FileStream(outputPath, FileMode.Create, FileAccess.Write)
presentation.SaveDocument(outputStream, DocumentFormat.Pptx)
End Using
Private Sub AddTextToSlide(slide As Slide, text As String)
Dim shape As New Shape(ShapeType.Rectangle) With {
.X = 0,
.Y = 0,
.Width = presentation.SlideSize.Width,
.Height = presentation.SlideSize.Height,
.TextArea = New TextArea With {
.Text = $"Summary by DevExpress AI Extensions:{vbCrLf}{text}",
.ParagraphProperties = New ParagraphProperties With {
.TextProperties = New TextProperties With {
.Fill = New SolidFill(Color.FromArgb(168, 177, 184)),
.FontSize = 24
}
},
.Properties = New TextAreaProperties With {
.AutoFit = TextAutoSize.Shape
}
},
.Fill = New SolidFill(Color.FromArgb(21, 25, 28)),
.Outline = New LineStyle With {
.Fill = New SolidFill(Color.FromArgb(21, 25, 28))
}
}
slide.Shapes.Add(shape)
End Sub
AI-powered extensions for DevExpress Office File API ship with the following limitations: