Windows Live Ag... 的个人资料Windows Live Agents照片日志列表 工具 帮助

日志


10月15日

Writing Tips With DisplayReminderToGetOutOfChat()

While we want users to chat with our agents about everything and anything, we want to make them aware of the agent’s main purpose. Adding tips to the procedure DisplayReminderToGetOutOfChat(), which is defined in ChatParams.pkg, is a good way to bring users back to the agent’s purpose.

 

The procedure is called through the post-process ReminderToGetOutOfChat. The post-process is BuddyScript that is called after the end of each routine that is within the scope of the processing zone. Any .ddl that includes ChatParams.pkg will have the processing zone “started” thanks to that last line “start processing ReminderToGetOutOfChat”.  The processing is active for every routine in the .ddl until you “end” it using the line “end processing ReminderToGetOutOfChat”. 

 

You should write 2-3 tips for each piece of the agent’s functionality. You will not override the procedure DisplayReminderToGetOutOfChat(), but simply add to it.

 

Example:

When a user is chatting too much, the agent will pull him/her back into the conversation. For example:

 

College Football Guru says:

Yeah.

 

Wanna see where your favorite college football team stands? Type "Boston College standings."

 

Writing Dialog Tips

The best use of the procedure DisplayReminderToGetOutOfChat() is to create tips with dialogs. Dialogs keep users engaged and users love to be asked questions.

 

                Example:

procedure DisplayReminderToGetOutOfChat()

  RAND=Rand(14)

  if RAND=0

    - Why don't you ask me something?

    - Why don't you tell me something new?

    - Don't you want to ask me something?

  else if RAND=1 && !SAW_TAROT

    SAW_TAROT = 1

    - Do you want to see what your Tarot Cards say today?

    ? No

      - If you ever change your mind, just type StyleTypeThis("tarot card reading.")

    ? Yes

      rematch tarot card reading

    ? Already did.

    ? I saw it already.

    ? Did it.

    ? Did that.

      - Cool! I hope it was helpful!

               

                Example in the Agent:

Astrology Bot  says (4:16 PM):

Yes.

 

So anyway...

Do you want to see what your Tarot Cards say today?

 Britt says (4:16 PM):

no

Astrology Bot  says (4:16 PM):

    If you ever change your mind, just type "tarot card reading."

 

 

Creating Tip Variables

You should use variables so that users do not see the same tip in a session. The user may see the tip in his/her next session with the agent. Define your variables in ChatParams.pkg:

 

variable SAW_ROSTER = 0

 

When you define the variable, you will set it 0. When the user sees the tip, you will set the variable to 1 within the procedure.

 

  else if RAND==3 && !SAW_ROSTER

    SAW_ROSTER = 1

    - I have every college football team roster. Wanna know whose playing on your favorite team? Simply type StyleTypeThisPeriod("UAlbany team roster")

 

End the Procedure with General Tips

If a user has seen every tip in DisplayReminderToGetOutOfChat(), you will want to have your ending “else” include general tips that users can see multiple times in the same session. You should direct the user to type “home” or “?” in order to see all of the agent’s functionalities.

 

Example:

else

    - Can we talk football now? Type StyleTypeThis("?") and I'll give you examples of what types of questions you can ask.

    - OK, OK, enough of that. Let's talk football! Ask me how your favorite football team is doing this season.

    - Yada yada... Can we talk about football?! Type StyleTypeThis("?") and I'll give you examples of what types of questions you can ask.

10月11日

Matching on Datasources and Datatables

Many of the most compelling agents use datasources and datatables to extend their functionality beyond static, written output.  For example, if a user asks about the weather, the agent's response can be drawn from a datasource that passes parameters to a web service and retrieves the current weather conditions.  Another use of datasources and datatables lies on the input side -- we want to recognize that the user is asking about something contained in this dynamic or preloaded pool of data the agent uses for output.  There are a few ways of doing this.

Datatables

 

A simple datatable is just that -- a table with rows and columns, sometimes in a tab-delimited text file, preloaded into memory when the agent compiles.  We can use datatables to map one value to others, or simply as a list, and then manipulate these values to display a dynamic output.  We can also use the table as the contents of a subpattern that users match on, using a datatable subpattern.

 

Say we have a list of actors in a text file, with their names and IDs.  The ID we use elsewhere, but we can use the names to see if the user is asking about an actor, and do something special if they are.  The list looks like this:

 

  485957    Jim Calabrese

  485958    Susan Leber

  485959    Michael Yanko

 

Next we need to define the datatable:

 

datatable ActorIDTable

  load Id {index=exact}, Name {index=thawed} from file

    ActorID.txt

 

Now we can create a subpattern to match on a column in the datatable. 

 

subpattern AllActors get Name, Name in ActorIDTable {maxlength=3}

 

"get Name, Name in ActorIDTable" means that the subpattern will look at the ActorIDTable datatable and match on the values in the Name column (which are thawed), and return the values in the Name column.  It's the equivalent of this:

 

subpattern AllActors {spellcorrect=”no”}

+ jim calabrese

  return "Jim Calabrese"

+ susan leber

  return "Susan Leber"

+ michael yanko

  return "Michael Yanko"

 

We can make the agent's actor-recognition more robust by matching on words that look like names, and rolling it all into an actor subpattern.

 

subpattern AnActor

+ VAR=AllActors

+ VAR=APossibleName {score=40}

  return VAR

 

The last step is to create topics:

 

? I'm a fan of ACTOR=AnActor.

  - Yes, ACTOR deserves an Oscar.

 

? I'm a fan of VAR=Anything.

  - You like VAR?  I'll keep that in mind.

 

  User:  I am a big fan of michael yanko.

  Agent: Yes, Michael Yanko deserves an Oscar.

  User:  I'm also a fan of ice cream.

  Agent: You like ice cream?  I'll keep that in mind.

 

Datasources

 

A datasource is a tool to access external data, like a web service or database.  While there is not a "datasource subpattern" in the BuddyScript platform, it is still possible to match on the dynamic data accessed by a datasource, using a variable subpattern.

 

A variable subpattern matches on the keys of an object, so if we use our datasource to fill an object, we can use that object’s keys in our matching.  The return value of the subpattern is the matched key.

 

For example, say we have a function that calls a datasource that returns a list of TV channels a user has in her area, called ChannelLineup().  It returns an list of objects, each with the channel number and call letters for one channel.  We can manipulate that list to populate an object variable, G_USER_CHANNELS, at some point in the user session before the variable subpattern is to be used.

 

stored variable G_USER_CHANNELS

 

procedure PopulateUserChannels()

  CHANNELS = ()

  CHANNELS = ChannelLineup()

  G_USER_CHANNELS = ()

  for IDX in CHANNELS

    NUMBER   = CHANNELS[IDX].ChannelNumber

    LETTERS  = StringClean(CHANNELS[IDX].CallLetters)

    G_USER_CHANNELS[NUMBER]   = LETTERS

    G_USER_CHANNELS[LETTERS]  = NUMBER

 

