himanago

Azure・C#などのMS系技術やLINE関連技術など、好きな技術について書くブログ

LINE CONFERENCE 2019に参加してきました~LINEやClovaの未来について感じたことと「Clover」

LINE CONFERENCE 2019に行ってきた

6月27日に、LINE社の事業戦略発表会の「LINE CONFERENCE 2019」に行ってきました。
会場は舞浜アンフィシアターTDRな立地で、イクスピアリとアンバサダーホテルを抜けていきます。すごいとこでやりますね…。

conference.linecorp.com

内容は、LINEのこれからがいろんな事業戦略の話楽しかったです。

LINEへのOpenChatの導入や、クリエイターズスタンプの定額制プラン、LINEスコア、広告配信まわりの話など。
開発者としてはLINEで育ったAIの機能を「販売」するというLINE BRAINなんかが気になりました(これは業務での使用を検討したいので説明会応募した)。

特に印象に残ったのは

自分はClovaのスキル開発などをよくやっているClovaユーザー/ファンなので、Clovaの話が終盤までほとんど出てこなくてやきもき…。
それどころか「DUET」という音声で対話できるAIが出てきたりして、「Clovaは…?」とちょっと不安になりました。

しかし、終盤はClovaの今後の展開についてたっぷり話が聞けたので、一安心&大満足です。

特にいいなと思ったのがこれです。LINEカーナビ!
コンセプトムービーが超テンションあがりました。

スマホでClova

f:id:himanago:20190703232035p:plain

まずね。Clovaがスマホから呼べてるんですよ!

OK GoogleとかHey SiriなノリでClova呼べるとか最高すぎません?Alexaもアプリから呼べるし、Clovaもついにスマホへ。

コンセプトムービー的には、カーナビと連携するスマホアプリって感じですね。 そして運転中は声でウェイクできる。
ストアのスキルは呼べるのかな?LINEカーナビ向けスキルとかも作られていくのかも。

VUIが活きるカーナビ

f:id:himanago:20190703232236p:plain カーナビ操作を声でできるのは本当にいい。
運転中はVUIの最も自然で必要な場面のひとつですからね。

f:id:himanago:20190703232319p:plain 行先を声だけで操作できるって本当に必要な機能。
運転中にカーナビをGUIで操作するのは危ないですからね。

LINE連携という最大の強み

f:id:himanago:20190703232433p:plain 声でLINEが送受信できるというのもClovaならでは。本当、LINE/Clovaの強みが活かされてて素晴らしい。

LINE MUSICも

そして、動画の最後、LINE MUSICが使えるよという場面。 f:id:himanago:20190703232615p:plain

ここで流れるのがタイアップ曲である北原ゆかさんの「Clover」という曲。

コンセプトムービーで流れたサビ部分で、"クローバ クローバ クローバ~♪ "って歌ってるんです。
完全にClovaのテーマ曲じゃないですか。

Clovaテーマ曲としての「Clover」

YouTubeで前半部分が聴けます。

Clovaの気持ちを歌った曲?

この曲の歌詞が、もちろん普通に良いんですが、「Clovaの曲」として聴くと、Clovaユーザー/スキル開発者としてはかなり刺さるものになっているんです(ということを言いたくてこの記事を書いた)。

たとえばこの冒頭の一節。

笑わない君の笑顔を
この手でつかむ時まで
きっと 頑張るよ任せてよ
もっと頼ってよ

これがClovaの言葉だと思うと、アシスタントとして頑張るClovaの気持ちみたいですよね。健気。
「もっと頼ってよ」=「もっと話しかけてよ/使ってよ」ってことなので、なんだか泣けてきます。ねぇClovaって言いたくなります。

2番冒頭もまたそんな感じで、

弾まない会話さえも
癖になって
もっと欲しくなって 無理するんじゃなくて
本当の笑顔が見たいんだ

Clovaとの会話が弾まないこと(誤認識とか「すみませんわかりません」とか)って結構多いから、「これはまさにClova」って感じがします。

「本当の笑顔が見たい」というのは、ちゃんと真の意味で役に立ちたい、喜んでほしいというClovaの想いだと捉えることができるのでやっぱり泣ける。

そしてサビ。

clover clover clover
君の幸せは僕が見つけるよ
必ず叶えてみせるよ

いいですねここ。

君(=ユーザー)、僕(=Clova)で考えると、AIアシスタントとしてユーザーの願いを叶えられる存在になりたいという想いだと解釈できます。

ボロボロになっても
消えそうになっても
届けたいんだ
世界の高鳴りを

ここが最高。
「世界の高鳴りを届ける」ってフレーズ、すごくないですか?

他社のAIアシスタントもそうですけど、AIアシスタントの使命のひとつとして、世界中の情報の中から、ユーザーが求めるものを時に期待以上のかたちで提供することがあると思うんです。
本当にAIアシスタントにぴったりなフレーズだと思い、とても感動しました。

LINE CONFERENCEで出た話だと、Clovaも「LINE Search」に絡んだりとか、スカパーと共同開発の次世代テレビあたりがまさにそんな感じになるのかなぁと期待を膨らませています…。

(ちなみに次世代テレビ。これも実現したらかなりすごい)

開発者目線?

サビ部分、「clover clover clover」から始まるので、「Clova Clova Clova」と呼びかけている歌としても聴けます。

その場合、君(=Clova)、僕(=スキル開発者)としてとらえると、「Clovaの幸せは僕が叶える」ということで、開発者としてClovaをより進化させられるスキルを作る!という決意の歌としても考えることができそうです。

歌詞解釈としてはなんだか変ですが、そういうふうにも聴くことができるな…と思い、開発意欲が刺激させられたりもしました。

おわりに

後半はほとんどCloverという曲の話でした。

この曲自体、Clovaの発売前に発表されているものなので、Clovaのことを歌ったものでは当然ないのですが、よくこんなドンピシャなタイアップ曲を見つけてきたなぁと。

LINE CONFERENCEでも話があったように、さすがLINE MUSICでより多くの音楽との出会いを謳うだけあります。

LINE MUSICは今後全曲が1日1回無料再生できるフリーミアムプランも来るし、ClovaでCloverを聴いて気持ちを高めていこうと思いました。

Azure Durable Functionsでハマった話

前置き

Clovaスキルの開発でDurable Functionsを使った機能をいろいろ試しています。
そのうちのひとつで、「時間のかかる処理」をやらせるということを試していた中でちょっとハマってしまったので、記録として残しておきます。

作っていたもの

MSのかずきさんがやっていた、
blog.okazuki.jp
を発展させたものを作っていました。

