架构设计内容分享(一百三十六):Spring AI 项目简介

这篇具有很好参考价值的文章主要介绍了架构设计内容分享(一百三十六):Spring AI 项目简介。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、概览

2、Spring AI 的主要概念

2.1、高级的 Prompt 和 AiResponse

3、Spring AI 入门

4、Spring AI 实践

4.1、在 Spring Boot 中注入 AiClient

4.2、使用 PromptTemplate 配置查询

5、Error 处理

6、总结


1、概览

Spring 通过 Spring AI 项目正式启用了 AI(人工智能)生成提示功能。本文将带你了解如何在 Spring Boot 应用中集成生成式 AI,以及 Spring AI 如何与模型互动。

2、Spring AI 的主要概念

首先回顾一下一些关键的领域术语和概念。

Spring AI 最初专注于处理语言输入和生成语言输出的模型。该项目的理念是为开发人员提供一个抽象接口,为将生成式 AI 作为独立组件纳入应用奠定基础。

接口 AiClient 就是这样一个抽象,它有两个基本实现:OpenAI 和 Azure OpenAI

public interface AiClient {
    default String generate(String message);
    AiResponse generate(Prompt prompt);
}

AiClient 为生成函数提供了两个选项。简化版生成函数:generate(String message),使用 String 作为输入和输出,可以避免使用 Prompt 和 AiResponse 类的额外复杂性。

2.1、高级的 Prompt 和 AiResponse

在 AI 领域,Prompt(提示)是指提供给 AI 的文本信息。它由上下文和问题组成,该模型用于生成答案。从 Spring AI 项目的角度来看,Prompt 是一个参数化 Message 列表。

public class Prompt {
    private final List<Message> messages;
    // 构造函数和其他方法
}

public interface Message {
    String getContent();
    Map<String, Object> getProperties();
    MessageType getMessageType();
}

Prompt 使开发人员能够对文本输入进行更多控制。Prompt 模板就是一个很好的例子,它使用预定义文本和占位符集构建。然后,可以使用传递给 Message 构造函数的 Map<String, Object> 值填充它们。

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

Message 接口还包含有关 AI 模型可处理的消息(Message)类别的高级信息。例如,OpenAI 实现区分会话角色,通过 MessageType 进行映射。对于其他模型,它可以反映消息格式或其他一些自定义属性。更多详情,请参阅 官方文档。

public class AiResponse {
    private final List<Generation> generations;
    // Get 和 Set
}

public class Generation {
    private final String text;
    private Map<String, Object> info;
}

AiResponse 由 Generation(生成)对象列表组成,每个对象都包含来自相应 Prompt(提示)的输出。此外,Generation 对象还提供 AI 响应的元数据信息。

不过,由于 Spring AI 项目仍处于测试阶段,并非所有功能都已完成并文档化。请关注 GitHub repository 中的 issues 进展。

github.com/spring-projects/spring-ai

3、Spring AI 入门

首先,AiClient 与 OpenAI 平台的所有通信都需要 API Key。为此,可以在 Openai 的“API Keys” 页面上创建一个 Token。

Spring AI 项目定义了配置属性:spring.ai.openai.api-key

可以在 application.yml 文件中进行设置。

spring:
  ai:
    openai.api-key: ${OPEN_AI_KEY}

下一步是配置依赖。Spring AI 项目在 Spring 里程碑库(Spring Milestone Repository)中提供了组件。

因此,需要添加 repository 定义:

<repositories>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/snapshot</url>
        <releases>
            <enabled>false</enabled>
        </releases>
    </repository>
</repositories>

之后,就可以导入 open-ai-spring-boot-starter:

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

Spring AI 项目正在积极发展,你可以查看 官方 GitHub 页面 了解最新版本。

4、Spring AI 实践

现在,编写一个简单的 REST API 用于演示。它由两个端点组成,可以返回想要的任何主题和流派的诗歌:

  • /ai/cathaiku:实现基本的 generate() 方法,并返回一个关于猫的的俳句(简单的字符串)。

  • /ai/poetry?theme={{theme}}&genre={{genre}}:演示 PromtTemplate 和 AiResponse 类的功能。

