commit
This commit is contained in:
@@ -1,19 +1,11 @@
|
||||
package org.example.service;
|
||||
|
||||
import com.alibaba.dashscope.embeddings.TextEmbedding;
|
||||
import com.alibaba.dashscope.embeddings.TextEmbeddingParam;
|
||||
import com.alibaba.dashscope.embeddings.TextEmbeddingResult;
|
||||
import com.alibaba.dashscope.embeddings.TextEmbeddingOutput;
|
||||
import com.alibaba.dashscope.embeddings.TextEmbeddingResultItem;
|
||||
import com.alibaba.dashscope.exception.NoApiKeyException;
|
||||
import com.alibaba.dashscope.utils.Constants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.ai.embedding.EmbeddingModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -27,44 +19,8 @@ public class VectorEmbeddingService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(VectorEmbeddingService.class);
|
||||
|
||||
@Value("${dashscope.api.key}")
|
||||
private String apiKey;
|
||||
|
||||
@Value("${dashscope.embedding.model}")
|
||||
private String model;
|
||||
|
||||
private TextEmbedding textEmbedding;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// 验证 API Key
|
||||
if (apiKey == null || apiKey.trim().isEmpty() || apiKey.equals("your-api-key-here")) {
|
||||
logger.error("API Key 未正确配置!当前值: {}", apiKey);
|
||||
throw new IllegalStateException("请设置环境变量 DASHSCOPE_API_KEY 或在 application.yml 中配置正确的 API Key");
|
||||
}
|
||||
|
||||
// 打印 API Key 前缀用于调试(不打印完整 Key 保证安全)
|
||||
String maskedKey = apiKey.length() > 8 ?
|
||||
apiKey.substring(0, 8) + "..." + apiKey.substring(apiKey.length() - 4) :
|
||||
"***";
|
||||
logger.info("API Key 已加载: {}", maskedKey);
|
||||
|
||||
// 设置全局 API Key(确保设置成功)
|
||||
Constants.apiKey = apiKey;
|
||||
|
||||
// 验证 API Key 是否设置成功
|
||||
if (Constants.apiKey == null || Constants.apiKey.isEmpty()) {
|
||||
logger.error("Constants.apiKey 设置失败!");
|
||||
throw new IllegalStateException("API Key 设置到 Constants 失败");
|
||||
}
|
||||
|
||||
logger.info("Constants.apiKey 已设置: {}", Constants.apiKey.substring(0, Math.min(8, Constants.apiKey.length())) + "...");
|
||||
|
||||
// 创建 TextEmbedding 实例
|
||||
textEmbedding = new TextEmbedding();
|
||||
|
||||
logger.info("阿里云 DashScope Embedding 服务初始化完成,模型: {}", model);
|
||||
}
|
||||
@Autowired
|
||||
private EmbeddingModel embeddingModel;
|
||||
|
||||
/**
|
||||
* 生成向量嵌入
|
||||
@@ -81,73 +37,25 @@ public class VectorEmbeddingService {
|
||||
}
|
||||
|
||||
logger.debug("开始生成向量嵌入, 内容长度: {} 字符", content.length());
|
||||
|
||||
// 确保 API Key 已设置(防止被其他地方覆盖)
|
||||
if (Constants.apiKey == null || Constants.apiKey.isEmpty()) {
|
||||
logger.warn("检测到 Constants.apiKey 为空,重新设置");
|
||||
Constants.apiKey = apiKey;
|
||||
|
||||
float[] embedding = embeddingModel.embed(content);
|
||||
|
||||
List<Float> floatEmbedding = new ArrayList<>(embedding.length);
|
||||
for (float v : embedding) {
|
||||
floatEmbedding.add(v);
|
||||
}
|
||||
|
||||
logger.debug("调用 API 前 Constants.apiKey: {}",
|
||||
Constants.apiKey != null ? Constants.apiKey.substring(0, Math.min(8, Constants.apiKey.length())) + "..." : "null");
|
||||
|
||||
// 构建请求参数
|
||||
TextEmbeddingParam param = TextEmbeddingParam
|
||||
.builder()
|
||||
.model(model)
|
||||
.texts(Collections.singletonList(content))
|
||||
.build();
|
||||
|
||||
// 调用 API
|
||||
TextEmbeddingResult result = textEmbedding.call(param);
|
||||
|
||||
// 检查结果
|
||||
List<Float> floatEmbedding = getFloats(result);
|
||||
|
||||
logger.info("成功生成向量嵌入, 内容长度: {} 字符, 向量维度: {}",
|
||||
logger.info("成功生成向量嵌入, 内容长度: {} 字符, 向量维度: {}",
|
||||
content.length(), floatEmbedding.size());
|
||||
|
||||
return floatEmbedding;
|
||||
|
||||
} catch (NoApiKeyException e) {
|
||||
logger.error("API Key 未设置或无效", e);
|
||||
throw new RuntimeException("API Key 未设置,请配置 dashscope.api.key", e);
|
||||
} catch (Exception e) {
|
||||
logger.error("生成向量嵌入失败, 内容长度: {}", content != null ? content.length() : 0, e);
|
||||
throw new RuntimeException("生成向量嵌入失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<Float> getFloats(TextEmbeddingResult result) {
|
||||
if (result == null || result.getOutput() == null || result.getOutput().getEmbeddings() == null) {
|
||||
throw new RuntimeException("DashScope API 返回空结果");
|
||||
}
|
||||
|
||||
TextEmbeddingOutput output = result.getOutput();
|
||||
List<TextEmbeddingResultItem> embeddings = output.getEmbeddings();
|
||||
|
||||
if (embeddings.isEmpty()) {
|
||||
throw new RuntimeException("DashScope API 返回空向量列表");
|
||||
}
|
||||
|
||||
// 获取第一个文本的向量
|
||||
List<Double> embeddingDoubles = embeddings.get(0).getEmbedding();
|
||||
|
||||
// 转换为 List<Float>
|
||||
List<Float> floatEmbedding = new ArrayList<>(embeddingDoubles.size());
|
||||
for (Double value : embeddingDoubles) {
|
||||
floatEmbedding.add(value.floatValue());
|
||||
}
|
||||
return floatEmbedding;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量生成向量嵌入
|
||||
*
|
||||
* @param contents 文本内容列表
|
||||
* @return 向量嵌入列表
|
||||
*/
|
||||
public List<List<Float>> generateEmbeddings(List<String> contents) {
|
||||
try {
|
||||
if (contents == null || contents.isEmpty()) {
|
||||
@@ -156,54 +64,24 @@ public class VectorEmbeddingService {
|
||||
}
|
||||
|
||||
logger.info("开始批量生成向量嵌入, 数量: {}", contents.size());
|
||||
|
||||
// 确保 API Key 已设置
|
||||
if (Constants.apiKey == null || Constants.apiKey.isEmpty()) {
|
||||
logger.warn("检测到 Constants.apiKey 为空,重新设置");
|
||||
Constants.apiKey = apiKey;
|
||||
}
|
||||
|
||||
// 构建请求参数 - 批量输入
|
||||
TextEmbeddingParam param = TextEmbeddingParam
|
||||
.builder()
|
||||
.model(model)
|
||||
.texts(contents)
|
||||
.build();
|
||||
List<float[]> embeddings = embeddingModel.embed(contents);
|
||||
|
||||
// 调用 API
|
||||
TextEmbeddingResult result = textEmbedding.call(param);
|
||||
|
||||
// 检查结果
|
||||
if (result == null || result.getOutput() == null || result.getOutput().getEmbeddings() == null) {
|
||||
throw new RuntimeException("批量 DashScope API 返回空结果");
|
||||
}
|
||||
|
||||
List<TextEmbeddingResultItem> embeddingItems = result.getOutput().getEmbeddings();
|
||||
|
||||
if (embeddingItems.isEmpty()) {
|
||||
throw new RuntimeException("批量 DashScope API 返回空向量列表");
|
||||
}
|
||||
|
||||
// 转换结果
|
||||
List<List<Float>> embeddings = new ArrayList<>();
|
||||
for (TextEmbeddingResultItem item : embeddingItems) {
|
||||
List<Double> embeddingDoubles = item.getEmbedding();
|
||||
List<Float> embedding = new ArrayList<>(embeddingDoubles.size());
|
||||
for (Double value : embeddingDoubles) {
|
||||
embedding.add(value.floatValue());
|
||||
List<List<Float>> result = new ArrayList<>();
|
||||
for (float[] embedding : embeddings) {
|
||||
List<Float> floatEmbedding = new ArrayList<>(embedding.length);
|
||||
for (float v : embedding) {
|
||||
floatEmbedding.add(v);
|
||||
}
|
||||
embeddings.add(embedding);
|
||||
result.add(floatEmbedding);
|
||||
}
|
||||
|
||||
logger.info("成功批量生成向量嵌入, 数量: {}, 维度: {}",
|
||||
embeddings.size(),
|
||||
embeddings.isEmpty() ? 0 : embeddings.get(0).size());
|
||||
logger.info("成功批量生成向量嵌入, 数量: {}, 维度: {}",
|
||||
result.size(),
|
||||
result.isEmpty() ? 0 : result.get(0).size());
|
||||
|
||||
return embeddings;
|
||||
return result;
|
||||
|
||||
} catch (NoApiKeyException e) {
|
||||
logger.error("批量调用时 API Key 未设置或无效", e);
|
||||
throw new RuntimeException("API Key 未设置,请配置 dashscope.api.key", e);
|
||||
} catch (Exception e) {
|
||||
logger.error("批量生成向量嵌入失败", e);
|
||||
throw new RuntimeException("批量生成向量嵌入失败: " + e.getMessage(), e);
|
||||
|
||||
Reference in New Issue
Block a user