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

使用SpringAI快速实现离线/本地大模型应用

前言

大模型(LLM),Large Language Model作为当前比较热门的技术,最近在年在各行各业中都得到了广泛的应用。

在我们目前使用较多的AI产品中,几乎都是使用的互联网(云端)上的AI工具,即:需要先把数据传输给AI平台,由AI平台处理后,再将信息回馈到我们的本地应用。

然而在许多领域,由于大模型的数据没有采集到更细化的信息,亦或者出于安全原因某些数据不能对外公开,这时使用离线大模型来实现信息生成与检索则变得非常重要。

很久没用Spring的我,最近看到Spring官网出了Spring AI这个框架,出于好奇体验了下感觉非常不错,在此写篇博文记录下。

本文重点为:如何快速从0到1搭建一个离线大模型,并使用SpringAI进行交互调用。

ollama介绍与安装

ollama作为一个工具(且开源),让大模型的安装与运行变得非常简单。
ollama

ollama支持多种操作系统,为了方便可以直接使用Docker运行。

下载命令一行搞定:

sudo docker pull ollama/ollama:latest

ollama上手

ollama下载好后,直接运行

#运行ollama,并指定挂载目录和映射端口
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
#进入ollama容器
docker exec -it ollama bash
#运行ollama命令pull一个大模型,这里拉取具有图像识别能力的minicpm-v
ollama pull minicpm-v

ollama支持的大模型非常多,如google的gemma、facebook的llama、阿里的qwen通通都有,按需所取。
模型仓库地址为:https://ollama.com/library

大模型下载好了后,就可以使用ollama run命令运行对应的模型,并可以进行命令行的文本交互

ollama run minicpm-v

ollama-run

open-webui安装

为了能获得更好的体验,可以使用开源的open-webui进行来访问离线大模型,UI界面和ChatGPT的非常像。

docker下拉取命令:

sudo docker pull ghcr.io/open-webui/open-webui:main

拉取好后直接运行:

docker run -d --network=host -v open-webui:/app/backend/data -e OLLAMA_BASE_URL=http://127.0.0.1:11434 --name open-webui --restart always ghcr.io/open-webui/open-webui:main

这里笔者为了方便使用的是host网络,默认暴露的端口为8080,指定了webui存储数据的目录为/app/backend/data,并指定了ollama的后端地址为http://127.0.0.1:11434

基本功能体验

通过上面几行命令安装好了ollama与open-webui,之后就可以体验下离线大模型的常用功能了。

访问方式:直接访问open-webui的ip+port就行。
如我这里的docker物理机为192.168.140.8,则访问地址为http://192.168.140.8:8080

智能对话

首次访问open-webui需要先本地注册,随便填一个账号信息就行,并且首次注册的账号也是管理员账号。

由于我前面下载的大模型为minicpm-v,它是支持中文,效果如下:
chat-gif

图片识别

如minicpm-v的介绍所述
minicpm-v

minicpm-v模型支持图像视频识别,传一个兴隆湖的照片让它试一下。
read-img
识别效果也还可以

文生图

文生图方面比较知名的开源大模型为StableDiffusion,为了方便我们可以使用在StableDiffusion基础上进行二次开发的ComfyUI。
关于comfyui的安装方式可以参考此链接https://comfyui-wiki.com/zh-CN进行学习。

要注意的是,要让open-webui能成功调用ComfyUI进行文生图,需要确保ComfyUI监听端口能访问到,且开启了DevMode

之后再进入open-webui的设置界面的图像栏进行设置,在其中填入ComfyUI的接口地址与模型配置即可。
open-webui-settings

配置好了之后再回到对话界面,如有符合可以生成图片的提示词界面上就会出点一个图像按钮点一下即可生成图片

以生成一个小女孩的需求为例,演示一下:
gen-img
上面例子中输入的关键字为:回复提示词"A girl",仅回复提示词,不要回复别的信息

如想让提示词更加完善,可以使用https://ollama.com/impactframes/llama3_ifai_sd_prompt_mkr_q4km这个模型,它可以自动完善提示词以让生成的图像更丰富。

ollama run impactframes/llama3_ifai_sd_prompt_mkr_q4km

用它生成图像时,就可以这样进行对话:

Write prompts for “A smiling girl,in bikini.”. Only response the prompts for the image and nothing else.

OpenWebUi中调用文生图,其最终都会调用到本地的ComfyUI里,大量生成图片、动画、视频的需求更建议直接使用ComfyUI,效果更佳
ComfyUI

spring-ai

前面介绍了如何使用ollamaopen-webui快速搭建一个离线大模型平台,并体验了AI的相关功能。

但在实际业务场景中,前端程序往往与后端平台进行对接,与大模型的交互后端程序来负责接入则更为合适。

站在这一维度考虑,使用Spring AI接入大模型则是一个不错的选择。

SpringAI

关于Spring AI的详细介绍可参考:https://spring.io/projects/spring-ai

Spring AI is an application framework for AI engineering. Its goal is to apply to the AI domain Spring ecosystem design principles such as portability and modular design and promote using POJOs as the building blocks of an application to the AI domain.

翻译一下:Spring AI是一个AI工程框架。它的目标是将Spring生态的设计原则应用到AI领域,比如可移植性和模块化,并推广使用POJO来构建AI生态。

换句话讲:Spring AI不生产AI,只是AI的搬运工

快速接入

尽管Spring AI目前还处于开发阶段,但已经提供了使用文档,以让我们能体验并使用Spring AI的基本功能。接入方式说明可参考:getting-started

Spring AI支持接入的大模型较多,这里以接入离线的ollama为例,记录下接入过程

spring-ai-flow

pom依赖

新建一个maven项目,其pom.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0</version><relativePath/></parent><groupId>com.haiyang</groupId><artifactId>spring-ai-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-ai-demo</name><description>spring-ai-demo</description><properties><java.version>17</java.version><spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-ollama-spring-boot-starter</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></repository></repositories>
</project>

需要了解到的是:目前Spring AI还没有正式版,所以需要添加repository标签以能从snapshot仓库下载到依赖。

大模型接口配置

在SpringBoot项目的配置文件中添加配置项,在application.properties中新增:

#配置ollama接口地址
spring.ai.ollama.base-url=http://192.168.140.8:11434/
#配置使用的ollama模型
spring.ai.ollama.chat.options.model=gemma:7b

启动类与接口实现

在Application类中创建ChatClient

@SpringBootApplication
public class SpringAiDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringAiDemoApplication.class, args);}@Beanpublic ChatClient chatClient(ChatClient.Builder builder) {return builder.build();}
}

在controller中添加一个接口

@RestController
public class AIController {@Resourceprivate ChatClient chatClient;@GetMapping("/ai")public Map<String, String> completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {return Map.of("generation",Objects.requireNonNull(chatClient.prompt().user(message).call().content()));}
}

以上,一个基于集成了gemma的离线大模型后端就实现好了。是不是非常简单

对话接口验证

访问http://127.0.0.1:8080/ai试一下
api-test

试一下携带参数,message=成都有哪些好玩的地方
withParamTest

stream消息接口实现

我们知道智能对话的底层是AIGC,也就是它的结果是一个字一个字冒出来的,为了视觉上更好的直观体验,我们也一般采用实时更新的方式将冒出的字词一个个通知到前端。

sse

用于后端向前端实时通信的方案有很多,为了实现性能好开销低,推荐使用SSE(Server-Sent Events)的方式进行字符(token)的推送

HTTP 短轮询、HTTP 长轮询、WebSocket、SSE 的顺序重新排列的对比表格
cmp-sse

在Spring AI中,使用自带的ChatModel就可以实现。示例接口代码如下:

    @GetMapping("/ai/generateStream")public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {Prompt prompt = new Prompt(new UserMessage(message));return this.chatModel.stream(prompt);}

使用stream返回数据时,则可以看到前端收到的消息则是一个字一个字发下去的了。
sse-cap

再搭配Vaadin实现一个前端界面,源码为:

@Route("")
public class HaiyangAIView extends VerticalLayout {public HaiyangAIView(ChatService chatService) {String chatId = chatService.establishChat();var messageList = new VerticalLayout();var messageInput = new MessageInput();messageInput.setWidthFull();messageInput.addSubmitListener(e -> submitPromptListener(chatId, e, chatService, messageList));addClassName("centered-content");add(messageList, messageInput);}private static void submitPromptListener(String chatId, MessageInput.SubmitEvent e, ChatService chatService, VerticalLayout messageList) {var question = e.getValue();var userMessage = new MarkdownMessage(question, "You", Color.AVATAR_PRESETS[6]);var assistantMessage = new MarkdownMessage("haiyangAI", Color.AVATAR_PRESETS[0]);messageList.add(userMessage, assistantMessage);chatService.chat(chatId, question).map(res -> Optional.ofNullable(res.getResult().getOutput().getContent()).orElse("")).subscribe(assistantMessage::appendMarkdownAsync);}
}

再看一下效果,应答内容就动起来了
haiyangAI-demo

总结

使用Spring AIollama进行离线大模型平台的搭建又快又简单。

为Spring AI点赞,向ollama与各种开源大模型致敬!

本文源码地址:https://github.com/puhaiyang/springai-demo


http://www.mrgr.cn/news/68944.html

相关文章:

  • 计算机网络易混淆知识点串记
  • 通过MT4调用Windows API进行文件读写操作
  • HBase 安装与基本操作指南
  • python可视化自动打包工具auto-py-to-exe使用介绍
  • uniapp实现H5和微信小程序获取当前位置(腾讯地图)
  • qt QWebSocketServer详解
  • [241109] 树莓派触摸显示屏 2 代上市 | LibreOffice 24.2.7 发布,24.2 分支的最终版本
  • Python函数专题:默认参数与关键字参数
  • PMP–一、二、三模、冲刺–分类–6.进度管理--技巧--资源平衡资源平滑
  • 【C语言】调试宏:进阶篇
  • Linux相关概念和易错知识点(19)(HDD、Block group)
  • 前端基础的讲解-JS(9)
  • 使用 PageHelper 在 Spring Boot 项目中实现分页查询
  • PostgreSQL INITDB 初始化失败问题
  • 【activiti工作流源码集成】springboot+activiti+mysql+vue+redis工作流审批流集成整合业务绑定表单流程图会签驳回
  • Golang | Leetcode Golang题解之第551题学生出勤记录I
  • 二维数组转一维数组提升效率方法
  • 网络安全技术及其在企业中的应用
  • CDMA(Code Division Multiple Access)
  • 数据分析主要干什么
  • IoTDB 与 HBase 对比详解:架构、功能与性能
  • 二叉树方面的题
  • 读数据工程之道:设计和构建健壮的数据系统32序列化和云网络
  • 一个灵活且功能强大的动画库 Popmotion
  • Redis集群模式之Redis Sentinel vs. Redis Cluster
  • java基础:反射