Lập Trình Trợ Lý Ảo Tiếng Việt Toàn Diện Với Python

Lập Trình Trợ Lý Ảo Tiếng Việt Toàn Diện Với Python

Ngoài Siri của Apple, Alexa của Amazon và gần đây là Google Asisstant của Google, còn gì tuyệt vời hơn khi biết bạn cũng có thể tự tạo cho mình một con trợ lý ảo, ngay cả phiên bản tiếng việt. Nào bắt tay vào làm thôi.

Trong bài viết, mình sẽ đi chi tiết làm thế nào để viết một trở lý ảo tiếng việt bằng Python, mình gọi tên cậu ấy là Alex.

Nhiều bạn vẫn chưa thực sự được tiếp cận với trí tuệ nhân tạo hay cụ thể hơn là xử lý ngôn ngữ tự nhiên hay một con trợ lý ảo nghĩa là gì. Thực sự, trí tuệ nhân tạo nói chung và xử lý ngôn ngữ tự nhiên đóng góp to lớn như thế nào đối với ngành công nghệ thông tin. Mình chọn sử dung python, Python là một ngôn ngữ lập trình có một bộ thư viện đa năng. Nên trí tuệ nhân tạo bây giờ cũng trở nên đơn giản hơn với chúng ta. Mình sẽ cụ thể hóa các chi tiết giúp bạn hình dung những công việc để làm một con trợ lý ảo nhé.

Trợ lý ảo đã phát triển thế nào?

Timeline trợ lý ảo từ 2010 đến nay

Kiến thức cần có

  • AI - Artificial Intelligence hay còn gọi là Trí tuệ nhân tạo là một ngành khoa học, kỹ thuật chế tạo máy móc thông minh, đặc biệt là các chương trình máy tính thông minh. AI được thực hiện bằng cách nghiên cứu cách suy nghĩ của con người, cách con người học hỏi, quyết định và làm việc trong khi giải quyết một vấn đề nào đó, và sử dụng những kết quả nghiên cứu này như một nền tảng để phát triển các phần mềm và hệ thống thông minh, từ đó áp dụng vào các mục đích khác nhau trong cuộc sống. Nói một cách dễ hiểu thì AI là việc sử dụng, phân tích các dữ liệu đầu vào nhằm đưa ra sự dự đoán rồi đi đến quyết định cuối cùng.
  • Xử lý ngôn ngữ tự nhiên (natural language processing - NLP) là một nhánh của trí tuệ nhân tạo tập trung vào các ứng dụng trên ngôn ngữ của con người. Trong trí tuệ nhân tạo thì xử lý ngôn ngữ tự nhiên là một trong những phần khó nhất vì nó liên quan đến việc phải hiểu ý nghĩa ngôn ngữ-công cụ hoàn hảo nhất của tư duy và giao tiếp.
  • Trợ lý ảo (Virtual Assistant) hay còn gọi là trợ lý AI hay trợ lý kỹ thuật số, là chương trình ứng dụng được thiết kế để "hiểu" các lệnh thoại bằng ngôn ngữ tự nhiên và thực hiện các tác vụ cho người dùng. Các tác vụ này bao gồm đọc tin nhắn văn bản hoặc địa chỉ email, tìm kiếm số điện thoại, lên lịch, đặt cuộc gọi điện và nhắc nhở người dùng cuối về các cuộc hẹn.

Nào chúng ta bắt đầu thôi. Let's go !!!!

Nguyên liệu cần chuẩn bị

  • System requirements: Python 3.7.6, Jupyter notebook, Anaconda.
  • Libraries:
    • speech_recognition: Nhận dạng giọng nói
    • time, datetime: Xử lý thời gian
    • wikipedia: Tìm kiếm trên từ điển wikipedia
    • webbrowser, selenium, webdriver_manager, urllib: Truy cập web, trình duyệt (Chrome)
    • gTTS: Chuyển văn bản thành âm thanh của Google (Chị Google)
    • requests: Crawl thông tin từ web
    • smtplib: Gửi Email bằng giao thức SMTP
    • re: Biểu thức chính quy (Regular Expression) 
    • os, sys, ctypes: Truy cập, xử lý file hệ thống
    • playsound: Phát âm thanh từ file mp3
    • json: Xử lý kiểu dữ liệu JSON
    • youtube_search: Tìm kiếm video trên Youtube

Cài đặt

Anaconda là một công cụ tổng hợp đã tích hợp sẵn rất nhiều các gói phần mềm, thư viện giúp chúng ta có một môi trường để thực hiện xây dựng các ứng dụng Python. Anacoda cũng tích hợp sẵn conda bên trong do đó bạn chỉ cần cài đặt Anacoda là đủ.

