【Rasa-Core源碼閱讀】Tracker

最近在做dialog policy相關(guān)的研究,實(shí)現(xiàn)就用了rasa的輪子,看源碼順便寫篇文章。水平有限,還請(qǐng)指正。

先吹一波

rasa core的代碼質(zhì)量非常高非常高非常高!我知道有許多中國工程師參與了開發(fā),牛逼!

整體思路

我們先從執(zhí)行的角度來分析tracker的源碼

  • 是什么?如何初始化
  • 輸入是什么
  • 跟蹤了什么內(nèi)容
  • 如何更新狀態(tài)
  • 狀態(tài)如何表達(dá)

如何初始化 —— init

下面是init的全部代碼,非常簡(jiǎn)單,我做了一些注釋方便理解,其實(shí)源碼里面的注釋很多,原來的注釋大家就直接看源碼吧。多說一句,rasa的源碼寫得太漂亮了,注釋詳細(xì),格式規(guī)范,讀起來就是享受。

    def __init__(self, sender_id, slots,
                 max_event_history=None):
        """Initialize the tracker.

        A set of events can be stored externally, and we will run through all
        of them to get the current state. The tracker will represent all the
        information we captured while processing messages of the dialogue."""

        # 可以跟蹤的最長(zhǎng)歷史,tracker記錄狀態(tài)是以event為單位的
        self._max_event_history = max_event_history
        # 歷史事件列表
        self.events = self._create_events([])
        # 這個(gè)id和rasa的chenel特性有關(guān)系
        self.sender_id = sender_id
        # slot列表
        self.slots = {slot.name: copy.deepcopy(slot) for slot in slots}

        ###
        # current state of the tracker - MUST be re-creatable by processing
        # all the events. This only defines the attributes, values are set in
        # `reset()`
        ###
        # 暫停標(biāo)志
        self._paused = None
        # 一些action記錄
        self.followup_action = ACTION_LISTEN_NAME
        self.latest_action_name = None
        self.latest_message = None
        # bot的上一個(gè)返回內(nèi)容
        self.latest_bot_utterance = None
        self._reset()

從init函數(shù)中我們可以知道些什么呢?

  • tracker是記錄一個(gè)用戶對(duì)話狀態(tài)的對(duì)象
  • tracker基于Event對(duì)象跟蹤對(duì)話狀態(tài)

Event

既然tracker是基于Event的,我們就來看看Event是啥

簡(jiǎn)單來說,Event就是對(duì)bot一切行為的抽象,每一個(gè)具體的事件類都繼承自Event基類

class Event(object):
    """Events describe everything that occurs in
    a conversation and tell the :class:`DialogueStateTracker`
    how to update its state."""

    type_name = "event"

    def __init__(self, timestamp=None):
        self.timestamp = timestamp if timestamp else time.time()

這種設(shè)計(jì)很優(yōu)秀,使得tracker可以跟蹤系統(tǒng)預(yù)定義以外的事件,只要你自己實(shí)現(xiàn)一個(gè)Event的子類就行。說起來這是應(yīng)該是面向?qū)ο蟮幕驹O(shè)計(jì)思維,但是真正編碼的時(shí)候很難考慮周全。

rasa-core內(nèi)部實(shí)現(xiàn)了以下Event


Event子類

名字一看就知道大概什么意思了

下面我們看一下Event核心的方法apply_to()

class UserUttered(Event):
        def apply_to(self, tracker):
            # type: (DialogueStateTracker) -> None

            tracker.latest_message = self
            tracker.clear_followup_action()

看一個(gè)就行,這是在干嘛呢?就是給tracker改屬性,把一些和自己有關(guān)的內(nèi)容更新了。

為什么要有這個(gè)方法呢?因?yàn)槊總€(gè)Event需要修改的屬性不一樣,把這部分邏輯放到子類自己實(shí)現(xiàn),調(diào)用邏輯在tracker實(shí)現(xiàn),最大化復(fù)用代碼。這同樣應(yīng)該屬于基礎(chǔ)思維,那么自己做到了么(逃

狀態(tài)更新 —— update

    def update(self, event):
        # type: (Event) -> None
        """Modify the state of the tracker according to an ``Event``. """

        if not isinstance(event, Event):  # pragma: no cover
            raise ValueError("event to log must be an instance "
                             "of a subclass of Event.")

        self.events.append(event)
        event.apply_to(self)

就是這么簡(jiǎn)單

輸出

上面說的內(nèi)容就是tracker的核心部分了,抽象非常優(yōu)美。題外話,推薦大家讀一讀Flask的源碼,我讀了一部分,說賞心悅目不為過,那種架構(gòu)設(shè)計(jì)的嚴(yán)謹(jǐn)優(yōu)雅看著是真tm舒服。

tracker記錄了整個(gè)交流的過程,提供了生成Story的接口和生成Dialog的接口

    def export_stories(self):
        # type: () -> Text
        """Dump the tracker as a story in the Rasa Core story format.

        Returns the dumped tracker as a string."""
        from dqn_policy.training.structures import Story

        story = Story.from_events(self.applied_events())
        return story.as_story_string(flat=True)

     def as_dialogue(self):
        # type: () -> Dialogue
        """Return a ``Dialogue`` object containing all of the turns.

        This can be serialised and later used to recover the state
        of this tracker exactly."""

        return Dialogue(self.sender_id, list(self.events))

其他接口

tracker還實(shí)現(xiàn)了很多接口,涉及到了rasa的各個(gè)部分,就不一一細(xì)說了。里面很多是用來featurize的輔助接口,我也還沒把這部分研究透,后面會(huì)再寫一篇聊featurize,這是rasa core的核心組件

總結(jié)一哈

tracker是rasa core中承上啟下的一環(huán),它記錄來自前端輸入的數(shù)據(jù),又為模型訓(xùn)練的featurize提供基礎(chǔ)。從tracker出發(fā)基本能摸清楚整個(gè)rasa core的框架結(jié)構(gòu)。rasa core抽象做得非常好,代碼質(zhì)量賊高,必須吹一波。這部分源碼相對(duì)比較簡(jiǎn)單,注釋非常詳細(xì),讀起來很舒服,推薦大家都讀一讀。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概念: FastDFS是余慶(前阿里巴巴架構(gòu)師,現(xiàn)易到用車架構(gòu)師)開發(fā)的一個(gè)開源的輕量級(jí)分布式文件系統(tǒng),對(duì)于小文件...
    yingyingguigui閱讀 5,982評(píng)論 0 2
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,656評(píng)論 1 32
  • core package 概要:Core是所有其他包的基礎(chǔ)包.它提供了大部分功能包括metadata,templa...
    LOVE小狼閱讀 2,872評(píng)論 0 3
  • 本文章是 Vert.x 藍(lán)圖系列 的第二篇教程。全系列: Vert.x Blueprint 系列教程(一) | 待...
    sczyh30閱讀 2,188評(píng)論 0 10
  • 和發(fā)小約了一場(chǎng)旅行,兩個(gè)女人,各自帶著一個(gè)剛滿4歲的兒子,相約千里之外的南方城市,因?yàn)槌霭l(fā)地不同,所以選擇...
    卷卷的圓寶閱讀 506評(píng)論 2 2

友情鏈接更多精彩內(nèi)容