Translate Microservice With ChatGPT .Net 7.0

Bora Kaşmer
Geek Culture
Published in
11 min readMar 11, 2023

--

Photo: Getty Images

Hi,

Today we will talk about, how to automize our daily routine with ChatGPT. Every day we create Turkish Email Template for the phishing simulators. We will translate this text template to English, German, and French by using ChatGPT automatically.

1-)OpenAI Account:

Firstly you have to get an account from OpenAI Api. You can get Api Key from the View API keys menu.

Your API Keys Screen must be like the below.

2-) Database

Let’s Create DatabaseTables:

LanguageType:

CREATE TABLE [dbo].[LanguageType](
[ID] [int] IDENTITY(1,1) NOT NULL,
[LanguageName] [nvarchar](50) NULL,
[CreatedDate] [datetime] NULL,
[IsDeleted] [bit] NULL,
CONSTRAINT [PK_LanguageType] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[LanguageType] ADD CONSTRAINT [DF_LanguageType_CreatedDate] DEFAULT (getdate()) FOR [CreatedDate]
GO

ALTER TABLE [dbo].[LanguageType] ADD CONSTRAINT [DF_LanguageType_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]
GO
Select * from LanguageType

MailTemplate:

  • MailText: String template
  • ParentID: We will put this ID for the current TurkishContext ID. Turkish Context is our ParentID. And all other translated languages are a child.
CREATE TABLE [dbo].[MailTemplate](
[ID] [int] IDENTITY(1,1) NOT NULL,
[MailText] [nvarchar](500) NULL,
[ParentID] [int] NOT NULL,
[LanguageID] [int] NULL,
[CreatedDate] [datetime] NULL,
[IsDeleted] [bit] NULL,
CONSTRAINT [PK_MailPhishingTemplate] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[MailTemplate] ADD CONSTRAINT [DF_MailTemplate_CreatedDate] DEFAULT (getdate()) FOR [CreatedDate]
GO

ALTER TABLE [dbo].[MailTemplate] ADD CONSTRAINT [DF_MailTemplate_IsDeleted] DEFAULT ((0)) FOR [IsDeleted]
GO

ALTER TABLE [dbo].[MailTemplate] WITH CHECK ADD CONSTRAINT [FK_MailTemplate_LanguageType] FOREIGN KEY([LanguageID])
REFERENCES [dbo].[LanguageType] ([ID])
GO

ALTER TABLE [dbo].[MailTemplate] CHECK CONSTRAINT [FK_MailTemplate_LanguageType]
GO

3-) Turkish Context Subscriber Console Application :

We will Create .Net 7.0 Console Application “ChatGPTInputText” and we will add DALChatGPT Project into the solution as seen below. For this application, we will take the DB First approach.

Add the below libraries to DALChatGPT Project from Nuget Manager.

We will create ChatDBContext under the DALChatGPT project from the “ChatGPT” Database as seen below. We will run the “scaffold” command under the “DalChatGPT” folder.

dotnet ef dbcontext scaffold "Server=.;Database=ChatGPT;Trusted_Connection=True;
Encrypt =False" Microsoft.EntityFrameworkCore.SqlServer -o Entities
--context-dir "Entities\DbContexts" --no-pluralize -c ChatGPTContext
This Is The Final Solution Picture

ChatGPTInputText/Program.cs:

  • Firstly add DALChatGPT as a Project Reference for DB operations.
  • Add RabbitMQ.Client from Nuget for Add EmialTemplate to RabbitMQ Channel.
  • If you use internal RabbitMQ, don’t forget to start RabbitMQ service on your local machine.
  • Get string Email Template from the console
Console.Write("Write Translate Email Template: ");
var textTRTemplate = Console.ReadLine();
  • This part is used for saving Email Template to DB. Firstly we will prepare service by Adding “<ChatGBTContext>” with SqlDB connection. And later we will use “BuilderServiceProvider” for getting “ChatGPTContext
try
{
//Save DB
var services = new ServiceCollection();
services.AddDbContext<ChatGPTContext>(options => options.UseSqlServer("Server=.;Database=ChatGPT;Trusted_Connection=True;TrustServerCertificate=True;"));

var serviceProvider = services.BuildServiceProvider();
ChatGPTContext _chatGPTContext = serviceProvider.GetService<ChatGPTContext>();
  • We will prepare to MailTemplate Entity as data. “ParentId” is zero because this is not a child this is a parent Turkish Mail Template. “LanguageID” is an enum. We set the default Turkish Language.
  • We will add MailTemplate “data” to the “_chatGPTContext.MailTemplate” context. And we will call SaveChanges() asynchronously for saving data to the SQL server.
  var data = new DALChatGPT.Entities.MailTemplate()
{
MailText = textTRTemplate,
IsDeleted = false,
CreatedDate = DateTime.Now,
ParentId = 0,
LanguageId = (int)LanguageType.Turkish
};
var result = await _chatGPTContext.MailTemplate.AddAsync(data);
await _chatGPTContext.SaveChangesAsync();
Console.WriteLine($"Mail Template Saved Successfully ID: {data.Id}");
//----------------------------

Enum.cs/LanguageType:

  public enum LanguageType
{
Turkish=1,
English=2,
German=3,
French=4
}
  • Now it is time to publish, the saved MailTemplate to the RabbitMQ channel. Firstly we will create ConnectionFactory with the RabbitMQ connection string. And later we will create a connection and channel by “using” the keyword it as a Scoped.
//Add RabbitMQ
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
  • We will create an EmailTemplate channel in local RabbitMQ.
  1. “queue”: Channel Name
  2. “durable”: It is determined whether the data will be stored in-memory or physically.
  3. “exclusive”: It is allowed to be used with other connections with the “exclusive” parameter.
  4. “autoDelete”: If the queue is marked as deleted and all consumers have finished using it, or if the last consumer is canceled or the channel is closed, deletion cannot be performed. In such cases, the “autoDelete” and the delete method are normally run. Thus, the corresponding queues are deleted.
  5. “arguments”: These keywords are the parameters to be defined related to the specified exchanges. Exchange is not defined in this application.
  • We will Serialize the EmailTemplate entity by using “System.Text.Json”, convert it to byte[] array, and set it to the body parameter.
 channel.QueueDeclare(queue: "EmailTemplate",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
var templateData = JsonSerializer.Serialize(data);
var body = Encoding.UTF8.GetBytes(templateData);
  • We will publish “templateData” to the “EmailTemplate” channel.
        channel.BasicPublish(exchange: "",
routingKey: "EmailTemplate",
basicProperties: null,
body: body);

Console.WriteLine($"Mail Template Add To The RabbitMQ EmailTemplate Channel");
}
//---------------------------
}
catch (Exception ex)
{
Console.Write($"Error Message: {ex.Message}");
}

Program.cs : Subscriber (Full Codes):

using ChatGPTInputText;
using DALChatGPT.Entities.DbContexts;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RabbitMQ.Client;
using System.Text;
using System.Text.Json;

Console.Write("Write Translate Email Template: ");
var textTRTemplate = Console.ReadLine();

try
{
//Save DB
var services = new ServiceCollection();
services.AddDbContext<ChatGPTContext>(options => options.UseSqlServer("Server=.;Database=Test;Trusted_Connection=True;TrustServerCertificate=True;"));

var serviceProvider = services.BuildServiceProvider();
ChatGPTContext _chatGPTContext = serviceProvider.GetService<ChatGPTContext>();

var data = new DALChatGPT.Entities.MailTemplate()
{
MailText = textTRTemplate,
IsDeleted = false,
CreatedDate = DateTime.Now,
ParentId = 0,
LanguageId = (int)LanguageType.Turkish
};
var result = await _chatGPTContext.MailTemplate.AddAsync(data);
await _chatGPTContext.SaveChangesAsync();
Console.WriteLine($"Mail Template Saved Successfully ID: {data.Id}");
//----------------------------

//Add RabbitMQ
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "EmailTemplate",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
var templateData = JsonSerializer.Serialize(data);
var body = Encoding.UTF8.GetBytes(templateData);

channel.BasicPublish(exchange: "",
routingKey: "EmailTemplate",
basicProperties: null,
body: body);

Console.WriteLine($"Mail Template Add To The RabbitMQ EmailTemplate Channel");
}
//---------------------------
}
catch (Exception ex)
{
Console.Write($"Error Message: {ex.Message}");
}

