From c8d606a16d481891743ccda5a811d2f9a5f5bdda Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Mon, 13 May 2024 21:50:51 +0800
Subject: [PATCH 01/24] Beta115 (#113)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115
---
 applogic/gensokyo.go | 55 ++++++++++++++++++++++++++++++++------------
 applogic/hunyuan.go  |  3 ++-
 2 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index 246c80c..71369e8 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -11,6 +11,7 @@ import (
 	"net/url"
 	"strconv"
 	"strings"
+	"sync"
 
 	"github.com/hoshinonyaruko/gensokyo-llm/acnode"
 	"github.com/hoshinonyaruko/gensokyo-llm/config"
@@ -20,7 +21,8 @@ import (
 )
 
 var newmsgToStringMap = make(map[string]string)
-var stringToIndexMap = make(map[string]int)
+var stringToIndexMap sync.Map
+var processMessageMu sync.Mutex
 
 // RecordStringById 根据id记录一个string
 func RecordStringByNewmsg(id, value string) {
@@ -38,20 +40,30 @@ func GetStringByNewmsg(newmsg string) string {
 
 // IncrementIndex 为给定的字符串递增索引
 func IncrementIndex(s string) int {
-	// 检查map中是否已经有这个字符串的索引
-	if _, exists := stringToIndexMap[s]; !exists {
-		// 如果不存在,初始化为0
-		stringToIndexMap[s] = 0
+	// 尝试从map中获取值,如果不存在则初始化为0
+	val, loaded := stringToIndexMap.LoadOrStore(s, 0)
+	if !loaded {
+		// 如果这是一个新的键,我们现在将其值设置为1
+		stringToIndexMap.Store(s, 1)
+		return 1
 	}
-	// 递增索引
-	stringToIndexMap[s]++
-	// 返回新的索引值
-	return stringToIndexMap[s]
+
+	// 如果已存在,递增索引
+	newVal := val.(int) + 1
+	stringToIndexMap.Store(s, newVal)
+	return newVal
 }
 
-// ResetIndex 将给定字符串的索引归零
+// ResetIndex 重置或删除给定字符串的索引
 func ResetIndex(s string) {
-	stringToIndexMap[s] = 0
+	// 直接从map中删除指定的键
+	stringToIndexMap.Delete(s)
+}
+
+// ResetAllIndexes 清空整个索引map
+func ResetAllIndexes() {
+	// 重新初始化stringToIndexMap,因为sync.Map没有提供清空所有条目的直接方法
+	stringToIndexMap = sync.Map{}
 }
 
 // checkMessageForHints 检查消息中是否包含给定的提示词
@@ -607,7 +619,11 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 						lastMessageID = id // 更新lastMessageID
 						// 检查是否有未发送的消息部分
 						key := utils.GetKey(message.GroupID, message.UserID)
-						accumulatedMessage, exists := groupUserMessages[key]
+						accumulatedMessageInterface, exists := groupUserMessages.Load(key)
+						var accumulatedMessage string
+						if exists {
+							accumulatedMessage = accumulatedMessageInterface.(string)
+						}
 
 						// 提取response字段
 						if response, ok = responseData["response"].(string); ok {
@@ -721,8 +737,8 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 								}
 							}
 
-							// 清空映射中对应的累积消息
-							groupUserMessages[key] = ""
+							// 清空key的值
+							groupUserMessages.Store(key, "")
 						}
 					} else {
 						//发送信息
@@ -909,7 +925,16 @@ func processMessage(response string, msg structs.OnebotGroupMessage, newmesssage
 			// 达到标点符号,发送累积的整个消息
 			if messageBuilder.Len() > 0 {
 				accumulatedMessage := messageBuilder.String()
-				groupUserMessages[key] += accumulatedMessage
+				// 锁定
+				processMessageMu.Lock()
+				// 从sync.map读取当前的value
+				valueInterface, _ := groupUserMessages.Load(key)
+				value, _ := valueInterface.(string)
+				// 添加当前messageBuilder中的新内容
+				value += accumulatedMessage
+				// 储存新的内容到sync.map
+				groupUserMessages.Store(key, value)
+				processMessageMu.Unlock() // 完成更新后时解锁
 
 				// 判断消息类型,如果是私人消息或私有群消息,发送私人消息;否则,根据配置决定是否发送群消息
 				if msg.RealMessageType == "group_private" || msg.MessageType == "private" {
diff --git a/applogic/hunyuan.go b/applogic/hunyuan.go
index 59dc088..8168e87 100644
--- a/applogic/hunyuan.go
+++ b/applogic/hunyuan.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"net/http"
 	"strings"
+	"sync"
 
 	"github.com/hoshinonyaruko/gensokyo-llm/config"
 	"github.com/hoshinonyaruko/gensokyo-llm/fmtf"
@@ -15,7 +16,7 @@ import (
 )
 
 var messageBuilder strings.Builder
-var groupUserMessages = make(map[string]string)
+var groupUserMessages sync.Map
 
 func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 	if r.Method != "POST" {

From d23d5239704c1f0a1ab1c4a795b09463d037a843 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Tue, 14 May 2024 18:22:59 +0800
Subject: [PATCH 02/24] Beta116 (#114)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116
---
 applogic/chatglm.go       |   6 +-
 applogic/tongyiqianwen.go |  50 ++---
 config/config.go          | 442 ++++++++++++++++++++++++++++++++------
 3 files changed, 405 insertions(+), 93 deletions(-)

diff --git a/applogic/chatglm.go b/applogic/chatglm.go
index 6373a6e..3405390 100644
--- a/applogic/chatglm.go
+++ b/applogic/chatglm.go
@@ -225,16 +225,16 @@ func (app *App) ChatHandlerGlm(w http.ResponseWriter, r *http.Request) {
 	}
 
 	// 获取配置信息
-	apiKey := config.GetGlmApiKey()
+	apiKey := config.GetGlmApiKey(promptstr)
 	// 创建请求体的映射结构
 	requestBody := map[string]interface{}{
-		"model":       config.GetGlmModel(),
+		"model":       config.GetGlmModel(promptstr),
 		"messages":    messages,
 		"do_sample":   config.GetGlmDoSample(),
 		"stream":      config.GetuseSse(promptstr),
 		"temperature": config.GetGlmTemperature(),
 		"top_p":       config.GetGlmTopP(),
-		"max_tokens":  config.GetGlmMaxTokens(),
+		"max_tokens":  config.GetGlmMaxTokens(promptstr),
 		"stop":        config.GetGlmStop(),
 		//"tools":       config.GetGlmTools(), 不太清楚参数格式
 		"tool_choice": config.GetGlmToolChoice(),
diff --git a/applogic/tongyiqianwen.go b/applogic/tongyiqianwen.go
index e067e90..e35e4d7 100644
--- a/applogic/tongyiqianwen.go
+++ b/applogic/tongyiqianwen.go
@@ -198,7 +198,7 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 	fmtf.Printf("Tyqw上下文history:%v\n", history)
 
 	// 构建请求到Tyqw API
-	apiURL := config.GetTyqwApiPath()
+	apiURL := config.GetTyqwApiPath(promptstr)
 
 	// 构造消息历史和当前消息
 	messages := []map[string]interface{}{}
@@ -216,29 +216,29 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 	})
 
 	var isIncrementalOutput bool
-	if config.GetTyqwSseType() == 1 {
+	if config.GetTyqwSseType(promptstr) == 1 {
 		isIncrementalOutput = true
 	}
 	// 获取配置信息
 	useSSE := config.GetuseSse(promptstr)
-	apiKey := config.GetTyqwKey()
+	apiKey := config.GetTyqwKey(promptstr)
 	var requestBody map[string]interface{}
 	if useSSE {
 		// 构建请求体,根据提供的文档重新调整
 		requestBody = map[string]interface{}{
 			"parameters": map[string]interface{}{
-				"max_tokens":         config.GetTyqwMaxTokens(),         // 最大生成的token数
-				"temperature":        config.GetTyqwTemperature(),       // 控制随机性和多样性的温度
-				"top_p":              config.GetTyqwTopP(),              // 核采样方法的概率阈值
-				"top_k":              config.GetTyqwTopK(),              // 采样候选集的大小
-				"repetition_penalty": config.GetTyqwRepetitionPenalty(), // 控制重复度的惩罚因子
-				"stop":               config.GetTyqwStopTokens(),        // 停止标记
-				"seed":               config.GetTyqwSeed(),              // 随机数种子
-				"result_format":      "message",                         // 返回结果的格式
-				"enable_search":      config.GetTyqwEnableSearch(),      // 是否启用互联网搜索
-				"incremental_output": isIncrementalOutput,               // 是否使用增量SSE模式,使用增量模式会更快,rwkv和openai不支持增量模式
+				"max_tokens":         config.GetTyqwMaxTokens(promptstr),   // 最大生成的token数
+				"temperature":        config.GetTyqwTemperature(promptstr), // 控制随机性和多样性的温度
+				"top_p":              config.GetTyqwTopP(promptstr),        // 核采样方法的概率阈值
+				"top_k":              config.GetTyqwTopK(promptstr),        // 采样候选集的大小
+				"repetition_penalty": config.GetTyqwRepetitionPenalty(),    // 控制重复度的惩罚因子
+				"stop":               config.GetTyqwStopTokens(),           // 停止标记
+				"seed":               config.GetTyqwSeed(),                 // 随机数种子
+				"result_format":      "message",                            // 返回结果的格式
+				"enable_search":      config.GetTyqwEnableSearch(),         // 是否启用互联网搜索
+				"incremental_output": isIncrementalOutput,                  // 是否使用增量SSE模式,使用增量模式会更快,rwkv和openai不支持增量模式
 			},
-			"model": config.GetTyqwModel(), // 指定对话模型
+			"model": config.GetTyqwModel(promptstr), // 指定对话模型
 			"input": map[string]interface{}{
 				"messages": messages, // 用户与模型的对话历史
 			},
@@ -251,17 +251,17 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 		// 构建请求体,根据提供的文档重新调整
 		requestBody = map[string]interface{}{
 			"parameters": map[string]interface{}{
-				"max_tokens":         config.GetTyqwMaxTokens(),         // 最大生成的token数
-				"temperature":        config.GetTyqwTemperature(),       // 控制随机性和多样性的温度
-				"top_p":              config.GetTyqwTopP(),              // 核采样方法的概率阈值
-				"top_k":              config.GetTyqwTopK(),              // 采样候选集的大小
-				"repetition_penalty": config.GetTyqwRepetitionPenalty(), // 控制重复度的惩罚因子
-				"stop":               config.GetTyqwStopTokens(),        // 停止标记
-				"seed":               config.GetTyqwSeed(),              // 随机数种子
-				"result_format":      "message",                         // 返回结果的格式
-				"enable_search":      config.GetTyqwEnableSearch(),      // 是否启用互联网搜索
+				"max_tokens":         config.GetTyqwMaxTokens(promptstr),   // 最大生成的token数
+				"temperature":        config.GetTyqwTemperature(promptstr), // 控制随机性和多样性的温度
+				"top_p":              config.GetTyqwTopP(promptstr),        // 核采样方法的概率阈值
+				"top_k":              config.GetTyqwTopK(promptstr),        // 采样候选集的大小
+				"repetition_penalty": config.GetTyqwRepetitionPenalty(),    // 控制重复度的惩罚因子
+				"stop":               config.GetTyqwStopTokens(),           // 停止标记
+				"seed":               config.GetTyqwSeed(),                 // 随机数种子
+				"result_format":      "message",                            // 返回结果的格式
+				"enable_search":      config.GetTyqwEnableSearch(),         // 是否启用互联网搜索
 			},
-			"model": config.GetTyqwModel(), // 指定对话模型
+			"model": config.GetTyqwModel(promptstr), // 指定对话模型
 			"input": map[string]interface{}{
 				"messages": messages, // 用户与模型的对话历史
 			},
@@ -402,7 +402,7 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 
 		reader := bufio.NewReader(resp.Body)
 		var totalUsage structs.GPTUsageInfo
-		if config.GetTyqwSseType() == 1 {
+		if config.GetTyqwSseType(promptstr) == 1 {
 			for {
 				line, err := reader.ReadString('\n')
 				if err != nil {
diff --git a/config/config.go b/config/config.go
index d3d2704..745d86a 100644
--- a/config/config.go
+++ b/config/config.go
@@ -2032,14 +2032,38 @@ func GetNo4Promptkeyboard() bool {
 	return false
 }
 
-// 获取TYQW API路径
-func GetTyqwApiPath() string {
+// GetTyqwApiPath 获取TYQW API路径,可接受basename作为参数
+func GetTyqwApiPath(options ...string) string {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.TyqwApiPath
+	return getTyqwApiPathInternal(options...)
+}
+
+// getTyqwApiPathInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTyqwApiPathInternal(options ...string) string {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TyqwApiPath
+		}
+		return "" // 默认值或错误处理
 	}
-	return "" // 默认值或错误处理
+
+	// 使用传入的 basename
+	basename := options[0]
+	apiPathInterface, err := prompt.GetSettingFromFilename(basename, "TyqwApiPath")
+	if err != nil {
+		log.Println("Error retrieving TyqwApiPath:", err)
+		return getTyqwApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	apiPath, ok := apiPathInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for TyqwApiPath, fetching default")
+		return getTyqwApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return apiPath
 }
 
 // 获取TYQW最大Token数量,可接受basename作为参数
@@ -2076,44 +2100,140 @@ func getTyqwMaxTokensInternal(options ...string) int {
 	return maxTokens
 }
 
-// 获取TYQW温度设置
-func GetTyqwTemperature() float64 {
+// GetTyqwTemperature 获取TYQW温度设置,可接受basename作为参数
+func GetTyqwTemperature(options ...string) float64 {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.TyqwTemperature
+	return getTyqwTemperatureInternal(options...)
+}
+
+// getTyqwTemperatureInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTyqwTemperatureInternal(options ...string) float64 {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TyqwTemperature
+		}
+		return 0.0 // 默认值或错误处理
 	}
-	return 0.0 // 默认值或错误处理
+
+	// 使用传入的 basename
+	basename := options[0]
+	temperatureInterface, err := prompt.GetSettingFromFilename(basename, "TyqwTemperature")
+	if err != nil {
+		log.Println("Error retrieving TyqwTemperature:", err)
+		return getTyqwTemperatureInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	temperature, ok := temperatureInterface.(float64)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for TyqwTemperature, fetching default")
+		return getTyqwTemperatureInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return temperature
 }
 
-// 获取TYQW Top P
-func GetTyqwTopP() float64 {
+// GetTyqwTopP 获取TYQW Top P值,可接受basename作为参数
+func GetTyqwTopP(options ...string) float64 {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.TyqwTopP
+	return getTyqwTopPInternal(options...)
+}
+
+// getTyqwTopPInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTyqwTopPInternal(options ...string) float64 {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TyqwTopP
+		}
+		return 0.0 // 默认值或错误处理
 	}
-	return 0.0 // 默认值或错误处理
+
+	// 使用传入的 basename
+	basename := options[0]
+	topPInterface, err := prompt.GetSettingFromFilename(basename, "TyqwTopP")
+	if err != nil {
+		log.Println("Error retrieving TyqwTopP:", err)
+		return getTyqwTopPInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	topP, ok := topPInterface.(float64)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for TyqwTopP, fetching default")
+		return getTyqwTopPInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return topP
 }
 
-// 获取TYQW Top K
-func GetTyqwTopK() int {
+// GetTyqwTopK 获取TYQW Top K设置,可接受basename作为参数
+func GetTyqwTopK(options ...string) int {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.TyqwTopK
+	return getTyqwTopKInternal(options...)
+}
+
+// getTyqwTopKInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTyqwTopKInternal(options ...string) int {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TyqwTopK
+		}
+		return 0 // 默认值或错误处理
 	}
-	return 0 // 默认值或错误处理
+
+	// 使用传入的 basename
+	basename := options[0]
+	topKInterface, err := prompt.GetSettingFromFilename(basename, "TyqwTopK")
+	if err != nil {
+		log.Println("Error retrieving TyqwTopK:", err)
+		return getTyqwTopKInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	topK, ok := topKInterface.(int)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for TyqwTopK, fetching default")
+		return getTyqwTopKInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return topK
 }
 
-// 获取TYQW SSE类型
-func GetTyqwSseType() int {
+// GetTyqwSseType 获取TYQW SSE类型,可接受basename作为参数
+func GetTyqwSseType(options ...string) int {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.TyqwSseType
+	return getTyqwSseTypeInternal(options...)
+}
+
+// getTyqwSseTypeInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTyqwSseTypeInternal(options ...string) int {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TyqwSseType
+		}
+		return 0 // 默认值或错误处理
 	}
-	return 0 // 默认值或错误处理
+
+	// 使用传入的 basename
+	basename := options[0]
+	sseTypeInterface, err := prompt.GetSettingFromFilename(basename, "TyqwSseType")
+	if err != nil {
+		log.Println("Error retrieving TyqwSseType:", err)
+		return getTyqwSseTypeInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	sseType, ok := sseTypeInterface.(int)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for TyqwSseType, fetching default")
+		return getTyqwSseTypeInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return sseType
 }
 
 // 获取TYQW用户名
@@ -2196,24 +2316,72 @@ func GetTyqwEnableSearch() bool {
 	return false // 默认值或错误处理
 }
 
-// 获取TYQW模型名称
-func GetTyqwModel() string {
+// GetTyqwModel 获取TYQW模型名称,可接受basename作为参数
+func GetTyqwModel(options ...string) string {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.TyqwModel
+	return getTyqwModelInternal(options...)
+}
+
+// getTyqwModelInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTyqwModelInternal(options ...string) string {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TyqwModel
+		}
+		return "default-model" // 默认值或错误处理
 	}
-	return "default-model" // 默认值或错误处理
+
+	// 使用传入的 basename
+	basename := options[0]
+	modelInterface, err := prompt.GetSettingFromFilename(basename, "TyqwModel")
+	if err != nil {
+		log.Println("Error retrieving TyqwModel:", err)
+		return getTyqwModelInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	model, ok := modelInterface.(string)
+	if !ok || model == "" { // 检查类型断言是否失败或结果为空字符串
+		log.Println("Type assertion failed or empty string for TyqwModel, fetching default")
+		return getTyqwModelInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return model
 }
 
-// 获取TYQW API Key
-func GetTyqwKey() string {
+// GetTyqwKey 获取TYQW API Key,可接受basename作为参数
+func GetTyqwKey(options ...string) string {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.TyqwApiKey
+	return getTyqwKeyInternal(options...)
+}
+
+// getTyqwKeyInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTyqwKeyInternal(options ...string) string {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TyqwApiKey
+		}
+		return "" // 默认值或错误处理,表示没有找到有效的API Key
+	}
+
+	// 使用传入的 basename
+	basename := options[0]
+	apiKeyInterface, err := prompt.GetSettingFromFilename(basename, "TyqwApiKey")
+	if err != nil {
+		log.Println("Error retrieving TyqwApiKey:", err)
+		return getTyqwKeyInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	apiKey, ok := apiKeyInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for TyqwApiKey, fetching default")
+		return getTyqwKeyInternal() // 递归调用内部函数,不传递任何参数
 	}
-	return "" // 默认值或错误处理,表示没有找到有效的API Key
+
+	return apiKey
 }
 
 // 获取TYQW Workspace
@@ -2229,34 +2397,106 @@ func GetTyqworkspace() (string, error) {
 	return "", fmt.Errorf("configuration instance is not initialized") // 错误处理,当配置实例未初始化时
 }
 
-// GetGlmApiPath 获取GLM API路径
-func GetGlmApiPath() string {
+// GetGlmApiPath 获取GLM API路径,可接受basename作为参数
+func GetGlmApiPath(options ...string) string {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.GlmApiPath
+	return getGlmApiPathInternal(options...)
+}
+
+// getGlmApiPathInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getGlmApiPathInternal(options ...string) string {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.GlmApiPath
+		}
+		return "" // 默认值或错误处理
 	}
-	return "" // 默认值或错误处理
+
+	// 使用传入的 basename
+	basename := options[0]
+	apiPathInterface, err := prompt.GetSettingFromFilename(basename, "GlmApiPath")
+	if err != nil {
+		log.Println("Error retrieving GlmApiPath:", err)
+		return getGlmApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	apiPath, ok := apiPathInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for GlmApiPath, fetching default")
+		return getGlmApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return apiPath
 }
 
-// GetGlmModel 获取模型编码
-func GetGlmModel() string {
+// GetGlmModel 获取模型编码,可接受basename作为参数
+func GetGlmModel(options ...string) string {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.GlmModel
+	return getGlmModelInternal(options...)
+}
+
+// getGlmModelInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getGlmModelInternal(options ...string) string {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.GlmModel
+		}
+		return "" // 默认值或错误处理
 	}
-	return ""
+
+	// 使用传入的 basename
+	basename := options[0]
+	modelInterface, err := prompt.GetSettingFromFilename(basename, "GlmModel")
+	if err != nil {
+		log.Println("Error retrieving GlmModel:", err)
+		return getGlmModelInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	model, ok := modelInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for GlmModel, fetching default")
+		return getGlmModelInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return model
 }
 
-// GetGlmApiKey 获取模型编码
-func GetGlmApiKey() string {
+// GetGlmApiKey 获取glm密钥,可接受basename作为参数
+func GetGlmApiKey(options ...string) string {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.GlmApiKey
+	return getGlmApiKeyInternal(options...)
+}
+
+// getGlmApiKeyInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getGlmApiKeyInternal(options ...string) string {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.GlmApiKey
+		}
+		return "" // 默认值或错误处理
 	}
-	return ""
+
+	// 使用传入的 basename
+	basename := options[0]
+	apiKeyInterface, err := prompt.GetSettingFromFilename(basename, "GlmApiKey")
+	if err != nil {
+		log.Println("Error retrieving GlmApiKey:", err)
+		return getGlmApiKeyInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	apiKey, ok := apiKeyInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for GlmApiKey, fetching default")
+		return getGlmApiKeyInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return apiKey
 }
 
 // GetGlmMaxTokens 获取模型输出的最大tokens数,可接受basename作为参数
@@ -2293,14 +2533,38 @@ func getGlmMaxTokensInternal(options ...string) int {
 	return maxTokens
 }
 
-// GetGlmTemperature 获取模型的采样温度
-func GetGlmTemperature() float64 {
+// GetGlmTemperature 获取模型的采样温度,可接受basename作为参数
+func GetGlmTemperature(options ...string) float64 {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.GlmTemperature
+	return getGlmTemperatureInternal(options...)
+}
+
+// getGlmTemperatureInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getGlmTemperatureInternal(options ...string) float64 {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.GlmTemperature
+		}
+		return 0.95 // 默认值或错误处理
+	}
+
+	// 使用传入的 basename
+	basename := options[0]
+	temperatureInterface, err := prompt.GetSettingFromFilename(basename, "GlmTemperature")
+	if err != nil {
+		log.Println("Error retrieving GlmTemperature:", err)
+		return getGlmTemperatureInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	temperature, ok := temperatureInterface.(float64)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for GlmTemperature, fetching default")
+		return getGlmTemperatureInternal() // 递归调用内部函数,不传递任何参数
 	}
-	return 0.95 // 返回默认值
+
+	return temperature
 }
 
 // GetGlmDoSample 获取是否启用采样策略
@@ -2343,14 +2607,38 @@ func GetGlmRequestID() string {
 	return "" // 返回默认值,表示没有设置
 }
 
-// GetGlmTopP 获取核取样概率
-func GetGlmTopP() float64 {
+// GetGlmTopP 获取核取样概率,可接受basename作为参数
+func GetGlmTopP(options ...string) float64 {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.GlmTopP
+	return getGlmTopPInternal(options...)
+}
+
+// getGlmTopPInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getGlmTopPInternal(options ...string) float64 {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.GlmTopP
+		}
+		return 0.7 // 默认值或错误处理
+	}
+
+	// 使用传入的 basename
+	basename := options[0]
+	topPInterface, err := prompt.GetSettingFromFilename(basename, "GlmTopP")
+	if err != nil {
+		log.Println("Error retrieving GlmTopP:", err)
+		return getGlmTopPInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	topP, ok := topPInterface.(float64)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for GlmTopP, fetching default")
+		return getGlmTopPInternal() // 递归调用内部函数,不传递任何参数
 	}
-	return 0.7 // 返回默认值
+
+	return topP
 }
 
 // GetGlmStop 获取停止生成的词列表
@@ -2373,12 +2661,36 @@ func GetGlmTools() []string {
 	return []string{} // 返回空切片,表示没有工具设置
 }
 
-// 获取GroupHintWords列表
-func GetGroupHintWords() []string {
+// GetGroupHintWords 获取GroupHintWords列表,可接受basename作为参数
+func GetGroupHintWords(options ...string) []string {
 	mu.Lock()
 	defer mu.Unlock()
-	if instance != nil {
-		return instance.Settings.GroupHintWords
+	return getGroupHintWordsInternal(options...)
+}
+
+// getGroupHintWordsInternal 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getGroupHintWordsInternal(options ...string) []string {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.GroupHintWords
+		}
+		return nil // 默认值或错误处理
 	}
-	return nil
+
+	// 使用传入的 basename
+	basename := options[0]
+	hintWordsInterface, err := prompt.GetSettingFromFilename(basename, "GroupHintWords")
+	if err != nil {
+		log.Println("Error retrieving GroupHintWords:", err)
+		return getGroupHintWordsInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	hintWords, ok := hintWordsInterface.([]string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for GroupHintWords, fetching default")
+		return getGroupHintWordsInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return hintWords
 }

From 4b1aa8dde3f827618f8f67d27250b0228876574d Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Tue, 14 May 2024 20:22:07 +0800
Subject: [PATCH 03/24] Beta117 (#115)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117
---
 applogic/gensokyo.go |  2 +-
 utils/blacklist.go   | 21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index 71369e8..60d5a94 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -264,7 +264,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		}
 
 		if utils.BlacklistIntercept(message, selfid) {
-			fmtf.Printf("userid:[%v]这位用户在黑名单中,被拦截", message.UserID)
+			fmtf.Printf("userid:[%v]groupid:[%v]这位用户或群在黑名单中,被拦截", message.UserID, message.GroupID)
 			return
 		}
 
diff --git a/utils/blacklist.go b/utils/blacklist.go
index 6d3b1f2..77b1aea 100644
--- a/utils/blacklist.go
+++ b/utils/blacklist.go
@@ -94,6 +94,26 @@ func WatchBlacklist(filePath string) {
 
 // BlacklistIntercept 检查用户ID是否在黑名单中,如果在,则发送预设消息
 func BlacklistIntercept(message structs.OnebotGroupMessage, selfid string) bool {
+	// 检查群ID是否在黑名单中
+	if IsInBlacklist(strconv.FormatInt(message.GroupID, 10)) {
+		// 获取黑名单响应消息
+		responseMessage := config.GetBlacklistResponseMessages()
+
+		// 根据消息类型发送响应
+		if message.RealMessageType == "group_private" || message.MessageType == "private" {
+			if !config.GetUsePrivateSSE() {
+				SendPrivateMessage(message.UserID, responseMessage, selfid)
+			} else {
+				SendSSEPrivateMessage(message.UserID, responseMessage)
+			}
+		} else {
+			SendGroupMessage(message.GroupID, message.UserID, responseMessage, selfid)
+		}
+
+		fmt.Printf("groupid:[%v]这个群在黑名单中,被拦截\n", message.GroupID)
+		return true // 拦截
+	}
+
 	// 检查用户ID是否在黑名单中
 	if IsInBlacklist(strconv.FormatInt(message.UserID, 10)) {
 		// 获取黑名单响应消息
@@ -113,5 +133,6 @@ func BlacklistIntercept(message structs.OnebotGroupMessage, selfid string) bool
 		fmt.Printf("userid:[%v]这位用户在黑名单中,被拦截\n", message.UserID)
 		return true // 拦截
 	}
+
 	return false // 用户ID不在黑名单中,不拦截
 }

From ec731c2f098623884ba4452bc0b7d3b81b7e76aa Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Thu, 16 May 2024 19:05:06 +0800
Subject: [PATCH 04/24] Beta118 (#116)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118
---
 applogic/chatglm.go         | 41 +++++++++++++++++--------------
 applogic/ernie.go           | 15 ++++++++----
 applogic/tongyiqianwen.go   | 49 ++++++++++++++++++++++---------------
 config/config.go            | 44 +++++++++++++++++++++++++++++++++
 prompt/prompt.go            | 23 +++++++++++++++++
 template/config_template.go |  2 +-
 6 files changed, 130 insertions(+), 44 deletions(-)

diff --git a/applogic/chatglm.go b/applogic/chatglm.go
index 3405390..14b4aac 100644
--- a/applogic/chatglm.go
+++ b/applogic/chatglm.go
@@ -133,7 +133,7 @@ func (app *App) ChatHandlerGlm(w http.ResponseWriter, r *http.Request) {
 			}
 		} else {
 			// 只获取系统提示词
-			systemMessage, err := prompt.FindFirstSystemMessage(history)
+			systemMessage, err := prompt.GetFirstSystemMessageStruct(promptstr)
 			if err != nil {
 				fmt.Println("Error:", err)
 			} else {
@@ -164,28 +164,33 @@ func (app *App) ChatHandlerGlm(w http.ResponseWriter, r *http.Request) {
 				fmtf.Printf("Error getting system history: %v,promptstr[%v]\n", err, promptstr)
 				return
 			}
-
-			// 处理增强QA逻辑
 			if config.GetEnhancedQA(promptstr) {
-				// 确保系统历史与用户或助手历史数量一致,如果不足,则补足空的历史记录
-				// 因为最后一个成员让给当前QA,所以-1
-				if len(systemHistory)-2 > len(userHistory) {
-					difference := len(systemHistory) - len(userHistory)
+				systemHistory, err := prompt.GetMessagesExcludingSystem(promptstr)
+				if err != nil {
+					fmt.Printf("Error getting system history: %v\n", err)
+					return
+				}
+
+				// 计算需要补足的历史记录数量
+				neededHistoryCount := len(systemHistory) - 2 // 最后两条留给当前QA处理
+				if neededHistoryCount > len(userHistory) {
+					// 补足用户或助手历史
+					difference := neededHistoryCount - len(userHistory)
 					for i := 0; i < difference; i++ {
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						if i%2 != 0 {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
+						} else {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						}
 					}
 				}
 
-				// 如果系统历史中只有一个成员,跳过覆盖逻辑,留给后续处理
-				if len(systemHistory) > 1 {
-					// 将系统历史(除最后2个成员外)附加到相应的用户或助手历史上,采用倒序方式处理最近的记录
-					for i := 0; i < len(systemHistory)-2; i++ {
-						sysMsg := systemHistory[i]
-						index := len(userHistory) - len(systemHistory) + i
-						if index >= 0 && index < len(userHistory) && (userHistory[index].Role == "user" || userHistory[index].Role == "assistant") {
-							userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
-						}
+				// 附加系统历史到用户或助手历史,除了最后两条
+				for i := 0; i < len(systemHistory)-2; i++ {
+					sysMsg := systemHistory[i]
+					index := len(userHistory) - neededHistoryCount + i
+					if index >= 0 && index < len(userHistory) {
+						userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
 					}
 				}
 			} else {
diff --git a/applogic/ernie.go b/applogic/ernie.go
index 4dbe725..eadb9d8 100644
--- a/applogic/ernie.go
+++ b/applogic/ernie.go
@@ -133,12 +133,17 @@ func (app *App) ChatHandlerErnie(w http.ResponseWriter, r *http.Request) {
 			// 处理增强QA逻辑
 			if config.GetEnhancedQA(promptstr) {
 				// 确保系统历史与用户或助手历史数量一致,如果不足,则补足空的历史记录
-				// 因为最后一个成员让给当前QA,所以-1
-				if len(systemHistory)-2 > len(userHistory) {
-					difference := len(systemHistory) - len(userHistory)
+				// 计算需要补足的历史记录数量
+				neededHistoryCount := len(systemHistory) - 2 // 最后两条留给当前QA处理
+				if neededHistoryCount > len(userHistory) {
+					// 补足用户或助手历史
+					difference := neededHistoryCount - len(userHistory)
 					for i := 0; i < difference; i++ {
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						if i%2 != 0 {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
+						} else {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						}
 					}
 				}
 
diff --git a/applogic/tongyiqianwen.go b/applogic/tongyiqianwen.go
index e35e4d7..8277437 100644
--- a/applogic/tongyiqianwen.go
+++ b/applogic/tongyiqianwen.go
@@ -128,7 +128,7 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 			}
 		} else {
 			// 只获取系统提示词
-			systemMessage, err := prompt.FindFirstSystemMessage(history)
+			systemMessage, err := prompt.GetFirstSystemMessageStruct(promptstr)
 			if err != nil {
 				fmt.Println("Error:", err)
 			} else {
@@ -138,7 +138,7 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 	}
-
+	// TODO: msgid是空的开始第一句也要处理 插入
 	// 获取历史信息
 	if msg.ParentMessageID != "" {
 		userhistory, err := app.getHistory(msg.ConversationID, msg.ParentMessageID)
@@ -159,28 +159,33 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 				fmtf.Printf("Error getting system history: %v,promptstr[%v]\n", err, promptstr)
 				return
 			}
-
-			// 处理增强QA逻辑
 			if config.GetEnhancedQA(promptstr) {
-				// 确保系统历史与用户或助手历史数量一致,如果不足,则补足空的历史记录
-				// 因为最后一个成员让给当前QA,所以-1
-				if len(systemHistory)-2 > len(userHistory) {
-					difference := len(systemHistory) - len(userHistory)
+				systemHistory, err := prompt.GetMessagesExcludingSystem(promptstr)
+				if err != nil {
+					fmt.Printf("Error getting system history: %v\n", err)
+					return
+				}
+
+				// 计算需要补足的历史记录数量
+				neededHistoryCount := len(systemHistory) - 2 // 最后两条留给当前QA处理
+				if neededHistoryCount > len(userHistory) {
+					// 补足用户或助手历史
+					difference := neededHistoryCount - len(userHistory)
 					for i := 0; i < difference; i++ {
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						if i%2 != 0 {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
+						} else {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						}
 					}
 				}
 
-				// 如果系统历史中只有一个成员,跳过覆盖逻辑,留给后续处理
-				if len(systemHistory) > 1 {
-					// 将系统历史(除最后2个成员外)附加到相应的用户或助手历史上,采用倒序方式处理最近的记录
-					for i := 0; i < len(systemHistory)-2; i++ {
-						sysMsg := systemHistory[i]
-						index := len(userHistory) - len(systemHistory) + i
-						if index >= 0 && index < len(userHistory) && (userHistory[index].Role == "user" || userHistory[index].Role == "assistant") {
-							userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
-						}
+				// 附加系统历史到用户或助手历史,除了最后两条
+				for i := 0; i < len(systemHistory)-2; i++ {
+					sysMsg := systemHistory[i]
+					index := len(userHistory) - neededHistoryCount + i
+					if index >= 0 && index < len(userHistory) {
+						userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
 					}
 				}
 			} else {
@@ -199,6 +204,7 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 
 	// 构建请求到Tyqw API
 	apiURL := config.GetTyqwApiPath(promptstr)
+	fmtf.Printf("Tyqw请求地址:%v\n", apiURL)
 
 	// 构造消息历史和当前消息
 	messages := []map[string]interface{}{}
@@ -216,8 +222,11 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 	})
 
 	var isIncrementalOutput bool
-	if config.GetTyqwSseType(promptstr) == 1 {
+	tyqwssetype := config.GetTyqwSseType(promptstr)
+	if tyqwssetype == 1 {
 		isIncrementalOutput = true
+	} else if tyqwssetype == 2 {
+		isIncrementalOutput = false
 	}
 	// 获取配置信息
 	useSSE := config.GetuseSse(promptstr)
diff --git a/config/config.go b/config/config.go
index 745d86a..a7368bc 100644
--- a/config/config.go
+++ b/config/config.go
@@ -262,6 +262,10 @@ func getMaxTokensHunyuanInternal(options ...string) int {
 		return getMaxTokensHunyuanInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if maxTokensHunyuan == 0 {
+		return getMaxTokensHunyuanInternal()
+	}
+
 	return maxTokensHunyuan
 }
 
@@ -316,6 +320,10 @@ func getWenxinApiPathInternal(options ...string) string {
 		return getWenxinApiPathInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if apiPath == "" {
+		return getWenxinApiPathInternal()
+	}
+
 	return apiPath
 }
 
@@ -360,6 +368,10 @@ func getGptModelInternal(options ...string) string {
 		return getGptModelInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if gptModel == "" {
+		return getGptModelInternal()
+	}
+
 	return gptModel
 }
 
@@ -2063,6 +2075,10 @@ func getTyqwApiPathInternal(options ...string) string {
 		return getTyqwApiPathInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if apiPath == "" {
+		return getTyqwApiPathInternal()
+	}
+
 	return apiPath
 }
 
@@ -2097,6 +2113,10 @@ func getTyqwMaxTokensInternal(options ...string) int {
 		return getTyqwMaxTokensInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if maxTokens == 0 {
+		return getTyqwMaxTokensInternal()
+	}
+
 	return maxTokens
 }
 
@@ -2131,6 +2151,10 @@ func getTyqwTemperatureInternal(options ...string) float64 {
 		return getTyqwTemperatureInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if temperature == 0 {
+		return getTyqwTemperatureInternal()
+	}
+
 	return temperature
 }
 
@@ -2165,6 +2189,10 @@ func getTyqwTopPInternal(options ...string) float64 {
 		return getTyqwTopPInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if topP == 0 {
+		return getTyqwTopPInternal()
+	}
+
 	return topP
 }
 
@@ -2199,6 +2227,10 @@ func getTyqwTopKInternal(options ...string) int {
 		return getTyqwTopKInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if topK == 0 {
+		return getTyqwTopKInternal()
+	}
+
 	return topK
 }
 
@@ -2233,6 +2265,10 @@ func getTyqwSseTypeInternal(options ...string) int {
 		return getTyqwSseTypeInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if sseType == 0 {
+		return getTyqwSseTypeInternal()
+	}
+
 	return sseType
 }
 
@@ -2347,6 +2383,10 @@ func getTyqwModelInternal(options ...string) string {
 		return getTyqwModelInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if model == "" {
+		return getTyqwModelInternal()
+	}
+
 	return model
 }
 
@@ -2381,6 +2421,10 @@ func getTyqwKeyInternal(options ...string) string {
 		return getTyqwKeyInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if apiKey == "" {
+		return getTyqwKeyInternal()
+	}
+
 	return apiKey
 }
 
diff --git a/prompt/prompt.go b/prompt/prompt.go
index ba3e8f0..1892f24 100644
--- a/prompt/prompt.go
+++ b/prompt/prompt.go
@@ -192,6 +192,29 @@ func FindFirstSystemMessage(history []structs.Message) (structs.Message, error)
 	return structs.Message{}, fmt.Errorf("no system message found in history")
 }
 
+// GetFirstSystemMessage returns the first message that is of "system" role.
+func GetFirstSystemMessageStruct(basename string) (structs.Message, error) {
+	lock.RLock()
+	defer lock.RUnlock()
+
+	filename := basename + ".yml"
+	promptFile, exists := promptsCache[filename]
+	if !exists {
+		return structs.Message{}, fmt.Errorf("no data for file: %s", filename)
+	}
+
+	for _, prompt := range promptFile.Prompts {
+		if prompt.Role == "system" || prompt.Role == "System" {
+			return structs.Message{
+				Text: prompt.Content,
+				Role: prompt.Role,
+			}, nil
+		}
+	}
+
+	return structs.Message{}, fmt.Errorf("no system message found in file: %s", filename)
+}
+
 // 返回除了 "system" 角色之外的所有消息
 // GetMessagesExcludingSystem returns a list of messages that are not of "system" role,
 // randomly selecting from options separated by "||" in prompt contents.
diff --git a/template/config_template.go b/template/config_template.go
index f6913f1..4c559a8 100644
--- a/template/config_template.go
+++ b/template/config_template.go
@@ -155,7 +155,7 @@ settings:
   tyqwRepetitionPenalty : 1.1                       # 用于控制模型生成时的重复度。提高repetition_penalty时可以降低模型生成的重复度。1.0表示不做惩罚,默认为1.1。没有严格的取值范围。
   tyqwTopK: 40                                      # 从概率最高的K个令牌中采样
   tyqwSeed : 1234                                   # 生成时使用的随机数种子,用户控制模型生成内容的随机性。seed支持无符号64位整数,默认值为1234。在使用seed时,模型将尽可能生成相同或相似的结果,但目前不保证每次生成的结果完全相同。
-  tyqwSseType: 1                                    # 同gptSseType, 例如0代表不使用, 1代表使用
+  tyqwSseType: 1                                    # 1=默认,sse发新内容 2=sse内容递增(不推荐)
   tyqwGlobalPenalty: false                          # 是否在全局上应用频率惩罚
   tyqwStop:                                         # 停止生成的标记列表
     - "\n\nUser"                                    

From 4a09fba361a13944fdfb0e5a257e0f0331aac49d Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Fri, 17 May 2024 17:12:45 +0800
Subject: [PATCH 05/24] Beta119 (#117)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119
---
 applogic/hunyuan.go         | 266 ++++++++++++-
 applogic/rwkv.go            |  39 +-
 config/config.go            | 100 +++++
 hunyuan/client.go           | 256 +++++++++++--
 hunyuan/errors.go           |   6 +-
 hunyuan/models.go           | 719 +++++++++++++++++++++++++++++++-----
 structs/struct.go           |   7 +-
 template/config_template.go |   5 +-
 utils/utils.go              |  11 +
 9 files changed, 1254 insertions(+), 155 deletions(-)

diff --git a/applogic/hunyuan.go b/applogic/hunyuan.go
index 8168e87..2efd13a 100644
--- a/applogic/hunyuan.go
+++ b/applogic/hunyuan.go
@@ -114,9 +114,22 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 	} else {
-		history, err = prompt.GetMessagesFromFilename(promptstr)
-		if err != nil {
-			fmtf.Printf("prompt.GetMessagesFromFilename error: %v\n", err)
+		// 默认执行 正常提示词顺序
+		if !config.GetEnhancedQA(promptstr) {
+			history, err = prompt.GetMessagesFromFilename(promptstr)
+			if err != nil {
+				fmtf.Printf("prompt.GetMessagesFromFilename error: %v\n", err)
+			}
+		} else {
+			// 只获取系统提示词
+			systemMessage, err := prompt.GetFirstSystemMessageStruct(promptstr)
+			if err != nil {
+				fmt.Println("Error:", err)
+			} else {
+				// 如果找到system消息,将其添加到历史数组中
+				history = append(history, systemMessage)
+				fmt.Println("Added system message back to history.")
+			}
 		}
 	}
 
@@ -137,31 +150,38 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 			// 获取系统级预埋的系统自定义QA对
 			systemHistory, err := prompt.GetMessagesExcludingSystem(promptstr)
 			if err != nil {
-				fmtf.Printf("Error getting system history: %v\n", err)
+				fmtf.Printf("Error getting system history: %v,promptstr[%v]\n", err, promptstr)
 				return
 			}
 
 			// 处理增强QA逻辑
 			if config.GetEnhancedQA(promptstr) {
-				// 确保系统历史与用户或助手历史数量一致,如果不足,则补足空的历史记录
-				// 因为最后一个成员让给当前QA,所以-1
-				if len(systemHistory)-2 > len(userHistory) {
-					difference := len(systemHistory) - len(userHistory)
+				systemHistory, err := prompt.GetMessagesExcludingSystem(promptstr)
+				if err != nil {
+					fmt.Printf("Error getting system history: %v\n", err)
+					return
+				}
+
+				// 计算需要补足的历史记录数量
+				neededHistoryCount := len(systemHistory) - 2 // 最后两条留给当前QA处理
+				if neededHistoryCount > len(userHistory) {
+					// 补足用户或助手历史
+					difference := neededHistoryCount - len(userHistory)
 					for i := 0; i < difference; i++ {
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						if i%2 != 0 {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
+						} else {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						}
 					}
 				}
 
-				// 如果系统历史中只有一个成员,跳过覆盖逻辑,留给后续处理
-				if len(systemHistory) > 1 {
-					// 将系统历史(除最后2个成员外)附加到相应的用户或助手历史上,采用倒序方式处理最近的记录
-					for i := 0; i < len(systemHistory)-2; i++ {
-						sysMsg := systemHistory[i]
-						index := len(userHistory) - len(systemHistory) + i
-						if index >= 0 && index < len(userHistory) && (userHistory[index].Role == "user" || userHistory[index].Role == "assistant") {
-							userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
-						}
+				// 附加系统历史到用户或助手历史,除了最后两条
+				for i := 0; i < len(systemHistory)-2; i++ {
+					sysMsg := systemHistory[i]
+					index := len(userHistory) - neededHistoryCount + i
+					if index >= 0 && index < len(userHistory) {
+						userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
 					}
 				}
 			} else {
@@ -181,6 +201,16 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 	if config.GetHunyuanType() == 0 {
 		// 构建 hunyuan 请求
 		request := hunyuan.NewChatProRequest()
+		// 配置块
+		request.StreamModeration = new(bool)
+		*request.StreamModeration = config.GetHunyuanStreamModeration(promptstr)
+		request.Stream = new(bool)
+		*request.Stream = config.GetHunyuanStreamModeration(promptstr)
+		request.TopP = new(float64)
+		*request.TopP = config.GetTopPHunyuan(promptstr)
+		request.Temperature = new(float64)
+		*request.Temperature = config.GetTemperatureHunyuan(promptstr)
+
 		// 添加历史信息
 		for _, hMsg := range history {
 			content := hMsg.Text // 创建新变量
@@ -335,9 +365,20 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 			fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
 			flusher.Flush()
 		}
-	} else {
+	} else if config.GetHunyuanType() == 1 {
 		// 构建 hunyuan 标准版请求
 		request := hunyuan.NewChatStdRequest()
+
+		// 配置块
+		request.StreamModeration = new(bool)
+		*request.StreamModeration = config.GetHunyuanStreamModeration(promptstr)
+		request.Stream = new(bool)
+		*request.Stream = config.GetHunyuanStreamModeration(promptstr)
+		request.TopP = new(float64)
+		*request.TopP = config.GetTopPHunyuan(promptstr)
+		request.Temperature = new(float64)
+		*request.Temperature = config.GetTemperatureHunyuan(promptstr)
+
 		// 添加历史信息
 		for _, hMsg := range history {
 			content := hMsg.Text // 创建新变量
@@ -493,6 +534,191 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 			flusher.Flush()
 
 		}
+	} else if config.GetHunyuanType() == 2 || config.GetHunyuanType() == 3 || config.GetHunyuanType() == 4 || config.GetHunyuanType() == 5 {
+		// 构建 hunyuan 请求
+		request := hunyuan.NewChatCompletionsRequest()
+		// 添加历史信息
+		for _, hMsg := range history {
+			content := hMsg.Text // 创建新变量
+			role := hMsg.Role    // 创建新变量
+			hunyuanMsg := hunyuan.Message{
+				Content: &content, // 引用新变量的地址
+				Role:    &role,    // 引用新变量的地址
+			}
+			request.Messages = append(request.Messages, &hunyuanMsg)
+		}
+
+		// 添加当前用户消息
+		currentUserContent := msg.Text // 创建新变量
+		currentUserRole := msg.Role    // 创建新变量
+		currentUserMsg := hunyuan.Message{
+			Content: &currentUserContent, // 引用新变量的地址
+			Role:    &currentUserRole,    // 引用新变量的地址
+		}
+		request.Messages = append(request.Messages, &currentUserMsg)
+
+		// 获取HunyuanType并设置对应的Model
+		switch config.GetHunyuanType() {
+		case 2:
+			request.Model = new(string)
+			*request.Model = "hunyuan-lite"
+		case 3:
+			request.Model = new(string)
+			*request.Model = "hunyuan-standard"
+		case 4:
+			request.Model = new(string)
+			*request.Model = "hunyuan-standard-256K"
+		case 5:
+			request.Model = new(string)
+			*request.Model = "hunyuan-pro"
+		default:
+			request.Model = new(string)
+			*request.Model = "default-value"
+		}
+		fmtf.Printf("请求的混元模型类型:%v", *request.Model)
+		request.StreamModeration = new(bool)
+		*request.StreamModeration = config.GetHunyuanStreamModeration(promptstr)
+		request.Stream = new(bool)
+		*request.Stream = config.GetHunyuanStreamModeration(promptstr)
+		request.TopP = new(float64)
+		*request.TopP = config.GetTopPHunyuan(promptstr)
+		request.Temperature = new(float64)
+		*request.Temperature = config.GetTemperatureHunyuan(promptstr)
+
+		// 打印请求以进行调试
+		utils.PrintChatCompletionsRequest(request)
+
+		// 发送请求并获取响应
+		response, err := app.Client.ChatCompletions(request)
+		if err != nil {
+			http.Error(w, fmtf.Sprintf("hunyuanapi返回错误: %v", err), http.StatusInternalServerError)
+			return
+		}
+		if !config.GetuseSse(promptstr) {
+			// 解析响应
+			var responseTextBuilder strings.Builder
+			var totalUsage structs.UsageInfo
+			for event := range response.BaseSSEResponse.Events {
+				if event.Err != nil {
+					http.Error(w, fmtf.Sprintf("接收事件时发生错误: %v", event.Err), http.StatusInternalServerError)
+					return
+				}
+
+				// 解析事件数据
+				var eventData map[string]interface{}
+				if err := json.Unmarshal(event.Data, &eventData); err != nil {
+					http.Error(w, fmtf.Sprintf("解析事件数据出错: %v", err), http.StatusInternalServerError)
+					return
+				}
+
+				// 使用extractEventDetails函数提取信息
+				responseText, usageInfo := utils.ExtractEventDetails(eventData)
+				responseTextBuilder.WriteString(responseText)
+				totalUsage.PromptTokens += usageInfo.PromptTokens
+				totalUsage.CompletionTokens += usageInfo.CompletionTokens
+			}
+			// 现在responseTextBuilder中的内容是所有AI助手回复的组合
+			responseText := responseTextBuilder.String()
+
+			assistantMessageID, err := app.addMessage(structs.Message{
+				ConversationID:  msg.ConversationID,
+				ParentMessageID: userMessageID,
+				Text:            responseText,
+				Role:            "assistant",
+			})
+
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+
+			// 构造响应
+			responseMap := map[string]interface{}{
+				"response":       responseText,
+				"conversationId": msg.ConversationID,
+				"messageId":      assistantMessageID,
+				"details": map[string]interface{}{
+					"usage": totalUsage,
+				},
+			}
+
+			json.NewEncoder(w).Encode(responseMap)
+		} else {
+			// 设置SSE相关的响应头部
+			w.Header().Set("Content-Type", "text/event-stream")
+			w.Header().Set("Cache-Control", "no-cache")
+			w.Header().Set("Connection", "keep-alive")
+
+			flusher, ok := w.(http.Flusher)
+			if !ok {
+				http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
+				return
+			}
+
+			var responseTextBuilder strings.Builder
+			var totalUsage structs.UsageInfo
+
+			for event := range response.BaseSSEResponse.Events {
+				if event.Err != nil {
+					fmtf.Fprintf(w, "data: %s\n\n", fmtf.Sprintf("接收事件时发生错误: %v", event.Err))
+					flusher.Flush()
+					continue
+				}
+
+				// 解析事件数据和提取信息
+				var eventData map[string]interface{}
+				if err := json.Unmarshal(event.Data, &eventData); err != nil {
+					fmtf.Fprintf(w, "data: %s\n\n", fmtf.Sprintf("解析事件数据出错: %v", err))
+					flusher.Flush()
+					continue
+				}
+
+				responseText, usageInfo := utils.ExtractEventDetails(eventData)
+				responseTextBuilder.WriteString(responseText)
+				totalUsage.PromptTokens += usageInfo.PromptTokens
+				totalUsage.CompletionTokens += usageInfo.CompletionTokens
+
+				// 发送当前事件的响应数据,但不包含assistantMessageID
+				//fmtf.Printf("发送当前事件的响应数据,但不包含assistantMessageID\n")
+				tempResponseMap := map[string]interface{}{
+					"response":       responseText,
+					"conversationId": msg.ConversationID,
+					"details": map[string]interface{}{
+						"usage": usageInfo,
+					},
+				}
+				tempResponseJSON, _ := json.Marshal(tempResponseMap)
+				fmtf.Fprintf(w, "data: %s\n\n", string(tempResponseJSON))
+				flusher.Flush()
+			}
+
+			// 处理完所有事件后,生成并发送包含assistantMessageID的最终响应
+			responseText := responseTextBuilder.String()
+			fmtf.Printf("处理完所有事件后,生成并发送包含assistantMessageID的最终响应:%v\n", responseText)
+			assistantMessageID, err := app.addMessage(structs.Message{
+				ConversationID:  msg.ConversationID,
+				ParentMessageID: userMessageID,
+				Text:            responseText,
+				Role:            "assistant",
+			})
+
+			if err != nil {
+				http.Error(w, err.Error(), http.StatusInternalServerError)
+				return
+			}
+
+			finalResponseMap := map[string]interface{}{
+				"response":       responseText,
+				"conversationId": msg.ConversationID,
+				"messageId":      assistantMessageID,
+				"details": map[string]interface{}{
+					"usage": totalUsage,
+				},
+			}
+			finalResponseJSON, _ := json.Marshal(finalResponseMap)
+			fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
+			flusher.Flush()
+		}
 	}
 
 }
diff --git a/applogic/rwkv.go b/applogic/rwkv.go
index acc3af3..543fd90 100644
--- a/applogic/rwkv.go
+++ b/applogic/rwkv.go
@@ -128,7 +128,7 @@ func (app *App) ChatHandlerRwkv(w http.ResponseWriter, r *http.Request) {
 			}
 		} else {
 			// 只获取系统提示词
-			systemMessage, err := prompt.FindFirstSystemMessage(history)
+			systemMessage, err := prompt.GetFirstSystemMessageStruct(promptstr)
 			if err != nil {
 				fmt.Println("Error:", err)
 			} else {
@@ -162,25 +162,32 @@ func (app *App) ChatHandlerRwkv(w http.ResponseWriter, r *http.Request) {
 
 			// 处理增强QA逻辑
 			if config.GetEnhancedQA(promptstr) {
-				// 确保系统历史与用户或助手历史数量一致,如果不足,则补足空的历史记录
-				// 因为最后一个成员让给当前QA,所以-1
-				if len(systemHistory)-2 > len(userHistory) {
-					difference := len(systemHistory) - len(userHistory)
+				systemHistory, err := prompt.GetMessagesExcludingSystem(promptstr)
+				if err != nil {
+					fmt.Printf("Error getting system history: %v\n", err)
+					return
+				}
+
+				// 计算需要补足的历史记录数量
+				neededHistoryCount := len(systemHistory) - 2 // 最后两条留给当前QA处理
+				if neededHistoryCount > len(userHistory) {
+					// 补足用户或助手历史
+					difference := neededHistoryCount - len(userHistory)
 					for i := 0; i < difference; i++ {
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
-						userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						if i%2 != 0 {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
+						} else {
+							userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+						}
 					}
 				}
 
-				// 如果系统历史中只有一个成员,跳过覆盖逻辑,留给后续处理
-				if len(systemHistory) > 1 {
-					// 将系统历史(除最后2个成员外)附加到相应的用户或助手历史上,采用倒序方式处理最近的记录
-					for i := 0; i < len(systemHistory)-2; i++ {
-						sysMsg := systemHistory[i]
-						index := len(userHistory) - len(systemHistory) + i
-						if index >= 0 && index < len(userHistory) && (userHistory[index].Role == "user" || userHistory[index].Role == "assistant") {
-							userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
-						}
+				// 附加系统历史到用户或助手历史,除了最后两条
+				for i := 0; i < len(systemHistory)-2; i++ {
+					sysMsg := systemHistory[i]
+					index := len(userHistory) - neededHistoryCount + i
+					if index >= 0 && index < len(userHistory) {
+						userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
 					}
 				}
 			} else {
diff --git a/config/config.go b/config/config.go
index a7368bc..c87ae21 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1229,6 +1229,10 @@ func getRwkvMaxTokensInternal(options ...string) int {
 		return getRwkvMaxTokensInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if maxTokens == 0 {
+		return getRwkvMaxTokensInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return maxTokens
 }
 
@@ -2738,3 +2742,99 @@ func getGroupHintWordsInternal(options ...string) []string {
 
 	return hintWords
 }
+
+// 获取HunyuanStreamModeration值
+func GetHunyuanStreamModeration(options ...string) bool {
+	mu.Lock()
+	defer mu.Unlock()
+	return getHunyuanStreamModerationInternal(options...)
+}
+
+// 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getHunyuanStreamModerationInternal(options ...string) bool {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.HunyuanStreamModeration
+		}
+		return false
+	}
+
+	basename := options[0]
+	valueInterface, err := prompt.GetSettingFromFilename(basename, "HunyuanStreamModeration")
+	if err != nil {
+		log.Println("Error retrieving HunyuanStreamModeration:", err)
+		return getHunyuanStreamModerationInternal()
+	}
+
+	value, ok := valueInterface.(bool)
+	if !ok || !value {
+		log.Println("Fetching default HunyuanStreamModeration")
+		return getHunyuanStreamModerationInternal()
+	}
+
+	return value
+}
+
+// 获取TopPHunyuan值
+func GetTopPHunyuan(options ...string) float64 {
+	mu.Lock()
+	defer mu.Unlock()
+	return getTopPHunyuanInternal(options...)
+}
+
+// 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTopPHunyuanInternal(options ...string) float64 {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TopPHunyuan
+		}
+		return 0.0
+	}
+
+	basename := options[0]
+	valueInterface, err := prompt.GetSettingFromFilename(basename, "TopPHunyuan")
+	if err != nil {
+		log.Println("Error retrieving TopPHunyuan:", err)
+		return getTopPHunyuanInternal()
+	}
+
+	value, ok := valueInterface.(float64)
+	if !ok || value == 0.0 {
+		log.Println("Fetching default TopPHunyuan")
+		return getTopPHunyuanInternal()
+	}
+
+	return value
+}
+
+// 获取TemperatureHunyuan值
+func GetTemperatureHunyuan(options ...string) float64 {
+	mu.Lock()
+	defer mu.Unlock()
+	return getTemperatureHunyuanInternal(options...)
+}
+
+// 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getTemperatureHunyuanInternal(options ...string) float64 {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.TemperatureHunyuan
+		}
+		return 0.0
+	}
+
+	basename := options[0]
+	valueInterface, err := prompt.GetSettingFromFilename(basename, "TemperatureHunyuan")
+	if err != nil {
+		log.Println("Error retrieving TemperatureHunyuan:", err)
+		return getTemperatureHunyuanInternal()
+	}
+
+	value, ok := valueInterface.(float64)
+	if !ok || value == 0.0 {
+		log.Println("Fetching default TemperatureHunyuan")
+		return getTemperatureHunyuanInternal()
+	}
+
+	return value
+}
diff --git a/hunyuan/client.go b/hunyuan/client.go
index 45501b1..e1c9bc0 100644
--- a/hunyuan/client.go
+++ b/hunyuan/client.go
@@ -45,6 +45,90 @@ func NewClient(credential common.CredentialIface, region string, clientProfile *
 	return
 }
 
+func NewChatCompletionsRequest() (request *ChatCompletionsRequest) {
+	request = &ChatCompletionsRequest{
+		BaseRequest: &tchttp.BaseRequest{},
+	}
+
+	request.Init().WithApiInfo("hunyuan", APIVersion, "ChatCompletions")
+
+	return
+}
+
+func NewChatCompletionsResponse() (response *ChatCompletionsResponse) {
+	response = &ChatCompletionsResponse{}
+	return
+
+}
+
+// ChatCompletions
+// 腾讯混元大模型是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口支持流式或非流式调用,当使用流式调用时为 SSE 协议。
+//
+//  1. 本接口暂不支持返回图片内容。
+//
+//  2. 默认每种模型单账号限制并发数为 5 路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//
+//  3. 请使用 SDK 调用本接口,每种开发语言的 SDK Git 仓库 examples/hunyuan/v20230901/ 目录下有提供示例供参考。SDK 链接在文档下方 “**开发者资源 - SDK**” 部分提供。
+//
+// 可能返回的错误码:
+//
+//	FAILEDOPERATION_ENGINEREQUESTTIMEOUT = "FailedOperation.EngineRequestTimeout"
+//	FAILEDOPERATION_ENGINESERVERERROR = "FailedOperation.EngineServerError"
+//	FAILEDOPERATION_ENGINESERVERLIMITEXCEEDED = "FailedOperation.EngineServerLimitExceeded"
+//	FAILEDOPERATION_FREERESOURCEPACKEXHAUSTED = "FailedOperation.FreeResourcePackExhausted"
+//	FAILEDOPERATION_RESOURCEPACKEXHAUSTED = "FailedOperation.ResourcePackExhausted"
+//	FAILEDOPERATION_SERVICENOTACTIVATED = "FailedOperation.ServiceNotActivated"
+//	FAILEDOPERATION_SERVICESTOP = "FailedOperation.ServiceStop"
+//	FAILEDOPERATION_SERVICESTOPARREARS = "FailedOperation.ServiceStopArrears"
+//	INTERNALERROR = "InternalError"
+//	INVALIDPARAMETER = "InvalidParameter"
+//	INVALIDPARAMETERVALUE = "InvalidParameterValue"
+//	INVALIDPARAMETERVALUE_MODEL = "InvalidParameterValue.Model"
+//	LIMITEXCEEDED = "LimitExceeded"
+func (c *Client) ChatCompletions(request *ChatCompletionsRequest) (response *ChatCompletionsResponse, err error) {
+	return c.ChatCompletionsWithContext(context.Background(), request)
+}
+
+// ChatCompletions
+// 腾讯混元大模型是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口支持流式或非流式调用,当使用流式调用时为 SSE 协议。
+//
+//  1. 本接口暂不支持返回图片内容。
+//
+//  2. 默认每种模型单账号限制并发数为 5 路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//
+//  3. 请使用 SDK 调用本接口,每种开发语言的 SDK Git 仓库 examples/hunyuan/v20230901/ 目录下有提供示例供参考。SDK 链接在文档下方 “**开发者资源 - SDK**” 部分提供。
+//
+// 可能返回的错误码:
+//
+//	FAILEDOPERATION_ENGINEREQUESTTIMEOUT = "FailedOperation.EngineRequestTimeout"
+//	FAILEDOPERATION_ENGINESERVERERROR = "FailedOperation.EngineServerError"
+//	FAILEDOPERATION_ENGINESERVERLIMITEXCEEDED = "FailedOperation.EngineServerLimitExceeded"
+//	FAILEDOPERATION_FREERESOURCEPACKEXHAUSTED = "FailedOperation.FreeResourcePackExhausted"
+//	FAILEDOPERATION_RESOURCEPACKEXHAUSTED = "FailedOperation.ResourcePackExhausted"
+//	FAILEDOPERATION_SERVICENOTACTIVATED = "FailedOperation.ServiceNotActivated"
+//	FAILEDOPERATION_SERVICESTOP = "FailedOperation.ServiceStop"
+//	FAILEDOPERATION_SERVICESTOPARREARS = "FailedOperation.ServiceStopArrears"
+//	INTERNALERROR = "InternalError"
+//	INVALIDPARAMETER = "InvalidParameter"
+//	INVALIDPARAMETERVALUE = "InvalidParameterValue"
+//	INVALIDPARAMETERVALUE_MODEL = "InvalidParameterValue.Model"
+//	LIMITEXCEEDED = "LimitExceeded"
+func (c *Client) ChatCompletionsWithContext(ctx context.Context, request *ChatCompletionsRequest) (response *ChatCompletionsResponse, err error) {
+	if request == nil {
+		request = NewChatCompletionsRequest()
+	}
+
+	if c.GetCredential() == nil {
+		return nil, errors.New("ChatCompletions require credential")
+	}
+
+	request.SetContext(ctx)
+
+	response = NewChatCompletionsResponse()
+	err = c.Send(request, response)
+	return
+}
+
 func NewChatProRequest() (request *ChatProRequest) {
 	request = &ChatProRequest{
 		BaseRequest: &tchttp.BaseRequest{},
@@ -62,13 +146,15 @@ func NewChatProResponse() (response *ChatProResponse) {
 }
 
 // ChatPro
-// 腾讯混元大模型高级版是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口为SSE协议。
+// <span style="font-size:1.5em;">注意:本接口将于 5 月 15 日下线;下线后将不再提供文档指引,接口本身可继续调用,建议使用 [hunyuan](https://cloud.tencent.com/document/api/1729/105701) 接入。</span>
 //
-//	1.本接口暂不支持返回图片内容。
+// 腾讯混元大模型(hunyuan-pro)是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口支持流式或非流式调用,当使用流式调用时为 SSE 协议。
 //
-//	2.默认单账号限制并发数为5路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//  1. 本接口暂不支持返回图片内容。
 //
-//	3.请使用SDK调用本接口 ,SDK GitHub仓库examples/hunyuan/v20230901/目录有提供[参考示例](https://github.com/TencentCloud/tencentcloud-sdk-python/blob/master/examples/hunyuan/v20230901/chat_std.py)。
+//  2. 默认单账号限制并发数为 5 路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//
+//  3. 请使用 SDK 调用本接口,每种开发语言的 SDK Git 仓库 examples/hunyuan/v20230901/ 目录下有提供示例供参考。SDK 链接在文档下方 “**开发者资源 - SDK**” 部分提供。
 //
 // 可能返回的错误码:
 //
@@ -83,19 +169,20 @@ func NewChatProResponse() (response *ChatProResponse) {
 //	INTERNALERROR = "InternalError"
 //	INVALIDPARAMETERVALUE = "InvalidParameterValue"
 //	LIMITEXCEEDED = "LimitExceeded"
-//	UNSUPPORTEDOPERATION_NONWHITELISTACCOUNT = "UnsupportedOperation.NonWhitelistAccount"
 func (c *Client) ChatPro(request *ChatProRequest) (response *ChatProResponse, err error) {
 	return c.ChatProWithContext(context.Background(), request)
 }
 
 // ChatPro
-// 腾讯混元大模型高级版是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口为SSE协议。
+// <span style="font-size:1.5em;">注意:本接口将于 5 月 15 日下线;下线后将不再提供文档指引,接口本身可继续调用,建议使用 [hunyuan](https://cloud.tencent.com/document/api/1729/105701) 接入。</span>
+//
+// 腾讯混元大模型(hunyuan-pro)是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口支持流式或非流式调用,当使用流式调用时为 SSE 协议。
 //
-//	1.本接口暂不支持返回图片内容。
+//  1. 本接口暂不支持返回图片内容。
 //
-//	2.默认单账号限制并发数为5路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//  2. 默认单账号限制并发数为 5 路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
 //
-//	3.请使用SDK调用本接口 ,SDK GitHub仓库examples/hunyuan/v20230901/目录有提供[参考示例](https://github.com/TencentCloud/tencentcloud-sdk-python/blob/master/examples/hunyuan/v20230901/chat_std.py)。
+//  3. 请使用 SDK 调用本接口,每种开发语言的 SDK Git 仓库 examples/hunyuan/v20230901/ 目录下有提供示例供参考。SDK 链接在文档下方 “**开发者资源 - SDK**” 部分提供。
 //
 // 可能返回的错误码:
 //
@@ -110,7 +197,6 @@ func (c *Client) ChatPro(request *ChatProRequest) (response *ChatProResponse, er
 //	INTERNALERROR = "InternalError"
 //	INVALIDPARAMETERVALUE = "InvalidParameterValue"
 //	LIMITEXCEEDED = "LimitExceeded"
-//	UNSUPPORTEDOPERATION_NONWHITELISTACCOUNT = "UnsupportedOperation.NonWhitelistAccount"
 func (c *Client) ChatProWithContext(ctx context.Context, request *ChatProRequest) (response *ChatProResponse, err error) {
 	if request == nil {
 		request = NewChatProRequest()
@@ -144,13 +230,15 @@ func NewChatStdResponse() (response *ChatStdResponse) {
 }
 
 // ChatStd
-// 腾讯混元大模型标准版是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口为SSE协议。
+// <span style="font-size:1.5em;">注意:本接口将于 5 月 15 日下线;下线后将不再提供文档指引,接口本身可继续调用,建议使用 [hunyuan](https://cloud.tencent.com/document/api/1729/105701) 接入。</span>
 //
-//	1.本接口暂不支持返回图片内容。
+// 腾讯混元大模型标准版是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口支持流式或非流式调用,当使用流式调用时为 SSE 协议。
 //
-//	2.默认单账号限制并发数为5路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//  1. 本接口暂不支持返回图片内容。
 //
-//	3.请使用SDK调用本接口 ,SDK GitHub仓库examples/hunyuan/v20230901/目录有提供[参考示例](https://github.com/TencentCloud/tencentcloud-sdk-python/blob/master/examples/hunyuan/v20230901/chat_std.py)。
+//  2. 默认单账号限制并发数为 5 路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//
+//  3. 请使用 SDK 调用本接口,每种开发语言的 SDK Git 仓库 examples/hunyuan/v20230901/ 目录下有提供示例供参考。SDK 链接在文档下方 “**开发者资源 - SDK**” 部分提供。
 //
 // 可能返回的错误码:
 //
@@ -166,19 +254,20 @@ func NewChatStdResponse() (response *ChatStdResponse) {
 //	INVALIDPARAMETER = "InvalidParameter"
 //	INVALIDPARAMETERVALUE = "InvalidParameterValue"
 //	LIMITEXCEEDED = "LimitExceeded"
-//	UNSUPPORTEDOPERATION_NONWHITELISTACCOUNT = "UnsupportedOperation.NonWhitelistAccount"
 func (c *Client) ChatStd(request *ChatStdRequest) (response *ChatStdResponse, err error) {
 	return c.ChatStdWithContext(context.Background(), request)
 }
 
 // ChatStd
-// 腾讯混元大模型标准版是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口为SSE协议。
+// <span style="font-size:1.5em;">注意:本接口将于 5 月 15 日下线;下线后将不再提供文档指引,接口本身可继续调用,建议使用 [hunyuan](https://cloud.tencent.com/document/api/1729/105701) 接入。</span>
+//
+// 腾讯混元大模型标准版是由腾讯研发的大语言模型,具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力。本接口支持流式或非流式调用,当使用流式调用时为 SSE 协议。
 //
-//	1.本接口暂不支持返回图片内容。
+//  1. 本接口暂不支持返回图片内容。
 //
-//	2.默认单账号限制并发数为5路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
+//  2. 默认单账号限制并发数为 5 路,如您有提高并发限制的需求请 [联系我们](https://cloud.tencent.com/act/event/Online_service) 。
 //
-//	3.请使用SDK调用本接口 ,SDK GitHub仓库examples/hunyuan/v20230901/目录有提供[参考示例](https://github.com/TencentCloud/tencentcloud-sdk-python/blob/master/examples/hunyuan/v20230901/chat_std.py)。
+//  3. 请使用 SDK 调用本接口,每种开发语言的 SDK Git 仓库 examples/hunyuan/v20230901/ 目录下有提供示例供参考。SDK 链接在文档下方 “**开发者资源 - SDK**” 部分提供。
 //
 // 可能返回的错误码:
 //
@@ -194,7 +283,6 @@ func (c *Client) ChatStd(request *ChatStdRequest) (response *ChatStdResponse, er
 //	INVALIDPARAMETER = "InvalidParameter"
 //	INVALIDPARAMETERVALUE = "InvalidParameterValue"
 //	LIMITEXCEEDED = "LimitExceeded"
-//	UNSUPPORTEDOPERATION_NONWHITELISTACCOUNT = "UnsupportedOperation.NonWhitelistAccount"
 func (c *Client) ChatStdWithContext(ctx context.Context, request *ChatStdRequest) (response *ChatStdResponse, err error) {
 	if request == nil {
 		request = NewChatStdRequest()
@@ -230,7 +318,7 @@ func NewGetEmbeddingResponse() (response *GetEmbeddingResponse) {
 }
 
 // GetEmbedding
-// 腾讯混元-Embedding接口,可以将文本转化为高质量的向量数据。
+// 腾讯混元 Embedding 接口,可以将文本转化为高质量的向量数据。
 //
 // 可能返回的错误码:
 //
@@ -243,7 +331,7 @@ func (c *Client) GetEmbedding(request *GetEmbeddingRequest) (response *GetEmbedd
 }
 
 // GetEmbedding
-// 腾讯混元-Embedding接口,可以将文本转化为高质量的向量数据。
+// 腾讯混元 Embedding 接口,可以将文本转化为高质量的向量数据。
 //
 // 可能返回的错误码:
 //
@@ -316,3 +404,127 @@ func (c *Client) GetTokenCountWithContext(ctx context.Context, request *GetToken
 	err = c.Send(request, response)
 	return
 }
+
+func NewQueryHunyuanImageJobRequest() (request *QueryHunyuanImageJobRequest) {
+	request = &QueryHunyuanImageJobRequest{
+		BaseRequest: &tchttp.BaseRequest{},
+	}
+
+	request.Init().WithApiInfo("hunyuan", APIVersion, "QueryHunyuanImageJob")
+
+	return
+}
+
+func NewQueryHunyuanImageJobResponse() (response *QueryHunyuanImageJobResponse) {
+	response = &QueryHunyuanImageJobResponse{
+		BaseResponse: &tchttp.BaseResponse{},
+	}
+	return
+
+}
+
+// QueryHunyuanImageJob
+// 混元生图接口基于混元大模型,将根据输入的文本描述,智能生成与之相关的结果图。分为提交任务和查询任务2个接口。
+//
+// 提交任务:输入文本等,提交一个混元生图异步任务,获得任务 ID。
+//
+// 查询任务:根据任务 ID 查询任务的处理状态、处理结果,任务处理完成后可获得生成图像结果。
+//
+// 并发任务数(并发)说明:并发任务数指能同时处理的任务数量。混元生图默认提供1个并发任务数,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后才能开始处理下一个任务。
+//
+// 可能返回的错误码:
+//
+//	FAILEDOPERATION = "FailedOperation"
+func (c *Client) QueryHunyuanImageJob(request *QueryHunyuanImageJobRequest) (response *QueryHunyuanImageJobResponse, err error) {
+	return c.QueryHunyuanImageJobWithContext(context.Background(), request)
+}
+
+// QueryHunyuanImageJob
+// 混元生图接口基于混元大模型,将根据输入的文本描述,智能生成与之相关的结果图。分为提交任务和查询任务2个接口。
+//
+// 提交任务:输入文本等,提交一个混元生图异步任务,获得任务 ID。
+//
+// 查询任务:根据任务 ID 查询任务的处理状态、处理结果,任务处理完成后可获得生成图像结果。
+//
+// 并发任务数(并发)说明:并发任务数指能同时处理的任务数量。混元生图默认提供1个并发任务数,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后才能开始处理下一个任务。
+//
+// 可能返回的错误码:
+//
+//	FAILEDOPERATION = "FailedOperation"
+func (c *Client) QueryHunyuanImageJobWithContext(ctx context.Context, request *QueryHunyuanImageJobRequest) (response *QueryHunyuanImageJobResponse, err error) {
+	if request == nil {
+		request = NewQueryHunyuanImageJobRequest()
+	}
+
+	if c.GetCredential() == nil {
+		return nil, errors.New("QueryHunyuanImageJob require credential")
+	}
+
+	request.SetContext(ctx)
+
+	response = NewQueryHunyuanImageJobResponse()
+	err = c.Send(request, response)
+	return
+}
+
+func NewSubmitHunyuanImageJobRequest() (request *SubmitHunyuanImageJobRequest) {
+	request = &SubmitHunyuanImageJobRequest{
+		BaseRequest: &tchttp.BaseRequest{},
+	}
+
+	request.Init().WithApiInfo("hunyuan", APIVersion, "SubmitHunyuanImageJob")
+
+	return
+}
+
+func NewSubmitHunyuanImageJobResponse() (response *SubmitHunyuanImageJobResponse) {
+	response = &SubmitHunyuanImageJobResponse{
+		BaseResponse: &tchttp.BaseResponse{},
+	}
+	return
+
+}
+
+// SubmitHunyuanImageJob
+// 混元生图接口基于混元大模型,将根据输入的文本描述,智能生成与之相关的结果图。分为提交任务和查询任务2个接口。
+//
+// 提交任务:输入文本等,提交一个混元生图异步任务,获得任务 ID。
+//
+// 查询任务:根据任务 ID 查询任务的处理状态、处理结果,任务处理完成后可获得生成图像结果。
+//
+// 并发任务数(并发)说明:并发任务数指能同时处理的任务数量。混元生图默认提供1个并发任务数,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后才能开始处理下一个任务。
+//
+// 可能返回的错误码:
+//
+//	FAILEDOPERATION = "FailedOperation"
+func (c *Client) SubmitHunyuanImageJob(request *SubmitHunyuanImageJobRequest) (response *SubmitHunyuanImageJobResponse, err error) {
+	return c.SubmitHunyuanImageJobWithContext(context.Background(), request)
+}
+
+// SubmitHunyuanImageJob
+// 混元生图接口基于混元大模型,将根据输入的文本描述,智能生成与之相关的结果图。分为提交任务和查询任务2个接口。
+//
+// 提交任务:输入文本等,提交一个混元生图异步任务,获得任务 ID。
+//
+// 查询任务:根据任务 ID 查询任务的处理状态、处理结果,任务处理完成后可获得生成图像结果。
+//
+// 并发任务数(并发)说明:并发任务数指能同时处理的任务数量。混元生图默认提供1个并发任务数,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后才能开始处理下一个任务。
+//
+// 可能返回的错误码:
+//
+//	FAILEDOPERATION = "FailedOperation"
+func (c *Client) SubmitHunyuanImageJobWithContext(ctx context.Context, request *SubmitHunyuanImageJobRequest) (response *SubmitHunyuanImageJobResponse, err error) {
+	if request == nil {
+		request = NewSubmitHunyuanImageJobRequest()
+	}
+
+	if c.GetCredential() == nil {
+		return nil, errors.New("SubmitHunyuanImageJob require credential")
+	}
+
+	request.SetContext(ctx)
+
+	response = NewSubmitHunyuanImageJobResponse()
+	err = c.Send(request, response)
+	return
+}
diff --git a/hunyuan/errors.go b/hunyuan/errors.go
index 6bd7ab4..d284c66 100644
--- a/hunyuan/errors.go
+++ b/hunyuan/errors.go
@@ -53,9 +53,9 @@ const (
 	// 参数取值错误。
 	INVALIDPARAMETERVALUE = "InvalidParameterValue"
 
+	// 模型不存在。
+	INVALIDPARAMETERVALUE_MODEL = "InvalidParameterValue.Model"
+
 	// 超过配额限制。
 	LIMITEXCEEDED = "LimitExceeded"
-
-	// 非白名单帐号,请前往控制台申请试用。
-	UNSUPPORTEDOPERATION_NONWHITELISTACCOUNT = "UnsupportedOperation.NonWhitelistAccount"
 )
diff --git a/hunyuan/models.go b/hunyuan/models.go
index 82e3e97..0f9a653 100644
--- a/hunyuan/models.go
+++ b/hunyuan/models.go
@@ -20,26 +20,225 @@ import (
 	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/json"
 )
 
+// Predefined struct for user
+type ChatCompletionsRequestParams struct {
+	// 模型名称,可选值包括 hunyuan-lite、hunyuan-standard、hunyuan-standard-256K、hunyuan-pro。
+	// 各模型介绍请阅读 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 中的说明。
+	//
+	// 注意:
+	// 不同的模型计费不同,请根据 [购买指南](https://cloud.tencent.com/document/product/1729/97731) 按需调用。
+	Model *string `json:"Model,omitnil,omitempty" name:"Model"`
+
+	// 聊天上下文信息。
+	// 说明:
+	// 1. 长度最多为 40,按对话时间从旧到新在数组中排列。
+	// 2. Message.Role 可选值:system、user、assistant。
+	// 其中,system 角色可选,如存在则必须位于列表的最开始。user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[system(可选) user assistant user assistant user ...]。
+	// 3. Messages 中 Content 总长度不能超过模型输入长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。
+	Messages []*Message `json:"Messages,omitnil,omitempty" name:"Messages"`
+
+	// 流式调用开关。
+	// 说明:
+	// 1. 未传值时默认为非流式调用(false)。
+	// 2. 流式调用时以 SSE 协议增量返回结果(返回值取 Choices[n].Delta 中的值,需要拼接增量数据才能获得完整结果)。
+	// 3. 非流式调用时:
+	// 调用方式与普通 HTTP 请求无异。
+	// 接口响应耗时较长,**如需更低时延建议设置为 true**。
+	// 只返回一次最终结果(返回值取 Choices[n].Message 中的值)。
+	//
+	// 注意:
+	// 通过 SDK 调用时,流式和非流式调用需用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。
+	Stream *bool `json:"Stream,omitnil,omitempty" name:"Stream"`
+
+	// 流式输出审核开关。
+	// 说明:
+	// 1. 当使用流式输出(Stream 字段值为 true)时,该字段生效。
+	// 2. 输出审核有流式和同步两种模式,**流式模式首包响应更快**。未传值时默认为流式模式(true)。
+	// 3. 如果值为 true,将对输出内容进行分段审核,审核通过的内容流式输出返回。如果出现审核不过,响应中的 FinishReason 值为 sensitive。
+	// 4. 如果值为 false,则不使用流式输出审核,需要审核完所有输出内容后再返回结果。
+	//
+	// 注意:
+	// 当选择流式输出审核时,可能会出现部分内容已输出,但中间某一段响应中的 FinishReason 值为 sensitive,此时说明安全审核未通过。如果业务场景有实时文字上屏的需求,需要自行撤回已上屏的内容,并建议自定义替换为一条提示语,如 “这个问题我不方便回答,不如我们换个话题试试”,以保障终端体验。
+	StreamModeration *bool `json:"StreamModeration,omitnil,omitempty" name:"StreamModeration"`
+
+	// 说明:
+	// 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。
+	// 2. 默认 1.0,取值区间为 [0.0, 1.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	TopP *float64 `json:"TopP,omitnil,omitempty" name:"TopP"`
+
+	// 说明:
+	// 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
+	// 2. 默认 1.0,取值区间为 [0.0, 2.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	Temperature *float64 `json:"Temperature,omitnil,omitempty" name:"Temperature"`
+}
+
+type ChatCompletionsRequest struct {
+	*tchttp.BaseRequest
+
+	// 模型名称,可选值包括 hunyuan-lite、hunyuan-standard、hunyuan-standard-256K、hunyuan-pro。
+	// 各模型介绍请阅读 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 中的说明。
+	//
+	// 注意:
+	// 不同的模型计费不同,请根据 [购买指南](https://cloud.tencent.com/document/product/1729/97731) 按需调用。
+	Model *string `json:"Model,omitnil,omitempty" name:"Model"`
+
+	// 聊天上下文信息。
+	// 说明:
+	// 1. 长度最多为 40,按对话时间从旧到新在数组中排列。
+	// 2. Message.Role 可选值:system、user、assistant。
+	// 其中,system 角色可选,如存在则必须位于列表的最开始。user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[system(可选) user assistant user assistant user ...]。
+	// 3. Messages 中 Content 总长度不能超过模型输入长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。
+	Messages []*Message `json:"Messages,omitnil,omitempty" name:"Messages"`
+
+	// 流式调用开关。
+	// 说明:
+	// 1. 未传值时默认为非流式调用(false)。
+	// 2. 流式调用时以 SSE 协议增量返回结果(返回值取 Choices[n].Delta 中的值,需要拼接增量数据才能获得完整结果)。
+	// 3. 非流式调用时:
+	// 调用方式与普通 HTTP 请求无异。
+	// 接口响应耗时较长,**如需更低时延建议设置为 true**。
+	// 只返回一次最终结果(返回值取 Choices[n].Message 中的值)。
+	//
+	// 注意:
+	// 通过 SDK 调用时,流式和非流式调用需用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。
+	Stream *bool `json:"Stream,omitnil,omitempty" name:"Stream"`
+
+	// 流式输出审核开关。
+	// 说明:
+	// 1. 当使用流式输出(Stream 字段值为 true)时,该字段生效。
+	// 2. 输出审核有流式和同步两种模式,**流式模式首包响应更快**。未传值时默认为流式模式(true)。
+	// 3. 如果值为 true,将对输出内容进行分段审核,审核通过的内容流式输出返回。如果出现审核不过,响应中的 FinishReason 值为 sensitive。
+	// 4. 如果值为 false,则不使用流式输出审核,需要审核完所有输出内容后再返回结果。
+	//
+	// 注意:
+	// 当选择流式输出审核时,可能会出现部分内容已输出,但中间某一段响应中的 FinishReason 值为 sensitive,此时说明安全审核未通过。如果业务场景有实时文字上屏的需求,需要自行撤回已上屏的内容,并建议自定义替换为一条提示语,如 “这个问题我不方便回答,不如我们换个话题试试”,以保障终端体验。
+	StreamModeration *bool `json:"StreamModeration,omitnil,omitempty" name:"StreamModeration"`
+
+	// 说明:
+	// 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。
+	// 2. 默认 1.0,取值区间为 [0.0, 1.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	TopP *float64 `json:"TopP,omitnil,omitempty" name:"TopP"`
+
+	// 说明:
+	// 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
+	// 2. 默认 1.0,取值区间为 [0.0, 2.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	Temperature *float64 `json:"Temperature,omitnil,omitempty" name:"Temperature"`
+}
+
+func (r *ChatCompletionsRequest) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *ChatCompletionsRequest) FromJsonString(s string) error {
+	f := make(map[string]interface{})
+	if err := json.Unmarshal([]byte(s), &f); err != nil {
+		return err
+	}
+	delete(f, "Model")
+	delete(f, "Messages")
+	delete(f, "Stream")
+	delete(f, "StreamModeration")
+	delete(f, "TopP")
+	delete(f, "Temperature")
+	if len(f) > 0 {
+		return tcerr.NewTencentCloudSDKError("ClientError.BuildRequestError", "ChatCompletionsRequest has unknown keys!", "")
+	}
+	return json.Unmarshal([]byte(s), &r)
+}
+
+// Predefined struct for user
+type ChatCompletionsResponseParams struct {
+	// Unix 时间戳,单位为秒。
+	Created *int64 `json:"Created,omitnil,omitempty" name:"Created"`
+
+	// Token 统计信息。
+	// 按照总 Token 数量计费。
+	Usage *Usage `json:"Usage,omitnil,omitempty" name:"Usage"`
+
+	// 免责声明。
+	Note *string `json:"Note,omitnil,omitempty" name:"Note"`
+
+	// 本轮对话的 ID。
+	Id *string `json:"Id,omitnil,omitempty" name:"Id"`
+
+	// 回复内容。
+	Choices []*Choice `json:"Choices,omitnil,omitempty" name:"Choices"`
+
+	// 错误信息。
+	// 如果流式返回中服务处理异常,返回该错误信息。
+	// 注意:此字段可能返回 null,表示取不到有效值。
+	ErrorMsg *ErrorMsg `json:"ErrorMsg,omitnil,omitempty" name:"ErrorMsg"`
+
+	// 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。本接口为流式响应接口,当请求成功时,RequestId 会被放在 HTTP 响应的 Header "X-TC-RequestId" 中。
+	RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
+}
+
+type ChatCompletionsResponse struct {
+	tchttp.BaseSSEResponse `json:"-"`
+	Response               *ChatCompletionsResponseParams `json:"Response"`
+}
+
+func (r *ChatCompletionsResponse) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *ChatCompletionsResponse) FromJsonString(s string) error {
+	return json.Unmarshal([]byte(s), &r)
+}
+
 // Predefined struct for user
 type ChatProRequestParams struct {
 	// 聊天上下文信息。
 	// 说明:
-	// 1.长度最多为40, 按对话时间从旧到新在数组中排列。
-	// 2.Message的Role当前可选值:system、user、assistant,其中,system角色是可选的,如果存在,必须位于列表的最开始。user和assistant需要交替出现(一问一答),最后一个为user提问, 且Content不能为空。
-	// 3.Messages中Content总长度不超过16000 token,超过则会截断最前面的内容,只保留尾部内容。建议不超过4000 token。
-	Messages []*Message `json:"Messages,omitnil" name:"Messages"`
+	// 1. 长度最多为 40,按对话时间从旧到新在数组中排列。
+	// 2. Message.Role 可选值:system、user、assistant。
+	// 其中,system 角色可选,如存在则必须位于列表的最开始。user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[system(可选) user assistant user assistant user ...]。
+	// 3. Messages 中 Content 总长度不能超过 hunyuan-pro 模型输入长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。
+	Messages []*Message `json:"Messages,omitnil,omitempty" name:"Messages"`
+
+	// 说明:
+	// 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。
+	// 2. 默认 1.0,取值区间为 [0.0, 1.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	TopP *float64 `json:"TopP,omitnil,omitempty" name:"TopP"`
 
 	// 说明:
-	// 1.影响输出文本的多样性,取值越大,生成文本的多样性越强。
-	// 2.默认1.0,取值区间为[0.0, 1.0]。
-	// 3.非必要不建议使用, 不合理的取值会影响效果。
-	TopP *float64 `json:"TopP,omitnil" name:"TopP"`
+	// 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
+	// 2. 默认 1.0,取值区间为 [0.0, 2.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	Temperature *float64 `json:"Temperature,omitnil,omitempty" name:"Temperature"`
 
+	// 流式调用开关。
 	// 说明:
-	// 1.较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
-	// 2.默认1.0,取值区间为[0.0,2.0]。
-	// 3.非必要不建议使用,不合理的取值会影响效果。
-	Temperature *float64 `json:"Temperature,omitnil" name:"Temperature"`
+	// 1. 未传值时默认为流式调用。
+	// 2. 流式调用时以 SSE 协议增量返回结果。
+	// 3. 非流式调用时接口响应耗时较长,非必要不建议使用。
+	// 4. 非流式调用时只返回一次最终结果,调用方式与普通 HTTP 请求无异。
+	//
+	// 注意:
+	// 通过 SDK 调用时,流式和非流式调用需要用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。
+	Stream *bool `json:"Stream,omitnil,omitempty" name:"Stream"`
+
+	// 流式输出审核开关。
+	// 说明:
+	// 1. 输出审核有流式和同步两种模式,**流式模式首包响应更快**。
+	// 2. 当使用流式输出(Stream 字段值为 true)时,该字段生效。
+	// 3. 如果值为 true,将对输出内容进行分段审核,审核通过的内容流式输出返回。如果出现审核不过,响应中的 FinishReason 值为 sensitive。
+	// 4. 如果未传值或值为 false,则不使用流式输出审核,需要审核完所有输出内容后再返回结果。
+	//
+	// 注意:
+	// 当选择流式输出审核时,可能会出现部分内容已输出,但中间某一段响应中的 FinishReason 值为 sensitive,此时说明安全审核未通过。如果业务场景有实时文字上屏的需求,需要自行撤回已上屏的内容,并建议自定义替换为一条提示语,如 “这个问题我不方便回答,不如我们换个话题试试”,以保障终端体验。
+	StreamModeration *bool `json:"StreamModeration,omitnil,omitempty" name:"StreamModeration"`
 }
 
 type ChatProRequest struct {
@@ -47,22 +246,45 @@ type ChatProRequest struct {
 
 	// 聊天上下文信息。
 	// 说明:
-	// 1.长度最多为40, 按对话时间从旧到新在数组中排列。
-	// 2.Message的Role当前可选值:system、user、assistant,其中,system角色是可选的,如果存在,必须位于列表的最开始。user和assistant需要交替出现(一问一答),最后一个为user提问, 且Content不能为空。
-	// 3.Messages中Content总长度不超过16000 token,超过则会截断最前面的内容,只保留尾部内容。建议不超过4000 token。
-	Messages []*Message `json:"Messages,omitnil" name:"Messages"`
+	// 1. 长度最多为 40,按对话时间从旧到新在数组中排列。
+	// 2. Message.Role 可选值:system、user、assistant。
+	// 其中,system 角色可选,如存在则必须位于列表的最开始。user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[system(可选) user assistant user assistant user ...]。
+	// 3. Messages 中 Content 总长度不能超过 hunyuan-pro 模型输入长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。
+	Messages []*Message `json:"Messages,omitnil,omitempty" name:"Messages"`
+
+	// 说明:
+	// 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。
+	// 2. 默认 1.0,取值区间为 [0.0, 1.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	TopP *float64 `json:"TopP,omitnil,omitempty" name:"TopP"`
 
 	// 说明:
-	// 1.影响输出文本的多样性,取值越大,生成文本的多样性越强。
-	// 2.默认1.0,取值区间为[0.0, 1.0]。
-	// 3.非必要不建议使用, 不合理的取值会影响效果。
-	TopP *float64 `json:"TopP,omitnil" name:"TopP"`
+	// 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
+	// 2. 默认 1.0,取值区间为 [0.0, 2.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	Temperature *float64 `json:"Temperature,omitnil,omitempty" name:"Temperature"`
 
+	// 流式调用开关。
 	// 说明:
-	// 1.较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
-	// 2.默认1.0,取值区间为[0.0,2.0]。
-	// 3.非必要不建议使用,不合理的取值会影响效果。
-	Temperature *float64 `json:"Temperature,omitnil" name:"Temperature"`
+	// 1. 未传值时默认为流式调用。
+	// 2. 流式调用时以 SSE 协议增量返回结果。
+	// 3. 非流式调用时接口响应耗时较长,非必要不建议使用。
+	// 4. 非流式调用时只返回一次最终结果,调用方式与普通 HTTP 请求无异。
+	//
+	// 注意:
+	// 通过 SDK 调用时,流式和非流式调用需要用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。
+	Stream *bool `json:"Stream,omitnil,omitempty" name:"Stream"`
+
+	// 流式输出审核开关。
+	// 说明:
+	// 1. 输出审核有流式和同步两种模式,**流式模式首包响应更快**。
+	// 2. 当使用流式输出(Stream 字段值为 true)时,该字段生效。
+	// 3. 如果值为 true,将对输出内容进行分段审核,审核通过的内容流式输出返回。如果出现审核不过,响应中的 FinishReason 值为 sensitive。
+	// 4. 如果未传值或值为 false,则不使用流式输出审核,需要审核完所有输出内容后再返回结果。
+	//
+	// 注意:
+	// 当选择流式输出审核时,可能会出现部分内容已输出,但中间某一段响应中的 FinishReason 值为 sensitive,此时说明安全审核未通过。如果业务场景有实时文字上屏的需求,需要自行撤回已上屏的内容,并建议自定义替换为一条提示语,如 “这个问题我不方便回答,不如我们换个话题试试”,以保障终端体验。
+	StreamModeration *bool `json:"StreamModeration,omitnil,omitempty" name:"StreamModeration"`
 }
 
 func (r *ChatProRequest) ToJsonString() string {
@@ -80,36 +302,100 @@ func (r *ChatProRequest) FromJsonString(s string) error {
 	delete(f, "Messages")
 	delete(f, "TopP")
 	delete(f, "Temperature")
+	delete(f, "Stream")
+	delete(f, "StreamModeration")
 	if len(f) > 0 {
 		return tcerr.NewTencentCloudSDKError("ClientError.BuildRequestError", "ChatProRequest has unknown keys!", "")
 	}
 	return json.Unmarshal([]byte(s), &r)
 }
 
+// Predefined struct for user
+type ChatProResponseParams struct {
+	// Unix 时间戳,单位为秒。
+	Created *int64 `json:"Created,omitnil,omitempty" name:"Created"`
+
+	// Token 统计信息。
+	// 按照总 Token 数量计费。
+	Usage *Usage `json:"Usage,omitnil,omitempty" name:"Usage"`
+
+	// 免责声明。
+	Note *string `json:"Note,omitnil,omitempty" name:"Note"`
+
+	// 本轮对话的 ID。
+	Id *string `json:"Id,omitnil,omitempty" name:"Id"`
+
+	// 回复内容。
+	Choices []*Choice `json:"Choices,omitnil,omitempty" name:"Choices"`
+
+	// 错误信息。
+	// 如果流式返回中服务处理异常,返回该错误信息。
+	// 注意:此字段可能返回 null,表示取不到有效值。
+	ErrorMsg *ErrorMsg `json:"ErrorMsg,omitnil,omitempty" name:"ErrorMsg"`
+
+	// 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。本接口为流式响应接口,当请求成功时,RequestId 会被放在 HTTP 响应的 Header "X-TC-RequestId" 中。
+	RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
+}
+
 type ChatProResponse struct {
-	tchttp.BaseSSEResponse
+	tchttp.BaseSSEResponse `json:"-"`
+	Response               *ChatProResponseParams `json:"Response"`
+}
+
+func (r *ChatProResponse) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *ChatProResponse) FromJsonString(s string) error {
+	return json.Unmarshal([]byte(s), &r)
 }
 
 // Predefined struct for user
 type ChatStdRequestParams struct {
 	// 聊天上下文信息。
 	// 说明:
-	// 1.长度最多为40, 按对话时间从旧到新在数组中排列。
-	// 2.Message的Role当前可选值:user、assistant,其中,user和assistant需要交替出现(一问一答),最后一个为user提问, 且Content不能为空。
-	// 3.Messages中Content总长度不超过16000 token,超过则会截断最前面的内容,只保留尾部内容。建议不超过4000 token。
-	Messages []*Message `json:"Messages,omitnil" name:"Messages"`
+	// 1. 长度最多为 40,按对话时间从旧到新在数组中排列。
+	// 2. Message 的 Role 当前可选值:user、assistant。
+	// 其中,user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[user assistant user assistant user ...]。
+	// 3. Messages 中 Content 总长度不能超过 hunyuan-standard 模型输入长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。
+	Messages []*Message `json:"Messages,omitnil,omitempty" name:"Messages"`
+
+	// 说明:
+	// 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。
+	// 2. 默认 1.0,取值区间为 [0.0, 1.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	TopP *float64 `json:"TopP,omitnil,omitempty" name:"TopP"`
 
 	// 说明:
-	// 1.影响输出文本的多样性,取值越大,生成文本的多样性越强。
-	// 2.默认1.0,取值区间为[0.0, 1.0]。
-	// 3.非必要不建议使用, 不合理的取值会影响效果。
-	TopP *float64 `json:"TopP,omitnil" name:"TopP"`
+	// 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
+	// 2. 默认 1.0,取值区间为 [0.0, 2.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	Temperature *float64 `json:"Temperature,omitnil,omitempty" name:"Temperature"`
 
+	// 流式调用开关。
 	// 说明:
-	// 1.较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
-	// 2.默认1.0,取值区间为[0.0,2.0]。
-	// 3.非必要不建议使用,不合理的取值会影响效果。
-	Temperature *float64 `json:"Temperature,omitnil" name:"Temperature"`
+	// 1. 未传值时默认为流式调用。
+	// 2. 流式调用时以 SSE 协议增量返回结果。
+	// 3. 非流式调用时接口响应耗时较长,非必要不建议使用。
+	// 4. 非流式调用时只返回一次最终结果,调用方式与普通 HTTP 请求无异。
+	//
+	// 注意:
+	// 通过 SDK 调用时,流式和非流式调用需要用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。
+	Stream *bool `json:"Stream,omitnil,omitempty" name:"Stream"`
+
+	// 流式输出审核开关。
+	// 说明:
+	// 1. 输出审核有流式和同步两种模式,**流式模式首包响应更快**。
+	// 2. 当使用流式输出(Stream 字段值为 true)时,该字段生效。
+	// 3. 如果值为 true,将对输出内容进行分段审核,审核通过的内容流式输出返回。如果出现审核不过,响应中的 FinishReason 值为 sensitive。
+	// 4. 如果未传值或值为 false,则不使用流式输出审核,需要审核完所有输出内容后再返回结果。
+	//
+	// 注意:
+	// 当选择流式输出审核时,可能会出现部分内容已输出,但中间某一段响应中的 FinishReason 值为 sensitive,此时说明安全审核未通过。如果业务场景有实时文字上屏的需求,需要自行撤回已上屏的内容,并建议自定义替换为一条提示语,如 “这个问题我不方便回答,不如我们换个话题试试”,以保障终端体验。
+	StreamModeration *bool `json:"StreamModeration,omitnil,omitempty" name:"StreamModeration"`
 }
 
 type ChatStdRequest struct {
@@ -117,22 +403,45 @@ type ChatStdRequest struct {
 
 	// 聊天上下文信息。
 	// 说明:
-	// 1.长度最多为40, 按对话时间从旧到新在数组中排列。
-	// 2.Message的Role当前可选值:user、assistant,其中,user和assistant需要交替出现(一问一答),最后一个为user提问, 且Content不能为空。
-	// 3.Messages中Content总长度不超过16000 token,超过则会截断最前面的内容,只保留尾部内容。建议不超过4000 token。
-	Messages []*Message `json:"Messages,omitnil" name:"Messages"`
+	// 1. 长度最多为 40,按对话时间从旧到新在数组中排列。
+	// 2. Message 的 Role 当前可选值:user、assistant。
+	// 其中,user 和 assistant 需交替出现(一问一答),以 user 提问开始和结束,且 Content 不能为空。Role 的顺序示例:[user assistant user assistant user ...]。
+	// 3. Messages 中 Content 总长度不能超过 hunyuan-standard 模型输入长度上限(可参考 [产品概述](https://cloud.tencent.com/document/product/1729/104753) 文档),超过则会截断最前面的内容,只保留尾部内容。
+	Messages []*Message `json:"Messages,omitnil,omitempty" name:"Messages"`
+
+	// 说明:
+	// 1. 影响输出文本的多样性,取值越大,生成文本的多样性越强。
+	// 2. 默认 1.0,取值区间为 [0.0, 1.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	TopP *float64 `json:"TopP,omitnil,omitempty" name:"TopP"`
 
 	// 说明:
-	// 1.影响输出文本的多样性,取值越大,生成文本的多样性越强。
-	// 2.默认1.0,取值区间为[0.0, 1.0]。
-	// 3.非必要不建议使用, 不合理的取值会影响效果。
-	TopP *float64 `json:"TopP,omitnil" name:"TopP"`
+	// 1. 较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
+	// 2. 默认 1.0,取值区间为 [0.0, 2.0]。
+	// 3. 非必要不建议使用,不合理的取值会影响效果。
+	Temperature *float64 `json:"Temperature,omitnil,omitempty" name:"Temperature"`
 
+	// 流式调用开关。
 	// 说明:
-	// 1.较高的数值会使输出更加随机,而较低的数值会使其更加集中和确定。
-	// 2.默认1.0,取值区间为[0.0,2.0]。
-	// 3.非必要不建议使用,不合理的取值会影响效果。
-	Temperature *float64 `json:"Temperature,omitnil" name:"Temperature"`
+	// 1. 未传值时默认为流式调用。
+	// 2. 流式调用时以 SSE 协议增量返回结果。
+	// 3. 非流式调用时接口响应耗时较长,非必要不建议使用。
+	// 4. 非流式调用时只返回一次最终结果,调用方式与普通 HTTP 请求无异。
+	//
+	// 注意:
+	// 通过 SDK 调用时,流式和非流式调用需要用**不同的方式**获取返回值,具体参考 SDK 中的注释或示例(在各语言 SDK 代码仓库的 examples/hunyuan/v20230901/ 目录中)。
+	Stream *bool `json:"Stream,omitnil,omitempty" name:"Stream"`
+
+	// 流式输出审核开关。
+	// 说明:
+	// 1. 输出审核有流式和同步两种模式,**流式模式首包响应更快**。
+	// 2. 当使用流式输出(Stream 字段值为 true)时,该字段生效。
+	// 3. 如果值为 true,将对输出内容进行分段审核,审核通过的内容流式输出返回。如果出现审核不过,响应中的 FinishReason 值为 sensitive。
+	// 4. 如果未传值或值为 false,则不使用流式输出审核,需要审核完所有输出内容后再返回结果。
+	//
+	// 注意:
+	// 当选择流式输出审核时,可能会出现部分内容已输出,但中间某一段响应中的 FinishReason 值为 sensitive,此时说明安全审核未通过。如果业务场景有实时文字上屏的需求,需要自行撤回已上屏的内容,并建议自定义替换为一条提示语,如 “这个问题我不方便回答,不如我们换个话题试试”,以保障终端体验。
+	StreamModeration *bool `json:"StreamModeration,omitnil,omitempty" name:"StreamModeration"`
 }
 
 func (r *ChatStdRequest) ToJsonString() string {
@@ -150,75 +459,122 @@ func (r *ChatStdRequest) FromJsonString(s string) error {
 	delete(f, "Messages")
 	delete(f, "TopP")
 	delete(f, "Temperature")
+	delete(f, "Stream")
+	delete(f, "StreamModeration")
 	if len(f) > 0 {
 		return tcerr.NewTencentCloudSDKError("ClientError.BuildRequestError", "ChatStdRequest has unknown keys!", "")
 	}
 	return json.Unmarshal([]byte(s), &r)
 }
 
+// Predefined struct for user
+type ChatStdResponseParams struct {
+	// Unix 时间戳,单位为秒。
+	Created *int64 `json:"Created,omitnil,omitempty" name:"Created"`
+
+	// Token 统计信息。
+	// 按照总 Token 数量计费。
+	Usage *Usage `json:"Usage,omitnil,omitempty" name:"Usage"`
+
+	// 免责声明。
+	Note *string `json:"Note,omitnil,omitempty" name:"Note"`
+
+	// 本轮对话的 ID。
+	Id *string `json:"Id,omitnil,omitempty" name:"Id"`
+
+	// 回复内容。
+	Choices []*Choice `json:"Choices,omitnil,omitempty" name:"Choices"`
+
+	// 错误信息。
+	// 如果流式返回中服务处理异常,返回该错误信息。
+	// 注意:此字段可能返回 null,表示取不到有效值。
+	ErrorMsg *ErrorMsg `json:"ErrorMsg,omitnil,omitempty" name:"ErrorMsg"`
+
+	// 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。本接口为流式响应接口,当请求成功时,RequestId 会被放在 HTTP 响应的 Header "X-TC-RequestId" 中。
+	RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
+}
+
 type ChatStdResponse struct {
-	tchttp.BaseSSEResponse
+	tchttp.BaseSSEResponse `json:"-"`
+	Response               *ChatStdResponseParams `json:"Response"`
+}
+
+func (r *ChatStdResponse) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *ChatStdResponse) FromJsonString(s string) error {
+	return json.Unmarshal([]byte(s), &r)
 }
 
 type Choice struct {
-	// 流式结束标志位,为 stop 则表示尾包。
-	FinishReason *string `json:"FinishReason,omitnil" name:"FinishReason"`
+	// 结束标志位,可能为 stop 或 sensitive。
+	// stop 表示输出正常结束,sensitive 只在开启流式输出审核时会出现,表示安全审核未通过。
+	FinishReason *string `json:"FinishReason,omitnil,omitempty" name:"FinishReason"`
+
+	// 增量返回值,流式调用时使用该字段。
+	// 注意:此字段可能返回 null,表示取不到有效值。
+	Delta *Delta `json:"Delta,omitnil,omitempty" name:"Delta"`
 
-	// 返回值。
-	Delta *Delta `json:"Delta,omitnil" name:"Delta"`
+	// 返回值,非流式调用时使用该字段。
+	// 注意:此字段可能返回 null,表示取不到有效值。
+	Message *Message `json:"Message,omitnil,omitempty" name:"Message"`
 }
 
 type Delta struct {
 	// 角色名称。
-	Role *string `json:"Role,omitnil" name:"Role"`
+	Role *string `json:"Role,omitnil,omitempty" name:"Role"`
 
 	// 内容详情。
-	Content *string `json:"Content,omitnil" name:"Content"`
+	Content *string `json:"Content,omitnil,omitempty" name:"Content"`
 }
 
 type EmbeddingData struct {
 	// embedding 信息。
 	// 注意:此字段可能返回 null,表示取不到有效值。
-	Embedding []*float64 `json:"Embedding,omitnil" name:"Embedding"`
+	Embedding []*float64 `json:"Embedding,omitnil,omitempty" name:"Embedding"`
 
 	// 下标。
 	// 注意:此字段可能返回 null,表示取不到有效值。
-	Index *int64 `json:"Index,omitnil" name:"Index"`
+	Index *int64 `json:"Index,omitnil,omitempty" name:"Index"`
 
 	// embedding
 	// 注意:此字段可能返回 null,表示取不到有效值。
-	Object *string `json:"Object,omitnil" name:"Object"`
+	Object *string `json:"Object,omitnil,omitempty" name:"Object"`
 }
 
 type EmbeddingUsage struct {
-	// 输入Token数。
-	PromptTokens *int64 `json:"PromptTokens,omitnil" name:"PromptTokens"`
+	// 输入 Token 数。
+	PromptTokens *int64 `json:"PromptTokens,omitnil,omitempty" name:"PromptTokens"`
 
-	// 总Token数。
-	TotalTokens *int64 `json:"TotalTokens,omitnil" name:"TotalTokens"`
+	// 总 Token 数。
+	TotalTokens *int64 `json:"TotalTokens,omitnil,omitempty" name:"TotalTokens"`
 }
 
 type ErrorMsg struct {
 	// 错误提示信息。
-	Msg *string `json:"Msg,omitnil" name:"Msg"`
+	Msg *string `json:"Msg,omitnil,omitempty" name:"Msg"`
 
 	// 错误码。
 	// 4000 服务内部异常。
 	// 4001 请求模型超时。
-	Code *int64 `json:"Code,omitnil" name:"Code"`
+	Code *int64 `json:"Code,omitnil,omitempty" name:"Code"`
 }
 
 // Predefined struct for user
 type GetEmbeddingRequestParams struct {
-	// 输入文本。总长度不超过1024 个token, 超过则会截断最后面的内容。
-	Input *string `json:"Input,omitnil" name:"Input"`
+	// 输入文本。总长度不超过 1024 个 Token,超过则会截断最后面的内容。
+	Input *string `json:"Input,omitnil,omitempty" name:"Input"`
 }
 
 type GetEmbeddingRequest struct {
 	*tchttp.BaseRequest
 
-	// 输入文本。总长度不超过1024 个token, 超过则会截断最后面的内容。
-	Input *string `json:"Input,omitnil" name:"Input"`
+	// 输入文本。总长度不超过 1024 个 Token,超过则会截断最后面的内容。
+	Input *string `json:"Input,omitnil,omitempty" name:"Input"`
 }
 
 func (r *GetEmbeddingRequest) ToJsonString() string {
@@ -242,14 +598,14 @@ func (r *GetEmbeddingRequest) FromJsonString(s string) error {
 
 // Predefined struct for user
 type GetEmbeddingResponseParams struct {
-	// 返回的 embedding 信息。
-	Data []*EmbeddingData `json:"Data,omitnil" name:"Data"`
+	// 返回的 Embedding 信息。当前不支持批量,所以数组元素数目为 1。
+	Data []*EmbeddingData `json:"Data,omitnil,omitempty" name:"Data"`
 
-	// token 使用计数,按照总token数量收费。
-	Usage *EmbeddingUsage `json:"Usage,omitnil" name:"Usage"`
+	// Token 使用计数,按照总 Token 数量收费。
+	Usage *EmbeddingUsage `json:"Usage,omitnil,omitempty" name:"Usage"`
 
-	// 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
-	RequestId *string `json:"RequestId,omitnil" name:"RequestId"`
+	// 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。
+	RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
 }
 
 type GetEmbeddingResponse struct {
@@ -271,14 +627,14 @@ func (r *GetEmbeddingResponse) FromJsonString(s string) error {
 // Predefined struct for user
 type GetTokenCountRequestParams struct {
 	// 输入文本
-	Prompt *string `json:"Prompt,omitnil" name:"Prompt"`
+	Prompt *string `json:"Prompt,omitnil,omitempty" name:"Prompt"`
 }
 
 type GetTokenCountRequest struct {
 	*tchttp.BaseRequest
 
 	// 输入文本
-	Prompt *string `json:"Prompt,omitnil" name:"Prompt"`
+	Prompt *string `json:"Prompt,omitnil,omitempty" name:"Prompt"`
 }
 
 func (r *GetTokenCountRequest) ToJsonString() string {
@@ -303,16 +659,16 @@ func (r *GetTokenCountRequest) FromJsonString(s string) error {
 // Predefined struct for user
 type GetTokenCountResponseParams struct {
 	// token计数
-	TokenCount *int64 `json:"TokenCount,omitnil" name:"TokenCount"`
+	TokenCount *int64 `json:"TokenCount,omitnil,omitempty" name:"TokenCount"`
 
 	// 字符计数
-	CharacterCount *int64 `json:"CharacterCount,omitnil" name:"CharacterCount"`
+	CharacterCount *int64 `json:"CharacterCount,omitnil,omitempty" name:"CharacterCount"`
 
 	// 切分后的列表
-	Tokens []*string `json:"Tokens,omitnil" name:"Tokens"`
+	Tokens []*string `json:"Tokens,omitnil,omitempty" name:"Tokens"`
 
-	// 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
-	RequestId *string `json:"RequestId,omitnil" name:"RequestId"`
+	// 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。
+	RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
 }
 
 type GetTokenCountResponse struct {
@@ -333,19 +689,200 @@ func (r *GetTokenCountResponse) FromJsonString(s string) error {
 
 type Message struct {
 	// 角色
-	Role *string `json:"Role,omitnil" name:"Role"`
+	Role *string `json:"Role,omitnil,omitempty" name:"Role"`
+
+	// 文本内容
+	Content *string `json:"Content,omitnil,omitempty" name:"Content"`
+}
+
+// Predefined struct for user
+type QueryHunyuanImageJobRequestParams struct {
+	// 任务 ID。
+	JobId *string `json:"JobId,omitnil,omitempty" name:"JobId"`
+}
+
+type QueryHunyuanImageJobRequest struct {
+	*tchttp.BaseRequest
+
+	// 任务 ID。
+	JobId *string `json:"JobId,omitnil,omitempty" name:"JobId"`
+}
+
+func (r *QueryHunyuanImageJobRequest) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *QueryHunyuanImageJobRequest) FromJsonString(s string) error {
+	f := make(map[string]interface{})
+	if err := json.Unmarshal([]byte(s), &f); err != nil {
+		return err
+	}
+	delete(f, "JobId")
+	if len(f) > 0 {
+		return tcerr.NewTencentCloudSDKError("ClientError.BuildRequestError", "QueryHunyuanImageJobRequest has unknown keys!", "")
+	}
+	return json.Unmarshal([]byte(s), &r)
+}
+
+// Predefined struct for user
+type QueryHunyuanImageJobResponseParams struct {
+	// 当前任务状态码:
+	// 1:等待中、2:运行中、4:处理失败、5:处理完成。
+	JobStatusCode *string `json:"JobStatusCode,omitnil,omitempty" name:"JobStatusCode"`
+
+	// 当前任务状态:排队中、处理中、处理失败或者处理完成。
+	JobStatusMsg *string `json:"JobStatusMsg,omitnil,omitempty" name:"JobStatusMsg"`
+
+	// 任务处理失败错误码。
+	JobErrorCode *string `json:"JobErrorCode,omitnil,omitempty" name:"JobErrorCode"`
+
+	// 任务处理失败错误信息。
+	JobErrorMsg *string `json:"JobErrorMsg,omitnil,omitempty" name:"JobErrorMsg"`
+
+	// 生成图 URL 列表,有效期1小时,请及时保存。
+	ResultImage []*string `json:"ResultImage,omitnil,omitempty" name:"ResultImage"`
+
+	// 结果 detail 数组,Success 代表成功。
+	ResultDetails []*string `json:"ResultDetails,omitnil,omitempty" name:"ResultDetails"`
+
+	// 对应 SubmitTextToImageProJob 接口中 Revise 参数。开启扩写时,返回扩写后的 prompt 文本。 如果关闭扩写,将直接返回原始输入的 prompt。
+	RevisedPrompt []*string `json:"RevisedPrompt,omitnil,omitempty" name:"RevisedPrompt"`
+
+	// 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。
+	RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
+}
 
-	// 消息的内容
-	Content *string `json:"Content,omitnil" name:"Content"`
+type QueryHunyuanImageJobResponse struct {
+	*tchttp.BaseResponse
+	Response *QueryHunyuanImageJobResponseParams `json:"Response"`
+}
+
+func (r *QueryHunyuanImageJobResponse) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *QueryHunyuanImageJobResponse) FromJsonString(s string) error {
+	return json.Unmarshal([]byte(s), &r)
+}
+
+// Predefined struct for user
+type SubmitHunyuanImageJobRequestParams struct {
+	// 文本描述。 算法将根据输入的文本智能生成与之相关的图像。 不能为空,推荐使用中文。最多可传100个 utf-8 字符。
+	Prompt *string `json:"Prompt,omitnil,omitempty" name:"Prompt"`
+
+	// 绘画风格。
+	// 请在 [混元生图风格列表](https://cloud.tencent.com/document/product/1729/105846) 中选择期望的风格,传入风格编号。
+	// 不传默认不指定风格。
+	Style *string `json:"Style,omitnil,omitempty" name:"Style"`
+
+	// 生成图分辨率。
+	// 支持生成以下分辨率的图片:768:768(1:1)、768:1024(3:4)、1024:768(4:3)、1024:1024(1:1)、720:1280(9:16)、1280:720(16:9)、768:1280(3:5)、1280:768(5:3),不传默认使用1024:1024。
+	Resolution *string `json:"Resolution,omitnil,omitempty" name:"Resolution"`
+
+	// 为生成结果图添加显式水印标识的开关,默认为1。
+	// 1:添加。
+	// 0:不添加。
+	// 其他数值:默认按1处理。
+	// 建议您使用显著标识来提示结果图使用了 AI 绘画技术,是 AI 生成的图片。
+	LogoAdd *int64 `json:"LogoAdd,omitnil,omitempty" name:"LogoAdd"`
+
+	// prompt 扩写开关。1为开启,0为关闭,不传默认开启。
+	// 开启扩写后,将自动扩写原始输入的 prompt 并使用扩写后的 prompt 生成图片,返回生成图片结果时将一并返回扩写后的 prompt 文本。
+	// 如果关闭扩写,将直接使用原始输入的 prompt 生成图片。
+	// 建议开启,在多数场景下可提升生成图片效果、丰富生成图片细节。
+	Revise *int64 `json:"Revise,omitnil,omitempty" name:"Revise"`
+}
+
+type SubmitHunyuanImageJobRequest struct {
+	*tchttp.BaseRequest
+
+	// 文本描述。 算法将根据输入的文本智能生成与之相关的图像。 不能为空,推荐使用中文。最多可传100个 utf-8 字符。
+	Prompt *string `json:"Prompt,omitnil,omitempty" name:"Prompt"`
+
+	// 绘画风格。
+	// 请在 [混元生图风格列表](https://cloud.tencent.com/document/product/1729/105846) 中选择期望的风格,传入风格编号。
+	// 不传默认不指定风格。
+	Style *string `json:"Style,omitnil,omitempty" name:"Style"`
+
+	// 生成图分辨率。
+	// 支持生成以下分辨率的图片:768:768(1:1)、768:1024(3:4)、1024:768(4:3)、1024:1024(1:1)、720:1280(9:16)、1280:720(16:9)、768:1280(3:5)、1280:768(5:3),不传默认使用1024:1024。
+	Resolution *string `json:"Resolution,omitnil,omitempty" name:"Resolution"`
+
+	// 为生成结果图添加显式水印标识的开关,默认为1。
+	// 1:添加。
+	// 0:不添加。
+	// 其他数值:默认按1处理。
+	// 建议您使用显著标识来提示结果图使用了 AI 绘画技术,是 AI 生成的图片。
+	LogoAdd *int64 `json:"LogoAdd,omitnil,omitempty" name:"LogoAdd"`
+
+	// prompt 扩写开关。1为开启,0为关闭,不传默认开启。
+	// 开启扩写后,将自动扩写原始输入的 prompt 并使用扩写后的 prompt 生成图片,返回生成图片结果时将一并返回扩写后的 prompt 文本。
+	// 如果关闭扩写,将直接使用原始输入的 prompt 生成图片。
+	// 建议开启,在多数场景下可提升生成图片效果、丰富生成图片细节。
+	Revise *int64 `json:"Revise,omitnil,omitempty" name:"Revise"`
+}
+
+func (r *SubmitHunyuanImageJobRequest) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *SubmitHunyuanImageJobRequest) FromJsonString(s string) error {
+	f := make(map[string]interface{})
+	if err := json.Unmarshal([]byte(s), &f); err != nil {
+		return err
+	}
+	delete(f, "Prompt")
+	delete(f, "Style")
+	delete(f, "Resolution")
+	delete(f, "LogoAdd")
+	delete(f, "Revise")
+	if len(f) > 0 {
+		return tcerr.NewTencentCloudSDKError("ClientError.BuildRequestError", "SubmitHunyuanImageJobRequest has unknown keys!", "")
+	}
+	return json.Unmarshal([]byte(s), &r)
+}
+
+// Predefined struct for user
+type SubmitHunyuanImageJobResponseParams struct {
+	// 任务 ID。
+	JobId *string `json:"JobId,omitnil,omitempty" name:"JobId"`
+
+	// 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。
+	RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
+}
+
+type SubmitHunyuanImageJobResponse struct {
+	*tchttp.BaseResponse
+	Response *SubmitHunyuanImageJobResponseParams `json:"Response"`
+}
+
+func (r *SubmitHunyuanImageJobResponse) ToJsonString() string {
+	b, _ := json.Marshal(r)
+	return string(b)
+}
+
+// FromJsonString It is highly **NOT** recommended to use this function
+// because it has no param check, nor strict type check
+func (r *SubmitHunyuanImageJobResponse) FromJsonString(s string) error {
+	return json.Unmarshal([]byte(s), &r)
 }
 
 type Usage struct {
-	// 输入 token 数量。
-	PromptTokens *int64 `json:"PromptTokens,omitnil" name:"PromptTokens"`
+	// 输入 Token 数量。
+	PromptTokens *int64 `json:"PromptTokens,omitnil,omitempty" name:"PromptTokens"`
 
-	// 输出 token 数量。
-	CompletionTokens *int64 `json:"CompletionTokens,omitnil" name:"CompletionTokens"`
+	// 输出 Token 数量。
+	CompletionTokens *int64 `json:"CompletionTokens,omitnil,omitempty" name:"CompletionTokens"`
 
-	// 总 token 数量。
-	TotalTokens *int64 `json:"TotalTokens,omitnil" name:"TotalTokens"`
+	// 总 Token 数量。
+	TotalTokens *int64 `json:"TotalTokens,omitnil,omitempty" name:"TotalTokens"`
 }
diff --git a/structs/struct.go b/structs/struct.go
index 9e01676..a04e96e 100644
--- a/structs/struct.go
+++ b/structs/struct.go
@@ -264,8 +264,11 @@ type Settings struct {
 	MdPromptKeyboardAtGroup bool     `yaml:"mdPromptKeyboardAtGroup"` // 群内使用md能力模拟PromptKeyboard
 	GroupHintWords          []string `yaml:"groupHintWords"`
 
-	HunyuanType      int `yaml:"hunyuanType"`
-	MaxTokensHunyuan int `yaml:"maxTokensHunyuan"`
+	HunyuanType             int     `yaml:"hunyuanType"`
+	MaxTokensHunyuan        int     `yaml:"maxTokensHunyuan"`
+	HunyuanStreamModeration bool    `yaml:"hunyuanStreamModeration"`
+	TopPHunyuan             float64 `yaml:"topPHunyuan"`
+	TemperatureHunyuan      float64 `yaml:"temperatureHunyuan"`
 
 	WenxinAccessToken     string  `yaml:"wenxinAccessToken"`
 	WenxinApiPath         string  `yaml:"wenxinApiPath"`
diff --git a/template/config_template.go b/template/config_template.go
index 4c559a8..215e99a 100644
--- a/template/config_template.go
+++ b/template/config_template.go
@@ -99,7 +99,10 @@ settings:
   secretKey : ""
   region : ""                                   #留空
   maxTokensHunyuan : 4096                       #最大上下文
-  hunyuanType : 0                               #0=高级版 1=标准版 价格差异10倍
+  hunyuanType : 0                               #0=高级版 1=标准版std 2=hunyuan-lite 3=hunyuan-standard 4=hunyuan-standard-256K 5=hunyuan-pro
+  hunyuanStreamModeration : false               #是否采用流式审核
+  topPHunyuan : 1.0                             #累积概率最高的令牌进行采样的界限
+  temperatureHunyuan : 1.0                      #生成的随机性控制
 
   #文心配置项
   wenxinAccessToken : ""                        #请求百度access_token接口获取到的,有效期一个月,需要自己请求获取
diff --git a/utils/utils.go b/utils/utils.go
index 37f798e..0c57b76 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -70,6 +70,17 @@ func PrintChatStdRequest(request *hunyuan.ChatStdRequest) {
 
 }
 
+func PrintChatCompletionsRequest(request *hunyuan.ChatCompletionsRequest) {
+
+	// 打印Messages
+	for i, msg := range request.Messages {
+		fmtf.Printf("Message %d:\n", i)
+		fmtf.Printf("Content: %s\n", *msg.Content)
+		fmtf.Printf("Role: %s\n", *msg.Role)
+	}
+
+}
+
 // contains 检查一个字符串切片是否包含一个特定的字符串
 func Contains(slice []string, item string) bool {
 	for _, a := range slice {

From d1053df9e9b60c88f20847e1873af8530ef5105e Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Sun, 19 May 2024 14:43:14 +0800
Subject: [PATCH 06/24] Beta120 (#118)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120
---
 applogic/gensokyo.go        | 12 ++----
 config/config.go            | 10 +++++
 main.go                     |  5 +++
 readme.md                   | 28 +++++++-----
 server/server.go            | 45 +++++++++++++++++--
 structs/struct.go           |  1 +
 template/config_template.go |  1 +
 utils/utils.go              | 86 ++++++++++++++++++++++++++++++++-----
 8 files changed, 156 insertions(+), 32 deletions(-)

diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index 60d5a94..eb5c435 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -206,18 +206,14 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
-	// 读取URL参数 "selfid"
-	selfid := r.URL.Query().Get("selfid")
-	if selfid != "" {
-		// 使用 prompt 变量进行后续处理
-		fmt.Printf("收到selfid参数: %s\n", selfid)
-	}
+	// 直接从ob11事件获取selfid
+	selfid := strconv.FormatInt(message.SelfID, 10)
 
 	// 读取URL参数 "api"
 	api := r.URL.Query().Get("api")
-	if selfid != "" {
+	if api != "" {
 		// 使用 prompt 变量进行后续处理
-		fmt.Printf("收到api参数: %s\n", selfid)
+		fmt.Printf("收到api参数: %s\n", api)
 	}
 
 	// 打印日志信息,包括prompt参数
diff --git a/config/config.go b/config/config.go
index c87ae21..5fda48c 100644
--- a/config/config.go
+++ b/config/config.go
@@ -231,6 +231,16 @@ func IPWhiteList() []string {
 	return nil
 }
 
+// 获取HttpPaths
+func GetHttpPaths() []string {
+	mu.Lock()
+	defer mu.Unlock()
+	if instance != nil {
+		return instance.Settings.HttpPaths
+	}
+	return nil
+}
+
 // 获取最大上下文
 func GetMaxTokensHunyuan(options ...string) int {
 	mu.Lock()
diff --git a/main.go b/main.go
index c950854..7de4084 100644
--- a/main.go
+++ b/main.go
@@ -195,6 +195,11 @@ func main() {
 		log.Fatalf("Failed to load blacklist: %v", err)
 	}
 
+	// 判断是否设置多个http地址,获取对应关系
+	if len(config.GetHttpPaths()) > 0 {
+		utils.FetchAndStoreUserIDs()
+	}
+
 	// 启动黑名单文件变动监听
 	go utils.WatchBlacklist(blacklistPath)
 
diff --git a/readme.md b/readme.md
index 6df07f8..f6750d1 100644
--- a/readme.md
+++ b/readme.md
@@ -32,16 +32,6 @@ _✨ 适用于Gensokyo以及Onebotv11的大模型一键端 ✨_
 
 并发环境下的sse内存安全,支持维持多用户同时双向sse传输
 
----
-
-## 效果
-
-![效果图](/pic/3.png)
-
-![效果图](/pic/4.png)
-
----
-
 ## 支持llm平台
 
 腾讯混元
@@ -117,6 +107,14 @@ AhoCorasick算法实现的超高效文本IN-Out替换规则,可大量替换n
 
 支持中间件开发,在gensokyo框架层到gensokyo-llm的http请求之间,可开发中间件实现向量拓展,数据库拓展,动态修改用户问题.
 
+支持反向ws连接,支持同时连接多个onebotv11的http-api
+
+---
+
+## 使用教程
+
+施工中...(部署非常简单,有一定onebotv11机器人部署经验者可参考config.yml注释直接部署出来.)
+
 ---
 
 # API接口调用说明
@@ -285,6 +283,16 @@ exitOnQ需要enhancedPromptChoices=true,其实enhancedPromptChoices最好就是t
 
 promptMarks和switchOnQ、switchOnA在功能上是相同的,都是根据关键字跳转分支,promptMarks先执行,不分轮次不分QA,switchOnQ和switchOnA更具体,区分Q和A,区分轮次,实现细节跳转。
 
+---
+
+## 故事模式效果(QQ开放平台)
+
+![效果图](/pic/3.png)
+
+![效果图](/pic/4.png)
+
+---
+
 ## 已知问题
 
 如果有固定且不需要切换的分支,请设置该yml的promptMarksLength为99999
diff --git a/server/server.go b/server/server.go
index eaa1706..bfcc210 100644
--- a/server/server.go
+++ b/server/server.go
@@ -30,12 +30,49 @@ var upgrader = websocket.Upgrader{
 	},
 }
 
+// 全局变量和互斥锁
+var (
+	selfIDs   []string
+	selfIDsMu sync.Mutex
+)
+
+// AddSelfID 添加一个 ID 到全局切片中
+func AddSelfID(id string) {
+	selfIDsMu.Lock()
+	defer selfIDsMu.Unlock()
+	selfIDs = append(selfIDs, id)
+}
+
+// GetSelfIDs 返回当前保存的所有 ID
+func GetSelfIDs() []string {
+	selfIDsMu.Lock()
+	defer selfIDsMu.Unlock()
+	// 返回切片的副本以防止外部修改
+	copiedIDs := make([]string, len(selfIDs))
+	copy(copiedIDs, selfIDs)
+	return copiedIDs
+}
+
+// IsSelfIDExists 检查一个 ID 是否存在于全局切片中
+func IsSelfIDExists(id string) bool {
+	selfIDsMu.Lock()
+	defer selfIDsMu.Unlock()
+	for _, sid := range selfIDs {
+		if sid == id {
+			return true
+		}
+	}
+	return false
+}
+
 // 用于处理WebSocket连接
 func WsHandler(w http.ResponseWriter, r *http.Request, config *config.Config) {
 	// 从请求头或URL查询参数中提取token
 	tokenFromHeader := r.Header.Get("Authorization")
 	selfID := r.Header.Get("X-Self-ID")
 	fmtf.Printf("接入机器人X-Self-ID[%v]", selfID)
+	// 加入到数组里
+	AddSelfID(selfID)
 	var token string
 	if strings.HasPrefix(tokenFromHeader, "Token ") {
 		token = strings.TrimPrefix(tokenFromHeader, "Token ")
@@ -86,13 +123,13 @@ func WsHandler(w http.ResponseWriter, r *http.Request, config *config.Config) {
 		}
 
 		if messageType == websocket.TextMessage {
-			processWSMessage(p, selfID)
+			processWSMessage(p)
 		}
 	}
 }
 
 // 处理收到的信息
-func processWSMessage(msg []byte, selfid string) {
+func processWSMessage(msg []byte) {
 	var genericMap map[string]interface{}
 	if err := json.Unmarshal(msg, &genericMap); err != nil {
 		log.Printf("Error unmarshalling message to map: %v, Original message: %s\n", err, string(msg))
@@ -131,9 +168,9 @@ func processWSMessage(msg []byte, selfid string) {
 			// 构造请求URL
 			var url string
 			if config.GetLotus() == "" {
-				url = "http://127.0.0.1:" + fmt.Sprint(port) + "/gensokyo?selfid=" + selfid
+				url = "http://127.0.0.1:" + fmt.Sprint(port) + "/gensokyo"
 			} else {
-				url = config.GetLotus() + "/gensokyo?selfid=" + selfid
+				url = config.GetLotus() + "/gensokyo"
 			}
 
 			// 创建POST请求
diff --git a/structs/struct.go b/structs/struct.go
index a04e96e..3c9cebd 100644
--- a/structs/struct.go
+++ b/structs/struct.go
@@ -254,6 +254,7 @@ type Settings struct {
 	Port                    int      `yaml:"port"`
 	SelfPath                string   `yaml:"selfPath"`
 	HttpPath                string   `yaml:"path"`
+	HttpPaths               []string `yaml:"paths"`
 	Lotus                   string   `yaml:"lotus"`
 	PathToken               string   `yaml:"pathToken"`
 	SystemPrompt            []string `yaml:"systemPrompt"`
diff --git a/template/config_template.go b/template/config_template.go
index 215e99a..d258476 100644
--- a/template/config_template.go
+++ b/template/config_template.go
@@ -10,6 +10,7 @@ settings:
   port : 46233                                  #本程序监听端口,支持gensokyo http上报,   请在gensokyo的反向http配置加入 post_url: ["http://127.0.0.1:port/gensokyo"] 
   selfPath : ""                                 #本程序监听地址,不包含http头,请放通port到公网,仅发图场景需要填写,可以是域名,暂不支持https.
   path : "http://123.123.123.123:11111"         #调用gensokyo api的地址,填入 gensokyo 的 正向http地址   http_address: "0.0.0.0:46231"  对应填入 "http://127.0.0.1:46231"
+  paths : []                                    #当要连接多个onebotv11的http正向地址时,多个地址填入这里.
   lotus : ""                                    #当填写另一个gensokyo-llm的http地址时,将请求另一个的conversation端点,实现多个llm不需要多次配置,简化配置,单独使用请忽略留空.例:http://192.168.0.1:12345(包含http头和端口)
   pathToken : ""                                #gensokyo正向http-api的access_token(是onebotv11标准的)
   apiType : 0                                   #0=混元 1=文心(文心平台包含了N种模型...) 2=gpt 3=rwkv 4=通义千问 5=智谱AI
diff --git a/utils/utils.go b/utils/utils.go
index 0c57b76..f543ef5 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -44,6 +44,57 @@ type MessageIDInfo struct {
 var UserIDMessageIDs = make(map[int64][]MessageIDInfo)
 var muUserIDMessageIDs sync.RWMutex // 用于UserIDMessageIDs的读写锁
 
+var (
+	baseURLMap   = make(map[string]string)
+	baseURLMapMu sync.Mutex
+)
+
+// 结构体用于解析 JSON 响应
+type loginInfoResponse struct {
+	Status  string `json:"status"`
+	Retcode int    `json:"retcode"`
+	Data    struct {
+		UserID   int64  `json:"user_id"`
+		Nickname string `json:"nickname"`
+	} `json:"data"`
+}
+
+// 构造 URL 并请求数据
+func FetchAndStoreUserIDs() {
+	httpPaths := config.GetHttpPaths()
+	for _, baseURL := range httpPaths {
+		url := baseURL + "/get_login_info"
+		resp, err := http.Get(url)
+		if err != nil {
+			fmtf.Printf("Error fetching login info from %s: %v", url, err)
+			continue
+		}
+		defer resp.Body.Close()
+
+		var result loginInfoResponse
+		if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
+			fmtf.Printf("Error decoding response from %s: %v", url, err)
+			continue
+		}
+
+		if result.Retcode == 0 && result.Status == "ok" {
+			fmtf.Printf("成功绑定机器人selfid[%v]onebot api baseURL[%v]", result.Data.UserID, baseURL)
+			baseURLMapMu.Lock()
+			useridstr := strconv.FormatInt(result.Data.UserID, 10)
+			baseURLMap[useridstr] = baseURL
+			baseURLMapMu.Unlock()
+		}
+	}
+}
+
+// GetBaseURLByUserID 通过 user_id 获取 baseURL
+func GetBaseURLByUserID(userID string) (string, bool) {
+	baseURLMapMu.Lock()
+	defer baseURLMapMu.Unlock()
+	url, exists := baseURLMap[userID]
+	return url, exists
+}
+
 func GenerateUUID() string {
 	return uuid.New().String()
 }
@@ -158,7 +209,7 @@ func ExtractEventDetails(eventData map[string]interface{}) (string, structs.Usag
 
 func SendGroupMessage(groupID int64, userID int64, message string, selfid string) error {
 	//TODO: 用userid作为了echo,在ws收到回调信息的时候,加入到全局撤回数组,AddMessageID,实现撤回
-	if selfid != "" {
+	if server.IsSelfIDExists(selfid) {
 		// 创建消息结构体
 		msg := map[string]interface{}{
 			"action": "send_group_msg",
@@ -173,8 +224,13 @@ func SendGroupMessage(groupID int64, userID int64, message string, selfid string
 		// 发送消息
 		return server.SendMessageBySelfID(selfid, msg)
 	}
-	// 获取基础URL
-	baseURL := config.GetHttpPath() // 假设config.getHttpPath()返回基础URL
+	var baseURL string
+	if len(config.GetHttpPaths()) > 0 {
+		baseURL, _ = GetBaseURLByUserID(selfid)
+	} else {
+		// 获取基础URL
+		baseURL = config.GetHttpPath() // 假设config.getHttpPath()返回基础URL
+	}
 
 	// 构建完整的URL
 	baseURL = baseURL + "/send_group_msg"
@@ -255,7 +311,7 @@ func SendGroupMessage(groupID int64, userID int64, message string, selfid string
 
 func SendGroupMessageMdPromptKeyboard(groupID int64, userID int64, message string, selfid string, newmsg string, response string, promptstr string) error {
 	//TODO: 用userid作为了echo,在ws收到回调信息的时候,加入到全局撤回数组,AddMessageID,实现反向ws连接时候的撤回
-	if selfid != "" {
+	if server.IsSelfIDExists(selfid) {
 		// 创建消息结构体
 		msg := map[string]interface{}{
 			"action": "send_group_msg",
@@ -493,7 +549,7 @@ func SendGroupMessageMdPromptKeyboard(groupID int64, userID int64, message strin
 }
 
 func SendPrivateMessage(UserID int64, message string, selfid string) error {
-	if selfid != "" {
+	if server.IsSelfIDExists(selfid) {
 		// 创建消息结构体
 		msg := map[string]interface{}{
 			"action": "send_private_msg",
@@ -507,8 +563,13 @@ func SendPrivateMessage(UserID int64, message string, selfid string) error {
 		// 发送消息
 		return server.SendMessageBySelfID(selfid, msg)
 	}
-	// 获取基础URL
-	baseURL := config.GetHttpPath() // 假设config.getHttpPath()返回基础URL
+	var baseURL string
+	if len(config.GetHttpPaths()) > 0 {
+		baseURL, _ = GetBaseURLByUserID(selfid)
+	} else {
+		// 获取基础URL
+		baseURL = config.GetHttpPath() // 假设config.getHttpPath()返回基础URL
+	}
 
 	// 构建完整的URL
 	baseURL = baseURL + "/send_private_msg"
@@ -587,7 +648,7 @@ func SendPrivateMessage(UserID int64, message string, selfid string) error {
 }
 
 func SendPrivateMessageRaw(UserID int64, message string, selfid string) error {
-	if selfid != "" {
+	if server.IsSelfIDExists(selfid) {
 		// 创建消息结构体
 		msg := map[string]interface{}{
 			"action": "send_private_msg",
@@ -601,8 +662,13 @@ func SendPrivateMessageRaw(UserID int64, message string, selfid string) error {
 		// 发送消息
 		return server.SendMessageBySelfID(selfid, msg)
 	}
-	// 获取基础URL
-	baseURL := config.GetHttpPath() // 假设config.getHttpPath()返回基础URL
+	var baseURL string
+	if len(config.GetHttpPaths()) > 0 {
+		baseURL, _ = GetBaseURLByUserID(selfid)
+	} else {
+		// 获取基础URL
+		baseURL = config.GetHttpPath() // 假设config.getHttpPath()返回基础URL
+	}
 
 	// 构建完整的URL
 	baseURL = baseURL + "/send_private_msg"

From e2a3709e3f506e5ca2d43e5e674d4b3902e82797 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Sun, 19 May 2024 14:54:47 +0800
Subject: [PATCH 07/24] Beta121 (#119)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121
---
 readme.md | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/readme.md b/readme.md
index f6750d1..df0318c 100644
--- a/readme.md
+++ b/readme.md
@@ -168,6 +168,16 @@ settings:
 GET /gensokyo?prompt=example&api=conversation_ernie
 ```
 
+支持端点列表:(需配置:allApi : true)
+```golang
+http.HandleFunc("/conversation_gpt", app.ChatHandlerChatgpt)
+		http.HandleFunc("/conversation_hunyuan", app.ChatHandlerHunyuan)
+		http.HandleFunc("/conversation_ernie", app.ChatHandlerErnie)
+		http.HandleFunc("/conversation_rwkv", app.ChatHandlerRwkv)
+		http.HandleFunc("/conversation_tyqw", app.ChatHandlerTyqw)
+		http.HandleFunc("/conversation_glm", app.ChatHandlerGlm)
+```
+
 ## 请求 `/conversation` 端点
 
 与 `/gensokyo` 类似,`/conversation` 端点支持附加 `prompt` 参数。

From 21a233dbeddaa86300f7177f0ad7b9a8b67c4741 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Sun, 19 May 2024 23:14:44 +0800
Subject: [PATCH 08/24] Beta122 (#120)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122
---
 ...47\345\244\247\346\250\241\345\236\213.md" | 90 +++++++++++++++++
 ...3-\345\233\275\351\231\205\347\257\207.md" | 49 ++++++++++
 ...216\245one-api\346\225\231\347\250\213.md" | 39 ++++++++
 ...45\346\234\272\345\231\250\344\272\272.md" | 98 +++++++++++++++++++
 readme.md                                     | 18 ++--
 5 files changed, 287 insertions(+), 7 deletions(-)
 create mode 100644 "docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\344\272\247\345\244\247\346\250\241\345\236\213.md"
 create mode 100644 "docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\351\231\205\347\257\207.md"
 create mode 100644 "docs/\344\270\255\347\272\247-\345\257\271\346\216\245one-api\346\225\231\347\250\213.md"
 create mode 100644 "docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"

diff --git "a/docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\344\272\247\345\244\247\346\250\241\345\236\213.md" "b/docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\344\272\247\345\244\247\346\250\241\345\236\213.md"
new file mode 100644
index 0000000..90bc014
--- /dev/null
+++ "b/docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\344\272\247\345\244\247\346\250\241\345\236\213.md"
@@ -0,0 +1,90 @@
+# 国产大模型配置实例
+
+### 混元配置项
+配置混元模型需要以下参数:
+```yaml
+secretId: "xxx"
+secretKey: "xxx"
+region: ""
+maxTokensHunyuan: 1024
+hunyuanType: 3  # 可选类型:0=高级版, 1=标准版std, 2=hunyuan-lite, 3=hunyuan-standard, 4=hunyuan-standard-256K, 5=hunyuan-pro
+hunyuanStreamModeration: true  # 启用流式内容审核
+topPHunyuan: 1.0
+temperatureHunyuan: 1.0  # 控制生成内容的随机性
+```
+
+### 文心配置项
+配置文心模型时需要以下参数,这里涵盖了接口的调用以及特殊参数的设置:
+```yaml
+wenxinAccessToken: "xxx"
+wenxinApiPath: "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant"
+wenxinEmbeddingUrl: "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/embeddings/embedding-v1"  # 百度的embedding接口URL
+maxTokenWenxin: 1024
+wenxinTopp: 0.7  # 控制输出文本的多样性,取值范围0.1~1.0,默认0.7
+wenxinPenaltyScore: 1.0  # 增加生成token的惩罚,以减少重复,值越大惩罚越重
+wenxinMaxOutputTokens: 100  # 模型最大输出token数,范围2~1024
+```
+
+### RWKV 模型配置(rwkv runner)
+```yaml
+rwkvApiPath: "https://"  # 符合RWKV标准的API地址
+rwkvMaxTokens: 100
+rwkvTemperature: 1.1
+rwkvTopP: 0.5
+rwkvPresencePenalty: 0.5
+rwkvFrequencyPenalty: 1.1
+rwkvPenaltyDecay: 0.99
+rwkvTopK: 25
+rwkvSseType: 0
+rwkvGlobalPenalty: false
+rwkvStop:
+  - "\n\nUser"
+rwkvUserName: "User"
+rwkvAssistantName: "Assistant"
+rwkvSystemName: "System"
+rwkvPreSystem: false
+```
+
+### TYQW 模型配置
+```yaml
+tyqwApiPath: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
+tyqwMaxTokens: 1500
+tyqwModel: "qwen-turbo"
+tyqwApiKey: "sk-"
+tyqwWorkspace: ""
+tyqwTemperature: 0.85
+tyqwTopP: 0.9
+tyqwPresencePenalty: 0.2
+tyqwFrequencyPenalty: 0.2
+tyqwRepetitionPenalty: 1.1
+tyqwPenaltyDecay: 0.99
+tyqwTopK: 40
+tyqwSeed: 1234
+tyqwSseType: 1
+tyqwGlobalPenalty: false
+tyqwStop:
+  - "\n\nUser"
+tyqwUserName: "User"
+tyqwAssistantName: "Assistant"
+tyqwSystemName: "System"
+tyqwPreSystem: false
+tyqwEnableSearch: false
+```
+
+### GLM 模型配置
+```yaml
+glmApiPath: "https://open.bigmodel.cn/api/paas/v4/chat/completions"
+glmModel: "glm-3-turbo"
+glmApiKey: ".xxx"
+glmRequestID: ""
+glmDoSample: true
+glmTemperature: 0.95
+glmTopP: 0.9
+glmMaxTokens: 1024
+glmStop:
+  - "stop_token"
+glmTools:
+  - ""
+glmToolChoice: "auto"
+glmUserID: ""
+```
\ No newline at end of file
diff --git "a/docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\351\231\205\347\257\207.md" "b/docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\351\231\205\347\257\207.md"
new file mode 100644
index 0000000..a773693
--- /dev/null
+++ "b/docs/\344\270\255\347\272\247-\345\244\247\346\250\241\345\236\213api\351\205\215\347\275\256\347\244\272\344\276\213-\345\233\275\351\231\205\347\257\207.md"
@@ -0,0 +1,49 @@
+### 国际模型配置实例
+
+#### api2d 配置项
+```yaml
+gptModel: "gpt-3.5-turbo"
+gptApiPath: "https://openai.api2d.net/v1/chat/completions"
+gptToken: "fk207628-***********"
+maxTokenGpt: 1024
+gptModeration: false  # 额外走腾讯云检查安全,不合规直接拦截. 仅api2d支持
+gptSafeMode: false
+gptSseType: 0
+```
+
+#### openai 测试配置
+```yaml
+gptModel: "gpt-3.5-turbo"
+gptApiPath: "https://api.openai.com/v1/chat/completions"
+gptToken: "sk_8*******"
+maxTokenGpt: 1024
+gptModeration: false  # 额外走腾讯云检查安全,不合规直接拦截. 仅api2d支持
+gptSafeMode: false
+gptSseType: 0
+standardGptApi: true  # 标准的gptApi, OpenAI 和 Groq 需要开启
+```
+
+#### Groq 测试配置
+```yaml
+gptModel: "llama3-70b-8192"
+gptApiPath: "https://api.groq.com/openai/v1/chat/completions"
+gptToken: "gsk_8*******"
+maxTokenGpt: 1024
+gptModeration: false  # 额外走腾讯云检查安全,不合规直接拦截. 仅api2d支持
+gptSafeMode: false
+gptSseType: 0
+standardGptApi: true  # 标准的gptApi, OpenAI 和 Groq 需要开启
+```
+
+#### One-API 测试配置(该项目也支持国内多个大模型,具体请参考one-api接入教程)
+[one-api](https://github.com/songquanpeng/one-api)
+```yaml
+gptModel: "chatglm_turbo"
+gptApiPath: "http://127.0.0.1:3000/v1/chat/completions"
+gptToken: "sk-d*****"
+maxTokenGpt: 1024
+gptModeration: false  # 额外走腾讯云检查安全,不合规直接拦截. 仅api2d支持
+gptSafeMode: false
+gptSseType: 0
+standardGptApi: true  # 标准的gptApi, OpenAI 和 Groq 需要开启
+```
\ No newline at end of file
diff --git "a/docs/\344\270\255\347\272\247-\345\257\271\346\216\245one-api\346\225\231\347\250\213.md" "b/docs/\344\270\255\347\272\247-\345\257\271\346\216\245one-api\346\225\231\347\250\213.md"
new file mode 100644
index 0000000..9345e4e
--- /dev/null
+++ "b/docs/\344\270\255\347\272\247-\345\257\271\346\216\245one-api\346\225\231\347\250\213.md"
@@ -0,0 +1,39 @@
+### 开始使用 One-API对接gsk-llm
+
+**步骤 1: 下载 One-API**
+- One-API 是一个轻便易用的项目,包含一个可执行文件,无需其他环境支持,且带有 Web UI。
+- 下载链接:[one-api](https://github.com/songquanpeng/one-api)
+
+**步骤 2: 运行 One-API**
+- 执行下载的 One-API 可执行文件。
+- 在浏览器中打开 `http://localhost:3000/`。
+
+**步骤 3: 登录**
+- 使用默认用户名 `root` 和密码 `123456` 登录。
+
+**步骤 4: 创建 API 渠道**
+- 在网页控制台的顶栏选择“渠道”-“添加新的渠道”。
+- 为你的模型渠道命名,并在模型栏中输入你申请的模型名称,该栏支持自动补全。
+- 输入你从模型所在平台(如腾讯云、智谱、通义等)获取的 API access token。
+- 点击“提交”以创建 API 渠道。
+
+**步骤 5: 生成令牌**
+- 点击顶栏的“令牌”并创建一个新令牌。
+- 选择要使用的模型,创建令牌后点击绿色的“复制”按钮复制生成的令牌。
+
+**步骤 6: 配置 gsk-llm**
+- 在 gsk-llm 配置文件中更新以下配置以连接到你的 one-api 平台。
+```yaml
+# One-API 测试配置
+gptModel: "chatglm_turbo"  # 使用的模型名称
+gptApiPath: "http://127.0.0.1:3000/v1/chat/completions"  # One-API 服务的端口号
+gptToken: "sk-dbmr0Oxxxxxxxxxxxxxxxxxxxxxxx"  # 生成的密钥
+maxTokenGpt: 1024
+gptModeration: false
+gptSafeMode: false
+gptSseType: 0
+standardGptApi: true  # 启用标准 GPT API
+```
+
+这样配置后,你就可以灵活地管理用量和使用的模型了。本项目的配置文件是热更新的,你不需要重启来应用配置.
+
diff --git "a/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md" "b/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
new file mode 100644
index 0000000..7deaf70
--- /dev/null
+++ "b/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
@@ -0,0 +1,98 @@
+
+# Gensokyo-LLM (gsk-llm) 初阶教程
+
+## 名词介绍
+**gsk-llm**:在本教程中,我们将 Gensokyo-LLM 缩写为 **gsk-llm**。
+
+**OneBot v11 实现端**:实现了 OneBot v11 标准的应用。在教程中使用 Gensokyo,任何采用 OneBot v11 的实现端均可成功对接使用。
+
+## 支持实现端列表
+访问 [OneBot 生态系统](https://onebot.dev/ecosystem.html) 查看支持实现端的完整列表。
+
+## 接入方法
+
+### 使用ob11反向 WebSocket 接入
+1. 直接让机器人连接到以下本程序地址的 port 上:
+   - **反向链接地址**:`ws://127.0.0.1:46233`
+   - **Port**:46233
+
+连接成功后,机器人便可收发信息。
+
+### 使用ob11 HTTP API 接入方法
+1. 运行 gsk-llm 的 exe 可执行程序。
+2. 打开 `config.yml` 文件并进行以下设置:
+   - **通用配置项**:
+     ```
+     allApi: true  # 同时开启全部 API
+     useSse: true  # 通过 stream 方式发送信息
+     port: 46233
+     path: "http://192.168.0.102:33800"
+     ```
+   - **配置监听地址**:确保没有端口冲突,可以保持默认。
+   - **配置 OneBot v11 的正向 HTTP API 地址**:
+     ```
+     path: "http://127.0.0.1:46233/gensokyo"
+     ```
+   - **上报消息地址**:
+     ```
+     http://192.168.0.102:33800
+     ```
+   - **API 类型选择**:
+     ```
+     apiType: 5  # 选择适合的 API 类型,文末对api类型有讲解
+     ```
+   - **API Key 设置**:填入对应平台的 API Key。
+
+3. 设置 `systemPrompt` 为需要的人设提示词。
+
+4. 根据注释完成其他必要配置。
+
+一旦配置完成,你的机器人将作为一个基本的 AI 聊天对话机器人运行。
+
+### 特别配置解释
+- **useSse: true**:API 通过 stream 方式发送信息,机器人将流式地发送信息。
+- **splitByPuntuations**: 40  #私聊截断率
+- **splitByPuntuationsGroup**: 40  #群聊截断率,仅在 SSE 时有效,100 表示每句截断。
+
+建议截断率取值范围为 30-40,以便优化信息流的连贯性。
+
+---
+
+### API apiType 类型选择
+
+在配置文件中,`apiType` 用于指定使用的 API 类型。您可以根据需要选择以下编号对应的 API 类型:
+
+- **0:混元**
+- **1:文心**
+- **2:GPT**
+- **3:RWKV**
+- **4:TYQW**
+- **5:GLm**
+
+确保您有对应平台的 API key。
+
+#### 特殊配置:API Type 2
+
+当 `apiType` 设置为 **2(GPT)** 时,本程序支持兼容包括但不限于以下项目,以及所有采用 OpenAI 格式的 API 或中转项目:
+
+- [one-api](https://github.com/songquanpeng/one-api)
+- [groq](https://console.groq.com)
+
+对于完全标准的 OpenAI 格式 API,调整配置如下:
+- `standardGptApi: true` 表示启用原生的 OpenAI 格式
+
+对于特殊的 OpenAI API 格式(api2d),则使用:
+- `standardGptApi: false`
+
+API2d 提供了一些额外的配置,如安全模式和腾讯云审核等:
+- [api-2d](https://api2d.com/)
+
+#### 网络代理设置
+
+可以通过设置 `proxy: "http://192.168.0.113:7890"` 来使本程序通过网络代理。
+
+#### 使用须知
+
+请注意,部分平台如 QQ 开放平台和微信开放平台要求模型需要通过算法备案。请不要在这些平台使用未备案的模型。由此产生的服务号或机器人被下线的问题,本项目已尽到提醒的责任,概不负责。
+
+---
\ No newline at end of file
diff --git a/readme.md b/readme.md
index df0318c..b54daad 100644
--- a/readme.md
+++ b/readme.md
@@ -10,6 +10,16 @@
 _✨ 适用于Gensokyo以及Onebotv11的大模型一键端 ✨_  
 </div> 
 
+---
+## 文档&教程
+
+[初阶-简单接入机器人](/docs/初阶-简单接入机器人.md):简单将机器人接入QQ等6大平台
+
+[中级-对接one-api教程](/docs/中级-对接one-api教程.md):可视化管理大模型api
+
+[中级-大模型api配置示例-国产大模型](/docs/中级-大模型api配置示例-国产大模型.md)
+
+[中级-大模型api配置示例-国际篇](/docs/中级-大模型api配置示例-国际篇.md)
 ---
 
 ## 特性
@@ -111,12 +121,6 @@ AhoCorasick算法实现的超高效文本IN-Out替换规则,可大量替换n
 
 ---
 
-## 使用教程
-
-施工中...(部署非常简单,有一定onebotv11机器人部署经验者可参考config.yml注释直接部署出来.)
-
----
-
 # API接口调用说明
 
 本文档提供了关于API接口的调用方法和配置文件的格式说明,帮助用户正确使用和配置。
@@ -170,7 +174,7 @@ GET /gensokyo?prompt=example&api=conversation_ernie
 
 支持端点列表:(需配置:allApi : true)
 ```golang
-http.HandleFunc("/conversation_gpt", app.ChatHandlerChatgpt)
+    http.HandleFunc("/conversation_gpt", app.ChatHandlerChatgpt)
 		http.HandleFunc("/conversation_hunyuan", app.ChatHandlerHunyuan)
 		http.HandleFunc("/conversation_ernie", app.ChatHandlerErnie)
 		http.HandleFunc("/conversation_rwkv", app.ChatHandlerRwkv)

From 8cc5b3d73c0ec10f60de74f9a878b485d113d2fc Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Sun, 19 May 2024 23:16:39 +0800
Subject: [PATCH 09/24] Update readme.md (#121)

---
 readme.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/readme.md b/readme.md
index b54daad..5db889d 100644
--- a/readme.md
+++ b/readme.md
@@ -20,6 +20,7 @@ _✨ 适用于Gensokyo以及Onebotv11的大模型一键端 ✨_
 [中级-大模型api配置示例-国产大模型](/docs/中级-大模型api配置示例-国产大模型.md)
 
 [中级-大模型api配置示例-国际篇](/docs/中级-大模型api配置示例-国际篇.md)
+
 ---
 
 ## 特性
@@ -462,4 +463,4 @@ GetAIPromptkeyboardPath可以是自身地址,可以带有prompt参数
 
 3. **Inklewriter**
     - **项目主页**,[Ink on GitHub](https://github.com/inkle/ink).
-    - 它是一个允许用户创建交互式故事的网页平台。它设计了**ink**语言,它是一个开源项目,用于编写交互式叙述和游戏。
\ No newline at end of file
+    - 它是一个允许用户创建交互式故事的网页平台。它设计了**ink**语言,它是一个开源项目,用于编写交互式叙述和游戏。

From f567a821b27787a4963ef5416a37f07eadc1ebf7 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Sun, 19 May 2024 23:21:41 +0800
Subject: [PATCH 10/24] Beta123 (#122)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123
---
 ...\245\345\205\245\346\234\272\345\231\250\344\272\272.md" | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git "a/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md" "b/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
index 7deaf70..783d281 100644
--- "a/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
+++ "b/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
@@ -29,13 +29,13 @@
      path: "http://192.168.0.102:33800"
      ```
    - **配置监听地址**:确保没有端口冲突,可以保持默认。
-   - **配置 OneBot v11 的正向 HTTP API 地址**:
+   - **上报消息地址**:
      ```
      path: "http://127.0.0.1:46233/gensokyo"
      ```
-   - **上报消息地址**:
+   - **配置 OneBot v11 的正向 HTTP API 地址**:
      ```
-     http://192.168.0.102:33800
+     http://192.168.0.102:33800(该地址是onebotv11实现端的所在ip地址:http监听端口)
      ```
    - **API 类型选择**:
      ```

From ea82b87f812fe3ed0af5ddcb09a2d74c24bb312f Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Sun, 19 May 2024 23:24:39 +0800
Subject: [PATCH 11/24] Beta124 (#123)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124
---
 ...16\245\345\205\245\346\234\272\345\231\250\344\272\272.md" | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git "a/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md" "b/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
index 783d281..2ddd001 100644
--- "a/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
+++ "b/docs/\345\210\235\351\230\266-\347\256\200\345\215\225\346\216\245\345\205\245\346\234\272\345\231\250\344\272\272.md"
@@ -29,11 +29,11 @@
      path: "http://192.168.0.102:33800"
      ```
    - **配置监听地址**:确保没有端口冲突,可以保持默认。
-   - **上报消息地址**:
+   - **上报消息地址**(在onebotv11实现端配置,指向gsk-llm):
      ```
      path: "http://127.0.0.1:46233/gensokyo"
      ```
-   - **配置 OneBot v11 的正向 HTTP API 地址**:
+   - **配置 OneBot v11 的正向 HTTP API 地址**(在gsk-llm配置,指向onebotv11实现端):
      ```
      http://192.168.0.102:33800(该地址是onebotv11实现端的所在ip地址:http监听端口)
      ```

From 5414683ff14e47721afa685b20d89aa3139ccc7e Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Mon, 20 May 2024 00:50:41 +0800
Subject: [PATCH 12/24] Beta125 (#124)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125
---
 applogic/chatglm.go  |  2 +-
 applogic/gensokyo.go |  2 +-
 applogic/hunyuan.go  | 46 ++++++++++++++++++++++++++++++++------------
 config/config.go     | 32 ++++++++++++++++++++++++++++++
 4 files changed, 68 insertions(+), 14 deletions(-)

diff --git a/applogic/chatglm.go b/applogic/chatglm.go
index 14b4aac..382f57a 100644
--- a/applogic/chatglm.go
+++ b/applogic/chatglm.go
@@ -59,7 +59,7 @@ func (app *App) ChatHandlerGlm(w http.ResponseWriter, r *http.Request) {
 
 	// 读取URL参数 "userid"
 	useridstr := r.URL.Query().Get("userid")
-	if promptstr != "" {
+	if useridstr != "" {
 		// prompt 参数存在,可以根据需要进一步处理或记录
 		fmtf.Printf("Received userid parameter: %s\n", useridstr)
 	}
diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index eb5c435..9c320ed 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -558,7 +558,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// glm会根据userid参数来封禁用户
-		if config.GetApiType() == 5 {
+		if config.GetApiType() == 5 || basePath == "/conversation_glm" {
 			urlParams.Add("userid", strconv.FormatInt(message.UserID, 10))
 		}
 
diff --git a/applogic/hunyuan.go b/applogic/hunyuan.go
index 2efd13a..a8d96ae 100644
--- a/applogic/hunyuan.go
+++ b/applogic/hunyuan.go
@@ -7,6 +7,7 @@ import (
 	"strings"
 	"sync"
 
+	"github.com/google/uuid"
 	"github.com/hoshinonyaruko/gensokyo-llm/config"
 	"github.com/hoshinonyaruko/gensokyo-llm/fmtf"
 	"github.com/hoshinonyaruko/gensokyo-llm/hunyuan"
@@ -15,8 +16,12 @@ import (
 	"github.com/hoshinonyaruko/gensokyo-llm/utils"
 )
 
-var messageBuilder strings.Builder
-var groupUserMessages sync.Map
+var (
+	messageBuilder               strings.Builder
+	groupUserMessages            sync.Map
+	mutexhunyuan                 sync.Mutex
+	lastCompleteResponseshunyuan sync.Map // 存储每个conversationId的完整累积信息
+)
 
 func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 	if r.Method != "POST" {
@@ -655,10 +660,16 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 				return
 			}
 
-			var responseTextBuilder strings.Builder
-			var totalUsage structs.UsageInfo
+			// 生成一个随机的UUID
+			randomUUID, err := uuid.NewRandom()
+			if err != nil {
+				http.Error(w, "Failed to generate UUID", http.StatusInternalServerError)
+				return
+			}
 
+			var totalUsage structs.UsageInfo // 有并发问题
 			for event := range response.BaseSSEResponse.Events {
+
 				if event.Err != nil {
 					fmtf.Fprintf(w, "data: %s\n\n", fmtf.Sprintf("接收事件时发生错误: %v", event.Err))
 					flusher.Flush()
@@ -673,13 +684,24 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 					continue
 				}
 
+				// 在修改共享资源之前锁定Mutex
+				mutexhunyuan.Lock()
+				// 由于同一个上下文中 msg.ConversationID是相同的,而我们要区分更细粒度 所以添加UUID openai的api则设计了更细粒度的stramid,可以直接使用
+				conversationId := msg.ConversationID + randomUUID.String()
+				// 读取完整信息
+				completeResponse, _ := lastCompleteResponseshunyuan.LoadOrStore(conversationId, "")
+				// 提取出本次请求的响应
 				responseText, usageInfo := utils.ExtractEventDetails(eventData)
-				responseTextBuilder.WriteString(responseText)
+				// 更新存储的完整累积信息
+				updatedCompleteResponse := completeResponse.(string) + responseText
+				lastCompleteResponseshunyuan.Store(conversationId, updatedCompleteResponse)
+				// 完成修改后解锁Mutex
+				mutexhunyuan.Unlock()
+
 				totalUsage.PromptTokens += usageInfo.PromptTokens
 				totalUsage.CompletionTokens += usageInfo.CompletionTokens
 
-				// 发送当前事件的响应数据,但不包含assistantMessageID
-				//fmtf.Printf("发送当前事件的响应数据,但不包含assistantMessageID\n")
+				// 构建并发送当前事件的响应数据
 				tempResponseMap := map[string]interface{}{
 					"response":       responseText,
 					"conversationId": msg.ConversationID,
@@ -693,12 +715,13 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 			}
 
 			// 处理完所有事件后,生成并发送包含assistantMessageID的最终响应
-			responseText := responseTextBuilder.String()
-			fmtf.Printf("处理完所有事件后,生成并发送包含assistantMessageID的最终响应:%v\n", responseText)
+			conversationId := msg.ConversationID + randomUUID.String()
+			completeResponse, _ := lastCompleteResponseshunyuan.LoadOrStore(conversationId, "")
+			fmtf.Printf("处理完所有事件后,生成并发送包含assistantMessageID的最终响应:%v\n", completeResponse.(string))
 			assistantMessageID, err := app.addMessage(structs.Message{
 				ConversationID:  msg.ConversationID,
 				ParentMessageID: userMessageID,
-				Text:            responseText,
+				Text:            completeResponse.(string),
 				Role:            "assistant",
 			})
 
@@ -708,7 +731,7 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 			}
 
 			finalResponseMap := map[string]interface{}{
-				"response":       responseText,
+				"response":       completeResponse.(string),
 				"conversationId": msg.ConversationID,
 				"messageId":      assistantMessageID,
 				"details": map[string]interface{}{
@@ -720,7 +743,6 @@ func (app *App) ChatHandlerHunyuan(w http.ResponseWriter, r *http.Request) {
 			flusher.Flush()
 		}
 	}
-
 }
 
 func truncateHistoryHunYuan(history []structs.Message, prompt string, promptstr string) []structs.Message {
diff --git a/config/config.go b/config/config.go
index 5fda48c..cb2f2f9 100644
--- a/config/config.go
+++ b/config/config.go
@@ -450,6 +450,10 @@ func getGptTokenInternal(options ...string) string {
 		return getGptTokenInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if gptToken == "" {
+		return getGptTokenInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return gptToken
 }
 
@@ -484,6 +488,10 @@ func getMaxTokenGptInternal(options ...string) int {
 		return getMaxTokenGptInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if maxTokenGpt == 0 {
+		return getMaxTokenGptInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return maxTokenGpt
 }
 
@@ -2486,6 +2494,10 @@ func getGlmApiPathInternal(options ...string) string {
 		return getGlmApiPathInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if apiPath == "" {
+		return getGlmApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return apiPath
 }
 
@@ -2520,6 +2532,10 @@ func getGlmModelInternal(options ...string) string {
 		return getGlmModelInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if model == "" {
+		return getGlmModelInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return model
 }
 
@@ -2554,6 +2570,10 @@ func getGlmApiKeyInternal(options ...string) string {
 		return getGlmApiKeyInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if apiKey == "" {
+		return getGlmApiKeyInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return apiKey
 }
 
@@ -2588,6 +2608,10 @@ func getGlmMaxTokensInternal(options ...string) int {
 		return getGlmMaxTokensInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if maxTokens == 0 {
+		return getGlmMaxTokensInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return maxTokens
 }
 
@@ -2622,6 +2646,10 @@ func getGlmTemperatureInternal(options ...string) float64 {
 		return getGlmTemperatureInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if temperature == 0 {
+		return getGlmTemperatureInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return temperature
 }
 
@@ -2696,6 +2724,10 @@ func getGlmTopPInternal(options ...string) float64 {
 		return getGlmTopPInternal() // 递归调用内部函数,不传递任何参数
 	}
 
+	if topP == 0 {
+		return getGlmTopPInternal() // 递归调用内部函数,不传递任何参数
+	}
+
 	return topP
 }
 

From d3d10a2420219752f3fcc7ef98bba2d5e90986dc Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Mon, 20 May 2024 21:58:57 +0800
Subject: [PATCH 13/24] Beta126 (#125)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126
---
 applogic/chatgpt.go       | 31 +++++++++++--------------
 applogic/gensokyo.go      | 49 ++++++++++++++++++++++++++++++++-------
 applogic/rwkv.go          | 26 ++++++++++-----------
 applogic/tongyiqianwen.go | 28 +++++++++++-----------
 4 files changed, 79 insertions(+), 55 deletions(-)

diff --git a/applogic/chatgpt.go b/applogic/chatgpt.go
index 2a242a4..9d1ba2d 100644
--- a/applogic/chatgpt.go
+++ b/applogic/chatgpt.go
@@ -425,6 +425,7 @@ func (app *App) ChatHandlerChatgpt(w http.ResponseWriter, r *http.Request) {
 					mutexchatgpt.Lock()
 
 					conversationId := eventData.ID // 假设conversationId从事件数据的ID字段获取
+					// 储存eventData.ID 和 msg.ConversationID 对应关系
 					conversationMap.Store(msg.ConversationID, conversationId)
 					//读取完整信息
 					completeResponse, _ := lastCompleteResponses.LoadOrStore(conversationId, "")
@@ -466,11 +467,10 @@ func (app *App) ChatHandlerChatgpt(w http.ResponseWriter, r *http.Request) {
 					if newContent != "" {
 						tempResponseMap := map[string]interface{}{
 							"response":       newContent,
-							"conversationId": conversationId,
+							"conversationId": msg.ConversationID,
 						}
 						tempResponseJSON, _ := json.Marshal(tempResponseMap)
 						fmtf.Fprintf(w, "data: %s\n\n", string(tempResponseJSON))
-						//fmt.Printf("测试返回:%v\n", string(tempResponseJSON))
 						flusher.Flush()
 					}
 				}
@@ -493,24 +493,19 @@ func (app *App) ChatHandlerChatgpt(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// 在所有事件处理完毕后发送最终响应
-		// 首先从 conversationMap 获取真实的 conversationId
-		if actualConversationId, ok := conversationMap.Load(msg.ConversationID); ok {
-			if finalContent, ok := lastCompleteResponses.Load(actualConversationId); ok {
-				finalResponseMap := map[string]interface{}{
-					"response":       finalContent,
-					"conversationId": actualConversationId,
-					"messageId":      assistantMessageID,
-					"details": map[string]interface{}{
-						"usage": totalUsage,
-					},
-				}
-				finalResponseJSON, _ := json.Marshal(finalResponseMap)
-				fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
-				flusher.Flush()
-			}
+		finalResponseMap := map[string]interface{}{
+			"response":       completeResponse.(string),
+			"conversationId": msg.ConversationID,
+			"messageId":      assistantMessageID,
+			"details": map[string]interface{}{
+				"usage": totalUsage,
+			},
 		}
-
+		finalResponseJSON, _ := json.Marshal(finalResponseMap)
+		fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
+		flusher.Flush()
 	}
+
 }
 
 func truncateHistoryGpt(history []structs.Message, prompt string, promptstr string) []structs.Message {
diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index 9c320ed..ad061c7 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -24,6 +24,15 @@ var newmsgToStringMap = make(map[string]string)
 var stringToIndexMap sync.Map
 var processMessageMu sync.Mutex
 
+// UserInfo 结构体用于储存用户信息
+type UserInfo struct {
+	UserID  int64
+	GroupID int64
+}
+
+// globalMap 用于存储conversationID与UserInfo的映射
+var globalMap sync.Map
+
 // RecordStringById 根据id记录一个string
 func RecordStringByNewmsg(id, value string) {
 	newmsgToStringMap[id] = value
@@ -464,6 +473,9 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 		// 请求conversation api 增加当前用户上下文
 		conversationID, parentMessageID, err := app.handleUserContext(message.UserID)
+		// 使用map映射conversationID和uid gid的关系
+		StoreUserInfo(conversationID, message.UserID, message.GroupID)
+
 		//每句话清空上一句话的messageBuilder
 		messageBuilder.Reset()
 		fmtf.Printf("conversationID: %s,parentMessageID%s\n", conversationID, parentMessageID)
@@ -893,7 +905,8 @@ func splitAndSendMessages(message structs.OnebotGroupMessage, line string, newme
 
 	// 解析JSON数据
 	var sseData struct {
-		Response string `json:"response"`
+		Response       string `json:"response"`
+		ConversationId string `json:"conversationId"`
 	}
 	err := json.Unmarshal([]byte(jsonStr), &sseData)
 	if err != nil {
@@ -903,13 +916,13 @@ func splitAndSendMessages(message structs.OnebotGroupMessage, line string, newme
 
 	if sseData.Response != "\n\n" {
 		// 处理提取出的信息
-		processMessage(sseData.Response, message, newmesssage, selfid)
+		processMessage(sseData.Response, sseData.ConversationId, message, newmesssage, selfid)
 	} else {
 		fmtf.Printf("忽略llm末尾的换行符")
 	}
 }
 
-func processMessage(response string, msg structs.OnebotGroupMessage, newmesssage string, selfid string) {
+func processMessage(response string, conversationid string, msg structs.OnebotGroupMessage, newmesssage string, selfid string) {
 	key := utils.GetKey(msg.GroupID, msg.UserID)
 
 	// 定义中文全角和英文标点符号
@@ -932,34 +945,36 @@ func processMessage(response string, msg structs.OnebotGroupMessage, newmesssage
 				groupUserMessages.Store(key, value)
 				processMessageMu.Unlock() // 完成更新后时解锁
 
+				// 从conversation对应的sync map取出对应的用户和群号,避免高并发内容发送错乱
+				userinfo, _ := GetUserInfo(conversationid)
 				// 判断消息类型,如果是私人消息或私有群消息,发送私人消息;否则,根据配置决定是否发送群消息
 				if msg.RealMessageType == "group_private" || msg.MessageType == "private" {
 					if !config.GetUsePrivateSSE() {
-						utils.SendPrivateMessage(msg.UserID, accumulatedMessage, selfid)
+						utils.SendPrivateMessage(userinfo.UserID, accumulatedMessage, selfid)
 					} else {
 						if IncrementIndex(newmesssage) == 1 {
 							//第一条信息
 							//取出当前信息作为按钮回调
 							//CallbackData := GetStringById(lastMessageID)
-							uerid := strconv.FormatInt(msg.UserID, 10)
+							uerid := strconv.FormatInt(userinfo.UserID, 10)
 							messageSSE := structs.InterfaceBody{
 								Content:      accumulatedMessage,
 								State:        1,
 								ActionButton: 10,
 								CallbackData: uerid,
 							}
-							utils.SendPrivateMessageSSE(msg.UserID, messageSSE)
+							utils.SendPrivateMessageSSE(userinfo.UserID, messageSSE)
 						} else {
 							//SSE的前半部分
 							messageSSE := structs.InterfaceBody{
 								Content: accumulatedMessage,
 								State:   1,
 							}
-							utils.SendPrivateMessageSSE(msg.UserID, messageSSE)
+							utils.SendPrivateMessageSSE(userinfo.UserID, messageSSE)
 						}
 					}
 				} else {
-					utils.SendGroupMessage(msg.GroupID, msg.UserID, accumulatedMessage, selfid)
+					utils.SendGroupMessage(userinfo.GroupID, userinfo.UserID, accumulatedMessage, selfid)
 				}
 
 				messageBuilder.Reset() // 重置消息构建器
@@ -993,3 +1008,21 @@ func handleWithdrawMessage(message structs.OnebotGroupMessage) {
 		return
 	}
 }
+
+// StoreUserInfo 用于存储用户信息到全局 map
+func StoreUserInfo(conversationID string, userID int64, groupID int64) {
+	userInfo := UserInfo{
+		UserID:  userID,
+		GroupID: groupID,
+	}
+	globalMap.Store(conversationID, userInfo)
+}
+
+// GetUserInfo 根据conversationID获取用户信息
+func GetUserInfo(conversationID string) (UserInfo, bool) {
+	value, ok := globalMap.Load(conversationID)
+	if ok {
+		return value.(UserInfo), true
+	}
+	return UserInfo{}, false
+}
diff --git a/applogic/rwkv.go b/applogic/rwkv.go
index 543fd90..104b7b6 100644
--- a/applogic/rwkv.go
+++ b/applogic/rwkv.go
@@ -459,7 +459,7 @@ func (app *App) ChatHandlerRwkv(w http.ResponseWriter, r *http.Request) {
 					if newContent != "" {
 						tempResponseMap := map[string]interface{}{
 							"response":       newContent,
-							"conversationId": conversationId,
+							"conversationId": msg.ConversationID,
 						}
 						tempResponseJSON, _ := json.Marshal(tempResponseMap)
 						fmtf.Fprintf(w, "data: %s\n\n", string(tempResponseJSON))
@@ -485,20 +485,18 @@ func (app *App) ChatHandlerRwkv(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// 在所有事件处理完毕后发送最终响应
-		// 首先从 conversationMap 获取真实的 conversationId
-		if finalContent, ok := lastCompleteResponsesRwkv.Load(conversationId); ok {
-			finalResponseMap := map[string]interface{}{
-				"response":       finalContent,
-				"conversationId": conversationId,
-				"messageId":      assistantMessageID,
-				"details": map[string]interface{}{
-					"usage": totalUsage,
-				},
-			}
-			finalResponseJSON, _ := json.Marshal(finalResponseMap)
-			fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
-			flusher.Flush()
+		finalResponseMap := map[string]interface{}{
+			"response":       completeResponse.(string),
+			"conversationId": msg.ConversationID,
+			"messageId":      assistantMessageID,
+			"details": map[string]interface{}{
+				"usage": totalUsage,
+			},
 		}
+		finalResponseJSON, _ := json.Marshal(finalResponseMap)
+		fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
+		flusher.Flush()
+
 	}
 
 }
diff --git a/applogic/tongyiqianwen.go b/applogic/tongyiqianwen.go
index 8277437..1197555 100644
--- a/applogic/tongyiqianwen.go
+++ b/applogic/tongyiqianwen.go
@@ -524,7 +524,7 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 					if newContent != "" {
 						tempResponseMap := map[string]interface{}{
 							"response":       newContent,
-							"conversationId": conversationId,
+							"conversationId": msg.ConversationID,
 						}
 						tempResponseJSON, _ := json.Marshal(tempResponseMap)
 						fmt.Fprintf(w, "data: %s\n\n", string(tempResponseJSON))
@@ -534,7 +534,7 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 
-		//一点点奇怪的转换
+		// 一点点奇怪的转换
 		conversationId := msg.ConversationID + randomUUID.String()
 		completeResponse, _ := lastCompleteResponsesTyqw.LoadOrStore(conversationId, "")
 		// 在所有事件处理完毕后发送最终响应
@@ -551,20 +551,18 @@ func (app *App) ChatHandlerTyqw(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// 在所有事件处理完毕后发送最终响应
-		// 首先从 conversationMap 获取真实的 conversationId
-		if finalContent, ok := lastCompleteResponsesTyqw.Load(conversationId); ok {
-			finalResponseMap := map[string]interface{}{
-				"response":       finalContent,
-				"conversationId": conversationId,
-				"messageId":      assistantMessageID,
-				"details": map[string]interface{}{
-					"usage": totalUsage,
-				},
-			}
-			finalResponseJSON, _ := json.Marshal(finalResponseMap)
-			fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
-			flusher.Flush()
+		finalResponseMap := map[string]interface{}{
+			"response":       completeResponse.(string),
+			"conversationId": conversationId,
+			"messageId":      assistantMessageID,
+			"details": map[string]interface{}{
+				"usage": totalUsage,
+			},
 		}
+		finalResponseJSON, _ := json.Marshal(finalResponseMap)
+		fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
+		flusher.Flush()
+
 	}
 
 }

From ffa8ad3a7157ec5f929d2e00de30e39fb8441b4c Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Tue, 21 May 2024 00:05:04 +0800
Subject: [PATCH 14/24] Beta127 (#126)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127
---
 applogic/gensokyo.go | 112 +++++++++++++++++++++++++++++--------------
 applogic/hunyuan.go  |   1 -
 2 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index ad061c7..1a6eedc 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -23,11 +23,14 @@ import (
 var newmsgToStringMap = make(map[string]string)
 var stringToIndexMap sync.Map
 var processMessageMu sync.Mutex
+var messages sync.Map
 
 // UserInfo 结构体用于储存用户信息
 type UserInfo struct {
-	UserID  int64
-	GroupID int64
+	UserID          int64
+	GroupID         int64
+	RealMessageType string
+	MessageType     string
 }
 
 // globalMap 用于存储conversationID与UserInfo的映射
@@ -474,10 +477,10 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		// 请求conversation api 增加当前用户上下文
 		conversationID, parentMessageID, err := app.handleUserContext(message.UserID)
 		// 使用map映射conversationID和uid gid的关系
-		StoreUserInfo(conversationID, message.UserID, message.GroupID)
+		StoreUserInfo(conversationID, message.UserID, message.GroupID, message.RealMessageType, message.MessageType)
 
 		//每句话清空上一句话的messageBuilder
-		messageBuilder.Reset()
+		ClearMessage(conversationID)
 		fmtf.Printf("conversationID: %s,parentMessageID%s\n", conversationID, parentMessageID)
 		if err != nil {
 			fmtf.Printf("Error handling user context: %v\n", err)
@@ -624,9 +627,13 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 					//接收到最后一条信息
 					if id, ok := responseData["messageId"].(string); ok {
 
+						conversationid := responseData["conversationId"].(string)
+						// 从conversation对应的sync map取出对应的用户和群号,避免高并发内容发送错乱
+						userinfo, _ := GetUserInfo(conversationid)
+
 						lastMessageID = id // 更新lastMessageID
 						// 检查是否有未发送的消息部分
-						key := utils.GetKey(message.GroupID, message.UserID)
+						key := utils.GetKey(userinfo.GroupID, userinfo.UserID)
 						accumulatedMessageInterface, exists := groupUserMessages.Load(key)
 						var accumulatedMessage string
 						if exists {
@@ -645,9 +652,9 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 								if newPart != "" {
 									fmtf.Printf("A完整信息: %s,已发送信息:%s 新部分:%s\n", response, accumulatedMessage, newPart)
 									// 判断消息类型,如果是私人消息或私有群消息,发送私人消息;否则,根据配置决定是否发送群消息
-									if message.RealMessageType == "group_private" || message.MessageType == "private" {
+									if userinfo.RealMessageType == "group_private" || userinfo.MessageType == "private" {
 										if !config.GetUsePrivateSSE() {
-											utils.SendPrivateMessage(message.UserID, newPart, selfid)
+											utils.SendPrivateMessage(userinfo.UserID, newPart, selfid)
 										} else {
 											//判断是否最后一条
 											var state int
@@ -660,23 +667,23 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 												Content: newPart,
 												State:   state,
 											}
-											utils.SendPrivateMessageSSE(message.UserID, messageSSE)
+											utils.SendPrivateMessageSSE(userinfo.UserID, messageSSE)
 										}
 									} else {
 										// 这里发送的是newPart api最后补充的部分
 										if !config.GetMdPromptKeyboardAtGroup() {
 											// 如果没有 EnhancedAContent
 											if EnhancedAContent == "" {
-												utils.SendGroupMessage(message.GroupID, message.UserID, newPart, selfid)
+												utils.SendGroupMessage(userinfo.GroupID, userinfo.UserID, newPart, selfid)
 											} else {
-												utils.SendGroupMessage(message.GroupID, message.UserID, newPart+EnhancedAContent, selfid)
+												utils.SendGroupMessage(userinfo.GroupID, userinfo.UserID, newPart+EnhancedAContent, selfid)
 											}
 										} else {
 											// 如果没有 EnhancedAContent
 											if EnhancedAContent == "" {
-												utils.SendGroupMessageMdPromptKeyboard(message.GroupID, message.UserID, newPart, selfid, newmsg, response, promptstr)
+												utils.SendGroupMessageMdPromptKeyboard(userinfo.GroupID, userinfo.UserID, newPart, selfid, newmsg, response, promptstr)
 											} else {
-												utils.SendGroupMessageMdPromptKeyboard(message.GroupID, message.UserID, newPart+EnhancedAContent, selfid, newmsg, response, promptstr)
+												utils.SendGroupMessageMdPromptKeyboard(userinfo.GroupID, userinfo.UserID, newPart+EnhancedAContent, selfid, newmsg, response, promptstr)
 											}
 										}
 									}
@@ -690,13 +697,13 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 								fmtf.Printf("B完整信息: %s,已发送信息:%s", response, accumulatedMessage)
 								if accumulatedMessage == "" {
 									// 判断消息类型,如果是私人消息或私有群消息,发送私人消息;否则,根据配置决定是否发送群消息
-									if message.RealMessageType == "group_private" || message.MessageType == "private" {
+									if userinfo.RealMessageType == "group_private" || userinfo.MessageType == "private" {
 										if !config.GetUsePrivateSSE() {
 											// 如果没有 EnhancedAContent
 											if EnhancedAContent == "" {
-												utils.SendPrivateMessage(message.UserID, response, selfid)
+												utils.SendPrivateMessage(userinfo.UserID, response, selfid)
 											} else {
-												utils.SendPrivateMessage(message.UserID, response+EnhancedAContent, selfid)
+												utils.SendPrivateMessage(userinfo.UserID, response+EnhancedAContent, selfid)
 											}
 										} else {
 											//判断是否最后一条
@@ -710,22 +717,22 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 												Content: response,
 												State:   state,
 											}
-											utils.SendPrivateMessageSSE(message.UserID, messageSSE)
+											utils.SendPrivateMessageSSE(userinfo.UserID, messageSSE)
 										}
 									} else {
 										if !config.GetMdPromptKeyboardAtGroup() {
 											// 如果没有 EnhancedAContent
 											if EnhancedAContent == "" {
-												utils.SendGroupMessage(message.GroupID, message.UserID, response, selfid)
+												utils.SendGroupMessage(userinfo.GroupID, userinfo.UserID, response, selfid)
 											} else {
-												utils.SendGroupMessage(message.GroupID, message.UserID, response+EnhancedAContent, selfid)
+												utils.SendGroupMessage(userinfo.GroupID, userinfo.UserID, response+EnhancedAContent, selfid)
 											}
 										} else {
 											// 如果没有 EnhancedAContent
 											if EnhancedAContent == "" {
-												utils.SendGroupMessageMdPromptKeyboard(message.GroupID, message.UserID, response, selfid, newmsg, response, promptstr)
+												utils.SendGroupMessageMdPromptKeyboard(userinfo.GroupID, userinfo.UserID, response, selfid, newmsg, response, promptstr)
 											} else {
-												utils.SendGroupMessageMdPromptKeyboard(message.GroupID, message.UserID, response+EnhancedAContent, selfid, newmsg, response, promptstr)
+												utils.SendGroupMessageMdPromptKeyboard(userinfo.GroupID, userinfo.UserID, response+EnhancedAContent, selfid, newmsg, response, promptstr)
 											}
 										}
 
@@ -733,7 +740,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 								}
 							}
 							// 提示词 整体切换A
-							app.ProcessPromptMarks(message.UserID, response, &promptstr)
+							app.ProcessPromptMarks(userinfo.UserID, response, &promptstr)
 							// 清空之前加入缓存
 							// 缓存省钱部分 这里默认不被覆盖,如果主配置开了缓存,始终缓存.
 							if config.GetUseCache() {
@@ -753,7 +760,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 						if !config.GetHideExtraLogs() {
 							fmtf.Printf("收到流数据,切割并发送信息: %s", string(line))
 						}
-						splitAndSendMessages(message, string(line), newmsg, selfid)
+						splitAndSendMessages(string(line), newmsg, selfid)
 					}
 				}
 			}
@@ -898,7 +905,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 }
 
-func splitAndSendMessages(message structs.OnebotGroupMessage, line string, newmesssage string, selfid string) {
+func splitAndSendMessages(line string, newmesssage string, selfid string) {
 	// 提取JSON部分
 	dataPrefix := "data: "
 	jsonStr := strings.TrimPrefix(line, dataPrefix)
@@ -916,24 +923,26 @@ func splitAndSendMessages(message structs.OnebotGroupMessage, line string, newme
 
 	if sseData.Response != "\n\n" {
 		// 处理提取出的信息
-		processMessage(sseData.Response, sseData.ConversationId, message, newmesssage, selfid)
+		processMessage(sseData.Response, sseData.ConversationId, newmesssage, selfid)
 	} else {
 		fmtf.Printf("忽略llm末尾的换行符")
 	}
 }
 
-func processMessage(response string, conversationid string, msg structs.OnebotGroupMessage, newmesssage string, selfid string) {
-	key := utils.GetKey(msg.GroupID, msg.UserID)
+func processMessage(response string, conversationid string, newmesssage string, selfid string) {
+	// 从conversation对应的sync map取出对应的用户和群号,避免高并发内容发送错乱
+	userinfo, _ := GetUserInfo(conversationid)
+	key := utils.GetKey(userinfo.GroupID, userinfo.UserID)
 
 	// 定义中文全角和英文标点符号
 	punctuations := []rune{'。', '!', '?', ',', ',', '.', '!', '?', '~'}
 
 	for _, char := range response {
-		messageBuilder.WriteRune(char)
-		if utils.ContainsRune(punctuations, char, msg.GroupID) {
+		AppendRune(conversationid, char)
+		if utils.ContainsRune(punctuations, char, userinfo.GroupID) {
 			// 达到标点符号,发送累积的整个消息
-			if messageBuilder.Len() > 0 {
-				accumulatedMessage := messageBuilder.String()
+			if GetMessageLength(conversationid) > 0 {
+				accumulatedMessage, _ := GetCurrentMessage(conversationid)
 				// 锁定
 				processMessageMu.Lock()
 				// 从sync.map读取当前的value
@@ -945,10 +954,8 @@ func processMessage(response string, conversationid string, msg structs.OnebotGr
 				groupUserMessages.Store(key, value)
 				processMessageMu.Unlock() // 完成更新后时解锁
 
-				// 从conversation对应的sync map取出对应的用户和群号,避免高并发内容发送错乱
-				userinfo, _ := GetUserInfo(conversationid)
 				// 判断消息类型,如果是私人消息或私有群消息,发送私人消息;否则,根据配置决定是否发送群消息
-				if msg.RealMessageType == "group_private" || msg.MessageType == "private" {
+				if userinfo.RealMessageType == "group_private" || userinfo.MessageType == "private" {
 					if !config.GetUsePrivateSSE() {
 						utils.SendPrivateMessage(userinfo.UserID, accumulatedMessage, selfid)
 					} else {
@@ -977,7 +984,7 @@ func processMessage(response string, conversationid string, msg structs.OnebotGr
 					utils.SendGroupMessage(userinfo.GroupID, userinfo.UserID, accumulatedMessage, selfid)
 				}
 
-				messageBuilder.Reset() // 重置消息构建器
+				ClearMessage(conversationid)
 			}
 		}
 	}
@@ -1010,10 +1017,12 @@ func handleWithdrawMessage(message structs.OnebotGroupMessage) {
 }
 
 // StoreUserInfo 用于存储用户信息到全局 map
-func StoreUserInfo(conversationID string, userID int64, groupID int64) {
+func StoreUserInfo(conversationID string, userID int64, groupID int64, realMessageType string, messageType string) {
 	userInfo := UserInfo{
-		UserID:  userID,
-		GroupID: groupID,
+		UserID:          userID,
+		GroupID:         groupID,
+		RealMessageType: realMessageType,
+		MessageType:     messageType,
 	}
 	globalMap.Store(conversationID, userInfo)
 }
@@ -1026,3 +1035,32 @@ func GetUserInfo(conversationID string) (UserInfo, bool) {
 	}
 	return UserInfo{}, false
 }
+
+func AppendRune(conversationID string, char rune) {
+	value, _ := messages.LoadOrStore(conversationID, "")
+	// 追加字符到现有字符串
+	updatedValue := value.(string) + string(char)
+	messages.Store(conversationID, updatedValue)
+}
+
+func GetCurrentMessage(conversationID string) (string, bool) {
+	value, ok := messages.Load(conversationID)
+	if ok {
+		return value.(string), true
+	}
+	return "", false
+}
+
+func ClearMessage(conversationID string) {
+	messages.Delete(conversationID)
+}
+
+func GetMessageLength(conversationID string) int {
+	value, ok := messages.Load(conversationID)
+	if ok {
+		// 断言字符串,返回长度
+		return len(value.(string))
+	}
+	// 如果没有找到对应的值,返回0
+	return 0
+}
diff --git a/applogic/hunyuan.go b/applogic/hunyuan.go
index a8d96ae..913eadc 100644
--- a/applogic/hunyuan.go
+++ b/applogic/hunyuan.go
@@ -17,7 +17,6 @@ import (
 )
 
 var (
-	messageBuilder               strings.Builder
 	groupUserMessages            sync.Map
 	mutexhunyuan                 sync.Mutex
 	lastCompleteResponseshunyuan sync.Map // 存储每个conversationId的完整累积信息

From 9cae967b3614ac13b7d5e6ea7ebdc2b31d9a77c2 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Thu, 23 May 2024 16:51:21 +0800
Subject: [PATCH 15/24] Beta128 (#127)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128
---
 applogic/chatglm.go         |   6 +-
 applogic/chatgpt.go         |   7 +-
 applogic/gensokyo.go        |   4 +-
 applogic/rwkv.go            |   6 +-
 applogic/tongyiqianwen.go   |   6 +-
 applogic/yuanqi.go          | 508 ++++++++++++++++++++++++++++++++++++
 config/config.go            | 175 +++++++++++++
 main.go                     |   4 +
 structs/struct.go           |   8 +
 structs/yuanqi.go           |  26 ++
 template/config_template.go |   8 +-
 11 files changed, 743 insertions(+), 15 deletions(-)
 create mode 100644 applogic/yuanqi.go
 create mode 100644 structs/yuanqi.go

diff --git a/applogic/chatglm.go b/applogic/chatglm.go
index 382f57a..45eb34a 100644
--- a/applogic/chatglm.go
+++ b/applogic/chatglm.go
@@ -477,9 +477,9 @@ func truncateHistoryGlm(history []structs.Message, prompt string, promptstr stri
 		}
 	}
 
-	// 确保以user结尾,如果不是则尝试移除直到满足条件
-	if len(history) > 0 && history[len(history)-1].Role != "user" {
-		for len(history) > 0 && history[len(history)-1].Role != "user" {
+	// 第三步:确保以assistant结尾
+	if len(history) > 0 && history[len(history)-1].Role == "user" {
+		for len(history) > 0 && history[len(history)-1].Role != "assistant" {
 			history = history[:len(history)-1]
 		}
 	}
diff --git a/applogic/chatgpt.go b/applogic/chatgpt.go
index 9d1ba2d..51e1513 100644
--- a/applogic/chatgpt.go
+++ b/applogic/chatgpt.go
@@ -515,6 +515,7 @@ func truncateHistoryGpt(history []structs.Message, prompt string, promptstr stri
 	for _, msg := range history {
 		tokenCount += len(msg.Text)
 	}
+	fmt.Printf("测试:%v\n", history)
 
 	if tokenCount >= MAX_TOKENS {
 		// 第一步:从开始逐个移除消息,直到满足令牌数量限制
@@ -544,9 +545,9 @@ func truncateHistoryGpt(history []structs.Message, prompt string, promptstr stri
 		}
 	}
 
-	// 确保以user结尾,如果不是则尝试移除直到满足条件
-	if len(history) > 0 && history[len(history)-1].Role != "user" {
-		for len(history) > 0 && history[len(history)-1].Role != "user" {
+	// 第三步:确保以assistant结尾
+	if len(history) > 0 && history[len(history)-1].Role == "user" {
+		for len(history) > 0 && history[len(history)-1].Role != "assistant" {
 			history = history[:len(history)-1]
 		}
 	}
diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index 1a6eedc..e3c2e9a 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -572,8 +572,8 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 			urlParams.Add("prompt", promptstr)
 		}
 
-		// glm会根据userid参数来封禁用户
-		if config.GetApiType() == 5 || basePath == "/conversation_glm" {
+		// 元器和glm会根据userid参数来自动封禁用户
+		if config.GetApiType() == 5 || basePath == "/conversation_glm" || config.GetApiType() == 6 || basePath == "/conversation_yq" {
 			urlParams.Add("userid", strconv.FormatInt(message.UserID, 10))
 		}
 
diff --git a/applogic/rwkv.go b/applogic/rwkv.go
index 104b7b6..ad205a2 100644
--- a/applogic/rwkv.go
+++ b/applogic/rwkv.go
@@ -537,9 +537,9 @@ func truncateHistoryRwkv(history []structs.Message, prompt string, promptstr str
 		}
 	}
 
-	// 确保以user结尾,如果不是则尝试移除直到满足条件
-	if len(history) > 0 && history[len(history)-1].Role != "user" {
-		for len(history) > 0 && history[len(history)-1].Role != "user" {
+	// 第三步:确保以assistant结尾
+	if len(history) > 0 && history[len(history)-1].Role == "user" {
+		for len(history) > 0 && history[len(history)-1].Role != "assistant" {
 			history = history[:len(history)-1]
 		}
 	}
diff --git a/applogic/tongyiqianwen.go b/applogic/tongyiqianwen.go
index 1197555..b4bb6a1 100644
--- a/applogic/tongyiqianwen.go
+++ b/applogic/tongyiqianwen.go
@@ -603,9 +603,9 @@ func truncateHistoryTyqw(history []structs.Message, prompt string, promptstr str
 		}
 	}
 
-	// 确保以user结尾,如果不是则尝试移除直到满足条件
-	if len(history) > 0 && history[len(history)-1].Role != "user" {
-		for len(history) > 0 && history[len(history)-1].Role != "user" {
+	// 第三步:确保以assistant结尾
+	if len(history) > 0 && history[len(history)-1].Role == "user" {
+		for len(history) > 0 && history[len(history)-1].Role != "assistant" {
 			history = history[:len(history)-1]
 		}
 	}
diff --git a/applogic/yuanqi.go b/applogic/yuanqi.go
new file mode 100644
index 0000000..542933c
--- /dev/null
+++ b/applogic/yuanqi.go
@@ -0,0 +1,508 @@
+package applogic
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"net/url"
+	"strings"
+	"sync"
+
+	"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"
+)
+
+// 用于存储每个conversationId的最后一条消息内容
+var (
+	// lastResponses 存储每个真实 conversationId 的最后响应文本
+	lastResponsesYQ sync.Map
+	// conversationMap 存储 msg.ConversationID 到真实 conversationId 的映射
+	conversationMapYQ       sync.Map
+	lastCompleteResponsesYQ sync.Map // 存储每个conversationId的完整累积信息
+	mutexyuanqi             sync.Mutex
+)
+
+func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) {
+	if r.Method != "POST" {
+		http.Error(w, "Only POST method is allowed", http.StatusMethodNotAllowed)
+		return
+	}
+
+	// 获取访问者的IP地址
+	ip := r.RemoteAddr             // 注意:这可能包含端口号
+	ip = strings.Split(ip, ":")[0] // 去除端口号,仅保留IP地址
+
+	// 获取IP白名单
+	whiteList := config.IPWhiteList()
+
+	// 检查IP是否在白名单中
+	if !utils.Contains(whiteList, ip) {
+		http.Error(w, "Access denied", http.StatusInternalServerError)
+		return
+	}
+
+	var msg structs.Message
+	err := json.NewDecoder(r.Body).Decode(&msg)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+
+	// 读取URL参数 "prompt"
+	promptstr := r.URL.Query().Get("prompt")
+	if promptstr != "" {
+		// prompt 参数存在,可以根据需要进一步处理或记录
+		fmtf.Printf("Received prompt parameter: %s\n", promptstr)
+	}
+
+	// 读取URL参数 "userid"
+	useridstr := r.URL.Query().Get("userid")
+	if useridstr != "" {
+		// prompt 参数存在,可以根据需要进一步处理或记录
+		fmtf.Printf("Received userid parameter: %s\n", useridstr)
+	}
+
+	msg.Role = "user"
+	//颠倒用户输入
+	if config.GetReverseUserPrompt() {
+		msg.Text = utils.ReverseString(msg.Text)
+	}
+
+	if msg.ConversationID == "" {
+		msg.ConversationID = utils.GenerateUUID()
+		app.createConversation(msg.ConversationID)
+	}
+
+	userMessageID, err := app.addMessage(msg)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	var history []structs.Message
+
+	//根据是否有prompt参数 选择是否载入config.yml的prompt还是prompts文件夹的
+	if promptstr == "" {
+		// 获取系统提示词
+		systemPromptContent := config.SystemPrompt()
+		if systemPromptContent != "0" {
+			systemPrompt := structs.Message{
+				Text: systemPromptContent,
+				Role: "system",
+			}
+			// 将系统提示词添加到历史信息的开始
+			history = append([]structs.Message{systemPrompt}, history...)
+		}
+
+		// 分别获取FirstQ&A, SecondQ&A, ThirdQ&A
+		pairs := []struct {
+			Q     string
+			A     string
+			RoleQ string // 问题的角色
+			RoleA string // 答案的角色
+		}{
+			{config.GetFirstQ(), config.GetFirstA(), "user", "assistant"},
+			{config.GetSecondQ(), config.GetSecondA(), "user", "assistant"},
+			{config.GetThirdQ(), config.GetThirdA(), "user", "assistant"},
+		}
+
+		// 检查每一对Q&A是否均不为空,并追加到历史信息中
+		for _, pair := range pairs {
+			if pair.Q != "" && pair.A != "" {
+				qMessage := structs.Message{
+					Text: pair.Q,
+					Role: pair.RoleQ,
+				}
+				aMessage := structs.Message{
+					Text: pair.A,
+					Role: pair.RoleA,
+				}
+
+				// 注意追加的顺序,确保问题在答案之前
+				history = append(history, qMessage, aMessage)
+			}
+		}
+	} else {
+		history, err = prompt.GetMessagesFromFilename(promptstr)
+		if err != nil {
+			fmtf.Printf("prompt.GetMessagesFromFilename error: %v\n", err)
+		}
+	}
+
+	// 获取历史信息
+	if msg.ParentMessageID != "" {
+		userhistory, err := app.getHistory(msg.ConversationID, msg.ParentMessageID)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+
+		// 截断历史信息
+		userHistory := truncateHistoryGpt(userhistory, msg.Text, promptstr)
+
+		if promptstr != "" {
+			// 注意追加的顺序,确保问题在系统提示词之后
+			// 使用...操作符来展开userhistory切片并追加到history切片
+			// 获取系统级预埋的系统自定义QA对
+			systemHistory, err := prompt.GetMessagesExcludingSystem(promptstr)
+			if err != nil {
+				fmtf.Printf("Error getting system history: %v\n", err)
+				return
+			}
+
+			// 处理增强QA逻辑
+			if config.GetEnhancedQA(promptstr) {
+				// 确保系统历史与用户或助手历史数量一致,如果不足,则补足空的历史记录
+				// 因为最后一个成员让给当前QA,所以-1
+				if len(systemHistory)-2 > len(userHistory) {
+					difference := len(systemHistory) - len(userHistory)
+					for i := 0; i < difference; i++ {
+						userHistory = append(userHistory, structs.Message{Text: "", Role: "user"})
+						userHistory = append(userHistory, structs.Message{Text: "", Role: "assistant"})
+					}
+				}
+
+				// 如果系统历史中只有一个成员,跳过覆盖逻辑,留给后续处理
+				if len(systemHistory) > 1 {
+					// 将系统历史(除最后2个成员外)附加到相应的用户或助手历史上,采用倒序方式处理最近的记录
+					for i := 0; i < len(systemHistory)-2; i++ {
+						sysMsg := systemHistory[i]
+						index := len(userHistory) - len(systemHistory) + i
+						if index >= 0 && index < len(userHistory) && (userHistory[index].Role == "user" || userHistory[index].Role == "assistant") {
+							userHistory[index].Text += fmt.Sprintf(" (%s)", sysMsg.Text)
+						}
+					}
+				}
+			} else {
+				// 将系统级别QA简单的附加在用户对话前方的位置(ai会知道,但不会主动引导)
+				history = append(history, systemHistory...)
+			}
+
+			// 留下最后一个systemHistory成员进行后续处理
+		}
+
+		// 添加用户历史到总历史中
+		history = append(history, userHistory...)
+	}
+
+	apiURL := config.GetYuanqiApiPath(promptstr)
+	token := config.GetYuanqiToken()
+	fmtf.Printf("YuanQi上下文history:%v\n", history)
+
+	// 构建请求到yuanqi API的请求体
+	var requestBody structs.RequestDataYuanQi
+
+	messages := make([]structs.MessageContent, 0, len(history)+1)
+	// 处理历史消息
+	for _, hMsg := range history {
+		messageContent := structs.MessageContent{
+			Role: hMsg.Role,
+			Content: []structs.ContentItem{{
+				Type: "text",
+				Text: hMsg.Text,
+			}},
+		}
+		messages = append(messages, messageContent)
+	}
+
+	// 添加当前用户消息
+	currentMessageContent := structs.MessageContent{
+		Role: "user",
+		Content: []structs.ContentItem{{
+			Type: "text",
+			Text: msg.Text,
+		}},
+	}
+	messages = append(messages, currentMessageContent)
+
+	// 创建请求数据结构体
+	requestBody = structs.RequestDataYuanQi{
+		AssistantID: config.GetYuanqiAssistantID(promptstr),
+		UserID:      useridstr,
+		Stream:      config.GetuseSse(promptstr),
+		ChatType:    config.GetYuanqiChatType(promptstr),
+		Messages:    messages,
+	}
+
+	requestBodyJSON, _ := json.Marshal(requestBody)
+
+	fmtf.Printf("yuanqi requestBody :%v", string(requestBodyJSON))
+
+	// 获取代理服务器地址
+	proxyURL := config.GetProxy(promptstr)
+	if err != nil {
+		http.Error(w, fmtf.Sprintf("Failed to get proxy: %v", err), http.StatusInternalServerError)
+		return
+	}
+
+	client := &http.Client{}
+
+	// 检查是否有有效的代理地址
+	if proxyURL != "" {
+		proxy, err := url.Parse(proxyURL)
+		if err != nil {
+			http.Error(w, fmtf.Sprintf("Failed to parse proxy URL: %v", err), http.StatusInternalServerError)
+			return
+		}
+
+		// 配置客户端使用代理
+		client.Transport = &http.Transport{
+			Proxy: http.ProxyURL(proxy),
+		}
+	}
+
+	// 创建HTTP请求
+	req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(requestBodyJSON))
+	if err != nil {
+		http.Error(w, fmtf.Sprintf("Failed to create request: %v", err), http.StatusInternalServerError)
+		return
+	}
+
+	req.Header.Set("Content-Type", "application/json")
+	req.Header.Set("X-Source", "openapi")
+	req.Header.Set("Authorization", fmtf.Sprintf("Bearer %s", token))
+
+	// 发送请求
+	resp, err := client.Do(req)
+	if err != nil {
+		http.Error(w, fmtf.Sprintf("Error sending request to ChatGPT API: %v", err), http.StatusInternalServerError)
+		return
+	}
+	defer resp.Body.Close()
+
+	if !config.GetuseSse(promptstr) {
+		// 处理响应
+		responseBody, err := io.ReadAll(resp.Body)
+		if err != nil {
+			http.Error(w, fmtf.Sprintf("Failed to read response body: %v", err), http.StatusInternalServerError)
+			return
+		}
+		fmtf.Printf("yuanqi返回:%v", string(responseBody))
+		// 假设已经成功发送请求并获得响应,responseBody是响应体的字节数据
+		var apiResponse struct {
+			Choices []struct {
+				Message struct {
+					Content string `json:"content"`
+				} `json:"message"`
+			} `json:"choices"`
+		}
+		if err := json.Unmarshal(responseBody, &apiResponse); err != nil {
+			http.Error(w, fmtf.Sprintf("Error unmarshaling API response: %v", err), http.StatusInternalServerError)
+			return
+		}
+
+		// 从API响应中获取回复文本
+		responseText := ""
+		if len(apiResponse.Choices) > 0 {
+			responseText = apiResponse.Choices[0].Message.Content
+		}
+
+		// 添加助理消息
+		assistantMessageID, err := app.addMessage(structs.Message{
+			ConversationID:  msg.ConversationID,
+			ParentMessageID: userMessageID,
+			Text:            responseText,
+			Role:            "assistant",
+		})
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+
+		// 构造响应数据,包括回复文本、对话ID、消息ID,以及使用情况(用例中未计算,可根据需要添加)
+		responseMap := map[string]interface{}{
+			"response":       responseText,
+			"conversationId": msg.ConversationID,
+			"messageId":      assistantMessageID,
+			// 在此实际使用情况中,应该有逻辑来填充totalUsage
+			// 此处仅为示例,根据实际情况来调整
+			"details": map[string]interface{}{
+				"usage": structs.UsageInfo{
+					PromptTokens:     0, // 示例值,需要根据实际情况计算
+					CompletionTokens: 0, // 示例值,需要根据实际情况计算
+				},
+			},
+		}
+
+		// 设置响应头部为JSON格式
+		w.Header().Set("Content-Type", "application/json")
+		// 将响应数据编码为JSON并发送
+		if err := json.NewEncoder(w).Encode(responseMap); err != nil {
+			http.Error(w, fmtf.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError)
+			return
+		}
+	} else {
+		// 设置SSE相关的响应头部
+		w.Header().Set("Content-Type", "text/event-stream")
+		w.Header().Set("Cache-Control", "no-cache")
+		w.Header().Set("Connection", "keep-alive")
+
+		flusher, ok := w.(http.Flusher)
+		if !ok {
+			http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
+			return
+		}
+
+		reader := bufio.NewReader(resp.Body)
+		var responseTextBuilder strings.Builder
+		var totalUsage structs.GPTUsageInfo
+		if config.GetGptSseType() == 1 {
+			for {
+				line, err := reader.ReadString('\n')
+				if err != nil {
+					if err == io.EOF {
+						break // 流结束
+					}
+					// 处理错误
+					fmtf.Fprintf(w, "data: %s\n\n", fmtf.Sprintf("读取流数据时发生错误: %v", err))
+					flusher.Flush()
+					continue
+				}
+
+				if strings.HasPrefix(line, "data: ") {
+					eventDataJSON := line[5:] // 去掉"data: "前缀
+
+					// 解析JSON数据
+					var eventData structs.GPTEventData
+					if err := json.Unmarshal([]byte(eventDataJSON), &eventData); err != nil {
+						fmtf.Fprintf(w, "data: %s\n\n", fmtf.Sprintf("解析事件数据出错: %v", err))
+						flusher.Flush()
+						continue
+					}
+
+					// 遍历choices数组,累积所有文本内容
+					for _, choice := range eventData.Choices {
+						responseTextBuilder.WriteString(choice.Delta.Content)
+					}
+
+					// 如果存在需要发送的临时响应数据(例如,在事件流中间点)
+					// 注意:这里暂时省略了使用信息的处理,因为示例输出中没有包含这部分数据
+					tempResponseMap := map[string]interface{}{
+						"response":       responseTextBuilder.String(),
+						"conversationId": msg.ConversationID, // 确保msg.ConversationID已经定义并初始化
+						// "details" 字段留待进一步处理,如有必要
+					}
+					tempResponseJSON, _ := json.Marshal(tempResponseMap)
+					fmtf.Fprintf(w, "data: %s\n\n", string(tempResponseJSON))
+					flusher.Flush()
+				}
+			}
+		} else {
+			for {
+				line, err := reader.ReadString('\n')
+				if err != nil {
+					if err == io.EOF {
+						break // 流结束
+					}
+					fmtf.Fprintf(w, "data: %s\n\n", fmtf.Sprintf("读取流数据时发生错误: %v", err))
+					flusher.Flush()
+					continue
+				}
+
+				if strings.HasPrefix(line, "data: ") {
+					eventDataJSON := line[5:] // 去掉"data: "前缀
+					if eventDataJSON[1] != '{' {
+						fmtf.Println("非JSON数据,跳过:", eventDataJSON)
+						continue
+					}
+
+					var eventData structs.GPTEventData
+					if err := json.Unmarshal([]byte(eventDataJSON), &eventData); err != nil {
+						fmtf.Fprintf(w, "data: %s\n\n", fmtf.Sprintf("解析事件数据出错: %v", err))
+						flusher.Flush()
+						continue
+					}
+
+					// 在修改共享资源之前锁定Mutex
+					mutexyuanqi.Lock()
+
+					conversationId := eventData.ID // 假设conversationId从事件数据的ID字段获取
+					// 储存eventData.ID 和 msg.ConversationID 对应关系
+					conversationMapYQ.Store(msg.ConversationID, conversationId)
+					//读取完整信息
+					completeResponse, _ := lastCompleteResponsesYQ.LoadOrStore(conversationId, "")
+
+					// 检索上一次的响应文本
+					lastResponse, _ := lastResponsesYQ.LoadOrStore(conversationId, "")
+					lastResponseText := lastResponse.(string)
+
+					newContent := ""
+					for _, choice := range eventData.Choices {
+						// 如果新内容以旧内容开头
+						if strings.HasPrefix(choice.Delta.Content, lastResponseText) {
+							// 特殊情况:当新内容和旧内容完全相同时,处理逻辑应当与新内容不以旧内容开头时相同
+							if choice.Delta.Content == lastResponseText {
+								newContent += choice.Delta.Content
+							} else {
+								// 剔除旧内容部分,只保留新增的部分
+								newContent += choice.Delta.Content[len(lastResponseText):]
+							}
+						} else {
+							// 如果新内容不以旧内容开头,可能是并发情况下的新消息,直接使用新内容
+							newContent += choice.Delta.Content
+						}
+					}
+
+					// 更新存储的完整累积信息
+					updatedCompleteResponse := completeResponse.(string) + newContent
+					lastCompleteResponsesYQ.Store(conversationId, updatedCompleteResponse)
+
+					// 使用累加的新内容更新存储的最后响应状态
+					if newContent != "" {
+						lastResponsesYQ.Store(conversationId, newContent)
+					}
+
+					// 完成修改后解锁Mutex
+					mutexyuanqi.Unlock()
+
+					// 发送新增的内容
+					if newContent != "" {
+						tempResponseMap := map[string]interface{}{
+							"response":       newContent,
+							"conversationId": msg.ConversationID,
+						}
+						tempResponseJSON, _ := json.Marshal(tempResponseMap)
+						fmtf.Fprintf(w, "data: %s\n\n", string(tempResponseJSON))
+						flusher.Flush()
+					}
+				}
+			}
+		}
+		//一点点奇怪的转换
+		conversationId, _ := conversationMapYQ.LoadOrStore(msg.ConversationID, "")
+		completeResponse, _ := lastCompleteResponsesYQ.LoadOrStore(conversationId, "")
+		// 在所有事件处理完毕后发送最终响应
+		assistantMessageID, err := app.addMessage(structs.Message{
+			ConversationID:  msg.ConversationID,
+			ParentMessageID: userMessageID,
+			Text:            completeResponse.(string),
+			Role:            "assistant",
+		})
+
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+
+		// 在所有事件处理完毕后发送最终响应
+		finalResponseMap := map[string]interface{}{
+			"response":       completeResponse.(string),
+			"conversationId": msg.ConversationID,
+			"messageId":      assistantMessageID,
+			"details": map[string]interface{}{
+				"usage": totalUsage,
+			},
+		}
+
+		finalResponseJSON, _ := json.Marshal(finalResponseMap)
+		fmtf.Fprintf(w, "data: %s\n\n", string(finalResponseJSON))
+		flusher.Flush()
+	}
+
+}
diff --git a/config/config.go b/config/config.go
index cb2f2f9..51d4b0f 100644
--- a/config/config.go
+++ b/config/config.go
@@ -2880,3 +2880,178 @@ func getTemperatureHunyuanInternal(options ...string) float64 {
 
 	return value
 }
+
+// 获取助手ID
+func GetYuanqiAssistantID(options ...string) string {
+	mu.Lock()
+	defer mu.Unlock()
+	return getYuanqiAssistantIDInternal(options...)
+}
+
+func getYuanqiAssistantIDInternal(options ...string) string {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.YuanqiAssistantID
+		}
+		return "" // 默认值或错误处理
+	}
+
+	basename := options[0]
+	assistantIDInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiAssistantID")
+	if err != nil {
+		log.Println("Error retrieving YuanqiAssistantID:", err)
+		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	assistantID, ok := assistantIDInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for YuanqiAssistantID, fetching default")
+		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	if assistantID == "" {
+		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return assistantID
+}
+
+// 获取Token
+func GetYuanqiToken(options ...string) string {
+	mu.Lock()
+	defer mu.Unlock()
+	return getYuanqiTokenInternal(options...)
+}
+
+func getYuanqiTokenInternal(options ...string) string {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.YuanqiToken
+		}
+		return "" // 默认值或错误处理
+	}
+
+	basename := options[0]
+	YuanqiTokenInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiToken")
+	if err != nil {
+		log.Println("Error retrieving YuanqiToken:", err)
+		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	YuanqiToken, ok := YuanqiTokenInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for YuanqiToken, fetching default")
+		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	if YuanqiToken == "" {
+		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return YuanqiToken
+}
+
+// 获取助手版本
+func GetYuanqiVersion(options ...string) float64 {
+	mu.Lock()
+	defer mu.Unlock()
+	return getYuanqiVersionInternal(options...)
+}
+
+func getYuanqiVersionInternal(options ...string) float64 {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.YuanqiVersion
+		}
+		return 0.0 // 默认值或错误处理
+	}
+
+	basename := options[0]
+	versionInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiVersion")
+	if err != nil {
+		log.Println("Error retrieving YuanqiVersion:", err)
+		return getYuanqiVersionInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	version, ok := versionInterface.(float64)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for YuanqiVersion, fetching default")
+		return getYuanqiVersionInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	if version == 0 {
+		return getYuanqiVersionInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return version
+}
+
+// 获取聊天类型
+func GetYuanqiChatType(options ...string) string {
+	mu.Lock()
+	defer mu.Unlock()
+	return getYuanqiChatTypeInternal(options...)
+}
+
+func getYuanqiChatTypeInternal(options ...string) string {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.YuanqiChatType
+		}
+		return "published" // 默认值或错误处理
+	}
+
+	basename := options[0]
+	chatTypeInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiChatType")
+	if err != nil {
+		log.Println("Error retrieving YuanqiChatType:", err)
+		return getYuanqiChatTypeInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	chatType, ok := chatTypeInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for YuanqiChatType, fetching default")
+		return getYuanqiChatTypeInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	if chatType == "" {
+		return getYuanqiChatTypeInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return chatType
+}
+
+// 获取API地址
+func GetYuanqiApiPath(options ...string) string {
+	mu.Lock()
+	defer mu.Unlock()
+	return getYuanqiApiPathInternal(options...)
+}
+
+func getYuanqiApiPathInternal(options ...string) string {
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.YuanqiApiPath
+		}
+		return "https://open.hunyuan.tencent.com/openapi/v1/agent/chat/completion" // 默认值或错误处理
+	}
+
+	basename := options[0]
+	chatTypeInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiApiPath")
+	if err != nil {
+		log.Println("Error retrieving YuanqiApiPath:", err)
+		return getYuanqiApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	YuanqiApiPath, ok := chatTypeInterface.(string)
+	if !ok { // 检查类型断言是否失败
+		log.Println("Type assertion failed for YuanqiApiPath, fetching default")
+		return getYuanqiApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	if YuanqiApiPath == "" {
+		return getYuanqiApiPathInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return YuanqiApiPath
+}
diff --git a/main.go b/main.go
index 7de4084..0ae4314 100644
--- a/main.go
+++ b/main.go
@@ -155,6 +155,9 @@ func main() {
 	case 5:
 		// 如果API类型是5,使用app.chatHandlerGlm
 		http.HandleFunc("/conversation", app.ChatHandlerGlm)
+	case 6:
+		// 如果API类型是6,使用app.ChatHandlerYuanQi
+		http.HandleFunc("/conversation", app.ChatHandlerYuanQi)
 	default:
 		// 如果是其他值,可以选择一个默认的处理器或者记录一个错误
 		log.Printf("Unknown API type: %d", apiType)
@@ -167,6 +170,7 @@ func main() {
 		http.HandleFunc("/conversation_rwkv", app.ChatHandlerRwkv)
 		http.HandleFunc("/conversation_tyqw", app.ChatHandlerTyqw)
 		http.HandleFunc("/conversation_glm", app.ChatHandlerGlm)
+		http.HandleFunc("/conversation_yq", app.ChatHandlerYuanQi)
 	}
 	if config.GetSelfPath() != "" {
 		rateLimiter := server.NewRateLimiter()
diff --git a/structs/struct.go b/structs/struct.go
index 3c9cebd..856598c 100644
--- a/structs/struct.go
+++ b/structs/struct.go
@@ -395,6 +395,14 @@ type Settings struct {
 	GlmToolChoice  string   `yaml:"glmToolChoice"`  // 工具选择策略
 	GlmUserID      string   `yaml:"glmUserID"`      // 用户ID
 
+	YuanqiApiPath     string  `yaml:"yuanqiApiPath"`     // 元器api地址
+	YuanqiAssistantID string  `yaml:"yuanqiAssistantID"` // 助手ID
+	YuanqiVersion     float64 `yaml:"yuanqiVersion"`     // 助手版本, 仅对内部开放
+	YuanqiUserID      string  `yaml:"yuanqiUserID"`      // 用户ID,调用者业务侧的用户ID,会影响智能体的数据统计,建议按实际情况填写
+	YuanqiStream      bool    `yaml:"yuanqiStream"`      // 是否启用流式返回,默认为false
+	YuanqiChatType    string  `yaml:"yuanqiChatType"`    // 聊天类型,默认为published,preview时使用草稿态智能体,仅对内部开放
+	YuanqiToken       string  `yaml:"yuanqiToken"`       // Token
+
 	WSServerToken string `yaml:"wsServerToken"`
 	WSPath        string `yaml:"wsPath"`
 
diff --git a/structs/yuanqi.go b/structs/yuanqi.go
new file mode 100644
index 0000000..94d7144
--- /dev/null
+++ b/structs/yuanqi.go
@@ -0,0 +1,26 @@
+package structs
+
+type ContentItem struct {
+	Type    string   `json:"type,omitempty"`     // "text" or "file_url"
+	Text    string   `json:"text,omitempty"`     // 文本内容
+	FileURL *FileURL `json:"file_url,omitempty"` // 文件内容
+}
+
+type FileURL struct {
+	Type string `json:"type"` // 文件类型: image, video, audio, pdf, doc, txt 等
+	URL  string `json:"url"`  // 文件的URL地址
+}
+
+type MessageContent struct {
+	Role    string        `json:"role"`    // "user" 或 "assistant"
+	Content []ContentItem `json:"content"` // 内容列表
+}
+
+type RequestDataYuanQi struct {
+	AssistantID string           `json:"assistant_id"`        // 助手ID
+	Version     float64          `json:"version,omitempty"`   // 助手版本
+	UserID      string           `json:"user_id"`             // 用户ID
+	Stream      bool             `json:"stream"`              // 是否启用流式返回
+	ChatType    string           `json:"chat_type,omitempty"` // 聊天类型
+	Messages    []MessageContent `json:"messages"`            // 消息历史和当前消息
+}
diff --git a/template/config_template.go b/template/config_template.go
index d258476..9b27cb8 100644
--- a/template/config_template.go
+++ b/template/config_template.go
@@ -13,7 +13,7 @@ settings:
   paths : []                                    #当要连接多个onebotv11的http正向地址时,多个地址填入这里.
   lotus : ""                                    #当填写另一个gensokyo-llm的http地址时,将请求另一个的conversation端点,实现多个llm不需要多次配置,简化配置,单独使用请忽略留空.例:http://192.168.0.1:12345(包含http头和端口)
   pathToken : ""                                #gensokyo正向http-api的access_token(是onebotv11标准的)
-  apiType : 0                                   #0=混元 1=文心(文心平台包含了N种模型...) 2=gpt 3=rwkv 4=通义千问 5=智谱AI
+  apiType : 0                                   #0=混元 1=文心(文心平台包含了N种模型...) 2=gpt 3=rwkv 4=通义千问 5=智谱AI 6=腾讯元器
   iPWhiteList : ["192.168.0.102"]               #接口调用,安全ip白名单,gensokyo的ip地址,或调用api的程序的ip地址
   systemPrompt : [""]                           #人格提示词,或多个随机
   firstQ : [""]                                 #强化思想钢印,在每次对话的system之前固定一个QA,需都填写内容,会增加token消耗,可一定程度提高人格提示词效果,或抵抗催眠
@@ -184,6 +184,12 @@ settings:
     - "web_search"                                 # 默认启用网络搜索工具
   glmToolChoice: "auto"                            # 工具选择策略,目前支持auto,自动选择最合适的工具
   glmUserID: ""                                    # 用户唯一标识,用于跟踪和分析用户行为
+
+  # Yuanqi 助手配置文件,确保按业务需求配置。
+  yuanqiApiPath: "https://open.hunyuan.tencent.com/openapi/v1/agent/chat/completions"
+  yuanqiAssistantID: ""         # 助手ID,唯一标识您的助手实例
+  yuanqiToken: ""               # 元器Token
+  yuanqiChatType: "published"   # 聊天类型,默认为published,支持preview模式下使用草稿态智能体
 `
 
 const Logo = `

From dfc18f70447ad5a6ee17dcb3f154efe7d4e84b73 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Fri, 24 May 2024 14:35:46 +0800
Subject: [PATCH 16/24] Beta129 (#128)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129
---
 applogic/yuanqi.go |  2 +-
 config/config.go   | 12 ++++++------
 prompt/prompt.go   |  2 +-
 utils/utils.go     |  5 +++++
 4 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/applogic/yuanqi.go b/applogic/yuanqi.go
index 542933c..7b2f61c 100644
--- a/applogic/yuanqi.go
+++ b/applogic/yuanqi.go
@@ -192,7 +192,7 @@ func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) {
 	}
 
 	apiURL := config.GetYuanqiApiPath(promptstr)
-	token := config.GetYuanqiToken()
+	token := config.GetYuanqiToken(promptstr)
 	fmtf.Printf("YuanQi上下文history:%v\n", history)
 
 	// 构建请求到yuanqi API的请求体
diff --git a/config/config.go b/config/config.go
index 51d4b0f..dff4434 100644
--- a/config/config.go
+++ b/config/config.go
@@ -65,7 +65,7 @@ func loadConfigFromFile(path string) (*Config, error) {
 
 	conf := &Config{}
 	if err := yaml.Unmarshal(configData, conf); err != nil {
-		log.Println("Failed to unmarshal YAML:", err)
+		log.Printf("failed to unmarshal YAML[%v]:%v", path, err)
 		return nil, err
 	}
 
@@ -2897,7 +2897,7 @@ func getYuanqiAssistantIDInternal(options ...string) string {
 	}
 
 	basename := options[0]
-	assistantIDInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiAssistantID")
+	assistantIDInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiAssistantID")
 	if err != nil {
 		log.Println("Error retrieving YuanqiAssistantID:", err)
 		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
@@ -2932,7 +2932,7 @@ func getYuanqiTokenInternal(options ...string) string {
 	}
 
 	basename := options[0]
-	YuanqiTokenInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiToken")
+	YuanqiTokenInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiToken")
 	if err != nil {
 		log.Println("Error retrieving YuanqiToken:", err)
 		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
@@ -2967,7 +2967,7 @@ func getYuanqiVersionInternal(options ...string) float64 {
 	}
 
 	basename := options[0]
-	versionInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiVersion")
+	versionInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiVersion")
 	if err != nil {
 		log.Println("Error retrieving YuanqiVersion:", err)
 		return getYuanqiVersionInternal() // 递归调用内部函数,不传递任何参数
@@ -3002,7 +3002,7 @@ func getYuanqiChatTypeInternal(options ...string) string {
 	}
 
 	basename := options[0]
-	chatTypeInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiChatType")
+	chatTypeInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiChatType")
 	if err != nil {
 		log.Println("Error retrieving YuanqiChatType:", err)
 		return getYuanqiChatTypeInternal() // 递归调用内部函数,不传递任何参数
@@ -3037,7 +3037,7 @@ func getYuanqiApiPathInternal(options ...string) string {
 	}
 
 	basename := options[0]
-	chatTypeInterface, err := prompt.GetSettingFromFilename(basename, "yuanqiApiPath")
+	chatTypeInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiApiPath")
 	if err != nil {
 		log.Println("Error retrieving YuanqiApiPath:", err)
 		return getYuanqiApiPathInternal() // 递归调用内部函数,不传递任何参数
diff --git a/prompt/prompt.go b/prompt/prompt.go
index 1892f24..c87c51f 100644
--- a/prompt/prompt.go
+++ b/prompt/prompt.go
@@ -129,7 +129,7 @@ func loadFile(filename string) {
 	var prompts PromptFile
 	err = yaml.Unmarshal(data, &prompts)
 	if err != nil {
-		log.Println("Failed to unmarshal YAML:", err)
+		log.Printf("failed to unmarshal YAML[%v]:%v", filename, err)
 		return
 	}
 
diff --git a/utils/utils.go b/utils/utils.go
index f543ef5..4c92a77 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -1119,6 +1119,11 @@ func SendSSEPrivateRestoreMessage(userID int64, RestoreResponse string) {
 
 // LanguageIntercept 检查文本语言,如果不在允许列表中,则返回 true 并发送消息
 func LanguageIntercept(text string, message structs.OnebotGroupMessage, selfid string) bool {
+	hintWords := config.GetGroupHintWords()
+	// 遍历所有触发词,将其从文本中剔除
+	for _, word := range hintWords {
+		text = strings.Replace(text, word, "", -1)
+	}
 	info := whatlanggo.Detect(text)
 	lang := whatlanggo.LangToString(info.Lang)
 	fmtf.Printf("LanguageIntercept:%v\n", lang)

From 38c3f7d20b9467c3cf163807712c877a3aed5109 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Fri, 24 May 2024 14:54:55 +0800
Subject: [PATCH 17/24] Beta130 (#129)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130
---
 prompt/prompt.go | 28 ++++++----------------------
 1 file changed, 6 insertions(+), 22 deletions(-)

diff --git a/prompt/prompt.go b/prompt/prompt.go
index c87c51f..b4b2ca4 100644
--- a/prompt/prompt.go
+++ b/prompt/prompt.go
@@ -9,7 +9,6 @@ import (
 	"reflect"
 	"strings"
 	"sync"
-	"time"
 
 	"github.com/fsnotify/fsnotify"
 
@@ -41,23 +40,6 @@ func init() {
 	}
 }
 
-// 防抖
-type FileLoader struct {
-	eventDelay time.Duration
-	lastLoad   time.Time
-	fileName   string
-}
-
-func (fl *FileLoader) LoadFile(event fsnotify.Event) {
-	now := time.Now()
-	if now.Sub(fl.lastLoad) < fl.eventDelay {
-		return
-	}
-	fl.lastLoad = now
-	fl.fileName = event.Name
-	loadFile(event.Name)
-}
-
 // LoadPrompts 确保目录存在并尝试加载提示词文件
 func LoadPrompts() error {
 	// 构建目录路径
@@ -86,9 +68,6 @@ func LoadPrompts() error {
 		return err
 	}
 
-	// 添加一个100毫秒的Debouncing
-	fileLoader := &FileLoader{eventDelay: 100 * time.Millisecond}
-
 	go func() {
 		for {
 			select {
@@ -97,7 +76,7 @@ func LoadPrompts() error {
 					return
 				}
 				if event.Op&fsnotify.Write == fsnotify.Write {
-					fileLoader.LoadFile(event)
+					loadFile(event.Name)
 				}
 			case err, ok := <-watcher.Errors:
 				if !ok {
@@ -134,6 +113,11 @@ func loadFile(filename string) {
 	}
 
 	baseName := filepath.Base(filename)
+	if len(prompts.Prompts) == 0 {
+		fmt.Printf("prompts[%v][%v]载入中\n", baseName, filename)
+		return
+	}
+
 	promptsCache[baseName] = prompts
 	fmt.Printf("成功载入prompts[%v]\n", baseName)
 }

From da306c289239f0b8c1402f675e44d5a4e1e7262f Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Mon, 27 May 2024 17:46:49 +0800
Subject: [PATCH 18/24] Beta131 (#130)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130

* beta131
---
 applogic/gensokyo.go        | 22 ++++++++++++++++++++--
 template/config_template.go |  2 +-
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index e3c2e9a..43e48dd 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -228,6 +228,24 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		fmt.Printf("收到api参数: %s\n", api)
 	}
 
+	// 从URL查询参数中获取skip_lang_check
+	skipLangCheckStr := r.URL.Query().Get("skip_lang_check")
+
+	// 默认skipLangCheck为false
+	skipLangCheck := false
+
+	if skipLangCheckStr != "" {
+		// 尝试将获取的字符串转换为布尔值
+		var err error
+		skipLangCheck, err = strconv.ParseBool(skipLangCheckStr)
+		if err != nil {
+			// 如果转换出错,向客户端返回错误消息
+			fmt.Fprintf(w, "Invalid skip_lang_check value: %s", skipLangCheckStr)
+			return
+		}
+		fmt.Printf("收到 skip_lang_check 参数: %v\n", skipLangCheck)
+	}
+
 	// 打印日志信息,包括prompt参数
 	fmtf.Printf("收到onebotv11信息: %+v\n", string(body))
 
@@ -335,8 +353,8 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 
-		// 进行语言判断拦截
-		if len(config.GetAllowedLanguages()) > 0 {
+		// 进行语言判断拦截 skipLangCheck为false时
+		if len(config.GetAllowedLanguages()) > 0 && !skipLangCheck {
 			if utils.LanguageIntercept(newmsg, message, selfid) {
 				fmtf.Printf("不安全!不支持的语言,可在config.yml设置允许的语言,allowedLanguages配置项,Q: %v", newmsg)
 				// 发送响应
diff --git a/template/config_template.go b/template/config_template.go
index 9b27cb8..5d0be0e 100644
--- a/template/config_template.go
+++ b/template/config_template.go
@@ -61,7 +61,7 @@ settings:
   #]
 
   #语言过滤
-  allowedLanguages : ["cmn"]                    #根据自身安全实力,酌情过滤,cmn代表中文,小写字母,[]空数组代表不限制.
+  allowedLanguages : ["cmn"]                    #根据自身安全实力,酌情过滤,cmn代表中文,小写字母,[]空数组代表不限制. /gensokyo api 可传参数skip_lang_check=true让某些信息跳过检查
   langResponseMessages : ["抱歉,我不会**这个语言呢","我不会**这门语言,请使用中文和我对话吧"]   #定型文,**会自动替换为检测到的语言
   questionMaxLenth : 100                        #最大问题字数. 0代表不限制
   qmlResponseMessages : ["问题太长了,缩短问题试试吧"]  #最大问题长度回复.

From f7d60c1af9473cf099b070dd14f5fe7b9715de3d Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Mon, 27 May 2024 22:31:00 +0800
Subject: [PATCH 19/24] Beta132 (#131)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130

* beta131

* beta132
---
 applogic/yuanqi.go |  3 +++
 utils/utils.go     | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/applogic/yuanqi.go b/applogic/yuanqi.go
index 7b2f61c..d9b04d5 100644
--- a/applogic/yuanqi.go
+++ b/applogic/yuanqi.go
@@ -221,6 +221,9 @@ func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) {
 	}
 	messages = append(messages, currentMessageContent)
 
+	// 保持QA顺序 即使用户发送多张图片
+	messages = utils.MakeAlternating(messages)
+
 	// 创建请求数据结构体
 	requestBody = structs.RequestDataYuanQi{
 		AssistantID: config.GetYuanqiAssistantID(promptstr),
diff --git a/utils/utils.go b/utils/utils.go
index 4c92a77..9371903 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -1340,3 +1340,39 @@ func DeleteLatestMessage(messageType string, id int64, userid int64) error {
 	// 发送删除消息请求
 	return sendDeleteRequest(u.String(), requestBodyBytes)
 }
+
+// MakeAlternating ensures that roles alternate between "user" and "assistant".
+func MakeAlternating(messages []structs.MessageContent) []structs.MessageContent {
+	if len(messages) < 2 {
+		return messages // Not enough messages to need alternation or check
+	}
+
+	// Initialize placeholders for the last seen user and assistant content
+	var lastUserContent, lastAssistantContent []structs.ContentItem
+
+	correctedMessages := make([]structs.MessageContent, 0, len(messages))
+	expectedRole := "user" // Start expecting "user" initially; this changes as we find roles
+
+	for _, message := range messages {
+		if message.Role != expectedRole {
+			// If the current message does not match the expected role, insert the last seen content of the expected role
+			if expectedRole == "user" && lastUserContent != nil {
+				correctedMessages = append(correctedMessages, structs.MessageContent{Role: "user", Content: lastUserContent})
+			} else if expectedRole == "assistant" && lastAssistantContent != nil {
+				correctedMessages = append(correctedMessages, structs.MessageContent{Role: "assistant", Content: lastAssistantContent})
+			}
+		}
+
+		// Append the current message and update last seen contents
+		correctedMessages = append(correctedMessages, message)
+		if message.Role == "user" {
+			lastUserContent = message.Content
+			expectedRole = "assistant"
+		} else if message.Role == "assistant" {
+			lastAssistantContent = message.Content
+			expectedRole = "user"
+		}
+	}
+
+	return correctedMessages
+}

From 85d7fc442d6d55f5d90b05915166a620dc79f48d Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Tue, 28 May 2024 23:23:00 +0800
Subject: [PATCH 20/24] Beta133 (#132)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130

* beta131

* beta132

* beta1333
---
 applogic/yuanqi.go          |   5 +-
 config/config.go            | 142 ++++++++++++++++++++++++------------
 structs/struct.go           |  19 +++--
 template/config_template.go |  10 ++-
 4 files changed, 118 insertions(+), 58 deletions(-)

diff --git a/applogic/yuanqi.go b/applogic/yuanqi.go
index d9b04d5..6479149 100644
--- a/applogic/yuanqi.go
+++ b/applogic/yuanqi.go
@@ -192,7 +192,8 @@ func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) {
 	}
 
 	apiURL := config.GetYuanqiApiPath(promptstr)
-	token := config.GetYuanqiToken(promptstr)
+
+	assistantID, token := config.GetYuanqiConf(promptstr)
 	fmtf.Printf("YuanQi上下文history:%v\n", history)
 
 	// 构建请求到yuanqi API的请求体
@@ -226,7 +227,7 @@ func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) {
 
 	// 创建请求数据结构体
 	requestBody = structs.RequestDataYuanQi{
-		AssistantID: config.GetYuanqiAssistantID(promptstr),
+		AssistantID: assistantID,
 		UserID:      useridstr,
 		Stream:      config.GetuseSse(promptstr),
 		ChatType:    config.GetYuanqiChatType(promptstr),
diff --git a/config/config.go b/config/config.go
index dff4434..ef2a01c 100644
--- a/config/config.go
+++ b/config/config.go
@@ -2881,74 +2881,122 @@ func getTemperatureHunyuanInternal(options ...string) float64 {
 	return value
 }
 
-// 获取助手ID
-func GetYuanqiAssistantID(options ...string) string {
-	mu.Lock()
-	defer mu.Unlock()
-	return getYuanqiAssistantIDInternal(options...)
-}
+// // 获取助手ID
+// func GetYuanqiAssistantID(options ...string) string {
+// 	mu.Lock()
+// 	defer mu.Unlock()
+// 	return getYuanqiAssistantIDInternal(options...)
+// }
 
-func getYuanqiAssistantIDInternal(options ...string) string {
-	if len(options) == 0 || options[0] == "" {
-		if instance != nil {
-			return instance.Settings.YuanqiAssistantID
-		}
-		return "" // 默认值或错误处理
-	}
+// func getYuanqiAssistantIDInternal(options ...string) string {
+// 	if len(options) == 0 || options[0] == "" {
+// 		if instance != nil {
+// 			return instance.Settings.YuanqiAssistantID
+// 		}
+// 		return "" // 默认值或错误处理
+// 	}
 
-	basename := options[0]
-	assistantIDInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiAssistantID")
-	if err != nil {
-		log.Println("Error retrieving YuanqiAssistantID:", err)
-		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
-	}
+// 	basename := options[0]
+// 	assistantIDInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiAssistantID")
+// 	if err != nil {
+// 		log.Println("Error retrieving YuanqiAssistantID:", err)
+// 		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
+// 	}
 
-	assistantID, ok := assistantIDInterface.(string)
-	if !ok { // 检查类型断言是否失败
-		log.Println("Type assertion failed for YuanqiAssistantID, fetching default")
-		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
-	}
+// 	assistantID, ok := assistantIDInterface.(string)
+// 	if !ok { // 检查类型断言是否失败
+// 		log.Println("Type assertion failed for YuanqiAssistantID, fetching default")
+// 		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
+// 	}
 
-	if assistantID == "" {
-		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
-	}
+// 	if assistantID == "" {
+// 		return getYuanqiAssistantIDInternal() // 递归调用内部函数,不传递任何参数
+// 	}
 
-	return assistantID
-}
+// 	return assistantID
+// }
+
+// // 获取Token
+// func GetYuanqiToken(options ...string) string {
+// 	mu.Lock()
+// 	defer mu.Unlock()
+// 	return getYuanqiTokenInternal(options...)
+// }
+
+// func getYuanqiTokenInternal(options ...string) string {
+// 	if len(options) == 0 || options[0] == "" {
+// 		if instance != nil {
+// 			return instance.Settings.YuanqiToken
+// 		}
+// 		return "" // 默认值或错误处理
+// 	}
+
+// 	basename := options[0]
+// 	YuanqiTokenInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiToken")
+// 	if err != nil {
+// 		log.Println("Error retrieving YuanqiToken:", err)
+// 		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+// 	}
+
+// 	YuanqiToken, ok := YuanqiTokenInterface.(string)
+// 	if !ok { // 检查类型断言是否失败
+// 		log.Println("Type assertion failed for YuanqiToken, fetching default")
+// 		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+// 	}
 
-// 获取Token
-func GetYuanqiToken(options ...string) string {
+// 	if YuanqiToken == "" {
+// 		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+// 	}
+
+// 	return YuanqiToken
+// }
+
+// GetYuanqiConf return conf.YuanqiAssistantID, conf.YuanqiToken
+func GetYuanqiConf(options ...string) (string, string) {
 	mu.Lock()
 	defer mu.Unlock()
-	return getYuanqiTokenInternal(options...)
+	return getYuanqiConfInternal(options...)
 }
 
-func getYuanqiTokenInternal(options ...string) string {
-	if len(options) == 0 || options[0] == "" {
-		if instance != nil {
-			return instance.Settings.YuanqiToken
+// getYuanqiConfInternal 内部递归函数,处理配置获取逻辑
+func getYuanqiConfInternal(options ...string) (string, string) {
+	// 从instance中读取配置数组
+	if instance != nil && len(instance.Settings.Yuanqiconfs) > 0 {
+		if len(options) == 0 || options[0] == "" {
+			// 从instance全局变量中随机选择一个配置
+			index := rand.Intn(len(instance.Settings.Yuanqiconfs))
+			conf := instance.Settings.Yuanqiconfs[index]
+			return conf.YuanqiAssistantID, conf.YuanqiToken
 		}
-		return "" // 默认值或错误处理
+	} else {
+		log.Println("No configurations available in instance or default behavior")
+		return "", "" // 默认值或错误处理
 	}
 
+	// 使用prompt包从指定的文件名中获取配置
 	basename := options[0]
-	YuanqiTokenInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiToken")
+	confInterface, err := prompt.GetSettingFromFilename(basename, "Yuanqiconfs")
 	if err != nil {
-		log.Println("Error retrieving YuanqiToken:", err)
-		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+		log.Printf("Error retrieving settings from file: %s, error: %v", basename, err)
+		return getYuanqiConfInternal() // 递归调用内部函数,不传递任何参数
 	}
 
-	YuanqiToken, ok := YuanqiTokenInterface.(string)
-	if !ok { // 检查类型断言是否失败
-		log.Println("Type assertion failed for YuanqiToken, fetching default")
-		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+	// 断言获取的interface{}为[]YuanqiConf
+	confs, ok := confInterface.([]structs.YuanqiConf)
+	if !ok {
+		log.Println("Type assertion failed for YuanqiConfs, attempting default behavior")
+		return getYuanqiConfInternal() // 递归调用内部函数,尝试默认配置
 	}
 
-	if YuanqiToken == "" {
-		return getYuanqiTokenInternal() // 递归调用内部函数,不传递任何参数
+	if len(confs) == 0 {
+		log.Println("No configurations found in file:", basename)
+		return getYuanqiConfInternal() // 递归调用内部函数,尝试默认配置
 	}
 
-	return YuanqiToken
+	// 随机选择一个配置返回
+	index := rand.Intn(len(confs))
+	conf := confs[index]
+	return conf.YuanqiAssistantID, conf.YuanqiToken
 }
 
 // 获取助手版本
diff --git a/structs/struct.go b/structs/struct.go
index 856598c..c88dff9 100644
--- a/structs/struct.go
+++ b/structs/struct.go
@@ -395,13 +395,12 @@ type Settings struct {
 	GlmToolChoice  string   `yaml:"glmToolChoice"`  // 工具选择策略
 	GlmUserID      string   `yaml:"glmUserID"`      // 用户ID
 
-	YuanqiApiPath     string  `yaml:"yuanqiApiPath"`     // 元器api地址
-	YuanqiAssistantID string  `yaml:"yuanqiAssistantID"` // 助手ID
-	YuanqiVersion     float64 `yaml:"yuanqiVersion"`     // 助手版本, 仅对内部开放
-	YuanqiUserID      string  `yaml:"yuanqiUserID"`      // 用户ID,调用者业务侧的用户ID,会影响智能体的数据统计,建议按实际情况填写
-	YuanqiStream      bool    `yaml:"yuanqiStream"`      // 是否启用流式返回,默认为false
-	YuanqiChatType    string  `yaml:"yuanqiChatType"`    // 聊天类型,默认为published,preview时使用草稿态智能体,仅对内部开放
-	YuanqiToken       string  `yaml:"yuanqiToken"`       // Token
+	YuanqiApiPath  string       `yaml:"yuanqiApiPath"`  // 元器api地址
+	Yuanqiconfs    []YuanqiConf `yaml:"yuanqiConfs"`    // 元器api配置 支持多个
+	YuanqiVersion  float64      `yaml:"yuanqiVersion"`  // 助手版本, 仅对内部开放
+	YuanqiUserID   string       `yaml:"yuanqiUserID"`   // 用户ID,调用者业务侧的用户ID,会影响智能体的数据统计,建议按实际情况填写
+	YuanqiStream   bool         `yaml:"yuanqiStream"`   // 是否启用流式返回,默认为false
+	YuanqiChatType string       `yaml:"yuanqiChatType"` // 聊天类型,默认为published,preview时使用草稿态智能体,仅对内部开放
 
 	WSServerToken string `yaml:"wsServerToken"`
 	WSPath        string `yaml:"wsPath"`
@@ -424,6 +423,12 @@ type Settings struct {
 	PromptCoverA          []string `yaml:"promptCoverA"` //暂时用不上 待实现
 }
 
+type YuanqiConf struct {
+	YuanqiAssistantID string `yaml:"yuanqiAssistantID"` // 助手ID
+	YuanqiToken       string `yaml:"yuanqiToken"`       // Token
+	YuanqiName        string `yaml:"yuanqiName"`        // 名字
+}
+
 type MetaEvent struct {
 	PostType      string `json:"post_type"`
 	MetaEventType string `json:"meta_event_type"`
diff --git a/template/config_template.go b/template/config_template.go
index 5d0be0e..35d1a88 100644
--- a/template/config_template.go
+++ b/template/config_template.go
@@ -187,9 +187,15 @@ settings:
 
   # Yuanqi 助手配置文件,确保按业务需求配置。
   yuanqiApiPath: "https://open.hunyuan.tencent.com/openapi/v1/agent/chat/completions"
-  yuanqiAssistantID: ""         # 助手ID,唯一标识您的助手实例
-  yuanqiToken: ""               # 元器Token
   yuanqiChatType: "published"   # 聊天类型,默认为published,支持preview模式下使用草稿态智能体
+  yuanqiConfs:
+  - yuanqiAssistantID: "123"
+    yuanqiToken: "123"
+    yuanqiName: "123"
+  - yuanqiAssistantID: "123"
+    uanqiToken: "123"
+    yuanqiName: "123"
+
 `
 
 const Logo = `

From 6c89588a008067cf62530177db306c26cc2b5473 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Sat, 1 Jun 2024 18:31:14 +0800
Subject: [PATCH 21/24] Beta134 (#133)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130

* beta131

* beta132

* beta1333

* beta134
---
 applogic/app.go             | 131 +++++++++++++++
 applogic/chatgpt.go         |   2 +-
 applogic/gensokyo.go        |  99 +++++++++++-
 applogic/memory.go          | 306 ++++++++++++++++++++++++++++++++++++
 applogic/yuanqi.go          |  50 +++++-
 config/config.go            |  68 ++++++++
 main.go                     |   6 +
 structs/struct.go           |  11 ++
 template/config_template.go |   5 +
 utils/utils.go              | 110 +++++++++++++
 10 files changed, 779 insertions(+), 9 deletions(-)
 create mode 100644 applogic/memory.go

diff --git a/applogic/app.go b/applogic/app.go
index 32b8711..8cf56ad 100644
--- a/applogic/app.go
+++ b/applogic/app.go
@@ -288,6 +288,18 @@ func (app *App) updateUserContext(userID int64, parentMessageID string) error {
 	return nil
 }
 
+func (app *App) updateUserContextPro(userID int64, conversationID, parentMessageID string) error {
+	updateQuery := `
+    UPDATE user_context
+    SET conversation_id = ?, parent_message_id = ?
+    WHERE user_id = ?;`
+	_, err := app.DB.Exec(updateQuery, conversationID, parentMessageID, userID)
+	if err != nil {
+		return fmt.Errorf("error updating user context: %w", err)
+	}
+	return nil
+}
+
 func (app *App) getHistory(conversationID, parentMessageID string) ([]structs.Message, error) {
 	// 如果不开启上下文
 	if config.GetNoContext() {
@@ -327,3 +339,122 @@ func (app *App) getHistory(conversationID, parentMessageID string) ([]structs.Me
 	}
 	return history, nil
 }
+
+// 记忆表
+func (app *App) EnsureUserMemoriesTableExists() error {
+	createTableSQL := `
+    CREATE TABLE IF NOT EXISTS user_memories (
+        memory_id INTEGER PRIMARY KEY AUTOINCREMENT,
+        user_id INTEGER NOT NULL,
+        conversation_id TEXT NOT NULL,
+        parent_message_id TEXT,
+        conversation_title TEXT NOT NULL
+    );`
+
+	_, err := app.DB.Exec(createTableSQL)
+	if err != nil {
+		return fmt.Errorf("error creating user_memories table: %w", err)
+	}
+
+	createUserIDIndexSQL := `CREATE INDEX IF NOT EXISTS idx_user_memories_user_id ON user_memories(user_id);`
+	_, err = app.DB.Exec(createUserIDIndexSQL)
+	if err != nil {
+		return fmt.Errorf("error creating index on user_memories(user_id): %w", err)
+	}
+
+	createConvDetailsIndexSQL := `CREATE INDEX IF NOT EXISTS idx_user_memories_conversation_details ON user_memories(conversation_id, parent_message_id);`
+	_, err = app.DB.Exec(createConvDetailsIndexSQL)
+	if err != nil {
+		return fmt.Errorf("error creating index on user_memories(conversation_id, parent_message_id): %w", err)
+	}
+
+	return nil
+}
+
+func (app *App) AddUserMemory(userID int64, conversationID, parentMessageID, conversationTitle string) error {
+	// 插入新的记忆
+	insertMemorySQL := `
+    INSERT INTO user_memories (user_id, conversation_id, parent_message_id, conversation_title)
+    VALUES (?, ?, ?, ?);`
+	_, err := app.DB.Exec(insertMemorySQL, userID, conversationID, parentMessageID, conversationTitle)
+	if err != nil {
+		return fmt.Errorf("error inserting new memory: %w", err)
+	}
+
+	// 检查并保持记忆数量不超过10条
+	return app.ensureMemoryLimit(userID)
+}
+
+func (app *App) updateConversationTitle(userID int64, conversationID, parentMessageID, newTitle string) error {
+	// 定义SQL更新语句
+	updateQuery := `
+    UPDATE user_memories
+    SET conversation_title = ?
+    WHERE user_id = ? AND conversation_id = ? AND parent_message_id = ?;`
+
+	// 执行SQL更新操作
+	_, err := app.DB.Exec(updateQuery, newTitle, userID, conversationID, parentMessageID)
+	if err != nil {
+		return fmt.Errorf("error updating conversation title: %w", err)
+	}
+
+	return nil
+}
+
+func (app *App) ensureMemoryLimit(userID int64) error {
+	// 查询当前记忆总数
+	countQuerySQL := `SELECT COUNT(*) FROM user_memories WHERE user_id = ?;`
+	var count int
+	row := app.DB.QueryRow(countQuerySQL, userID)
+	err := row.Scan(&count)
+	if err != nil {
+		return fmt.Errorf("error counting memories: %w", err)
+	}
+
+	// 如果记忆超过5条,则删除最旧的记忆
+	if count > 5 {
+		deleteOldestMemorySQL := `
+        DELETE FROM user_memories
+        WHERE memory_id IN (
+            SELECT memory_id FROM user_memories
+            WHERE user_id = ?
+            ORDER BY memory_id ASC
+            LIMIT ?
+        );`
+		_, err := app.DB.Exec(deleteOldestMemorySQL, userID, count-5)
+		if err != nil {
+			return fmt.Errorf("error deleting old memories: %w", err)
+		}
+	}
+
+	return nil
+}
+
+func (app *App) GetUserMemories(userID int64) ([]structs.Memory, error) {
+	// 定义查询SQL,获取所有相关的记忆
+	querySQL := `
+    SELECT conversation_id, parent_message_id, conversation_title
+    FROM user_memories
+    WHERE user_id = ?;
+    `
+	rows, err := app.DB.Query(querySQL, userID)
+	if err != nil {
+		return nil, fmt.Errorf("error querying user memories: %w", err)
+	}
+	defer rows.Close() // 确保关闭rows以释放数据库资源
+
+	var memories []structs.Memory
+	for rows.Next() {
+		var m structs.Memory
+		if err := rows.Scan(&m.ConversationID, &m.ParentMessageID, &m.ConversationTitle); err != nil {
+			return nil, fmt.Errorf("error scanning memory: %w", err)
+		}
+		memories = append(memories, m)
+	}
+
+	if err := rows.Err(); err != nil {
+		return nil, fmt.Errorf("error during rows iteration: %w", err)
+	}
+
+	return memories, nil
+}
diff --git a/applogic/chatgpt.go b/applogic/chatgpt.go
index 51e1513..0816252 100644
--- a/applogic/chatgpt.go
+++ b/applogic/chatgpt.go
@@ -515,7 +515,7 @@ func truncateHistoryGpt(history []structs.Message, prompt string, promptstr stri
 	for _, msg := range history {
 		tokenCount += len(msg.Text)
 	}
-	fmt.Printf("测试:%v\n", history)
+	//fmt.Printf("测试:%v\n", history)
 
 	if tokenCount >= MAX_TOKENS {
 		// 第一步:从开始逐个移除消息,直到满足令牌数量限制
diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index 43e48dd..4db4ac4 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -136,7 +136,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 	// 判断是否是群聊 然后判断触发词
 	if message.RealMessageType != "group_private" && message.MessageType != "private" {
-		if !checkMessageForHints(message.RawMessage) {
+		if !checkMessageForHints(utils.RemoveBracketsContent(message.RawMessage)) {
 			w.WriteHeader(http.StatusOK)
 			w.Write([]byte("Group message not hint words."))
 			return
@@ -497,6 +497,70 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		// 使用map映射conversationID和uid gid的关系
 		StoreUserInfo(conversationID, message.UserID, message.GroupID, message.RealMessageType, message.MessageType)
 
+		// 保存记忆
+		memoryCommand := config.GetMemoryCommand()
+
+		// 检查checkResetCommand是否在memoryCommand列表中
+		ismemoryCommand := false
+		for _, command := range memoryCommand {
+			if checkResetCommand == command {
+				ismemoryCommand = true
+				break
+			}
+		}
+
+		// 处理保存记忆
+		if ismemoryCommand {
+			app.handleSaveMemory(message, conversationID, parentMessageID)
+			return
+		}
+
+		// 记忆列表
+		memoryLoadCommand := config.GetMemoryLoadCommand()
+
+		// 检查checkResetCommand是否在memoryLoadCommand列表中或以其为前缀
+		ismemoryLoadCommand := false
+		isPrefixedMemoryLoadCommand := false // 新增变量用于检测前缀匹配
+		for _, command := range memoryLoadCommand {
+			if checkResetCommand == command {
+				ismemoryLoadCommand = true
+				break
+			}
+			if strings.HasPrefix(checkResetCommand, command) { // 检查前缀
+				isPrefixedMemoryLoadCommand = true
+			}
+		}
+
+		// 处理记忆列表
+		if ismemoryLoadCommand {
+			app.handleMemoryList(message)
+			return
+		}
+
+		// 新增处理载入记忆的逻辑
+		if isPrefixedMemoryLoadCommand {
+			app.handleLoadMemory(message, checkResetCommand)
+			return
+		}
+
+		// 新对话
+		newConversationCommand := config.GetNewConversationCommand()
+
+		// 检查checkResetCommand是否在newConversationCommand列表中
+		isnewConversationCommand := false
+		for _, command := range newConversationCommand {
+			if checkResetCommand == command {
+				isnewConversationCommand = true
+				break
+			}
+		}
+
+		// 处理新对话
+		if isnewConversationCommand {
+			app.handleNewConversation(message, conversationID, parentMessageID)
+			return
+		}
+
 		//每句话清空上一句话的messageBuilder
 		ClearMessage(conversationID)
 		fmtf.Printf("conversationID: %s,parentMessageID%s\n", conversationID, parentMessageID)
@@ -822,15 +886,36 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 						// 添加第四个气泡
 						if config.GetNo4Promptkeyboard() {
+							// 合并所有命令到一个数组
+							var allCommands []string
+
+							// 获取并添加RestoreResponses
 							RestoreResponses := config.GetRestoreCommand()
-							if len(RestoreResponses) > 0 {
-								selectedRestoreResponse := RestoreResponses[rand.Intn(len(RestoreResponses))]
+							allCommands = append(allCommands, RestoreResponses...)
+
+							// 获取并添加memoryLoadCommand
+							memoryLoadCommand := config.GetMemoryLoadCommand()
+							allCommands = append(allCommands, memoryLoadCommand...)
+
+							// 获取并添加memoryCommand
+							memoryCommand := config.GetMemoryCommand()
+							allCommands = append(allCommands, memoryCommand...)
+
+							// 获取并添加newConversationCommand
+							newConversationCommand := config.GetNewConversationCommand()
+							allCommands = append(allCommands, newConversationCommand...)
+
+							// 检查合并后的命令数组长度
+							if len(allCommands) > 0 {
+								// 随机选择一个命令
+								selectedCommand := allCommands[rand.Intn(len(allCommands))]
+
+								// 在promptkeyboard的末尾添加选中的命令
 								if len(promptkeyboard) > 0 {
-									// 在promptkeyboard的末尾添加selectedRestoreResponse
-									promptkeyboard = append(promptkeyboard, selectedRestoreResponse)
+									promptkeyboard = append(promptkeyboard, selectedCommand)
 								} else {
-									// 如果promptkeyboard为空,我们也应当初始化它,并添加选中的恢复命令
-									promptkeyboard = []string{selectedRestoreResponse}
+									// 如果promptkeyboard为空,我们也应当初始化它,并添加选中的命令
+									promptkeyboard = []string{selectedCommand}
 								}
 							}
 						}
diff --git a/applogic/memory.go b/applogic/memory.go
new file mode 100644
index 0000000..3979203
--- /dev/null
+++ b/applogic/memory.go
@@ -0,0 +1,306 @@
+package applogic
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"net/url"
+	"strconv"
+	"strings"
+	"unicode"
+
+	"github.com/hoshinonyaruko/gensokyo-llm/config"
+	"github.com/hoshinonyaruko/gensokyo-llm/fmtf"
+	"github.com/hoshinonyaruko/gensokyo-llm/structs"
+	"github.com/hoshinonyaruko/gensokyo-llm/utils"
+)
+
+// 请你为我将我所输入的对话浓缩总结为一个标题
+func GetMemoryTitle(msg string) string {
+	baseurl := config.GetAIPromptkeyboardPath()
+	fmtf.Printf("获取到keyboard baseurl(复用):%v", baseurl)
+	// 使用net/url包来构建和编码URL
+	urlParams := url.Values{}
+	urlParams.Add("prompt", "memory")
+
+	// 将查询参数编码后附加到基本URL上
+	fullURL := baseurl
+	if len(urlParams) > 0 {
+		fullURL += "?" + urlParams.Encode()
+	}
+
+	fmtf.Printf("Generated GetMemoryTitle URL:%v\n", fullURL)
+
+	requestBody, err := json.Marshal(map[string]interface{}{
+		"message":         msg,
+		"conversationId":  "",
+		"parentMessageId": "",
+		"user_id":         "",
+	})
+
+	if err != nil {
+		fmt.Printf("Error marshalling request: %v\n", err)
+		return "默认标题"
+	}
+
+	resp, err := http.Post(fullURL, "application/json", bytes.NewBuffer(requestBody))
+	if err != nil {
+		fmt.Printf("Error sending request: %v\n", err)
+		return "默认标题"
+	}
+	defer resp.Body.Close()
+
+	responseBody, err := io.ReadAll(resp.Body)
+	if err != nil {
+		fmt.Printf("Error reading response body: %v\n", err)
+		return "默认标题"
+	}
+	fmt.Printf("Response: %s\n", string(responseBody))
+
+	var responseData ResponseDataPromptKeyboard
+	if err := json.Unmarshal(responseBody, &responseData); err != nil {
+		fmt.Printf("Error unmarshalling response data: %v[%v]\n", err, string(responseBody))
+		return "默认标题"
+	}
+
+	// 预处理响应数据,移除可能的换行符
+	preprocessedResponse := strings.TrimSpace(responseData.Response)
+
+	// 去除所有标点符号和空格
+	cleanedResponse := strings.Map(func(r rune) rune {
+		if unicode.IsPunct(r) || unicode.IsSpace(r) {
+			return -1 // 在 strings.Map 中,返回 -1 表示删除字符
+		}
+		return r
+	}, preprocessedResponse)
+
+	return cleanedResponse
+}
+
+// 保存记忆
+func (app *App) handleSaveMemory(msg structs.OnebotGroupMessage, ConversationID string, ParentMessageID string) {
+	conversationTitle := "2024-5-19/18:26" // 默认标题,根据实际需求可能需要调整为动态生成的时间戳
+
+	// 添加用户记忆
+	err := app.AddUserMemory(msg.UserID, ConversationID, ParentMessageID, conversationTitle)
+	if err != nil {
+		log.Printf("Error saving memory: %s", err)
+		return
+	}
+
+	// 启动Go routine进行历史信息处理和标题更新
+	go func() {
+		userHistory, err := app.getHistory(ConversationID, ParentMessageID)
+		if err != nil {
+			log.Printf("Error retrieving history: %s", err)
+			return
+		}
+
+		// 处理历史信息为特定格式的字符串
+		memoryTitle := formatHistory(userHistory)
+		newTitle := GetMemoryTitle(memoryTitle) // 获取最终的记忆标题
+
+		// 更新记忆标题
+		err = app.updateConversationTitle(msg.UserID, ConversationID, ParentMessageID, newTitle)
+		if err != nil {
+			log.Printf("Error updating conversation title: %s", err)
+		}
+	}()
+
+	var keyboard []string // 准备一个空的键盘数组
+	// 获取记忆载入命令
+	memoryLoadCommands := config.GetMemoryLoadCommand()
+	if len(memoryLoadCommands) > 0 {
+		keyboard = append(keyboard, memoryLoadCommands[0]) // 添加第一个命令到键盘数组
+	}
+
+	// 发送保存成功的响应
+	saveMemoryResponse := "记忆保存成功!"
+	app.sendMemoryResponseWithkeyBoard(msg, saveMemoryResponse, keyboard)
+}
+
+// 获取记忆列表
+func (app *App) handleMemoryList(msg structs.OnebotGroupMessage) {
+	memories, err := app.GetUserMemories(msg.UserID)
+	if err != nil {
+		log.Printf("Error retrieving memories: %s", err)
+		return
+	}
+
+	// 组合格式化的文本
+	var responseBuilder strings.Builder
+	responseBuilder.WriteString("当前记忆列表:\n")
+
+	// 准备键盘数组,最多包含4个标题
+	var keyboard []string
+	var loadMemoryCommand string
+	// 获取载入记忆指令
+	memoryLoadCommands := config.GetMemoryLoadCommand()
+	if len(memoryLoadCommands) > 0 {
+		loadMemoryCommand = memoryLoadCommands[0]
+	} else {
+		loadMemoryCommand = "未设置载入指令"
+	}
+
+	for _, memory := range memories {
+		responseBuilder.WriteString(memory.ConversationTitle + "\n")
+		// 更新键盘数组,确保最多只有4个元素
+		if len(keyboard) >= 4 {
+			keyboard = keyboard[1:] // 移除最早的元素
+		}
+		keyboard = append(keyboard, loadMemoryCommand+" "+memory.ConversationTitle) // 添加新的标题
+	}
+
+	var exampleTitle string
+	if len(memories) > 0 {
+		exampleTitle = string([]rune(memories[0].ConversationTitle)[:3])
+	}
+	responseBuilder.WriteString(fmt.Sprintf("提示:发送 %s 任意标题开头的前n字即可载入记忆\n如:%s %s", loadMemoryCommand, loadMemoryCommand, exampleTitle))
+
+	// 发送组合后的信息,包括键盘数组
+	app.sendMemoryResponseByline(msg, responseBuilder.String(), keyboard)
+}
+
+// 载入记忆
+func (app *App) handleLoadMemory(msg structs.OnebotGroupMessage, checkResetCommand string) {
+	// 从配置获取载入记忆指令
+	memoryLoadCommands := config.GetMemoryLoadCommand()
+
+	// 移除所有载入记忆指令部分
+	for _, command := range memoryLoadCommands {
+		checkResetCommand = strings.Replace(checkResetCommand, command, "", -1)
+	}
+
+	// 移除空格得到匹配词
+	matchTerm := strings.TrimSpace(checkResetCommand)
+
+	// 获取用户记忆
+	memories, err := app.GetUserMemories(msg.UserID)
+	if err != nil {
+		log.Printf("Error retrieving memories: %s", err)
+		app.sendMemoryResponse(msg, "获取记忆失败")
+		return
+	}
+
+	// 查找匹配的记忆
+	var matchedMemory *structs.Memory
+	for _, memory := range memories {
+		if strings.HasPrefix(memory.ConversationTitle, matchTerm) {
+			matchedMemory = &memory
+			break
+		}
+	}
+
+	if matchedMemory == nil {
+		app.sendMemoryResponse(msg, "未找到匹配的记忆")
+		return
+	}
+
+	// 载入记忆
+	err = app.updateUserContextPro(msg.UserID, matchedMemory.ConversationID, matchedMemory.ParentMessageID)
+	if err != nil {
+		log.Printf("Error adding memory: %s", err)
+		app.sendMemoryResponse(msg, "载入记忆失败")
+		return
+	}
+
+	// 组合回复信息
+	responseMessage := fmt.Sprintf("成功载入了标题为 '%s' 的记忆", matchedMemory.ConversationTitle)
+	app.sendMemoryResponse(msg, responseMessage)
+}
+
+func (app *App) sendMemoryResponseWithkeyBoard(msg structs.OnebotGroupMessage, response string, keyboard []string) {
+	strSelfID := strconv.FormatInt(msg.SelfID, 10)
+	if msg.RealMessageType == "group_private" || msg.MessageType == "private" {
+		if !config.GetUsePrivateSSE() {
+			utils.SendPrivateMessage(msg.UserID, response, strSelfID)
+		} else {
+			utils.SendSSEPrivateMessageWithKeyboard(msg.UserID, response, keyboard)
+		}
+	} else {
+		utils.SendGroupMessage(msg.GroupID, msg.UserID, response, strSelfID)
+	}
+}
+
+func (app *App) sendMemoryResponse(msg structs.OnebotGroupMessage, response string) {
+	strSelfID := strconv.FormatInt(msg.SelfID, 10)
+	if msg.RealMessageType == "group_private" || msg.MessageType == "private" {
+		if !config.GetUsePrivateSSE() {
+			utils.SendPrivateMessage(msg.UserID, response, strSelfID)
+		} else {
+			utils.SendSSEPrivateMessage(msg.UserID, response)
+		}
+	} else {
+		utils.SendGroupMessage(msg.GroupID, msg.UserID, response, strSelfID)
+	}
+}
+
+func (app *App) sendMemoryResponseByline(msg structs.OnebotGroupMessage, response string, keyboard []string) {
+	strSelfID := strconv.FormatInt(msg.SelfID, 10)
+	if msg.RealMessageType == "group_private" || msg.MessageType == "private" {
+		if !config.GetUsePrivateSSE() {
+			utils.SendPrivateMessage(msg.UserID, response, strSelfID)
+		} else {
+			utils.SendSSEPrivateMessageByLine(msg.UserID, response, keyboard)
+		}
+	} else {
+		utils.SendGroupMessage(msg.GroupID, msg.UserID, response, strSelfID)
+	}
+}
+
+func formatHistory(history []structs.Message) string {
+	var result string
+	for _, message := range history {
+		rolePrefix := "Q:"
+		if message.Role == "answer" {
+			rolePrefix = "A:"
+		}
+		result += fmt.Sprintf("%s%s ", rolePrefix, message.Text)
+	}
+	return result
+}
+
+func (app *App) handleNewConversation(msg structs.OnebotGroupMessage, conversationID string, parentMessageID string) {
+	// 使用预定义的时间戳作为会话标题
+	conversationTitle := "2024-5-19/18:26" // 实际应用中应使用动态生成的时间戳
+
+	// 添加用户记忆
+	err := app.AddUserMemory(msg.UserID, conversationID, parentMessageID, conversationTitle)
+	if err != nil {
+		log.Printf("Error saving memory: %s", err)
+		return
+	}
+
+	// 启动Go routine进行历史信息处理和标题更新
+	go func() {
+		userHistory, err := app.getHistory(conversationID, parentMessageID)
+		if err != nil {
+			log.Printf("Error retrieving history: %s", err)
+			return
+		}
+
+		// 处理历史信息为特定格式的字符串
+		memoryTitle := formatHistory(userHistory)
+		newTitle := GetMemoryTitle(memoryTitle) // 获取最终的记忆标题
+
+		// 更新记忆标题
+		err = app.updateConversationTitle(msg.UserID, conversationID, parentMessageID, newTitle)
+		if err != nil {
+			log.Printf("Error updating conversation title: %s", err)
+		}
+	}()
+
+	// 迁移用户到新的上下文
+	app.migrateUserToNewContext(msg.UserID)
+
+	// 获取并使用配置中指定的加载记忆指令
+	loadCommand := config.GetMemoryLoadCommand()
+	if len(loadCommand) > 0 {
+		loadMemoryCommand := loadCommand[0] // 使用数组中的第一个指令
+		saveMemoryResponse := fmt.Sprintf("旧的对话已经保存,可发送 %s 来查看,可以开始新的对话了!", loadMemoryCommand)
+		app.sendMemoryResponse(msg, saveMemoryResponse)
+	}
+}
diff --git a/applogic/yuanqi.go b/applogic/yuanqi.go
index 6479149..f5dc2bf 100644
--- a/applogic/yuanqi.go
+++ b/applogic/yuanqi.go
@@ -144,7 +144,7 @@ func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// 截断历史信息
-		userHistory := truncateHistoryGpt(userhistory, msg.Text, promptstr)
+		userHistory := truncateHistoryYuanQi(userhistory, msg.Text, promptstr)
 
 		if promptstr != "" {
 			// 注意追加的顺序,确保问题在系统提示词之后
@@ -510,3 +510,51 @@ func (app *App) ChatHandlerYuanQi(w http.ResponseWriter, r *http.Request) {
 	}
 
 }
+
+func truncateHistoryYuanQi(history []structs.Message, prompt string, promptstr string) []structs.Message {
+	MAX_TOKENS := config.GetYuanqiMaxToken(promptstr)
+	fmtf.Printf("测试,该用户最大上下文长度:%v\n", MAX_TOKENS)
+	fmtf.Printf("测试,该用户当前上下文:%v\n", history)
+
+	tokenCount := len(prompt)
+	for _, msg := range history {
+		tokenCount += len(msg.Text)
+	}
+
+	if tokenCount >= MAX_TOKENS {
+		// 第一步:从开始逐个移除消息,直到满足令牌数量限制
+		for tokenCount > MAX_TOKENS && len(history) > 0 {
+			tokenCount -= len(history[0].Text)
+			history = history[1:]
+
+			// 确保移除后,历史记录仍然以user消息结尾
+			if len(history) > 0 && history[0].Role == "assistant" {
+				tokenCount -= len(history[0].Text)
+				history = history[1:]
+			}
+		}
+	}
+
+	// 第二步:检查并移除包含空文本的QA对
+	for i := 0; i < len(history)-1; i++ { // 使用len(history)-1是因为我们要检查成对的消息
+		q := history[i]
+		a := history[i+1]
+
+		// 检查Q和A是否成对,且A的角色应为assistant,Q的角色为user,避免删除非QA对的消息
+		if q.Role == "user" && a.Role == "assistant" && (len(q.Text) == 0 || len(a.Text) == 0) {
+			fmtf.Println("closeai-找到了空的对话: ", q, a)
+			// 移除这对QA
+			history = append(history[:i], history[i+2:]...)
+			i-- // 因为删除了元素,调整索引以正确检查下一个元素
+		}
+	}
+
+	// 第三步:确保以assistant结尾
+	if len(history) > 0 && history[len(history)-1].Role == "user" {
+		for len(history) > 0 && history[len(history)-1].Role != "assistant" {
+			history = history[:len(history)-1]
+		}
+	}
+
+	return history
+}
diff --git a/config/config.go b/config/config.go
index ef2a01c..173c44c 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1132,6 +1132,36 @@ func GetWithdrawCommand() []string {
 	return nil
 }
 
+// 获取MemoryCommand
+func GetMemoryCommand() []string {
+	mu.Lock()
+	defer mu.Unlock()
+	if instance != nil {
+		return instance.Settings.MemoryCommand
+	}
+	return nil
+}
+
+// 获取MemoryLoadCommand
+func GetMemoryLoadCommand() []string {
+	mu.Lock()
+	defer mu.Unlock()
+	if instance != nil {
+		return instance.Settings.MemoryLoadCommand
+	}
+	return nil
+}
+
+// 获取NewConversationCommand
+func GetNewConversationCommand() []string {
+	mu.Lock()
+	defer mu.Unlock()
+	if instance != nil {
+		return instance.Settings.NewConversationCommand
+	}
+	return nil
+}
+
 // 获取FunctionMode
 func GetFunctionMode() bool {
 	mu.Lock()
@@ -3103,3 +3133,41 @@ func getYuanqiApiPathInternal(options ...string) string {
 
 	return YuanqiApiPath
 }
+
+// 获取YuanqiMaxToken
+func GetYuanqiMaxToken(options ...string) int {
+	mu.Lock()
+	defer mu.Unlock()
+	return getYuanqiMaxTokenInternal(options...)
+}
+
+// 内部逻辑执行函数,不处理锁,可以安全地递归调用
+func getYuanqiMaxTokenInternal(options ...string) int {
+	// 检查是否有参数传递进来,以及是否为空字符串
+	if len(options) == 0 || options[0] == "" {
+		if instance != nil {
+			return instance.Settings.YuanqiMaxToken
+		}
+		return 0
+	}
+
+	// 使用传入的 basename
+	basename := options[0]
+	YuanqiMaxTokenInterface, err := prompt.GetSettingFromFilename(basename, "YuanqiMaxToken")
+	if err != nil {
+		log.Println("Error retrieving MaxTokenYuanQi:", err)
+		return getYuanqiMaxTokenInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	YuanqiMaxToken, ok := YuanqiMaxTokenInterface.(int)
+	if !ok { // 检查是否断言失败
+		fmt.Println("Type assertion failed for MaxTokenYuanQi, fetching default")
+		return getYuanqiMaxTokenInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	if YuanqiMaxToken == 0 {
+		return getYuanqiMaxTokenInternal() // 递归调用内部函数,不传递任何参数
+	}
+
+	return YuanqiMaxToken
+}
diff --git a/main.go b/main.go
index 0ae4314..ce052ed 100644
--- a/main.go
+++ b/main.go
@@ -122,6 +122,12 @@ func main() {
 		log.Fatalf("Failed to ensure CustomTableExist table exists: %v", err)
 	}
 
+	// 用户多个记忆表
+	err = app.EnsureUserMemoriesTableExists()
+	if err != nil {
+		log.Fatalf("Failed to ensure UserMemoriesTableExists table exists: %v", err)
+	}
+
 	// 加载 拦截词
 	err = app.ProcessSensitiveWords()
 	if err != nil {
diff --git a/structs/struct.go b/structs/struct.go
index c88dff9..e90d480 100644
--- a/structs/struct.go
+++ b/structs/struct.go
@@ -334,6 +334,10 @@ type Settings struct {
 	BlacklistResponseMessages []string `yaml:"blacklistResponseMessages"`
 	NoContext                 bool     `yaml:"noContext"`
 	WithdrawCommand           []string `yaml:"withdrawCommand"`
+	MemoryCommand             []string `yaml:"memoryCommand"`
+	MemoryLoadCommand         []string `yaml:"memoryLoadCommand"`
+	NewConversationCommand    []string `yaml:"newConversationCommand"`
+	MemoryListMD              bool     `yaml:"memoryListMD"`
 	FunctionMode              bool     `yaml:"functionMode"`
 	FunctionPath              string   `yaml:"functionPath"`
 	UseFunctionPromptkeyboard bool     `yaml:"useFunctionPromptkeyboard"`
@@ -401,6 +405,7 @@ type Settings struct {
 	YuanqiUserID   string       `yaml:"yuanqiUserID"`   // 用户ID,调用者业务侧的用户ID,会影响智能体的数据统计,建议按实际情况填写
 	YuanqiStream   bool         `yaml:"yuanqiStream"`   // 是否启用流式返回,默认为false
 	YuanqiChatType string       `yaml:"yuanqiChatType"` // 聊天类型,默认为published,preview时使用草稿态智能体,仅对内部开放
+	YuanqiMaxToken int          `yaml:"yuanqiMaxToken"` // 内部控制的最大上下文对话截断
 
 	WSServerToken string `yaml:"wsServerToken"`
 	WSPath        string `yaml:"wsPath"`
@@ -490,3 +495,9 @@ type CustomRecord struct {
 	PromptStrStat int        // New integer field for storing promptstr_stat
 	Strs          [10]string // Array to store str1 to str10
 }
+
+type Memory struct {
+	ConversationID    string
+	ParentMessageID   string
+	ConversationTitle string
+}
diff --git a/template/config_template.go b/template/config_template.go
index 35d1a88..051c26d 100644
--- a/template/config_template.go
+++ b/template/config_template.go
@@ -42,6 +42,10 @@ settings:
   savelogs : false                              #本地落地日志.
   noContext : false                             #不开启上下文     
   withdrawCommand : ["撤回"]                    #撤回指令
+  memoryCommand : ["记忆"]                      #记忆指令
+  memoryLoadCommand : ["载入"]                  #载入指令
+  newConversationCommand : ["新对话"]           #新对话指令
+  memoryListMD : false                          #记忆列表使用md按钮(qq开放平台)
   hideExtraLogs : false                         #忽略流信息的log,提高性能
   urlSendPics : false                           #自己构造图床加速图片发送.需配置公网ip+放通port+设置正确的selfPath
   groupHintWords : []                           #当机器人位于群内时,需满足包含groupHintWords数组任意内容如[CQ:at,qq=2] 机器人的名字 等
@@ -188,6 +192,7 @@ settings:
   # Yuanqi 助手配置文件,确保按业务需求配置。
   yuanqiApiPath: "https://open.hunyuan.tencent.com/openapi/v1/agent/chat/completions"
   yuanqiChatType: "published"   # 聊天类型,默认为published,支持preview模式下使用草稿态智能体
+  yuanqiMaxToken: 4096
   yuanqiConfs:
   - yuanqiAssistantID: "123"
     yuanqiToken: "123"
diff --git a/utils/utils.go b/utils/utils.go
index 9371903..981b1e4 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -999,6 +999,116 @@ func SendSSEPrivateMessage(userID int64, content string) {
 	}
 }
 
+// SendSSEPrivateMessageWithKeyboard 分割并发送消息的核心逻辑,直接遍历字符串
+func SendSSEPrivateMessageWithKeyboard(userID int64, content string, keyboard []string) {
+	punctuations := []rune{'。', '!', '?', ',', ',', '.', '!', '?', '~'}
+	splitProbability := config.GetSplitByPuntuations()
+
+	var parts []string
+	var currentPart strings.Builder
+
+	for _, runeValue := range content {
+		currentPart.WriteRune(runeValue)
+		if strings.ContainsRune(string(punctuations), runeValue) {
+			// 根据概率决定是否分割
+			if rand.Intn(100) < splitProbability {
+				parts = append(parts, currentPart.String())
+				currentPart.Reset()
+			}
+		}
+	}
+	// 添加最后一部分(如果有的话)
+	if currentPart.Len() > 0 {
+		parts = append(parts, currentPart.String())
+	}
+
+	// 根据parts长度处理状态
+	for i, part := range parts {
+		state := 1
+		if i == len(parts)-2 { // 倒数第二部分
+			state = 11
+		} else if i == len(parts)-1 { // 最后一部分
+			state = 20
+		}
+
+		// 构造消息体并发送
+		messageSSE := structs.InterfaceBody{
+			Content: part,
+			State:   state,
+		}
+
+		if state == 20 { // 对最后一部分特殊处理
+			var promptKeyboard []string
+			if len(keyboard) == 0 {
+				RestoreResponses := config.GetRestoreCommand()
+				promptKeyboard = config.GetPromptkeyboard()
+
+				if len(RestoreResponses) > 0 {
+					selectedRestoreResponse := RestoreResponses[rand.Intn(len(RestoreResponses))]
+					if len(promptKeyboard) > 0 {
+						promptKeyboard[0] = selectedRestoreResponse
+					}
+				}
+			} else {
+				promptKeyboard = keyboard
+			}
+
+			messageSSE.PromptKeyboard = promptKeyboard
+		}
+
+		// 发送SSE消息函数
+		SendPrivateMessageSSE(userID, messageSSE)
+	}
+}
+
+// SendSSEPrivateMessageByline 分割并发送消息的核心逻辑,直接遍历字符串
+func SendSSEPrivateMessageByLine(userID int64, content string, keyboard []string) {
+	// 直接使用 strings.Split 按行分割字符串
+	parts := strings.Split(content, "\n")
+
+	// 根据parts长度处理状态
+	for i, part := range parts {
+		if part == "" {
+			continue // 跳过空行
+		}
+
+		state := 1
+		if i == len(parts)-2 { // 倒数第二部分
+			state = 11
+		} else if i == len(parts)-1 { // 最后一部分
+			state = 20
+		}
+
+		// 构造消息体并发送
+		messageSSE := structs.InterfaceBody{
+			Content: part + "\n",
+			State:   state,
+		}
+
+		if state == 20 { // 对最后一部分特殊处理
+			var promptKeyboard []string
+			if len(keyboard) == 0 {
+				RestoreResponses := config.GetRestoreCommand()
+				promptKeyboard = config.GetPromptkeyboard()
+
+				if len(RestoreResponses) > 0 {
+					selectedRestoreResponse := RestoreResponses[rand.Intn(len(RestoreResponses))]
+					if len(promptKeyboard) > 0 {
+						promptKeyboard[0] = selectedRestoreResponse
+					}
+				}
+			} else {
+				promptKeyboard = keyboard
+			}
+
+			messageSSE.PromptKeyboard = promptKeyboard
+		}
+
+		// 发送SSE消息函数
+		SendPrivateMessageSSE(userID, messageSSE)
+	}
+}
+
 // SendSSEPrivateSafeMessage 分割并发送安全消息的核心逻辑,直接遍历字符串
 func SendSSEPrivateSafeMessage(userID int64, saveresponse string) {
 	// 将字符串转换为rune切片,以正确处理多字节字符

From 89745a25c56d2d3485dcd535ba2e6a781ea78db0 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Mon, 3 Jun 2024 21:18:36 +0800
Subject: [PATCH 22/24] Beta135 (#134)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130

* beta131

* beta132

* beta1333

* beta134

* beta135
---
 applogic/gensokyo.go        | 38 +++++++++++++++++++++++++++++--------
 config/config.go            | 10 ++++++++++
 structs/struct.go           |  1 +
 template/config_template.go |  1 +
 utils/utils.go              |  6 +++---
 5 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index 4db4ac4..a92b76e 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -492,8 +492,14 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 
-		// 请求conversation api 增加当前用户上下文
-		conversationID, parentMessageID, err := app.handleUserContext(message.UserID)
+		var conversationID, parentMessageID string
+		// 请求conversation api 增加当前群/用户上下文
+		if config.GetGroupContext() && message.MessageType != "private" {
+			conversationID, parentMessageID, err = app.handleUserContext(message.GroupID)
+		} else {
+			conversationID, parentMessageID, err = app.handleUserContext(message.UserID)
+		}
+
 		// 使用map映射conversationID和uid gid的关系
 		StoreUserInfo(conversationID, message.UserID, message.GroupID, message.RealMessageType, message.MessageType)
 
@@ -863,10 +869,18 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 			// 在SSE流结束后更新用户上下文 在这里调用gensokyo流式接口的最后一步 插推荐气泡
 			if lastMessageID != "" {
 				fmtf.Printf("lastMessageID: %s\n", lastMessageID)
-				err := app.updateUserContext(message.UserID, lastMessageID)
-				if err != nil {
-					fmtf.Printf("Error updating user context: %v\n", err)
+				if config.GetGroupContext() && message.MessageType != "private" {
+					err := app.updateUserContext(message.GroupID, lastMessageID)
+					if err != nil {
+						fmtf.Printf("Error updating user context: %v\n", err)
+					}
+				} else {
+					err := app.updateUserContext(message.UserID, lastMessageID)
+					if err != nil {
+						fmtf.Printf("Error updating user context: %v\n", err)
+					}
 				}
+
 				if message.RealMessageType == "group_private" || message.MessageType == "private" {
 					if config.GetUsePrivateSSE() {
 
@@ -960,10 +974,18 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 			// 更新用户上下文
 			if messageId, ok := responseData["messageId"].(string); ok {
-				err := app.updateUserContext(message.UserID, messageId)
-				if err != nil {
-					fmtf.Printf("Error updating user context: %v\n", err)
+				if config.GetGroupContext() && message.MessageType != "private" {
+					err := app.updateUserContext(message.GroupID, messageId)
+					if err != nil {
+						fmtf.Printf("Error updating user context: %v\n", err)
+					}
+				} else {
+					err := app.updateUserContext(message.UserID, messageId)
+					if err != nil {
+						fmtf.Printf("Error updating user context: %v\n", err)
+					}
 				}
+
 			}
 		}
 
diff --git a/config/config.go b/config/config.go
index 173c44c..1b9fff1 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1122,6 +1122,16 @@ func GetNoContext() bool {
 	return false
 }
 
+// 获取GroupContext
+func GetGroupContext() bool {
+	mu.Lock()
+	defer mu.Unlock()
+	if instance != nil {
+		return instance.Settings.GroupContext
+	}
+	return false
+}
+
 // 获取WithdrawCommand
 func GetWithdrawCommand() []string {
 	mu.Lock()
diff --git a/structs/struct.go b/structs/struct.go
index e90d480..9fe5828 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"`
+	GroupContext            bool     `yaml:"groupContext"`
 
 	HunyuanType             int     `yaml:"hunyuanType"`
 	MaxTokensHunyuan        int     `yaml:"maxTokensHunyuan"`
diff --git a/template/config_template.go b/template/config_template.go
index 051c26d..a8739a3 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] 机器人的名字 等
+  groupContext : false                          #群上下文 在智能体在群内时,以群为单位处理上下文.
 
   #Ws服务器配置
   wsServerToken : ""                            #ws密钥 可以由onebotv11反向ws接入
diff --git a/utils/utils.go b/utils/utils.go
index 981b1e4..85a59b9 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -981,11 +981,11 @@ func SendSSEPrivateMessage(userID int64, content string) {
 		}
 
 		if state == 20 { // 对最后一部分特殊处理
-			RestoreResponses := config.GetRestoreCommand()
+			MemoryLoadCommand := config.GetMemoryLoadCommand()
 			promptKeyboard := config.GetPromptkeyboard()
 
-			if len(RestoreResponses) > 0 {
-				selectedRestoreResponse := RestoreResponses[rand.Intn(len(RestoreResponses))]
+			if len(MemoryLoadCommand) > 0 {
+				selectedRestoreResponse := MemoryLoadCommand[rand.Intn(len(MemoryLoadCommand))]
 				if len(promptKeyboard) > 0 {
 					promptKeyboard[0] = selectedRestoreResponse
 				}

From 9473012173e60e80720b6aad18d323b6fe80db1b Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Mon, 3 Jun 2024 23:03:16 +0800
Subject: [PATCH 23/24] Beta136 (#135)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130

* beta131

* beta132

* beta1333

* beta134

* beta135

* beta136
---
 applogic/flow.go     |  65 ++++++++++++++++++++------
 applogic/gensokyo.go | 109 ++++++++++++++++++++++++++++++++-----------
 applogic/memory.go   |  38 +++++++++++----
 3 files changed, 164 insertions(+), 48 deletions(-)

diff --git a/applogic/flow.go b/applogic/flow.go
index d402ace..605ff7b 100644
--- a/applogic/flow.go
+++ b/applogic/flow.go
@@ -14,6 +14,10 @@ import (
 
 // ApplyPromptChoiceQ 应用promptchoiceQ的逻辑,动态修改requestmsg
 func (app *App) ApplyPromptChoiceQ(promptstr string, requestmsg *string, message *structs.OnebotGroupMessage) {
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
 
 	// 检查是否启用了EnhancedQA
 	if config.GetEnhancedQA(promptstr) {
@@ -35,7 +39,7 @@ func (app *App) ApplyPromptChoiceQ(promptstr string, requestmsg *string, message
 		} else {
 			var ischange bool
 			// 获取用户剧情存档中的当前状态
-			CustomRecord, err := app.FetchCustomRecord(message.UserID)
+			CustomRecord, err := app.FetchCustomRecord(userid)
 			if err != nil {
 				fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
 				return
@@ -133,6 +137,11 @@ func (app *App) ApplyPromptChoiceQ(promptstr string, requestmsg *string, message
 
 // ApplyPromptCoverQ 应用promptCoverQ的逻辑,动态覆盖requestmsg
 func (app *App) ApplyPromptCoverQ(promptstr string, requestmsg *string, message *structs.OnebotGroupMessage) {
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
+
 	// 检查是否启用了EnhancedQA
 	if config.GetEnhancedQA(promptstr) {
 		promptCover := config.GetPromptCoverQ(promptstr)
@@ -142,7 +151,7 @@ func (app *App) ApplyPromptCoverQ(promptstr string, requestmsg *string, message
 		} else {
 			var ischange bool
 			// 获取用户剧情存档中的当前状态
-			CustomRecord, err := app.FetchCustomRecord(message.UserID)
+			CustomRecord, err := app.FetchCustomRecord(userid)
 			if err != nil {
 				fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
 				return
@@ -240,11 +249,16 @@ func (app *App) ApplyPromptCoverQ(promptstr string, requestmsg *string, message
 
 // ApplySwitchOnQ 应用switchOnQ的逻辑,动态修改promptstr
 func (app *App) ApplySwitchOnQ(promptstr *string, requestmsg *string, message *structs.OnebotGroupMessage) {
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
+
 	// promptstr 随 switchOnQ 变化
 	promptstrChoices := config.GetSwitchOnQ(*promptstr)
 	if len(promptstrChoices) != 0 {
 		// 获取用户剧情存档中的当前状态
-		CustomRecord, err := app.FetchCustomRecord(message.UserID)
+		CustomRecord, err := app.FetchCustomRecord(userid)
 		if err != nil {
 			fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
 			return
@@ -298,7 +312,7 @@ func (app *App) ApplySwitchOnQ(promptstr *string, requestmsg *string, message *s
 						*promptstr = bestText
 						// 获取新的信号长度 刷新持久化数据库
 						PromptMarksLength := config.GetPromptMarksLength(*promptstr)
-						app.InsertCustomTableRecord(message.UserID, *promptstr, PromptMarksLength)
+						app.InsertCustomTableRecord(userid, *promptstr, PromptMarksLength)
 						fmt.Printf("enhancedChoices=true,根据关键词切换prompt为: %s,newPromptStrStat:%d\n", *promptstr, PromptMarksLength)
 						// 故事模式规则 应用 PromptChoiceQ 这一次是为了,替换了分支后,再次用新的分支的promptstr处理一次,因为原先的promptstr是跳转前,要用跳转后的再替换一次
 						app.ApplyPromptChoiceQ(*promptstr, requestmsg, message)
@@ -323,7 +337,7 @@ func (app *App) ApplySwitchOnQ(promptstr *string, requestmsg *string, message *s
 						*promptstr = selectedText
 						// 获取新的信号长度 刷新持久化数据库
 						PromptMarksLength := config.GetPromptMarksLength(*promptstr)
-						app.InsertCustomTableRecord(message.UserID, *promptstr, PromptMarksLength)
+						app.InsertCustomTableRecord(userid, *promptstr, PromptMarksLength)
 						fmt.Printf("enhancedChoices=false,根据关键词切换prompt为: %s,newPromptStrStat:%d\n", *promptstr, PromptMarksLength)
 						// 故事模式规则 应用 PromptChoiceQ 这一次是为了,替换了分支后,再次用新的分支的promptstr处理一次,因为原先的promptstr是跳转前,要用跳转后的再替换一次
 						app.ApplyPromptChoiceQ(*promptstr, requestmsg, message)
@@ -341,8 +355,13 @@ func (app *App) ProcessExitChoicesQ(promptstr string, requestmsg *string, messag
 		return
 	}
 
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
+
 	// 获取用户剧情存档中的当前状态
-	CustomRecord, err := app.FetchCustomRecord(message.UserID)
+	CustomRecord, err := app.FetchCustomRecord(userid)
 	if err != nil {
 		fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
 		return
@@ -413,8 +432,13 @@ func (app *App) ProcessExitChoicesQ(promptstr string, requestmsg *string, messag
 
 // HandleExit 处理用户退出逻辑,包括发送消息和重置用户状态。
 func (app *App) HandleExit(exitText string, message *structs.OnebotGroupMessage, selfid string) {
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
+
 	fmt.Printf("处理重置操作on:%v", exitText)
-	app.migrateUserToNewContext(message.UserID)
+	app.migrateUserToNewContext(userid)
 	RestoreResponse := config.GetRandomRestoreResponses()
 	if message.RealMessageType == "group_private" || message.MessageType == "private" {
 		if !config.GetUsePrivateSSE() {
@@ -425,7 +449,7 @@ func (app *App) HandleExit(exitText string, message *structs.OnebotGroupMessage,
 	} else {
 		utils.SendGroupMessage(message.GroupID, message.UserID, RestoreResponse, selfid)
 	}
-	app.deleteCustomRecord(message.UserID)
+	app.deleteCustomRecord(userid)
 }
 
 // ProcessExitChoicesA 处理基于关键词的退出逻辑。
@@ -435,8 +459,13 @@ func (app *App) ProcessExitChoicesA(promptstr string, response *string, message
 		return
 	}
 
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
+
 	// 获取用户剧情存档中的当前状态
-	CustomRecord, err := app.FetchCustomRecord(message.UserID)
+	CustomRecord, err := app.FetchCustomRecord(userid)
 	if err != nil {
 		fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
 		return
@@ -507,11 +536,16 @@ func (app *App) ProcessExitChoicesA(promptstr string, response *string, message
 
 // ApplySwitchOnA 应用switchOnA的逻辑,动态修改promptstr
 func (app *App) ApplySwitchOnA(promptstr *string, response *string, message *structs.OnebotGroupMessage) {
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
+
 	// 获取与 switchOnA 相关的选择
 	promptstrChoices := config.GetSwitchOnA(*promptstr)
 	if len(promptstrChoices) != 0 {
 		// 获取用户剧情存档中的当前状态
-		CustomRecord, err := app.FetchCustomRecord(message.UserID)
+		CustomRecord, err := app.FetchCustomRecord(userid)
 		if err != nil {
 			fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
 			return
@@ -557,7 +591,7 @@ func (app *App) ApplySwitchOnA(promptstr *string, response *string, message *str
 					if bestMatchCount > 0 {
 						*promptstr = bestText
 						PromptMarksLength := config.GetPromptMarksLength(*promptstr)
-						app.InsertCustomTableRecord(message.UserID, *promptstr, PromptMarksLength)
+						app.InsertCustomTableRecord(userid, *promptstr, PromptMarksLength)
 						fmt.Printf("enhancedChoices=true,根据关键词A切换prompt为: %s,newPromptStrStat:%d\n", *promptstr, PromptMarksLength)
 					}
 				}
@@ -577,7 +611,7 @@ func (app *App) ApplySwitchOnA(promptstr *string, response *string, message *str
 						selectedText := texts[rand.Intn(len(texts))] // 随机选择一个文本
 						*promptstr = selectedText
 						PromptMarksLength := config.GetPromptMarksLength(*promptstr)
-						app.InsertCustomTableRecord(message.UserID, *promptstr, PromptMarksLength)
+						app.InsertCustomTableRecord(userid, *promptstr, PromptMarksLength)
 						fmt.Printf("enhancedChoices=false,根据关键词A切换prompt为: %s,newPromptStrStat:%d\n", *promptstr, PromptMarksLength)
 					}
 				}
@@ -588,6 +622,11 @@ func (app *App) ApplySwitchOnA(promptstr *string, response *string, message *str
 
 // ApplyPromptChoiceA 应用故事模式的情绪增强逻辑,并返回增强内容。
 func (app *App) ApplyPromptChoiceA(promptstr string, response string, message *structs.OnebotGroupMessage) string {
+	userid := message.UserID
+	if config.GetGroupContext() && message.MessageType != "private" {
+		userid = message.GroupID
+	}
+
 	promptChoices := config.GetPromptChoicesA(promptstr)
 	if len(promptChoices) == 0 {
 		// 获取系统历史,但不包括系统消息
@@ -608,7 +647,7 @@ func (app *App) ApplyPromptChoiceA(promptstr string, response string, message *s
 	}
 
 	// 获取用户剧情存档中的当前状态
-	CustomRecord, err := app.FetchCustomRecord(message.UserID)
+	CustomRecord, err := app.FetchCustomRecord(userid)
 	if err != nil {
 		fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
 		return ""
diff --git a/applogic/gensokyo.go b/applogic/gensokyo.go
index a92b76e..953faa6 100644
--- a/applogic/gensokyo.go
+++ b/applogic/gensokyo.go
@@ -142,11 +142,19 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 	}
-
-	// 从数据库读取用户的剧情存档
-	CustomRecord, err := app.FetchCustomRecord(message.UserID)
-	if err != nil {
-		fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
+	var CustomRecord *structs.CustomRecord
+	if config.GetGroupContext() && message.MessageType != "private" {
+		// 从数据库读取用户的剧情存档
+		CustomRecord, err = app.FetchCustomRecord(message.GroupID)
+		if err != nil {
+			fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
+		}
+	} else {
+		// 从数据库读取用户的剧情存档
+		CustomRecord, err = app.FetchCustomRecord(message.UserID)
+		if err != nil {
+			fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
+		}
 	}
 
 	var promptstr string
@@ -163,14 +171,27 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 			promptstr = CustomRecord.PromptStr
 			fmt.Printf("刷新prompt参数: %s,newPromptStrStat:%d\n", promptstr, CustomRecord.PromptStrStat-1)
 			newPromptStrStat := CustomRecord.PromptStrStat - 1
-			err = app.InsertCustomTableRecord(message.UserID, promptstr, newPromptStrStat)
-			if err != nil {
-				fmt.Printf("app.InsertCustomTableRecord 出错: %s\n", err)
+			// 根据条件区分群和私聊
+			if config.GetGroupContext() && message.MessageType != "private" {
+				err = app.InsertCustomTableRecord(message.GroupID, promptstr, newPromptStrStat)
+				if err != nil {
+					fmt.Printf("app.InsertCustomTableRecord 出错: %s\n", err)
+				}
+			} else {
+				err = app.InsertCustomTableRecord(message.UserID, promptstr, newPromptStrStat)
+				if err != nil {
+					fmt.Printf("app.InsertCustomTableRecord 出错: %s\n", err)
+				}
 			}
+
 		}
 
 		// MARK: 提示词之间 整体切换Q
-		app.ProcessPromptMarks(message.UserID, message.Message.(string), &promptstr)
+		if config.GetGroupContext() && message.MessageType != "private" {
+			app.ProcessPromptMarks(message.GroupID, message.Message.(string), &promptstr)
+		} else {
+			app.ProcessPromptMarks(message.UserID, message.Message.(string), &promptstr)
+		}
 
 		// 提示词之间流转 达到信号量
 		markType := config.GetPromptMarkType(promptstr)
@@ -189,7 +210,12 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 				}
 
 				// 刷新新的提示词给用户目前的状态 新的场景应该从1开始
-				app.InsertCustomTableRecord(message.UserID, newPromptStr, 1)
+				if config.GetGroupContext() && message.MessageType != "private" {
+					app.InsertCustomTableRecord(message.GroupID, newPromptStr, 1)
+				} else {
+					app.InsertCustomTableRecord(message.UserID, newPromptStr, 1)
+				}
+
 				fmt.Printf("流转prompt参数: %s,newPromptStrStat:%d\n", newPromptStr, 1)
 				promptstr = newPromptStr
 			}
@@ -203,7 +229,12 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// MARK: 提示词之间 整体切换Q 当用户没有存档时
-		app.ProcessPromptMarks(message.UserID, message.Message.(string), &promptstr)
+		if config.GetGroupContext() && message.MessageType != "private" {
+			app.ProcessPromptMarks(message.GroupID, message.Message.(string), &promptstr)
+		} else {
+			app.ProcessPromptMarks(message.UserID, message.Message.(string), &promptstr)
+		}
+
 		var newstat int
 		if config.GetPromptMarksLength(promptstr) > 1000 {
 			newstat = config.GetPromptMarksLength(promptstr)
@@ -212,7 +243,12 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// 初始状态就是 1 设置了1000以上长度的是固有场景,不可切换
-		err = app.InsertCustomTableRecord(message.UserID, promptstr, newstat)
+		if config.GetGroupContext() && message.MessageType != "private" {
+			err = app.InsertCustomTableRecord(message.GroupID, promptstr, newstat)
+		} else {
+			err = app.InsertCustomTableRecord(message.UserID, promptstr, newstat)
+		}
+
 		if err != nil {
 			fmt.Printf("app.InsertCustomTableRecord 出错: %s\n", err)
 		}
@@ -297,7 +333,11 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		//处理重置指令
 		if isResetCommand {
 			fmtf.Println("处理重置操作")
-			app.migrateUserToNewContext(message.UserID)
+			if config.GetGroupContext() && message.MessageType != "private" {
+				app.migrateUserToNewContext(message.GroupID)
+			} else {
+				app.migrateUserToNewContext(message.UserID)
+			}
 			RestoreResponse := config.GetRandomRestoreResponses()
 			if message.RealMessageType == "group_private" || message.MessageType == "private" {
 				if !config.GetUsePrivateSSE() {
@@ -309,7 +349,11 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 				utils.SendGroupMessage(message.GroupID, message.UserID, RestoreResponse, selfid)
 			}
 			// 处理故事情节的重置
-			app.deleteCustomRecord(message.UserID)
+			if config.GetGroupContext() && message.MessageType != "private" {
+				app.deleteCustomRecord(message.GroupID)
+			} else {
+				app.deleteCustomRecord(message.UserID)
+			}
 			return
 		}
 
@@ -517,7 +561,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 		// 处理保存记忆
 		if ismemoryCommand {
-			app.handleSaveMemory(message, conversationID, parentMessageID)
+			app.handleSaveMemory(message, conversationID, parentMessageID) // 适配群
 			return
 		}
 
@@ -539,13 +583,13 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 		// 处理记忆列表
 		if ismemoryLoadCommand {
-			app.handleMemoryList(message)
+			app.handleMemoryList(message) // 适配群
 			return
 		}
 
 		// 新增处理载入记忆的逻辑
 		if isPrefixedMemoryLoadCommand {
-			app.handleLoadMemory(message, checkResetCommand)
+			app.handleLoadMemory(message, checkResetCommand) // 适配群
 			return
 		}
 
@@ -563,7 +607,7 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 
 		// 处理新对话
 		if isnewConversationCommand {
-			app.handleNewConversation(message, conversationID, parentMessageID)
+			app.handleNewConversation(message, conversationID, parentMessageID) // 适配群
 			return
 		}
 
@@ -597,21 +641,29 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 		}
 
 		// 关键词退出部分ExitChoicesQ
-		app.ProcessExitChoicesQ(promptstr, &requestmsg, &message, selfid)
+		app.ProcessExitChoicesQ(promptstr, &requestmsg, &message, selfid) // 适配群
 
 		// 故事模式规则 应用 PromptChoiceQ
-		app.ApplyPromptChoiceQ(promptstr, &requestmsg, &message)
+		app.ApplyPromptChoiceQ(promptstr, &requestmsg, &message) // 适配群
 
 		// 故事模式规则 应用 PromptCoverQ
-		app.ApplyPromptCoverQ(promptstr, &requestmsg, &message)
+		app.ApplyPromptCoverQ(promptstr, &requestmsg, &message) // 适配群
 
 		// promptstr 随 switchOnQ 变化 切换Q
-		app.ApplySwitchOnQ(&promptstr, &requestmsg, &message)
+		app.ApplySwitchOnQ(&promptstr, &requestmsg, &message) // 适配群
 
 		// 从数据库读取用户的剧情存档
-		CustomRecord, err := app.FetchCustomRecord(message.UserID)
-		if err != nil {
-			fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
+		var CustomRecord *structs.CustomRecord
+		if config.GetGroupContext() && message.MessageType != "private" {
+			CustomRecord, err = app.FetchCustomRecord(message.GroupID)
+			if err != nil {
+				fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
+			}
+		} else {
+			CustomRecord, err = app.FetchCustomRecord(message.UserID)
+			if err != nil {
+				fmt.Printf("app.FetchCustomRecord 出错: %s\n", err)
+			}
 		}
 
 		// 生成场景
@@ -620,8 +672,11 @@ func (app *App) GensokyoHandler(w http.ResponseWriter, r *http.Request) {
 			PromptMarksLength := config.GetPromptMarksLength(promptstr)
 			app.GetAndSendEnv(requestmsg, promptstr, message, selfid, CustomRecord.PromptStrStat, PromptMarksLength)
 		}
-
-		fmtf.Printf("实际请求conversation端点内容:[%v]%v\n", message.UserID, requestmsg)
+		if config.GetGroupContext() && message.MessageType != "private" {
+			fmtf.Printf("实际请求conversation端点内容:[%v]%v\n", message.GroupID, requestmsg)
+		} else {
+			fmtf.Printf("实际请求conversation端点内容:[%v]%v\n", message.UserID, requestmsg)
+		}
 
 		requestBody, err := json.Marshal(map[string]interface{}{
 			"message":         requestmsg,
diff --git a/applogic/memory.go b/applogic/memory.go
index 3979203..ce6ece5 100644
--- a/applogic/memory.go
+++ b/applogic/memory.go
@@ -84,8 +84,13 @@ func GetMemoryTitle(msg string) string {
 func (app *App) handleSaveMemory(msg structs.OnebotGroupMessage, ConversationID string, ParentMessageID string) {
 	conversationTitle := "2024-5-19/18:26" // 默认标题,根据实际需求可能需要调整为动态生成的时间戳
 
+	userid := msg.UserID
+	if config.GetGroupContext() && msg.MessageType != "private" {
+		userid = msg.GroupID
+	}
+
 	// 添加用户记忆
-	err := app.AddUserMemory(msg.UserID, ConversationID, ParentMessageID, conversationTitle)
+	err := app.AddUserMemory(userid, ConversationID, ParentMessageID, conversationTitle)
 	if err != nil {
 		log.Printf("Error saving memory: %s", err)
 		return
@@ -104,7 +109,7 @@ func (app *App) handleSaveMemory(msg structs.OnebotGroupMessage, ConversationID
 		newTitle := GetMemoryTitle(memoryTitle) // 获取最终的记忆标题
 
 		// 更新记忆标题
-		err = app.updateConversationTitle(msg.UserID, ConversationID, ParentMessageID, newTitle)
+		err = app.updateConversationTitle(userid, ConversationID, ParentMessageID, newTitle)
 		if err != nil {
 			log.Printf("Error updating conversation title: %s", err)
 		}
@@ -124,7 +129,13 @@ func (app *App) handleSaveMemory(msg structs.OnebotGroupMessage, ConversationID
 
 // 获取记忆列表
 func (app *App) handleMemoryList(msg structs.OnebotGroupMessage) {
-	memories, err := app.GetUserMemories(msg.UserID)
+
+	userid := msg.UserID
+	if config.GetGroupContext() && msg.MessageType != "private" {
+		userid = msg.GroupID
+	}
+
+	memories, err := app.GetUserMemories(userid)
 	if err != nil {
 		log.Printf("Error retrieving memories: %s", err)
 		return
@@ -166,6 +177,12 @@ func (app *App) handleMemoryList(msg structs.OnebotGroupMessage) {
 
 // 载入记忆
 func (app *App) handleLoadMemory(msg structs.OnebotGroupMessage, checkResetCommand string) {
+
+	userid := msg.UserID
+	if config.GetGroupContext() && msg.MessageType != "private" {
+		userid = msg.GroupID
+	}
+
 	// 从配置获取载入记忆指令
 	memoryLoadCommands := config.GetMemoryLoadCommand()
 
@@ -178,7 +195,7 @@ func (app *App) handleLoadMemory(msg structs.OnebotGroupMessage, checkResetComma
 	matchTerm := strings.TrimSpace(checkResetCommand)
 
 	// 获取用户记忆
-	memories, err := app.GetUserMemories(msg.UserID)
+	memories, err := app.GetUserMemories(userid)
 	if err != nil {
 		log.Printf("Error retrieving memories: %s", err)
 		app.sendMemoryResponse(msg, "获取记忆失败")
@@ -200,7 +217,7 @@ func (app *App) handleLoadMemory(msg structs.OnebotGroupMessage, checkResetComma
 	}
 
 	// 载入记忆
-	err = app.updateUserContextPro(msg.UserID, matchedMemory.ConversationID, matchedMemory.ParentMessageID)
+	err = app.updateUserContextPro(userid, matchedMemory.ConversationID, matchedMemory.ParentMessageID)
 	if err != nil {
 		log.Printf("Error adding memory: %s", err)
 		app.sendMemoryResponse(msg, "载入记忆失败")
@@ -266,9 +283,14 @@ func formatHistory(history []structs.Message) string {
 func (app *App) handleNewConversation(msg structs.OnebotGroupMessage, conversationID string, parentMessageID string) {
 	// 使用预定义的时间戳作为会话标题
 	conversationTitle := "2024-5-19/18:26" // 实际应用中应使用动态生成的时间戳
+	userid := msg.UserID
+
+	if config.GetGroupContext() && msg.MessageType != "private" {
+		userid = msg.GroupID
+	}
 
 	// 添加用户记忆
-	err := app.AddUserMemory(msg.UserID, conversationID, parentMessageID, conversationTitle)
+	err := app.AddUserMemory(userid, conversationID, parentMessageID, conversationTitle)
 	if err != nil {
 		log.Printf("Error saving memory: %s", err)
 		return
@@ -287,14 +309,14 @@ func (app *App) handleNewConversation(msg structs.OnebotGroupMessage, conversati
 		newTitle := GetMemoryTitle(memoryTitle) // 获取最终的记忆标题
 
 		// 更新记忆标题
-		err = app.updateConversationTitle(msg.UserID, conversationID, parentMessageID, newTitle)
+		err = app.updateConversationTitle(userid, conversationID, parentMessageID, newTitle)
 		if err != nil {
 			log.Printf("Error updating conversation title: %s", err)
 		}
 	}()
 
 	// 迁移用户到新的上下文
-	app.migrateUserToNewContext(msg.UserID)
+	app.migrateUserToNewContext(userid)
 
 	// 获取并使用配置中指定的加载记忆指令
 	loadCommand := config.GetMemoryLoadCommand()

From 151d6f7f46bbe001b50be9b63ee1d94ea0f28916 Mon Sep 17 00:00:00 2001
From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com>
Date: Thu, 6 Jun 2024 09:23:23 +0800
Subject: [PATCH 24/24] Beta137 (#136)

* beta1

* beta2

* beta3

* beta4

* beta5

* beta6

* beta7

* beta8

* beta9

* beta10

* beta11

* beta12

* beta13

* beta14

* beta15

* beta16

* beta16

* beta19

* beta20

* beta21

* beta22

* beta23

* beta24

* beta25

* beta27

* beta28

* beta29

* beta30

* beta31

* beta33

* beta34

* beta35

* beta36

* beta37

* beta38

* beta39

* beta40

* beta41

* beta42

* beta43

* beta44

* beta45

* beta45

* beta46

* beat48

* beta49

* beta50

* beta51

* beta52

* beta53

* beta54

* beta55

* beta57

* beta58

* beta59

* beta61

* beta62

* beta63

* beta63

* beta64

* beta65

* beta66

* beta67

* beta70

* beta71

* beta72

* beta72

* beta74

* beta75

* beta76

* beta77

* beta78

* beta79

* beta80

* beta81

* beta82

* beta83

* beta85

* beta86

* beta87

* beta88

* beta89

* beta90

* beta91

* beta92

* beta93

* beta94

* beta94

* beta96

* beta97

* beta98

* beta99

* beta100

* beta101

* beta102

* beta104

* beta105

* beta106

* beta107

* beta108

* beta109

* beta110

* beta111

* beta112

* beta113

* beta115

* beta116

* beta117

* beta118

* beta119

* beta120

* beta121

* beta122

* beta123

* beta124

* beta125

* beta126

* beta127

* beta128

* beta129

* beta130

* beta131

* beta132

* beta1333

* beta134

* beta135

* beta136

* beta137
---
 applogic/gensokyo.go        |  38 +++++++++---
 applogic/yuanqi.go          |   1 +
 config/config.go            | 112 +++++++++++++++++++++++++++++++++---
 prompt/prompt.go            |  14 +++++
 server/server.go            |   2 +-
 structs/struct.go           |   1 +
 template/config_template.go |   1 +
 utils/utils.go              |   6 +-
 8 files changed, 153 insertions(+), 22 deletions(-)

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 {