Former-commit-id: b9a63135985181860db8f8ad620b2ca1e0144c6f
This commit is contained in:
tzwang 2024-06-26 17:14:02 +08:00
commit 10e39bbd61
11 changed files with 381 additions and 14 deletions

View File

@ -175,7 +175,7 @@ type VmInfo struct {
//DeletedAt string `json:"deletedAt,omitempty"`
VmName string `json:"vmName,omitempty"`
Replicas int64 `json:"replicas,omitempty"`
ServerId string `json:"serverId,omitempty"`
//ServerId string `json:"serverId,omitempty"`
}
type ResourceStats struct {

View File

@ -1818,4 +1818,12 @@ service AICore-api {
get /getVisualizationJob (GetVisualizationJobReq) returns (GetVisualizationJobResp)
@handler createVisualizationJobHandler
post /CreateVisualizationJob (CreateVisualizationJobReq) returns (CreateVisualizationJobResp)
}*/
}*/
type (
ChatReq{
ApiUrl string `json:"apiUrl,optional"`
Method string `json:"method,optional"`
ReqData map[string]interface{} `json:"reqData"`
}
)

View File

@ -1256,5 +1256,14 @@ type (
ClusterName string `json:"clusterName" db:"cluster_name"`
Status string `json:"status" db:"status"`
Remark string `json:"remark" db:"remark"`
InferUrl string `json:"inferUrl"`
}
)
type (
CommonResp {
Code int `json:"code,omitempty"`
Msg string `json:"msg,omitempty"`
Data interface{} `json:"data,omitempty"`
}
)

View File

@ -366,6 +366,12 @@ service pcm {
@handler createVisualizationJobHandler
post /ai/CreateVisualizationJob (CreateVisualizationJobReq) returns (CreateVisualizationJobResp)
/******************Visualization Job Method start*************************/
/***********chat***********/
@doc "文本识别"
@handler ProxyApiHandler
post /ai/chat (ChatReq) returns (CommonResp)
/******chat end***********/
}
//screen接口

View File

@ -0,0 +1,24 @@
package ai
import (
"github.com/zeromicro/go-zero/rest/httpx"
"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/logic/ai"
"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result"
"net/http"
)
func ProxyApiHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.ChatReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := ai.NewProxyApiLogic(r.Context(), svcCtx)
resp, err := l.ProxyApi(&req, w)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -437,6 +437,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/ai/CreateVisualizationJob",
Handler: ai.CreateVisualizationJobHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/ai/chat",
Handler: ai.ProxyApiHandler(serverCtx),
},
},
rest.WithPrefix("/pcm/v1"),
)

View File

@ -0,0 +1,89 @@
package ai
import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"fmt"
tool "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils"
"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils/hws"
"net/http"
"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc"
"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ProxyApiLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewProxyApiLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ProxyApiLogic {
return &ProxyApiLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
type ChatResult struct {
Results string `json:"results"`
}
type ResponseData struct {
Results string `json:"results"`
}
func (l *ProxyApiLogic) ProxyApi(req *types.ChatReq, w http.ResponseWriter) (resp *types.CommonResp, err error) {
jsonBytes, err := json.Marshal(&req.ReqData)
// 调用第三方接口的 POST 方法
thirdReq, err := http.NewRequest("POST", req.ApiUrl, bytes.NewBuffer(jsonBytes))
if err != nil {
return
}
signer := &hws.Signer{
Key: "UNEHPHO4Z7YSNPKRXFE4",
Secret: "JWXCE9qcYbc7RjpSRIWt4WgG3ZKF6Q4lPzkJReX9",
}
if err := signer.Sign(thirdReq); err != nil {
return nil, err
}
// 设置client信任所有证书
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{
Transport: tr,
}
thirdReq.Header.Set("X-Project-Id", "d18190e28e3f45a281ef0b0696ec9d52")
thirdReq.Header.Set("x-stage", "RELEASE")
thirdReq.Header.Set("Authorization", thirdReq.Header.Get(hws.HeaderXAuthorization))
thirdReq.Header.Set("X-Sdk-Date", thirdReq.Header.Get(hws.HeaderXDateTime))
thirdReq.Header.Set("Content-Type", "application/json")
thirdResp, err := client.Do(thirdReq)
defer thirdReq.Body.Close()
var responseData ResponseData
decoder := json.NewDecoder(thirdResp.Body)
if err := decoder.Decode(&responseData); err != nil {
fmt.Println("Error decoding response:", err)
}
chatResult := &ChatResult{}
tool.Convert(responseData, &chatResult)
return &types.CommonResp{
Code: thirdResp.StatusCode,
Msg: "success",
Data: chatResult,
}, nil
}

View File

@ -445,6 +445,7 @@ func sendInferReq(images []struct {
func getInferResult(url string, file multipart.File, fileName string, clusterName string) (string, error) {
if clusterName == "鹏城云脑II-modelarts" {
r, err := getInferResultModelarts(url, file, fileName)
log.Printf("图形识别url: %s", url)
if err != nil {
return "", err
}
@ -464,19 +465,8 @@ func getInferResult(url string, file multipart.File, fileName string, clusterNam
func getInferResultModelarts(url string, file multipart.File, fileName string) (string, error) {
var res Res
/* req := GetRestyRequest(20)
_, err := req.
SetFileReader("file", fileName, file).
SetHeaders(map[string]string{
"ak": "UNEHPHO4Z7YSNPKRXFE4",
"sk": "JWXCE9qcYbc7RjpSRIWt4WgG3ZKF6Q4lPzkJReX9",
}).
SetResult(&res).
Post(url)
if err != nil {
return "", err
}*/
body, err := utils.SendRequest("POST", url, file, fileName)
log.Printf("图形识别url: %s", url)
if err != nil {
return "", err
}
@ -484,6 +474,7 @@ func getInferResultModelarts(url string, file multipart.File, fileName string) (
if errjson != nil {
log.Fatalf("Error parsing JSON: %s", errjson)
}
log.Printf("推理结果: %s", res.Result)
return res.Result, nil
}

View File

@ -1179,6 +1179,13 @@ type SubTaskInfo struct {
ClusterName string `json:"clusterName" db:"cluster_name"`
Status string `json:"status" db:"status"`
Remark string `json:"remark" db:"remark"`
InferUrl string `json:"inferUrl"`
}
type CommonResp struct {
Code int `json:"code,omitempty"`
Msg string `json:"msg,omitempty"`
Data interface{} `json:"data,omitempty"`
}
type CommitHpcTaskReq struct {
@ -2869,6 +2876,12 @@ type AiTask struct {
TimeElapsed int32 `json:"elapsed,optional"`
}
type ChatReq struct {
ApiUrl string `json:"apiUrl,optional"`
Method string `json:"method,optional"`
ReqData map[string]interface{} `json:"reqData"`
}
type StorageScreenReq struct {
}

38
pkg/utils/hws/escape.go Normal file
View File

@ -0,0 +1,38 @@
package hws
func shouldEscape(c byte) bool {
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c == '-' || c == '~' || c == '.' {
return false
}
return true
}
func Escape(s string) string {
hexCount := 0
for i := 0; i < len(s); i++ {
c := s[i]
if shouldEscape(c) {
hexCount++
}
}
if hexCount == 0 {
return s
}
t := make([]byte, len(s)+2*hexCount)
j := 0
for i := 0; i < len(s); i++ {
switch c := s[i]; {
case shouldEscape(c):
t[j] = '%'
t[j+1] = "0123456789ABCDEF"[c>>4]
t[j+2] = "0123456789ABCDEF"[c&15]
j += 3
default:
t[j] = s[i]
j++
}
}
return string(t)
}

184
pkg/utils/hws/signer.go Normal file
View File

@ -0,0 +1,184 @@
package hws
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"fmt"
"io/ioutil"
"net/http"
"sort"
"strings"
"time"
)
const (
DateFormat = "20060102T150405Z"
SignAlgorithm = "SDK-HMAC-SHA256"
HeaderXDateTime = "X-Sdk-Date"
HeaderXHost = "host"
HeaderXAuthorization = "Authorization"
HeaderXContentSha256 = "X-Sdk-Content-Sha256"
)
func hmacsha256(keyByte []byte, dataStr string) ([]byte, error) {
hm := hmac.New(sha256.New, []byte(keyByte))
if _, err := hm.Write([]byte(dataStr)); err != nil {
return nil, err
}
return hm.Sum(nil), nil
}
func CanonicalRequest(request *http.Request, signedHeaders []string) (string, error) {
var hexencode string
var err error
if hex := request.Header.Get(HeaderXContentSha256); hex != "" {
hexencode = hex
} else {
bodyData, err := RequestPayload(request)
if err != nil {
return "", err
}
hexencode, err = HexEncodeSHA256Hash(bodyData)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", request.Method, CanonicalURI(request), CanonicalQueryString(request), CanonicalHeaders(request, signedHeaders), strings.Join(signedHeaders, ";"), hexencode), err
}
func CanonicalURI(request *http.Request) string {
pattens := strings.Split(request.URL.Path, "/")
var uriSlice []string
for _, v := range pattens {
uriSlice = append(uriSlice, Escape(v))
}
urlpath := strings.Join(uriSlice, "/")
if len(urlpath) == 0 || urlpath[len(urlpath)-1] != '/' {
urlpath = urlpath + "/"
}
return urlpath
}
func CanonicalQueryString(request *http.Request) string {
var keys []string
queryMap := request.URL.Query()
for key := range queryMap {
keys = append(keys, key)
}
sort.Strings(keys)
var query []string
for _, key := range keys {
k := Escape(key)
sort.Strings(queryMap[key])
for _, v := range queryMap[key] {
kv := fmt.Sprintf("%s=%s", k, Escape(v))
query = append(query, kv)
}
}
queryStr := strings.Join(query, "&")
request.URL.RawQuery = queryStr
return queryStr
}
func CanonicalHeaders(request *http.Request, signerHeaders []string) string {
var canonicalHeaders []string
header := make(map[string][]string)
for k, v := range request.Header {
header[strings.ToLower(k)] = v
}
for _, key := range signerHeaders {
value := header[key]
if strings.EqualFold(key, HeaderXHost) {
value = []string{request.Host}
}
sort.Strings(value)
for _, v := range value {
canonicalHeaders = append(canonicalHeaders, key+":"+strings.TrimSpace(v))
}
}
return fmt.Sprintf("%s\n", strings.Join(canonicalHeaders, "\n"))
}
func SignedHeaders(r *http.Request) []string {
var signedHeaders []string
for key := range r.Header {
signedHeaders = append(signedHeaders, strings.ToLower(key))
}
sort.Strings(signedHeaders)
return signedHeaders
}
func RequestPayload(request *http.Request) ([]byte, error) {
if request.Body == nil {
return []byte(""), nil
}
bodyByte, err := ioutil.ReadAll(request.Body)
if err != nil {
return []byte(""), err
}
request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyByte))
return bodyByte, err
}
func StringToSign(canonicalRequest string, t time.Time) (string, error) {
hashStruct := sha256.New()
_, err := hashStruct.Write([]byte(canonicalRequest))
if err != nil {
return "", err
}
return fmt.Sprintf("%s\n%s\n%x",
SignAlgorithm, t.UTC().Format(DateFormat), hashStruct.Sum(nil)), nil
}
func SignStringToSign(stringToSign string, signingKey []byte) (string, error) {
hmsha, err := hmacsha256(signingKey, stringToSign)
return fmt.Sprintf("%x", hmsha), err
}
func HexEncodeSHA256Hash(body []byte) (string, error) {
hashStruct := sha256.New()
if len(body) == 0 {
body = []byte("")
}
_, err := hashStruct.Write(body)
return fmt.Sprintf("%x", hashStruct.Sum(nil)), err
}
func AuthHeaderValue(signatureStr, accessKeyStr string, signedHeaders []string) string {
return fmt.Sprintf("%s Access=%s, SignedHeaders=%s, Signature=%s", SignAlgorithm, accessKeyStr, strings.Join(signedHeaders, ";"), signatureStr)
}
type Signer struct {
Key string
Secret string
}
func (s *Signer) Sign(request *http.Request) error {
var t time.Time
var err error
var date string
if date = request.Header.Get(HeaderXDateTime); date != "" {
t, err = time.Parse(DateFormat, date)
}
if err != nil || date == "" {
t = time.Now()
request.Header.Set(HeaderXDateTime, t.UTC().Format(DateFormat))
}
signedHeaders := SignedHeaders(request)
canonicalRequest, err := CanonicalRequest(request, signedHeaders)
if err != nil {
return err
}
stringToSignStr, err := StringToSign(canonicalRequest, t)
if err != nil {
return err
}
signatureStr, err := SignStringToSign(stringToSignStr, []byte(s.Secret))
if err != nil {
return err
}
authValueStr := AuthHeaderValue(signatureStr, s.Key, signedHeaders)
request.Header.Set(HeaderXAuthorization, authValueStr)
return nil
}