Quantcast
Channel: Developer Express Inc.
Viewing all articles
Browse latest Browse all 2370

Office File API — Enhance Accessibility in Office Documents using OpenAI Models (Part 2)

$
0
0

In our last AI-related post, we described how to generate AltText (meaningful descriptions) for images and charts using DevExpress Office File API libraries and Azure AI OpenAI service (Office File API — Enhance Accessibility in Office Documents (Word & Excel) using OpenAI Models).  In this post, I’ll explain how to generate hyperlink descriptions for Word and Excel files.

When you generate accessible Word or Excel documents, it’s essential to create hyperlinks with meaningful screentips. Meaningful screentips help individuals with visual impairments or those using screen readers understand the purpose of the hyperlink, add clarity, and enhance document navigation. Additionally, hyperlink screentips are important when you export documents to the Accessible PDF format, aligning with accessibility standards (WCAG). With the help of the DevExpress Word Processing Document API and Spreadsheet Document API libraries, you can locate document hyperlinks that do not offer accessible descriptions and generate these descriptions using OpenAI models.

We added two new endpoints for this capability in our sample project on GitHub: Office File API – Integrate AI to Generate Accessible Descriptions.  I'll detail implementation steps below...

Implement OpenAI Model API

Before you incorporate this solution in your app, please be sure to read and understand OpenAI's license agreement and terms of use.

This step is similar to the one we already demonstrated in our previous AI-related blog post. Install the Azure.AI.OpenAI NuGet package in your project and use OpenAI APIs to send requests.

This code snippet sends a request to describe a hyperlink URI and obtain a string with a response.

publicclassOpenAIClientHyperlinkHelper
{
    OpenAIClient client;
    internalOpenAIClientHyperlinkHelper(string openAIApiKey)
    {
        client = new OpenAIClient(openAIApiKey, new OpenAIClientOptions());
    }
    internalasync Task<string> DescribeHyperlinkAsync(string link)
    {
        ChatCompletionsOptions chatCompletionsOptions = new()
        {
            DeploymentName = "gpt-4-vision-preview",
            Messages =
            {
                new ChatRequestSystemMessage("You are a helpful assistant that describes hyperlinks."),
                new ChatRequestUserMessage(
                    new ChatMessageTextContentItem("Give a description for this hyperlink URI in 10-20 words"),
                    new ChatMessageTextContentItem(link))
            },
            MaxTokens = 300
        };

        Response<ChatCompletions> chatResponse = await client.GetChatCompletionsAsync(chatCompletionsOptions);
        ChatChoice choice = chatResponse.Value.Choices[0];
        return choice.Message.Content;
    }
}

Word Processing Document API Endpoint

To use the API above within your DevExpress-powered Word Processing Document API application, access the Document.Hyperlinks collection to retrieve document hyperlinks. Check whether document hyperlinks include sceentips (the Hyperlink.ToolTip property value shouldn't be empty or equal to the Hyperlink.NavigateUri value). Otherwise, call the OpenAIClientHyperlinkHelper.DescribeHyperlinkAsync method to generate a hyperlink description.

public async Task<IActionResult> GenerateHyperlinkDescriptionForWord(IFormFile documentWithHyperlinks, [FromQuery] RichEditFormat outputFormat)
{
    try
    {
        var hyperlinkHelper = new OpenAIClientHyperlinkHelper(openAIApiKey);
        using (var wordProcessor = new RichEditDocumentServer())
        {
            await RichEditHelper.LoadFile(wordProcessor, documentWithHyperlinks);

            wordProcessor.IterateSubDocuments(async (document) =>
            {
                foreach (var hyperlink in document.Hyperlinks)
                {
                    if (string.IsNullOrEmpty(hyperlink.ToolTip) || hyperlink.ToolTip == hyperlink.NavigateUri)
                    {
                        hyperlink.ToolTip = hyperlinkHelper.DescribeHyperlinkAsync(hyperlink.NavigateUri).Result;
                    }
                }
            });
            Stream result = RichEditHelper.SaveDocument(wordProcessor, outputFormat);
            string contentType = RichEditHelper.GetContentType(outputFormat);
            string outputStringFormat = outputFormat.ToString().ToLower();
            return File(result, contentType, $"result.{outputStringFormat}");
        }
    }
    catch (Exception e)
    {
        return StatusCode(500, e.Message + Environment.NewLine + e.StackTrace);
    }
}

The following image shows the hyperlink description generated with this code.


Spreadsheet Document API Endpoint

For a DevExpress-powered Spreadsheet Document API application, iterate through document worksheets and access worksheet hyperlinks using the Worksheet.Hyperlinks collection. Once complete, you must determine whether the Hyperlink.TooltipText property meets the condition and call the OpenAIClientHyperlinkHelper.DescribeHyperlinkAsync method to generate a hyperlink description if required.

publicasync Task<IActionResult> GenerateHyperlinkDescriptionForSpreadsheet(IFormFile documentWithHyperlinks, [FromQuery] SpreadsheetFormat outputFormat)
{
    try
    {
        var hyperlinkHelper = new OpenAIClientHyperlinkHelper(openAIApiKey);
        using (var workbook = new Workbook())
        {
            await SpreadsheetHelper.LoadWorkbook(workbook, documentWithHyperlinks);

            foreach (var worksheet in workbook.Worksheets)
            {
                foreach (var hyperlink in worksheet.Hyperlinks)
                {
                    if(hyperlink.IsExternal && (string.IsNullOrEmpty(hyperlink.TooltipText) || hyperlink.TooltipText == hyperlink.Uri))
                    hyperlink.TooltipText = hyperlinkHelper.DescribeHyperlinkAsync(hyperlink.Uri).Result;
                }
            }

            Stream result = SpreadsheetHelper.SaveDocument(workbook, outputFormat);
            string contentType = SpreadsheetHelper.GetContentType(outputFormat);
            string outputStringFormat = outputFormat.ToString().ToLower();
            return File(result, contentType, $"result.{outputStringFormat}");
        }
    }
    catch (Exception e)
    {
        return StatusCode(500, e.Message + Environment.NewLine + e.StackTrace);
    }
}


As always, we welcome your feedback. We'd love to learn more about your AI-related usage requirements and what you are planning in this regard in the near term. 


Viewing all articles
Browse latest Browse all 2370

Trending Articles