Getting Same response to any query in Watson Assistant V2 : Watson-Unity-SDK

695 views Asked by At

I just got to a point where I could set-up the Watson Assistant V2 with Unity and trying to converse with an Assistant I created with a single Skill. I need further help to get the assistant set up to work with my Unity app.

In V1 of the assistant, it was possible to target a workspace and also the response was returning the intent, nodes visited so on. My queries were correctly processed and the responses were identical to the one on the "try it" application in the IBM cloud dashboard.

In the new version though, I am getting the same response for any query I send to the assistant. How can I target the right skill or rather pass correct settings to the assistant to get the correct responses?

IMAGE - Unity log showing assistant responses

[IMAGE - Assistant trial on dashboard][2]

The code I'm using to send queries and get responses is:

IEnumerator TokenExample()
{
    //  Create IAM token options and supply the apikey. IamUrl is the URL used to get the 
    //  authorization token using the IamApiKey. It defaults to https://iam.bluemix.net/identity/token
    TokenOptions iamTokenOptions = new TokenOptions()
    {
        IamApiKey = "API KEY",
        IamUrl = "https://iam.bluemix.net/identity/token"

    };
    //  Create credentials using the IAM token options

    _credentials = new Credentials(iamTokenOptions, "https://gateway-fra.watsonplatform.net/assistant/api");
    while (!_credentials.HasIamTokenData())
        yield return null;

    _assistant = new Assistant(_credentials);
    _assistant.VersionDate = "2018-11-01";

    Debug.Log(_assistant.GetServiceID()); // returns "AssitantV2"

}

public void PingAssistantV2() // triggered from a button press in UI
{
    _assistant.CreateSession(OnCreateSession, OnFail, AssistantID); // Assistant ID is entered through the Inspector

}

public void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
{
    Log.Debug("ExampleAssistantV2.OnMessage()", "Assistant: Create Session Response: {0}", customData["json"].ToString());

    string _si = response.SessionId;
    Debug.Log("SessionID: " +_si);

    MessageInput mi = new MessageInput();
    mi.Text = Query.textComponent.text; // get user query from an input field in unity UI


    MessageRequest messageRequest = new MessageRequest()
    {
        Input = mi

    };
    Debug.LogFormat("<b> Query Sent: {0} </b>", Query.textComponent.text);
    if (response.SessionId != null ) _assistant.Message(OnMessage, OnFail, AssistantID, _si, messageRequest);
}

private void OnMessage(MessageResponse AssistantResponse, Dictionary<string, object> customData)
{
    Log.Debug("ExampleAssistant.OnMessage()", "Response: {0}", customData["json"].ToString());
    Debug.LogFormat("<b> SUCCESS </b>");
    Debug.Log(customData["json"].ToString());

    //  Convert resp to fsdata
    fsData fsdata = null;
    fsResult r = _serializer.TrySerialize(AssistantResponse.GetType(), AssistantResponse, out fsdata);
    if (!r.Succeeded)
        throw new WatsonException(r.FormattedMessages);

    //  Convert fsdata to MessageResponse
    IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse messageResponse = new IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse();
    object obj = messageResponse;
    r = _serializer.TryDeserialize(fsdata, obj.GetType(), ref obj);
    if (!r.Succeeded)
        throw new WatsonException(r.FormattedMessages);

    Response.text = AssistantResponse.Output.Generic.First().Text; // send response to unity UI text box

}

private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
    Log.Debug("OnFail()", "Failed: {0}", error.ToString());
    Debug.LogFormat("<b> Failed </b>");
    Debug.Log(error.ToString());
}

EDIT to address @Taj's comment

The Issue persists even with the sample for assitant V2 in the SDK:

Wrong Unity Responses v/s appropriate responses in dashboardtrail

The code adopted from the example included in the SDK:

/**
* Copyright 2018 IBM Corp. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using IBM.Watson.DeveloperCloud.Connection;
using IBM.Watson.DeveloperCloud.Logging;
using IBM.Watson.DeveloperCloud.Utilities;
using IBM.WatsonDeveloperCloud.Assistant.v2;
using UnityEngine;
using TMPro;

namespace IBM.Watson.DeveloperCloud.Services.Assistant.v2
{
    public class ExampleAssistantV2 : MonoBehaviour
    {
        #region PLEASE SET THESE VARIABLES IN THE INSPECTOR
        [Space(10)]
        [Tooltip("The service URL (optional). This defaults to \"https://gateway.watsonplatform.net/assistant/api\"")]
        [SerializeField]
        private string _serviceUrl;
        [Tooltip("The assistantId to run the example.")]
        [SerializeField]
        private string _assistantId;
        [Tooltip("The version date with which you would like to use the service in the form YYYY-MM-DD.")]
        [SerializeField]
        private string _versionDate;
        [Header("CF Authentication")]
        [Tooltip("The authentication username.")]
        [SerializeField]
        private string _username;
        [Tooltip("The authentication password.")]
        [SerializeField]
        private string _password;
        [Header("IAM Authentication")]
        [Tooltip("The IAM apikey.")]
        [SerializeField]
        private string _iamApikey;
        [Tooltip("The IAM url used to authenticate the apikey (optional). This defaults to \"https://iam.bluemix.net/identity/token\".")]
        [SerializeField]
        private string _iamUrl;
        #endregion

        private Assistant _service;

        private bool _createSessionTested = false;
        private bool _messageTested = false;
        private bool _deleteSessionTested = false;
        private string _sessionId;

        public TMP_InputField query;
        public TextMeshProUGUI response;

        private void Start()
        {
            LogSystem.InstallDefaultReactors();
            Runnable.Run(CreateService());
        }



        private IEnumerator CreateService()
        {
            //  Create credential and instantiate service
            Credentials credentials = null;
            if (!string.IsNullOrEmpty(_username) && !string.IsNullOrEmpty(_password))
            {
                //  Authenticate using username and password
                credentials = new Credentials(_username, _password, _serviceUrl);
            }
            else if (!string.IsNullOrEmpty(_iamApikey))
            {
                //  Authenticate using iamApikey
                TokenOptions tokenOptions = new TokenOptions()
                {
                    IamApiKey = _iamApikey,
                    IamUrl = _iamUrl
                };

                credentials = new Credentials(tokenOptions, _serviceUrl);

                //  Wait for tokendata
                while (!credentials.HasIamTokenData())
                    yield return null;
            }
            else
            {
                throw new WatsonException("Please provide either username and password or IAM apikey to authenticate the service.");
            }

            _service = new Assistant(credentials);
            _service.VersionDate = _versionDate;

            Runnable.Run(SessionCreate());
        }

        private IEnumerator SessionCreate()
        {
            Log.Debug("ExampleAssistantV2.Examples()", "Attempting to CreateSession");
            _service.CreateSession(OnCreateSession, OnFail, _assistantId);

            while (!_createSessionTested)
            {
                yield return null;
            }

        }

        private IEnumerator Examples()
        {


            Log.Debug("ExampleAssistantV2.Examples()", "Attempting to Message");

            MessageInput mi = new MessageInput(); // construct a messgae input
            mi.Text = query.textComponent.text;


            MessageRequest messageRequest = new MessageRequest() // construct a message request
            {
                Input = mi

            };

            Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>Query: </b> <b>{0}</b>", messageRequest.Input.Text);

            _service.Message(OnMessage, OnFail, _assistantId, _sessionId,messageRequest); // send a message request

            while (!_messageTested)
            {
                yield return null;
            }

            //Log.Debug("ExampleAssistantV2.Examples()", "Attempting to DeleteSession");
            //_service.DeleteSession(OnDeleteSession, OnFail, _assistantId, _sessionId);

            //while (!_deleteSessionTested)
            //{
            //    yield return null;
            //}

            //Log.Debug("ExampleAssistantV2.Examples()", "Assistant examples complete.");
        }

        private void OnDeleteSession(object response, Dictionary<string, object> customData)
        {
            Log.Debug("ExampleAssistantV2.OnDeleteSession()", "Session deleted.");
            _createSessionTested = true;
        }

        private void OnMessage(MessageResponse _response, Dictionary<string, object> customData)
        {
            _messageTested = true;
            response.text = _response.Output.Generic.First().Text; // trying to get response

            Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>RESPONSE: </b> <b>{0}</b>", response.text);
        }

        private void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
        {
            Log.Debug("ExampleAssistantV2.OnCreateSession()", "Session: <b>{0}</b>", response.SessionId);
            _sessionId = response.SessionId;
            _createSessionTested = true;

        }

        private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
        {
            Log.Debug("ExampleAssistantV2.OnFail()", "Call failed: {0}: {1}", error.ErrorCode, error.ErrorMessage);
        }

        public void PingAssitant ()
        {
            Runnable.Run(Examples());
        }
    }
}
2

There are 2 answers

10
taj On BEST ANSWER

I can see from your log that you have a new sessionId each time you message. You do not need to create a session each time you send a message. The session should persist during the conversation. I moved the call to CreateSession to your TokenExample() and call PingAssistantV2() once you have a sessionId.

string _si = "";

IEnumerator TokenExample()
{
    //  Create IAM token options and supply the apikey. IamUrl is the URL used to get the 
    //  authorization token using the IamApiKey. It defaults to https://iam.bluemix.net/identity/token
    TokenOptions iamTokenOptions = new TokenOptions()
    {
        IamApiKey = "API KEY",
        IamUrl = "https://iam.bluemix.net/identity/token"

    };
    //  Create credentials using the IAM token options

    _credentials = new Credentials(iamTokenOptions, "https://gateway-fra.watsonplatform.net/assistant/api");
    while (!_credentials.HasIamTokenData())
        yield return null;

    _assistant = new Assistant(_credentials);
    _assistant.VersionDate = "2018-11-01";

    Debug.Log(_assistant.GetServiceID()); // returns "AssitantV2"

    _assistant.CreateSession(OnCreateSession, OnFail, AssistantID); // Assistant ID is entered through the Inspector
}

public void PingAssistantV2() // triggered from a button press in UI
{
    MessageInput mi = new MessageInput();
    mi.Text = Query.textComponent.text; // get user query from an input field in unity UI

    MessageRequest messageRequest = new MessageRequest()
    {
        Input = mi

    };
    Debug.LogFormat("<b> Query Sent: {0} </b>", Query.textComponent.text);
    if (response.SessionId != null ) _assistant.Message(OnMessage, OnFail, AssistantID, _si, messageRequest);
}

public void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
{
    Log.Debug("ExampleAssistantV2.OnMessage()", "Assistant: Create Session Response: {0}", customData["json"].ToString());

    _si = response.SessionId;
    Debug.Log("SessionID: " +_si);

    PingAssistantV2();
}

private void OnMessage(MessageResponse AssistantResponse, Dictionary<string, object> customData)
{
    Log.Debug("ExampleAssistant.OnMessage()", "Response: {0}", customData["json"].ToString());
    Debug.LogFormat("<b> SUCCESS </b>");
    Debug.Log(customData["json"].ToString());

    //  Convert resp to fsdata
    fsData fsdata = null;
    fsResult r = _serializer.TrySerialize(AssistantResponse.GetType(), AssistantResponse, out fsdata);
    if (!r.Succeeded)
        throw new WatsonException(r.FormattedMessages);

    //  Convert fsdata to MessageResponse
    IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse messageResponse = new IBM.WatsonDeveloperCloud.Assistant.v2.MessageResponse();
    object obj = messageResponse;
    r = _serializer.TryDeserialize(fsdata, obj.GetType(), ref obj);
    if (!r.Succeeded)
        throw new WatsonException(r.FormattedMessages);

    Response.text = AssistantResponse.Output.Generic.First().Text; // send response to unity UI text box

}

private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
{
    Log.Debug("OnFail()", "Failed: {0}", error.ToString());
    Debug.LogFormat("<b> Failed </b>");
    Debug.Log(error.ToString());
}
0
the_nandavar On

@taj your develop branch at https://github.com/watson-developer-cloud/unity-sdk/archive/develop.zip is now working! Thank you for your commitment towards sorting this out. I do not have sufficient rep to upvote your answer but ya, Kudos!

Working Code as provided by @taj on the WDC Slack channel:

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using IBM.Watson.DeveloperCloud.Connection;
using IBM.Watson.DeveloperCloud.Logging;
using IBM.Watson.DeveloperCloud.Utilities;
using IBM.WatsonDeveloperCloud.Assistant.v2;
using UnityEngine;
using TMPro;
namespace IBM.Watson.DeveloperCloud.Services.Assistant.v2
{
    public class ExampleAssistantV2b : MonoBehaviour
    {
        #region PLEASE SET THESE VARIABLES IN THE INSPECTOR
        [Space(10)]
        [Tooltip("The service URL (optional). This defaults to \"https://gateway.watsonplatform.net/assistant/api\"")]
        [SerializeField]
        private string _serviceUrl;
        [Tooltip("The assistantId to run the example.")]
        [SerializeField]
        private string _assistantId;
        [Tooltip("The version date with which you would like to use the service in the form YYYY-MM-DD.")]
        [SerializeField]
        private string _versionDate;
        [Header("CF Authentication")]
        [Tooltip("The authentication username.")]
        [SerializeField]
        private string _username;
        [Tooltip("The authentication password.")]
        [SerializeField]
        private string _password;
        [Header("IAM Authentication")]
        [Tooltip("The IAM apikey.")]
        [SerializeField]
        private string _iamApikey;
        [Tooltip("The IAM url used to authenticate the apikey (optional). This defaults to \"https://iam.bluemix.net/identity/token\".")]
        [SerializeField]
        private string _iamUrl;
        #endregion
        private Assistant _service;
        private string _sessionId;
        public TMP_InputField query;
        public TextMeshProUGUI response;
        public List<string> testQueryList;
        public int queryNum = 0;
        private void Start()
        {
            LogSystem.InstallDefaultReactors();
            testQueryList = new List<string>()
            {
                "",
                "What are your hours?",
                "Are you open on Christmas?",
                "I would like to make an appointment",
                "Friday at 12pm",
                "yes"
            };
            Runnable.Run(CreateService());
        }
        private IEnumerator CreateService()
        {
            //  Create credential and instantiate service
            Credentials credentials = null;
            if (!string.IsNullOrEmpty(_username) && !string.IsNullOrEmpty(_password))
            {
                //  Authenticate using username and password
                credentials = new Credentials(_username, _password, _serviceUrl);
            }
            else if (!string.IsNullOrEmpty(_iamApikey))
            {
                //  Authenticate using iamApikey
                TokenOptions tokenOptions = new TokenOptions()
                {
                    IamApiKey = _iamApikey,
                    IamUrl = _iamUrl
                };
                credentials = new Credentials(tokenOptions, _serviceUrl);
                //  Wait for tokendata
                while (!credentials.HasIamTokenData())
                    yield return null;
            }
            else
            {
                throw new WatsonException("Please provide either username and password or IAM apikey to authenticate the service.");
            }
            _service = new Assistant(credentials);
            _service.VersionDate = _versionDate;
            SessionCreate();
        }
        private void SessionCreate()
        {
            Log.Debug("ExampleAssistantV2.Examples()", "Attempting to CreateSession");
            _service.CreateSession(OnCreateSession, OnFail, _assistantId);
        }
        private void Examples()
        {
            Log.Debug("ExampleAssistantV2.Examples()", "Attempting to Message");
            MessageInput mi = new MessageInput(); // construct a messgae input
            //mi.Text = query.textComponent.text;
            mi.Text = testQueryList[queryNum];
            MessageRequest messageRequest = new MessageRequest() // construct a message request
            {
                Input = mi
            };
            Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>Query: </b> <b>{0}</b>", messageRequest.Input.Text);
            _service.Message(OnMessage, OnFail, _assistantId, _sessionId, messageRequest); // send a message request
        }
        private void OnMessage(MessageResponse _response, Dictionary<string, object> customData)
        {
            //response.text = _response.Output.Generic[0].Text; // trying to get response
            string assistantResponse = _response.Output.Generic[0].Text; // trying to get response
            Log.Debug("ExampleAssistantV2.OnDeleteSession()", "<b>RESPONSE: </b> <b>{0}</b>", assistantResponse);
            queryNum++;
        }
        private void OnCreateSession(SessionResponse response, Dictionary<string, object> customData)
        {
            Log.Debug("ExampleAssistantV2.OnCreateSession()", "Session: <b>{0}</b>", response.SessionId);
            _sessionId = response.SessionId;
        }
        private void OnFail(RESTConnector.Error error, Dictionary<string, object> customData)
        {
            Log.Debug("ExampleAssistantV2.OnFail()", "Call failed: {0}: {1}", error.ErrorCode, error.ErrorMessage);
        }
        public void PingAssitant()
        {
            Examples();
        }
    }
}