11package com .genexus .util .saia ;
22
33import com .fasterxml .jackson .databind .ObjectMapper ;
4+ import com .genexus .GXProcedure ;
45import com .genexus .SdtMessages_Message ;
56import com .genexus .common .interfaces .SpecificImplementation ;
67import com .genexus .diagnostics .core .ILogger ;
78import com .genexus .diagnostics .core .LogManager ;
89import com .genexus .internet .HttpClient ;
10+ import com .genexus .util .ChatResult ;
11+ import com .genexus .util .GXProperties ;
912import org .json .JSONObject ;
1013import com .genexus .util .CallResult ;
1114import org .slf4j .Logger ;
1215import org .slf4j .LoggerFactory ;
1316
17+ import java .util .ArrayList ;
18+
1419public class SaiaService {
1520 private static final ILogger logger = LogManager .getLogger (SaiaService .class );
1621 private static final String apiKey = (String ) SpecificImplementation .Application .getProperty ("AI_PROVIDER_API_KEY" , "" );;
1722 private static final String aiProvider = (String ) SpecificImplementation .Application .getProperty ("AI_PROVIDER" , "" );
1823 private static final Logger log = LoggerFactory .getLogger (SaiaService .class );
1924
20- public static OpenAIResponse call (OpenAIRequest request , HttpClient client , CallResult result ) {
21- return call (request , false , client , result );
25+ public static OpenAIResponse call (GXProcedure proc , OpenAIRequest request , HttpClient client , String agent , boolean stream , GXProperties properties , ArrayList < OpenAIResponse . Message > messages , CallResult result , ChatResult chatResult ) {
26+ return call (proc , request , false , client , agent , stream , properties , messages , result , chatResult );
2227 }
2328
2429 public static OpenAIResponse call (OpenAIRequest request , boolean isEmbedding , CallResult result ) {
25- return call (request , isEmbedding , new HttpClient (), result );
30+ return call (null , request , isEmbedding , new HttpClient (), null , false , null , null , result , null );
2631 }
2732
28- public static OpenAIResponse call (OpenAIRequest request , boolean isEmbedding , HttpClient client , CallResult result ) {
33+ public static OpenAIResponse call (GXProcedure proc , OpenAIRequest request , boolean isEmbedding , HttpClient client , String agent , boolean stream , GXProperties properties , ArrayList < OpenAIResponse . Message > messages , CallResult result , ChatResult chatResult ) {
2934 try {
3035 String jsonRequest = new ObjectMapper ().writeValueAsString (request );
3136 logger .debug ("Agent payload: " + jsonRequest );
@@ -44,25 +49,8 @@ public static OpenAIResponse call(OpenAIRequest request, boolean isEmbedding, Ht
4449 if (client .getStatusCode () == 200 ) {
4550 String saiaResponse ;
4651 if (client .getHeader ("Content-Type" ).contains ("text/event-stream" )){
47- saiaResponse = client .readChunk ();
48- int index = saiaResponse .indexOf ("data:" ) + "data:" .length ();
49- String chunkJson = saiaResponse .substring (index ).trim ();
50- try {
51- JSONObject jsonResponse = new JSONObject (chunkJson );
52- OpenAIResponse chunkResponse = new ObjectMapper ().readValue (jsonResponse .toString (), OpenAIResponse .class );
53- OpenAIResponse .Choice choise = chunkResponse .getChoices ().get (0 );
54- if (choise .getFinishReason () != null && choise .getFinishReason ().equals ("tool_calls" )){
55- saiaResponse = chunkJson ;
56- }
57- else {
58- client .unreadChunk ();
59- return null ;
60- }
61- }
62- catch (Exception e ) {
63- client .unreadChunk ();
64- return null ;
65- }
52+ getChunkedSaiaResponse (proc , client , agent , stream , properties , messages , result , chatResult );
53+ return null ;
6654 }
6755 else {
6856 saiaResponse = client .getString ();
@@ -88,6 +76,38 @@ public static OpenAIResponse call(OpenAIRequest request, boolean isEmbedding, Ht
8876 return null ;
8977 }
9078
79+ private static void getChunkedSaiaResponse (GXProcedure proc , HttpClient client , String agent , boolean stream , GXProperties properties , ArrayList <OpenAIResponse .Message > messages , CallResult result , ChatResult chatResult ) {
80+ String saiaChunkResponse = client .readChunk ();;
81+ String chunkJson ;
82+ while (!client .getEof ()) {
83+ logger .debug ("Agent response chunk: " + saiaChunkResponse );
84+ if (saiaChunkResponse .isEmpty () || saiaChunkResponse .equals ("data: [DONE]" )) {
85+ saiaChunkResponse = client .readChunk ();
86+ continue ;
87+ }
88+ int index = saiaChunkResponse .indexOf ("data:" ) + "data:" .length ();
89+ chunkJson = saiaChunkResponse .substring (index ).trim ();
90+ try {
91+ JSONObject jsonResponse = new JSONObject (chunkJson );
92+ OpenAIResponse chunkResponse = new ObjectMapper ().readValue (jsonResponse .toString (), OpenAIResponse .class );
93+ if (!chunkResponse .getChoices ().isEmpty ()) {
94+ OpenAIResponse .Choice choice = chunkResponse .getChoices ().get (0 );
95+ if (choice .getFinishReason () != null && choice .getFinishReason ().equals ("tool_calls" )) {
96+ messages .add (choice .getMessage ());
97+ proc .processNotChunkedResponse (agent , stream , properties , messages , result , chatResult , choice .getMessage ().getToolCalls ());
98+ ;
99+ } else if (choice .getDelta () != null && choice .getDelta ().getContent () != null ) {
100+ chatResult .addChunk (((OpenAIResponse .StringContent ) choice .getDelta ().getContent ()).getValue ());
101+ }
102+ }
103+ saiaChunkResponse = client .readChunk ();
104+ }
105+ catch (Exception e ) {
106+ logger .warn ("Error deserializing the response chunk" , e );
107+ saiaChunkResponse = client .readChunk ();
108+ }
109+ }
110+ }
91111
92112 private static void addResultMessage (String id , byte type , String description , CallResult result ){
93113 if (type == 1 )
0 commit comments