LoginSignup
2
1

More than 5 years have passed since last update.

Watson Conversation を NLP として使う(Java)(自然言語処理)

Last updated at Posted at 2018-01-09

Watson Conversation には System Entity として日付、時刻、数値、通貨をテキストから抽出する機能があるので、それに特化して利用する。

利用するライブラリは watson Java SDK
https://github.com/watson-developer-cloud/java-sdk

概要

入力:"平成30年4月1日です。"
出力:
EntityKeyword [facet=sys-date, begin=0, end=9, lex=2018-04-01, str=平成30年4月1日]
EntityKeyword [facet=sys-number, begin=2, end=4, lex=30, str=30]
EntityKeyword [facet=sys-number, begin=5, end=6, lex=4, str=4]
EntityKeyword [facet=sys-number, begin=7, end=8, lex=1, str=1]

SDK のライブラリを以下のようにWrapして使う。

サービス本体

ConversationNLPService.java

package com.ibm.watson.developer_cloud.conversation;
import java.util.*;
import com.ibm.watson.developer_cloud.conversation.v1.ConversationService;
import com.ibm.watson.developer_cloud.conversation.v1.model.Entity;
import com.ibm.watson.developer_cloud.conversation.v1.model.MessageRequest;
import com.ibm.watson.developer_cloud.conversation.v1.model.MessageResponse;
public class ConversationNLPService {
    String username;
    String password;
    String workspaceid;
    public ConversationNLPService(String username, String password, String workspaceid) {
        this.username = username;
        this.password = password;
        this.workspaceid = workspaceid;
    }
    public ConversationNLPServiceResponse nlp(String input) throws Exception {
    ConversationService service = new ConversationService(ConversationService.VERSION_DATE_2016_09_20);
        service.setUsernameAndPassword(username, password);
        Map<String, Object> context = new HashMap<String, Object>();
        {
            // SET TIMEZONE
            context.put("timezone", TimeZone.getDefault().getID());
        }
        // remove control code
        input = input.replace("\t", " ").replace("\n", " ").replace("\r", " ");
    MessageRequest newMessage = new MessageRequest.Builder() //
                .inputText(input) //
                .context(context) //
                .build();
        MessageResponse response = service.message(workspaceid, newMessage).execute();
        String s = response.getInputText();
        ConversationNLPServiceResponse rsp = new ConversationNLPServiceResponse();
        List<Entity> list = response.getEntities();
        for (Entity e : list) {
            EntityKeyword kwd = new EntityKeyword(e.getEntity(), e.getLocation()[0], e.getLocation()[1], e.getValue(),
                    s.substring(e.getLocation()[0], e.getLocation()[1]));
            rsp.addKeyword(kwd);
        }
        return rsp;
    }
}
ConversationNLPServiceResponse

package com.ibm.watson.developer_cloud.conversation;
import java.util.ArrayList;
public class ConversationNLPServiceResponse {
    ArrayList<EntityKeyword> kwds = new ArrayList<>();
    protected void addKeyword(EntityKeyword kwd) {
        for (EntityKeyword kw : kwds) {
            if (kw.getFacet().equals(kwd.getFacet()) && kw.isLongerMach(kwd)) {
                System.err.println("!! " + kwd);
                return;
            }
        }
        this.kwds.add(kwd);
    }
    public ArrayList<EntityKeyword> asList() {
        return kwds;
    }
}

EntityKeyword.java

package com.ibm.watson.developer_cloud.conversation;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class EntityKeyword {
    public static String SYS_DATE = "sys-date";
    public static String SYS_NUMBER = "sys-number";
    public static String SYS_CURRENCY = "sys-currency";
    String facet;
    int begin;
    int end;
    String lex;
    String str;
    static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    public boolean isLongerMach(EntityKeyword kwd) {
        return (this.begin <= kwd.begin) && (kwd.end <= this.end) && ((kwd.end - kwd.begin) < (this.end - this.begin));
    }
    public Date asDate() {
        if (isDate() == false) {
            return null;
        } else {
            try {
                return sdf.parse(this.lex);
            } catch (ParseException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    public boolean isDate() {
        return facet != null && facet.equals(SYS_DATE);
    }
    public boolean isCurrency() {
        return facet != null && facet.equals(SYS_CURRENCY);
    }
    public boolean isNumber() {
        return facet != null && facet.equals(SYS_NUMBER);
    }
    public EntityKeyword(String facet, int begin, int end, String lex, String str) {
        super();
        this.facet = facet;
        this.begin = begin;
        this.end = end;
        this.lex = lex;
        this.str = str;
    }
    public int getBegin() {
        return begin;
    }
    public int getEnd() {
        return end;
    }
    public String getLex() {
        return lex;
    }
    public String getFacet() {
        return facet;
    }
    public String getStr() {
        return str;
    }
    @Override
    public String toString() {
        return "EntityKeyword [facet=" + facet + ", begin=" + begin + ", end=" + end + ", lex=" + lex + ", str=" + str
                + "]";
    }
}


使い方

ConversationNLPServiceMain.java
package com.ibm.watson.developer_cloud.conversation;
import java.util.ArrayList;

public class ConversationNLPServiceMain {
    public static void main(String[] args) throws Exception {
        // PLEASE GET credentials from https://console.bluemix.net/home/

        // Enablement_Conversation
        String username = "xxx";
        String password = "xxx";
        // CONV_NLP
        String workspaceid = "xxx";

        ConversationNLPService service = new ConversationNLPService(username, password, workspaceid);

        String input = "平成30年4月1日です。";

        ConversationNLPServiceResponse response = service.nlp(input);
        ArrayList<EntityKeyword> kwds = response.asList();

        for (EntityKeyword kwd : kwds) {
            System.err.println(kwd.toString());
        }
    }
}


System.err

EntityKeyword [facet=sys-date, begin=0, end=9, lex=2018-04-01, str=平成30年4月1日]
EntityKeyword [facet=sys-number, begin=2, end=4, lex=30, str=30]
EntityKeyword [facet=sys-number, begin=5, end=6, lex=4, str=4]
EntityKeyword [facet=sys-number, begin=7, end=8, lex=1, str=1]

だいたいこんな感じ...

「平成30年4月1日」が「2018-04-01」に正規化されます。
「明日」とか「来週の日曜」でも正規化できます。
ただし、間違いもあるので過度に依存しないようにする必要はあると思います。
このクラスを改造して「結果の中に日付が1つだけの場合の処理」「日付と時刻が連続している場合の扱い」などを追加するとよいと思います。

所感
Watson API に NLP系のAPIもあってよいと思いますが、なぜか提供されていないのでこのようなものを作ってみました。
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1