3.3. Playing with the Demo Web Services

So far in the previous tutorials we have not seen much of the actual web services (WSs) of the QALL-ME Framework. We have seen how they are deployed and how they are introduced to the QAPlanner but we have not directly worked with them ourselves. This will change in the following subsections: in 3.3.1: “Being the QAPlanner” we will manually reproduce what is automatically being done in the QAPlanner before we will show in section 3.3.2: “Using the Framework’s Components in Independent Java Applications” that the framework WSs are really independent components which can be easily integrated in other, non-QA Java applications. We then conclude this tutorial section in 3.3.3: “WS Invocations in the QueryGenerator” with a quick look at the internals of the quite complex QueryGenerator WSs or rather at how this WS internally calls implementations of the EntailmenTester and the Timex2SparqlConverter.

The previous tutorial in section 3.2 has shown you how to deploy your first QALL-ME Framework based QA system and how to feed it with a few test questions using the central QAPlanner WS. In doing so, the latter WS has been used as kind of a black box. Section 2.3.1: “Question Answering Workflow” has provided a conceptual view on the internal workflow of the QAPlanner but maybe you are interested in seeing what concretely happens under the hood of the QAPlanner implementation – possibly without looking at the source code of the implementation. This section will provide such insights; we will manually reproduce a nearly complete QA run as it is internally performed by the QAPlanner. For this we will again resort to the WS testing tool soapUI.

In this tutorial we will asume that the German question “Wo kann ich heute Abend in Alicante den Film Saw 5 sehen?” (“Where can I see the movie Saw 5 in Alicante tonight?”) has been asked somewhere in Alicante in the morning of December 11, 2008. As a SOAP request to the QAPlanner’s answerQuestion web method this inquiry might have looked like this (showing only the SOAP request body):

<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<qap:inquiry xmlns:qap="http://qallme.sf.net/xsd/qaplanner.xsd">
		<qap:question>Wo kann ich heute Abend in Alicante den Film Saw 5 sehen?</qap:question>
		<spatiotemporalContext xmlns="http://qallme.sf.net/xsd/qallmeshared.xsd">
			<location lon="-0.48" lat="38.35">ES</location>
			<time>2008-12-11T10:51:26</time>
		</spatiotemporalContext>
	</qap:inquiry>
</soapenv:Body>
According to Figure 2.1, after receiving such an inquiry, the QAPlanner tries to identify the question language. So this is the first step we have to manually perform, too.

In soapUI, open a new request for the getLanguage web method of the LanguageIdentifier WS and enter the above question. The result of the request will be an ISO 639-1 alpha-2 language code, hopefully “de” for our German question:

<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<languageCode xmlns="http://qallme.sf.net/wsdl/qallmeshared.wsdl">de</languageCode>
</soapenv:Body>
Now, after performing this step, the QAPlanner and we know that we have to use the language specific components for German for answering the given question.

The next step in the QA process is the annotation of entities. The EntityAnnotator is location dependent as it annotates entities like movie and cinema which are mainly relevant for the location at which a question is posed. Through reverse geocoding using the given location’s geocoordinates, the QAPlanner can find out that the question was posed in Alicante, Spain; as a fallback it may also use the provided country code (“ES”). So we choose the Spanish location subsystem and thus the Spanish EntityAnnotator and pass our German question to the annotateEntities web method of this annotator. The result is an <AnnotatedSentence> (cf. 4.2.1: “General Remarks”) in the SOAP response body:

<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<AnnotatedSentence xmlns="http://qallme.sf.net/xsd/qallmeshared.xsd"
		>Wo kann ich heute Abend in <annotation canonicalForm="Alicante" type="DESTINATION"
		>Alicante</annotation> den Film <annotation canonicalForm="Saw 5" type="MOVIE"
		>Saw 5</annotation> sehen?</AnnotatedSentence>
</soapenv:Body>

