Spring AI與大模型Ollama如何整合整合?

banq發表於2024-03-04

Python 是進入人工智慧領域(認為是機器學習或生成人工智慧AIGC)的主要武器,Java 和 Spring 仍引領著大多數開發社群, Java 開發人員如何與 LLM大模型 一起工作?這就是 Spring AI 彌補差距的地方。

Spring AI在 Spring 應用程式和可以在本地執行的 LLM 之間建立整合,這為所有 Java 開發人員提供了開發人工智慧應用程式的能力。

在本文中,我們將瞭解如何使用 Ollama 在本地執行大模型,我們將考慮四個方面。

  1. 本地安裝並執行 Ollama 和 LLM
  2. 建立SpringAI專案並詳細檢視專案配置。
  3. 訪問本地嵌入。
  4. 訪問本地聊天模型。

安裝並執行 Ollama
導航至https://ollama.com/download下載適用於特定作業系統的 ollama。

下載 ollama 後,開啟終端並輸入以下命令以提取 LLM 並在本地執行它們。
ollama run llama2 # pulls llama2 LLM model
ollama run mistral # pulls and runs mistral LLM

建立 Spring AI 專案
如果你使用任何整合開發環境(我使用的是 IntelliJ)或基於 Web 的 Spring Intializr,那麼你可以看到現在可以直接從 Spring Intializr 新增 AI 依賴項。在本例中,我們將新增 Ollama。在執行此步驟之前,請按照步驟 1 確保已安裝 Ollama 並在本地執行。

讓我們深入研究一下 application.yaml,看看與 ollama 有關的不同專案配置。

spring:
  ai:
    ollama:
      embedding:
        model: <font>"llama2"
        options:
          temperature: 0.5
          top-p: 0.2
          top-k: 2
          num-g-p-u: 1 enable metal gpu on MAC
      base-url:
"http://localhost:11434"


有關嵌入和聊天模型的更多配置可分別在這裡 here 和這裡here 找到。請注意一點,Spring 預設配置可與 Mistral LLM 配合使用,但我們已明確用 llama2 替代。

實體記錄
首先,我們將建立兩個記錄:Payload 和 Response,名稱更加直觀。

package org.vaslabs.springai2.records;

public record Payload(String strings) {
}
package org.vaslabs.springai2.records;

import java.util.List;

public record Response(List<Double> data) {
}

服務類
現在讓我們建立一個服務類,它將幫助我們為給定的輸入字串生成嵌入結果。

import org.springframework.ai.embedding.EmbeddingClient;
import org.springframework.ai.embedding.EmbeddingRequest;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.stereotype.Service;
import org.vaslabs.springai2.records.Payload;

import java.util.List;
import java.util.Map;

@Service
public class OllamaEmbeddingsGenerator {
    private final EmbeddingClient embeddingClient;

    public OllamaEmbeddingsGenerator(EmbeddingClient embeddingClient) {
        this.embeddingClient = embeddingClient;
    }

    public EmbeddingResponse getEmbeddingsWithModelOverride(Payload payload) {
        return this.embeddingClient.call(new EmbeddingRequest(
                List.of(payload.strings()),
                OllamaOptions.create().withModel(<font>"mistral")));
    }

    public Map<String, EmbeddingResponse> getEmbeddingsWithDefaultModel(Payload payload) {
        EmbeddingResponse embeddingResponse = this.embeddingClient.embedForResponse(
                List.of(payload.strings()));
        return Map.of(
"embedding", embeddingResponse);
    }
}

上述 OllamaEmbeddingsGenerator 類定義在 Spring 應用程式的 org.vaslabs.springai2.service 包中,是生成文字嵌入的服務元件。它利用 Spring AI 框架的嵌入式客戶端(EmbeddingClient)將文字資料轉換為嵌入式,即在自然語言處理任務中非常有用的向量表示。

該服務配備了兩個主要方法:getEmbeddingsWithModelOverride 和 getEmbeddingsWithDefaultModel。

  • 前一種方法允許指定用於嵌入生成的模型(例如 "mistral"),從而可以根據請求自定義行為。
  • 後一種方法則使用客戶端的預設模型設定生成嵌入。這兩種方法的操作方式都是獲取一個 Payload 物件(該物件封裝了要嵌入的字串),並以不同的格式返回嵌入結果--在 getEmbeddingsWithModelOverride 的情況下直接返回 EmbeddingResponse,而在 getEmbeddingsWithDefaultModel 的情況下返回一個包含 EmbeddingResponse 的對映。

這種設計封裝了與嵌入式生成技術互動的複雜性,併為應用程式中的各種嵌入式生成需求提供了靈活的應用程式介面。