Note that we must use StringClean to make the call letters lowercase -- otherwise the subpattern will contain illegal characters.

 

Next we create the subpattern:

 

subpattern AUserTVChannel variable G_USER_CHANNELS {style=raw score=MACRO_STRONG_SCORE}

 

And topics.

 

? Do I have CHANNEL=AUserTVChannel?

  - You do have CHANNEL.

 

? Do I have VAR=Anything?

  - I'm not sure if you have VAR.

 

  User: Do I have FOX?

  Agent: You do have fox.

  User: Do I have a car?

  Agent: I'm not sure if you have a car.

 

However, using a variable subpattern in this case is actually unnecessary.  A better solution is to create a datatable subpattern with all possible call letters and channel numbers, and then procedurally figure out whether the user has the channel they’ve matched on.

 

Consider another example.  We have a function calling a datasource that returns a list of products currently available, along with price and description.  Every week new products are added and old ones removed, so we never have quite the same list, or know what new products may be added. 

 

The agent must recognize when users are asking how much a product is, even if it is out of stock.  What we can do is maintain a list of all products ever sold, and add to the list when we find a new product.

 

subpattern APossibleProduct variable G_ALL_PRODUCTS {style=raw score=MACRO_STRONG_SCORE}

 

procedure DisplayProductDetails(NAME)

  PRODUCTS |= ()

  PRODUCTS = GetProductDetails(NAME)

  if !PRODUCTS || PRODUCTS == ()

    - Sorry, NAME is no longer available.

  else

    for value PRODUCT in PRODUCTS

      * Here are the products available:

      - PRODUCT.name, PRODUCT.price

  PRODUCT.detail

 

procedure AddProductsToPossibleProducts(NAME)

  PRODUCTS <= GetProductDetails(NAME)

  for value PRODUCT in PRODUCTS

    G_ALL_PRODUCTS[PRODUCT.name] = PRODUCT.price

   

? Do you have any PRODUCT=APossibleProduct?

? Do you have any VAR=Anything?

  if PRODUCT

    call DisplayProductDetails(PRODUCT)

  else

    if IsAStockedProduct(VAR)

      call AddProductsToPossibleProducts(VAR)

      call DisplayProductDetails(VAR)

    else

      - Sorry, I don't recognize VAR as a valid product.

 

One warning: depending on the size of the object variable, variable subpatterns are potentially big resource hogs, and can harm your agent's response time.  So use with care.

10月3日

Fuzzing in BuddyScript: How to use brute force to test your Agent.

In his last post, Mirco explained how to add unit tests to your Agent: it’s an absolutely critical investment to add unit tests covering as much of the functionality of your Agent as possible, to make sure it performs the way you want throughout development and beyond.

In this post I’ll describe a complementary testing approach (you’ll still need to write unit tests!), known as fuzzing.

 

Fuzzing???

Fuzzing an Agent works like this: for each handle in your project the platform builds a random question that should match on it. It then asks all these questions to your Agent as a user would. Finally, it reports what questions caused execution errors, and gives you a sorted list of the slowest ones.

 

For instance, assuming you have the following routine in your code (not that you’d write something like that, of course):

 

? I was born in YEAR=Anything.

  AGE = GetCurrentYear() - YEAR

  - OK, so that makes you about AGE years old, right?

 

The tool would take your handle “? I was born in YEAR=Anything.”, try to randomly generate a question that would match it, and ask that question. In this case, the tool might come up with something random like “i am born in Blah blah blah” (through stemming, synonyms, etc). Of course trying to execute that question generates an error, which the tool would detect.

 

 

Step-by-step

That’s for the theory. Concretely to take advantage of this test, you simply need to launch your project in the IDE (via the query window) and type the following as your questions:

-        !d 0 => this turns off debug info display which speeds up the test substantially

-        !testmode => enters the Test mode, which offers a variety of options to tweak how the test is run (leaving the defaults is ok)

-        go => launches the test

Depending on the size of your project, the test might take a long time to finish, since it will ask at least one question for each handle of your project.

 

Important: if you have debug code somewhere in your code, it will be executed unless you “protect” it!

 

// MACRO_PROTECTED_MATCHING prevents this handle from being “fuzzed” during the test

// You wouldn’t want a random amount transferred to your test account…

+ _for_debug_transfer NUMBER=ANumber dollars to test account {MACRO_PROTECTED_MATCHING}

  call BankingDataSourceTransfer(NUMBER, G_MY_ACCOUNT, G_TEST_ACCOUNT)

 

 

Sample output

Below is a sample output of this coverage test, edited for brevity:

 

joeuser: !d 0

null

joeuser: !testmode

Automated Agent:
****************************

**   Entering Test Mode   **

****************************

 

Type: "help" or just "h" to see a list of available commands.

 

testmode: go

At this point you have to wait for the test to complete, which takes between a few seconds and a few hours depending on your agent and on your machine.

Automated Agent:

=======================================

Error Report:

*************************************************************

That’s a test executed for our sample routine described above

Problem encountered testing pattern 325: I was born in YEAR=Anything. (in ? I was born in YEAR=Anything.)

Sequence:

  i am born in Blah blah blah

 

Problem:

Exception: Exception while processing "i am born in Blah blah blah":

Error executing script associated to query "i am born in Blah blah blah"

  Error executing script labeled "? I was born in YEAR=Anything." at line 106 in file "domains:/TestProject/English/UserInfo/UserName.ddl":

    Error executing command "AGE = GetCurrentYear() - YEAR" in "domains:/TestProject/English/UserInfo/UserName.ddl", line "107"

      Can't convert expression "Blah blah blah" to a float

 

=======================================

30 slowest queries:

This section tells you which questions were the slowest ones to answer. If you access slow web services that you then cache in memory you might want to run the test twice to get more accurate results. Many factors may slow down a query execution rate. To “debug” slow queries, you need to check how it was analyzed by the NL engine (did it trigger “runaway rephrase rules” or involve a subpattern that happens to be slow?), if the associated script can execute quickly, etc.

588ms:  Query(ies) asked: "which gr8 dose common factor of 3 & 3"   Pattern represented="What is the Greatest Common Factor of X=AnInteger and Y=AnInteger? (in answers WhatIsTheGreatestCommonFactorOf<X, Y>)".

320ms:  Query(ies) asked: "divide the sinus of ( 12.34 ) percent with sq rt ( a million a hundred ) cubed is what in its simplest form"   Pattern represented="EXPRESSION=AComplexExpressionNoPlug =EqualsWhat [FORMAT=AResultFormatType] (in +- Calculate EXPRESSION.description)".

271ms:  Query(ies) asked: "which being the plural of white dwarf"   Pattern represented="What is the plural of NOUN=ANoun? (in answers WhatIsThePluralOfNoun<NOUN>)".

254ms:  Query(ies) asked: "we would prefer those you people call us which"   Pattern represented="I would prefer that you call me that. (in answers CallMeThat)".