The annotated question sentence is then further processed in a TermAnnotator implementation. As TermAnnotator implementations are language dependent (cf. Figure 2.1), we have to use the German TermAnnotator implementation for our German question. The input for a request to the annotateTerms web method of the TermAnnotator is an <AnnotatedSentence> just like the one we have gotten in the response from the EntityAnnotator. So you can simply copy the whole <AnnotatedSentence> element from the previous response and paste it into the request body of the annotateTerms web method. Submitting this request should result in the same response as previously: there are no domain-relevant terms in the question, so no additional annotation is added here by the TermAnnotator.

The last annotation step is the annotation of temporal expressions using a language dependent TimeAnnotator; again we select the one for German. The request for the annotateTime web method again takes an annotated question sentence but additionally also the temporal context of the inquiry. Again we can copy the <AnnotatedSentence> from the previous response here. The temporal context information was given to the QAPlanner as a parameter and is internally just copied here; in our manual QA run we have to fill it by hand. The SOAP request body for our example will then look like this:

<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<tim:AnnotationRequest xmlns:tim="http://qallme.sf.net/wsdl/timeannotation.wsdl">
		<AnnotatedSentence xmlns="http://qallme.sf.net/xsd/qallmeshared.xsd"
			>Wo kann ich heute Abend in <annotation canonicalForm="Alicante" type="DESTINATION"
			>Alicante</annotation> den Film <annotation canonicalForm="Saw 5" type="MOVIE"
			>Saw 5</annotation> sehen?</AnnotatedSentence>
		<temporalContext>2008-12-11T10:51:26</temporalContext>
	</tim:AnnotationRequest>
</soapenv:Body>
As you may have guessed, the response is again an <AnnotatedSentence>; here’s the SOAP response body which should be equivalent to the one you have gotten:
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<AnnotatedSentence xmlns="http://qallme.sf.net/xsd/qallmeshared.xsd"
		>Wo kann ich <annotation canonicalForm="&lt;TIMEX2 VAL=&quot;2008-12-11TEV&quot;
		>heute Abend&lt;/TIMEX2>" type="TIMEX2">heute Abend</annotation> in <annotation canonicalForm="Alicante" type="DESTINATION"
		>Alicante</annotation> den Film <annotation canonicalForm="Saw 5" type="MOVIE"
		>Saw 5</annotation> sehen?</AnnotatedSentence>
</soapenv:Body>

By now we have collected enough information around the inquiry, so we can go ahead and try finding an answer to the inquiry.

According to Figure 2.1, the next step in the QA run is to generate a SPARQL query for the extraction of answers from the relevant local database. This is done in the language dependent QueryGenerator WS; we select the one for German and create a new SOAP request to the generateSPARQLQuery web method:

<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<quer:generateSPARQLQuery xmlns:quer="http://qallme.sf.net/wsdl/querygeneration.wsdl">
		<queryGenRequest>
			<AnnotatedSentence xmlns="http://qallme.sf.net/xsd/qallmeshared.xsd"
				>Wo kann ich <annotation canonicalForm="&lt;TIMEX2 VAL=&quot;2008-12-11TEV&quot;
				>heute Abend&lt;/TIMEX2>" type="TIMEX2">heute Abend</annotation> in <annotation canonicalForm="Alicante" type="DESTINATION"
				>Alicante</annotation> den Film <annotation canonicalForm="Saw 5" type="MOVIE"
				>Saw 5</annotation> sehen?</AnnotatedSentence>
			<spatiotemporalContext xmlns="http://qallme.sf.net/xsd/qallmeshared.xsd">
				<location lon="-0.48" lat="38.35">ES</location>
				<time>2008-12-11T10:51:26</time>
			</spatiotemporalContext>
		</queryGenRequest>
	</quer:generateSPARQLQuery>
