package llm import ( "fmt" "strings" ) // BuildPrompt builds a prompt from components func BuildPrompt(tenantConfig *TenantConfig, conversationHistory []Message, userInput string, retrievedDocs []RetrievedDoc) string { var parts []string // System message systemMsg := buildSystemMessage(tenantConfig) parts = append(parts, systemMsg) // Retrieved documents (RAG context) if len(retrievedDocs) > 0 { parts = append(parts, "\n## Context:") for i, doc := range retrievedDocs { parts = append(parts, fmt.Sprintf("\n[Document %d]", i+1)) parts = append(parts, fmt.Sprintf("Title: %s", doc.Title)) parts = append(parts, fmt.Sprintf("Content: %s", doc.Content)) if doc.URL != "" { parts = append(parts, fmt.Sprintf("Source: %s", doc.URL)) } } } // Conversation history if len(conversationHistory) > 0 { parts = append(parts, "\n## Conversation History:") for _, msg := range conversationHistory { parts = append(parts, fmt.Sprintf("%s: %s", strings.Title(msg.Role), msg.Content)) } } // Current user input parts = append(parts, fmt.Sprintf("\n## User: %s", userInput)) parts = append(parts, "\n## Assistant:") return strings.Join(parts, "\n") } // TenantConfig holds tenant-specific configuration type TenantConfig struct { Greeting string Tone string // "professional", "friendly", "formal" Disclaimers []string AllowedTools []string } // RetrievedDoc represents a retrieved document from RAG type RetrievedDoc struct { Title string Content string URL string Score float64 } // BuildPromptWithRAG builds a prompt with RAG context func BuildPromptWithRAG(tenantConfig *TenantConfig, conversationHistory []Message, userInput string, retrievedDocs []RetrievedDoc) string { var parts []string // System message systemMsg := buildSystemMessage(tenantConfig) parts = append(parts, systemMsg) // Retrieved documents (RAG context) if len(retrievedDocs) > 0 { parts = append(parts, "\n## Context:") for i, doc := range retrievedDocs { parts = append(parts, fmt.Sprintf("\n[Document %d]", i+1)) parts = append(parts, fmt.Sprintf("Title: %s", doc.Title)) parts = append(parts, fmt.Sprintf("Content: %s", doc.Content)) if doc.URL != "" { parts = append(parts, fmt.Sprintf("Source: %s", doc.URL)) } } } // Conversation history if len(conversationHistory) > 0 { parts = append(parts, "\n## Conversation History:") for _, msg := range conversationHistory { parts = append(parts, fmt.Sprintf("%s: %s", strings.Title(msg.Role), msg.Content)) } } // Current user input parts = append(parts, fmt.Sprintf("\n## User: %s", userInput)) parts = append(parts, "\n## Assistant:") return strings.Join(parts, "\n") } // buildSystemMessage builds the system message func buildSystemMessage(config *TenantConfig) string { var parts []string parts = append(parts, "You are a helpful Virtual Banker assistant.") if config.Tone != "" { parts = append(parts, fmt.Sprintf("Your tone should be %s.", config.Tone)) } if len(config.Disclaimers) > 0 { parts = append(parts, "\nImportant disclaimers:") for _, disclaimer := range config.Disclaimers { parts = append(parts, fmt.Sprintf("- %s", disclaimer)) } } if len(config.AllowedTools) > 0 { parts = append(parts, "\nYou have access to the following tools:") for _, tool := range config.AllowedTools { parts = append(parts, fmt.Sprintf("- %s", tool)) } } parts = append(parts, "\nAlways be helpful, accurate, and respectful.") parts = append(parts, "If you don't know something, say so and offer to help find the answer.") return strings.Join(parts, "\n") }