saw-go/service/spark/spark-image.go

171 lines
4.7 KiB
Go
Raw Permalink Blame History

package spark
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
"time"
"github.com/gorilla/websocket"
)
var (
hostUrl = "wss://spark-api.cn-huabei-1.xf-yun.com/v2.1/image"
appid = "XXXXXXXX"
apiKey = "XXXXXXXXXXXXXXXXXXXXXXXX"
apiSecret = "XXXXXXXXXXXXXXXXXXXXXXXX"
)
func sparkImage() {
d := websocket.Dialer{
HandshakeTimeout: 20 * time.Second,
}
conn, resp, err := d.Dial(assembleAuthUrl(hostUrl, apiKey, apiSecret), nil)
if err != nil {
panic(readResp(resp) + err.Error())
return
} else if resp.StatusCode != 101 {
panic(readResp(resp) + err.Error())
}
//璇诲彇鍥剧墖
image, err := os.ReadFile("./1.png")
messages := []Message{
{Role: "user", Content: base64.StdEncoding.EncodeToString(image), ContentType: "image"}, // 棣栨潯蹇呴』鏄浘鐗<E6B598>
{Role: "user", Content: "鍥剧墖鏈夊嚑涓汉", ContentType: "text"},
{Role: "assistant", Content: "鍥剧墖閲岄潰鏈変竴涓汉", ContentType: "text"},
{Role: "user", Content: "杩欎釜浜虹┛浠€涔堣。鏈<E38082>", ContentType: "text"},
}
data := map[string]interface{}{
"header": map[string]interface{}{
"app_id": appid,
},
"parameter": map[string]interface{}{
"chat": map[string]interface{}{
"domain": "imagev3",
},
},
"payload": map[string]interface{}{ // 鏍规嵁瀹為檯鎯呭喌淇敼杩斿洖鐨勬暟鎹粨鏋勫拰瀛楁鍚<EE868C>
"message": map[string]interface{}{ // 鏍规嵁瀹為檯鎯呭喌淇敼杩斿洖鐨勬暟鎹粨鏋勫拰瀛楁鍚<EE868C>
"text": messages, // 鏍规嵁瀹為檯鎯呭喌淇敼杩斿洖鐨勬暟鎹粨鏋勫拰瀛楁鍚<EE868C>
},
},
}
conn.WriteJSON(data)
var answer = ""
//鑾峰彇杩斿洖鐨勬暟鎹<E69A9F>
for {
_, msg, err := conn.ReadMessage()
if err != nil {
fmt.Println("read message error:", err)
break
}
var data map[string]interface{}
err1 := json.Unmarshal(msg, &data)
if err1 != nil {
fmt.Println("Error parsing JSON:", err)
return
}
fmt.Println(string(msg))
//瑙f瀽鏁版嵁
payload := data["payload"].(map[string]interface{})
choices := payload["choices"].(map[string]interface{})
header := data["header"].(map[string]interface{})
code := header["code"].(float64)
if code != 0 {
fmt.Println(data["payload"])
return
}
status := choices["status"].(float64)
fmt.Println(status)
text := choices["text"].([]interface{})
content := text[0].(map[string]interface{})["content"].(string)
if status != 2 {
answer += content
} else {
fmt.Println("鏀跺埌鏈€缁堢粨鏋<E7B2A8>")
answer += content
usage := payload["usage"].(map[string]interface{})
temp := usage["text"].(map[string]interface{})
totalTokens := temp["total_tokens"].(float64)
fmt.Println("total_tokens:", totalTokens)
conn.Close()
break
}
}
//杈撳嚭杩斿洖缁撴灉
fmt.Println(answer)
time.Sleep(1 * time.Second)
}
// 鍒涘缓閴存潈url apikey 鍗<> hmac username
func assembleAuthUrl(hosturl string, apiKey, apiSecret string) string {
ul, err := url.Parse(hosturl)
if err != nil {
fmt.Println(err)
}
//绛惧悕鏃堕棿
date := time.Now().UTC().Format(time.RFC1123)
//date = "Tue, 28 May 2019 09:10:42 MST"
//鍙備笌绛惧悕鐨勫瓧娈<E793A7> host ,date, request-line
signString := []string{"host: " + ul.Host, "date: " + date, "GET " + ul.Path + " HTTP/1.1"}
//鎷兼帴绛惧悕瀛楃涓<EE8381>
sgin := strings.Join(signString, "\n")
// fmt.Println(sgin)
//绛惧悕缁撴灉
sha := HmacWithShaTobase64("hmac-sha256", sgin, apiSecret)
// fmt.Println(sha)
//鏋勫缓璇锋眰鍙傛暟 姝ゆ椂涓嶉渶瑕乽rlencoding
authUrl := fmt.Sprintf("hmac username=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey,
"hmac-sha256", "host date request-line", sha)
//灏嗚姹傚弬鏁颁娇鐢╞ase64缂栫爜
authorization := base64.StdEncoding.EncodeToString([]byte(authUrl))
v := url.Values{}
v.Add("host", ul.Host)
v.Add("date", date)
v.Add("authorization", authorization)
//灏嗙紪鐮佸悗鐨勫瓧绗︿覆url encode鍚庢坊鍔犲埌url鍚庨潰
callurl := hosturl + "?" + v.Encode()
return callurl
}
func HmacWithShaTobase64(algorithm, data, key string) string {
mac := hmac.New(sha256.New, []byte(key))
mac.Write([]byte(data))
encodeData := mac.Sum(nil)
return base64.StdEncoding.EncodeToString(encodeData)
}
func readResp(resp *http.Response) string {
if resp == nil {
return ""
}
b, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
return fmt.Sprintf("code=%d,body=%s", resp.StatusCode, string(b))
}
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
ContentType string `json:"content_type"`
}