讓我們再瞭解一項有助於建立聊天一代的服務。

import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class OllamaChatGenerator {

    private final OllamaChatClient ollamaChatClient;

    public OllamaChatGenerator(OllamaChatClient ollamaChatClient) {
        this.ollamaChatClient = ollamaChatClient;
    }

    public Map generate(String message) {
        return Map.of(<font>"generation", this.ollamaChatClient.call(message));
    }
}

  • 上述 Java 類 OllamaChatGenerator 定義在 org.vaslabs.springai2.service 包中,設計為 Spring 服務,透過利用 Spring AI 框架中的 OllamaChatClient 來促進聊天互動。
  • 該服務使用 @Service 註解進行 Spring 元件掃描,封裝了一種簡單而有效的方法來生成聊天響應。
  • 透過建構函式例項化後,它會接收一個 OllamaChatClient 物件,從而建立起與底層聊天模型或服務通訊的依賴關係。
  • 該服務的主要功能透過 generate 方法公開,該方法接受字串訊息作為輸入,並返回一個包含以 "generation "為關鍵字的聊天生成結果的對映。

這種設定抽象化了與人工智慧驅動的聊天功能進行互動的複雜性,為 Spring 應用程式的其他元件提供了一種直接的方法,可根據使用者輸入生成動態的對話式響應。

控制器
現在是為上述兩個服務編寫控制器的時候了,它們可以分別處理終端使用者的請求。這些控制器將幫助我們選擇使用者所需的功能。

import org.springframework.ai.embedding.Embedding;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.vaslabs.springai2.records.Payload;
import org.vaslabs.springai2.records.Response;
import org.vaslabs.springai2.service.OllamaEmbeddingsGenerator;

import java.util.Map;

@RestController
@RequestMapping(<font>"/api/v1")
public class OllamaEmbeddingController {

    private final OllamaEmbeddingsGenerator ollamaEmbeddingsGenerator;

    public OllamaEmbeddingController(OllamaEmbeddingsGenerator ollamaEmbeddingsGenerator) {
        this.ollamaEmbeddingsGenerator = ollamaEmbeddingsGenerator;
    }
    @PostMapping(value =
"/embedding1", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Response> fetchEmbeddings1(@RequestBody Payload payload){
        Embedding embedding = this.ollamaEmbeddingsGenerator.getEmbeddingsWithModelOverride(payload).getResult();
        return ResponseEntity.ok(new Response(embedding.getOutput()));
    }

    @PostMapping(value =
"/embedding2", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Map<String, EmbeddingResponse>> fetchEmbeddings2(@RequestBody Payload payload){
        Map<String, EmbeddingResponse> embedding = this.ollamaEmbeddingsGenerator.getEmbeddingsWithDefaultModel(payload);
        return ResponseEntity.ok(embedding);
    }
}

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.vaslabs.springai2.records.Payload;
import org.vaslabs.springai2.service.OllamaChatGenerator;

import java.util.Map;

@RestController
@RequestMapping(<font>"/api/v1")
public class OllamaChatController {

    private final OllamaChatGenerator ollamaChatGenerator;

    public OllamaChatController(OllamaChatGenerator ollamaChatGenerator) {
        this.ollamaChatGenerator = ollamaChatGenerator;
    }

    @PostMapping(value =
"/chat", produces = MediaType.APPLICATION_JSON_VALUE)
    public Map chat(@RequestBody Payload payload){
        return this.ollamaChatGenerator.generate(payload.strings());
    }
}

如果上述程式碼和配置都沒有問題,那麼我們就可以執行該專案了(需要注意的是,請確保在本地執行 ollama)。

檢視 OllamaEmbeddingController 的路由 /embedding1 和 /embedding2 非常有趣,第一個路由透過在服務中以程式設計方式覆蓋模型的配置來使用 Mistral 模型,而後一個路由則使用 application.yaml 中的預設配置。

結論
總之,將 Ollama 與 Spring AI 結合使用,是將先進的大型語言模型 (LLM) 直接整合到應用程式中的令人信服的解決方案,可提供嵌入和文字生成功能。藉助 Ollama 在本地執行 LLM 的能力,開發人員可以對人工智慧驅動的功能獲得前所未有的控制力和靈活性,確保資料隱私並減少延遲。

Spring AI 透過 OllamaEmbeddingClient 和 OllamaChatClient 對 Ollama 的支援簡化了整合過程,在 Spring 生態系統中實現了無縫嵌入生成和對話式人工智慧功能。這種組合不僅使最先進的人工智慧技術的使用更加平民化,而且還增強了應用程式的可擴充套件性和響應能力,使其成為希望整合智慧、上下文感知互動和資料處理功能的開發人員的理想選擇。

相關文章