Spring AI 阿里巴巴学习

1、Spring AI alibaba介绍

Spring AI Alibaba是基于Spring AI框架构建的实现,专注于接入阿里云百炼系列的大模型服务。通过Spring AI Alibaba,开发者可以轻松地利用通义大模型进行文本生成、图像生成、语音合成等任务。其核心优势在于提供了统一的API接口,使得开发者能够以一致的方式调用不同类型的AI服务,并且只需修改配置即可切换不同的AI提供者,极大地简化了开发过程中的复杂度。此外,Spring AI Alibaba还支持本地部署及多种主流AI框架(如OpenAI和Ollama)的集成,进一步增强了其灵活性与适用性。

模型 Model

一句话说明:支持多种模型,包括多模态处理与图像识别。 输入输出举例:输入为文本或图片等,输出为相应的内容生成、分析结果。例如使用qwen-vl-max-latest模型进行图像内容识别。

提示 Prompt

一句话说明:提供给AI的初始信息或问题,用于引导其生成特定类型的响应。 输入输出举例:输入可以是一段话如"请描述这张照片",输出则是基于此提示对图片内容的解释。

提示词模板 Prompt Template

一句话说明:预设好的结构化提示模板,简化了复杂提示的设计过程。 输入输出举例:通过定义类似"我想知道消息id: {id}"这样的模板,并填充具体值(如{id}替换为实际ID),以产生针对特定场景的有效查询语句。

嵌入 Embedding

一句话说明:将数据转换成固定长度向量表示的方法,便于进行相似度计算和检索。 输入输出举例:一段文本作为输入,经过嵌入处理后得到一个数值向量作为输出,该向量可用于后续的相似性比较或其他机器学习任务中。

结构化输出 Structured Output

一句话说明:确保生成的内容符合预定格式,提高数据的一致性和可解析性。 输入输出举例:请求天气预报时,返回的数据不仅包含天气状况的文字描述,还包括温度、湿度等具体数值信息,这些都按照事先定义好的JSON格式组织起来。

检索增强生成 RAG

一句话说明:结合检索技术和生成模型,利用私有知识库来提升回答质量和准确性。 输入输出举例:用户询问公司财报中的某个具体数字,系统先从已存储的文档中检索相关信息,再结合这些上下文生成精准的回答。

函数调用 Function Calling

一句话说明:允许大语言模型在需要时执行开发者提供的功能,如调用外部API或执行特定代码。 输入输出举例:当询问某条消息的状态时,LLM不会直接回应,而是触发一个函数去查询数据库并返回状态详情。

向量存储 Vector Store

一句话说明:用于保存和管理大量高维向量数据的数据库,支持快速搜索相似项。 输入输出举例:上传一系列文档后将其转化为向量形式存入向量库,在需要时可通过关键词快速定位相关资料。

2、代码实现

前置条件

确保您的开发环境满足以下要求:

  • JDK版本至少为17。
  • Spring Boot版本为3.3.x或更高。
  • 已经在阿里云上申请了通义千问服务的API Key,并且已经按照指示将其设置到了系统变量中。

2.1创建一个springboot工程,添加依赖

python 复制代码
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter</artifactId>
            <version>1.0.0-M6.1</version>
        </dependency>

由于Spring AI的部分库尚未发布到Maven中央仓库,因此需要额外配置Spring自己的仓库地址至项目的pom.xml中

java 复制代码
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

配置apikey

2.2创建一个控制器类用于接收用户的输入并通过聊天客户端向AI发送请求

java 复制代码
private final ChatClient chatClient;
    private final ImageModel imageModel;
    private final ChatModel chatMduel;

    public AIController(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory, ImageModel imageModel, ChatModel chatMduel) {
        this.chatMduel = chatMduel;
        this.chatClient = chatClientBuilder
                .defaultAdvisors(new PromptChatMemoryAdvisor(chatMemory))
                .defaultSystem("You are a helpful assistant.")
                .build();
        this.imageModel = imageModel;
    }
@GetMapping("/chat")
    public String chat(@RequestParam("message") String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }

2.3流式响应

java 复制代码
 @GetMapping(value = "/stream",produces = "text/html;charset=UTF-8")
    public Flux<String> streamChat(@RequestParam String message) {
        return chatClient.prompt()
                .user(message)
                .stream()
                .content();
    }

Flux进行流式响应,

复制代码
produces = "text/html;charset=UTF-8",解决响应乱码

2.4生成图片

java 复制代码
 @GetMapping("/image")
    public ResponseEntity<String> generateImage(@RequestParam String message) {
        try {
            ImageOptions options = ImageOptionsBuilder.builder()
                    .width(1024)
                    .height(1024)
                    .model("wanx-v1") // 使用从阿里云获取到的具体模型名称
                    .N(1)
                    .build();

            ImagePrompt prompt = new ImagePrompt(message, options);
            ImageResponse response = imageModel.call(prompt);
            List<ImageGeneration> results = response.getResults();
            if (results.isEmpty()) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("No image generated.");
            }
            String imageUrl = results.get(0).getOutput().getUrl();
            return ResponseEntity.ok(imageUrl);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }

2.5图片识别