Khi cài đặt xong, bạn mở Anaconda Prompt (có thể tìm thấy trong thư mục cài đặt Anaconda), di chuyển đến thư mục chứa project và thực hiện chạy Jupyter Notebook bằng câu lệnh:

jupyter notebook

Cửa số hiện lên, bạn chỉ cần vào new chọn python 3 ta đã có một notebook có thể chạy Python dưới dạng các interactive shell

Cuối cùng là việc cài đặt các thư viện cần thiết, chúng ta tiếp tục vào Anaconda Prompt và thực hiện cài các Python Package thông qua gói thư viện pip. Ví dụ, ta muốn cài đặt thư viện abcxyz thì gõ câu lệnh:

pip install abcxyz

Xây dựng trợ lý ảo tiếng việt Alex

1. Import các thư viện cần thiết

import os
import playsound
import speech_recognition as sr
import time
import sys
import ctypes
import wikipedia
import datetime
import json
import re
import webbrowser
import smtplib
import requests
import urllib
import urllib.request as urllib2
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
from time import strftime
from gtts import gTTS
from youtube_search import YoutubeSearch

Ở trên, thư viện urlllib2 thực ra đã được thay thế bằng thư viện urllib.requesturllib ở phiên bản Python 3. Mình vẫn đặt tên là urllib2 để tránh nhầm lẫn.

Với mỗi chức năng mà trợ lý ảo thực hiện mình sẽ đại diện bằng một hàm. Mỗi hàm có thể trả về giá trị hoặc chỉ thực hiện lệnh tùy theo chức năng của nó.

Việc đầu tiên mình sẽ khai báo một vài biến để lưu đường dẫn hay các tham số để xử lý ngôn ngữ dưới dạng tiếng việt.

2. Khai báo biến mặc định

wikipedia.set_lang('vi')
language = 'vi'
path = ChromeDriverManager().install()

Hiện tại, các Lab nghiên cứu về trí tuệ nhân tạo ở Việt Nam đang đầu tư đẩy mạnh nghiên cứu mảng xử lý ngôn ngữ tự nhiên (Natural Language Processing) ở dạng tiếng việt và đã đạt được những kết quả đáng ghi nhận. Các mô hình nghiên cứu được có thể xử lý ngôn ngữ tiếng việt ở nhiều vùng miền, cả nam lẫn nữ, rất thực. Ở góc độ người sử dụng phổ thông thì khó có thể biết đâu là do máy tính, đâu là do người thực hiện. Các nghiên cứu đều có tính ứng dụng cao, đang được các công ty công nghệ áp dụng triển khai thực tế, nâng cao năng suất lao động một cách rõ rệt.

Các thư viện mình sử dụng ở trên đều rất phổ thông, tích hợp nhiều hàm xử lý. Tuy chất lượng xử lý tiếng việt chưa thực sự tuyệt vời nhưng ở góc độ bài viết thì mình thấy là khá ổn.

Mình lưu thêm biến path để lưu đường dẫn cài đặt Chrome để tránh việc cài đặt lại Chrome khi chạy lại hàm.

3. Chức năng chuyển văn bản thành âm thanh

Google Cloud Text To Speech

def speak(text):
    print("Bot: {}".format(text))
    tts = gTTS(text=text, lang=language, slow=False)
    tts.save("sound.mp3")
    playsound.playsound("sound.mp3", False)
    os.remove("sound.mp3")

Chức năng đầu tiên mình cần là chuyển một đoạn văn bản thành âm thanh và đọc nó lên trên máy tính.

Mình sử dụng hàm gTTS (google Text To Speech) để chuyển văn bản thành âm thanh theo ngôn ngữ nhận dạng tiếng việt rồi lưu về máy tính dữ liệu âm thanh dưới file sound.mp3.

Sau đó, minh dùng hàm playsound.playsound() để đọc file sound.mp3 trên máy tính.

Sau khi đọc xong, mình phải xóa file sound.mp3 để tránh lỗi khi mình đọc một đoạn văn bản khác thì cũng được lưu lại dưới file sound.mp3.

4. Chức năng chuyển âm thanh thành văn bản

Quy trình chung hệ thống nhận dạng giọng nói

Đây là chức năng cơ bản thứ hai cùng với chức năng chuyển văn bản thành âm thanh.

Trong chức năng này, mình sử dụng 2 hàm khác hỗ trợ là get_audio() và stop()

def get_audio():
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("Tôi: ", end='')
        audio = r.listen(source, phrase_time_limit=5)
        try:
            text = r.recognize_google(audio, language="vi-VN")
            print(text)
            return text
        except:
            print("...")
            return 0

