學習資源
Learning Center — 學習資源
gTTS函式庫修正(11/30更新)
使用google的gTTS函式庫是很方便的文字轉語音函式庫,原理是基於網路爬蟲相關技術,到google的翻譯網頁傳要求請google轉成語音,再把語音下載下來。
但google回傳的東西往往會突然變更格式--這時候這種函式庫就需要更新解析的方法。
因此我們設立本專頁,專門處理gTTS修正的方法。
————————————————————————————————————–
11/29後更新,請將以下程式碼放在你有用到gTTS的程式碼之前:
import calendar import time import math import re import requests from gtts import gTTS from gtts_token.gtts_token import Token def _patch_faulty_function(self): if self.token_key is not None: return self.token_key timestamp = calendar.timegm(time.gmtime()) hours = int(math.floor(timestamp / 3600)) results = requests.get("https://translate.google.com/") tkk_expr = re.search("(tkk:*?'\d{2,}.\d{3,}')", results.text).group(1) tkk = re.search("(\d{5,}.\d{6,})", tkk_expr).group(1) a , b = tkk.split('.') result = str(hours) + "." + str(int(a) + int(b)) self.token_key = result return result Token._get_token_key = _patch_faulty_function
AI導論(一)
何謂人工智慧?
早期歷史
圖靈測試
達特茅斯會議
Python IDLE簡介
我們介紹過Python的hello程式,而今天我們就要從IDLE開始。
當我們下載並安裝完Python之後,程式列會出現Python的資料夾。
至於一般的程式碼編輯模式,又稱為editor,看起來會像這樣:
在editor編寫完成的程式會回到shell執行,而在shell內執行也是可以的。
另外,IDLE也可以調整顯示的字形或大小。
設定方法都一樣,在Options底下的Configure IDLE。
在這裡就能調整Python的顯示方式了。
Python內也帶有說明文件,可以在這裡看到更詳細的說明。
飆的Python小學堂:This-Python之禪(一)
我們上次提到了import這個方法跟Python背後的設計哲學,這一次我們就要來瞭解Python的設計哲學。
(上次的文章連結)
首先一樣,打開我們的Python IDLE(或是其他開發環境)。
輸入import this。
我們在這幾次的介紹中,都採用不同的環境。這也說明了Python跨平台的能力。
執行後,會出現一篇文章。
我們下面提供了一些解釋:
The Zen of Python, by Tim Peters
Python之禪,Tim Peters作於1999年
Beautiful is better than ugly.
優美勝於醜陋。
Python,以編寫優美的程式碼為目標。
Explicit is better than implicit.
明確勝於晦澀。
而優美的程式碼應該簡單明瞭。
Simple is better than complex.
簡單勝於複雜。
優美的程式碼應該編寫簡單,不該有複雜的關係。
Complex is better than complicated.
複雜勝於繁複。
即使需要複雜的關係,也不該有繁複的介面。
Flat is better than nested.
平坦勝於築巢。
優美的程式碼不該有過多的內嵌結構。
Sparse is better than dense.
分散勝於密集。
優美的程式碼寧願分散程序,也不該擠在一行。
Readability counts.
可讀性很重要。
優美的程式碼,一定要易讀,加上註解吧。
Special cases aren’t special enough to break the rules.
特例也不該違背這些規則,
Although practicality beats purity.
即使實用性打敗了純粹性。
這些規則應當遵守,就算傷害了程式碼的實用性。
Errors should never pass silently.
錯誤不該被無聲地忽略,
Unless explicitly silenced.
除非你如此期望。
除非需要,否則要捕捉所有的錯誤。
In the face of ambiguity, refuse the temptation to guess.
面對雙關的語意時,拒絕猜測的誘惑。
There should be one– and preferably only one –obvious way to do it.
用明顯的方法來完成一件事,而且最好只有一種。
不要去猜想完成程序的方式,只需要用一種明顯的解法。
Although that way may not be obvious at first unless you’re Dutch.
這並不是件容易的事,誰叫你不是荷蘭人呢?
找出一種明顯的解法,在一開始並不容易,畢竟我們都不是Python之父。
Now is better than never.
把握現在勝於停滯不前,
Although never is often better than *right* now.
即使停滯不前勝於立刻動手。
先考慮過程式是好的,但必須要動手寫。
If the implementation is hard to explain, it’s a bad idea.
如果實作難以被說明,那就是個壞主意。
If the implementation is easy to explain, it may be a good idea.
如果實作能輕鬆說明,那可能是個好主意。
能夠被說明的程式才是好程式。
Namespaces are one honking great idea — let’s do more of those!
命名空間是個絕妙的點子,我們應當多加利用!
善用python的命名空間。
上面的「禪」中有幾個有趣的地方:
- Right now一般可以解釋為「現在」,而這裡卻也能做為「正確」解釋。
「即使不做出程式,勝於找出並完成有『正確』作法的程式;作出程式仍勝於不動手做。」
所謂的「正確」作法,可能是指為了心中的完美而加入不必要又難以維護的功能;又或者是為了盡早發佈而留下糟糕的結構。這兩者在開發實務上都是正確的,但也都會帶來麻煩,還不如不做。這是一個雙關句,然而「禪」中卻要我們停止猜測雙關,找出簡單的解釋:現在。
- Dutch是荷蘭人的代稱,用來指Python之父吉多·范·羅蘇姆(Guido van Rossum)。
當我們打開this的原始檔時,可以發現更有趣的地方,不過這就留待下次討論了。
飆的Python小學堂:每個人的第一課Hello World
之前我們提過了Python的誕生,而這一次會介紹的是所有程式語言的第一步:
「Hello World」。
「Hello World」,據說最早(備註1)是出現在B語言的示範教學程式。以下是他的範例:
main(){ extrn a,b,c; putchar(a); putchar(b); putchar(c); putchar('!*n'); } a 'hell'; b 'o, w'; c 'orld';
#include <stdio.h> main( ){ printf("hello, world\n"); }
自此之後,幾乎所有程式設計師的第一堂課都是「Hello World」,而後所開發的程式語言也會使用「Hello World」作為第一個範例。
至於為什麼是這句話呢?起源至今難以確認(備註2),不過倒是留下一些浪漫的傳說。
那在這裡要先介紹Python的重要概念:import。
如同C需要#include,Python藉由import其它的模組來增加他可以操作的函式。
而在這裡,我們import了hello。
import __hello__
print (‘hello, world’)
不過import __hello__這個方法就跟Python背後的設計哲學有關了,我們之後會再討論。
「In interview with Forbes India, he said his memory’s dim. “What I do remember is that I had seen a cartoon that showed an egg and a chick and the chick was saying, “Hello, World.”」 ( from The History of ‘Hello, World’ )
飆的Python小學堂:Python的起源
Respeaker mic array v2教學
Respeaker mic array V2(後簡稱array V2)就如上圖所示,是一片圓形的麥克風陣列擴展版。由於以USB通訊的關係,他能接到各種支援USB的裝置上作為聲音類感測器使用。
目前我們測試兩個連接方案──Windows系統和樹莓派,其中比較推薦使用樹莓派進行連接:
樹莓派:
插上之後請輸入以下指令安裝必要的函式庫
sudo apt-get update(可省略)
sudo pip3 install pyusb click
windows:
請至http://zadig.akeo.ie/ 下載安裝用的小程式,開啟後選擇SEEED DFU,以及在Driver上選擇libusb-win32
到這步驟完成,array V2至少已經有麥克風的功能了,各位可以利用一些錄音軟體或者python的錄音函式庫來測試一下狀況:
控制LED燈與DOA
相信各位都有注意到,array V2上有一圈LED燈。接上電之後他內建的DOA程式就開始執行(晶片組內),上面的亮藍色燈光便會一直追著聲音的方向。在說明DOA之前,我們先說明如何控制上面的LED燈光,使他能像很多語音助理一樣透過燈號表示各種狀態。
首先我們要先得到相關的函式庫,請至https://github.com/respeaker/pixel_ring/tree/master/pixel_ring中,下載usb_pixel_ring_v2.py這個檔案,以及至https://github.com/respeaker/usb_4_mic_array中,下載tuning.py,並將這兩個檔案放置在你開發python程式的資料夾中。
接著請依照以下程式碼引用函式庫,並定義裝置:
from tuning import Tuning
from usb_pixel_ring_v2 import PixelRing
import usb.core
import usb.util
dev = usb.core.find(idVendor=0x2886, idProduct=0x0018)
if dev:
pixel_ring = PixelRing(dev)
Mic_tuning = Tuning(dev)
接著,只要使用以下方法就可以控制LED陣列:
pixel_ring.wakeup(角度數值)
就可以像他預設執行的DOA一樣,在特定角度以亮藍燈,其餘角度深藍燈的方式標出角度
pixel_ring.think()
pixel_ring.speak()
這邊的兩個函式則是像語音助理的燈號,分別為兩種LED變化模式表達思考跟回答
pixel_ring.mono()
可以讓整個陣列變成同色,接收參數為0xRRGGBB
pixel_ring.set_color_palette()
這個函式可以調整think、wakeup等雙色顯示的雙色是哪兩色
比方說,pixel_ring.set_color_palette(0xf00000, 0x0000f0)就會將它變成紅+藍
對於DOA而言,前面的參數會是指示方向的顏色
pixel_ring.off()
這個函式可以關閉LED陣列。
pixel_ring.trace()
開啟DOA模式,注意這個函式實測時他會變更wakeup的角度,不推薦直接使用而是以底下的DOA方法。
以上所有指令在樹莓派下都需要sudo權限,但這樣會產生一些問題──比方說ALSA系統在sudo模式下會無法正常放出聲音這點,作為智慧音箱或智慧機器人的配件來說是個有點致命的問題。
但不代表沒辦法解決:
至於DOA的取得,則是利用Mic_tuning.direction()取得即時的DOA數據,也就是說,利用一個while迴圈包覆pixel_ring.wakeup(Mic_tuning.direction())這行程式碼,就會跟pixel_ring.trace()達成類似的效果。
而錄音的部分,請參考seeed原廠文件,或是參加研習的老師有取得我們的示範程式碼,則可以直接引用record_wave子程式或是Ex_2_1的main即可。
若需要更詳細資料請參考seeed wiki:http://wiki.seeedstudio.com/ReSpeaker_Mic_Array_v2.0/
包含有接入其他語音助理的方法、其他的STT方法等等。
LineBot開源教學
第一章、 前言
在現在這時代,最多人使用的通訊軟體就是LINE了。我們想做一些服務或展示,比起生一個APP,使用網頁或者其他軟體內嵌服務可能更快速。而AI能應用的東西很廣,如果有一個可以結合我們上述提到的那些小系統的方案,顯然是個不錯的展示平台。
而我們想到的就是LINE了,LINE提供了一個開發者介面,讓開發者可以將LINE連結自己的API來做一些有趣的應用,而其中一個就是聊天機器人,許多的明星或者公司會利用這個技術做類似客服的LINE帳號。這類機器人通常會對特定的語句做出反應,高階一點的則是語句有些許變化也能容忍──這剛好是我們前面NLP部分的應用。而LINE也有接收聲音、圖片的事件,可以結合智慧音箱和影像辨識。
我們利用Heroku提供的雲端API執行平台,連結Line開發者帳號來嘗試製作一個對話機器人Kotori(吉祥物教阿的日文名字)。
第二章、 前置準備
要將我們設計的機器人架在LINE上面得先做一點準備,第一步,我們先申請一個Heroku帳號,從官方網站https://www.heroku.com/點選右上角的SignUp註冊。
註冊完成後,登入點選右上角的New->Create New App,建立一個自己喜歡的App專案(請記住專案的名稱)。完成之後依以下網址下載Heroku CLI並安裝:https://devcenter.heroku.com/articles/heroku-cli。
第二步,安裝git:https://git-scm.com/downloads。
第三步:申請Line的開發者專案,詳情可以參考https://developers.line.me/en/docs/messaging-api/getting-started/。
以上,先期的準備大致完成,接著進入程式碼撰寫的部分。由於程式本身要在雲端執行,故main裡面和一般的程式寫法有一點差異。另外本程式基於line-bot-sdk開發而成。
第三章、 文字訊息事件
在linebot之中有許多的事件類型,當你需要針對某個類型事件作處理的時候就要先宣告它的接收體,@handler.add幫助各位建立各種不同的接收體,以下我們將為各位說明幾個比較常用的大類
文字訊息是LINE上面最常見的訊息,大致上就是純文字所構成,偶爾可能混一些符號:
這類訊息我們可以使用
@handler.add(MessageEvent, message=TextMessage)
來宣告接收體,並在handle_message(event)中對訊息做處理。處理LINE訊息時,第一個要記起來的物件是event.message.text,如字面翻譯,就是當有人傳訊息給這個機器人時訊息的主體。如上圖,我傳送給教阿後,教阿透過event.message.text取得我傳送的訊息(”C4cat是什麼”,以及”?”),並分析後回應。
而第二個重要的物件是event.reply_token,這個物件決定你收到這條訊息要回應的對象。event.reply_token是一次性的,即使是同一個人,第二次傳訊過來你收到的event.reply_token也不會一樣。
而文字訊息分析我們前面提過幾個方法,比方說全句對應型或者是斷詞後對特定詞作反應:
第1節. 全句符合
包含了全句式的回應(智慧居家管家系統、智慧講桌系統)以及占卜系統(占卜球),占卜球因為強制要求日期格式,劃分至全句符合的區塊。具體內容前面章節皆有說明,不再贅述。
第2節. 關鍵詞符合
包含股票查詢系統和WikiQA系統,股票查詢系統利用twstock函式庫取得資料,要求有股票關鍵字,以及上市代號或名稱。
twstock在本系統主要利用它的幾個功能:即時交易價查詢、最高最低點查詢(前二皆為twstock.realtime.get取得)以及四大買賣點分析(BestFourPoint)。
WikiQA系統則需要有5W(什麼、誰、哪裡之類)疑問詞,以及最好有介系詞(是、在之類)來幫助教阿利用wikipedia函式庫尋找答案並回答
第3節. 子字串符合
本機器人已經上線一段時間了,觀察使用者使用紀錄以及程式歷程,訊息無法正確回應的一大原因是斷詞系統錯誤,造成以關鍵詞為準的分析無法觸發。
依照此現象,一個想法是將詞的概念去除,單純以子字串作為觸發來做為最後防線。字串物件的find方法可以達成這件事情。
子字串方法由於不受斷詞正確率影響,通常做為檢查的最後手段,注意它雖然不受斷詞干擾,但容易被誤觸發──比方說以上面例子,萬一用戶說的是”這個公式老師沒有教阿!”這種句子就會誤觸發,雖然正常來說作為語尾助詞「阿」應該是選「啊」這個字,但很遺憾的是,其實LINE用戶在打字時選字是很隨便的。
第四章、 貼圖訊息事件
在LINE上第二多的應該算是貼圖訊息,某些人在好友群組甚至可以光依靠貼圖就完成對話和意見交流。因此我們也會稍微對貼圖訊息做處理,但LineBot本身只能回應前4組Line內建的普通貼圖。
第一件事情當然是建立貼圖的接收器,和文字訊息類似,使用@handler.add(MessageEvent, message=StickerMessage)宣告接收器,再從之後的handle_sticker_message(event)編寫對應。
貼圖在LINE之中是以兩組號碼代表,第一組號碼是該貼圖屬於那個系列的貼圖,在event物件中為event.message.package_id,第二組號碼是該貼圖在系列中的第幾張,為event.message.sticker_id物件。因為版權問題,此處不方便截圖說明建立的貼圖,但可以藉由自行發送貼圖給Line機器人,再請它回傳的方式得到這些號碼。
第五章、 PostBack事件
PostBack事件是一種比較特殊的事件,用戶不會因為打字或傳送什麼東西而觸發它,比較常見的觸發方法是用了LINE提供的內建選單,像底下這種:
這種清單當你按下按鈕,有可能是傳回PostBack到LINE Bot的伺服器,LINE Bot再根據PostBack做回應,類似我們一般程式傳變數的感覺。我們將在回應部分說明如何生出這種選單式的LINE訊息。
而要接收PostBack使用的是@handler.add(PostbackEvent),一樣使用後面的handle_postback(event)定義接收到的反應。
我們的系統中,PostBack基本上只對列表或按鈕做出反應,而其中包含了兩個列表:說明文件和IoT列表。原理相同都是分析PostBack傳回的變數。
第六章、 回應
回應部分雖然分為四片,但實質上就只是更動一些物件及變數,主要方法並沒有變更,故合併一起說明。
回應的基本函式都是基於以下函式:
line_bot_api.reply_message(event.reply_token, message)
差別只在message的種類差別。
第1節. 文字訊息
TextSendMessage(text=message)
最常見的回應,單純回一個文字字串回去:
第2節. 貼圖訊息
StickerSendMessage(
package_id=event.message.package_id,
sticker_id=event.message.sticker_id)
參考前面有關貼圖事件,發送一樣也是兩個id組成。前面也提到過只能使用前四組普通貼圖,很無聊就不示範了
第3節. 圖形訊息
message = ImageSendMessage(
original_content_url=’https://i.imgur.com/Hn6lBtg.jpg’,
preview_image_url=’https://i.imgur.com/Hn6lBtg.jpg’)
圖形訊息必須從url傳送,且格式限制為jpg。程式接受自己製作縮圖,縮圖和原圖的大小有其限制(請參考line-sdk)。
預防各種版權問題,這邊不呈現運作結果。
第4節. Template訊息
Template訊息可以視為是Line的互動功能,按下列表會有特定反應,也可以讓點列表的用戶說出特定訊息:
在電腦版上不能顯示列表時就是顯示替代文字:
其他部分對應程式碼大略可以推出是哪部分的參數,比較麻煩的是actions部分。actions有許多種類,PostbackTemplateAction可以在點選之後傳一個Postback,觸發我們前面提到的Postback事件。另外也有MessageTemplateAction事件,點選之後使用者會發出選單指定的訊息──再使用一般文字訊息事件做回應。
第七章、 發佈
最後就是架到雲端執行的部分。如果各位還記得我們開始寫程式前的步驟(申請帳號等等),那些都是為了現在所做的前期工作。
開啟聊天機器人python檔放置之資料夾,並在路徑列輸入cmd:
就會直接開啟命令提示字元,在底下依序輸入指令:
heroku login
git config –global user.name 你的名字
git config –global user.email 你的信箱
git init
heroku git:remote -a 前面步驟你為APP取的專案名稱
git add .
git commit -m “任意名字” 以後更新程式時下最後這三行藍字指令即可
git push heroku master
上傳完成,可以到Line添加你的開發者專案產生的機器人好友,開始測試。