Commit 950495a2 by renyizhao

模型列表接口返回数据不全问题

parent 23c4e82f
...@@ -156,6 +156,7 @@ public class AppAiModelController { ...@@ -156,6 +156,7 @@ public class AppAiModelController {
// 2. 构造 model_name -> pricing 索引 // 2. 构造 model_name -> pricing 索引
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Map<String, Object>> modelPricingList = (List<Map<String, Object>>) pricingData.get("data"); List<Map<String, Object>> modelPricingList = (List<Map<String, Object>>) pricingData.get("data");
log.info("[诊断] /api/pricing 返回的 model 数量 = {}", modelPricingList == null ? 0 : modelPricingList.size());
Map<String, Map<String, Object>> pricingIndex = new java.util.HashMap<>(); Map<String, Map<String, Object>> pricingIndex = new java.util.HashMap<>();
if (modelPricingList != null) { if (modelPricingList != null) {
for (Map<String, Object> p : modelPricingList) { for (Map<String, Object> p : modelPricingList) {
...@@ -170,16 +171,16 @@ public class AppAiModelController { ...@@ -170,16 +171,16 @@ public class AppAiModelController {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Map<String, Object>> vendors = (List<Map<String, Object>>) pricingData.get("vendors"); List<Map<String, Object>> vendors = (List<Map<String, Object>>) pricingData.get("vendors");
// 4. 拉取所有模型元数据(分页拉满 // 4. 拉取所有模型元数据(分页循环,因 New API page_size 上限为 100
NewApiResponse<Map<String, Object>> modelsResp = newApiClient.getModels(0, 200); NewApiResponse<List<Map<String, Object>>> modelsResp = newApiClient.getAllModels();
if (modelsResp.getSuccess() == null || !modelsResp.getSuccess() || modelsResp.getData() == null) { if (modelsResp.getSuccess() == null || !modelsResp.getSuccess() || modelsResp.getData() == null) {
log.error("[getModelsWithPricing] 获取模型列表失败:{}", modelsResp.getMessage()); log.error("[getModelsWithPricing] 获取模型列表失败:{}", modelsResp.getMessage());
return CommonResult.error(1, "获取模型列表失败"); return CommonResult.error(1, "获取模型列表失败");
} }
@SuppressWarnings("unchecked") List<Map<String, Object>> items = modelsResp.getData();
List<Map<String, Object>> items = (List<Map<String, Object>>) modelsResp.getData().get("items"); log.info("[诊断] /api/models/ 返回的 items 数量 = {}", items == null ? 0 : items.size());
if (items == null) { if (items == null || items.isEmpty()) {
return CommonResult.success(Collections.emptyList()); return CommonResult.success(Collections.emptyList());
} }
...@@ -287,6 +288,10 @@ public class AppAiModelController { ...@@ -287,6 +288,10 @@ public class AppAiModelController {
result.add(vo); result.add(vo);
} }
log.info("[诊断] 最终返回的模型数量 = {}, 唯一 modelName 数量 = {}",
result.size(),
result.stream().map(AppModelPricingVO::getModelName).distinct().count());
return CommonResult.success(result); return CommonResult.success(result);
} }
......
...@@ -14,6 +14,7 @@ import org.springframework.stereotype.Service; ...@@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
@Slf4j @Slf4j
...@@ -364,6 +365,9 @@ public class NewApiClient { ...@@ -364,6 +365,9 @@ public class NewApiClient {
/** /**
* 获取模型列表(管理员权限) * 获取模型列表(管理员权限)
* GET /api/models/?p=0&page_size=100 * GET /api/models/?p=0&page_size=100
*
* 注意:New API 服务端对 page_size 存在上限(最大 100),
* 超过 100 仍按 100 返回,因此需要分页循环拉取全部模型。
*/ */
public NewApiResponse<Map<String, Object>> getModels(Integer page, Integer pageSize) { public NewApiResponse<Map<String, Object>> getModels(Integer page, Integer pageSize) {
String url = newApiProperties.getBaseUrl() + "/api/models/"; String url = newApiProperties.getBaseUrl() + "/api/models/";
...@@ -396,6 +400,85 @@ public class NewApiClient { ...@@ -396,6 +400,85 @@ public class NewApiClient {
} }
/** /**
* 循环分页拉取全部模型(解决 New API page_size 上限 100 的限制)
*
* <p>注意:New API 的 {@code p} 参数是 <b>1-based</b>(不是 0-based),
* 从 1 开始计数。p=0 会被服务端当作 p=1 处理,导致拉两遍首页。
*
* @return 包含全部模型 items 列表的响应
*/
public NewApiResponse<List<Map<String, Object>>> getAllModels() {
// New API 服务端 page_size 上限为 100,按 100 循环
final int pageSize = 100;
// 安全上限:防止 total 字段异常时死循环
final int maxPages = 200;
List<Map<String, Object>> allItems = new java.util.ArrayList<>();
// 记录已见过的 model_name,作为分页重叠的安全网
java.util.Set<String> seenModelNames = new java.util.HashSet<>();
int total = -1;
// New API 分页从 1 开始(p=0 会被当作 p=1)
for (int page = 1; page <= maxPages; page++) {
NewApiResponse<Map<String, Object>> resp = getModels(page, pageSize);
if (resp.getSuccess() == null || !resp.getSuccess() || resp.getData() == null) {
log.error("[NewApiClient.getAllModels] 第 {} 页拉取失败:{}", page, resp.getMessage());
return NewApiResponse.<List<Map<String, Object>>>builder()
.success(false)
.message("拉取第 " + page + " 页失败: " + resp.getMessage())
.httpResponse(resp.getHttpResponse())
.build();
}
Map<String, Object> data = resp.getData();
// 首次请求解析 total
if (page == 1) {
Object totalObj = data.get("total");
if (totalObj instanceof Number) {
total = ((Number) totalObj).intValue();
} else if (totalObj != null) {
try {
total = Integer.parseInt(totalObj.toString());
} catch (Exception ignored) {
}
}
log.info("[NewApiClient.getAllModels] 模型总数 total={}", total);
}
@SuppressWarnings("unchecked")
List<Map<String, Object>> items = (List<Map<String, Object>>) data.get("items");
if (items == null || items.isEmpty()) {
break;
}
// 按 model_name 去重加入(防御 New API 分页重叠的潜在 bug)
for (Map<String, Object> item : items) {
Object nameObj = item.get("model_name");
if (nameObj == null) continue;
if (seenModelNames.add(nameObj.toString())) {
allItems.add(item);
}
}
// 终止条件 1:已拉满 total
if (total > 0 && allItems.size() >= total) {
break;
}
// 终止条件 2:本次返回不足一页(最后一页)
if (items.size() < pageSize) {
break;
}
}
log.info("[NewApiClient.getAllModels] 去重后模型数={}, 期望 total={}", allItems.size(), total);
NewApiResponse<List<Map<String, Object>>> result = new NewApiResponse<>();
result.setSuccess(true);
result.setData(allItems);
return result;
}
/**
* 获取个人日志统计 * 获取个人日志统计
* GET /api/log/self/stat?type=0&model_name=&start_timestamp=&end_timestamp= * GET /api/log/self/stat?type=0&model_name=&start_timestamp=&end_timestamp=
* *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment