Skip to content

Commit 97fba00

Browse files
authored
Merge pull request #23 from SEPIA-Framework/dev
v0.9.25
2 parents 666c19c + 57662e2 commit 97fba00

11 files changed

+500
-12
lines changed
986 KB
Binary file not shown.
-979 KB
Binary file not shown.

pom.xml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>net.b07z.sepia.sdk</groupId>
77
<artifactId>sepia-sdk-java</artifactId>
8-
<version>0.9.24</version>
8+
<version>0.9.25</version>
99
<name>SEPIA SDK</name>
1010
<description>Tools to develop services for the SEPIA framework</description>
1111
<url>https://sepia-framework.github.io</url>
@@ -31,7 +31,7 @@
3131
<dependency>
3232
<groupId>net.b07z.sepia.server.assist</groupId>
3333
<artifactId>sepia-assist-API</artifactId>
34-
<version>2.5.2</version>
34+
<version>2.6.0</version>
3535
</dependency>
3636
-->
3737

@@ -94,9 +94,9 @@
9494
<dependency>
9595
<groupId>net.b07z.sepia.server.core</groupId>
9696
<artifactId>sepia-core-tools</artifactId>
97-
<version>2.2.9</version>
97+
<version>2.2.10</version>
9898
<scope>system</scope>
99-
<systemPath>${basedir}/libs/sepia-core-tools-v2.2.9.jar</systemPath>
99+
<systemPath>${basedir}/libs/sepia-core-tools-v2.2.10.jar</systemPath>
100100
</dependency>
101101

102102
<dependency>
@@ -112,9 +112,9 @@
112112
<dependency>
113113
<groupId>net.b07z.sepia.websockets</groupId>
114114
<artifactId>sepia-websockets</artifactId>
115-
<version>1.3.2</version>
115+
<version>1.3.3</version>
116116
<scope>system</scope>
117-
<systemPath>${basedir}/libs/sepia-chat-v1.3.2.jar</systemPath>
117+
<systemPath>${basedir}/libs/sepia-chat-v1.3.3.jar</systemPath>
118118
</dependency>
119119

120120
<dependency>
@@ -135,9 +135,9 @@
135135
<dependency>
136136
<groupId>net.b07z.sepia.server.assist</groupId>
137137
<artifactId>sepia-assist-API</artifactId>
138-
<version>2.5.2</version>
138+
<version>2.6.0</version>
139139
<scope>system</scope>
140-
<systemPath>${basedir}/libs/sepia-assist-v2.5.2.jar</systemPath>
140+
<systemPath>${basedir}/libs/sepia-assist-v2.6.0.jar</systemPath>
141141
</dependency>
142142
<!-- -->
143143

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
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.CustomParameter;
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 required parameter because the question is generated dynamically inside the result handler.
114+
//We define the custom parameter as optional though to extract it properly later (or in regular expression trigger):
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+
//Example HTTP call e.g. to a web API, your PythonBridge or any other micro-service with HTTP interface:
165+
/*
166+
try{
167+
JSONObject response = Connectors.apacheHttpGETjson("http://localhost:20731/my-service/");
168+
if (response != null && response.containsKey("answer")){
169+
questionResponse = JSON.getString(response, "answer");
170+
}
171+
}catch (Exception e){
172+
Debugger.println("DynamicQuestionAnswering - failed to call API - Error: " + e.getMessage(), 1);
173+
}
174+
*/
175+
//JUST FOR TESTING: return the question:
176+
questionResponse = qRaw;
177+
//TODO: Implement your own checks depending on how you generate answers!
178+
boolean answeredSuccessfully = Is.notNullOrEmpty(questionResponse);
179+
180+
//success or no answer?
181+
if (!answeredSuccessfully){
182+
//no error but also no answer
183+
api.setStatusOkay();
184+
}else{
185+
//Set answer parameters as defined in getInfo():
186+
api.resultInfoPut("answer", questionResponse);
187+
188+
//all good
189+
api.setStatusSuccess();
190+
}
191+
192+
//build the API_Result
193+
ServiceResult result = api.buildResult();
194+
return result;
195+
}
196+
}
197+
198+
//----------------- custom parameters -------------------
199+
200+
/**
201+
* Custom parameter that tries to extract the question from first input or response.
202+
* It will contain the normalized and full raw input by default.
203+
*/
204+
public static class SpecialQuestion extends CustomParameter {
205+
206+
@Override
207+
public String extract(String input){
208+
//If you use regular expression triggers in 'getInfo' you could try to extract
209+
//the question here. For now we just return nothing and get the input during
210+
//response phase (after "what do you want to know?")
211+
return "";
212+
}
213+
}
214+
}

src/main/java/net/b07z/sepia/sdk/services/uid1007/PythonBridgeDemo.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
import net.b07z.sepia.server.core.tools.Sdk;
1919

2020
/**
21-
* Demonstration of how to use SEPIA Python-Bridge to enhance NLU and services.
21+
* Demonstration of how to use SEPIA Python-Bridge to enhance NLU and services.<br>
22+
* <br>
23+
* To use this service please make sure your Python-Bridge server is running:<br>
24+
* https://github.com/SEPIA-Framework/sepia-python-bridge
2225
*
2326
* @author Florian Quirin
2427
*
@@ -35,10 +38,10 @@ public TreeSet<String> getSampleSentences(String lang) {
3538
TreeSet<String> samples = new TreeSet<>();
3639
//GERMAN
3740
if (lang.equals(Language.DE.toValue())){
38-
samples.add("Ich würde gerne die Python Brücke testen.");
41+
samples.add("Python Brücke testen.");
3942
//OTHER
4043
}else{
41-
samples.add("I'd like to test the Python bridge.");
44+
samples.add("Test Python bridge.");
4245
}
4346
return samples;
4447
}
@@ -116,7 +119,7 @@ public ServiceInfo getInfo(String language) {
116119

117120
//Parameters:
118121

119-
//This service has a one required parameter, the code word.
122+
//This service has one required parameter, the code word.
120123
//Required parameters will be asked automatically by SEPIA using the defined question.
121124
Parameter p1 = new Parameter(new CodeWord())
122125
.setRequired(true)
@@ -158,6 +161,21 @@ public ServiceResult getResult(NluResult nluResult) {
158161

159162
// ... here you could put some code that runs after successful code word.
160163
// wrong code will automatically lead to rejection before reaching this part ...
164+
165+
//Example call to another PythonBridge endpoint (define yourself)
166+
/*
167+
String myReply = "";
168+
try{
169+
JSONObject response = Connectors.apacheHttpGETjson("http://localhost:20731/my-service/");
170+
if (response != null && response.containsKey("myReply")){
171+
myReply = JSON.getString(response, "myReply");
172+
...
173+
}
174+
}catch (Exception e){
175+
Debugger.println("PythonBridgeDemo - failed to call API - Error: " + e.getMessage(), 1);
176+
}
177+
if (Is.notNullOrEmpty(myReply)){ ... }
178+
*/
161179

162180
//all good
163181
api.setStatusSuccess();

0 commit comments

Comments
 (0)