Как заставить Session Entities работать как часть намерения Dialogflow обнаружить - PullRequest
3 голосов
/ 19 мая 2019

У меня есть сущность, которая должна обновляться для каждой сессии с помощью информации, специфичной для пользователя. Это работало, когда я использовал Dialogflow v1, и я думал, что это работало с v2, но теперь у меня есть значительные проблемы с ним.

Я полагаю, что я правильно устанавливаю информацию об объекте сеанса, но для намерения, которое его использует, оно совпадает только при использовании значения из объекта разработчика.

Как мне заставить его использовать Session Entity? Я делаю что-то не так при обновлении? Я использую неправильный идентификатор сессии? Есть ли способ, которым я могу лучше проверить или проверить, что я использую правильный идентификатор или что я обновляю сущность правильно? Это просто ошибка?

Документация всего следует.

Проект настроен на использование версии 2 и допускает бета-функции, хотя я пробовал и без бета-функций.

configuration

Есть только три Интента. Резервное намерение для захвата сбоев, Приветственное намерение, которое получает событие приветствия, и намерение «входа», которое должно захватывать код входа, который должен соответствовать сущности «код». Все они используют веб-крючок для выполнения. intent list

отступление намерения fallback intent

Приветственное намерение welcome intent

Намерение "входа" entry intent

Как показано в намерении "entry", он использует объект "code", который является единственным объектом разработчика в системе

code entity

Код выполняет большую часть работы, связанной с Dialogflow, в отдельном модуле, который использует модуль dialogflow из npm для установки объекта сеанса. (Обратите внимание, что это отличается от модуля dialogflow-executement, который используется для обработки выполнения. Я использую многоязычную библиотеку для выполнения, но это не должно иметь значения.) (Он также использует функции firebase для запуска, но я не не думаю, что что-то из этого уместно.)

Из пакета. Json:

  "dependencies": {
    "dialogflow": "^0.9.0",
    "firebase-admin": "~7.0.0",
    "firebase-functions": "^2.2.0",
    "multivocal": "^0.11.1"
  },

Это импортируется как dialogflow, указывая используемую версию API:

const dialogflow = require('dialogflow').v2beta1;

Функции, которые я показываю ниже, вызывают envToConfig(env), который использует среду (многоцелевую концепцию, которая просто хранит соответствующую информацию, включая Dialogflow parent и информацию о сертификате) и возвращает конфигурацию, которую необходимо передать на dialogflow.SessionEntityTypesClient( config ). Если при дальнейших вызовах не возникает ошибок, похоже, что он работает правильно.

Функция makeEntityType( name, entityMap ) берет карту значений, которые будут использоваться для entities в SessionEntityType , и возвращает объект, который будет использоваться для построения полного SessionEntityType. name - это отображаемое имя.

function makeEntityType( name, entityMap ){
  let ret = {
    displayName: name,
    entities: []
  };

  Object.keys( entityMap ).map( key => {
    let val = entityMap[key];
    let entity = {
      value: key,
      synonyms: [key, ...val]
    };
    ret.entities.push( entity );
  });

  return ret;
}
exports.makeEntityType = makeEntityType;

Результат этого передается в setSessionEntity( env, entityType ) вместе с многовоконной средой, которая содержит некоторую информацию, которую мы используем в сеансе. Он проверяет, правильно ли установлены name и entityOverrideMode в entityType, а затем пытается их создать. Я также пытался использовать PATCH, и он ведет себя так же. Он также выполняет кучу журналирования, который я покажу позже, когда он запустится, чтобы доказать, что он действительно работает.

function setSessionEntity( env, entityType ){
  const config = envToConfig( env );
  const client = new dialogflow.SessionEntityTypesClient( config );

  let parent = env.dialogflow.parent;
  if( entityType.displayName && !entityType.name ){
    entityType.name = `${parent}/entityTypes/${entityType.displayName}`;
  }
  if( !entityType.entityOverrideMode ){
    entityType.entityOverrideMode = 'ENTITY_OVERRIDE_MODE_OVERRIDE';
  }

  console.log('setSessionEntity parent',parent);
  const request = {
    parent: parent,
    sessionEntityType: entityType
  };
  console.log('setSessionEntity request',JSON.stringify(request,null,1));
  return client.createSessionEntityType( request )
    .then( create => {
      console.log('setSessionEntity created',JSON.stringify(create,null,1));
      return Promise.resolve( env );
    })
    .catch( err => {
      console.error('setSessionEntity problem creating',err);
      return Promise.resolve( env );
    })
}
exports.setSessionEntity = setSessionEntity;

Для отладки у меня также есть функция, которая перечисляет сущности сеанса:

function listSessionEntities( env ){
  let parent = env.dialogflow && env.dialogflow.parent;
  console.log('listSessionEntities parent', parent);
  if( !parent ){
    return Promise.resolve( env );
  }

  const config = envToConfig( env );
  const client = new dialogflow.SessionEntityTypesClient( config );
  const request = {
    parent: parent
  };
  return client.listSessionEntityTypes(request)
    .then( result => {
      console.log('listSessionEntities', JSON.stringify(result,null,1));
    })
    .catch( err => {
      console.log('listSessionEntities err', err);
    })
    .then( () => Promise.resolve( env ) );
}
exports.listSessionEntities = listSessionEntities;

Код, который вызывает это, импортирует его как Dialogflow:

const Dialogflow = require('./dialogflow');

Как часть всех вызовов webhook, функция listSessionEntities() вызывается до того, как какой-либо конкретный обработчик будет:

function debugSessionEntities( env ){
  return Dialogflow.listSessionEntities( env );
}

Когда инициируется Приветственное намерение, он устанавливает для объекта сеанса «код» два новых типа, которые должны переопределять тип, определенный в объекте разработчика «кода»:

function handleWelcome( env ){
  const entityType = Dialogflow.makeEntityType('code',{
    'alpha': [],
    'bravo': []
  });
  return Dialogflow.setSessionEntity( env, entityType )
    .then( env => Multivocal.handleDefault( env ) );
}

Когда я запускаю это через симулятор, он не принимает установленные типы сущностей сеансов, но все равно реагирует на тип сущностей разработчиков. (Использование реального устройства работает так же.)

simulator conversation

В симуляторе это то, что он сообщает на вкладке Запрос для Приветственного намерения:

{
  "responseId": "55a9eb06-ce05-48f9-8a56-b993fa512aee",
  "queryResult": {
    "queryText": "GOOGLE_ASSISTANT_WELCOME",
    "action": "multivocal.welcome",
    "parameters": {},
    "allRequiredParamsPresent": true,
    "fulfillmentText": "Hello! How can I help you?",
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            "Greetings! How can I assist?"
          ]
        }
      }
    ],
    "outputContexts": [
      {
        "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/contexts/google_assistant_welcome"
      },
      {
        "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/contexts/actions_capability_screen_output"
      },
      {
        "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/contexts/actions_capability_audio_output"
      },
      {
        "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/contexts/actions_capability_account_linking"
      },
      {
        "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/contexts/google_assistant_input_type_keyboard"
      },
      {
        "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/contexts/actions_capability_media_response_audio"
      },
      {
        "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/contexts/actions_capability_web_browser"
      }
    ],
    "intent": {
      "name": "projects/session-test-XXXXX/agent/intents/ca79c951-4d75-4b2b-acd4-7dac2f81856e",
      "displayName": "welcome"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "en-us"
  },
  "originalDetectIntentRequest": {
    "source": "google",
    "version": "2",
    "payload": {
      "isInSandbox": true,
      "surface": {
        "capabilities": [
          {
            "name": "actions.capability.SCREEN_OUTPUT"
          },
          {
            "name": "actions.capability.ACCOUNT_LINKING"
          },
          {
            "name": "actions.capability.AUDIO_OUTPUT"
          },
          {
            "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
          },
          {
            "name": "actions.capability.WEB_BROWSER"
          }
        ]
      },
      "requestType": "SIMULATOR",
      "inputs": [
        {
          "rawInputs": [
            {
              "query": "Talk to my test app",
              "inputType": "KEYBOARD"
            }
          ],
          "intent": "actions.intent.MAIN"
        }
      ],
      "user": {
        "userStorage": "{\"UserId\":\"ABwppHHd40lIZ1o0bRERAKlHNtNcS2qFtz7NbRQnb31AQDFuV41VPFQivXwwpQGtv_5SlsZNp0N3kxalIIXXXXXX\",\"NumVisits\":1}",
        "lastSeen": "2019-05-18T19:12:38Z",
        "locale": "en-US",
        "userId": "ABwppHHd40lIZ1o0bRERAKlHNtNcS2qFtz7NbRQnb31AQDFuV41VPFQivXwwpQGtv_5SlsZNp0N3kxalIIXXXXXX"
      },
      "conversation": {
        "conversationId": "ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX",
        "type": "NEW"
      },
      "availableSurfaces": [
        {
          "capabilities": [
            {
              "name": "actions.capability.AUDIO_OUTPUT"
            },
            {
              "name": "actions.capability.WEB_BROWSER"
            },
            {
              "name": "actions.capability.SCREEN_OUTPUT"
            }
          ]
        }
      ]
    }
  },
  "session": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX"
}

Наиболее примечательным из этого является атрибут session, установленный внизу.Код использует это как значения parent и session при построении

Объекты запроса для двух других Intents одинаковы и имеют одинаковое значение для session.Ни один из объектов ответа никоим образом не заметен.

Когда инициируется Welcome Intent, неудивительно, что вызов listSessionEntities() показывает, что его еще нет:

info: listSessionEntities parent projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX
info: listSessionEntities [
 [],
 null,
 null
]

Тем не менее, parent имеет правильное значение из session.

Когда обработчик для Приветственного намерения отправляется и создает объект сеанса, кажется, что все работает нормально:

info: setSessionEntity request {
 "parent": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX",
 "sessionEntityType": {
  "displayName": "code",
  "entities": [
   {
    "value": "alpha",
    "synonyms": [
     "alpha"
    ]
   },
   {
    "value": "bravo",
    "synonyms": [
     "bravo"
    ]
   }
  ],
  "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/entityTypes/code",
  "entityOverrideMode": "ENTITY_OVERRIDE_MODE_OVERRIDE"
 }
}
info: setSessionEntity created [
 {
  "entities": [
   {
    "synonyms": [
     "alpha"
    ],
    "value": "alpha"
   },
   {
    "synonyms": [
     "bravo"
    ],
    "value": "bravo"
   }
  ],
  "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/entityTypes/code",
  "entityOverrideMode": "ENTITY_OVERRIDE_MODE_OVERRIDE"
 },
 null,
 null
]

* * * * * * parent выглядит так же, как session, а name соответствует правильному формату, включая дополнительную часть, которая имеет "/ entityTypes /", за которым следует отображаемое имя.

Когда я пытаюсь вызвать его с помощью кода «альфа», который должен вызвать «входной» замысел, он вместо этого запускает резервный замысел.Вызов listSessionEntities(), кажется, показывает "кодирующую" сущность с ожидаемыми нами типами сущностей, даже если не было совпадения с "альфой".

info: listSessionEntities parent projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX
info: listSessionEntities [
 [
  {
   "entities": [
    {
     "synonyms": [
      "alpha"
     ],
     "value": "alpha"
    },
    {
     "synonyms": [
      "bravo"
     ],
     "value": "bravo"
    }
   ],
   "name": "projects/session-test-XXXXX/agent/sessions/ABwppHFGTpcFtHOOo6ehQfKys9AnH14V5-RhzrNKsea6y6L5zgv4eN-j3IesfuqSsKMc7qRt1CAOhkUYA9XXXXXX/entityTypes/code",
   "entityOverrideMode": "ENTITY_OVERRIDE_MODE_OVERRIDE"
  }
 ],
 null,
 null
]

Опять же, все выглядит правильно.Когда я пытаюсь сделать это снова с "zulu", он показывает то же самое для вызова listSessionEntites(), но на этот раз он соответствует намерению "entry", поскольку "zulu" является одним из типов сущностей для "code", который являетсяопределяется как объект разработчика.

Вот где я застрял.Все выглядит правильно.Похоже, что Session Entity должен быть установлен правильно для этого сеанса .Похоже, следует использовать эти значения.Но, похоже, этого никогда не происходит.

Что происходит?Вся помощь будет очень благодарна.(Вы даже читали до конца вопроса? Если так - спасибо! Я знаю, что это долго, но хотелось быть максимально полным.)

1 Ответ

5 голосов
/ 21 мая 2019

Похоже, что это ошибка - я получил отзывы от других разработчиков о том, что они видят ту же проблему, иногда в ранее работающем коде.

Ошибка была открыта в https://issuetracker.google.com/issues/133166381 чтобы отслеживать проблему.Пометьте его, чтобы указать, что у вас есть похожие проблемы и отслеживать прогресс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...