java 复制代码
 @Value("classpath:231.png")
    private Resource imageResource;

    private static final String DEFAULT_PROMPT = "这些是什么?";
    private static final String DEFAULT_MODEL = "qwen-vl-max-latest";

    @GetMapping("/imageRecognition")
    public Flux<String> imageRecognition(@RequestParam(value = "prompt", required = false, defaultValue = DEFAULT_PROMPT) String prompt,
                                         HttpServletResponse response) throws Exception {
        response.setCharacterEncoding("UTF-8");

        List<Media> mediaList = Collections.singletonList(new Media(MimeTypeUtils.IMAGE_PNG, imageResource));
        UserMessage message = new UserMessage(prompt, mediaList);
        message.getMetadata().put(DashScopeChatModel.MESSAGE_FORMAT, MessageFormat.IMAGE);

        return chatMduel.stream(
                        new Prompt(message,
                                DashScopeChatOptions.builder()
                                        .withModel(DEFAULT_MODEL)
                                        .withMultiModel(true)
                                        .build()))
                .map(resp -> resp.getResult().getOutput().toString());
    }

2.6Function Call

**大模型是怎么知道: **

1)当前有哪些接口可以调用的?

2)每个接口能干什么?

3)接口有什么入参出参的?

函数调用的实现依赖于开发者定义一个实现了java.util.function.Function接口的Java类,并通过注解描述其输入参数、输出结果及功能。

具体来说,使用@JsonProperty和@JsonPropertyDescription等Jackson注解来详细说明方法的参数与返回值。 Json property标记了函数的输入参数和输出参数,然后Function的Description则表达了这函数是干啥的。

java 复制代码
 @GetMapping(value ="/chatStream",produces = "text/html;charset=UTF-8")
    public Flux<String> chatSteam(@RequestParam String input) {
        PromptTemplate promptTemplate = new PromptTemplate("我想知道{company}的最新财务状况");
        DashScopeChatOptions ops = DashScopeChatOptions.builder()
                .withFunction("xueQiuFinanceFunction").build();
        Map<String, Object> map = Map.of("company", input);
        Prompt promp = promptTemplate.create(map, ops);
        return chatClient.prompt(promp).stream().content();
    }

当大模型判断需要调用方法时,去调用

复制代码
withFunction配置的方法名称
java 复制代码
package com.lijianxi.springai.springailearn;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;

import java.util.function.Function;

@Configuration
public class AppConfig {

    @Bean
    @Description("查询指定公司代码的财务信息")
    public Function<XueQiuFinanceService.FinanceRequest, String> xueQiuFinanceFunction() {
        return new XueQiuFinanceService();
    }
}
java 复制代码
package com.lijianxi.springai.springailearn;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import org.springframework.web.client.RestTemplate;

import java.util.function.Function;

public class XueQiuFinanceService implements Function<XueQiuFinanceService.FinanceRequest, String> {

    @Override
    public String apply(FinanceRequest request) {
        RestTemplate restTemplate = new RestTemplate();
        String url = "https://stock.xueqiu.com/v5/stock/finance/cn/income.json?symbol=" + request.getSymbol() + "&type=all&is_detail=true&count=1";
        // String response = restTemplate.getForObject(url, String.class);
        
        // 解析response并生成简单分析,这里仅做示意
        return "解析后的数据及简要分析:" + "业务很好,继续保持";
    }

    public static class FinanceRequest {
        @JsonProperty(required = true, value = "公司代码")
        @JsonPropertyDescription("上市公司的股票代码")
        private String symbol;

        public FinanceRequest() {}

        public FinanceRequest(String symbol) {
            this.symbol = symbol;
        }

        public String getSymbol() {
            return symbol;
        }

        public void setSymbol(String symbol) {
            this.symbol = symbol;
        }
    }
}

实际来说就是三步,

第一步:定义一个类继承实现Functiion的applay方法,在这个方法里边调用工具。

第二步:Spring配置类中注册该函数

第三步:通过withFunction告诉大模型什么时候来调用该函数

相关推荐
码荼23 分钟前
学习开发之hashmap
java·python·学习·哈希算法·个人开发·小白学开发·不花钱不花时间crud
书玮嘎26 分钟前
【WIP】【VLA&VLM——InternVL系列】
人工智能·深度学习
猫头虎37 分钟前
猫头虎 AI工具分享:一个网页抓取、结构化数据提取、网页爬取、浏览器自动化操作工具:Hyperbrowser MCP
运维·人工智能·gpt·开源·自动化·文心一言·ai编程
要努力啊啊啊1 小时前
YOLOv2 正负样本分配机制详解
人工智能·深度学习·yolo·计算机视觉·目标跟踪
CareyWYR1 小时前
大模型真的能做推荐系统吗?ARAG论文给了我一个颠覆性的答案
人工智能
特立独行的猫a1 小时前
百度AI文心大模型4.5系列开源模型评测,从安装部署到应用体验
人工智能·百度·开源·文心一言·文心一言4.5
武昌库里写JAVA1 小时前
Oracle如何使用序列 Oracle序列使用教程
java·开发语言·spring boot·学习·课程设计
SKYDROID云卓小助手1 小时前
无人设备遥控器之自动调整编码技术篇
人工智能·嵌入式硬件·算法·自动化·信号处理
小陈phd1 小时前
李宏毅机器学习笔记——梯度下降法
人工智能·python·机器学习