Artificial intelligence is one of the most profound things we’re working on as humanity. It is more profound than fire or electricity.” — Sundar Pichai ( CEO, Google)

Translate Consumer and ChatGPT Console Application :

We will create a new ConsoleApplication for getting EmailTemplate data from the queue and translate it to the multi-language[En, Ge, Fr] with ChatGPT.

Firstly we will add two below libraries. You can add the OpenAI library with below NuGet code. [Unofficial] Betalgo.OpenAI.Gpt3. You can find more information here. We will use this library for translating Email Templates into other languages.You have to use .Net 6.0 or bigger .Net frameworks for using the Gpt3 libraryFinallyRabbitMQ.Client” library is the same as the other console application. We will write RabbitMQ consumer with this library.

Install-Package Betalgo.OpenAI.GPT3

Database Context: We will use this context, for all DB operations.

  • Add the DALChatConsumer class library to the solution for the DBContext.
  • Install the same below libraries like other Console Application.
  • We will create ChatDBContext under DALChatConsumer project from the “ChatGPT” Database as seen below. We will run the “scaffold” command under the “DalChatConsumer” folder as before.
dotnet ef dbcontext scaffold "Server=.;Database=ChatGPT;Trusted_Connection=True;
Encrypt =False" Microsoft.EntityFrameworkCore.SqlServer -o Entities
--context-dir "Entities\DbContexts" --no-pluralize -c ChatGPTContext
This Final Result Of Solution
  1. Firstly we will create RabbitMQ Consumer for listening to the “Email Template” channel.
 static async Task Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "EmailTemplate",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);

