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>
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>
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>
<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="<TIMEX2 VAL="2008-12-11TEV" >heute Abend</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="<TIMEX2 VAL="2008-12-11TEV" >heute Abend</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>
<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.