diff --git a/public/plugins/chatbot/ChitChatAssistant/ReadMe.md b/public/plugins/chatbot/ChitChatAssistant/ReadMe.md new file mode 100644 index 00000000..a03400f0 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/ReadMe.md @@ -0,0 +1,165 @@ +# RASA中文聊天机器人项目 + + + +--- + +**RASA 开发中文指南系列博文:** + +- [Rasa中文聊天机器人开发指南(1):入门篇](https://jiangdg.blog.csdn.net/article/details/104328946) +- [Rasa中文聊天机器人开发指南(2):NLU篇](https://jiangdg.blog.csdn.net/article/details/104530994) +- [Rasa中文聊天机器人开发指南(3):Core篇](https://jiangdg.blog.csdn.net/article/details/105434136) +- Rasa中文聊天机器人开发指南(4):RasaX篇 +- Rasa中文聊天机器人开发指南(5):Action篇 + +**注:本系列博客翻译自[Rasa官方文档](https://rasa.com/docs/rasa/),并融合了自己的理解和项目实战,同时对文档中涉及到的技术点进行了一定程度的扩展,目的是为了更好的理解Rasa工作机制。与本系列博文配套的项目GitHub地址:[ChitChatAssistant](https://github.com/jiangdongguo/ChitChatAssistant),欢迎`star`和`issues`,我们共同讨论、学习!** + +--- + + +# 1. 安装rasa + +## 1.1 环境要求 + +- python 3.6 + +- mitie +- jieba + +## 1.2 安装步骤 + +**1. 安装rasa** + +```shell +# 当前版本为1.9.5 +# 该命令运行时间较长,会安装完所有的依赖 +pip --default-timeout=500 install -U rasa +``` + +**2. 安装mitie** + +```shell +# 在线安装Mitie +pip install git+https://github.com/mit-nlp/MITIE.git +pip install rasa[mitie] # 注:由于第一步始终没成功过,没尝试过这个命令的意义 +``` + 由于自己在线安装尝试了很多次都拉不下来,因此只能走离线安装的方式,有三个步骤: + +- 首先,下载[MITIE源码](https://github.com/mit-nlp/MITIE)和中文词向量模型[total_word_feature_extractor_zh.dat(密码:p4vx)](https://pan.baidu.com/s/1kNENvlHLYWZIddmtWJ7Pdg),这里需要将该模型拷贝到创建的python项目data目录下(可任意位置),后面训练NLU模型时用到; + +- 其次,安装[Visual Studio 2017](https://blog.csdn.net/qq_42276781/article/details/88594870) ,需要勾选“`用于 CMake 的 Visual C++ 工具`”,因为编译MITIE源码需要Cmake和Visual C++环境。安装完毕后,将`C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin`添加到环境变量中,再重启电脑使之生效; + +- 从Pycharm的命令终端进行Mitie源码根目录,执行下面的命令: + + > python setup.py build + > python setup.py install + + +**3. 安装jieba** + +```shell +# 安装Jieba中文分词 +pip install jieba +``` + +# 2. 训练模型 + + 当所有样本和配置文件准备好后,接下来就是训练模型了,打开命令终端执行下面的命令,该命令会同时训练NLU和Core模型。 + +- 使用MITIE + +```shell +python -m rasa train --config configs/config.yml --domain configs/domain.yml --data data/ +``` + +- 使用Supervised_Embedding + +```bash +python -m rasa train --config configs/zh_jieba_supervised_embeddings_config.yml --domain configs/domain.yml --data data/ +``` + +- 使用MITIE+Supervised_Embedding + +```bash +python -m rasa train --config configs/zh_jieba_mitie_embeddings_config.yml --domain configs/domain.yml --data data/ +``` + +# 3. 运行服务 + +**(1)启动Rasa服务** + + 在命令终端,输入下面命令: + +```shell +# 启动rasa服务 +# 该服务实现自然语言理解(NLU)和对话管理(Core)功能 +# 注:该服务的--port默认为5005,如果使用默认则可以省略 +python -m rasa run --port 5005 --endpoints configs/endpoints.yml --credentials configs/credentials.yml --debug +``` + +**(2)启动Action服务** + +在命令终端,输入下面命令: + +```shell +# 启动action服务 +# 注:该服务的--port默认为5055,如果使用默认则可以省略 +Python -m rasa run actions --port 5055 --actions actions --debug +``` + +**(3)启动server.py服务** + +```shell +python server.py +``` + +当**Rasa Server**、**Action Server**和**Server.py**运行后,在浏览器输入测试: + +` http://127.0.0.1:8088/ai?content=查询广州明天的天气` + +终端调用效果为: + +![](https://img-blog.csdnimg.cn/20200227153932228.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0FuZHJFeHBlcnQ=,size_16,color_FFFFFF,t_70) + + + +# 4. 更新日志 + + +**(1)V1.0.2020.02.15** + +- 创建项目,模型训练成功; +- 前端访问Rasa服务器正常响应; +- 对接图灵闲聊机器人、心知天气API,便于测试; + +**(2)V1.1.2020.02.27** + +- 优化NLU样本,尝试使用同义词、正则、查找表; +- 改进supervised_embeddings,实体提取和意图识别明显提高,训练速度加快很多; +- 完成`Rasa中文聊天机器人开发指南(2):NLU篇`文章撰写; + +**(3)V1.2.2020.04.10** + +- 使用Interactive Learning构建样本; +- 新增MITIE+supervised_embeddings管道,并训练相应的模型; +- 新增身份查询案例; +- 将Rasa版本升级到1.9.5,解决win10使用tensorflow出现的异常(详见`入门篇`); +- 完成`Rasa中文聊天机器人开发指南(3):Core篇`文章撰写; + +# 5. License + +> ``` +> Copyright 2020 Jiangdongguo +> +> Licensed under the Apache License, Version 2.0 (the "License"); +> you may not use this file except in compliance with the License. +> You may obtain a copy of the License at +> +> http://www.apache.org/licenses/LICENSE-2.0 +> +> Unless required by applicable law or agreed to in writing, software +> distributed under the License is distributed on an "AS IS" BASIS, +> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +> See the License for the specific language governing permissions and +> limitations under the License. +> ``` + diff --git a/public/plugins/chatbot/ChitChatAssistant/actions/ChatApis.py b/public/plugins/chatbot/ChitChatAssistant/actions/ChatApis.py new file mode 100644 index 00000000..0251c0a5 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/actions/ChatApis.py @@ -0,0 +1,59 @@ +# 访问图灵机器人openapi +# -*- coding: utf-8 -*- +""" + ChatApis.py + ~~~~~~~~~ + + 图灵机器人(公司)闲聊系统API对接 + 免费版只限每天调用100次,需联外网 + + :date: 2020-02-10 15:56:00 + :author: by jiangdg +""" +import requests +import json + + +def get_response(msg): + """ + 访问图灵机器人openApi + + :param msg 用户输入的文本消息 + :return string or None + """ + apiurl = "http://openapi.tuling123.com/openapi/api/v2" + # 构造请求参数实体 + params = {"reqType": 0, + "perception": { + "inputText": { + "text": msg + } + }, + "userInfo": { + "apiKey": "ca7bf19ac0e644c38cfbe9d6fdc08de1", + "userId": "439608" + }} + # 将表单转换为json格式 + content = json.dumps(params) + + # 发起post请求 + r = requests.post(url=apiurl, data=content, verify=False).json() + print("r = " + str(r)) + + # 解析json响应结果 + # {'emotion':{ + # 'robotEmotion': {'a': 0, 'd': 0, 'emotionId': 0, 'p': 0}, + # 'userEmotion': {'a': 0, 'd': 0, 'emotionId': 10300, 'p': 0} + # }, + # 'intent': { + # 'actionName': '', + # 'code': 10004, + # 'intentName': '' + # }, + # 'results': [{'groupType': 1, 'resultType': 'text', 'values': {'text': '欢迎来到本机器人的地盘。'}}]} + code = r['intent']['code'] + if code == 10004 or code == 10008: + message = r['results'][0]['values']['text'] + return message + return None + diff --git a/public/plugins/chatbot/ChitChatAssistant/actions/WeatherApis.py b/public/plugins/chatbot/ChitChatAssistant/actions/WeatherApis.py new file mode 100644 index 00000000..3db5a4fd --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/actions/WeatherApis.py @@ -0,0 +1,54 @@ +# 访问openapi +# -*- coding: utf-8 -*- +""" + WeatherApis.py + ~~~~~~~~~ + + 使用心知天气数据查询天气 + + :date: 2020-02-10 15:56:00 + :author: by jiangdg +""" + +import requests +import json + +KEY = 'rmhrne8hal69uwyv' # API key(私钥) +UID = "" # 用户ID, TODO: 当前并没有使用这个值,签名验证方式将使用到这个值 + +LOCATION = 'beijing' # 所查询的位置,可以使用城市拼音、v3 ID、经纬度等 +API = 'https://api.seniverse.com/v3/weather/daily.json' # API URL,可替换为其他 URL +UNIT = 'c' # 单位 +LANGUAGE = 'zh-Hans' # 查询结果的返回语言 + + +def fetch_weather(location, start=0, days=15): + result = requests.get(API, params={ + 'key': KEY, + 'location': location, + 'language': LANGUAGE, + 'unit': UNIT, + 'start': start, + 'days': days + }, timeout=2) + return result.json() + + +def get_weather_by_day(location, day=1): + result = fetch_weather(location) + normal_result = { + "location": result["results"][0]["location"], + "result": result["results"][0]["daily"][day] + } + + return normal_result + + +if __name__ == '__main__': + default_location = "合肥" + result = fetch_weather(default_location) + print(json.dumps(result, ensure_ascii=False)) + + default_location = "合肥" + result = get_weather_by_day(default_location) + print(json.dumps(result, ensure_ascii=False)) diff --git a/public/plugins/chatbot/ChitChatAssistant/actions/__init__.py b/public/plugins/chatbot/ChitChatAssistant/actions/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/public/plugins/chatbot/ChitChatAssistant/actions/action.py b/public/plugins/chatbot/ChitChatAssistant/actions/action.py new file mode 100644 index 00000000..927aee9d --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/actions/action.py @@ -0,0 +1,171 @@ +from typing import Dict, Text, Any, List, Union + +from rasa_sdk import Tracker, Action +from rasa_sdk.events import UserUtteranceReverted, Restarted, SlotSet +from rasa_sdk.executor import CollectingDispatcher +from rasa_sdk.forms import FormAction +import re + +from actions import ChatApis +from actions.WeatherApis import get_weather_by_day +from requests import ( + ConnectionError, + HTTPError, + TooManyRedirects, + Timeout +) + + +class NumberForm(FormAction): + """Example of a custom form action""" + + def name(self) -> Text: + """Unique identifier of the form""" + + return "number_form" + + @staticmethod + def required_slots(tracker: Tracker) -> List[Text]: + """A list of required slots that the form has to fill""" + return ["type", "number", "business"] + + def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]: + """A dictionary to map required slots to + - an extracted entity + - intent: value pairs + - a whole message + or a list of them, where a first match will be picked""" + + return { + "type": self.from_entity(entity="type", not_intent="chitchat"), + "number": self.from_entity(entity="number", not_intent="chitchat"), + "business": [ + self.from_entity( + entity="business", intent=["inform", "request_number"] + ), + self.from_entity(entity="business"), + ], + } + + def submit( + self, + dispatcher: CollectingDispatcher, + tracker: Tracker, + domain: Dict[Text, Any], + ) -> List[Dict]: + """Define what the form has to do + after all required slots are filled""" + number_type = tracker.get_slot('type') + number = tracker.get_slot('number') + business = tracker.get_slot('business') + if not business: + dispatcher.utter_message(text="您要查询的{}{}所属人为张三,湖南长沙人,现在就职于地球村物业管理有限公司。".format(number_type, number)) + return [] + + dispatcher.utter_message(text="你要查询{}为{}的{}为:balabalabalabalabala。".format(number_type, number, business)) + return [SlotSet("business", None)] + + +class WeatherForm(FormAction): + + def name(self) -> Text: + """Unique identifier of the form""" + + return "weather_form" + + @staticmethod + def required_slots(tracker: Tracker) -> List[Text]: + """A list of required slots that the form has to fill""" + + return ["date_time", "address"] + + def submit( + self, + dispatcher: CollectingDispatcher, + tracker: Tracker, + domain: Dict[Text, Any], + ) -> List[Dict]: + """Define what the form has to do + after all required slots are filled""" + address = tracker.get_slot('address') + date_time = tracker.get_slot('date_time') + + date_time_number = text_date_to_number_date(date_time) + + if isinstance(date_time_number, str): # parse date_time failed + dispatcher.utter_message("暂不支持查询 {} 的天气".format([address, date_time_number])) + else: + weather_data = get_text_weather_date(address, date_time, date_time_number) + dispatcher.utter_message(weather_data) + return [] + + +def get_text_weather_date(address, date_time, date_time_number): + try: + result = get_weather_by_day(address, date_time_number) + except (ConnectionError, HTTPError, TooManyRedirects, Timeout) as e: + text_message = "{}".format(e) + else: + text_message_tpl = """ + {} {} ({}) 的天气情况为:白天:{};夜晚:{};气温:{}-{} °C + """ + text_message = text_message_tpl.format( + result['location']['name'], + date_time, + result['result']['date'], + result['result']['text_day'], + result['result']['text_night'], + result['result']["high"], + result['result']["low"], + ) + + return text_message + + +def text_date_to_number_date(text_date): + if text_date == "今天": + return 0 + if text_date == "明天": + return 1 + if text_date == "后天": + return 2 + + # Not supported by weather API provider freely + if text_date == "大后天": + # return 3 + return text_date + + if text_date.startswith("星期"): + # TODO: using calender to compute relative date + return text_date + + if text_date.startswith("下星期"): + # TODO: using calender to compute relative date + return text_date + + # follow APIs are not supported by weather API provider freely + if text_date == "昨天": + return text_date + if text_date == "前天": + return text_date + if text_date == "大前天": + return text_date + + +class ActionDefaultFallback(Action): + """Executes the fallback action and goes back to the previous state + of the dialogue""" + + def name(self): + return 'action_default_fallback' + + def run(self, dispatcher, tracker, domain): + + # 访问图灵机器人API(闲聊) + text = tracker.latest_message.get('text') + message = ChatApis.get_response(text) + if message is not None: + dispatcher.utter_message(message) + else: + dispatcher.utter_template('utter_default', tracker, silent_fail=True) + return [UserUtteranceReverted()] diff --git a/public/plugins/chatbot/ChitChatAssistant/configs/config.yml b/public/plugins/chatbot/ChitChatAssistant/configs/config.yml new file mode 100644 index 00000000..81ec0e42 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/configs/config.yml @@ -0,0 +1,22 @@ +language: "zh" + +pipeline: +- name: "MitieNLP" + model: "data/total_word_feature_extractor_zh.dat" +- name: "JiebaTokenizer" + dictionary_path: "data/dict" +- name: "MitieEntityExtractor" +- name: "EntitySynonymMapper" +- name: "RegexFeaturizer" +- name: "MitieFeaturizer" +- name: "SklearnIntentClassifier" + +policies: + - name: KerasPolicy + epochs: 500 + max_history: 5 + - name: FallbackPolicy + fallback_action_name: 'action_default_fallback' + - name: MemoizationPolicy + max_history: 5 + - name: FormPolicy \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/configs/credentials.yml b/public/plugins/chatbot/ChitChatAssistant/configs/credentials.yml new file mode 100644 index 00000000..0e6f78fd --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/configs/credentials.yml @@ -0,0 +1,29 @@ +# This file contains the credentials for the voice & chat platforms +# which your bot is using. +# https://rasa.com/docs/rasa/user-guide/messaging-and-voice-channels/ + +rest: +# # you don't need to provide anything here - this channel doesn't +# # require any credentials + + +#facebook: +# verify: "" +# secret: "" +# page-access-token: "" + +#slack: +# slack_token: "" +# slack_channel: "" + +#socketio: +# user_message_evt: +# bot_message_evt: +# session_persistence: + +#mattermost: +# url: "https:///api/v4" +# team: "" +# user: "" +# pw: "" +# webhook_url: "" diff --git a/public/plugins/chatbot/ChitChatAssistant/configs/domain.yml b/public/plugins/chatbot/ChitChatAssistant/configs/domain.yml new file mode 100644 index 00000000..bde3f628 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/configs/domain.yml @@ -0,0 +1,130 @@ +intents: + - affirm + - deny + - greet + - goodbye + - thanks + - whoareyou + - whattodo + - request_weather + - request_number + - inform + - inform_business + - stop + - chitchat + +session_config: + carry_over_slots_to_new_session: true + session_expiration_time: 60 + +slots: + date_time: + type: unfeaturized + auto_fill: false + address: + type: unfeaturized + auto_fill: false + type: + type: unfeaturized + auto_fill: false + number: + type: unfeaturized + auto_fill: false + business: + type: unfeaturized + auto_fill: false + +entities: + - date_time + - address + - type + - number + - business + +actions: + - utter_answer_affirm + - utter_answer_deny + - utter_answer_greet + - utter_answer_goodbye + - utter_answer_thanks + - utter_answer_whoareyou + - utter_answer_whattodo + - utter_ask_date_time + - utter_ask_address + - utter_ask_number + - utter_ask_business + - utter_ask_type + - action_default_fallback + +forms: + - weather_form + - number_form + +responses: + utter_answer_affirm: + - text: "嗯嗯,好的!" + - text: "嗯嗯,很开心能够帮您解决问题~" + - text: "嗯嗯,还需要什么我能够帮助您的呢?" + + utter_answer_greet: + - text: "您好!请问我可以帮到您吗?" + - text: "您好!很高兴为您服务。请说出您要查询的功能?" + + utter_answer_goodbye: + - text: "再见" + - text: "拜拜" + - text: "虽然我有万般舍不得,但是天下没有不散的宴席~祝您安好!" + - text: "期待下次再见!" + - text: "嗯嗯,下次需要时随时记得我哟~" + - text: "see you!" + + utter_answer_deny: + - text: "主人,您不开心吗?不要离开我哦" + - text: "怎么了,主人?" + + utter_answer_thanks: + - text: "嗯呢。不用客气~" + - text: "这是我应该做的,主人~" + - text: "嗯嗯,合作愉快!" + + utter_answer_whoareyou: + - text: "您好!我是小蒋呀,您的AI智能助理" + + utter_answer_whattodo: + - text: "您好!很高兴为您服务,我目前只支持查询天气哦。" + + utter_ask_date_time: + - text: "请问您要查询哪一天的天气?" + + utter_ask_address: + - text: "请问您要查下哪里的天气?" + + utter_ask_number: + - text: "请问您要查的{type}号码是多少?" + + utter_ask_business: + - text: "请问您要查询什么业务呢?" + + utter_default: + - text: "没听懂,请换种说法吧~" + + utter_ask_continue: + - text: "请问您还要继续吗?" + + utter_noworries: + - text: "不用客气 :)" + - text: "没事啦" + - text: "不客气哈,都是老朋友了 :)" + + utter_wrong_business: + - text: "当前还不支持{business}业务,请重新输入。" + + utter_wrong_type: + - text: "当前还不支持查询{type}。" + + utter_wrong_number: + - text: "您输入的{number}有误,请重新输入。" + + utter_chitchat: + - text: "呃呃呃呃呃" + - text: "您这是在尬聊吗?" \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/configs/endpoints.yml b/public/plugins/chatbot/ChitChatAssistant/configs/endpoints.yml new file mode 100644 index 00000000..2ff5a092 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/configs/endpoints.yml @@ -0,0 +1,42 @@ +# This file contains the different endpoints your bot can use. + +# Server where the models are pulled from. +# https://rasa.com/docs/rasa/user-guide/running-the-server/#fetching-models-from-a-server/ + +#models: +# url: http://my-server.com/models/default_core@latest +# wait_time_between_pulls: 10 # [optional](default: 100) + +# Server which runs your custom actions. +# https://rasa.com/docs/rasa/core/actions/#custom-actions/ + +action_endpoint: + url: "http://localhost:5055/webhook" + +# Tracker store which is used to store the conversations. +# By default the conversations are stored in memory. +# https://rasa.com/docs/rasa/api/tracker-stores/ + +#tracker_store: +# type: redis +# url: +# port: +# db: +# password: +# use_ssl: + +#tracker_store: +# type: mongod +# url: +# db: +# username: +# password: + +# Event broker which all conversation events should be streamed to. +# https://rasa.com/docs/rasa/api/event-brokers/ + +#event_broker: +# url: localhost +# username: username +# password: password +# queue: queue diff --git a/public/plugins/chatbot/ChitChatAssistant/configs/zh_jieba_mitie_embeddings_config.yml b/public/plugins/chatbot/ChitChatAssistant/configs/zh_jieba_mitie_embeddings_config.yml new file mode 100644 index 00000000..957d43e2 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/configs/zh_jieba_mitie_embeddings_config.yml @@ -0,0 +1,25 @@ +language: "zh" + +pipeline: +- name: "MitieNLP" + model: "data/total_word_feature_extractor_zh.dat" +- name: "JiebaTokenizer" + dictionary_path: "data/dict" +- name: "MitieEntityExtractor" +- name: "EntitySynonymMapper" +- name: "RegexFeaturizer" +- name: "MitieFeaturizer" +- name: "EmbeddingIntentClassifier" + +policies: + - name: FallbackPolicy + nlu_threshold: 0.5 + ambiguity_threshold: 0.1 + core_threshold: 0.5 + fallback_action_name: 'action_default_fallback' + - name: MemoizationPolicy + max_history: 5 + - name: FormPolicy + - name: MappingPolicy + - name: EmbeddingPolicy + epochs: 500 \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/configs/zh_jieba_supervised_embeddings_config.yml b/public/plugins/chatbot/ChitChatAssistant/configs/zh_jieba_supervised_embeddings_config.yml new file mode 100644 index 00000000..dafb2807 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/configs/zh_jieba_supervised_embeddings_config.yml @@ -0,0 +1,24 @@ +language: "zh" + +pipeline: +- name: "JiebaTokenizer" + dictionary_path: "data/dict" +- name: "RegexFeaturizer" +- name: "CRFEntityExtractor" +- name: "EntitySynonymMapper" +- name: "CountVectorsFeaturizer" +- name: "CountVectorsFeaturizer" + analyzer: "char_wb" + min_ngram: 1 + max_ngram: 4 +- name: "EmbeddingIntentClassifier" + +policies: + - name: EmbeddingPolicy + epochs: 100 + max_history: 5 + - name: FallbackPolicy + fallback_action_name: 'action_default_fallback' + - name: MemoizationPolicy + max_history: 5 + - name: FormPolicy \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/data/dict/userdict.txt b/public/plugins/chatbot/ChitChatAssistant/data/dict/userdict.txt new file mode 100644 index 00000000..f9d2eba5 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/data/dict/userdict.txt @@ -0,0 +1,3 @@ +电话号码 5 n +手机号 5 n +电话号 5 n \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/data/nlu/chitchat_nlu.md b/public/plugins/chatbot/ChitChatAssistant/data/nlu/chitchat_nlu.md new file mode 100644 index 00000000..3aab51a5 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/data/nlu/chitchat_nlu.md @@ -0,0 +1,164 @@ +## intent:greet +- 你好 +- 你好啊 +- 早上好 +- 晚上好 +- hello +- hi +- 嗨 +- 嗨喽 +- 见到你很高兴 +- 嘿 +- 早 +- 上午好 +- hello哈喽 +- 哈喽哈喽 +- hello hello +- 喂喂 + +## intent:goodbye +- goodbye +- bye +- bye bye +- 88 +- 886 +- 再见 +- 拜 +- 拜拜 +- 拜拜,下次再聊 +- 下次见 +- 回头见 +- 下次再见 +- 下次再聊 +- 有空再聊 +- 先这样吧 +- 好了,就说这么多了 +- 好了,先这样 +- 没事 + +## intent:whoareyou +- 你是谁 +- 我知道你吗 +- 谁 +- 我认识你吗 +- 这是谁啊 +- 是谁 +- 请问你是谁 +- 请问我认识你吗 +- 你是哪位 +- 你是? +- 是谁? +- 可以告诉我你的名字吗 +- 你叫什么名字 + +## intent:whattodo +- 你支持什么功能 +- 你有什么功能 +- 你能干什么 +- 你能做什么 + +## intent:thanks +- 谢谢 +- thanks +- thank you +- 真的太感谢你了,帮了我大忙 +- 谢谢你帮了我大忙 +- 你帮了我大忙,谢谢你小智 +- 非常感谢 +- 谢了 + +## intent:deny +- 不了 +- 算了 +- 不用了 +- 不需要 +- 就这样吧 +- 不 +- no +- 不可以 +- 不是的 +- 不认同 +- 否定 +- 不是这样子的 +- 我不同意你的观点 +- 不同意 +- 不好 +- 你长得很美,就不要想得太美。 +- 拒绝 +- 不行 + +## intent:affirm +- 知道了 +- 是的 +- 当然 +- 好的 +- ok +- 嗯 +- 可以 +- 你可以这么做 +- 你做得可以啊 +- 同意 +- 听起来不错 +- 是这样的 +- 的确是这样子的 +- 我同意你的观点 +- 对的 +- 好滴 +- 行 +- 还行 +- 当然可以 + +## intent:chitchat +- 你是不是傻 +- 你喜欢靓仔靓女吗 +- 能跟我说说你的男朋友吗 +- 嘿,朋友,你好啊? +- 你是堆的 +- 你今天过得开心吗 +- 你没事吧 +- 今天感觉怎么样 +- 广州今天下雨了 +- 我能够知道谁邀请你吗 +- 请告诉我谁创造了你 +- 你的老板是谁 +- 我想知道谁发明了你 +- 你是哪家公司的 +- 你是谁发明的 +- 你是什么 +- 你还好吗 +- 你现在在干什么 +- 最近怎么样 +- 你最近过得怎么样 +- 谁是林俊杰 +- 卢十瓦是不是疯了 +- 你这个早上干什么了 +- 外面真安静 +- 现在的生活变得越来越好了 +- 是不是下雨了 +- 今天的天气很好,不是吗 +- 外面好冷啊 +- 你认识张天爱吗 +- 现在的世界真乱,你说是不是 +- 你今天看不起不错哟 +- 你觉得华为手机怎么样 +- 你知不知道新型冠形病毒 +- 你现在在干什么 + +## intent:stop +- 你是不是傻 +- 你就像个傻逼一样 +- 真差劲,什么都不懂 +- 真蠢 +- 什么都查不到 +- 你什么都不会 +- 感觉你什么都不知道 +- 你太蠢了 +- 我不查了,太傻了 +- 就这样吧 +- 感觉你什么都不会 +- 没有了 +- 什么都没查到 +- 我猜你是不是坏了 + + + diff --git a/public/plugins/chatbot/ChitChatAssistant/data/nlu/number_nlu.md b/public/plugins/chatbot/ChitChatAssistant/data/nlu/number_nlu.md new file mode 100644 index 00000000..b051681d --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/data/nlu/number_nlu.md @@ -0,0 +1,164 @@ +## intent:request_number +- 帮我查一个[电话号码](type) +- 帮我查询[手机号](type) +- 查询[手机号码](type) +- 查询[电话号码](type) +- [手机号](type) +- [电话号](type) +- 查一个[手机](type) +- [13548501905](number) +- 号码是[19820618425](number) +- 查一下[19862618425](number) +- 查下[19862618425](number) +- 我要查的是[19860612425](number) +- 查询的号码是[11160222425](number) +- 我想查的号码是[12260222425](number) +- 帮我查询[电话号码](type),号码是[19820618425](number) +- 帮我查一个号码[19862618425](number) +- [12260222425](number)这[手机号](type) +- 查询[电话](type)[19862618425](number) +- 查询[电话号码](type)[19860612425](number) +- [电话号码](type)为[19860218425](number) +- [电话号](type)为[12860618425](number) +- 查[电话](type)[19820618425](number) +- 我想知道[电话号码](type)为[19860612425](number) +- 我想查[电话号码](type)[19860618422](number) +- 我要查下[电话号](type)[19822618425](number) +- 你好!请帮我查询一下[电话](type)[12260618425](number) +- 查一下[手机号码](type)[19862228425](number) +- 帮我查个[电话](type)[19860612222](number) +- 请告诉我[电话号码](type)为[19860222425](number) +- 查[电话](type)[11160222425](number) +- 查[电话号码](type)[19800222425](number) +- 查[手机号码](type)[12260222425](number) +- 查询[手机](type)[12260222425](number) +- [手机号](type)[12260222425](number) +- [12260222425](number)这[手机号](type) +- 我想查[身份证](type) +- 我要查下[身份证](type) +- 你好!请帮我查询一下[身份证](type) +- 帮我查一个[身份证号码](type) +- 帮我查询[身份证](type) +- 查询[身份证](type) +- 查询[身份证号码](type) +- [身份证](type) +- [身份证号码](type) +- [查身份证](type) +- 我想查[身份证](type) +- 我要查下[身份证](type) +- 你好!请帮我查询一下[身份证](type) +- [330781198509071514](number) +- [44010319790115345X](number) +- 请告诉我[33078119850907853X](number)这个号码是谁的 +- [110101199909073876](number)谁的号码 +- 查下[320102198708085599](number) +- 查[433335196712305681](number) +- 号码[430102199711012075](number) +- 帮我查下[110101199909073876](number) +- [110101199909073876](number)的个人信息 +- [433335196712305681](number)是谁 +- 身份证[433335196712305681](number) +- 查下号码[433335196712305681](number) +- 帮我查询身份证[441235196712305622](number) +- 查询身份证[441235192212305681](number) +- 我想查身份证[441222296712305681](number) +- 身份证号码为[441235196712302222](number) +- 查个身份证,号码是[33078119850907853X](number) + +## intent:inform_business +- [开房信息](business) +- [开房](business) +- [住宿信息](business) +- [住宿记录](business) +- 查一查[开房记录](business) +- 查[开房信息](business) +- [住宿信息](business)怎么样 +- 查下[住宿信息](business) +- 我想了解[开房记录](business) +- [违章记录](business) +- [违章](business) +- [违章信息](business) +- 查下[违章记录](business) +- 我想知道这个号码的[违章信息](business) +- 能告诉我他的[违章记录](business)吗 +- 最近的[违章记录](business) +- [犯罪记录](business) +- [犯罪信息](business) +- [违法记录](business) +- [犯罪](business) +- [违法](business) +- 我要查询这个人的[犯罪记录](business) +- 帮我查[犯罪记录](business) +- 查查[犯罪信息](business) +- 这个人有没有[违法](business) +- 告诉我[犯罪记录](business) +- 查[违法信息](business) +- 我要知道这个人是否有[违法犯罪](business) +- [教育经历](business) +- [教育情况](business) +- [教育](business) +- [教育信息](business) +- 查一查[教育经历](business) +- 这个人的[教育经历](business) +- 看下[教育情况](business) +- 查下[教育信息](business) +- 帮我查一查[教育径路](business) +- [出行轨迹](business) +- [出行信息](business) +- [出行路线](business) +- [出行](business) +- 查下[出行轨迹](business) +- 我想知道这个人的[出行信息](business) + +## synonym:身份证号码 +- 身份证 +- 身份证号码 + +## synonym:电话号码 +- 电话 +- 电话号 +- 电话号码 +- 手机 +- 手机号 +- 手机号码 + +## synonym:违章记录 +- 违章 +- 违章信息 +- 违章记录 +- 违章处罚 +- 违章情况 + +## synonym:教育经历 +- 教育 +- 教育经历 +- 教育信息 +- 教育情况 + +## synonym:出行轨迹 +- 出行 +- 出行路线 +- 出行信息 +- 出行轨迹 +- 出行记录 + +## synonym:开房信息 +- 开房记录 +- 开房 +- 住宿记录 +- 住宿信息 +- 开房信息 + +- ## synonym:犯罪记录 +- 犯罪 +- 犯罪信息 +- 犯罪记录 +- 违法记录 +- 违法 +- 违法犯罪 + +## regex:phone_number +- ((\d{3,4}-)?\d{7,8})|(((\+86)|(86))?(1)\d{10}) + +## regex:number +- ([1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx])|([1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}[0-9Xx]) \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/data/nlu/weather_nlu.md b/public/plugins/chatbot/ChitChatAssistant/data/nlu/weather_nlu.md new file mode 100644 index 00000000..62e55a5c --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/data/nlu/weather_nlu.md @@ -0,0 +1,65 @@ +## intent:request_weather +- 查天气 +- 帮我查下天气 +- 告诉我天气怎么样 +- 查下天气 +- 我要查天气 +- 天气怎么样 +- 看下天气 +- 天气如何 +- 天气 +- 查询天气 +- 帮我查天气信息 +- 我想知道[明天](date_time)的天气 +- [星期一](date_time)的天气 +- [今天](date_time)的天气怎么样 +- 帮我查下[后天](date_time)的天气 +- 查下[广州](address)的天气怎么样 +- [长沙](address)的天气 +- [深圳](address)[明天](date_time)的天气 +- 查下[今天](date_time)[上海](address)的天气 +- 帮我查查[佛山](address)这[周六](date_time)的天气 +- 我想知道[上海](address)[明天](date_time)的天气 +- [上海](address)[明天](date_time)的天气 +- [广州](address)[今天](date_time)的天气 +- [永州](address)[后天](date_time)的天气 +- 你能告诉我[后天](date_time)[广州](address)的天气吗? +- [明天](date_time)在[北京](address) +- 请问[北京](address)[今天](date_time)的天气如何? +- [后天](date_time)我会在[南京](address),请问哪里的天气如何? +- [明天](date_time)我要回[乌鲁木齐](address)了,那里的天气怎么样? +- [今天](date_time)的天气有点冷,不知道[哈尔滨](address)是不是一样冷? +- 小智,帮我查下[明天](date_time)[广州](address)的天气 +- 查询[长沙](address)[后天](date_time)的天气 +- [今天](date_time)[重庆](address)的天气怎么样? +- [深圳](address)昨天下冰雹了,[明天](date_time)还会下吗? + +## intent:inform +- 告诉我在[广州](address)的怎么样 +- [武汉](address) +- 在[北京](address)的呢? +- 我想知道[杭州](address)的天气 +- 我现在在[上海](address) +- [佛山](address)的吧 +- 我要查询[乌鲁木齐](address)的天气 +- 查询[深圳](address)的天气 +- [常德](address)的天气怎么样? +- 请告诉我[武汉](address)的天气 +- 还在[宁波](address) +- [永州](address)的 +- 我现在在[广州](address) +- [上海](address)的天气 +- [今天](date_time)的 +- [明天](date_time)的天气 +- [后天](date_time)的天气 +- 我想知道[明天](date_time)的天气 +- [明天](date_time) +- [后天](date_time) +- [今天](date_time) +- 告诉我[明天](date_time)的天气 +- [明天](date_time)的怎么样 +- 查询[后天](date_time)的天气 +- 查下[明天](date_time)的 +- [后天](date_time)的吧 +- 帮我查下[今天](date_time)的 +- 不知道[今天](date_time)的怎么样 \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/data/stories/chitchat_stories.md b/public/plugins/chatbot/ChitChatAssistant/data/stories/chitchat_stories.md new file mode 100644 index 00000000..b2c12b99 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/data/stories/chitchat_stories.md @@ -0,0 +1,67 @@ +## greet +* greet + - utter_answer_greet + +## say affirm with greet +* greet + - utter_answer_greet +* affirm + - utter_answer_affirm + +## say affirm +* affirm + - utter_answer_affirm + +## say no with greet +* greet + - utter_answer_greet +* deny + - utter_answer_deny + +## say no +* deny + - utter_answer_deny + + +## say goodbye +* goodbye + - utter_answer_goodbye + +## thanks with greet +* greet + - utter_answer_greet +* thanks + - utter_answer_thanks + +## thanks +* thanks + - utter_answer_thanks + +## who are you with greet +* greet + - utter_answer_greet +* whoareyou + - utter_answer_whoareyou + +## who are you +* whoareyou + - utter_answer_whoareyou + +## who are you with greet +* greet + - utter_answer_greet +* whoareyou + - utter_answer_whoareyou + +## what to do +* whattodo + - utter_answer_whattodo + +## what to do with greet +* greet + - utter_answer_greet +* whattodo + - utter_answer_whattodo + + + \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/data/stories/number_story.md b/public/plugins/chatbot/ChitChatAssistant/data/stories/number_story.md new file mode 100644 index 00000000..8b0de960 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/data/stories/number_story.md @@ -0,0 +1,351 @@ +## interactive_story_1 +## happy path +* greet + - utter_answer_greet +* request_number + - number_form + - form{"name": "number_form"} + - form{"name": null} +* thanks + - utter_noworries + +## interactive_story_2 +## happy path +* greet + - utter_answer_greet +* request_number + - number_form + - form{"name": "number_form"} + - slot{"requested_slot": "business"} +* form: inform{"business": "开房记录"} + - slot{"business": "开房记录"} + - form: restaurant_form + - slot{"business": "开房记录"} +* thanks + - utter_noworries + +## interactive_story_3 +# happy path:item+number+business+business+business +* request_number{"type": "身份证号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "身份证号码"} + - slot{"requested_slot": "number"} +* form: request_number{"number": "431124199720139720"} + - form: number_form + - slot{"number": "431124199720139720"} + - slot{"type": "身份证号码"} + - form{"name": null} + - slot{"requested_slot": null} +* inform_business{"business": "违章记录"} + - number_form + - form{"name": "number_form"} + - slot{"type": "身份证号码"} + - slot{"number": "431124199720139720"} + - slot{"business": "违章记录"} + - slot{"business": null} + - form{"name": null} + - slot{"requested_slot": null} +* inform_business{"business": "开房信息"} + - number_form + - form{"name": "number_form"} + - slot{"type": "身份证号码"} + - slot{"number": "431124199720139720"} + - slot{"business": "开房信息"} + - slot{"business": null} + - form{"name": null} + - slot{"requested_slot": null} +* inform_business{"business": "出行轨迹"} + - number_form + - form{"name": "number_form"} + - slot{"type": "身份证号码"} + - slot{"number": "431124199720139720"} + - slot{"business": "出行轨迹"} + - slot{"business": null} + - form{"name": null} + - slot{"requested_slot": null} +* affirm + - utter_answer_affirm + +## interactive_story_4 +# happy path:number+business+business+business +* request_number{"number": "18902346721"} + - number_form + - form{"name": "number_form"} + - slot{"number": "18902346721"} + - slot{"type": "电话号码"} + - form{"name": null} + - slot{"requested_slot": null} +* inform_business{"business": "违章记录"} + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": "18902346721"} + - slot{"business": "违章记录"} + - slot{"business": null} + - form{"name": null} + - slot{"requested_slot": null} +* inform_business{"business": "犯罪记录"} + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": "18902346721"} + - slot{"business": "犯罪记录"} + - slot{"business": null} + - form{"name": null} + - slot{"requested_slot": null} +* inform_business{"business": "开房信息"} + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": "18902346721"} + - slot{"business": "开房信息"} + - slot{"business": null} + - form{"name": null} + - slot{"requested_slot": null} +* affirm + - utter_answer_affirm + +## interactive_story_5 +# unhappy:chit+answer +* greet + - utter_answer_greet +* request_number{"type": "身份证号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "身份证号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* chitchat{"date_time": "今天"} + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* form: request_number{"number": "440123199087233467"} + - form: number_form + - slot{"number": "440123199087233467"} + - slot{"type": "身份证号码"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_6 +# very unhappy:chit + chit + answer +* greet + - utter_answer_greet +* request_number{"type": "电话号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* form: request_number{"number": "18902346721"} + - form: number_form + - slot{"number": "18902346721"} + - slot{"type": "电话号码"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_7 +# very very unhappy:chitchat+chitchat+chitchat+answer +* greet + - utter_answer_greet +* request_number{"type": "电话号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* form: request_number{"number": "18902346721"} + - form: number_form + - slot{"number": "18902346721"} + - slot{"type": "电话号码"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_8 +## unhappy path:stop and really stop path +* greet + - utter_answer_greet +* request_number{"type": "身份证号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "身份证号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* stop + - utter_ask_continue +* deny + - action_deactivate_form + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_9 +## unhappy path:stop but continue path +* greet + - utter_answer_greet +* request_number{"type": "电话号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* stop + - utter_ask_continue +* affirm + - number_form + - slot{"requested_slot": "number"} +* form: request_number{"number": "18902346721"} + - form: number_form + - slot{"number": "18902346721"} + - slot{"type": "电话号码"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_10 +# unhappy path:chitchat stop but continue path +* greet + - utter_answer_greet +* request_number{"type": "身份证号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "身份证号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* stop + - utter_ask_continue +* affirm + - number_form + - slot{"requested_slot": "number"} +* form: request_number{"number": "440123199087233467"} + - form: number_form + - slot{"number": "440123199087233467"} + - slot{"type": "身份证号码"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_11 +## unhappy path: stop but continue and chitchat path +* greet + - utter_answer_greet +* request_number{"type": "电话号码"} + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* stop + - utter_ask_continue +* affirm + - number_form + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* form: request_number{"number": "18902346721"} + - form: number_form + - slot{"number": "18902346721"} + - slot{"type": "电话号码"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_12 +## unhappy path: chitchat stop but continue and chitchat path +* greet + - utter_answer_greet +* request_number + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* stop + - utter_ask_continue +* affirm + - number_form + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* form: request_number{"number": "18902346721"} + - form: number_form + - slot{"number": "18902346721"} + - slot{"type": "电话号码"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries + +## interactive_story_13 +## unhappy path: chitchat, stop and really stop path +* greet + - utter_answer_greet +* request_number + - number_form + - form{"name": "number_form"} + - slot{"type": "电话号码"} + - slot{"number": null} + - slot{"business": null} + - slot{"requested_slot": "number"} +* chitchat + - utter_chitchat + - number_form + - slot{"requested_slot": "number"} +* stop + - utter_ask_continue +* deny + - action_deactivate_form + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_noworries \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/data/stories/weather_story.md b/public/plugins/chatbot/ChitChatAssistant/data/stories/weather_story.md new file mode 100644 index 00000000..0eaf3ff0 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/data/stories/weather_story.md @@ -0,0 +1,420 @@ +## happy path +* request_weather + - weather_form + - form{"name": "weather_form"} + - form{"name": null} + +## happy path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} + - form{"name": null} +* thanks + - utter_noworries + +## unhappy path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} +* chitchat + - utter_chitchat + - weather_form + - form{"name": null} +* thanks + - utter_noworries + +## very unhappy path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} +* chitchat + - utter_chitchat + - weather_form +* chitchat + - utter_chitchat + - weather_form +* chitchat + - utter_chitchat + - weather_form + - form{"name": null} +* thanks + - utter_noworries + +## stop but continue path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} +* stop + - utter_ask_continue +* affirm + - weather_form + - form{"name": null} +* thanks + - utter_noworries + +## stop and really stop path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} +* stop + - utter_ask_continue +* deny + - action_deactivate_form + - form{"name": null} + +## chitchat stop but continue path +* request_weather + - weather_form + - form{"name": "weather_form"} +* chitchat + - utter_chitchat + - weather_form +* stop + - utter_ask_continue +* affirm + - weather_form + - form{"name": null} +* thanks + - utter_noworries + +## stop but continue and chitchat path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} +* stop + - utter_ask_continue +* affirm + - weather_form +* chitchat + - utter_chitchat + - weather_form + - form{"name": null} +* thanks + - utter_noworries + +## chitchat stop but continue and chitchat path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} +* chitchat + - utter_chitchat + - weather_form +* stop + - utter_ask_continue +* affirm + - weather_form +* chitchat + - utter_chitchat + - weather_form + - form{"name": null} +* thanks + - utter_noworries + +## chitchat, stop and really stop path +* greet + - utter_answer_greet +* request_weather + - weather_form + - form{"name": "weather_form"} +* chitchat + - utter_chitchat + - weather_form +* stop + - utter_ask_continue +* deny + - action_deactivate_form + - form{"name": null} + +## interactive_story_1 +## 天气 + 时间 + 地点 + 地点 +* request_weather + - weather_form + - form{"name": "weather_form"} + - slot{"requested_slot": "date_time"} +* form: inform{"date_time": "明天"} + - form: weather_form + - slot{"date_time": "明天"} + - slot{"requested_slot": "address"} +* form: inform{"address": "广州"} + - form: weather_form + - slot{"address": "广州"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "后天"} OR request_weather{"date_time": "后天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "广州"} + - slot{"date_time": "后天"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks + +## interactive_story_1 +## 天气 + 时间 + 地点 + 时间 +* request_weather + - weather_form + - form{"name": "weather_form"} + - slot{"requested_slot": "date_time"} +* form: inform{"date_time": "明天"} + - form: weather_form + - slot{"date_time": "明天"} + - slot{"requested_slot": "address"} +* form: inform{"address": "广州"} + - form: weather_form + - slot{"address": "广州"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"address": "上海"} OR request_weather{"address": "深圳"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "广州"} + - slot{"address": "上海"} + - form{"name": null} + - slot{"requested_slot": null} +* affirm + - utter_answer_affirm + +## interactive_story_2 +## 天气/时间/地点 + 地点 +* request_weather{"date_time": "明天", "address": "上海"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "上海"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"address": "广州"} OR request_weather{"address": "广州"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "上海"} + - slot{"address": "广州"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks + +## interactive_story_3 +## 天气/时间/地点 + 时间 +* request_weather{"address": "深圳", "date_time": "后天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "深圳"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "大后天"} OR request_weather{"date_time": "大后天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "深圳"} + - slot{"date_time": "大后天"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks + +## interactive_story_2 +## 天气/时间/地点 + 地点 + 时间 +* request_weather{"date_time": "明天", "address": "上海"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "上海"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"address": "北京"} OR request_weather{"address": "北京"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "上海"} + - slot{"address": "北京"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "后天"} OR request_weather{"date_time": "后天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "北京"} + - slot{"date_time": "后天"} + - form{"name": null} + - slot{"requested_slot": null} +* affirm + - utter_answer_affirm + +## interactive_story_3 +## 天气/时间/地点 + 地点 + 地点 +* request_weather{"date_time": "后天", "address": "北京"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "北京"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"address": "深圳"} OR request_weather{"address": "深圳"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "北京"} + - slot{"address": "深圳"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"address": "南京"} OR request_weather{"address": "南京"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "深圳"} + - slot{"address": "南京"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks + +## interactive_story_4 +## 天气/时间/地点 + 时间 + 地点 +* request_weather{"date_time": "明天", "address": "长沙"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "长沙"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "后天"} OR request_weather{"date_time": "后天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "长沙"} + - slot{"date_time": "后天"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "大后天"} OR request_weather{"date_time": "大后天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "长沙"} + - slot{"date_time": "大后天"} + - form{"name": null} + - slot{"requested_slot": null} +* affirm + - utter_answer_affirm + +## interactive_story_5 +## 天气/时间/地点 + 时间 + 时间 +* request_weather{"date_time": "后天", "address": "深圳"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "深圳"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "明天"} OR request_weather{"date_time": "明天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "深圳"} + - slot{"date_time": "明天"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"address": "广州"} OR request_weather{"address": "广州"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "深圳"} + - slot{"address": "广州"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks + +## interactive_story_4 +## 天气/时间 + 地点 + 时间 +* request_weather{"date_time": "明天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"requested_slot": "address"} +* form: inform{"address": "广州"} + - form: weather_form + - slot{"address": "广州"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "后天"} OR request_weather{"date_time": "后天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "明天"} + - slot{"address": "广州"} + - slot{"date_time": "后天"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks + +## interactive_story_5 +## 天气/地点 + 时间 + 时间 +* request_weather{"address": "广州"} + - weather_form + - form{"name": "weather_form"} + - slot{"address": "广州"} + - slot{"requested_slot": "date_time"} +* form: inform{"date_time": "后天"} + - form: weather_form + - slot{"date_time": "后天"} + - form{"name": null} + - slot{"requested_slot": null} +* inform{"date_time": "明天"} OR request_weather{"date_time": "明天"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "后天"} + - slot{"address": "广州"} + - slot{"date_time": "明天"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks + +## interactive_story_1 +## 天气/时间/地点 + chit + chit(restart)+询问天气 +* request_weather{"date_time": "今天", "address": "广州"} + - weather_form + - form{"name": "weather_form"} + - slot{"date_time": "今天"} + - slot{"address": "广州"} + - form{"name": null} + - slot{"requested_slot": null} +* chitchat + - utter_chitchat +* chitchat + - utter_chitchat + - action_restart +* request_weather + - weather_form + - form{"name": "weather_form"} + - slot{"requested_slot": "date_time"} +* form: inform{"date_time": "今天"} + - form: weather_form + - slot{"date_time": "今天"} + - slot{"requested_slot": "address"} +* form: inform{"address": "广州"} + - form: weather_form + - slot{"address": "广州"} + - form{"name": null} + - slot{"requested_slot": null} +* thanks + - utter_answer_thanks \ No newline at end of file diff --git a/public/plugins/chatbot/ChitChatAssistant/models/20200410-161951.tar.gz b/public/plugins/chatbot/ChitChatAssistant/models/20200410-161951.tar.gz new file mode 100644 index 00000000..ef13e1ed Binary files /dev/null and b/public/plugins/chatbot/ChitChatAssistant/models/20200410-161951.tar.gz differ diff --git a/public/plugins/chatbot/ChitChatAssistant/requirements.txt b/public/plugins/chatbot/ChitChatAssistant/requirements.txt new file mode 100644 index 00000000..bc7dd5aa --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/requirements.txt @@ -0,0 +1,148 @@ +absl-py==0.9.0 +aiofiles==0.4.0 +aiohttp==3.6.2 +APScheduler==3.6.3 +astor==0.8.1 +async-generator==1.10 +async-timeout==3.0.1 +attrs==19.3.0 +bleach==1.5.0 +boto3==1.12.36 +botocore==1.15.36 +cachetools==4.0.0 +certifi==2019.11.28 +cffi==1.14.0 +chardet==3.0.4 +Click==7.0 +cloudpickle==1.2.2 +colorama==0.4.3 +colorclass==2.2.0 +coloredlogs==10.0 +colorhash==1.0.2 +contextvars==2.4 +cryptography==2.9 +cycler==0.10.0 +decorator==4.4.2 +dnspython==1.16.0 +docopt==0.6.2 +docutils==0.15.2 +enum34==1.1.10 +fbmessenger==6.0.0 +Flask==1.1.2 +future==0.18.2 +gast==0.2.2 +gevent==1.4.0 +google-auth==1.13.1 +google-auth-oauthlib==0.4.1 +google-pasta==0.2.0 +greenlet==0.4.15 +grpcio==1.28.1 +h11==0.8.1 +h2==3.2.0 +h5py==2.10.0 +hpack==3.0.0 +hstspreload==2020.3.31 +html5lib==0.9999999 +httplib2==0.17.1 +httptools==0.1.1 +httpx==0.9.3 +humanfriendly==8.1 +hyperframe==5.2.0 +idna==2.8 +idna-ssl==1.1.0 +immutables==0.11 +importlib-metadata==1.6.0 +itsdangerous==1.1.0 +jieba==0.42.1 +Jinja2==2.11.1 +jmespath==0.9.4 +joblib==0.14.1 +jsonpickle==1.3 +jsonschema==3.2.0 +kafka-python==1.4.7 +Keras-Applications==1.0.8 +Keras-Preprocessing==1.1.0 +kiwisolver==1.1.0 +Markdown==3.2.1 +MarkupSafe==1.1.1 +matplotlib==3.1.3 +mattermostwrapper==2.1 +mitie==0.7.0 +multidict==4.7.5 +networkx==2.4 +numpy==1.18.2 +oauth2client==4.1.3 +oauthlib==3.1.0 +opt-einsum==3.2.0 +packaging==19.0 +pika==1.1.0 +prompt-toolkit==2.0.10 +protobuf==3.11.3 +psycopg2-binary==2.8.4 +pyasn1==0.4.8 +pyasn1-modules==0.2.8 +pycparser==2.19 +pydot==1.4.1 +PyJWT==1.7.1 +pykwalify==1.7.0 +pymongo==3.8.0 +pyparsing==2.4.6 +pyreadline==2.1 +pyrsistent==0.16.0 +PySocks==1.7.1 +python-crfsuite==0.9.6 +python-dateutil==2.8.1 +python-engineio==3.11.2 +python-socketio==4.4.0 +python-telegram-bot==11.1.0 +pytz==2019.3 +PyYAML==5.3.1 +questionary==1.5.1 +rasa==1.9.5 +rasa-sdk==1.9.0 +redis==3.4.1 +requests==2.23.0 +requests-oauthlib==1.3.0 +requests-toolbelt==0.9.1 +rfc3986==1.3.2 +rocketchat-API==0.6.36 +rsa==4.0 +ruamel.yaml==0.15.100 +s3transfer==0.3.3 +sanic==19.12.2 +Sanic-Cors==0.10.0.post3 +sanic-jwt==1.3.2 +Sanic-Plugins-Framework==0.9.2 +scikit-learn==0.22.2.post1 +scipy==1.4.1 +six==1.14.0 +sklearn-crfsuite==0.3.6 +slack==0.0.2 +slackclient==2.5.0 +sniffio==1.1.0 +SQLAlchemy==1.3.15 +tabulate==0.8.7 +tensorboard==2.1.1 +tensorflow==2.1.0 +tensorflow-addons==0.8.3 +tensorflow-estimator==2.1.0 +tensorflow-hub==0.7.0 +tensorflow-probability==0.7.0 +tensorflow-tensorboard==0.4.0 +termcolor==1.1.0 +terminaltables==3.1.0 +tqdm==4.31.1 +twilio==6.26.3 +typeguard==2.7.1 +typing-extensions==3.7.4.2 +tzlocal==2.0.0 +ujson==1.35 +urllib3==1.25.8 +wcwidth==0.1.9 +webexteamssdk==1.1.1 +websocket-client==0.54.0 +websockets==8.1 +Werkzeug==1.0.1 +wrapt==1.12.1 +yarl==1.4.2 +zipp==3.1.0 diff --git a/public/plugins/chatbot/ChitChatAssistant/run_server.bash b/public/plugins/chatbot/ChitChatAssistant/run_server.bash new file mode 100644 index 00000000..8b39e186 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/run_server.bash @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# 启动服务 +# 1. 启动rasa server +python -m rasa run --port 5005 -m models/20200319-162558.tar.gz --endpoints configs/endpoints.yml --credentials configs/credentials.yml --debug +# 2. 启动action server +python -m rasa run actions --port 5055 --actions actions --debug +# 3. 启动server.py +python server.py + diff --git a/public/plugins/chatbot/ChitChatAssistant/server.py b/public/plugins/chatbot/ChitChatAssistant/server.py new file mode 100644 index 00000000..a32710d7 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/server.py @@ -0,0 +1,85 @@ +""" + server.py + ~~~~~~~~~ + + web server,定义前端调用接口 + + :date: 2020-02-14 14:36:00 + :author: by jiangdg +""" + +from flask import Flask, jsonify +from flask import request +import requests +import json +import logging + +app = Flask(__name__) + + +@app.route('/', methods=['GET', 'POST']) +def test(): + return"测试" + + +@app.route('/ai', methods=['GET', 'POST']) +def webToBot(): + """ + 前端调用接口 + 路径:/ai + 请求方式:GET、POST + 请求参数:content + :return: response rasa响应数据 + """ + content = request.values.get('content') + if content is None: + return 'empty input' + response = requestRasabotServer('jiangdg', content) + return response.text.encode('utf-8').decode("unicode-escape") + + +def requestRasabotServer(userid, content): + """ + 访问rasa服务 + :param userid: 用户id + :param content: 自然语言文本 + :return: json格式响应数据 + """ + params = {'sender': userid, 'message': content} + botIp = '127.0.0.1' + botPort = '5005' + # rasa使用rest channel + # https://rasa.com/docs/rasa/user-guide/connectors/your-own-website/#rest-channels + # POST /webhooks/rest/webhook + rasaUrl = "http://{0}:{1}/webhooks/rest/webhook".format(botIp, botPort) + + reponse = requests.post( + rasaUrl, + data=json.dumps(params), + headers={'Content-Type': 'application/json'} + ) + return reponse + + +if __name__ == '__main__': + webIp = '127.0.0.1' + webPort = '8088' + + print("##### webIp={}, webPort={}".format(webIp, webPort)) + # 初始化日志引擎 + fh = logging.FileHandler(encoding='utf-8', mode='a', filename='chitchat.log') + logging.basicConfig( + handlers=[fh], + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + datefmt='%a, %d %b %Y %H:%M:%S', + ) + + # 启动服务,开启多线程、debug模式 + # 浏览器访问http://127.0.0.1:8088/ai?content="你好" + app.run( + host=webIp, + port=int(webPort), + threaded=True, + debug=True + ) diff --git a/public/plugins/chatbot/ChitChatAssistant/train.bash b/public/plugins/chatbot/ChitChatAssistant/train.bash new file mode 100644 index 00000000..0e9982e9 --- /dev/null +++ b/public/plugins/chatbot/ChitChatAssistant/train.bash @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# 训练NLU和Core模型 +python -m rasa train --config configs/config.yml --domain configs/domain.yml --data data/ + +python -m rasa train --config configs/zh_jieba_supervised_embeddings_config.yml --domain configs/domain.yml --data data/ + +python -m rasa train --config configs/zh_jieba_mitie_embeddings_config.yml --domain configs/domain.yml --data data/ + +#usage: rasa train [-h] [-v] [-vv] [--quiet] [--data DATA [DATA ...]] +# [-c CONFIG] [-d DOMAIN] [--out OUT] +# [--augmentation AUGMENTATION] [--debug-plots] +# [--dump-stories] [--fixed-model-name FIXED_MODEL_NAME] +# [--persist-nlu-data] [--force] +# {core,nlu} ... + +# 交互式学习构建样本 +python -m rasa run actions --port 5055 --actions actions --debug +python -m rasa interactive -m models/20200319-162558.tar.gz --endpoints configs/endpoints.yml --config configs/zh_jieba_mitie_embeddings_config.yml diff --git a/public/plugins/chatbot/README.md b/public/plugins/chatbot/README.md index 5929bc17..c87935df 100644 --- a/public/plugins/chatbot/README.md +++ b/public/plugins/chatbot/README.md @@ -5,6 +5,7 @@ [春松客服机器人客服文档](https://docs.chatopera.com/products/cskefu/work-chatbot.html) ## 安装插件 + 安装脚本为Bash Shell脚本,需要在命令行控制台执行。 ``` @@ -13,7 +14,20 @@ **提示**: Windows环境使用Git Bash 命令行终端执行该命令,也可以完成安装。 +## RASA中文聊天机器人 + +参考搭建自 https://github.com/jiangdongguo/ChitChatAssistant + +目录位于 + +``` +./ChitChatAssistant +``` + +请求接口 http://127.0.0.1:8088/ai?content="YouInput" + ## 卸载插件 + 卸载脚本为Bash Shell脚本,需要在命令行控制台执行。 ``` diff --git a/public/plugins/chatbot/classes/ApiChatbotController.java b/public/plugins/chatbot/classes/ApiChatbotController.java index d9feefd4..70807841 100644 --- a/public/plugins/chatbot/classes/ApiChatbotController.java +++ b/public/plugins/chatbot/classes/ApiChatbotController.java @@ -35,7 +35,21 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.google.gson.internal.$Gson$Preconditions; import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,11 +66,22 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; +import java.awt.*; +import java.io.IOException; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.util.Date; import java.util.List; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.tbp.v20190627.TbpClient; +import com.tencentcloudapi.tbp.v20190627.models.TextResetRequest; +import com.tencentcloudapi.tbp.v20190627.models.TextResetResponse; +import com.google.gson.Gson; /** * 聊天机器人 * 请求聊天机器人服务 @@ -80,7 +105,7 @@ public class ApiChatbotController extends Handler { private final static String botServiecProvider = SystemEnvHelper.getenv( ChatbotConstants.BOT_PROVIDER, ChatbotConstants.DEFAULT_BOT_PROVIDER); - + private final static String TencentbotServiecProvider = SystemEnvHelper.getenv(ChatbotConstants.BOT_PROVIDER,ChatbotConstants.DEFAULT_TENCENTBOT_PROVIDER); /** * 聊天机器人 * @@ -195,12 +220,101 @@ public class ApiChatbotController extends Handler { final String id = j.get("id").getAsString(); Chatbot c = chatbotRes.findOne(id); - + final String RobotType = c.getrobottype(); if (c == null) { resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4); resp.addProperty(RestUtils.RESP_KEY_ERROR, "该聊天机器人不存在。"); return resp; } + switch (RobotType) { + case "cosin": + resp = enableCosin(j, c, isEnabled,resp); + + break; + case "tencent": + resp = enableTencent(j, c, isEnabled,resp); + break; + case "rasa": + resp = enableRASA(j, c, isEnabled,resp); + break; + } + + return resp; + } + + private JsonObject enableTencent(JsonObject j,Chatbot c, boolean isEnabled,JsonObject resp) + { + String BotId = c.getBotId(); + String TerminalId = c.getTerminalId(); + String SecretId = c.getSecretId(); + String SecretKey = c.getSecretKey(); + String BotEnv = c.getBotEnv(); + + try { + JsonObject botRes = TextReset(SecretId,SecretKey,BotId,BotEnv,TerminalId); + if (!botRes.has("Error")) { + c.setEnabled(isEnabled); + chatbotRes.save(c); + + // 更新访客网站配置 + CousultInvite invite = OnlineUserProxy.consult(c.getSnsAccountIdentifier(), c.getOrgi()); + invite.setAi(isEnabled); + consultInviteRes.save(invite); + OnlineUserProxy.cacheConsult(invite); + + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC); + resp.addProperty(RestUtils.RESP_KEY_DATA, "完成。"); + } else { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_7); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "智能问答引擎不存在该聊天机器人,未能正确设置。"); + } + } + catch (Exception e) { + + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5); + resp.addProperty(RestUtils.RESP_KEY_DATA, "设置不成功,智能问答引擎服务异常。"); + } + return resp; + } + private JsonObject enableRASA(JsonObject j,Chatbot c, boolean isEnabled,JsonObject resp) + { + + try { + JsonObject botRes = RasaTest(c.getBaseUrl()); + //System.out.println(botRes); + if (!botRes.has("Error")) { + c.setEnabled(isEnabled); + chatbotRes.save(c); + // 更新访客网站配置 + CousultInvite invite = OnlineUserProxy.consult(c.getSnsAccountIdentifier(), c.getOrgi()); + invite.setAi(isEnabled); + consultInviteRes.save(invite); + OnlineUserProxy.cacheConsult(invite); + + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC); + resp.addProperty(RestUtils.RESP_KEY_DATA, "完成。"); + } else { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_7); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "智能问答引擎不存在该聊天机器人,未能正确设置。"); + } + } + catch (Exception e) { + + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5); + resp.addProperty(RestUtils.RESP_KEY_DATA, "设置不成功,智能问答引擎服务异常。"); + } + System.out.println(resp); + return resp; + } + + + + /** + * + */ + + private JsonObject enableCosin(JsonObject j,Chatbot c, boolean isEnabled,JsonObject resp) + { try { com.chatopera.bot.sdk.Chatbot bot = new com.chatopera.bot.sdk.Chatbot( @@ -231,7 +345,6 @@ public class ApiChatbotController extends Handler { } return resp; } - /** * Enable Chatbot 智能回复 * @@ -475,6 +588,10 @@ public class ApiChatbotController extends Handler { return resp; } + + + + /** * 创建聊天机器人 * @@ -483,13 +600,417 @@ public class ApiChatbotController extends Handler { * @param orgi * @return */ - private JsonObject create(final JsonObject j, final String creater, final String orgi) throws Exception { + + private JsonObject create(final JsonObject j, final String creater, final String orgi) throws Exception + { JsonObject resp = new JsonObject(); + String RobotType = j.get("robottype").getAsString(); + //System.out.println(RobotType); + switch (RobotType) { + case "cosin": + resp = createCosinRobot(j, creater, orgi); + break; + case "tencent": + resp = createTencentRobot(j, creater, orgi); + break; + case "rasa": + //System.out.println("RASA Robot"); + resp = createRASARobot(j, creater, orgi); + break; + } + //System.out.println(resp); + return resp; + } + + + + private JsonObject TextReset(final String SecretId, final String SecretKey, final String BotId,final String BotEnv,final String TerminalId ) { + JsonObject result = new JsonObject(); + try{ + + Credential cred = new Credential(SecretId, SecretKey); + + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("tbp.tencentcloudapi.com"); + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + + TbpClient client = new TbpClient(cred, "", clientProfile); + + String params = "{\"BotId\":\""+BotId+"\",\"BotEnv\":\""+BotEnv+"\",\"TerminalId\":\""+TerminalId+"\"}"; + TextResetRequest req = TextResetRequest.fromJsonString(params, TextResetRequest.class); + + TextResetResponse resp = client.TextReset(req); + + result =new JsonParser().parse(TextResetResponse.toJsonString(resp)).getAsJsonObject(); + //System.out.println("hello"+result); + return result; + + } catch (TencentCloudSDKException e) { + System.out.println(e.toString()); + } + + return result; + + } + + + /** + * + */ + + private JsonObject createTencentRobot(final JsonObject j, final String creater, final String orgi) + { + + JsonObject resp = new JsonObject(); + String snsid = null; + String BotEnv = null; + String BotId = null; + String SecretId = null; + String SecretKey = null; + String TerminalId = null; + + if ((!j.has("BotId")) || StringUtils.isBlank(j.get("BotId").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【BotId】。"); + return resp; + } else { + BotId = j.get("BotId").getAsString(); + } + + if ((!j.has("TerminalId")) || StringUtils.isBlank(j.get("TerminalId").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【TerminalId】。"); + return resp; + } else { + TerminalId = j.get("TerminalId").getAsString(); + } + + if ((!j.has("SecretId")) || StringUtils.isBlank(j.get("SecretId").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【SecretId】。"); + return resp; + } else { + SecretId = j.get("SecretId").getAsString(); + } + + if ((!j.has("SecretKey")) || StringUtils.isBlank(j.get("SecretKey").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【SecretKey】。"); + return resp; + } else { + SecretKey = j.get("SecretKey").getAsString(); + } + if (!(j.has("BotEnv"))) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入有效【BotEnv】。"); + return resp; + } else { + BotEnv = j.get("BotEnv").getAsString(); + } + + if ((!j.has("snsid")) || StringUtils.isBlank(j.get("snsid").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【snsid】。"); + return resp; + } else { + snsid = j.get("snsid").getAsString(); + // #TODO 仅支持webim + if (!snsAccountRes.existsBySnsidAndSnstypeAndOrgi(snsid, Constants.CHANNEL_TYPE_WEBIM, orgi)) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,不存在【snsid】对应的网站渠道。"); + return resp; + } + + if (chatbotRes.existsBySnsAccountIdentifierAndOrgi(snsid, orgi)) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,该渠道【snsid】已经存在聊天机器人。"); + return resp; + } + } + + if (chatbotRes.existsByClientIdAndOrgi(BotId, orgi)) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,数据库中存在该聊天机器人。"); + return resp; + } + + try { + logger.info("create bot with ", TencentbotServiecProvider ); + JsonObject botRes = TextReset(SecretId,SecretKey,BotId,BotEnv,TerminalId); + + + if (!botRes.has("Error")) { // 该机器人存在,clientId 和 Secret配对成功 + // 创建成功 + Chatbot c = new Chatbot(); + //JSONObject botDetails = bot.details(); + c.setId(MainUtils.getUUID()); + c.setSecretId(SecretId); + c.setSecretKey(SecretKey); + c.setBotId(BotId); + c.setName(BotId); + //c.setClientId(BotId);//ClientID 不能为空 暂时设定为一样的值 + c.setBotEnv(BotEnv); + c.setTerminalId(TerminalId); + c.setWorkmode("机器人客服优先"); + c.setBaseUrl(TencentbotServiecProvider); + + c.setCreater(creater); + c.setOrgi(orgi); + c.setChannel(Constants.CHANNEL_TYPE_WEBIM); + c.setSnsAccountIdentifier(snsid); + Date dt = new Date(); + c.setCreatetime(dt); + c.setUpdatetime(dt); + c.setrobottype(j.get("robottype").getAsString()); + // 默认不开启 + boolean enabled = false; + c.setEnabled(enabled); + + // 更新访客网站配置 + CousultInvite invite = OnlineUserProxy.consult(c.getSnsAccountIdentifier(), c.getOrgi()); + invite.setAi(enabled); + //invite.setAifirst(StringUtils.equals(Constants.CHATBOT_CHATBOT_FIRST, workmode)); + invite.setAiid(c.getId()); + invite.setAiname(c.getName()); + invite.setAisuccesstip(c.getWelcome()); + + consultInviteRes.save(invite); + OnlineUserProxy.cacheConsult(invite); + chatbotRes.save(c); + JsonObject data = new JsonObject(); + data.addProperty("id", c.getId()); + data.addProperty("robottype", c.getrobottype()); + resp.add(RestUtils.RESP_KEY_DATA, data); + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC); + return resp; + } else { + // 创建失败 + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_6); + resp.addProperty( + RestUtils.RESP_KEY_ERROR, "Chatopera云服务:该机器人不存在,请先创建机器人, 登录 https://console.cloud.tencent.com/tbp"); + return resp; + } + } + catch (Exception e){ + System.out.println(e); + logger.error("bot create error"); + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5); + resp.addProperty( + RestUtils.RESP_KEY_ERROR, + "无法访问该机器人,请确认【1】该服务器可以访问互联网,【2】该聊天机器人已经创建,【3】参数正确设置。"); + return resp; + } + + + + } + + private JsonObject RasaTest(final String BotUrl) + { + String Url = BotUrl; + JsonObject result = new JsonObject(); + result.addProperty("error",1); + CloseableHttpClient httpClient = HttpClients.createDefault(); + try { + URIBuilder uriBuilder = new URIBuilder(Url); + uriBuilder.setParameter("content","查询广州明天的天气"); + + HttpGet httpGet = new HttpGet(uriBuilder.build()); + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(5000) //连接超时时间 + .setConnectionRequestTimeout(5000) //请求超时时间 + .setSocketTimeout(5000) //socket读写超时时间 + .setRedirectsEnabled(true) //是否允许重定向 + .build(); + + httpGet.setConfig(requestConfig); + CloseableHttpResponse response = null; + response = httpClient.execute(httpGet); + + if (response.getStatusLine().getStatusCode() == 200) { + String content = EntityUtils.toString(response.getEntity(), "utf8"); + JsonArray tempArray = new JsonParser().parse(content).getAsJsonArray(); + + result = tempArray.get(0).getAsJsonObject(); + //System.out.println(result); + } + + //请求内容 + + } catch (IOException e) { + e.printStackTrace(); + + } catch (URISyntaxException e) { + e.printStackTrace(); + } + return result; + } + + + /** + * 创建 RASARobot + * + * */ + private JsonObject createRASARobot(final JsonObject j, final String creater, final String orgi) + { + + JsonObject resp = new JsonObject(); + String snsid = null; + String BotId = null; + String BotUrl = null; + String workmode = "机器人客服优先";; + String SecretId = null; + + if ((!j.has("BotId")) || StringUtils.isBlank(j.get("BotId").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【BotId】。"); + return resp; + } else { + BotId = j.get("BotId").getAsString(); + } + if ((!j.has("BotUrl")) || StringUtils.isBlank(j.get("BotUrl").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【BotUrl】。"); + return resp; + } else { + BotUrl = j.get("BotUrl").getAsString(); + } + + + + + if ((!j.has("SecretId")) || StringUtils.isBlank(j.get("SecretId").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【SecretId】。"); + return resp; + } else { + SecretId = j.get("SecretId").getAsString(); + } + + + + + if ((!j.has("snsid")) || StringUtils.isBlank(j.get("snsid").getAsString())) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【snsid】。"); + return resp; + } else { + snsid = j.get("snsid").getAsString(); + // #TODO 仅支持webim + if (!snsAccountRes.existsBySnsidAndSnstypeAndOrgi(snsid, Constants.CHANNEL_TYPE_WEBIM, orgi)) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,不存在【snsid】对应的网站渠道。"); + return resp; + } + + if (chatbotRes.existsBySnsAccountIdentifierAndOrgi(snsid, orgi)) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,该渠道【snsid】已经存在聊天机器人。"); + return resp; + } + } + + if (chatbotRes.existsByClientIdAndOrgi(BotId, orgi)) { + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); + resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,数据库中存在该聊天机器人。"); + return resp; + } + + try { + logger.info("create bot with ",BotUrl ); + JsonObject botRes = RasaTest(BotUrl); + + if (!botRes.has("Error")) { // 该机器人存在,clientId 和 Secret配对成功 + // 创建成功 + Chatbot c = new Chatbot(); + //JSONObject botDetails = bot.details(); + c.setId(MainUtils.getUUID()); + c.setSecretId(SecretId); + c.setBotId(BotId); + c.setName(BotId); + c.setClientId(BotId);//ClientID 不能为空 暂时设定为一样的值 + //c.setBotEnv(BotEnv); + + c.setBaseUrl(BotUrl); + //c.setTerminalId(TerminalId); + /** + c.setDescription(botDetails.getJSONObject("data").getString("description")); + c.setFallback(botDetails.getJSONObject("data").getString("fallback")); + c.setPrimaryLanguage(botDetails.getJSONObject("data").getString("primaryLanguage")); + c.setName(botDetails.getJSONObject("data").getString("name")); + c.setWelcome(botDetails.getJSONObject("data").getString("welcome")); + */ + c.setCreater(creater); + c.setOrgi(orgi); + c.setChannel(Constants.CHANNEL_TYPE_WEBIM); + c.setSnsAccountIdentifier(snsid); + Date dt = new Date(); + c.setCreatetime(dt); + c.setUpdatetime(dt); + c.setrobottype(j.get("robottype").getAsString()); + // 默认不开启 + c.setWorkmode("机器人客服优先"); + boolean enabled = false; + c.setEnabled(enabled); + + // 更新访客网站配置 + CousultInvite invite = OnlineUserProxy.consult(c.getSnsAccountIdentifier(), c.getOrgi()); + invite.setAi(enabled); + invite.setAifirst(StringUtils.equals(Constants.CHATBOT_CHATBOT_FIRST, workmode)); + invite.setAiid(c.getId()); + invite.setAiname(c.getName()); + invite.setAisuccesstip(c.getWelcome()); + consultInviteRes.save(invite); + OnlineUserProxy.cacheConsult(invite); + chatbotRes.save(c); + JsonObject data = new JsonObject(); + data.addProperty("id", c.getId()); + data.addProperty("robottype", c.getrobottype()); + resp.add(RestUtils.RESP_KEY_DATA, data); + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC); + return resp; + } else { + // 创建失败 + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_6); + resp.addProperty( + RestUtils.RESP_KEY_ERROR, "Chatopera云服务:该机器人不存在,请先创建机器人, 登录 https://console.cloud.tencent.com/tbp"); + return resp; + } + } + catch (Exception e){ + System.out.println(e); + logger.error("bot create error"); + resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5); + resp.addProperty( + RestUtils.RESP_KEY_ERROR, + "无法访问该机器人,请确认【1】该服务器可以访问互联网,【2】该聊天机器人已经创建,【3】参数正确设置。"); + return resp; + } + + + + } + /** + * 创建春松聊天机器人 + * + * @param j + * @param creater + * @param orgi + * @return + */ + private JsonObject createCosinRobot(final JsonObject j, final String creater, final String orgi) throws Exception { JsonObject resp = new JsonObject(); String snsid = null; String workmode = null; String clientId = null; String secret = null; + if(!j.has("workmode")) + { + //System.out.println(j); + j.addProperty("workmode","机器人客服优先"); + } + //System.out.println(j); if ((!j.has("clientId")) || StringUtils.isBlank(j.get("clientId").getAsString())) { resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3); resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【clientId】。"); @@ -565,7 +1086,7 @@ public class ApiChatbotController extends Handler { c.setCreatetime(dt); c.setUpdatetime(dt); c.setWorkmode(workmode); - + c.setrobottype(j.get("robottype").getAsString()); // 默认不开启 boolean enabled = false; c.setEnabled(enabled); @@ -580,9 +1101,9 @@ public class ApiChatbotController extends Handler { consultInviteRes.save(invite); OnlineUserProxy.cacheConsult(invite); chatbotRes.save(c); - JsonObject data = new JsonObject(); data.addProperty("id", c.getId()); + data.addProperty("robottype", c.getrobottype()); resp.add(RestUtils.RESP_KEY_DATA, data); resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC); return resp; diff --git a/public/plugins/chatbot/classes/ChatbotConstants.java b/public/plugins/chatbot/classes/ChatbotConstants.java index 1cfd6222..56834375 100644 --- a/public/plugins/chatbot/classes/ChatbotConstants.java +++ b/public/plugins/chatbot/classes/ChatbotConstants.java @@ -20,4 +20,5 @@ public class ChatbotConstants { public static final String THRESHOLD_FAQ_BEST_REPLY = "BOT_THRESHOLD_FAQ_BEST_REPLY"; public static final String THRESHOLD_FAQ_SUGG_REPLY = "BOT_THRESHOLD_FAQ_SUGG_REPLY"; public static final String DEFAULT_BOT_PROVIDER = "https://bot.chatopera.com"; + public static final String DEFAULT_TENCENTBOT_PROVIDER = "https://console.cloud.tencent.com/tbp"; } diff --git a/public/plugins/chatbot/classes/ChatbotController.java b/public/plugins/chatbot/classes/ChatbotController.java index 73583acf..a2970286 100644 --- a/public/plugins/chatbot/classes/ChatbotController.java +++ b/public/plugins/chatbot/classes/ChatbotController.java @@ -67,7 +67,205 @@ public class ChatbotController extends Handler { logger.info("[index] chatbot id {}", chatbotid); ModelAndView view = request(super.createAppsTempletResponse("/apps/chatbot/index")); - List chatbots = chatbotRes.findByOrgi(super.getOrgi(request)); + String Orgi = super.getOrgi(request); + System.out.println(Orgi); + List chatbots = chatbotRes.findByOrgi(Orgi); + Chatbot currentbot = null; + + + logger.info("[index] chatbot size {}", chatbots.size()); + if (chatbots.size() > 0) { + view.addObject("chatbots", chatbots); + if (StringUtils.isNotBlank(chatbotid)) { + view.addObject("currentbotid", chatbotid); + boolean resolved = false; + for (final Chatbot b : chatbots) { + if (StringUtils.equals(b.getId(), chatbotid)) { + view.addObject("currentbot", b); + currentbot = b; + resolved = true; + break; + } + } + + if (!resolved) { + // TODO 优化查到不到Bot的提示 + throw new CSKefuException("Can not find target chatbot by id [" + chatbotid + "]"); + } + + } else { + currentbot = chatbots.get(0); + view.addObject("currentbotid", currentbot.getId()); + view.addObject("currentbot", currentbot); + } + } + + view.addObject("botServiecProvider", botServiecProvider); + + // 增加当前bot的更多信息 + if (currentbot != null) { + // 创建人 + final User creator = userProxy.findOne(currentbot.getCreater()); + if (creator != null) { + view.addObject("creatorname", creator.getUname()); + } + // 隶属渠道 + if (StringUtils.isNotBlank(currentbot.getSnsAccountIdentifier())) { + snsAccountRepository.findOneBySnsTypeAndSnsIdAndOrgi( + currentbot.getChannel(), + currentbot.getSnsAccountIdentifier(), + currentbot.getOrgi()).ifPresent(p -> { + view.addObject("snsAccountName", p.getName()); + view.addObject("snsAccountId", p.getId()); + }); + + } + } + + + return view; + } + + + + + @RequestMapping(value = "/cosin") + @Menu(type = "chatbot", subtype = "index", access = true) + public ModelAndView cosin(ModelMap map, HttpServletRequest request, @Valid final String chatbotid) throws CSKefuException { + logger.info("[index] chatbot id {}", chatbotid); + + ModelAndView view = request(super.createAppsTempletResponse("/apps/chatbot/cosin")); + String Orgi = super.getOrgi(request); + System.out.println(Orgi); + List chatbots = chatbotRes.findByOrgi(Orgi); + Chatbot currentbot = null; + + + logger.info("[index] chatbot size {}", chatbots.size()); + if (chatbots.size() > 0) { + view.addObject("chatbots", chatbots); + if (StringUtils.isNotBlank(chatbotid)) { + view.addObject("currentbotid", chatbotid); + boolean resolved = false; + for (final Chatbot b : chatbots) { + if (StringUtils.equals(b.getId(), chatbotid)) { + view.addObject("currentbot", b); + currentbot = b; + resolved = true; + break; + } + } + + if (!resolved) { + // TODO 优化查到不到Bot的提示 + throw new CSKefuException("Can not find target chatbot by id [" + chatbotid + "]"); + } + + } else { + currentbot = chatbots.get(0); + view.addObject("currentbotid", currentbot.getId()); + view.addObject("currentbot", currentbot); + } + } + + view.addObject("botServiecProvider", botServiecProvider); + + // 增加当前bot的更多信息 + if (currentbot != null) { + // 创建人 + final User creator = userProxy.findOne(currentbot.getCreater()); + if (creator != null) { + view.addObject("creatorname", creator.getUname()); + } + // 隶属渠道 + if (StringUtils.isNotBlank(currentbot.getSnsAccountIdentifier())) { + snsAccountRepository.findOneBySnsTypeAndSnsIdAndOrgi( + currentbot.getChannel(), + currentbot.getSnsAccountIdentifier(), + currentbot.getOrgi()).ifPresent(p -> { + view.addObject("snsAccountName", p.getName()); + view.addObject("snsAccountId", p.getId()); + }); + + } + } + + + return view; + } + + @RequestMapping(value = "/tencent") + @Menu(type = "chatbot", subtype = "index", access = true) + public ModelAndView tencent(ModelMap map, HttpServletRequest request, @Valid final String chatbotid) throws CSKefuException { + logger.info("[index] chatbot id {}", chatbotid); + ModelAndView view = request(super.createAppsTempletResponse("/apps/chatbot/tencent")); + String Orgi = super.getOrgi(request); + //System.out.println(Orgi); + List chatbots = chatbotRes.findByOrgi(Orgi); + Chatbot currentbot = null; + + + logger.info("[index] chatbot size {}", chatbots.size()); + if (chatbots.size() > 0) { + view.addObject("chatbots", chatbots); + if (StringUtils.isNotBlank(chatbotid)) { + view.addObject("currentbotid", chatbotid); + boolean resolved = false; + for (final Chatbot b : chatbots) { + if (StringUtils.equals(b.getId(), chatbotid)) { + view.addObject("currentbot", b); + currentbot = b; + resolved = true; + break; + } + } + + if (!resolved) { + // TODO 优化查到不到Bot的提示 + throw new CSKefuException("Can not find target chatbot by id [" + chatbotid + "]"); + } + + } else { + currentbot = chatbots.get(0); + view.addObject("currentbotid", currentbot.getId()); + view.addObject("currentbot", currentbot); + } + } + + view.addObject("botServiecProvider", botServiecProvider); + + // 增加当前bot的更多信息 + if (currentbot != null) { + // 创建人 + final User creator = userProxy.findOne(currentbot.getCreater()); + if (creator != null) { + view.addObject("creatorname", creator.getUname()); + } + // 隶属渠道 + if (StringUtils.isNotBlank(currentbot.getSnsAccountIdentifier())) { + snsAccountRepository.findOneBySnsTypeAndSnsIdAndOrgi( + currentbot.getChannel(), + currentbot.getSnsAccountIdentifier(), + currentbot.getOrgi()).ifPresent(p -> { + view.addObject("snsAccountName", p.getName()); + view.addObject("snsAccountId", p.getId()); + }); + + } + } + + + return view; + } + + @RequestMapping(value = "/rasa") + @Menu(type = "chatbot", subtype = "index", access = true) + public ModelAndView RASA(ModelMap map, HttpServletRequest request, @Valid final String chatbotid) throws CSKefuException { + logger.info("[index] chatbot id {}", chatbotid); + ModelAndView view = request(super.createAppsTempletResponse("/apps/chatbot/rasa")); + String Orgi = super.getOrgi(request); + + List chatbots = chatbotRes.findByOrgi(Orgi); Chatbot currentbot = null; diff --git a/public/plugins/chatbot/classes/ChatbotEventHandler.java b/public/plugins/chatbot/classes/ChatbotEventHandler.java index ad3b8cb4..9c9aa192 100644 --- a/public/plugins/chatbot/classes/ChatbotEventHandler.java +++ b/public/plugins/chatbot/classes/ChatbotEventHandler.java @@ -15,6 +15,7 @@ */ package com.chatopera.cc.plugins.chatbot; +import com.chatopera.bot.exception.ChatbotException; import com.chatopera.cc.acd.ACDServiceRouter; import com.chatopera.cc.basic.Constants; import com.chatopera.cc.basic.MainContext; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.net.InetSocketAddress; +import java.net.MalformedURLException; import java.util.Date; public class ChatbotEventHandler { @@ -106,55 +108,11 @@ public class ChatbotEventHandler { // send out welcome message if (invite != null) { Chatbot chatbot = getChatbotRes().findOne(invite.getAiid()); - com.chatopera.bot.sdk.Chatbot bot = new com.chatopera.bot.sdk.Chatbot( - chatbot.getClientId(), chatbot.getSecret(), chatbot.getBaseUrl()); - JSONObject details = bot.details(); + RobotsOnconnect(chatbot,client,invite); - // 发送欢迎语 - if (details.has("rc") && - details.getInt("rc") == 0) { - ChatMessage welcome = new ChatMessage(); - String welcomeTextMessage = details.getJSONObject("data").getString("welcome"); - if (StringUtils.isNotBlank(welcomeTextMessage)) { - welcome.setCalltype(MainContext.CallType.OUT.toString()); - welcome.setAppid(appid); - welcome.setOrgi(orgi); - welcome.setAiid(aiid); - welcome.setMessage(welcomeTextMessage); - welcome.setTouser(user); - welcome.setMsgtype(MainContext.MessageType.MESSAGE.toString()); - welcome.setUserid(user); - welcome.setUsername(invite.getAiname()); - welcome.setUpdatetime(System.currentTimeMillis()); - client.sendEvent(MainContext.MessageType.MESSAGE.toString(), welcome); - } - // 发送常见问题列表 - JSONObject faqhotresp = bot.conversation(user, "__faq_hot_list"); - logger.info("faqhot {}", faqhotresp.toString()); - if (faqhotresp.getInt("rc") == 0) { - JSONObject faqhotdata = faqhotresp.getJSONObject("data"); - if ((!faqhotdata.getBoolean("logic_is_fallback")) && - faqhotdata.has("string") && - faqhotdata.has("params")) { - ChatMessage faqhotmsg = new ChatMessage(); - faqhotmsg.setCalltype(MainContext.CallType.OUT.toString()); - faqhotmsg.setAppid(appid); - faqhotmsg.setOrgi(orgi); - faqhotmsg.setAiid(aiid); - faqhotmsg.setMessage(faqhotdata.getString("string")); - faqhotmsg.setExpmsg(faqhotdata.getJSONArray("params").toString()); - faqhotmsg.setTouser(user); - faqhotmsg.setMsgtype(MainContext.MessageType.MESSAGE.toString()); - faqhotmsg.setUserid(user); - faqhotmsg.setUsername(invite.getAiname()); - faqhotmsg.setUpdatetime(System.currentTimeMillis()); - client.sendEvent(MainContext.MessageType.MESSAGE.toString(), faqhotmsg); - } - } - } } - + //System.out.println("aiid:"+aiid); InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress(); String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString()); OnlineUser onlineUser = getOnlineUserRes().findOne(user); @@ -225,6 +183,76 @@ public class ChatbotEventHandler { } } + public void RobotsOnconnect(Chatbot chatbot,SocketIOClient client,CousultInvite invite) throws ChatbotException, MalformedURLException { + + String user = client.getHandshakeData().getSingleUrlParam("userid"); + String nickname = client.getHandshakeData().getSingleUrlParam("nickname"); + String orgi = client.getHandshakeData().getSingleUrlParam("orgi"); + String session = MainUtils.getContextID(client.getHandshakeData().getSingleUrlParam("session")); + String appid = client.getHandshakeData().getSingleUrlParam("appid"); + String aiid = client.getHandshakeData().getSingleUrlParam("aiid"); + + String RobotType = chatbot.getrobottype(); + switch (RobotType) { + case "cosin": + com.chatopera.bot.sdk.Chatbot bot = new com.chatopera.bot.sdk.Chatbot( + chatbot.getClientId(), chatbot.getSecret(), chatbot.getBaseUrl()); + JSONObject details = bot.details(); + // 发送欢迎语 + if (details.has("rc") && + details.getInt("rc") == 0) { + ChatMessage welcome = new ChatMessage(); + String welcomeTextMessage = details.getJSONObject("data").getString("welcome"); + if (StringUtils.isNotBlank(welcomeTextMessage)) { + welcome.setCalltype(MainContext.CallType.OUT.toString()); + welcome.setAppid(appid); + welcome.setOrgi(orgi); + welcome.setAiid(aiid); + welcome.setMessage(welcomeTextMessage); + welcome.setTouser(user); + welcome.setMsgtype(MainContext.MessageType.MESSAGE.toString()); + welcome.setUserid(user); + welcome.setUsername(invite.getAiname()); + welcome.setUpdatetime(System.currentTimeMillis()); + client.sendEvent(MainContext.MessageType.MESSAGE.toString(), welcome); + } + + // 发送常见问题列表 + JSONObject faqhotresp = bot.conversation(user, "__faq_hot_list"); + logger.info("faqhot {}", faqhotresp.toString()); + if (faqhotresp.getInt("rc") == 0) { + JSONObject faqhotdata = faqhotresp.getJSONObject("data"); + if ((!faqhotdata.getBoolean("logic_is_fallback")) && + faqhotdata.has("string") && + faqhotdata.has("params")) { + ChatMessage faqhotmsg = new ChatMessage(); + faqhotmsg.setCalltype(MainContext.CallType.OUT.toString()); + faqhotmsg.setAppid(appid); + faqhotmsg.setOrgi(orgi); + faqhotmsg.setAiid(aiid); + faqhotmsg.setMessage(faqhotdata.getString("string")); + faqhotmsg.setExpmsg(faqhotdata.getJSONArray("params").toString()); + faqhotmsg.setTouser(user); + faqhotmsg.setMsgtype(MainContext.MessageType.MESSAGE.toString()); + faqhotmsg.setUserid(user); + faqhotmsg.setUsername(invite.getAiname()); + faqhotmsg.setUpdatetime(System.currentTimeMillis()); + client.sendEvent(MainContext.MessageType.MESSAGE.toString(), faqhotmsg); + } + } + } + break; + case "tencent": + System.out.println("腾讯"); + break; + case "rasa": + System.out.println("rasa"); + break; + } + } + + + // 添加 @OnDisconnect 事件,客户端断开连接时调用,刷新客户端信息 @OnDisconnect public void onDisconnect(SocketIOClient client) { diff --git a/public/plugins/chatbot/classes/ChatbotEventSubscription.java b/public/plugins/chatbot/classes/ChatbotEventSubscription.java index d82f07eb..ce0dbdf7 100644 --- a/public/plugins/chatbot/classes/ChatbotEventSubscription.java +++ b/public/plugins/chatbot/classes/ChatbotEventSubscription.java @@ -27,6 +27,17 @@ import com.chatopera.cc.persistence.repository.ChatbotRepository; import com.chatopera.cc.socketio.message.ChatMessage; import com.chatopera.cc.util.SerializeUtil; import com.chatopera.cc.util.SystemEnvHelper; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.tencentcloudapi.tbp.v20190627.models.Group; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -36,7 +47,19 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; +import java.io.IOException; import java.net.MalformedURLException; +import java.net.URISyntaxException; + +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; + +import com.tencentcloudapi.tbp.v20190627.TbpClient; + +import com.tencentcloudapi.tbp.v20190627.models.TextProcessRequest; +import com.tencentcloudapi.tbp.v20190627.models.TextProcessResponse; /** * 发送消息给聊天机器人并处理返回结果 @@ -59,10 +82,10 @@ public class ChatbotEventSubscription { ChatbotConstants.BOT_PROVIDER, ChatbotConstants.DEFAULT_BOT_PROVIDER); // FAQ最佳回复阀值 - private final static double faqBestReplyThreshold = Double.parseDouble(SystemEnvHelper.getenv( + private final static double thresholdFaqBestReply = Double.parseDouble(SystemEnvHelper.getenv( ChatbotConstants.THRESHOLD_FAQ_BEST_REPLY, "0.8")); // FAQ建议回复阀值 - private final static double faqSuggReplyThreshold = Double.parseDouble(SystemEnvHelper.getenv( + private final static double thresholdFaqSuggReply = Double.parseDouble(SystemEnvHelper.getenv( ChatbotConstants.THRESHOLD_FAQ_SUGG_REPLY, "0.6")); @Autowired @@ -75,7 +98,9 @@ public class ChatbotEventSubscription { */ @JmsListener(destination = Constants.INSTANT_MESSAGING_MQ_QUEUE_CHATBOT, containerFactory = "jmsListenerContainerQueue") public void onMessage(final String payload) { + System.out.println(payload); ChatMessage message = SerializeUtil.deserialize(payload); + System.out.println("Hello chat began"); try { chat(message); } catch (MalformedURLException e) { @@ -87,18 +112,198 @@ public class ChatbotEventSubscription { private void chat(final ChatMessage request) throws MalformedURLException, ChatbotException, JSONException { - Chatbot c = chatbotRes - .findOne(request.getAiid()); - - logger.info( - "[chat] chat request baseUrl {}, chatbot {}, fromUserId {}, textMessage {}", botServiecProvider, - c.getName(), - request.getUserid(), request.getMessage()); + Chatbot c = chatbotRes.findOne(request.getAiid()); + //System.out.println(c); + //System.out.println(request); + logger.info("[chat] chat request request baseUrl {},RobotType {}, chatbot {}, fromUserId {}, textMessage {}", botServiecProvider,c.getrobottype(), c.getName(), request.getUserid(), request.getMessage()); // Get response from Conversational Engine. + String RobotType = c.getrobottype(); + switch (RobotType) { + case "cosin": + CosinChat(c,request); + break; + case "tencent": + //System.out.println("腾讯"); + TencentChat(c,request); + break; + case "rasa": + //System.out.println("RASA"); + rasaChat(c,request); + break; + } + + + } + + private void rasaChat(Chatbot c,ChatMessage request) + { + + String BotUrl = c.getBaseUrl(); + JsonObject result = new JsonObject(); + CloseableHttpClient httpClient = HttpClients.createDefault(); + try { + URIBuilder uriBuilder = new URIBuilder(BotUrl); + uriBuilder.setParameter("content",request.getMessage()); + + HttpGet httpGet = new HttpGet(uriBuilder.build()); + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(5000) //连接超时时间 + .setConnectionRequestTimeout(5000) //请求超时时间 + .setSocketTimeout(5000) //socket读写超时时间 + .setRedirectsEnabled(true) //是否允许重定向 + .build(); + + httpGet.setConfig(requestConfig); + CloseableHttpResponse response = null; + response = httpClient.execute(httpGet); + System.out.println(response); + if (response.getStatusLine().getStatusCode() == 200) { + String content = EntityUtils.toString(response.getEntity(), "utf8"); + JsonArray tempArray = new JsonParser().parse(content).getAsJsonArray(); + result = tempArray.get(0).getAsJsonObject(); + //System.out.println(result); + } + //请求内容 + + } catch (IOException e) { + e.printStackTrace(); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + + // parse response + if (result != null) { + logger.info("[chat] chat response {}", result.toString()); + if (result.size()>0) { + // reply + //System.out.println(result.toString()); + JSONObject data = new JSONObject(result.toString()); + + if (data != null) { + ChatMessage resp = new ChatMessage(); + resp.setCalltype(MainContext.CallType.OUT.toString()); + resp.setAppid(resp.getAppid()); + resp.setOrgi(request.getOrgi()); + resp.setAiid(request.getAiid()); + resp.setMessage(result.get("text").getAsString()); + if (data.has("logic_is_fallback")) + { + if (data.getBoolean("logic_is_fallback")) { + // 兜底回复,检查FAQ + JSONArray faqReplies = data.getJSONArray("faq"); + JSONArray suggs = new JSONArray(); + for (int i = 0; i < faqReplies.length(); i++) { + JSONObject sugg = new JSONObject(); + JSONObject faqReply = faqReplies.getJSONObject(i); + sugg.put("label", Integer.toString(i + 1) + ". " + faqReply.getString("post")); + sugg.put("text", faqReply.getString("post")); + sugg.put("type", "qlist"); + suggs.put(sugg); + } + if (suggs.length() > 0) { + // TODO set help message on View Page + resp.setMessage("为您找到如下信息:"); + resp.setExpmsg(suggs.toString()); + } + } else if (data.has("params")) { + resp.setExpmsg(data.get("params").toString()); + } + } + + resp.setTouser(request.getUserid()); + resp.setAgentserviceid(request.getAgentserviceid()); + resp.setMsgtype(request.getMsgtype()); + resp.setUserid(request.getUserid()); + resp.setType(request.getType()); + resp.setChannel(request.getChannel()); + + resp.setContextid(request.getContextid()); + resp.setSessionid(request.getSessionid()); + resp.setUsession(request.getUsession()); + resp.setUsername(c.getName()); + resp.setUpdatetime(System.currentTimeMillis()); + + // 更新聊天机器人累计值 + updateAgentUserWithRespData(request.getUserid(), request.getOrgi(), data); + // 保存并发送 + System.out.println("resp"); + System.out.println(resp); + chatbotProxy.saveAndPublish(resp); + } + } else { + logger.warn("[chat] can not get expected response {}", result.toString()); + } + } + } + private void TencentChat(Chatbot c,ChatMessage request){ + try{ + String SecretId = c.getSecretId(); + String SecretKey = c.getSecretKey(); + Credential cred = new Credential(SecretId, SecretKey); + + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("tbp.tencentcloudapi.com"); + + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + + TbpClient client = new TbpClient(cred, "", clientProfile); + String BotId = c.getBotId(); + String BotEnv = c.getBotEnv(); + String TerminalId = c.getTerminalId(); + String InputText = request.getMessage(); + String params = "{" + + "\"BotId\":\""+BotId+"\"," + + "\"BotEnv\":\""+BotEnv+"\"," + + "\"TerminalId\":\""+TerminalId+"\"," + + "\"InputText\":\""+InputText+"\" }"; + System.out.println(params); + TextProcessRequest req = TextProcessRequest.fromJsonString(params, TextProcessRequest.class); + TextProcessResponse respout = client.TextProcess(req); + + //System.out.println(TextProcessResponse.toJsonString(respout)); + ChatMessage resp = new ChatMessage(); + resp.setCalltype(MainContext.CallType.OUT.toString()); + resp.setAppid(resp.getAppid()); + resp.setOrgi(request.getOrgi()); + resp.setAiid(request.getAiid()); + Group[] ResResult = respout.getResponseMessage().getGroupList(); + if (ResResult.length==1) + { + resp.setMessage(ResResult[0].getContent()); + } + + resp.setTouser(request.getUserid()); + resp.setAgentserviceid(request.getAgentserviceid()); + resp.setMsgtype(request.getMsgtype()); + resp.setUserid(request.getUserid()); + resp.setType(request.getType()); + resp.setChannel(request.getChannel()); + + resp.setContextid(request.getContextid()); + resp.setSessionid(request.getSessionid()); + resp.setUsession(request.getUsession()); + resp.setUsername(c.getName()); + resp.setUpdatetime(System.currentTimeMillis()); + + System.out.println(TextProcessResponse.toJsonString(respout)); + JSONObject resObject = new JSONObject(TextProcessResponse.toJsonString(respout)); + + // 更新聊天机器人累计值 + updateAgentUserWithRespData(request.getUserid(), request.getOrgi(), resObject); + // 保存并发送 + chatbotProxy.saveAndPublish(resp); + + } catch (TencentCloudSDKException e) { + System.out.println(e.toString()); + } + } + + private void CosinChat(Chatbot c,ChatMessage request) throws ChatbotException, MalformedURLException { com.chatopera.bot.sdk.Chatbot bot = new com.chatopera.bot.sdk.Chatbot( c.getClientId(), c.getSecret(), botServiecProvider); JSONObject result = bot.conversation( - request.getUserid(), request.getMessage(), faqBestReplyThreshold, faqSuggReplyThreshold); + request.getUserid(), request.getMessage(), thresholdFaqBestReply, thresholdFaqSuggReply); // parse response if (result != null) { @@ -151,6 +356,7 @@ public class ChatbotEventSubscription { // 更新聊天机器人累计值 updateAgentUserWithRespData(request.getUserid(), request.getOrgi(), data); // 保存并发送 + //System.out.println(resp); chatbotProxy.saveAndPublish(resp); } } else { @@ -159,11 +365,14 @@ public class ChatbotEventSubscription { } } + /** * 根据聊天机器人返回数据更新agentUser * * @param userid * @param data + * + * 待修改 加入对腾讯对话机器人错误的兼容 */ private void updateAgentUserWithRespData(final String userid, final String orgi, final JSONObject data) throws JSONException { cache.findOneAgentUserByUserIdAndOrgi(userid, orgi).ifPresent(p -> { diff --git a/public/plugins/chatbot/views/apps/chatbot/cosin.html b/public/plugins/chatbot/views/apps/chatbot/cosin.html new file mode 100644 index 00000000..66399944 --- /dev/null +++ b/public/plugins/chatbot/views/apps/chatbot/cosin.html @@ -0,0 +1,315 @@ +
+
+ <#include "/apps/chatbot/include/left.html"> +
+
+ +
+ <#if currentbotid??> +
+
+

