prompts-core
This commit is contained in:
325
service/form_processor.go
Normal file
325
service/form_processor.go
Normal file
@@ -0,0 +1,325 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ============================================
|
||||
// 表单处理
|
||||
// ============================================
|
||||
|
||||
// FormProcessor 表单处理器
|
||||
type FormProcessor struct {
|
||||
SystemForm map[string]any
|
||||
UserForm map[string]any
|
||||
}
|
||||
|
||||
// NewFormProcessor 创建表单处理器
|
||||
func NewFormProcessor(systemForm, userForm map[string]any) *FormProcessor {
|
||||
return &FormProcessor{
|
||||
SystemForm: systemForm,
|
||||
UserForm: userForm,
|
||||
}
|
||||
}
|
||||
|
||||
// Merge 合并表单,用户表单覆盖系统表单
|
||||
func (p *FormProcessor) Merge() map[string]any {
|
||||
if len(p.SystemForm) == 0 {
|
||||
return p.SystemForm
|
||||
}
|
||||
|
||||
result := make(map[string]any)
|
||||
for k, v := range p.SystemForm {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
if len(p.UserForm) == 0 {
|
||||
return result
|
||||
}
|
||||
|
||||
// 构建用户表单索引
|
||||
userIndex := buildFieldIndex(p.UserForm)
|
||||
|
||||
// 覆盖匹配的字段
|
||||
for key, value := range result {
|
||||
item, ok := value.(map[string]any)
|
||||
if !ok || len(item) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
field := getField(item, key)
|
||||
|
||||
if userItem, exists := findInIndex(userIndex, field, getLabel(item)); exists {
|
||||
if userValue := getValue(userItem); !isNilOrEmpty(userValue) {
|
||||
result[key] = cloneWithValue(item, userValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// RemoveDuplicates 移除被用户表单覆盖的字段
|
||||
func (p *FormProcessor) RemoveDuplicates() map[string]any {
|
||||
if len(p.SystemForm) == 0 || len(p.UserForm) == 0 {
|
||||
return p.SystemForm
|
||||
}
|
||||
|
||||
userFields := buildFieldSet(p.UserForm)
|
||||
result := make(map[string]any)
|
||||
|
||||
for key, value := range p.SystemForm {
|
||||
item, ok := value.(map[string]any)
|
||||
if !ok || len(item) == 0 {
|
||||
result[key] = value
|
||||
continue
|
||||
}
|
||||
|
||||
field := getField(item, key)
|
||||
label := getLabel(item)
|
||||
|
||||
// 跳过重复字段
|
||||
if userFields.contains(field) || userFields.containsLabel(label) {
|
||||
continue
|
||||
}
|
||||
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// RemoveSemanticDuplicates 语义去重
|
||||
func (p *FormProcessor) RemoveSemanticDuplicates() map[string]any {
|
||||
if len(p.SystemForm) == 0 || len(p.UserForm) == 0 {
|
||||
return p.SystemForm
|
||||
}
|
||||
|
||||
userText := renderUserTextOnly(p.UserForm)
|
||||
if userText == "" {
|
||||
return p.SystemForm
|
||||
}
|
||||
|
||||
result := make(map[string]any)
|
||||
for key, value := range p.SystemForm {
|
||||
item, ok := value.(map[string]any)
|
||||
if !ok || len(item) == 0 {
|
||||
result[key] = value
|
||||
continue
|
||||
}
|
||||
|
||||
if isDuplicate(userText, getField(item, key), getLabel(item), getValue(item)) {
|
||||
continue
|
||||
}
|
||||
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// RenderSystemText 渲染系统提示词文本
|
||||
func (p *FormProcessor) RenderSystemText() string {
|
||||
return renderFormText(p.SystemForm, false)
|
||||
}
|
||||
|
||||
// RenderUserText 渲染用户提示词文本
|
||||
func (p *FormProcessor) RenderUserText() string {
|
||||
return renderUserText(p.UserForm, p.SystemForm)
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 表单处理辅助方法
|
||||
// ============================================
|
||||
|
||||
type fieldSet struct {
|
||||
fields map[string]bool
|
||||
labels map[string]bool
|
||||
}
|
||||
|
||||
func buildFieldSet(form map[string]any) *fieldSet {
|
||||
fs := &fieldSet{
|
||||
fields: make(map[string]bool),
|
||||
labels: make(map[string]bool),
|
||||
}
|
||||
|
||||
for key, value := range form {
|
||||
item, ok := value.(map[string]any)
|
||||
if !ok || len(item) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
field := strings.ToLower(getField(item, key))
|
||||
if field != "" {
|
||||
fs.fields[field] = true
|
||||
}
|
||||
|
||||
if label := strings.ToLower(getLabel(item)); label != "" {
|
||||
fs.labels[label] = true
|
||||
}
|
||||
}
|
||||
|
||||
return fs
|
||||
}
|
||||
|
||||
func (fs *fieldSet) contains(field string) bool {
|
||||
return fs.fields[strings.ToLower(field)]
|
||||
}
|
||||
|
||||
func (fs *fieldSet) containsLabel(label string) bool {
|
||||
return label != "" && fs.labels[strings.ToLower(label)]
|
||||
}
|
||||
|
||||
func buildFieldIndex(form map[string]any) map[string]map[string]any {
|
||||
index := make(map[string]map[string]any)
|
||||
|
||||
for key, value := range form {
|
||||
item, ok := value.(map[string]any)
|
||||
if !ok || len(item) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
field := strings.ToLower(getField(item, key))
|
||||
if field != "" {
|
||||
index[field] = item
|
||||
}
|
||||
|
||||
if label := strings.ToLower(getLabel(item)); label != "" {
|
||||
if _, exists := index[label]; !exists {
|
||||
index[label] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index
|
||||
}
|
||||
|
||||
func findInIndex(index map[string]map[string]any, field, label string) (map[string]any, bool) {
|
||||
key := strings.ToLower(field)
|
||||
if item, ok := index[key]; ok {
|
||||
return item, true
|
||||
}
|
||||
|
||||
if label != "" {
|
||||
key = strings.ToLower(label)
|
||||
if item, ok := index[key]; ok {
|
||||
return item, true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 表单渲染
|
||||
// ============================================
|
||||
|
||||
func renderFormText(form map[string]any, isUserForm bool) string {
|
||||
if len(form) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 用户表单只有一个文本字段时,直接返回值
|
||||
if isUserForm && len(form) == 1 {
|
||||
for _, value := range form {
|
||||
if item, ok := value.(map[string]any); ok {
|
||||
return strings.TrimSpace(asString(getValue(item)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 拼接渲染
|
||||
items := extractFormItems(form)
|
||||
if isUserForm {
|
||||
return renderUserFormItems(items)
|
||||
}
|
||||
return renderSystemFormItems(items)
|
||||
}
|
||||
|
||||
type formItem struct {
|
||||
Key string
|
||||
Field string
|
||||
Label string
|
||||
Value any
|
||||
}
|
||||
|
||||
func extractFormItems(form map[string]any) []formItem {
|
||||
var items []formItem
|
||||
|
||||
keys := sortedKeys(form)
|
||||
for _, key := range keys {
|
||||
item, ok := form[key].(map[string]any)
|
||||
if !ok || len(item) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
field := getField(item, key)
|
||||
value := getValue(item)
|
||||
|
||||
// 跳过敏感字段和空值
|
||||
if isSensitiveField(field) || isNilOrEmpty(value) {
|
||||
continue
|
||||
}
|
||||
|
||||
items = append(items, formItem{
|
||||
Key: key,
|
||||
Field: field,
|
||||
Label: getLabel(item),
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
func renderUserFormItems(items []formItem) string {
|
||||
// 只有一个文本类型字段时,直接返回值
|
||||
if len(items) == 1 && isTextType(items[0].Field, items[0].Label) {
|
||||
return formatValue(items[0].Value)
|
||||
}
|
||||
|
||||
// 拼接
|
||||
var parts []string
|
||||
for _, item := range items {
|
||||
if isTextType(item.Field, item.Label) {
|
||||
parts = append(parts, formatValue(item.Value))
|
||||
} else {
|
||||
label := item.Label
|
||||
if label == "" {
|
||||
label = item.Field
|
||||
}
|
||||
parts = append(parts, fmt.Sprintf("%s:%s", label, formatValue(item.Value)))
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func renderSystemFormItems(items []formItem) string {
|
||||
var parts []string
|
||||
for _, item := range items {
|
||||
label := item.Label
|
||||
if label == "" {
|
||||
label = item.Field
|
||||
}
|
||||
parts = append(parts, fmt.Sprintf("%s:%s", label, formatValue(item.Value)))
|
||||
}
|
||||
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func renderUserText(userForm, systemForm map[string]any) string {
|
||||
if text := renderFormText(userForm, true); text != "" {
|
||||
return text
|
||||
}
|
||||
// 用户表单为空时,使用系统表单生成
|
||||
if text := renderFormText(systemForm, false); text != "" {
|
||||
return "参考系统字段生成用户提示词:" + text
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func renderUserTextOnly(userForm map[string]any) string {
|
||||
return renderFormText(userForm, true)
|
||||
}
|
||||
Reference in New Issue
Block a user