從Java SDK看DuerOS的技能開發(fā)

DuerOS是對話式AI系統(tǒng)滑臊,既然都已經(jīng)是人工智能了贿条,為什么還要在DuerOS上開發(fā)技能服務(wù)呢?


溫故知新船惨,我們還是要重新審視一下AI堪澎,具體可以參見《老碼農(nóng)眼中的簡明AI》擂错。從編程的角度看,面向人工智能的應(yīng)用大約由三部分組成:領(lǐng)域知識樱蛤、數(shù)學(xué)算法和計算方式钮呀。數(shù)學(xué)算法和計算已經(jīng)由類似DuerOS這樣的AI系統(tǒng)提供了,但是領(lǐng)域知識涉及到具體的行業(yè)知識刹悴,業(yè)務(wù)邏輯行楞,專業(yè)術(shù)語等等,尤其是業(yè)務(wù)邏輯土匀,AI系統(tǒng)也難以做到面面俱到子房。做一個不太恰當(dāng)?shù)念惐龋ヂ?lián)網(wǎng)擁有了web技術(shù)就轧,但是具體的Web應(yīng)用服務(wù)還是需求開發(fā)的证杭,面向?qū)υ捠紸I系統(tǒng)的技能服務(wù)也是類似。

面向人的交互

《面向協(xié)議的DuerOS技能開發(fā)》一文中談到妒御,技能開發(fā)基本上可以理解為Web服務(wù)開發(fā)解愤,只是用戶交互的方式發(fā)生了改變。

電腦/手機(jī)等原來使用鍵盤/鼠標(biāo)/觸摸屏完成輸入乎莉,用顯示屏幕完成輸出送讲,現(xiàn)在基于DuerOS的小度系列產(chǎn)品使用語音對話完成輸入,使用揚(yáng)聲器完成音頻輸出惋啃,當(dāng)然哼鬓,有屏設(shè)備同時支持了原有的功能。

簡單地說边灭,傳統(tǒng)的交互方式是面向機(jī)器的异希,DuerOS的交互方式是面向人的。

DBP的SDK

為了方便開發(fā)者高效地完成技能服務(wù)的開發(fā)绒瘦,DuerOS Bot Platform (DBP)提供了多種語言的SDK:Java称簿,JavaScript,PHP惰帽,Go以及Python憨降。對程序員而言,實(shí)現(xiàn)一個基于HTTP的協(xié)議善茎,并不是一個很輕松的事券册,而使用DBP的SDK,則可以極大的提升開發(fā)效率。

我們可以在https://github.com/dueros看到關(guān)于DuerOS的各種語言SDK烁焙,而Java SDK 就成為了Java程序員的福音航邢。

DBP的Bot-SDK-Java提供了一下主要功能:

  • 封裝了DuerOS的request和response
  • 提供了session的簡化接口
  • 提供了nlu簡化接口
  • 提供了多輪對話開發(fā)接口
  • 提供了事件監(jiān)聽接口

需要注意的是,DBP的Java版SDK 需要在Java 8 及以上版本運(yùn)行骄蝇,采用Maven作為工程管理工具膳殷,同時DBP Java SDK的升級、維護(hù)也都通過Maven進(jìn)行發(fā)布九火,在pom.xml中添加最新版本依賴的示例如下:

<dependency>
    <groupId>com.baidu.dueros</groupId>
    <artifactId>bot-sdk</artifactId>
    <version>1.1.8</version>
</dependency>

DBP Java SDK 淺析

從DBP Java SDK 的POM 文件中可以看到其中的依賴:


Javax.serverlet 3.0.1

Jackson 2.9.7

commons-codec 1.6

commons-io 2.4

commons-digester 2.1

百度的APM SDK 1.1.0

這與一般的Java 工程差別不大赚窃,唯一有點(diǎn)特殊的,可能算是APM的SDK了岔激。 對于微服務(wù)而言勒极,APM SDK 提供了類似sidecar之類的能力。