Ở hàm trên, mình sử dụng thư viện speech_recognition (sr) có chức năng là nhận dạng giọng nói để chuyển âm thanh thành văn bản. Âm thanh được đọc vào microphone của máy tính sau đó được xử lý qua hàm listen của sr.Recognition rồi lưu dữ liệu âm thanh vào biến audio. Dữ liệu âm thanh audio thu được sẽ được nhận dạng ở ngôn ngữ tiếng việt trong hàm r.recognize_google để chuyển thành dạng văn bản rồi lưu dữ liệu vào biến text

Nếu dữ liệu âm thanh audio không lỗi tức là hàm r.recognize_google có thể nhận dạng được audio để chuyên thành text thì hàm get_audio() sẽ được trả về giá trị là text còn nếu dữ liệu audio bị lỗi mà hàm r.recognition_google không nhận dạng được thì hàm get_audio() sẽ được trả về giá trị là 0 (Mục đích là khi máy tính không hiểu mình nói gì thì mình sẽ thực hiện lại hàm get_audio() để đọc lại) 

def stop():
    speak("Hẹn gặp lại bạn sau!")

Hàm stop() đơn giản là đọc đoạn text "Hẹn gặp lại bạn sau" sử dụng hàm speak() ở trên.

def get_text():
    for i in range(3):
        text = get_audio()
        if text:
            return text.lower()
        elif i < 2:
            speak("Bot không nghe rõ. Bạn nói lại được không!")
    time.sleep(2)
    stop()
    return 0

Hàm get_text() có chức năng là máy tính sẽ cố gắng nhận dạng âm thanh của người đọc tối đa 3 lần cho đến khi máy tính hiểu. Mình sử dụng hàm for lặp lại 3 lần, nếu đoạn text có giá trị khác 0 thì hàm get_text sẽ được trả về giá trị text.lower() (Chuyển chữ cái in hoa thành in thường), còn nếu text nhận giá trị là 0 (Tức là minh đọc mà máy tính không hiểu) mà chưa đọc đến lần thứ 3 thì mình sẽ yêu cầu người sử dụng đọc lại. Nếu sau 3 lần mà máy tính vẫn không hiểu thì mình nói gì hay không nghe thấy gì thì mình sẽ cho dừng lại sử dụng hàm stop và hàm get_text lúc này sẽ được trả về giá trị là 0 (Mục đích là khi máy tính không nghe thấy gì thì mình sẽ cho dừng chương trình luôn).

Mình thêm câu lệnh time.sleep(2) mục đích là chương trình tạm dừng 2 giây để tránh máy tính đọc các đoạn văn bản bị khớp nhau.

5. Chức năng giao tiếp, chào hỏi

def hello(name):
    day_time = int(strftime('%H'))
    if day_time < 12:
        speak("Chào buổi sáng bạn {}. Chúc bạn một ngày tốt lành.".format(name))
    elif 12 <= day_time < 18:
        speak("Chào buổi chiều bạn {}. Bạn đã dự định gì cho chiều nay chưa.".format(name))
    else:
        speak("Chào buổi tối bạn {}. Bạn đã ăn tối chưa nhỉ.".format(name))

Nội dung chức năng này là để giao tiếp thông thường giữa người và máy tính. Đơn cử như: chào hỏi, hỏi thăm sức khỏe hay nói về thông tin trợ lý ảo,... Ở đây, mình sẽ mô phỏng bằng chức năng chào hỏi sử dụng hàm hello.

Mình sử dụng biến day_time để lưu giờ hiện tại trong ngày. Sau đó, biến sẽ được so sánh với các mốc giờ trong ngày để đưa ra lời chào.

Như trên thì trước 12 giờ thì mình sẽ chào buổi sáng, từ 12 giờ đến sau 18 giờ mình sẽ chào buổi chiều, từ 18 giờ trở đi mình sẽ chào buổi tối.

6. Chức năng hiển thị thời gian

def get_time(text):
    now = datetime.datetime.now()
    if "giờ" in text:
        speak('Bây giờ là %d giờ %d phút' % (now.hour, now.minute))
    elif "ngày" in text:
        speak("Hôm nay là ngày %d tháng %d năm %d" %
              (now.day, now.month, now.year))
    else:
        speak("Bot chưa hiểu ý của bạn. Bạn nói lại được không?")

Chức năng này khá là đơn giản. Mình sử dụng thư viện datetime để lưu thông tin thời gian tại thời điểm hiện tại trong ngày rồi lưu vào biến now

