日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

釘釘開放平臺集成云小蜜開發指導

適用范圍

云小蜜對焦釘釘企業內部機器人(內部群機器人、內部機器人應用)

功能對照說明

功能點

子功能

云小蜜

問答

純文本

支持

富文本

支持

卡片消息

支持,需要適配

人工客服

暫時不支持

知識詳情頁

暫時不支持,現在釘釘支持富文本的數據展示,不再需要知識詳情頁來輔助展示知識了。

點贊點踩

支持

FAQ知識庫

支持

多輪對話

支持

消息推送

暫時不支持

渠道

網頁渠道

支持

微信渠道

暫時不支持

數據看板

支持,效果和功能更完善

前期準備

1. 準備一個域名

*必需:域名是用來接收機器人消息的,沒有域名則無法接收機器人消息,也就無法進行后續處理。

溫馨提醒:

域名購買網址:https://wanwang.aliyun.com/

域名要求:http/https可用,注:遵循釘釘開放平臺要求即可

釘釘開放平臺說明:https://open.dingtalk.com/document/orgapp/enterprise-created-chatbot

2. 在釘釘開放平臺創建機器人

*必需:https://open-dev.dingtalk.com/fe/app#/corp/robot

image.pngimage.png

說明:

  1. 消息推送到釘釘的服務端出口IP,如果出口IP不在列表中,會被釘釘拒絕處理。

  2. 用戶問機器人時,釘釘平臺會把對應的消息作為參數,調用這個服務地址。

云小蜜配置

  1. 創建機器人

  2. 綁定FAQ類目/創建多輪對話

  3. 發布機器人

  4. 獲取機器人ID,對應的是Chat API的InstanceId參數

72A8D9D4-FDDE-4E07-A479-4DF221D35F27.png

開發接入

  1. 和機器人問答后,釘釘平臺會調用上述配置的消息接收地址,繼而獲取到用戶的query和webhook回調地址

  2. 構建請求云小蜜ChatAPI的請求參數,并請求得到ChatAPI的出參

  1. 根據釘釘消息協議把云小蜜Chat的響應轉換參數,通過webhook調用發送到釘釘平臺,釘釘平臺會通過機器人回復給用戶。

代碼示例

機器人回調參數

{
	"atUsers": [{
		"dingtalkId": "$:LWCP_v1:$oUB47jFNK0bPR4e2lMpbUHsBiGCf6T"
	}],
	"chatbotCorpId": "dinge6f87ffe2e6d911f5bf40eda33b7ba0",
	"chatbotUserId": "$:LWCP_v1:$oUB47jFNK0bPR4e2lMpbUHsBidCf6T",
	"conversationId": "cid+ECvHAqZrIbIabqczkImg==",
	"conversationTitle": "云釘小蜜機器人測試",
	"conversationType": 2,
	"createAt": "169226429002",
	"isAdmin": true,
	"isInAtList": true,
	"msgId": "msgE7malneyJVy6xyDIC+l6zQ==",
	"msgtype": "text",
	"senderCorpId": "dinge6f87ffe2e6d911f5bf40eda33b7ba0",
	"senderId": "$:LWCP_v1:$+a/f9rESEqLnp3cAfE8G0Q==",
	"senderNick": "克霖 | KE",
	"senderStaffId": "04076552577297403",
	"sessionWebhook": "https://oapi.dingtalk.com/robot/sendBySession?session=5d200a7961856d31239e49f083438c",
	"sessionWebhookExpiredTime": 1692269670800,
	"text": {
		"content": "杭州公積金怎么查詢?"
	}
}

調用云小蜜Chat API

public static Client createClient() throws Exception {
 Config config = new Config()
 // 必填,您的 AccessKey ID
 .setAccessKeyId(ALIYUN_ACCESS_KEY_ID)
 // 必填,您的 AccessKey Secret
 .setAccessKeySecret(ALIYUN_ACCESS_KEY_SECRET);
 // Endpoint 請參考 https://api.aliyun.com/product/Chatbot
 config.endpoint = "chatbot.cn-shanghai.aliyuncs.com";
 return new Client(config);
}

public ChatResponseBody doChat(String query, String sessionId) throws Exception {
 Client client = createClient();
 // "cid+ECvHAqZrIbFIabqczkImg=="
 sessionId = sessionId.replace("+", StringUtils.EMPTY).replaceAll("==", StringUtils.EMPTY);
 ChatRequest chatRequest = new ChatRequest();
 chatRequest.setUtterance(query);
 chatRequest.setInstanceId(CLOUD_BOT_INSTANCE_ID);
 chatRequest.setSessionId(sessionId);
 RuntimeOptions runtime = new RuntimeOptions();
 ChatResponse chatResponse = client.chatWithOptions(chatRequest, runtime);

 ChatResponseBody body = chatResponse.getBody();
 log.info("doChat response:{}", JSON.toJSONString(body));
 return body;
}

調用云小蜜點贊點踩API

@Data
@Accessors(chain = true)
public static class FeedbackContext {
 private String messageId;
 private String feedback;
}

public void doFeedback(FeedbackContext feedbackContext) throws Exception {
 Client client = createClient();
 FeedbackRequest feedbackRequest = new FeedbackRequest();
 feedbackRequest.setMessageId(feedbackContext.messageId);
 feedbackRequest.setFeedback(feedbackContext.feedback);
 FeedbackResponse response = client.feedback(feedbackRequest);
 log.info("doFeedback response:{}", JSON.toJSONString(response.getBody()));
}

協議轉換

ChatResponseBody chatResponseBody = doChat(query, request.getConversationId());
String answer = "無答案";
ChatResponseBodyMessages message = chatResponseBody.getMessages().get(0);
if ("Text".equals(message.answerType)) {
 ChatResponseBodyMessagesText text = message.getText();
 answer = text.getContent();
 // 富文本
 if ("RICH_TEXT".equals(text.getContentType())) {
 answer = htmlTansToMarkdown(answer);
 msgType = "markdown";
 }
}
if ("Knowledge".equals(message.answerType)) {
 ChatResponseBodyMessagesKnowledge knowledge = message.getKnowledge();
 answer = htmlTansToMarkdown(knowledge.getContent());
 title = knowledge.getTitle();
 if ("RICH_TEXT".equals(knowledge.getContentType())) {
 msgType = "markdown";
 title = knowledge.getTitle();
 }
 // 關聯知識處理
 List<ChatResponseBodyMessagesKnowledgeRelatedKnowledges> relatedKnowledges
 = knowledge.getRelatedKnowledges();
 if (CollectionUtils.isNotEmpty(relatedKnowledges)) {
 msgType = "markdown";
 answer = appendRelevanceAnswer(knowledge.getRelatedKnowledges(), answer);
 }
}

if ("Recommend".equals(message.answerType)) {
 List<ChatResponseBodyMessagesRecommends> recommends = message.getRecommends();
 answer = getRecommendText(message.getTitle(), recommends);
 msgType = "markdown";
 title = message.getTitle();
}
// 有幫助,無幫助
if (enableFeedback) {
 answer += String.format("\n\n--- \n\n該答復是否有幫助? [%s](%s) [%s](%s)",
 "有幫助", getContentLinkSendMsgUrl(GOOD_FEEDBACK_TEXT,
 new FeedbackContext().setFeedback("good").setMessageId(chatResponseBody.getMessageId())),
 "無幫助", getContentLinkSendMsgUrl(BAD_FEEDBACK_TEXT,
 new FeedbackContext().setFeedback("bad").setMessageId(chatResponseBody.getMessageId())));
 msgType = "markdown";
}
sendMessageWebhook(title, answer, request.getSessionWebhook(), msgType);

回調消息到釘釘

public void sendMessageWebhook(String title, String answer, String webhook, String msgType) throws Exception {
 log.info("sendMessageWebhook answer:{}, webhook:{}, msgType:{}", answer, webhook, msgType);
 DingTalkClient client = new DefaultDingTalkClient(webhook);
 OapiRobotSendRequest request = new OapiRobotSendRequest();
 request.setMsgtype(msgType);
 OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
 text.setContent(answer);
 if ("markdown".equals(msgType)) {
 Markdown markdown = new Markdown();
 markdown.setText(answer);
 markdown.setTitle(title);
 request.setMarkdown(markdown);
 } else {
 request.setText(text);
 }
 OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
 request.setAt(at);
 OapiRobotSendResponse response = client.execute(request);
 log.info("sendMessageWebhook response:{}", response.getBody());
}

完整代碼

依賴項

<dependency>
 <groupId>com.aliyun</groupId>
 <artifactId>chatbot20220408</artifactId>
 <version>1.0.9</version>
</dependency>
<dependency>
 <groupId>io.github.furstenheim</groupId>
 <artifactId>copy_down</artifactId>
 <version>1.1</version>
</dependency>
<dependency>
 <groupId>com.aliyun</groupId>
 <artifactId>alibaba-dingtalk-service-sdk</artifactId>
 <version>2.0.0</version>
</dependency>
<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>fastjson</artifactId>
 <version>1.2.68.noneautotype</version>
</dependency>
<dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.16.22</version>
</dependency>

問答

import com.aliyun.chatbot20220408.Client;
import com.aliyun.chatbot20220408.models.ChatRequest;
import com.aliyun.chatbot20220408.models.ChatResponse;
import com.aliyun.chatbot20220408.models.ChatResponseBody;
import com.aliyun.chatbot20220408.models.ChatResponseBody.ChatResponseBodyMessages;
import com.aliyun.chatbot20220408.models.ChatResponseBody.ChatResponseBodyMessagesKnowledge;
import com.aliyun.chatbot20220408.models.ChatResponseBody.ChatResponseBodyMessagesKnowledgeRelatedKnowledges;
import com.aliyun.chatbot20220408.models.ChatResponseBody.ChatResponseBodyMessagesRecommends;
import com.aliyun.chatbot20220408.models.ChatResponseBody.ChatResponseBodyMessagesText;
import com.aliyun.chatbot20220408.models.FeedbackRequest;
import com.aliyun.chatbot20220408.models.FeedbackResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.request.OapiRobotSendRequest.Markdown;
import com.dingtalk.api.response.OapiRobotSendResponse;
import io.github.furstenheim.CopyDown;
import io.github.furstenheim.Options;
import io.github.furstenheim.OptionsBuilder;

@Controller
@Slf4j
public class ChatController {

 private static final boolean enableFeedback = true;
 private static final String ALIYUN_ACCESS_KEY_ID = "";
 private static final String ALIYUN_ACCESS_KEY_SECRET = "";
 private static final String CLOUD_BOT_INSTANCE_ID = "chatbot-cn-xxxxx";
 private static final String BAD_FEEDBACK_TEXT = "評價:無幫助";
 private static final String GOOD_FEEDBACK_TEXT = "評價:有幫助";

 @PostMapping("/dingme/chat")
 public @ResponseBody
 String chat(@RequestBody DingtalkChatRequest request) {
 try {
 log.info("chat request params:{}", JSON.toJSONString(request));
 String query = null;
 String msgType = "text";
 String title;
 switch (request.getMsgtype()) {
 // 純文本
 case "text":
 query = JSON.parseObject(JSON.toJSONString(request.getText()),
 DingtalkChatRequest.RequestText.class).getContent();
 break;
 default:
 sendMessageWebhook("", "這個問題我還不會哦!", request.getSessionWebhook(), "text");
 }
 query = StringUtils.trimToNull(query);
 if (StringUtils.isBlank(query)) {
 return "query empty";
 }
 if (feedback(request, query)) {
 return "feedback";
 }
 title = query;
 ChatResponseBody chatResponseBody = doChat(query, request.getConversationId());

 String answer = "無答案";
 ChatResponseBodyMessages message = chatResponseBody.getMessages().get(0);
 if ("Text".equals(message.answerType)) {
 ChatResponseBodyMessagesText text = message.getText();
 answer = text.getContent();
 // 富文本
 if ("RICH_TEXT".equals(text.getContentType())) {
 answer = htmlTansToMarkdown(answer);
 msgType = "markdown";
 }

 }
 if ("Knowledge".equals(message.answerType)) {
 ChatResponseBodyMessagesKnowledge knowledge = message.getKnowledge();
 answer = htmlTansToMarkdown(knowledge.getContent());
 title = knowledge.getTitle();
 if ("RICH_TEXT".equals(knowledge.getContentType())) {
 msgType = "markdown";
 title = knowledge.getTitle();
 }
 // 關聯知識處理
 List<ChatResponseBodyMessagesKnowledgeRelatedKnowledges> relatedKnowledges
 = knowledge.getRelatedKnowledges();
 if (CollectionUtils.isNotEmpty(relatedKnowledges)) {
 msgType = "markdown";
 answer = appendRelevanceAnswer(knowledge.getRelatedKnowledges(), answer);
 }
 }

 if ("Recommend".equals(message.answerType)) {
 List<ChatResponseBodyMessagesRecommends> recommends = message.getRecommends();
 answer = getRecommendText(message.getTitle(), recommends);
 msgType = "markdown";
 title = message.getTitle();
 }

 // 有幫助,無幫助
 if (enableFeedback) {
 answer += String.format("\n\n--- \n\n該答復是否有幫助? [%s](%s) [%s](%s)",
 "有幫助", getContentLinkSendMsgUrl(GOOD_FEEDBACK_TEXT,
 new FeedbackContext().setFeedback("good").setMessageId(chatResponseBody.getMessageId())),
 "無幫助", getContentLinkSendMsgUrl(BAD_FEEDBACK_TEXT,
 new FeedbackContext().setFeedback("bad").setMessageId(chatResponseBody.getMessageId())));
 msgType = "markdown";
 }

 sendMessageWebhook(title, answer, request.getSessionWebhook(), msgType);

 } catch (Exception e) {
 log.error("unknown error, request:{}", JSON.toJSONString(request), e);
 }
 return "empty";
 }

 private boolean feedback(DingtalkChatRequest request, String query) throws Exception {
 if (enableFeedback && request.getContext() != null) {
 if (BAD_FEEDBACK_TEXT.equals(query) || GOOD_FEEDBACK_TEXT.equals(query)) {
 String ctx;
 if (request.getContext() instanceof String) {
 ctx = (String)request.getContext();
 } else {
 ctx = JSON.toJSONString(request.getContext());
 }
 FeedbackContext feedbackContext = JSON.parseObject(ctx, FeedbackContext.class);
 doFeedback(feedbackContext);
 sendMessageWebhook(null, "感謝您的評價!", request.getSessionWebhook(), "text");
 return true;
 }
 }
 return false;
 }

 private static final String RELATED_QUESTION_SEPARATE_LINE = " \n\n---";
 private static final String RELATED_QUESTION_PROMPT = " \n是否還想了解";
 private static final String RELATED_QUESTION_FORMAT = " \n[%s](dtmd://dingtalkclient/sendMessage?content=%s)";

 public static String htmlTansToMarkdown(String htmlStr) {
 OptionsBuilder optionsBuilder = OptionsBuilder.anOptions();
 Options options = optionsBuilder
 // more options
 .build();
 CopyDown converter = new CopyDown(options);
 String convert = converter.convert(htmlStr);

 // 兼容從釘釘上導入的知識,沒有帶https前綴的問題
 return convert.replaceAll("\\(//knowledgecloud.oss-cn-hangzhou.aliyuncs.com",
 "\\(https://knowledgecloud.oss-cn-hangzhou.aliyuncs.com");
 }

 //組裝關聯問題
 private String appendRelevanceAnswer(List<ChatResponseBodyMessagesKnowledgeRelatedKnowledges> answers,
 String cardText) {
 if (CollectionUtils.isEmpty(answers)) {
 return cardText;
 }
 StringBuilder recommendString = new StringBuilder(cardText + " \n\n");
 recommendString.append(RELATED_QUESTION_SEPARATE_LINE);
 recommendString.append(RELATED_QUESTION_PROMPT);
 for (ChatResponseBodyMessagesKnowledgeRelatedKnowledges childKnowledge : answers) {
 recommendString.append(String.format(RELATED_QUESTION_FORMAT, childKnowledge.getTitle(),
 encodeContentBlank(childKnowledge.getTitle())));
 }
 return recommendString.toString();
 }

 public static String getRecommendText(String title, List<ChatResponseBodyMessagesRecommends> recommends) {

 StringBuilder builder = new StringBuilder(" \n #### " + title + " \n");
 for (ChatResponseBodyMessagesRecommends recommend : recommends) {
 // 推薦的title
 String label = recommend.getTitle().replaceAll("[\r\n]", "");
 String encodeRemTitle = encodeContentBlank(recommend.getTitle());
 builder.append("> [").append(label).append("]");
 builder.append("(dtmd://dingtalkclient/sendMessage?content=");
 builder.append(encodeRemTitle);
 builder.append(") \n\n");
 }

 return builder.toString();
 }

 private static String encodeContentBlank(String content) {
 try {
 String remContent = content.replaceAll("/[\\r\\n]/g", "");
 // 解決空格問題
 return URLEncoder.encode(remContent, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
 } catch (UnsupportedEncodingException e) {
 return content;
 }
 }

 public static final String DING_TALK_CLIENT_SEND_MSG_URL = "dtmd://dingtalkclient/sendMessage?content=";
 public static final String JUMP_CONTEXT_REPLACE = "&context=";

 public static String getContentLinkSendMsgUrl(String content, Object context) {
 StringBuilder askUrl = new StringBuilder();
 String encodeRemContent = encodeContentBlank(content);
 askUrl.append(DING_TALK_CLIENT_SEND_MSG_URL);
 askUrl.append(encodeRemContent);
 if (context != null) {
 String encodeContext = encodeUtf8(JSONObject.toJSONString(context));
 askUrl.append(JUMP_CONTEXT_REPLACE);
 askUrl.append(encodeContext);
 }
 return askUrl.toString();
 }

 private static String encodeUtf8(String content) {
 try {
 return URLEncoder.encode(content, StandardCharsets.UTF_8.name());
 } catch (UnsupportedEncodingException e) {
 return content;
 }
 }

 public static Client createClient() throws Exception {
 Config config = new Config()
 // 必填,您的 AccessKey ID
 .setAccessKeyId(ALIYUN_ACCESS_KEY_ID)
 // 必填,您的 AccessKey Secret
 .setAccessKeySecret(ALIYUN_ACCESS_KEY_SECRET);
 // Endpoint 請參考 https://api.aliyun.com/product/Chatbot
 config.endpoint = "chatbot.cn-shanghai.aliyuncs.com";
 return new Client(config);
 }

 public void sendMessageWebhook(String title, String answer, String webhook, String msgType) throws Exception {
 log.info("sendMessageWebhook answer:{}, webhook:{}, msgType:{}", answer, webhook, msgType);
 DingTalkClient client = new DefaultDingTalkClient(webhook);
 OapiRobotSendRequest request = new OapiRobotSendRequest();
 request.setMsgtype(msgType);
 OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
 text.setContent(answer);
 if ("markdown".equals(msgType)) {
 Markdown markdown = new Markdown();
 markdown.setText(answer);
 markdown.setTitle(title);
 request.setMarkdown(markdown);
 } else {
 request.setText(text);
 }
 OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
 request.setAt(at);
 OapiRobotSendResponse response = client.execute(request);
 log.info("sendMessageWebhook response:{}", response.getBody());
 }

 public ChatResponseBody doChat(String query, String sessionId) throws Exception {
 Client client = createClient();
 // "cid+ECvHAqZrIbFIabqczkImg=="
 sessionId = sessionId.replace("+", StringUtils.EMPTY).replaceAll("==", StringUtils.EMPTY);
 ChatRequest chatRequest = new ChatRequest();
 chatRequest.setUtterance(query);
 chatRequest.setInstanceId(CLOUD_BOT_INSTANCE_ID);
 chatRequest.setSessionId(sessionId);
 RuntimeOptions runtime = new RuntimeOptions();
 ChatResponse chatResponse = client.chatWithOptions(chatRequest, runtime);

 ChatResponseBody body = chatResponse.getBody();
 log.info("doChat response:{}", JSON.toJSONString(body));
 return body;
 }

 @Data
 @Accessors(chain = true)
 public static class FeedbackContext {
 private String messageId;
 private String feedback;
 }

 public void doFeedback(FeedbackContext feedbackContext) throws Exception {
 Client client = createClient();
 FeedbackRequest feedbackRequest = new FeedbackRequest();
 feedbackRequest.setMessageId(feedbackContext.messageId);
 feedbackRequest.setFeedback(feedbackContext.feedback);
 FeedbackResponse response = client.feedback(feedbackRequest);
 log.info("doFeedback response:{}", JSON.toJSONString(response.getBody()));
 }

}

參數對象

import lombok.Data;

@Data
public class DingtalkChatRequest {
 private String msgtype;
 private Object content;
 private Object text;
 private String msgId;
 private String createAt;
 private Integer conversationType;
 private String conversationId;
 private String conversationTitle;
 private String senderId;
 private String senderNick;
 private String senderRole;
 private String senderCorpId;
 private String senderStaffId;
 private Boolean isAdmin;
 private String chatbotCorpId;
 private String chatbotUserId;
 private String source;
 private String replyMsgId;
 private Integer isCustom;
 private Object context;
 private Object customerContext;
 private String originalMsgId;
 private Object atUsers;
 private String atUserDingtalkIds;
 private String atUserStaffIds;
 private String sessionWebhook;
 private Long sessionWebhookExpiredTime;
 private Boolean isInAtList;
 private String senderContactStaffId;
 @Data
 public static class RequestText{
 private String content;
 }
}