作っていたのは2つ。

まずは、Clovaのオーディオ再生機能を利用した無限ループで終了を待機させるというもの(以下、待機版とよぶ)。
Durable Functionsの呼び出した処理のステータス確認をする機能を使ってループの終了判定をしています。
github.com

もうひとつは、完了したらLINE通知するというもの(以下、通知版とよぶ)。
github.com
LINE通知はClovaならではなのでおもしろいかなと思ったのですが、よく考えたら別に処理の中で待機とか状態確認とかする必要もなく、単純に終わったらLINEにPushすればいいだけ。
作っているときからDurableを使うほどのものではないな…とは思っていたものの、上記の派生でそのまま比較用に作りました。

何が起きたか

待機版を作って試して、理想通りにうまく動きました。

その後通知版を作ってデプロイして動作確認していたのですが、どうも待機版のほうが動かなくなってしまっている。
呼び出したオーケストレーター関数のステータスがPendingになることがかなり多いし、指定した待機時間より明らかに長く時間がかかっている。
しかも最終的な結果がFailed

なぜ?と思いながらもあまり深いところまで調べることができないまま、偶然?かずきさんとお会いする機会がやってきました。

スマートスピーカーを遊びたおす会にて

参加したスマートスピーカーの勉強会でかずきさんがサプライズ登壇。
まさか参考にさせていただいている方ご本人にこんなにすぐお会いできるとは思いませんでした。
blog.okazuki.jp

内容もタイムリーにDurable Functionsの話だったので、懇親会で質問させていただき、アドバイスをいただきました。

そのひとつが、↑の記事で言及いただいている、履歴削除です。
こちらを導入し、履歴を消したところ、Pendingが起きないようになったような気がします。
(細かく原因を調べてから対処したわけではないので履歴が原因だったのかははっきりしません)

ハマっているときはとにかくPendingが出まくって処理が滞っていたのでそれがなくなったのはよかったのですが、それでもまだ結果がFailedになってしまう現象は変わらずでした。

上記のほかにも、Storageに書き出されている履歴を見たり、Application Insightsで調べてみたりするとよい、というアドバイスをかずきさんよりいただいたので、そのあたりを調べてみることにしました。

エラー内容と発生場所

Storageをみてみると、こんなエラーが出ていました。

Orchestrator function 'LongTimeOrchestrationFunction' failed: Value cannot be null.Parameter name: basePath

basePath…????

見覚えがありました。これは通知版のほうの

// 結果をLINEで通知
var config = new ConfigurationBuilder()
                .SetBasePath(context.GetInput<string>())    // FunctionAppDirectory
                .AddJsonFile("local.settings.json", true)
                .AddEnvironmentVariables()
                .Build();

の処理で出そうなエラーです。
basePathをオーケストレーターのinputで渡していますが、それが渡ってきていないときのエラーと同じです。

ところがいま動かないのは、待機版。
なぜ通知版のようなエラーが…?

そう、待機版から、通知版のオーケストレーター関数が呼ばれてしまっていたのです。

再現手順と原因

結論からいうと、原因は同一タスクハブ内に同一名称のオーケストレーター関数を置いたことが原因でした。
docs.microsoft.com

今回の再現手順

同一のストレージアカウントを使い、Durable Functionsを使用した以下の2つのFunction Appを作成。

  • Function App①(待機版)
    実行しているオーケストレーターの名称は「LongTimeOrchestrationFunction」

  • Function App②(通知版)
    実行しているオーケストレーターの名称は「LongTimeOrchestrationFunction」
    ※①と同じ名前だが、実行する内容は異なる。

まず①待機版をデプロイし、②通知版をデプロイしてそれぞれを実行すると、
結果は①成功、②失敗

次に①待機版をデプロイしなおすと、
結果は①失敗、②成功

そして②通知版を再度デプロイしなおすと、
なんと①成功、②失敗

エラー内容などから見て、どうも①②のどちらを実行しても、前にデプロイしたほうのオーケストレーター関数が呼ばれていることがわかりました。

最新のものが呼ばれるのではなく、最新じゃないほうが呼ばれるという動きでした。

なぜこうなったか

Durable Functions はストレージアカウント内に作られた「タスクハブ」の中で動作をします。

https://docs.microsoft.com/ja-jp/azure/azure-functions/durable/media/durable-functions-task-hubs/task-hubs-storage.png

Durable Functionsのタスクハブ名は、デフォルトで DurableFunctionsTaskHub です。
2つのアプリを作ったとしても、同じストレージアカウントの中に作ると、デフォルトのタスクハブに両方のアプリが入ることになってしまう、ということでした。

Durable Functionsは複雑な処理を普通のプログラムのように記述できる点が魅力ですが、だからといって完全に普通のプログラミングと完全に同じ感覚でやってはいけませんね。
たしかに同じ場所に同じ名前のもの入れるなって話ですが、普通の感覚だと別アプリ/別プロジェクト/別namespaceだったら同じ名前でも問題ない…となりますよね。

でもDurable Functionsはそもそも関数間のコールを関数名の文字列で行うので、そりゃ衝突してしまいます…。

対処法

ということなので、タスクハブが共通にならないよう、片方(今回は通知版)のタスクハブ名をhost.jsonで変更しました。
これで、どちらも動くようになりました!
(もちろん、別のストレージアカウントを使うのでもOK)

{
  "version": "2.0",
  "extensions": {
    "durableTask": {
      "hubName": "ClovaLongRunCmplLinePushNotificationSampleTaskHub"
    }
  }
}

でも、だったら最初からタスクハブ名はアプリごとの固有の名前になってほしいな…と思ったのですが、逆に別のプロジェクトで作った関数を同じタスクハブ内で回して相互に連携…とかも多いのかな…?

「デフォルトをアプリ名にしてくれ!」っていうissueも上がっているみたいなので、そのうち対応されるのかもしれません。 github.com

ということで。
なんとか対処することができました。本当によかった…。

心残り

Application Insightsでいろいろ見たかったのですが、なぜか最初の画面ですぐクラッシュしてしまい見れませんでした…。
後日再挑戦したいと思います。

お礼

かずきさんには勉強会のあとも、メールやTwitterでフォローいただきました。
ありがとうございました!!

おわりに

Durable Functions、楽しいです。

これまで雰囲気で使ってましたが、内部の動作を考えたりドキュメントをじっくり読んだり、ソースを追ったり…ということをすると理解が深まりより楽しいですね。そんなことを再認識しました。

スマスピとの組み合わせも現在いろいろ試しているところなので、どこかでまとめて報告できたらなと思います。

