patch 9.2

This commit is contained in:
team 1
2026-04-30 19:04:48 +02:00
parent d6e73ef5a2
commit 0a8d0cc5a6
2 changed files with 91 additions and 28 deletions

View File

@@ -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

View File

@@ -339,6 +339,38 @@ final class PromptBuilderConfig
return $out; 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[] * @return string[]
*/ */
@@ -362,6 +394,21 @@ final class PromptBuilderConfig
return $current; 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 private function getRequiredValue(string $path): mixed
{ {
$current = $this->config; $current = $this->config;
@@ -451,34 +498,24 @@ final class PromptBuilderConfig
*/ */
public function getOutputPriorityRules(): array public function getOutputPriorityRules(): array
{ {
return $this->getStringList('output_priority.rules', [ return $this->getRequiredStringList('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 string[] * @return string[]
*/ */
public function getOutputPriorityTechnicalRules(): array public function getOutputPriorityTechnicalRules(): array
{ {
return $this->getStringList('output_priority.technical_rules', [ return $this->getRequiredStringList('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.',
]);
} }
public function getFallbackEscalationSectionLabel(): string 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 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 public function getFallbackEscalationBaseRules(): array
{ {
return $this->getStringList('fallback_escalation.base_rules', [ return $this->getRequiredStringList('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.',
]);
} }
/** /**
@@ -501,7 +531,7 @@ final class PromptBuilderConfig
*/ */
public function getFallbackEscalationStateRules(string $state): array 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 public function getFallbackEscalationWithoutShopCheckRules(): array
{ {
return $this->getStringList('fallback_escalation.without_shop_check_rules', [ return $this->getRequiredStringList('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.',
]);
} }
public function getResponseFormatSectionLabel(): string public function getResponseFormatSectionLabel(): string