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.