172 lines
4.7 KiB
Go
172 lines
4.7 KiB
Go
|
|
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: 5 * time.Second,
|
|||
|
|
}
|
|||
|
|
//鎻℃墜骞跺缓绔媤ebsocket 杩炴帴
|
|||
|
|
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"`
|
|||
|
|
}
|