在langchain4j中 UserMessage注解和SystemMessage两个注解的区别
在 LangChain4j 框架中,@UserMessage 和 @SystemMessage 是构建 AI 服务时控制提示词(Prompt)的核心注解,两者的作用与使用场景有显著区别:
一、核心作用对比
注解类型 | 功能定位 | 典型应用场景 |
---|---|---|
@SystemMessage | 设定 AI 角色与行为准则:定义系统级指令,用于控制 AI 的固定行为模式或角色身份。 | - 设定 AI 身份(如“法律顾问”“作家”) - 限制回答范围(如“仅用中文回答”) - 注入全局规则(如“不要虚构法律条文”) |
@UserMessage | 标注用户输入内容:标记动态的用户请求或问题,作为 AI 生成答案的主要依据。 | - 接收用户提问(如“如何解除劳动合同?”) - 传递动态参数(如生成文章的字数限制) - 多模态输入(文本、图片等) |
二、技术特性差异
维度 | @SystemMessage | @UserMessage |
---|---|---|
作用域 | 通常作用于接口或方法级别,全局生效 | 通常作用于方法参数级别,单次调用生效 |
变量注入方式 | 支持 {{变量名}} 语法引用方法参数(需搭配 @V("变量名") 注解) | 支持直接引用参数值(如 {{it}} 表示第一个参数)或通过 @V 指定变量名 |
对话内存处理 | 默认被 ChatMemory 保留,不会被驱逐策略清除(如 MessageWindowChatMemory ) | 作为普通用户消息存入 ChatMemory ,可能被驱逐策略清除 |
多消息支持 | 同一对话中仅保留一条有效 SystemMessage ,重复定义会覆盖 | 可多次添加 UserMessage ,形成多轮对话 |
底层实现 | 生成 SystemMessage 类型的 ChatMessage ,在请求中作为系统指令发送 | 生成 UserMessage 类型的 ChatMessage ,作为用户输入发送 |
三、实战示例解析
1. 角色定义与输入处理
// 系统指令:设定 AI 为法律顾问,并限制回答格式
@SystemMessage({"你是一名专业法律顾问,熟悉《中华人民共和国劳动合同》","回答需包含法律条文引用,格式:根据《XX法》第X条..."
})
interface LegalAdvisor {// 用户输入:动态接收劳动合同问题String answer(@UserMessage String question);
}
- @SystemMessage:定义 AI 的专业领域和回答规范
- @UserMessage:标注用户提问参数
question
,动态生成提示词
2. 动态参数注入
// 系统提示中引用方法参数
@SystemMessage("生成一篇关于{{theme}}的{{wordCount}}字作文")
interface Writer {String generate(@V("theme") String theme, @V("wordCount") int wordCount);
}
{{theme}}
和{{wordCount}}
从方法参数动态注入
四、使用注意事项
-
避免冲突
- 若同时使用接口级别和方法级别的
@SystemMessage
,后者会覆盖前者。 @UserMessage
标注的参数需与提示模板中的变量名匹配,否则会引发VariableNotFoundException
。
- 若同时使用接口级别和方法级别的
-
性能优化
- 复杂的
@SystemMessage
提示词可存入资源文件,通过@SystemMessage("file:legal_prompt.txt")
加载。 - 高频调用的服务建议启用
ChatMemory
缓存,避免重复生成提示词。
- 复杂的
-
调试技巧
- 通过
AiService
的debug()
方法打印完整提示词,验证变量替换效果。 - 使用
StructuredPrompt
替代复杂@SystemMessage
,实现 JSON/XML 等结构化输出。
- 通过
五、引用说明
- :通过
@SystemMessage
实现角色扮演(如作家、法律顾问),动态参数通过{{变量}}
注入。 - :
SystemMessage
作为系统指令影响 AI 行为,UserMessage
处理用户输入。 - :
SystemMessage
的覆盖规则与内存管理特性。 - :变量绑定与多轮对话实现方式。