@UserMessage 注解是 LangChain4j 中用于标记用户输入消息的核心注解,主要作用是指定每次调用 AI 服务时要使用的完整用户消息或用户消息模板。用户消息可以包含模板变量,这些变量将通过用 @V 注释的方法参数中的值来解析。例如:
interface Assistant {
@UserMessage("Say hello to {{name}}")
String greet(@V("name") String name);
}上述代码,{{name}} 占位符将使用 name 参数的实际值进行替换。
@UserMessage 也可以与方法参数一起使用:
interface Assistant {
@SystemMessage("You are a {{characteristic}} assistant")
String chat(@UserMessage String userMessage, @V("characteristic") String characteristic);
}在这种情况下,String userMessage 可能包含未解析的模板变量(例如 “{{characteristic}}”),这些变量将使用带有 @V 注解的方法参数值来解析。
该注解位于 dev.langchain4j.service 包下,定义如下:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER})
public @interface UserMessage {
// 提示词模板可以定义为一行或多行。如果模板定义为多行,这些行将通过下面定义的分隔符(delimiter() 定义)连接起来。
String[] value() default {""};
// 当 value 为多字符串数组时,用于拼接各段文本的分隔符。
String delimiter() default "\n";
// 用于读取提示模板的资源。
// 如果未指定资源,提示模板将从 value() 中获取。
// 如果未找到该资源,将抛出 IllegalConfigurationException。
// 资源将通过在 AI 服务类(接口)上调用 Class.getResourceAsStream(String) 来读取该资源
String fromResource() default "";
}现在,让我们假设我们使用的模型不支持系统消息,或者我们可能只是想为此目的使用 UserMessage。那么,可以将系统提示信息放在用户消息中,像这样做:
interface Friend {
@UserMessage("你是我的好哥们儿/好姐们儿。用俚语来回答哈。 {{it}}")
String chat(String userMessage);
}
Friend friend = AiServices.create(Friend.class, model);
String answer = friend.chat("你好"); // Hey! What's shakin'?我们已经用 @UserMessage 替换了 @SystemMessage 注解,并指定了一个包含变量 it 的提示模板({{it}}),该变量引用了唯一的方法参数。
注意:{{it}} 中的 it 指默认上下文变量,指代当前方法的唯一输入参数。
完整代码如下:
package com.hxstrive.langchain4j.aiServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.UserMessage;
public class AnnotationUserMessageDemo {
// 推荐:将OPEN_API_KEY设置成环境变量, 避免硬编码或随着代码泄露
// 注意,设置完环境变量记得重启IDEA,不然可能环境变量不会生效
private static final String API_KEY = System.getenv("OPEN_API_KEY");
// 定义业务接口
interface Friend {
@UserMessage("你是我的好哥们儿/好姐们儿。用俚语来回答哈。{{it}}")
String chat(String userMessage);
}
public static void main(String[] args) {
// 创建 ChatModel 实现类(OpenAI 为例)
ChatModel chatModel = OpenAiChatModel.builder()
.baseUrl("https://api.xty.app/v1")
.apiKey(API_KEY)
.modelName("gpt-3.5-turbo")
.temperature(0.7)
.logRequests(true)
.logResponses(false)
.build();
// 使用 AiServices 创建服务
Friend assistant = AiServices.builder(Friend.class)
.chatModel(chatModel)
.build();
// 发起对话
String answer = assistant.chat("你好! ");
System.out.println(answer);
}
}运行示例,输出如下:
[main] INFO dev.langchain4j.http.client.log.LoggingHttpClient -- HTTP request:
- method: POST
- url: https://api.xty.app/v1/chat/completions
- headers: [Authorization: Beare...00], [User-Agent: langchain4j-openai], [Content-Type: application/json]
- body: {
"model" : "gpt-3.5-turbo",
"messages" : [ {
"role" : "user",
"content" : "你是我的好哥们儿/好姐们儿。用俚语来回答哈。你好! "
} ],
"temperature" : 0.7,
"stream" : false
}
哈哈,嗨~兄弟/姐妹!😎
来啦来啦,状态在线!有啥事儿直说,咱唠就完了~
今天咋样?🔥
Process finished with exit code 0当然,也可以用 @V 来注解 String userMessage,并为提示模板变量分配一个自定义名称:
interface Friend {
@UserMessage("你是我的好哥们儿/好姐们儿。用俚语来回答哈。{{message}}")
String chat(@V("message") String userMessage);
}请注意,在将 LangChain4j 与 Quarkus 或 Spring Boot 一起使用时,无需使用 @V。只有在 Java 编译期间未启用 -parameters 选项时,此注解才有必要。
@UserMessage 还可以从资源中加载提示模板:
interface Friend {
@UserMessage(fromResource = "my-user-prompt-template.txt")
String chat(String userMessage);
}注意,将 my-user-prompt-template.txt 文件放在 maven 项目的 resources 目录。