Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
229 lines
7.3 KiB
Go
229 lines
7.3 KiB
Go
package types
|
||
|
||
import (
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// PromptPlaceholder represents a placeholder that can be used in prompt templates
|
||
type PromptPlaceholder struct {
|
||
// Name is the placeholder name (without braces), e.g., "query"
|
||
Name string `json:"name"`
|
||
// Label is a short label for the placeholder
|
||
Label string `json:"label"`
|
||
// Description explains what this placeholder represents
|
||
Description string `json:"description"`
|
||
}
|
||
|
||
// PromptFieldType represents the type of prompt field
|
||
type PromptFieldType string
|
||
|
||
const (
|
||
// PromptFieldSystemPrompt is for system prompts (normal mode)
|
||
PromptFieldSystemPrompt PromptFieldType = "system_prompt"
|
||
// PromptFieldAgentSystemPrompt is for agent mode system prompts
|
||
PromptFieldAgentSystemPrompt PromptFieldType = "agent_system_prompt"
|
||
// PromptFieldContextTemplate is for context templates
|
||
PromptFieldContextTemplate PromptFieldType = "context_template"
|
||
// PromptFieldRewriteSystemPrompt is for rewrite system prompts
|
||
PromptFieldRewriteSystemPrompt PromptFieldType = "rewrite_system_prompt"
|
||
// PromptFieldRewritePrompt is for rewrite user prompts
|
||
PromptFieldRewritePrompt PromptFieldType = "rewrite_prompt"
|
||
// PromptFieldFallbackPrompt is for fallback prompts
|
||
PromptFieldFallbackPrompt PromptFieldType = "fallback_prompt"
|
||
)
|
||
|
||
// All available placeholders in the system
|
||
var (
|
||
// Common placeholders
|
||
PlaceholderQuery = PromptPlaceholder{
|
||
Name: "query",
|
||
Label: "用户问题",
|
||
Description: "用户当前的问题或查询内容",
|
||
}
|
||
|
||
PlaceholderContexts = PromptPlaceholder{
|
||
Name: "contexts",
|
||
Label: "检索内容",
|
||
Description: "从知识库检索到的相关内容列表",
|
||
}
|
||
|
||
PlaceholderCurrentTime = PromptPlaceholder{
|
||
Name: "current_time",
|
||
Label: "当前时间",
|
||
Description: "当前日期(ISO 格式:2006-01-02)。只用日期、不用时钟,避免秒级变化打断 provider 前缀缓存。",
|
||
}
|
||
|
||
PlaceholderCurrentWeek = PromptPlaceholder{
|
||
Name: "current_week",
|
||
Label: "当前星期",
|
||
Description: "当前星期几(如:星期一、Monday)",
|
||
}
|
||
|
||
// Rewrite prompt placeholders
|
||
PlaceholderConversation = PromptPlaceholder{
|
||
Name: "conversation",
|
||
Label: "历史对话",
|
||
Description: "格式化的历史对话内容,用于多轮对话改写",
|
||
}
|
||
|
||
PlaceholderYesterday = PromptPlaceholder{
|
||
Name: "yesterday",
|
||
Label: "昨天日期",
|
||
Description: "昨天的日期(格式:2006-01-02)",
|
||
}
|
||
|
||
PlaceholderAnswer = PromptPlaceholder{
|
||
Name: "answer",
|
||
Label: "助手回答",
|
||
Description: "助手的回答内容(用于对话历史格式化)",
|
||
}
|
||
|
||
// Agent mode specific placeholders
|
||
PlaceholderKnowledgeBases = PromptPlaceholder{
|
||
Name: "knowledge_bases",
|
||
Label: "知识库列表",
|
||
Description: "自动格式化的知识库列表,包含名称、描述、文档数量等信息",
|
||
}
|
||
|
||
PlaceholderWebSearchStatus = PromptPlaceholder{
|
||
Name: "web_search_status",
|
||
Label: "网络搜索状态",
|
||
Description: "网络搜索工具是否启用的状态(Enabled 或 Disabled)",
|
||
}
|
||
|
||
PlaceholderLanguage = PromptPlaceholder{
|
||
Name: "language",
|
||
Label: "用户语言",
|
||
Description: "用户界面的语言偏好,如 Chinese (Simplified)、English、Korean 等,用于控制 LLM 回答语言",
|
||
}
|
||
)
|
||
|
||
// PlaceholdersByField returns the available placeholders for a specific prompt field type
|
||
func PlaceholdersByField(fieldType PromptFieldType) []PromptPlaceholder {
|
||
switch fieldType {
|
||
case PromptFieldSystemPrompt:
|
||
// Normal mode system prompt
|
||
return []PromptPlaceholder{
|
||
PlaceholderQuery,
|
||
PlaceholderContexts,
|
||
PlaceholderCurrentTime,
|
||
PlaceholderCurrentWeek,
|
||
PlaceholderLanguage,
|
||
}
|
||
case PromptFieldAgentSystemPrompt:
|
||
// Agent mode system prompt
|
||
return []PromptPlaceholder{
|
||
PlaceholderKnowledgeBases,
|
||
PlaceholderWebSearchStatus,
|
||
PlaceholderCurrentTime,
|
||
PlaceholderLanguage,
|
||
}
|
||
case PromptFieldContextTemplate:
|
||
return []PromptPlaceholder{
|
||
PlaceholderQuery,
|
||
PlaceholderContexts,
|
||
PlaceholderCurrentTime,
|
||
PlaceholderCurrentWeek,
|
||
PlaceholderLanguage,
|
||
}
|
||
case PromptFieldRewriteSystemPrompt:
|
||
// Rewrite system prompt supports same placeholders as rewrite user prompt
|
||
return []PromptPlaceholder{
|
||
PlaceholderQuery,
|
||
PlaceholderConversation,
|
||
PlaceholderCurrentTime,
|
||
PlaceholderYesterday,
|
||
PlaceholderLanguage,
|
||
}
|
||
case PromptFieldRewritePrompt:
|
||
return []PromptPlaceholder{
|
||
PlaceholderQuery,
|
||
PlaceholderConversation,
|
||
PlaceholderCurrentTime,
|
||
PlaceholderYesterday,
|
||
PlaceholderLanguage,
|
||
}
|
||
case PromptFieldFallbackPrompt:
|
||
return []PromptPlaceholder{
|
||
PlaceholderQuery,
|
||
PlaceholderLanguage,
|
||
}
|
||
default:
|
||
return []PromptPlaceholder{}
|
||
}
|
||
}
|
||
|
||
// AllPlaceholders returns all available placeholders in the system
|
||
func AllPlaceholders() []PromptPlaceholder {
|
||
return []PromptPlaceholder{
|
||
PlaceholderQuery,
|
||
PlaceholderContexts,
|
||
PlaceholderCurrentTime,
|
||
PlaceholderCurrentWeek,
|
||
PlaceholderConversation,
|
||
PlaceholderYesterday,
|
||
PlaceholderAnswer,
|
||
PlaceholderKnowledgeBases,
|
||
PlaceholderWebSearchStatus,
|
||
PlaceholderLanguage,
|
||
}
|
||
}
|
||
|
||
// PlaceholderMap returns a map of field types to their available placeholders
|
||
func PlaceholderMap() map[PromptFieldType][]PromptPlaceholder {
|
||
return map[PromptFieldType][]PromptPlaceholder{
|
||
PromptFieldSystemPrompt: PlaceholdersByField(PromptFieldSystemPrompt),
|
||
PromptFieldAgentSystemPrompt: PlaceholdersByField(PromptFieldAgentSystemPrompt),
|
||
PromptFieldContextTemplate: PlaceholdersByField(PromptFieldContextTemplate),
|
||
PromptFieldRewriteSystemPrompt: PlaceholdersByField(PromptFieldRewriteSystemPrompt),
|
||
PromptFieldRewritePrompt: PlaceholdersByField(PromptFieldRewritePrompt),
|
||
PromptFieldFallbackPrompt: PlaceholdersByField(PromptFieldFallbackPrompt),
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Unified prompt placeholder rendering
|
||
// ---------------------------------------------------------------------------
|
||
|
||
// PlaceholderValues is a map of placeholder names (without braces) to their
|
||
// replacement values. Example: {"query": "How to use?", "language": "English"}
|
||
type PlaceholderValues map[string]string
|
||
|
||
// RenderPromptPlaceholders replaces all {{key}} occurrences in template with
|
||
// the corresponding values from vals. Unknown placeholders are left untouched.
|
||
//
|
||
// Built-in auto-values (filled when not supplied explicitly):
|
||
// - {{current_time}} -> time.Now().Format("2006-01-02") (date only; clock
|
||
// precision would bust provider prefix caches on every request)
|
||
// - {{current_week}} -> current weekday name
|
||
// - {{yesterday}} -> yesterday's date (2006-01-02)
|
||
func RenderPromptPlaceholders(template string, vals PlaceholderValues) string {
|
||
if template == "" {
|
||
return ""
|
||
}
|
||
|
||
// Populate auto-generated values when callers don't supply them.
|
||
autoFill := func(key, value string) {
|
||
if _, exists := vals[key]; !exists {
|
||
if strings.Contains(template, "{{"+key+"}}") {
|
||
vals[key] = value
|
||
}
|
||
}
|
||
}
|
||
|
||
now := time.Now()
|
||
autoFill("current_time", now.Format("2006-01-02"))
|
||
autoFill("current_week", now.Weekday().String())
|
||
autoFill("yesterday", now.AddDate(0, 0, -1).Format("2006-01-02"))
|
||
|
||
result := template
|
||
for key, value := range vals {
|
||
placeholder := "{{" + key + "}}"
|
||
if strings.Contains(result, placeholder) {
|
||
result = strings.ReplaceAll(result, placeholder, value)
|
||
}
|
||
}
|
||
return result
|
||
}
|