最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

三種Spring AI本地/低成本模型接入方案

 更新時間:2026年04月14日 09:10:57   作者:冰點.  
文章詳細介紹了三種本地低成本接入模型方案的配置與實戰(zhàn)代碼,包括Ollama本地大模型零成本運行、DashScope國內(nèi)低價直連通義千問和API代理統(tǒng)一管理多模型,每種方案都有詳細步驟、配置代碼和適用場景,幫助開發(fā)者根據(jù)實際需求選擇合適的接入方案,需要的朋友可以參考下

1. 為什么需要本地模型接入?

在生產(chǎn)環(huán)境中,調(diào)用 OpenAI / Claude API 存在三大痛點:

痛點影響
數(shù)據(jù)隱私用戶數(shù)據(jù)不能離開企業(yè)內(nèi)網(wǎng),合規(guī)審計嚴格
網(wǎng)絡延遲國內(nèi)訪問海外 API 往返 >300ms,體驗差
成本壓力GPT-4o 約 $2.5/1M tokens,中小項目難以承受

Spring AI 提供了三大接入路徑:本地 Ollama、DashScope API(國內(nèi)直連低價)、API 代理(如 OneAPI)統(tǒng)一管理多模型,本篇逐一拆解。

2. Ollama:本地大模型零成本運行

2.1 安裝與模型下載

macOS / Linux 一行安裝:

# 一鍵安裝
curl -fsSL https://ollama.com/install.sh | sh
# Windows 直接下載安裝包:https://ollama.com/download

拉取常用模型(根據(jù)顯存選型):

# 通義千問 7B(推薦入門,int4 量化約 4GB 顯存)
ollama pull qwen2.5:7b
# Llama 3.1 8B(通用能力強)
ollama pull llama3.1:8b
# Mistral 7B(指令遵循優(yōu)秀)
ollama pull mistral
# Phi-3.5(微軟小模型,CPU 可跑)
ollama pull phi3.5:latest
# bge-m3 嵌入模型(知識庫必備)
ollama pull nomic-embed-text

顯存參考表:

模型參數(shù)量級FP16 顯存int4 量化顯存CPU 可跑
Phi-3.53.8B~8GB~2GB?
Qwen2.5 7B7B~14GB~4GB?? 慢
Llama 3.1 8B8B~16GB~5GB?
Qwen2.5 14B14B~28GB~8GB?
Qwen2.5 32B32B~64GB~18GB?

驗證安裝:

ollama list
# NAME              ID           SIZE      MODIFIED
# qwen2.5:7b        a3........   4.7GB     5 minutes ago
# nomic-embed-text  0a........   274MB     2 hours ago
ollama run qwen2.5:7b "用一句話解釋什么是 RAG"
# RAG(檢索增強生成)是通過檢索外部知識庫來增強大語言模型生成能力的技術

2.2 Modelfile:自定義模型行為

Ollama 支持用 Modelfile 配置文件深度定制模型行為,無需重新訓練。

場景一:固定系統(tǒng)提示詞,打造專屬客服人格

# 創(chuàng)建文件:./modelfiles/rag-assistant
FROM qwen2.5:7b
PARAMETER temperature 0.3
PARAMETER top_p 0.85
PARAMETER num_ctx 8192
TEMPLATE """
{% for message in messages %}
{{ '[BOT]' if message['role'] == 'assistant' else '[USER]' }}
{{ message['content'] }}
{% endfor %}
[BOT]
"""
SYSTEM """
你是一個專業(yè)的企業(yè)知識庫助手?;卮鸨仨殻?
1. 基于提供的上下文信息回答,不要編造
2. 如果上下文沒有相關信息,誠實告知用戶
3. 回答簡潔有條理,優(yōu)先使用列表格式
"""

場景二:流式輸出配置(工程化必須)

# ./modelfiles/fast-response
FROM qwen2.5:7b
PARAMETER temperature 0.7
PARAMETER num_predict 512        # 最大生成長度
PARAMETER stop "[DONE]"          # 停止詞
PARAMETER num_ctx 4096           # 上下文窗口

創(chuàng)建并測試自定義模型:

ollama create rag-assistant -f ./modelfiles/rag-assistant
ollama run rag-assistant "Spring Boot 如何集成 Redis?"

2.3 Spring AI + Ollama 集成

Maven 依賴:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>

application.yml 配置:

spring:
  application:
    name: spring-ai-ollama-demo
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: qwen2.5:7b
          temperature: 0.7
          numCtx: 8192
          keepAlive: 5m
# 嵌入模型單獨配置(知識庫用)
  rag:
    embedding:
      model: nomic-embed-text

基礎對話代碼:

@RestController
@RequestMapping("/ai")
@RequiredArgsConstructor
public class OllamaChatController {
    private final ChatClient chatClient;
    @GetMapping("/chat")
    public String chat(@RequestParam(defaultValue = "你好,介紹一下你自己") String question) {
        return chatClient.prompt()
                .user(question)
                .call()
                .content();
    }
    // 流式響應:適合前端 SSE 推送
    @GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chatStream(@RequestParam String question) {
        return chatClient.prompt()
                .user(question)
                .stream()
                .content();
    }
}

知識庫嵌入配置:

@Configuration
public class OllamaEmbeddingConfig {

    @Bean
    public OllamaEmbeddingModel embeddingModel(OllamaApi api) {
        return new OllamaEmbeddingModel(api);
    }

    @Bean
    public VectorStore vectorStore(OllamaEmbeddingModel embeddingModel) {
        // 使用 SimpleVectorStore(輕量級,生產(chǎn)推薦 PGVector/Chroma)
        return new SimpleVectorStore(embeddingModel);
    }
}

導入文檔到向量庫:

@Service
@RequiredArgsConstructor
public class DocumentIngestionService {

    private final OllamaEmbeddingModel embeddingModel;
    private final VectorStore vectorStore;

    public void ingestDocument(Path pdfPath) throws Exception {
        // PDF 解析
        PdfDocumentReader pdfReader = new PdfDocumentReader(pdfPath.toUri().toString());
        var document = pdfReader.get();

        // 文本分割(控制每段 token 數(shù)量)
        var splitter = new TokenTextSplitter(800, 200, 10, 5000, true);
        var chunks = splitter.apply(List.of(document));

        // 寫入向量庫
        vectorStore.add(chunks);

        System.out.println("? 已導入 " + chunks.size() + " 個文本塊到向量庫");
    }

    public List<Document> search(String query, int topK) {
        return vectorStore.similaritySearch(
            SearchRequest.query(query).withTopK(topK)
        );
    }
}

3. DashScope API:國內(nèi)低價直連通義千問

3.1 為什么選 DashScope?

對比項OpenAI APIDashScope
網(wǎng)絡需代理,延遲高國內(nèi)直連 <50ms
價格GPT-4o $2.5/1MQwen-Turbo ¥0.002/1K tokens
政策存在封號風險阿里云合規(guī)保障
開源模型?? 支持開源模型 API

獲取 API Key:

  1. 阿里云百煉平臺 → 開通服務 → 創(chuàng)建 API Key
  2. 或阿里云 DashScope 控制臺

3.2 Spring AI DashScope 配置

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-alibaba-spring-boot-starter</artifactId>
</dependency>
spring:
  ai:
    dashscope:
      api-key: ${DASHSCOPE_API_KEY}    # 推薦從環(huán)境變量讀取
      base-url: https://dashscope.aliyuncs.com
      chat:
        options:
          model: qwen-turbo
          # qwen-plus / qwen-max 也可選
          temperature: 0.8
          max-tokens: 2000
@RestController
@RequestMapping("/ai")
public class DashScopeController {

    private final ChatClient chatClient;

    public DashScopeController(ChatClient.Builder builder) {
        this.chatClient = builder
            .defaultSystem("你是一個 Java 技術專家,用簡潔專業(yè)的語言回答問題")
            .build();
    }

    @PostMapping("/ask")
    public Map<String, Object> ask(@RequestBody Map<String, String> request) {
        String question = request.get("question");
        String answer = chatClient.prompt()
            .user(question)
            .call()
            .content();

        return Map.of("question", question, "answer", answer);
    }
}

3.3 DashScope 嵌入模型(知識庫必備)

spring:
  ai:
    dashscope:
      embedding:
        options:
          model: text-embedding-v3   # 阿里自研嵌入模型,1536 維
// 配合 RAG 使用
@Service
public class RAGService {

    private final VectorStore vectorStore;
    private final ChatClient chatClient;

    public String ragQuery(String question) {
        // Step 1: 檢索相關上下文
        List<Document> contextDocs = vectorStore.similaritySearch(
            SearchRequest.query(question).withTopK(5)
        );

        String context = contextDocs.stream()
            .map(Document::getText)
            .collect(Collectors.joining("\n\n"));

        // Step 2: 構造有上下文的 Prompt
        String prompt = String.format("""
            基于以下參考資料回答用戶問題。如果資料中沒有相關信息,請如實說明。

            參考資料:
            %s

            用戶問題:%s
            """, context, question);

        // Step 3: 調(diào)用通義千問
        return chatClient.prompt()
            .user(prompt)
            .call()
            .content();
    }
}

4. API 代理:OneAPI 統(tǒng)一管理多模型

4.1 為什么需要 API 代理層?

在企業(yè)場景中,通常需要同時接入多個 AI 供應商:

業(yè)務代碼
    ↓ 統(tǒng)一調(diào)用
OneAPI(本地代理)
    ├── OpenAI(主力)
    ├── Claude(備選)
    ├── DashScope(國內(nèi)備選)
    └── Ollama(內(nèi)網(wǎng)補充)

核心價值:

  • 統(tǒng)一接口:業(yè)務代碼只對接一個端點,換模型改配置不碰代碼
  • 負載均衡:多渠道 token 輪詢,降低單渠道限流風險
  • 用量統(tǒng)計:一個面板看所有模型的調(diào)用量和費用
  • 密鑰管理:API Key 集中存儲,不分散在各個服務中

4.2 OneAPI 快速部署

# Docker 一鍵部署
docker run -d \
  --name oneapi \
  -p 3000:3000 \
  -v ~/oneapi/data:/data \
  --restart always \
  ghcr.io/songquanpeng/one-api:latest
# 訪問 http://localhost:3000
# 默認賬號:root   默認密碼:123456

配置渠道(以 OpenAI 為例):

  1. 登錄管理后臺 → 渠道管理 → 添加渠道
  2. 類型選 OpenAI,填入 API Key 和 base-url(國內(nèi)需代理)
  3. 模型列表填入:gpt-4o,gpt-4o-mini,gpt-3.5-turbo,gpt-4-turbo
  4. 額度設置合理閾值

配置渠道(以 DashScope 為例):

  • 類型選 自定義,base-url 填:https://dashscope.aliyuncs.com/compatible-mode/v1
  • API Key 填阿里云 DashScope Key
  • 模型列表:qwen-turbo,qwen-plus,qwen-max,text-embedding-v3

4.3 Spring AI 通過 OneAPI 接入

spring:
  ai:
    openai:
      base-url: http://localhost:3000/v1   # OneAPI 代理地址
      api-key: ${ONEAPI_API_KEY}           # OneAPI 的 API Key(管理后臺→個人API密鑰)
      chat:
        options:
          model: gpt-4o                    # 可動態(tài)切換:gpt-4o / qwen-turbo / claude-3-5-sonnet

效果:業(yè)務代碼完全不用改,只需改配置中的模型名稱!

// 同一個 ChatClient,換模型只需改 yml
@RestController
public class ChatController {

    private final ChatClient chatClient;

    public ChatController(ChatClient.Builder builder) {
        // 配置統(tǒng)一從 yml 讀取,這里零改動
        this.chatClient = builder.build();
    }
}

4.4 模型切換策略實戰(zhàn)

@Service
public class SmartChatService {
    private final OpenAiApi openAiApi;
    // 簡單路由:根據(jù)輸入長度選擇模型
    public String chatWithRouting(String input) {
        String model;
        if (input.length() < 200) {
            // 簡單問題用小模型,省錢
            model = "gpt-4o-mini";
        } else if (input.length() < 2000) {
            // 中等復雜度用主力模型
            model = "gpt-4o";
        } else {
            // 復雜任務用最強模型
            model = "gpt-4-turbo";
        }
        return ChatClient.builder(new OpenAiChatModel(openAiApi, OpenAiChatOptions.builder()
                .withModel(model)
                .withTemperature(0.7)
                .build()))
            .build()
            .prompt()
            .user(input)
            .call()
            .content();
    }
    // 熔斷降級:主模型失敗自動切換備選
    public String chatWithFallback(String input) {
        try {
            return primaryChat(input);
        } catch (Exception e) {
            System.err.println("主模型調(diào)用失敗,切換備選:" + e.getMessage());
            return fallbackChat(input);
        }
    }
    private String primaryChat(String input) {
        return ChatClient.builder(new DashScopeChatModel(DashScopeApi.builder()
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .build(),
                DashScopeChatOptions.builder()
                    .withModel("qwen-plus")
                    .build()))
            .build()
            .prompt()
            .user(input)
            .call()
            .content();
    }
    private String fallbackChat(String input) {
        return ChatClient.builder(new OpenAiApi("http://localhost:3000/v1",
                System.getenv("ONEAPI_API_KEY")))
            .build()
            .prompt()
            .user(input)
            .call()
            .content();
    }
}