238ms:  Query(ies) asked: "sum body calls me which"   Pattern represented="People call me that. (in answers CallMeThat)".

… edited for brevity…

107ms:  Query(ies) asked: "which percents of 3 is pi"   Pattern represented="(what|which) =nsPercent of WHOLE=AnAtomicExpression is PART=AnAtomicExpression (in answers WhatPercentOf<WHOLE>Is<PART>)".

107ms:  Query(ies) asked: "be u top of the line at math"   Pattern represented="Are you good at math? (in answers CanYouHelpMeWithMath)".

105ms:  Query(ies) asked: "my names is it" => "call us mrs godowns" => "pass" => "aye" => "nah thank yo u sorry" => "if u insist" => "that s wrong" => "alright" => "nada" => "thats wrong" => "we might prefer which you calls us sir plasmapheresis"   Pattern represented="my =nName is it (in answers CallMeThat)".

=======================================

Total of 2115 questions asked in 24050 milliseconds.

  Breakdown of execution time:

    Rephrasing:         8863 milliseconds 36.852390852391% of processing time

    Matching:           6329 milliseconds 26.316008316008% of processing time

    Preprocessing:      1 milliseconds 0.0041580041580042% of processing time

    ScriptExecution:    6154 milliseconds 25.588357588358% of processing time

    Postprocessing:     2248 milliseconds 9.3471933471933% of processing time

    Presentation layer: 100 milliseconds 0.41580041580042% of processing time

    Rest:               355 milliseconds 1.4760914760915% of processing time

and 2114 answers received (99.95%)