+ +
+
+ 春松客服智能机器人 +
+
+
+ +
+
+ + + + + +
+
+

+
+
+ + +
+
+
+

智能机器人用于在访客端实现机器人客服,具体使用参考文档中心《春松客服机器人客服》。 +

+
+
+
+ + +
+
+
+ 智能客服 +
+
+

在开启状态下,在访客端可以看到智能客服对话窗口并与机器人客服对话。

+
+
+
+
+ checked> +
+
+
+
+ 知识库建议 +
+
+

知识库建议包括知识库联想知识库快捷知识库联想:当坐席与访客进行对话过程中,坐席输入消息时是否得到机器人的建议回复;知识库快捷:当坐席与访客进行对话过程中,坐席收到访客的消息时是否得到机器人的建议回复。

+
+
+
+
+ checked> +
+
+
+
+
+
+
+ + +
+
+
+ 绑定 +
+
+

以下信息为春松客服使用该智能机器人集成的信息,去设置

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
渠道 + <#if currentbot.channel == "webim"> + 网站 + <#elseif currentbot.channel == "skype"> + Skype + <#elseif currentbot.channel == "callout"> + 外呼 + <#else> + 未知渠道类型 + +

访客接入的方式

渠道名称${snsAccountName!""}

限定了智能机器人出现的渠道标识。

