package main import ( "bytes" "encoding/json" "errors" "fmt" "io" "net/http" "strings" "time" ) func requestLLM(config Config, prompt string, imageDataURL string) (string, error) { url := strings.TrimRight(config.Volcengine.BaseURL, "/") + "/chat/completions" body := openAIRequest{ Model: config.Volcengine.Model, Messages: []openAIMessage{ { Role: "user", Content: []openAIContent{ {Type: "text", Text: prompt}, {Type: "image_url", ImageURL: &openAIImageURL{URL: imageDataURL}}, }, }, }, Temperature: 0.2, } data, err := json.Marshal(body) if err != nil { return "", err } request, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data)) if err != nil { return "", err } request.Header.Set("Authorization", "Bearer "+config.Volcengine.APIKey) request.Header.Set("Content-Type", "application/json") client := http.Client{Timeout: 90 * time.Second} response, err := client.Do(request) if err != nil { return "", err } defer response.Body.Close() responseBody, err := io.ReadAll(response.Body) if err != nil { return "", err } if response.StatusCode < 200 || response.StatusCode >= 300 { return "", fmt.Errorf("LLM request failed: status=%d body=%s", response.StatusCode, string(responseBody)) } var result openAIResponse if err := json.Unmarshal(responseBody, &result); err != nil { return "", err } if result.Error != nil && result.Error.Message != "" { return "", errors.New(result.Error.Message) } if len(result.Choices) == 0 || result.Choices[0].Message.Content == "" { return "", errors.New("LLM returned empty content") } return result.Choices[0].Message.Content, nil }