Mình kiểm tra nếu trong đoạn text mình hỏi có chữ "giờ", mình sẽ đọc thời gian hiện tại trong ngày còn nếu có chữ "ngày" trong text thì mình sẽ đọc thời điểm hiện tại trong năm.

Ví dụ:

text = "Bây giờ là mấy giờ"

Tức là có chữ "giờ" trong text thì hàm get_time thực hiện lệnh đọc:

Bây giờ là 10 giờ 26 phút

7. Chức năng mở ứng dụng hệ thống, website và chức năng tìm kiếm từ khóa trên Google

def open_application(text):
    if "google" in text:
        speak("Mở Google Chrome")
        os.startfile('C:\Program Files (x86)\Google\Chrome\Application\chrome.exe')
    elif "word" in text:
        speak("Mở Microsoft Word")
        os.startfile('C:\Program Files\Microsoft Office\\root\Office16\\WINWORD.EXE')
    elif "excel" in text:
        speak("Mở Microsoft Excel")
        os.startfile('C:\Program Files\Microsoft Office\\root\Office16\EXCEL.EXE')
    else:
        speak("Ứng dụng chưa được cài đặt. Bạn hãy thử lại!")

Khi xuất hiện các từ khóa đặc biệt như google hay word hay excel trong text thì mình dùng hàm os.startfile() để mở các file ứng dụng từ hệ thống.

Chỉ kiểm tra từ google hay word hay excel trong text là chưa đủ. Mình cần giới hạn ngữ nghĩa của text ở trong hàm assistant để bot có thể hiểu là mở chương trình Google Chrome, Word, Excel chứ không nhầm lẫn với các chức năng khác.

def open_website(text):
    reg_ex = re.search('mở (.+)', text)
    if reg_ex:
        domain = reg_ex.group(1)
        url = 'https://www.' + domain
        webbrowser.open(url)
        speak("Trang web bạn yêu cầu đã được mở.")
        return True
    else:
        return False

Mình sử dụng hàm re.search() (Hàm tìm kiếm trong biểu thức chính quy Regular Expression) để tách phần domain sau chữ "mở" trong text rồi ghép với phần tiền tố "https://www." để tạo thành đường dẫn url của web.

Sau đó, mình sử dụng webbroser.open(url) để mở trang web mình yêu cầu.

Nếu domain được hàm re.search() tìm thấy thì mình sẽ thực hiện chức năng mở website và hàm open_website được trả về giá trị là True, còn nếu domain không được tìm thấy thì mình sẽ không thực hiện chức năng gì cả và hàm open_website trả về giá trị là False.

def open_google_and_search(text):
    search_for = text.split("kiếm", 1)[1]
    speak('Okay!')
    driver = webdriver.Chrome(path)
    driver.get("http://www.google.com")
    que = driver.find_element_by_xpath("//input[@name='q']")
    que.send_keys(str(search_for))
    que.send_keys(Keys.RETURN)

Cuối cùng là chức năng tìm kiếm từ khóa trên Google. Mình tiếp tục thực hiện tách từ khóa phía sau chữ "kiếm" trong text sử dụng hàm split() rồi lưu vào biến search_for.

Tiếp theo mình gọi hàm webdriver.Chrome(path) để mở ứng dụng Google Chrome rồi vào trang chủ "https://www.google.com".

Sau đó, mình sử dụng hàm driver.find_element_by_path() để lấy thẻ query (viết tắt là q) rồi lưu vào biến que

Biến que thực hiện tìm kiếm từ khóa search_for và trả về kết quả trên Google Search.

8. Chức năng gửi Email

SMTP là 3 chữ cái đầu viết tắt của Simple Mail Transfer Protocol dịch ra có nghĩa là giao thức truyền tải thư tín đơn giản hóa. Và giao thức này thực hiện nhiệm vụ chính là gửi mail còn việc nhận mail hay truy xuất dữ liệu mail server sẽ có giao thức IMAP hay POP3 đảm nhiệm.

SMTP Server (server dùng để gửi mail) là một dịch vụ cho phép gửi email với số lượng lớn, tốc độ nhanh mà không bị giới hạn như các hòm mail miễn phí của Gmail hoặc mail đi kèm hosting. Nói cách khác các máy chỉ chủ giúp bạn thao tác gửi thư người ta thường gọi là SMTP server chúng thực hiện gửi thư qua giao thức TCP hoặc IP.

def send_email(text):
    speak('Bạn gửi email cho ai nhỉ')
    recipient = get_text()
    if 'yến' in recipient:
        speak('Nội dung bạn muốn gửi là gì')
        content = get_text()
        mail = smtplib.SMTP('smtp.gmail.com', 587)
        mail.ehlo()
        mail.starttls()
        mail.login('[email protected]', 'hung23081997')
        mail.sendmail('[email protected]',
                      '[email protected]', content.encode('utf-8'))
        mail.close()
        speak('Email của bạn vùa được gửi. Bạn check lại email nhé hihi.')
    else:
        speak('Bot không hiểu bạn muốn gửi email cho ai. Bạn nói lại được không?')

