主题
14 · 结构化提示词元素(Structured Prompt Elements)
Embabel 提供多种方式来表达与管理提示词内容。
Prompt contributor(提示词贡献器) 是把内容结构化地注入 LLM 提示词的一种基础方式。 你不必使用它们 —— 完全可以直接把提示词拼成字符串 —— 但当你想在多个动作、甚至多个使用同一批领域对象的 Agent 之间取得一致性与复用时,它们很有用。
Prompt contributor 实现 PromptContributor 接口,提供一段文本,最终会被包含进发给 LLM 的提示词里。 默认情况下,这段文本会放进 system prompt 消息中。
PromptContributor 接口与它的子接口 LlmReference
所有 prompt contributor 都实现 PromptContributor 接口,其中 contribution() 方法返回要放进提示词的字符串。
用 withPromptContributor() 方法把 PromptContributor 实例加入 PromptRunner。
PromptContributor 有一个子接口:LlmReference。
LlmReference 是一种 prompt contributor,同时还能通过带注解的 @Tool 方法提供工具。 为了能消除工具命名歧义,LlmReference 必须包含 name 与 description 元数据。
用 withReference() 方法把 LlmReference 实例加入 PromptRunner。
在以下情况使用 LlmReference:
- 你想从同一个对象同时提供提示词内容与工具;
- 你想给出如何使用这些工具的具体说明,而不仅是单个工具的描述;
- 你的数据视上下文而定,既适合作为提示词内容、也适合作为工具暴露。 例如你有 10 个条目,直接放进提示词说"这是全部条目:…"即可; 但如果你有 10,000 个对象,就应该附上"请用工具查询它们"的指引。
LlmReference 在某种程度上类似于 Claude Skill。
LlmReference 实例既可以通过编程方式创建,也可以用 LlmReferenceProvider 实现在 YML 中定义。 例如,你可以定义一个 references.yml:
yaml
- fqn: com.embabel.coding.tools.git.GitHubRepository
url: https://github.com/embabel/embabel-agent-examples.git
description: Embabel examples Repository
- fqn: com.embabel.coding.tools.git.GitHubRepository
url: https://github.com/embabel/java-agent-template.git
description: >
Java agent template Repository: Simplest Java example with Maven
Can be used as a GitHub template
- fqn: com.embabel.coding.tools.git.GitHubRepository
url: https://github.com/embabel/embabel-agent.git
description: >
Embabel agent framework implementation repo: Look to check code under embabel-agent-api
- fqn: com.embabel.coding.tools.api.ApiReferenceProvider
name: embabel-agent
description: Embabel Agent API
acceptedPackages:
- com.embabel.agent
- com.embabel.commonfqn 属性指定 LlmReferenceProvider 实现的全限定类名。这让你可以定义自己的 LlmReferenceProvider 实现。 开箱即用,Embabel 提供:
com.embabel.agent.api.reference.LiteralText:notes 中的文本;com.embabel.agent.api.reference.SpringResource:给定 Spring 资源路径的内容;com.embabel.agent.api.reference.WebPage:给定网页的内容(若能抓取到);com.embabel.coding.tools.git.GitHubRepository:GitHub 仓库(embabel-agent-code模块);com.embabel.coding.tools.api.ApiReferenceProvider:来自 classpath 的 API(embabel-agent-code模块)。
你可以用 LlmReferenceProviders.fromYml 方法把 YML 文件解析成 List<LlmReference>。
其 resource 参数是一个 Spring 资源描述。因此 LlmReferenceProviders.fromYml("references.yml") 会加载 src/main/resources/ 下的 references.yml。
内置便捷类(Built-in Convenience Classes)
Embabel 提供了若干为常见用例实现 PromptContributor 的便捷类。 这些都是可选工具 —— 有自定义需求时,你随时可以直接实现接口。
Persona
Persona 类提供了一种结构化方式来定义 AI Agent 的人格与行为:
java
var persona = Persona.create(
"Alex the Analyst",
"A detail-oriented data analyst with expertise in financial markets",
"Professional yet approachable, uses clear explanations",
"Help users understand complex financial data through clear analysis"
);它生成的提示词贡献类似:
You are Alex the Analyst.
Your persona: A detail-oriented data analyst with expertise in financial markets.
Your objective is Help users understand complex financial data through clear analysis.
Your voice: Professional yet approachable, uses clear explanations.RoleGoalBackstory
RoleGoalBackstory 类遵循 Crew AI 的模式,是为从该框架迁移过来的用户准备的:
java
var agent = RoleGoalBackstory.withRole("Senior Software Engineer")
.andGoal("Write clean, maintainable code")
.andBackstory("10+ years experience in enterprise software development");它生成:
Role: Senior Software Engineer
Goal: Write clean, maintainable code
Backstory: 10+ years experience in enterprise software development自定义 PromptContributor 实现
你可以直接实现接口来创建自定义 prompt contributor,从而完全掌控提示词内容:
java
public class CustomSystemPrompt implements PromptContributor {
private final String systemName;
public CustomSystemPrompt(String systemName) {
this.systemName = systemName;
}
@Override
public String contribution() {
return "System: " + systemName + " - Current time: " + LocalDateTime.now();
}
}
public class ConditionalPrompt implements PromptContributor {
private final Supplier<Boolean> condition;
private final String trueContent;
private final String falseContent;
public ConditionalPrompt(Supplier<Boolean> condition, String trueContent, String falseContent) {
this.condition = condition;
this.trueContent = trueContent;
this.falseContent = falseContent;
}
@Override
public String contribution() {
return condition.get() ? trueContent : falseContent;
}
}来自 embabel-agent-examples 的示例
embabel-agent-examples 仓库演示了多种 Agent 开发模式,以及用 Embabel 构建 AI Agent 时的 Spring Boot 集成方式。
最佳实践(Best Practices)
- 让每个 prompt contributor 聚焦、单一职责;
- 在合用的时候使用便捷类(
Persona、RoleGoalBackstory); - 针对领域特定需求,实现自定义
PromptContributor类; - 对依赖上下文的内容,考虑使用动态贡献器;
- 测试你的提示词贡献,确保它们产生期望的 LLM 行为。