玖叶教程网

前端编程开发入门

Java生态圈的Langchain来了,Spring AI上架Spring Initializr

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

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

主要特性:

- 对所有主流 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;

    }
}


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言