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)
}