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!
Comments