Skip to content

Commit ee4c52b

Browse files
authored
Embedding support in Java Generator (#906)
* Embedding support in Java Generator * - Add Assitant Object support in Java Generator - Change Embedding implementation to use common util classes to call saia. * GXEmbedding module do not exists any more * Implement CallResult External Object to use in Agent Object * Change Saia URL to consider Embedding and Chat * Add support for chat and tool call messages * Message was not added to CallResult * Json API was updated in master * Change getmessages method in CallResult to getMessages * Change callAssistant to callAgent Add getExternalInstance method in EO Collections. Support ChatMessage EO * Fix Build error in Github * Fix Build error in Github * Remove Assistant Test * Add Tool Calls support * TRN with Embedded fails when the PK is validated in Java issue 202652 * Embedding must be initialized with empty values. * Add ToolCall y Stream support to Agent Object Add logging calling saia. * Changes to better CallTools support. * Avoid Exception procesing Agent response when Choices is not in the json response. * Implements Embedding in MySQL * Add stream in chat Agent calls. * Implements support for multimodal content in Agent messages. * Implements support for multimodal content in Agent messages. * Implements support for multimodal content in Agent messages. * Implements support for multimodal content in Agent messages. * Implements support for multimodal content in Agent messages.
1 parent 55cf746 commit ee4c52b

30 files changed

+1202
-12
lines changed

android/src/main/java/com/genexus/db/ForEachCursor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ public void setTimestamp(int index, java.sql.Timestamp value) throws SQLExceptio
217217
public void setBLOBFile(int index, String fileName) throws SQLException {}
218218
public void setBLOBFile(int index, String fileName, boolean isMultiMedia) throws SQLException {}
219219
public void setBLOBFile(int index, String fileName, boolean isMultiMedia, boolean downloadContent) throws SQLException {}
220+
public void setEmbedding(int index, Float[] value) throws SQLException {}
220221

221222
public void setVarchar(int index, String value, int length, boolean allowsNull) throws SQLException {}
222223
public void setLongVarchar(int index, String value, boolean allowsNull) throws SQLException {}

android/src/main/java/com/genexus/db/driver/GXCallableStatement.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,11 @@ public byte[] getBytes(int columnIndex) throws SQLException
651651
return stmt.getBytes(columnIndex);
652652
}
653653

654+
public Float[] getGxembedding (int columnIndex) throws SQLException
655+
{
656+
return null;
657+
}
658+
654659
public java.util.UUID getGUID(int columnIndex) throws SQLException
655660
{
656661
if (DEBUG)

android/src/main/java/com/genexus/db/driver/GXPreparedStatement.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,9 @@ else if (file.exists() && !fileNameNew.startsWith(blobBasePath))
13071307
}
13081308
}
13091309
}
1310-
1310+
1311+
public void setEmbedding(int index, Float[] value) throws SQLException{
1312+
}
13111313
public void setBinaryStream(int index, java.io.InputStream value, int length) throws SQLException
13121314
{
13131315
if (DEBUG)

android/src/main/java/com/genexus/db/driver/GXResultSet.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,11 @@ public byte[] getBytes(int columnIndex) throws SQLException
770770
return result.getBytes(columnIndex);
771771
}
772772

773+
public Float[] getGxembedding (int columnIndex) throws SQLException
774+
{
775+
return null;
776+
}
777+
773778
public java.util.UUID getGUID(int columnIndex) throws SQLException
774779
{
775780
java.util.UUID value;

common/src/main/java/com/genexus/GXExternalCollection.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,22 @@ public Vector getStruct()
9898
}
9999
return struct;
100100
}
101-
101+
102+
public ArrayList getExternalInstance() {
103+
ArrayList list = new ArrayList();
104+
for (T Item : this)
105+
{
106+
try
107+
{
108+
list.add(Item.getClass().getMethod("getExternalInstance", new Class[]{}).invoke(Item));
109+
}
110+
catch (Exception e)
111+
{
112+
e.printStackTrace();
113+
}
114+
}
115+
return list;
116+
}
117+
102118
}
103119

common/src/main/java/com/genexus/db/BufferIFieldGetter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ public byte[] getBytes(int columnIndex) throws SQLException {
8585
return ((byte[]) value[columnIndex - 1]);
8686
}
8787

88+
public Float[] getGxembedding(int columnIndex) throws SQLException {
89+
return ((Float[]) value[columnIndex - 1]);
90+
}
91+
8892
public java.sql.Date getDate(int columnIndex) throws SQLException {
8993
return ((java.sql.Date) value[columnIndex - 1]);
9094
}

common/src/main/java/com/genexus/db/CachedIFieldGetter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ public byte[] getBytes(int columnIndex) throws SQLException
220220
else
221221
return ((byte[][])value[index])[0];
222222
}
223+
224+
public Float[] getGxembedding(int columnIndex) throws SQLException
225+
{
226+
return ((Float[][])value[getColumnIndex(columnIndex)])[0];
227+
}
223228

224229
public java.sql.Date getDate(int columnIndex) throws SQLException
225230
{

common/src/main/java/com/genexus/db/IFieldGetter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ public interface IFieldGetter
3333
String getMultimediaUri(int columnIndex) throws SQLException;
3434
String getMultimediaUri(int columnIndex, boolean absPath) throws SQLException;
3535
java.util.UUID getGUID(int columnIndex) throws SQLException;
36+
Float[] getGxembedding(int columnIndex) throws SQLException;
3637
}

common/src/main/java/com/genexus/db/IFieldSetter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public interface IFieldSetter
3535
public void setBLOBFile(int index, String fileName) throws SQLException;
3636
public void setBLOBFile(int index, String fileName, boolean isMultiMedia) throws SQLException;
3737
public void setBLOBFile(int index, String fileName, boolean isMultiMedia, boolean downloadContent) throws SQLException;
38+
public void setEmbedding(int index, Float[] value) throws SQLException;
3839

3940
public void setVarchar(int index, String value, int length, boolean allowsNull) throws SQLException;
4041
public void setLongVarchar(int index, String value, boolean allowsNull) throws SQLException;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.genexus.util;
2+
3+
import com.genexus.GXBaseCollection;
4+
import com.genexus.SdtMessages_Message;
5+
6+
public class CallResult {
7+
private boolean success = true;
8+
private boolean fail;
9+
private final GXBaseCollection<SdtMessages_Message> messages = new GXBaseCollection<>();
10+
11+
public boolean success() {
12+
return success;
13+
}
14+
15+
public void setFail() {
16+
fail = true;
17+
success =false;
18+
}
19+
20+
public boolean fail() {
21+
return fail;
22+
}
23+
24+
public void addMessage(SdtMessages_Message message) {
25+
messages.add(message);
26+
}
27+
public GXBaseCollection<SdtMessages_Message> getMessages() {
28+
return messages;
29+
}
30+
}

common/src/main/java/com/genexus/util/GXProperties.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.genexus.util;
22

3-
import java.util.LinkedHashMap;
3+
import java.util.*;
44

55
import com.genexus.internet.IGxJSONSerializable;
66

@@ -10,8 +10,6 @@
1010
import com.genexus.CommonUtil;
1111
import com.genexus.SdtMessages_Message;
1212
import com.genexus.GXBaseCollection;
13-
import java.util.Iterator;
14-
import java.util.Map;
1513

