Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@
*
* @author Makoto
*/

public record PromptConfigDTO(String id, // Configuration ID (required for update)
String name, // Configuration name
String promptType, // Prompt type
String systemPrompt, // User-defined system prompt content
String optimizationPrompt, // User-defined system prompt content
Boolean enabled, // Whether to enable this configuration
String description, // Configuration description
String creator // Creator
) {
public PromptConfigDTO(String promptType, String systemPrompt) {
this(null, null, promptType, systemPrompt, true, null, null);
public PromptConfigDTO(String promptType, String optimizationPrompt) {
this(null, null, promptType, optimizationPrompt, true, null, null);
}

@Override
Expand Down Expand Up @@ -61,8 +62,8 @@ public String promptType() {
}

@Override
public String systemPrompt() {
return systemPrompt;
public String optimizationPrompt() {
return optimizationPrompt;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.alibaba.cloud.ai.node;

import com.alibaba.cloud.ai.entity.UserPromptConfig;
import com.alibaba.cloud.ai.enums.StreamResponseType;
import com.alibaba.cloud.ai.graph.OverAllState;
import com.alibaba.cloud.ai.graph.action.NodeAction;
Expand Down Expand Up @@ -136,14 +137,15 @@ private Flux<ChatResponse> generateReport(String userInput, Plan plan, HashMap<S
// Build analysis steps and data results description
String analysisStepsAndData = buildAnalysisStepsAndData(plan, executionResults);

// Get custom prompt content if available
String customPrompt = promptConfigService.getCustomPromptContent("report-generator");
// Get optimization configs if available
List<UserPromptConfig> optimizationConfigs = promptConfigService.getOptimizationConfigs("report-generator");

// Use PromptHelper to build report generation prompt with custom prompt support
String reportPrompt = PromptHelper.buildReportGeneratorPromptWithCustom(userRequirementsAndPlan,
analysisStepsAndData, summaryAndRecommendations, customPrompt);
// Use PromptHelper to build report generation prompt with optimization support
String reportPrompt = PromptHelper.buildReportGeneratorPromptWithOptimization(userRequirementsAndPlan,
analysisStepsAndData, summaryAndRecommendations, optimizationConfigs);

logger.info("Using {} prompt for report generation", customPrompt != null ? "custom" : "default");
logger.info("Using {} prompt for report generation",
!optimizationConfigs.isEmpty() ? "optimized (" + optimizationConfigs.size() + " configs)" : "default");

return chatClient.prompt().user(reportPrompt).stream().chatResponse();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
import com.alibaba.cloud.ai.dto.schema.ColumnDTO;
import com.alibaba.cloud.ai.dto.schema.SchemaDTO;
import com.alibaba.cloud.ai.dto.schema.TableDTO;
import com.alibaba.cloud.ai.entity.UserPromptConfig;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.apache.commons.collections.CollectionUtils;

import java.util.*;
Expand Down Expand Up @@ -235,21 +238,20 @@ public static String buildSemanticConsistenPrompt(String nlReq, String sql) {
* @param customPrompt user-defined prompt content, use default prompt if null
* @return built prompt
*/
public static String buildReportGeneratorPromptWithCustom(String userRequirementsAndPlan,
String analysisStepsAndData, String summaryAndRecommendations, String customPrompt) {
public static String buildReportGeneratorPromptWithOptimization(String userRequirementsAndPlan,
String analysisStepsAndData, String summaryAndRecommendations, List<UserPromptConfig> optimizationConfigs) {

Map<String, Object> params = new HashMap<>();
params.put("user_requirements_and_plan", userRequirementsAndPlan);
params.put("analysis_steps_and_data", analysisStepsAndData);
params.put("summary_and_recommendations", summaryAndRecommendations);

if (customPrompt != null && !customPrompt.trim().isEmpty()) {
// Use custom prompt
return new org.springframework.ai.chat.prompt.PromptTemplate(customPrompt).render(params);
}
else {
// Use default prompt
return PromptConstant.getReportGeneratorPromptTemplate().render(params);
}
// Build optional optimization section content from user configs
String optimizationSection = buildOptimizationSection(optimizationConfigs, params);
params.put("optimization_section", optimizationSection);

// Render using the default report generator template
return PromptConstant.getReportGeneratorPromptTemplate().render(params);
}

public static String buildSqlErrorFixerPrompt(String question, DbConfig dbConfig, SchemaDTO schemaDTO,
Expand Down Expand Up @@ -285,4 +287,49 @@ public static String buildSemanticModelPrompt(List<SemanticModelDTO> semanticMod
return PromptConstant.getSemanticModelPromptTemplate().render(params);
}

/**
* 构建优化提示词部分内容
* @param optimizationConfigs 优化配置列表
* @param params 模板参数
* @return 优化部分的内容
*/
private static String buildOptimizationSection(List<UserPromptConfig> optimizationConfigs,
Map<String, Object> params) {

if (optimizationConfigs == null || optimizationConfigs.isEmpty()) {
return "";
}

StringBuilder result = new StringBuilder();
result.append("## 优化要求\n");

for (UserPromptConfig config : optimizationConfigs) {
String optimizationContent = renderOptimizationPrompt(config.getSystemPrompt(), params);
if (!optimizationContent.trim().isEmpty()) {
result.append("- ").append(optimizationContent).append("\n");
}
}

return result.toString().trim();
}

/**
* 渲染优化提示词模板
* @param optimizationPrompt 优化提示词模板
* @param params 参数
* @return 渲染后的内容
*/
private static String renderOptimizationPrompt(String optimizationPrompt, Map<String, Object> params) {
if (optimizationPrompt == null || optimizationPrompt.trim().isEmpty()) {
return "";
}
try {
return new PromptTemplate(optimizationPrompt).render(params);
}
catch (Exception e) {
// 如果模板渲染失败,直接返回原始内容
return optimizationPrompt;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
* User Prompt Configuration Management Service Provides CRUD functionality for prompt
Expand All @@ -41,21 +42,31 @@ public class UserPromptConfigService {
@Autowired
private UserPromptConfigMapper userPromptConfigMapper;

/**
* 内存存储,用于缓存配置(可选的性能优化)
*/
private final Map<String, UserPromptConfig> configStorage = new ConcurrentHashMap<>();

/**
* 根据提示词类型存储启用的配置ID列表(支持多个配置同时启用)
*/
private final Map<String, List<String>> promptTypeToConfigIds = new ConcurrentHashMap<>();

/**
* Create or update prompt configuration
* @param configDTO configuration data transfer object
* @return saved configuration object
*/
public UserPromptConfig saveOrUpdateConfig(PromptConfigDTO configDTO) {
logger.info("保存或更新提示词配置:{}", configDTO);
logger.info("保存或更新提示词优化配置:{}", configDTO);

UserPromptConfig config;
if (configDTO.id() != null) {
// Update existing configuration
config = userPromptConfigMapper.selectById(configDTO.id());
if (config != null) {
config.setName(configDTO.name());
config.setSystemPrompt(configDTO.systemPrompt());
config.setSystemPrompt(configDTO.optimizationPrompt());
config.setEnabled(configDTO.enabled());
config.setDescription(configDTO.description());
userPromptConfigMapper.updateById(config);
Expand All @@ -66,7 +77,7 @@ public UserPromptConfig saveOrUpdateConfig(PromptConfigDTO configDTO) {
config.setId(configDTO.id());
config.setName(configDTO.name());
config.setPromptType(configDTO.promptType());
config.setSystemPrompt(configDTO.systemPrompt());
config.setSystemPrompt(configDTO.optimizationPrompt());
config.setEnabled(configDTO.enabled());
config.setDescription(configDTO.description());
config.setCreator(configDTO.creator());
Expand All @@ -78,13 +89,19 @@ public UserPromptConfig saveOrUpdateConfig(PromptConfigDTO configDTO) {
config = new UserPromptConfig();
config.setName(configDTO.name());
config.setPromptType(configDTO.promptType());
config.setSystemPrompt(configDTO.systemPrompt());
config.setSystemPrompt(configDTO.optimizationPrompt());
config.setEnabled(configDTO.enabled());
config.setDescription(configDTO.description());
config.setCreator(configDTO.creator());
userPromptConfigMapper.insert(config);
}

// 更新缓存
configStorage.put(config.getId(), config);

// 更新类型映射(支持多个配置)
updatePromptTypeMapping(config);

// If the configuration is enabled, disable other configurations of the same type
if (Boolean.TRUE.equals(config.getEnabled())) {
userPromptConfigMapper.disableAllByPromptType(config.getPromptType());
Expand All @@ -104,13 +121,40 @@ public UserPromptConfig getConfigById(String id) {
return userPromptConfigMapper.selectById(id);
}

/**
* 根据提示词类型获取所有启用的配置
* @param promptType 提示词类型
* @return 配置列表
*/
public List<UserPromptConfig> getActiveConfigsByType(String promptType) {
List<String> configIds = promptTypeToConfigIds.get(promptType);
if (configIds == null || configIds.isEmpty()) {
return new ArrayList<>();
}

return configIds.stream()
.map(configStorage::get)
.filter(Objects::nonNull)
.filter(config -> Boolean.TRUE.equals(config.getEnabled()))
.sorted(Comparator.comparing(UserPromptConfig::getUpdateTime).reversed())
.toList();
}

/**
* Get enabled configuration by prompt type
* @param promptType prompt type
* @return configuration object, returns null if not exists
*/
public UserPromptConfig getActiveConfigByType(String promptType) {
return userPromptConfigMapper.selectActiveByPromptType(promptType);
// 优先从数据库获取
UserPromptConfig dbConfig = userPromptConfigMapper.selectActiveByPromptType(promptType);
if (dbConfig != null) {
return dbConfig;
}

// 备用:从内存缓存获取
List<UserPromptConfig> configs = getActiveConfigsByType(promptType);
return configs.isEmpty() ? null : configs.get(0);
}

/**
Expand Down Expand Up @@ -139,8 +183,12 @@ public List<UserPromptConfig> getConfigsByType(String promptType) {
public boolean deleteConfig(String id) {
UserPromptConfig config = userPromptConfigMapper.selectById(id);
if (config != null) {
// 从数据库删除
int deleted = userPromptConfigMapper.deleteById(id);
if (deleted > 0) {
// 从内存缓存和类型映射中移除该配置
configStorage.remove(id);
removeFromPromptTypeMapping(config);
logger.info("已删除配置:{}", id);
return true;
}
Expand All @@ -162,6 +210,10 @@ public boolean enableConfig(String id) {
// Enable the current configuration
int updated = userPromptConfigMapper.enableById(id);
if (updated > 0) {
// 更新内存缓存
config.setEnabled(true);
configStorage.put(id, config);
updatePromptTypeMapping(config);
logger.info("已启用配置:{}", id);
return true;
}
Expand All @@ -177,6 +229,12 @@ public boolean enableConfig(String id) {
public boolean disableConfig(String id) {
int updated = userPromptConfigMapper.disableById(id);
if (updated > 0) {
// 更新内存缓存
UserPromptConfig config = configStorage.get(id);
if (config != null) {
config.setEnabled(false);
removeFromPromptTypeMapping(config);
}
logger.info("已禁用配置:{}", id);
return true;
}
Expand All @@ -187,29 +245,43 @@ public boolean disableConfig(String id) {
* Disable all configurations of specified type
* @param promptType prompt type
*/
public void disableConfigsByType(String promptType) {
userPromptConfigMapper.disableAllByPromptType(promptType);
private void updatePromptTypeMapping(UserPromptConfig config) {
if (Boolean.TRUE.equals(config.getEnabled())) {
promptTypeToConfigIds.computeIfAbsent(config.getPromptType(), k -> new ArrayList<>());
List<String> configIds = promptTypeToConfigIds.get(config.getPromptType());
if (!configIds.contains(config.getId())) {
configIds.add(config.getId());
logger.info("已将配置 {} 添加到提示词类型 [{}] 的映射中", config.getId(), config.getPromptType());
}
}
else {
removeFromPromptTypeMapping(config);
}
}

/**
* Get custom prompt content, returns null if no custom configuration
* @param promptType prompt type
* @return custom prompt content
*/
public String getCustomPromptContent(String promptType) {
// TODO 需要优化,提示词不能完全替代现有的,仅用作补充使用
return null;
// UserPromptConfig config = getActiveConfigByType(promptType);
// return config != null ? config.getSystemPrompt() : null;
private void removeFromPromptTypeMapping(UserPromptConfig config) {
List<String> configIds = promptTypeToConfigIds.get(config.getPromptType());
if (configIds != null) {
configIds.remove(config.getId());
if (configIds.isEmpty()) {
promptTypeToConfigIds.remove(config.getPromptType());
}
logger.info("已从提示词类型 [{}] 的映射中移除配置 {}", config.getPromptType(), config.getId());
}
}

/**
* Check if there is custom configuration
* @param promptType prompt type
* @return whether there is custom configuration
*/
public boolean hasCustomConfig(String promptType) {
return getActiveConfigByType(promptType) != null;
public List<UserPromptConfig> getOptimizationConfigs(String promptType) {
return getActiveConfigsByType(promptType);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@
## 总结建议要求
{summary_and_recommendations}

{optimization_section}

请根据以上信息生成一份专业、全面的数据分析报告。
Loading
Loading