mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-07-22 06:37:11 +08:00
14
plugins/bdunit/README.md
Normal file
14
plugins/bdunit/README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
利用百度UNIT实现智能对话
|
||||||
|
1.解决问题:chatgpt无法处理的指令,交给百度UNIT处理如:天气,日期时间,数学运算等
|
||||||
|
2.如问时间:现在几点钟,今天几号
|
||||||
|
3.如问天气:明天广州天气怎么样,这个周末深圳会不会下雨
|
||||||
|
4.如问数学运算:23+45=多少,100-23=多少,35转化为二进制是多少?
|
||||||
|
大家可以在百度UNIT官网上自己创建应用,申请百度机器人,可以把预先训练好的模型导入到自己的应用中,
|
||||||
|
see https://ai.baidu.com/unit/home#/home?track=61fe1b0d3407ce3face1d92cb5c291087095fc10c8377aaf
|
||||||
|
https://console.bce.baidu.com/ai平台申请
|
||||||
|
然后在百度UNIT官网上获取应用的API Key和Secret Key,然后在config.json中配置
|
||||||
|
{
|
||||||
|
"service_id": "s...", #"机器人ID"
|
||||||
|
"api_key": "",
|
||||||
|
"secret_key": ""
|
||||||
|
}
|
||||||
0
plugins/bdunit/__init__.py
Normal file
0
plugins/bdunit/__init__.py
Normal file
297
plugins/bdunit/bdunit.py
Normal file
297
plugins/bdunit/bdunit.py
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
# encoding:utf-8
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
import requests
|
||||||
|
from bridge.context import ContextType
|
||||||
|
from bridge.reply import Reply, ReplyType
|
||||||
|
from common.log import logger
|
||||||
|
import plugins
|
||||||
|
from plugins import *
|
||||||
|
from uuid import getnode as get_mac
|
||||||
|
|
||||||
|
|
||||||
|
"""利用百度UNIT实现智能对话
|
||||||
|
如果命中意图,返回意图对应的回复,否则返回继续交付给下个插件处理
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@plugins.register(name="BDunit", desc="Baidu unit bot system", version="0.1", author="jackson", desire_priority=0)
|
||||||
|
class BDunit(Plugin):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
try:
|
||||||
|
curdir = os.path.dirname(__file__)
|
||||||
|
config_path = os.path.join(curdir, "config.json")
|
||||||
|
conf = None
|
||||||
|
if not os.path.exists(config_path):
|
||||||
|
conf = {"service_id": "", "api_key": "",
|
||||||
|
"secret_key": ""}
|
||||||
|
with open(config_path, "w") as f:
|
||||||
|
json.dump(conf, f, indent=4)
|
||||||
|
else:
|
||||||
|
with open(config_path, "r") as f:
|
||||||
|
conf = json.load(f)
|
||||||
|
self.service_id = conf["service_id"]
|
||||||
|
self.api_key = conf["api_key"]
|
||||||
|
self.secret_key = conf["secret_key"]
|
||||||
|
self.access_token = self.get_token()
|
||||||
|
self.handlers[Event.ON_HANDLE_CONTEXT] = self.on_handle_context
|
||||||
|
logger.info("[BDunit] inited")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warn(
|
||||||
|
"BDunit init failed: %s, ignore " % e)
|
||||||
|
|
||||||
|
def on_handle_context(self, e_context: EventContext):
|
||||||
|
|
||||||
|
if e_context['context'].type != ContextType.TEXT:
|
||||||
|
return
|
||||||
|
|
||||||
|
content = e_context['context'].content
|
||||||
|
logger.debug("[BDunit] on_handle_context. content: %s" % content)
|
||||||
|
parsed = self.getUnit2(content)
|
||||||
|
intent = self.getIntent(parsed)
|
||||||
|
if intent: # 找到意图
|
||||||
|
logger.debug("[BDunit] Baidu_AI Intent= %s", intent)
|
||||||
|
reply = Reply()
|
||||||
|
reply.type = ReplyType.TEXT
|
||||||
|
reply.content = self.getSay(parsed)
|
||||||
|
e_context['reply'] = reply
|
||||||
|
e_context.action = EventAction.BREAK_PASS # 事件结束,并跳过处理context的默认逻辑
|
||||||
|
else:
|
||||||
|
e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑
|
||||||
|
|
||||||
|
def get_help_text(self, **kwargs):
|
||||||
|
help_text = "本插件会处理询问实时日期时间,天气,数学运算等问题,这些技能由您的百度智能对话UNIT决定\n"
|
||||||
|
return help_text
|
||||||
|
|
||||||
|
def get_token(self):
|
||||||
|
"""获取访问百度UUNIT 的access_token
|
||||||
|
#param api_key: UNIT apk_key
|
||||||
|
#param secret_key: UNIT secret_key
|
||||||
|
Returns:
|
||||||
|
string: access_token
|
||||||
|
"""
|
||||||
|
url = "https://aip.baidubce.com/oauth/2.0/token?client_id={}&client_secret={}&grant_type=client_credentials".format(
|
||||||
|
self.api_key, self.secret_key)
|
||||||
|
payload = ""
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.request("POST", url, headers=headers, data=payload)
|
||||||
|
|
||||||
|
# print(response.text)
|
||||||
|
return response.json()['access_token']
|
||||||
|
|
||||||
|
def getUnit(self, query):
|
||||||
|
"""
|
||||||
|
NLU 解析version 3.0
|
||||||
|
:param query: 用户的指令字符串
|
||||||
|
:returns: UNIT 解析结果。如果解析失败,返回 None
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = (
|
||||||
|
'https://aip.baidubce.com/rpc/2.0/unit/service/v3/chat?access_token='
|
||||||
|
+ self.access_token
|
||||||
|
)
|
||||||
|
request = {"query": query, "user_id": str(
|
||||||
|
get_mac())[:32], "terminal_id": "88888"}
|
||||||
|
body = {
|
||||||
|
"log_id": str(uuid.uuid1()),
|
||||||
|
"version": "3.0",
|
||||||
|
"service_id": self.service_id,
|
||||||
|
"session_id": str(uuid.uuid1()),
|
||||||
|
"request": request,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
response = requests.post(url, json=body, headers=headers)
|
||||||
|
return json.loads(response.text)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getUnit2(self, query):
|
||||||
|
"""
|
||||||
|
NLU 解析 version 2.0
|
||||||
|
|
||||||
|
:param query: 用户的指令字符串
|
||||||
|
:returns: UNIT 解析结果。如果解析失败,返回 None
|
||||||
|
"""
|
||||||
|
url = (
|
||||||
|
"https://aip.baidubce.com/rpc/2.0/unit/service/chat?access_token="
|
||||||
|
+ self.access_token
|
||||||
|
)
|
||||||
|
request = {"query": query, "user_id": str(get_mac())[:32]}
|
||||||
|
body = {
|
||||||
|
"log_id": str(uuid.uuid1()),
|
||||||
|
"version": "2.0",
|
||||||
|
"service_id": self.service_id,
|
||||||
|
"session_id": str(uuid.uuid1()),
|
||||||
|
"request": request,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
response = requests.post(url, json=body, headers=headers)
|
||||||
|
return json.loads(response.text)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getIntent(self, parsed):
|
||||||
|
"""
|
||||||
|
提取意图
|
||||||
|
|
||||||
|
:param parsed: UNIT 解析结果
|
||||||
|
:returns: 意图数组
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
parsed
|
||||||
|
and "result" in parsed
|
||||||
|
and "response_list" in parsed["result"]
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
return parsed["result"]["response_list"][0]["schema"]["intent"]
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(e)
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def hasIntent(self, parsed, intent):
|
||||||
|
"""
|
||||||
|
判断是否包含某个意图
|
||||||
|
|
||||||
|
:param parsed: UNIT 解析结果
|
||||||
|
:param intent: 意图的名称
|
||||||
|
:returns: True: 包含; False: 不包含
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
parsed
|
||||||
|
and "result" in parsed
|
||||||
|
and "response_list" in parsed["result"]
|
||||||
|
):
|
||||||
|
response_list = parsed["result"]["response_list"]
|
||||||
|
for response in response_list:
|
||||||
|
if (
|
||||||
|
"schema" in response
|
||||||
|
and "intent" in response["schema"]
|
||||||
|
and response["schema"]["intent"] == intent
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getSlots(self, parsed, intent=""):
|
||||||
|
"""
|
||||||
|
提取某个意图的所有词槽
|
||||||
|
|
||||||
|
:param parsed: UNIT 解析结果
|
||||||
|
:param intent: 意图的名称
|
||||||
|
:returns: 词槽列表。你可以通过 name 属性筛选词槽,
|
||||||
|
再通过 normalized_word 属性取出相应的值
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
parsed
|
||||||
|
and "result" in parsed
|
||||||
|
and "response_list" in parsed["result"]
|
||||||
|
):
|
||||||
|
response_list = parsed["result"]["response_list"]
|
||||||
|
if intent == "":
|
||||||
|
try:
|
||||||
|
return parsed["result"]["response_list"][0]["schema"]["slots"]
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(e)
|
||||||
|
return []
|
||||||
|
for response in response_list:
|
||||||
|
if (
|
||||||
|
"schema" in response
|
||||||
|
and "intent" in response["schema"]
|
||||||
|
and "slots" in response["schema"]
|
||||||
|
and response["schema"]["intent"] == intent
|
||||||
|
):
|
||||||
|
return response["schema"]["slots"]
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getSlotWords(self, parsed, intent, name):
|
||||||
|
"""
|
||||||
|
找出命中某个词槽的内容
|
||||||
|
|
||||||
|
:param parsed: UNIT 解析结果
|
||||||
|
:param intent: 意图的名称
|
||||||
|
:param name: 词槽名
|
||||||
|
:returns: 命中该词槽的值的列表。
|
||||||
|
"""
|
||||||
|
slots = self.getSlots(parsed, intent)
|
||||||
|
words = []
|
||||||
|
for slot in slots:
|
||||||
|
if slot["name"] == name:
|
||||||
|
words.append(slot["normalized_word"])
|
||||||
|
return words
|
||||||
|
|
||||||
|
def getSayByConfidence(self, parsed):
|
||||||
|
"""
|
||||||
|
提取 UNIT 置信度最高的回复文本
|
||||||
|
|
||||||
|
:param parsed: UNIT 解析结果
|
||||||
|
:returns: UNIT 的回复文本
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
parsed
|
||||||
|
and "result" in parsed
|
||||||
|
and "response_list" in parsed["result"]
|
||||||
|
):
|
||||||
|
response_list = parsed["result"]["response_list"]
|
||||||
|
answer = {}
|
||||||
|
for response in response_list:
|
||||||
|
if (
|
||||||
|
"schema" in response
|
||||||
|
and "intent_confidence" in response["schema"]
|
||||||
|
and (
|
||||||
|
not answer
|
||||||
|
or response["schema"]["intent_confidence"]
|
||||||
|
> answer["schema"]["intent_confidence"]
|
||||||
|
)
|
||||||
|
):
|
||||||
|
answer = response
|
||||||
|
return answer["action_list"][0]["say"]
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def getSay(self, parsed, intent=""):
|
||||||
|
"""
|
||||||
|
提取 UNIT 的回复文本
|
||||||
|
|
||||||
|
:param parsed: UNIT 解析结果
|
||||||
|
:param intent: 意图的名称
|
||||||
|
:returns: UNIT 的回复文本
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
parsed
|
||||||
|
and "result" in parsed
|
||||||
|
and "response_list" in parsed["result"]
|
||||||
|
):
|
||||||
|
response_list = parsed["result"]["response_list"]
|
||||||
|
if intent == "":
|
||||||
|
try:
|
||||||
|
return response_list[0]["action_list"][0]["say"]
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(e)
|
||||||
|
return ""
|
||||||
|
for response in response_list:
|
||||||
|
if (
|
||||||
|
"schema" in response
|
||||||
|
and "intent" in response["schema"]
|
||||||
|
and response["schema"]["intent"] == intent
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
return response["action_list"][0]["say"]
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(e)
|
||||||
|
return ""
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
5
plugins/bdunit/config.json.template
Normal file
5
plugins/bdunit/config.json.template
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"service_id": "s...",
|
||||||
|
"api_key": "",
|
||||||
|
"secret_key": ""
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user