Skip to content

Commit 97f442e

Browse files
committed
Create DynamicQuestionAnswering.java
1 parent af57258 commit 97f442e

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
package net.b07z.sepia.sdk.services.uid1007;
2+
3+
import java.util.TreeSet;
4+
5+
import net.b07z.sepia.server.assist.answers.ServiceAnswers;
6+
import net.b07z.sepia.server.assist.assistant.LANGUAGES;
7+
import net.b07z.sepia.server.assist.data.Parameter;
8+
import net.b07z.sepia.server.assist.interpreters.NluResult;
9+
import net.b07z.sepia.server.assist.interviews.InterviewData;
10+
import net.b07z.sepia.server.assist.parameters.GenericEmptyParameter;
11+
import net.b07z.sepia.server.assist.services.ServiceBuilder;
12+
import net.b07z.sepia.server.assist.services.ServiceInfo;
13+
import net.b07z.sepia.server.assist.services.ServiceInterface;
14+
import net.b07z.sepia.server.assist.services.ServiceResult;
15+
import net.b07z.sepia.server.assist.services.ServiceInfo.Content;
16+
import net.b07z.sepia.server.assist.services.ServiceInfo.Type;
17+
import net.b07z.sepia.server.core.data.Language;
18+
import net.b07z.sepia.server.core.tools.Is;
19+
import net.b07z.sepia.server.core.tools.Sdk;
20+
21+
/**
22+
* Demonstration of a dynamic service with 3 steps: trigger activation - question input - answer or fail.<br>
23+
* Questions will be generated dynamically and not with predefined parameters.
24+
*
25+
* @author Florian Quirin
26+
*
27+
*/
28+
public class DynamicQuestionAnswering implements ServiceInterface {
29+
30+
//Command name of your service (will be combined with userId to be unique, e.g. 'uid1007.question_answer')
31+
private static final String CMD_NAME = "question_answer";
32+
33+
//Define some sentences for testing:
34+
35+
@Override
36+
public TreeSet<String> getSampleSentences(String lang) {
37+
TreeSet<String> samples = new TreeSet<>();
38+
//GERMAN
39+
if (lang.equals(Language.DE.toValue())){
40+
samples.add("Ich habe eine spezielle Frage.");
41+
//OTHER
42+
}else{
43+
samples.add("I have a special question.");
44+
}
45+
return samples;
46+
}
47+
48+
//Basic service setup:
49+
50+
//Overriding the 'getAnswersPool' methods enables you to define custom answers with more complex features..
51+
52+
@Override
53+
public ServiceAnswers getAnswersPool(String language) {
54+
ServiceAnswers answerPool = new ServiceAnswers(language);
55+
56+
//Build English answers
57+
if (language.equals(LANGUAGES.EN)){
58+
answerPool
59+
//the default answer
60+
.addAnswer(successAnswer, 0, "Here is what I found: <1>")
61+
//ask what the users wants to know
62+
.addAnswer(askForInput, 0, "What do you want to know?")
63+
.addAnswer(askForInput, 1, "Say again please.") //used on 2nd consecutive try...
64+
//found no answer
65+
.addAnswer(noAnswerFound, 0, "Sorry but it seems I have no answer to that yet.")
66+
;
67+
return answerPool;
68+
69+
//Other languages not yet supported
70+
}else{
71+
answerPool
72+
//the default answer
73+
.addAnswer(successAnswer, 0, "Das habe ich gefunden: <1>")
74+
//ask what the users wants to know
75+
.addAnswer(askForInput, 0, "Was würdest du gerne wissen?")
76+
.addAnswer(askForInput, 1, "Sag noch mal bitte.")
77+
//found no answer
78+
.addAnswer(noAnswerFound, 0, "Sorry, aber das kann ich wohl noch nicht beantworten.")
79+
;
80+
return answerPool;
81+
}
82+
}
83+
//We keep a reference here for easy access in getResult - Note that custom answers need to start with a certain prefix
84+
private static final String failAnswer = "error_0a";
85+
private static final String successAnswer = ServiceAnswers.ANS_PREFIX + CMD_NAME + "_success_0a";
86+
private static final String noAnswerFound = ServiceAnswers.ANS_PREFIX + CMD_NAME + "_no_answer_0a";
87+
private static final String askForInput = ServiceAnswers.ANS_PREFIX + CMD_NAME + "_ask_input_0a";
88+
89+
90+
@Override
91+
public ServiceInfo getInfo(String language) {
92+
//Type of service (for descriptions, choose what you think fits best)
93+
ServiceInfo info = new ServiceInfo(Type.plain, Content.data, false);
94+
95+
//Should be available publicly or only for the developer? Set this when you are done with testing and want to release
96+
//info.makePublic();
97+
98+
//Command
99+
info.setIntendedCommand(Sdk.getMyCommandName(this, CMD_NAME));
100+
101+
//Direct-match trigger sentences in different languages
102+
String EN = Language.EN.toValue();
103+
info.addCustomTriggerSentence("I have a special question.", EN);
104+
String DE = Language.DE.toValue();
105+
info.addCustomTriggerSentence("Ich habe eine spezielle Frage.", DE);
106+
107+
//Add some regular expression triggers if you like ...
108+
//info.setCustomTriggerRegX(".*\\b(a special question)\\b.*", EN);
109+
//info.setCustomTriggerRegXscoreBoost(4); //boost service a bit to increase priority over similar ones
110+
111+
//Parameters:
112+
113+
//This service has no fixed parameter. The question is instead generated dynamically inside the result handler.
114+
//We still need to define the custom parameter as optional though to extract it properly later:
115+
Parameter p1 = new Parameter(new SpecialQuestion());
116+
info.addParameter(p1);
117+
118+
//Answers (these are the default answers, you can trigger a custom answer at any point in the module
119+
//with serviceBuilder.setCustomAnswer(..)):
120+
info.addSuccessAnswer(successAnswer)
121+
.addFailAnswer(failAnswer)
122+
.addOkayAnswer(noAnswerFound)
123+
.addCustomAnswer("askForInput", askForInput);
124+
125+
//Add answer parameters that are used to replace <1>, <2>, ... in your answers.
126+
//The name is arbitrary but you need to use the same one in getResult(...) later for api.resultInfoPut(...)
127+
info.addAnswerParameters("answer"); //<1>=answer text
128+
129+
return info;
130+
}
131+
132+
@Override
133+
public ServiceResult getResult(NluResult nluResult) {
134+
//initialize result
135+
ServiceBuilder api = new ServiceBuilder(nluResult,
136+
getInfoFreshOrCache(nluResult.input, this.getClass().getCanonicalName()),
137+
getAnswersPool(nluResult.language));
138+
139+
//we haven't defined anything specific but we will ask for our custom parameter and the result will be stored here in the 2nd stage of the dialog
140+
Parameter questionParameter = nluResult.getOptionalParameter(SpecialQuestion.class.getName(), "");
141+
String qNormalized = questionParameter.getValueAsString();
142+
String qRaw = (String) questionParameter.getDataFieldOrDefault(InterviewData.INPUT_RAW); //raw input (before normalization)
143+
//String q = nluResult.getParameter(PARAMETERS.ANY_ANSWER); //alternative way for "ad-hoc" parameters (not recommended)
144+
145+
//in the 1st stage of the dialog our input will be empty because no parameter was defined, so we need to ask manually:
146+
if (Is.nullOrEmpty(qNormalized)){
147+
//ask and ...
148+
api.setIncompleteAndAsk(SpecialQuestion.class.getName(), askForInput);
149+
//api.setIncompleteAndAsk(PARAMETERS.ANY_ANSWER, askForInput); //define a parameter "ad-hoc" (never registered in 'getInfo')
150+
//.. return
151+
ServiceResult result = api.buildResult();
152+
return result;
153+
154+
}else{
155+
//in the 2nd stage this will be the user "answer"
156+
157+
//we could check the parameter here and still reject it (e.g. asking again)
158+
//if (qNormalized.equalsIgnoreCase("...")){ ... }
159+
160+
//generate answer:
161+
162+
//TODO: Here you can add your scripts to answer the question. Write your own logic or maybe use a web API?
163+
String questionResponse = "";
164+
boolean answeredSuccessfully = false;
165+
//Example HTTP call e.g. to a web API, your PythonBridge or any other micro-service with HTTP interface:
166+
/*
167+
try{
168+
JSONObject response = Connectors.apacheHttpGETjson("http://localhost:20731/my-service/");
169+
if (response != null && response.containsKey("answer")){
170+
questionResponse = JSON.getString(response, "answer");
171+
answeredSuccessfully = true;
172+
}
173+
}catch (Exception e){
174+
e.printStackTrace();
175+
}
176+
*/
177+
//JUST FOR TESTING: return the question:
178+
questionResponse = qRaw;
179+
answeredSuccessfully = Is.notNullOrEmpty(questionResponse); //implement your own checks depending on how you generate answers!
180+
181+
//success or no answer?
182+
if (!answeredSuccessfully){
183+
//no error but also no answer
184+
api.setStatusOkay();
185+
}else{
186+
//Set answer parameters as defined in getInfo():
187+
api.resultInfoPut("answer", questionResponse);
188+
189+
//all good
190+
api.setStatusSuccess();
191+
}
192+
193+
//build the API_Result
194+
ServiceResult result = api.buildResult();
195+
return result;
196+
}
197+
}
198+
199+
//----------------- custom parameters -------------------
200+
201+
/**
202+
* Parameter handler that is just a placeholder for our custom question.
203+
* It will contain the full input, normalized and raw if used in a response.
204+
*/
205+
public static class SpecialQuestion extends GenericEmptyParameter {}
206+
}

0 commit comments

Comments
 (0)