diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go index 953faa6..6e88ed7 100644 --- a/applogic/gensokyo.go +++ b/applogic/gensokyo.go @@ -16,6 +16,7 @@ import ( "github.com/hoshinonyaruko/gensokyo-llm/acnode" "github.com/hoshinonyaruko/gensokyo-llm/config" "github.com/hoshinonyaruko/gensokyo-llm/fmtf" + "github.com/hoshinonyaruko/gensokyo-llm/prompt" "github.com/hoshinonyaruko/gensokyo-llm/structs" "github.com/hoshinonyaruko/gensokyo-llm/utils" ) @@ -134,14 +135,27 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) { return } - // 判断是否是群聊 然后判断触发词 + // 判断是否是群聊,然后检查触发词 if message.RealMessageType != "group_private" && message.MessageType != "private" { if !checkMessageForHints(utils.RemoveBracketsContent(message.RawMessage)) { - w.WriteHeader(http.StatusOK) - w.Write([]byte("Group message not hint words.")) - return + // 获取概率值 + chance := config.GetGroupHintChance() + + // 生成0-100之间的随机数 + randomValue := rand.Intn(100) + + // 比较随机值与配置中的概率 + if randomValue >= chance { + w.WriteHeader(http.StatusOK) + w.Write([]byte("Group message not hint words.")) + return + } else { + // 记录日志,表明概率检查通过 + fmt.Printf("Probability check passed: %d%% chance, random value: %d\n", chance, randomValue) + } } } + var CustomRecord *structs.CustomRecord if config.GetGroupContext() && message.MessageType != "private" { // 从数据库读取用户的剧情存档 @@ -709,6 +723,12 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) { baseURL = config.GetLotus(promptstr) + basePath } + // 在加入prompt之前 判断promptstr.yml是否存在 + if !prompt.CheckPromptExistence(promptstr) { + fmtf.Printf("该请求内容所对应yml文件不存在:[%v]:[%v]\n", requestmsg, promptstr) + promptstr = "" + } + // 使用net/url包来构建和编码URL urlParams := url.Values{} if promptstr != "" { @@ -903,7 +923,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) { if !config.GetHideExtraLogs() { fmtf.Printf("收到流数据,切割并发送信息: %s", string(line)) } - splitAndSendMessages(string(line), newmsg, selfid) + splitAndSendMessages(string(line), newmsg, selfid, promptstr) } } } @@ -1085,7 +1105,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) { } -func splitAndSendMessages(line string, newmesssage string, selfid string) { +func splitAndSendMessages(line string, newmesssage string, selfid string, promptstr string) { // 提取JSON部分 dataPrefix := "data: " jsonStr := strings.TrimPrefix(line, dataPrefix) @@ -1103,13 +1123,13 @@ func splitAndSendMessages(line string, newmesssage string, selfid string) { if sseData.Response != "\n\n" { // 处理提取出的信息 - processMessage(sseData.Response, sseData.ConversationId, newmesssage, selfid) + processMessage(sseData.Response, sseData.ConversationId, newmesssage, selfid, promptstr) } else { fmtf.Printf("忽略llm末尾的换行符") } } -func processMessage(response string, conversationid string, newmesssage string, selfid string) { +func processMessage(response string, conversationid string, newmesssage string, selfid string, promptstr string) { // 从conversation对应的sync map取出对应的用户和群号,避免高并发内容发送错乱 userinfo, _ := GetUserInfo(conversationid) key := utils.GetKey(userinfo.GroupID, userinfo.UserID) @@ -1119,7 +1139,7 @@ func processMessage(response string, conversationid string, newmesssage string, for _, char := range response { AppendRune(conversationid, char) - if utils.ContainsRune(punctuations, char, userinfo.GroupID) { + if utils.ContainsRune(punctuations, char, userinfo.GroupID, promptstr) { // 达到标点符号,发送累积的整个消息 if GetMessageLength(conversationid) > 0 { accumulatedMessage, _ := GetCurrentMessage(conversationid) diff --git a/applogic/yuanqi.go b/applogic/yuanqi.go index f5dc2bf..b88a061 100644 --- a/applogic/yuanqi.go +++ b/applogic/yuanqi.go @@ -153,6 +153,7 @@ func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) { systemHistory, err := prompt.GetMessagesExcludingSystem(promptstr) if err != nil { fmtf.Printf("Error getting system history: %v\n", err) + // 如果进行到不存在的分支,这里就return了,导致没有回复 但如果不return,模型是没有system提示词的原始状态,所以要在前面做处理 return } diff --git a/config/config.go b/config/config.go index 1b9fff1..f91c204 100644 --- a/config/config.go +++ b/config/config.go @@ -536,23 +536,117 @@ func GetGroupmessage() bool { } // 获取SplitByPuntuations -func GetSplitByPuntuations() int { +func GetSplitByPuntuations(options ...string) int { mu.Lock() defer mu.Unlock() - if instance != nil { - return instance.Settings.SplitByPuntuations + return getSplitByPuntuationsInternal(options...) +} + +// 内部逻辑执行函数,不处理锁,可以安全地递归调用 +func getSplitByPuntuationsInternal(options ...string) int { + // 检查是否有参数传递进来,以及是否为空字符串 + if len(options) == 0 || options[0] == "" { + if instance != nil { + return instance.Settings.SplitByPuntuations + } + return 0 // 默认值或错误处理 } - return 0 + + // 使用传入的 basename 来查找特定配置 + basename := options[0] + SplitByPuntuationsInterface, err := prompt.GetSettingFromFilename(basename, "SplitByPuntuations") + if err != nil { + log.Println("Error retrieving SplitByPuntuations:", err) + return getSplitByPuntuationsInternal() // 递归调用内部函数,不传递任何参数 + } + + SplitByPuntuations, ok := SplitByPuntuationsInterface.(int) + if !ok { // 检查类型断言是否失败 + fmt.Println("Type assertion failed for SplitByPuntuations, fetching default") + return getSplitByPuntuationsInternal() // 递归调用内部函数,不传递任何参数 + } + + if SplitByPuntuations == 0 { + return getSplitByPuntuationsInternal() // 递归调用内部函数,不传递任何参数 + } + + return SplitByPuntuations } -// 获取SplitByPuntuationsGroup -func GetSplitByPuntuationsGroup() int { +// 获取GetSplitByPuntuationsGroup +func GetSplitByPuntuationsGroup(options ...string) int { mu.Lock() defer mu.Unlock() - if instance != nil { - return instance.Settings.SplitByPuntuationsGroup + return getSplitByPuntuationsGroupInternal(options...) +} + +// 内部逻辑执行函数,不处理锁,可以安全地递归调用 +func getSplitByPuntuationsGroupInternal(options ...string) int { + // 检查是否有参数传递进来,以及是否为空字符串 + if len(options) == 0 || options[0] == "" { + if instance != nil { + return instance.Settings.SplitByPuntuationsGroup + } + return 0 // 默认值或错误处理 } - return 0 + + // 使用传入的 basename 来查找特定配置 + basename := options[0] + SplitByPuntuationsGroupInterface, err := prompt.GetSettingFromFilename(basename, "SplitByPuntuationsGroup") + if err != nil { + log.Println("Error retrieving SplitByPuntuationsGroup:", err) + return getSplitByPuntuationsGroupInternal() // 递归调用内部函数,不传递任何参数 + } + + SplitByPuntuationsGroup, ok := SplitByPuntuationsGroupInterface.(int) + if !ok { // 检查类型断言是否失败 + fmt.Println("Type assertion failed for SplitByPuntuationsGroup, fetching default") + return getSplitByPuntuationsGroupInternal() // 递归调用内部函数,不传递任何参数 + } + + if SplitByPuntuationsGroup == 0 { + return getSplitByPuntuationsGroupInternal() // 递归调用内部函数,不传递任何参数 + } + + return SplitByPuntuationsGroup +} + +// 获取GroupHintChance +func GetGroupHintChance(options ...string) int { + mu.Lock() + defer mu.Unlock() + return getGroupHintChanceInternal(options...) +} + +// 内部逻辑执行函数,不处理锁,可以安全地递归调用 +func getGroupHintChanceInternal(options ...string) int { + // 检查是否有参数传递进来,以及是否为空字符串 + if len(options) == 0 || options[0] == "" { + if instance != nil { + return instance.Settings.GroupHintChance + } + return 0 // 默认值或错误处理 + } + + // 使用传入的 basename 来查找特定配置 + basename := options[0] + GroupHintChanceInterface, err := prompt.GetSettingFromFilename(basename, "GroupHintChance") + if err != nil { + log.Println("Error retrieving GroupHintChance:", err) + return getGroupHintChanceInternal() // 递归调用内部函数,不传递任何参数 + } + + GroupHintChance, ok := GroupHintChanceInterface.(int) + if !ok { // 检查类型断言是否失败 + fmt.Println("Type assertion failed for GroupHintChance, fetching default") + return getGroupHintChanceInternal() // 递归调用内部函数,不传递任何参数 + } + + if GroupHintChance == 0 { + return getGroupHintChanceInternal() // 递归调用内部函数,不传递任何参数 + } + + return GroupHintChance } // 获取HunyuanType diff --git a/prompt/prompt.go b/prompt/prompt.go index b4b2ca4..a8d3ad8 100644 --- a/prompt/prompt.go +++ b/prompt/prompt.go @@ -276,3 +276,17 @@ func GetSettingFromFilename(basename, settingName string) (interface{}, error) { // 返回字段的值,转换为interface{} return field.Interface(), nil } + +// CheckPromptExistence 检查基于 basename 组合的 filename 是否存在于 promptsCache 中 +func CheckPromptExistence(basename string) bool { + // 组合 basename 和 ".yml" 形成完整的文件名 + filename := basename + ".yml" + + // 用读锁来确保并发安全 + lock.RLock() + defer lock.RUnlock() + + // 检查文件是否存在于缓存中 + _, exists := promptsCache[filename] + return exists +} diff --git a/server/server.go b/server/server.go index bfcc210..19c5da1 100644 --- a/server/server.go +++ b/server/server.go @@ -100,7 +100,7 @@ func WsHandler(w http.ResponseWriter, r *http.Request, config *config.Config) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { - log.Printf("Failed to set websocket upgrade: %+v", err) + log.Printf("Failed to set websocket upgrade[%v]: %+v", r.Header, err) return } defer conn.Close() diff --git a/structs/struct.go b/structs/struct.go index 9fe5828..41cfa19 100644 --- a/structs/struct.go +++ b/structs/struct.go @@ -264,6 +264,7 @@ type Settings struct { UrlSendPics bool `yaml:"urlSendPics"` // 自己构造图床加速图片发送 MdPromptKeyboardAtGroup bool `yaml:"mdPromptKeyboardAtGroup"` // 群内使用md能力模拟PromptKeyboard GroupHintWords []string `yaml:"groupHintWords"` + GroupHintChance int `yaml:"groupHintChance"` GroupContext bool `yaml:"groupContext"` HunyuanType int `yaml:"hunyuanType"` diff --git a/template/config_template.go b/template/config_template.go index a8739a3..08ade01 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -49,6 +49,7 @@ settings: hideExtraLogs : false #忽略流信息的log,提高性能 urlSendPics : false #自己构造图床加速图片发送.需配置公网ip+放通port+设置正确的selfPath groupHintWords : [] #当机器人位于群内时,需满足包含groupHintWords数组任意内容如[CQ:at,qq=2] 机器人的名字 等 + groupHintChance : 0 #需与groupHintWords联用,代表不满足hintwords时概率触发,不启用groupHintWords相当于百分百概率回复. groupContext : false #群上下文 在智能体在群内时,以群为单位处理上下文. #Ws服务器配置 diff --git a/utils/utils.go b/utils/utils.go index 85a59b9..8022efc 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -148,14 +148,14 @@ func GetKey(groupid int64, userid int64) string { } // 随机的分布发送 -func ContainsRune(slice []rune, value rune, groupid int64) bool { +func ContainsRune(slice []rune, value rune, groupid int64, promptstr string) bool { var probability int if groupid == 0 { // 获取概率百分比 - probability = config.GetSplitByPuntuations() + probability = config.GetSplitByPuntuations(promptstr) } else { // 获取概率百分比 - probability = config.GetSplitByPuntuationsGroup() + probability = config.GetSplitByPuntuationsGroup(promptstr) } for _, item := range slice {