var consumer = new EventingBasicConsumer(channel);

2. When we get an “Email Template” from the channel of RabbitMQ, we will deserialize data to the “MailTemplate”. Later we will create “gpt3” by using OpenAIService with your own “API Key”. And finally, we will loop in all LanguageType enums for translating to Template.

Not: “Don’t forget to Eliminate the default Turkish language. Because it is the root language. And we have already saved it to the DB”

 consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var data = Encoding.UTF8.GetString(body);
MailTemplate mailTemplate = JsonSerializer.Deserialize<MailTemplate>(data);
Console.WriteLine(" [x] Received Mail Template ID: {0}", mailTemplate.Id);

//ChatGPT
var gpt3 = new OpenAIService(new OpenAiOptions()
{
ApiKey = "***Your OpenAI Api Key***"
});
foreach (LanguageType lang in Enum.GetValues(typeof(LanguageType)))
{
if (lang == LanguageType.Turkish) continue; //Eliminate Turkish
Consumer & Subscriber

3. Now we have to create TranslateTextByLanguage() method, to not repeat the code for every language. And we will call it for every enum LanguageType.

  • CompletionCreateRequest” is so importent class for the gpt3 library. We will set all gpt3 ptoperties in this class.
  • Prompt:” This is the question, which we will ask to the gpt3. We will translate mailText with language parameter.
  • Model”: We have to select the gbt3 learning model. There are so many learning models in the OpenAI library. But the most expensive one is “TextDavinciV3”. And it is also the most successful one. This is a pre-trained model, that can generate text for us.
  • Temperature”: It is a parameter of OpenAI ChatGPT and GPT-3 models that govern the randomness and thus the creativity of the responses. It is always a number between 0 and 1.
  • MaxTokens”: Maximum word number. Tokens can be thought of as pieces of words. Before the API processes the prompts, the input is broken down into tokens. These tokens are not cut up exactly where the words start or end — tokens can include trailing spaces and even sub-words.
  • TopP”: “Top p” parameter is like a filter that controls how many different words or phrases the language model considers when it’s trying to predict the next word. If you set the “top p” value to 0.5, the language model will only consider the 50 most likely words or phrases that might come next. But if you set the “top p” value to 0.9, the language model will consider the 90 most likely words or phrases.
  • FrequencyPenalty”: Frequency penalty works by lowering the chances of a word being selected again the more times that word has already been used. Presence penalty does not consider how frequently a word has been used, but just if the word exists in the text.
  • PresencePenalty”: The OpenAI Presence Penalty setting is used to adjust how much the presence of tokens in the source material will influence the output of the model.
public static void TranslateTextByLanguage(OpenAIService gpt3, string mailText, LanguageType languageType, int parentID)
{
//English | German | French
var completionResult = gpt3.Completions.CreateCompletion(new CompletionCreateRequest()
{
Prompt = $"Can you translate this to {languageType} ? '{mailText}'",
Model = Models.TextDavinciV3,
Temperature = 0.7F,
MaxTokens = 512,
TopP = 1,
FrequencyPenalty = 0,
PresencePenalty = 0
});
SqlDB MailTemplate Table

4. “if (completionResult.Result.Successful)”: If we get a successful result from OpenAI, we will get the first choice from the result and save DB by LanguageID and ParentID. If we get an error, we will throw an exception and write a log.

 if (completionResult.Result.Successful)
{
var resultText = completionResult.Result.Choices.FirstOrDefault().Text.Trim();

//DB Operaitons
var services = new ServiceCollection();
services.AddDbContext<ChatGPTContext>(options => options.UseSqlServer("Server=.;Database=ChatGPT;Trusted_Connection=True;TrustServerCertificate=True;"));

var serviceProvider = services.BuildServiceProvider();
ChatGPTContext _chatGPTContext = serviceProvider.GetService<ChatGPTContext>();

var data = new DALChatConsumer.Entities.MailTemplate()
{
MailText = resultText,
IsDeleted = false,
CreatedDate = DateTime.Now,
ParentId = parentID,
LanguageId = (int)languageType
};
var result = _chatGPTContext.MailTemplate.Add(data);
_chatGPTContext.SaveChanges();
Console.WriteLine($"Mail Template Saved Successfully.. Language {languageType}, ID: {data.Id}");
//------------------
}
else
{
if (completionResult.Result.Error == null)
{
throw new Exception("Unknown Error");
}
Console.WriteLine($"{completionResult.Result.Error.Code}: {completionResult.Result.Error.Message}");
}
}

“ChatGPT is scary good. We are not far from dangerously strong AI.” — Elon Musk

Full Demo Translate ChatGPT Microservice

Program.cs: Consumer(Full Codes):

using OpenAI.GPT3.Managers;
using OpenAI.GPT3;
using System;
using OpenAI.GPT3.ObjectModels.RequestModels;
using OpenAI.GPT3.ObjectModels;
using System.Threading.Tasks;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;
using System.Text.Json;
using DALChatConsumer.Entities;
using System.Linq;
using DALChatConsumer.Entities.DbContexts;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;

namespace ChatGPT
{
internal class Program
{
static async Task Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "EmailTemplate",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);

var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var data = Encoding.UTF8.GetString(body);
MailTemplate mailTemplate = JsonSerializer.Deserialize<MailTemplate>(data);
Console.WriteLine(" [x] Received Mail Template ID: {0}", mailTemplate.Id);

//ChatGPT
var gpt3 = new OpenAIService(new OpenAiOptions()
{
ApiKey = "***Your OpenAI Api Key***"
});
foreach (LanguageType lang in Enum.GetValues(typeof(LanguageType)))
{
if (lang == LanguageType.Turkish) continue; //Eliminate Turkish
TranslateTextByLanguage(gpt3, mailTemplate.MailText, lang, mailTemplate.Id);
}
};
channel.BasicConsume(queue: "EmailTemplate",
autoAck: true,
consumer: consumer);
Console.WriteLine("Listening to Mail Template Queue...");
Console.WriteLine("Press [enter] to exit.");
Console.ReadLine();
}
}

