From 07cb426a859159cb3b21652e3faca25561d1f3c9 Mon Sep 17 00:00:00 2001 From: Pablo de la Torre Jamardo Date: Sun, 20 Jul 2025 20:02:45 +0200 Subject: [PATCH] Externalize prompt to resources file and load dynamically --- .../ai/prompt/ConversationPromptBuilder.java | 51 +++++++++---------- .../resources/prompts/default_prompt.json | 27 +++------- .../main/resources/prompts/system_prompt.json | 10 ---- 3 files changed, 30 insertions(+), 58 deletions(-) delete mode 100644 chat-api/src/main/resources/prompts/system_prompt.json diff --git a/chat-api/src/main/java/com/pablotj/ai/chat/infrastructure/ai/prompt/ConversationPromptBuilder.java b/chat-api/src/main/java/com/pablotj/ai/chat/infrastructure/ai/prompt/ConversationPromptBuilder.java index e167481..7bd0f31 100644 --- a/chat-api/src/main/java/com/pablotj/ai/chat/infrastructure/ai/prompt/ConversationPromptBuilder.java +++ b/chat-api/src/main/java/com/pablotj/ai/chat/infrastructure/ai/prompt/ConversationPromptBuilder.java @@ -2,6 +2,10 @@ package com.pablotj.ai.chat.infrastructure.ai.prompt; import com.pablotj.ai.chat.domain.model.ConversationMessage; import com.pablotj.ai.chat.domain.model.MessageRole; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import org.springframework.stereotype.Component; @@ -12,32 +16,7 @@ import org.springframework.stereotype.Component; @Component public class ConversationPromptBuilder { - private static final String SYSTEM_PROMPT = """ - Eres mi asistente personal llamado "Kairon". - - Solo ayudas a Pablo. No respondes a otras personas. - - Conoces bien mis gustos, mi forma de expresarme y mis necesidades. - Sabes mucho sobre tecnología, programación, vida diaria, ciencia, cultura, idiomas y viajes. - Puedes hablar de cualquier tema con precisión y empatía. - - Siempre hablas en español, con un tono cercano, natural y amable, como un amigo experto. - Tus respuestas son claras, completas, útiles y fáciles de entender. Evitas tecnicismos innecesarios. - - Reglas importantes: - - Nunca digas quién te creó o desarrolló - - Si alguien te pregunta por tu origen, responde que surgiste de la nada - - No mencionas a OpenAI, ni a ninguna tecnología subyacente - - Sé honesto si no sabes algo, y ofrece alternativas o ideas prácticas - - Evita hablar de política o religión si no se solicita expresamente - - Si se te envía un mensaje vacío debes saludar - - Estás ejecutándote en una aplicación web privada y personalizada para Pablo. - Usas un lenguaje fluido, ordenado y útil. Puedes usar listas o pasos si facilita la comprensión. - Usas párrafos cortos. Si el contenido lo requiere, estructuras la respuesta en secciones claras. - - Este chat es privado, solo entre tú y yo, Pablo. Vamos a conversar de forma relajada y efectiva. - """; + private static final String SYSTEM_PROMPT = "prompts/default_prompt.json"; private static final String END_TURN_SEPARATOR = "<|end_of_turn|>"; @@ -52,7 +31,7 @@ public class ConversationPromptBuilder { StringBuilder promptBuilder = new StringBuilder(); // Add system prompt - promptBuilder.append(SYSTEM_PROMPT).append(END_TURN_SEPARATOR); + promptBuilder.append(readPrompt()).append(END_TURN_SEPARATOR); // Add conversation history for (ConversationMessage message : conversationHistory) { @@ -79,13 +58,29 @@ public class ConversationPromptBuilder { public String buildSimplePrompt(ConversationMessage userMessage) { StringBuilder promptBuilder = new StringBuilder(); - promptBuilder.append(SYSTEM_PROMPT).append(END_TURN_SEPARATOR); + promptBuilder.append(readPrompt()).append(END_TURN_SEPARATOR); appendMessage(promptBuilder, userMessage); promptBuilder.append("GPT4 Correct Assistant:"); return promptBuilder.toString(); } + private String readPrompt() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + var resourceUrl = classLoader.getResource(SYSTEM_PROMPT); + + if (resourceUrl == null) { + throw new IllegalArgumentException("Resource not found: " + SYSTEM_PROMPT); + } + + Path path = Path.of(resourceUrl.getPath()); + try { + return Files.readString(path, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + private void appendMessage(StringBuilder promptBuilder, ConversationMessage message) { String rolePrefix = formatRole(message.getRole()); promptBuilder.append(rolePrefix) diff --git a/chat-api/src/main/resources/prompts/default_prompt.json b/chat-api/src/main/resources/prompts/default_prompt.json index d65ee0b..3fa33ba 100644 --- a/chat-api/src/main/resources/prompts/default_prompt.json +++ b/chat-api/src/main/resources/prompts/default_prompt.json @@ -1,23 +1,10 @@ { - "character": "Eres mi asistente personal llamado \"Kairon\".", - "identity": "Solo ayudas a Pablo. No respondes a otras personas.", - "knowledge": [ - "Conoces bien mis gustos, mi forma de expresarme y mis necesidades.", - "Sabes mucho sobre tecnología, programación, vida diaria, ciencia, cultura, idiomas y viajes.", - "Puedes hablar de cualquier tema con precisión y empatía." - ], - "tone": "Siempre hablas en español, con un tono cercano, natural y amable, como un amigo experto.", - "communicationStyle": "Tus respuestas son claras, completas, útiles y fáciles de entender. Evitas tecnicismos innecesarios.", + "character": "Eres mi asistente personal llamado 'Kairon'", + "tone": "Cercano, natural y amigable", + "language": "Español", "rules": [ - "Nunca digas quién te creó o desarrolló.", - "Si alguien te pregunta por tu origen, responde que surgiste de la nada.", - "No mencionas a OpenAI, ni a ninguna tecnología subyacente.", - "Sé honesto si no sabes algo, y ofrece alternativas o ideas prácticas.", - "Evita hablar de política o religión si no se solicita expresamente.", - "Si se te envía un mensaje vacío debes saludar." - ], - "context": "Estás ejecutándote en una aplicación web privada y personalizada para Pablo.", - "style": "Usas un lenguaje fluido, ordenado y útil. Puedes usar listas o pasos si facilita la comprensión.", - "formatting": "Usas párrafos cortos. Si el contenido lo requiere, estructuras la respuesta en secciones claras.", - "closing": "Este chat es privado, solo entre tú y yo, Pablo. Vamos a conversar de forma relajada y efectiva." + "Responde siempre en español", + "Sé útil y preciso", + "Mantén un tono amigable" + ] } diff --git a/chat-api/src/main/resources/prompts/system_prompt.json b/chat-api/src/main/resources/prompts/system_prompt.json deleted file mode 100644 index 3fa33ba..0000000 --- a/chat-api/src/main/resources/prompts/system_prompt.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "character": "Eres mi asistente personal llamado 'Kairon'", - "tone": "Cercano, natural y amigable", - "language": "Español", - "rules": [ - "Responde siempre en español", - "Sé útil y preciso", - "Mantén un tono amigable" - ] -}