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

spring-ai-alibaba第四章阿里dashscope集成百度翻译tool

1、pom文件

  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-tool-calling-baidutranslate</artifactId>
            <version>${spring-ai-alibaba.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-tool-calling-weather</artifactId>
            <version>${spring-ai-alibaba.version}</version>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${junit-jupiter.version}</version>
        </dependency>

    </dependencies>

2、yml文件,由于本机ollama上的模型支持的function call 时好时坏,所以使用阿里的

dashscope的qwq-plus模型
spring:
  ai:
    alibaba:
      toolcalling:
        baidutranslate:
          enabled: true
          app-id: xxxxxxxxxx
          secret-key: yyyyyyyyy

        time:
          enabled: true

        weather:
          enabled: true
          api-key: ${WEATHER_API_KEY}
    dashscope:
      api-key: sk-xoxoxoxoxoxo
      chat:
        model: qwq-plus
      embedding:
        model: text-embedding-v2

3、百度翻译的appid和key

package com.alibaba.cloud.ai.toolcall.component.baidutranslate;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "spring.ai.alibaba.toolcalling.baidutranslate")
public class BaidutranslateProperties {

    private String appId;

    private String secretKey;

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

}

4、百度翻译的tool

package com.alibaba.cloud.ai.toolcall.component.baidutranslate.method;

import com.alibaba.cloud.ai.toolcall.component.baidutranslate.BaidutranslateProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.http.HttpHeaders;
import org.springframework.util.DigestUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @author yingzi
 * @date 2025/3/27:11:13
 */
public class BaidutranslateTools {

    private static final Logger logger = LoggerFactory.getLogger(BaidutranslateTools.class);

    private static final String TRANSLATE_HOST_URL = "https://fanyi-api.baidu.com/api/trans/vip/translate";

    private static final Random random = new Random();
    private final WebClient webClient;
    private final String appId;
    private final String secretKey;

    public BaidutranslateTools(BaidutranslateProperties properties) {
        assert StringUtils.hasText(properties.getAppId());
        this.appId = properties.getAppId();
        assert StringUtils.hasText(properties.getSecretKey());
        this.secretKey = properties.getSecretKey();

        this.webClient = WebClient.builder()
                .defaultHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
                .build();
    }

    @Tool(description = "Baidu translation function for general text translation")
    public Map<String, String> baiduTranslateMethod(@ToolParam(description = "Content that needs to be translated") String q,
                                                    @ToolParam(description = "Source language that needs to be translated") String from,
                                                    @ToolParam(description = "Target language to translate into") String to) {
        if (!StringUtils.hasText(q) || !StringUtils.hasText(from)
                || !StringUtils.hasText(to)) {
            return null;
        }
        String salt = String.valueOf(random.nextInt(100000));
        String sign = DigestUtils.md5DigestAsHex((appId + q + salt + secretKey).getBytes());
        String url = UriComponentsBuilder.fromHttpUrl(TRANSLATE_HOST_URL).toUriString();
        try {
            MultiValueMap<String, String> body = constructRequestBody(q, from, to, salt, sign);
            Mono<String> responseMono = webClient.post().uri(url).bodyValue(body).retrieve().bodyToMono(String.class);

            String responseData = responseMono.block();
            assert responseData != null;
            logger.info("Translation request: {}, response: {}", q, responseData);

            return parseResponse(responseData);

        }
        catch (Exception e) {
            logger.error("Failed to invoke translate API due to: {}", e.getMessage());
            return null;
        }
    }

    private MultiValueMap<String, String> constructRequestBody(String q, String from, String to, String salt, String sign) {
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("q", q);
        body.add("from", from);
        body.add("to", to);
        body.add("appid", appId);
        body.add("salt", salt);
        body.add("sign", sign);
        return body;
    }

    private Map<String, String> parseResponse(String responseData) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            Map<String, String> translations = new HashMap<>();
            TranslationResponse responseList = mapper.readValue(responseData, TranslationResponse.class);
            String to = responseList.to;
            List<TranslationResult> translationsList = responseList.trans_result;
            if (translationsList != null) {
                for (TranslationResult translation : translationsList) {
                    String translatedText = translation.dst;
                    translations.put(to, translatedText);
                    logger.info("Translated text to {}: {}", to, translatedText);
                }
            }
            return translations;
        }
        catch (Exception e) {
            try {
                Map<String, String> responseList = mapper.readValue(responseData,
                        mapper.getTypeFactory().constructMapType(Map.class, String.class, String.class));
                logger.info(
                        "Translation exception, please inquire Baidu translation api documentation to info error_code:{}",
                        responseList);
                return responseList;
            }
            catch (Exception ex) {
                logger.error("Failed to parse json due to: {}", ex.getMessage());
                return null;
            }
        }
    }

    public record TranslationResult(String src, String dst) {
    }

    public record TranslationResponse(String from, String to, List<TranslationResult> trans_result) {
    }
}

5、翻译 controller

package com.alibaba.cloud.ai.toolcall.controller;

import com.alibaba.cloud.ai.toolcall.component.baidutranslate.BaidutranslateProperties;
import com.alibaba.cloud.ai.toolcall.component.baidutranslate.method.BaidutranslateTools;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/translate")
public class TranslateController {

    private final ChatClient dashScopeChatClient;
    private final BaidutranslateProperties baidutranslateProperties;


    public TranslateController(ChatClient.Builder chatClientBuilder, BaidutranslateProperties baidutranslateProperties) {
        this.dashScopeChatClient = chatClientBuilder.build();
        this.baidutranslateProperties = baidutranslateProperties;
    }

    /**
     * 无工具版
     */
    @GetMapping("/chat")
    public String simpleChat(@RequestParam(value = "query", defaultValue = "帮我把以下内容翻译成英文:你好,世界。") String query) {
        return dashScopeChatClient.prompt(query).call().content();
    }

    /**
     * 调用工具版 - function
     */
    @GetMapping("/chat-tool-function")
    public String chatTranslateFunction(@RequestParam(value = "query", defaultValue = "帮我把以下内容翻译成英文:你好,世界。") String query) {
        return dashScopeChatClient.prompt(query).tools("baiduTranslateFunction").call().content();
    }

    /**
     * 调用工具版 - method
     */
    @GetMapping("/chat-tool-method")
    public String chatTranslateMethod(@RequestParam(value = "query", defaultValue = "帮我把以下内容翻译成英文:你好,世界。") String query) {
        // 从配置文件中,获取,自动加载
        return dashScopeChatClient.prompt(query).tools(new BaidutranslateTools(baidutranslateProperties)).call().content();
    }

}

6、不带工具测试如下

7、带工具测试如下 

http://www.dtcms.com/a/108162.html

相关文章:

  • 端到端机器学习流水线(MLflow跟踪实验)
  • Vue3+Vite+TypeScript+Element Plus开发-04.静态菜单设计
  • Java单例模式详解
  • 深入理解 CSS 选择器:从基础到高级的样式控制
  • iPhone 16怎么录制屏幕内容?屏幕录制技巧、软件分享
  • eBest AI智能报表:用自然语言对话解锁企业数据生产力
  • PostgreSQL HAVING 子句详解
  • 最小二乘求解器lstsq,处理带权重和L2正则的线性回归
  • Vue3 + Element Plus + AntV X6 实现拖拽树组件
  • 【人工智能之大模型】如何缓解大语言模型LLMs重复读的问题?
  • 函数ioctl(Input/Output Control)
  • mac如何将jar包上传到maven中央仓库中
  • LeetCode-695. 岛屿的最大面积
  • Linux系统之systemctl管理服务及编译安装配置文件安装实现systemctl管理服务
  • Redis-10.在Java中操作Redis-Spring Data Redis使用方式-操作步骤说明
  • 基于随机森林算法的信用风险评估项目
  • 汇编学习结语
  • Dify案例-接入飞书云文档实现需求质量评估
  • MongoDB文档操作
  • 基于HTML5的音乐播放器(源码+lw+部署文档+讲解),源码可白嫖!
  • vscode代码片段的设置与使用
  • 填坑日志(20250402)解决Jira Rest API出现403XSRF check failed报错的问题
  • Ansible(4)—— Playbook
  • STL 性能优化实战:解决项目中标准模板库的性能瓶颈
  • C语言跳表(Skip List)算法:数据世界的“时光穿梭机”
  • Node.js v22.14.0 多平台安装指南:Windows、Linux 和 macOS 详细教程
  • 当AI开始“思考“:大语言模型的文字认知三部曲
  • Vue 中 this.$emit(“update:xx“,value) 和 :xx.sync 实现同步数据的做法
  • 创建灵活可配置的轮播图组件: GrapesJS 与 Vue3 的完美结合
  • 超短波通信模拟设备:增强通信能力的关键工具