Dieser Artikel wurde maschinell übersetzt.

Die Working Programmer

Sprich mit mir, Teil 3: Die Therapie

Ted Neward

 

Ted NewardIm ersten Teil dieser Serie (msdn.microsoft.com/magazine/hh781028), ich baute ein einfaches Spracheingabe System über das Telefon mit dem Tropo Wolke gehosteten Stimme/SMS-System. Es war nicht zu kompliziert, aber es zeigte, wie man die Skripting-API, gehostet auf den Servern Tropo, Tropo verwenden, um Anrufe empfangen, stellen ein Menü, Antwort Benutzereingaben abgerufen und so weiter.

In der zweiten Spalte (msdn.microsoft.com/magazine/hh852597), nahm ich einen Schritt zur Seite und Feliza gesprochen, ein "Chat-Bot" im Geiste des ursprünglichen Programms "ELIZA", entwickelt, um Benutzer Text eingeben und reagieren darauf in einer Weise ähnlich, was wir hören können, während auf einem Psychologen Couch liegend. Wieder "sie" nicht allzu anspruchsvoll, aber Feliza bekam die zeigen über, und noch wichtiger, demonstriert, wie einfach das System erweitert werden könnte, viel näher an den Turing-Test übergeben.

Es scheint dann, natürlich, diese zwei Stücke und Schweißen sie zusammen: Lassen Sie Tropo zu sammeln, die Sprach- oder SMS-Eingabe des Benutzers, um Feliza, füttern ließ sie berechnen eine Tiefe, durchdachte Antwort, schicken Sie es zurück zu Tropo und Tropo in Futtermittel übergehen es zurück an den Benutzer haben. Leider verhindert eine deutliche Trennung, dass nicht so einfach wie es klingt. Da wir die Tropo Skripterstellungs-API verwenden, unsere Tropo-app auf seinen Servern gehostet wird und Tropo ist nicht Öffnung von seinen Servern zu host eine ASP.Netz-app, geschweige denn unsere benutzerdefinierten Feliza-Binärdateien (, die als letzte Spalte nur ein Satz von Microsoft.NET Framework-DLLs).

Glücklicherweise Tropo realisiert, dass die Fähigkeit zu tun, Stimme und SMS selbst nicht gehen, wirklich unter der Menge Geschäftssinn Entwickler schneiden, und es bietet die gleiche Art der Stimme/SMS Zugang, sondern über HTTP/REST-ähnliche Kanäle. Mit anderen Worten, Tropo dauert die eingehende Sprach- oder SMS-Eingang, übergeben Sie es an eine URL Ihrer Wahl, dann erfassen die Antwort … gut tun, was auch immer die Antwort sagt es zu (siehe Abbildung 1).

Tropo-Hosted API Call Flow
Abbildung 1 Tropo gehosteten API Call-Flow

Wahr, addiert dies eine andere Schicht der Netzwerkkommunikation für das gesamte System, mit allen Failover und Performance sorgen, die ein anderes Netzwerkroundtrip bringt. Aber es bedeutet auch, dass wir die Daten und speichern Sie es auf einem beliebigen Server nach unserer Wahl, die eine erhebliche Sorge für bestimmte Anwendungen sehr gut sein könnte — Sicherheit, Datenbankzugriff und So weiter.

Also lassen Sie uns nehmen einen weiteren Schritt seitwärts und herauszufinden, wie Tropo dieses Tänzchen HTTP funktioniert.

Hallo, Tropo … aus meiner Domain

Der Ort, um zu beginnen ist mit einem einfachen "Hello World"-Stil Zugang. Tropo, wie viele Internet-APIs verwendet HTTP als Kommunikationskanal und JSON serialisierten Format der gesendeten Daten. Die einfachste Sache zu tun, Build ist ein einfacher, statischer JSON Objekt für Tropo anfordern, wenn eine Telefonnummer genannt wird, zu sagen "Hallo" an den Aufrufer. Die JSON dafür sieht wie folgt aus:

{
  "tropo": [
    {
      "say": {
        "value":"Hello, Tropo, from my host!"
      }
    }
  ]
}