DBP Java SDK 工程結(jié)構(gòu)主體包括:

  • bot:技能服務(wù)的基類

  • certificate:資源證書的實(shí)現(xiàn)

  • data:DBP協(xié)議的實(shí)體封裝

  • model:對請求和響應(yīng)的封裝

  • nlu:對槽位和意圖的實(shí)現(xiàn)

  • samples: 示例代碼

從命名來看虑鼎,除了data稍顯歧義辱匿,其他都基本上可以見字知意。

DBP協(xié)議的主體——請求和響應(yīng)

Model目錄的request.java 和 response.java 實(shí)現(xiàn)了DBP協(xié)議中請求和響應(yīng)的封裝炫彩。

從面向?qū)ο蟮慕嵌瓤碦equest的組成大體如下:

而Response的響應(yīng)大體是這樣的:

各成員變量的意義可以參見《在面向協(xié)議的DuerOS技能開發(fā)》匾七。DBP協(xié)議中的實(shí)體分別位于Data目錄中的Request 和 Response Package。下面逐一看一下代碼中實(shí)現(xiàn)的協(xié)議實(shí)體江兢。

DBP協(xié)議Request中的實(shí)體

Request中的數(shù)據(jù)實(shí)體可以用戶相關(guān)昨忆,設(shè)備相關(guān),對話相關(guān)以及消息事件杉允。

用戶相關(guān)

Account類承載了百度賬號的信息邑贴,也就是說整個DBP平臺的用戶體系是基于百度賬號的,技能平臺可以基于百度賬號進(jìn)行用戶的綁定以及用戶系統(tǒng)的貫通叔磷。

CoordinatesInfo類表達(dá)了位置的經(jīng)緯度痢缎,而GeoLocation類承載了不同坐標(biāo)系的用戶位置信息,是LocationInfo 的成員變量世澜。

應(yīng)用服務(wù)相關(guān)

AccessToken類用于實(shí)現(xiàn)DuerOS設(shè)備與DuerOS技能之間的鑒權(quán)。

Application類表明了技能服務(wù)也就是bot的標(biāo)識署穗,開發(fā)者通過DBP管理平臺生成的bot-id就是這里的ApplicationID寥裂,而 Appinfo類描述了終端伴侶app的軟件信息,成員變量包括包括技能名稱案疲,應(yīng)用包名封恰,版本號及版本名稱。

Skillinfo 用于在有屏終端和App 伴侶上的技能呈現(xiàn)褐啡,包括了圖標(biāo)Icon類和技能的名稱诺舔。

終端設(shè)備的屬性特征

Device類和DeviceInfo類描述了基于DuerOS的終端終端信息,成員變量包括終端的ID以及終端的硬件能力即supportedInterface:

public class SupportedInterfaces {

    private TextInput textInput;
    private VoiceInput voiceInput;
    private VoiceOutput voiceOutput;
    private PlayController playController;
    private AudioPlayer audioPlayer;
    private Alerts alerts;
    private com.baidu.dueros.data.request.supportedInterfaces.Screen screen;
    private SpeakerController speakerController;
    private com.baidu.dueros.data.request.supportedInterfaces.System system;
    private ScreenExtendedCard screenExtendedCard;
    private VideoPlayer videoPlayer;
    private Display display;
    ....

Context是一個比較重要的類,成員變量包括:

  • System類:系統(tǒng)信息包括Application低飒,User许昨,Device以及apiAccessToken和apiEndPoint
  • 音/視頻播放器狀態(tài)
  • 顯示屏幕的信息。

對話請求相關(guān)

RequestBody類封裝了http post中的body褥赊,是個基礎(chǔ)類糕档,繼承關(guān)系如下:

LaunchRequest是技能服務(wù)生命周期的開始,SessionEndedRequest是技能服務(wù)生命周期的終止拌喉,IntentRequest 則對應(yīng)著技能服務(wù)處理的消息循環(huán)速那。

IntentRequest 中的成員Query是DuerOS設(shè)備語音識別后的結(jié)果,成員DialogState代表對話的狀態(tài)尿背,對應(yīng)的意圖以列表方式表達(dá)端仰。

人機(jī)交互的對話是Dialog,而會話是session田藐。這里的Session是另一個重要的類荔烧,Session ID 是本次多輪對話的唯一標(biāo)識,更重要的是Session類中屬性列表:

private Map<String, String> attributes = new HashMap<String, String>();

該屬性列表實(shí)現(xiàn)了類似瀏覽器cookie的功能坞淮。

事件

事件是DBP協(xié)議中從DuerOS設(shè)備端發(fā)往技能服務(wù)的消息茴晋,目前包括顯示,音/視頻播放器回窘,支付和用戶授權(quán)事件诺擅。顯示相關(guān)的繼承關(guān)系如下:

LinkAccountSucceededEvent類對應(yīng)與協(xié)議中的Connections.Response事件,當(dāng)用戶授權(quán)完成之后啡直,技能服務(wù)會收到此事件烁涌。

ButtonClickedEvent和 RadioButtonClickedEvent了實(shí)現(xiàn)了Form.ButtonClicked和Form.RadioButtonClicked事件,當(dāng)用戶在有屏設(shè)備的表單上點(diǎn)擊按鈕/單選按鈕酒觅,技能服務(wù)會收到此事件撮执。

ElementSelectedEvent類實(shí)現(xiàn)了Display.ElementSelected事件,當(dāng)用戶在有屏設(shè)備的列表模版上選擇了某一項時舷丹,技能服務(wù)會收到此事件抒钱。

LinkClickedEvent類實(shí)現(xiàn)了Screen.LinkClicked事件,如果在卡片或者卡片列表配置了URL地址颜凯,當(dāng)用戶點(diǎn)擊卡片或者卡片列表時谋币,技能服務(wù)會收到此事件。

在Audioplayer 的事件中症概,AudioPlayerEvent繼承自httpbody蕾额,而其他事件類均繼承自AudioPlayerEvent。

事件名 對應(yīng)的類
AudioPlayer.PlaybackFailed  PlaybackFailedEvent
AudioPlayer.PlaybackFinished    PlaybackFinishedEvent
AudioPlayer.PlaybackNearlyFinished  PlaybackNearlyFinishedEvent
AudioPlayer.PlaybackPaused  PlaybackPausedEvent
AudioPlayer.PlaybackResumed PlaybackResumedEvent
AudioPlayer.PlaybackStarted PlaybackStartedEvent
AudioPlayer.PlaybackStopped PlaybackStoppedEvent
AudioPlayer.PlaybackStutterFinished PlaybackStutterFinishedEvent
AudioPlayer.PlaybackStutterStarted  PlaybackStutterStartedEvent
AudioPlayer.ProgressReportDelayElapsed  ProgressReportDelayElapsedEvent
AudioPlayer.ProgressReportIntervalElapsed   ProgressReportIntervalElapsedEvent

類似的彼城,在videoplayer 的事件中诅蝶,VideoPlayerEvent繼承自httpbody退个,而其他事件類均繼承自VideoPlayerEvent。

事件名 對應(yīng)的類
VideoPlayer.PlaybackFinished    PlaybackFinishedEvent
VideoPlayer.PlaybackNearlyFinished  PlaybackNearlyFinishedEvent
VideoPlayer.PlaybackPaused  PlaybackPausedEvent
VideoPlayer.PlaybackQueueCleared    PlaybackQueueClearedEvent
VideoPlayer.PlaybackResumed PlaybackResumedEvent
VideoPlayer.PlaybackStarted PlaybackStartedEvent
VideoPlayer.PlaybackStopped PlaybackStoppedEvent
VideoPlayer.PlaybackStutterFinished PlaybackStutterFinishedEvent
VideoPlayer.PlaybackStutterStarted  PlaybackStutterStartedEvent
VedioPlayer.ProgressReportDelayElapsed  ProgressReportDelayElapsedEvent
VideoPlayer.ProgressReportIntervalElapsed   ProgressReportIntervalElapsedEvent

支付及應(yīng)用內(nèi)付費(fèi)涉及到具體的商業(yè)模式调炬,ChargeEvent.java 是主要的支付事件语盈,繼承自RequestBody類,包括了支付指令的token和詳細(xì)的支付信息筐眷。

凡是涉及到用戶隱私的數(shù)據(jù)或者操作均需用戶授權(quán)黎烈,與用戶授權(quán)相關(guān)的事件有:

PermissionGrantFailedEvent.java 
PermissionGrantedEvent.java 
PermissionRejectedEvent.java    
PermissionRequiredEvent.java

DBP協(xié)議Response中的實(shí)體

ResponseBody類是響應(yīng)的核心:

public class ResponseBody {

