OSC (オープンソースカンファレンス) 2018 北海道 ~ ハンズオンの補足

今回のハンズオンで触れたの補足記事になります。参加者向けとなります。

https://osc2018-kitaazu.azurewebsites.net/

の下部にある share からスライドを見ていただくとわかるかもしれません。

[slideshare id=104957665&doc=20180707kitaazuv5-180709124212]

要約

今回の実装したところは以下のようになります。
Basic C# テンプレートを元に、特定のアクティビティ (メッセージ)で、添付ファイル (Attachment Class)があるときだけ、Bot Frameworkが提供してくれているイメージのURLを引数として、Custom Vision – Custom Vision Prediction 2.0 – PredictImageUrl を呼び出し、結果を文字列にして返す。

Bot Service

ボットの実装をぐっと楽にしてくれるものになります。
https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-3.0

Bot Framework Bot Builder (https://github.com/Microsoft/BotBuilder)

また、ハンズオン中にこれはどういうメンバーを持っているか?といったような質問がありました。リファレンスとして参照するものは、. NET SDK のものを見ていただければよいかと思います。(下のリンク)

https://docs.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-overview?view=azure-bot-service-3.0

C# スクリプト

今回のハンズオンでは、.NET を扱えて、Visual Studio が不要な C# スクリプト(.csx)をベースに、API呼び出しを追加しました。この記事(++C++; // 未確認飛行 C – C#スクリプト実行)を参考にするとわかりやすいかもしれません。 #r で必要とするアセンブリの参照を追加すること。 #load で追加した csx ファイルを読み込んでいます。それ以外は、スクリプトではない、C#と全く同じになります。

Visual Studio を使って、C#として同じこともできますので、Visual Studio をお持ちの方はそちらのほうが、ぐっと楽になります。

Custom Vision プレビュー

ボットの判断能力となるものになります。概要としては、こちらを
これは、画像と分類を教えてあげることで勉強してくれます。
成果として、画像を分類してくれます。教えられたそれぞれの分類に対して、0 ~ 1.00のスコアが与えられます。展示・ハンズオン用の「ラムネ判別機」は、ラムネ、ボトル、チュアブル、飲み物、フローズン、などの分類を教えました。
これは、ブラウザで作ることができるため、今回のハンズオンにぴったりでした。また、受け取った画像は、学習データとして蓄積させていくことができます。もちろん、学習データとして蓄積しないようにもできます。
ラムネ判別機の画像は100程度からスタートして、展示中も学習を続けて130枚程度になりました。

App Service

Web Chat を配置したものになります。概要としては、こちらを
見ていただくとわかりますが、本来はアプリケーションを動作させるものです。
が、今回はオンラインでの編集機能を使いたいためこれを利用しました。
App Service Editor

Azure Functions

ボットの本体の部分です。
しかし、これは、Bot Service (Functions Bot)の一部となります。
概要はこちら

まとめ

というわけで、実はこのハンズオンに参加された方、30分弱で大きく3つ以上のサービスに触れていました。
目的としては、動くものができる!としていましたので、それぞれの使い方を触れる時間はありませんでした。
なお、プレビューの機能も含まれていることは注意してください。
もしどこかの機能に興味があれば、ぜひ、チャレンジしてみてください!
それでは!

Azure Functions Runtime

Build 2017
の中でひそかに更新されたBlogがあった。

Introducing Azure Functions Runtime preview

なんというか、Runtime?ってどういうことだろうと思って開いてみたところ。

Azure Functionをオンプレミスでも動かせるようにできるものらしい。

 

最低要件とか

細かいドキュメントは、「Azure Functions Runtime Overview」あたりから

Windows Server 2016 or Windows 10 Creators Update with access to a SQL Server instance.

Windows Server 2016 または、Windows 10 Creators Updateとなっている。
このあたり、Windows Containerに依存している部分があるためと考えられそうだ。また、SQL Serverへの接続も必要と。

機能

このRuntimeが持つ機能は大きく二つ

「Azure Functions Management Role」
ポータルのような管理する機能を提供する

「Azure Functions Worker Role」
FunctionをWindows Containerに展開して実行する

ドキュメントでは、VisualStudio 2017からの直接デプロイもできるとはなっている。

ダウンロードは、Blog記事より下部にある

How do I get started?

Please download the Azure Functions Runtime installer.

からできた。

ちょっとだけ

以下、Windows Server 2016 へのインストールと、インストール後の画面
SQL Serverへの接続を構成しない限り動作しないようだ。
インストール後は再起動が必要となった。

Microsoft TranslatorのAPIを使うに当たって・・

Azureの認証が必要となるために、単純な呼び出しでは利用できない様子。

https://github.com/MicrosoftTranslator/GetAzureToken

ここのソースが参考になった。

Functionsで利用する場合は

https://github.com/MicrosoftTranslator/GetAzureToken/blob/master/AzureAuthToken.cs

Tokenの取得が必要となるため、上記を参考にするとよさそうだ。
リクエストがTokenの取得と、取得したTokenを渡すAPI呼び出しになっていることに注意が必要。

 

 

Visual Studio Tools for Azure Functions の修正版

Azure Functions 向けの拡張機能を入れたところで、.NET Coreのプロジェクトがだめになるっていうものに対する修正版が出てたようです。

https://blogs.msdn.microsoft.com/webdev/2016/12/01/visual-studio-tools-for-azure-functions/

Update 12-6-16 @5:00 PM: Updated version of the tools are available that fix the ability to open .NET Core projects with Azure Functions tools installed. Install the updated version over your old version to fix the issue, there is no need to uninstall the previous copy.

というわけで、入れてみたところ・・・

2016-12-10

インストール完了。
プロジェクトの新規作成で、ASP.NET Coreのプロジェクトテンプレートから作成したみところ、無事にできました。

2016-12-10-2

良かった良かったー

風邪っぽい・・・?VS2015の拡張機能

Microsoft Azure2 Advent Calendar 2016 の6日目の記事です。
.NET Core Advent Calendarの6日目の記事です。


2016-12-10追記
Visual Studio Tools for Azure Functions の修正版が出たようで、解消しました。

両方空いていたのと、両方を好きな人はこれから私と悲しい気持ちを味わう前に楽しくなってもらえればという願いを込めて書きました。
相変わらず、しょうもないネタなのですが・・・お時間あればお付き合いください。
Visual Studio 2015の話になります。

季節の変わり目で、咳が止まらず目が覚めて何気なく.NET Coreプロジェクトを作ろうとしたら・・・

2016-12-05-1

2016-12-05-2

あ、、、あれれ?コンソールだめなら、Webは・・・?

2016-12-05-3

2016-12-05-4

 

うーむ、VS2017 RCと共存してるからかなぁ・・・とか思いつつ、既存の.NET Coreアプリを開いてみたところ・・・

=====================
2016/12/04 5:47:00
Recoverable
System.Exception: ディスク上のプロジェクトファイルの検出中に次のエラーが発生しました。Could not load file or assembly 'Microsoft.VisualStudio.ProjectSystem.DotNet, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. 指定されたファイルが見つかりません。。
   at Microsoft.VisualStudio.ProjectSystem.DotNet.Common.FileMirroring.SourceItemsInMemoryProject.<InitializeFromDiskAsync>d__54.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.DotNet.Common.FileMirroring.SourceItemsInMemoryProject.<Creator>d__52.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.VisualStudio.ProjectSystem.UnconfiguredProjectImpl.AutoLoadMethodStateMachine.<<StartExecution>b__6_0>d.MoveNext()
===================

どうやら風邪がうつったようです

いやいやそんなわけはなく・・・いろいろ調べてみたところ・・・
どうやら、Visual Studio Tools for Azure Funtionsの問題として認識されてるよというところまでは見つけました。

https://blogs.msdn.microsoft.com/webdev/2016/12/01/visual-studio-tools-for-azure-functions/

Warning: We have discovered that installing this Preview breaks the ability to create or open .NET Core projects in Visual Studio 2015.  We are currently investigating, and will make a fix available as soon as it is ready.  In the meantime, do not install this on any machines where you plan to work with .NET Core projects.

.NET Coreプロジェクトを扱うことができなくなってしまうということで、対策をがんばってるそうです。

そう・・・思えばFunctionsへの浮気心が、.NET Coreとの距離を近づけたのかもしれない・・・

そうか、浮気といえば・・・電話番号は二つ・・・つまり、マシンをもう一つAzureで作ればいいじゃない!
この発想には賛否両論あると思いますが…

というわけで、デプロイ!!
で、さりげなく機能紹介。

2016-12-05-5

というわけで、デプロイできた仮想マシンのブレードを開くと、
Automation スクリプトというのがあるのでそこを選択すると出てくるものです。
これは、ご存知の方多いとは思いますが、ARMというテンプレートで、この仮想マシンと同じものを再現するために使える逆起しの設計書みたいな状態です。
ただ、エラーが出てる通り、この仮想マシンに設定した自動シャットダウンと、仮想マシン拡張の診断機能は含まれていません。なので100%ではないですが、このJSONを1から作るよりも、一度作ってみたものをもとにJSON取得して、修正。
ARMとしてテンプレートデプロイをするというシナリオが近道のような気がします。

 

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "virtualMachines_vm20161206_adminPassword": {
            "defaultValue": null,
            "type": "SecureString"
        },
        "virtualMachines_vm20161206_name": {
            "defaultValue": "vm20161206",
            "type": "String"
        },
        "networkInterfaces_vm20161206128_name": {
            "defaultValue": "vm20161206128",
            "type": "String"
        },
        "networkSecurityGroups_vm20161206_nsg_name": {
            "defaultValue": "vm20161206-nsg",
            "type": "String"
        },
        "publicIPAddresses_vm20161206_ip_name": {
            "defaultValue": "vm20161206-ip",
            "type": "String"
        },
        "virtualNetworks_vm20161206_vnet_name": {
            "defaultValue": "vm20161206-vnet",
            "type": "String"
        },
        "storageAccounts_vm20161206diag122_name": {
            "defaultValue": "vm20161206diag122",
            "type": "String"
        },
        "storageAccounts_vm20161206disks246_name": {
            "defaultValue": "vm20161206disks246",
            "type": "String"
        }
    },
    "variables": {},
    "resources": [
        {
            "comments": "リソース '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/vm20161206/providers/Microsoft.Compute/virtualMachines/vm20161206' から一般化されました。",
            "type": "Microsoft.Compute/virtualMachines",
            "name": "[parameters('virtualMachines_vm20161206_name')]",
            "apiVersion": "2015-06-15",
            "location": "japaneast",
            "properties": {
                "hardwareProfile": {
                    "vmSize": "Standard_F8s"
                },
                "storageProfile": {
                    "imageReference": {
                        "publisher": "MicrosoftVisualStudio",
                        "offer": "VisualStudio",
                        "sku": "VS-2015-Ent-VSU3-AzureSDK-29-Win10-N",
                        "version": "latest"
                    },
                    "osDisk": {
                        "name": "[parameters('virtualMachines_vm20161206_name')]",
                        "createOption": "FromImage",
                        "vhd": {
                            "uri": "[concat('https', '://', parameters('storageAccounts_vm20161206disks246_name'), '.blob.core.windows.net', concat('/vhds/', parameters('virtualMachines_vm20161206_name'),'20161204060340.vhd'))]"
                        },
                        "caching": "ReadWrite"
                    },
                    "dataDisks": []
                },
                "osProfile": {
                    "computerName": "[parameters('virtualMachines_vm20161206_name')]",
                    "adminUsername": "watashi.kanrisha",
                    "windowsConfiguration": {
                        "provisionVMAgent": true,
                        "enableAutomaticUpdates": true
                    },
                    "secrets": [],
                    "adminPassword": "[parameters('virtualMachines_vm20161206_adminPassword')]"
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaces_vm20161206128_name'))]"
                        }
                    ]
                }
            },
            "resources": [],
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccounts_vm20161206disks246_name'))]",
                "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaces_vm20161206128_name'))]"
            ]
        },
        {
            "comments": "リソース '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/vm20161206/providers/Microsoft.Network/networkInterfaces/vm20161206128' から一般化されました。",
            "type": "Microsoft.Network/networkInterfaces",
            "name": "[parameters('networkInterfaces_vm20161206128_name')]",
            "apiVersion": "2016-03-30",
            "location": "japaneast",
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAddress": "10.0.0.4",
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_vm20161206_ip_name'))]"
                            },
                            "subnet": {
                                "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworks_vm20161206_vnet_name')), '/subnets/default')]"
                            }
                        }
                    }
                ],
                "dnsSettings": {
                    "dnsServers": []
                },
                "enableIPForwarding": false,
                "networkSecurityGroup": {
                    "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_vm20161206_nsg_name'))]"
                }
            },
            "resources": [],
            "dependsOn": [
                "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_vm20161206_ip_name'))]",
                "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworks_vm20161206_vnet_name'))]",
                "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroups_vm20161206_nsg_name'))]"
            ]
        },
        {
            "comments": "リソース '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/vm20161206/providers/Microsoft.Network/networkSecurityGroups/vm20161206-nsg' から一般化されました。",
            "type": "Microsoft.Network/networkSecurityGroups",
            "name": "[parameters('networkSecurityGroups_vm20161206_nsg_name')]",
            "apiVersion": "2016-03-30",
            "location": "japaneast",
            "properties": {
                "securityRules": [
                    {
                        "name": "default-allow-rdp",
                        "properties": {
                            "protocol": "TCP",
                            "sourcePortRange": "*",
                            "destinationPortRange": "3389",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 1000,
                            "direction": "Inbound"
                        }
                    }
                ]
            },
            "resources": [],
            "dependsOn": []
        },
        {
            "comments": "リソース '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/vm20161206/providers/Microsoft.Network/publicIPAddresses/vm20161206-ip' から一般化されました。",
            "type": "Microsoft.Network/publicIPAddresses",
            "name": "[parameters('publicIPAddresses_vm20161206_ip_name')]",
            "apiVersion": "2016-03-30",
            "location": "japaneast",
            "properties": {
                "publicIPAllocationMethod": "Dynamic",
                "idleTimeoutInMinutes": 4
            },
            "resources": [],
            "dependsOn": []
        },
        {
            "comments": "リソース '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/vm20161206/providers/Microsoft.Network/virtualNetworks/vm20161206-vnet' から一般化されました。",
            "type": "Microsoft.Network/virtualNetworks",
            "name": "[parameters('virtualNetworks_vm20161206_vnet_name')]",
            "apiVersion": "2016-03-30",
            "location": "japaneast",
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "10.0.0.0/24"
                    ]
                },
                "subnets": [
                    {
                        "name": "default",
                        "properties": {
                            "addressPrefix": "10.0.0.0/24"
                        }
                    }
                ]
            },
            "resources": [],
            "dependsOn": []
        },
        {
            "comments": "リソース '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/vm20161206/providers/Microsoft.Storage/storageAccounts/vm20161206diag122' から一般化されました。",
            "type": "Microsoft.Storage/storageAccounts",
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "kind": "Storage",
            "name": "[parameters('storageAccounts_vm20161206diag122_name')]",
            "apiVersion": "2016-01-01",
            "location": "japaneast",
            "tags": {},
            "properties": {},
            "resources": [],
            "dependsOn": []
        },
        {
            "comments": "リソース '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/vm20161206/providers/Microsoft.Storage/storageAccounts/vm20161206disks246' から一般化されました。",
            "type": "Microsoft.Storage/storageAccounts",
            "sku": {
                "name": "Premium_LRS",
                "tier": "Premium"
            },
            "kind": "Storage",
            "name": "[parameters('storageAccounts_vm20161206disks246_name')]",
            "apiVersion": "2016-01-01",
            "location": "japaneast",
            "tags": {},
            "properties": {},
            "resources": [],
            "dependsOn": []
        }
    ]
}

このテンプレートを見て、何をデプロイしたか分かった人はすごい!

で、話は戻りまして・・・こうしてどちらかの環境用のマシンを分けておくと、何かと便利なので、あまり使ってないサブスクリプションを持ってる人とかはどうでしょうか?

まとめ

こんな状態でもツールをリリースして、たたかれる覚悟でも一歩でも進もうとしていることに私はすごいことなんじゃないかと思っています。

enjoy azure !
enjoy .NET Core !