Thursday, 28 February 2019

Cortana Hosting Off Azure

Yesterday I decided to start moving my skills off Azure. Messaging is still handled by bot service, but the bot lives elsewhere. This is in no way a comment on Azure App Services. It has everything to do with me paying for a GoDaddy VM and I want to have everything in one place. Sure, its not scalable in its current form, but who cares when you have insignificant TPS.

The things that Azure App Services give you for free... a SSL certificate so you can use HTTPS (that you must for bots messaging) and a preconfigured IIS web server that is always managed (because its a container). But its the free tier restrictions... you can't set your web app and skill to "always on", so you get unloaded every 20 minutes. That means your skill will timeout when invoked, and that's a really crappy experience. I wonder how many people actually try a skill twice after it craters the first time? You also can't use web jobs to tickle the endpoint.

So, first step, install Apache. In hindsight, I should have paid GoDaddy the managed fee (that was reasonable, $50 or so) to configure Apache - with their bundled 509 Cert. What a pain... I don't miss running my own web servers.

Why run Apache? Because you want the web server to take care of the SSL for you. It is a lot of work to build a bot supporting HTTPS without a web server. So the trick is, get Apache to handle the secure request, and then tunnel it via proxy to a port without SSL.My node.js bots - they don't know anything about SSL.

How to have all my bots run in one place? Multiple proxies that redirect based on different paths. Instead of https://myserver/api/messages, we now have http://myserver/mybot/api/messages. And the latter redirects to different local ports via a proxy to http://localhost:3000/mybot/api/messages.

Then you have a choice of registering the Cortana skill via a Bot Channel Registration (the right way), or swap out the endpoint after creating a Web App Bot. Why would you want to do the latter? Updated: Because there is a bug in Bot Channel Registrations. Do not use Bot Channel Registration until the glitch is fixed. Create a web app bot, configure the Cortana channel, and then change the bots end point (and tombstone the Azure app service).

I will add my web.conf here when I have time. It is magic that I'll never remember. And the next trick is running node as a daemon. My VM is running Ubuntu server - so
bash -c 'nohup node app &>/dev/null & jobs -p %1'

Tuesday, 22 January 2019

Cortana Availability


Ever notice that it can take two invocations to a Cortana skill to get it to work on Azure?

This is because resources are unloaded if they are idle for 20 minutes.  The first invocation; you need to wait for the resources (web app service) to load. You can change this in basic and standard service plans by changing the app service’s settings to “Always On”. 

But if you are using a free tier, what do you do? Set up an availability test that pings your web server every 15 minutes via an Azure web job or Azure monitor. 
But be aware: keeping resources live can consume your credits!

Saturday, 19 January 2019

Two months later...

Hello! It seems I have not posted in almost two months. Life always gets interesting. My in-laws and oldest daughter visited. Then there was the flu, head colds, and administrative issues... so my tinkering slowed down to nothing. I've barely even managed to explore my Christmas present: a Playstation Classic.

I have lots of topics I could write about, because between work and personal enlightenment, I've touched on a lot. I am more than happy to take direction on what to write about - because often times I tell myself no one reads what I write so there is no hurry in getting things down.

Cortana

I did get to push out work related samples on building against bot framework v4. It is different enough to cause people grief in upgrading, and v4 is slightly more complicated and less documented than v3. I've been thinking about writing a guide or giving some sample "search and replace" scripts to help. But that also seems too close to work to use my own time. So expect to see more Cortana stuff here:


Unfortunately I hit a policy blocker on publishing skills - that has seen all my Cortana pet projects delayed or shelved.  However, I am happy that Safety Moments averages 6 requests a day on Windows.  Thanks to those who are using it!

Google Actions

I am happy about how Art of War is doing.  It gets about 60 users a week and sends about 200 messages. When I have time, I intend to get Colossal Cave launched on Google.  It was so close to being done on Cortana, and the server is written in Java and platform agnostic.

Tuesday, 13 November 2018

Actions On Google


Well, after some frustration, I have a chat bot working on Google Actions. But now that the frustration is over, the flood gate is open!

The first challenge; using my existing code. Safety Moments, my first skill, uses json files. I needed to upload them to a Google bucket. And then, for whatever reason, the promise loading these files took > 5s to execute (a download of a file <1K), so my conversation was over before my content loaded. There was no synchronous hack I found. Then, I figured I'd load them on invocation of the cloud function. It worked for a while, and then it just stopped working. No idea why. I received connection resets downloading the files. So second solution? Embed all the json in the webhook itself.  (What is a webhook?  It is the node code that fulfills the request to do something after LU digestion.)

The second challenge; competing SDKs. It looks like Dialogflow and Actions on Google were inseparable. But they are. And if you follow the code examples for Dialogflow (that I did, because it looked like a really cool tool compared to LUIS), you will discover mismatches between how Actions On Google (for assistants) implements bot behavior. So... I couldn't immediately figure out what was Dialogflow SDK (agent.add) and what was Actions SDK (conversation.ask). It manifested itself in my conversation data not persisting and me scratching my head.

The third challenge; moving targets.  The Google tech is migrating from V1 to V2, and Dialogflow seems not to have caught up to Actions. Part of my confusion was out-of-the-box webhooks were V1.  Dialogflow examples integrating with Actions was V1. But V2 is pretty much were all Actions documentation and examples sit.  Ugh. Now I know what to look for.

What I Like


  • International availability.
  • Excellent TTS for female and male voice.
  • Dialogflow (the tool) and how it builds intents (utterances) and actions (entities).
  • You can build dev without charge.
  • Events get fired when media stops playing.


What I Dislike


  • You can't have a Card before a SimpleResponse.  I use cards as banners.
  • Cards can have one button, though the JSON supports multiple buttons.  Why?
  • You can't segment long conversations naturally. You have to make them turn based and granular. Not so good for my experiments.That will, in my opinion, seriously cripple enterprise capability.
  • Your action will not pass certification if it does not end the dialog on a question. This forces dialogs to be very transactional.


References

Actions on Google and Dialogflow.



Useful documentation



Sunday, 26 August 2018

Enabling Colossal Cave on Cortana

I am back at it. The first step was getting a version of Colossal Cave running. I found Eric Raymond's official public port:

  • https://gitlab.com/esr/open-adventure
  • http://www.catb.org/~esr/open-adventure/

I compiled it for Windows (using MinGW-64) and made a few changes (removing unix curses and flushing input appropriately so it worked inside a pipe.)

The next step was putting together a Cortana dialog-based shell calling an external process to invoke it. The fun here is the node.js event loop. Reading and writing to the pipe did not happen when I expected, so the dialog was out of sync until I forced the Cortana dialog to happen after pipe write.

So I now how a demo-able version of Colossal Cave on an Invoke with Cortana.




What is next before publishing?

  1. Support multiple, concurrent users (yay fork).
  2. Support save game.
  3. Improve the Windows 10 prompt to repeat the text.

Sunday, 12 August 2018

Recovering my files....

So... I bought this lovely ROG portable (Strix 17 GL703GE) and started developing on it.  Near the 90 day mark, I noticed the machine would not sleep.  I found out, slowly, that the left arrow key would fire whenever it liked.  It was pretty random at first, and then got persistently worse.  Imagine trying to type when some invisible monkey keeps hitting backspace...

In my wisdom, I thought "heck I'll just make an image of the two disks" with disk2vhd.  Smart right? And I'll wipe the computer and restore the disks on my replacement.

No. Windows does not have any tools out the box that do low level device copy for exact cloning. And mounting a vhd, though Windows can do it via diskmgmt or partdisk, there are some issues...

I tried to make a bootable partition on a USB drive.  First problem, my partition was out-of-range for an MBR style boot.  I needed EFI/GPT, but for whatever reason my ROG's boot menu would not recognize my cloned partition.

I though I'd use linux and gparted.  Nope. After trying to find the right drivers for the ROG, I could not get the vhd mounted as guestfish uses a "FUSE" device that doesn't support block level reads (no cat, no dd from /dev/fuse...)  And... most of the live USB tools would crash loading gparted. I spent hours getting to a point I had a bootable linux with the right video and track drivers just to discover I couldn't copy from a "file system in user space".

So... bought a new USB drive and made a partition of the same size as my former boot disk.  I use cygwin to copy from a mounted vhd to this partition. Then, I had to fix up the partition to be bootable.  And then, I had to use bcdedit, bootmgr, and msconfig to let me boot from my clone... so that I could repeat the process back to the new machine's boot partition.

And then, I discovered that my windows login credentials didn't work.  For whatever reason, my login account didn't have permission to access my own home directory.  So I got to figure out takeown, and regrant permissions to myself.

What a pain...

Monday, 23 July 2018

Why doesn't printf / fprintf output anything...


In my build of Colossal Cave to Windows, I had to get rid of getline (as this is a linux function found in <editline/readline.h> and it allocates a string dynamically) by replacing it with fgets. I compiled (under mingw) with no other modifications. And, I played advent.exe for an hour. I was happy.

And then I kicked up my IDE and wrote some node / Javascript to spawn a child_process running my new executable. It should work...

It didn't. My output handler, instead of asking me if I would like instructions, sat there.  Did I fail in launching the process?  I added logging the PID. It looked like it launched. I looked up the PID in taskmgr.  I didn't see it. I looked up the PID in tasklist. There it was. But there was no output.

I searched the internet (using the wrong terms) and found nothing. But then I figured it out. I changed the executable from advent.exe to tasklist.exe. And magic; node dumped out some output... but truncated the last bit. That was the hint.

Programs with pipes work differently than console ttys. Most times you won't notice because a console terminal will by default flush stdout when it hits a newline (on unix at least.) Windows, and as it turns out a few stdio implementations, will buffer any stdout unless fflush is explicitly called or the buffer limit is reached.  This is good.  I/O writes are typically expensive, and if you have a process in the background (or without a terminal) this is a good optimization.

But it is not good if you are expecting a dialog or stream that would flush stdout on the next stdin call. A newline will not flush stdout onWindows (with the stdio implementation under mingw/cygwin.) On unix, you can use stdbuf or unbuffer to make a process not buffer its output. I saw no way to do this in Windows. (There might be, I just didn't see it.)

The solution? Fortunately the getline removal is also my savior. If I flush stdout before calling fgets, advent.exe works the way I expect. But... this won't help me with any and all other Windows commands. I won't always have the code of the command I'm executing (that adds a flush called or setbuf (stdio, null ). When I find it, I'll post...