Go: add LLM usage (#17049)

### Summary

```
RAGFlow(api/default)> CHAT WITH 'glm-4-flash@new_test@zhipu-ai' MESSAGE '30 words describes LLM';
Answer: Hello! I'm ChatGLM, an AI assistant. Feel free to ask me any questions or request help with any tasks.
Input tokens: 5
Output tokens: 28
Time: 12.748241
```

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
Jin Hai
2026-07-17 21:28:43 +08:00
committed by GitHub
parent c420de0dc5
commit 8ebdc02cf6
7 changed files with 78 additions and 47 deletions

View File

@@ -193,6 +193,7 @@ func NewDriverHTTPClient() *http.Client {
t.IdleConnTimeout = 90 * time.Second
t.DisableCompression = false
t.ResponseHeaderTimeout = 60 * time.Second
t.TLSHandshakeTimeout = 30 * time.Second
return &http.Client{Transport: t}
}

View File

@@ -177,6 +177,28 @@ type ChatConfig struct {
StreamCallback func(contentDelta, reasoningDelta string) `json:"-"`
}
type ChatAppConfig struct {
UserID string `json:"user_id"`
UserEmail string `json:"user_email"`
TenantID string `json:"tenant_id"`
TenantEmail string `json:"tenant_email"`
GroupID *string `json:"group_id"`
GroupName *string `json:"group_name"`
AppID string `json:"app_id"`
AppName string `json:"app_name"`
SessionID *string `json:"session_id"`
ProviderName string `json:"provider_name"`
InstanceID string `json:"instance_id"`
ModelName string `json:"model_name"`
Type string `json:"type"`
InputTokens uint64 `json:"input_tokens"`
OutputTokens uint64 `json:"output_tokens"`
TotalTokens uint64 `json:"total_tokens"`
RequestID *string `json:"request_id"`
ResponseTimeMS uint64 `json:"response_time_ms"`
ErrorMessage *string `json:"error_message"`
}
type APIConfig struct {
ApiKey *string
Region *string

View File

@@ -55,6 +55,31 @@ func (z *ZhipuAIModel) Name() string {
return "zhipu"
}
type ZhipuChatResponse struct {
Choices []struct {
FinishReason string `json:"finish_reason"`
Index int `json:"index"`
Message struct {
Content string `json:"content"`
ReasoningContent string `json:"reasoning_content"`
Role string `json:"role"`
} `json:"message"`
} `json:"choices"`
Created int `json:"created"`
Id string `json:"id"`
Model string `json:"model"`
Object string `json:"object"`
RequestId string `json:"request_id"`
Usage struct {
CompletionTokens int `json:"completion_tokens"`
PromptTokens int `json:"prompt_tokens"`
PromptTokensDetails struct {
CachedTokens int `json:"cached_tokens"`
} `json:"prompt_tokens_details"`
TotalTokens int `json:"total_tokens"`
} `json:"usage"`
}
// ChatWithMessages sends multiple messages with roles and returns response
func (z *ZhipuAIModel) ChatWithMessages(modelName string, messages []Message, apiConfig *APIConfig, chatModelConfig *ChatConfig) (*ChatResponse, error) {
if err := z.baseModel.APIConfigCheck(apiConfig); err != nil {
@@ -155,46 +180,28 @@ func (z *ZhipuAIModel) ChatWithMessages(modelName string, messages []Message, ap
}
// Parse response
var result map[string]interface{}
var result ZhipuChatResponse
if err = json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("failed to parse response: %w", err)
}
choices, ok := result["choices"].([]interface{})
if !ok || len(choices) == 0 {
return nil, fmt.Errorf("no choices in response")
}
content := &result.Choices[0].Message.Content
firstChoice, ok := choices[0].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("invalid choice format")
}
messageMap, ok := firstChoice["message"].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("invalid message format")
}
content, ok := messageMap["content"].(string)
if !ok {
return nil, fmt.Errorf("invalid content format")
}
var reasonContent string
var reasonContent *string
if chatModelConfig != nil && chatModelConfig.Thinking != nil && *chatModelConfig.Thinking {
reasonContent, ok = messageMap["reasoning_content"].(string)
if !ok {
return nil, fmt.Errorf("invalid content format")
}
// if first char of reasonContent is \n remove the '\n'
if reasonContent != "" && reasonContent[0] == '\n' {
reasonContent = reasonContent[1:]
}
reasonContent = &result.Choices[0].Message.ReasoningContent
}
usage := &ChatUsage{
PromptTokens: result.Usage.PromptTokens,
CompletionTokens: result.Usage.CompletionTokens,
TotalTokens: result.Usage.TotalTokens,
}
chatResponse := &ChatResponse{
Answer: &content,
ReasonContent: &reasonContent,
Answer: content,
ReasonContent: reasonContent,
Usage: usage,
}
return chatResponse, nil