    // 如果DuerOS仍然會選用當(dāng)前Bot結(jié)果,應(yīng)該再次下發(fā)請求匀谣,并將request.determined字段設(shè)置為true
    private boolean needDetermine;
    // 表示本次返回的結(jié)果是否為兜底結(jié)果
    private boolean fallBack;
    // 表示本次返回結(jié)果中需要播報的語音信息
    private OutputSpeech outputSpeech;
    // 在需要用戶輸入時照棋,如果用戶沒有輸入或用戶輸入內(nèi)容系統(tǒng)不理解,則播報reprompt內(nèi)容
    private Reprompt reprompt;
    // Bot輸出的Resource內(nèi)容
    private Resource resource;
    // Bot輸出的Card內(nèi)容武翎,用于在有屏場景下展示
    private Card card;
    // Bot輸出的指令烈炭,分為: 對DuerOS指令主要是對話指令;其他都是對端的指令
    private List<Directive> directives = new ArrayList<>();
    // 是否需要結(jié)束本次會話,DuerOS用于判斷是否需要關(guān)閉某個打開的Bot宝恶,端用于關(guān)閉麥克風(fēng)
    private boolean shouldEndSession;
    // 麥克風(fēng)是否開啟
    private boolean expectSpeech;
    ......

輸出相關(guān)

Card類主要應(yīng)用于有屏設(shè)備的展示符隙,是個抽象類,派生出多種卡片展示:

ImageCard.java

LinkAccountCard.java

ListCard.java

StandardCard.java

TextCard.java

語音的輸出主要是通過OutputSpeech類來實(shí)現(xiàn)垫毙,Reprompt的應(yīng)用場景不同霹疫,但在實(shí)現(xiàn)上封裝了OutputSpeech類。

對于具體的播放資源實(shí)體综芥,通過Resource類實(shí)現(xiàn)丽蝎,可以使用各種Entity的各種數(shù)據(jù)對象,尤其要注意Entity中的token膀藐,錯誤的token設(shè)置可能會導(dǎo)致資源無法播放屠阻。

會話相關(guān)

Session類與Request package中的Session類類似,主要是HashMap的session attribute 列表额各。

技能服務(wù)的指令

和Event 對應(yīng)国觉, 技能服務(wù)返回一系列指令(directive)使DuerOS的設(shè)備端完成對應(yīng)的操作。Directive 是一個抽象類虾啦,其他的各種directive大都繼承于此麻诀。

音視頻播放器都保護(hù)play.java和stop.java 指令,但是視頻播放還有一個ClearQueue.java 的指令傲醉。同時针饥,二者都有對媒體內(nèi)容的封裝,例如Stream需频,AudioItem,VedioItem等筷凤。

與對話相關(guān)的指令都繼承自DialogDirective類昭殉,指令對應(yīng)的類文件如下所示:

事件名 對應(yīng)的類
Dialog.ElicitSlot   ElicitSlot.java
Dialog.Delegate Delegate.java
Dialog.ConfirmIntent    ConfirmIntent.java
Dialog.ConfirmSlot  ConfirmSlot

需要注意的是苞七,Delegate代理的是處理邏輯,話術(shù)及意圖需要通過DBP 平臺進(jìn)行配置挪丢。

用戶授權(quán)的指令包括permission類和AskForPermissionsConsent類蹂风。 目前,DBP平臺提高了4種類型的用戶授權(quán):