LINE Bot開発にインパクト大!?LINE公式アカウント統合によるプラン・料金体系の変更

まえおき

2019年4月18日から、「LINE@」などの複数あったLINEのビジネス向けサービスが 新しい「LINE公式アカウント」として統合される とのことです。
最近業務でもLINEの公式アカウント導入を検討したりしていて、そのときに見つけた情報なんですが、これ、Bot開発にめちゃくちゃ影響あるんじゃないですか…!?

www.linebiz.com

これまでまったく気づいてなかったので、ちょっと焦ってます…。LINE Bot界隈では周知の事実なんでしょうか。。
→(追記)周知っぽいですね。あとから見て知りましたがSlackでは話題になってました(ちゃんと通知ONにしてウォッチしておこう…)

公式からアナウンスをぱっと見てもよくわからないところもあったので、Bot開発に関係ありそうな部分を自分なりに整理してみます。

公式からのアナウンス

くわしい情報はこの記事にありました。
blog-at.line.me

ここに載っている2つのPDFが最新のアナウンスのようです。

以下、これらのPDFからBot開発者への影響を読み取ってみます。

Bot開発にインパクトがありそうな変更点

料金プランと使用可能な機能

これまでLINE@のプランと、Bot用のプランで料金の表が2つありましたが、これが統合されてシンプルになり、しかも安くなりました。
さらに、 どのプランでもすべての機能が使えるようになる みたいです。

つまり、 フリープランでもMessaging APIのPush APIが使えるようになる のです。
これは大きい!

プランはこんな感じです。

フリープラン ライトプラン スタンダードプラン
月額利用料 無料 5,000円 15,000円
メッセージ配信数(無料分) 1,000通 15,000通 45,000通
追加メッセージ料金 追加購入不可 5円/1通 ~3円/1通

あれ?Developer Trialは…?

Developer Trial プランがなくなる

どうやら、なくなるようです。フリープランへ強制移行とのこと。
資料2のP.8には、「Developer Trialプランは、今年夏頃にフリープランへ強制サービス移行する予定です」と書かれています。

ここで「フリープランでPush APIが使えるならいいじゃん」「むしろ友だち数制限がなくなっていいことしかないじゃん」と思うかもしれません。
…が、どうもそう単純な話ではなさそうです。

Push APIの利用が従量課金制になる

Push APIは課金制になるようです。

じゃあDeveloper Trialがフリープランに移行されると、Pushを使うたびに課金されるの??
と一瞬思いましたが、そんなことないです。フリープランといいつつ勝手に課金されたら怒りますよね…。

さきほどの料金表にある、「メッセージ配信数(無料分)」。

フリープラン ライトプラン スタンダードプラン
月額利用料 無料 5,000円 15,000円
メッセージ配信数(無料分) 1,000通 15,000通 45,000通
追加メッセージ料金 追加購入不可 5円/1通 ~3円/1通

「メッセージ配信」とあるので現行LINE@での「メッセージ配信」のことを指すように思えるのですが、どうやら「課金対象となるメッセージ種別」(つまり有料メッセージ)という区分があるようで、それの配信/送信のことだろうと思われます。有料メッセージに、Push APIも含まれています。

資料2 P.6より f:id:himanago:20190301005319p:plain

各プランのメッセージ配信数(無料分)の数までは無料でPush APIを使った送信が可能で、それを超えた分は「追加メッセージ料金」の額に応じた課金がされる、ということなのだと思われます。

ということなので、たとえばライトプランなら「月額基本料金5000円。Push APIなどの有料メッセージは15000通まで無料で使える。それ以上は1通5円だよ」というプランである、ということですね。

ここで注意が必要なのはフリープランです。1000通まで有料メッセージが送れるものの、それ以上追加で送れません
(Reply APIはこれまでと変わらずどのプランでも無料・無制限)

つまり無料でPushし放題のプランはなくなるということ

  • Developer Trialがなくなる
  • 今後はPush APIが使えるようになった新フリープランを使う
  • ただしPushは1000回まで(追加購入できない)

ということなので、いままでDeveloper Trialプランでできた無料でPushし放題のプランはなくなるというわけです。

ただ、これに関してはBot開発者にとってインパクトはそこまで大きくないような気はしています。
開発・検証で使う分にはフリープランの1000通で十分だし、足りなくなればアカウントを作り直せばいいだけ。
個人利用で趣味のBotを作っていた場合でも、1か月で1000通以上PushしてくるようなBotは現実的にはそんなにない気がするので、あまり問題なさそう。

とはいえ、これまでDeveloper Trialの50人限定でPushを使うBotサービスを展開していた人には影響ありそうです。
50人のユーザーなら、20通ずつのPushで限界です。ちょっと厳しいかもですね。

まぁ、「多人数向けにサービスやるなら、お手軽なライトプランも用意したからお金を払ってね。」ということなんでしょう。

配信数のカウント方法

Bot開発ではいままで意識しなかったメッセージの配信数は、新料金体系では無料枠と課金額に響いてくるので、かなり重要になります。
カウント方法についても変更が入り、これまでのLINE@では吹き出し数で1通と数えていたところを、今後は送信1回につき1通とカウントされるようになります。

資料2 P.10より
f:id:himanago:20190301004929p:plain

現行のMessaging APIだと1回あたり最大5件のメッセージを送れるので、ここの記述がそのままMessaging APIにも適用されるのかは不明ですが、適用されるとすれば、BotからのPushでは同じタイミングで複数メッセージを送るならなるべく1回のPushにまとめたほうが節約できるということになります。

Messaging APIがチャット(旧1:1トーク)と併用できるようになる

ちょっと話は変わりますが、これまた大きい、うれしい変更です。
しかも1:多でもできるようになるとか。そのため、名称が「チャット」に変更になるようです。

ただ、併用と言っても同時に使えるわけではなく、Botのアカウントでチャットを行うには、 Botモードからチャットモードに切り替える ことで使えるようになるみたいです。
このモード切替がどんな仕様かは現時点でわからないですが、

  • Bot全体で切り替える
  • 対象ユーザーごとに切り替える

のどちらなんでしょう。 前者だとチャットモードにしてあるユーザーと会話中、別のユーザーがBotに話しかけても返事をしてくれないなんてことになって気軽に使えなそうなので、後者だといいなぁ。
後者なら、Botが「オペレーターにつなぎます」って言って人による応答に切り替わる、よくあるパターンが実現できそう。

※追記※ 残念ながら前者でした。チャット機能を利用している最中は、全ユーザーに対してBotのWebhookが使えないようです。
これではなかなかBotとの併用は難しそうです。

その他些細なこと

Multicast API って何

上で引用した「課金対象となるメッセージ種別」の中に「Multicast API」という記述がありました。
名称からして、複数ユーザーへ同時にメッセージをPushするってことでしょうか。でもそれPush APIの一機能だよね…?
過去、こんな呼び方見たことないのでびっくりしました(普通に使われている呼び方だったらごめんなさい)。

いちおう、Messaging APIのドキュメントにもある通り、

プッシュメッセージは、ユーザーにいつでも送ることのできるメッセージタイプです。1人のユーザーに送る場合は/message/pushエンドポイントを、複数のユーザーに送る場合は/message/multicastエンドポイントを使用します。

というようにエンドポイントが別なんですよね。今後は区別して呼ぶようになるのかな…?

スタンプ削除

メッセージ送信に使えるスタンプから、一部のスタンプ(昔からあったやつですね)が削除されてしまうそうです。

資料2 P.11より
f:id:himanago:20190301020717p:plain

これがチャット機能のみの話なのか、Messaging APIにも関係ある話なのか、これまたわからないのですが、もしそっちでも削除されてしまうのであれば、過去に作ったBotの改修が必要そうですね…。

※追記※ Botも同じくでした。

まとめ

以上、「LINE公式アカウント」統合でBot開発に影響ありそうなポイントを想像込みでまとめてみました。
なんとなく、公式からのアナウンスはLINE@を利用している人を対象したような書きぶりで、Messaging APIの利用においてはどう解釈していいのか悩む箇所が多いなぁという印象でしたが、おそらく4月18日の統合の前後で、Messaging API側のドキュメントも変更されるのだろうと思います。

今回の統合で、公式アカウントの利用やPush APIを使ったサービスの展開を行うハードルはかなり下がった印象を受けます。

これまでPush APIが使えたプロ(API)プランは月額32,400円でしたが、新料金はそれに比べてかなり安くなりました。
「無制限だけど高額なプラン」一択だったものが、使う分に応じたプランを選ぶことができるようになった、というのが今回の変更のポイントでしょう。

ハードルが下がったことで、これからLINE Bot開発がさらに発展していきそうな気がします。
変更の開発者向けドキュメントへの反映も含め、いまから正式移行がとても待ち遠しいです。