Auf der Oberfläche ist die Struktur relativ einfach.Das JSON-Objekt ist ein Einzelfeld-Objekt, das Feld "Tropo" ein Array von Objekten zu speichern, dass jede Tropo sagen was zu tun ist; in diesem Fall ist es eine einzelne "sagen" Befehl mit das Sprachausgabemodul Tropo um zu sagen, "Hallo Tropo, von meinem Host!" Aber Tropo muss kennen wie zu befinden dieses JSON-Objekt, das heißt, wir müssen zum Erstellen und Konfigurieren einer neuen Tropo-Anwendungs, und wir müssen einen Server, Tropo finden (bedeutet, dass es wahrscheinlich kein Entwickler-Laptop versteckt sich hinter einer Firewall sein kann).Dieser zweite Punkt ist leicht über einen Abstecher zu Ihrer bevorzugten ASP behoben.NET hosting-Anbieter (ich verwendete WinHost — seine grundlegende Plan ist perfekt für diese).Die erste erfordert eine Reise zurück in die Tropo-Systemsteuerung.

Diesmal, wenn Sie eine neue Anwendung erstellen, wählen Sie "Tropo WebAPI" anstelle von "Tropo Scripting" (siehe Abbildung 2), und geben sie die URL, um zu finden, dass bestimmte JSON-Datei; in meinem Fall, ich habe feliza.org (im Vorgriff auf die Schritte danach) und das Stammverzeichnis der Website abgesetzt.Vollständig konfiguriert, es sieht aus wie Abbildung 3.

The Application WizardAbbildung 2 der Anwendungs-Assistent

The Configured ApplicationAbbildung 3 die konfigurierte Anwendung

Obwohl Tropo gerne hook up etliche Skype und Session Initiation Protocol (SIP) für uns war, haben wir noch ein Standardtelefon-Anzahl manuell einbinden.Das habe ich während Sie waren nicht auf der Suche, und die Nummer ist 425-247-3096, falls Sie möchten, nehmen einen Moment, und wählen Sie den Server.

Und das ist es!Art von.

Wenn Sie eigene Tropo Dienst neben mir aufgebaut habe, erhalten keine Art von Antwort vom Telefon Sie bei Einwahl in.Wenn dies der Fall ist, stellt Tropo ein Anwendungsdebugger, die Protokolle von Ihrem Tropo app sehen können.(In der blauen Leiste am oberen Rand der Seite sehen Sie.) Wenn das Ereignisprotokoll betrachten, sehen wir etwas wie folgt: "Nicht-2XX-Statuscode auf Tropo-Thread-8d60bf40bc3409843b52f30f929f641c empfangen [url=http://www.feliza.org/helloworld.json, Code = 405]."

Ja, habe Tropo einen HTTP-Fehler.Insbesondere hat es ein "405" Fehler, der (für diejenigen, die die HTTP-Spezifikation noch nicht noch auswendig) übersetzt "Methode nicht unterstützt."

Um ehrlich zu sein, ist ein Aufruf Tropo einen REST-Dienst etwas irreführend, da es nicht wirklich eine der kardinalen Regeln der REST folgt: das HTTP-Verb beschreibt die Aktion für die Ressource.Tropo kümmert sich nicht wirklich über das Verb; Sie stellen einfach alles.Und das ist, warum der Host reagiert (richtig) auf die HTTP POST-Anforderung, weil eine statische Seite POSTable nicht.Oy.

Glücklicherweise wissen wir eine Technologie, die behebt, die ziemlich leicht.Zu diesem Zeitpunkt erstellen wir eine ASP.Netz-app (eine leere ist in Ordnung), und geben sie einen Arbeitsplan, die akzeptiert "/ helloworld.json" und ordnet sie einer einfachen Controller, wie im folgenden Code (mit viel nicht-relevanter Code ausgelassen) dargestellt:

namespace TropoApp
{
  public class MvcApplication : System.Web.HttpApplication
  {
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.MapRoute("HelloWorld", "helloworld.json",
        new { controller = "HelloWorld", action = "Index" });
    }
  }
}

