🎨 优化日志输出
This commit is contained in:
@@ -7,7 +7,7 @@ type ChatCompletionResponse struct {
|
|||||||
Created int64 `json:"created"`
|
Created int64 `json:"created"`
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
Choices []ChatCompletionChoice `json:"choices"`
|
Choices []ChatCompletionChoice `json:"choices"`
|
||||||
Usage ChatCompletionUsage `json:"usage"`
|
Usage *ChatCompletionUsage `json:"usage,omitempty"`
|
||||||
// 统一格式的用量统计(用于各种上游的标准化)
|
// 统一格式的用量统计(用于各种上游的标准化)
|
||||||
StandardUsage *ChatCompletionUsage `json:"standard_usage,omitempty"`
|
StandardUsage *ChatCompletionUsage `json:"standard_usage,omitempty"`
|
||||||
// 扩展字段:正则脚本执行日志
|
// 扩展字段:正则脚本执行日志
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ import (
|
|||||||
|
|
||||||
// ProcessClaudeMessage 处理 Claude 消息请求
|
// ProcessClaudeMessage 处理 Claude 消息请求
|
||||||
func (s *AiProxyService) ProcessClaudeMessage(ctx context.Context, req *request.ClaudeMessageRequest) (*response.ClaudeMessageResponse, error) {
|
func (s *AiProxyService) ProcessClaudeMessage(ctx context.Context, req *request.ClaudeMessageRequest) (*response.ClaudeMessageResponse, error) {
|
||||||
|
// 记录请求参数
|
||||||
|
global.GVA_LOG.Info("收到 Claude Messages 请求",
|
||||||
|
zap.String("model", req.Model),
|
||||||
|
zap.Any("messages", req.Messages),
|
||||||
|
zap.Any("full_request", req),
|
||||||
|
)
|
||||||
|
|
||||||
// 1. 根据模型获取配置
|
// 1. 根据模型获取配置
|
||||||
if req.Model == "" {
|
if req.Model == "" {
|
||||||
return nil, fmt.Errorf("model 参数不能为空")
|
return nil, fmt.Errorf("model 参数不能为空")
|
||||||
@@ -32,8 +39,9 @@ func (s *AiProxyService) ProcessClaudeMessage(ctx context.Context, req *request.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. 注入预设
|
// 2. 注入预设
|
||||||
|
var injector *PresetInjector
|
||||||
if preset != nil {
|
if preset != nil {
|
||||||
injector := NewPresetInjector(preset)
|
injector = NewPresetInjector(preset)
|
||||||
req.Messages = s.convertClaudeMessages(injector.InjectMessages(s.convertToOpenAIMessages(req.Messages)))
|
req.Messages = s.convertClaudeMessages(injector.InjectMessages(s.convertToOpenAIMessages(req.Messages)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,24 +51,74 @@ func (s *AiProxyService) ProcessClaudeMessage(ctx context.Context, req *request.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 处理响应
|
// 获取 AI 输出内容
|
||||||
if preset != nil && len(resp.Content) > 0 {
|
aiOutput := ""
|
||||||
injector := NewPresetInjector(preset)
|
if len(resp.Content) > 0 {
|
||||||
|
aiOutput = resp.Content[0].Text
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 处理响应(使用同一个 injector 实例)
|
||||||
|
if injector != nil && len(resp.Content) > 0 {
|
||||||
resp.Content[0].Text = injector.ProcessResponse(resp.Content[0].Text)
|
resp.Content[0].Text = injector.ProcessResponse(resp.Content[0].Text)
|
||||||
|
aiOutput = resp.Content[0].Text
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 统一填充 standard_usage,转换为 OpenAI 风格的用量统计
|
// 5. 统一填充 standard_usage,转换为 OpenAI 风格的用量统计
|
||||||
resp.StandardUsage = &response.ChatCompletionUsage{
|
if resp.Usage.InputTokens > 0 || resp.Usage.OutputTokens > 0 {
|
||||||
PromptTokens: resp.Usage.InputTokens,
|
resp.StandardUsage = &response.ChatCompletionUsage{
|
||||||
CompletionTokens: resp.Usage.OutputTokens,
|
PromptTokens: resp.Usage.InputTokens,
|
||||||
TotalTokens: resp.Usage.InputTokens + resp.Usage.OutputTokens,
|
CompletionTokens: resp.Usage.OutputTokens,
|
||||||
|
TotalTokens: resp.Usage.InputTokens + resp.Usage.OutputTokens,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 记录响应内容
|
||||||
|
logFields := []zap.Field{
|
||||||
|
zap.String("ai_output", aiOutput),
|
||||||
|
zap.Any("usage", resp.Usage),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加正则脚本执行日志(使用同一个 injector 实例)
|
||||||
|
if injector != nil {
|
||||||
|
regexLogs := injector.GetRegexLogs()
|
||||||
|
if regexLogs != nil && (regexLogs.TotalMatches > 0 || len(regexLogs.InputScripts) > 0 || len(regexLogs.OutputScripts) > 0) {
|
||||||
|
// 收集触发的脚本名称
|
||||||
|
triggeredScripts := make([]string, 0)
|
||||||
|
for _, scriptLog := range regexLogs.InputScripts {
|
||||||
|
if scriptLog.MatchCount > 0 {
|
||||||
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输入:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, scriptLog := range regexLogs.OutputScripts {
|
||||||
|
if scriptLog.MatchCount > 0 {
|
||||||
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输出:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(triggeredScripts) > 0 {
|
||||||
|
logFields = append(logFields,
|
||||||
|
zap.Strings("triggered_regex_scripts", triggeredScripts),
|
||||||
|
zap.Int("total_matches", regexLogs.TotalMatches),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logFields = append(logFields, zap.Any("full_response", resp))
|
||||||
|
global.GVA_LOG.Info("Claude Messages 响应", logFields...)
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessClaudeMessageStream 处理 Claude 流式消息请求
|
// ProcessClaudeMessageStream 处理 Claude 流式消息请求
|
||||||
func (s *AiProxyService) ProcessClaudeMessageStream(c *gin.Context, req *request.ClaudeMessageRequest) {
|
func (s *AiProxyService) ProcessClaudeMessageStream(c *gin.Context, req *request.ClaudeMessageRequest) {
|
||||||
|
// 记录请求参数
|
||||||
|
global.GVA_LOG.Info("收到 Claude Messages 流式请求",
|
||||||
|
zap.String("model", req.Model),
|
||||||
|
zap.Any("messages", req.Messages),
|
||||||
|
zap.Any("full_request", req),
|
||||||
|
)
|
||||||
|
|
||||||
// 1. 根据模型获取配置
|
// 1. 根据模型获取配置
|
||||||
if req.Model == "" {
|
if req.Model == "" {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "model 参数不能为空"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "model 参数不能为空"})
|
||||||
@@ -142,9 +200,22 @@ func (s *AiProxyService) forwardClaudeStreamRequest(c *gin.Context, provider *ap
|
|||||||
}
|
}
|
||||||
defer httpResp.Body.Close()
|
defer httpResp.Body.Close()
|
||||||
|
|
||||||
|
if httpResp.StatusCode != http.StatusOK {
|
||||||
|
body, _ := io.ReadAll(httpResp.Body)
|
||||||
|
global.GVA_LOG.Error("Claude 流式请求上游返回错误",
|
||||||
|
zap.Int("status_code", httpResp.StatusCode),
|
||||||
|
zap.String("response_body", string(body)),
|
||||||
|
)
|
||||||
|
return fmt.Errorf("上游返回错误: %d - %s", httpResp.StatusCode, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
reader := bufio.NewReader(httpResp.Body)
|
reader := bufio.NewReader(httpResp.Body)
|
||||||
flusher, _ := c.Writer.(http.Flusher)
|
flusher, _ := c.Writer.(http.Flusher)
|
||||||
|
|
||||||
|
// 聚合完整输出用于日志
|
||||||
|
var fullContent bytes.Buffer
|
||||||
|
var totalInputTokens, totalOutputTokens int
|
||||||
|
|
||||||
for {
|
for {
|
||||||
line, err := reader.ReadBytes('\n')
|
line, err := reader.ReadBytes('\n')
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -157,10 +228,21 @@ func (s *AiProxyService) forwardClaudeStreamRequest(c *gin.Context, provider *ap
|
|||||||
if bytes.HasPrefix(line, []byte("data: ")) {
|
if bytes.HasPrefix(line, []byte("data: ")) {
|
||||||
data := bytes.TrimPrefix(line, []byte("data: "))
|
data := bytes.TrimPrefix(line, []byte("data: "))
|
||||||
var chunk response.ClaudeStreamResponse
|
var chunk response.ClaudeStreamResponse
|
||||||
if json.Unmarshal(data, &chunk) == nil && chunk.Delta != nil {
|
if json.Unmarshal(data, &chunk) == nil {
|
||||||
if injector != nil {
|
// 收集 usage 信息
|
||||||
chunk.Delta.Text = injector.ProcessResponse(chunk.Delta.Text)
|
if chunk.Usage != nil {
|
||||||
|
totalInputTokens = chunk.Usage.InputTokens
|
||||||
|
totalOutputTokens = chunk.Usage.OutputTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理文本内容
|
||||||
|
if chunk.Delta != nil && chunk.Delta.Text != "" {
|
||||||
|
fullContent.WriteString(chunk.Delta.Text)
|
||||||
|
if injector != nil {
|
||||||
|
chunk.Delta.Text = injector.ProcessResponse(chunk.Delta.Text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
processedData, _ := json.Marshal(chunk)
|
processedData, _ := json.Marshal(chunk)
|
||||||
c.Writer.Write([]byte("data: "))
|
c.Writer.Write([]byte("data: "))
|
||||||
c.Writer.Write(processedData)
|
c.Writer.Write(processedData)
|
||||||
@@ -169,6 +251,43 @@ func (s *AiProxyService) forwardClaudeStreamRequest(c *gin.Context, provider *ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 记录完整的流式响应日志
|
||||||
|
logFields := []zap.Field{
|
||||||
|
zap.String("ai_output", fullContent.String()),
|
||||||
|
zap.Int("input_tokens", totalInputTokens),
|
||||||
|
zap.Int("output_tokens", totalOutputTokens),
|
||||||
|
zap.Int("total_tokens", totalInputTokens+totalOutputTokens),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加正则脚本执行日志
|
||||||
|
if injector != nil {
|
||||||
|
regexLogs := injector.GetRegexLogs()
|
||||||
|
if regexLogs != nil && (regexLogs.TotalMatches > 0 || len(regexLogs.InputScripts) > 0 || len(regexLogs.OutputScripts) > 0) {
|
||||||
|
// 收集触发的脚本名称
|
||||||
|
triggeredScripts := make([]string, 0)
|
||||||
|
for _, scriptLog := range regexLogs.InputScripts {
|
||||||
|
if scriptLog.MatchCount > 0 {
|
||||||
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输入:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, scriptLog := range regexLogs.OutputScripts {
|
||||||
|
if scriptLog.MatchCount > 0 {
|
||||||
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输出:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(triggeredScripts) > 0 {
|
||||||
|
logFields = append(logFields,
|
||||||
|
zap.Strings("triggered_regex_scripts", triggeredScripts),
|
||||||
|
zap.Int("total_matches", regexLogs.TotalMatches),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global.GVA_LOG.Info("Claude Messages 流式响应完成", logFields...)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,13 @@ type AiProxyService struct{}
|
|||||||
|
|
||||||
// ProcessChatCompletion 处理聊天补全请求
|
// ProcessChatCompletion 处理聊天补全请求
|
||||||
func (s *AiProxyService) ProcessChatCompletion(ctx context.Context, req *request.ChatCompletionRequest) (*response.ChatCompletionResponse, error) {
|
func (s *AiProxyService) ProcessChatCompletion(ctx context.Context, req *request.ChatCompletionRequest) (*response.ChatCompletionResponse, error) {
|
||||||
|
// 记录请求参数
|
||||||
|
global.GVA_LOG.Info("收到 ChatCompletion 请求",
|
||||||
|
zap.String("model", req.Model),
|
||||||
|
zap.Any("messages", req.Messages),
|
||||||
|
zap.Any("full_request", req),
|
||||||
|
)
|
||||||
|
|
||||||
// 1. 根据模型获取配置
|
// 1. 根据模型获取配置
|
||||||
if req.Model == "" {
|
if req.Model == "" {
|
||||||
return nil, fmt.Errorf("model 参数不能为空")
|
return nil, fmt.Errorf("model 参数不能为空")
|
||||||
@@ -48,73 +55,87 @@ func (s *AiProxyService) ProcessChatCompletion(ctx context.Context, req *request
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. 处理响应并收集正则日志
|
// 4. 处理响应并收集正则日志
|
||||||
if resp != nil {
|
if resp != nil && resp.Usage != nil {
|
||||||
// 统一填充 standard_usage,方便上游使用统一格式解析
|
// 统一填充 standard_usage,方便上游使用统一格式解析
|
||||||
resp.StandardUsage = &response.ChatCompletionUsage{
|
if resp.Usage.PromptTokens > 0 || resp.Usage.CompletionTokens > 0 || resp.Usage.TotalTokens > 0 {
|
||||||
PromptTokens: resp.Usage.PromptTokens,
|
resp.StandardUsage = &response.ChatCompletionUsage{
|
||||||
CompletionTokens: resp.Usage.CompletionTokens,
|
PromptTokens: resp.Usage.PromptTokens,
|
||||||
TotalTokens: resp.Usage.TotalTokens,
|
CompletionTokens: resp.Usage.CompletionTokens,
|
||||||
|
TotalTokens: resp.Usage.TotalTokens,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取 AI 输出内容
|
||||||
|
aiOutput := ""
|
||||||
|
if len(resp.Choices) > 0 {
|
||||||
|
aiOutput = resp.Choices[0].Message.Content
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用预设处理
|
||||||
if preset != nil && injector != nil && len(resp.Choices) > 0 {
|
if preset != nil && injector != nil && len(resp.Choices) > 0 {
|
||||||
resp.Choices[0].Message.Content = injector.ProcessResponse(resp.Choices[0].Message.Content)
|
resp.Choices[0].Message.Content = injector.ProcessResponse(resp.Choices[0].Message.Content)
|
||||||
|
aiOutput = resp.Choices[0].Message.Content
|
||||||
|
|
||||||
// 添加正则执行日志到响应
|
// 添加正则执行日志到响应
|
||||||
regexLogs := injector.GetRegexLogs()
|
regexLogs := injector.GetRegexLogs()
|
||||||
if regexLogs.TotalMatches > 0 || len(regexLogs.InputScripts) > 0 || len(regexLogs.OutputScripts) > 0 {
|
if regexLogs.TotalMatches > 0 || len(regexLogs.InputScripts) > 0 || len(regexLogs.OutputScripts) > 0 {
|
||||||
resp.RegexLogs = regexLogs
|
resp.RegexLogs = regexLogs
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 记录匹配到正则时的脚本名称
|
// 记录响应内容(统一日志输出)
|
||||||
if regexLogs.TotalMatches > 0 {
|
logFields := []zap.Field{
|
||||||
matchedScripts := make([]string, 0)
|
zap.String("ai_output", aiOutput),
|
||||||
|
}
|
||||||
|
if resp.Usage != nil {
|
||||||
|
logFields = append(logFields, zap.Any("usage", resp.Usage))
|
||||||
|
}
|
||||||
|
if resp.StandardUsage != nil {
|
||||||
|
logFields = append(logFields, zap.Any("standard_usage", resp.StandardUsage))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加正则脚本执行日志
|
||||||
|
if injector != nil {
|
||||||
|
regexLogs := injector.GetRegexLogs()
|
||||||
|
if regexLogs != nil && (regexLogs.TotalMatches > 0 || len(regexLogs.InputScripts) > 0 || len(regexLogs.OutputScripts) > 0) {
|
||||||
|
// 收集触发的脚本名称
|
||||||
|
triggeredScripts := make([]string, 0)
|
||||||
for _, scriptLog := range regexLogs.InputScripts {
|
for _, scriptLog := range regexLogs.InputScripts {
|
||||||
if scriptLog.MatchCount > 0 {
|
if scriptLog.MatchCount > 0 {
|
||||||
matchedScripts = append(matchedScripts, scriptLog.ScriptName)
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输入:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, scriptLog := range regexLogs.OutputScripts {
|
for _, scriptLog := range regexLogs.OutputScripts {
|
||||||
if scriptLog.MatchCount > 0 {
|
if scriptLog.MatchCount > 0 {
|
||||||
matchedScripts = append(matchedScripts, scriptLog.ScriptName)
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输出:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录接口调用参数和 AI 输出内容
|
if len(triggeredScripts) > 0 {
|
||||||
aiOutput := resp.Choices[0].Message.Content
|
logFields = append(logFields,
|
||||||
global.GVA_LOG.Info("AI 请求完成",
|
zap.Strings("triggered_regex_scripts", triggeredScripts),
|
||||||
zap.Any("request", req),
|
zap.Int("total_matches", regexLogs.TotalMatches),
|
||||||
zap.String("ai_output", aiOutput),
|
)
|
||||||
zap.Strings("matched_regex_scripts", matchedScripts),
|
}
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// 未匹配到正则时仅记录请求和输出
|
|
||||||
aiOutput := resp.Choices[0].Message.Content
|
|
||||||
global.GVA_LOG.Info("AI 请求完成(无正则匹配)",
|
|
||||||
zap.Any("request", req),
|
|
||||||
zap.String("ai_output", aiOutput),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 无预设或无注入器时也记录基础请求与输出
|
|
||||||
if len(resp.Choices) > 0 {
|
|
||||||
aiOutput := resp.Choices[0].Message.Content
|
|
||||||
global.GVA_LOG.Info("AI 请求完成(无预设/注入器)",
|
|
||||||
zap.Any("request", req),
|
|
||||||
zap.String("ai_output", aiOutput),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
global.GVA_LOG.Info("AI 请求完成(无输出)",
|
|
||||||
zap.Any("request", req),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logFields = append(logFields, zap.Any("full_response", resp))
|
||||||
|
global.GVA_LOG.Info("ChatCompletion 响应", logFields...)
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessChatCompletionStream 处理流式聊天补全请求
|
// ProcessChatCompletionStream 处理流式聊天补全请求
|
||||||
func (s *AiProxyService) ProcessChatCompletionStream(c *gin.Context, req *request.ChatCompletionRequest) {
|
func (s *AiProxyService) ProcessChatCompletionStream(c *gin.Context, req *request.ChatCompletionRequest) {
|
||||||
|
// 记录请求参数
|
||||||
|
global.GVA_LOG.Info("收到 ChatCompletion 流式请求",
|
||||||
|
zap.String("model", req.Model),
|
||||||
|
zap.Any("messages", req.Messages),
|
||||||
|
zap.Any("full_request", req),
|
||||||
|
)
|
||||||
|
|
||||||
// 1. 根据模型获取配置
|
// 1. 根据模型获取配置
|
||||||
if req.Model == "" {
|
if req.Model == "" {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "model 参数不能为空"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "model 参数不能为空"})
|
||||||
@@ -304,39 +325,38 @@ func (s *AiProxyService) forwardStreamRequest(c *gin.Context, provider *app.AiPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 流式请求结束后记录日志
|
// 流式请求结束后记录日志
|
||||||
|
logFields := []zap.Field{
|
||||||
|
zap.String("ai_output", fullContent.String()),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加正则脚本执行日志
|
||||||
if injector != nil {
|
if injector != nil {
|
||||||
regexLogs := injector.GetRegexLogs()
|
regexLogs := injector.GetRegexLogs()
|
||||||
|
|
||||||
if regexLogs != nil && (regexLogs.TotalMatches > 0 || len(regexLogs.InputScripts) > 0 || len(regexLogs.OutputScripts) > 0) {
|
if regexLogs != nil && (regexLogs.TotalMatches > 0 || len(regexLogs.InputScripts) > 0 || len(regexLogs.OutputScripts) > 0) {
|
||||||
matchedScripts := make([]string, 0)
|
// 收集触发的脚本名称
|
||||||
|
triggeredScripts := make([]string, 0)
|
||||||
for _, scriptLog := range regexLogs.InputScripts {
|
for _, scriptLog := range regexLogs.InputScripts {
|
||||||
if scriptLog.MatchCount > 0 {
|
if scriptLog.MatchCount > 0 {
|
||||||
matchedScripts = append(matchedScripts, scriptLog.ScriptName)
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输入:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, scriptLog := range regexLogs.OutputScripts {
|
for _, scriptLog := range regexLogs.OutputScripts {
|
||||||
if scriptLog.MatchCount > 0 {
|
if scriptLog.MatchCount > 0 {
|
||||||
matchedScripts = append(matchedScripts, scriptLog.ScriptName)
|
triggeredScripts = append(triggeredScripts, fmt.Sprintf("%s(输出:%d次)", scriptLog.ScriptName, scriptLog.MatchCount))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
global.GVA_LOG.Info("AI 流式请求完成",
|
if len(triggeredScripts) > 0 {
|
||||||
zap.Any("request", req),
|
logFields = append(logFields,
|
||||||
zap.String("ai_output", fullContent.String()),
|
zap.Strings("triggered_regex_scripts", triggeredScripts),
|
||||||
zap.Strings("matched_regex_scripts", matchedScripts),
|
zap.Int("total_matches", regexLogs.TotalMatches),
|
||||||
)
|
)
|
||||||
} else {
|
}
|
||||||
global.GVA_LOG.Info("AI 流式请求完成(无正则匹配)",
|
|
||||||
zap.Any("request", req),
|
|
||||||
zap.String("ai_output", fullContent.String()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
global.GVA_LOG.Info("AI 流式请求完成(无预设/注入器)",
|
|
||||||
zap.Any("request", req),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global.GVA_LOG.Info("ChatCompletion 流式响应完成", logFields...)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user