Conversation
…timization with "Gradient Descent" and Beam Search" of Pryzant et al. 2023
- add new redis cache replacement strategy
…n-module' into feature/add-protegi-optimization
There was a problem hiding this comment.
Pull request overview
This pull request adds the ProTeGi Prompt Optimizer, implementing an automatic prompt optimization approach based on gradient descent by Pryzant et al. (2023). The implementation transcribes the original Python code into the LiSSA framework and modifies the core optimization interface to return arrays of prompts representing all intermediate optimization states rather than just the final result.
Changes:
- Adds AutomaticPromptOptimizer with gradient-based prompt refinement using textual gradients and beam search
- Modifies PromptOptimizer interface to return String[] instead of String to capture all intermediate optimization states
- Implements cache improvements including OpenAI model instance caching and configurable cache conflict resolution strategies
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java | New gradient-based optimizer implementation with textual gradients, synonym generation, and beam search |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/GradientOptimizerConfig.java | Configuration record for gradient optimizer parameters |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/PromptOptimizer.java | Interface changed to return String[] instead of String |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeOptimizer.java | Updated to return array of prompts from all iterations |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeFeedbackOptimizer.java | Updated to return array of prompts from all iterations |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/MockOptimizer.java | Updated to return String[] instead of String |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/OptimizerFactory.java | Added gradient optimizer case to factory method |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/classifier/ChatLanguageModelProvider.java | Added singleton caching for OpenAI chat model instances |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/CacheReplacementStrategy.java | New enum defining strategies for cache conflict resolution |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/RedisCache.java | Integrated conflict resolution strategy |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/CacheManager.java | Updated to use new conflict resolution strategy |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/Statistics.java | Added method to generate statistics for specific iteration counts |
| src/main/java/edu/kit/kastel/sdq/lissa/ratlr/Optimization.java | Updated to handle array of prompts and generate statistics for each iteration |
| src/main/java/edu/kit/kastel/sdq/lissa/cli/command/OptimizeCommand.java | Updated to handle array of prompts and evaluate all iterations |
| src/test/java/edu/kit/kastel/sdq/lissa/ratlr/e2e/Requirement2RequirementE2ETest.java | Updated test to handle array return and select final prompt |
| src/test/resources/simplelogger.properties | Changed log level from debug to info |
| example-configs/gradient-optimizer-config.json | Example configuration file for gradient optimizer |
| src/test/resources/warc/WARC_gradient_gpt_gpt-4o-mini-2024-07-18_0.json | Test configuration file |
| src/test/resources/expected/GradientOptimizerExpectation.txt | Expected output for gradient optimizer test |
| src/test/resources/warc/cache/optimizerTests/gradient/*.json | Cached test responses |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/cli/command/OptimizeCommand.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeFeedbackOptimizer.java
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/classifier/ChatLanguageModelProvider.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java
Outdated
Show resolved
Hide resolved
…d-protegi-optimization # Conflicts: # src/main/java/edu/kit/kastel/sdq/lissa/cli/command/OptimizeCommand.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/CacheManager.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/cache/RedisCache.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeFeedbackOptimizer.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeOptimizer.java # src/test/resources/simplelogger.properties
…n-module' into feature/add-protegi-optimization # Conflicts: # src/main/java/edu/kit/kastel/sdq/lissa/cli/command/OptimizeCommand.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/Optimization.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeFeedbackOptimizer.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeOptimizer.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/OptimizerFactory.java # src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/PromptOptimizer.java
…h protegi" This reverts commit d5f758b.
…timizer" This reverts commit 83b5b7b
…d-protegi-optimization
src/main/java/edu/kit/kastel/sdq/lissa/cli/command/OptimizeCommand.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/classifier/ChatLanguageModelProvider.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/cli/command/OptimizeCommand.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/cli/command/OptimizeCommand.java
Outdated
Show resolved
Hide resolved
...it/kastel/sdq/lissa/ratlr/promptoptimizer/evaluator/UpperConfidenceBoundBanditEvaluator.java
Outdated
Show resolved
Hide resolved
...it/kastel/sdq/lissa/ratlr/promptoptimizer/evaluator/UpperConfidenceBoundBanditEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java
Outdated
Show resolved
Hide resolved
| import edu.kit.kastel.sdq.lissa.ratlr.promptoptimizer.samplestrategy.SampleStrategy; | ||
| import edu.kit.kastel.sdq.lissa.ratlr.promptoptimizer.samplestrategy.SamplerFactory; | ||
|
|
||
| public record GradientOptimizerConfig( |
There was a problem hiding this comment.
Docs. Also document what the different prompts are for
| @Nullable ModuleConfiguration configuration, | ||
| Set<TraceLink> goldStandard, | ||
| Metric metric, | ||
| Evaluator evaluator) { |
There was a problem hiding this comment.
The Evaluator is not (independently) nullable currently. Same as with the metric and goldstandard. The config null check may be extended to include any parameter, as the other parameters may be null iff config is also null.
- rename sampleAndEvaluate to selectAndEvaluate - add documentation - rework abstract base class as interface
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 27 out of 28 changed files in this pull request and generated 10 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeFeedbackOptimizer.java
Show resolved
Hide resolved
...u/kit/kastel/sdq/lissa/ratlr/promptoptimizer/promptselector/UpperConfidenceBoundBandits.java
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/GradientOptimizerConfig.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/promptselector/SimpleSelector.java
Outdated
Show resolved
Hide resolved
| private @Nullable ChatModel delegate; | ||
|
|
||
| /** | ||
| * Creates a new LazyChatModel with the specified supplier for the delegate. | ||
| * | ||
| * @param delegateSupplier The supplier that provides the chat model delegate | ||
| */ | ||
| public LazyChatModel(Supplier<ChatModel> delegateSupplier) { | ||
| this.delegateSupplier = Objects.requireNonNull(delegateSupplier); | ||
| } | ||
|
|
||
| private ChatModel delegate() { | ||
| if (delegate != null) { | ||
| return delegate; | ||
| } | ||
| synchronized (this) { | ||
| if (delegate == null) { | ||
| delegate = delegateSupplier.get(); | ||
| } | ||
| return delegate; | ||
| } |
There was a problem hiding this comment.
LazyChatModel uses double-checked locking, but delegate is not volatile. Without safe publication, another thread can observe a partially constructed delegate instance when reading delegate outside the synchronized block. Make delegate volatile (or synchronize all reads / use an AtomicReference/Supplier memoization) to ensure thread-safety matches the class Javadoc.
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/AutomaticPromptOptimizer.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/IterativeOptimizer.java
Show resolved
Hide resolved
… jackson json handling
…onfig.java to ProTeGiOptimizer(Config) for clarity - add doc section about the ProTeGi optimizer - add new "protegi" config alias but keep previous "gradient" for compatibility
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/classifier/LazyChatModel.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 29 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/ProTeGiOptimizer.java
Outdated
Show resolved
Hide resolved
| public record OptimizerConfiguration( | ||
| @JsonUnwrapped EvaluationConfiguration evaluationConfiguration, | ||
| @JsonProperty("prompt_optimizer") ModuleConfiguration promptOptimizer, | ||
| @JsonProperty("metric") ModuleConfiguration metric) | ||
| @JsonProperty(PROMPT_OPTIMIZER_FIELD) ModuleConfiguration promptOptimizer, | ||
| @JsonProperty("metric") ModuleConfiguration metric, | ||
| @JsonProperty("evaluator") ModuleConfiguration evaluator) |
There was a problem hiding this comment.
Making evaluator a mandatory field forces all existing optimizer configs to include an evaluator section; otherwise Jackson deserialization will fail. If backward compatibility is desired, consider making this field @Nullable and defaulting Selector.createSelector(null) to MockSelector (as it already does), and guard evaluator.finalizeForSerialization() accordingly.
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/MockOptimizer.java
Show resolved
Hide resolved
src/test/java/edu/kit/kastel/sdq/lissa/ratlr/e2e/Requirement2RequirementE2ETest.java
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/EvaluationResult.java
Show resolved
Hide resolved
...u/kit/kastel/sdq/lissa/ratlr/promptoptimizer/promptselector/UpperConfidenceBoundBandits.java
Outdated
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/ProTeGiOptimizer.java
Show resolved
Hide resolved
…roTeGiOptimizer.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 29 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/ProTeGiOptimizer.java
Show resolved
Hide resolved
| evaluationConfiguration.serializeAndDestroyConfiguration(); | ||
| promptOptimizer.finalizeForSerialization(); | ||
| metric.finalizeForSerialization(); | ||
| evaluator.finalizeForSerialization(); |
There was a problem hiding this comment.
serializeAndDestroyConfiguration() unconditionally calls evaluator.finalizeForSerialization(). If an optimization config omits the new evaluator section (e.g., older configs), evaluator will deserialize as null and this will throw a NullPointerException. Consider marking evaluator as @Nullable and null-checking here (defaulting to a mock selector), or enforce non-null by validation with a clearer error message.
| evaluator.finalizeForSerialization(); | |
| if (evaluator != null) { | |
| evaluator.finalizeForSerialization(); | |
| } |
…iles for consistency - various additional small tweaks
|
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/configuration/OptimizerConfiguration.java
Show resolved
Hide resolved
src/main/java/edu/kit/kastel/sdq/lissa/ratlr/promptoptimizer/samplestrategy/SamplerFactory.java
Show resolved
Hide resolved
| * Checks if the classification does not match the ground truth. | ||
| * @return false if the classification is equal to the ground truth, true otherwise | ||
| */ | ||
| public boolean isIncorrect() { |
There was a problem hiding this comment.
try to flip this. typically you would ask for "isCorrect"
There was a problem hiding this comment.
This function is only used in this negated form, flipping it would mean always using !isCorrect(). How about renaming it to isWrong() instead?



Adds the ProTeGi Prompt Optimizer by Pryzant et al. of their paper "Automatic Prompt Optimization with "Gradient Descent" and Beam Search".