… die wiederum nur die statische JSON für unser "HelloWorld", gibt, wie hier gezeigt (mit viel nicht-relevanter Code ausgelassen):

namespace TropoApp.Controllers
  {
    public class HelloWorldController : Controller
    {
      public const string helloworldJSON =
        "{ \"tropo\":[{\"say\":{\"value\":\"Hello, Tropo," +
        " from my host!
\"}}]}";
      [AcceptVerbs("GET", "POST")]
      public string Index() {
        return helloworldJSON;
      }
    }
  }

Drücken Sie diese auf den Server, und wir sind golden.

Sagen Sie, sagen, sagen...

Wenn das "sagen" in die JSON Ihr Gedächtnis ein wenig kitzelt, ist es weil wir während der früheren Erforschung der Tropo Scripting API hinein lief. Damals war es eine Methode, die wir, vorbei an einer Reihe von Name-Wert genannt-Paaren (im wahren JavaScript Mode) der Parameter beschreiben, wie die gesprochene Ausgabe anpassen. Hier, weil wir nicht die Möglichkeit, auf dem-Server-APIs aufrufen — denken Sie daran, diese JSON-Datei gehostet wird, auf meinem Server, nicht die Wolken das Tropo — wir haben, um es stattdessen in eine strukturelle Form beschreiben. Also, wenn wir eine andere Stimme, die dem Benutzer sprechen wollen, müssen wir angeben, dass als ein Feld in dem Objekt "sagen":

{
  "tropo":[
    {
      "say":
      {
        "value":"Hello, Tropo, from my host!",
        "voice":"Grace"
      }
    }
  ]
}

Jetzt, Grace (wer wird beschrieben als "Australisches Englisch") begrüßen uns im Namen der Tropo. Die vollständigen Details von "sagen" werden beschrieben in den Tropo API Docs auf seiner Web Site, wie alle die JSON-Objekten hin und her übergeben wird.

Hier ist, wo die Verwendung von ASP.NET wirklich glänzt: Anstatt zu versuchen, diese Zeichenfolgen im Code von JSON aufzubauen, können wir die impliziten Objekt zu JSON-Bindungen in ASP.NET zu erleichtern, diese JSON-Objekte slam (siehe Abbildung 4).

Abbildung 4 verwenden.NET Framework-Objekt zu JSON Bindungen

public static object helloworld =
  new { tropo =
    new[] {
      new {
        say = new {
          value = "Hello, Tropo, from my host!",
          voice = "Grace"
        }
      }
    }
  };
[AcceptVerbs("POST")]
public JsonResult Index()
{
  return Json(helloworld);
}

