一篇文章搞懂Spring AI,Java程序员玩转大模型

目录

一篇文章搞懂Spring AI,Java程序员玩转大模型

一、Java程序员为什么学习SpringAI?

二、概括 Spring AI 是什么

三、AI 概念介绍

模型

提示

嵌入

Token(代币)

结构化输出

微调

填充提示(检索增强(RAG))

四、实战案例

案例介绍

代码讲解

总结


一、Java程序员为什么学习SpringAI?

现如今,传统IT环境今非昔比,以大模型为首的人工智能浪潮正在席卷越来越多的产业,各种基于大模型的对话问答、文生图、图生图、文生语音等等产品,层出不穷,一个接一个,犹如繁星点点接连闪烁登场。

而这些大模型基本上都是通过Python语言训练出来的,对于类似我这种一直从事Java开发的程序员来说,自然认为Java程序员才是最优美的语言,Python虽然语法简单,但是不够优雅,编写Python代码不如写Java代码得心应手。好在,Spring官方大佬们也紧跟时代潮流,开发出一个可供Java程序员入门使用大模型的框架:SpringAi

本篇文章主要介绍了Java程序员学习SpringAI的一些可能的原因,然后介绍了SpringAI是什么、一些大模型相关概念和一个使用SpringAi搭建本地知识库检索的实战项目,并配备了完整代码。

下面是我通过豆包这个大模型助手总结的Java程序员学习SpringAi的一些原因。

  • 拓展技术能力边界

作为 Java 程序员,掌握 Spring Ai 意味着能够将传统的 Java 开发与先进的人工智能技术相结合,极大地扩展了自身能够解决问题的范围和能力。

例如,能够开发出具有智能客服功能的 Java 应用,为用户提供更智能、高效的服务。

  • 提升职业竞争力
    • 在就业市场上,对具备人工智能知识和技能的 Java 开发者的需求日益增长。
    • 拥有 Spring Ai 的技能,能让您在众多 Java 程序员中脱颖而出,获得更多更好的职业机会。
  • 增强应用功能
    • 可以为现有的 Java 应用程序添加智能特性,如智能推荐、智能搜索等。
    • 比如在电商平台中,基于用户的行为和偏好,利用 Spring Ai 实现精准的商品推荐。
  • 紧跟技术趋势
    • 技术领域不断发展,人工智能是当前的热门趋势。
    • 学习 Spring Ai 有助于 Java 程序员保持对新技术的敏锐感知,不被技术发展所淘汰。
  • 提高开发效率
    • Spring Ai 提供了一系列的工具和框架,能够简化人工智能功能的集成和开发过程。
    • 相比自行从零开始实现人工智能功能,使用 Spring Ai 可以节省大量的时间和精力。
  • 参与创新项目
    • 许多创新的项目都涉及到人工智能与传统技术的融合。
    • 掌握 Spring Ai 为参与这类前沿、创新性的项目打开了大门。

二、概括 Spring AI 是什么

简单概括就是一个在在Java程序中集成大模型的框架。

下面是Spring AI 官方的介绍:

该项目从著名的 Python 项目(例如 LangChain 和 LlamaIndex)中汲取灵感,但 Spring AI 并非这些项目的直接移植。该项目的成立基于这样的信念:下一波生成式 AI 应用将不仅面向 Python 开发人员,还将遍及多种编程语言。

从本质上讲,Spring AI 解决了 AI 集成的基本挑战:将您企业的数据和 API 与人工智能模型相连接。

Spring AI 提供了抽象概念,作为开发 AI 应用程序的基础。这些抽象概念具有多种实现,只需进行少量代码更改即可轻松更换组件。

Spring AI 提供以下功能:

支持所有主要模型提供商,例如 OpenAI、Microsoft、Amazon、Google 和 Hugging Face。

支持的模型类型包括聊天、文本到图像、音频转录、文本到语音等。

适用于所有模型的跨 AI 提供商的可移植 API。支持同步流式 API 选项。还支持下拉以访问特定于模型的功能。

将 AI 模型输出映射到 POJO。

支持所有主要的矢量数据库提供商,例如 Apache Cassandra、Azure Vector Search、Chroma、Milvus、MongoDB Atlas、Neo4j、Oracle、PostgreSQL/PGVector、PineCone、Qdrant、Redis 和 Weaviate。