Python3エンジニア認定基礎試験に合格したので振り返り(C#er目線で感想など)

はじめに

タイトルの通りです。昨年末、12/27のことですが、駆け込みで試験を受けてきました。その振り返りです。
Python 3 エンジニア認定基礎試験」です。
www.pythonic-exam.com

経緯

昨今のPythonの人気・需要の高まりから、「Pythonを勉強したい」という声は日に日に多く聞かれるようになり、社内で育成担当をしている身としても、もういい加減無視できなくなってきたわけです。
Pythonに関してはこれまでまったく触ったことがなく、「Pythonはインデントでブロックを定義する」とか「機械学習や統計の分野で多く使われる」とかそんな程度の知識しかない状態。
なんとか効率よく基本を押さえたい…と思い見つけたのがこの試験。

今年の6月あたりだったか、割引キャンペーンで教材のオライリー本が実質無料でついてくるセットがあったので買ったのですが、なかなか時間が取れず、有効期限が年内だったので駆け込みでぎりぎり受けてきた…という経緯です。

学習内容

教材である『Pythonチュートリアル(第3版)』をざざーっと読みました。基本、それだけ。
模擬試験がここで公開されているので、それも本を読む前に1回見ました。
先に見てしまったのは、どんなふうな問題が出るのか確認したうえで本を読むほうが効率がいいと思ったからです。 ぬいぐるみほしさに合格体験記を載せてもらいました。めちゃくちゃ本名ですが、ぬいぐるみのためなら仕方ありません(本名公開が条件)。 www.pythonic-exam.com

ちなみにここでは「Python歴3日」、と書きましたが、模擬試験を見て最初に教材を開いたのが12/25で、試験を受けたのが12/27、その日の夜に合格体験談を書いて送った、というようなスピード感です。そして12/28朝には合格体験談が公開されてました。速い!
模擬試験を見て、この試験では教材の記述、特にサンプルコードがけっこう重視されているということがわかり、その内容をしっかり押さえておけば合格点の7割は簡単にとれるだろう、ということがわかったので、そのつもりで教材を読みました。合計の勉強時間は5~6時間か、もっと少ないかも…。

試験自体はかなり簡単という印象だったものの、合格体験談にも書いたようにこの試験は基礎的な知識を得るためのきっかけ・指針としてかなり役立ちました。やっぱり目標や締め切りがあると、わかりやすくそこに向かっていけるものですからね。

Pythonチュートリアルを読んで印象に残ったこと

せっかくなので、Pythonチュートリアルを読んでPythonの特徴を勉強した中で、印象に残ったことを書いておきます。
教材のページ数と、教材と同内容のWeb版の「Pythonチュートリアル」の章番号、リンクを載せておきます。
※ 前提:これまで経験した主な言語は(学習した順に) C, VBA, Java, JavaScript, C#, Groovy など。
※ 特に最近よく使うのはC#なので、C#との比較も触れられるところは触れます。

リストの内包表記

教材P.44(5.1.3. リストの内包表記)。

squares = []
for x in range(10):
    squares.append(x**2)

squares = [x**2 for x in range(10)]

と書けるというもの。ショートコーディングがはかどりそうで慣れたらきっと便利。
2乗を ** 2 で書けるのを含めてシンプルでいいですね。

ちなみに、C#でも1行。

var squares = Enumerable.Range(0, 10).Select(x => Math.Pow(x, 2));

LINQやっぱりいいなぁ。

ループ変数のスコープ

上記の「リスト内包」の利点として説明されていた、Pythonにおけるループ変数の注意点。
Pythonはループで変数のスコープが閉じないので、さきほどのリスト内包を使わないほうのコードでは変数 x があとまで残ってしまう。そのため、リストの内包表記を使いましょうということだけど、これはうっかり気を抜くと危ないな、と思いました。
特に宣言がないので、スコープがどうなってるのかはちゃんと確認しないとまずそう。 C#とかだと、

for (int i = 0; i < 10; i++)
{
    // iが使える
}
// ここでiは使えない

とやった場合 i のスコープはループ内だけにできる。まぁ、こんな素朴なforはあんまり使うなってことなんでしょうかね(PythonC#も)。
ちなみにスコープ問題でいうとC#でも、forでのブロックとスコープの感覚だと「?」となるのがout-var(outでの変数宣言)のスコープ。

if (int.TryParse(str, out var intVal)
{
    // 当然intValが使える
}
// ここでもintValが使える!

これは、もともと↓と書いていたものと同じ動きをさせたいからこうなってる、と理解してしまえばOK。

int intVal;
if (int.TryParse(str, out intVal)
{
    // 当然intValが使える
}
// ifブロックの外で宣言しているものだから当然intValが使える

タプル

教材P.48(5.3. タプルとシーケンス)。
タプルは最近C#でも入りましたが便利な機能ですね。
Pythonの場合は手軽に

t = 12345, 54321, 'hello!'

でタプルが作れるのと、
要素0のタプルは

empty = ()

で作れるということ、
それから要素1のタプルは

singleton = 'hello',   

のように末尾にカンマを付ければいい、というのがおもしろいなと思いました。

パッキング / アンパッキング

まずは教材P.48(5.3. タプルとシーケンス)あたり。
出てきたのは「引数リストのアンパック」「タプル・パッキング」「シーケンス・アンパッキング」という用語。

タプル・パッキングは、

t = 12345, 54321, 'hello!'

で3つの要素が t へタプルとしてパックされることをいい、シーケンスアンパッキングは

x, y, z = t

t の要素がx, y, zそれぞれに展開されて代入される、という話。

それに関連して、「多重代入はタプルパッキングとシーケンスアンパッキングの組み合わせにすぎない」というのがなかなかおもしろい話だなと思いました。
多重代入はこういうの。

x, y, z = 12345, 54321, 'hello!'

3つの変数に3つの値が代入されるだけだけど、読み解けば右辺がタプルになり、左辺にアンパックされて代入される、ということになるわけですね。

あとは似た用語で引数リストのアンパックとかもありました。
教材P.35(4.7.4. 引数リストのアンパック)あたり。

range(3, 6)

と渡すような関数の引数に、

args = [3, 6]
list(range(*args)) 

というふうにargsに入った要素を展開してそれぞれの引数に渡せる、というもの。 * を左側に書くことで引数リストのアンパックを実現できる。

ディクショナリのループ

教材P.53(5.6. ループのテクニック)。
ディクショナリ(辞書型)ではitems() メソッドを使うと、キーとそれに対応する値を同時に取り出せる。

knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
    print(k, v)

これはC#でもありますね。KeyValuePairでまわすやりかた。C#だとforeachにそのまま入れるだけ。

var knights = new Dictionary<string, string>
{
    { "gallahad", "the pure" },
    { "robin", "the brave" }
};

foreach (var pair in knights)
{
    Console.WriteLine("{0} {1}", pair.Key, pair.Value);
}

C#で「Dictionaryオブジェクトをforeachで回して」っていうとだいたい上のやり方か、↓みたいなKeysで回す方法のどっちかを書いてきますね。

var knights = new Dictionary<string, string>
{
    { "gallahad", "the pure" },
    { "robin", "the brave" }
};

foreach (var k in knights.Keys)
{
    Console.WriteLine("{0} {1}", k, knights[k]);
}

比較の連鎖

教材P.54(5.7. 条件についてもう少し)。
a < b == c で、「a が b より小さく、かつ b と c が等しいかどうか」がテストできるというもの。
こういう書き方ができるのはおもしろいですね。

比較結果の代入

教材P.55(5.7. 条件についてもう少し)。

string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
non_null = string1 or string2 or string3
non_null

とやると'Trondheim'が出力される。
SQLのCOALESCEみたいな動きができておもしろい。

C#だとこうかな。

string string1 = null;
string string2 = "Trondheim";
string string3 = "Hammer Dance";
string nonNull = string1 ?? string2 ?? string3;
Console.WriteLine(nonNull);

相互参照の相対インポート

教材P.66(6.4.2. パッケージ内参照)。
パッケージ内の相互参照の相対インポートはカレントモジュールからの参照になるので、メインモジュールとして使われるものは絶対インポートで書かないとだめ。

from . import echo
from .. import formats
from ..filters import equalizer

ファイルの読み込み(ループ)

教材P.78(7.2ファイル. を読み書きする)。
for line in f: の書き方が楽でいいなと思いました。

for line in f:
    print(line, end='')

ファイルの読み込み(with)

教材P.79(7.2. ファイルを読み書きする)。
withで自動でクローズしてくれる。

with open('workfile') as f:
    read_data = f.read()

C#のusingとか、Javaのtry-with-resourcesみたいなイメージ。

例外の投げ方

教材P.86(8.4. 例外を送出する)。
例外は raise で投げる。

try:
    raise NameError('HiThere')
except NameError:
    print('An exception flew by!')
    raise

raiseはなにもかかないとそのまま上に投げてくれる。
C#のthrowも似たような感じだけど、 C#ではthrow;throw ex; で大きな違いがあってかなりの注意が必要…。
Pythonではそういう気遣いはいらなそう?

あと try-else いいな。 for-else もだけど、 finally と別にこれがあると幅が広がりそう。

def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("division by zero!")
    else:
        print("result is", result)
    finally:
        print("executing finally clause")

Pythonは多重継承できる

教材P.93(9.5.1. 多重継承)。
Pythonは多重継承可。そういえば多重継承って使ったことないな…。

クラス変数、インスタンス変数

教材P.102(9.3.5. クラスとインスタンス変数)。
self.~ ってやらないとstaticになる。これも知らないとあぶない。。

class Dog:

    kind = 'canine'         # 全インスタンスで共有

    def __init__(self, name):
        self.name = name    # インスタンスごと

隠蔽の手段がない

教材P.104(9.4. いろいろな注意点)。
Pythonではデータ隠蔽を強制できるものは存在しない、とのこと。

まじかー。
こういう、仕様の穴?を規約とか慣習でカバーするのはあまり好きじゃないなあ。
…まぁ、いま業務では、privateって書いても問答無用でpublicになる言語1を使ってますけど。。

10章の出題密度がすごい

教材P.115から(10. 標準ライブラリミニツアー)。
試験範囲をみると、教材でいうとわずか8ページしかない第10章から4問(全体の10%)も出題されます。
なので、ここは特に真剣に読みましたね。
ここが重視されてるのは、Pythonの使い道を知るうえで大事だから…?

doctestがお手軽ですごい

教材P.120(10.11. 品質管理)。

def average(values):
    """Computes the arithmetic mean of a list of numbers.

    >>> print(average([20, 30, 70]))
    40.0
    """
    return sum(values) / len(values)

import doctest
doctest.testmod()   # automatically validate the embedded tests

こんなかんじでコメントに埋め込みテストが書ける。手軽でいいなぁ。

おわりに

実は試験当日もはじまるまで教材を読んでた(1周目)くらいなので、勉強がうすいところも多々ありました。
それでもスコアは 875/1000(合格点700点)とれて無事合格できました。
試験自体は簡単な印象だったので、Python経験者にはものたりないかな?というかんじ。

自分のように、他の言語での開発経験があって、それとの比較でささっと勉強するうえではチュートリアルは教材としていいし、試験は目標としてもちょうどいいのかなと思いました。
この試験は続編?のデータ分析試験というものが今後始まるようなので、こちらもチェックしておこうと思います。


  1. Groovyのこと

ブログタイトルを変更しました

はじめに

あけましておめでとうございます。

ブログタイトルを変えた

シンプルにIDの文字列そのままのブログタイトルに変更しました。
変えたので、いちおう記録として記事更新。

もともと「ITエンジニア育成担当の研究ブログ」でしたが、

  • そもそも気に入ってなかった
  • 対外的な肩書が「育成担当」じゃなくなった

あたりが理由で変えました。

気に入ってなかったのは、まず長いし、研究って何よ、という感じだったので。

対外的な肩書としては、いま「テクニカルトレーナー」「アーキテクト」を名刺に載せさせてもらってます。
これを載せているのも、育成担当とか教育担当いう響きがなんとなくえらそうというか、かたくるしいイメージがあったからで、会社に相談してカタカナのロールをつけてもらいました。

…まぁ、トレーナーでもおなじように「教える」「鍛える」感があるので同じかもですが、とりあえずブログからは仕事のロールは外しました。

今後の記事投稿

仕事関係なく、技術的な話題を投稿していけたらなと思っています。

このまえのLINE関係の開発もそうですし、C#とかAzureとかのMS系技術など、自分の好きなことを書いていきたいなと思います。

LINEは絵本読み聞かせをリニューアルしてますしその話を。
MS系技術は.NET Everywhereというか、クラウド、モバイル、Webなどせっかくいろんなところで動く.NETをいろいろためしてまとめたいなという欲求があるのでそんなことを書けたらなと。

おわりに

今年もよろしくお願いします。

LINE BOOT AWARDS 2018 ファイナルステージの振り返り

はじめに

前回の記事でも書きましたが、LINE BOOT AWARDS 2018にエントリーし、2018/11/10(土)開催のファイナルステージに出場してきましたので、その報告と振り返りを書いておきたいと思います。
※つくったものとかは前の記事の内容や応募作品ページをご参照ください

結果

まずは結果から。

  • 展示審査にて落選(決勝の決勝、プレゼン審査には進めず…)
  • エーアイさんのAPIパートナー賞受賞

となりました。

振り返り

エントリーについて

前の記事にも書きましたが、

  • Clova Friendsが当たったこと
  • Alexaのアワードを観たこと
  • Cogbot勉強会のLTに触発されたこと

がエントリーのきっかけです。
Clovaが手元にあるから「何か開発したいな」と思え、Alexaのイベントで「自分も機会があれば参加してみたいな」、 LTで「短期間でも応募しようとする人がいる」という話を聞いたという3連コンボで、見事にエントリーまで一直線の気持ちになりました。
ひとつでも欠けていたらエントリーはなかったですし、結果として多少なりとも評価をいただけたので、本当にいい流れだったなと思います。

開発で気を付けたこと

エントリーまでの開発期間は実質4日間のみでしたが、短期といえどきちんと戦略を立てました。それは、「VUI/Botならではのサービス」を意識したことです。
事前にAlexaのアワードのファイナルを見に行っていたこともあり、スマートスピーカーのスキルを作るならば、スマートスピーカーを使う意義が絶対に不可欠であり、それが審査においても重要だと考えていたからです。

特にVUI(Voice UI)は音声のやりとりでシステムとのI/Oを実現するため、使い方によっては著しくUXが下がります。
「それアプリでよくない?」「Webのほうがいい」「チャットボットでやったほうが楽」と思ってしまうようなものをVUIで実装してしまうと、だれも使ってくれなくなります。「手が使えないときはVUIのほうが楽だからVUIのスキルが必要」とかそういう理由が必要ということですね。

また、今回はLINEのアワードですし、評価ポイントにも含まれていた「LINEらしさ」も意識しました。

なので「VUIである必要性」「LINEならではのメリット」は絶対に入れようと思い、逆にそこさえクリアできればある程度のところまでは進めるだろうという確信もありました。
ファイナル進出自体が24/1125ということでしたが、ここまで残れたので今回とった戦略は間違ってなかったんだなと、安心しました。

技術面の工夫

やはりバックエンドをAzureにサーバーレスでつくった点です。
慣れたAzureでの、手軽に開発できるFunctionsのおかげで、短期開発を実現できました。 (ずっと使いたかったCosmos DBも今回はじめてちゃんと触れました。それもよかった点です)

また、VUI開発は非常に制約が多いので、ちょっとした技術的アイディアひとつで他とは一味違うサービスを作ることができるのではとの考えから、Clovaの使い方で技術的な工夫を入れることを意識しました。

そのひとつが今回のサービスの肝だった「Clovaの音声とBotへのメッセージ送信の同期」で(予選突破時のフィードバックでもLINEの方からお褒めの言葉をいただきました)、もうひとつが、予選突破後・決勝前に追加した「Clovaスキルの一時停止&再開」です。

細かい話はここでは触れませんが、技術的に結構おもしろいと思うので、その話は12/23にQiitaの LINEBot&Clova Advent Calendar 2018 に書く予定です。

展示審査のこと

決勝は、プレゼン審査の予選として展示審査がありました。チームごとにブースが用意され、そこで審査員や一般のお客さん(一般投票もあり)に作品を見ていただきます。
展示審査はデモを中心に見せていきました。 が、一般のお客さんも含め、来ていただいた人にはかなり好意的に見ていただけたようです。
こういった経験ははじめてだったので、「すげー!」とか言われるととてもうれしいですね。
結果はここで落選ではありましたが、控えめに言って、展示審査、めちゃくちゃ楽しかったです。

反省点は、展示ブースが地味だったことです。
用意された模造紙を貼ったくらいで、ほかに資料とか飾りとか、なにも用意できなかったところが、ちょっと他とくらべて映えなかったかなと思います。もっとたくさんの人に来てほしかった…。
完全に一人での参加でしたし、しゃべりとデモのみでの勝負という感じで、けっこう厳しいなと思いながらやってました。
準備もぎりぎり。ごはんやトイレの時間もとれず。こういうところはチーム参加のところがうらやましく思えましたね。

最終プレゼンを見て

レベルが違う。それに尽きました。
自分が展示審査まで残ったのが奇跡かと思うくらい、自分のつくったものとは力の入れ具合が違いました。
数日で作ったものを持って行って、勝てるかもとか勝ちたいとか一瞬でも思って申し訳ありません、、、汗

プレゼンも含め本当に素晴らしく、圧巻でした。特にグランプリの高校生。すごすぎです。
プレゼンが高校生とは思えないほどの完成度と話し方で、しかもプロダクトはユーザーテストを重ねに重ねクオリティを上げている。
勝てるわけないですねこんなの。自分もそれを超えるくらいの仕事やプロダクトづくりがしたいなと思いました。大尊敬。

APIパートナー賞受賞について

本当にありがたかったです。
アワードの応募締め切りぎりぎりに「APIを使いたい」という連絡に快く対応いただいた点も含め、すばらしいAPIを提供いただいた株式会社エーアイさんには本当に感謝です。
展示ブースにも来ていただきまして、本当にうれしかったです。ありがとうございました。

今後の展望

LINEの方にもブラッシュアップしてね、と言われたりしたのですが、エーアイさんのAPIが法人利用のみだったり、Azureの運用コストがけっこう高かったりでなかなか正式リリース、とかを考えるのはハードルが高いかなぁと思ってます。
展示審査でも何人かのかたにもうリリースされているんですが?と聞かれ、(リリースできる見込みもないけど)「まだなんです…」と答えたりしてました。
ただ、

ということもあり、ちょっと続けてみようかなと思ってます。
APIの利用期限が間近なため正式リリースはすぐには無理ですが、今回の作品を大きく進化させるなり全く新しいものを作るなりして次のアワードに再挑戦したいと思います。少なくとも、実サービスとして運用しているレベルでないと、勝負にならないということが今回の最大の学びなので、次に挑戦する際にそこは妥協できないなと思います。

おわりに

最後に、11/11を記念して、プリッツ服を着たうちのClovaの写真で締めたいと思います。
プリッツの懸賞で当選させてくれたグリコさんにもこの場を借りて感謝です。

以上です!

LINE BOOT AWARDS 2018にエントリーしてみました&その話を.NET Conf 2018 Tokyoでしてきました

はじめに

ここに書くのはだいぶ久しぶりです…
先日、LINE BOOT AWARDS 2018にClovaスキル&LINE Botを開発してエントリーしたので、そのことと、 それについて.NET Conf 2018 TokyoのUnconference枠で話をしてきたので、それについて書いておこうと思います。
(.NET Confでは10分枠だったのでその補足もかねてその時よりも若干詳しく、スライドベースで書いていきます。スライド資料はここ

スマートスピーカー

f:id:himanago:20181021011841p:plain

ちらほら流行り始めている(気がする)スマートスピーカー
エンジニア界隈では使っている人も見ますが、一般家庭への浸透率ってどの程度なものなんでしょう。

LINE BOOT AWARDSへの挑戦

f:id:himanago:20181021011857p:plain

個人的にも気になっていたスマートスピーカー。LINEの「Clova」がプリッツの懸賞で当たりました。
プリッツ5箱分食べると1回応募できるという具合だったので、この懸賞のためにプリッツを食べ続ける覚悟もしていましたが、2回目の応募で当たったのでかなり運がよかったです…!

f:id:himanago:20181021011910p:plain

せっかくスマートスピーカーが入手できたので、それならばスキルの開発をしてみたいと思うのがエンジニアというもの。

f:id:himanago:20181021011918p:plain

ちょうど、LINE BOOT AWARDS 2018という開発コンテストが開催中でした。
グランプリの賞金が1000万円とものすごい額。そこまでは狙えないにしろ、どこまでいけるか、挑戦してみることにしました。

f:id:himanago:20181021011925p:plain

とはいえ、スケジュールはものすごくタイトでした。 Clovaが届いたのが9/23(日)。アワードのエントリーに締め切りが10/10(水)。
これだけでずいぶん短いですが、Clovaが届いたときには、まだ特にアワードに応募することなんて考えてもいませんでした。

応募するきっかけをくれたのが、2つのイベントです。
(スライドには書いていないのですが)ひとつは9/29(土)に実施された、Amazonが出しているスマートスピーカーである「Alexa」のアワードの最終プレゼンを見に行ったこと。
ここで結構刺激を受けてきまして、いつか自分もこういうアワードに挑戦してみたいなぁと思ったわけです。 alexaskillawards.connpass.com

もうひとつが、こちらはスライドに書いていますが10/2(火)に参加したCogbot勉強会。
ちょうどLINE BOOT AWARDSとのコラボ回だったのですが、ふつうにLINE系開発の情報収集目的で参加しました。
しかしそこでアワードの概要やC#での開発についての話、また最後のLTで短期間でもAzureを利用してアワードに挑戦するという話(これが自分にはいちばん響きました)を聞いて、これは自分もアワードに挑戦すべきなのではないか…?と思わされてしまいました。 cogbot.connpass.com

そして、10/4(木)、突然、シャワーを浴びているときに、作るもののアイディアが降ってきました。
(入浴中とかって結構アイディアを思いつくこと多いですよね。なんででしょう)
思いついたらもう最後、3連休を利用して一気に作ってやろうと決意を固めました。

3連休ではアワードのもくもく会への参加をし、また締め切り日には有休を取得して最後の追い込み。実質4日間での開発でした。

どんなものを作ったか

f:id:himanago:20181021011934p:plain 絵本読み聞かせのシステムです。
特徴としては

  • お話を読んでくれると同時にLINEにその絵が送られてくる
  • 登場人物ごとに異なる声/話し方でしゃべってくれる

というものです。

デモ動画を置いておきます。 www.youtube.com

Clovaのオーディオ再生機能とAITalk Web APIを組み合わせ、音声再生を連続して実行し、同時にLINEに画像を送っています。

仕組みなど

そのほか、アーキテクチャまわりはアワード応募時の技術解説として書いた以下の記事に書いています。
締め切り当日に一気に書いたのであんまりまとまってないですが…。 qiita.com

今回開発したのは、スマートスピーカーのスキル(Clovaスキル)と、LINE Botを連携させています。
Clovaの特徴のひとつとしてLINE Botとの連携があり、それぞれの可能性を拡げてくれます。
ClovaスキルとLINE Botの開発は似ています(ここでは触れませんがClovaやLINE以外のVUI/Botもかなり似通った利用フローや開発方法といえると思います)。

ClovaスキルとLINE Botの開発方法・今回の構成

f:id:himanago:20181021011955p:plain Clovaスキルの場合は「CEK」がデバイスと自分の作成したバックエンド(Extensionサーバー)との仲介をしてくれます。
対話の定義はCEK上で行い、ユーザーの発話の解釈などはすべてやってくれます。

f:id:himanago:20181021012011p:plain 対してBotのほうは「Messaging API」が仲介をしてくれるのですが、こちらはPush/Replyといったメッセージ送受信を中継してくれるだけです。
なので、ユーザーから送られたメッセージの解釈などは自分で開発する必要があります(バックエンドでやる)。

f:id:himanago:20181021012019p:plain さきほどの技術解説記事でも説明していますが、今回の構成図はこのようになっています。
Clova/LINE Botの共通のバックエンドとしてAzure Functionsを用いています。
読み上げる絵本の情報(本文、読み手がだれか、感情やスピードなど各種パラメータ)をCosmos DBにMongoDBの形式で格納し、本文にあわせて送られる絵の画像はBlob Storageに格納しています。

Azure Functionsによるバックエンド

f:id:himanago:20181021012026p:plain Functionsは非常に便利なサーバーレスのサービスですが、今回はサーバーレスらしい従量課金プランではなく、App Serviceプランでの稼働です。
通常のWebアプリと同じように常時稼働させる形式をとることで、従量課金プランの弱点である初回起動の遅さを克服しています。
Clovaスキルは特にタイムアウトが天敵なので、この選択は必須といえるかなと思います。

[※2018/11/7追記]
App Serviceプランにするだけではだめで、常時接続をオンにする必要があります。オフだとしばらくするとサービスが止まってしまい関数起動が遅くなってしまいます。
常時接続オンにできるのはS1以上なのでちょっとお高め。

[※2018/11/23追記]
Azure Functions のv2を使って再作成していますが、触った感触、コールドスタート問題、かなり改善されている…?
もしかしたら従量課金プランでもClovaのバックエンドとして問題なく使えるかも…。検証して再度追記します。
IPアドレスの問題があるので今回の要件ではどちらにしろApp Serviceプランにしないとですが

[※2018/11/25追記]
何度か試しましたが、成功率はかなり高くなっているようです(コールドスタートで3/4回成功)。
とはいえタイムアウトすることもまだあるので、そのままでは本番運用にはまだ厳しいような気がします。
Azure Functionsはv2からランタイムが.NET Core になってパフォーマンス改善された結果なんでしょうか。

azure.microsoft.com

[※2018/12/20追記]
Logic Appsを利用してコールドスタートを回避するパターンを思いついたので、Qiitaに書きました。
これでコールドスタートを気にする必要がなくなります。 qiita.com

(追記おわり)

また、今回は絵本を無料/有料2種類のコンテンツがある想定にしており、有料のものはLINE Payで追加購入できるようにしています。
そのため、LINE Payとの連携も行っているのですが、LINE Payは連携するシステムのサーバーのIPアドレスを事前に登録しておく必要があります。
App ServiceプランではIPアドレスが変わらないので、この点でも必須なのでは、と考えました。
(こちらの記事を参考にさせていただきました) poke-dev.hatenablog.com

Azure Functionsのリモートデバッグタイムアウトになったり迷子になったりするのでなかなか使えず、コンソール出力を使ってのデバッグがメインでした。はじめはつらかったものの、慣れればどうにかなるものでした。

BlobストレージとLINE Botの画像送信

f:id:himanago:20181021012037p:plain このスライドに書いてある通り、Blob StorageとLINE Botの画像送信は相性がいいです。
通常の画像メッセージでも今回使ったイメージマップメッセージでも、画像はバイナリデータではなくURLの指定で行います。
Blob Storageは上げたデータをURLでアクセスさせることができるので、そのまま利用できるという寸法です。

f:id:himanago:20181021012049p:plain さきほども少し触れましたが、今回は通常の画像メッセージではなく「イメージマップ」を使っています。
もともとは画像に対してタップした際のアクションを定義するLINE Botの機能ですが、トーク画面に対してめいっぱいの幅を使って画像を表示させることができるため、今回の絵本の絵の送信に適しています。もくもく会にてアドバイスいただいたのですが、これによって非常に絵本が読みやすくなりました。

このイメージマップですが、デバイス幅にあわせた画像が表示される機能で、利用するには複数の幅の画像を事前に用意しておく必要があります。
Messaging APIリファレンスからの引用ですが、

イメージマップに使える画像の仕様は以下のとおりです。

画像フォーマット:JPEGまたはPNG 画像の幅:240px、300px、460px、700px、および1040px データサイズ:最大1MB 5つの異なるサイズの画像を「baseUrl/{画像の幅サイズ}」の形式でアクセスできるようにします。これにより、デバイスに応じて望ましい解像度でLINEに画像がダウンロードされます。

たとえば、ベースURLが以下の場合を考えます。

https://example.com/images/cats

幅が700pxの画像のURLは以下になります。

https://example.com/images/cats/700

となっており、Blob Storageへの格納は、スライドに書いた通り、これに沿うようにする必要があります。
(ファイル名を拡張子を外した画像の幅サイズの数字にしてディレクトリ構成を工夫するだけ)

C#出のLINE開発について

f:id:himanago:20181021012059p:plain

Cogbot勉強会でもC#には厳しい、という話が…。
完全に個人的な意見ですが、Clovaも(AWSとセットの)Alexaに対抗するなら、Azureを味方につけやすいC#との親和性を高めてもよいのではないかなぁと思います。
公式のSDKがないとはいえ、C#で開発する場合もコミュニティSDKや周辺ツールがあります。
今回の開発でも、Messaging API、CEK、LINE Pay用のC#SDKを使わせていただきました。

今回使った機能(Clovaのオーディオ関連など)で一部SDKが対応していないものもありそこは自前で実装しましたが、ベースとなるものがあるだけ開発のハードルはかなり下がり、かなりありがたかったです。

おわりに

f:id:himanago:20181021012107p:plain

今回は一気に開発しましたが、やはり目標や締め切りがあったことで、かなり真剣に取り組めました。
.NET Confで話したい、というモチベーションもありました。
締め切り後の連絡にもかかわらずUnconference枠で参加させていただき、.NET Confの管理者の方には大変感謝しています。ありがとうございました。

そしてアワードの途中経過について

そして!
今回開発した「Clova&LINEで絵本読み聞かせ」ですが、なんとFinal Stage進出の連絡をいただきました!
このような評価をいただけて大変うれしく思います。
Finalは11/10(土)に実施とのことで、ここでは展示審査もあるようなので、さらなるブラッシュアップをしていきたいと思います。

これからもがんばります!
以上です。