44 lines
1.6 KiB
Go
44 lines
1.6 KiB
Go
|
|
// Package persona owns the bot's identity and the system prompt the LLM
|
||
|
|
// sees. The full prompt text lives in the YAML's `system_prompt` field
|
||
|
|
// (long, freeform, hand-tuned for the deployment). This package only
|
||
|
|
// adds the RAG context after it.
|
||
|
|
package persona
|
||
|
|
|
||
|
|
import (
|
||
|
|
"github.com/VictorVargas/rony-llm-agent/pkg/persona"
|
||
|
|
|
||
|
|
"github.com/VictorVargas/rony-chat-bot/internal/config"
|
||
|
|
)
|
||
|
|
|
||
|
|
// FromConfig returns a minimal persona used only for the UI greeting and
|
||
|
|
// the SSE event metadata. The system prompt itself comes from
|
||
|
|
// config.SystemPrompt, not from this struct — see BuildSystemPrompt.
|
||
|
|
func FromConfig(c *config.Config) (persona.Persona, error) {
|
||
|
|
lang := c.Persona.Language
|
||
|
|
if lang == "" {
|
||
|
|
lang = "the user's language"
|
||
|
|
}
|
||
|
|
return persona.Persona{
|
||
|
|
ID: "rony",
|
||
|
|
Name: c.Persona.Name,
|
||
|
|
Tone: c.Persona.Tone,
|
||
|
|
Language: lang,
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// BuildSystemPrompt returns the full prompt for one chat turn:
|
||
|
|
// 1. The hand-written system prompt from the YAML (who Rony is, how to speak)
|
||
|
|
// 2. The RAG block (omitted when the index returns no hits)
|
||
|
|
//
|
||
|
|
// The RAG block is appended, not prepended, so the persona instructions
|
||
|
|
// always come first and the LLM never gets the chance to "forget" them.
|
||
|
|
func BuildSystemPrompt(systemPrompt, ragContext string) string {
|
||
|
|
out := systemPrompt
|
||
|
|
if ragContext != "" {
|
||
|
|
out += "\n\n## Relevant context from the portfolio\n\n" +
|
||
|
|
"Use these excerpts to answer. Cite the project filename when you reference a detail. " +
|
||
|
|
"If the excerpts don't contain the answer, say you don't have that information — do not invent.\n\n" +
|
||
|
|
ragContext
|
||
|
|
}
|
||
|
|
return out
|
||
|
|
}
|