先行一步
VMware 提供培训和认证,助您加速前行。
了解更多作为一名探索生成式 AI 世界的 Java 开发者,您可能已经了解了一些承诺使 AI 集成变得容易的框架。我相信 Spring AI 是一个自然的绝佳选择,特别是对于已经在 Spring 生态系统内工作的开发者。Spring AI 基于与 Spring Boot 和 Spring Data 相同的构建基础,使得为您的应用添加 AI 能力变得无缝且直观,而无需您学习一套全新的范例。
Spring AI 最显著的优势之一是它与 Spring 生态系统的深度集成。如果您已经熟悉开发 Spring Boot 应用,那么 Spring AI 会让您感觉它只是现有知识的延伸。驱动 Spring Data 的相同概念——例如依赖注入、注解和清晰的抽象——同样适用于 Spring AI。这种一致性意味着您可以轻松进入 AI 领域,而无需重新思考如何开发应用。
与某些工具不同,Spring AI 入门无需复杂的配置或工作流设置。它能与您现有的代码库完美契合,允许您重用现有的 bean、服务和仓库。Spring AI 不是将外部 AI 平台附加进来,而是直接与您已构建的业务逻辑和企业服务集成,充分利用您在 Spring 生态系统中的投资。
Spring AI 专注于简化企业级应用的 AI 操作。它非常适合需要向业务应用中添加简单 AI 功能(如文本生成、嵌入和函数调用)的开发者。Spring AI 的魅力在于其简洁性:您可以在不增加管理复杂工作流或编排多步骤流程开销的情况下获得生成式 AI 的强大能力。对于大多数企业用例而言,AI 的作用是增强现有功能而非驱动整个工作流,Spring AI 正好提供了所需的一切。
Spring AI 的另一个关键优势是其与向量存储的集成。无论您是使用带 pgVector 的 Postgres、Redis,还是任何其他受支持的支持向量的数据库,Spring AI 都扩展了 Spring 众所周知的能力,以处理向量嵌入和其他 AI 驱动的数据存储需求。
Spring AI 使得在不同向量存储实现之间切换变得异常容易。使用 Spring 开发者熟悉的相同依赖注入模式,您只需更改 Spring Boot Starter 依赖项,而无需触动核心应用逻辑,即可替换一个向量存储。对于构建需要可扩展、高效存储和检索嵌入或其他 AI 生成数据的 AI 增强应用,这种灵活性是一个显著的优势。
将源数据嵌入向量存储是一个强大的功能,但在嵌入之前如何处理不同的数据结构呢?借助 Spring AI,您可以使用现成的文档读取器来处理各种格式,包括 PDF、Markdown、Microsoft Word 和 PowerPoint 文档、HTML 等等。文档读取器功能确保您可以处理各种源格式。如果某个特定格式不受支持,创建您自己的实现也非常简单。
Spring AI 的一个突出特点是支持对嵌入进行元数据过滤,这与底层向量存储实现无关。在典型的 RAG(检索增强生成)应用中,会在向量存储上执行相似度搜索,计算查询与数据集中每个数据点之间的距离度量(例如,余弦相似度)。虽然这种方法对于较小的数据集来说尚可管理,但随着数据量的增长,其挑战也越来越大。为了解决这个问题,向量存储实现了各种性能增强算法,例如近似最近邻(ANN)、局部敏感哈希(LSH)或分层可导航小世界(HNSW)。
为了进一步应对这一挑战,另一种有效的策略是首先在执行相似度搜索之前减少要查询的数据量。例如,如果您只对位于波士顿的客户感兴趣,则可以将数据集过滤到仅包含居住在此地的客户。这种缩减过程称为元数据过滤。
许多向量存储都提供了自己的元数据过滤实现,各有优缺点。然而,Spring AI 提供了一个供应商中立的解决方案,弥合了各种向量存储之间的差距。这种能力在企业应用中尤为宝贵,在这些应用中,仅靠语义可能不足够,并且必须从相似度搜索中排除某些个人身份信息(PII)数据。通过利用元数据过滤,可以在相关的文档子集上执行相似度搜索,而不是扫描整个数据集。
以下是一个简单的示例,更详细的信息可在Spring AI 参考文档中找到
public void example() {
// Assume we have a large dataset of customers.
// Embedding the data is computationally expensive
// but it is typically a one-time / ETL process
List<Document> allMyCustomers = new ArrayList<>();
allMyCustomers.add(new Document("""
{
"customerId": 12345,
"name": "John Doe",
"email": "[email protected]",
"phone": "+1234567890",
"address": "123 Main St, Boston, MA"
}
""", Map.of("city", "Boston"))); // Metadata filter!
// Add more customers...
allMyCustomers.add(...);
// Add all embedded documents and their
// associated metadata to the vector store
vectorStore.add(allMyCustomers);
// Prepare a search query, for example:
// "Which customers are named John?"
SearchRequest searchRequest =
SearchRequest.query("Which customers are named John?");
// This similarity search is computationally intensive
List<Document> results = vectorStore.similaritySearch(
searchRequest.withTopK(5)
.withSimilarityThresholdAll());
// Instead, we'll first filter by city to reduce the dataset size,
// then perform the similarity search on the filtered results
results = vectorStore.similaritySearch(
searchRequest.withTopK(5)
.withSimilarityThresholdAll()
.withFilterExpression("city == 'Boston'"));
}
Spring AI 的一个突出功能是其函数调用能力,通过解决其最大的挑战:与您自己的 API 集成!,这简化了企业应用中的 AI 交互。
我最近读到 Jonathan Schneider 在 LinkedIn 上的一篇文章,它引起了我的注意。他写道,函数调用之于检索增强生成 (RAG),就像 IoC 之于 Java 开发一样。IoC 使开发者能够专注于业务逻辑,而 Spring 则负责对象创建和依赖注入。类似地,Spring AI 中的函数调用使开发者能够专注于他们的函数做什么,而大型语言模型 (LLM) 则负责处理幕后的复杂交互。
您用自然语言描述您的函数做什么,Spring AI 会确保 LLM 在需要时理解并执行它。这极大地减少了与 AI 模型交互通常所需的样板代码量,让您可以专注于构建功能,而不是管理复杂的 AI 流程。
以下是来自Spring AI 参考文档的一个简单示例
@Configuration
static class Config {
@Bean
@Description("Get the current weather in location")
public Function<WeatherService.Request, WeatherService.Response> currentWeather() {
return new MockWeatherService();
}
}
public class WeatherService implements Function<Request, Response> {
public enum Unit { C, F }
public record Request(String location, Unit unit) {}
public record Response(double temp, Unit unit) {}
public Response apply(Request request) {
// Logic goes here!
}
}
目前没有 AI 模型能够提供特定地点的实时天气数据。因此,LLM 可能会回复说它不知道答案——或者更糟,它可能会返回一个幻觉响应。
然而,通过注册如上所示的函数,Spring AI 允许 LLM 从 @Description
注解中推断出此函数可以提供实时天气数据。然后,LLM 可以根据用户输入,以正确的格式为 WeatherService.Request
构建请求。例如,如果用户询问“波士顿的天气怎么样?”,LLM 将自动用位置和单位填充 Request
对象,请求 Spring AI 调用该函数,从 WeatherService
中检索实际的天气数据,然后根据该数据为用户格式化一个人类可读的响应。
以下是调用流程的分步分解
虽然向量存储通过将您的数据嵌入 LLM 可以理解的格式来预处理数据,但函数调用使 LLM 能够与您现有的事务性 API 进行实时交互,从而使其能够在需要时生成有意义的响应。
Spring AI 引入了 Advisors,这是一种强大的机制,用于处理 AI 应用中的横切关注点。如果您熟悉 面向切面编程 (AOP) 拦截器或 Spring MVC 拦截器,其概念是相似的。然而,考虑到并非所有开发者都熟悉这些术语,Spring AI 团队选择了使用“Advisor”一词来强调其目的——增强请求/响应提示流——而不是其操作的技术细节,后者涉及拦截请求/响应并应用过滤器。Advisors 简化了对诸如日志记录、消息转换和聊天记忆管理等任务的管理,同时保持您的应用代码干净整洁。
通过将这些例行任务分流,Advisors 确保您的应用专注于业务逻辑,而必要的 AI 相关操作则在后台无缝运行。这种方法在有效解决必要的运营问题的同时,保持了代码库的清晰度。
以下是一个简单示例
this.chatClient = builder
.defaultAdvisors(
new MessageChatMemoryAdvisor(chatMemory),
new SimpleLoggerAdvisor())
.build();
这个聊天客户端集成了两个 Advisor:一个记忆 Advisor,它将先前的用户提示附加到当前消息中以提供上下文和连贯性;以及一个日志记录 Advisor,它捕获与 LLM 的请求和响应,并将其输出到应用日志中,以便有效进行故障排除。
使用生成式 AI 模型时经常出现的一个挑战是每个模型都有自己的一套怪癖。例如,要求大型语言模型提供结构化响应(例如 JSON)并非看起来那么简单。LLM 经过训练生成对话文本,它们通常喜欢以更像人类的方式“聊天”。这可能导致不可预测或过于冗长的输出,这在您期望机器可读格式时并不理想。
Spring AI 为您抽象了这些细微之处。它通过根据所使用的特定 LLM 添加适当的用户提示或指令来自动处理这些差异。因此,无论您使用的是 OpenAI 的 GPT4-o、Anthropic 的 Claude,还是不同的 LLM,Spring AI 都确保您收到的响应是所需结构。这种能力消除了开发者进行反复试验的提示工程的需要,让您可以专注于利用 AI,而不是费力应对其怪癖。
以下是 Spring AI 的 BeanOutputConverter
实现的一个示例,旨在从 LLM 以 JSON 格式检索响应,并遵循给定数据类的模式。请注意,要达到期望的结果,需要向 LLM 提供多么详细和具体的提示
@Override
public String getFormat() {
String template = """
Your response should be in JSON format.
Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.
Do not include markdown code blocks in your response.
Remove the ```json markdown from the output.
Here is the JSON Schema instance your output must adhere to:
```%s```
""";
return String.format(template, this.jsonSchema);
}
Spring AI 替您完成了繁重的工作。
可观测性在任何企业应用中都至关重要,而增强了生成式 AI 的应用也不例外。Spring AI 提供了内置的可观测性功能,使得无缝监控 AI 服务的健康状况和性能成为可能。这包括全面的指标、跟踪和日志记录,以便对您的生成式 AI 应用实现端到端的可见性。这不仅仅是针对聊天模型,而是针对整个堆栈,包括嵌入模型和向量数据库。这项能力再次凸显了 Spring 这种集成解决方案的强大之处,因为可观测性功能由 micrometer 提供支持,就像其他 Spring 项目一样
借助 Spring AI,您可以深入了解关键指标,例如令牌使用率,这对于在使用根据处理的令牌数量收费的模型时管理成本至关重要。此外,您还可以监控向量存储的延迟、错误率,甚至可以跟踪请求如何在您的 AI 增强服务中流动。这种级别的可观测性确保您可以在性能瓶颈或潜在问题影响您的应用之前快速识别它们,就像您习惯于处理其他基于 Spring 的服务一样。
使用 Spring AI 的另一个显著优势是可以在不同的 LLM 提供商之间轻松进行 A/B 测试。为了在成本和响应质量之间取得最佳平衡,能够比较多个模型是无价的。
借助 Spring AI,您只需替换 Spring Boot Starter 依赖项并更改属性文件中的几行代码,即可轻松在各种 LLM 之间切换。这种简单直接的方法让您无需进行大量重新配置或编码开销即可评估不同模型的性能。无论您是在评估准确性、响应时间还是成本效益,Spring AI 都提供了工具来促进这些无缝比较。
通过将 A/B 测试直接集成到您的工作流程中,您可以根据数据驱动的决策来确定哪家 LLM 提供商最适合您的应用需求。这项能力不仅增强了您 AI 实现的整体有效性,而且随着生成式 AI 领域新模型和功能的出现,还允许进行持续优化。
Spring AI 专为 Java 开发者设计,提供一种无缝且高效的方式将 AI 集成到其应用中。它不仅仅是添加 AI 能力,更重要的是以一种自然融入现有系统的方式来实现。将生成式 AI 应用于应用主要是一个集成挑战,而这正是 Spring 框架的优势所在。Spring AI 是 Spring 生态系统的自然延伸,旨在轻松处理企业应用集成的复杂性。
如果您的目标是使用生成模型、函数调用和向量嵌入来增强企业应用,那么 Spring AI 是理想的选择。它与 Spring 生态系统的深度集成,以及广泛的大型语言模型和向量存储选择,使其在 AI 开发中既强大又直接。它非常适合将 AI 集成到现有业务逻辑中,消除了管理多步工作流或链式模型的复杂性。
总而言之,Spring AI 的一些突出优势包括
无缝集成:毫不费力地将 AI 能力嵌入到现有 Spring 应用中。
专为 RAG 构建:简化数据嵌入和运行相似度搜索的过程,同时支持强大的元数据过滤器。
函数调用:实现与事务性 API 的实时交互。
Advisors: 使用内置的 Advisor 处理横切关注点,或在需要时编写您自己的 Advisor。
供应商无关:使用各种向量存储和 LLM 提供商,而无需锁定特定解决方案,从而在数据和模型管理方面提供灵活性。
A/B 测试:轻松进行 A/B 测试以优化 AI 性能。
内置可观测性:访问监控、日志记录和跟踪功能以提高透明度。
选择 Spring AI,您将为您的企业应用注入先进的 AI 能力,推动创新并提升用户体验。