跳转到主要内容
PRODUCT DOCUMENTS

快速找到所需文档,高效完成接入与排障

浏览产品文档与友盟 Skill,展开目录并阅读正文。

Go

纯标准库,无第三方依赖。

1) 非流式聊天

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

const BaseURL = "https://ai.umeng.com"

func apiKey() string {
    if k := os.Getenv("UMENG_AI_KEY"); k != "" {
        return k
    }
    return "YOUR_API_KEY"
}

type Message struct {
    Role    string `json:"role"`
    Content string `json:"content"`
}

type ChatRequest struct {
    Model          string    `json:"model"`
    EnableThinking bool      `json:"enableThinking"`
    Messages       []Message `json:"messages"`
}

type ChatResponse struct {
    Success bool   `json:"success"`
    Msg     string `json:"msg"`
    Data    struct {
        Content string `json:"content"`
        Meta    struct {
            ActualModel string `json:"actual_model"`
        } `json:"meta"`
        Usage struct {
            CostCredits int `json:"cost_credits"`
        } `json:"usage"`
    } `json:"data"`
}

func Chat(prompt string) (*ChatResponse, error) {
    body, _ := json.Marshal(ChatRequest{
        Model:    "auto",
        Messages: []Message{{Role: "user", Content: prompt}},
    })

    req, _ := http.NewRequest("POST", BaseURL+"/api/llm/chat", bytes.NewReader(body))
    req.Header.Set("Authorization", "Bearer "+apiKey())
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{Timeout: 60 * time.Second}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        b, _ := io.ReadAll(resp.Body)
        return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(b))
    }

    var out ChatResponse
    if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
        return nil, err
    }
    if !out.Success {
        return nil, fmt.Errorf("接口返回失败: %s", out.Msg)
    }
    return &out, nil
}

func main() {
    res, err := Chat("用一句话介绍牛顿第一定律")
    if err != nil {
        fmt.Println("调用失败:", err)
        return
    }
    fmt.Printf("[路由] %s [算力点] %d\n", res.Data.Meta.ActualModel, res.Data.Usage.CostCredits)
    fmt.Println("回答:", res.Data.Content)
}

2) 流式聊天(SSE)

package main

import (
    "bufio"
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "strings"
    "time"
)

const BaseURL = "https://ai.umeng.com"

func apiKey() string {
    if k := os.Getenv("UMENG_AI_KEY"); k != "" {
        return k
    }
    return "YOUR_API_KEY"
}

func ChatStream(prompt string, onDelta func(text string)) error {
    body, _ := json.Marshal(map[string]interface{}{
        "model":          "auto",
        "enableThinking": false,
        "messages":       []map[string]string{{"role": "user", "content": prompt}},
    })

    req, _ := http.NewRequest("POST", BaseURL+"/api/llm/chat/stream", bytes.NewReader(body))
    req.Header.Set("Authorization", "Bearer "+apiKey())
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Accept", "text/event-stream")

    client := &http.Client{Timeout: 120 * time.Second}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    reader := bufio.NewReader(resp.Body)
    var eventType, dataBuf string
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            return nil
        }
        line = strings.TrimRight(line, "\r\n")

        if line == "" {
            if eventType != "" && dataBuf != "" {
                var obj map[string]interface{}
                _ = json.Unmarshal([]byte(dataBuf), &obj)
                switch eventType {
                case "delta":
                    if obj["type"] == "content" {
                        if d, ok := obj["delta"].(string); ok {
                            onDelta(d)
                        }
                    }
                case "done":
                    fmt.Printf("\n[完成] tokens=%v cost=%v\n", obj["total_tokens"], obj["cost_credits"])
                }
            }
            eventType, dataBuf = "", ""
            continue
        }
        if strings.HasPrefix(line, "event:") {
            eventType = strings.TrimSpace(line[6:])
        } else if strings.HasPrefix(line, "data:") {
            dataBuf = strings.TrimSpace(line[5:])
        }
    }
}

func main() {
    ChatStream("请用 Python 写一个 LRU 缓存", func(text string) {
        fmt.Print(text)
    })
}

3) 视频生成(提交 + 轮询)

client := &http.Client{Timeout: 30 * time.Second}

type videoResp struct {
    Success bool `json:"success"`
    Data    struct {
        RequestID string  `json:"request_id"`
        Status    string  `json:"status"`
        VideoURL  string  `json:"video_url"`
        Credits   float64 `json:"credits"`
    } `json:"data"`
}

post := func(path string, payload map[string]interface{}) (videoResp, error) {
    var out videoResp
    b, _ := json.Marshal(payload)
    req, _ := http.NewRequest("POST", BaseURL+path, bytes.NewReader(b))
    req.Header.Set("Authorization", "Bearer "+apiKey())
    req.Header.Set("Content-Type", "application/json")
    resp, err := client.Do(req)
    if err != nil { return out, err }
    defer resp.Body.Close()
    return out, json.NewDecoder(resp.Body).Decode(&out)
}

// ① 提交
submitted, _ := post("/api/llm/chat", map[string]interface{}{
    "model":    "wan2.5-t2v-preview",
    "messages": []map[string]string{{"role": "user", "content": "一只橘猫在窗台上晒太阳"}},
    "videoParams": map[string]interface{}{"resolution": "480P", "ratio": "16:9", "duration": 5},
})
fmt.Println("任务已提交:", submitted.Data.RequestID)

// ② 轮询
for i := 1; i <= 40; i++ {
    r, _ := post("/api/llm/chat/video/result", map[string]interface{}{"requestId": submitted.Data.RequestID})
    fmt.Printf("第 %d 次轮询,状态:%s\n", i, r.Data.Status)
    if r.Data.Status == "SUCCEEDED" {
        fmt.Println("视频地址:", r.Data.VideoURL)
        break
    }
    if r.Data.Status == "FAILED" { break }
    time.Sleep(15 * time.Second)
}