From e1b8a5f011fbd0164c6617f7ada6012eed9cc4e9 Mon Sep 17 00:00:00 2001 From: yangzhen Date: Mon, 20 Apr 2026 16:07:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8D=83=E9=97=AE3=E9=87=8D?= =?UTF-8?q?=E6=8E=92=E5=BA=8F=E6=A8=A1=E5=9E=8B=EF=BC=8C=E5=B9=B6=E9=99=84?= =?UTF-8?q?=E5=B8=A6=E6=96=B0=E5=A2=9Esql=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/script/sql/update/updat-0420.sql | 46 +++++++ .../dto/request/AliBaiLianRerankRequest.java | 55 ++++++++ .../response/AliBaiLianRerankResponse.java | 81 +++++++++++ .../dto/response/ZhipuRerankResponse.java | 3 + .../impl/AliBaiLianRerankModelService.java | 115 ++++++++++++++++ .../rerank/impl/JinaRerankModelService.java | 107 --------------- .../rerank/impl/ZhiPuRerankModelService.java | 5 +- .../AliBaiLianRerankModelServiceTest.java | 126 ++++++++++++++++++ .../rerank/impl/AliBaiLianRerankTestMain.java | 73 ++++++++++ 9 files changed, 502 insertions(+), 109 deletions(-) create mode 100644 docs/script/sql/update/updat-0420.sql create mode 100644 ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/request/AliBaiLianRerankRequest.java create mode 100644 ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/AliBaiLianRerankResponse.java create mode 100644 ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelService.java delete mode 100644 ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/JinaRerankModelService.java create mode 100644 ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelServiceTest.java create mode 100644 ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankTestMain.java diff --git a/docs/script/sql/update/updat-0420.sql b/docs/script/sql/update/updat-0420.sql new file mode 100644 index 00000000..628a6b5c --- /dev/null +++ b/docs/script/sql/update/updat-0420.sql @@ -0,0 +1,46 @@ +/* + Navicat Premium Dump SQL + + Source Server : localhost-mysql + Source Server Type : MySQL + Source Server Version : 80045 (8.0.45) + Source Host : localhost:3306 + Source Schema : ruoyi-ai + + Target Server Type : MySQL + Target Server Version : 80045 (8.0.45) + File Encoding : 65001 + + Date: 20/04/2026 15:30:00 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- 新增:重排序模型(chat_model) +-- ---------------------------- +INSERT INTO `chat_model` +(id, category, model_name, provider_code, model_describe, model_dimension, model_show, api_host, api_key, create_dept, create_by, create_time, update_by, update_time, remark, tenant_id) +VALUES(2045071617578237953, 'rerank', 'rerank', 'zhipu', '智谱重排序', NULL, 'Y', 'https://open.bigmodel.cn', 'e9xx', 103, 1, '2026-04-17 17:27:24', 1, '2026-04-20 15:21:48', '智谱重排序', 0); + +INSERT INTO `chat_model` +(id, category, model_name, provider_code, model_describe, model_dimension, model_show, api_host, api_key, create_dept, create_by, create_time, update_by, update_time, remark, tenant_id) +VALUES(2046119803482902530, 'rerank', 'qwen3-rerank', 'qianwen', '千问3重排序', NULL, NULL, 'https://dashscope.aliyuncs.com', 'sk-xx', 103, 1, '2026-04-20 14:52:31', 1, '2026-04-20 15:03:13', '千问3文本重排序', 0); + +-- ---------------------------- +-- 新增:字典类型 - 重排序模型分类 +-- ---------------------------- +INSERT INTO `sys_dict_data` +(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) +VALUES(2045070879435259905, '000000', 4, '重排序', 'rerank', 'chat_model_category', NULL, '#000000', 'N', 103, 1, '2026-04-17 17:24:28', 1, '2026-04-19 01:02:20', '重排序模型'); + +-- ---------------------------- +-- 修改表:knowledge_info 增加重排序相关字段 +-- ---------------------------- +ALTER TABLE `knowledge_info` ADD COLUMN `enable_rerank` tinyint DEFAULT 0 NULL COMMENT '是否启用重排序(0否 1是)'; +ALTER TABLE `knowledge_info` ADD COLUMN `rerank_score_threshold` double NULL COMMENT '重排序相关性分数阈值'; +ALTER TABLE `knowledge_info` ADD COLUMN `rerank_top_n` int NULL COMMENT '重排序后返回的文档数量'; +ALTER TABLE `knowledge_info` ADD COLUMN `rerank_model` varchar(100) NULL COMMENT '重排序模型名称'; + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/request/AliBaiLianRerankRequest.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/request/AliBaiLianRerankRequest.java new file mode 100644 index 00000000..285db7c2 --- /dev/null +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/request/AliBaiLianRerankRequest.java @@ -0,0 +1,55 @@ +package org.ruoyi.domain.dto.request; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; + +/** + * 阿里百炼重排序请求DTO(OpenAI兼容格式) + * + * @author yang + * @date 2026-04-20 + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AliBaiLianRerankRequest( + String model, + List documents, + String query, + @JsonProperty("top_n") + Integer topN, + String instruct, + @JsonProperty("return_documents") + Boolean returnDocuments +) { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + /** + * 创建文本重排序请求 + */ + public static AliBaiLianRerankRequest create(String modelName, String query, + List documents, Integer topN, + Boolean returnDocuments) { + return new AliBaiLianRerankRequest( + modelName, + documents, + query, + topN != null ? topN : documents.size(), + null, + returnDocuments != null ? returnDocuments : true + ); + } + + /** + * 转换为JSON字符串 + */ + public String toJson() { + try { + return OBJECT_MAPPER.writeValueAsString(this); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("序列化阿里百炼重排序请求失败", e); + } + } +} diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/AliBaiLianRerankResponse.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/AliBaiLianRerankResponse.java new file mode 100644 index 00000000..3c68267c --- /dev/null +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/AliBaiLianRerankResponse.java @@ -0,0 +1,81 @@ +package org.ruoyi.domain.dto.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.ruoyi.domain.bo.rerank.RerankResult; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 阿里百炼重排序响应DTO(OpenAI兼容格式) + * + * @author yang + * @date 2026-04-20 + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public record AliBaiLianRerankResponse( + String id, + String object, + List results, + UsageInfo usage +) { + /** + * 单个重排序结果项 + */ + @JsonIgnoreProperties(ignoreUnknown = true) + public record ResultItem( + Integer index, + @JsonProperty("relevance_score") + Double relevanceScore, + Object document + ) { + /** + * 获取文档文本内容 + */ + public String getDocumentText() { + if (document == null) return null; + if (document instanceof String) return (String) document; + if (document instanceof Map) { + Object text = ((Map) document).get("text"); + return text != null ? text.toString() : null; + } + return document.toString(); + } + } + + /** + * Token使用信息 + */ + @JsonIgnoreProperties(ignoreUnknown = true) + public record UsageInfo( + @JsonProperty("total_tokens") + Integer totalTokens, + @JsonProperty("prompt_tokens") + Integer promptTokens + ) {} + + /** + * 转换为通用RerankResult + */ + public RerankResult toRerankResult(int totalDocs, long durationMs) { + if (results == null || results.isEmpty()) { + return RerankResult.empty(); + } + + List documents = results.stream() + .map(item -> RerankResult.RerankDocument.builder() + .index(item.index()) + .relevanceScore(item.relevanceScore()) + .document(item.getDocumentText()) + .build()) + .collect(Collectors.toList()); + + return RerankResult.builder() + .documents(documents) + .totalDocuments(totalDocs) + .durationMs(durationMs) + .build(); + } +} diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/ZhipuRerankResponse.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/ZhipuRerankResponse.java index ff08d129..848b1cdc 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/ZhipuRerankResponse.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/domain/dto/response/ZhipuRerankResponse.java @@ -1,5 +1,6 @@ package org.ruoyi.domain.dto.response; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import org.ruoyi.domain.bo.rerank.RerankResult; @@ -12,6 +13,7 @@ import java.util.stream.Collectors; * @author yang * @date 2026-04-19 */ +@JsonIgnoreProperties(ignoreUnknown = true) public record ZhipuRerankResponse( String model, String object, @@ -31,6 +33,7 @@ public record ZhipuRerankResponse( /** * Token使用信息 */ + @JsonIgnoreProperties(ignoreUnknown = true) public record UsageInfo( @JsonProperty("total_tokens") Integer totalTokens, diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelService.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelService.java new file mode 100644 index 00000000..a7975bf8 --- /dev/null +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelService.java @@ -0,0 +1,115 @@ +package org.ruoyi.service.rerank.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; +import org.ruoyi.domain.bo.rerank.RerankRequest; +import org.ruoyi.domain.bo.rerank.RerankResult; +import org.ruoyi.domain.dto.request.AliBaiLianRerankRequest; +import org.ruoyi.domain.dto.response.AliBaiLianRerankResponse; +import org.ruoyi.service.rerank.RerankModelService; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * 阿里百炼重排序模型实现 + * 参考设计模式:AliBaiLianMultiEmbeddingProvider + * + * @author yang + * @date 2026-04-20 + */ +@Slf4j +@Component("qianwenRerank") +public class AliBaiLianRerankModelService implements RerankModelService { + + private final OkHttpClient okHttpClient; + private final ObjectMapper objectMapper = new ObjectMapper(); + private ChatModelVo chatModelVo; + + public AliBaiLianRerankModelService() { + this.okHttpClient = new OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .build(); + } + + @Override + public void configure(ChatModelVo config) { + this.chatModelVo = config; + } + + @Override + public RerankResult rerank(RerankRequest rerankRequest) { + long startTime = System.currentTimeMillis(); + + try { + // 构建请求 + AliBaiLianRerankRequest request = buildRequest(rerankRequest); + AliBaiLianRerankResponse response = executeRequest(request); + + return response.toRerankResult( + rerankRequest.getDocuments().size(), + System.currentTimeMillis() - startTime + ); + + } catch (Exception e) { + log.error("阿里百炼重排序失败: {}", e.getMessage(), e); + throw new RuntimeException("重排序服务调用失败: " + e.getMessage(), e); + } + } + + /** + * 构建请求对象 + */ + private AliBaiLianRerankRequest buildRequest(RerankRequest rerankRequest) { + return AliBaiLianRerankRequest.create( + chatModelVo.getModelName(), + rerankRequest.getQuery(), + rerankRequest.getDocuments(), + rerankRequest.getTopN(), + rerankRequest.getReturnDocuments() + ); + } + + /** + * 执行HTTP请求并解析响应 + */ + private AliBaiLianRerankResponse executeRequest(AliBaiLianRerankRequest request) throws IOException { + String jsonBody = request.toJson(); + RequestBody body = RequestBody.create(jsonBody, MediaType.get("application/json")); + + // 阿里百炼重排序 OpenAI兼容端点 + String url = chatModelVo.getApiHost() + "/compatible-api/v1/reranks"; + Request httpRequest = new Request.Builder() + .url(url) + .addHeader("Authorization", "Bearer " + chatModelVo.getApiKey()) + .addHeader("Content-Type", "application/json") + .post(body) + .build(); + + try (Response response = okHttpClient.newCall(httpRequest).execute()) { + if (!response.isSuccessful()) { + String err = response.body() != null ? response.body().string() : "无错误信息"; + throw new IllegalArgumentException("阿里百炼API调用失败: " + response.code() + " - " + err); + } + + ResponseBody responseBody = response.body(); + if (responseBody == null) { + throw new IllegalArgumentException("响应体为空"); + } + + return parseResponse(responseBody.string()); + } + } + + /** + * 解析响应 + */ + private AliBaiLianRerankResponse parseResponse(String responseBody) throws IOException { + return objectMapper.readValue(responseBody, AliBaiLianRerankResponse.class); + } +} diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/JinaRerankModelService.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/JinaRerankModelService.java deleted file mode 100644 index 642e807d..00000000 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/JinaRerankModelService.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.ruoyi.service.rerank.impl; - -import com.fasterxml.jackson.databind.ObjectMapper; -import dev.langchain4j.http.client.*; -import lombok.extern.slf4j.Slf4j; -import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; -import org.ruoyi.domain.bo.rerank.RerankRequest; -import org.ruoyi.domain.bo.rerank.RerankResult; -import org.ruoyi.service.rerank.RerankModelService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Jina AI 重排序模型实现 - * 参考设计模式:OpenAiEmbeddingProvider - * 使用 Jina 官方重排序API - * - * @author yang - * @date 2026-04-19 - */ -@Slf4j -@Component("jina") -public class JinaRerankModelService implements RerankModelService { - - protected ChatModelVo chatModelVo; - protected HttpClient httpClient; - protected final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public void configure(ChatModelVo config) { - this.chatModelVo = config; - HttpClientBuilder httpClientBuilder = HttpClientBuilderLoader.loadHttpClientBuilder(); - this.httpClient = httpClientBuilder.build(); - } - - @Override - public RerankResult rerank(RerankRequest rerankRequest) { - long startTime = System.currentTimeMillis(); - - try { - // 构建Jina重排序请求体 - Map requestBody = new HashMap<>(); - requestBody.put("model", chatModelVo.getModelName()); - requestBody.put("query", rerankRequest.getQuery()); - requestBody.put("documents", rerankRequest.getDocuments()); - requestBody.put("top_n", rerankRequest.getTopN() != null ? - rerankRequest.getTopN() : rerankRequest.getDocuments().size()); - requestBody.put("return_documents", rerankRequest.getReturnDocuments()); - - // 构建HTTP请求 - HttpRequest httpRequest = HttpRequest.builder() - .url(chatModelVo.getApiHost()) - .method(HttpMethod.POST) - .addHeader("Content-Type", "application/json") - .addHeader("Authorization", "Bearer " + chatModelVo.getApiKey()) - .body(objectMapper.writeValueAsString(requestBody)) - .build(); - - // 发送请求 - SuccessfulHttpResponse httpResponse = httpClient.execute(httpRequest); - - // 解析响应 - @SuppressWarnings("unchecked") - Map response = objectMapper.readValue(httpResponse.body(), Map.class); - return parseResponse(response, rerankRequest.getDocuments().size(), - System.currentTimeMillis() - startTime); - - } catch (Exception e) { - log.error("Jina重排序失败: {}", e.getMessage(), e); - throw new RuntimeException("重排序服务调用失败: " + e.getMessage(), e); - } - } - - /** - * 解析Jina API响应 - */ - @SuppressWarnings("unchecked") - private RerankResult parseResponse(Map response, int totalDocs, long durationMs) { - List> results = (List>) response.get("results"); - if (results == null || results.isEmpty()) { - return RerankResult.empty(); - } - - List documents = new ArrayList<>(); - for (Map result : results) { - Integer index = (Integer) result.get("index"); - Double score = ((Number) result.get("relevance_score")).doubleValue(); - String document = (String) result.get("document"); - - documents.add(RerankResult.RerankDocument.builder() - .index(index) - .relevanceScore(score) - .document(document) - .build()); - } - - return RerankResult.builder() - .documents(documents) - .totalDocuments(totalDocs) - .durationMs(durationMs) - .build(); - } -} diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/ZhiPuRerankModelService.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/ZhiPuRerankModelService.java index ff15908a..54054091 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/ZhiPuRerankModelService.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/service/rerank/impl/ZhiPuRerankModelService.java @@ -90,14 +90,15 @@ public class ZhiPuRerankModelService implements RerankModelService { // 生成智谱认证Token String token = generateToken(chatModelVo.getApiKey()); - String url = chatModelVo.getApiHost() + "/" + chatModelVo.getModelName(); + // 智谱重排序固定端点路径 + String url = chatModelVo.getApiHost() + "/api/paas/v4/rerank"; Request httpRequest = new Request.Builder() .url(url) .addHeader("Authorization", token) .post(body) .build(); - try (okhttp3.Response response = okHttpClient.newCall(httpRequest).execute()) { + try (Response response = okHttpClient.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { String err = response.body() != null ? response.body().string() : "无错误信息"; throw new IllegalArgumentException("智谱API调用失败: " + response.code() + " - " + err); diff --git a/ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelServiceTest.java b/ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelServiceTest.java new file mode 100644 index 00000000..a63ded68 --- /dev/null +++ b/ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankModelServiceTest.java @@ -0,0 +1,126 @@ +package org.ruoyi.service.rerank.impl; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; +import org.ruoyi.domain.bo.rerank.RerankRequest; +import org.ruoyi.domain.bo.rerank.RerankResult; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * 阿里百炼重排序模型测试类 + * 运行前请设置环境变量 DASHSCOPE_API_KEY 或直接修改 apiKey + */ +class AliBaiLianRerankModelServiceTest { + + private AliBaiLianRerankModelService service; + + // 请替换为你的 API Key + private static final String API_KEY = System.getenv("DASHSCOPE_API_KEY"); + private static final String API_HOST = "https://dashscope.aliyuncs.com"; + private static final String MODEL_NAME = "qwen3-rerank"; + + @BeforeEach + void setUp() { + service = new AliBaiLianRerankModelService(); + } + + @Test + void testConfigure() { + ChatModelVo config = createConfig(); + service.configure(config); + assertNotNull(service); + } + + @Test + void testRerank() { + // 跳过测试如果没有配置 API Key + if (API_KEY == null || API_KEY.isEmpty()) { + System.out.println("跳过测试: 未设置环境变量 DASHSCOPE_API_KEY"); + return; + } + + ChatModelVo config = createConfig(); + service.configure(config); + + List documents = Arrays.asList( + "文本排序模型广泛用于搜索引擎和推荐系统中,它们根据文本相关性对候选文本进行排序", + "量子计算是计算科学的一个前沿领域", + "预训练语言模型的发展给文本排序模型带来了新的进展" + ); + + RerankRequest request = RerankRequest.builder() + .query("什么是文本排序模型") + .documents(documents) + .topN(2) + .returnDocuments(true) + .build(); + + RerankResult result = service.rerank(request); + + System.out.println("=== 重排序结果 ==="); + System.out.println("总文档数: " + result.getTotalDocuments()); + System.out.println("耗时: " + result.getDurationMs() + "ms"); + + result.getDocuments().forEach(doc -> { + System.out.println("索引: " + doc.getIndex() + + ", 相关性分数: " + doc.getRelevanceScore() + + ", 文档: " + doc.getDocument()); + }); + + assertNotNull(result); + assertNotNull(result.getDocuments()); + assertFalse(result.getDocuments().isEmpty()); + assertEquals(2, result.getDocuments().size()); + } + + @Test + void testRerankWithFullDocuments() { + if (API_KEY == null || API_KEY.isEmpty()) { + System.out.println("跳过测试: 未设置环境变量 DASHSCOPE_API_KEY"); + return; + } + + ChatModelVo config = createConfig(); + service.configure(config); + + List documents = Arrays.asList( + "Java是一种广泛使用的编程语言", + "Python是人工智能领域最流行的语言", + "Go语言由Google开发,适合并发编程" + ); + + RerankRequest request = RerankRequest.builder() + .query("哪种语言适合AI开发") + .documents(documents) + .build(); + + RerankResult result = service.rerank(request); + + System.out.println("=== 重排序结果2 ==="); + result.getDocuments().forEach(doc -> { + System.out.println("索引: " + doc.getIndex() + + ", 分数: " + doc.getRelevanceScore() + + ", 文档: " + doc.getDocument()); + }); + + assertNotNull(result); + assertEquals(3, result.getDocuments().size()); + + // Python相关文档应该排在前面 + assertEquals(1, result.getDocuments().get(0).getIndex()); + assertTrue(result.getDocuments().get(0).getRelevanceScore() > 0.5); + } + + private ChatModelVo createConfig() { + ChatModelVo config = new ChatModelVo(); + config.setApiHost(API_HOST); + config.setApiKey(API_KEY != null ? API_KEY : "test-api-key"); + config.setModelName(MODEL_NAME); + return config; + } +} diff --git a/ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankTestMain.java b/ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankTestMain.java new file mode 100644 index 00000000..cbd70449 --- /dev/null +++ b/ruoyi-modules/ruoyi-chat/src/test/java/org/ruoyi/service/rerank/impl/AliBaiLianRerankTestMain.java @@ -0,0 +1,73 @@ +package org.ruoyi.service.rerank.impl; + +import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo; +import org.ruoyi.domain.bo.rerank.RerankRequest; +import org.ruoyi.domain.bo.rerank.RerankResult; + +import java.util.Arrays; +import java.util.List; + +/** + * 阿里百炼重排序模型测试 - Main方法直接运行 + * 运行前请设置 API_KEY + */ +public class AliBaiLianRerankTestMain { + + // 请替换为你的 API Key + private static final String API_KEY = "sk-your-api-key-here"; + private static final String API_HOST = "https://dashscope.aliyuncs.com"; + private static final String MODEL_NAME = "qwen3-rerank"; + + public static void main(String[] args) { + AliBaiLianRerankModelService service = new AliBaiLianRerankModelService(); + + // 配置 + ChatModelVo config = new ChatModelVo(); + config.setApiHost(API_HOST); + config.setApiKey(API_KEY); + config.setModelName(MODEL_NAME); + service.configure(config); + + // 测试数据 + List documents = Arrays.asList( + "文本排序模型广泛用于搜索引擎和推荐系统中,它们根据文本相关性对候选文本进行排序", + "量子计算是计算科学的一个前沿领域", + "预训练语言模型的发展给文本排序模型带来了新的进展" + ); + + RerankRequest request = RerankRequest.builder() + .query("什么是文本排序模型") + .documents(documents) + .topN(2) + .returnDocuments(true) + .build(); + + System.out.println("=== 开始测试阿里百炼重排序 ==="); + System.out.println("API Host: " + API_HOST); + System.out.println("Model: " + MODEL_NAME); + System.out.println("Query: 什么是文本排序模型"); + System.out.println(); + + try { + RerankResult result = service.rerank(request); + + System.out.println("=== 重排序结果 ==="); + System.out.println("总文档数: " + result.getTotalDocuments()); + System.out.println("耗时: " + result.getDurationMs() + "ms"); + System.out.println(); + + result.getDocuments().forEach(doc -> { + System.out.println("索引: " + doc.getIndex()); + System.out.println("相关性分数: " + doc.getRelevanceScore()); + System.out.println("文档: " + doc.getDocument()); + System.out.println("---"); + }); + + System.out.println("=== 测试成功 ==="); + + } catch (Exception e) { + System.err.println("=== 测试失败 ==="); + e.printStackTrace(); + } + } +}