99import io .kestra .core .utils .IdUtils ;
1010import io .kestra .plugin .ai .domain .ChatConfiguration ;
1111import io .kestra .plugin .ai .memory .KestraKVStore ;
12+ import io .kestra .plugin .ai .provider .GoogleGemini ;
1213import io .kestra .plugin .ai .provider .OpenAI ;
14+ import io .kestra .plugin .ai .rag .IngestDocument ;
1315import io .kestra .plugin .ai .tool .DockerMcpClient ;
1416import io .kestra .plugin .ai .tool .StdioMcpClient ;
1517import jakarta .inject .Inject ;
1618import org .junit .jupiter .api .Test ;
19+ import org .junit .jupiter .api .condition .EnabledIfEnvironmentVariable ;
1720
1821import java .util .List ;
1922import java .util .Map ;
2225
2326@ KestraTest
2427class AIAgentTest {
28+ private final String GOOGLE_API_KEY = System .getenv ("GOOGLE_API_KEY" );
2529 @ Inject
2630 private TestRunContextFactory runContextFactory ;
2731
@@ -170,4 +174,116 @@ void withOutputFiles() throws Exception {
170174 assertThat (content ).isEqualTo ("Hello World" );
171175 }
172176 }
177+
178+ @ EnabledIfEnvironmentVariable (named = "GOOGLE_API_KEY" , matches = ".*" )
179+ @ Test
180+ void withEmbeddingRetriever () throws Exception {
181+ RunContext runContext = runContextFactory .of ("namespace" , Map .of (
182+ "modelName" , "gemini-2.0-flash" ,
183+ "apiKey" , GOOGLE_API_KEY
184+ ));
185+ // First ingest some documents
186+ var ingest = IngestDocument .builder ()
187+ .provider (
188+ GoogleGemini .builder ()
189+ .type (GoogleGemini .class .getName ())
190+ .modelName (Property .ofValue ("gemini-embedding-exp-03-07" ))
191+ .apiKey (Property .ofExpression ("{{ apiKey }}" ))
192+ .build ()
193+ )
194+ .embeddings (io .kestra .plugin .ai .embeddings .KestraKVStore .builder ().build ())
195+ .fromDocuments (List .of (
196+ IngestDocument .InlineDocument .builder ()
197+ .content (Property .ofValue ("Paris is the capital of France with a population of over 2.1 million people" ))
198+ .build (),
199+ IngestDocument .InlineDocument .builder ()
200+ .content (Property .ofValue ("The Eiffel Tower is the most famous landmark in Paris at 330 meters tall" ))
201+ .build ()
202+ ))
203+ .build ();
204+
205+ IngestDocument .Output ingestOutput = ingest .run (runContext );
206+ assertThat (ingestOutput .getIngestedDocuments ()).isEqualTo (2 );
207+
208+ var agent = AIAgent .builder ()
209+ .provider (
210+ GoogleGemini .builder ()
211+ .type (GoogleGemini .class .getName ())
212+ .modelName (Property .ofExpression ("{{ modelName }}" ))
213+ .apiKey (Property .ofExpression ("{{ apiKey }}" ))
214+ .build ()
215+ )
216+ .embeddingProvider (
217+ GoogleGemini .builder ()
218+ .type (GoogleGemini .class .getName ())
219+ .modelName (Property .ofValue ("gemini-embedding-exp-03-07" ))
220+ .apiKey (Property .ofExpression ("{{ apiKey }}" ))
221+ .build ()
222+ ).embeddings (io .kestra .plugin .ai .embeddings .KestraKVStore .builder ().build ())
223+ .prompt (Property .ofValue ("What is the capital of France and how many people live there?" ))
224+ .configuration (ChatConfiguration .builder ().temperature (Property .ofValue (0.1 )).seed (Property .ofValue (123456789 )).build ())
225+ .build ();
226+
227+ var output = agent .run (runContext );
228+ assertThat (output .getTextOutput ()).isNotNull ();
229+ assertThat (output .getTextOutput ()).contains ("Paris" );
230+ }
231+
232+ @ EnabledIfEnvironmentVariable (named = "GOOGLE_API_KEY" , matches = ".*" )
233+ @ Test
234+ void withEmbeddingRetriever_andWithTool () throws Exception {
235+ RunContext runContext = runContextFactory .of ("namespace" , Map .of (
236+ "modelName" , "gemini-2.0-flash" ,
237+ "apiKey" , GOOGLE_API_KEY
238+ ));
239+ // First ingest some documents
240+ var ingest = IngestDocument .builder ()
241+ .provider (
242+ GoogleGemini .builder ()
243+ .type (GoogleGemini .class .getName ())
244+ .modelName (Property .ofValue ("gemini-embedding-exp-03-07" ))
245+ .apiKey (Property .ofExpression ("{{ apiKey }}" ))
246+ .build ()
247+ )
248+ .embeddings (io .kestra .plugin .ai .embeddings .KestraKVStore .builder ().build ())
249+ .fromDocuments (List .of (
250+ IngestDocument .InlineDocument .builder ()
251+ .content (Property .ofValue ("Paris is the capital of France with a population of over 2.1 million people" ))
252+ .build (),
253+ IngestDocument .InlineDocument .builder ()
254+ .content (Property .ofValue ("The Eiffel Tower is the most famous landmark in Paris at 330 meters tall" ))
255+ .build ()
256+ ))
257+ .build ();
258+
259+ IngestDocument .Output ingestOutput = ingest .run (runContext );
260+ assertThat (ingestOutput .getIngestedDocuments ()).isEqualTo (2 );
261+
262+ var agent = AIAgent .builder ()
263+ .provider (
264+ GoogleGemini .builder ()
265+ .type (GoogleGemini .class .getName ())
266+ .modelName (Property .ofExpression ("{{ modelName }}" ))
267+ .apiKey (Property .ofExpression ("{{ apiKey }}" ))
268+ .build ()
269+ )
270+ .embeddingProvider (
271+ GoogleGemini .builder ()
272+ .type (GoogleGemini .class .getName ())
273+ .modelName (Property .ofValue ("gemini-embedding-exp-03-07" ))
274+ .apiKey (Property .ofExpression ("{{ apiKey }}" ))
275+ .build ()
276+ ).embeddings (io .kestra .plugin .ai .embeddings .KestraKVStore .builder ().build ())
277+ .tools (
278+ List .of (StdioMcpClient .builder ().command (Property .ofValue (List .of ("docker" , "run" , "--rm" , "-i" , "mcp/everything" ))).build ())
279+ )
280+ .prompt (Property .ofValue ("What is the capital of France and how many people live there?" ))
281+ .configuration (ChatConfiguration .builder ().temperature (Property .ofValue (0.1 )).seed (Property .ofValue (123456789 )).build ())
282+ .build ();
283+
284+ var output = agent .run (runContext );
285+ assertThat (output .getTextOutput ()).isNotNull ();
286+ assertThat (output .getTextOutput ()).contains ("Paris" );
287+ }
288+
173289}
0 commit comments