Average speed for queries answered: 11.381921438713 milliseconds (that's 87.858627858628 QPS)

1 error(s) during the test.

Complete test took 13885 milliseconds to process.

=======================================

 

 

Conclusion

Having a thorough test strategy is critical to the quality of your Agent. You want to find bugs before your users do! Nothing replaces good unit tests (see Mirco’s post), but fuzzing is a good way to detect cases you didn’t think about, or to identify slow queries. It’s a good idea to run a fuzzing test on your Agent when you reach critical milestones (before you make a beta available, before you launch, before releasing a major update, etc).

 

9月25日

Creating And Adding Dynamic Display Pictures (DDP) to Windows Live Agents

Dynamic Display Pictures are animated display pictures with advanced functionality (Moods, Animation) that users can create and purchase from third party partners.  Due to security concerns, Dynamic Display Pictures can only be purchased from official Microsoft content partners such as:

American Greetings/Blue Mountain à http://www.aginteractive.com/products_overview.html

3H Group (MeeGos) à http://www.3hgroup.com/index.htm

Saw-You (Weemees) à http://www.weeworld.com/

Wisepost/YNK (Korea) à http://www.ynkkorea.com/

DDPs support Flash (.swf) files for animations and conversation-specific moods. You must also include a flat image (96 x 96 pixels, gif or png) for the default image to be used for downlevel applications, including Mac Messenger, mobile devices, etc. The default size and shape of a dynamic display file is 142 x 98 pixels. Since a dynamic display picture consists of multiple elements it needs to be shipped as a .CAB file. This .CAB file is cryptographically signed and placed along with the signature in a content pack (e.g. a theme). It will be shipped as a .CAB file inside a .CAB file. Sometimes .CAB files are also .MCT files. Despite the different extension, the contents are identical.

When developing a Windows Live Agent that uses a Dynamic Display Picture, use the following criteria:

 

                - An *uncompressed* .CAB or .MCT file with the appropriate assets

                - ASCII content.xml files. Unicode is not currently supported.

                - A Microsoft signature -- this may be inside the .CAB or .MCT, or it may be a separate file

 

Add the following line to the service in your .bfg that should display the DDP:

 

               <buddyicon>

            $_BFG_DIR/sparkle-pack.cab

      </buddyicon>

 

You can also use buddyicon-dynamic, but it's deprecated in current builds of the SDK. It can be usefull in case you have a compressed .CAB file. You decompress it manually and setup the .BFG file with the individual components inside it.               

 

               <buddyicon>

            $_BFG_DIR/sparkle-downlevel.png

      </buddyicon>

      <buddyicon-dynamic>

            $_BFG_DIR/sparkle-signed.cab

      </buddyicon-dynamic>

      <buddyicon-cert>

            $_BFG_DIR/sparkle.sig

      </buddyicon-cert>

      <buddyicon-name>

            Secret Sparkle

      </buddyicon-name> 

9月17日

How to add automated tests to your agent

You want to make sure that the most complex features of your project work and keep working throughout development. This post explains how to write tests and how to run them either one by one or via the "Sanity Check" mechanism.

 

 

Testing one feature

 

Let’s assume you have a feature, you give it a noun (singular or plural) and it returns the singular or plural form of the noun. For instance:

User: What is the plural of cat?

Automated Agent: The plural form of cat is cats.

Here is how you write a test for this feature: 

procedure TestForGrammarFeatures(CTX)

  if (!CTX.Summary)

    - *****Testing Grammar Features*****

  //

  // Nouns

  //

  RESULT = TestQuery(CTX, "What is the plural of cat?", "The plural form of cat is cats.")

  RESULT = TestQuery(CTX, "What is the plural of foot?", "The plural form of foot is feet.")

  RESULT = TestQuery(CTX, "What is the plural of child?", "The plural form of child is children.")

  RESULT = TestQuery(CTX, "What is the singular of cats?", "The singular form of cats is cat.")

  RESULT = TestQuery(CTX, "What is the singular of feet?", "The singular form of feet is foot.")

  RESULT = TestQuery(CTX, "What is the singular of children?", "The singular form of children is child.")

  //

  // ...this is where you add more test.

  //RESULT = TestQuery(CTX, "A user query", "A regular expression that the answer should match on")

 

+ _start_test_grammar_features [TEST_SUMMARY=Anything] {MACRO_PROTECTED_MATCHING}

  // CTX and TEST_SUMMARY are variables used internally by the testing engine

  CTX = InitializeTest(TEST_SUMMARY, "Grammar Test")

  call TestForGrammarFeatures(CTX)

  call ReportTestResults(CTX, "Grammar Test")

 

Once you execute the test by calling "_start_test_grammar_features", it will run every single query in it and compare the answers your agent gave against the expected results (which are regular expressions). Ideally the result would look like this: 

User: _start_test_grammar_features

Automated Agent: Done testing Grammar Test (6 tests): Grammar Test passed 

For every query in the test that might have failed, the expected and the returned result are displayed. Tip: If you are interested in writing tests with more complex regular expressions you can look in BuddyScriptLib\English\Core\DateTime.pkg. There are a lot of tests at the bottom of the file covering all the different date and time features.

Every complex feature should have its own tests to assure its functionality.

 

 

Testing your Agent

 

A simple but very efficient way to check that all of your tests are working properly is the "Sanity Check". All you have to do is register a test to the Sanity Check with the help of function RegisterTestQuery("name_of_test_here"). 

procedure ABStartSessionProc()

  call RegisterTestQuery("_start_test_grammar_features")

  //

  // ...this is where you register more tests.

  //

The procedure ABStartSessionProc() is called whenever a user session starts. In a single procedure ABStartSessionProc() you can add as many tests to register as you want to and you can use ABStartSessionProc() more than once in different domains/packages as well. Ideally you should register a test to the Sanity Check in the same .ddl (Domain Description File) from where you call the test, just to keep it organized.

To launch the Sanity Check, simply type "project_sanity" as a user query. Once you have tests registered, we recommend to use the Sanity Check whenever you publish your project, when you make significant changes to your project, or even in automated tests.

 Note: The Sanity Check is available in KnowledgeManagement mode only (in the IDE, add "--filter KnowledgeManagement" to the field "Connection Options -> Extra Options"). 

 
9月10日

Using StringToXML and XMLToString

 

One of the new BuddyScript functions introduced in the 4.2 release of the SDK is StringToXML. The goal of this blog post is to familiarize you with how to use it. XMLToString does the reverse operation and will not be discussed in detail here, but it should be intuitive to use once you have an understanding of StringToXML.

Let’s assume that you have XML file that needs parsing. In the simple case of a hierarchical structure, we could use simple xml filter, but for a more complex case you may find StringToXML to be more useful. For example, you could have some movie information as follows:

<movies>

 <city name="London"/>

 <info>

   <title>Gone With The Wind</title>

 </info>

 <city name="Manchester" />

 <info>

   <title>Pirates of the Carribean</title>

 </info>

</movies>

 

In this case it’s not entirely clear how one would easily use the simple XML datasource for parsing. You could try to parse this function with regular expression matching, however one such XML feed may be more easily (and less error prone) parsed using the StringToXML function.

StringToXML takes as a parameter a string of the XML source and will return an XML object that can be more easily traversed.

In this example, the XML object returned from this XML by StringToXML would be as follows (generated using dbg_display XML_OBJECT)

!-kind = ""

!-name = "movies"

!-nodes

! !-0

! ! !-kind = ""

! ! !-name = "city"

! ! !-attributes

! ! ! !-name = "London"

! !-1

! ! !-kind = ""

! ! !-name = "info"

! ! !-nodes

! ! ! !-0

! ! ! ! !-kind = ""

! ! ! ! !-name = "title"

! ! ! ! !-nodes

! ! ! ! ! !-0

! ! ! ! ! ! !-kind = 2 (int)

! ! ! ! ! ! !-content = "Gone With The Wind"

! !-2

! ! !-kind = ""

! ! !-name = "city"

! ! !-attributes

! ! ! !-name = "Manchester"

! !-3

! ! !-kind = ""

! ! !-name = "info"

! ! !-nodes

! ! ! !-0

! ! ! ! !-kind = ""

! ! ! ! !-name = "title"

! ! ! ! !-nodes

! ! ! ! ! !-0

! ! ! ! ! ! !-kind = 2 (int)

! ! ! ! ! ! !-content = "Pirates of the Carribean"

 

To decipher the object, the following are various values that the members can take on.

Name

Possible Values

Explanation

kind

1, 2**

1: this is either an attribute or more nodes will follow

2: this XML node has content

name

String value

The name of the XML element

nodes

List of nodes

Contains a list of nodes as specified in this table

attributes

Name value pairs of attributes

Names and values of each attribute will be placed in this list

content

Actual content

Actual content of the XML node

 

** There is a small bug in 4.2 where “kind” is either “” or 2. In 4.3, kind will either be 1 or 2. For 4.2, just detect for “2” or not “2”.

Here is a full example of how to navigate the above XML file using StringToXML.

datasource dsMovieInfo1(URL) => RESULT {timeout = "20" expire = "now"}

  http

    URL

 

//returns the data in a list

function GetMovieInfo1()

  ALL_MOVIE_INFO = ()

  MOVIE_INFO.CITY = ""

  MOVIE_INFO.TITLE = ""

  //the XML file in this example is being served by my local machine

  T_INFO = dsMovieInfo1("http://localhost/gadgets/movietest.xml")

  XML_OBJECT = StringToXML(T_INFO)

  //nice display for XML object, very useful for debugging purposes

  dbg_display XML_OBJECT

  for value GENERAL_INFO in XML_OBJECT.nodes

    if GENERAL_INFO.name eq "city" && Exist(GENERAL_INFO.attributes) && Exist(GENERAL_INFO.attributes.name)

      MOVIE_INFO.CITY = GENERAL_INFO.attributes.name

    if GENERAL_INFO.name eq "info" && Exist(GENERAL_INFO.nodes)

      for value MOVIE_DETAILS in GENERAL_INFO.nodes

        if MOVIE_DETAILS.name eq "title" && Exist(MOVIE_DETAILS.nodes)

          MOVIE_INFO.TITLE = MOVIE_DETAILS.nodes[0].content

          //keep a list of the results

          insert last in ALL_MOVIE_INFO MOVIE_INFO

          //reset movie info

          MOVIE_INFO.CITY = ""

          MOVIE_INFO.TITLE = ""

  return ALL_MOVIE_INFO

 

? Test StringToXML

  MOVIEINFO = GetMovieInfo1()

  - MOVIEINFO

 

Note: In this release StringToXML only works for ANSI encoded sources. In future releases we are planning to add support for Unicode, UTF-8 and other encodings.

Please feel free to comment and ask questions on this post (or others) at our forum found at:

http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=1687&SiteID=1

Other suggestions for what tutorials or topics you would like to see are also very welcome.

 

8月31日

Console User Release Notes 4.2

Console User Release Notes 4.2

1 Introduction

These notes include broad descriptions of the major changes to the Management Console for version 4.2. They are primarily targeted at the users of the Management Console; however, they are of interest to agent developers as well.

2 General UI Improvements

2.1 “Arrange By” in Listboxes

We have added the ability to group the elements in a listbox. The idea was to create an additional way to quickly visualize the elements in the listbox. It is essentially a collapsible sort, as shown below:

clip_image002

The user may elect to turn on the “arrange by” feature by using the listbox configuration menu (the wrench icon in the upper right of the listbox). If a listbox supports the feature, additional menu items will be visible showing the various ways the list may be arranged. The user may collapse the groups by clicking on them, and may toggle the state of all of the groups by shift-clicking (or right-clicking and selecting the “Collapse/Expand All Groups” item from the context menu.

The console remembers whether you turned on the feature across console sessions (it is saved with your user profile).

This feature is currently implemented in the following places:

· Knowledge Editor: Manage Topics, Manage Response Fragments and Approve Changes

· Task List

3 Knowledge Editor

3.1 Enabled Column in Manage Topics

There is a new column in the “Manage Topics” navigation list, called “Enabled”. It shows whether a topic is enabled or disabled (as of today). The column is sortable.

clip_image004

3.2 Procedural Topic Search

There several new search methods in “Manage Topics”, in addition to the existing “matching query” and “string search” methods already available in 4.1. They are generally functions based on simple heuristics that find common and useful sets of topics.

· Insufficient Natural Language Comprehension: Selects topics that have too few reference questions (and they are too long to be general). User provides a threshold.

· Find Topics with No Response: Selects topics that have no “response” field set at all. Optionally, the user may provide a search string to limit the search to topics that contain that string as well.

clip_image006

Additionally, agent developers may add new search methods by overriding the GetSearchFuncList() method and providing additional functions to call. See the specification “Procedural Topic Search” for more details.

3.3 Talk to Agent: Restart Session

In “Talk to Agent”, you may now restart the current user’s session by clicking on the “Restart Session” button in the upper right corner of the http-msm’s user interface.

clip_image008

4 Quality Analysis

4.1 Improved Task Analysis in Session Audits

Console users who perform or browse audits and have the “own tasks” role and the “create tasks” role may now do more sophisticated task creation within session audits.

When users with “own task” and “create tasks” see session transcripts in a session audit, they also see “add task” icons on the right side of the elements of the transcript:

clip_image010

When clicked, the “Add Task” dialog opens and allows users to directly create new tasks for queries and topics without having to create an unanalyzed session task and analyze it later.

4.2 Non-Evaluation Audits

We have introduced the notion of “non-evaluation” audits. These audits are exactly like normal audits, but you may not vote on them. They are replacing the “Session Search” component completely; as such:

· There is no longer a “Session Search” component

· Existing session searches will appear in Quality Analysis as non-evaluation session audits

To create a new non-evaluation audit, clear the checkbox near the auditor popup labeled “Allow Evaluations”. When creating a non-evaluation audit, there is no need to specify an auditor.

clip_image012

A new column is available in the audit listbox called “Eval” which shows whether an audit allows evaluations or not.

NOTE: You may not create a non-evaluation audit series, since the purpose of audit series are to track evaluation trends over time.

4.3 Preset Audits

In the “Create New Audit” page, there is a new popup called “Preset”.

clip_image014

Choosing a preset (besides “custom”) fills in predetermined parameters of the audit. For instance, choosing “poor matches” (the only preset so far) does the following:

· Sets the type to “query”

· Turns off evaluations

· Adds the filter “only include queries whose match score is less than 50”

All other parameters are left alone. Changing any of the parameters of a preset will switch the preset popup back to “custom”.

The console remembers that an audit was created as a preset, and a new column in the listbox called “preset” allows users to sort by preset to quickly find their preset audits.

NOTE: Presets can be defined in the qa_config.xml file for an agent. See a console management developer for more information. “Poor Matches” is defined in the javascript and is always available.

NOTE: Presets are not available in audit series.

5 Task List

5.1 Session Summary in Task Summary

In session tasks, we now display the first several exchanges of the session in the task summary pane (to allow users to quickly see the content of the session without jumping into analysis):

clip_image016

5.2 Add Task Dialog: Pre-Analyze Query Tasks

In the “Add Task” dialog, console users who have the “own tasks” role may pre-analyze query tasks.

If the user has that role, he will additional fields in the dialog to pre-select an analysis (and supporting information):

clip_image018

The “analysis” popup contains the values “none” (no pre-analysis), “add new topic” (the user must provide a new topic name), or “custom” (the user must supply an explanation). Note that the user may not find another matching topic (to do this kind of analysis, the task list is necessary).

This dialog change applies to creating tasks from both session audits (see “Improved Task Analysis in Audits” above) and query audits.

5.3 New Filters

Users may now filter by comment and by analysis. The filters (available in “Additional Filters”) are case-sensitive string searches in the respective fields. It is NOT a keyword search (that is, users may not enter a list of comma-separated words and search for any or all of them).

clip_image020

5.4 Task Creators May See Created Tasks

In the past, users who only had the “create tasks” role had trouble going to the task list component and viewing the list of their created tasks. This has been fixed.

5.5 Task Editing is Limited to the Owner

Task editing is now limited to the owner of the task. Exceptions:

· Any user (who has a task list role) may add a comment to a task

· Any user who has the “manage tasks” role may reassign a task

6 Usage Reporting

6.1 Scheduled Delivery of Usage Reports in Excel Format By Email

PLEASE NOTE: This feature is only available on deployments on Windows boxes (due to the required libraries).

The console now has the ability to periodically generate Excel 2007 (.xlsx) files of various sections of the usage reporting data for an agent, and e-mail those generated files to a group of usage users.

In usage reporting, console users with the “manage scheduled reports” role can see a new command called “Scheduled Reports”.

clip_image022

Clicking on the command takes the user to the scheduled report subcomponent:

clip_image024

Schedules are similar to audit series in that they create objects periodically on some given schedule. Schedules have the following properties:

· The Owner: the creator of the schedule. The owner can add and remove recipients.

· The start date: when to begin generating reports (this date may be in the past, the present or the future). If the start date is in the past, all reports from that date to the present will be created at once to “catch up”.

· The frequency: determines what time frame to use for usage data in the report, as well as how often to generate the report (and the send the e-mails). The possible frequencies are:

o Every day: generate usage reports every day for the previous calendar day

o Every week: generate usage reports every seven days for the previous seven days

o Every month: generate usage reports every month for the previous month (no matter how many days are in the month)

· The recipients: the list of people who should receive the generated report. These users must be console users whose username is an e-mail address and who have the “view usage reports” role.

· The usage section paths: the list of sections of the usage reporting interface that should be included in the reports. Each path consists of a particular choice of tabs in the usage interface (e.g., “All Entry Points->Volume Summary”).

· The generated reports: once a report is generated, it is e-mailed to current recipients, and is stored for future reference (clicking on a generated report in the UI will download the report to the local machine).

Schedules may be suspended and resumed (once resumed, they will generate all missing reports since the suspension).

NOTE: a user may remove himself/herself from a schedule at any time (although only an owner may add a recipient).

NOTE: adding a recipient only affects generated reports going forward (old reports are not e-mailed to the new recipient).

7 Server Management

7.1 Edit BMD.conf

NOTE: This feature is only available to users with the “admin” (superuser) role and should be used with extreme caution.

In “Server Management”, there is a new command to edit the bmd.conf file from the console. The page provides a simple edit text that contains the body of the bmd.conf file.

NOTE: Passwords are shown encrypted, and any clear text passwords saved will be re-encrypted before saving.

7.2 Update Agents

NOTE: This feature is only available to users with the “admin” (superuser) role and should be used with extreme caution.

In “Server Management”, there is a new command to allow admins to “resurrect” a machine that has a bmd.conf, but needs to re-checkout all the agents. This can happen when a machine dies, and the bmd.conf is transferred to a new machine with a clean build, but no agents are checked out on the machine.

7.3 View Active Users

This command allows console users with the “View Active Users” role to see other “active” (i.e., logged in) users on the same console. A user may only see users with a subset of the roles of the requesting user; the rest are aggregated into a count.

clip_image026

This feature is also available in the “Lock KMS” page of the Knowledge Editor.

8 Other Features

8.1 “Functional” hyperlinks and onclicks in Session Transcripts

When session transcripts are displayed (in Task List session analysis and Quality Analysis’s session audits), any existing links (<a href=…></a>) or onclick elements (<span onclick=…></span>) now “function”. When clicked, they open a modal dialog that displays the content of the href or onclick. In the case of hrefs, we allow the user to follow the link.

clip_image028

8.2 HTTP MSM: Session Timeout

There is a new method of creating a countdown which will clear the transcript window after a specified amount of time. This is different than the normal session timeout, where the user’s session is marked complete, or the user profile purge, where the user’s data is written out to the user profile server. This timeout was created to allow sensitive information (such as financial or medical or other personal information) to be hidden from prying eyes on an idle session.

When enabled, the user is notified that the session will expire in a certain amount of time (default is 5 minutes). After a certain amount of time (default is 2 minutes), the user is presented a warning that the session will expire soon:

clip_image030

Dismissing the dialog indicates the user is still there, and resets the timer. If the user remains idle, the transcript is cleared, and the user is notified:

clip_image032

All messages and timeout values are configurable in the defines.txt file.

NOTE: If the http msm for a particular agent implements a “print transcript” or “save transcript”, this transcript should also be cleared when the window transcript is cleared (but since we do not control the code of the various http msms in all the agents, we did not implement that --- as we move those features back into the default http msm, we will implement that then).

8月30日

Developer Release Notes: 4.2

For those that currently have access, a new version of our platform and SDK has been released. It is available for download here: https://buddyscript.colloquis.com/protected/down.pl?
 
Here are the release notes for developers on that version.
 

Developer Release Notes 4.2

1      Dynamically Changing Agent friendly name, Display Picture and  personal message

 

You can now change the friendly name, icon, and/or personal message of your agent directly from the buddyscript code without having to change the bfg file and restart the agent.

 

 

To do so you have to override the following functions that defined in shared/WLMUtilities.pkg

·         WLMGetAgentFriendlyName()

·         WLMGetAgentIcon()

·         WLMGetAgentPersonalMessage()

 

For example:

 

function overrides WLMGetAgentFriendlyName()

     return "Friendly name of agent"

 

function overrides WLMGetAgentIcon()

    return "domains:/AgentName/image.jpg.png"

 

function overrides WLMGetAgentPersonalMessage()

    return "Your personal message"

 

You can obviously put a more complex logic in place to allow for thse message and or display picture to change on a schedule.

 

We recommend using this mechanism going forward rather than using the parameters of the MSN-msm component.

 

2      Windows Live/Passport  Account Profile Information

What Can be accessed and where

MSN Messenger users profile information stored with their passport account can now be used in usage reports.

 

To allow for that information to be accessible during usage reporting The following call has to be made:

call LogPassportProfileData()

 

This will stores the following  user’s passport profile data in the session log:

 

·         UserAge

·         UserGender

·         UserCountry

·         UserZipCode

 

This information is however not accessible to the code of the agent.

 

Availability of information during development

 

The actual information for each user will only be available when the agent is deployed within a Windows Live Data Center.

 

During Testing and if you would like your session logs to actually contain “test” information you can override the PPDIsInDebugMode function to return true.

 

If you want to simulate more variation in the data, you can also override the PPDGetDebugProfileData(SCREENNAME)function defined in Buddyscript Libs:

 /Shared_a1/Utilities/UserInfo/UserPUIDUtilities.pkg

 

 

3      PUID Access

 

If you agent needs access to other Windows Live Service using the end user PUID, contact the Windows Live Agents team to discuss your scenario and get access.

8月27日

Best Practices for Developing a Windows Live Agent: part 10

Today's post concludes the best practices for developing a windows live agent series. We hope that you found it useful. Most posts from now on will still be best practices, as well as tips and tricks, but this series is officially over.

 

If you have any questions the best place for them is our forum on: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=1687&SiteID=1. Please do not hesitate to ask on the forum what other topics you would like covered.

 

Multiple screen names

This post covers current functionality. We are looking into making this process more intuitive and less error prone. At that time, there will be a new post with new recommendations.

 

You should test your agent locally before you submit it to be hosted by Windows Live Agents. You can test much of the functionality of your agent in the IDE, but you’ll need to deploy it on Windows Live Messenger to see how it will act and appear to end users.

 

To do this, associate a login to a “KnowledgeManagement” filter, using the “Edit Agent Configuration” tab of your local KMS. When launching the web administration console and working with the KMS, the default filter is always “KnowledgeManagement”, and this should generally not be changed.

The new service will look like this in the agent’s .bfg file:

        <service type="MSN" only-in="KnowledgeManagement">

            <login>

                Friendbot_local@hotmail.com

            </login>

            <password>

                crypto: xxxXXXXxxxxxXX

            </password>

            <friendly-name>

                FriendBot name for knowledge management

            </friendly-name>

        </service>

 

Once your agent is hosted by Windows Live Agents, you will also need a deployment agent that the end users will chat with. You should provide a log in that you will need to associate with the “Deploy” filter and should be a different screen name than the “KnowledgeManagement” filter screen name, since both agents will be logged in at the same time. You will then be able to continue to update and improve your knowledge management agent (which is now on our servers), with the options to publish the changes that you are making to your Deploy agent.

 

Be aware that once we host your agent, whenever you log in locally with the same log in as the KnowledgeManagement or Deploy agents, you will sign out the agent that is logged in under the same screen name. To avoid this problem, if something now needs to be done locally (e.g. testing a change to an activity window), you should use a different screen name for your agent altogether. 

8月13日

Best Practices for Developing a Windows Live Agent: part 9

Make Your Agent Chatty

Users will chat with your agent about more than the agent's primary content—be prepared. When you start your Agent from the WLATemplate project that ships with the SDK, it will “understand” a lot of Chat questions, but its answers will be generic. You can easily customize these answers to give your Agent its own voice. Customize in priority the answers to the questions you expect to be asked the most often, from “Are you married?” to “Where do you live?” Your users will likely ask absurd questions, make vulgar and inappropriate remarks, and just want to have a friendly chat about nothing in particular, so try to cover all the bases. You can make your answers funny: “Robots can’t get married!”

 

Personalize Your Agent

Make your agent stand out with a display name, personal message, and display picture.

 

Example: See example photo at the end of this post.

 

- SmarterChild - *unicef contributing to charity is the display name. Display names are cleaner-looking and stand out more than the raw email address (smarterchild@hotmail.com). Here’s how the display name is set in the .bfg file:

 

            <friendly-name>

                - SmarterChild - *unicef contributing to charity

            </friendly-name>

 

ask me how! is the personal message. Personal messages should be short and should compel end users to initiate a session, either with a call to action or a brief description of the agent’s functionality. If the agent is sponsored by a company, you may want to use their advertising slogan. Here’s how the personal message is set in the .bfg file:

 

            <contact-card>

                ask me how!

            </contact-card>

 

The display image must be a 96x96 static .png, .jpg, or .gif. Here’s how the display image is set in the .bfg file:

 

            <buddyicon>

                $_BFG_DIR/buddy_icon_01.gif

            </buddyicon> 

8月8日

Best Practices for Developing a Windows Live Agent: part 8

Make Your Project Modular

Keeping your code modular will save a lot of work and make your code easier to read. Instead of doing everything in a large block, break it up into separate pieces that do specific smaller jobs.

 

DON’T:

 

procedure WelcomeMessage()

  - Hi, I’m FriendBot!

  if !Exist(G_USER_PROPS.favoriteFood)

    - What is your favorite food?

   ? It is FOOD=AFood

      G_USER_PROPS.favoriteFood = FOOD

      - Thanks!

      if !Exist(G_USER_PROPS.favoriteBand)

        - And what is your favorite music band?

        ? It is BAND=ABand

          G_USER_PROPS.favoriteBand = BAND

          - Great, thanks!

 

 

DO:

 

function UserFavFood()

  if Exist(G_USER_PROPS.favoriteFood) && G_USER_PROPS.favoriteFood ne ""

    return G_USER_PROPS.favoriteFood

  return 0

 

function UserFavBand()

  if Exist(G_USER_PROPS.favoriteBand) && G_USER_PROPS.favoriteBand ne ""

    return G_USER_PROPS.favoriteBand

  return ""

 

function AskUserFavFood()

- What is your favorite food?

? It is FOOD=AFood.

? My favorite food is FOOD=AFood.

    - Thanks!

  return FOOD

 

function AskUserFavBand()

  - What is your favorite music band?
  ? It is BAND=ABand.
  ? My favorite band is BAND=ABand

    - Great, thanks!

  return BAND

 

function UserFavorites()

  if !UserFavFood()

    G_USER_PROPS.favoriteFood = AskUserFavFood()

  if !UserFavBand()

    G_USER_PROPS.favoriteBand = AskUserFavBand()

  return G_USER_PROPS

 

procedure WelcomeMessage()

  - Hi, I'm FriendBot!

  G_USER_PROPS = UserFavorites()

 

This means more coding initially, but each piece can be used again. In the example below, the CheckMenu function checks a given restaurant to see if their menu contains a food type.

 

? Would I enjoy restaurant RESTAURANT=ARestaurant?

  if CheckMenu(RESTAURANT, UserFavFood())

    - There is a high chance you will like it.

  else

    - I’m not sure, since your favorite food is not on the menu.

 

In the example above, you could also recommend a restaurant based on the user’s favorite food. The recommendation may come from a list of restaurants that are advertising with your bot.

 

Also, include patterngroups in your project to avoid copying the same natural language handles over and over.

 

                Example:

 

     patterngroup WhatIsSomeonesEMailAddress<Someone>

? What is Someone’s email address?
? Where can I send an email to Someone?

? How do I send email to Someone?

? How do I send Someone email?

? How do I email Someone?

 

You can call the patterngroup in your matching like this:

 

+- What is Bill’s email address?

     answers WhatIsSomeonesEMailAddress<Bill> 

8月2日

Best Practices for Developing a Windows Live Agent: part 7

Be Careful When Using Public Variables

When using stored public variables, be careful not to lock the profile and write to them too often. If many users try to lock the profile at once, there is a risk of the agent timing out. Only use public variables if it’s necessary for that information to be available to all users of your agent. Only use stored public variables if that information must be maintained over a long period of time (otherwise, use unstored public variables for which you do not need to lock the profile).

 

Use Clear Naming Conventions

When naming your procedures, variables, functions,  etc., use a naming convention that will make sense to everyone—not only those who have worked on your project. If someone outside of your development team needs to troubleshoot an issue, you want him/her to get some idea of what your code does by merely reading the names used.

 

Do not:

 

function Horoscope1(VAR)

  return VAR.day + "-" + VAR.month + "-" + VAR.year

 

Do:

 

function GetHoroscopeDateFromObject(DATE)

  return DATE.day + "-" + DATE.month + "-" + DATE.year 

7月25日

Best Practices for Developing a Windows Live Agent: part 6

Create a Clear and Concise Welcome Message

A welcome message should welcome the user and give a brief explanation of the scope of the agent. Keep the copy to a minimum so as not to overwhelm the user.

 

                Example:

 

      Hi Britt! I'm *AstroBot*. I can provide you with all of your Astrology needs and more!

 

If you would like to know what I do, just ask me!

 

When your user returns to the agent, rather than giving the user the initial welcome message, consider creating a welcome back message:

 

         Example:

 

    Welcome back, Britt! It’s good to see you again!

    

    What would you like to do today? For ideas, just ask me!

 

Give your Agent a Help Page

Give your users a central place to get information and help.  Creating a help page puts each feature of your agent in one place that is easily reachable by your users. Create matching for words and sentences such as:

 

     ? Help

     ? What can you do?

     ? Home

     ? I’m confused

 

A typical help message looks like this:

 

Here are some things you can ask me:

 

What are some movies in my area? 

Search for movies by genre.

Change the location of my search.

 

You can make it more engaging and exciting:

 

Here are some of the things that I can do for you, Britt!

 

·         Get *info* such as news, weather and sports

·         Visit my *library* including a dictionary, a thesaurus and world facts

·         Have *fun* with hangman, 4-in-a-row, reversi and more

·         Use *tools* like Web search, reminders and conversions

·         *Join in* - create a poll, tell me about a crush, leave a message and more

·         See *what's new* - I've got something new to tell you about now.

 

Just tell me what you want to do, and we can start!

 

 

Catch What Your Agent Doesn’t Know

For those questions your agent doesn’t know the answer to, you should use a “catch” message that matches on the default =Catch subpattern.  A catch message should be concise and point your user to the help message.

 

          Example:

 

    I'm sorry, I didn't understand your question. Please ask again using as few words as necessary.

               

    You can ask for help if you are not sure what to do.

 

Make it fun:

 

           Whoa! That’s a little outside of my scope. Come again?

 

    If you’re lost, just ask for help!

  

7月16日

Best Practices for Developing a Windows Live Agent: part 5

Remember User Information

Take advantage of stored user variables to remember things that you can use in the future to better personalize the long-term user experience.

 Example:  

stored variable G_USER_FAVORITE_COLOR = ()

procedure AskUserFavoriteColor()

  - What is your favorite color?

  ? =Anything

    - That doesn’t sound like a color to me, I hope we can try again. What is your favorite color?

    restart dialog

? It is COLOR=AColor.
  ? My favorite color is COLOR=AColor.

  G_USER_FAVORITE_COLOR = COLOR

    - Thanks! I’ll remember that your favorite color is COLOR.

 The above code assumes that AColor is a valid subpattern.

7月9日

Windows Live Agents Training Videos


 
Video: Windows Live Agents SDK Training -  Part 1

 
Video: Windows Live Agents SDK Training - Part 2

 
Video: Windows Live Agents SDK Training - Part 3

 
Video: Windows Live Agents SDK Training - Part 4
7月6日

Best Practices for Developing a Windows Live Agent: part 4

Use Canonical Questions

A canonical question establishes the most concise, “representative” question for a topic.  If a user asks an ambiguous question, the agent responds with a clarification request using the canonicals for each matched topic. Note that only one question should be marked as a canonical in a topic.

          Example:

   +- What is my horoscope?

 ? What is my horoscope?

 ? Zodiac

 

 +- What is my Zodiac sign?

 ? What is my Zodiac sign?

 ? Zodiac

 User: zodiac

   Agent: What did you mean?

   1 What is my horoscope?

   2 What is my Zodiac sign?

7月2日

Best Practices for Developing a Windows Live Agent: part 3

Use Dialogs

Dialogs create a more interactive experience and help the user to feel like he/she is driving the conversation.

         Example:

     - Hey, I have really cool games. You wanna see them?

     ? Yes.

       - Here are my games:

         <empty/>

         Hangman {*}

         Word Scramble {*}

         Reversi {*}

     ? No.

       - OK! Next time you want to see my games, just type “games.”

6月27日

Best Practices for Developing a Windows Live Agent: part 2

Create Good Subpatterns

Subpatterns are one of the most powerful NL recognition features in the BuddyScript language. They allow you to write efficient, reusable code. Many subpatterns are defined in various packages in the Vocabulary directories for each language in BuddyScriptLib. Have a look at the subpatterns created there before you create your own. Many general parts-of-speech and “chat” subpatterns, as well as subpatterns for industry-specific terminology, are defined there.  Create subpatterns for anything else you foresee your end users chatting about – product names, peoples’ names, place names, etc.

 NL-brick Subpatterns

When you define a subpattern as an NL-brick, every element of the subpattern that is recognized at maximum strength is a candidate to replace sections of your NL handles.  This is a very useful property, but use it carefully. If you want only certain elements to replace the natural language in an NL-brick subpattern, make the other elements score lower.

 Define subpatterns as NL-bricks by putting them within NL-brick zones. If your project is derived from the WLATemplate, add NL-bricks in “YourAgent/YourLanguage/CustomSubpatterns.pkg,” which already contains an NL-brick zone.

                Example:

                begin properties SubpatternsAreNLBricks // Start of NL brick zone

    

     ### “n” prefix: Noun Stems
     subpattern nBike + (bike|bikes)

subpattern nMotorcycle
+ (motorcycle|motorcycles)
+ motor (cycle|cycles)

subpattern nMotorbike
+ (motorbike|motorbikes)
+ motor =nBike

### “ns” prefix: Noun Senses

     subpattern nsMotorcycle

     + (=nMotorcycle|=nMotorbike)

     + =nBike {score=MACRO_ MEDIUM_SCORE}

    

     end properties SubpatternsAreNLBricks // End of NL brick zone

In the above example, the word “motorcycles” in the natural language handle “? How much do motorcycles cost?” will be replaced by = nsMotorcycle, but the word “bike” in the natural language handle  “? Can I ride my bike to work?” will not be replaced by =nsMotorcycle as “bike” does not match at maximum strength in the subpattern. Therefore, if the user types “How much do bikes cost?” it will match on “? How much do motorcycles cost?” (albeit with a lower score), but if the user types “Can I ride my motorcycle to work?” it will not match on “? Can I ride my bike to work?”

                Example:

     begin properties SubpatternsAreNLBricks

     subpattern nsNewYorkCity

     + (new york [city]|manhattan)

     + nyc {spellcorrect=no}

       return “New York City”

     end properties SubpatternsAreNLBricks

 

     subpattern ACity

     + CITY=NewYorkCity

     + CITY=SanFrancisco

     + CITY=Chicago

       return CITY

 In the above example, the  =ACity  subpattern should not be an NL-brick because you would not want “New York City” in a natural language handle such as “? What are some good restaurants in New York City?” to be replaced by =ACity (if it were, the user query “What are some good restaurants in Chicago?” would match on “? What are some good restaurants in New York City?”)

  In general, specifying some subpatterns as NL-bricks and leaving others as non-NL-bricks (the default behavior) allows you great control over how subpatterns are used in your matching.

  Binding Subpatterns to Variables

Bind subpatterns to variables whenever you need to use the value returned by a subpattern, either as a parameter in a data request, to store interesting user data, or simply to make the agent’s response “smarter.”

                Example:

     - Where do you live?

     ? I live in CITY=ACity

     ? CITY=ACity

        STATE = GetStateForCity(CITY)

        USER_LOCATION = CITY

       - Wow! I love CITY! That’s in the state of STATE, right?

                User: I live in nyc

                Agent: Wow! I love New York City! That’s in the state of New York, right?

6月22日

Best Practices for Developing a Windows Live Agent: Part 1

Today we will start a series on best practices for developing a Windows Live Agent (WLA). Here we go:
 
Use the WLATemplate Project as a Starting Point

The WLATemplate Project (“C:\Program Files\Colloquis\Colloquis SDK\Projects\WLATemplate“) is a generic project you can quickly customize into your own Agent. Simply launch the instantiation script “StartInstantiation.bat” and follow the instructions to start a new Agent in the right directory.

Use Natural Language Handles

The fastest and most efficient way to get your Agent to recognize User questions is to add Natural Language Handles. NL Handles are analyzed against the libraries of rephrase rules and synonym subpatterns defined in your project and in the BuddyScriptLib packages (included in the SDK) and are transformed into regular “+” style matching patterns.

Example:

This natural language handle:

? What can you do?

is rephrased as:

? What do you do?

and “patternized” into these subpatterns:

+ =qsWhat =vDo =You =vDo  

This user query:

Tell me what you do

is rephrased as:

What do you do?

Case and punctuation are stripped from queries, so:

what do you do

matches perfectly on the patternized natural language in the agent.

Natural language handles should be:

  • Concise—ideally 15 words or less and one sentence
  • Unambiguous
  • Grammatically correct and properly punctuated (including question marks or periods)
  • Free of spelling mistakes
6月19日

Welcome

Welcome to the Windows Live Agents Team blog!

 

This blog will be used to post announcements, tips, and documentation supplements to help planning, development, deployment, and support of your agent. Our SDK is currently in an Alpha release stage, accessible by only a very small audience. Please look out for a public beta coming later this year! This blog and other community resources should help to prepare and give you a very rough idea of some features even before you have full access to the SDK.

 

Comments are always welcome, but to effectively engage the community and product group in discussion, please post your questions to our forum found at: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=1687&SiteID=1