创建人${creatorname!"未知"}

创建人初次设定了智能机器人。

工作模式 + ${currentbot.workmode} +

工作模式有"机器人优先","人工坐席优先"和"仅机器人客服"三种,这决定了访客连线后默认对接的方式。

+
+
+
+
+ + +
+
+
+ 配置 +
+
+

进入Chatopera云服务设置以下信息及知识库、多轮对话、意图识别、使用情况分析和对话历史等信息。

+
+ + + + + + + + + + + + + + + + + + + + + + + +
描述${currentbot.description}

智能机器人的描述,侧重于业务,访客不会看到该信息。

欢迎语${currentbot.welcome}

与访客建立连接后,智能机器人发送的打招呼信息。

兜底回复${currentbot.fallback}

当智能机器人不清楚如何回复时的回复。

+
+
+
+
+ <#else> +
+
+

+ +
+
+ 智能机器人 +
+
+
+ +
+
+ + + +
+
+

+
+
+
+
+ 还没有智能机器人,现在去创建! +
+
+ +
+ \ No newline at end of file diff --git a/public/plugins/chatbot/views/apps/chatbot/edit.html b/public/plugins/chatbot/views/apps/chatbot/edit.html index f769216c..4f0f3052 100644 --- a/public/plugins/chatbot/views/apps/chatbot/edit.html +++ b/public/plugins/chatbot/views/apps/chatbot/edit.html @@ -1,4 +1,4 @@ - + +
-
- -
- -
- <#if id!=null> - - <#else> - - +
+
    +
  • 春松客服
  • +
  • 腾讯智能对话
  • +
  • Rasa NLU
  • +
