ModleArts对接中吐槽
我记得从2019年底开始,在个大公众场合的宣传上,华为的ModelArts就成为了明星产品,一度超过了IoT平台的宣传。
到了最近才开始要用一下物体分类的图像识别功能,本以为ModelArts经过这么长时间的打磨,应该是用起来效果好,而且很容易对接了,在我之前应该有不计其数的用户,不方便的点都填过坑了。
事实上和我预期的很不一样。
具体表现为:
1、对个人用户使用上,每次启动实例只有一小时,虽然是免费阶段,但和其他平台比,显得比较不够友好。
2、Api使用说明不够清晰,没有提供各个主流语言的Demo样例,工单上的售后更是说,只实现了Python的Api,其他语言要自己实现。
3、要说到接口实现,Api Explorer也是最近全栈开发课程推广的重点,但是ModeArts却不在列。
4、要想自己实现Api,第一个看到的就是作为文件上传,但是没有给足够的说明上传要求,根据通用做法还不行,需要走AK、SK认证,这个认证就需要他们的类库,但是类库signer后返回的东西,不包含如何上传给ModelArts图片。而且只支持image文件上传识别,不支持base64格式,这一点最不理解。下载了华为的.net SDK 用了其中的签名,依然不行,最后是看懂了源码uaweicloud-sdk-net-v3\Core\Signer,尝试修改了签名httprequest对象接收。
最后根据自己的需要从SDK V3代码中之拿了Core\Signer的2个文件HttpEncoder.cs和Signer.cs稍微修改了一下其中一个方法,让它接收自定义的MultipartFormDataContent。移植过程发现,此代码还和HuaweiCloud.SDK.Core中单Signer冲突,当时还以为后者是完善的,可发现除了名字一样,实现的功能更少。看来华为这方面合格产品还没整合好SDK统一性。
修改的代码段如下:
public HttpRequestMessage SignHttp(HttpRequest r, MultipartFormDataContent formDataContent = null)
{
var queryString = CanonicalQueryString(r);
if (queryString != "")
{
queryString = "?" + queryString;
}
HttpRequestMessage req = new HttpRequestMessage(new HttpMethod(r.Method), r.Host + r.Url + queryString);
if (r.Method != "POST" && r.Method != "PATCH" && r.Method != "PUT")
{
r.Body = "";
}
else
{
req.Content = new StringContent(r.Body);
}
if (formDataContent != null)
{
req.Content = formDataContent;
}
var time = r.Headers.GetValues(HeaderXDate);
DateTime t;
if (time == null)
{
t = DateTime.Now;
r.Headers.Add(HeaderXDate, t.ToUniversalTime().ToString(BasicDateFormat));
}
else
{
t = DateTime.ParseExact(time[0], BasicDateFormat, CultureInfo.CurrentCulture);
}
string host = null;
if (r.Headers.GetValues(HeaderHost) != null)
{
host = r.Headers.GetValues(HeaderHost)[0];
req.Headers.Host = host;
}
else
{
host = req.RequestUri.Host;
}
r.Headers.Set("host", host);
var signedHeaders = SignedHeaders(r);
var canonicalRequest = CanonicalRequest(r, signedHeaders);
r.CanonicalRequest = canonicalRequest;
var stringToSign = StringToSign(canonicalRequest, t);
r.StringToSign = stringToSign;
var signature = SignStringToSign(stringToSign, Encoding.UTF8.GetBytes(secret));
var authValue = AuthHeaderValue(signature, signedHeaders);
r.Headers.Set(HeaderAuthorization, authValue);
r.Headers.Remove("host");
foreach (string key in r.Headers.AllKeys)
{
req.Headers.TryAddWithoutValidation(key, r.Headers[key]);
}
return req;
}
修改后的使用如下,可以上传图片给图像预测结果
/// <summary>
/// 识别图像类别
/// </summary>
/// <param name="filebuffer"></param>
/// <param name="filename"></param>
/// <returns>PredictedLabel</returns>
public static async Task<string> RecognizeImage(byte[] filebuffer, string filename)
{
try
{
var signer = new HwSdkCore2.Signer
{
Key = _AK,
Secret = _SK
};
var r = new HwSdkCore2.HttpRequest(method: "POST",
url: new Uri("https://********************.apig.cn-north-4.huaweicloudapis.com/v1/infers/**************"));
r.Headers.Add("x-stage", "RELEASE");
r.Headers.Add("x-sdk-content-sha256", "UNSIGNED-PAYLOAD");
r.Headers.Add("content-type", "multipart/form-data");
var content = new MultipartFormDataContent
{
{ new ByteArrayContent(filebuffer), "images", filename }
};
var req = signer.SignHttp(r, content);
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(req);
var data = JsonUtils.DeSerialize<Models.RecognizeImageResp>(response);
return data.PredictedLabel;
}
catch (Exception ex)
{
var a = ex;
}
return string.Empty;
}
- 点赞
- 收藏
- 关注作者
评论(0)