4.1、在 Spring Boot 中注入 AiClient

为了简单起见,从 cathaiku 端点开始。通过 @RestController 注解,设置 PoetryController 并添加 GET 方法映射:

@RestController
@RequestMapping("ai")
public class PoetryController {
    private final PoetryService poetryService;

    // 构造函数

    @GetMapping("/cathaiku")
    public ResponseEntity<String> generateHaiku(){
        return ResponseEntity.ok(poetryService.getCatHaiku());
    }
}

接下来,按照 DDD 概念,Service 层将定义所有 domain 逻辑。要调用 generate() 方法,只需将 AiClient 注入到 PoetryService 中。现在,可以定义字符串 Prompt,并在其中指定生成俳句的请求。

@Service
public class PoetryServiceImpl implements PoetryService {
    public static final String WRITE_ME_HAIKU_ABOUT_CAT = """
        Write me Haiku about cat,
        haiku should start with the word cat obligatory""";

    private final AiClient aiClient;

    // 构造函数

    @Override
    public String getCatHaiku() {
        return aiClient.generate(WRITE_ME_HAIKU_ABOUT_CAT);
    }
}

启动端点,处理请求。响应包含一个简单的字符串:

Cat prowls in the night,
Whiskers twitch with keen delight,
Silent hunter's might.

目前看来效果不错,但目前的解决方案存在一些缺陷。首先,纯字符串响应并不是 REST 标准的最佳解决方案。

用固定的 Prompt 来查询 ChatGPT 并没有太大的价值。因此,下一步是添加参数值:theme 和 genre。这就是 PromptTemplate 的用武之地。

4.2、使用 PromptTemplate 配置查询

就其本质而言,PromptTemplate 的工作方式与 StringBuilder 和 dictionary 的组合非常相似。

与 /cathaiku 端点类似,首先定义 Prompt 的基本字符串,然后再定义用实际值填充的占位符名称:

String promptString = """
    Write me {genre} poetry about {theme}
    """;
PromptTemplate promptTemplate = new PromptTemplate(promptString);
promptTemplate.add("genre", genre);
promptTemplate.add("theme", theme);

接下来,对端点的输出进行标准化。为此,引入简单的 Record 类 - PoetryDto,其中将包含诗歌标题(title)、名称(poetry)和流派(theme):

public record PoetryDto (String title, String poetry, String genre, String theme){}

下一步是在 BeanOutputParser 类中注册 PoetryDto;它提供了序列化和反序列化 OpenAI API 输出的功能。

然后,把该解析器(Parser)提供给 promtTemple,现在,消息(Message)将被序列化为 DTO 对象。

最后,生成函数如下:

@Override
public PoetryDto getPoetryByGenreAndTheme(String genre, String theme) {
    BeanOutputParser<PoetryDto> poetryDtoBeanOutputParser = new BeanOutputParser<>(PoetryDto.class);

    String promptString = """
        Write me {genre} poetry about {theme}
        {format}
    """;

    PromptTemplate promptTemplate = new PromptTemplate(promptString);
    promptTemplate.add("genre", genre);
    promptTemplate.add("theme", theme);
    promptTemplate.add("format", poetryDtoBeanOutputParser.getFormat());
    promptTemplate.setOutputParser(poetryDtoBeanOutputParser);

    AiResponse response = aiClient.generate(promptTemplate.create());

    return poetryDtoBeanOutputParser.parse(response.getGeneration().getText());
}

现在,客户收到的响应看起来要好得多,更重要的是,它符合 REST API 标准和最佳实践:

{
    "title": "Dancing Flames",
    "poetry": "In the depths of night, flames dance with grace,
       Their golden tongues lick the air with fiery embrace.
       A symphony of warmth, a mesmerizing sight,
       In their flickering glow, shadows take flight.
       Oh, flames so vibrant, so full of life,
       Burning with passion, banishing all strife.
       They consume with ardor, yet do not destroy,
       A paradox of power, a delicate ploy.
       They whisper secrets, untold and untamed,
       Their radiant hues, a kaleidoscope unnamed.
       In their gentle crackling, stories unfold,
       Of ancient tales and legends untold.
       Flames ignite the heart, awakening desire,
       They fuel the soul, setting it on fire.
       With every flicker, they kindle a spark,
       Guiding us through the darkness, lighting up the dark.
       So let us gather 'round, bask in their warm embrace,
       For in the realm of flames, magic finds its place.
       In their ethereal dance, we find solace and release,
       And in their eternal glow, our spirits find peace.",
    "genre": "Liric",
    "theme": "Flames"
}

5、Error 处理

Spring AI 项目通过 OpenAiHttpException 类提供了 OpenAPI Error 的抽象。遗憾的是,它没有为每种 Error 类型提供单独的类映射。不过,得益于这种抽象,我们可以在一个 Handler 中使用 RestControllerAdvice 处理所有异常。

下面的代码使用了 Spring 6 的 ProblemDetail 标准。如果你还不熟悉该标准,请查阅 中文文档(springdoc.cn)。

@RestControllerAdvice
public class ExceptionTranslator extends ResponseEntityExceptionHandler {
    public static final String OPEN_AI_CLIENT_RAISED_EXCEPTION = "Open AI client raised exception";

    @ExceptionHandler(OpenAiHttpException.class)
    ProblemDetail handleOpenAiHttpException(OpenAiHttpException ex) {
        HttpStatus status = Optional
          .ofNullable(HttpStatus.resolve(ex.statusCode))
          .orElse(HttpStatus.BAD_REQUEST);
        ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(status, ex.getMessage());
        problemDetail.setTitle(OPEN_AI_CLIENT_RAISED_EXCEPTION);
        return problemDetail;
    }
}

现在,如果 OpenAPI 响应包含错误,该 Advice 就会进行处理。下面是一个响应示例:

{
    "type": "about:blank",
    "title": "Open AI client raised exception",
    "status": 401,
    "detail": "Incorrect API key provided: sk-XG6GW***************************************wlmi. 
       You can find your API key at https://platform.openai.com/account/api-keys.",
    "instance": "/ai/cathaiku"
}

可能出现的异常状态的完整列表请参见 官方文档页面。

6、总结

本文介绍了 Spring AI 项目及其在 REST API 方面的功能,它为生成式 AI 集成到 Spring Boot 应用中提供了一个可靠的接口。在撰写本文时,spring-ai-starter 仍在积极开发中(可以访问快照版本)。

本文介绍了与 Spring AI 的基本集成和高级集成,包括 AiClient 的底层原理,还通过实际案例介绍了 Spring AI 高级功能的示例:PromtTemplateAiResponse 和 BeanOutputParser 以及异常处理。文章来源地址https://www.toymoban.com/news/detail-835934.html

到了这里,关于架构设计内容分享(一百三十六):Spring AI 项目简介的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • C++之C++11 thread线程示例(一百三十八)

    简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏: Audio工程师进阶系列 【 原创干货持续更新中…… 】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:An

    2023年04月15日
    浏览(45)
  • 一百三十七、Hive——HQL运行报错(持续更新中)

    样例:from_unixtime(unix_timestamp(change_time, \\\'yyyy-MM-dd HH:mm:ss\\\') + green) AS new_timestamp  成功!!! 在DWS层中,对多层SQL使用with语句嵌套查询,然后insert插入数据。如果直接把insert放在with语句上面,那么就会如下报错 org.apache.hadoop.hive.ql.parse.ParseException:line 2:0 cannot recognize input near \\\'w

    2024年02月15日
    浏览(40)
  • PCL点云处理之pcd文件的读写(详细注释版)(一百三十三)

    `处理点云数据的第一步总是把点云从不同格式的文件读取到自己的程序里, 存储点云信息的文件包括但不限于pcd,las,ply,txt等等,由于我们用的是PCL库进行点云处理,所以最适合的还是pcd格式的点云文件,所以有必要学习如何从pcd文件中读取点云的信息:如坐标等,以及如何

    2023年04月18日
    浏览(64)
  • C/C++基础讲解(一百三十一)之经典篇(信息合并/平均分数存储)

    很多时候,特别是刚步入大学的学子们,对于刚刚开展的计算机课程基本上是一团迷雾,想要弄明白其中的奥秘,真的要花费一些功夫,我和大家一样都是这么啃过来的,从不知到知知,懵懂到入门,每一步都走的很艰辛,课程上,大学老师基本上讲解上机实操得时间特别有

    2024年02月07日
    浏览(42)
  • Linux图形管理框架gdm3、lightdm、sddm、kdm介绍(一百三十七)

    1.Gnome系列图形管理器:gdm、gdm3 Ubuntu默认界面管理器:gdm3 2.KDE系列图形管理器:KDM,SDDM LUbuntu默认界面管理器:sddm 3.Canonical公司系列图形管理器:Lightdm XUbuntu默认界面管理器:lightdm 查看当前使用的显示管理器 

    2024年02月12日
    浏览(35)
  • 一百三十三、Hive——Hive外部表加载含有JSON格式字段的CSV文件数据

    在Hive的ODS层建外部表,然后加载HDFS中的CSV文件数据 注意 :CSV文件中含有未解析的JSON格式的字段数据,并且JSON字段中还有逗号 JSON数据的字段track_data只显示一部分数据,因为JSON格式数据里面也含有逗号 [{\\\"id\\\":\\\"14\\\",\\\"length\\\":5.0,\\\"height\\\":3.0,\\\"posX\\\":63.0,\\\"posY\\\":37.0,\\\"acs\\\":99.0,\\\"angle\\\":83.0,\\\"alti

    2024年02月16日
    浏览(45)
  • 架构设计内容分享(二百一十):设计一个大并发、大数据的系统架构,说说设计思路

    目录 大并发/大数据的软件有如下特点 大并发/大数据的架构目标有如下几个 大并发/大数据的设计思路与原则 大并发/大数据的分层架构 1 接入层的架构方案: 第二三层:应用层/服务层架构方案 第四层:数据层架构方案 第五层:基础设施层架构 高并发核武器:单元化+异地

    2024年02月21日
    浏览(47)
  • 架构设计内容分享(四十一):100万级连接,爱奇艺WebSocket网关如何架构

    目录 100W级连接,爱奇艺WebSocket推送网关架构 1、旧方案存在的技术痛点 2、新方案的技术目标 3、新方案的技术选型 4、新方案的实现思路 4.1 系统架构 4.2 会话管理 4.3 监控与报警 5、新方案的性能压测 6、新方案的实际应用案例 7、总结 HTTP 协议属于一种无状态、基于 TCP 的请

    2024年01月23日
    浏览(47)
  • 架构设计内容分享(二百零一):什么是数据仓库的架构?企业数据仓库架构如何建设?

    目录 企业数据仓库架构 单层架构(直连) 两层数据架构(数据集市层) 三层架构(OLAP) 数据仓库数据库 1、采用传统关系型数据库,或经过功能扩展的MPP数据库 2、大数据平台架构:Hadoop+Hive 采集、收集、清洗和转换工具(ETL) 1、抽取 2、清洗 3、转化和加载 前端应用工具

    2024年02月21日
    浏览(45)
  • AIGC内容分享(三十四):AIGC+信息流广告

    目录 AIGC发展概览  AIGC发展的重要里程碑事件 媒体平台AIGC功能  媒体平台AIGC功能-广点通 媒体平台AIGC功能  AIGC在广告各场景应用  AIGC在广告各场景应用—文生文 AIGC在广告各场景应用—文生图 视频生成 AIGC在广告各场景应用——AI投手  展望   问答  AIGC,即 AI文本生成

    2024年01月17日
    浏览(48)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包