+
+
+ + +
+ +
+ <#if id!=null> + + <#else> + + +
+
智能机器人服务的渠道标识
+
+
+ +
+ +
+
智能机器人ClientId.春松客服创建!
+
+ +
+ +
+ +
+
智能机器人Secret
+
+
+ +
+ +
+
来自访客的会话默认以什么方式接待
+
+
+
+ +
+
+ +
+
+
+ +
+ +
+ <#if id!=null> + + <#else> + + +
+
智能机器人服务的渠道标识
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
智能机器人Secret
+
+
+ +
+ +
+
调试/线上 版本
+
+
+ +
+ +
+
+ +
+
+ +
+
+
-
智能机器人服务的渠道标识
-
-
- -
- +
+
+
+ +
+ +
+ <#if id!=null> + + <#else> + + +
+
智能机器人服务的渠道网址
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+ +
+
+
-
智能机器人ClientId,还没有?现在去创建!
-
-
- -
-
-
智能机器人Secret
-
-
- -
- -
-
来自访客的会话默认以什么方式接待
-
-
-
- -
-
- +
\ No newline at end of file diff --git a/public/plugins/chatbot/views/apps/chatbot/tencent.html b/public/plugins/chatbot/views/apps/chatbot/tencent.html new file mode 100644 index 00000000..327baa43 --- /dev/null +++ b/public/plugins/chatbot/views/apps/chatbot/tencent.html @@ -0,0 +1,315 @@ +
+
+ <#include "/apps/chatbot/include/left.html"> +
+
+ +
+ <#if currentbotid??> +
+
+

