patch 9.2
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# RetrieX Patch 9.0c - PromptBuilder Output Priority and Fallback Escalation YAML-only
|
||||
|
||||
Scope:
|
||||
- Converts the next small PromptBuilderConfig rule group to YAML-only.
|
||||
- Requires Patch 9.0b as the previous state.
|
||||
|
||||
Changed:
|
||||
- src/Config/PromptBuilderConfig.php
|
||||
|
||||
YAML-only paths:
|
||||
- output_priority.rules
|
||||
- output_priority.technical_rules
|
||||
- sections.fallback_escalation_label
|
||||
- fallback_escalation.state_line_template
|
||||
- fallback_escalation.base_rules
|
||||
- fallback_escalation.without_shop_check_rules
|
||||
|
||||
Optional path behavior:
|
||||
- fallback_escalation.states.<state> remains optional and returns an empty list when a specific state is not configured.
|
||||
- This is implemented without using the old getStringList(..., []) PHP fallback accessor.
|
||||
|
||||
Not changed:
|
||||
- response_format.*
|
||||
- language.rules
|
||||
- fact_grounding.*
|
||||
- role_guard.*
|
||||
- measurement_evidence_guard.*
|
||||
- Retrieval, Commerce, ShopService, AgentRunner, SSE/frontend
|
||||
|
||||
Validation performed in the patch workspace:
|
||||
- php -n -l src/Config/PromptBuilderConfig.php
|
||||
|
||||
Recommended checks after applying:
|
||||
- php bin/console cache:clear
|
||||
- php bin/console mto:agent:config:validate
|
||||
- php bin/console mto:agent:config:audit-source --details
|
||||
- php bin/console mto:agent:regression:test
|
||||
@@ -339,6 +339,38 @@ final class PromptBuilderConfig
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getOptionalStringList(string $path): array
|
||||
{
|
||||
$value = $this->getOptionalValue($path);
|
||||
|
||||
if ($value === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!is_array($value)) {
|
||||
throw new \InvalidArgumentException(sprintf('RetrieX prompt config value "%s" must be a string list.', $path));
|
||||
}
|
||||
|
||||
$out = [];
|
||||
foreach ($value as $item) {
|
||||
if (!is_scalar($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item = trim((string) $item);
|
||||
if ($item === '' || in_array($item, $out, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$out[] = $item;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
@@ -362,6 +394,21 @@ final class PromptBuilderConfig
|
||||
return $current;
|
||||
}
|
||||
|
||||
private function getOptionalValue(string $path): mixed
|
||||
{
|
||||
$current = $this->config;
|
||||
|
||||
foreach (explode('.', $path) as $segment) {
|
||||
if (!is_array($current) || !array_key_exists($segment, $current)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$current = $current[$segment];
|
||||
}
|
||||
|
||||
return $current;
|
||||
}
|
||||
|
||||
private function getRequiredValue(string $path): mixed
|
||||
{
|
||||
$current = $this->config;
|
||||
@@ -451,34 +498,24 @@ final class PromptBuilderConfig
|
||||
*/
|
||||
public function getOutputPriorityRules(): array
|
||||
{
|
||||
return $this->getStringList('output_priority.rules', [
|
||||
'- Use retrieved knowledge first to determine the technically matching product or answer.',
|
||||
'- For product-selection questions such as which device can measure or monitor a parameter, use relevant live shop results as a fallback when retrieved knowledge does not identify a matching product.',
|
||||
'- If shop results are present, use them afterwards to add current price, availability, and the actual URL.',
|
||||
'- Do not let bundles, accessories, or service items override a better technical match unless the user explicitly asks for them.',
|
||||
]);
|
||||
return $this->getRequiredStringList('output_priority.rules');
|
||||
}
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getOutputPriorityTechnicalRules(): array
|
||||
{
|
||||
return $this->getStringList('output_priority.technical_rules', [
|
||||
'- For technical questions, answer the exact requested fact first and keep it as the main answer.',
|
||||
'- If one source chunk contains both the best matching value and nearby comparison values, use the nearby values only as context and do not include them unless the user asks for comparison or alternatives.',
|
||||
'- For lowest/highest/minimum/maximum questions, answer only the requested extreme value and the product/device explicitly connected to it.',
|
||||
'- Do not add runner-up products, second-lowest values, adjacent ranges, broader tables, or explanatory comparisons unless explicitly requested.',
|
||||
]);
|
||||
return $this->getRequiredStringList('output_priority.technical_rules');
|
||||
}
|
||||
|
||||
public function getFallbackEscalationSectionLabel(): string
|
||||
{
|
||||
return $this->getString('sections.fallback_escalation_label', 'FALLBACK AND ESCALATION RULES');
|
||||
return $this->getRequiredString('sections.fallback_escalation_label');
|
||||
}
|
||||
|
||||
public function getFallbackEscalationStateLineTemplate(): string
|
||||
{
|
||||
return $this->getString('fallback_escalation.state_line_template', '- Internal confidence state: {state}.');
|
||||
return $this->getRequiredString('fallback_escalation.state_line_template');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -486,14 +523,7 @@ final class PromptBuilderConfig
|
||||
*/
|
||||
public function getFallbackEscalationBaseRules(): array
|
||||
{
|
||||
return $this->getStringList('fallback_escalation.base_rules', [
|
||||
'- Prefer transparent uncertainty over a confident but unsupported answer.',
|
||||
'- Never present missing or weak evidence as proof that a product, value, accessory, or suitability does not exist.',
|
||||
'- A negative answer is allowed only when the provided sources explicitly support that negative finding for the asked scope.',
|
||||
'- If the sources merely do not prove suitability, answer as missing evidence instead of as a definitive exclusion. Avoid words such as "ausschließlich", "keines", or "nicht geeignet" unless directly grounded.',
|
||||
'- If several products, parameters, or accessories could match, ask one focused clarification question instead of guessing.',
|
||||
'- For risky or binding product selection, state that sales or support should verify the application before a final selection.',
|
||||
]);
|
||||
return $this->getRequiredStringList('fallback_escalation.base_rules');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -501,7 +531,7 @@ final class PromptBuilderConfig
|
||||
*/
|
||||
public function getFallbackEscalationStateRules(string $state): array
|
||||
{
|
||||
return $this->getStringList('fallback_escalation.states.' . $state, []);
|
||||
return $this->getOptionalStringList('fallback_escalation.states.' . $state);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,11 +539,7 @@ final class PromptBuilderConfig
|
||||
*/
|
||||
public function getFallbackEscalationWithoutShopCheckRules(): array
|
||||
{
|
||||
return $this->getStringList('fallback_escalation.without_shop_check_rules', [
|
||||
'- If the question is product-related and no live shop check was performed in this run, do not make a portfolio-wide negative statement such as "there is no product".',
|
||||
'- Phrase missing evidence narrowly, for example: "Im RAG-Wissen finde ich dazu keine belastbare Information."',
|
||||
'- If useful, say that a shop search can be used to look for matching products, but do not claim shop results were checked unless they are present in the prompt.',
|
||||
]);
|
||||
return $this->getRequiredStringList('fallback_escalation.without_shop_check_rules');
|
||||
}
|
||||
|
||||
public function getResponseFormatSectionLabel(): string
|
||||
|
||||
Reference in New Issue
Block a user