Tạo kỹ năng có trạng thái cho Alice bằng cách sử dụng các chức năng serverless của Yandex.Cloud và Python

Hãy bắt đầu với tin tức. Hôm qua Yandex.Cloud đã công bố ra mắt dịch vụ điện toán không có máy chủ Chức năng đám mây Yandex. Điều này có nghĩa là: bạn chỉ viết mã cho dịch vụ của mình (ví dụ: ứng dụng web hoặc chatbot) và Đám mây sẽ tự tạo và duy trì các máy ảo nơi nó chạy và thậm chí sao chép chúng nếu tải tăng lên. Bạn không cần phải suy nghĩ gì cả, nó rất tiện lợi. Và việc thanh toán chỉ dành cho thời gian tính toán.

Tuy nhiên, một số có thể không trả chút nào. Đây là những nhà phát triển Kỹ năng bên ngoài của Alice, tức là các chatbot được tích hợp sẵn trong đó. Bất kỳ nhà phát triển nào cũng có thể viết, lưu trữ và đăng ký một kỹ năng như vậy và kể từ hôm nay, các kỹ năng đó thậm chí không cần phải được lưu trữ - chỉ cần tải mã của họ lên đám mây theo biểu mẫu chức năng không có máy chủ tương tự.

Nhưng có một vài sắc thái. Đầu tiên, mã pit của bạn có thể yêu cầu một số phụ thuộc và việc kéo chúng vào Đám mây là điều không hề nhỏ. Thứ hai, bất kỳ chatbot thông thường nào cũng cần lưu trữ trạng thái của cuộc đối thoại ở đâu đó (do đó có trạng thái); Cách dễ nhất để thực hiện việc này trong chức năng không có máy chủ là gì? Thứ ba, làm thế nào bạn có thể viết một kỹ năng nhanh chóng và bẩn thỉu cho Alice hoặc thậm chí một loại bot nào đó có cốt truyện khác XNUMX? Trên thực tế, bài viết nói về những sắc thái này.

Tạo kỹ năng có trạng thái cho Alice bằng cách sử dụng các chức năng serverless của Yandex.Cloud và Python

Chuẩn bị đạo đức

Dành cho người thiếu kiên nhẫn: Tôi thu thập các phần phụ thuộc cần thiết bằng tệp tạo tệp trước khi tải chức năng lên đám mây, tôi lưu trữ trạng thái của hộp thoại trong Bộ lưu trữ đối tượng Yandex (nó hỗ trợ API S3) và tôi sử dụng thư viện của riêng mình để quản lý hộp thoại tgalice. Kết quả là, hóa ra như vậy kỹ năng trình diễn. Bây giờ chúng ta hãy xem xét tất cả điều này chi tiết hơn một chút.

Đối với những người ít thiếu kiên nhẫn hơn, trước khi đi sâu vào câu chuyện của tôi về sự phức tạp, tôi thực sự khuyên bạn nên bắt đầu với điều gì đó đơn giản. Cụ thể là tạo một hàm echobot một tệp, đăng ký và kiểm tra nó trong bảng điều khiển dành cho nhà phát triển Dialogs; chi tiết - trong blog đối thoại и Tài liệu về đám mây. Và chỉ sau đó bắt đầu.

Nếu bạn muốn cảm nhận ngay những gì chúng tôi đang đấu tranh ở đây, hãy hỏi Alice 'kích hoạt kỹ năng “tử vi CNTT”'. Một cuộc đối thoại tương tự như sau sẽ xảy ra:

Alice: Xin chào! Bạn đang ở trong kỹ năng “Tử vi CNTT”. Nói “Bắt đầu” để tìm hiểu những gì các ngôi sao hứa hẹn với bạn.
Người dùng: Bắt đầu
A: Hãy cho biết tên của bạn
Yu: Vasisualiy
A: Bây giờ hãy cho tôi biết năm sinh của bạn. Chỉ có bốn chữ số, không có gì thêm.
Yu: thứ hai
Đáp: Vui lòng thử lại. Nhập năm sinh của bạn - bốn chữ số.
Vũ: 2002
Một điều tuyệt vời! Bây giờ hãy đặt tên cho tháng sinh của bạn.
Yu: Tháng hai
Một điều tuyệt vời! Cuối cùng, hãy cho tôi biết ngày sinh của bạn - chỉ một con số, một hoặc hai chữ số.
Vũ: 18
Đáp: Cảm ơn Vasisualiy! Bây giờ chúng tôi biết: bạn 17 tuổi và thuộc cung Bảo Bình. Vâng, tất nhiên, bạn may mắn! Các ngôi sao nói với bạn: а что говорят звёзды, вы узнаете, запустив навык.

Vấn đề là để duy trì một cuộc đối thoại đơn giản như vậy, bạn cần phải nhớ tên và ngày sinh của người dùng, và trong môi trường chức năng không có máy chủ, điều này là không hề nhỏ. Sẽ không thể lưu trữ ngữ cảnh trong RAM hoặc dưới dạng tệp trên đĩa, bởi vì Yandex.Cloud có thể chạy một chức năng trên nhiều máy ảo cùng lúc và chuyển đổi giữa chúng theo ý muốn. Bạn sẽ phải sử dụng một số loại bộ nhớ ngoài. Bộ lưu trữ đối tượng được chọn làm bộ lưu trữ khá rẻ tiền và không phức tạp trực tiếp trong Yandex.Cloud (tức là có thể nhanh). Ví dụ: như một giải pháp thay thế miễn phí, bạn có thể dùng thử một phần miễn phí Mây Monga ở một nơi nào đó rất xa. Có các trình bao bọc Python tiện lợi cho cả Bộ lưu trữ đối tượng (hỗ trợ giao diện S3) và Mongo.

Một vấn đề khác là để truy cập Object Storage, MongoDB và bất kỳ cơ sở dữ liệu hoặc kho dữ liệu nào khác, bạn cần tải một số phụ thuộc bên ngoài lên Yandex Functions cùng với mã chức năng của bạn. Và tôi muốn làm điều này một cách thuận tiện. Thật không may, nó sẽ không hoàn toàn thuận tiện (như trên Heroku), nhưng có thể tạo ra một số tiện nghi cơ bản bằng cách viết một tập lệnh để xây dựng môi trường (tạo tệp).

Cách khởi động kỹ năng tử vi

  1. Chuẩn bị: đi tới một số máy có Linux. Về nguyên tắc, bạn cũng có thể làm việc với Windows, nhưng sau đó bạn sẽ phải thực hiện một số phép thuật khi khởi chạy tệp thực hiện. Và trong mọi trường hợp, bạn sẽ cần cài đặt ít nhất Python 3.6.
  2. Sao chép nó từ Github ví dụ về kỹ năng tử vi.
  3. Đăng ký trong Y.Cloud: https://cloud.yandex.ru
  4. Tạo cho mình hai nhóm trong Lưu trữ đối tượng, gọi họ bằng bất kỳ tên nào {BUCKET NAME} и tgalice-test-cold-storage (tên thứ hai này hiện đã được mã hóa cứng trong main.py ví dụ của tôi). Nhóm đầu tiên sẽ chỉ cần thiết để triển khai, nhóm thứ hai - để lưu trữ trạng thái hộp thoại.
  5. sáng tạo tài khoản dịch vụ, hãy giao cho anh ấy một vai trò editorvà nhận thông tin xác thực tĩnh cho nó {KEY ID} и {KEY VALUE} — chúng tôi sẽ sử dụng chúng để ghi lại trạng thái của cuộc đối thoại. Tất cả điều này là cần thiết để một chức năng từ Ya.Cloud có thể truy cập vào bộ lưu trữ từ Ya.Cloud. Tôi hy vọng một ngày nào đó việc ủy ​​quyền sẽ trở nên tự động, nhưng hiện tại thì nó đã như vậy.
  6. (Tùy chọn) cài đặt giao diện dòng lệnh yc. Bạn cũng có thể tạo một chức năng thông qua giao diện web, nhưng CLI rất tốt vì tất cả các loại đổi mới đều xuất hiện trong đó nhanh hơn.
  7. Bây giờ bạn thực sự có thể chuẩn bị tập hợp phụ thuộc: chạy nó trên dòng lệnh từ thư mục với ví dụ về kỹ năng make all. Một loạt thư viện (hầu hết, như thường lệ, không cần thiết) sẽ được cài đặt trong thư mục dist.
  8. Đổ thủ công vào Object Storage (vào thùng {BUCKET NAME}) lưu trữ thu được ở bước trước dist.zip. Nếu muốn, bạn có thể thực hiện việc này từ dòng lệnh, chẳng hạn như sử dụng AWSCLI.
  9. Tạo chức năng serverless thông qua giao diện web hoặc sử dụng tiện ích yc. Đối với tiện ích, lệnh sẽ trông như thế này:

yc serverless function version create
    --function-name=horoscope
    --environment=AWS_ACCESS_KEY_ID={KEY ID},AWS_SECRET_ACCESS_KEY={KEY VALUE}
    --runtime=python37
    --package-bucket-name={BUCKET NAME}
    --package-object-name=dist.zip
    --entrypoint=main.alice_handler
    --memory=128M
    --execution-timeout=3s

Khi tạo một hàm theo cách thủ công, tất cả các tham số đều được điền theo cùng một cách.

Giờ đây, chức năng bạn đã tạo có thể được kiểm tra thông qua bảng điều khiển dành cho nhà phát triển, sau đó kỹ năng có thể được cải thiện và xuất bản.

Tạo kỹ năng có trạng thái cho Alice bằng cách sử dụng các chức năng serverless của Yandex.Cloud và Python

Có gì dưới mui xe

Tệp thực hiện thực sự chứa một tập lệnh khá đơn giản để cài đặt các phần phụ thuộc và đưa chúng vào kho lưu trữ dist.zip, đại khái như thế này:

mkdir -p dist/
pip3 install -r requirements.txt --target dist/ 
cp main.py dist/main.py
cp form.yaml dist/form.yaml
cd dist && zip --exclude '*.pyc' -r ../dist.zip ./*

Phần còn lại là một vài công cụ đơn giản được gói gọn trong thư viện tgalice. Quá trình điền dữ liệu người dùng được mô tả bằng config form.yaml:

form_name: 'horoscope_form'
start:
  regexp: 'старт|нач(ать|ни)'
  suggests:
    - Старт
fields:
  - name: 'name'
    question: Пожалуйста, назовите своё имя.
  - name: 'year'
    question: Теперь скажите мне год вашего рождения. Только четыре цифры, ничего лишнего.
    validate_regexp: '^[0-9]{4}$'
    validate_message: Пожалуйста, попробуйте ещё раз. Назовите год вашего рождения - четыре цифры.
  - name: 'month'
    question: Замечательно! Теперь назовите месяц вашего рождения.
    options:
      - январь
     ...
      - декабрь
    validate_message: То, что вы назвали, не похоже на месяц. Пожалуйста, назовите месяц вашего рождения, без других слов.
  - name: 'day'
    question: Отлично! Наконец, назовите мне дату вашего рождения - только число, всего одна или две цифры.
    validate_regexp: '[0123]?d$'
    validate_message: Пожалуйста, попробуйте ещё раз. Вам нужно назвать число своего рождения (например, двадцатое); это одна или две цифры.

Công việc phân tích cấu hình này và tính toán kết quả cuối cùng được đảm nhận bởi lớp Python

class CheckableFormFiller(tgalice.dialog_manager.form_filling.FormFillingDialogManager):
    SIGNS = {
        'январь': 'Козерог',
        ...
    }

    def handle_completed_form(self, form, user_object, ctx):
        response = tgalice.dialog_manager.base.Response(
            text='Спасибо, {}! Теперь мы знаем: вам {} лет, и вы {}. n'
                 'Вот это вам, конечно, повезло! Звёзды говорят вам: {}'.format(
                form['fields']['name'],
                2019 - int(form['fields']['year']),
                self.SIGNS[form['fields']['month']],
                random.choice(FORECASTS),
            ),
            user_object=user_object,
        )
        return response

Chính xác hơn, lớp cơ sở FormFillingDialogManager xử lý việc điền vào “biểu mẫu” và phương thức lớp con handle_completed_form bảo cô ấy phải làm gì khi cô ấy sẵn sàng.

Ngoài luồng đối thoại chính này, người dùng cũng phải được chào đón cũng như được trợ giúp bằng cách sử dụng lệnh “trợ giúp” và thoát khỏi kỹ năng bằng lệnh “thoát”. Để làm điều này trong tgalice Ngoài ra còn có một mẫu, do đó toàn bộ trình quản lý hộp thoại được tạo thành từ các phần:

dm = tgalice.dialog_manager.CascadeDialogManager(
    tgalice.dialog_manager.GreetAndHelpDialogManager(
        greeting_message=DEFAULT_MESSAGE,
        help_message=DEFAULT_MESSAGE,
        exit_message='До свидания, приходите в навык "Айтишный гороскоп" ещё!'
    ),
    CheckableFormFiller(`form.yaml`, default_message=DEFAULT_MESSAGE)
)

CascadeDialogManager Nó hoạt động đơn giản: nó cố gắng lần lượt áp dụng tất cả các thành phần của nó vào trạng thái hiện tại của cuộc đối thoại và chọn thành phần thích hợp đầu tiên.

Trình quản lý hộp thoại trả về một đối tượng Python dưới dạng phản hồi cho mỗi thông báo. Response, sau đó có thể được chuyển đổi thành văn bản thuần túy hoặc thành tin nhắn trong Alice hoặc Telegram - tùy thuộc vào nơi bot đang chạy; nó cũng chứa trạng thái đã thay đổi của đoạn hội thoại cần được lưu. Toàn bộ nhà bếp này được xử lý bởi một tầng lớp khác, DialogConnector, do đó, tập lệnh trực tiếp để khởi chạy một kỹ năng trên Yandex Functions trông như thế này:

...
session = boto3.session.Session()
s3 = session.client(
    service_name='s3',
    endpoint_url='https://storage.yandexcloud.net',
    aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'],
    region_name='ru-central1',
)
storage = tgalice.session_storage.S3BasedStorage(s3_client=s3, bucket_name='tgalice-test-cold-storage')
connector = tgalice.dialog_connector.DialogConnector(dialog_manager=dm, storage=storage)
alice_handler = connector.serverless_alice_handler

Như bạn có thể thấy, hầu hết mã này tạo kết nối đến giao diện S3 của Bộ lưu trữ đối tượng. Bạn có thể đọc cách kết nối này được sử dụng trực tiếp trong mã tgalice.
Dòng cuối cùng tạo hàm alice_handler — chính cái mà chúng tôi đã yêu cầu Yandex.Cloud kéo khi chúng tôi đặt tham số --entrypoint=main.alice_handler.

Thực ra đó là tất cả. Các tệp tạo tệp để lắp ráp, Bộ lưu trữ đối tượng giống như S3 để lưu trữ ngữ cảnh và thư viện Python tgalice. Kết hợp với các chức năng serverless và tính biểu cảm của Python, điều này đủ để phát triển một kỹ năng lành mạnh của con người.

Bạn có thể hỏi tại sao cần thiết phải tạo tgalice? Tất cả các mã nhàm chán chuyển JSON từ yêu cầu sang phản hồi và từ bộ lưu trữ sang bộ nhớ và ngược lại đều nằm trong đó. Ngoài ra còn có một ứng dụng mã thông thường, một chức năng để hiểu rằng “Tháng Hai” tương tự như “Tháng Hai” và các NLU khác dành cho người nghèo. Theo ý tưởng của tôi, điều này là đủ để bạn có thể phác thảo nguyên mẫu các kỹ năng trong tệp yaml mà không bị phân tâm bởi các chi tiết kỹ thuật.

Nếu bạn muốn một NLU nghiêm túc hơn, bạn có thể gắn nó vào kỹ năng của mình Rasa hoặc sâuPavlov, nhưng việc thiết lập chúng sẽ yêu cầu các điệu nhảy bổ sung với tambourine, đặc biệt là trên serverless. Nếu bạn không thích viết mã chút nào, bạn nên sử dụng một hàm tạo trực quan như aimylogic. Khi tạo tgalice, tôi đã nghĩ về một số loại đường dẫn trung gian. Hãy xem điều gì đến từ điều này.

Nào, bây giờ hãy tham gia trò chuyện của nhà phát triển kỹ năng alice, đọc tài liệu, và tạo ra điều tuyệt vời kỹ năng!

Nguồn: www.habr.com

Thêm một lời nhận xét