+ +
+
+ 腾讯智能对话 +
+
+
+ +
+
+ + + + + +
+
+

+
+
+ + +
+
+
+

智能机器人用于在访客端实现机器人客服,具体使用参考文档中心《腾讯智能对话平台 》。 +

+
+
+
+ + +
+
+
+ 智能客服 +
+
+

在开启状态下,在访客端可以看到智能客服对话窗口并与机器人客服对话。

+
+
+
+
+ checked> +
+
+
+
+ 知识库建议 +
+
+

知识库建议包括知识库联想知识库快捷知识库联想:当坐席与访客进行对话过程中,坐席输入消息时是否得到机器人的建议回复;知识库快捷:当坐席与访客进行对话过程中,坐席收到访客的消息时是否得到机器人的建议回复。

+
+
+
+
+ checked> +
+
+
+
+
+
+
+ + +
+
+
+ 绑定 +
+
+

以下信息为腾讯对话使用该智能机器人集成的信息,去设置

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
渠道 + <#if currentbot.channel == "webim"> + 网站 + <#elseif currentbot.channel == "skype"> + Skype + <#elseif currentbot.channel == "callout"> + 外呼 + <#else> + 未知渠道类型 + +

访客接入的方式

渠道名称${snsAccountName!""}

限定了智能机器人出现的渠道标识。

创建人${creatorname!"未知"}

创建人初次设定了智能机器人。

工作模式 + ${currentbot.workmode} +

工作模式有"机器人优先","人工坐席优先"和"仅机器人客服"三种,这决定了访客连线后默认对接的方式。

+
+
+
+
+ + +
+
+
+ 配置 +
+
+

进入Chatopera云服务设置以下信息及知识库、多轮对话、意图识别、使用情况分析和对话历史等信息。

+
+ + + + + + + + + + + + + + + + + + + + + + + +
描述${currentbot.description}

智能机器人的描述,侧重于业务,访客不会看到该信息。

欢迎语${currentbot.welcome}

与访客建立连接后,智能机器人发送的打招呼信息。

兜底回复${currentbot.fallback}

当智能机器人不清楚如何回复时的回复。

+
+
+
+
+ <#else> +
+
+

+ +
+
+ 智能机器人 +
+
+
+ +
+
+ + + +
+
+

+
+
+
+
+ 还没有智能机器人,现在去创建! +
+
+ +
+ \ No newline at end of file