Introduction
As we transition Actualog PIM from .Net 4.2 to .Net 8.0 MVC Core with the help of ChatGPT Guru, we’re seizing the chance to also refine our translation services by integrating AI technology. We manage a diverse array of items: facets, categories, attributes and their values, measure and measure units, and of course, products and services — across multiple industries. Our goal is to enhance translation and context enrichment using AI to enable context-aware translations.
The core idea is to go beyond traditional translation tools by developing a deeper, more nuanced understanding of context. This means not just translating words but understanding their meaning within the specific industry and usage. To achieve this, we’ve implemented a combination of AI-driven services and a systematically organized class system. These enhancements have significantly improved the accuracy of our translations and their relevance to specific fields.
This context-enabled approach is particularly beneficial for industry-specific product data, where precision and technical accuracy are crucial. By understanding the context in which terms and phrases are used, our system can provide translations that are not only linguistically correct but also appropriate and effective within the industry context. This leads to clearer communication and better usability for international clients in their respective markets.
System Architecture
The translation system is centered around the AIContext
class, which encapsulates all relevant information required to perform accurate translations. Here is a brief overview of how the system components interact:
AIContext Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class AIContext { public EntityType EntityType { get; set; } public string Term { get; set; } // The term to be translated. public string Description { get; set; } // Description of the term, if applicable. public string? Community { get; set; } // Community the entity belongs to, if applicable. public string? ParentCategory { get; set; } // Parent category, if applicable. public List<string>? Synonyms { get; set; } = new List<string>(); // Synonyms of the term, if any. public List<string>? Facets { get; set; } = new List<string>(); // Facets associated with the entity, if any. public List<string>? SimilarCategories { get; set; } = new List<string>(); // Similar categories within the same parent category, if any. public Dictionary<string, string>? VerifiedTranslations { get; set; } = new Dictionary<string, string>(); // Verified translations for the term, if any. public List<string>? RelatedTerms { get; set; } = new List<string>(); // Terms related to the entity for richer context. public List<string> Attributes { get; set; } = new List<string>(); // Attributes for product category template. // Constructor ensures the essential properties are initialized to avoid null reference exceptions. public string Purpose { get; set; } = "Translation"; public AIContext() { } } |
The AIContext
class holds detailed entity information including synonyms, related terms, facets, and more. This class is pivotal in providing a rich context to the translation process, which is essential for achieving accuracy and cultural relevance.
AiFeaturesService
- Orchestrates the translation process.
- Calls upon the
ContextBuilder
to create an instance ofAIContext
for the entity to be translated. - Uses the
OpenAITranslationService
to perform the actual translation based on the narrative constructed from theAIContext
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
using Actualog.Abstract; using Actualog.Data; using Actualog.Data.Custom; using Actualog.Tools.Helpers; using Actualog.Tools.Provider; using System.Linq.Expressions; public interface IAiFeaturesService { Task TranslateEntityAsync<T>(T model, Expression<Func<T, string>> propertyExpression, List<string> targetLanguageCodes) where T : class, IBaseModelEntity; } public class AiFeaturesService : IAiFeaturesService { private readonly IContextBuilder _contextBuilder; private readonly ITermService _termService; private readonly IAiTranslationService _aiTranslationService; // Use the IAiTranslationService interface private readonly IPromptBuilder _promptBuilder; // Assuming this is responsible for creating the narrative public AiFeaturesService(IContextBuilder contextBuilder, ITermService termService, IAiTranslationService aiTranslationService, IPromptBuilder promptBuilder) { _contextBuilder = contextBuilder; _termService = termService; _aiTranslationService = aiTranslationService; _promptBuilder = promptBuilder; } public async Task TranslateEntityAsync<T>(T model, Expression<Func<T, string>> propertyExpression, List<string> targetLanguageCodes) where T : class, IBaseModelEntity { // Build the AI context for the specified model and property // Example of setting purpose before building context var aiContext = await _contextBuilder .SetPurpose("Translation") .BuildContextAsync(model, propertyExpression); // Create the translation narrative using the built context var narrative = _promptBuilder.CreatePrompt(aiContext, propertyExpression.Body.ToString()); foreach (var targetLanguageCode in targetLanguageCodes) { // Translate the narrative into the target language var translatedText = await _aiTranslationService.TranslateTextAsync(narrative, targetLanguageCode); // Prepare the term dictionary for the translated text var termDictionary = new TermDictionary { { LanguageHelper.GetDataLanguageByCultureName(targetLanguageCode), translatedText } }; // Update the translated term using TermService await _termService.UpdateTermAsync(model, propertyExpression, termDictionary, deferSaveChanges: false); } } } |
ContextBuilder
- Responsible for constructing the
AIContext
by pulling data from various repositories related to the entity. - Ensures that the
AIContext
is comprehensive and filled with all necessary data to inform the translation process.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
using Actualog.Abstract; using Actualog.Data; using Actualog.Tools.Helpers; using System.Linq.Expressions; using System.Reflection; namespace Actualog.Tools.Provider; public interface IContextBuilder { Task<AIContext> BuildContextAsync<T>(T model, Expression<Func<T, string>> propertyExpression = null) where T : class, IBaseModelEntity; ContextBuilder SetPurpose(string purpose); } public class ContextBuilder : IContextBuilder { private readonly ICommunityRepository _communityRepository; private readonly ICategoryRepository _categoryRepository; private readonly IProductRepository _productRepository; private readonly IFacetRepository _facetRepository; private readonly ICompanyRepository _companyRepository; private readonly ICatalogRepository _catalogRepository; private readonly IAttributeRepository _attributeRepository; private readonly IUserRepository _userRepository; private readonly IMeasureRepository _measureRepository; private readonly ITermService _termService; private AIContext _context; public ContextBuilder( ICommunityRepository communityRepository, ICategoryRepository categoryRepository, IFacetRepository facetRepository, IProductRepository productRepository, ICompanyRepository companyRepository, ICatalogRepository catalogRepository, IAttributeRepository attributeRepository, IUserRepository userRepository, IMeasureRepository measureRepository, ITermService termService) { _communityRepository = communityRepository; _categoryRepository = categoryRepository; _facetRepository = facetRepository; _productRepository = productRepository; _companyRepository = companyRepository; _catalogRepository = catalogRepository; _attributeRepository = attributeRepository; _userRepository = userRepository; _measureRepository = measureRepository; _termService = termService; _context = new AIContext(); } public ContextBuilder SetPurpose(string purpose) { _context.Purpose = purpose; return this; } public async Task<AIContext> BuildContextAsync<T>(T model, Expression<Func<T, string>> propertyExpression = null) where T : class, IBaseModelEntity { _context = new AIContext(); _context.EntityType = InferEntityTypeFromModel(model); if (propertyExpression != null) { await PopulateBasicProperties(model); await PopulateVerifiedTranslations(model, propertyExpression); } return _context; } private EntityType InferEntityTypeFromModel<T>(T model) where T : class { var modelTypeName = model.GetType().Name; if (Enum.TryParse<EntityType>(modelTypeName, out var entityType)) { return entityType; } return EntityType.Other; } private async Task PopulateBasicProperties<T>(T model) where T : class, IBaseModelEntity { var nameProperty = typeof(T).GetProperty("Name"); if (nameProperty != null) { _context.Term = nameProperty.GetValue(model) as string; } var descriptionProperty = typeof(T).GetProperty("Description"); if (descriptionProperty != null) { _context.Description = descriptionProperty.GetValue(model) as string; } } private async Task PopulateVerifiedTranslations<T>(T model, Expression<Func<T, string>> propertyExpression) where T : class, IBaseModelEntity { var languages = LanguageHelper.VerifiedLanguages; foreach (var language in languages) { var localizedTerm = await _termService.TermAsync(model, propertyExpression, language); if (!string.IsNullOrEmpty(localizedTerm)) { var propertyName = ((MemberExpression)propertyExpression.Body).Member.Name; _context.VerifiedTranslations[$"{propertyName}_{language.Code}"] = localizedTerm; } } } } |
OpenAITranslationService:
- Integrates with OpenAI’s API to translate the text.
- Receives a narrative or context-rich string from
AiFeaturesService
and performs the translation into the specified language(s).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
using Actualog.Tools.Helpers; using Newtonsoft.Json; using OpenAI_API; using System.Threading.Tasks; namespace Actualog.Tools.Helpers; public interface IAiTranslationService { Task<string> TranslateTextAsync(string prompt, string targetLanguageCode); } public class OpenAITranslationService : IAiTranslationService { private readonly OpenAIAPI _api; public OpenAITranslationService(string apiKey) { // Initialize the OpenAI API with the provided API key _api = new OpenAIAPI(apiKey); } public async Task<string> TranslateTextAsync(string prompt, string targetLanguageCode) { // Example: Convert the targetLanguageCode to a human-readable language name var targetLanguageName = LanguageHelper.GetLanguageByCode(targetLanguageCode).Title; // Craft a prompt for translation var translationPrompt = $"Translate the following text to {targetLanguageName}: {prompt}"; try { var chat = _api.Chat.CreateConversation(); chat.AppendUserInput(translationPrompt); // Here we capture the response directly for logging var response = await chat.GetResponseFromChatbotAsync(); // Log the successful response Console.WriteLine($"OpenAI Response: {response}"); return response.Trim(); } catch (Exception ex) { // Log the exception details Console.WriteLine($"Error communicating with OpenAI: {ex.Message}"); // Optionally log more details about the exception // This might include the raw response if the exception provides access to it return "Error translating text."; } } } |
Interactions Between Classes
The flow of data and control between these components is crucial for the functionality of the system:
- Translation Request: When a translation is requested,
AiFeaturesService
initiates the process by invokingContextBuilder
. - Context Building:
ContextBuilder
constructs anAIContext
based on the specific entity, fetching all necessary data from various repositories. - Narrative Construction: Once the context is built,
AiFeaturesService
constructs a narrative that includes all contextual information. This narrative is what will be translated to ensure the translated text retains the context’s nuances. - Performing Translation: The narrative is passed to
OpenAITranslationService
, which interacts with the OpenAI API to translate the narrative into the target language. - Result Handling: The translated text is then returned and can be post-processed or directly used depending on the application requirements.
Future Development Perspectives
Looking forward, the development of this translation system can be enhanced in several ways:
- Advanced AI Integration: Incorporating more sophisticated AI models to improve the understanding and generation of narratives.
- Increased Language Coverage: Expanding the system to support more languages and dialects, adapting to the growing needs of Actualog’s global user base.
- Feedback Loop Implementation: Establishing mechanisms to gather and analyze user feedback on translation accuracy and contextual relevance. This data can be used to fine-tune the AI models and improve the system iteratively.
The design and implementation of Actualog’s translation service represent a significant advancement in handling the complexities of translating entity-specific content. By carefully designing the interaction between AI-powered services and structured classes, the system achieves a high level of accuracy and maintains the context integrity crucial for diverse global communications. This technical architecture not only facilitates current needs but also provides a scalable foundation for future enhancements.
0 Comments