Package dyntabs.ai

Class AssistantBuilder<T>

java.lang.Object
dyntabs.ai.AssistantBuilder<T>
Type Parameters:
T - the assistant interface type

public class AssistantBuilder<T> extends Object
Builder for creating AI assistant proxies from annotated interfaces.

This builder creates a runtime proxy that forwards method calls to an AI model. You can optionally add tool objects (your existing Java services) that the AI can call, and document sources (RAG) that the AI can reference.

Use Case 1: Simple AI Assistant (No Tools)


 @EasyAIAssistant(systemMessage = "You are a helpful translator")
 public interface Translator {
     String translate(String text);
 }

 Translator t = EasyAI.assistant(Translator.class).build();
 String result = t.translate("Hello, how are you?");
 // result: "Bonjour, comment allez-vous?" (depending on system message)
 

Use Case 2: AI Assistant with Tools (AI Calls Your Java Code)

This is the most powerful feature. Pass your existing service objects to withTools(Object...), and the AI will call their methods when needed. No annotations are required on your service classes.


 // Your existing service - plain Java, no AI annotations
 public class WeatherService {
     public String getWeather(String city) {
         return weatherApi.fetch(city).toString();
     }
 }

 @EasyAIAssistant(systemMessage = "You are a weather assistant")
 public interface WeatherBot {
     String ask(String question);
 }

 // Wire it together
 WeatherBot bot = EasyAI.assistant(WeatherBot.class)
     .withTools(new WeatherService())
     .build();

 // AI automatically calls WeatherService.getWeather("London") behind the scenes
 String answer = bot.ask("What's the weather like in London?");
 

Use Case 3: Multiple Tool Services


 SupportBot bot = EasyAI.assistant(SupportBot.class)
     .withTools(orderService, userService, inventoryService)
     .build();

 // AI can call methods from ANY of the three services
 bot.ask("What is the status of order #123 for user john@example.com?");
 

Use Case 4: Jakarta EJB Beans as Tools

EJB beans (@Stateless, @Stateful, @Singleton) injected via @Inject work as tools out of the box. EasyAI automatically detects the EJB proxy and discovers business methods from the actual bean class. Method calls go through the container proxy, so transactions, security, and interceptors work normally.


 @Stateless
 public class OrderService {
     @PersistenceContext private EntityManager em;

     public String findOrder(String orderId) {
         return em.find(Order.class, orderId).toString();
     }
 }

 // In your CDI bean:
 @Inject OrderService orderService;   // EJB proxy from the container

 SupportBot bot = EasyAI.assistant(SupportBot.class)
     .withTools(orderService)          // just pass the injected proxy
     .build();

 bot.ask("Where is order #123?");
 // AI calls orderService.findOrder("123") through the EJB proxy
 

Use Case 5: Override Settings Per-Assistant


 Translator t = EasyAI.assistant(Translator.class)
     .withModel("gpt-4o")           // use a specific model
     .withMemory(50)                 // remember 50 messages
     .withSystemMessage("Translate everything to Serbian")
     .build();
 
See Also:
  • Method Details

    • withTools

      public AssistantBuilder<T> withTools(Object... tools)
      Adds tool objects whose public methods the AI can call.

      Accepts plain POJOs and Jakarta EJB proxies (@Stateless, @Stateful, @Singleton) obtained via @Inject. EJB proxies are detected automatically — business methods are discovered from the actual bean class, while invocations go through the proxy so that container services (transactions, security, interceptors) work normally.

      Parameters:
      tools - one or more service objects (POJOs or injected EJB proxies)
      Returns:
      this builder
    • withMemory

      public AssistantBuilder<T> withMemory(int maxMessages)
    • withSystemMessage

      public AssistantBuilder<T> withSystemMessage(String systemMessage)
    • withModel

      public AssistantBuilder<T> withModel(String modelName)
    • withApiKey

      public AssistantBuilder<T> withApiKey(String apiKey)
    • withRAG

      public AssistantBuilder<T> withRAG(String... sources)
      Enables RAG (document-powered AI) with the given document sources.

      This is the programmatic alternative to the @EasyRAG annotation. Use this when your document paths are not known at compile time, for example when they come from a database, user upload, or application configuration.

      In a web application, use file: prefix to point to documents on the server's file system, or pass any absolute path:

      
       // Documents on the server file system
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG("file:C:/app-data/docs/policy.pdf")
           .build();
      
       // Path from application config or database
       String docPath = appConfig.getDocumentPath();
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG(docPath)
           .build();
      
       // Multiple documents
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG("file:/data/policy.pdf", "file:/data/faq.pdf")
           .build();
       

      Supports the same path prefixes as @EasyRAG: classpath:, file:, or plain relative paths.

      Parameters:
      sources - one or more document paths
      Returns:
      this builder
      See Also:
    • withRAG

      public AssistantBuilder<T> withRAG(String[] sources, int maxResults, double minScore)
      Enables RAG with full control over retrieval parameters.
      
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG(
               new String[]{"file:/data/policy.pdf", "file:/data/terms.pdf"},
               5,     // return top 5 relevant segments
               0.7    // only segments with 70%+ relevance
           )
           .build();
       
      Parameters:
      sources - one or more document paths
      maxResults - maximum number of relevant segments to retrieve (default 3)
      minScore - minimum relevance score, 0.0 to 1.0 (default 0.5)
      Returns:
      this builder
    • withRAG

      public AssistantBuilder<T> withRAG(DocumentSource... sources)
      Enables RAG from in-memory document sources (byte arrays).

      Use this when your documents come from a DMS, database, REST API, or any source that provides content as byte[].

      
       // From a DMS
       byte[] pdfBytes = dmsClient.downloadDocument("DOC-12345");
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG(DocumentSource.of("policy.pdf", pdfBytes))
           .build();
      
       // From a database BLOB
       byte[] content = resultSet.getBytes("document_content");
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG(DocumentSource.of("terms.pdf", content))
           .build();
      
       // Plain text (no file needed)
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG(DocumentSource.ofText("policy", "All employees get 25 vacation days..."))
           .build();
      
       // Multiple documents from different sources
       PolicyBot bot = EasyAI.assistant(PolicyBot.class)
           .withRAG(
               DocumentSource.of("policy.pdf", dmsClient.download("policy")),
               DocumentSource.of("faq.txt", restApi.getFaqBytes()),
               DocumentSource.ofText("extra-rules", additionalRulesText)
           )
           .build();
       
      Parameters:
      sources - one or more document sources with content as byte arrays
      Returns:
      this builder
      See Also:
    • withRAG

      public AssistantBuilder<T> withRAG(List<DocumentSource> sources, int maxResults, double minScore)
      Enables RAG from in-memory document sources with tuning parameters.
      Parameters:
      sources - document sources with content as byte arrays
      maxResults - maximum number of relevant segments to retrieve
      minScore - minimum relevance score, 0.0 to 1.0
      Returns:
      this builder
    • withChatLanguageModel

      public AssistantBuilder<T> withChatLanguageModel(dev.langchain4j.model.chat.ChatLanguageModel model)
    • build

      public T build()