5. 混合路由:本地 + 云端智能調(diào)度

在實際生產(chǎn)中,最優(yōu)方案是分層使用

用戶請求
    │
    ▼
┌─────────────────────────────┐
│  路由層(Spring AI Router)   │
└─────────────────────────────┘
    │
    ├── 簡單/隱私數(shù)據(jù) ──→ Ollama 本地(零成本,極速)
    │
    ├── 復雜推理 ──→ DashScope(國內(nèi)低價,高性能)
    │
    └── 最高質(zhì)量要求 ──→ OpenAI / Claude(最強能力)

5.1 路由策略設計

@Component
public class ModelRouter {

    private final OllamaChatModel localModel;
    private final DashScopeChatModel dashscopeModel;
    private final OpenAiApi openaiApi;

    /**
     * 根據(jù)請求特征選擇最優(yōu)模型
     * @param input 用戶輸入
     * @param mode  業(yè)務場景:SIMPLE / COMPLEX / PREMIUM
     */
    public String route(String input, String mode) {
        return switch (mode) {
            case "SIMPLE" -> callLocal(input);
            case "COMPLEX" -> callDashScope(input);
            case "PREMIUM" -> callOpenAI(input);
            default -> callDashScope(input); // 默認用 DashScope
        };
    }

    private String callLocal(String input) {
        return ChatClient.builder(localModel)
            .build()
            .prompt().user(input).call().content();
    }

    private String callDashScope(String input) {
        return ChatClient.builder(dashscopeModel)
            .build()
            .prompt().user(input).call().content();
    }

    private String callOpenAI(String input) {
        return ChatClient.builder(new OpenAiChatModel(openaiApi,
                OpenAiChatOptions.builder().withModel("gpt-4o").build()))
            .build()
            .prompt().user(input).call().content();
    }
}

5.2 根據(jù)隱私程度自動路由

public String privacyAwareRoute(String input, boolean containsUserData) {
    if (containsUserData) {
        // 敏感數(shù)據(jù)強制走本地,避免合規(guī)風險
        return "?? 包含用戶隱私數(shù)據(jù),已路由至本地模型處理:" + callLocal(input);
    } else {
        // 非敏感數(shù)據(jù)走云端,享受最強能力
        return "?? 已路由至云端高性能模型:" + callDashScope(input);
    }
}

6. 性能對比實測

測試環(huán)境:MacBook M2 Pro(32GB),網(wǎng)絡為上海家寬

方案模型首次響應成本適合場景
OllamaQwen2.5 7B int4~1.2s¥0內(nèi)網(wǎng)/隱私/開發(fā)
OllamaLlama 3.1 8B int4~1.8s¥0通用對話
DashScopeQwen-Turbo~0.8s¥0.002/1K國內(nèi)生產(chǎn)主力
DashScopeQwen-Plus~1.2s¥0.02/1K高質(zhì)量需求
OneAPI→OpenAIGPT-4o-mini~1.5s~$0.15/1M復雜推理

7. 選型決策樹

輸入類型是什么?
│
├─ 包含敏感/隱私數(shù)據(jù)?
│   └─ ? 是 ──→ Ollama 本地(qwen2.5:7b)
│
├─ 國內(nèi)生產(chǎn)環(huán)境,低成本優(yōu)先?
│   └─ ? 是 ──→ DashScope Qwen-Turbo/Plus
│
├─ 需要最強推理能力(代碼/復雜分析)?
│   └─ ? 是 ──→ OpenAI GPT-4o / Claude 3.5
│
└─ 多模型混合使用?
    └─ ? 是 ──→ OneAPI + 智能路由層

8. 常見問題

Q1: Ollama 模型更新后需要重啟嗎?

不需要。ollama pull 會自動更新。正在運行的模型不受影響,下次調(diào)用時自動使用新版本。

Q2: OneAPI 和直接調(diào) API 的性能差異?

OneAPI 多一跳 HTTP 轉(zhuǎn)發(fā),延遲增加約 5-20ms。對于 LLM 的 token 生成時間(通常數(shù)百毫秒~數(shù)秒),這個開銷可以忽略。

Q3: Ollama 顯存不夠怎么辦?

  • 換用更小的量化版本(如 qwen2.5:3b)
  • 使用 Phi-3.5(3.8B,CPU 可跑)
  • 調(diào)低 num_ctx 參數(shù)減少 KV Cache 顯存占用

Q4: DashScope 和 OpenAI API 語法兼容嗎?

不完全兼容。Spring AI 的 spring-ai-alibaba 提供了獨立適配器,需要單獨引入依賴并配置,不能和 spring-ai-openai 混用同一個 ChatClient。

Q5: 如何監(jiān)控各模型的調(diào)用量和費用?

OneAPI 自帶統(tǒng)計面板,可以按渠道、模型查看調(diào)用次數(shù)和預估費用。也可接入 Prometheus + Grafana 展示自定義指標。

以上就是三種Spring AI本地/低成本模型接入方案的詳細內(nèi)容,更多關于Spring AI本地/低成本模型接入的資料請關注腳本之家其它相關文章!

相關文章

  • 淺談Java并發(fā)編程基礎知識

    淺談Java并發(fā)編程基礎知識

    這篇文章主要介紹了淺談Java并發(fā)編程基礎知識,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • SpringSecurity JWT基于令牌的無狀態(tài)認證實現(xiàn)

    SpringSecurity JWT基于令牌的無狀態(tài)認證實現(xiàn)

    Spring Security中實現(xiàn)基于JWT的無狀態(tài)認證是一種常見的做法,本文就來介紹一下SpringSecurity JWT基于令牌的無狀態(tài)認證實現(xiàn),感興趣的可以了解一下
    2025-04-04
  • Spring中@Scope的幾種取值方式

    Spring中@Scope的幾種取值方式

    這篇文章主要介紹了Spring中@Scope的幾種取值方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • java中創(chuàng)建兩表之間的觸發(fā)器詳解

    java中創(chuàng)建兩表之間的觸發(fā)器詳解

    這篇文章主要介紹了java中創(chuàng)建兩表之間的觸發(fā)器詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-06-06
  • springBoot 打war包 程序包com.sun.istack.internal不存在的問題及解決方案

    springBoot 打war包 程序包com.sun.istack.internal不存在的問題及解決方案

    這篇文章主要介紹了springBoot 打war包 程序包com.sun.istack.internal不存在的問題及解決方案,親測試過可以,需要的朋友可以參考下
    2018-07-07
  • java實現(xiàn)簡單斗地主(看牌排序)

    java實現(xiàn)簡單斗地主(看牌排序)

    這篇文章主要介紹了java實現(xiàn)簡單斗地主,看牌進行排序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2010-11-11
  • Java管道流實現(xiàn)線程間通信過程解析

    Java管道流實現(xiàn)線程間通信過程解析

    這篇文章主要介紹了Java管道流實現(xiàn)線程間通信過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • Java獲取classpath根路徑的三種方法

    Java獲取classpath根路徑的三種方法

    本文介紹了在Java中獲取classpath根路徑的三種方法:ClassLoader.getResource、Class.getResource和System.getProperty,每種方法都有其適用場景,開發(fā)者可以根據(jù)具體需求選擇合適的方法,需要的朋友可以參考下
    2026-01-01
  • Java中static變量作用和用法詳解

    Java中static變量作用和用法詳解

    Java 中被 static 修飾的成員稱為靜態(tài)成員或類成員。它屬于整個類所有,而不是某個對象所有,即被類的所有對象所共享。靜態(tài)成員可以使用類名直接訪問,也可以使用對象名進行訪問.下面我們來詳細了解一下吧
    2019-06-06
  • Java基礎篇_有關接口和抽象類的幾道練習題(分享)

    Java基礎篇_有關接口和抽象類的幾道練習題(分享)

    下面小編就為大家?guī)硪黄狫ava基礎篇_有關接口和抽象類的幾道練習題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06

最新評論

嫩江县| 志丹县| 邹城市| 湾仔区| 措勤县| 兴海县| 綦江县| 新乐市| 肃南| 丰原市| 监利县| 报价| 松阳县| 扬中市| 苗栗市| 钟山县| 虞城县| 荣成市| 南城县| 句容市| 广汉市| 沾益县| 无锡市| 万盛区| 崇阳县| 拜城县| 古交市| 宣城市| 巴马| 汝南县| 石河子市| 宿州市| 德保县| 正宁县| 满洲里市| 台南市| 五指山市| 磐安县| 衢州市| 江山市| 望江县|