feat(autocontext): support custom context compress prompt#386
Conversation
Change-Id: I245703e09158de869fb1fa297d8f7cba1fbb2af6
Change-Id: I604015fed79efef852979b523e033928e7ad4f5e
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR adds support for customizable context compression prompts in AutoContextMemory, enabling users to tailor compression behavior for specific domains and scenarios. The implementation includes new configuration classes, comprehensive test coverage, and updated documentation in both English and Chinese.
Key changes:
- Introduced
PromptConfigandPromptProviderclasses to support custom compression prompts with fallback to defaults - Added
customPromptfield toAutoContextConfigfor optional prompt customization - Updated documentation with detailed usage examples and domain-specific prompt templates
- Relaxed
AutoContextHookrequirement from "must use" to "recommended" for better flexibility
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| PromptConfig.java | New configuration class using builder pattern for custom compression prompts |
| PromptProvider.java | New utility class providing prompt selection with automatic fallback to defaults |
| AutoContextConfig.java | Added customPrompt field and getter with builder support |
| AutoContextMemory.java | Integrated custom prompts via PromptProvider in compression strategies |
| Prompts.java | Separated character count requirement from main compression prompt for Strategy 6 |
| PromptConfigTest.java | Comprehensive unit tests for PromptConfig builder pattern and getters |
| PromptProviderTest.java | Unit tests for PromptProvider fallback logic with various scenarios |
| AutoContextConfigTest.java | Tests for customPrompt integration in AutoContextConfig |
| AutoContextMemoryTest.java | Integration tests verifying custom prompt usage in memory compression |
| README.md | Added custom prompt documentation with e-commerce domain example |
| README_zh.md | Chinese version of custom prompt documentation |
| AutoMemoryExample.java | Removed StudioManager initialization (unrelated cleanup) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...ons-autocontext-memory/src/main/java/io/agentscope/core/memory/autocontext/PromptConfig.java
Outdated
Show resolved
Hide resolved
...ons-autocontext-memory/src/main/java/io/agentscope/core/memory/autocontext/PromptConfig.java
Outdated
Show resolved
Hide resolved
...ons-autocontext-memory/src/main/java/io/agentscope/core/memory/autocontext/PromptConfig.java
Outdated
Show resolved
Hide resolved
| public PromptConfig build() { | ||
| return config; | ||
| } |
There was a problem hiding this comment.
Missing Javadoc for public method build(). All public methods must have Javadoc according to coding guidelines.
| public String getPreviousRoundToolCompressPrompt() { | ||
| return previousRoundToolCompressPrompt; | ||
| } | ||
|
|
||
| public String getPreviousRoundSummaryPrompt() { | ||
| return previousRoundSummaryPrompt; | ||
| } | ||
|
|
||
| public String getCurrentRoundLargeMessagePrompt() { | ||
| return currentRoundLargeMessagePrompt; | ||
| } | ||
|
|
||
| public String getCurrentRoundCompressPrompt() { | ||
| return currentRoundCompressPrompt; | ||
| } |
There was a problem hiding this comment.
Missing Javadoc for public getter methods. All public methods must have Javadoc according to coding guidelines.
| public static Builder builder() { | ||
| return new Builder(); | ||
| } |
There was a problem hiding this comment.
Missing Javadoc for public method builder(). All public methods must have Javadoc according to coding guidelines.
...ons-autocontext-memory/src/main/java/io/agentscope/core/memory/autocontext/PromptConfig.java
Show resolved
Hide resolved
| @Test | ||
| @DisplayName("Should handle empty string prompts") | ||
| void testEmptyStringPrompts() { | ||
| PromptConfig config = | ||
| PromptConfig.builder() | ||
| .previousRoundToolCompressPrompt("") | ||
| .previousRoundSummaryPrompt("") | ||
| .build(); | ||
|
|
||
| assertEquals("", config.getPreviousRoundToolCompressPrompt()); | ||
| assertEquals("", config.getPreviousRoundSummaryPrompt()); | ||
| } |
There was a problem hiding this comment.
The test for empty string prompts may expose unexpected behavior. When a user sets an empty string as a custom prompt, it will be used instead of falling back to the default. This might not be the intended behavior - typically empty or blank strings should be treated the same as null and fall back to defaults. Consider validating input or treating empty/blank strings as null in PromptProvider methods.
...s-autocontext-memory/src/main/java/io/agentscope/core/memory/autocontext/PromptProvider.java
Show resolved
Hide resolved
...s-autocontext-memory/src/main/java/io/agentscope/core/memory/autocontext/PromptProvider.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Getters (return null to use default value) | ||
| public String getPreviousRoundToolCompressPrompt() { | ||
| return previousRoundToolCompressPrompt; | ||
| } | ||
|
|
||
| public String getPreviousRoundSummaryPrompt() { | ||
| return previousRoundSummaryPrompt; | ||
| } | ||
|
|
||
| public String getCurrentRoundLargeMessagePrompt() { | ||
| return currentRoundLargeMessagePrompt; | ||
| } | ||
|
|
||
| public String getCurrentRoundCompressPrompt() { | ||
| return currentRoundCompressPrompt; | ||
| } |
There was a problem hiding this comment.
The public getter methods (getPreviousRoundToolCompressPrompt, getPreviousRoundSummaryPrompt, getCurrentRoundLargeMessagePrompt, getCurrentRoundCompressPrompt) are missing Javadoc documentation. According to the coding guidelines, all public methods must have Javadoc comments. The inline comment "return null to use default value" should be incorporated into proper Javadoc @return tags.
| private PromptConfig config = new PromptConfig(); | ||
|
|
||
| /** Strategy 1: Sets prompt for compressing previous round tool invocations */ | ||
| public Builder previousRoundToolCompressPrompt(String prompt) { | ||
| config.previousRoundToolCompressPrompt = prompt; | ||
| return this; | ||
| } | ||
|
|
||
| /** Strategy 4: Sets prompt for summarizing previous round conversations */ | ||
| public Builder previousRoundSummaryPrompt(String prompt) { | ||
| config.previousRoundSummaryPrompt = prompt; | ||
| return this; | ||
| } | ||
|
|
||
| /** Strategy 5: Sets prompt for summarizing current round large messages */ | ||
| public Builder currentRoundLargeMessagePrompt(String prompt) { | ||
| config.currentRoundLargeMessagePrompt = prompt; | ||
| return this; | ||
| } | ||
|
|
||
| /** Strategy 6: Sets prompt for compressing current round messages (supports format: %d, %d, %.0f, %.0f) */ | ||
| public Builder currentRoundCompressPrompt(String prompt) { | ||
| config.currentRoundCompressPrompt = prompt; | ||
| return this; | ||
| } | ||
|
|
||
| public PromptConfig build() { | ||
| return config; | ||
| } | ||
| } | ||
|
|
||
| public static Builder builder() { | ||
| return new Builder(); | ||
| } | ||
|
|
||
| // Getters (return null to use default value) | ||
| public String getPreviousRoundToolCompressPrompt() { | ||
| return previousRoundToolCompressPrompt; | ||
| } | ||
|
|
||
| public String getPreviousRoundSummaryPrompt() { | ||
| return previousRoundSummaryPrompt; | ||
| } | ||
|
|
||
| public String getCurrentRoundLargeMessagePrompt() { | ||
| return currentRoundLargeMessagePrompt; | ||
| } | ||
|
|
There was a problem hiding this comment.
The Builder pattern implementation has a critical thread-safety and reusability issue. The builder stores a single mutable PromptConfig instance and modifies it across multiple method calls. This creates two problems:
-
If a Builder instance is reused to build multiple PromptConfig objects, all built instances will reference the same underlying object, causing unintended shared state.
-
The builder is not thread-safe, as multiple threads could access and modify the same config instance.
The builder should create a new PromptConfig instance in the build() method or use a defensive copy approach. For example, the build() method should transfer values from builder fields to a new PromptConfig instance.
| private PromptConfig config = new PromptConfig(); | |
| /** Strategy 1: Sets prompt for compressing previous round tool invocations */ | |
| public Builder previousRoundToolCompressPrompt(String prompt) { | |
| config.previousRoundToolCompressPrompt = prompt; | |
| return this; | |
| } | |
| /** Strategy 4: Sets prompt for summarizing previous round conversations */ | |
| public Builder previousRoundSummaryPrompt(String prompt) { | |
| config.previousRoundSummaryPrompt = prompt; | |
| return this; | |
| } | |
| /** Strategy 5: Sets prompt for summarizing current round large messages */ | |
| public Builder currentRoundLargeMessagePrompt(String prompt) { | |
| config.currentRoundLargeMessagePrompt = prompt; | |
| return this; | |
| } | |
| /** Strategy 6: Sets prompt for compressing current round messages (supports format: %d, %d, %.0f, %.0f) */ | |
| public Builder currentRoundCompressPrompt(String prompt) { | |
| config.currentRoundCompressPrompt = prompt; | |
| return this; | |
| } | |
| public PromptConfig build() { | |
| return config; | |
| } | |
| } | |
| public static Builder builder() { | |
| return new Builder(); | |
| } | |
| // Getters (return null to use default value) | |
| public String getPreviousRoundToolCompressPrompt() { | |
| return previousRoundToolCompressPrompt; | |
| } | |
| public String getPreviousRoundSummaryPrompt() { | |
| return previousRoundSummaryPrompt; | |
| } | |
| public String getCurrentRoundLargeMessagePrompt() { | |
| return currentRoundLargeMessagePrompt; | |
| } | |
| private String previousRoundToolCompressPrompt; | |
| private String previousRoundSummaryPrompt; | |
| private String currentRoundLargeMessagePrompt; | |
| private String currentRoundCompressPrompt; | |
| /** Strategy 1: Sets prompt for compressing previous round tool invocations */ | |
| public Builder previousRoundToolCompressPrompt(String prompt) { | |
| this.previousRoundToolCompressPrompt = prompt; | |
| return this; | |
| } | |
| /** Strategy 4: Sets prompt for summarizing previous round conversations */ | |
| public Builder previousRoundSummaryPrompt(String prompt) { | |
| this.previousRoundSummaryPrompt = prompt; | |
| return this; | |
| } | |
| /** Strategy 5: Sets prompt for summarizing current round large messages */ | |
| public Builder currentRoundLargeMessagePrompt(String prompt) { | |
| this.currentRoundLargeMessagePrompt = prompt; | |
| return this; | |
| } | |
| /** | |
| * Strategy 6: Sets prompt for compressing current round messages | |
| * (supports format: %d, %d, %.0f, %.0f). | |
| * | |
| * @param prompt the prompt template for compressing current round messages | |
| * @return this builder instance | |
| */ | |
| public Builder currentRoundCompressPrompt(String prompt) { | |
| this.currentRoundCompressPrompt = prompt; | |
| return this; | |
| } | |
| /** | |
| * Builds a new {@link PromptConfig} instance using the values configured on this builder. | |
| * | |
| * @return a new {@link PromptConfig} instance | |
| */ | |
| public PromptConfig build() { | |
| PromptConfig config = new PromptConfig(); | |
| config.previousRoundToolCompressPrompt = this.previousRoundToolCompressPrompt; | |
| config.previousRoundSummaryPrompt = this.previousRoundSummaryPrompt; | |
| config.currentRoundLargeMessagePrompt = this.currentRoundLargeMessagePrompt; | |
| config.currentRoundCompressPrompt = this.currentRoundCompressPrompt; | |
| return config; | |
| } | |
| } | |
| /** | |
| * Creates a new {@link Builder} for configuring {@link PromptConfig} instances. | |
| * | |
| * @return a new {@link Builder} instance | |
| */ | |
| public static Builder builder() { | |
| return new Builder(); | |
| } | |
| // Getters (return null to use default value) | |
| /** | |
| * Gets the prompt for compressing previous round tool invocations. | |
| * | |
| * @return the configured prompt, or {@code null} to use the default value | |
| */ | |
| public String getPreviousRoundToolCompressPrompt() { | |
| return previousRoundToolCompressPrompt; | |
| } | |
| /** | |
| * Gets the prompt for summarizing previous round conversations. | |
| * | |
| * @return the configured prompt, or {@code null} to use the default value | |
| */ | |
| public String getPreviousRoundSummaryPrompt() { | |
| return previousRoundSummaryPrompt; | |
| } | |
| /** | |
| * Gets the prompt for summarizing current round large messages. | |
| * | |
| * @return the configured prompt, or {@code null} to use the default value | |
| */ | |
| public String getCurrentRoundLargeMessagePrompt() { | |
| return currentRoundLargeMessagePrompt; | |
| } | |
| /** | |
| * Gets the prompt for compressing current round messages. | |
| * | |
| * @return the configured prompt, or {@code null} to use the default value | |
| */ |
| * default prompts from {@link Prompts} when custom prompts are not provided. | ||
| */ | ||
| public class PromptProvider { | ||
|
|
There was a problem hiding this comment.
PromptProvider is a utility class with only static methods but lacks a private constructor. According to Java best practices, utility classes should have a private constructor to prevent instantiation. This makes the intent clearer and prevents accidental instantiation.
| private PromptProvider() { | |
| } |
| /** Strategy 6: Prompt for compressing current round messages (supports format: %d, %d, %.0f, %.0f) */ | ||
| private String currentRoundCompressPrompt; |
There was a problem hiding this comment.
The comment mentions format support "supports format: %d, %d, %.0f, %.0f" which appears to be incorrect. Based on the Prompts.java changes, the character count requirement has been separated into CURRENT_ROUND_MESSAGE_COMPRESS_CHAR_REQUIREMENT, and the currentRoundCompressPrompt itself no longer contains format placeholders. The comment should be updated to reflect that this prompt does not include character count requirements, which are handled separately.
| /** Strategy 6: Sets prompt for compressing current round messages (supports format: %d, %d, %.0f, %.0f) */ | ||
| public Builder currentRoundCompressPrompt(String prompt) { | ||
| config.currentRoundCompressPrompt = prompt; | ||
| return this; |
There was a problem hiding this comment.
The comment mentions format support "supports format: %d, %d, %.0f, %.0f" which appears to be incorrect. Based on the Prompts.java changes, the character count requirement has been separated into CURRENT_ROUND_MESSAGE_COMPRESS_CHAR_REQUIREMENT, and the currentRoundCompressPrompt itself no longer contains format placeholders. The comment should be updated to reflect that this prompt does not include character count requirements, which are handled separately.
| public static Builder builder() { | ||
| return new Builder(); | ||
| } |
There was a problem hiding this comment.
The public static builder() method is missing Javadoc documentation. According to the coding guidelines, all public methods must have Javadoc comments that explain their purpose, parameters, and return values.
This pull request introduces support for customizable context compression prompts in
AutoContextMemory, allowing users to fine-tune how memory compression operates for specific domains and scenarios. The documentation in both English and Chinese has been updated to reflect these changes, and the integration requirements forAutoContextHookhave been relaxed from "required" to "recommended" for easier adoption and flexibility.Custom Prompt Support & Documentation Updates
customPromptfield toAutoContextConfigand corresponding getter, enabling users to specify aPromptConfigfor domain-specific context compression prompts. [1] [2]README.md,README_zh.md) to describe the new customizable prompt feature, including usage examples and domain-specific prompt templates (e.g., e-commerce order processing). [1] [2] [3] [4] [5] [6]customPromptas a documented configuration parameter in the configuration tables. [1] [2]Integration & Usage Guidance Improvements
AutoContextHookfrom "must use" to "recommended," clarifying that it is no longer strictly required but still best practice for automatic setup. This is reflected in both documentation and code comments. [1] [2] [3] [4] [5] [6]Other Documentation Refinements
These changes make
AutoContextMemorymore flexible and adaptable to real-world business needs, while improving clarity and usability for developers integrating it into their agents.## AgentScope-Java Version[The version of AgentScope-Java you are working on, e.g. 1.0.4, check your pom.xml dependency version or run
mvn dependency:tree | grep agentscope-parent:pom(only mac/linux)]Description
[Please describe the background, purpose, changes made, and how to test this PR]
Checklist
Please check the following items before code is ready to be reviewed.
mvn spotless:applymvn test)