mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-02 02:21:19 +08:00
fix: 修复编辑交易员时「AI模型配置不存在或未启用」错误
问题: - 编辑交易员并修改系统提示词模板时,保存失败 - 错误提示:AI模型配置不存在或未启用 根本原因: 1. 后端 API 返回的 ai_model 被截断(admin_deepseek → deepseek) 2. 前端验证时找不到对应的模型 ID(enabledModels 存的是完整 ID) 3. API 缺少 system_prompt_template 字段 修复内容: - api/server.go: 移除 AI model ID 截断逻辑,返回完整 ID - api/server.go: 在 handleGetTraderConfig 中添加 system_prompt_template 字段 - web/src/types.ts: TraderConfigData 接口添加 system_prompt_template 字段 - web/src/components/AITradersPage.tsx: 添加 fallback 机制和详细日志 测试: - 编辑交易员 → 修改系统提示词模板 → 保存成功 - Console 输出验证日志,不再报错
This commit is contained in:
@@ -801,30 +801,24 @@ func (s *Server) handleGetTraderConfig(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// AIModelID 应该已经是 provider(如 "deepseek"),直接使用
|
||||
// 如果是旧数据格式(如 "admin_deepseek"),提取 provider 部分
|
||||
aiModelID := traderConfig.AIModelID
|
||||
// 兼容旧数据:如果包含下划线,提取最后一部分作为 provider
|
||||
if strings.Contains(aiModelID, "_") {
|
||||
parts := strings.Split(aiModelID, "_")
|
||||
aiModelID = parts[len(parts)-1]
|
||||
}
|
||||
|
||||
// 返回完整的 AIModelID(如 "admin_deepseek"),不要截断
|
||||
// 前端需要完整 ID 来验证模型是否存在
|
||||
result := map[string]interface{}{
|
||||
"trader_id": traderConfig.ID,
|
||||
"trader_name": traderConfig.Name,
|
||||
"ai_model": aiModelID,
|
||||
"exchange_id": traderConfig.ExchangeID,
|
||||
"initial_balance": traderConfig.InitialBalance,
|
||||
"btc_eth_leverage": traderConfig.BTCETHLeverage,
|
||||
"altcoin_leverage": traderConfig.AltcoinLeverage,
|
||||
"trading_symbols": traderConfig.TradingSymbols,
|
||||
"custom_prompt": traderConfig.CustomPrompt,
|
||||
"override_base_prompt": traderConfig.OverrideBasePrompt,
|
||||
"is_cross_margin": traderConfig.IsCrossMargin,
|
||||
"use_coin_pool": traderConfig.UseCoinPool,
|
||||
"use_oi_top": traderConfig.UseOITop,
|
||||
"is_running": isRunning,
|
||||
"trader_id": traderConfig.ID,
|
||||
"trader_name": traderConfig.Name,
|
||||
"ai_model": traderConfig.AIModelID, // 使用完整 ID
|
||||
"exchange_id": traderConfig.ExchangeID,
|
||||
"initial_balance": traderConfig.InitialBalance,
|
||||
"btc_eth_leverage": traderConfig.BTCETHLeverage,
|
||||
"altcoin_leverage": traderConfig.AltcoinLeverage,
|
||||
"trading_symbols": traderConfig.TradingSymbols,
|
||||
"custom_prompt": traderConfig.CustomPrompt,
|
||||
"override_base_prompt": traderConfig.OverrideBasePrompt,
|
||||
"system_prompt_template": traderConfig.SystemPromptTemplate, // 添加此字段
|
||||
"is_cross_margin": traderConfig.IsCrossMargin,
|
||||
"use_coin_pool": traderConfig.UseCoinPool,
|
||||
"use_oi_top": traderConfig.UseOITop,
|
||||
"is_running": isRunning,
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
|
||||
@@ -165,34 +165,60 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
if (!editingTrader) return;
|
||||
|
||||
try {
|
||||
const model = enabledModels?.find(m => m.id === data.ai_model_id);
|
||||
const exchange = enabledExchanges?.find(e => e.id === data.exchange_id);
|
||||
|
||||
if (!model) {
|
||||
alert(t('modelConfigNotExist', language));
|
||||
// 1. 确保 ai_model_id 有值(使用 fallback)
|
||||
const ai_model_id = data.ai_model_id || editingTrader.ai_model;
|
||||
if (!ai_model_id) {
|
||||
console.error('缺少 AI 模型配置', { data, editingTrader });
|
||||
alert('错误:缺少 AI 模型配置');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 确保 exchange_id 有值(使用 fallback)
|
||||
const exchange_id = data.exchange_id || editingTrader.exchange_id;
|
||||
if (!exchange_id) {
|
||||
console.error('缺少交易所配置', { data, editingTrader });
|
||||
alert('错误:缺少交易所配置');
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 验证模型存在
|
||||
console.log('验证 AI 模型:', { ai_model_id, enabledModels: enabledModels?.map(m => m.id) });
|
||||
const model = enabledModels?.find(m => m.id === ai_model_id);
|
||||
if (!model) {
|
||||
console.error('找不到模型:', {
|
||||
ai_model_id,
|
||||
availableModels: enabledModels?.map(m => ({ id: m.id, name: m.name }))
|
||||
});
|
||||
alert(`AI模型配置不存在或未启用: ${ai_model_id}\n\n可用的模型: ${enabledModels?.map(m => m.name).join(', ')}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 验证交易所存在
|
||||
const exchange = enabledExchanges?.find(e => e.id === exchange_id);
|
||||
if (!exchange) {
|
||||
console.error('找不到交易所:', { exchange_id });
|
||||
alert(t('exchangeConfigNotExist', language));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 5. 构建请求(使用修正后的值)
|
||||
const request = {
|
||||
name: data.name,
|
||||
ai_model_id: data.ai_model_id,
|
||||
exchange_id: data.exchange_id,
|
||||
ai_model_id: ai_model_id, // 使用修正后的值
|
||||
exchange_id: exchange_id, // 使用修正后的值
|
||||
initial_balance: data.initial_balance,
|
||||
btc_eth_leverage: data.btc_eth_leverage,
|
||||
altcoin_leverage: data.altcoin_leverage,
|
||||
trading_symbols: data.trading_symbols,
|
||||
custom_prompt: data.custom_prompt,
|
||||
override_base_prompt: data.override_base_prompt,
|
||||
system_prompt_template: data.system_prompt_template, // 添加此字段
|
||||
is_cross_margin: data.is_cross_margin,
|
||||
use_coin_pool: data.use_coin_pool,
|
||||
use_oi_top: data.use_oi_top
|
||||
};
|
||||
|
||||
|
||||
console.log('保存交易员配置:', request);
|
||||
await api.updateTrader(editingTrader.trader_id, request);
|
||||
setShowEditModal(false);
|
||||
setEditingTrader(null);
|
||||
|
||||
@@ -194,6 +194,7 @@ export interface TraderConfigData {
|
||||
trading_symbols: string;
|
||||
custom_prompt: string;
|
||||
override_base_prompt: boolean;
|
||||
system_prompt_template: string; // 添加系统提示词模板字段
|
||||
is_cross_margin: boolean;
|
||||
use_coin_pool: boolean;
|
||||
use_oi_top: boolean;
|
||||
|
||||
Reference in New Issue
Block a user