public static void TranslateTextByLanguage(OpenAIService gpt3, string mailText, LanguageType languageType, int parentID)
{
//English | German | French
var completionResult = gpt3.Completions.CreateCompletion(new CompletionCreateRequest()
{
Prompt = $"Can you translate this to {languageType} ? '{mailText}'",
Model = Models.TextDavinciV3,
Temperature = 0.7F,
MaxTokens = 512,
TopP = 1,
FrequencyPenalty = 0,
PresencePenalty = 0
});

if (completionResult.Result.Successful)
{
var resultText = completionResult.Result.Choices.FirstOrDefault().Text.Trim();

//DB Operaitons
var services = new ServiceCollection();
services.AddDbContext<ChatGPTContext>(options => options.UseSqlServer("Server=.;Database=ChatGPT;Trusted_Connection=True;TrustServerCertificate=True;"));

var serviceProvider = services.BuildServiceProvider();
ChatGPTContext _chatGPTContext = serviceProvider.GetService<ChatGPTContext>();

var data = new DALChatConsumer.Entities.MailTemplate()
{
MailText = resultText,
IsDeleted = false,
CreatedDate = DateTime.Now,
ParentId = parentID,
LanguageId = (int)languageType
};
var result = _chatGPTContext.MailTemplate.Add(data);
_chatGPTContext.SaveChanges();
Console.WriteLine($"Mail Template Saved Successfully.. Language {languageType}, ID: {data.Id}");
//------------------
}
else
{
if (completionResult.Result.Error == null)
{
throw new Exception("Unknown Error");
}
Console.WriteLine($"{completionResult.Result.Error.Code}: {completionResult.Result.Error.Message}");
}
}
}
}

Conclusion:

In this article, we tried to translate some Turkish text into other languages with ChatGPT. We used “Message Broker” (RabbitMQ), for Event Sourcing Microservices. We wrote simple subscriber and consumer services. We used Entity for all DB Operations. We looped in an Enum List and dynamically translated the Turkish text to other languages which are in the enum list. If you want to add a new language for translation, all you have to do is add the relevant language as a new element to the Enum and add another record to the LanguageType table. That’s all..

Firstly I wrote ChatGPT microservice with Python for using official OpenAI Api, but after all, I figured out “Betalgo.OpenAI.GPT3”. Thanks “Tolga Kayhanfor this awesome .Net library.

I think OpenAI is one of the most successful tools, we developers can use these days. This tool, which has many different abilities, amazed even a dinosaur like me, who believes he saw everything from ancient times :)

The End

No company is going to survive in the future without implementing, or at least gaining an understanding of, artificial intelligence and how it can be used to better grasp data they collect.” — David Gasparyan ( President of Phonexa)

See you until the next article.

“If you have read so far, first of all, thank you for your patience and support. I welcome all of you to my blog for more!”

Source:

--

--

Bora Kaşmer
Geek Culture

I have been coding since 1993. I am computer and civil engineer. Microsoft MVP. Software Architect(Cyber Security). https://www.linkedin.com/in/borakasmer/