    public static final String READ_USER_PROFILE = "READ::USER:PROFILE";
    public static final String READ_DEVICE_LOCATION = "READ::DEVICE:LOCATION";
    public static final String WRITE_SMARTHOME_PRINTER = "WRITE::SMARTHOME:PRINTER";
    public static final String RECORD_SPEECH = "RECORD::SPEECH";

當(dāng)然乾蓬,這些授權(quán)可以組合傳遞惠啄。

DBP 提供了輕量級的支付體系,類ChargeBaiduPay實(shí)現(xiàn)了主要的支付功能任内,SellerOrderAttributes 是訂單的信息撵渡。也就是說, DBP 是通過百度的聚合收銀臺實(shí)現(xiàn)了支付特性死嗦,用戶可以通過支付寶趋距、微信和百度錢包完成支付。

對DuerOS的有屏設(shè)備如小度在家而言越除,DBP的SDK還有完成觸摸屏上的人機(jī)交互节腐,主要指令只有一個Hint。但是摘盆,為了使開發(fā)更為高效翼雀,在Display.templates中提供了大量的模版可以使用。

NLU相關(guān)

NLU的模塊主要提供了Intent類和Slot類孩擂, 用于描述意圖和槽位狼渊。

public class Intent {

    // 意圖名稱
    private final String name;
    // 意圖確認(rèn)狀態(tài)
    private final ConfirmationStatus confirmationStatus;
    // 意圖中的槽位
    private final Map<String, Slot> slots;
    // 意圖置信度
    private final int score;
    ......

關(guān)于意圖和槽位的具體含義,可以參見《感知自然語言理解(NLU)》一文肋殴。

技能服務(wù)的載體——Bot

Bot 是技能服務(wù)的載體囤锉,BaseBot是所有Bot的基類,使用Bot-SDK開發(fā)的Bot都需要繼承這個類护锤。

public class BaseBot {

    // Base子類構(gòu)造的Response
    protected Response response;
    // Bot收到的Request請求
    private final Request request;
    // 會話信息
    private Session session = new Session();
    // 是否需要結(jié)束本次會話
    private boolean shouldEndSession = false;
    // 如果DuerOS仍然會選用當(dāng)前Bot結(jié)果官地,應(yīng)該再次下發(fā)請求,并將request.determined字段設(shè)置為true
    private boolean needDetermine = false;
    // 麥克風(fēng)開關(guān)是否打開
    private boolean expectSpeech = false;
    // 返回的指令
    private List<Directive> directives = new ArrayList<Directive>();
    // 通過NLU解析出來的Intent
    private Intent intent;

    // 是否打開參數(shù)驗(yàn)證烙懦,默認(rèn)為false
    private boolean enableCertificate = false;
    // afterSearchScore
    private float afterSearchScore = 1.0f;
    private List<ExpectResponse> expectResponses = new ArrayList<>();
    // 認(rèn)證簽名
    private Certificate certificate;
    // 緩存認(rèn)證相關(guān)信息
    private static ConcurrentHashMap<String, PublicKey> cache = new ConcurrentHashMap<>();
    // 數(shù)據(jù)統(tǒng)計信息
    public BotMonitor botMonitor;
    ......

BaseBot通過一系列方法完成了對Request/Response的讀取和設(shè)置驱入,可以通過Serverlet的request來構(gòu)造BaseBot:

    protected BaseBot(HttpServletRequest request) throws IOException, JsonMappingException {
        certificate = new Certificate(request);
        String message = certificate.getMessage();
        ObjectMapper mapper = new ObjectMapper();
        this.request = mapper.readValue(message, Request.class);
        this.botMonitor = new BotMonitor(message);
        this.session.getAttributes().putAll(this.request.getSession().getAttributes());
    }

BaseBot 還完成了事件的分發(fā),證書驗(yàn)證等功能氯析,是主要的邏輯處理引擎亏较。

AudioPlayer和VideoPlayer繼承自BaseBot,主要對DuerOS設(shè)備端上傳的事件進(jìn)行具體處理掩缓。

DBP Java SDK 的應(yīng)用

建議采用Maven 來構(gòu)建工程雪情,這樣可以避免庫版本的不一致性帶來的困擾。

通過DBP Java SDK 構(gòu)建一個DuerOS技能和開發(fā)一個web服務(wù)沒什么區(qū)別你辣,只需要實(shí)現(xiàn)對應(yīng)的Action 和自己的技能服務(wù)邏輯即可巡通。

以sample中的個稅計算器為例尘执,只有TaxAction.java和TaxBot.java兩個文件,但可以看到實(shí)現(xiàn)的要點(diǎn)宴凉。

Action的實(shí)現(xiàn)

TaxAction 繼承自HttpServlet誊锭,但只實(shí)現(xiàn)了http中的3個方法:Head,GET和POST弥锄。

在POST方法中實(shí)現(xiàn)了技能服務(wù)的入口:

 protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 根據(jù)request創(chuàng)建Bot
        TaxBot bot;
        try {
            bot = new TaxBot(request);
            // 線下調(diào)試時丧靡,可以關(guān)閉簽名驗(yàn)證
            // bot.enableVerify();
            bot.disableVerify();

            // 調(diào)用bot的run方法
            String responseJson = bot.run();
            // 設(shè)置response的編碼UTF-8
            response.setCharacterEncoding("UTF-8");
            // 返回response
            response.getWriter().append(responseJson);

            // 打開簽名驗(yàn)證
            // bot.enableVerify();

        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().append(e.toString());
        }
    }

其中,在測試環(huán)境中籽暇,可以關(guān)閉簽名的驗(yàn)證温治。

TaxBot的實(shí)現(xiàn)

TaxBot繼承自BaseBot,onLaunch()方法是啟動對話的入口:

    protected Response onLaunch(LaunchRequest launchRequest) {
        // 新建文本卡片
        TextCard textCard = new TextCard("所得稅為您服務(wù)");
        // 設(shè)置鏈接地址
        textCard.setUrl("www:....");
        // 設(shè)置鏈接內(nèi)容
        textCard.setAnchorText("setAnchorText");
        // 添加引導(dǎo)話術(shù)
        textCard.addCueWord("歡迎進(jìn)入");

        // 新建返回的語音內(nèi)容
        OutputSpeech outputSpeech = new OutputSpeech(SpeechType.PlainText, "所得稅為您服務(wù)");

        // 構(gòu)造返回的Response
        Response response = new Response(outputSpeech, textCard);
        return response;
    }
onInent()方法實(shí)現(xiàn)了DuerOS處理后的語音意圖:

@Override
protected Response onInent(IntentRequest intentRequest) {

    // 判斷NLU解析的意圖名稱是否匹配 inquiry
    if ("inquiry".equals(intentRequest.getIntentName())) {
        // 判斷NLU解析解析后是否存在這個槽位
        if (getSlot("monthlysalary") == null) {
            // 詢問月薪槽位monthlysalary
            ask("monthlysalary");
            return askSalary();
        } else if (getSlot("location") == null) {
            // 詢問城市槽位location
            ask("location");
            return askLocation();
        } else if (getSlot("compute_type") == null) {
            // 詢問查詢種類槽位compute_type
            ask("compute_type");
            return askComputeType();
        } else {
            // 具體計算方法
            return compute();
        }
    }
    return null;
}
onSessionEnded()方法用于結(jié)束會話:

