| Windows Live Ag... 的个人资料Windows Live Agents照片日志列表 | 帮助 |
|
4月23日 Microsoft Partner ProgramHello Developers,
As we are nearing the public release of our new Visual Studio SDK and Partner on-boarding system, we wanted to make sure that we expose our developers to all the benefits from Microsoft in terms of certifications. We realize there are a large number of Agent developers that make their business through the Agent platform and we are working closely with the rest of Windows Live Platform to get you the recognition you need with your customers. In the future, Windows Live will have a program specifically within the Microsoft Partner Program (MSPP) and you’ll be able to fully leverage that designation. Membership in MSPP is free with graduated levels of certification (fee and skill based). In the past, there was a notion of “MSN Bot Certified”, but because of business and technology reasons, this designation has essentially expired and won’t be recognized by Microsoft. Windows Live is moving forward with MSPP as the official method of partnering and we encourage you to start MSPP enrollment at your earliest convenience.
We look forward to building out this developer community with you! 4月17日 So, you think you know everything about Buddyscript?So, you think you know everything about Buddyscript?
Well, let’s see how much of such a statement is true. Try to answer this short quiz! If you score all of them it doesn’t mean you are an expert, but you could say you are getting there ;-)
1- Let’s talk about matching. Say we want to match precisely on full URLs (and only full URLs) during a conversation, which one of the following cases would be the way to go: a) subpattern AFullUrl /^www`.`S+`.(com|fr|org|net)$/ {minlength=3, example=”www.microsoft.com”} b) subpattern AFullUrl + www =Anything (com|fr|org|net) {canskip=”no”, minlength=3} c) subpattern AFullUrl www.=Anything.(com|fr|org|net) {canskip=”no” minlength=3}
2- Nl-bricks? Only one of the following affirmations is true: a) “NL- bricks” along with “regular subpatterns” are processed during the “patternization” process, but “NL-bricks” have precedence over “regular subpatterns”. b) “NL- bricks” are the minimum expression of a meaning unit, and are “patternized” into “regular subpatterns” at compile time. c) “NL-bricks” are “skippable”, as opposed to “regular subpatterns” that need to have the property {canskip=”yes”}
3- Defining macros in Buddyscript, only one of the following statements is true: a) If the code contains any line breaks, it should be placed immediately below the first line of the statement. If you want your macro to contain an empty line, add a line containing only the character “\”. The first empty line defines the end of the macro. b) If you want your macro to contain an empty line, add a line containing the character “\” at the end of the line before. I will add an empty line right between this and the following line. The first empty line defines the end of the macro. c) Macro definitions can’t contain line breaks. The first empty line defines the end of the macro.
4- Only one of the following statements is true: a) The “always match as” statement allows you to associate a variable name with a particular subpattern throughout a group of patterns only. b) The “always match as” statement allows you to associate a variable name with a particular subpattern throughout a group of patterns, a package, or an entire domain. c) The “always match as” statement allows you to associate a variable name with a particular subpattern in a routine, or in a multi-line of code.
5- What do you know about composite subpatterns? Only one of the following is true! a) Composite sub-patterns let you assemble multiple static subpatterns together, so that a candidate string is filtered through the first subpattern, then the result of this filtering is passed to the second one, etc. b) The minimum number of compositions is one, but there’s not a limit on the maximum number of compositions you can add. c) The default values for the properties of a composite subpattern are those of the outer-most subpattern, since it's going to be evaluated last.
6- Hum, have you ever tried to create datasources? Let’s see if you know which one of the following is true: a) The “postprocess-block“ of a datasource is a BuddyScript routine used to set the offset and the total count of rows when the “preprocess-block” didn't return any of those values, or if the value returned is not accurate. b) “Expire” is a common property to the different datasource kinds. This information allows the platform to remember (cache) the result for a certain time. By default, expire is set to “now” (information is not stored). If you want the information to be cached, set it to “never”, or when the information won't be valid anymore (in 5 minutes, in 2 days, etc.) c) Datasources are BuddyScript tools to access external data. The external data retrieved can be accessed through many methods, including gateway calls, SQL queries, SOAP methods, datatables, etc.
7- How about rephrasing rules? We want to use the property “MACRO_BEST_ONLY” when: a) We need to make sure the rule it’s only applied when it matches best from all of the other rephrasing rules. b) We want the rule to be applied only when it matches best, and no other rule can be applied after. c) We want to avoid matching on rules scoring lower than 80.
Solutions: 1-a, 2-b, 3-a, 4-b, 5-b, 6-c, 7-a If you failed the quiz, and you want to know more about Buddyscript, besides this blog you can browse the Windows Live Agents forum in MSDN, and of course read the documentation shipped with the platform. 4月7日 Quality Analysis AuditsAudits are an important piece to the ongoing maintenance of your agent. The purpose of auditing is to take a look at how users are interacting with the agent, and identify ways to improve the experience. Any issues that you uncover in audits should be addressed in a regularly scheduled agent update window. There are two types of audits—Query and Session. Session audits answer the question “Was this session satisfactory to the user?“ and are best for evaluating the overall user experience. Did the user find the information he or she was looking for? Was the answer complete? Did the user express any frustration that was not appropriately addressed? As a client, do you feel that the interaction served your purpose in deploying the agent? Query audits answer the question “Was the query answered by the correct topic?” and are ideal for fine-tuning the Natural Language comprehension and finding commonly unanswered queries. Once your agent launches, it’s preferred that you audit every 2-3 days for the first two weeks and then once every 2 weeks for the remainder of the agent’s life. Of course, it is up to you to determine how often you audit your agent. If your agent has a ton of traffic, you might want to audit more often. If you choose not to audit your agent, the agent will never improve and you will supply users with a poor experience. Auditing your agent will not only improve it, but improve your development style and guidelines for future agents. Auditing Guidelines Session AuditSuggestions for how to score sessions in a session audit:
Query Audit* All internal query audits should use the option to "Only include queries relevant to natural language." Suggestions for how to score queries in a query audit:
4月2日 Customizing WLATemplate
Ideally you start creating a new Agent using the WLATemplate! Detailed information on how to instantiate a new project [currently available languages are: English, Chinese (simplified), French, German, Italian, Japanese, and Spanish] from the WLATemplate: http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!446.entry
As you can imagine, this is only the beginning... In order to make your Agent a success and stand out in the crowd, you have to customize it to whatever you want your Agent to be, simple things like giving your Agent a personality and making "him" or "her" more natural. Here are a bunch of former blog posts that talk about exactly that:
Creating a Personality Spec - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!317.entry
Customizing Chat - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!230.entry
Welcome Messages and ABGreetingProc - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!408.entry
Changing PSM, Friendly Name, and Icon - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!315.entry
Best Practices for Developing a Windows Live Agent:
Part 1 [Use the WLATemplate Project as a Starting Point] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!149.entry
Part 2 [Create Good Subpatterns] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!150.entry
Part 3 [Use Dialogs] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!151.entry
Part 4 [Use Canonical Questions] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!152.entry
Part 5 [Remember User Information] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!156.entry
Part 6 [Create a Clear and Concise Welcome Message] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!160.entry
Part 7 [Be Careful When Using Public Variables] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!163.entry
Part 8 [Make Your Project Modular] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!164.entry
Part 9 [Make Your Agent Chatty] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!166.entry
Part 10 [Conclusion of Best Practices Series] - http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!176.entry
----------------------------------------- Blog post contributor(s): Mirco
3月27日 Logging Topics and CategoriesOne of the most powerful parts of the BuddyScript platform is its extensible reporting suite. This article will describe how to log data relating to what your agent is saying, in a form that can be displayed in the Usage Reporting tab of the web console.
Category and topic logging is something that has been used for agent projects developed "internally," but the code to do this was never exposed to partners in the libraries that ship with the platform. This is likely to change in future releases, but in the meantime feel free to implement the code here.
A topicis a routine with user input, agent output. For example, we may have a routine that associates matching for "how are you" to various outputs saying "I'm doing fine." This is a topic.
A category is a grouping of topics, often associated with a single DDL file. For example, we might have a category for all the topics that handle queries relating to the agent as a person, like "how are you", "where did you come from", etc.
When we associate a title to a topic, we can log that title and keep a tally of how many users hit that topic. When we associate a topic to a category, we can also tally how many times users hit that category. Thus, we will have data relating to where user queries are matching the most, at two levels of granularity.
To get this working, we need to:
1. Define categories 2. Assign topics to categories 3. Log the topics and categories
Here is an example of how to do this:
Say we have a domain for English conversational routines, Topics/EN-US/Conversation.ddl.
At the top of the Topics/EN-US/Conversation.ddl, we add this:
{category="Conversation (English)" label="CategoryDefinition"} + _ignore_me do nothing
This defines a new category called “Conversation (English)”. Next, we need to associate routines to this category. Here is an existing routine:
{label="? Hi" uid="MyAgent-1195066867"} ? Hi - Hi! - Hello there! - Hi there. - Greetings! nop - How are you? - What's new with you? - How are things? insist - Good to know.<br/> - Interesting.<br/> - Glad I asked.<br/> - Really? <br/>
The key-value pairs between brackets ("label" and "uid") were automatically generated by the KMS as part of its tracking mechanism. If they are not present, don't worry about it.
Add this (the order of key-value pairs doesn’t matter):
{category="Conversation (English)" title="Hi" label="? Hi" uid="MyAgent-1195066867"}
Still, we are just labeling the routine, and nothing will happen unless we log it. The platform will automatically do some simple logging, but we should override that to use categories. Look at this part of the libaries, in Required/ABProcs:
######################################## ## ## ABPostQueryLog ## ## This procedure is called at the end of a user query ## and can be overriden to log specific information. ## ########################################
procedure ABPostQueryLog() SYS.Log.ScriptFile[SYS.History[0].Match.ScriptFile]++
processing ABPostQueryLog post-process call ABPostQueryLog()
So, if we just want to know what file is being hit, right now that is being logged as “ScriptFile”, which we could add to usage_config.xml and show in Usage Reporting in the console. However, a better approach is to define categories for every ddl, and assign titles and categories for each topic in the ddl. Then we can override the logging behavior like so:
### Logging
variable G_LAST_LOGGED_QR_RECEPTION_TIME=0
procedure LogCategory(CATEGORY) SYS.Log.Categories[CATEGORY]++
procedure LogTopic(TOPIC_TITLE) SYS.Log.Topics[TOPIC_TITLE]++
procedure PerformTopicLogging() if G_LAST_LOGGED_QR_RECEPTION_TIME == SYS.History[0].Execution.QRReceptionTime exit G_LAST_LOGGED_QR_RECEPTION_TIME = SYS.History[0].Execution.QRReceptionTime if SYS.History[0].Match.RoutineId == "" exit TOPIC_TO_LOG = "" CATEGORY_TO_LOG = "" ROUTINE_ID = SYS.History[0].Match.RoutineId if !ROUTINE_ID exit TOPIC_KEYS = GetRoutineKeys(ROUTINE_ID) if Exist(TOPIC_KEYS["menu"]) exit if !Exist(TOPIC_KEYS["title"]) exit TOPIC_TO_LOG = TOPIC_KEYS["title"] if !Exist(TOPIC_KEYS["category"]) CATEGORY_TO_LOG = "undefined" else CATEGORY_TO_LOG = TOPIC_KEYS["category"] call LogTopic(TOPIC_TO_LOG) call LogCategory(CATEGORY_TO_LOG)
procedure overrides ABPostQueryLog() call PerformTopicLogging()
Note that all we are really doing is piggy-backing on the existing logging mechanism, using it to write the values associated with the “title” and “category” keys for each routine the agent matches to. These values are written to the SYS.Log variable, a special object used for logging. Anything written to SYS.Log is fair game to show in the reporting console, but to do so, we also need to make alterations to the usage_config.xml file, to accommodate SYS.Log.Categories and SYS.Log.Topics and specify how the data should appear. Editing the usage_config.xml file is beyond the scope of the article and will be covered later, so let the WLA team know if you need help setting it up. 3月21日 Data Consumption in BuddyscriptAn important component in creating a good agent is to access and display rich content. Often, this content comes from sources such as data feeds, flat files, SQL databases, or SOAP/RES methods.
There are two common components in Buddyscript that is needed to access, store and retrieve data. They are datatables and datasources.
Datatables are two-dimensional arrays of data that is preloaded into memory. For those of you familiar with SQL databases, these are tables that are pinned in memory. The common sources where datatables are loaded from are from a hard coded list, tab-delimited flat files, SQL tables, or an external source that can return back an array of data.
The datatable statement looks like this:
datatable tablename [propertyoptions] load column1 [, column2...] from source retrievalmethod
For example, to load from a hard-coded list, the statement might look something like this:
datatable MovieGenreTable load GenreCode {index="exact"}, GenreName {index="exact"} from 1, Action 2, Adventure 3, Comedy
This loads a datatable called MovieGenreTable with 3 rows of two columns, GenreCode and GenreName. Both columns are indexed, using an 'exact' index. From the BuddyScript documentation, the types of indexes you can use are as follows:
• exact: the two entries need to be exactly equal. => "exact" = "exact" but "Exact" != "exact" • case-insensitive: the two entries can have different case => "exact" = "eXaCt" but "exact" != "exact?" • thawed: the "thawed" version of the two entries need to be equal => "that's exact" = "$$ThaT %% S&&ExAcT!!", "François" = "fRAncois". This is because the thawed version of both "That's exact!" and of "$$ThaT %% S&&ExAcT??" is "that s exact".
It's slightly faster to access a column indexed as exact, than a column indexed as case-insensitive. thawed indexed columns are the slowest.
To load from a tab-delimited file would look like this:
datatable CitiesMetaTiered load value*, score from file Data/CitiesMetaTiered.txt
This loads a datatable called CitiesMetaTiered into a two column table, the columns being value and score. The file has two columns separated by a tab. The table never expires from memory. The asterisk after the column (as in value*) is a shortcut for an index, with the property of exact.
Accessing the datatable
The way to access the datatable is as follows:
list of variables = get column1, [column2, ...] in datatableName [where columnX is value [and columnY is value2...]] [limit startIndex, count]
Note that this syntax looks fairly similar to the SQL SELECT statement.
For example, using the above datatable definitions, to retrieve data from the datatable called CitiesMetaTiered, a typical statement might look like this:
SEARCHVAR = 'x' V, S = get value, score in CitiesMetaTiered where value is SEARCHVAR limit 1
This will put into the variables V and S the value and score content in the CitiesMetaTiered datatable where the value is 'x'. It will put into the variable the first row that it finds.
Datasources
Datasources are a way to define how data looks when retrieved from an external source. The most useful and common ways to use a datasource is to define a web data feed page, a datatable, or a SQL data table.
For example, to define a web datafeed page, an example might look like this:
datasource dsProductRecall() => ititle, idescription, ipubDate, ilink http http://www.cpsc.gov/cpscpub/prerel/prerelhousehold.xml simple xml channel // title // description // link // language // lastBuildDate // webMaster item {loop="content"} title description pubDate link // guid
This looks at an XML feed called http://www.cpsc.gov/cpscpub/prerel/prerelhousehold.xml.
The XML has master information and item repeating information. The datasource captures node information into the output variables. The output variables are strictly positional based on what is captured from the feed.
The indentation in the datasource definition has to match the same parent-child level of the web page. The {loop="content"} indicates that the variable and all the children variables will repeat and the content put into an array. The // are comment statements, in this particular case, some variables are commented out because the code has no use for the particular data.
In some instances, you would use a datasource instead of a datatable. For example, if you only need part of a table in memory at any one time, it is much better to use a datasource than a datatable.
Here is an example of a datasource that loads from a datatable.
datasource DatGetAllCityInfo(ZIP) => city, state, region, country table get city, state, region, country in CombinedGeography where id is ZIP
This datasource takes in a parameter called ZIP, and will output 4 columns, city, state, region, and country. It gets its output from a datatable, getting city, state, region, country from the datatable called CombinedGeography, and filters for those values in the id column where it is equal to the passed-in value called ZIP.
You can then access a datasource just like a function. For example, using basic Buddyscript syntax:
? What products have been recalled lately? TITLE, DESCRIPTION, PUBDATE, LINK = dsProductRecall() show 5 * Here are the results for product recalls : - TITLE, DESCRIPTION, PUBDATE, LINK
you can also access the datasource function with the OBJ <= datasourcename() statement. This puts the data into an object. When there are multiple rows of data you can indent a block below the datasource call and the block will be looped on. This will give you better display control over each line.
By Carl Moy 3月3日 Tracking ClickThroughsMany clients want to see how much traffic their agent is pushing back to their client’s website. By integrating ClickThrough tracking in your agent, you will be able to track Clicks and Impressions. Impressions are how many times a URL is presented to the user. Clicks are how many times a URL is clicked on by the user.
In order to track ClickThroughs in your project, we must wrap a redirect URL around the real URL. You will need to contact the Agents team to set up a redirect URL for you. Please note that your Agents contact does not personally set up the redirect URL—they must send a request to the Hosting Department. Redirect URL requests can take several days. The Project Manager will send you the redirect URL and you will add the following to your project: 1. Include the following package in a central file, such as YourProject/Shared/YourProject.pkg. This package includes all of the procedures and functions needed to track clicks and impressions in your agent.
lib:/Shared/Utilities/ClickThroughUtilities
2. Override the following function in the same file as above and return the redirect URL your PM sends you. function overrides GetClickThroughBaseUrl() return "http://zz.rdir.us"
When you want to track a URL in your project, you will use the following function: Click ClickThroughLink(“URL”, "here", " ---> ", "TEXT") URL will be replaced with the URL you want to track. TEXT will be what you want displayed in the Usage Reports. For example, if you are tracking the URL http://movies.msn.com/, you will include the following code: Click ClickThroughLink(“http://movies.msn.com/”, "here", " ---> ", "MSN Movies") In the agent output, it will display like so: Click here ---> http://zz.rdir.us/ct?K/0 The Agents team will set up the Usage Reporting site so you can view ClickThrough tracking. There will be a high level graph, displaying Total Clicks, Impressions, etc.:
There will also be separate sections for Impression and Click breakdowns. For example:
2月22日 How to get your Agent to speak another language than EnglishOur blog posts to date have been talking about tips and tricks to develop better, more unique and more reliable Windows Live Agents...in English. So, let's find out what other languages are available.
First of all you have to instantiate a new Agent using StartInstantiation.bat. This script will generate an Agent that includes all the languages we currently support (see below for a list of available languages) out of the box. With our 5.0 release, this will be replaced by a new project wizard! All you have to do now, is to adjust your Agent's DLS (Domain List File) so you're including the right DDLs (Domain Definition File) for the language of your Agent. Some adjustments in the Agent's BFG (Runtime Configuration) are necessary as well. Detailed step-by-step instructions on how to instantiate an Agent that only speaks language are to find below (#2).
1. What languages are currently supported
The latest SDK Beta ships with agent libraries in the following languages:
Coming soon:
The library structure for each language is the same:
Language · Core o Rephrase Rules o Lexicon & Vocabulary o Dates, Numbers, etc. Handles recognition and display of strings for date, time, numbers, etc. · Extensions o Chat o User Info o Etc. · Utilities A variety of different utilities to take advantage of. Scope of these utils is to make your Agent more unique, smarter, and to add features such as the activity window. o Math, Randomness... o Activity Window o Output processing & formatting... o Etc. 2. Step-by-step to instantiate an Agent that speaks only German
Again, with our upcoming 5.0 release, these steps will be replaced by a new project wizard!
· Run the script StartInstantiation.bat and follow its instructions. We'll assume you instantiated a project named YourProjectName. If you installed the SDK in the default directory, you can find it in "C:\Program Files\Colloquis\Colloquis SDK\Projects\WLATemplate\StartInstantiation.bat" · Open YourProjectName.dls o Remove sections for languages you don't need. o Replace references to English files to reference your language. o See #3 for an example for a DLS for a German speaking Agent. · Open YourProjectName.bfg and remove the sections for languages you don't need. · Delete the folders (languages) you don't need · Open Project in SDK, start compilation, and type "Hallo!"
· Read README.txt to customize your project. 3. YourProjectName.dls - Example <domain-list import="/Shared/SharedSettings.dls">
<deployments> <deployment id="dev" /> <deployment id="Deploy" /> <deployment id="DeployKMS" /> </deployments> <file-sets> <file-set id="SharedRephrasings"> <domain> lib:/Shared/Core/Rephrasing/*.ddl </domain> </file-set> <file-set id="SharedFiles"> <domain> /Variables.ddl </domain> <domain> /Shared/Overrides.ddl </domain> <domain> /Shared/Personality.ddl </domain> <domain only-in="KnowledgeManagement"> /Shared/Tests.ddl </domain> <domain> /Shared/Chat/*.ddl </domain> <domain only-in="KnowledgeManagement"> lib:/Shared/Core/Vocabulary/VocabularyAnalysis.ddl </domain> <domain only-in="KnowledgeManagement"> lib:/Shared/Utilities/TestUtilities.ddl </domain> </file-set> <file-set id="German"> <domain> /German/Chat/*.ddl </domain> <domain> /German/UserInfo/*.ddl </domain> </file-set> <file-set id="KnowledgeManagementFiles"> <file-set-ref id="German" /> <file-set-ref id="SharedFiles" /> </file-set> </file-sets> <language-sets> <language-set id="German"> <rephrasings> <file-set-ref id="SharedRephrasings" /> <domain> lib:/German/Core/Rephrasing/*.ddl </domain> <domain> /German/CustomRephrasings_de.ddl </domain> </rephrasings> </language-set> </language-sets> <buddy id="AutomatedAgent" name="Automated Agent"> <file-set-ref id="KnowledgeManagementFiles" /> <domain> /German/Main.ddl </domain> <domain> /German/Overrides.ddl </domain> <domain only-in="KnowledgeManagement"> /German/Tests_de.ddl </domain> </buddy> <buddy id="KnowledgeEditor" name="Knowledge Editor"> <file-set-ref id="KnowledgeManagementFiles" /> <domain> /German/Main.ddl </domain> <domain> /German/Overrides.ddl </domain> <domain only-in="KnowledgeManagement"> /German/Tests_de.ddl </domain> </buddy> <buddy id="YourProjectName_de" name="Windows Live Agent Template - German"> <file-set-ref id="German" /> <file-set-ref id="SharedFiles" /> <domain> /German/Main.ddl </domain> <domain> /German/Overrides.ddl </domain> <domain only-in="KnowledgeManagement"> /German/Tests_de.ddl </domain> </buddy> </domain-list> 4. Some example Windows Live Agents to talk to in other languages than English -----------------------------------------
Blog post contributor(s): Mirco 2月21日 Integrating Buddyscript and Web Services Part IThis is part I of a two-part blog entry. IntroductionThis posting will go over various methods of inserting a Web Service call in Buddyscript code as a datasource. We will assume that you already have a working Web Service and Buddyscript project. For my example, I have a Web Service called Service1 running on my local machine. Background InformationOur HelloWorld FunctionOur very basic HelloWorld Web Service function simply takes an input parameter and outputs “you said <input>”.
Start Your Web ServiceBefore you begin, you must start your Web Service. Note the web address. My web service is running at http://localhost:54908/Service1.asmx. GET Web Service CallStep 1: Determine Web Service Call FormatTo send requests to, and receive responses from, your Web Service, you need to figure out how to call it. We did this by going to our Web Service’s URL in a web browser. For the GET method, the Web Service XML code looks like this: The following is a sample HTTP GET request and response. The placeholders shown need to be replaced with actual values. Request: GET /Service1.asmx/HelloWorld?input=string HTTP/1.1 Host: localhost
Response: HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length
<?xml version="1.0" encoding="utf-8"?> <string xmlns=”http://tempuri.org/”>string</string> Step 2: Create the Datasource in BuddyscriptThe GET method is the easiest one to use in Buddyscript, and therefore is the recommended method of doing Web Service calls. To create the datasource that will call the HelloWorld function, the Buddyscript code looks like this: // GET DataSource HelloWorld datasource HelloWorldGet(INPUT) => HelloWorldResult http http://localhost:54908/Service1.asmx/HelloWorld?input=INPUT simple xml string The result of this function is the string returned by the HelloWorld Web Service function call.
Step 3: Use the DatasourceTo use the datasource we just created, we can do something like this: ? HelloWorldGet INPUT=Anything RESPONSE = HelloWorldGet(INPUT) - GET Web Service Response: "RESPONSE". So if you type the query: HelloWorldGet get test The Agent would respond with: GET Web Service Response: “you said get test”. POST Web Service CallStep 1: Determine Web Service Call FormatOnce again, we went to the URL of our Web Service in a web browser to figure out the format of a POST call. The XML looks like this: The following is a sample HTTP POST request and response. The placeholders shown need to be replaced with actual values. Request: POST /Service1.asmx/HelloWorld HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded Content-Length: length
input=string
Response: HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length
<?xml version="1.0" encoding="utf-8"?> <string xmlns="http://tempuri.org/">string</string>
Step 2: Create the Datasource in BuddyscriptUsing the POST method to call a web service is not much more difficult than using a GET. To create the datasource, the Buddyscript code looks like this: // POST DataSource HelloWorld datasource HelloWorldPost(INPUT) => HelloWorldResult http http://localhost:54908/Service1.asmx/HelloWorld postdata input=INPUT simple xml string Once again, the result of this function is the string returned by the HelloWorld Web Service function call.
Step 3: Use the DatasourceUsing the POST HelloWorld datasource we just created is done in exactly the same way as using the GET HelloWorld datasource. So for the following routine: ? HelloWorldPost INPUT=Anything RESPONSE = HelloWorldPost(INPUT) - POST Web Service Response: "RESPONSE". If we type the query: HelloWorldPost post test The Agent would respond with: POST Web Service Response: “you said post test”. For the Integrating Buddyscript and Web Services Part II, please click here. Integrating Buddyscript and Web Services Part IIThis is a continuation of Integrating Buddyscript and Web Services Part I. SOAP Web Service CallStep 1: Determine Web Service Call FormatBy going to our Web Service’s URL in a web browser, we can see that the Web Service XML code for a SOAP call looks like this: The following is a sample SOAP 1.1 request and response. The placeholders shown need to be replaced with actual values. Request: POST /Service1.asmx HTTP/1.1 Host: localhost Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://tempuri.org/HelloWorld"
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <HelloWorld xmlns="http://tempuri.org/"> <input>string</input> </HelloWorld> </soap:Body> </soap:Envelope>
Response: HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <HelloWorldResponse xmlns="http://tempuri.org/"> <HelloWorldResult>string</HelloWorldResult> </HelloWorldResponse> </soap:Body> </soap:Envelope>
Step 2: Create the Datasource in BuddyscriptUsing the SOAP method for calling the Web Service is the most restricted and least recommended. However, if you would like to use SOAP, the following is an example how to do so: // SOAP DataSource HelloWorld datasource HelloWorldSoap(INPUT) => HelloWorldResult soap proxy http://localhost:54908/Service1.asmx name HelloWorld namespace http://tempuri.org/ action http://tempuri.org/HelloWorld input string input = INPUT simple xml HelloWorldResult The datasource will return the output of the HelloWorld Web Service function call.
Step 2.1 Manually Create the Datasource in BuddyscriptInstead of using the method in Step 2 above, you can also manually create the Web Service call using Buddyscript. This is the longest and most difficult (and tedious) way to query the Web Service. To do this, we first have to build the request. The code to do that looks like this: // Build HelloWorld XML Query function BuildGatewayAPIPostData_HelloWorld(INPUT) POST_DATA = '<?xml version="1.0" encoding="UTF-8" ?>\n' POST_DATA = StringConcat(POST_DATA, '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">') POST_DATA = StringConcat(POST_DATA, ' <soap:Body>') POST_DATA = StringConcat(POST_DATA, ' <HelloWorld xmlns="http://tempuri.org/">') POST_DATA = StringConcat(POST_DATA, ' <input>',INPUT,'</input>') POST_DATA = StringConcat(POST_DATA, ' </HelloWorld>') POST_DATA = StringConcat(POST_DATA, ' </soap:Body>') POST_DATA = StringConcat(POST_DATA, '</soap:Envelope>') return POST_DATA You can see how each line of code adds a line of the Request XML onto the POST_DATA string. Now that we can build a request, we need to be able to use it. The following datasource will send the request to the Web Service and receive and process the response: // Call HelloWorld Web Service and get response datasource HelloWorldSoap(INPUT) => HelloWorldResult {expire="now"} preprocess // Build the Request string POST_DATA = BuildGatewayAPIPostData_HelloWorld(INPUT) http http://localhost:54908/Service1.asmx header Host: localhost Content-Type: text/xml; charset=utf-8 SOAPAction: "http://tempuri.org/HelloWorld" postdata {encode=no} POST_DATA simple xml Envelope Body HelloWorldResponse HelloWorldResult The preprocess section is used to set variables that will be used in the following sections. The http section describes the source. The source can be one of the following: abgw, absql, table, file, http, soap, or Buddyscript. The section format varies depending on the source type. The simple xml section is called the filter. It describes the filtering to be performed on the incoming data in order to build a table to return. The filter can be abgwtab, abgwxml, simple xml, xslt, or Buddyscript. The content of this section depends on the filter type. For our particular datasource, the URL under http is the URL of our Web Service. The data in the header section comes from the Web Service web page that we have open (see Step 1). The simple xml section lists the tags in the Response hierarchy (see Response XML code in Step 1). The result, stored in <HelloWorldResult>, will be returned.
Step 3: Use the datasourceOnce again, we use the SOAP datasource in the same way as the GET and POST datasources. Here is a sample routine that can be used with either method used above for querying the Web Service: ? HelloWorldSoap INPUT=Anything RESPONSE = HelloWorldSoap(INPUT) - SOAP Web Service Response: "RESPONSE" The query: HelloWorldSoap soap test Would return: SOAP Web Service Response: “you said soap test” ConclusionThe ability to call Web Services from your Buddyscript project is a very powerful tool. Following these steps will allow you to quickly and easily set up your Web Service calls using a variety of different methods, and will afford you much greater flexibility in your Agents. 2月11日 Using Activity Window feature in WL Messenger to make your Agents stand out1. What is an Activity Window (AW) and how can it be used to enhance Agents? The Activity Window is an area in the Messenger Client that allows Windows Live Agents developers to provide rich content to the user to make the Agents experience much more engaging than simply conversing through the conversation window. This can also greatly increase the interaction between the user and agent. Activity Windows can be used to enhance Agents by providing rich content such as Animation, Games, Videos, Charts, Tables, etc… that are not possible to display in the Conversation Window. Activity Windows is also able to accept input (just like any web page can) through mouse or keyboard, and send this data to the Agent, which can respond in turn. Note: AWs are a feature of Windows Live Messenger and has a lot more functionality to offer that are unrelated to Windows Live Agents. For more information about Activity Windows, please follow this link: http://msdn2.microsoft.com/en-us/library/aa751014.aspx Activity Windows are a feature of Windows Live Messenger. This document only addresses how to use AW in the context of Windows Live Agents. For more information about Activity Windows, please follow this link: http://msdn2.microsoft.com/en-us/library/aa751014.aspx
2. What you need to implement AWs for Windows Live Agents: a. Basic knowledge of the following technologies: i. HyperText Markup Language (HTML) ii. BuddyScript (scripting language used to add logic to Agents) iii. Javascript (JS) * iv. eXtensible Markup Language (XML) * b. Familiarity with the Messenger Activity API Process. c. A hosting site to host your Activity Window pages and JS code. d. An application provisioned for your specific Activity Window by Messenger. (please see section 7 for more information on this) e. Last but not the least, you need the user’s consent to display the AW. (The end user needs to Accept the invitation from your agent to start an Activity Window). * These are needed only if using the Data Interchange method of interacting with the AW. Currently this method is only available to internal Agents developers but should be available to external Agents developers in a future release.
3. Basic Idea of how User à Agentà AW interaction works: a. First, anapplication ID is provisioned by Microsoft points to your specific Agent’s AW. This enables Windows Live Messenger to know which Activity it needs to call when the user accepts the invitation. b. When the user asks a question for which the Agent has an answer that can be displayed in the AW, the Agent will send the output data to the AW application (hosted in the hosting site that you provide) instead of the conversation window. c. Once the AW application receives the data, the code in the AW uses the data to display the content requested. d. In certain cases, it is also possible for the AW code to send data back to the Agent.
4. AW Implementations used in Agents: There are several ways to achieve the functionality shown in the above diagram. The ones used by WL Agents team so far include the following: a. Page Drive Samples of Agents using this method include Encarta Instant Answers agent and MSN Music agent. b. Data Interchange using Javascript Object Notation (JSON) and XML* Samples of Agents using this method include College Football Guru agent. *As of this time, this method is still in Beta and available only to internal Agents developers. We expect to make this available to external Agents developers in a future release.
5. The Page Drive method
Taking the example from MSN Music agent, it uses the AW to display Artist information when the user asks for it.
BuddyScript code is used to match on the user input, and if the user input is understood to be a request for Artist info, we search our list of Artist info.
Sample Code:
subpattern AnArtist
<Your subpattern of an artist here>
? What do you know about ARTIST=AnArtist?
ARTIST_ID = ArtistIDFromArtistName(ARTIST)
If ARTIST_ID < 0
- Sorry, I don’t have info about ARTIST :-(
exit all
- Let me take you to the MSN Music page about ARTIST =>
call PageDrive(StringConcat(“http://music.msn.com/artist/?artist=, ARTIST_ID, “#”))
BuddyScript code that calls the Page Drive procedure
In the above sample code, this is the handle that is executed when someone asks a question about an artist. The code will get an Artist ID and then call the PageDrive procedure which simply takes the URL string, starts up the AW process, and (assuming the user accepted the AW invitation), displays the page indicated by the URL in the AW.
The PageDrive procedure is part of the WL Agents Activity Window Utilities API. This main package for handling AW functions in Agents is called WLMActivityUtilities.pkg and can be found under Modules\Shared\Utilities directory.
On the AW side, there is also JavaScript code that handles the request. Once the AW receives the request, the following JS code (embedded in an HTML file) is triggered.
Sample JS Code:
function Channel_OnDataReceived() {
var myData=window.external.Channel.Data;
DisplayDebugInfo("received data: " + myData);
if (myData=="READY") {
Channel_OnRemoteAppLoaded();
return;
}
// Input sent by the BuddyScript code follows the format:
// param1=value1\nparam2=value2 ...
var myDataArray=myData.split("\n");
var destinationURL="";
for (var i=0; i < myDataArray.length; i++) {
if (myDataArray[i].indexOf("url=")==0) {
destinationURL = myDataArray[i].substring(4);
} else if (myDataArray[i].indexOf("debug=")==0) {
debugInfo = myDataArray[i].substring(6) * 1; // * 1 to make sure we have a number
}
}
if (destinationURL!="") {
// Go to the new location
DisplayDebugInfo("URL=" + destinationURL);
top.mainFrame.location.href = destinationURL;
}
}
Snippet of Javascript code that handles data from the Agent’s PageDrive procedure
To learn more about the different JS functions provided by the Window Live Messenger Activity API, please see their documentation.
6. The Data Interchange method (a Sneak Peek)
Oftentimes it is not sufficient and certainly less interesting to simply use the AW to page drive to a URL. After all, AWs should be engaging and should provide rich content and functionality in order to increase user interaction time with your agent.
Windows Live Agents provides another way to implement AW in your Agent that allows for more complex AW displays. This is accomplished through data interchange using Javascript Object Notation (JSON) (please see http://www.json.org for more info) and eXtensible Markup Language (XML).
In a nutshell, here is how this works:
Note: The Data Interchange method is currently not available for use as of this time by external Agents Developers because it is still in Beta. More detailed information will be posted on the Windows Live Agents Team blog as soon as this feature becomes available for external Agents developers.
7. All about the AW Application ID
The AW Application ID allows the MSN Messenger Client to determine which Activity it should load when the user accepts your Agent’s invitation to start an Activity Window session. This application ID can be obtained by contacting the Window Live Gallery team at http://gallery.live.com and submit a request. Please click here to read a post for more information regarding this process.
The msgrp2p.xml file contains information that the Messenger client uses to load your AW application. It looks like this:
<?xml version="1.0"?>
<Entry>
<EntryID>99999999</EntryID>
<Error />
<Locale>en-us</Locale>
<Kids>1</Kids>
<Page>1</Page>
<Category>50</Category>
<Sequence>10</Sequence>
<Name>Windows Live Agents Sample Activity</Name>
<Description>Windows Live Agents SDK Activity Description</Description>
<URL>http://localhost/activity.html</URL>
<IconURL />
<PassportSiteID>0</PassportSiteID>
<Type>App</Type>
<Height>498</Height>
<Width>498</Width>
<Location>side</Location>
<MinUsers>2</MinUsers>
<MaxUsers>2</MaxUsers>
<PassportSiteID>0</PassportSiteID>
<EnableIP>False</EnableIP>
<ActiveX>False</ActiveX>
<SendFile>False</SendFile>
<SendIM>False</SendIM>
<ReceiveIM>True</ReceiveIM>
<ReplaceIM>False</ReplaceIM>
<Windows>True</Windows>
<MaxPacketRate>120</MaxPacketRate>
<UserProperties>False</UserProperties>
<ClientVersion>6.0</ClientVersion>
<AppType>0</AppType>
<Hidden>false</Hidden>
</Entry>
The elements to take note here are the ones bolded and displayed in red. The P4 Application ID that is provided to you by the Messenger team goes into the EntryID. The Name should be the name of the Activity that you are developing, and will appear in the Window Title of the AW. The Description is a description of the Activity, and the URL element specifies where the Messenger client will take the user once he accepts the invitation to start an AW.
Shown below is sample BuddyScript code that the Agent uses to get the Application Name and Application ID that will be passed to the AW in order to indicate which AW Application should be loaded.
function overrides MSNSLPGetAgentMainP4ApplicationName()
return " Windows Live Agents Sample Activity "
function overrides MSNSLPGetAgentMainP4ApplicationId()
return "99999999"
procedure MSNSLPSendInvitationToOpenP4Application(APP_ID, APP_NAME)
if LogActivityUsage()
call LogActivityInvitationMade()
call IncrementIgnoredInvitationAttempts() // This invitation is ignored until an event accepts or rejects it
SESSION_INVITE_STRING = StringConcat("msnslp invite session ", APP_ID, ";1;", APP_NAME)
ABSendServiceEvent(SESSION_INVITE_STRING)
Note: For testing purposes, in order to see the Activity that you are developing even before you get it provision, you can put the EntryID value of 7, and provide correct values for Name, Description, and URL. Then, restart your Messenger client. When it starts up, you can talk to your agent, accept an invitation, and your Messenger client will automatically send you to the URL that you specified in the msgrp2p.xml.
For more information about this, please refer to Windows Live Messenger Activity SDK.
---------------------------------------------------------------------
Blog post contributor(s): Alan Chan
2月4日 Auto-EnumerationBuddyScript comes with a feature that numbers a list and associates actions to each number, called enumeration, which is useful for drawing menus.
Read this first for background: https://buddyscript.colloquis.com/docs/SDKWin/st_re030.html
In conversation, enumeration look like this:
Let's look at the procedure that displays this menu:
We can ignore the TOPIC_TO_EXCLUDE flag. The important part is what's in the curly braces -- sometimes there's text, sometimes an asterisk. If the braces contain text, that text will be executed as a query. For example, in the menu above, if the user types the number "2", the query "City Life" will be executed just as if the user typed "City Life" and not "2". Presumably there is a topic that matches on the query "City Life", and if so, the output associated with the matching pattern is displayed.
If someone types "6", the query executed is "Special Event Highlights". The asterisk in the braces is a wildcard that is replaced with the text in the output.
There are two other common things to put in the enumeration braces. One is an "action," and looks like this:
- I can answer your questions using any of the following MACRO_COMPANY_NAME sites: nop - MACRO_COMPANY_NAME Australia {action=Australia()} An action is basically a mini-procedure named and called within the scope of a procedure. We call the action within the procedure with the "action=ActionName(PARAM)" within the braces. One problem with this approach is that user inputs will only match to the enumerated list once. That is, if you typc "1", the action is executed, but if you then type "2", it will be as if you were merely typing the number 2.
To get around this, you can call a procedure from within the braces.
setagentisrobot {call SetAgentIsRobot()} setagentismale {call SetAgentIsMale()}
setagentisfemale {call SetAgentIsFemale()}
setagentage {call SetAgentAgeFromMenu()}
setagentisadult {call SetAgentIsAdult()}
setagentisteen {call SetAgentIsTeen()}
setagentisyoungadult {call SetAgentIsYoungAdult()}
setagentisneutral {call SetAgentIsNeutral()}
setagentischeerful {call SetAgentIsCheerful()}
setagentisplayful {call SetAgentIsPlayful()}
setagentisedgy {call SetAgentIsEdgy()}
In this case, the user can pick a number to execute the procedure, keep talking about something else, then pick another number to pick another procedure, and so on. 1月28日 Wecome Messages and ABGreetingProcA Welcome Message is the first message an agent displays to the user after the session begins. As such, it deserves special attention. The Welcome Message serves two purposes:
Here's an example: Hi Tom, I'm SmarterChild! I'm your new robot friend. I give you conversational access to news, weather, movie times and lots more. I can also play games or just chat! During the course of our conversations you may see sponsored messages. These messages have the word "sponsorship" at the end. Sponsors help me remain free of cost to you! To learn more about sponsored messages, click here ---> http://web.smarterchild.com/ct?60oTHi/0I can't wait to show you what I can do, but first I'd like get to know you a little. May I ask you a few general questions? (To do this later, type "skip." You can also skip any question.) First, SmarterChild introduces himself and explains what he is, a robot friend that can chat, play games, and provide information. Next he provides an explanation about sponsored messages that appear during the conversation, setting the expectation early on so that users are not surprised to see such messages, and telling them why they appear. Then, he guides the user into a questionnaire. The example above is the "first message ever" between the agent and the user, so it includes a lot of information. A message like this is the first impression the agent gets to bring users back again and again, and is the best place to explain what it is and what to do continue the conversation. When the user does come back, we don't necessarily want to show the same lengthy introduction. Rather, the agent should display a "welcome back" message that shows the agent remembers the user, and possibly provides a short reminder of what the agent does and what the next steps are. Here's an example of a succint "welcome back" message: Hi, Tom. Nice to see you again. I'm here for all your autos needs. Type "home" to see what you can ask. The Welcome Message is displayed in the ABGreetingProc procedure. Here's the first half of it: The FROM_USER_ARRIVES flag is set when the user opens the conversation window. The NEW_USER flag is set when the user has never talked to the agent before. So, this part of the procedure is the "first message ever," and of course the default text should be overridden. You should also consider overridding the DisplaySomeExampleQuestionsEnglish()procedure.procedure overrides ABGreetingProc(FROM_USER_ARRIVES, NEW_USER)
SYS.Matching.ActiveLanguageSet = "English"
if NEW_USER
// Make sure to adapt this if your Agent is not English US (example: call SetCultureCodeToEnglishUK())
call SetCultureCodeToEnglishUS() // FRHNB: Can't have this in ABStartSessionProc, see bug 2975
// FRHNB: Temporary workaround bug where an MSN Bot contacts people out of the blue, because an icon information request is mistaken for a user arrives request.
- Hello UserName(), this is the default first message of the WLA Template. My developer can customize it in /English/Overrides.ddl.
<blank/>
Here, s/he can implement an initial interview and ask you questions, for instance what content/locale do you want to use:
nop
- MACRO_COMPANY_NAME Australia {Use MACRO_COMPANY_NAME Australia.}
MACRO_COMPANY_NAME Canada (English) {Use MACRO_COMPANY_NAME Canada.}
MACRO_COMPANY_NAME UK {Use MACRO_COMPANY_NAME UK.}
MACRO_COMPANY_NAME US {Use MACRO_COMPANY_NAME US.}
nop
- <blank/>
You can also display some example questions:
call DisplaySomeExampleQuestionsEnglish()
exit all
The other branch of the procedure looks like this, for those users who are not new:
else
if !LanguageIsEnglish()
Here we set the culture code if it hasn't been set, and display the "welcome back" message. In addition, if we are displaying the welcome message because the user simply opened the window (FROM_USER_ARRIVES), we append additional text remind the user the agent is ready to go. 1月18日 Simple Presentation SettingsThere's no reason to make your agent stick with whatever default style the IM client chooses. Mix it up a little by changing a few presentation settings. In particular, the SYS.Presentation variable.
Here is an example of setting the SYS.Presentation variable, which is normally done when the session begins :
SYS.Presentation.Encoding.In = "utf8"
SYS.Presentation.DefaultFontColor = "red" SYS.Presentation.DefaultFontFace = "Arial" SYS.Presentation.DefaultFontSize = 2 This should be pretty self-explanatory, but there are a couple of gotchas.
First, in Messenger you can only manipulate the presentation at the message level -- that is, you can't change the color of individual words or lines.
Second, changing the font size in Messenger has no effect whatever on what the other person sees in their client. This applies whether you are a bot or a human :).
1月11日 Restricting Users Based on AgeSometimes an agent’s content and purpose is inappropriate for certain age groups, specifically younger audiences. For example, if your agent markets a brand of beer, you may want to restrict users under 21 from chatting with the agent. We developed an agent for Match.com (datingbot@botmetro.net), which is an online dating site for people 18 and over. We noticed that many people under the age of 18 were chatting with the agent. We decided to ask the user’s birth date at the beginning of the conversation and if the user is under 18, we don’t allow him/her to chat with the agent. You will want to stores users’ birth dates. You will then create a function that checks whether we have the user’s birth date when they begin a conversation with the agent. For example:
function GetBirthday() if Exist(G_USER_PROPS.Birthday) return G_USER_PROPS.Birthday return ""
A returning user who is over 18 will not have to enter his/her birth date. You will add the following code to your overridden ABGreetingProc:
procedure overrides ABGreetingProc(FROM_USER_ARRIVES, NEW_USER) + SOMETHING=AnythingVeryStrong if !GetBirthday() - You must be at least 18 years old to interact with me. <empty/> What is your date of birth? Please enter your date of birth in MM/DD/YYYY format. while !GetBirthday() ? My birthday is BIRTHDAY=ADateAsNumbers {score=110} + BIRTHDAY=ADateAsNumbers {score=110} AGE = GetAgeFromBirthday(BIRTHDAY) if AGE < 18 - Sorry! You have to be 18 or older to talk to me. while 1 + =AnythingPerfect - Sorry! You have to be 18 or older to talk to me. restart dialog Once we know the user is under 18, he/she will get the same message over and over no matter what he/she types. If you have another agent developed and live that is appropriate for all ages, you may want to suggest the user add that agent to his/her Contact List. In the live agent, it looks like this:
MSN Dating Bot says: You must be at least 18 years old to interact with me.
What is your date of birth? Please enter your date of birth in MM/DD/YYYY format. Britt says: 05/15/1999 MSN Dating Bot says: Sorry! You have to be 18 or older to talk to me. Britt says: Come on! MSN Dating Bot says: Sorry! You have to be 18 or older to talk to me. 12月26日 Follow up questions from TrainingHow do developers enable Multi-User conversation: In the SDK, change the command line option in your BFG file for enabling Multi-User conversation (<multi-user> on|off <multi-user>), under MSM-MSN settings. This will allow an Agent to make use of the button on the Messenger Client chrome and “invite” another user to join the conversation.
How can developers integrate Windows Live Alerts: Currently, this feature is only available for Agents that are built and hosted by Microsoft. We’ll post a blog entry when this is made publically available.
How do we do more reporting on Activity Window (P4) usage: The Agent Foundations team has this on their near term roadmap for external release. Developers will be able to grab statistics from AW use, including time spent on the window. We’ll post a blog entry when this is made publically available.
When does a session time-out? If a conversation has gone inactive for 15 minutes, the session will close and any new messages will constitute a new session.
How do developers bring in datasources: http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!222.entry
How do developers detect which client version of Messenger is running? http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2550244&SiteID=1&mode=1
Does the Activity Window (P4) work on Mac Messenger? Unfortunately, it does not at this time. We’ll post something when we get more updates from that team.
Can Agents make use of Windows Live Calendar? The APIs are not currently available. We’ll post a blog entry when developers can make use of them.
How do we update Dynamic Display Pictures, etc? http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!178.entry
Is there support for LDAP access? Not at this time. No immediate plans to enable this now.
For the generic pointers about Agent testing: http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!221.entry http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!219.entry
Are there plans for VOIP integration? The Agents team will be working with the Windows Live Messenger team to take advantage of their integration efforts. Please watch this blog for any future updates.
Skype integration for Agents? We don’t have support or plans for that protocol at the moment.
Have trouble with the trial SDK? After installing the SDK, if you have trouble instantiating a new project or viewing the contents of the solution explorer, please to the following:
1. Uninstall Windows Live Agents SDK 2. Reset settings using the following steps:
1. Go to menu “Tools” 2. “Import and Export Settings” (see figure 1) 3. Select “Reset all settings” radial button 4. Choose “Just reset settings, overwriting my current settings” 5. Highlight “General Development Settings” 6. Click “Finish”
Figure 1
3. Make sure to pick C# as the new default settings when Visual Studio is launched again 4. Close Visual Studio and install the Windows Live Agents SDK. The problem should now be solved, and are working on fixing this bug for the 5.0 release of our platform, which is the Beta release of the SDK. 12月20日 Plan - Code - TestIt's useful to step back and think in terms of the high-level process for developing an agent, the way we organize our work, and how we approach complex technical problems. Here's a rough outline of one approach.
Stories, symphonies, movies, and transatlantic flights all have at least three things in common: a beginning, middle, and end. Approach your project in the same way. It's tempting to start with a minimal set of requirements, fire up the IDE, and start coding, but this way leads to endless problems down the road. You need a solid beginning. You need a PLAN.
Plan
Planning is, let's face it, a pain. It's fun to brainstorm, to think of pie-in-the-sky ideas and how easy they will be to execute. But before you start, you need to write something down.
First, you should at the very least write a SPECIFICATION. This will force you to figure out what it is you're making, what it will do, and what problems you anticipate. For the purposes of describing an agent, it's important to define what the conversation will look like. In addition to descriptions of features, include example sessions, use-cases, and other scenarios. If there are external dependencies, list them. If there are security, privacy, and internationalization concerns, go into detail. The important thing here is coverage -- this document will be your reference for development, a tool to help structure and drive your thinking, and a de facto "contract" which all the stakeholders will sign off on as the last word on the project's scope.
Second, you should DESIGN the technical aspects of the agent. Visualize each feature in terms of modular components talking to each other via APIs, and diagram this out. Like a spec, this will help you think the problem out, and also serve as a reference later. The more granular you can be here, the better. This is your blueprint. Tape it to the wall.
Spend half your time on planning, or your project will take twice as long.
Code
With design in hand, coding should be easy, right? Well, if everything goes according to the design, it is... Keep a few principles in mind:
1. Get the easy stuff working. Instead of starting with the most daunting tasks, start with tasks that are necessary but straightforward.
2. Get small parts to work. Break the problem into small chunks, and make each chunk work in isolation.
3. Make a schedule. Instead of winging it, use a schedule to figure out what tasks you will do when, approximately. This will help you determine dependencies, and will set the expectations of those waiting to see the final product.
Test
If you don't test, you might as well assume the agent is broken, because it probably is. And if it isn't, you don't know it isn't. Your spec should include a test plan, and this plan should include both automated and user tests.
Automated tests are covered elsewhere (http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!219.entry and http://windowsliveagents.spaces.live.com/blog/cns!5BCD45E519E07634!221.entry), but keep a few things in mind for testing in general.
- Test for functionality. This is straightforward -- you test to make sure the various features of the agent work. But this isn't enough.
- Test for code coverage. Your tests should hit all the code in the agent.
- Test for edge cases. If you are expecting a numeric input, what happens if someone types the name of their dog in Chinese? Test for bad input and situations where the user doesn't follow the rules.
- Test for performance. Figure out what happens under load. Not usually applicable to the agent itself, but to the web services the agent accesses.
- Test for security.
- Engage non-technical users for user tests. You are too close to the project to be a valuable user. Get other people with fresh eyes to look at it -- they will provide the most valuable feedback.
Whatever you do, don't just sit down without a sense of direction. Structuring your work like this not only saves time and aggravation, but gives you a higher-quality product. 12月19日 Thanks for attending training!Thanks to all the developers and partners who attended our developer training in London last week. It was great to meet so many folks from around the world (and put names to faces!). The slides from the presentation are now posted on SkyDrive:
http://cid-5bcd45e519e07634.skydrive.live.com/browse.aspx/London%20Training%20December%202007 Look for another blog posting soon with answers to all the questions from the training. 12月13日 Creating a Personality SpecCustomizing
chat outputs in your agent is important and creating a well-defined personality
spec will make the process of chat customization easier. A thoroughly
customized personality will entertain users and make your agent stand out among
the others.
Many agents are created by more than one developer/programmer. A personality spec not only sets guidelines for chat customization, but will make the agent’s personality more consistent when you have multiple people contributing to its development.
Summarize Your Agent’s Personality Write a few paragraphs summarizing your agent’s personality. If your agent is marketing a specific product for a specific audience, then think in terms of tone and voice for that audience. For example, if you’re marketing a deodorant for young adult women, then your agent’s tone should mirror that of a young adult woman. Also think about the agent’s relationship to the user. Does the agent act as an older sister type or a peer to users? Is the agent funny or serious and informative?
What does your agent do for a living (other than live in a cage as an agent)? Does your agent have any hobbies? Quirks? A specific dialect?
Example: Below is the agent personality summary created for MovieScout (moviescout@botmetro.net), which is an agent that provides users with movie show times.
Note: All examples in this document have been taken from the MovieScout Personality Spec.
Summary: The agent is a middle-aged movie critic. He is snotty and pretentious. He has a weakness for romantic comedies. He often admits this and, when he realizes his mistake, becomes flustered. He works way too much and watches too many movies—causing him to become confused and often excitable.
(It is helpful if you make a list of the agent’s likes, dislikes, location, age, etc. The more specific you get, the better!)
Example: Age: 45-50 Sex: Male Location: Hollywood, CA Likes: Hollywood endings, romantic comedies, center seats, popcorn, soda, flat screen TVs, opening nights Dislikes: Loud cell phones, tall people sitting in front of him, people who have weird laughs, slurp soda, and eat popcorn with their mouths open. Favorite Actress: Reese Witherspoon Favorite Actor: Russell Crowe Favorite Movie: Too many to decide Favorite Food: Popcorn and soda
Create Example Chat Overrides Creating a few example chat overrides will help you and your team get a sense of the agent’s voice and tone before you start customizing the chat. Choose at least 10 of the most popular chat topics and customize them.
Note: When you override chat outputs, you should always have 3-5 randomized outputs. Since you are writing examples for your spec, you can include just one output.
Example: procedure overrides ILikeYouOutput() - Well isn’t that pleasant! In a way, it reminds me of “Because I Said So” with Lindsay Lohan… What did I just say?! Oh boy, what’s gotten into me? I absolutely abhor romantic comedies!
procedure overrides HowMuchDoYouLikeMe(LIKE_LOVE="like") - I like you as much as I love romantic comedies… <empty/> I mean, um, as much as I love Morgan Freeman in “Gone Baby Gone.”
procedure overrides WhatColorIsTheSkyAnswer() - That’s like asking if Paris Hilton is a real actress. I think you know the answer to both questions.
Create an Example Conversation The best way to get a sense of your agent’s voice is to write an example conversation between the agent and the user. Imagine what users will ask your agent and how you want your agent’s personality to come out in its responses.
Example: Note: Your example conversation should be longer than the one below, emulating a 5 minute conversation from start to finish.
Tom: Hi! MovieScout: Thank you for joining me again, Tom. We had a most pleasurable time previously.
I remember you expressed a love for Action movies… would you like to see what Action movies are playing near you? Tom: Yes
… Agent displays Action movies for Tom.
Tom: What movies do you like? MovieScout: I only prefer very serious and dry movies, like “My Left Foot.”
But OMG! Did you see “The Heartbreak Kid”? It was super cute (please don’t tell anyone I just said that). Tom: Haha MovieScout: What are you laughing at? Tom Cruise’s career? Tom: You’re funny MovieScout: Only as funny as a Jessica Simpson film.
Tom: What’s the last good movie you’ve seen? / What is good right now? MovieScout: I really really liked “High School Musical”! Oh, and “Dan in Real Life.” And “The Game Plan” rocked! <= based on last genre inquired about, and rating
Tom: Is Saw IV any good? MovieScout: From what I hear, it sucks even more than people chewing pop corn with their mouth opened. Here is the full review: …
Tom: I’m bored. MovieScout: Take some initiative, Tom. How about going to see Gone Baby Gone? It plays at the Embarcadero Landmark Theater in a couple hours. (based on last/favorite genre and rating) 12月7日 Changing PSM, Friendly Name, and IconHere are some ways you can switch your agent's PSM (personal status message, or contact card), friendly name, or icon.
Method One - Change the BFG
Make the service for your agent look like this, with contact-card, buddyicon, and friendly-name elements:
<service only-in="Deploy dualbox" type="MSN">
<login> mybot@hotmail.com </login> <password> crypto:somepassword== </password> <friendly-name> My Bot </friendly-name> <buddyicon> $_BFG_DIR/mybot.jpg </buddyicon> <contact-card> Ask me something interesting! </contact-card> </service> Advantage: The PSM, friendly name, and icon will always use the specified values when the agent server starts. Disadvantage: If you change any of these on the fly, they will revert back to the values in the BFG if the agent logs out and back in for any reason. Method Two - Create a Special Command
We can change the PSM, friendly name, or icon on the fly by creating a special command. For example:
+ (_reset|_set) friendly name MESSAGE=AnythingPerfect
if SYS.User.ScreenName == "authorized_developer@hotmail.com" if UserIsOnMSN() ABSendServiceEvent(setfriendlyname MESSAGE) - Friendly name changed to MESSAGE. else - Sorry, I can't change my friendly name if I'm not on MSN. Be sure to include the WLMUtilities package for sending events to Messenger.
Advantage: Authorized users can make changes to the bot on the fly simply by issuing a command.
Disadvantage: If the Messenger cloud becomes unavailable or the agent restarts at any time, changes made on the fly will be lost. Method Three - Manipulate Messenger Functions
As it so happens, the BuddyScript platform includes functions for overriding the PSM, icon, and friendly name, in the same package above, WLMUtilities.
// FRIENDLY NAME
// e.g. => function overrides WLMGetAgentFriendlyName() // return "Friendly name of agent" function WLMGetAgentFriendlyName() return MACRO_KEEP_DEFAULT_VALUE // ICON
// e.g. => function overrides WLMGetAgentIcon() // return "domains:/AgentName/image.jpg.png" function WLMGetAgentIcon()
return MACRO_KEEP_DEFAULT_VALUE // PERSONAL MESSAGE
// e.g. => function overrides WLMGetAgentPersonalMessage() // if SYS.Configuration.Filter eq "KnowledgeManagement" // this is how you can distinguish between "KnowledgeManagement" and "Deploy" mode // return "Your personal message" // return "" function WLMGetAgentPersonalMessage() return MACRO_KEEP_DEFAULT_VALUE Since we are overriding functions to make the changes, we can now do things like schedule the PSM and friendly name to change on certain days, or according to other conditions. Advantage: A lot of flexibility -- we can script changes to these things based on whatever conditions we want. Disadvantage: Takes some time for the PSM, icon, and name to propagate the Messenger network -- users may not see changes immediately, or at the same time. |
|
|