跨 Vector Store 提供商的可移植 API,包括一种新颖的类似 SQL 的元数据过滤器 API,它也是可移植的。

函数调用。

用于 AI 模型和向量存储的 Spring Boot 自动配置和启动器。

数据工程的 ETL 框架

三、AI 概念介绍

模型

AI 模型是用于处理和生成信息的算法,通常模仿人类的认知功能。通过从大型数据集中学习模式和见解,这些模型可以做出预测、文本、图像或其他输出,从而增强各行各业的各种应用。

提示

提示是指导 AI 模型产生特定输出的语言输入基础,对熟悉 ChatGPT 的人来说它不只是简单文本。ChatGPT 的 API 中一个提示有多个带角色的文本输入,如系统角色和用户角色。制作有效提示既是艺术也是科学,需像与人交流一样与模型互动。

提示模板

创建有效提示需建立请求上下文并用特定值替换部分,此过程利用传统文本模板引擎,Spring AI 使用 OSS 库 StringTemplate,例如简单提示模板:

Tell me a {adjective} joke about {content}.

在 Spring AI 中提示模板可比作 Spring MVC 架构中的“视图”,用模型对象填充占位符。

嵌入

嵌入是把文本、图像、视频转为向量的数字表示,以捕捉输入间关系。其通过将内容转为含其含义的向量,计算文本向量距离确定相似性。在实际应用中,如检索增强生成模式,它能将数据在语义空间中表示为点,反映含义相似性,有助于多种任务。对 Java 开发人员,了解其作用和功能基本知识即可。嵌入具体能用于搜索、聚类、推荐、异常检测、多样性测量、分类等。

Token(代币)

Token 是 AI 模型工作的基石,输入时模型将单词转换为token,输出时转换回单词。在英语中,一个Token约对应一个单词的 75%,如莎士比亚全集约 90 万个单词对应 120 万个标记。Token在托管 AI 模型中意味着费用由使用的Token数量决定,输入和输出都影响总量,且模型有 token 限制即“上下文窗口”限制处理的文本量,不同模型的代币限制不同,如 ChatGPT3 为 4K,GPT4 有多种选项,Anthropic 的 Claude AI 模型为 100K,Meta 有 1M Token限制模型。

结构化输出

即使您要求回复为 JSON ,AI 模型的输出通常也会以 的形式出现java.lang.String。它可能是正确的 JSON,但它不是 JSON 数据结构。它只是一个字符串。此外,在提示中要求“输入 JSON”并非 100% 准确。

这种复杂性导致了一个专门领域的出现,涉及创建提示以产生预期的输出,然后将生成的简单字符串转换为可用于应用程序集成的数据结构。

微调

这种传统的机器学习技术涉及定制模型并更改其内部权重。然而,对于机器学习专家来说,这是一个具有挑战性的过程,而且由于 GPT 等模型的大小,它极其耗费资源。此外,有些模型可能不提供此选项。

填充提示(检索增强(RAG))

一种更实用的替代方案是将您的数据嵌入到提供给模型的提示中。考虑到模型的令牌限制,需要使用技术在模型的上下文窗口中显示相关数据。这种方法俗称“填充提示”。Spring AI 库可帮助您基于“填充提示”技术(也称为检索增强生成 (RAG))实现解决方案。

四、实战案例

案例介绍

有了上述的基本知识之后,我们就可以通过SpringAi 结合 Ollama、Elasticsearch 编写一个法律智能问答方面的RAG 检索增强实战案例,通过这个案例,除了可以学习SpringAi,还可以了解RAG相关的技术。

该项目完整代码github地址:https://github.com/maniu2024/chat-bot-rag

这个项目还实现了 网络检索、RAG的混合检索、还实现了对话记忆、多伦对话的功能。

注:Ollama 是一个可以很方便下载、运行、部署大模型的一个工具,有点类似Docker。

代码讲解

下面通过这个实战项目的代码讲解SpringAi的相关用法。

pom.xml 中 包括Ollam和Springboot整合的Maven依赖、ElasticSearch整合SpringBoot的依赖等等。

        <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>

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

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

需要注意的是,需要配置SpringAI的仓库才能下载SpringAi的依赖。

<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>

然后在application.yml中配置对话模型和嵌入模型:

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          temperature: 0.8
          model: qwen2
          repeat-penalty: 1.2
      embedding:
        model: mofanke/acge_text_embedding

这里的对话模型是阿里的 qwen2,嵌入模型是acge_text_embedding,因为使用的是ollama,所以要下载Ollama,

下载地址:https://ollama.com/download ,下载完之后,在命令行运行命令:

ollama run qwen2

ollama pull mofanke/acge_text_embedding

第一条命令会下载并运行 qwen2 7B的模型,命令执行完后会开默认开启11434端口,spring ai 的客户端便可以发送Http请求给这个端口,从而执行文本问答工作。

第二条命令拉取mofanke/acge_text_embedding这个模型,命令执行完就可以了,嵌入模型拉取完毕就行了。

在ChatServiceImpl的chat方法中如下代码实现了模型客户端发出对话的Http请求,并得到模型响应。

ChatClient chatClient = ChatClient.builder(chatModel)
        .defaultAdvisors(new PromptChatMemoryAdvisor(chatMemory),new SimpleLoggerAdvisor())
        .build();
String content = chatClient.prompt()
        .user(userPromptStr)
        .system(systemPrompt)
        .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, userSendMessage.getUserId()).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, chatMemorySize))
        .call()
        .content();

简单介绍下ChatClient和ChatModel的区别,ChatClient代表的通用的模型客户端,ChatModel代表的是具体的某个类型的模型客户端,比如OllamaChatModel 就是用于和Ollama运行的模型进行交互的客户端。

下面的代码就是使用EmbeddingModel对用户输入文本计算其向量,并封装为一个嵌入结果中。

public EmbeddingResult embedding(String text) {
    List<Double> doubles = this.embeddingModel.embed(text);
    EmbeddingResult embeddingResult = new EmbeddingResult();
    embeddingResult.setText(text);
    embeddingResult.setEmbedding(doubles);
    return embeddingResult;
}

整个对话的流程如下:

  • 首先通过嵌入模型,这里配置的是mofanke/acge_text_embedding 模型,对用户输入文本计算向量。
  • 拿着个文本向量到Elasticsearch中通过相似度算法查询最相似的几个文档,这里的混合检索也使用了关键词检索,当向量检索的结果不为空时,才会用到关键词检索的结果,主要是在重新排序阶段能重新计算检索到文档的分值,以向量检索的结果分值基础,然后加上关键词检索的分值的开根号。
  • 然后将这些检索结果放入到模型的提示词中,这样,模型接受的内容就是用户的输入文本和检索结果,模型根据这些内容进行回复,这样能让模型能使用这些新的文档知识进行回复,这样回复更加准确,大大减少了模型幻觉。

当然,Elasticsearch中的文档需要进行切分成块,然后存入到ES中。可见LawDocHelper中的代码简单实现了对目录中的文档进行索引的处理,这个项目是对法律法条文档进行处理的,将每一篇法律文本按照章节中的法条进行切分,然后存入到ES中。

还有,RAG仍然不是完美,还是有不少问题,比如非常依赖检索检索结果,如果检索的结果不准或没有相关的内容,那么还是有可能回答错误。还比如,是否使用检索系统来增强查询依然是个问题,也许可以通过训练一个模型来判断用户的查询是否需要使用检索系统。这里主要还是学习SpringAi的技术,就不展开了。

总结

Spring都开始制作AI大模型应用相关的框架了,不得不说这次AI浪潮可能真的还不错,至于未来人工智能 大模型究竟能发展成什么样子,我想谁也不清楚,不过还是很期待。至于现在很多人担心的人工智能可能会让很多人失业,比如前段时间武汉的萝卜快跑,引发了人们的热议,什么互联网巨头居然和地层老百姓钱抢饭碗,我想百度虽然没品,但是花这么大的代价就是为了抢出租车师傅的饭碗,那还不至于!

那如果国家都大力发展无人化,那么多劳动力怎么办? 我觉得人工智能的发展一定是以造福人类为前提的,不然,聪明的人类一定会抵制 人工智能发展的。比如这个萝卜快跑,普通司机是不是可以租萝卜快跑的车进行赚钱呢?以前是需要司机坐在车里开,不仅累人,效率还差,如果一个司机可以租多辆无人汽车,那么是不是在家就可以赚取更多的钱呢?

所以,我觉得技术本身没有错误,关键是如何利用技术切入应用场景中,切入的不好,比如和普通人抢饭碗,老百姓不骂人才怪呢。

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马丁的代码日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值