CRUD операции с Entities в DialogFlow (C#)

от автора

Вступление

Совсем недавно я начал работу над новым проектом, который включал в себя работу с уже достаточно известны сервисом (AI) от Google — DialogFlow. Суть заключалась в том, что у нас был бот (Telegram) который работал с API нескольких сайтов, а сам же DialogFlow помогал нам структурировать само общение с человеком, для чего он в принципе и создавался. Нужно сказать, что статья предназначена для людей, которые только начали знакомство с сервисом или уже имеют небольшой опыт, так далее возможны термины: Intent, Context, Action, Event ну и то ради чего мы и собрались — Entities. Надеюсь, что статья будет полезна тем, кто немного не понял как именно через код можно проделывать CRUD операции с Entities.

Entities в DialogFlow

В DialogFlow Entities представляют собой некие сущности, которые состоят из ReferenceValue и Synonyms. Что-то похожее на ключ-значение, только с той разницей, что синонимов может быть много, и чем их больше — тем лучше, поскольку это «упрощает боту жизнь» и ему легче понять о каком значении идет сейчас речь, а поставленная галочка на Fuzzy matching поможет боту еще и понимать о чём идет речь, даже если вы упустили одну букву или другой символ. Выглядит это примерно так:
Москва — москва, Москва, Мсква…
Заканчивая короткий экскурс, хотел бы добавить, что именно с Entity происходит очень много всякой возни. Я конечно же не уменьшаю значение интентов и так далее, но факт остается фактом.

EntityTypes

Вот тут и был для меня первый, хоть и небольшой, подводный камень. Ведь в документации есть методы для работы с Entity, а есть для работы с EntityType — что из них что?
На самом деле всё не так и сложно, просто путаница возникает из-за того, что в самом DialogFlow вкладка с EntityTypes называется Entities:
image
EntityType:image
Entitie:image
Хотя в самом DialogFlow считается, что есть Entity и в ней есть Entries (т.е. Сущность и записи в ней).
Перейдём дальше.
Можно создать EntityType вручную прямо на DialoFlow, но я покажу, как это возможно сделать через код (ведь потом, чтобы создавать Entities нам нужно будет знать в каком именно EntityType это делать).
Сперва подключим NuGet пакет Google.Cloud.Dialogflow.V2. На момент написания статьи, была установлена версия 1.1.0:
image
Создадим сперва клас и назовём его EntityTypeManagement в котором будут основные операции:

using Google.Api.Gax; using Google.Cloud.Dialogflow.V2;  public class EntityTypeManagement     {       //Create - создание нового EntityType по типу Test1 (на картинке выше)        //projectId - Id вашего агента с DialogFlow       //displayName - имя которые вы хотите задать для нового           public async Task Create(string projectId, string displayName, EntityType.Types.Kind kind =        EntityType.Types.Kind.Map)         {             var client = await EntityTypesClient.CreateAsync();              var entityType = new EntityType();             entityType.DisplayName = displayName;             entityType.Kind = kind;              var createdEntityType = client.CreateEntityType(                 parent: new ProjectAgentName(projectId),                 entityType: entityType             );              Console.WriteLine($"Created EntityType: {createdEntityType.Name}");         }               //List - получение всех EntityTypes от вашего агента       //projectId - Id вашего агента с DialogFlow         public async Task<PagedEnumerable<ListEntityTypesResponse,EntityType>> List(string projectId)         {             var client = await EntityTypesClient.CreateAsync();             var response = client.ListEntityTypes(                 parent: new ProjectAgentName(projectId)             );             return response;         }         //GetEntityTypeId - получение EntityType за именем        //projectId - Id вашего агента с DialogFlow        //targetEventTypeName - имя EntityType, которое вы ищите          public async Task<string> GetEntityTypeId(string projectId,string targetEventTypeName)         {             var client = await EntityTypesClient.CreateAsync();             var response = client.ListEntityTypes(                 parent: new ProjectAgentName(projectId)             );             string id = response.Where(x => x.DisplayName == targetEventTypeName).FirstOrDefault().Name;             string returningId = id.Replace($"projects/{projectId}/agent/entityTypes/", "");             return returningId;         }         //Delete и BatchDelete удаление одного и нескольких сразу EntityType        //Удаление происходит по entityTypeId         public async Task Delete(string projectId, string entityTypeId)         {             var client = await EntityTypesClient.CreateAsync();              client.DeleteEntityType(new EntityTypeName(projectId, entityTypeId: entityTypeId));              Console.WriteLine($"Deleted EntityType: {entityTypeId}");          }                   public async Task BatchDelete(string projectId, IEnumerable<string> entityTypeIds)         {             var client = await EntityTypesClient.CreateAsync();             var entityTypeNames = entityTypeIds.Select(                 id => new EntityTypeName(projectId, id).ToString());             client.BatchDeleteEntityTypes(new ProjectAgentName(projectId),                 entityTypeNames);         }     }

Тут сразу нужно сказать, что функции Update нет лишь потому, что Create уже выполняет её функцию.
Теперь когда мы имеем базовые методы для работы с EntityTypes перейдём к Entity и сразу же создадим клас EntityManagement:

public class EntityManagement     {        using Google.Cloud.Dialogflow.V2;                 //Create - создание только одной Entity       //entityTypeId - Id EntityType в котором мы хотим создать Entity       //entityValue - ReferenceValue для Entity       // synonyms - массив синонимов для Entity         public async Task Create(string projectId,                                  string entityTypeId,                                  string entityValue,                                  string[] synonyms)         {             var client = await EntityTypesClient.CreateAsync();             var entity = new EntityType.Types.Entity() { Value = entityValue};             entity.Synonyms.AddRange(synonyms);                          var operation = await client.BatchCreateEntitiesAsync(                 parent: new EntityTypeName(projectId, entityTypeId),                 entities: new[] { entity }             );              operation.PollUntilCompleted();         }         //CreateMany - Создание многих Entities         //entityTypeId - Id EntityType в котором мы хотим создать Entity        //entities - коллекция Entities для создания         public async Task CreateMany(string projectId,string entityTypeId, IEnumerable<Entity> entities)         {             var client = await EntityTypesClient.CreateAsync();             List<EntityType.Types.Entity> results = new List<EntityType.Types.Entity>();             foreach (var item in entities)             {                 var entity = new EntityType.Types.Entity() { Value = item.value };                 entity.Synonyms.AddRange(item.synonyms);                 results.Add(entity);             }                         var operation = await client.BatchCreateEntitiesAsync(                 parent: new EntityTypeName(projectId, entityTypeId),                 entities: results.ToArray());             operation.PollUntilCompleted();         }        //Delete - для удаления одной Entity, но если "string entityValue" заменить на       //string[] entityValue и в коде просто присвоить entityValues: entityValue      //то будет для нескольких сразу.         public async Task Delete(string projectId, string entityTypeId, string entityValue)         {             var client = await EntityTypesClient.CreateAsync();              var operation = await client.BatchDeleteEntitiesAsync(                 parent: new EntityTypeName(projectId, entityTypeId),                 entityValues: new[] { entityValue }             );              Console.WriteLine("Waiting for the entity deletion operation to complete.");             operation.PollUntilCompleted();              Console.WriteLine($"Deleted Entity: {entityValue}");          }                //List - Получение всех Entities с EntityType       public async Task<List<Entity>> List(string projectId, string entityTypeId)         {             var client = await EntityTypesClient.CreateAsync();             var entityType = await client.GetEntityTypeAsync(new EntityTypeName(                 projectId, entityTypeId             ));             List<Entity> EntitiesList = new List<Entity>();                          foreach (var entity in entityType.Entities)             {                 List<string> Synonyms = new List<string>();                 foreach (var item in entity.Synonyms)                 {                     Synonyms.Add(item);                 }                 EntitiesList.Add(new Entity { value = entity.Value, synonyms = Synonyms.ToArray() });                 Synonyms = null;             }              return EntitiesList;         }     } 

Добавим нашу модель, которая будет представлять Entity:

public class Entity     {         public string value { get; set; }         public string[] synonyms { get; set; }     } 

Готово, все базовые функции CRUD готовы. Опять-таки, возвращаясь к Update, ее можно отдельно реализовать, но она попросту не нужна, так как Create работает и как Update тоже.
Примеры достаточно просты и, нужно согласиться, тут есть таки «хардкод», но надеюсь статья пригодится тем, кто, как и я, не мог понять как же правильно проделывать CRUD операции через код.

static void Main(string[] args)         {       EntityTypesManagement entityTypesManagement = new EntityTypesManagement();       EntityManagement entityManagement = new EntityManagement();        string ProjectId = "Your Project`s id";        string EntityName = "Your EntityName";       var entityId = await entityTypesManagement.GetEntityTypeId(ProjectId, EntityName);        Entity entity =  new Entity{value = "1", synonyms = new[]{"1","1"}};       /*await*/ entityManagement.Create(ProjectId,entityId,entity);  } 

ссылка на оригинал статьи https://habr.com/ru/post/486348/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *