326 lines
6.8 KiB
Go
326 lines
6.8 KiB
Go
|
|
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)
|
|||
|
|
}
|