feat: 新增max_tokens和调整
parent
8703b8bdc7
commit
3df2e753c5
|
|
@ -412,6 +412,7 @@ CREATE TABLE biz_llm_models (
|
||||||
model_code VARCHAR(100),
|
model_code VARCHAR(100),
|
||||||
temperature DECIMAL(3,2) DEFAULT 0.7,
|
temperature DECIMAL(3,2) DEFAULT 0.7,
|
||||||
top_p DECIMAL(3,2) DEFAULT 0.9,
|
top_p DECIMAL(3,2) DEFAULT 0.9,
|
||||||
|
max_tokens BIGINT NOT NULL DEFAULT 30000,
|
||||||
is_default SMALLINT DEFAULT 0,
|
is_default SMALLINT DEFAULT 0,
|
||||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||||
status SMALLINT DEFAULT 1,
|
status SMALLINT DEFAULT 1,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.imeeting.dto.biz;
|
package com.imeeting.dto.biz;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -32,6 +33,9 @@ public class AiModelDTO {
|
||||||
private BigDecimal temperature;
|
private BigDecimal temperature;
|
||||||
@Schema(description = "TopP 参数")
|
@Schema(description = "TopP 参数")
|
||||||
private BigDecimal topP;
|
private BigDecimal topP;
|
||||||
|
@JsonProperty("max_tokens")
|
||||||
|
@Schema(description = "最大输出 token 数")
|
||||||
|
private Long maxTokens;
|
||||||
@Schema(description = "媒体配置")
|
@Schema(description = "媒体配置")
|
||||||
private Map<String, Object> mediaConfig;
|
private Map<String, Object> mediaConfig;
|
||||||
@Schema(description = "是否默认")
|
@Schema(description = "是否默认")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.imeeting.dto.biz;
|
package com.imeeting.dto.biz;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -33,6 +34,9 @@ public class AiModelVO {
|
||||||
private BigDecimal temperature;
|
private BigDecimal temperature;
|
||||||
@Schema(description = "TopP 参数")
|
@Schema(description = "TopP 参数")
|
||||||
private BigDecimal topP;
|
private BigDecimal topP;
|
||||||
|
@JsonProperty("max_tokens")
|
||||||
|
@Schema(description = "最大输出 token 数")
|
||||||
|
private Long maxTokens;
|
||||||
@Schema(description = "多媒体配置")
|
@Schema(description = "多媒体配置")
|
||||||
private Map<String, Object> mediaConfig;
|
private Map<String, Object> mediaConfig;
|
||||||
@Schema(description = "是否为默认模型")
|
@Schema(description = "是否为默认模型")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.imeeting.entity.biz;
|
package com.imeeting.entity.biz;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.unisbase.entity.BaseEntity;
|
import com.unisbase.entity.BaseEntity;
|
||||||
|
|
@ -43,6 +44,10 @@ public class LlmModel extends BaseEntity {
|
||||||
@Schema(description = "Top P参数")
|
@Schema(description = "Top P参数")
|
||||||
private BigDecimal topP;
|
private BigDecimal topP;
|
||||||
|
|
||||||
|
@TableField("max_tokens")
|
||||||
|
@Schema(description = "最大输出 token 数")
|
||||||
|
private Long maxTokens;
|
||||||
|
|
||||||
@Schema(description = "是否默认模型")
|
@Schema(description = "是否默认模型")
|
||||||
private Integer isDefault;
|
private Integer isDefault;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
private static final String MEDIA_TENCENT_OFFLINE_MODEL_CODE = "tencentOfflineModelCode";
|
private static final String MEDIA_TENCENT_OFFLINE_MODEL_CODE = "tencentOfflineModelCode";
|
||||||
private static final String MEDIA_TENCENT_REALTIME_MODEL_CODE = "tencentRealtimeModelCode";
|
private static final String MEDIA_TENCENT_REALTIME_MODEL_CODE = "tencentRealtimeModelCode";
|
||||||
private static final int DEFAULT_SORT_ORDER = 0;
|
private static final int DEFAULT_SORT_ORDER = 0;
|
||||||
|
private static final long DEFAULT_LLM_MAX_TOKENS = 30000L;
|
||||||
private static final String DEFAULT_LLM_API_PATH = "/v1/chat/completions";
|
private static final String DEFAULT_LLM_API_PATH = "/v1/chat/completions";
|
||||||
private static final String DEFAULT_ANTHROPIC_API_PATH = "/messages";
|
private static final String DEFAULT_ANTHROPIC_API_PATH = "/messages";
|
||||||
private static final String CONNECTIVITY_TEST_SYSTEM_PROMPT = """
|
private static final String CONNECTIVITY_TEST_SYSTEM_PROMPT = """
|
||||||
|
|
@ -397,7 +398,7 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
Map<String, Object> body = new LinkedHashMap<>();
|
Map<String, Object> body = new LinkedHashMap<>();
|
||||||
body.put("model", dto.getModelCode().trim());
|
body.put("model", dto.getModelCode().trim());
|
||||||
body.put("stream", false);
|
body.put("stream", false);
|
||||||
body.put("max_tokens", 32);
|
body.put("max_tokens", resolveConnectivityMaxTokens(dto.getMaxTokens()));
|
||||||
if (dto.getTemperature() != null) {
|
if (dto.getTemperature() != null) {
|
||||||
body.put("temperature", dto.getTemperature());
|
body.put("temperature", dto.getTemperature());
|
||||||
}
|
}
|
||||||
|
|
@ -425,7 +426,7 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
Map<String, Object> body = new LinkedHashMap<>();
|
Map<String, Object> body = new LinkedHashMap<>();
|
||||||
body.put("model", dto.getModelCode().trim());
|
body.put("model", dto.getModelCode().trim());
|
||||||
body.put("system", CONNECTIVITY_TEST_SYSTEM_PROMPT);
|
body.put("system", CONNECTIVITY_TEST_SYSTEM_PROMPT);
|
||||||
body.put("max_tokens", 32);
|
body.put("max_tokens", resolveConnectivityMaxTokens(dto.getMaxTokens()));
|
||||||
body.put("messages", List.of(
|
body.put("messages", List.of(
|
||||||
Map.of("role", "user", "content", resolveTestMessage(dto.getTestMessage()))
|
Map.of("role", "user", "content", resolveTestMessage(dto.getTestMessage()))
|
||||||
));
|
));
|
||||||
|
|
@ -461,7 +462,7 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
"parts", List.of(Map.of("text", resolveTestMessage(dto.getTestMessage())))
|
"parts", List.of(Map.of("text", resolveTestMessage(dto.getTestMessage())))
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
if (dto.getTemperature() != null || dto.getTopP() != null) {
|
if (dto.getTemperature() != null || dto.getTopP() != null || dto.getMaxTokens() != null) {
|
||||||
Map<String, Object> generationConfig = new LinkedHashMap<>();
|
Map<String, Object> generationConfig = new LinkedHashMap<>();
|
||||||
if (dto.getTemperature() != null) {
|
if (dto.getTemperature() != null) {
|
||||||
generationConfig.put("temperature", dto.getTemperature());
|
generationConfig.put("temperature", dto.getTemperature());
|
||||||
|
|
@ -469,6 +470,9 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
if (dto.getTopP() != null) {
|
if (dto.getTopP() != null) {
|
||||||
generationConfig.put("topP", dto.getTopP());
|
generationConfig.put("topP", dto.getTopP());
|
||||||
}
|
}
|
||||||
|
if (dto.getMaxTokens() != null) {
|
||||||
|
generationConfig.put("maxOutputTokens", resolveConnectivityMaxTokens(dto.getMaxTokens()));
|
||||||
|
}
|
||||||
body.put("generationConfig", generationConfig);
|
body.put("generationConfig", generationConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -874,6 +878,11 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
if (Integer.valueOf(1).equals(dto.getIsDefault()) && !Integer.valueOf(1).equals(dto.getStatus())) {
|
if (Integer.valueOf(1).equals(dto.getIsDefault()) && !Integer.valueOf(1).equals(dto.getStatus())) {
|
||||||
throw new RuntimeException("默认模型必须为启用状态");
|
throw new RuntimeException("默认模型必须为启用状态");
|
||||||
}
|
}
|
||||||
|
if (TYPE_LLM.equals(normalizeType(dto.getModelType()))
|
||||||
|
&& dto.getMaxTokens() != null
|
||||||
|
&& dto.getMaxTokens() <= 0) {
|
||||||
|
throw new RuntimeException("max_tokens 必须为正整数");
|
||||||
|
}
|
||||||
validateTencentAsrConfig(dto);
|
validateTencentAsrConfig(dto);
|
||||||
// if ("custom".equals(normalizeProvider(dto.getProvider()))) {
|
// if ("custom".equals(normalizeProvider(dto.getProvider()))) {
|
||||||
// if (TYPE_ASR.equals(normalizeType(dto.getModelType()))) {
|
// if (TYPE_ASR.equals(normalizeType(dto.getModelType()))) {
|
||||||
|
|
@ -1178,12 +1187,21 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
entity.setModelCode(dto.getModelCode());
|
entity.setModelCode(dto.getModelCode());
|
||||||
entity.setTemperature(dto.getTemperature() == null ? BigDecimal.valueOf(0.2) : dto.getTemperature());
|
entity.setTemperature(dto.getTemperature() == null ? BigDecimal.valueOf(0.2) : dto.getTemperature());
|
||||||
entity.setTopP(dto.getTopP() == null ? BigDecimal.valueOf(0.9) : dto.getTopP());
|
entity.setTopP(dto.getTopP() == null ? BigDecimal.valueOf(0.9) : dto.getTopP());
|
||||||
|
entity.setMaxTokens(resolveMaxTokens(dto.getMaxTokens()));
|
||||||
entity.setIsDefault(dto.getIsDefault());
|
entity.setIsDefault(dto.getIsDefault());
|
||||||
entity.setStatus(dto.getStatus());
|
entity.setStatus(dto.getStatus());
|
||||||
entity.setSortOrder(normalizeSortOrder(dto.getSortOrder()));
|
entity.setSortOrder(normalizeSortOrder(dto.getSortOrder()));
|
||||||
entity.setRemark(dto.getRemark());
|
entity.setRemark(dto.getRemark());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Long resolveMaxTokens(Long maxTokens) {
|
||||||
|
return maxTokens == null ? DEFAULT_LLM_MAX_TOKENS : maxTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long resolveConnectivityMaxTokens(Long maxTokens) {
|
||||||
|
return maxTokens == null ? 32L : maxTokens;
|
||||||
|
}
|
||||||
|
|
||||||
private AiModelVO toAsrVO(AsrModel entity) {
|
private AiModelVO toAsrVO(AsrModel entity) {
|
||||||
return toAsrVO(entity, null, true);
|
return toAsrVO(entity, null, true);
|
||||||
}
|
}
|
||||||
|
|
@ -1281,6 +1299,7 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
vo.setModelCode(entity.getModelCode());
|
vo.setModelCode(entity.getModelCode());
|
||||||
vo.setTemperature(entity.getTemperature());
|
vo.setTemperature(entity.getTemperature());
|
||||||
vo.setTopP(entity.getTopP());
|
vo.setTopP(entity.getTopP());
|
||||||
|
vo.setMaxTokens(resolveMaxTokens(entity.getMaxTokens()));
|
||||||
vo.setIsDefault(entity.getIsDefault());
|
vo.setIsDefault(entity.getIsDefault());
|
||||||
vo.setStatus(entity.getStatus());
|
vo.setStatus(entity.getStatus());
|
||||||
vo.setScope(Long.valueOf(0L).equals(entity.getTenantId()) ? "PLATFORM" : "TENANT");
|
vo.setScope(Long.valueOf(0L).equals(entity.getTenantId()) ? "PLATFORM" : "TENANT");
|
||||||
|
|
|
||||||
|
|
@ -1325,7 +1325,7 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
|
||||||
Map<String, Object> req = new HashMap<>();
|
Map<String, Object> req = new HashMap<>();
|
||||||
req.put("model", llmModel.getModelCode());
|
req.put("model", llmModel.getModelCode());
|
||||||
req.put("temperature", llmModel.getTemperature());
|
req.put("temperature", llmModel.getTemperature());
|
||||||
req.put("max_tokens", 30000);
|
req.put("max_tokens", llmModel.getMaxTokens() == null ? 30000L : llmModel.getMaxTokens());
|
||||||
req.put("messages", List.of(
|
req.put("messages", List.of(
|
||||||
Map.of("role", "system", "content", meetingSummaryPromptAssembler.buildSystemMessage(taskRecord.getTaskConfig())),
|
Map.of("role", "system", "content", meetingSummaryPromptAssembler.buildSystemMessage(taskRecord.getTaskConfig())),
|
||||||
Map.of("role", "user", "content", meetingSummaryPromptAssembler.buildUserMessage(taskRecord.getTaskConfig(), meeting, summarySource, userPrompt))
|
Map.of("role", "user", "content", meetingSummaryPromptAssembler.buildUserMessage(taskRecord.getTaskConfig(), meeting, summarySource, userPrompt))
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,7 @@ public class MeetingExternalSummaryWebhookTrigger {
|
||||||
config.put("modelCode", model.getModelCode());
|
config.put("modelCode", model.getModelCode());
|
||||||
config.put("temperature", model.getTemperature());
|
config.put("temperature", model.getTemperature());
|
||||||
config.put("topP", model.getTopP());
|
config.put("topP", model.getTopP());
|
||||||
|
config.put("max_tokens", model.getMaxTokens() == null ? 30000L : model.getMaxTokens());
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,7 @@ public class MeetingTranscriptChapterServiceImpl implements MeetingTranscriptCha
|
||||||
Map<String, Object> requestBody = new LinkedHashMap<>();
|
Map<String, Object> requestBody = new LinkedHashMap<>();
|
||||||
requestBody.put("model", llmModel.getModelCode());
|
requestBody.put("model", llmModel.getModelCode());
|
||||||
requestBody.put("temperature", llmModel.getTemperature());
|
requestBody.put("temperature", llmModel.getTemperature());
|
||||||
requestBody.put("max_tokens", 30000);
|
requestBody.put("max_tokens", llmModel.getMaxTokens() == null ? 30000L : llmModel.getMaxTokens());
|
||||||
requestBody.put("messages", List.of(
|
requestBody.put("messages", List.of(
|
||||||
Map.of("role", "system", "content", renderChapterSystemPrompt()),
|
Map.of("role", "system", "content", renderChapterSystemPrompt()),
|
||||||
Map.of("role", "user", "content", renderChapterUserPrompt(transcripts))
|
Map.of("role", "user", "content", renderChapterUserPrompt(transcripts))
|
||||||
|
|
@ -1015,7 +1015,7 @@ public class MeetingTranscriptChapterServiceImpl implements MeetingTranscriptCha
|
||||||
Map<String, Object> requestBody = new LinkedHashMap<>();
|
Map<String, Object> requestBody = new LinkedHashMap<>();
|
||||||
requestBody.put("model", llmModel.getModelCode());
|
requestBody.put("model", llmModel.getModelCode());
|
||||||
requestBody.put("temperature", llmModel.getTemperature());
|
requestBody.put("temperature", llmModel.getTemperature());
|
||||||
requestBody.put("max_tokens", 30000);
|
requestBody.put("max_tokens", llmModel.getMaxTokens() == null ? 30000L : llmModel.getMaxTokens());
|
||||||
requestBody.put("messages", List.of(
|
requestBody.put("messages", List.of(
|
||||||
Map.of("role", "system", "content", renderChapterSystemPrompt()),
|
Map.of("role", "system", "content", renderChapterSystemPrompt()),
|
||||||
Map.of("role", "user", "content", renderChapterUserPrompt(transcripts))
|
Map.of("role", "user", "content", renderChapterUserPrompt(transcripts))
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,64 @@ class AiModelServiceImplTest {
|
||||||
assertEquals(7, captor.getValue().getSortOrder());
|
assertEquals(7, captor.getValue().getSortOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void saveModelShouldPersistMaxTokensForLlm() throws Exception {
|
||||||
|
AsrModelMapper asrModelMapper = mock(AsrModelMapper.class);
|
||||||
|
LlmModelMapper llmModelMapper = mock(LlmModelMapper.class);
|
||||||
|
when(llmModelMapper.insert(any(LlmModel.class))).thenReturn(1);
|
||||||
|
|
||||||
|
AiModelServiceImpl service = new AiModelServiceImpl(
|
||||||
|
objectMapper,
|
||||||
|
asrModelMapper,
|
||||||
|
llmModelMapper
|
||||||
|
);
|
||||||
|
|
||||||
|
AiModelDTO dto = new AiModelDTO();
|
||||||
|
dto.setModelType("LLM");
|
||||||
|
dto.setModelName("max-token-llm");
|
||||||
|
dto.setProvider("openai");
|
||||||
|
dto.setBaseUrl("http://127.0.0.1:9000");
|
||||||
|
dto.setApiPath("/v1/chat/completions");
|
||||||
|
dto.setModelCode("gpt-test");
|
||||||
|
dto.setMaxTokens(8192L);
|
||||||
|
dto.setIsDefault(0);
|
||||||
|
dto.setStatus(1);
|
||||||
|
|
||||||
|
AiModelVO result = service.saveModel(dto);
|
||||||
|
|
||||||
|
ArgumentCaptor<LlmModel> captor = ArgumentCaptor.forClass(LlmModel.class);
|
||||||
|
verify(llmModelMapper, times(1)).insert(captor.capture());
|
||||||
|
assertEquals(8192L, captor.getValue().getMaxTokens());
|
||||||
|
assertEquals(8192L, result.getMaxTokens());
|
||||||
|
|
||||||
|
JsonNode json = objectMapper.readTree(objectMapper.writeValueAsString(result));
|
||||||
|
assertEquals(8192L, json.path("max_tokens").asLong());
|
||||||
|
assertEquals(false, json.has("maxTokens"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void saveModelShouldRejectNonPositiveMaxTokensForLlm() {
|
||||||
|
AiModelServiceImpl service = new AiModelServiceImpl(
|
||||||
|
objectMapper,
|
||||||
|
mock(AsrModelMapper.class),
|
||||||
|
mock(LlmModelMapper.class)
|
||||||
|
);
|
||||||
|
|
||||||
|
AiModelDTO dto = new AiModelDTO();
|
||||||
|
dto.setModelType("LLM");
|
||||||
|
dto.setModelName("invalid-max-token-llm");
|
||||||
|
dto.setProvider("openai");
|
||||||
|
dto.setBaseUrl("http://127.0.0.1:9000");
|
||||||
|
dto.setApiPath("/v1/chat/completions");
|
||||||
|
dto.setModelCode("gpt-test");
|
||||||
|
dto.setMaxTokens(0L);
|
||||||
|
dto.setIsDefault(0);
|
||||||
|
dto.setStatus(1);
|
||||||
|
|
||||||
|
RuntimeException ex = assertThrows(RuntimeException.class, () -> service.saveModel(dto));
|
||||||
|
assertEquals("max_tokens 必须为正整数", ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void saveModelShouldRejectDisabledDefaultModel() {
|
void saveModelShouldRejectDisabledDefaultModel() {
|
||||||
AiModelServiceImpl service = new AiModelServiceImpl(
|
AiModelServiceImpl service = new AiModelServiceImpl(
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ export interface AiModelVO {
|
||||||
wsUrl?: string;
|
wsUrl?: string;
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
topP?: number;
|
topP?: number;
|
||||||
|
max_tokens?: number;
|
||||||
mediaConfig?: Record<string, any>;
|
mediaConfig?: Record<string, any>;
|
||||||
isDefault: number;
|
isDefault: number;
|
||||||
status: number;
|
status: number;
|
||||||
|
|
@ -47,6 +48,7 @@ export interface AiModelDTO {
|
||||||
wsUrl?: string;
|
wsUrl?: string;
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
topP?: number;
|
topP?: number;
|
||||||
|
max_tokens?: number;
|
||||||
mediaConfig?: Record<string, any>;
|
mediaConfig?: Record<string, any>;
|
||||||
isDefault: number;
|
isDefault: number;
|
||||||
status: number;
|
status: number;
|
||||||
|
|
@ -157,6 +159,7 @@ export const testLlmModelConnectivity = (data: {
|
||||||
modelCode: string;
|
modelCode: string;
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
topP?: number;
|
topP?: number;
|
||||||
|
max_tokens?: number;
|
||||||
testMessage: string;
|
testMessage: string;
|
||||||
}) => {
|
}) => {
|
||||||
return http.post<{ code: string; data: boolean; msg: string }>(
|
return http.post<{ code: string; data: boolean; msg: string }>(
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,7 @@ const AiModels: React.FC = () => {
|
||||||
: undefined,
|
: undefined,
|
||||||
temperature: values.temperature,
|
temperature: values.temperature,
|
||||||
topP: values.topP,
|
topP: values.topP,
|
||||||
|
max_tokens: values.max_tokens,
|
||||||
isDefault: values.isDefaultChecked ? 1 : 0,
|
isDefault: values.isDefaultChecked ? 1 : 0,
|
||||||
status: values.statusChecked ? 1 : 0,
|
status: values.statusChecked ? 1 : 0,
|
||||||
sortOrder: values.sortOrder ?? 0,
|
sortOrder: values.sortOrder ?? 0,
|
||||||
|
|
@ -347,8 +348,8 @@ const AiModels: React.FC = () => {
|
||||||
|
|
||||||
const handleTestConnectivity = async () => {
|
const handleTestConnectivity = async () => {
|
||||||
if (activeType === "LLM") {
|
if (activeType === "LLM") {
|
||||||
const values = await form.validateFields(["provider", "baseUrl", "apiPath", "modelCode"]);
|
const values = await form.validateFields(["provider", "baseUrl", "apiPath", "modelCode", "max_tokens"]);
|
||||||
const extraValues = form.getFieldsValue(["apiKey", "temperature", "topP"]);
|
const extraValues = form.getFieldsValue(["apiKey", "temperature", "topP", "max_tokens"]);
|
||||||
setConnectivityLoading(true);
|
setConnectivityLoading(true);
|
||||||
try {
|
try {
|
||||||
await testLlmModelConnectivity({
|
await testLlmModelConnectivity({
|
||||||
|
|
@ -359,6 +360,7 @@ const AiModels: React.FC = () => {
|
||||||
modelCode: values.modelCode,
|
modelCode: values.modelCode,
|
||||||
temperature: extraValues.temperature,
|
temperature: extraValues.temperature,
|
||||||
topP: extraValues.topP,
|
topP: extraValues.topP,
|
||||||
|
max_tokens: extraValues.max_tokens,
|
||||||
testMessage: DEFAULT_LLM_TEST_MESSAGE,
|
testMessage: DEFAULT_LLM_TEST_MESSAGE,
|
||||||
});
|
});
|
||||||
message.success("LLM 连通性测试成功");
|
message.success("LLM 连通性测试成功");
|
||||||
|
|
@ -773,16 +775,38 @@ const AiModels: React.FC = () => {
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Row gutter={16} className="app-responsive-form-row">
|
<Row gutter={16} className="app-responsive-form-row">
|
||||||
<Col xs={24} md={12}>
|
<Col xs={24} md={8}>
|
||||||
<Form.Item name="temperature" label="Temperature">
|
<Form.Item name="temperature" label="Temperature">
|
||||||
<InputNumber min={0} max={2} step={0.1} style={{ width: "100%" }} />
|
<InputNumber min={0} max={2} step={0.1} style={{ width: "100%" }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} md={12}>
|
<Col xs={24} md={8}>
|
||||||
<Form.Item name="topP" label="Top P">
|
<Form.Item name="topP" label="Top P">
|
||||||
<InputNumber min={0} max={1} step={0.1} style={{ width: "100%" }} />
|
<InputNumber min={0} max={1} step={0.1} style={{ width: "100%" }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col xs={24} md={8}>
|
||||||
|
<Form.Item
|
||||||
|
name="max_tokens"
|
||||||
|
label="max_tokens"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: "请输入 max_tokens" },
|
||||||
|
{
|
||||||
|
validator: (_, value) => {
|
||||||
|
if (value === undefined || value === null || value === "") {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
if (Number.isInteger(value) && value > 0) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error("max_tokens 必须为正整数"));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber min={1} precision={0} style={{ width: "100%" }} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue