diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-baidusearch/pom.xml b/community/plugins/spring-ai-alibaba-starter-plugin-baidusearch/pom.xml
index e352df6d..9d4cda69 100644
--- a/community/plugins/spring-ai-alibaba-starter-plugin-baidusearch/pom.xml
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-baidusearch/pom.xml
@@ -27,7 +27,7 @@
spring-ai-alibaba-starter-plugin-baidusearch
spring-ai-alibaba-starter-plugin-baidusearch
- Baidu seartch tool for Spring AI Alibaba
+ Baidu search tool for Spring AI Alibaba
UTF-8
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/pom.xml b/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/pom.xml
index 07de51da..bbdcdbb7 100644
--- a/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/pom.xml
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/pom.xml
@@ -27,7 +27,7 @@
spring-ai-alibaba-starter-plugin-bingsearch
spring-ai-alibaba-starter-plugin-bingsearch
- Bing seartch tool for Spring AI Alibaba
+ Bing search tool for Spring AI Alibaba
UTF-8
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index bd142889..95d09ebd 100644
--- a/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-bingsearch/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1 +1 @@
-com.alibaba.cloud.ai.plugin.bing.BingSearchPluginConfiguration
\ No newline at end of file
+com.alibaba.cloud.ai.plugin.bing.BingSearchPluginConfiguration
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/pom.xml b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/pom.xml
new file mode 100644
index 00000000..259e15b8
--- /dev/null
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/pom.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+ 4.0.0
+
+ com.alibaba.cloud.ai
+ spring-ai-alibaba
+ ${revision}
+ ../../../pom.xml
+
+ spring-ai-alibaba-starter-plugin-dingtalk
+ spring-ai-alibaba-starter-plugin-dingtalk
+ Ding Talk tool for Spring AI Alibaba
+
+
+ 2.1.68
+ 2.0.0
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+ org.springframework.ai
+ spring-ai-spring-boot-autoconfigure
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ commons-codec
+ commons-codec
+
+
+
+ com.aliyun
+ dingtalk
+ ${dingtalk-sdk-version}
+
+
+
+ com.aliyun
+ alibaba-dingtalk-service-sdk
+ ${old-dingtalk-sdk-version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ ${maven-deploy-plugin.version}
+
+ true
+
+
+
+
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkConfiguration.java b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkConfiguration.java
new file mode 100644
index 00000000..abce715b
--- /dev/null
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkConfiguration.java
@@ -0,0 +1,41 @@
+package com.alibaba.cloud.ai.plugin.dingtalk;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Description;
+
+/**
+ * @author YunLong
+ */
+@Configuration
+@ConditionalOnClass(DingTalkService.class)
+@EnableConfigurationProperties(DingTalkProperties.class)
+public class DingTalkConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ @Description("Send DingTalk group chat messages using a custom robot")
+ @ConditionalOnProperty(prefix = "spring.ai.alibaba.plugin.dingtalk", name = "enabled", havingValue = "true")
+ public DingTalkService dingTalkGroupSendMessageByCustomRobotFunction(DingTalkProperties dingTalkProperties) {
+ return new DingTalkService(dingTalkProperties);
+ }
+}
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkProperties.java b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkProperties.java
new file mode 100644
index 00000000..b457f1c7
--- /dev/null
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkProperties.java
@@ -0,0 +1,53 @@
+package com.alibaba.cloud.ai.plugin.dingtalk;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author YunLong
+ */
+@ConfigurationProperties(prefix = "spring.ai.alibaba.plugin.dingtalk")
+public class DingTalkProperties {
+
+ // Official Document Address:https://open.dingtalk.com/document/orgapp/custom-robots-send-group-messages
+ private String customRobotAccessToken;
+
+ private String customRobotSignature;
+
+ public DingTalkProperties() {}
+
+ public DingTalkProperties(String customRobotAccessToken, String customRobotSignature) {
+ this.customRobotAccessToken = customRobotAccessToken;
+ this.customRobotSignature = customRobotSignature;
+ }
+
+ public String getCustomRobotAccessToken() {
+ return customRobotAccessToken;
+ }
+
+ public void setCustomRobotAccessToken(String customRobotAccessToken) {
+ this.customRobotAccessToken = customRobotAccessToken;
+ }
+
+ public String getCustomRobotSignature() {
+ return customRobotSignature;
+ }
+
+ public void setCustomRobotSignature(String customRobotSignature) {
+ this.customRobotSignature = customRobotSignature;
+ }
+}
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkService.java b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkService.java
new file mode 100644
index 00000000..b6f6fbdc
--- /dev/null
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/DingTalkService.java
@@ -0,0 +1,82 @@
+package com.alibaba.cloud.ai.plugin.dingtalk;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.alibaba.cloud.ai.plugin.dingtalk.utils.SignUtils;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiRobotSendRequest;
+import com.dingtalk.api.response.OapiRobotSendResponse;
+import com.fasterxml.jackson.annotation.JsonClassDescription;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyDescription;
+import org.springframework.util.ObjectUtils;
+
+import java.util.function.Function;
+
+/**
+ * @author YunLong
+ */
+public class DingTalkService implements Function {
+
+ private final DingTalkProperties dingTalkProperties;
+
+ public DingTalkService(DingTalkProperties dingTalkProperties) {
+ this.dingTalkProperties = dingTalkProperties;
+ }
+
+ /**
+ * The old version of DingTalk SDK. Some interfaces have not been fully replaced yet.
+ * Official Document Address:https://open.dingtalk.com/document/orgapp/custom-robots-send-group-messages
+ */
+ @Override
+ public Response apply(Request request) {
+
+ if (ObjectUtils.isEmpty(dingTalkProperties.getCustomRobotAccessToken()) || ObjectUtils.isEmpty(dingTalkProperties.getCustomRobotSignature())) {
+ throw new IllegalArgumentException("spring.ai.alibaba.plugin.dingtalk.custom-robot must not be null.");
+ }
+
+ String accessToken = dingTalkProperties.getCustomRobotAccessToken();
+ String signature = dingTalkProperties.getCustomRobotSignature();
+
+ // Request Body, please see the official document for more parameters.
+ OapiRobotSendRequest req = new OapiRobotSendRequest();
+ req.setMsgtype("text");
+ req.setText(String.format("{\"content\":\"%s\"}", request.message()));
+
+ try {
+ DingTalkClient client = new DefaultDingTalkClient(String.format("https://oapi.dingtalk.com/robot/send?%s", SignUtils.getSign(signature)));
+ OapiRobotSendResponse response = client.execute(req, accessToken);
+
+ if (response.isSuccess()) {
+ return new Response("The custom robot message was sent successfully!");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Custom robot message sending failed!");
+ }
+
+ return null;
+ }
+
+ @JsonClassDescription("Send group chat messages using a custom robot")
+ public record Request(
+ @JsonProperty(required = true, value = "message")
+ @JsonPropertyDescription("Customize what the robot needs to send") String message) {
+ }
+
+ public record Response(String message) {
+ }
+}
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/utils/SignUtils.java b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/utils/SignUtils.java
new file mode 100644
index 00000000..15fabcbb
--- /dev/null
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/java/com/alibaba/cloud/ai/plugin/dingtalk/utils/SignUtils.java
@@ -0,0 +1,44 @@
+package com.alibaba.cloud.ai.plugin.dingtalk.utils;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author YunLong
+ */
+public class SignUtils {
+
+ public static String getSign(String signature) {
+ Long timestamp = System.currentTimeMillis();
+ String stringToSign = timestamp + "\n" + signature;
+
+ try {
+ Mac mac = Mac.getInstance("HmacSHA256");
+ mac.init(new SecretKeySpec(signature.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
+ byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
+ String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), StandardCharsets.UTF_8);
+ return "×tamp=" + timestamp + "&sign=" + sign;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..1b1e0434
--- /dev/null
+++ b/community/plugins/spring-ai-alibaba-starter-plugin-dingtalk/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.alibaba.cloud.ai.plugin.dingtalk.DingTalkConfiguration
diff --git a/pom.xml b/pom.xml
index 5517cbf0..97316284 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@
community/plugins/spring-ai-alibaba-starter-plugin-time
community/plugins/spring-ai-alibaba-starter-plugin-baidusearch
community/plugins/spring-ai-alibaba-starter-plugin-bingsearch
+ community/plugins/spring-ai-alibaba-starter-plugin-dingtalk
diff --git a/spring-ai-alibaba-examples/function-calling-example/pom.xml b/spring-ai-alibaba-examples/function-calling-example/pom.xml
index 27268a07..e5bc7542 100644
--- a/spring-ai-alibaba-examples/function-calling-example/pom.xml
+++ b/spring-ai-alibaba-examples/function-calling-example/pom.xml
@@ -53,21 +53,31 @@
org.springframework.boot
spring-boot-starter-web
+
+
+ com.alibaba.cloud.ai
+ spring-ai-alibaba-starter-plugin-time
+ ${spring-ai-alibaba.version}
+
+
com.alibaba.cloud.ai
- spring-ai-alibaba-starter-plugin-time
- 1.0.0-M3.2
+ spring-ai-alibaba-starter-plugin-baidusearch
+ ${spring-ai-alibaba.version}
+
com.alibaba.cloud.ai
- spring-ai-alibaba-starter-plugin-baidusearch
- 1.0.0-M3.2
+ spring-ai-alibaba-starter-plugin-bingsearch
+ ${spring-ai-alibaba.version}
+
com.alibaba.cloud.ai
- spring-ai-alibaba-starter-plugin-bingsearch
- 1.0.0-M3.2
+ spring-ai-alibaba-starter-plugin-dingtalk
+ ${spring-ai-alibaba.version}
+
diff --git a/spring-ai-alibaba-examples/function-calling-example/src/main/java/com/alibaba/cloud/ai/example/functioncalling/FunctionCallingController.java b/spring-ai-alibaba-examples/function-calling-example/src/main/java/com/alibaba/cloud/ai/example/functioncalling/FunctionCallingController.java
index afacf651..a66cee77 100644
--- a/spring-ai-alibaba-examples/function-calling-example/src/main/java/com/alibaba/cloud/ai/example/functioncalling/FunctionCallingController.java
+++ b/spring-ai-alibaba-examples/function-calling-example/src/main/java/com/alibaba/cloud/ai/example/functioncalling/FunctionCallingController.java
@@ -27,20 +27,20 @@
@RequestMapping("/ai/func")
public class FunctionCallingController {
- private final ChatClient chatClient;
+ private final ChatClient chatClient;
- public FunctionCallingController(ChatClient.Builder chatClientBuilder) {
- this.chatClient = chatClientBuilder.build();
- }
+ public FunctionCallingController(ChatClient.Builder chatClientBuilder) {
+ this.chatClient = chatClientBuilder.build();
+ }
- @GetMapping("/weather-service")
- public String weatherService(String subject) {
- return chatClient.prompt()
- .function("getWeather", "根据城市查询天气", new MockWeatherService())
- .user(subject)
- .call()
- .content();
- }
+ @GetMapping("/weather-service")
+ public String weatherService(String subject) {
+ return chatClient.prompt()
+ .function("getWeather", "根据城市查询天气", new MockWeatherService())
+ .user(subject)
+ .call()
+ .content();
+ }
@GetMapping("/order-detail")
public String orderDetail() {
@@ -50,7 +50,7 @@ public String orderDetail() {
.call()
.content();
}
-
+
@GetMapping("/baidu-search")
public String baiduSearch(@RequestParam String query) {
return chatClient.prompt()
@@ -69,13 +69,22 @@ public String bingSearch(@RequestParam String query) {
.content();
}
- @GetMapping("/getTime")
- public String getTime(String text) {
- return chatClient.prompt()
- .functions("getCityTimeFunction")
- .user(text)
- .call()
- .content();
- }
+ @GetMapping("/getTime")
+ public String getTime(String text) {
+ return chatClient.prompt()
+ .functions("getCityTimeFunction")
+ .user(text)
+ .call()
+ .content();
+ }
+
+ @GetMapping("/dingTalk-custom-robot-send")
+ public String dingTalkCustomRobotSend(String input) {
+ return chatClient.prompt()
+ .functions("dingTalkGroupSendMessageByCustomRobotFunction")
+ .user(String.format("帮我用自定义机器人发送'%s'", input))
+ .call()
+ .content();
+ }
}
diff --git a/spring-ai-alibaba-examples/function-calling-example/src/main/resources/application.yml b/spring-ai-alibaba-examples/function-calling-example/src/main/resources/application.yml
index 973bf747..0ef70685 100644
--- a/spring-ai-alibaba-examples/function-calling-example/src/main/resources/application.yml
+++ b/spring-ai-alibaba-examples/function-calling-example/src/main/resources/application.yml
@@ -1,12 +1,16 @@
spring:
application:
- name: cfunction-calling-example
+ name: function-calling-example
ai:
dashscope:
- api-key: ${AI_DASHSCOPE_API_KEY}
+ api-key: ${AI_DASHSCOPE_API_KEY}
alibaba:
plugin:
+ dingtalk:
+ enabled: true
+ custom-robot-access-token: ${spring.ai.alibaba.plugin.dingtalk.custom-robot-access-token} # accessToken of custom robot
+ custom-robot-signature: ${spring.ai.alibaba.plugin.dingtalk.custom-robot-signature} # sign of custom robot
bing:
enabled: true
token: ${AI_BING_TOKEN}
\ No newline at end of file