当前位置: 首页 > news >正文

【通义晓蜜CCAI实践】通过任务类型调用通义晓蜜CCAI-对话分析AIO应用

ROA风格请求体&签名机制

通过公共请求头设置接口必要的参数信息,在签名机制的实现上屏蔽了接口风格的差异,更标准、更简单。本文提供了详细的指南,用于帮助您了解和实施阿里云SDK V3版的请求结构和签名过程。您会了解如何构造标准的HTTP请求,以及如何使用正确的签名算法来验证请求的身份,确保传输的数据的完整性和安全性。如果您想自研阿里云OpenAPI的请求签名,您可以参考本文。

请求编码

请求及返回结果都使用UTF-8字符集进行编码。

RequestHeader(公共请求头)

一个完整的阿里云 OpenAPI 请求,包含以下部分。

名称

类型

是否必选

描述

示例值

x-acs-action

String

API的名称。

RunInstances

x-acs-version

String

API 版本。

2014-05-26

Authorization

String

非匿名请求必须

用于验证请求合法性的认证信息,格式为Authorization:SignatureAlgorithmCredential=AccessKeyId,SignedHeaders=SignedHeaders,Signature=Signature。其中SignatureAlgorithm为签名加密方式,为ACS3-HMAC-SHA256。

Credential为用户的访问密钥ID。您可以在RAM 控制台查看您的 AccessKeyId。如需创建 AccessKey,请参见创建AccessKey。SignedHeaders为请求头中包含的参与签名字段键名,【说明】:除Authorization外的所有公共请求头,只要存在必须被加入签名。

Signature为请求签名,取值参见签名机制。

ACS3-HMAC-SHA256 Credential=YourAccessKeyId,SignedHeaders=host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version,Signature=e521358f7776c97df52e6b2891a8bc73026794a071b50c3323388c4e0df64804

x-acs-signature-nonce

String

签名唯一随机数。用于防止网络重放攻击,建议您每一次请求都使用不同的随机数。

d410180a5abf7fe235dd9b74aca91fc0

x-acs-date

String

按照ISO 8601标准表示的UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ,例如2018-01-01T12:00:00Z。值为请求发出前15分钟内的时间。

2023-10-26T09:01:01Z

host

String

即 Endpoint。您可以查阅不同云产品的服务接入地址文档,查阅不同服务区域下的服务地址。

ecs.cn-shanghai.aliyuncs.com

x-acs-content-sha256

String

请求正文Hash摘要后再base-16编码的结果,与HashedRequestPayload一致。

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

x-acs-security-token

String

STS认证必传

为调用Assumerole接口返回值中SecurityToken的值。

签名机制

为保证API的安全调用,在调用API时阿里云会对每个API请求通过签名(Signature)进行身份验证。无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名信息。本文指导您如何进行签名处理。

步骤一:构造规范化请求

使用AK/SK方式进行签名与认证,首先需要规范请求内容,然后再进行签名。客户端与云服务API网关使用相同的请求规范,可以确保同一个HTTP请求的前后端得到相同的签名结果,从而完成身份校验。

构造规范化请求(CanonicalRequest)的伪代码如下:

CanonicalRequest =HTTPRequestMethod + '\n' +    //http请求方法,全大写CanonicalURI + '\n' +         //规范化URICanonicalQueryString + '\n' + //规范化查询字符串CanonicalHeaders + '\n' +     //规范化消息头SignedHeaders + '\n' +        //已签名消息头HashedRequestPayload			
  • 请求方法(HTTPRequestMethod)

    即大写的HTTP方法名,如GET、POST。

  • 规范化URI(CanonicalURI)

    即URL的资源路径部分经过编码得到,资源路径部分指URL中host与查询字符串之间的部分,包含host之后的/但不包含查询字符串前的?。用户发起请求时的URI应使用规范化URI,编码方式使用UTF-8字符集按照RFC3986的规则对URI中的每一部分(即被/分割开的字符串)进行编码:

    • 字符A~Z、a~z、0~9以及字符-_.~不编码。

    • 其他字符编码成%加字符对应ASCII码的16进制。示例:半角双引号(")对应%22

    • 空格( )编码成%20,而不是加号(+)、星号(*)替换为%2A%7E替换为波浪号(~)。

      如果您使用的是Java标准库中的java.net.URLEncoder,可以先用标准库中encode编码,随后将编码后的字符中加号(+)替换为%20、星号(*)替换为%2A%7E替换为波浪号(~),即可得到上述规则描述的编码字符串。

    重要

    RPC风格API使用正斜杠(/)作为CanonicalURI,

    ROA风格API该参数为元数据文件中path的值,例如/api/v1/clusters。

  • 规范化查询字符串(CanonicalQueryString)

    构造方法如下:

    1. 将查询字符串中的参数按照参数名的字符代码升序排列,具有重复名称的参数应按值进行排序。

    2. 使用UTF-8字符集按照RFC3986的规则对每个参数的参数名和参数值分别进行URI编码,具体规则与上一节中的CanonicalURI编码规则相同。

    3. 使用等号(=)连接编码后的请求参数名和参数值,对于没有值的参数使用空字符串。

    4. 按照步骤4中的顺序使用与号(&)连接编码后的请求参数。

    重要

    当请求的查询字符串为空时,使用空字符串作为规范化查询字符串。

  • 规范化请求头(CanonicalizedHeaders)

    一个非标准HTTP头部信息。需要将请求中包含以x-acs-为前缀、hostcontent-type的参数信息,添加到规范化请求头中,构造方法如下:

    1. 将所有需要签名的参数的名称转换为小写。

    2. 将所有参数按照参数名称的字符顺序以升序排列。

    3. 将参数的值除去首尾空格。对于有多个值的参数,将多个值分别除去首尾空格后按值升序排列,然后用逗号(,)连接。

    4. 将步骤2、3的结果以英文冒号(:)连接,并在尾部添加换行符,组成一个规范化消息头(CanonicalHeaderEntry)。

    5. 如果没有需要签名的消息头,使用空字符串作为规范化消息头列表。

    重要

    除Authorization外的所有公共请求头,只要符合要求的参数都必须被加入签名。

  • 已签名消息头列表(SignedHeaders)

    用于说明此次请求包含了哪些消息头参与签名,与CanonicalHeaders中包含的消息头是一一对应的,构造方法如下:

    • 将CanonicalHeaders中包含的请求头的名称转为小写。

    • 多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔,例如content-type;host;x-acs-date

    • 伪代码如下:

      CanonicalHeaderEntry = Lowercase(HeaderName) + ':' + Trim(HeaderValue) + '\n'CanonicalHeaders = CanonicalHeaderEntry0 + CanonicalHeaderEntry1 + ... + CanonicalHeaderEntryN
  • HashedRequestPayload

    当请求体(body)为空时,RequestPayload固定为空字符串,否则RequestPayload的值为请求体(body)对应的JSON字符串。再使用哈希函数对RequestPayload进行转换得到HashedRequestPayload,转换规则用伪代码可表示为HashedRequestPayload = HexEncode(Hash(RequestPayload))

    • Hash表示消息摘要函数,目前支持SHA256算法,例如,当签名协议使用ACS3-HMAC-SHA256时,应使用SHA256作为Hash函数。

    • HexEncode表示以小写的十六进制的形式返回摘要的编码函数(即Base16编码)。

    表1:签名协议与签名算法、摘要函数的对应关系

    签名协议(SignatureAlgorithm)

    处理RequestPayload以及CanonicalRequest时使用的摘要函数(Hash)

    计算签名时实际使用的签名算法

    (SignatureMethod)

    ACS3-HMAC-SHA256

    SHA256

    HMAC-SHA256

步骤二:构造待签名字符串

按照以下伪代码构造待签名字符串(stringToSign):

StringToSign =SignatureAlgorithm + '\n' +HashedCanonicalRequest
  • SignatureAlgorithm

    签名协议,目前支持ACS3-HMAC-SHA256,不再支持基于MD5或SHA1的算法。

  • HashedCanonicalRequest

    规范化请求摘要串,计算方法伪代码如下:

    HashedCanonicalRequest = HexEncode(Hash(CanonicalRequest))
  1. 使用哈希函数(Hash)对步骤一中得到的规范化请求(CanonicalRequest)进行摘要处理,具体使用的Hash函数取决于签名协议(SignatureAlgorithm),参见表1,例如,当签名协议为ACS3-HMAC-SHA256时,应使用SHA256作为Hash函数。

  2. 将上一步得到的摘要结果以小写的十六进制形式编码。

步骤三:计算签名

按照以下伪代码计算签名值(Signature)

Signature = HexEncode(SignatureMethod(Secret, StringToSign))
  • StringToSign:步骤二中构造的待签名字符串,UTF-8编码。

  • SignatureMethod:签名算法,具体使用的算法取决于签名协议(SignatureAlgorithm),其对应关系如表1。

  • Secret:用户的签名密钥,为二进制数据。

  • HexEncode:以小写的十六进制的形式返回摘要的编码函数(即Base16编码)。

步骤四:将签名添加到请求中

计算完签名后,构造Authorization请求头,格式为:Authorization:<SignatureAlgorithm>Credential=<AccessKeyId>,SignedHeaders=<SignedHeaders>,Signature=<Signature>

接口签名示例

运行Java示例,需要您在pom.xml中添加以下Maven依赖。

<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.9.0</version></dependency>

package org.example.service;import com.alibaba.fastjson.JSONObject;import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;@Slf4j
public class RoaDemo {/*** 日期格式化工具,用于将日期时间字符串格式化为"yyyy-MM-dd'T'HH:mm:ss'Z'"的格式。*/private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");private static class Request {// HTTP Methodprivate final String httpMethod;// 请求路径,当资源路径为空时,使用正斜杠(/)作为CanonicalURIprivate final String canonicalUri;// endpointprivate final String host;// API nameprivate final String xAcsAction;// API versionprivate final String xAcsVersion;// headersTreeMap<String, Object> headers = new TreeMap<>();// 调用API所需要的参数,参数位置在body。Json字符串String body;// 调用API所需要的参数,参数位置在query,参数按照参数名的字符代码升序排列TreeMap<String, Object> queryParam = new TreeMap<>();public Request(String httpMethod, String canonicalUri, String host, String xAcsAction, String xAcsVersion) {this.httpMethod = httpMethod;this.canonicalUri = canonicalUri;this.host = host;this.xAcsAction = xAcsAction;this.xAcsVersion = xAcsVersion;initBuilder();}// init headersprivate void initBuilder() {headers.put("host", host);headers.put("x-acs-action", xAcsAction);headers.put("x-acs-version", xAcsVersion);SDF.setTimeZone(new SimpleTimeZone(0, "GMT")); // 设置日期格式化时区为GMTheaders.put("x-acs-date", SDF.format(new Date()));headers.put("x-acs-signature-nonce", UUID.randomUUID().toString());}}/*** 这里通过环境变量获取Access Key ID和Access Key Secret,*/private final static String ACCESS_KEY_ID = "YOUR_ACCESS_KEY_ID";private final static String ACCESS_KEY_SECRET = "YOUR_ACCESS_KEY_SECRET";/*** 签名协议*/private static final String ALGORITHM = "ACS3-HMAC-SHA256";public static void main(String[] args) throws Exception {String workspaceId = "YOUR_WORKSPACEID";String appId = "YOUR_APPID";// RPC接口请求String httpMethod = "POST"; // 请求方式String canonicalUri = "/" + percentCode(workspaceId) + "/ccai/app/" + percentCode(appId) + "/completion";String host = "contactcenterai.cn-shanghai.aliyuncs.com";  // endpointString xAcsAction = "RunCompletion";  // API名称String xAcsVersion = "2024-06-03"; // API版本号Request request = new Request(httpMethod, canonicalUri, host, xAcsAction, xAcsVersion);// 调用API所需要的参数,参数按照参数名的字符代码升序排列,具有重复名称的参数应按值进行排序。request.queryParam.put("RegionId", "cn-shanghai");request.headers.put("content-type", "application/json; charset=utf-8");//请求体setBody(request);// 签名过程getAuthorization(request);// 调用APIcallApi(request);}private static void setBody(Request requestIn) {Map<String, Object> bodyMap = buildRunCompletionRequestMap();requestIn.body = JSONObject.toJSONString(bodyMap);}private static Map<String, Object> buildRunCompletionRequestMap() {// 对话内容List<Map<String, String>> sentenceDTOList = new ArrayList<>();Map<String, String> sentenceDTO1 = new HashMap<>();sentenceDTO1.put("ChatId", "chat_1");sentenceDTO1.put("Role", "user");sentenceDTO1.put("Text", "我要办理信用卡");Map<String, String> sentenceDTO2 = new HashMap<>();sentenceDTO2.put("ChatId", "chat_2");sentenceDTO2.put("Role", "agent");sentenceDTO2.put("Text", "好的,稍等10分钟,我现在为您办理,请先提供相关的个人信息");sentenceDTOList.add(sentenceDTO1);sentenceDTOList.add(sentenceDTO2);Map<String, Object> dialogue = new HashMap<>();dialogue.put("SessionId", "session_01_asdfasdfasd");dialogue.put("Sentences", sentenceDTOList);// 信息抽取的字段(非信息抽取场景可以不填)List<Map<String, String>> fieldList = new ArrayList<>();Map<String, String> field1 = new HashMap<>();field1.put("Name", "姓名");field1.put("Desc", "用户的名称");Map<String, String> field2 = new HashMap<>();field2.put("Name", "信用卡号");field2.put("Desc", "用户的信用卡号");fieldList.add(field1);fieldList.add(field2);//templateIds需填写真实的模板ID,47L为示例IDMap<String, Object> body = new java.util.HashMap<>();body.put("Dialogue", dialogue);//body.put("Dimensions", new java.util.ArrayList<>());body.put("Fields", fieldList);body.put("ModelCode", "tyxmTurbo");body.put("Stream", false);body.put("TemplateIds", Arrays.asList(47L));return body;}private static void callApi(Request request) throws Exception {try {// 通过HttpClient发送请求String url = "https://" + request.host + request.canonicalUri;URIBuilder uriBuilder = new URIBuilder(url);// 添加请求参数for (Map.Entry<String, Object> entry : request.queryParam.entrySet()) {uriBuilder.addParameter(entry.getKey(), String.valueOf(entry.getValue()));}HttpRequestBase httpRequest;switch (request.httpMethod) {case "GET":httpRequest = new HttpGet(uriBuilder.build());break;case "POST":HttpPost httpPost = new HttpPost(uriBuilder.build());if (request.body != null) {StringEntity postEntity = new StringEntity(request.body, StandardCharsets.UTF_8);httpPost.setEntity(postEntity);}httpRequest = httpPost;break;case "DELETE":httpRequest = new HttpDelete(uriBuilder.build());break;case "PUT":HttpPut httpPut = new HttpPut(uriBuilder.build());if (request.body != null) {StringEntity putEntity = new StringEntity(request.body);httpPut.setEntity(putEntity);}httpRequest = httpPut;break;default:System.out.println("Unsupported HTTP method: " + request.body);throw new IllegalArgumentException("Unsupported HTTP method");}// 添加http请求头for (Map.Entry<String, Object> entry : request.headers.entrySet()) {httpRequest.addHeader(entry.getKey(), String.valueOf(entry.getValue()));}System.out.println("curl  "+toCurlCommand(httpRequest));// 发送请求try (CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = httpClient.execute(httpRequest)) {String result = EntityUtils.toString(response.getEntity(), "UTF-8");System.out.println(result);} catch (IOException e) {// 异常处理System.out.println("Failed to send request");e.printStackTrace();}} catch (URISyntaxException e) {// 异常处理System.out.println("Invalid URI syntax");e.printStackTrace();} catch (UnsupportedEncodingException e) {// 异常处理System.out.println("UnsupportedEncodingException");e.printStackTrace();}}public static String toCurlCommand(HttpRequestBase request) throws Exception{StringBuilder curlCommand = new StringBuilder("curl -X ");curlCommand.append(request.getMethod()); // GET, POST, etc.// Add headersfor (org.apache.http.Header header : request.getAllHeaders()) {curlCommand.append(" -H '");curlCommand.append(header.getName());curlCommand.append(": ");curlCommand.append(header.getValue());curlCommand.append("'");}// Add body if it's a POST or PUT requestif (request instanceof HttpPost || request instanceof HttpPut) {// TODO: Handle entitycurlCommand.append(" -d '");curlCommand.append(EntityUtils.toString(((HttpEntityEnclosingRequestBase) request).getEntity()));curlCommand.append("'");}// Add URLcurlCommand.append(" '");curlCommand.append(request.getURI().toString());curlCommand.append("'");return curlCommand.toString();}/*** 该方法用于根据传入的HTTP请求方法、规范化的URI、查询参数等,计算并生成授权信息。*/private static void getAuthorization(Request request) {try {// 步骤 1:拼接规范请求串// 请求参数,当请求的查询字符串为空时,使用空字符串作为规范化查询字符串StringBuilder canonicalQueryString = new StringBuilder();request.queryParam.entrySet().stream().map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue()))).forEachOrdered(queryPart -> {// 如果canonicalQueryString已经不是空的,则在新查询参数前添加"&"if (canonicalQueryString.length() > 0) {canonicalQueryString.append("&");}canonicalQueryString.append(queryPart);});// 请求体,当请求正文为空时,比如GET请求,RequestPayload固定为空字符串String requestPayload = "";if (request.body != null) {requestPayload = request.body;}// 计算请求体的哈希值String hashedRequestPayload = sha256Hex(requestPayload);request.headers.put("x-acs-content-sha256", hashedRequestPayload);// 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起StringBuilder canonicalHeaders = new StringBuilder();// 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔StringBuilder signedHeadersSb = new StringBuilder();request.headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-") || entry.getKey().equalsIgnoreCase("host") || entry.getKey().equalsIgnoreCase("content-type")).sorted(Map.Entry.comparingByKey()).forEach(entry -> {String lowerKey = entry.getKey().toLowerCase();String value = String.valueOf(entry.getValue()).trim();canonicalHeaders.append(lowerKey).append(":").append(value).append("\n");signedHeadersSb.append(lowerKey).append(";");});String signedHeaders = signedHeadersSb.substring(0, signedHeadersSb.length() - 1);String canonicalRequest = request.httpMethod + "\n" + request.canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;System.out.println("canonicalRequest=========>\n" + canonicalRequest);// 步骤 2:拼接待签名字符串String hashedCanonicalRequest = sha256Hex(canonicalRequest); // 计算规范化请求的哈希值String stringToSign = ALGORITHM + "\n" + hashedCanonicalRequest;System.out.println("stringToSign=========>\n" + stringToSign);// 步骤 3:计算签名String signature = DatatypeConverter.printHexBinary(hmac256(ACCESS_KEY_SECRET.getBytes(StandardCharsets.UTF_8), stringToSign)).toLowerCase();System.out.println("signature=========>" + signature);// 步骤 4:拼接 AuthorizationString authorization = ALGORITHM + " " + "Credential=" + ACCESS_KEY_ID + ",SignedHeaders=" + signedHeaders + ",Signature=" + signature;System.out.println("authorization=========>" + authorization);request.headers.put("Authorization", authorization);} catch (Exception e) {// 异常处理System.out.println("Failed to get authorization");e.printStackTrace();}}/*** 使用HmacSHA256算法生成消息认证码(MAC)。** @param key 密钥,用于生成MAC的密钥,必须保密。* @param str 需要进行MAC认证的消息。* @return 返回使用HmacSHA256算法计算出的消息认证码。* @throws Exception 如果初始化MAC或计算MAC过程中遇到错误,则抛出异常。*/public static byte[] hmac256(byte[] key, String str) throws Exception {// 实例化HmacSHA256消息认证码生成器Mac mac = Mac.getInstance("HmacSHA256");// 创建密钥规范,用于初始化MAC生成器SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());// 初始化MAC生成器mac.init(secretKeySpec);// 计算消息认证码并返回return mac.doFinal(str.getBytes(StandardCharsets.UTF_8));}/*** 使用SHA-256算法计算字符串的哈希值并以十六进制字符串形式返回。** @param str 需要进行SHA-256哈希计算的字符串。* @return 计算结果为小写十六进制字符串。* @throws Exception 如果在获取SHA-256消息摘要实例时发生错误。*/public static String sha256Hex(String str) throws Exception {获取SHA-256消息摘要实例MessageDigest md = MessageDigest.getInstance("SHA-256");计算字符串s的SHA-256哈希值byte[] d = md.digest(str.getBytes(StandardCharsets.UTF_8));将哈希值转换为小写十六进制字符串并返回return DatatypeConverter.printHexBinary(d).toLowerCase();}/*** 对指定的字符串进行URL编码。* 使用UTF-8编码字符集对字符串进行编码,并对特定的字符进行替换,以符合URL编码规范。** @param str 需要进行URL编码的字符串。* @return 编码后的字符串。其中,加号"+"被替换为"%20",星号"*"被替换为"%2A",波浪号"%7E"被替换为"~"。*/public static String percentCode(String str) {if (str == null) {throw new IllegalArgumentException("输入字符串不可为null");}try {return URLEncoder.encode(str, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");} catch (UnsupportedEncodingException e) {throw new RuntimeException("UTF-8编码不被支持", e);}}}

签名失败常见报错

Code

Message

解决方案

SignatureDoesNotMatch

Specified signature does not match our calculation.

在签名过程中,您可能遗漏了对参数进行升序排序,也可能是多加了空格。请您仔细阅读签名机制的讲解,可以根据提供的固定参数示例验证您的签名过程是否正确。

IncompleteSignature

The request signature does not conform to Aliyun standards.

接下来向您介绍通义晓蜜CCAI-对话分析AIO应用Java SDK的安装、使用及注意事项。

  • 关于Java SDK的更多说明,请参见开始使用。

  • 关于各API的详细出入参说明,请参见API目录。

  • 关于任务类型,请参见AnalyzeConversation - 通过任务类型调用通义晓蜜CCAI-对话分析AIO应用中resultTypes字段的描述。

前提条件

如果您还未创建AccessKeyID和AccessKeySecret,请参考AccessKey、AppID及AgentKey获取方式。

获取workspaceId和appId

workspaceId

image

  1. 点击右上角主账号管理,进入业务空间管理页面。

  2. 业务空间管理列表中Workspace ID为入参中workspaceId。

appId

image

  1. 点击应用广场,点击通义晓蜜CCAI-对话分析AIO的查看详情

  2. 点击上方我的应用,展示应用卡片列表。

  3. 每个卡片上的应用ID即为接口参数中appId。

安装SDK

同步Java

异步Java

<dependency>

<groupId>com.aliyun</groupId>

<artifactId>contactcenterai20240603</artifactId>

<version>3.0.0</version>

</dependency>

代码示例

说明

请用workspaceId替换示例中的YOUR_WORKSPACEID,AccessKeyID替换示例中的YOUR_ACCESS_KEY_ID,AccessKeySecret替换示例中的YOUR_ACCESS_KEY_SECRET,appId替换示例中的YOUR_APPID,代码才能正常运行。为防止密钥泄露,建议将AccessKeyID和AccessKeySecret设置为环境变量。

异步流式调用

public class CcaiPaasTest {private static String accessKeyId="YOUR_ACCESS_KEY_ID";private static String accessKeySecret="YOUR_ACCESS_KEY_SECRET";private static String workspaceId="YOUR_WORKSPACEID";private static String appId="YOUR_APPID";private static StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder().accessKeyId(accessKeyId).accessKeySecret(accessKeySecret).build());private static AsyncClient client = AsyncClient.builder().region("cn-shanghai") .credentialsProvider(provider).serviceConfiguration(Configuration.create().setSignatureVersion(SignatureVersion.V3).setSignatureAlgorithmV3(SignatureAlgorithm.ACS3_HMAC_SHA256)).overrideConfiguration(ClientOverrideConfiguration.create().setProtocol("HTTPS").setEndpointOverride("contactcenterai.cn-shanghai.aliyuncs.com")).build();public static void main(String[] args) throws Exception{List<AnalyzeConversationRequest.Sentences>  messageList = new ArrayList<>();messageList.add(AnalyzeConversationRequest.Sentences.builder().role("agent").text("请问您想咨询五险一金哪方面的问题呢").build());messageList.add(AnalyzeConversationRequest.Sentences.builder().role("user").text("怎么领取五险一金呢").build());List<String> resultTypes=new ArrayList<>();resultTypes.add("summary");AnalyzeConversationRequest.Dialogue dialogue=AnalyzeConversationRequest.Dialogue.builder().sessionId("session-01").sentences(messageList).build();AnalyzeConversationRequest completionParam = AnalyzeConversationRequest.builder().modelCode("tyxmPlus").resultTypes(resultTypes).workspaceId(workspaceId).appId(appId).dialogue(dialogue).requestConfiguration(RequestConfiguration.create().setHttpMethod(HttpMethod.POST)).stream(true).build();System.out.println(JSON.toJSONString(completionParam));ResponseIterable<AnalyzeConversationResponseBody> x = client.analyzeConversationWithResponseIterable(completionParam);ResponseIterator<AnalyzeConversationResponseBody> iterator = x.iterator();String lastTxt="";while (iterator.hasNext()) {AnalyzeConversationResponseBody event = iterator.next();//System.out.println(event.getText());//System.out.println(event.getFinishReason());//System.out.println(event.getRequestId());lastTxt=event.getText();}System.out.println("ALL***********************");System.out.println(lastTxt);System.out.println("请求成功的请求头值:");System.out.println(x.getStatusCode());System.out.println(x.getHeaders());}
}

同步非流式调用

public class CcaiPaasTest {public static void main(String[] args) throws Exception{String accessKeyId = "YOUR_ACCESS_KEY_ID";String accessKeySecret = "YOUR_ACCESS_KEY_SECRET";String workspaceId = "YOUR_WORKSPACEID";String appId = "YOUR_APPID";Config config = new Config();config.setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret).setEndpoint("contactcenterai.cn-shanghai.aliyuncs.com").setRegionId("cn-shanghai").setProtocol("HTTPS");Client client = new Client(config);com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest request = new com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest();com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest.AnalyzeConversationRequestDialogue dialogue = new com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest.AnalyzeConversationRequestDialogue();List<com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest.AnalyzeConversationRequestDialogueSentences> sentenceList = new ArrayList<>();com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest.AnalyzeConversationRequestDialogueSentences sentences1 = new com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest.AnalyzeConversationRequestDialogueSentences();sentences1.setRole("agent");sentences1.setText("请问您想咨询五险一金哪方面的问题呢");sentenceList.add(sentences1);com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest.AnalyzeConversationRequestDialogueSentences sentences2 = new com.aliyun.contactcenterai20240603.models.AnalyzeConversationRequest.AnalyzeConversationRequestDialogueSentences();sentences2.setRole("user");sentences2.setText("怎么查询账户呢");sentenceList.add(sentences2);dialogue.setSentences(sentenceList);dialogue.setSessionId("session-1111");request.setDialogue(dialogue);request.setSceneName("中国移动");request.setResultTypes(Arrays.asList("summary"));request.setStream(false);com.aliyun.contactcenterai20240603.models.AnalyzeConversationResponse response = client.analyzeConversation(workspaceId, appId, request);System.out.println(JSONObject.toJSONString(response));}}

异步非流式调用

public class CcaiPaasTest {private static String accessKeyId="YOUR_ACCESS_KEY_ID";private static String accessKeySecret="YOUR_ACCESS_KEY_SECRET";private static String workspaceId="YOUR_WORKSPACEID";private static String appId="YOUR_APPID";private static StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder().accessKeyId(accessKeyId).accessKeySecret(accessKeySecret).build());private static AsyncClient client = AsyncClient.builder().region("cn-shanghai") .credentialsProvider(provider).serviceConfiguration(Configuration.create().setSignatureVersion(SignatureVersion.V3).setSignatureAlgorithmV3(SignatureAlgorithm.ACS3_HMAC_SHA256)).overrideConfiguration(ClientOverrideConfiguration.create().setProtocol("HTTPS").setEndpointOverride("contactcenterai.cn-shanghai.aliyuncs.com")).build();public static void main(String[] args) throws Exception{List<AnalyzeConversationRequest.Sentences> messageList = new ArrayList<>();messageList.add(AnalyzeConversationRequest.Sentences.builder().role("agent").text("请问您想咨询五险一金哪方面的问题呢").build());messageList.add(AnalyzeConversationRequest.Sentences.builder().role("user").text("怎么查询账户呢").build());List<String> resultTypes = new ArrayList<>();resultTypes.add("summary");AnalyzeConversationRequest.Dialogue dialogue = AnalyzeConversationRequest.Dialogue.builder().sessionId("session-01").sentences(messageList).build();AnalyzeConversationRequest completionParam = AnalyzeConversationRequest.builder().modelCode("tyxmPlus").resultTypes(resultTypes).workspaceId(workspaceId).appId(appId).dialogue(dialogue).requestConfiguration(RequestConfiguration.create().setHttpMethod(HttpMethod.POST)).stream(false).build();System.out.println(JSON.toJSONString(completionParam));CompletableFuture<AnalyzeConversationResponse> x = client.analyzeConversation(completionParam);AnalyzeConversationResponse generateCompletionResponse = x.get(10, TimeUnit.SECONDS);System.out.println("ALL***********************");System.out.println(JSON.toJSONString(generateCompletionResponse.getBody()));System.out.println(generateCompletionResponse.getBody().getText());System.out.println(generateCompletionResponse.getBody().getRequestId());}
}

同步流式调用

// 示例代码,其中阿里云AK、SK,CCAI的业务空间ID(workspaceId)和应用ID(appId),替换为用户当前的。
// tea-utils使用这个版本,go get github.com/alibabacloud-go/tea-utils/v2@v2.0.5-0.20240708091240-f3d7eca052de// This file is auto-generated, don't edit it. Thanks.
package mainimport ("fmt""io""os"openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"openapiutil "github.com/alibabacloud-go/openapi-util/service"util "github.com/alibabacloud-go/tea-utils/v2/service""github.com/alibabacloud-go/tea/tea"
)/*** API 相关* @param path params* @return OpenApi.Params*/
func CreateApiInfo() (_result *openapi.Params) {params := &openapi.Params{// 接口名称Action: tea.String("AnalyzeConversation"),// 接口版本Version: tea.String("2024-06-03"),// 接口协议Protocol: tea.String("HTTPS"),// 接口 HTTP 方法Method:   tea.String("POST"),AuthType: tea.String("AK"),Style:    tea.String("ROA"),// 接口 PATHPathname: tea.String("/YOUR_CCAI_WORKSPACEID/ccai/app/YOUR_CCAI_APP_ID/analyze_conversation"),// 接口请求体内容格式ReqBodyType: tea.String("json"),// 接口响应体内容格式,注意一定得是binary格式,CallApi才会透传出response body进行ReadAsSSEBodyType: tea.String("binary"),}_result = paramsreturn _result
}func _main(args []*string) (_err error) {// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。// 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378661.html。config := &openapi.Config{AccessKeyId:     tea.String("YOUR_ALIYUN_AK"),AccessKeySecret: tea.String("YOUR_ALIYUN_SK"),}config.Endpoint = tea.String("contactcenterai.cn-shanghai.aliyuncs.com")client, err := openapi.NewClient(config)if err != nil {return err}params := CreateApiInfo()// query paramsqueries := map[string]interface{}{}queries["workspaceId"] = tea.String("YOUR_CCAI_WORKSPACEID")queries["appId"] = tea.String("YOUR_CCAI_APP_ID")body := map[string]interface{}{"dialogue": map[string]interface{}{"sentences": []map[string]*string{map[string]*string{"role": tea.String("agent"),"text": tea.String("您好,请问有什么问题需要解决"),}, map[string]*string{"role": tea.String("user"),"text": tea.String("怎么领取游戏币呢"),}, map[string]*string{"role": tea.String("agent"),"text": tea.String("请登录个人账号,在账号下,看看是否有推荐的待领取的游戏币呢,如果有会推送给您的"),}, map[string]*string{"role": tea.String("user"),"text": tea.String("好,谢谢"),}},"sessionId": "2323",},"modelCode":   "tyxmPlus","resultTypes": []*string{tea.String("question_solution")},"stream":      true,}// runtime optionsruntime := &util.RuntimeOptions{}request := &openapi.OpenApiRequest{Query: openapiutil.Query(queries),Body:  body,//Body:  tea.String("{\n  \"stream\": false,\n  \"modelCode\": \"tyxmPlus\",\n  \"dialogue\": {\n    \"sentences\": [\n      {\n        \"role\": \"user\",\n        \"text\": \"号主开挂了模拟宇宙无线祝福\\n联系方式: ******\\n图片上传:\\n视频上传:\\n\"\n      },\n      {\n        \"role\": \"agent\",\n        \"text\": \"乘客您好,欢迎登录本次星穹列车帕~麻烦您提供一下以下信息:*游戏项目:\\n*被举报角色UID:\"\n      },\n      {\n        \"role\": \"user\",\n        \"text\": \"通行证id******\\n\\n2024-06-10 18:25:52 [玩家] ***:\\nuid******\\n\"\n      },\n      {\n        \"role\": \"agent\",\n        \"text\": \"您的问题我们之前已经记录反馈了,会进行核实的~如有结果我们会在服务进度或在线服务中告知,您可以留意相关提示。十分抱歉给您带来不便\\n\"\n      },\n      {\n        \"role\": \"agent\",\n        \"text\": \"您的问题咨询完成啦,那客服娘贴心提示,不要忘记消耗开拓力哦~祝愿您在完成探索的途中获得美好的回忆哦~希望您抽空也记得给客服娘进行下评价,挥挥~~\\n\"\n      }\n    ],\n    \"sessionId\": \"ss01\"\n  },\n  \"resultTypes\": [\n    \"question_solution\"\n  ],\n  \"serviceInspection\": {\n    \"inspectionIntroduction\": \"请检测客服是否存在服务不当的行为,包括:过度承诺、故意套取客户隐私信息等\",\n    \"sceneIntroduction\": \"保险销售场景\",\n    \"inspectionContents\": [\n      {\n        \"title\": \"客服是否过度承诺\",\n        \"content\": \"客服在服务客户过程中,基于已有的服务标准是否存在过度承诺的行为,如:最快到货时间是12小时,无法给客户承诺更快的到货时间。\"\n      }\n    ]\n  },\n  \"fields\": [\n    {\n      \"code\": \"name\",\n      \"name\": \"姓名\",\n      \"desc\": \"用户的姓名\"\n    },\n    {\n      \"code\": \"question\",\n      \"name\": \"问题\",\n      \"desc\": \"用户的问题\"\n    }\n  ]\n}"),}// 复制代码运行请自行打印 API 的返回值// 返回值为 Map 类型,可从 Map 中获得三类数据:响应体 body、响应头 headers、HTTP 返回的状态码 statusCode。resp, err := client.CallApi(params, request, runtime)if err != nil {return err}fmt.Println(resp["headers"])fmt.Println(resp["statusCode"])// 迭代读取SSE内容events, err := util.ReadAsSSE(resp["body"].(io.ReadCloser))if err != nil {fmt.Printf("Error: %v\n", err)return err}fmt.Println(tea.StringValue(events))return nil}func main() {err := _main(tea.StringSlice(os.Args[1:]))if err != nil {panic(err)}
}


http://www.mrgr.cn/news/59413.html

相关文章:

  • (北京政务服务满意度公司)满意度调查助力服务质量提升
  • elselect iphone上 要点两次
  • Kafka相关API开发
  • 设计模式4-工厂模式策略模式
  • 【ArcGIS Pro实操第5期】全局及局部空间插值:GPI、LPI、IDW等
  • #网络安全#NGSOC与传统SOC的区别
  • 基于云平台的智能家居管理系统设计与通信协议分析
  • Bootstrap 5 容器
  • C语言 | Leetcode C语言题解之第514题自由之路
  • 蒙特卡洛算法(Monte Carlo Algorithm)详细解读
  • 【人工智能-初级】第21章 线性代数与 AI:理解矩阵乘法和特征向量
  • 关于我的数据库——MySQL——第四篇
  • 【2024|滑坡数据集论文解读3】CAS滑坡数据集:用于深度学习滑坡检测的大规模多传感器数据集
  • Linux基础命令:轻松掌握终端操作
  • 道路车辆功能安全 ISO 26262标准(9-2)—面向汽车安全完整性等级 (ASIL) 和安全的分析
  • C语言浮点数实现(一)
  • 自定义类型:联合和枚举【上】
  • OA命令执行漏洞挖掘
  • [专有网络VPC]限制不同交换机下的ECS间的互通
  • 面试域——岗位职责以及工作流程
  • 高级网络互联技术:AS3001与AS3000的路由交换方案
  • 【SQL Server】中关于 COUNT 的一些使用方式区别
  • 道路车辆功能安全 ISO 26262标准(9-1)—面向汽车安全完整性等级 (ASIL) 和安全的分析
  • Java 中的 `final` 关键字详解
  • Agent与大模型的区别
  • 基于Python的自然语言处理系列(45):Sentence-BERT句子相似度计算