Spring AI 接入通义千问向量模型

本文介绍如何在 Spring Boot 项目中使用 Spring AI Alibaba 接入阿里云百炼 DashScope 的通义千问文本向量模型,实现文本向量化、查询向量生成以及简单的相似度计算。示例使用 text-embedding-v4。如果你的账号或依赖版本仍使用 text-embedding-v3、text-embedding-v2,只需要替换模型名称和对应支持的维度即可。

一、什么是 Embedding

Embedding 模型可以把一段文本转换成一个浮点数数组,例如:

复制代码
"Spring AI 是什么?"
        ↓
[0.0123, -0.0841, 0.2231, ...]

这个浮点数组称为文本向量。语义相近的文本,生成的向量通常也更接近,因此向量可以用于:

  • 语义搜索;

  • RAG 知识库检索;

  • 文本聚类;

  • 文本分类;

  • 推荐和相似内容匹配;

  • 重复内容检测。

本文只演示如何生成向量。要实现完整的 RAG,还需要将向量保存到 Milvus、PGVector、Elasticsearch、Redis 等向量数据库中。

二、准备工作

开始之前,需要准备:

  1. JDK 17 或更高版本;

  2. Maven 3.9+;

  3. Spring Boot 项目;

  4. 阿里云百炼 API Key;

  5. 已在百炼控制台开通对应的 Embedding 模型权限。

可以在 阿里云百炼控制台 创建 API Key。

不要把 API Key 直接写入 Git 仓库。 本文使用环境变量 AI_DASHSCOPE_API_KEY 注入密钥。

三、Maven 依赖配置

Spring AI Alibaba 为 DashScope 提供了 Spring Boot Starter,Starter 同时支持 DashScope 的 ChatModel 和 EmbeddingModel 自动配置。

下面是一个完整的 pom.xml 示例。版本应保持 Spring Boot、Spring AI Alibaba 和 Spring AI 核心依赖相互兼容。本文示例使用 Maven Central 中的 spring-ai-alibaba-starter-dashscope:2.0.0-M1.1。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.0.0</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>spring-ai-qwen-embedding-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-ai-qwen-embedding-demo</name>

    <properties>
        <java.version>17</java.version>
        <spring-ai-alibaba.version>2.0.0-M1.1</spring-ai-alibaba.version>
    </properties>

    <dependencies>
        <!-- Web 接口 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring AI Alibaba DashScope Starter ,包含 Embedding 自动配置 -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
            <version>${spring-ai-alibaba.version}</version>
        </dependency>

        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

版本选择说明

Spring AI Alibaba 的版本会随着 Spring AI 和 Spring Boot 的大版本变化。实际项目中建议:

  1. 先查看 Spring AI Alibaba 官方仓库的兼容说明;

  2. 从 Maven Central确认可用版本;

  3. 保证 Starter 的传递依赖没有和项目中手工指定的 Spring AI 版本冲突。

如果项目已经使用 Spring AI Alibaba 1.x,请把依赖版本替换为与你的 Spring Boot 版本匹配的 1.x 稳定版本,不要直接混用 1.x 和 2.x 的依赖。

四、配置 application.yml

在 src/main/resources/application.yml 中配置 DashScope:

yaml 复制代码
server:
  port: 8080

spring:
  application:
    name: spring-ai-qwen-embedding-demo

  ai:
    dashscope:
      # 从环境变量中读取百炼 API Key
      api-key: ${AI_DASHSCOPE_API_KEY}
      # DashScope 公共云基础地址
      base-url: https://dashscope.aliyuncs.com
      embedding:
        # 启用 DashScope Embedding 自动配置
        # 不同版本可能默认已启用 ,显式配置更清晰
        options:
          # 推荐使用当前可用的通用文本向量模型
          model: text-embedding-v4
          # 文档入库使用 document,用户查询使用 query
          text-type: document
          # v4 支持 2048、1536、1024、768、512、256、128、64
          dimensions: 1024

    # 新版 Spring AI Alibaba 文档使用该顶层属性选择 Embedding 模型
    model:
      embedding: dashscope

    retry:
      # 网络临时异常可以重试,4xx 参数错误默认不重试
      max-attempts: 3
      backoff:
        initial-interval: 1s
        multiplier: 2
        max-interval: 10s
      on-client-errors: false

设置环境变量:

Linux/macOS

bash 复制代码
export AI_DASHSCOPE_API_KEY="你的百炼 API Key"

Windows PowerShell

复制代码
$env:AI_DASHSCOPE_API_KEY = "你的百炼 API Key"

也可以在启动时临时传入:

bash 复制代码
AI_DASHSCOPE_API_KEY="你的百炼 API Key" mvn spring-boot:run

五、通义千问向量模型选择

DashScope 常见文本向量模型如下:

模型 说明 常见维度
text-embedding-v4 新版通用多语言文本向量模型,适合新建知识库 2048、1536、1024、768、512、256、128、64
text-embedding-v3 多语言文本向量模型 1024、768、512、256、128、64
text-embedding-v2 较早版本通用文本向量模型 1536
text-embedding-v1 基础文本向量模型 以平台实际支持为准

本文使用 text-embedding-v4 和 1024 维。维度越高并不一定代表业务效果一定越好,需要结合检索质量、存储空间、查询延迟和向量数据库索引能力选择。

重要原则:索引和查询维度必须一致

例如文档入库使用:

yaml 复制代码
model: text-embedding-v4
dimensions: 1024

那么用户问题也必须使用同一个模型和同一个维度:

复制代码
text-embedding-v4 + 1024 维

如果文档向量是 1024 维,而查询向量是 768 维,向量数据库通常会直接报维度不匹配错误。

六、编写 Spring Boot 启动类

java 复制代码
package com.example.embedding;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class QwenEmbeddingApplication {

    public static void main(String[] args) {
        SpringApplication.run(QwenEmbeddingApplication.class, args);
    }
}

添加 DashScope Starter 后,Spring Boot 会自动创建 EmbeddingModel Bean,业务代码可以直接注入它。

七、生成单条文本向量

下面编写一个 Controller,通过 HTTP 参数接收文本并生成向量:

java 复制代码
package com.example.embedding.controller;

import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@RestController
public class EmbeddingController {

    private final EmbeddingModel embeddingModel;

    public EmbeddingController(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    @GetMapping("/ai/embedding")
    public Map<String, Object> embedding(
            @RequestParam(value = "text", defaultValue = "Spring AI 可以接入通义千问向量模型")
            String text) {

        EmbeddingResponse response = embeddingModel.embedForResponse(
                java.util.List.of(text)
        );

        float[] vector = response.getResults().get(0).getOutput();

        Map<String, Object> result = new HashMap<>();
        result.put("text", text);
        result.put("dimensions", vector.length);
        // 示例只返回前 5 个元素,避免接口响应过大
        result.put("preview", Arrays.copyOf(vector, Math.min(5, vector.length)));
        result.put("model", response.getMetadata().getModel());
        return result;
    }
}

启动项目:

bash 复制代码
mvn spring-boot:run

调用接口:

bash 复制代码
curl --get 'http://localhost:8080/ai/embedding' \
  --data-urlencode 'text=Spring AI 如何实现语义搜索?'

返回结果类似:

json 复制代码
{
  "text": "Spring AI 如何实现语义搜索?",
  "dimensions": 1024,
  "preview": [0.0123, -0.0831, 0.2214, 0.0172, -0.1045],
  "model": "text-embedding-v4"
}

实际向量包含 1024 个浮点数 ,示例中只返回前 5 个元素。

不建议在生产接口中直接返回完整向量。完整向量体积较大,也可能暴露不必要的内部数据。通常应该在服务端直接写入向量数据库。

八、批量生成文本向量

Spring AI 的 EmbeddingModel 支持一次传入多条文本:

java 复制代码
package com.example.embedding.service;

import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmbeddingService {

    private final EmbeddingModel embeddingModel;

    public EmbeddingService(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    public List<float[]> embedDocuments(List<String> documents) {
        return embeddingModel.embed(documents);
    }
}

调用示例:

java 复制代码
List<String> documents = List.of(
        "Spring AI 是面向 Java 的人工智能应用框架。",
        "Embedding 可以将文本转换为向量。",
        "向量数据库适合保存和检索文本向量。"
);

List<float[]> vectors = embeddingService.embedDocuments(documents);

for (int i = 0; i < vectors.size(); i++) {
    System.out.println("第 " + i + " 条向量维度:" + vectors.get(i).length);
}

批量大小需要遵守当前模型的限制。以 text-embedding-v4 为例,官方接口文档显示单次请求最多支持 10 条输入,每条输入还有 Token 长度限制。业务代码中建议自行分批,不要一次提交几百或几千条文本。

九、区分 document 和 query 文本

在语义检索中,通常存在两种文本:

  • document:知识库中被检索的文档;

  • query:用户输入的查询问题。

为了让模型更好地适配非对称检索任务,建议:

  • 文档入库时使用 text-type: document;

  • 用户查询时使用 text-type: query。

默认配置可以用于文档入库:

yaml 复制代码
spring:
  ai:
    dashscope:
      embedding:
        options:
          model: text-embedding-v4
          text-type: document
          dimensions: 1024

如果需要在同一个应用中针对不同请求切换 document 和 query,可以使用运行时 Embedding 选项。不同 Spring AI Alibaba 版本的 options builder 方法可能略有不同,常见写法如下:

java 复制代码
import com.alibaba.cloud.ai.dashscope.api.DashScopeModel;
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
import org.springframework.ai.embedding.EmbeddingRequest;
import org.springframework.ai.embedding.EmbeddingResponse;

import java.util.List;

public EmbeddingResponse embedQuery(EmbeddingModel embeddingModel, String query) {
    DashScopeEmbeddingOptions options = DashScopeEmbeddingOptions.builder()
            .model("text-embedding-v4")
            .textType(DashScopeModel.EmbeddingTextType.QUERY.getValue())
            .dimensions(1024)
            .build();

    return embeddingModel.call(new EmbeddingRequest(List.of(query), options));
}

如果 IDE 提示 DashScopeEmbeddingOptions 的包路径或 builder 方法不存在,说明当前项目使用的 Spring AI Alibaba 版本 API 有差异,应以该版本源码或 JavaDoc 为准。最稳妥的方式是先使用 application.yml 配置默认参数,确认基础调用成功后,再增加运行时选项。

十、计算两个文本的余弦相似度

向量生成后,可以使用余弦相似度判断两个文本的语义接近程度:

java 复制代码
package com.example.embedding.util;

public final class VectorSimilarity {

    private VectorSimilarity() {
    }

    public static double cosineSimilarity(float[] a, float[] b) {
        if (a == null || b == null || a.length != b.length) {
            throw new IllegalArgumentException("两个向量不能为空且维度必须一致");
        }

        double dot = 0.0;
        double normA = 0.0;
        double normB = 0.0;

        for (int i = 0; i < a.length; i++) {
            dot += (double) a[i] * b[i];
            normA += (double) a[i] * a[i];
            normB += (double) b[i] * b[i];
        }

        if (normA == 0.0 || normB == 0.0) {
            return 0.0;
        }

        return dot / (Math.sqrt(normA) * Math.sqrt(normB));
    }
}

使用:

java 复制代码
List<float[]> vectors = embeddingModel.embed(List.of(
        "Java 是一种编程语言",
        "Spring Boot 是 Java 生态中的开发框架"
));

double score = VectorSimilarity.cosineSimilarity(
        vectors.get(0),
        vectors.get(1)
);

System.out.println("相似度:" + score);

实际生产环境通常不在应用内遍历全部向量,而是将向量写入向量数据库,再使用数据库的 ANN 索引完成近似最近邻检索。

十一、封装成文档入库服务

下面给出一个简单的 Service 示例,用于将文档转换成向量对象。真实项目中可以在 save 方法中写入 PGVector、Milvus 或 Elasticsearch:

java 复制代码
package com.example.embedding.service;

import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class KnowledgeDocumentService {

    private final EmbeddingModel embeddingModel;

    public KnowledgeDocumentService(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    public void saveDocument(String documentId, String content) {
        float[] vector = embeddingModel.embed(content);

        // TODO: 将 documentId、content、vector 写入向量数据库
        // 例如:vectorStore.add(List.of(new Document(content, metadata)))
        System.out.printf(
                "documentId=%s, contentLength=%d, vectorDimensions=%d%n",
                documentId,
                content.length(),
                vector.length
        );
    }

    public List<float[]> embedBatch(List<String> contents) {
        return embeddingModel.embed(contents);
    }
}

十二、常见问题排查

1. 启动时报 API Key 为空

检查启动进程是否读取到了环境变量:

bash 复制代码
echo "$AI_DASHSCOPE_API_KEY"

如果使用 IDE 启动,需要在 IDE 的 Run Configuration 中配置环境变量,而不仅仅是在另一个 Shell 窗口中执行 export。

也可以临时使用命令行启动:

bash 复制代码
AI_DASHSCOPE_API_KEY="你的 API Key" mvn spring-boot:run

2. 返回 401 或 403

常见原因:

  • API Key 错误或已失效;

  • 百炼账号没有开通对应模型;

  • 使用了错误的地域或 Workspace;

  • 环境变量中包含多余空格;

  • 项目实际读取的不是你以为的那个配置文件。

3. 返回模型不存在

确认配置项:

yaml 复制代码
spring:
  ai:
    dashscope:
      embedding:
        options:
          model: text-embedding-v4

模型名称不能写成聊天模型名称,例如 qwen-plus、qwen-turbo 等不是文本向量模型。

4. 向量维度不匹配

检查三处是否一致:

  1. application.yml 的 dimensions;

  2. 向量数据库 collection/index 的维度;

  3. 查询向量生成时使用的维度。

例如全部使用 1024 维:

yaml 复制代码
dimensions: 1024

5. EmbeddingModel 无法注入

检查:

  • 是否加入了 spring-ai-alibaba-starter-dashscope;

  • Starter 版本和 Spring Boot 版本是否兼容;

  • 是否存在多个 EmbeddingModel Bean 导致注入歧义;

  • 是否将 spring.ai.model.embedding 错误设置成了 none;

  • 是否把 ChatScope 的 Chat 依赖误当成 Embedding 依赖。

6. 是否必须使用 OpenAI 兼容接口

不必须。Spring AI Alibaba 的 DashScope Starter 直接封装了 DashScope API,适合使用 DashScope 特有的 text_type、dimension、稀疏向量等能力。

阿里云也提供 OpenAI 兼容的 Embedding 接口。如果项目已经统一使用 OpenAI SDK,可以选择兼容接口;但本文使用的是 Spring AI Alibaba 原生 DashScope 集成。

十三、项目目录结构

复制代码
spring-ai-qwen-embedding-demo
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com/example/embedding
        │       ├── QwenEmbeddingApplication.java
        │       ├── controller
        │       │   └── EmbeddingController.java
        │       ├── service
        │       │   ├── EmbeddingService.java
        │       │   └── KnowledgeDocumentService.java
        │       └── util
        │           └── VectorSimilarity.java
        └── resources
            └── application.yml

十四、总结

Spring AI 接入通义千问向量模型的核心步骤如下:

  1. 引入 spring-ai-alibaba-starter-dashscope;

  2. 配置 spring.ai.dashscope.api-key;

  3. 将 Embedding 模型配置为 text-embedding-v4;

  4. 注入 EmbeddingModel;

  5. 调用 embed 或 embedForResponse 生成向量;

  6. 将文档向量保存到向量数据库,用于后续相似度检索。

最简单的调用代码如下:

java 复制代码
float[] vector = embeddingModel.embed("Spring AI 接入通义千问向量模型");

在生产环境中,还需要继续完善:

  • 文档切分策略;

  • 批量向量化和限流;

  • 向量数据库索引;

  • 查询和文档的 text_type 区分;

  • API Key 安全管理;

  • 超时、重试和熔断;

  • Token 用量与成本统计;

  • 文档更新和向量删除机制。

参考资料

相关推荐
龙腾AI白云1 小时前
AI微调技术:让通用大模型精准适配垂直行业
数据库·人工智能·机器学习·flask·scikit-learn
武雄(小星Ai)1 小时前
Opus 5.5 降价40%、GPT-6 API腰斩:2026年9月AI编程模型选购指南(附成本计算器)
人工智能·ai·编程语言
二川bro1 小时前
当AI加速错误:美军Maven误击事件深度拆解
人工智能
麦豆GEO1 小时前
GEO信源布局策略:看懂大模型信源偏好,搭建动态可迭代的全域信源矩阵
大数据·人工智能·矩阵
Sarvartha1 小时前
数组基础知识
java·开发语言
旋生万物2 小时前
Agent System Prompt 注入螺旋公理:让 AI 推理不跑偏的可复制模板(附完整 Prompt)
人工智能·算法
泡海椒2 小时前
金融报表开发:jquick-pdf K 线图 PDF 可视化解决方案
java·开发语言·金融·pdf
光锥智能2 小时前
AI成旗舰手机标配,OPPO高端化能否突围?
人工智能·智能手机
uncle_ll2 小时前
分类任务解决样本数据不均衡的落地实战指南
人工智能·深度学习·机器学习·分类·数据处理