</soapenv:Body>
All of the information that we have to provide in the request should already be known from previous steps: the first part is just a verbatim copy of the <AnnotatedSentence> response from the last annotator we have called. And the second part, the <spatiotemporalContext>, is the same as the inquiry context that was passed to the QAPlanner at the very beginning of the QA run. As expected, we get back a SPARQL query for our inquiry in response:
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<ns2:generateSPARQLQueryResponse xmlns:ns2="http://qallme.sf.net/wsdl/querygeneration.wsdl">
		<sparqlQuery><![CDATA[
		PREFIX qmo: <http://qallme.itc.it/ontology/qallme-tourism.owl#>
		PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
		PREFIX qma: <http://qallme.fbk.eu/ontology/qallme-answers.owl#>
		PREFIX fn: <http://www.w3.org/2005/xpath-functions#>
		CONSTRUCT {
		?cinema qmo:name ?cinemaName ;
		        a qmo:Cinema ;
		        qmo:hasPostalAddress ?pAddr ;
		        qmo:hasGPSCoordinate ?gps .
		?pAddr qmo:isInDestination ?dest ; 
		       qmo:street ?street .
		?dest qmo:name ?destName .
		?gps qmo:longitude ?longitude ;
		     qmo:latitude ?latitude ;
		     qmo:statusOfGPSCoordinate ?gpsStat .
		?movie qmo:name ?movieName ;
		       a qmo:Movie .
		?event qmo:isInSite ?cinema ;
		       qmo:hasEventContent ?movie ;
		       qmo:hasPeriod ?period .
		?period qmo:hasDatePeriod ?datePeriod ;
		        a qmo:DateTimePeriod ;
		        qmo:hasTimePeriod ?timePeriod .
		?datePeriod qmo:startDate ?date .
		?timePeriod qmo:startTime ?time .
		qma:AnswerInstance a qma:AnswersObject ;
		                   qma:hasAnswerValue ?cinema .
		}
		WHERE {
		?cinema qmo:name ?cinemaName ;
		        a qmo:Cinema ;
		        qmo:hasPostalAddress ?pAddr .
		?pAddr qmo:isInDestination ?dest .
		OPTIONAL { ?pAddr qmo:street ?street . } .
		?dest qmo:name ?destName .
		?movie qmo:name ?movieName ;
		       a qmo:Movie .
		?event qmo:isInSite ?cinema ;
		       qmo:hasEventContent ?movie ;
		       qmo:hasPeriod ?period .
		?period qmo:hasDatePeriod ?datePeriod ;
		        a qmo:DateTimePeriod ;
		        qmo:hasTimePeriod ?timePeriod .
		?datePeriod qmo:startDate ?date .
		?timePeriod qmo:startTime ?time .
		OPTIONAL { ?cinema qmo:hasGPSCoordinate ?gps .
		           ?gps qmo:longitude ?longitude ;
		                qmo:latitude ?latitude .
		           OPTIONAL { ?gps qmo:statusOfGPSCoordinate ?gpsStat . } . } .
		FILTER(?destName = "Alicante"^^xsd:string) .
		FILTER(?movieName = "Saw 5"^^xsd:string) .
		FILTER (((xsd:dateTime("2008-12-11T18:00:00") <= xsd:dateTime(fn:string-join(fn:string-join(xsd:string(?date),"T"),xsd:string(?time)))) && (xsd:dateTime("2008-12-11T23:00:00") >= xsd:dateTime(fn:string-join(fn:string-join(xsd:string(?date),"T"),xsd:string(?time)))))).
		}]]></sparqlQuery>
	</ns2:generateSPARQLQueryResponse>
</soapenv:Body>

With this SPARQL query string we now simply need to ask the location dependent AnswerPool for the answers. As the question was posed in Alicante, we choose the AnswerPool implementation for Spain: simply copy the SPARQL query string from the QueryGenerator response’s <sparqlQuery> element into a new request to the getAnswers web method of the chosen AnswerPool WS and you should get back a nice answer RDF graph for the original inquiry.

All these steps that we have now gone through manually are also made internally by the QAPlanner. The answer graph you have gotten as a result from our manual QA run should be the same as the answer graph that you will get for the same inquiry from the QAPlanner. Just test it.