Commit 13e7c005 authored by alex yao's avatar alex yao

feat:智能问数

parent 7674903c
......@@ -33,6 +33,8 @@ import cn.com.poc.thirdparty.resource.demand.ai.entity.function.FunctionCallResu
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelDemandResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelResponse;
import cn.com.poc.thirdparty.resource.demand.ai.function.AbstractFunctionResult;
import cn.com.poc.thirdparty.resource.demand.ai.function.chart_data_convert.ChartData;
import cn.com.poc.thirdparty.resource.demand.ai.function.chart_data_convert.ChartDataConvertFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.echart.EChartGenerateFunction;
import cn.com.poc.thirdparty.service.ChainService;
import cn.com.poc.thirdparty.service.LLMService;
......@@ -106,6 +108,9 @@ public class AiBiServiceImpl implements AiBiService {
@Resource
private EChartGenerateFunction eChartGenerateFunction;
@Resource
private ChartDataConvertFunction chartDataConvertFunction;
@Resource
private BizAgentApplicationGcConfigService bizAgentApplicationGcConfigService;
......@@ -281,13 +286,19 @@ public class AiBiServiceImpl implements AiBiService {
result.setKnowledgeContentResult(null);
sseUtil.send(JsonUtils.serialize(result));
JSONObject echartJSONObject = new JSONObject();
echartJSONObject.put("sql", dbChainResult.getSql());
echartJSONObject.put("sql_result", dbChainResult.getSqlResult());
echartJSONObject.put("question", input);
AbstractFunctionResult<String> functionResult = eChartGenerateFunction.doFunction(echartJSONObject.toJSONString(), null, null, null);
String eChartOption = functionResult.getFunctionResult();
functionRecord = outputECharts(eChartOption, sseUtil, functionRecord);
JSONObject chartJSONObject = new JSONObject();
chartJSONObject.put("data", JsonUtils.serialize(dbChainResult));
chartJSONObject.put("question", input);
AbstractFunctionResult<ChartData> functionResult = chartDataConvertFunction.doFunction(chartJSONObject.toJSONString(), null, null, null);
functionRecord = outputChartData(functionResult.getPromptContent(), sseUtil, functionRecord);
//
// JSONObject echartJSONObject = new JSONObject();
// echartJSONObject.put("sql", dbChainResult.getSql());
// echartJSONObject.put("sql_result", dbChainResult.getSqlResult());
// echartJSONObject.put("question", input);
// AbstractFunctionResult<String> functionResult = eChartGenerateFunction.doFunction(echartJSONObject.toJSONString(), null, null, null);
// String eChartOption = functionResult.getFunctionResult();
// functionRecord = outputECharts(eChartOption, sseUtil, functionRecord);
}
} else if (StringUtils.isNotBlank(fileUrl)) {
CSVChainResponse csvChainResponse = new CSVChainResponse();
......@@ -306,13 +317,20 @@ public class AiBiServiceImpl implements AiBiService {
result.setCsvChainResult(csvChainResult);
sseUtil.send(JsonUtils.serialize(result));
if (StringUtils.isNotBlank(csvChainResult.getResult())) {
JSONObject echartJSONObject = new JSONObject();
echartJSONObject.put("sql", StringUtils.EMPTY);
echartJSONObject.put("sql_result", csvChainResult.getResult());
echartJSONObject.put("question", input);
AbstractFunctionResult<String> functionResult = eChartGenerateFunction.doFunction(echartJSONObject.toJSONString(), null, null, null);
String eChartOption = functionResult.getFunctionResult();
functionRecord = outputECharts(eChartOption, sseUtil, functionRecord);
JSONObject chartJSONObject = new JSONObject();
chartJSONObject.put("data", csvChainResult.getResult());
chartJSONObject.put("question", input);
AbstractFunctionResult<ChartData> functionResult = chartDataConvertFunction.doFunction(chartJSONObject.toJSONString(), null, null, null);
functionRecord = outputChartData(functionResult.getPromptContent(), sseUtil, functionRecord);
// JSONObject echartJSONObject = new JSONObject();
// echartJSONObject.put("sql", StringUtils.EMPTY);
// echartJSONObject.put("sql_result", csvChainResult.getResult());
// echartJSONObject.put("question", input);
// AbstractFunctionResult<String> functionResult = eChartGenerateFunction.doFunction(echartJSONObject.toJSONString(), null, null, null);
// String eChartOption = functionResult.getFunctionResult();
// functionRecord = outputECharts(eChartOption, sseUtil, functionRecord);
}
}
}
......@@ -381,6 +399,30 @@ public class AiBiServiceImpl implements AiBiService {
return functionRecord;
}
private String outputChartData(String chartData, SSEUtil sseUtil, String functionRecord) throws IOException {
if (chartData != null && StringUtils.isNotBlank(chartData)) {
JSONObject jsonObject = JSONObject.parseObject(chartData);
if (!jsonObject.containsKey("skip")) {
ToolFunction toolFunction = new ToolFunction();
toolFunction.setName("chart_data_generate");
toolFunction.setResult(chartData);
toolFunction.setDisplayFormat("json");
toolFunction.setArguments(null);
LargeModelDemandResult result = new LargeModelDemandResult();
result.setCode("0");
result.setFunction(toolFunction);
result.setDbChainResult(null);
result.setKnowledgeContentResult(null);
String toolFunctionJson = JsonUtils.serialize(result);
sseUtil.send(toolFunctionJson);
functionRecord = toolFunctionJson;
}
}
return functionRecord;
}
private List<Message> buildMessage(Long userId, String dialoguesId, String prompt, String input, List<DBChainResult> dbChainResults, CSVChainResult csvChainResult) throws Exception {
List<Message> messages = new ArrayList<>();
String databaseResult = StringUtils.EMPTY, csvResult = StringUtils.EMPTY;
......
......@@ -2,6 +2,7 @@ package cn.com.poc.thirdparty.resource.demand.ai.function;
import cn.com.poc.common.utils.SpringUtils;
import cn.com.poc.thirdparty.resource.demand.ai.function.calculator.CalculatorFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.chart_data_convert.ChartDataConvertFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.chart_generate.ChartGenerateFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.csv_data_analysis.CSVFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.document_reader.DocumentReaderFunction;
......@@ -61,6 +62,7 @@ public enum LargeModelFunctionEnum {
completion_of_travel_v2_form(TravelFormV2Function.class),
chart_data_generate(ChartDataConvertFunction.class),
;
private Class<? extends AbstractLargeModelFunction> function;
......
package cn.com.poc.thirdparty.resource.demand.ai.function.chart_data_convert;
import java.util.List;
/**
* @author alex.yao
* @date 2025/9/2
*/
public class ChartData {
private List<String> xData;
private List<String> yData;
private String title;
private boolean skip;
public List<String> getxData() {
return xData;
}
public void setxData(List<String> xData) {
this.xData = xData;
}
public List<String> getyData() {
return yData;
}
public void setyData(List<String> yData) {
this.yData = yData;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isSkip() {
return skip;
}
public void setSkip(boolean skip) {
this.skip = skip;
}
}
package cn.com.poc.thirdparty.resource.demand.ai.function.chart_data_convert;
import cn.com.poc.agent_application.entity.KnowledgeContentResult;
import cn.com.poc.agent_application.entity.Variable;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.StringUtils;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dbchain.DBChainResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelDemandResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelResponse;
import cn.com.poc.thirdparty.resource.demand.ai.function.AbstractFunctionResult;
import cn.com.poc.thirdparty.resource.demand.ai.function.AbstractLargeModelFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.entity.FunctionLLMConfig;
import cn.com.poc.thirdparty.resource.demand.ai.function.entity.Parameters;
import cn.com.poc.thirdparty.resource.demand.ai.function.entity.Properties;
import cn.com.poc.thirdparty.service.LLMService;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* Chart数据转成
*
* @author alex.yao
* @date 2025/9/2
*/
@Component
public class ChartDataConvertFunction extends AbstractLargeModelFunction {
private final Logger logger = LoggerFactory.getLogger(ChartDataConvertFunction.class);
private final String MODEL = "deepseek-v3";
private final String PROMPT = "## 任务\n" +
"将现有数据转化成可供 EChart 使用的数据,仅需要处理X轴与Y轴。\n" +
"\n" +
"## 输出\n" +
"1. 字段 xData 用于放入x轴的数据,并且数据应为字符串类型,如 xData:[\"1月\",\"2月\",\"3月\"]\n" +
"2. 字段 yData 用于放入y轴的数据,并且数据应为字符串类型,如 yData:[\"12\",\"34\",\"47\"]\n" +
"3. 字段 title 用于存放该图表的标题\n" +
"4. 若现有数据无法生成图表,则输出 {\"skip\":true} , 表示跳过,无法生成图表数据\n" +
"\n" +
"## 例子\n" +
"{\"xData\":[\"1月\",\"2月\",\"3月\"], yData:[\"12\",\"34\",\"47\"],\"title\":\"第一季度销售额\"}\n" +
"\n" +
"## 用户问题\n" +
"{question}\n" +
"\n" +
"## 数据\n" +
"{data}";
private final String DESC = "根据用户问题和现有数据生成图表可用数据";
private final FunctionLLMConfig functionLLMConfig = new FunctionLLMConfig.FunctionLLMConfigBuilder()
.name("chart_data_generate")
.description(DESC)
.parameters(new Parameters("object")
.addProperties("data", new Properties("string", "参考数据"))
.addProperties("question", new Properties("string", "用户问题优化后的问题")))
.build();
@Resource
private LLMService llmService;
@Override
public AbstractFunctionResult<ChartData> doFunction(String content, String identifier, List<DBChainResult> dbChainResults, List<KnowledgeContentResult> knowledgeContentResults) {
AbstractFunctionResult<ChartData> result = new AbstractFunctionResult<>();
result.setFunctionResult(null);
result.setPromptContent(StringUtils.EMPTY);
if (StringUtils.isBlank(content)) {
return result;
}
JSONObject jsonObject = JSON.parseObject(content);
if (!jsonObject.containsKey("question") || !jsonObject.containsKey("data")) {
logger.warn("缺少必要参数,无法生成图表数据,content:{}", content);
return result;
}
Message systemMessage = new Message();
systemMessage.setRole("system");
systemMessage.setContent(buildPrompt(jsonObject));
Message userMessage = new Message();
userMessage.setContent("invoke");
userMessage.setRole("user");
Message[] messages = new Message[]{systemMessage, userMessage};
LargeModelResponse largeModelResponse = new LargeModelResponse();
largeModelResponse.setMessages(messages);
largeModelResponse.setModel(MODEL);
LargeModelDemandResult largeModelDemandResult = llmService.chat(largeModelResponse);
if (largeModelDemandResult == null || StringUtils.isBlank(largeModelDemandResult.getMessage())) {
logger.error("-----------------LLM 执行失败----------------");
return result;
}
String message = largeModelDemandResult.getMessage();
int startEnd = message.indexOf("{");
int endIndex = message.lastIndexOf("}");
if (startEnd == -1 || endIndex == -1) {
logger.error("---------------解析内容失败, message:{}--------------", message);
throw new BusinessException("解析内容失败");
}
ChartData chartData = JsonUtils.deSerialize(message, ChartData.class);
result.setFunctionResult(chartData);
result.setPromptContent(message);
return result;
}
@Override
public String getDesc() {
return DESC;
}
@Override
public List<String> getLLMConfig() {
return ListUtil.toList(JsonUtils.serialize(functionLLMConfig));
}
@Override
public List<String> getLLMConfig(List<Variable> variableStructure) {
return getLLMConfig();
}
private String buildPrompt(JSONObject jsonObject) {
String data = StringUtils.EMPTY;
String question = StringUtils.EMPTY;
if (jsonObject.containsKey("data")) {
data = jsonObject.getString("data");
}
if (jsonObject.containsKey("question")) {
question = jsonObject.getString("question");
}
return PROMPT.replace("${question}", question)
.replace("{data}", data);
}
}
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 to comment