1614
public class GXProperties implements IGxJSONSerializable {
1715
private LinkedHashMap < String, GXProperty > properties = new LinkedHashMap < > ();
@@ -118,6 +116,16 @@ public String toJSonString() {
118116
return jObj.toString();
119117
}
120118

119+
public ArrayList<GXProperty> getList() {
120+
ArrayList<GXProperty> list = new ArrayList<>();
121+
int i = 0;
122+
while (count() > i) {
123+
list.add(item(i));
124+
i++;
125+
}
126+
return list;
127+
}
128+
121129
public boolean fromJSonString(String s) {
122130
return fromJSonString(s, null);
123131
}

java/client.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ ORQ_CLIENT_URL=
4747
ORQ_SERVER_DIR=
4848
TMPMEDIA_DIR=PrivateTempStorage
4949
PRINT_LAYOUT_METADATA_DIR=LayoutMetadata
50+
AI_PROVIDER=https://api.saia.ai/chat
51+
AI_PROVIDER_API_KEY=xxx
5052
HTTP_PROTOCOL=Unsecure
5153
SAMESITE_COOKIE=Lax
5254
StorageTimeZone= 1

java/src/main/java/com/genexus/GXProcedure.java

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,24 @@
22
package com.genexus;
33

44
import java.sql.SQLException;
5+
import java.util.ArrayList;
56
import java.util.Date;
7+
8+
import com.fasterxml.jackson.databind.ObjectMapper;
69
import com.genexus.db.Namespace;
710
import com.genexus.db.UserInformation;
811
import com.genexus.diagnostics.GXDebugInfo;
912
import com.genexus.diagnostics.GXDebugManager;
13+
import com.genexus.internet.HttpClient;
1014
import com.genexus.internet.HttpContext;
1115
import com.genexus.mock.GXMockProvider;
1216
import com.genexus.performance.ProcedureInfo;
1317
import com.genexus.performance.ProceduresInfo;
14-
import com.genexus.util.ReorgSubmitThreadPool;
15-
import com.genexus.util.SubmitThreadPool;
18+
import com.genexus.util.*;
19+
import com.genexus.util.saia.OpenAIRequest;
20+
import com.genexus.util.saia.OpenAIResponse;
21+
import com.genexus.util.saia.SaiaService;
22+
import org.json.JSONObject;
1623

1724
public abstract class GXProcedure implements IErrorHandler, ISubmitteable {
1825
public abstract void initialize();
@@ -28,7 +35,8 @@ public abstract class GXProcedure implements IErrorHandler, ISubmitteable {
2835
UserInformation ui=null;
2936

3037
private Date beginExecute;
31-
38+
private HttpClient client;
39+
3240
public static final int IN_NEW_UTL = -2;
3341

3442
public GXProcedure(int remoteHandle, ModelContext context, String location) {
@@ -257,4 +265,70 @@ protected void mockExecute() {
257265
}
258266
privateExecute( );
259267
}
268+
269+
protected String callTool(String name, String arguments) {
270+
return "";
271+
}
272+
273+
protected String callAssistant(String agent, GXProperties properties, ArrayList<OpenAIResponse.Message> messages, CallResult result) {
274+
return callAgent(agent, properties, messages, result);
275+
}
276+
277+
protected ChatResult chatAgent(String agent, GXProperties properties, ArrayList<OpenAIResponse.Message> messages, CallResult result) {
278+
callAgent(agent, true, properties, messages, result);
279+
return new ChatResult(this, agent, properties, messages, result, client);
280+
}
281+
282+
protected String callAgent(String agent, GXProperties properties, ArrayList<OpenAIResponse.Message> messages, CallResult result) {
283+
return callAgent(agent, false, properties, messages, result);
284+
}
285+
286+
protected String callAgent(String agent, boolean stream, GXProperties properties, ArrayList<OpenAIResponse.Message> messages, CallResult result) {
287+
OpenAIRequest aiRequest = new OpenAIRequest();
288+
aiRequest.setModel(String.format("saia:agent:%s", agent));
289+
if (!messages.isEmpty())
290+
aiRequest.setMessages(messages);
291+
aiRequest.setVariables(properties.getList());
292+
if (stream)
293+
aiRequest.setStream(true);
294+
client = new HttpClient();
295+
OpenAIResponse aiResponse = SaiaService.call(aiRequest, client, result);
296+
if (aiResponse != null && aiResponse.getChoices() != null) {
297+
for (OpenAIResponse.Choice element : aiResponse.getChoices()) {
298+
String finishReason = element.getFinishReason();
299+
if (finishReason.equals("stop"))
300+
return element.getMessage().getStringContent();
301+
if (finishReason.equals("tool_calls")) {
302+
messages.add(element.getMessage());
303+
return processNotChunkedResponse(agent, stream, properties, messages, result, element.getMessage().getToolCalls());
304+
}
305+
}
306+
} else if (client.getStatusCode() == 200) {
307+
return "";
308+
}
309+
return "";
310+
}
311+
312+
public String processNotChunkedResponse(String agent, boolean stream, GXProperties properties, ArrayList<OpenAIResponse.Message> messages, CallResult result, ArrayList<OpenAIResponse.ToolCall> toolCalls) {
313+
for (OpenAIResponse.ToolCall tollCall : toolCalls) {
314+
processToolCall(tollCall, messages);
315+
}
316+
return callAgent(agent, stream, properties, messages, result);
317+
}
318+
319+
private void processToolCall(OpenAIResponse.ToolCall toolCall, ArrayList<OpenAIResponse.Message> messages) {
320+
String result;
321+
String functionName = toolCall.getFunction().getName();
322+
try {
323+
result = callTool(functionName, toolCall.getFunction().getArguments());
324+
}
325+
catch (Throwable e) {
326+
result = String.format("Error calling tool %s", functionName);
327+
}
328+
OpenAIResponse.Message toolCallMessage = new OpenAIResponse.Message();
329+
toolCallMessage.setRole("tool");
330+
toolCallMessage.setStringContent(result);
331+
toolCallMessage.setToolCallId(toolCall.getId());
332+
messages.add(toolCallMessage);
333+
}
260334
}

java/src/main/java/com/genexus/GXutil.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import com.genexus.common.interfaces.SpecificImplementation;
1111
import com.genexus.db.DataStoreProvider;
12+
import com.genexus.db.GXEmbedding;
1213
import com.genexus.internet.HttpContext;
1314
import com.genexus.internet.StringCollection;
1415
import com.genexus.platform.INativeFunctions;
@@ -1777,4 +1778,8 @@ public static String buildURLFromHttpClient(com.genexus.internet.HttpClient GXSo
17771778
return url.toString();
17781779
}
17791780

1781+
public static String embeddingToStr(GXEmbedding embedding) {
1782+
return embedding.toString();
1783+
}
1784+
17801785
}

java/src/main/java/com/genexus/db/ForEachCursor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ public void setTimestamp(int index, java.sql.Timestamp value) throws SQLExceptio
327327
public void setBLOBFile(int index, String fileName) throws SQLException {}
328328
public void setBLOBFile(int index, String fileName, boolean isMultiMedia) throws SQLException {}
329329
public void setBLOBFile(int index, String fileName, boolean isMultiMedia, boolean downloadContet) throws SQLException {}
330+
public void setEmbedding(int index, Float[] value) throws SQLException {}
330331

331332
public void setVarchar(int index, String value, int length, boolean allowsNull) throws SQLException {}
332333
public void setLongVarchar(int index, String value, boolean allowsNull) throws SQLException {}
@@ -339,6 +340,8 @@ public void setParameterRT(String name, String value)
339340
boolean isLike = false;
340341
if(value.equals("like"))
341342
isLike = true;
343+
else if (value.equals("Distance"))
344+
value = ds.getDistanceFunction();
342345
else if(!value.equals("=") && !value.equals(">") && !value.equals(">=")
343346
&& !value.equals("<=") && !value.equals("<") && !value.equals("<>"))
344347
{

0 commit comments

Comments
 (0)