【阿里云】| 智能对话机器人(云小蜜) | 快速开发入门

355 阅读5分钟

一、环境要求

  • Python 3

  • 安装 SDK 核心库 OpenAPI ,使用pip安装包依赖: pip install alibabacloud_tea_openapi

  • SDK 安装方式

    1. PyPI PIP:pip install alibabacloud_chatbot20171011==2.0.1
    2. PyPI Anaconda:conda install alibabacloud_chatbot20171011=2.0.1

二、实现代码

  • sample demo 如下(涉及具体个人核心配置数据处,请对应自行修改填充)
# -*- coding: utf-8 -*-
#  @ Date   : 2022/1/27 16:27
#  @ Author : RichardLau_Cx
#  @ Project: Chatbot
#  @ File   : API_sample_new.py
#  @ IDE    : PyCharm


import ssl
import time
import uuid
import hmac
import base64
import requests
import urllib.parse
from hashlib import sha1
from Chatbot import configs  # 自定义的配置数据信息文件


# 解决访问ssl网站证书的问题
try:
    _create_unverified_https_context = ssl._create_unverified_context

except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass

else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

protocol = 'https://'
domain_name = 'chatbot.cn-shanghai.aliyuncs.com/'
Parameters = {
    'Format': 'JSON',
    'Version': '2017-10-11',
    'AccessKeyId': configs.AccessKeyId,
    'SignatureMethod': 'HMAC-SHA1',
    'SignatureVersion': 1.0
}


def percent_encode(code):
    """
    名称和值要使用 UTF-8 字符集进行 URL 编码,URL 编码的编码规则是:
        1.字符 A-Z、a-z、0-9 以及字符“-”、“_”、“.”、“~”,不进行编码;
        2.对于其他字符编码成“%XY”的格式,其中 XY 是字符对应 ASCII 码的 16 进制表示。比如英文的双引号对应的编码就是 “%22”;
        3.对于扩展的 UTF-8 字符,编码成“%XY%ZA…”的格式;
        4.注意英文空格要被编码成 “%20”,而不是加号“+”。
    :param code: 待编码串
    :return: 编码字符串
    """

    # result = urllib.parse.quote(str(code))
    encode = str(code)
    result = urllib.parse.quote(encode)
    result = result.replace('+', '%20')
    result = result.replace('/', '%2F')
    result = result.replace('*', '%2A')
    result = result.replace('%7E', '~')

    return result

# print("/: " + percent_encode('/'))


def signature(params):
    """
    签名机制
    :param params: 公共请求参数
    :return: 签名结果串
    """

    # 1. 使用请求参数来构造规范化的请求字符串(Canonicalized Query String)
    # 1.1 按照参数名称的字母顺序对请求中所有的请求参数进行排序
    sorted_params = sorted(params.items(), key=lambda params: params[0])
    print("sorted_params: " + str(sorted_params))

    # 1.2 对每个请求参数的名称和值进行编码
    canonicalize_query_string = ''

    for (k, v) in sorted_params:
        # 1.3 对编码后的参数名称和值使用英文等号“=”进行连接
        # 1.4 再把英文等号连接得到的字符串按参数名称的字母顺序依次使用“&”符号连接,即得到规范化请求字符串
        canonicalize_query_string += '&' + percent_encode(k) + '=' + percent_encode(v)
    # print("canonicalize_query_string: " + str(canonicalize_query_string))

    # 2. 使用上一步构造的规范化字符串,按照下面的规则构造用于计算签名的字符串
    http_method = 'GET'
    string_to_sign = http_method + '&' + percent_encode('/') + '&' + percent_encode(canonicalize_query_string[1:])
    # print("string_to_sign: " + str(string_to_sign))
    string_to_sign = bytes(string_to_sign, encoding='utf8')
    # print("string_to_sign: " + str(string_to_sign))

    # 3. 按照 RFC2104 的定义,使用上面的用于签名的字符串计算签名 HMAC 值
    sign_key = bytes((configs.AccessKeySecret + '&'), encoding='utf8')
    hmacs = hmac.new(key=sign_key, msg=string_to_sign, digestmod=sha1)

    # 4. 按照 Base64 编码规则把上面的 HMAC 值编码成字符串,即得到签名值(Signature)
    sign = base64.b64encode(hmacs.digest()).strip()

    return sign


formats = "%Y-%m-%dT%H:%M:%SZ"
timestamp = time.strftime(formats, time.gmtime())  # 函数用于格式化时间,返回以可读字符串表示的当地时间,格式由参数 format 决定
Parameters['Timestamp'] = timestamp

Parameters['SignatureNonce'] = str(uuid.uuid1())
Parameters['Action'] = "Chat"
Parameters['InstanceId'] = configs.InstanceId
Parameters['Utterance'] = "你能够解决什么问题?"  # 想AI机器人进行提问
Parameters['Signature'] = signature(Parameters)  # 其函数操作包含了之前的一些属性值,因此理应放置到最后计算赋值

sorted_params = sorted(Parameters.items(), key=lambda Parameters: Parameters[0])
url = protocol + domain_name + '?' + urllib.parse.urlencode(sorted_params)
print("url: " + str(url))

r = requests.get(url)  # 进行接口访问
print('r.text: ' + str(r.text))
  • 优化封装版(基于class)
# -*- coding: utf-8 -*-
#  @ Date   : 2022/1/27 16:27
#  @ Author : RichardLau_Cx
#  @ Project: Python
#  @ File   : API_sample_new.py
#  @ IDE    : PyCharm


import ssl
import time
import uuid
import hmac
import base64
import requests
import urllib.parse
from hashlib import sha1
from Chatbot.configs import Configs  # 自定义的配置数据信息文件


def percent_encode(code):
    """
    名称和值要使用 UTF-8 字符集进行 URL 编码,URL 编码的编码规则是:
        1.字符 A-Z、a-z、0-9 以及字符“-”、“_”、“.”、“~”,不进行编码;
        2.对于其他字符编码成“%XY”的格式,其中 XY 是字符对应 ASCII 码的 16 进制表示。比如英文的双引号对应的编码就是 “%22”;
        3.对于扩展的 UTF-8 字符,编码成“%XY%ZA…”的格式;
        4.注意英文空格要被编码成 “%20”,而不是加号“+”。
    :param code: 待编码串
    :return: 编码字符串
    """

    encode = str(code)
    result = urllib.parse.quote(encode)
    result = result.replace('+', '%20')
    result = result.replace('/', '%2F')
    result = result.replace('*', '%2A')
    result = result.replace('%7E', '~')

    return result


class ChatBot:
    def __init__(self):
        self.configs = Configs()

    def signature(self, params):
        """
        签名机制
        :param params: 公共请求参数
        :return: 签名结果串
        """

        # 1. 使用请求参数来构造规范化的请求字符串(Canonicalized Query String)
        # 1.1 按照参数名称的字母顺序对请求中所有的请求参数进行排序
        sorted_params = sorted(params.items(), key=lambda params: params[0])
        # print("sorted_params: " + str(sorted_params))

        # 1.2 对每个请求参数的名称和值进行编码
        canonicalize_query_string = ''

        for (k, v) in sorted_params:
            # 1.3 对编码后的参数名称和值使用英文等号“=”进行连接
            # 1.4 再把英文等号连接得到的字符串按参数名称的字母顺序依次使用“&”符号连接,即得到规范化请求字符串
            canonicalize_query_string += '&' + percent_encode(k) + '=' + percent_encode(v)
        # print("canonicalize_query_string: " + str(canonicalize_query_string))

        # 2. 使用上一步构造的规范化字符串,按照下面的规则构造用于计算签名的字符串
        http_method = 'GET'
        string_to_sign = http_method + '&' + percent_encode('/') + '&' + percent_encode(canonicalize_query_string[1:])
        # print("string_to_sign: " + str(string_to_sign))
        string_to_sign = bytes(string_to_sign, encoding='utf8')
        # print("string_to_sign: " + str(string_to_sign))

        # 3. 按照 RFC2104 的定义,使用上面的用于签名的字符串计算签名 HMAC 值
        sign_key = bytes((self.configs.AccessKeySecret + '&'), encoding='utf8')
        hmacs = hmac.new(key=sign_key, msg=string_to_sign, digestmod=sha1)

        # 4. 按照 Base64 编码规则把上面的 HMAC 值编码成字符串,即得到签名值(Signature)
        sign = base64.b64encode(hmacs.digest()).strip()

        return sign

    def send(self, utterance):
        """
        向服务器发出请求
        :param utterance: 向AI机器人进行发话
        :return: 响应结果(json数据)
        """

        # 解决访问ssl网站证书的问题
        try:
            _create_unverified_https_context = ssl._create_unverified_context

        except AttributeError:
            # Legacy Python that doesn't verify HTTPS certificates by default
            pass

        else:
            # Handle target environment that doesn't support HTTPS verification
            ssl._create_default_https_context = _create_unverified_https_context

        self.configs = Configs()
        protocol = 'https://'
        domain_name = 'chatbot.cn-shanghai.aliyuncs.com/'
        Parameters = {
            'Format': 'JSON',
            'Version': '2017-10-11',
            'AccessKeyId': self.configs.AccessKeyId,
            'SignatureMethod': 'HMAC-SHA1',
            'SignatureVersion': 1.0
        }

        formats = "%Y-%m-%dT%H:%M:%SZ"
        timestamp = time.strftime(formats, time.gmtime())  # 函数用于格式化时间,返回以可读字符串表示的当地时间,格式由参数 formats 决定
        Parameters['Timestamp'] = timestamp
        Parameters['SignatureNonce'] = str(uuid.uuid1())
        Parameters['Action'] = "Chat"
        Parameters['InstanceId'] = self.configs.InstanceId
        Parameters['Utterance'] = utterance
        Parameters['Signature'] = self.signature(Parameters)  # 其函数操作包含了之前的一些属性值,因此理应放置到最后计算赋值

        sorted_params = sorted(Parameters.items(), key=lambda Parameters: Parameters[0])
        url = protocol + domain_name + '?' + urllib.parse.urlencode(sorted_params)
        # print("url: " + str(url))

        response = requests.get(url).json()  # 进行接口访问处
        # print('response: ' + str(type(response)))
        # print('response.content: ' + str(response["Messages"][0]["Text"]["Content"]))  # 获取应答内容))

        return response


if '__main__' == __name__:
    data = "你是谁?"  # 言论内容
    chatbot = ChatBot()
    response = chatbot.send(utterance=data)
    print('response.content: ' + str(response["Messages"][0]["Text"]["Content"]))

三、参考文档

  1. 阿里云 Python SDK
  2. 智能对话机器人 SDK参考
  3. 智能对话机器人 API参考