Die JSON gesendet muss seine Felder und Werte mit doppelten Anführungszeichen, im Gegensatz zu den normalen JavaScript "Es kann" Apostroph oder doppeltes Anführungszeichen zitiert haben. Mit die Objekt zu JSON-Bindungen macht all das völlig irrelevant für dem Anwendungsentwickler. Schön. (Hinweis: Tropo bietet auch eine Client-Bibliothek für c#, die viele der JSON-stuff abstrahiert, aber ich bin mit Schwerpunkt auf REST Anrufe "von hand" weil dadurch auch zeigen, wie Sie tun die gleiche Sache mit ASP.NET MVC im Allgemeinen — finden Sie unter bit.ly/bMMJDv für Details.)

Hören Sie den Ton …

Der Punkt der Feliza nicht nur zufällige Ausstecher Bits psychologische Kutteln, aber speien. Sie muss hören die gesprochene Eingabe des Benutzers, zu analysieren, und dann zufällige Ausstecher Bits psychologische Kutteln speien. Um dies zu erreichen, müssen wir in der Lage, das eingehende POSTed JSON-Objekt verarbeiten, das Tropo uns schickt. Dabei ist relativ einfach, es ist ein JSON-Objekt (und beschrieben bei bit.ly/yV5ect über die "Fragen" Struktur, die etwas sagen wird, dann anhalten und warten auf Eingabe) und ASP.NET MVC hat einige schönen Auto-JSON-Objekt-Bindungen für dies zu tun. Also, z. B. um eine Frage des Benutzers und haben post es Laufwerk zu einem anderen JSON-Ergebnis, wünschen wir uns eine "Fragen" wie in Abbildung 5 (wie in den Tropo-Docs).

Abbildung 5 ein "Fragen" Beispiel

public static object helloworld =   new { tropo =
    new[] {
      new {
        say = new {
          value = "Hello, Tropo, from my host!",
          voice = "Grace"
        }
      }
    }
};
[AcceptVerbs("POST")]
public JsonResult Index()
{
  return Json(helloworld);
}
{
  "tropo": [
    {
      "ask": {
        "say": [
          {
            "value": "Please say your account number"  
          }
        ],
        "required": true,
        "timeout": 30,
        "name": "acctNum",
        "choices": {
          "value": "[5 DIGITS]"
        } 
      } 
    },
    {
      "on":{
        "next":"/accountDescribe.json",
        "event":"continue"
      }
    },
    {
      "on":{
        "next":"/accountIncomplete.json",
        "event":"incomplete"
      }
    }
  ] 
}

Da die Parameter bedeuten, "Fragen" Timeout wird in 30 Sekunden, dann binden Sie die Ergebnisse (die fünf Ziffern sein müssen) in einen Parameter namens "AcctNum" in der nachfolgenden JSON Antwort geschrieben zurück, die an den "accountDescribe.json"-Endpunkt gesendet werden soll. Wenn die Konto-Nummer unvollständig ist, wird "accountIncomplete.json" und so weiter Tropo hinzuzufügen.

Es gibt nur ein Problem mit dem System, wie es derzeit geschrieben steht: Wenn wir den Eingabetyp (im Feld "Optionen") von "[5 DIGITS]" zu ändern "[ANY]" (das ist, was Feliza, schließlich möchte — will sie Benutzer in der Lage, etwas zu sagen, was sie wollen), Tropo erzählt uns in der Dokumentation zu "Fragen", die versuchen, "[ANY]" Arten von Beiträgen über den Sprachkanal erfassen nicht zulässig ist. Das setzt die Kibosh auf mit Stimme, um mit Feliza zu sprechen. In fast jedem anderen Szenario wäre dies kein Problem. In der Regel Spracheingabe auf eine kleine Gruppe von Eingängen eingeschränkt werden müssen, oder sonst brauchen wir ein enormes Maß an Genauigkeit bei der Umwandlung von Sprache in Text. Tropo den Sprachkanal aufzeichnen und speichern sie als MP3-Datei für offline-Analyse kann, aber Tropo bietet uns eine weitere Alternative für die offene Texteingabe.

ASP.NET im Gespräch mit f#

Wir haben Tropo verkabelt, bis zu unserer Web Site, aber Feliza sitzt noch in ihr F-DLLs, unverbunden. Wir können jetzt beginnen, die Feliza F#-Binärdateien für die eingehende Eingabe verbinden, aber das geht zu ASP erfordern.NET, mit f#, eine Übung zu sprechen, das ist relativ einfach, aber nicht immer offensichtlich. Die ASP.NET-Website wird auch müssen benutzerdefinierte JSON Antworten zurück, also ausgeben, anstatt überlassen die Arbeit halb fertig, wir werde ausklingen Feliza nächste Mal – und schauen Sie sich einige Möglichkeiten, um potenziell das System noch weiter zu erweitern.

Viel Spaß beim Programmieren!

Ted Neward ist ein architektonischer Berater mit Neudesic LLC. Er hat mehr als 100 Artikel geschrieben, ist ein C#-MVP und INETA-Sprecher und hat verfasst und Mitautor von einem Dutzend Bücher, einschließlich der kürzlich veröffentlichten "professionelle f# 2.0" (Wrox, 2010). Er berät und Mentoren regelmäßig. Sie erreichen ihn am ted@tedneward.com Wenn Sie ihn zusammen mit Ihrem Team, oder lesen Sie seinen Blog unter blogs.tedneward.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Adam Kalsey