Mình sử dụng thư viện smtplib để thực hiện chức năng gửi Email bằng phương thức smtp.

Mình lấy tên người gửi sử dụng bằng hàm get_text() rồi lưu vào biến recipient.

Ở hàm này, mình lấy ví dụ đơn giản là nếu tìm thấy chữ "yến" trong tên người cần gửi (recipient) thì mình sẽ thực hiện chức năng gửi Email.

Tiếp tục, mình gọi hàm get_text() để lấy nội dung cần gửi rồi lưu vào biến content.

Tiếp theo, mình mở đường truyền gửi Email bằng smtp rồi đăng nhập lại vào tài khoản gmail của mình. Sau khi kết nối thành công, mình gửi email từ địa chỉ "[email protected]" đến địa chỉ "[email protected]" với nội dung content đã lấy ở trên. Cuối cùng, mình sẽ đóng đường truyền lại.

Khá là đơn giản phải không!!!

9. Chức năng xem dự báo thời tiết

OpenWeatherMap là một dịch vụ trực tuyến cung cấp dữ liệu thời tiết. Nó thuộc sở hữu của OpenWeather Ltd, có trụ sở tại London, Vương quốc Anh. Nó cung cấp dữ liệu thời tiết hiện tại, dự báo và dữ liệu lịch sử cho hơn 2 triệu khách hàng, bao gồm các công ty Fortune 500 và hàng ngàn doanh nghiệp khác trên toàn cầu.

def current_weather():
    speak("Bạn muốn xem thời tiết ở đâu ạ.")
    ow_url = "http://api.openweathermap.org/data/2.5/weather?"
    city = get_text()
    if not city:
        pass
    api_key = "fe8d8c65cf345889139d8e545f57819a"
    call_url = ow_url + "appid=" + api_key + "&q=" + city + "&units=metric"
    response = requests.get(call_url)
    data = response.json()
    if data["cod"] != "404":
        city_res = data["main"]
        current_temperature = city_res["temp"]
        current_pressure = city_res["pressure"]
        current_humidity = city_res["humidity"]
        suntime = data["sys"]
        sunrise = datetime.datetime.fromtimestamp(suntime["sunrise"])
        sunset = datetime.datetime.fromtimestamp(suntime["sunset"])
        wthr = data["weather"]
        weather_description = wthr[0]["description"]
        now = datetime.datetime.now()
        content = """
        Hôm nay là ngày {day} tháng {month} năm {year}
        Mặt trời mọc vào {hourrise} giờ {minrise} phút
        Mặt trời lặn vào {hourset} giờ {minset} phút
        Nhiệt độ trung bình là {temp} độ C
        Áp suất không khí là {pressure} héc tơ Pascal
        Độ ẩm là {humidity}%
        Trời hôm nay quang mây. Dự báo mưa rải rác ở một số nơi.""".format(day = now.day,month = now.month, year= now.year, hourrise = sunrise.hour, minrise = sunrise.minute,
                                                                           hourset = sunset.hour, minset = sunset.minute, 
                                                                           temp = current_temperature, pressure = current_pressure, humidity = current_humidity)
        speak(content)
        time.sleep(20)
    else:
        speak("Không tìm thấy địa chỉ của bạn")

Mình sử dụng nguồn dữ liệu thời tiết của hầu hết các thành phố trên toàn thể thời cung cấp tại trang web openweathermap.org

Đầu tiên, mình sẽ sử dụng biến ow_url để lưu đường đẫn đến api của trang web openweathermap.org. Thông tin các thẻ để thực hiện request mình sẽ bổ sung sau.

Mình gọi hàm get_text() để lấy thông tin thành phố cần truy vấn thời tiết rồi lưu vào biến city.

Nếu máy tính không nghe được tên thành phố thì hàm sẽ pass (Bỏ qua hàm)

Tiếp theo là thực hiện kết nối với api trang web openweathermap.org. Ở bước này, mình phải đăng kí tài khoản mới ở đây và lấy api_key để có thể thực hiện thao tác truy vấn.

Biến call_url sẽ lưu đường dẫn đầy đủ để truy vấn bao gồm thông tin tên thành phố cityapi_key mình đã lấy ở trên.

Thư viện requests là một mô-đun Python mà bạn có thể sử dụng để gửi tất cả các loại yêu cầu HTTP. Mình gọi hàm requests.get(call_url) để lấy thông tin truy vấn được từ trang web rồi lưu vào biến response. response.json() sẽ chuyển dữ liệu thuần về kiểu dữ liệu json rồi lưu vào biến data.

Nếu data["cod"] không trả về 404 tức là requests không bị lỗi hay có nghĩa là thông tin tên thành phố city chuẩn xác (truy vấn được) thì mình sẽ thực hiện chức năng xem thời tiết.

Bạn nên tìm hiểu về kiểu dữ liệu json. Mình không đề cập ở đây. Từ dữ liệu kiểu json được lưu trong biến data mình sẽ lấy được thông tin thời tiết bao gồm temperature, pressure, humidity,..

Cuối cùng mình kết nối những thông tin trên với nhau rồi lưu vào biến content và thực hiện đọc content.

Tương tự như trên, câu lệnh time.sleep(20) yêu cầu chương trình tạm dừng 20 giây để có thời gian đọc xong content trên.

10. Chức năng phát nhạc trên Youtube

def play_song():
    speak('Xin mời bạn chọn tên bài hát')
    mysong = get_text()
    while True:
        result = YoutubeSearch(mysong, max_results=10).to_dict()
        if result:
            break
    url = 'https://www.youtube.com' + result[0]['channel_link']
    webbrowser.open(url)
    speak("Bài hát bạn yêu cầu đã được mở.")

Mình gọi hàm get_text() để lấy thông tin tên bài hát muốn phát rồi lưu vào biến mysong.

Mình gọi vòng While là vì mình thực hiện tìm kiếm sử dụng mạng Internet nên sẽ có lúc kết nối yếu không tìm thấy. Mình chạy While True khi nào tìm thấy thì thôi.

Biến url lưu đường dẫn đến kết quả đầu tiên khi tìm kiếm trên Youtube.

Mình sẽ dùng hàm webbrowser.open(url) mở đường dẫn url đến video vừa được tìm kiếm trên Google Chrome để phát nhạc.

11. Chức năng thay đổi hình nền máy tính

Unsplash là một cộng đồng nhiếp ảnh – nơi mọi người chia sẻ miễn phí ảnh chụp chất lượng cao

def change_wallpaper():
    api_key = 'RF3LyUUIyogjCpQwlf-zjzCf1JdvRwb--SLV6iCzOxw'
    url = 'https://api.unsplash.com/photos/random?client_id=' + \
        api_key  # pic from unspalsh.com
    f = urllib2.urlopen(url)
    json_string = f.read()
    f.close()
    parsed_json = json.loads(json_string)
    photo = parsed_json['urls']['full']
    # Location where we download the image to.
    urllib2.urlretrieve(photo, "C:/Users/Night Fury/Downloads/a.png")
    image=os.path.join("C:/Users/Night Fury/Downloads/a.png")
    ctypes.windll.user32.SystemParametersInfoW(20,0,image,3)
    speak('Hình nền máy tính vừa được thay đổi')

Tương tự như khi lấy thông tin dự báo thời tiết. Mình sẽ lấy nguồn dữ liệu kho ảnh của trang web unsplash.com.

Mình cần đăng ký để có api_key do trang web cung cấp để có thể kết nối với api của unsplash.com.

Biến url lưu đường dẫn đến api của trang unsplash.com.

Mình mở đường dẫn url và lấy requests rồi lưu thông tin vào biến json_string.

Bức ảnh sẽ được load và đọc từ json_string rồi lưu vào biến photo.

Dữ liệu hình ảnh photo được lưu lại thành file ảnh trong máy tính.

Cuối cùng, mình dùng lệnh thay đổi hình nền của hệ thống qua hàm số ctypes.windll.user32.SystemParametersInfoW().

Chỉ cần như vậy, máy tính đã được thay hình nền mới.

12. Chức năng đọc báo ngày hôm nay

News API là một API REST HTTP đơn giản sử dụng để tìm kiếm và truy xuất các bài viết trực tiếp từ khắp nơi trên web

def read_news():
    speak("Bạn muốn đọc báo về gì")
    
    queue = get_text()
    params = {
        'apiKey': '30d02d187f7140faacf9ccd27a1441ad',
        "q": queue,
    }
    api_result = requests.get('http://newsapi.org/v2/top-headlines?', params)
    api_response = api_result.json()
    print("Tin tức")

    for number, result in enumerate(api_response['articles'], start=1):
        print(f"""Tin {number}:\nTiêu đề: {result['title']}\nTrích dẫn: {result['description']}\nLink: {result['url']}
    """)
        if number <= 3:
            webbrowser.open(result['url'])

Cách thực hiện tương tự như với chức năng dự báo thời tiết hay thay đổi hình nền máy tính.

Mình chọn trang web newsapi.org là nguồn các bài báo được cập nhật nhanh nhất và cho mình thông tin requests tốt nhất.

Ở đây, mình cũng phải đăng kí tài khoản và lấy apiKey trang web cung cấp để kết nối với nguồn dữ liệu của họ.

Mình sử dụng hàm get_text() để lấy thông tin về chủ đề mình muốn đọc.

Sau đó, mình gọi hàm requests.get() để khai thác thông tin từ đường dẫn url mình nhập và lưu vào biến api_result.

Kết quả được định dạng lại kiểu dữ liệu json và lưu vào biến api_response.

Cuối cùng, mình hiển thị tối đa 20 tin tức thu thập được và mở 3 đường dẫn đến 3 bài báo đầu tiên để tiện theo dõi. 

13. Chức năng tìm định nghĩa trên từ điển wikipedia

Wikipedia là một bách khoa toàn thư mở với mục đích chính là cho phép mọi người đều có thể viết bài bằng nhiều loại ngôn ngữ trên Internet. Wikipedia đang là công trình tham khảo viết chung lớn nhất và phổ biến nhất trên Internet và hiện tại được xếp hạng trang web phổ biến thứ 5 trên toàn cầu. Wikipedia thuộc về tổ chức phi lợi nhuận Wikimedia Foundation.

def tell_me_about():
    try:
        speak("Bạn muốn nghe về gì ạ")
        text = get_text()
        contents = wikipedia.summary(text).split('\n')
        speak(contents[0])
        time.sleep(10)
        for content in contents[1:]:
            speak("Bạn muốn nghe thêm không")
            ans = get_text()
            if "có" not in ans:
                break    
            speak(content)
            time.sleep(10)

        speak('Cảm ơn bạn đã lắng nghe!!!')
    except:
        speak("Bot không định nghĩa được thuật ngữ của bạn. Xin mời bạn nói lại")

Bot của mình có thể lấy thông tin chi tiết của hầu hết mọi thứ mình hỏi cô ấy. Như “Alex cho tôi biết về Google” hoặc “Vui lòng cho tôi biết về Siêu máy tính” hoặc “hãy cho tôi biết về Internet”. Vì vậy, như bạn có thể thấy, mình có thể hỏi về hầu hết mọi thứ.

Hàm tìm kiếm của thư viện wikipedia sẽ tìm kiếm chủ đề mình yêu cầu và trích xuất 500 ký tự đầu tiên (nếu bạn không chỉ định giới hạn, bot sẽ đọc toàn bộ trang cho bạn). Wikipedia là một thư viện Python giúp dễ dàng truy cập và phân tích dữ liệu từ Wikipedia.

Đầu tiên mình sử dụng hàm get_text() để lấy thông tin về thứ mình muốn định nghĩa rồi lưu vào biến text.

Sau đó, mình gọi hàm wikipedia.summary(text).split('\n') để lưu lại thành một list các đoạn nội dung mà wikipedia tìm kiếm được.

Tiếp theo, mình đọc đoạn định nghĩa đầu tiên.

Nếu có yêu cầu đọc thêm các nội dung sau thì mình phải yêu cầu là "có" còn nếu không yêu cầu thì trợ lý ảo sẽ dừng đọc nội dung trong phần contents. 

14. Chức năng hiển thị các khả năng của trợ lý ảo

def help_me():
    speak("""Bot có thể giúp bạn thực hiện các câu lệnh sau đây:
    1. Chào hỏi
    2. Hiển thị giờ
    3. Mở website, application
    4. Tìm kiếm trên Google
    5. Gửi email
    6. Dự báo thời tiết
    7. Mở video nhạc
    8. Thay đổi hình nền máy tính
    9. Đọc báo hôm nay
    10. Kể bạn biết về thế giới """)

Hàm đọc lại 10 chức năng mà trợ lý ảo có thể thực hiện được phòng khi người sử dụng chưa biết công dụng của trợ lý ảo.

15. Kết hợp tất cả chức năng Trợ lý ảo Tiếng Việt 

def assistant():
    speak("Xin chào, bạn tên là gì nhỉ?")
    name = get_text()
    if name:
        speak("Chào bạn {}".format(name))
        speak("Bạn cần Bot Alex có thể giúp gì ạ?")
        while True:
            text = get_text()
            if not text:
                break
            elif "dừng" in text or "tạm biệt" in text or "chào robot" in text or "ngủ thôi" in text:
                stop()
                break
            elif "có thể làm gì" in text:
                help_me()
            elif "chào trợ lý ảo" in text:
                hello(name)
            elif "hiện tại" in text:
                get_time(text)
            elif "mở" in text:
                if 'mở google và tìm kiếm' in text:
                    open_google_and_search(text)
                elif "." in text:
                    open_website(text)
                else:
                    open_application(text)
            elif "email" in text or "mail" in text or "gmail" in text:
                send_email(text)
            elif "thời tiết" in text:
                current_weather()
            elif "chơi nhạc" in text:
                play_song()
            elif "hình nền" in text:
                change_wallpaper()
            elif "đọc báo" in text:
                read_news()
            elif "định nghĩa" in text:
                tell_me_about()
            else:
                speak("Bạn cần Bot giúp gì ạ?")

Chức năng cuối cùng là kết hợp các chức năng trên lại thành một con trợ lý ảo tiếng việt bằng phương pháp sử dụng các câu lệnh if... elif... else.

Mình sử dụng vòng lặp While True nhằm mục đích cho trợ lý ảo chạy vô hạn để trả lời liên tục các câu hỏi.

Mình gọi hàm get_text() để lấy thông tin về yêu cầu của mình rồi lưu vào biến text.

Nếu text nhận giá trị là 0 tức là máy tính không nghe thấy gì thì vòng lặp sẽ gặp lệnh break và dừng lại.

Còn nếu text là một yêu cầu của người dùng thì mình chia nhỏ ra các trường hợp để thực hiện tất cả các chức năng mình vừa cài đặt ở trên.

Nếu trợ lý ảo nghe thấy "dừng lại" hay "tạm biệt", ... thì chương trình cũng tự động dừng lại.

Ví dụ, trợ lý ảo của mình nghe được yêu cầu

text = "mở google và tìm kiếm một quả táo"

Thì hàm open_google_and_search(text) sẽ được gọi với yêu cầu text để thực hiện chức năng mình yêu cầu. Trong trường hợp này, trợ lý ảo sẽ thực hiện mở ứng dụng Google Chrome rồi vào trang chủ www.google.com và nhập từ khóa "một quả táo" sau đó sẽ trả về các kết quả mà google tìm kiếm được.

Các chức năng còn lại hoạt động một cách tương tự.

Trên đây là toàn bộ nội dung mà mình thực hiện để hoàn thiện một trợ lý ảo tiếng việt. 

Vậy là mình đã thực hiện xong trợ lý ảo tiếng việt chỉ bằng những dòng code Python đơn giản, có thể nói tự mình tạo ra một trợ lý ảo máy tính để bàn hay laptop rất thú vị. Ngoài những tính năng trên, bạn cũng có thể tích hợp thêm nhiều tính năng khác nhau trong trợ lý giọng nói của mình.

Lưu ý: Khi bắt đầu thực hiện chương trình của mình, hãy nói to và rõ ràng để trợ lý ảo tương tác với bạn tốt hơn, nhiều khi trợ lý của bạn không hiểu bạn lắm đâu.

Demo

Source code

Bạn có thể tham khảo Full code của mình ở đây.

Hướng đến tương lai

Trong suốt chiều dài lịch sử phát triển máy tính, giao diện người dùng (User Interface) đang dần trở nên tự nhiên dễ sử dụng hơn. Đầu tiên đó là sự kết hợp của màn hình và bàn phím. Sau đó là chuột và đồ họa giao diện người dùng. Màn hình cảm ứng là bước phát triển vĩ đại trong cuộc cách mạng cải tiến máy tính. Chúng ta dự đoán bước tiếp theo sẽ có thể bao gồm sự kết hợp giữa thực tế ảo, hành vi con người và ra lệnh bằng giọng nói. Rốt cuộc thì việc giao tiếp luôn luôn là dễ dàng và hiệu quả để truyền đạt nội dung hơn là nhập tay một câu lệnh hay biểu mẫu nào đấy.

Càng nhiều người tương tác với các thiết bị kích hoạt bằng giọng nói thì hệ thống càng có nhiều dữ liệu về đặc điểm ngôn ngữ của người dùng. Hệ thống sẽ xác định được xu hướng và mô hình hóa thông tin nhận được. Sau đó, dữ liệu này có thể được sử dụng để xác định sở thích và thị hiều người dùng, đây là một trong những kế hoạch dài hạn để biến ngôi nhà trở nên thông minh hơn. Google và Amazon đang tìm cách tích hợp trí tuệ nhân tạo hỗ trợ giọng nói có khả năng phân tích và phản hồi lại cảm xúc của con người.

Mình hy vọng các bạn đã thích đọc bài viết này. Hãy chia sẻ suy nghĩ, nhận xét của bạn trong phần bình luận.