Aniket
Feb 27, 2023
  3649
(0 votes)

ChatGPT/OpenAI integration for text generation using Prompt in Optimizely

Here's how you can use a simple publishing event to generate content using OpenAI.

The code is pretty simple - I will avoid getting into too many details as Tomas has done a wonderful job of explaining it in his blog post here:
https://www.gulla.net/en/blog/integrating-generative-ai-in-optimizely-cms-a-quick-test-with-openai/

...And from Allan here:
https://www.codeart.dk/blog/2022/11/ai-assisted-content-creation---in-optimizely-cms--commerce-ai-series---part-2/ 

Here's sample code which has been requested by a few people. 

namespace ClientName.CMS.Features.Sample
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    using System.Web;
    using EPiServer;
    using EPiServer.Core;
    using EPiServer.Framework;
    using EPiServer.Framework.Initialization;
    using EPiServer.ServiceLocation;
    using Newtonsoft.Json;
    using ClientName.CMS.Features.Basics.RichTextBlock.Models;
    using ClientName.Common.Features.Foundation.Threading.Utilities;

    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class OpenAIBlockInitialization : IInitializableModule
    {
        private static readonly HttpClient _client = new HttpClient();
        private readonly string _apiKey = "YOUR API KEY GOES HERE"; // You can generate it here: https://platform.openai.com/account/api-keys

        public void Initialize(InitializationEngine context)
        {
            // Add initialization logic, this method is called once after CMS has been initialized
            var contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            contentEvents.PublishingContent += ContentEvents_PublishingContent;
        }

        public async Task<dynamic> SendRequestAsync(string model, string prompt, int maxTokens)
        {
            var requestUrl = "https://api.openai.com/v1/engines/" + model + "/completions";
            var requestData = new
            {
                prompt = prompt,
                max_tokens = maxTokens
            };
            var jsonRequestData = JsonConvert.SerializeObject(requestData);
            var requestContent = new StringContent(jsonRequestData, System.Text.Encoding.UTF8, "application/json");

            _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiKey);

            var response = await _client.PostAsync(requestUrl, requestContent);
            response.EnsureSuccessStatusCode();

            var responseContent = await response.Content.ReadAsStringAsync();
            var responseData = JsonConvert.DeserializeObject<dynamic>(responseContent);

            return responseData;
        }

        private void ContentEvents_PublishingContent(object sender, EPiServer.ContentEventArgs e)
        {
            try
            {
                if (e.Content != null)
                {
                    if (e.Content is RichTextBlock richTextBlock)
                    {
                        var blockData = e.Content as RichTextBlock;

                        string textToOpenAI = blockData.OpenAIPrompt;

                        // Call Open AI and get results
                        var response = AsyncHelper.RunSync(async () => await SendRequestAsync("text-davinci-003", textToOpenAI, 3000));

                        blockData.OpenAIGeneratedText = response?.choices[0]?.text;
                    }
                }
            }
            catch (Exception ex)
            {
                // Optinal logging
            }
        }

        public void Uninitialize(InitializationEngine context)
        {
            // Add uninitialization logic
            var contentEvents = ServiceLocator.Current.GetInstance<IContentEvents>();
            contentEvents.PublishingContent -= ContentEvents_PublishingContent;
        }
    }
}

AsyncHelper class to run async method synchronously (due to initialization functions limitations)

namespace ClientName.Common.Features.Foundation.Threading.Utilities
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    public static class AsyncHelper
    {
        private static readonly TaskFactory TaskFactory =
            new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);

        /// <summary>
        /// Executes an async Task method which has a void return value synchronously
        /// USAGE: AsyncUtil.RunSync(() => AsyncMethod());
        /// </summary>
        /// <param name="task">Task method to execute</param>
        public static void RunSync(Func<Task> task) => TaskFactory.StartNew(task).Unwrap().GetAwaiter().GetResult();

        /// <summary>
        /// Executes an async Task<T> method which has a T return type synchronously
        /// USAGE: T result = AsyncUtil.RunSync(() => AsyncMethod<T>());
        /// </summary>
        /// <typeparam name="TResult">Return Type</typeparam>
        /// <param name="task">Task<T> method to execute</param>
        /// <returns></returns>
        public static TResult RunSync<TResult>(Func<Task<TResult>> task) =>
            TaskFactory.StartNew(task).Unwrap().GetAwaiter().GetResult();
    }
}

Happy coding!

Feb 27, 2023

Comments

Please login to comment.
Latest blogs
Understanding Optimizely Opal Cost

Opal pricing are transparent at large extent, It is based on a credit consumption model rather than fixed per-user licensing or tokens consumptions...

K Khan | May 25, 2026

Optimizely CMS 12 Now Fully Supports .NET 10

This is the latest installment in our ongoing series covering .NET version support for Optimizely products. If you've been following along, you may...

Bien Nguyen | May 25, 2026

Optimizely Opal: How to Build Effective Workflow Agents

If you're building workflow agents in Optimizely Opal, this post covers how specialized agents pass context to each other, why keeping agents small...

Andre | May 20, 2026

ReviewPR: An Azure Function That Reviews Your Azure DevOps Pull Requests With Claude

A while back I wrote about an  Azure Function App for PDF creation that we use to offload PDF rendering from our Optimizely DXP site. That same...

KennyG | May 19, 2026

Accelerating Optimizely CMS and Commerce upgrades with agentic AI (Part 2 of 2)

The Real Transformation in Optimizely CMS 13: Why the Upgrade Itself Is the Easy Part. A field-tested playbook for enterprise teams moving from...

Hung Le Hoang | May 18, 2026

Is the most powerful AI model really the best value?

Artificial Intelligence is already becoming part of everyday software development. Developers now use AI tools to generate code, write documentatio...

K Khan | May 16, 2026