mirror of
https://github.com/alibaba/higress.git
synced 2026-05-28 22:57:31 +08:00
feat(ai-statistics): add system field support for Claude /v1/messages API (#3511)
This commit is contained in:
@@ -105,6 +105,7 @@ const (
|
|||||||
BuiltinAnswerKey = "answer"
|
BuiltinAnswerKey = "answer"
|
||||||
BuiltinToolCallsKey = "tool_calls"
|
BuiltinToolCallsKey = "tool_calls"
|
||||||
BuiltinReasoningKey = "reasoning"
|
BuiltinReasoningKey = "reasoning"
|
||||||
|
BuiltinSystemKey = "system"
|
||||||
BuiltinReasoningTokens = "reasoning_tokens"
|
BuiltinReasoningTokens = "reasoning_tokens"
|
||||||
BuiltinCachedTokens = "cached_tokens"
|
BuiltinCachedTokens = "cached_tokens"
|
||||||
BuiltinInputTokenDetails = "input_token_details"
|
BuiltinInputTokenDetails = "input_token_details"
|
||||||
@@ -115,6 +116,9 @@ const (
|
|||||||
QuestionPathOpenAI = "messages.@reverse.0.content"
|
QuestionPathOpenAI = "messages.@reverse.0.content"
|
||||||
QuestionPathClaude = "messages.@reverse.0.content" // Claude uses same format
|
QuestionPathClaude = "messages.@reverse.0.content" // Claude uses same format
|
||||||
|
|
||||||
|
// System prompt paths (from request body)
|
||||||
|
SystemPathClaude = "system" // Claude /v1/messages has system as a top-level field
|
||||||
|
|
||||||
// Answer paths (from response body - non-streaming)
|
// Answer paths (from response body - non-streaming)
|
||||||
AnswerPathOpenAINonStreaming = "choices.0.message.content"
|
AnswerPathOpenAINonStreaming = "choices.0.message.content"
|
||||||
AnswerPathClaudeNonStreaming = "content.0.text"
|
AnswerPathClaudeNonStreaming = "content.0.text"
|
||||||
@@ -150,6 +154,10 @@ func getDefaultAttributes() []Attribute {
|
|||||||
Key: BuiltinQuestionKey,
|
Key: BuiltinQuestionKey,
|
||||||
ApplyToLog: true,
|
ApplyToLog: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Key: BuiltinSystemKey,
|
||||||
|
ApplyToLog: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Key: BuiltinAnswerKey,
|
Key: BuiltinAnswerKey,
|
||||||
ApplyToLog: true,
|
ApplyToLog: true,
|
||||||
@@ -871,7 +879,7 @@ func setAttributeBySource(ctx wrapper.HttpContext, config AIStatisticsConfig, so
|
|||||||
|
|
||||||
// isBuiltinAttribute checks if the given key is a built-in attribute
|
// isBuiltinAttribute checks if the given key is a built-in attribute
|
||||||
func isBuiltinAttribute(key string) bool {
|
func isBuiltinAttribute(key string) bool {
|
||||||
return key == BuiltinQuestionKey || key == BuiltinAnswerKey || key == BuiltinToolCallsKey || key == BuiltinReasoningKey ||
|
return key == BuiltinQuestionKey || key == BuiltinAnswerKey || key == BuiltinToolCallsKey || key == BuiltinReasoningKey || key == BuiltinSystemKey ||
|
||||||
key == BuiltinReasoningTokens || key == BuiltinCachedTokens ||
|
key == BuiltinReasoningTokens || key == BuiltinCachedTokens ||
|
||||||
key == BuiltinInputTokenDetails || key == BuiltinOutputTokenDetails
|
key == BuiltinInputTokenDetails || key == BuiltinOutputTokenDetails
|
||||||
}
|
}
|
||||||
@@ -880,7 +888,7 @@ func isBuiltinAttribute(key string) bool {
|
|||||||
// Returns nil if the key is not a built-in attribute
|
// Returns nil if the key is not a built-in attribute
|
||||||
func getBuiltinAttributeDefaultSources(key string) []string {
|
func getBuiltinAttributeDefaultSources(key string) []string {
|
||||||
switch key {
|
switch key {
|
||||||
case BuiltinQuestionKey:
|
case BuiltinQuestionKey, BuiltinSystemKey:
|
||||||
return []string{RequestBody}
|
return []string{RequestBody}
|
||||||
case BuiltinAnswerKey, BuiltinToolCallsKey, BuiltinReasoningKey:
|
case BuiltinAnswerKey, BuiltinToolCallsKey, BuiltinReasoningKey:
|
||||||
return []string{ResponseStreamingBody, ResponseBody}
|
return []string{ResponseStreamingBody, ResponseBody}
|
||||||
@@ -918,6 +926,13 @@ func getBuiltinAttributeFallback(ctx wrapper.HttpContext, config AIStatisticsCon
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case BuiltinSystemKey:
|
||||||
|
if source == RequestBody {
|
||||||
|
// Try Claude /v1/messages format (system is a top-level field)
|
||||||
|
if value := gjson.GetBytes(body, SystemPathClaude).Value(); value != nil && value != "" {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
case BuiltinAnswerKey:
|
case BuiltinAnswerKey:
|
||||||
if source == ResponseStreamingBody {
|
if source == ResponseStreamingBody {
|
||||||
// Try OpenAI format first
|
// Try OpenAI format first
|
||||||
@@ -1069,6 +1084,9 @@ func debugLogAiLog(ctx wrapper.HttpContext) {
|
|||||||
if question := ctx.GetUserAttribute("question"); question != nil {
|
if question := ctx.GetUserAttribute("question"); question != nil {
|
||||||
userAttrs["question"] = question
|
userAttrs["question"] = question
|
||||||
}
|
}
|
||||||
|
if system := ctx.GetUserAttribute("system"); system != nil {
|
||||||
|
userAttrs["system"] = system
|
||||||
|
}
|
||||||
if answer := ctx.GetUserAttribute("answer"); answer != nil {
|
if answer := ctx.GetUserAttribute("answer"); answer != nil {
|
||||||
userAttrs["answer"] = answer
|
userAttrs["answer"] = answer
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user