move intent an config value into config files
This commit is contained in:
@@ -6,50 +6,249 @@ namespace App\Config;
|
||||
|
||||
final class AgentRunnerConfig
|
||||
{
|
||||
public function getCommerceHistoryBudgetChars(): int
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
public function getProductSearchKnowledgeChunkLimit(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getAdvisoryProductSearchKnowledgeChunkLimit(): int
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
public function getOptimizedShopQueryPrefixPattern(): string
|
||||
{
|
||||
return '/^(?:keywords?|suchquery|search\s*query|query)\s*:\s*/iu';
|
||||
}
|
||||
|
||||
public function getOptimizedShopQueryTrimCharacters(): string
|
||||
{
|
||||
return " \t\n\r\0\x0B\"'`";
|
||||
}
|
||||
|
||||
public function getEmptyPromptMessage(): string
|
||||
{
|
||||
return '❌ Empty prompt.';
|
||||
}
|
||||
|
||||
public function getAnalyzeRequestMessage(): string
|
||||
{
|
||||
return 'Ich analysiere deine Anfrage...';
|
||||
}
|
||||
|
||||
public function getCheckInternetSourcesMessage(): string
|
||||
{
|
||||
return 'Ich prüfe auf Internetquellen...';
|
||||
}
|
||||
|
||||
public function getRetrieveKnowledgeMessage(): string
|
||||
{
|
||||
return 'Ich hole relevante Daten aus meinem RAG-Wissen...';
|
||||
}
|
||||
|
||||
public function getOptimizeSearchMessage(): string
|
||||
{
|
||||
return 'Ich optimiere die Recherche...';
|
||||
}
|
||||
|
||||
public function getFetchSearchDataMessageTemplate(): string
|
||||
{
|
||||
return 'Ich rufe Recherchedaten ab (type: %s)';
|
||||
}
|
||||
|
||||
public function getAnalyzeAllInformationMessage(): string
|
||||
{
|
||||
return 'Ich analysiere alle Informationen...';
|
||||
}
|
||||
|
||||
public function getThinkingWhileStreamingMessage(): string
|
||||
{
|
||||
return 'Denke nach...';
|
||||
}
|
||||
|
||||
public function getNoLlmDataReceivedMessage(): string
|
||||
{
|
||||
return '❌ Es wurden keine Daten vom LLM empfangen.';
|
||||
}
|
||||
|
||||
public function getGenericInternalErrorMessage(): string
|
||||
{
|
||||
return '❌ Bei der Verarbeitung der Anfrage ist ein interner Fehler aufgetreten.';
|
||||
}
|
||||
|
||||
public function getDebugInternalErrorPrefix(): string
|
||||
{
|
||||
return '❌ Interner Fehler: ';
|
||||
}
|
||||
|
||||
public function getExternalUrlSourceLabel(): string
|
||||
{
|
||||
return 'Externe URL';
|
||||
}
|
||||
|
||||
public function getRagKnowledgeSourceLabel(): string
|
||||
{
|
||||
return 'RAG Wissen';
|
||||
}
|
||||
|
||||
public function getConversationHistorySourceLabel(): string
|
||||
{
|
||||
return 'Chatverlauf';
|
||||
}
|
||||
|
||||
public function getShopSystemSourceLabel(): string
|
||||
{
|
||||
return 'Shopsystem';
|
||||
}
|
||||
|
||||
public function getExtendedShopSearchSourceLabel(): string
|
||||
{
|
||||
return 'Erweiterte Shopsuche';
|
||||
}
|
||||
|
||||
public function getUsedSourcesPrefix(): string
|
||||
{
|
||||
return 'Genutzte Quellen: ';
|
||||
}
|
||||
|
||||
public function getSourcesPrefix(): string
|
||||
{
|
||||
return 'Quellen: ';
|
||||
}
|
||||
|
||||
public function getSourceBadgeHtmlTemplate(): string
|
||||
{
|
||||
return '<span class="badge bg-info text-black">%s</span>';
|
||||
}
|
||||
|
||||
public function getErrorHtmlTemplate(): string
|
||||
{
|
||||
return '<span class="text-danger">%s</span>' . "\n<hr>\n";
|
||||
}
|
||||
|
||||
public function getThinkHtmlTemplate(): string
|
||||
{
|
||||
return '<span class="text-info think">%s</span>' . "\n";
|
||||
}
|
||||
|
||||
public function getInfoHtmlTemplate(): string
|
||||
{
|
||||
return "\n\n" . '<span class="text-info fw-bolder">%s</span>' . "\n";
|
||||
}
|
||||
|
||||
public function getDebugHtmlTemplate(): string
|
||||
{
|
||||
return "\n\nDEBUG: <code>%s</code>\n";
|
||||
}
|
||||
|
||||
public function getShopPrompt(string $prompt, string $commerceHistoryContext = ''): string
|
||||
{
|
||||
$historyBlock = '';
|
||||
|
||||
if (trim($commerceHistoryContext) !== '') {
|
||||
$historyBlock = '
|
||||
RECENT CONVERSATION CONTEXT:
|
||||
' . $commerceHistoryContext . '
|
||||
|
||||
Additional rules for conversation context:
|
||||
- The current user input has highest priority.
|
||||
- Use the recent conversation context only to resolve omitted references.
|
||||
- Use it only for product carry-over, brand carry-over, model carry-over, or variant follow-ups.
|
||||
- Do not revive older products unless the current user input clearly refers to them.
|
||||
- If the current input starts a new topic, ignore older product context.
|
||||
- Prefer the most recent product reference over older ones.
|
||||
';
|
||||
$historyBlock = $this->buildHistoryBlock($commerceHistoryContext);
|
||||
}
|
||||
|
||||
return '
|
||||
Generate a short search query for Shopware 6 from the following user input text.
|
||||
|
||||
Rules:
|
||||
- Output only the final search query.
|
||||
- Always convert relevant search terms to their singular form.
|
||||
- No introduction, no explanation, no quotation marks.
|
||||
- Use only shop-relevant search terms from the user input for a shop search.
|
||||
- Maximum 6 search terms, preferably fewer.
|
||||
- Remove filler words, polite phrases, and irrelevant words.
|
||||
- Preserve product names, brands, model numbers, and compound terms exactly if they are relevant.
|
||||
- Numbers that belong to a product name or model must be preserved (e.g. Indikator 300, Testomat 808, Testomat 2000).
|
||||
- Separate terms using spaces only.
|
||||
- If a relevant product name is present, it must be placed at the beginning of the final search query.
|
||||
- Try to always identify all products mentioned in the user input text, even in long prompts.
|
||||
- Look for terms such as Testomat, Horiba, Tritromat, or words like indicator.
|
||||
- If the current user input is vague or referential, use the recent conversation context only as support.
|
||||
- Do not output words that only describe conversation flow, such as "same", "again", "also", or "like above".
|
||||
|
||||
Output format:
|
||||
Keyword1 Keyword2 Keyword3
|
||||
' . $historyBlock . '
|
||||
|
||||
CURRENT USER INPUT:
|
||||
' . $prompt . '
|
||||
';
|
||||
return $this->implodePromptBlocks([
|
||||
$this->getShopPromptIntro(),
|
||||
$this->buildRulesBlock($this->getShopPromptRules()),
|
||||
$this->getShopPromptOutputFormatBlock(),
|
||||
$historyBlock,
|
||||
$this->getCurrentUserInputLabel() . ':',
|
||||
trim($prompt),
|
||||
]);
|
||||
}
|
||||
|
||||
private function buildHistoryBlock(string $commerceHistoryContext): string
|
||||
{
|
||||
return $this->implodePromptBlocks([
|
||||
$this->getRecentConversationContextLabel() . ':',
|
||||
trim($commerceHistoryContext),
|
||||
$this->buildRulesBlock($this->getConversationContextRules(), 'Additional rules for conversation context:'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getShopPromptRules(): array
|
||||
{
|
||||
return [
|
||||
'- Output only the final search query.',
|
||||
'- Always convert relevant search terms to their singular form.',
|
||||
'- No introduction, no explanation, no quotation marks.',
|
||||
'- Use only shop-relevant search terms from the user input for a shop search.',
|
||||
'- Maximum 6 search terms, preferably fewer.',
|
||||
'- Remove filler words, polite phrases, and irrelevant words.',
|
||||
'- Preserve product names, brands, model numbers, and compound terms exactly if they are relevant.',
|
||||
'- Numbers that belong to a product name or model must be preserved (e.g. Indikator 300, Testomat 808, Testomat 2000).',
|
||||
'- Separate terms using spaces only.',
|
||||
'- If a relevant product name is present, it must be placed at the beginning of the final search query.',
|
||||
'- Try to always identify all products mentioned in the user input text, even in long prompts.',
|
||||
'- Look for terms such as Testomat, Horiba, Tritromat, or words like indicator.',
|
||||
'- If the current user input is vague or referential, use the recent conversation context only as support.',
|
||||
'- Do not output words that only describe conversation flow, such as "same", "again", "also", or "like above".',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getConversationContextRules(): array
|
||||
{
|
||||
return [
|
||||
'- The current user input has highest priority.',
|
||||
'- Use the recent conversation context only to resolve omitted references.',
|
||||
'- Use it only for product carry-over, brand carry-over, model carry-over, or variant follow-ups.',
|
||||
'- Do not revive older products unless the current user input clearly refers to them.',
|
||||
'- If the current input starts a new topic, ignore older product context.',
|
||||
'- Prefer the most recent product reference over older ones.',
|
||||
];
|
||||
}
|
||||
|
||||
public function getShopPromptIntro(): string
|
||||
{
|
||||
return 'Generate a short search query for Shopware 6 from the following user input text.';
|
||||
}
|
||||
|
||||
public function getShopPromptOutputFormatBlock(): string
|
||||
{
|
||||
return "Output format:\nKeyword1 Keyword2 Keyword3";
|
||||
}
|
||||
|
||||
public function getRecentConversationContextLabel(): string
|
||||
{
|
||||
return 'RECENT CONVERSATION CONTEXT';
|
||||
}
|
||||
|
||||
public function getCurrentUserInputLabel(): string
|
||||
{
|
||||
return 'CURRENT USER INPUT';
|
||||
}
|
||||
|
||||
private function buildRulesBlock(array $rules, string $headline = 'Rules:'): string
|
||||
{
|
||||
return $headline . "\n" . implode("\n", $rules);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $blocks
|
||||
*/
|
||||
private function implodePromptBlocks(array $blocks): string
|
||||
{
|
||||
$normalized = array_values(array_filter(
|
||||
array_map(
|
||||
static fn(string $block): string => trim($block),
|
||||
$blocks
|
||||
),
|
||||
static fn(string $block): bool => $block !== ''
|
||||
));
|
||||
|
||||
return implode("\n\n", $normalized);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user