There is an analogy to make between GenerationTemplate and JdbcTemplate that will help simplify the use of the lower level classes such as AiClient, Prompts, and OutputParsers. Note: AiClient should likely be renamed GenerationClient as it is focused on generation, specifcally text, so perhaps even TextGenerationClient as we haven't yet experimented with multi-modal apis.

DataSource <-> AiClient

String Query with placeholdres <-> Prompt with placeholders

RowMapper <-> OutputParser

The simplest method (which is a default method in AiClient) is string input and string output, that could be removed from the AiClient interface and used in GenerateTemplate instead. Here are a few sample signatures for consideration.

public interface GenerateOperations {

    String generate(String message);

    String generate(String message, Map<String, Object> model)

    String generate(PromptTemplate promptTemplate, Map<String, Object> model);

    <T> T generate(String message, Class<T> elementType, Map<String, Object> model);

    <T> T generate(String message, OutputParser<T> parser, Map<String, Object> model);

    <T> List<T> generateList(String message, Class<T> elementType, Map<String, Object> model);

    <T> List<T> generateList(String message, OutputParser<T> parser, Map<String, Object> model);

        AiResponse generateResponse(PromptTemplate promptTemplate, Map<String, Object> model);
}

Example usage

ActorsFilms actorsFilms = generateTemplate.generate("Generate the filmography for the actor {actor}",
                                            ActorsFilms.class, Map.of("actor", "Tom Hanks"));

Simple "chains" for flows can be done with standard Java functional programming, and we can see how our needs for a "chain" or a "flow" evolve over time. e.g. the example of a chain from langchain using functional programming

    @Test
    void functionalChains() {
        Function<String, String> combinedFunction = generateSynopsis.andThen(generateReview);
        System.out.println(combinedFunction.apply("Tragedy at sunset on the beach"));
    }

    private Function<String, String> generateSynopsis = title -> {
        String synopsisInput = """
                You are a playwright. Given the title of play, it is your job to write a synopsis for that title.

                Title: {title}
                Playwright: This is a synopsis for the above play:""";

        return generateTemplate.generate(synopsisInput, Map.of("title", title));
    };

    private Function<String, String> generateReview = synopsis -> {
        String synopsisInput = """
                You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.

                Play Synopsis:
                {synopsis}
                Review from a New York Times play critic of the above play:""";

        return generateTemplate.generate(synopsisInput, Map.of("synopsis", synopsis));
    };

Comment From: markpollack

As a note, a new issue to create a 'GenerateTextOperation' class that has a fluent api, akin to SimpleJdbcCall and company

Comment From: markpollack

this has been addressed with the fluent api in the updated chatclient.