feat: 添加腾讯离线和实时 ASR 模型配置并优化相关逻辑
- 在 `AiModelServiceImpl` 和 `AiTaskServiceImpl` 中添加处理腾讯离线和实时 ASR 模型的逻辑 - 更新前端 `AiModels` 页面,支持腾讯 ASR 配置表单字段 - 在 `RealtimeMeetingSocketSessionServiceImpl` 中添加解析腾讯实时模型代码的方法 - 更新单元测试以验证腾讯 ASR 模型保存逻辑dev_na
parent
982425e21e
commit
57f343ddfd
|
|
@ -205,7 +205,7 @@ public class LegacyMeetingAdapterServiceImpl implements LegacyMeetingAdapterServ
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
true,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
List.of()
|
List.of()
|
||||||
|
|
@ -281,7 +281,7 @@ public class LegacyMeetingAdapterServiceImpl implements LegacyMeetingAdapterServ
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
true,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
List.of()
|
List.of()
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
private static final String MEDIA_TENCENT_APP_ID = "tencentAppId";
|
private static final String MEDIA_TENCENT_APP_ID = "tencentAppId";
|
||||||
private static final String MEDIA_TENCENT_SECRET_ID = "tencentSecretId";
|
private static final String MEDIA_TENCENT_SECRET_ID = "tencentSecretId";
|
||||||
private static final String MEDIA_TENCENT_SECRET_KEY = "tencentSecretKey";
|
private static final String MEDIA_TENCENT_SECRET_KEY = "tencentSecretKey";
|
||||||
|
private static final String MEDIA_TENCENT_OFFLINE_MODEL_CODE = "tencentOfflineModelCode";
|
||||||
|
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 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";
|
||||||
|
|
@ -964,8 +966,11 @@ public class AiModelServiceImpl implements AiModelService {
|
||||||
if (readConfigString(mediaConfig.get(MEDIA_TENCENT_SECRET_KEY)) == null) {
|
if (readConfigString(mediaConfig.get(MEDIA_TENCENT_SECRET_KEY)) == null) {
|
||||||
throw new RuntimeException("腾讯 ASR 模型必须配置 mediaConfig.tencentSecretKey");
|
throw new RuntimeException("腾讯 ASR 模型必须配置 mediaConfig.tencentSecretKey");
|
||||||
}
|
}
|
||||||
if (dto.getModelCode() == null || dto.getModelCode().isBlank()) {
|
if (readConfigString(mediaConfig.get(MEDIA_TENCENT_OFFLINE_MODEL_CODE)) == null) {
|
||||||
throw new RuntimeException("腾讯 ASR 模型必须配置 modelCode");
|
throw new RuntimeException("腾讯 ASR 模型必须配置 mediaConfig.tencentOfflineModelCode");
|
||||||
|
}
|
||||||
|
if (readConfigString(mediaConfig.get(MEDIA_TENCENT_REALTIME_MODEL_CODE)) == null) {
|
||||||
|
throw new RuntimeException("腾讯 ASR 模型必须配置 mediaConfig.tencentRealtimeModelCode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
|
||||||
private static final String MEDIA_TENCENT_APP_ID = "tencentAppId";
|
private static final String MEDIA_TENCENT_APP_ID = "tencentAppId";
|
||||||
private static final String MEDIA_TENCENT_SECRET_ID = "tencentSecretId";
|
private static final String MEDIA_TENCENT_SECRET_ID = "tencentSecretId";
|
||||||
private static final String MEDIA_TENCENT_SECRET_KEY = "tencentSecretKey";
|
private static final String MEDIA_TENCENT_SECRET_KEY = "tencentSecretKey";
|
||||||
|
private static final String MEDIA_TENCENT_OFFLINE_MODEL_CODE = "tencentOfflineModelCode";
|
||||||
private static final String TENCENT_ASR_REGION = "ap-guangzhou";
|
private static final String TENCENT_ASR_REGION = "ap-guangzhou";
|
||||||
|
|
||||||
private final MeetingMapper meetingMapper;
|
private final MeetingMapper meetingMapper;
|
||||||
|
|
@ -756,7 +757,7 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
|
||||||
|
|
||||||
protected Map<String, Object> buildTencentOfflineCreateRequest(Meeting meeting, AiTask taskRecord, AiModelVO asrModel) {
|
protected Map<String, Object> buildTencentOfflineCreateRequest(Meeting meeting, AiTask taskRecord, AiModelVO asrModel) {
|
||||||
Map<String, Object> req = new HashMap<>();
|
Map<String, Object> req = new HashMap<>();
|
||||||
req.put("engineModelType", asrModel.getModelCode());
|
req.put("engineModelType", resolveTencentOfflineModelCode(asrModel));
|
||||||
req.put("channelNum", 1L);
|
req.put("channelNum", 1L);
|
||||||
req.put("resTextFormat", 2L);
|
req.put("resTextFormat", 2L);
|
||||||
req.put("sourceType", 0L);
|
req.put("sourceType", 0L);
|
||||||
|
|
@ -1646,6 +1647,15 @@ public class AiTaskServiceImpl extends ServiceImpl<AiTaskMapper, AiTask> impleme
|
||||||
transcript.setEndTime(endTime);
|
transcript.setEndTime(endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveTencentOfflineModelCode(AiModelVO asrModel) {
|
||||||
|
Map<String, Object> mediaConfig = asrModel == null || asrModel.getMediaConfig() == null ? Map.of() : asrModel.getMediaConfig();
|
||||||
|
String offlineModelCode = stringValue(mediaConfig.get(MEDIA_TENCENT_OFFLINE_MODEL_CODE));
|
||||||
|
if (offlineModelCode != null && !offlineModelCode.isBlank()) {
|
||||||
|
return offlineModelCode.trim();
|
||||||
|
}
|
||||||
|
return asrModel == null ? null : asrModel.getModelCode();
|
||||||
|
}
|
||||||
|
|
||||||
private AiModelVO resolveAsrModelForRevision(AiTask asrTask) {
|
private AiModelVO resolveAsrModelForRevision(AiTask asrTask) {
|
||||||
if (asrTask == null || asrTask.getTaskConfig() == null) {
|
if (asrTask == null || asrTask.getTaskConfig() == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ import java.util.UUID;
|
||||||
public class RealtimeMeetingSocketSessionServiceImpl implements RealtimeMeetingSocketSessionService {
|
public class RealtimeMeetingSocketSessionServiceImpl implements RealtimeMeetingSocketSessionService {
|
||||||
|
|
||||||
private static final String WS_PATH = "/ws/meeting/realtime";
|
private static final String WS_PATH = "/ws/meeting/realtime";
|
||||||
|
private static final String TENCENT_PROVIDER = "tencent";
|
||||||
|
private static final String MEDIA_TENCENT_REALTIME_MODEL_CODE = "tencentRealtimeModelCode";
|
||||||
|
|
||||||
private final RealtimeMeetingSocketSessionCache socketSessionCache;
|
private final RealtimeMeetingSocketSessionCache socketSessionCache;
|
||||||
private final MeetingAccessService meetingAccessService;
|
private final MeetingAccessService meetingAccessService;
|
||||||
|
|
@ -87,7 +89,7 @@ public class RealtimeMeetingSocketSessionServiceImpl implements RealtimeMeetingS
|
||||||
sessionData.setAsrModelId(asrModelId);
|
sessionData.setAsrModelId(asrModelId);
|
||||||
sessionData.setProvider(realtimeAsrChannelFactory.normalizeProvider(asrModel.getProvider()));
|
sessionData.setProvider(realtimeAsrChannelFactory.normalizeProvider(asrModel.getProvider()));
|
||||||
sessionData.setTargetWsUrl(targetWsUrl);
|
sessionData.setTargetWsUrl(targetWsUrl);
|
||||||
sessionData.setModelCode(asrModel.getModelCode());
|
sessionData.setModelCode(resolveRealtimeModelCode(asrModel));
|
||||||
sessionData.setMediaConfig(asrModel.getMediaConfig());
|
sessionData.setMediaConfig(asrModel.getMediaConfig());
|
||||||
|
|
||||||
String sessionToken = UUID.randomUUID().toString().replace("-", "");
|
String sessionToken = UUID.randomUUID().toString().replace("-", "");
|
||||||
|
|
@ -111,6 +113,25 @@ public class RealtimeMeetingSocketSessionServiceImpl implements RealtimeMeetingS
|
||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String resolveRealtimeModelCode(AiModelVO asrModel) {
|
||||||
|
if (asrModel == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!TENCENT_PROVIDER.equalsIgnoreCase(asrModel.getProvider())) {
|
||||||
|
return asrModel.getModelCode();
|
||||||
|
}
|
||||||
|
Map<String, Object> mediaConfig = asrModel.getMediaConfig();
|
||||||
|
if (mediaConfig == null) {
|
||||||
|
return asrModel.getModelCode();
|
||||||
|
}
|
||||||
|
Object realtimeModelCode = mediaConfig.get(MEDIA_TENCENT_REALTIME_MODEL_CODE);
|
||||||
|
if (realtimeModelCode == null) {
|
||||||
|
return asrModel.getModelCode();
|
||||||
|
}
|
||||||
|
String value = String.valueOf(realtimeModelCode).trim();
|
||||||
|
return value.isEmpty() ? asrModel.getModelCode() : value;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RealtimeSocketSessionData getSessionData(String sessionToken) {
|
public RealtimeSocketSessionData getSessionData(String sessionToken) {
|
||||||
return socketSessionCache.get(sessionToken);
|
return socketSessionCache.get(sessionToken);
|
||||||
|
|
|
||||||
|
|
@ -397,6 +397,31 @@ class AiModelServiceImplTest {
|
||||||
assertEquals("腾讯 ASR 模型必须配置 mediaConfig.tencentSecretKey", ex.getMessage());
|
assertEquals("腾讯 ASR 模型必须配置 mediaConfig.tencentSecretKey", ex.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void saveModelShouldRejectTencentAsrWithoutRealtimeModelCode() {
|
||||||
|
AiModelServiceImpl service = new AiModelServiceImpl(
|
||||||
|
objectMapper,
|
||||||
|
mock(AsrModelMapper.class),
|
||||||
|
mock(LlmModelMapper.class)
|
||||||
|
);
|
||||||
|
|
||||||
|
AiModelDTO dto = new AiModelDTO();
|
||||||
|
dto.setModelType("ASR");
|
||||||
|
dto.setModelName("tencent-asr");
|
||||||
|
dto.setProvider("tencent");
|
||||||
|
dto.setIsDefault(0);
|
||||||
|
dto.setStatus(1);
|
||||||
|
dto.setMediaConfig(Map.of(
|
||||||
|
"tencentAppId", "app-id",
|
||||||
|
"tencentSecretId", "secret-id",
|
||||||
|
"tencentSecretKey", "secret-key",
|
||||||
|
"tencentOfflineModelCode", "16k_zh"
|
||||||
|
));
|
||||||
|
|
||||||
|
RuntimeException ex = assertThrows(RuntimeException.class, () -> service.saveModel(dto));
|
||||||
|
assertEquals("腾讯 ASR 模型必须配置 mediaConfig.tencentRealtimeModelCode", ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void saveModelShouldPersistTencentAsrWithoutBaseUrl() {
|
void saveModelShouldPersistTencentAsrWithoutBaseUrl() {
|
||||||
AsrModelMapper asrModelMapper = mock(AsrModelMapper.class);
|
AsrModelMapper asrModelMapper = mock(AsrModelMapper.class);
|
||||||
|
|
@ -412,13 +437,14 @@ class AiModelServiceImplTest {
|
||||||
dto.setModelType("ASR");
|
dto.setModelType("ASR");
|
||||||
dto.setModelName("tencent-asr");
|
dto.setModelName("tencent-asr");
|
||||||
dto.setProvider("tencent");
|
dto.setProvider("tencent");
|
||||||
dto.setModelCode("16k_zh");
|
|
||||||
dto.setIsDefault(0);
|
dto.setIsDefault(0);
|
||||||
dto.setStatus(1);
|
dto.setStatus(1);
|
||||||
dto.setMediaConfig(Map.of(
|
dto.setMediaConfig(Map.of(
|
||||||
"tencentAppId", "app-id",
|
"tencentAppId", "app-id",
|
||||||
"tencentSecretId", "secret-id",
|
"tencentSecretId", "secret-id",
|
||||||
"tencentSecretKey", "secret-key"
|
"tencentSecretKey", "secret-key",
|
||||||
|
"tencentOfflineModelCode", "16k_zh",
|
||||||
|
"tencentRealtimeModelCode", "16k_zh_realtime"
|
||||||
));
|
));
|
||||||
|
|
||||||
service.saveModel(dto);
|
service.saveModel(dto);
|
||||||
|
|
@ -426,7 +452,9 @@ class AiModelServiceImplTest {
|
||||||
ArgumentCaptor<AsrModel> captor = ArgumentCaptor.forClass(AsrModel.class);
|
ArgumentCaptor<AsrModel> captor = ArgumentCaptor.forClass(AsrModel.class);
|
||||||
verify(asrModelMapper, times(1)).insert(captor.capture());
|
verify(asrModelMapper, times(1)).insert(captor.capture());
|
||||||
assertEquals("tencent", captor.getValue().getProvider());
|
assertEquals("tencent", captor.getValue().getProvider());
|
||||||
assertEquals("16k_zh", captor.getValue().getModelCode());
|
assertNull(captor.getValue().getModelCode());
|
||||||
|
assertEquals("16k_zh", captor.getValue().getMediaConfig().get("tencentOfflineModelCode"));
|
||||||
|
assertEquals("16k_zh_realtime", captor.getValue().getMediaConfig().get("tencentRealtimeModelCode"));
|
||||||
assertEquals("secret-key", captor.getValue().getMediaConfig().get("tencentSecretKey"));
|
assertEquals("secret-key", captor.getValue().getMediaConfig().get("tencentSecretKey"));
|
||||||
assertNull(captor.getValue().getBaseUrl());
|
assertNull(captor.getValue().getBaseUrl());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,11 +133,13 @@ class AiTaskServiceImplTest {
|
||||||
)));
|
)));
|
||||||
|
|
||||||
AiModelVO model = new AiModelVO();
|
AiModelVO model = new AiModelVO();
|
||||||
model.setModelCode("16k_zh");
|
model.setModelCode("legacy-model-code");
|
||||||
model.setMediaConfig(Map.of(
|
model.setMediaConfig(Map.of(
|
||||||
"tencentAppId", "123456",
|
"tencentAppId", "123456",
|
||||||
"tencentSecretId", "secret-id",
|
"tencentSecretId", "secret-id",
|
||||||
"tencentSecretKey", "secret-key"
|
"tencentSecretKey", "secret-key",
|
||||||
|
"tencentOfflineModelCode", "16k_zh",
|
||||||
|
"tencentRealtimeModelCode", "16k_zh_realtime"
|
||||||
));
|
));
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
@ -211,11 +213,13 @@ class AiTaskServiceImplTest {
|
||||||
|
|
||||||
AiModelVO model = new AiModelVO();
|
AiModelVO model = new AiModelVO();
|
||||||
model.setProvider("tencent");
|
model.setProvider("tencent");
|
||||||
model.setModelCode("16k_zh");
|
model.setModelCode("legacy-model-code");
|
||||||
model.setMediaConfig(Map.of(
|
model.setMediaConfig(Map.of(
|
||||||
"tencentAppId", "123456",
|
"tencentAppId", "123456",
|
||||||
"tencentSecretId", "secret-id",
|
"tencentSecretId", "secret-id",
|
||||||
"tencentSecretKey", "secret-key"
|
"tencentSecretKey", "secret-key",
|
||||||
|
"tencentOfflineModelCode", "16k_zh",
|
||||||
|
"tencentRealtimeModelCode", "16k_zh_realtime"
|
||||||
));
|
));
|
||||||
|
|
||||||
TaskStatus doing = new TaskStatus();
|
TaskStatus doing = new TaskStatus();
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import {
|
||||||
testLocalModelConnectivity,
|
testLocalModelConnectivity,
|
||||||
updateAiModel,
|
updateAiModel,
|
||||||
} from "../../api/business/aimodel";
|
} from "../../api/business/aimodel";
|
||||||
|
import {getMeetingCreateConfig, type MeetingCreateConfig} from "../../api/business/meeting";
|
||||||
import AppPagination from "../../components/shared/AppPagination";
|
import AppPagination from "../../components/shared/AppPagination";
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
@ -31,6 +32,12 @@ const { Title } = Typography;
|
||||||
|
|
||||||
type ModelType = "ASR" | "LLM";
|
type ModelType = "ASR" | "LLM";
|
||||||
|
|
||||||
|
const DEFAULT_CREATE_CONFIG: MeetingCreateConfig = {
|
||||||
|
offlineEnabled: true,
|
||||||
|
realtimeEnabled: false,
|
||||||
|
offlineAudioMaxSizeMb: 1024,
|
||||||
|
};
|
||||||
|
|
||||||
const PROVIDER_BASE_URL_MAP: Record<string, string> = {
|
const PROVIDER_BASE_URL_MAP: Record<string, string> = {
|
||||||
openai: "https://api.openai.com",
|
openai: "https://api.openai.com",
|
||||||
deepseek: "https://api.deepseek.com",
|
deepseek: "https://api.deepseek.com",
|
||||||
|
|
@ -64,6 +71,7 @@ const AiModels: React.FC = () => {
|
||||||
const [connectivityLoading, setConnectivityLoading] = useState(false);
|
const [connectivityLoading, setConnectivityLoading] = useState(false);
|
||||||
const [remoteModels, setRemoteModels] = useState<string[]>([]);
|
const [remoteModels, setRemoteModels] = useState<string[]>([]);
|
||||||
const [speakerModels, setSpeakerModels] = useState<string[]>([]);
|
const [speakerModels, setSpeakerModels] = useState<string[]>([]);
|
||||||
|
const [createConfig, setCreateConfig] = useState<MeetingCreateConfig>(DEFAULT_CREATE_CONFIG);
|
||||||
const modelNameAutoFilledRef = useRef(false);
|
const modelNameAutoFilledRef = useRef(false);
|
||||||
const localProfileLoadedRef = useRef(false);
|
const localProfileLoadedRef = useRef(false);
|
||||||
|
|
||||||
|
|
@ -86,6 +94,20 @@ const AiModels: React.FC = () => {
|
||||||
void fetchData();
|
void fetchData();
|
||||||
}, [current, size, searchName, activeType]);
|
}, [current, size, searchName, activeType]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getMeetingCreateConfig()
|
||||||
|
.then((res) => {
|
||||||
|
const config = (res as any)?.data?.data ?? (res as any);
|
||||||
|
setCreateConfig({
|
||||||
|
...DEFAULT_CREATE_CONFIG,
|
||||||
|
...(config || {}),
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setCreateConfig(DEFAULT_CREATE_CONFIG);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!drawerVisible || !provider) {
|
if (!drawerVisible || !provider) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -137,6 +159,8 @@ const AiModels: React.FC = () => {
|
||||||
const tencentAppId = record.mediaConfig?.tencentAppId;
|
const tencentAppId = record.mediaConfig?.tencentAppId;
|
||||||
const tencentSecretId = record.mediaConfig?.tencentSecretId;
|
const tencentSecretId = record.mediaConfig?.tencentSecretId;
|
||||||
const tencentSecretKey = record.mediaConfig?.tencentSecretKey;
|
const tencentSecretKey = record.mediaConfig?.tencentSecretKey;
|
||||||
|
const tencentOfflineModelCode = record.mediaConfig?.tencentOfflineModelCode || record.modelCode;
|
||||||
|
const tencentRealtimeModelCode = record.mediaConfig?.tencentRealtimeModelCode || record.modelCode;
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
...record,
|
...record,
|
||||||
modelType: record.modelType,
|
modelType: record.modelType,
|
||||||
|
|
@ -145,6 +169,8 @@ const AiModels: React.FC = () => {
|
||||||
tencentAppId,
|
tencentAppId,
|
||||||
tencentSecretId,
|
tencentSecretId,
|
||||||
tencentSecretKey,
|
tencentSecretKey,
|
||||||
|
tencentOfflineModelCode,
|
||||||
|
tencentRealtimeModelCode,
|
||||||
isDefaultChecked: record.isDefault === 1,
|
isDefaultChecked: record.isDefault === 1,
|
||||||
statusChecked: record.status === 1,
|
statusChecked: record.status === 1,
|
||||||
});
|
});
|
||||||
|
|
@ -261,8 +287,8 @@ const AiModels: React.FC = () => {
|
||||||
baseUrl: values.baseUrl,
|
baseUrl: values.baseUrl,
|
||||||
apiPath: values.apiPath,
|
apiPath: values.apiPath,
|
||||||
apiKey: values.apiKey,
|
apiKey: values.apiKey,
|
||||||
modelCode: values.modelCode,
|
modelCode: activeType === "ASR" && isTencentProvider ? values.tencentOfflineModelCode : values.modelCode,
|
||||||
wsUrl: values.wsUrl,
|
wsUrl: activeType === "ASR" ? values.wsUrl : undefined,
|
||||||
mediaConfig:
|
mediaConfig:
|
||||||
activeType === "ASR" && isLocalProvider
|
activeType === "ASR" && isLocalProvider
|
||||||
? {
|
? {
|
||||||
|
|
@ -274,6 +300,8 @@ const AiModels: React.FC = () => {
|
||||||
tencentAppId: values.tencentAppId,
|
tencentAppId: values.tencentAppId,
|
||||||
tencentSecretId: values.tencentSecretId,
|
tencentSecretId: values.tencentSecretId,
|
||||||
tencentSecretKey: values.tencentSecretKey,
|
tencentSecretKey: values.tencentSecretKey,
|
||||||
|
tencentOfflineModelCode: values.tencentOfflineModelCode,
|
||||||
|
tencentRealtimeModelCode: values.tencentRealtimeModelCode,
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
temperature: values.temperature,
|
temperature: values.temperature,
|
||||||
|
|
@ -567,13 +595,14 @@ const AiModels: React.FC = () => {
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="模型名称"
|
label="模型名称"
|
||||||
required={activeType === "LLM"}
|
required={activeType === "LLM"}
|
||||||
|
hidden={activeType === "ASR" && isTencentProvider}
|
||||||
tooltip="可从远程列表选择,也可手动输入;值将作为模型 code 传给后端"
|
tooltip="可从远程列表选择,也可手动输入;值将作为模型 code 传给后端"
|
||||||
>
|
>
|
||||||
<Space.Compact style={{ width: "100%" }}>
|
<Space.Compact style={{ width: "100%" }}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="modelCode"
|
name="modelCode"
|
||||||
noStyle
|
noStyle
|
||||||
rules={activeType === "LLM" || isTencentProvider ? [{
|
rules={activeType === "LLM" ? [{
|
||||||
required: true,
|
required: true,
|
||||||
message: "请输入或选择模型名称"
|
message: "请输入或选择模型名称"
|
||||||
}] : []}
|
}] : []}
|
||||||
|
|
@ -602,7 +631,8 @@ const AiModels: React.FC = () => {
|
||||||
</Space.Compact>
|
</Space.Compact>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item name="wsUrl" label="WebSocket 地址" hidden>
|
<Form.Item name="wsUrl" label="WebSocket 地址"
|
||||||
|
hidden={!(activeType === "ASR" && createConfig.realtimeEnabled)}>
|
||||||
<Input placeholder="wss://api.example.com/v1/ws" />
|
<Input placeholder="wss://api.example.com/v1/ws" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
|
@ -660,6 +690,24 @@ const AiModels: React.FC = () => {
|
||||||
<Input.Password/>
|
<Input.Password/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="tencentOfflineModelCode"
|
||||||
|
label="离线识别模型名"
|
||||||
|
rules={[{required: true, message: "请输入离线识别模型名"}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="例如:16k_zh"/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="tencentRealtimeModelCode"
|
||||||
|
label="实时识别模型名"
|
||||||
|
rules={[{required: true, message: "请输入实时识别模型名"}]}
|
||||||
|
>
|
||||||
|
<Input placeholder="例如:16k_zh_realtime"/>
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue