feat(backend): implement step 5 — PromptBuilderService
This commit is contained in:
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user