Java生态圈的Langchain来了,Spring AI上架Spring Initializr(内有上手视频)

技术

一直以来,LLM应用都以python语言为主,虽然微软也提供了Semantic Kernel的java版本,但也一直不温不火。然而情况发生了转机,作为java生态圈拥有最大用户数的Spring框架终于达成阶段性里程碑,Spring AI在二月最后一天悄悄登陆Spring Initializr,这也标志着Spring AI走过了实验阶段,进入了推广落地阶段。

picture.image

Spring AI 的目标是为应用程序融入AI功能提供一个简洁的开发途径,摒弃不必要的复杂操作。该项目吸取了一些知名 Python 项目的精髓,如 LangChain 和 LlamaIndex,但并非单纯地将它们照搬过来。Spring AI 是基于这样一个理念创立的:未来的生成式AI应用将不仅限于 Python 开发者,而且会普及到多种编程语言中。Spring AI 的核心是提供了开发 AI 应用所需的基本抽象模型,这些抽象拥有多种实现方式,使得开发者可以用很少的代码改动就能实现组件的轻松替换。

picture.image

主要特性:

  • 对所有主流 AI 模型供应商如 OpenAI、Microsoft、Amazon、Google 和 Huggingface 的支持。

  • 支持的 AI 模型类型包括聊天和文本到图像转换,未来将加入更多类型。- 固定的 API 设计简化了跨不同 AI 模型供应商之间的聊天与聚合模型(embedding models)的应用,支持同步和流式 API。也可以方便地使用特定模型的高级特性。

  • 把 AI 模型输出映射到简单的 Java 对象(POJOs)上。

  • 支持所有主要的类似向量的数据库供应商,如 Azure Vector Search、Chroma、Milvus、Neo4j 、PostgreSQL/PGVector、PineCone、Redis 和 Weaviate。

  • 提供了一种新的类 SQL 元数据筛选 API,可在不同的向量存储提供商之间进行移植使用。

  • 拥有函数调用(function calling)功能。

  • 支持 Spring Boot 自动配置和快速启动,便于运行 AI 模型和管理向量库。

  • 为数据工程提供 ETL(数据抽取、转换和加载)框架。

当前,spring AI最新版本为0.8.0,具体使用也比较简单,符合java开发者的开发习惯,下面是两个例子(文章后面有学习视频)。

1)简单对话:


          
package org.springframework.ai.openai.samples.helloworld.simple;
          

          
import org.springframework.ai.chat.ChatClient;
          
import org.springframework.beans.factory.annotation.Autowired;
          
import org.springframework.web.bind.annotation.GetMapping;
          
import org.springframework.web.bind.annotation.RequestParam;
          
import org.springframework.web.bind.annotation.RestController;
          

          
import java.util.Map;
          

          
@RestController
          
public class SimpleAiController {
          

          
  private final ChatClient chatClient;
          

          
  @Autowired
          
  public SimpleAiController(ChatClient chatClient) {
          
    this.chatClient = chatClient;
          
  }
          

          
  @GetMapping("/ai/simple")
          
  public Map<String, String> completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
          
    return Map.of("generation", chatClient.call(message));
          
  }
          
}
      

2)RAG:


          
package org.springframework.samples.ai.azure.openai.rag;
          

          
import org.slf4j.Logger;
          
import org.slf4j.LoggerFactory;
          
import org.springframework.ai.client.AiClient;
          
import org.springframework.ai.client.AiResponse;
          
import org.springframework.ai.client.Generation;
          
import org.springframework.ai.document.Document;
          
import org.springframework.ai.embedding.EmbeddingClient;
          
import org.springframework.ai.loader.impl.JsonLoader;
          
import org.springframework.ai.prompt.Prompt;
          
import org.springframework.ai.prompt.SystemPromptTemplate;
          
import org.springframework.ai.prompt.messages.Message;
          
import org.springframework.ai.prompt.messages.UserMessage;
          
import org.springframework.ai.retriever.impl.VectorStoreRetriever;
          
import org.springframework.ai.vectorstore.VectorStore;
          
import org.springframework.ai.vectorstore.impl.InMemoryVectorStore;
          
import org.springframework.beans.factory.annotation.Value;
          
import org.springframework.core.io.Resource;
          

          
import java.util.List;
          
import java.util.Map;
          
import java.util.stream.Collectors;
          

          
public class RagService {
          

          
    private static final Logger logger = LoggerFactory.getLogger(RagService.class);
          

          
    @Value("classpath:/data/bikes.json")
          
    private Resource bikesResource;
          

          
    @Value("classpath:/prompts/system-qa.st")
          
    private Resource systemBikePrompt;
          

          
    private final AiClient aiClient;
          
    private final EmbeddingClient embeddingClient;
          

          
    public RagService(AiClient aiClient, EmbeddingClient embeddingClient) {
          
        this.aiClient = aiClient;
          
        this.embeddingClient = embeddingClient;
          
    }
          

          
    public Generation retrieve(String message) {
          

          
        // Step 1 - Load JSON document as Documents
          

          
        logger.info("Loading JSON as Documents");
          
        JsonLoader jsonLoader = new JsonLoader(bikesResource,
          
                "name", "price", "shortDescription", "description");
          
        List<Document> documents = jsonLoader.load();
          
        logger.info("Loading JSON as Documents");
          

          
        // Step 2 - Create embeddings and save to vector store
          

          
        logger.info("Creating Embeddings...");
          
        VectorStore vectorStore = new InMemoryVectorStore(embeddingClient);
          
        vectorStore.add(documents);
          
        logger.info("Embeddings created.");
          

          
        // Step 3 retrieve related documents to query
          

          
        VectorStoreRetriever vectorStoreRetriever = new VectorStoreRetriever(vectorStore);
          
        logger.info("Retrieving relevant documents");
          
        List<Document> similarDocuments = vectorStoreRetriever.retrieve(message);
          
        logger.info(String.format("Found %s relevant documents.", similarDocuments.size()));
          

          
        // Step 4 Embed documents into SystemMessage with the `system-qa.st` prompt template
          

          
        Message systemMessage = getSystemMessage(similarDocuments);
          
        UserMessage userMessage = new UserMessage(message);
          

          
        // Step 4 - Ask the AI model
          

          
        logger.info("Asking AI model to reply to question.");
          
        Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
          
        logger.info(prompt.toString());
          
        AiResponse response = aiClient.generate(prompt);
          
        logger.info("AI responded.");
          
        logger.info(response.getGeneration().toString());
          
        return response.getGeneration();
          
    }
          

          
    private Message getSystemMessage(List<Document> similarDocuments) {
          

          
        String documents = similarDocuments.stream().map(entry -> entry.getContent()).collect(Collectors.joining("\n"));
          
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemBikePrompt);
          
        Message systemMessage = systemPromptTemplate.createMessage(Map.of("documents", documents));
          
        return systemMessage;
          

          
    }
          
}
      

视频教程(0.7.0版本):

参考:https://docs.spring.io/spring-ai/reference/index.html

欢迎点赞加关注,并可

在公众号内回复"进群"可进群交流。

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动 XR 技术的探索与实践
火山引擎开发者社区技术大讲堂第二期邀请到了火山引擎 XR 技术负责人和火山引擎创作 CV 技术负责人,为大家分享字节跳动积累的前沿视觉技术及内外部的应用实践,揭秘现代炫酷的视觉效果背后的技术实现。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论