    @Override
    protected Response onSessionEnded(SessionEndedRequest sessionEndedRequest) {

        // 構(gòu)造TextCard
        TextCard textCard = new TextCard("感謝使用所得稅服務(wù)");
        textCard.setAnchorText("setAnchorText");
        textCard.addCueWord("歡迎再次使用");

        // 構(gòu)造OutputSpeech
        OutputSpeech outputSpeech = new OutputSpeech(SpeechType.PlainText, "歡迎再次使用所得稅服務(wù)");

        ListCard listCard = new ListCard();
        StandardCardInfo item1 = new StandardCardInfo("title1", "content1");
        StandardCardInfo item2 = new StandardCardInfo("title2", "content2");
        listCard.addStandardCardInfo(item1);
        listCard.addStandardCardInfo(item2);

        // 構(gòu)造Response
        Response response = new Response(outputSpeech, textCard);

        return response;
    }

具體的图仓,askLocation()和askComputeType()完成槽位的填充罐盔,compute()完成具體的個稅計算。

當(dāng)然救崔,開發(fā)技能服務(wù)需要從開發(fā)者注冊開始惶看,還需要在DBP的管理平臺對意圖技能配置單很簡單,從注冊到配置技能在10分鐘內(nèi)可以完成六孵,詳情參考官網(wǎng):dueros.baidu.com/dbp

小結(jié)

為了方便DBP協(xié)議實(shí)現(xiàn)纬黎,可以使用DBP SDK 提高開發(fā)的效率,理解SDK的實(shí)現(xiàn)方式和原理對于SDK的使用有著很大的幫助劫窒,從而本今,開發(fā)者可以方便且高效地發(fā)布自己的技能服務(wù)。對于嘗鮮的用戶而言主巍,可以嘗試小技能的開發(fā)冠息。無需編程,幾分鐘就可能實(shí)現(xiàn)一個自己的小技能孕索。

當(dāng)然逛艰,各種編程語言的DBP SDK還在持續(xù)演進(jìn)中,值得期待搞旭。

參考:
https://dueros.baidu.com/dbp
https://github.com/dueros/bot-sdk-java

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末散怖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肄渗,更是在濱河造成了極大的恐慌镇眷,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翎嫡,死亡現(xiàn)場離奇詭異欠动,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)惑申,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門具伍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铆遭,“玉大人,你說我怎么就攤上這事沿猜。” “怎么了碗脊?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵啼肩,是天一觀的道長。 經(jīng)常有香客問我衙伶,道長祈坠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任矢劲,我火速辦了婚禮赦拘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芬沉。我一直安慰自己躺同,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布丸逸。 她就那樣靜靜地躺著蹋艺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪黄刚。 梳的紋絲不亂的頭發(fā)上捎谨,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音憔维,去河邊找鬼涛救。 笑死,一個胖子當(dāng)著我的面吹牛业扒,可吹牛的內(nèi)容都是我干的检吆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼凶赁,長吁一口氣:“原來是場噩夢啊……” “哼咧栗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起虱肄,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤致板,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后咏窿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體斟或,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年集嵌,在試婚紗的時候發(fā)現(xiàn)自己被綠了萝挤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片御毅。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖怜珍,靈堂內(nèi)的尸體忽然破棺而出端蛆,到底是詐尸還是另有隱情,我是刑警寧澤酥泛,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布今豆,位于F島的核電站,受9級特大地震影響柔袁,放射性物質(zhì)發(fā)生泄漏呆躲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一捶索、第九天 我趴在偏房一處隱蔽的房頂上張望插掂。 院中可真熱鬧,春花似錦腥例、人聲如沸辅甥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肆氓。三九已至,卻和暖如春底瓣,著一層夾襖步出監(jiān)牢的瞬間谢揪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工捐凭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拨扶,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓茁肠,卻偏偏與公主長得像患民,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子垦梆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一般地托猩,開發(fā)一個對話系統(tǒng)或者機(jī)器人問答系統(tǒng)會涉及諸多領(lǐng)域的技術(shù)印蓖,除了硬件系統(tǒng)之外,還包括語言識別京腥,自然語言處理/識...
    abel_cao閱讀 427評論 0 0
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個完善的 IM 系統(tǒng)...
    layjoy閱讀 13,758評論 0 15
  • AI即人工智能是一個令人著迷的領(lǐng)域赦肃,尤其是基于對話式AI系統(tǒng)的智能音箱的興起,使人工智能直接走進(jìn)了我們的家庭。 自...
    abel_cao閱讀 12,697評論 0 8
  • 每天進(jìn)步一點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)~~從開始只能寫幾句話他宛、模仿別人的觀點(diǎn)船侧,到現(xiàn)...
    一個帥氣的名字呀閱讀 18,083評論 4 31
  • 點(diǎn)此進(jìn)入南京郵電大學(xué)網(wǎng)絡(luò)攻防訓(xùn)練平臺 解題過程 在瀏覽器中顯示的亂亂的東西,是編碼的問題換成正常編碼之后是這樣的:...
    Cytosine閱讀 3,147評論 0 3