
AIServices 和 Chains都是 langserver4j中提供的高级API。封装了ChatModel 、 ChatMessage 、 ChatMemory 等低级组件。提供更加方便简单的使用方式。
LLM 驱动的应用程序通常不仅需要一个组件,而是需要多个组件协同工作(例如,提示模板、聊天记忆、LLMs、输出解析器、RAG 组件:嵌入模型和存储)并且经常涉及多个交互,因此协调它们变得更加繁琐。所以Langchain4j提供了高级API来简化开发。
链的概念起源于 Python 的 LangChain。在Langchain4j中已经逐渐不再维护。转而定义了AiService。
AiService将与 LLMs 和其他组件交互的复杂性隐藏在简单的 API 后面。这种方法与 Spring Data JPA 非常相似:声明性地定义一个具有所需 API 的接口,LangChain4j 提供了一个实现此接口的对象(代理)。可以将 AI 服务视为应用程序服务层的一个组件。它提供 AI 服务。因此得名。
底层实现:反射+代理。根据定义的AiService接口+配置的低级组件,生成代理类。
使用方式:
@AiService
interface Assistant {
@SystemMessage("You are a polite assistant")
String chat(String userMessage);
}
@Autowired
Assistant assistant;
public void chatMeme() {
ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(qwenChatModel)
.chatMemory(chatMemory)
.build();
String answer = assistant.chat("Hello! My name is Klaus.");
System.out.println(answer); // Hello Klaus! How can I assist you today?
String answerWithName = assistant.chat("What is my name?");
System.out.println(answerWithName); // Your name is Klaus.
}使用示例:
@SystemMessage("Given a name of a country, answer with a name of it's capital")
String chat(String userMessage);
@SystemMessage("Given a name of a country, answer with a name of it's capital")
String chat(@UserMessage String userMessage);
@SystemMessage("Given a name of a country, {{answerInstructions}}")
String chat(@V("answerInstructions") String answerInstructions, @UserMessage String userMessage);
@SystemMessage("Given a name of a country, answer with a name of it's capital")
String chat(@UserMessage String userMessage, @V("country") String country); // userMessage contains "{{country}}" template variable
@SystemMessage("Given a name of a country, {{answerInstructions}}")
String chat(@V("answerInstructions") String answerInstructions, @UserMessage String userMessage, @V("country") String country); // userMessage contains "{{country}}" template variable
@SystemMessage("Given a name of a country, answer with a name of it's capital")
@UserMessage("Germany")
String chat();
@SystemMessage("Given a name of a country, {{answerInstructions}}")
@UserMessage("Germany")
String chat(@V("answerInstructions") String answerInstructions);
@SystemMessage("Given a name of a country, answer with a name of it's capital")
@UserMessage("{{it}}")
String chat(String country);
@SystemMessage("Given a name of a country, answer with a name of it's capital")
@UserMessage("{{country}}")
String chat(@V("country") String country);
@SystemMessage("Given a name of a country, {{answerInstructions}}")
@UserMessage("{{country}}")
String chat(@V("answerInstructions") String answerInstructions, @V("country") String country);AI 服务方法可以返回以下类型之一:
String - 在这种情况下,LLM 生成的输出将直接返回,不进行任何处理/解析任何类型都可以额外包装成 Result<T> 以获取关于 AI 服务调用的额外元数据:
TokenUsage - 在 AI 服务调用期间使用的总令牌数。如果 AI 服务对 LLM 进行了多次调用(例如,因为执行了工具),它将汇总所有调用的令牌使用量。interface Assistant {
@UserMessage("Generate an outline for the article on the following topic: {{it}}")
Result<List<String>> generateOutlineFor(String topic);
}
Result<List<String>> result = assistant.generateOutlineFor("Java");
List<String> outline = result.content();
TokenUsage tokenUsage = result.tokenUsage();
List<Content> sources = result.sources();
List<ToolExecution> toolExecutions = result.toolExecutions();
FinishReason finishReason = result.finishReason();ChatResponsesChatResponse
示例://boolean类型
interface SentimentAnalyzer {
@UserMessage("Does {{it}} has a positive sentiment?")
boolean isPositive(String text);
}
SentimentAnalyzer sentimentAnalyzer = AiServices.create(SentimentAnalyzer.class, model);
boolean positive = sentimentAnalyzer.isPositive("It's wonderful!");
//枚举类型
enum Priority {
CRITICAL, HIGH, LOW
}
interface PriorityAnalyzer {
@UserMessage("Analyze the priority of the following issue: {{it}}")
Priority analyzePriority(String issueDescription);
}
PriorityAnalyzer priorityAnalyzer = AiServices.create(PriorityAnalyzer.class, model);
Priority priority = priorityAnalyzer.analyzePriority("The main payment gateway is down, and customers cannot process transactions.");
//POJO类型
class Person {
@Description("first name of a person") // you can add an optional description to help an LLM have a better understanding
String firstName;
String lastName;
LocalDate birthDate;
Address address;
}
@Description("an address") // you can add an optional description to help an LLM have a better understanding
class Address {
String street;
Integer streetNumber;
String city;
}
interface PersonExtractor {
@UserMessage("Extract information about a person from {{it}}")
Person extractPersonFrom(String text);
}
PersonExtractor personExtractor = AiServices.create(PersonExtractor.class, model);
String text = """
In 1968, amidst the fading echoes of Independence Day,
a child named John arrived under the calm evening sky.
This newborn, bearing the surname Doe, marked the start of a new journey.
He was welcomed into the world at 345 Whispering Pines Avenue
a quaint street nestled in the heart of Springfield
an abode that echoed with the gentle hum of suburban dreams and aspirations.
""";
Person person = personExtractor.extractPersonFrom(text);
System.out.println(person); 原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。