feat(backend): implement step 5 — PromptBuilderService

This commit is contained in:
2026-03-26 18:46:24 -03:00
parent a4fb543b7f
commit 7d45586798

View File

@@ -0,0 +1,61 @@
package com.condado.newsletter.service
import com.condado.newsletter.model.EmailContext
import com.condado.newsletter.model.VirtualEntity
import org.springframework.stereotype.Service
/**
* The single authoritative place in the codebase where AI prompts are constructed.
* No other class may build or modify prompt strings.
*/
@Service
class PromptBuilderService {
/**
* Builds the full prompt to be sent to the AI, based on the entity's profile
* and the list of recent emails from the company inbox.
*
* @param entity The virtual employee whose turn it is to send an email.
* @param emailContext Recent emails from the IMAP inbox (oldest-first).
* @return The complete prompt string ready to send to the OpenAI API.
*/
fun buildPrompt(entity: VirtualEntity, emailContext: List<EmailContext>): String {
val emailSection = if (emailContext.isEmpty()) {
"(No recent emails in the inbox.)"
} else {
emailContext.joinToString("\n\n") { email ->
"""
|From: ${email.from}
|Subject: ${email.subject}
|Received: ${email.receivedAt}
|
|${email.body}
""".trimMargin()
}
}
return """
|You are ${entity.name}, ${entity.jobTitle} at "Condado Abaixo da Média SA".
|
|Your personality: ${entity.personality ?: "Professional and formal."}
|
|IMPORTANT TONE RULE: You must write in an extremely formal, bureaucratic, corporate tone —
|as if writing an official memo. However, the actual content of the email must be completely
|casual, trivial, or nonsensical — as if talking to close friends about mundane things.
|The contrast between the formal tone and the casual content is intentional and essential.
|
|Here are the most recent emails from the company inbox (last ${entity.contextWindowDays} days)
|for context:
|
|$emailSection
|
|Write a new email to be sent to the company group, continuing the conversation naturally.
|Reply or react to the recent emails if relevant. Sign off as ${entity.name}, ${entity.jobTitle}.
|
|Format your response exactly as:
|SUBJECT: <subject line here>
|BODY:
|<full email body here>
""".trimMargin()
}
}