今天要來跟各位一起解析 QnA Maker Bot,以下簡稱 QA Bot。
今天是參考 官方範例程式碼。
class QnABot(ActivityHandler):
def __init__(
self,
conversation_state: ConversationState,
user_state: UserState,
dialog: Dialog,
):
self.conversation_state = conversation_state
self.user_state = user_state
self.dialog = dialog
async def on_turn(self, turn_context: TurnContext):
await super().on_turn(turn_context)
await self.conversation_state.save_changes(turn_context)
await self.user_state.save_changes(turn_context)
async def on_members_added_activity(
self, members_added: List[ChannelAccount], turn_context: TurnContext
):
for member in members_added:
if member.id != turn_context.activity.recipient.id:
await turn_context.send_activity("Hello and welcome!")
async def on_message_activity(self, turn_context: TurnContext):
await DialogHelper.run_dialog(
self.dialog,
turn_context,
self.conversation_state.create_property("DialogState"),
)
這裡大家不知道有沒有發現一件事情,就是這個範例明明有用到 Dialog,但是卻沒有看到像昨天一樣的 .py 檔。這是因為 Microsoft 專門幫 QnA Maker 寫了一個 dialog.py 檔,放在 SDK 裡了。
def __init__(
self,
knowledgebase_id: str,
endpoint_key: str,
hostname: str,
no_answer: Activity = None,
threshold: float = DEFAULT_THRESHOLD,
active_learning_card_title: str = DEFAULT_CARD_TITLE,
card_no_match_text: str = DEFAULT_CARD_NO_MATCH_TEXT,
top: int = DEFAULT_TOP_N,
card_no_match_response: Activity = None,
strict_filters: [Metadata] = None,
dialog_id: str = "QnAMakerDialog",
):
"""
Initializes a new instance of the QnAMakerDialog class.
:param knowledgebase_id: The ID of the QnA Maker knowledge base to query.
:param endpoint_key: The QnA Maker endpoint key to use to query the knowledge base.
:param hostname: The QnA Maker host URL for the knowledge base, starting with "https://" and
ending with "/qnamaker".
:param no_answer: The activity to send the user when QnA Maker does not find an answer.
:param threshold: The threshold for answers returned, based on score.
:param active_learning_card_title: The card title to use when showing active learning options
to the user, if active learning is enabled.
:param card_no_match_text: The button text to use with active learning options,
allowing a user to indicate none of the options are applicable.
:param top: The maximum number of answers to return from the knowledge base.
:param card_no_match_response: The activity to send the user if they select the no match option
on an active learning card.
:param strict_filters: QnA Maker metadata with which to filter or boost queries to the
knowledge base; or null to apply none.
:param dialog_id: The ID of this dialog.
"""
super().__init__(dialog_id)
self.knowledgebase_id = knowledgebase_id
self.endpoint_key = endpoint_key
self.hostname = hostname
self.no_answer = no_answer
self.threshold = threshold
self.active_learning_card_title = active_learning_card_title
self.card_no_match_text = card_no_match_text
self.top = top
self.card_no_match_response = card_no_match_response
self.strict_filters = strict_filters
self.maximum_score_for_low_score_variation = 0.95
self.add_step(self.__call_generate_answer)
self.add_step(self.__call_train)
self.add_step(self.__check_for_multiturn_prompt)
self.add_step(self.__display_qna_result)
從這個 dialog 的建構函式來看,用的是 waterfall dialog,若要自己客製化步驟,則加在
## 若要新增步驟,則是加在這裡,並在底下定義新的函式
self.add_step(self.__newSTEP)
self.add_step(self.__call_generate_answer)
self.add_step(self.__call_train)
self.add_step(self.__check_for_multiturn_prompt)
self.add_step(self.__display_qna_result)
接下來再回到 官方範例程式碼 的 config.py。
import os
class DefaultConfig:
""" Bot Configuration """
PORT = 3978
APP_ID = os.environ.get("MicrosoftAppId", "")
APP_PASSWORD = os.environ.get("MicrosoftAppPassword", "")
QNA_KNOWLEDGEBASE_ID = os.environ.get("QnAKnowledgebaseId", "")
QNA_ENDPOINT_KEY = os.environ.get("QnAEndpointKey", "")
QNA_ENDPOINT_HOST = os.environ.get("QnAEndpointHostName", "")
要使用哪一個 QnA Maker 的 Knowledge Base(知識庫) 則是在這邊設定。
# Create ConversationState and UserState
STORAGE = MemoryStorage()
CONVERSATION_STATE = ConversationState(STORAGE)
USER_STATE = UserState(STORAGE)
# Create the main dialog and bot
DIALOG = QnAMakerDialog(
CONFIG.QNA_KNOWLEDGEBASE_ID,
CONFIG.QNA_ENDPOINT_KEY,
CONFIG.QNA_ENDPOINT_HOST,
)
BOT = QnABot(CONVERSATION_STATE, USER_STATE, DIALOG)
這個範例的 Storage 一樣也是用 In-memory Storage
,並且也可以看到 Dialog 是用官方 SDK 的 class 來實作。
若要回顧 QnA Maker 的學理及操作,請參考:
以上是今天嘗試解析 QA Bot 的程式碼,我們明天見。