开源模型应用落地-工具使用篇-Spring AI(七)

这篇具有很好参考价值的文章主要介绍了开源模型应用落地-工具使用篇-Spring AI(七)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

    在AI大模型百花齐放的时代,很多人都对新兴技术充满了热情,都想尝试一下。但是,实际上要入门AI技术的门槛非常高。除了需要高端设备,还需要面临复杂的部署和安装过程,这让很多人望而却步。不过,随着开源技术的不断进步,使得入门AI变得越来越容易。通过使用Ollama,您可以快速体验大语言模型的乐趣,不再需要担心繁琐的设置和安装过程。另外,通过集成Spring AI,让更多Java爱好者能便捷的将AI能力集成到项目中,接下来,跟随我的脚步,一起来体验一把。


二、术语

2.1、Spring AI

    是 Spring 生态系统的一个新项目,它简化了 Java 中 AI 应用程序的创建。它提供以下功能:

  • 支持所有主要模型提供商,例如 OpenAI、Microsoft、Amazon、Google 和 Huggingface。
  • 支持的模型类型包括“聊天”和“文本到图像”,还有更多模型类型正在开发中。
  • 跨 AI 提供商的可移植 API,用于聊天和嵌入模型。
  • 支持同步和流 API 选项。
  • 支持下拉访问模型特定功能。
  • AI 模型输出到 POJO 的映射。

2.2、Ollama
    是一个强大的框架,用于在 Docker 容器中部署 LLM(大型语言模型)。它的主要功能是在 Docker 容器内部署和管理 LLM 的促进者,使该过程变得简单。它可以帮助用户快速在本地运行大模型,通过简单的安装指令,用户可以执行一条命令就在本地运行开源大型语言模型。

    Ollama 支持 GPU/CPU 混合模式运行,允许用户根据自己的硬件条件(如 GPU、显存、CPU 和内存)选择不同量化版本的大模型。它提供了一种方式,使得即使在没有高性能 GPU 的设备上,也能够运行大型模型。
 


三、前置条件

3.1、JDK 17+

    下载地址:https://www.oracle.com/java/technologies/downloads/#jdk17-windows

    开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

    类文件具有错误的版本 61.0, 应为 52.0

3.2、创建Maven项目

    SpringBoot版本为3.2.3

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.3</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

3.3、导入Maven依赖包

<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<optional>true</optional>
</dependency>

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-core</artifactId>
</dependency>

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
</dependency>

<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-core</artifactId>
	<version>5.8.24</version>
</dependency>

<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
	<version>0.8.0</version>
</dependency>

<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
	<version>0.8.0</version>
</dependency>

3.4、 科学上网的软件

3.5、 安装Ollama及部署Qwen模型

    参见:开源模型应用落地-工具使用篇-Ollama(六)-CSDN博客


四、技术实现

4.1、调用Open AI

4.1.1、非流式调用

@RequestMapping("/chat")
public String chat(){
	String systemPrompt = "{prompt}";
	SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

	String userPrompt = "广州有什么特产?";
	Message userMessage = new UserMessage(userPrompt);

	Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));

	Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

	List<Generation> response = openAiChatClient.call(prompt).getResults();

	String result = "";

	for (Generation generation : response){
		String content = generation.getOutput().getContent();
		result += content;
	}

	return result;
}

    调用结果:

    开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

4.1.2、流式调用

@RequestMapping("/stream")
public SseEmitter stream(HttpServletResponse response){
	response.setContentType("text/event-stream");
	response.setCharacterEncoding("UTF-8");
	SseEmitter emitter = new SseEmitter();


	String systemPrompt = "{prompt}";
	SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

	String userPrompt = "广州有什么特产?";
	Message userMessage = new UserMessage(userPrompt);

	Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));
	Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

	openAiChatClient.stream(prompt).subscribe(x -> {
		try {
			log.info("response: {}",x);
			List<Generation> generations = x.getResults();
			if(CollUtil.isNotEmpty(generations)){
				for(Generation generation:generations){
				   AssistantMessage assistantMessage =  generation.getOutput();
					String content = assistantMessage.getContent();
					if(StringUtils.isNotEmpty(content)){
						emitter.send(content);
					}else{
						if(StringUtils.equals(content,"null"))
						emitter.complete(); // Complete the SSE connection
					}
				}
			}


		} catch (Exception e) {
			emitter.complete();
			log.error("流式返回结果异常",e);
		}
	});

	return emitter;
}

流式输出返回的数据结构:

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

    调用结果:

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

 开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

4.2、调用Ollama API

Spring封装的很好,基本和调用OpenAI的代码一致

4.2.1、非流式调用

@RequestMapping("/chat")
public String chat(){
	String systemPrompt = "{prompt}";
	SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

	String userPrompt = "广州有什么特产?";
	Message userMessage = new UserMessage(userPrompt);

	Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));

	Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

	List<Generation> response = ollamaChatClient.call(prompt).getResults();

	String result = "";

	for (Generation generation : response){
		String content = generation.getOutput().getContent();
		result += content;
	}

	return result;
}

调用结果:

Ollam的server.log输出

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

4.2.2、流式调用

@RequestMapping("/stream")
public SseEmitter stream(HttpServletResponse response){
	response.setContentType("text/event-stream");
	response.setCharacterEncoding("UTF-8");
	SseEmitter emitter = new SseEmitter();


	String systemPrompt = "{prompt}";
	SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

	String userPrompt = "广州有什么特产?";
	Message userMessage = new UserMessage(userPrompt);

	Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));
	Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

	ollamaChatClient.stream(prompt).subscribe(x -> {
		try {
			log.info("response: {}",x);
			List<Generation> generations = x.getResults();
			if(CollUtil.isNotEmpty(generations)){
				for(Generation generation:generations){
					AssistantMessage assistantMessage =  generation.getOutput();
					String content = assistantMessage.getContent();
					if(StringUtils.isNotEmpty(content)){
						emitter.send(content);
					}else{
						if(StringUtils.equals(content,"null"))
							emitter.complete(); // Complete the SSE connection
					}
				}
			}


		} catch (Exception e) {
			emitter.complete();
			log.error("流式返回结果异常",e);
		}
	});

	return emitter;
}

调用结果:

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring


五、附带说明

5.1、OpenAiChatClient默认使用gpt-3.5-turbo模型

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

5.2、流式输出如何关闭连接

    不能判断是否为''(即空字符串),以下代码将提前关闭连接

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

    流式输出会返回''的情况

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

      应该在返回内容为字符串null的时候关闭开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

5.3、配置文件中指定的Ollama的模型参数,要和运行的模型一致,即

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

开源模型应用落地-工具使用篇-Spring AI(七),开源大语言模型-新手试炼,深度学习,spring

5.4、OpenAI调用完整代码

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.Generation;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.List;

@Slf4j
@RestController
@RequestMapping("/api")
public class OpenaiTestController {
    @Autowired
    private OpenAiChatClient openAiChatClient;

//    http://localhost:7777/api/chat
    @RequestMapping("/chat")
    public String chat(){
        String systemPrompt = "{prompt}";
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

        String userPrompt = "广州有什么特产?";
        Message userMessage = new UserMessage(userPrompt);

        Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));

        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

        List<Generation> response = openAiChatClient.call(prompt).getResults();

        String result = "";

        for (Generation generation : response){
            String content = generation.getOutput().getContent();
            result += content;
        }

        return result;
    }

    @RequestMapping("/stream")
    public SseEmitter stream(HttpServletResponse response){
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");
        SseEmitter emitter = new SseEmitter();


        String systemPrompt = "{prompt}";
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

        String userPrompt = "广州有什么特产?";
        Message userMessage = new UserMessage(userPrompt);

        Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));
        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

        openAiChatClient.stream(prompt).subscribe(x -> {
            try {
                log.info("response: {}",x);
                List<Generation> generations = x.getResults();
                if(CollUtil.isNotEmpty(generations)){
                    for(Generation generation:generations){
                       AssistantMessage assistantMessage =  generation.getOutput();
                        String content = assistantMessage.getContent();
                        if(StringUtils.isNotEmpty(content)){
                            emitter.send(content);
                        }else{
                            if(StringUtils.equals(content,"null"))
                            emitter.complete(); // Complete the SSE connection
                        }
                    }
                }


            } catch (Exception e) {
                emitter.complete();
                log.error("流式返回结果异常",e);
            }
        });

        return emitter;
    }
}

5.5、Ollama调用完整代码

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.Generation;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.List;

@Slf4j
@RestController
@RequestMapping("/api")
public class OllamaTestController {
    @Autowired
    private OllamaChatClient ollamaChatClient;

    @RequestMapping("/chat")
    public String chat(){
        String systemPrompt = "{prompt}";
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

        String userPrompt = "广州有什么特产?";
        Message userMessage = new UserMessage(userPrompt);

        Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));

        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

        List<Generation> response = ollamaChatClient.call(prompt).getResults();

        String result = "";

        for (Generation generation : response){
            String content = generation.getOutput().getContent();
            result += content;
        }

        return result;
    }


    @RequestMapping("/stream")
    public SseEmitter stream(HttpServletResponse response){
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");
        SseEmitter emitter = new SseEmitter();


        String systemPrompt = "{prompt}";
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

        String userPrompt = "广州有什么特产?";
        Message userMessage = new UserMessage(userPrompt);

        Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));
        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

        ollamaChatClient.stream(prompt).subscribe(x -> {
            try {
                log.info("response: {}",x);
                List<Generation> generations = x.getResults();
                if(CollUtil.isNotEmpty(generations)){
                    for(Generation generation:generations){
                        AssistantMessage assistantMessage =  generation.getOutput();
                        String content = assistantMessage.getContent();
                        if(StringUtils.isNotEmpty(content)){
                            emitter.send(content);
                        }else{
                            if(StringUtils.equals(content,"null"))
                                emitter.complete(); // Complete the SSE connection
                        }
                    }
                }


            } catch (Exception e) {
                emitter.complete();
                log.error("流式返回结果异常",e);
            }
        });

        return emitter;
    }
}

5.6、核心配置

spring:
  ai:
    openai:
      api-key: sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ollama:
      base-url: http://localhost:11434
      chat:
        model: qwen:1.8b-chat

5.7、启动类文章来源地址https://www.toymoban.com/news/detail-838278.html

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AiApplication {

    public static void main(String[] args) {
        System.setProperty("http.proxyHost","127.0.0.1");
        System.setProperty("http.proxyPort","7078"); // 修改为你代理软件的端口
        System.setProperty("https.proxyHost","127.0.0.1");
        System.setProperty("https.proxyPort","7078"); // 同理

        SpringApplication.run(AiApplication.class, args);
    }

}

到了这里,关于开源模型应用落地-工具使用篇-Spring AI(七)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 开源模型应用落地-工具使用篇-向量数据库(三)

    一、前言     通过学习\\\"开源模型应用落地\\\"系列文章,我们成功地建立了一个完整可实施的AI交付流程。现在,我们要引入向量数据库,作为我们AI服务的二级缓存。本文将详细介绍如何使用Milvus Lite来为我们的AI服务部署一个前置缓存。 二、术语 2.1、向量数据库     向量数

    2024年02月19日
    浏览(59)
  • 【AI 开源框架】BMTools 是一能让语言模型使用扩展工具的开源仓库

    BMTools 是一能让语言模型使用扩展工具的开源仓库,其也是开源社区构建和共享工具的一个平台。在这个仓库中,您可以: (1) 通过编写 Python 函数轻松构建插件, (2) 使用外部的 ChatGPT-Plugins。 本项目受到开源项目LangChain的启发,针对开源工具的使用(例如ChatGPT-Plugins)进行了

    2024年02月08日
    浏览(51)
  • rk3588使用npu进行模型转换和推理,加速AI应用落地

    本文完成于2022-07-02 20:21:55 。博主在瑞芯微RK3588的开发板上跑了deepsort跟踪算法,从IP相机中的server拉取rtsp视频流,但是fps只有1.2,和放PPT一样卡顿,无法投入实际应用。本来想使用tensorrt进行加速推理,但是前提需要cuda,rk的板子上都是Arm的手机gpu,没有Nvidia的cuda,所以这条

    2023年04月12日
    浏览(45)
  • 开源模型应用落地-总述

            在当今社会,实际应用比纯粹理解原理和概念更为重要。即使您对某个领域的原理和概念有深入的理解,但如果无法将其应用于实际场景并受制于各种客观条件,那么与其一开始就过于深入,不如先从基础开始,实际操作后再逐步深入探索。         在这种实践至上

    2024年03月14日
    浏览(55)
  • 开源模型应用落地-业务优化篇(六)

    一、前言     经过线程池优化、请求排队和服务实例水平扩容等措施,整个AI服务链路的性能得到了显著地提升。但是,作为追求卓越的大家,绝不会止步于此。我们的目标是在降低成本和提高效率方面不断努力,追求最佳结果。如果你们在实施AI项目方面有经验,那一定会

    2024年02月22日
    浏览(49)
  • 开源模型应用落地-业务整合篇(四)

    一、前言     通过学习第三篇文章,我们已经成功地建立了IM与AI服务之间的数据链路。然而,我们目前面临一个紧迫需要解决的安全性问题,即非法用户可能会通过获取WebSocket的连接信息,顺利地连接到我们的服务。这不仅占用了大量的无效连接和资源,还对业务数据带来

    2024年01月24日
    浏览(43)
  • 开源模型应用落地-业务整合篇(一)

    一、前言     经过对qwen-7b-chat的部署以及与vllm的推理加速的整合,我们成功构建了一套高性能、高可靠、高安全的AI服务能力。现在,我们将着手整合具体的业务场景,以实现完整可落地的功能交付。     作为上游部门,通常会采用最常用的方式来接入下游服务。为了调用

    2024年01月20日
    浏览(49)
  • 开源模型应用落地-qwen模型小试-入门篇(三)

    一、前言     相信您已经学会了如何在Windows环境下以最低成本、无需GPU的情况下运行qwen大模型。现在,让我们进一步探索如何在Linux环境下,并且拥有GPU的情况下运行qwen大模型,以提升性能和效率。 二、术语     2.1. CentOS         CentOS是一种基于Linux的自由开源操作系统。

    2024年01月21日
    浏览(53)
  • 以太坊实现、语言模型应用与实用工具 | 开源日报 0817

    Go Ethereum 是以太坊协议的官方 Golang 执行层实现,可运行各种节点并提供网关访问以太坊网络;LangChain-Chatchat 是基于大语言模型的本地知识库问答应用实现,支持离线运行和多种模型接入;Shiori 是简单易用的书签管理器,支持命令行和 Web 应用程序,且可移植性强;Awesome G

    2024年02月09日
    浏览(39)
  • 开源模型应用落地-qwen2模型小试-入门篇(六)

        经过前五篇“qwen模型小试”文章的学习,我们已经熟练掌握qwen大模型的使用。然而,就在前几天开源社区又发布了qwen1.5版本,它是qwen2模型的测试版本。在基于transformers的使用方式上有较大的调整,现在,我们赶紧跟上脚步,去体验一下新版本模型的推理质量。    

    2024年03月17日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包