Различия в моделях Watson SpeechToText Java и javascript

Я работаю над интеграцией библиотеки javascript watson-speech.js с сервером на основе Spring с использованием Watson Java SDK. Я безуспешно пытаюсь отправить результат вызова WatsonSpeech.SpeechToText.recognizeMicrophone на сервер. Кажется, что классы Java Speech имеют соответствующие @SerializedName аннотации, которые соответствуют json, отправляемому клиентом, но я получаю UnrecognizedPropertyException ошибки от Джексона.

Unrecognized field "keywords_result" (class com.ibm.watson.developer_cloud.speech_to_text.v1.model.SpeechResults), not marked as ignorable (2 known properties: "resultIndex", "results"])

Вот метод контроллера:

    @RequestMapping(value = "/postWatsonRequest", method = RequestMethod.POST)
    @ResponseBody
    @ResponseStatus(value=HttpStatus.OK)
    public ResponseObject postWatsonRequest(@RequestBody SpeechResults speechResults) {
    ...
    }

Я явно чего-то упускаю. Нужно ли мне распаковывать json вручную на стороне сервера (настраиваемый десериализатор?) Или форматировать его в приемлемую строку json на стороне клиента?


person LWK69    schedule 18.09.2016    source источник


Ответы (1)


Оказалось, что это была пара ошибок с моей стороны, и хотя я не уверен, что это лучшее решение, оно действительно работает. Вот полный код для всех, кого это интересует. Ключевые вещи, которые заставили его работать:

  • Вы должны использовать событие receive-jason, чтобы получить полный результат json. Событие data, похоже, возвращает только окончательный текст
  • Данные результата нужно было обернуть в допустимую оболочку json - data:{message:data} (это была моя большая ошибка)
  • Не включайте contentType: 'application/json; charset=utf-8', в вызов ajax, иначе контроллер не распознает данные json
  • Watson Java SDK WebSocketManager получает okhttp3.ResponseBody от Watson, из которого извлекает строку. Я предполагаю, что это похоже на то, что получает javascript SDK, поэтому я использовал тот же код из WebSocketManager для преобразования строки JSON.stringify в объект SpeechResults в контроллере.

Из javadoc okhttp3.ResponseBody:

Одноразовый поток от исходного сервера к клиентскому приложению с необработанными байтами тела ответа

Watson javascript

function listen(token) {
    stream = WatsonSpeech.SpeechToText.recognizeMicrophone({
        token: token,
        readableObjectMode: true,
        objectMode: true,
        word_confidence: true,
        format: false,
        keywords: keywordsArray,
        keywords_threshold : 0.5,
        continuous : false
        //interim_results : false
        //keepMicrophone: navigator.userAgent.indexOf('Firefox') > 0
    });

    stream.setEncoding('utf8');

    stream.on('error', function(err) {
        console.log(err);
        stream.stop();
    });

    stream.on('receive-json', function(msg) {
        console.log(msg);
        if (msg.state != 'listening') {
            if (msg.results[0].final) {
                console.log('receive-json: ' + msg);
                postResults(msg);               
                stream.stop();
            }
        }
    });
}

Сообщение Ajax

function postResults(results) {
    var data = JSON.stringify(results);
    console.log('stringify: ' + data);
    $.ajax({
        type: 'POST',
        url: appContextPath + '/postWatsonResult',
        dataType: 'json',
        data: {message:data}
    })
    .done(function(data) {
        console.log('done data: '+ data);
    })
    .fail(function(jqXHR, status, error) {
        var data = jqXHR.responseJSON;
        console.log('fail data: '+ data);
    });
}

Контроллер Spring

@RequestMapping(value = "/postWatsonResult", method = RequestMethod.POST)
@ResponseBody
@ResponseStatus(value=HttpStatus.OK)
public ResponseObject postWatsonResult(@RequestParam("message") String message, Locale locale) {
    logger.info("postWatsonRequest");
    JsonObject json = new JsonParser().parse(message).getAsJsonObject();
    SpeechResults results = null;
    if (json.has("results")) {
        results = GSON.fromJson(message, SpeechResults.class);
    }
    if (results != null) {
        logger.debug("results: " + results.getResults().get(0).getAlternatives().get(0).getTranscript());
    }

    return new ResponseObject();
}

Я все еще думаю, что можно каким-то образом использовать @RequestBody SpeechResults speechResults, поэтому я продолжу экспериментировать с этим, но, по крайней мере, у меня есть рабочее решение.

person LWK69    schedule 19.09.2016
comment
@DanielBolanos Пожалуйста. Я должен предупредить вас, что я все еще на раннем этапе разработки и очень новичок в Watson, поэтому вы захотите поиграть с этим кодом самостоятельно. Например, я думаю, что вызов stream.stop () должен быть stream.close, но я еще не провел достаточного тестирования. Я также немного поэкспериментировал с подходом RequestBody и добился некоторого ограниченного успеха, но сейчас я выберу то, что работает, и, возможно, вернусь к нему позже. - person LWK69; 20.09.2016
comment
Спасибо LWK69, это будет полезно и для других пользователей :) - person Daniel Bolanos; 21.09.2016