Commit 754c2b15 authored by alex yao's avatar alex yao

feat: 新增ai智能问数接口

parent ba875f4c
package cn.com.poc.agent_application.utils;
import cn.com.poc.agent_application.entity.BizAgentApplicationDialoguesRecordEntity;
import cn.com.poc.agent_application.entity.CheckPluginUseEntity;
import cn.com.poc.agent_application.entity.Variable;
import cn.com.poc.agent_application.service.BizAgentApplicationDialoguesRecordService;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.utils.DocumentLoad;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.SpringUtils;
import cn.com.poc.thirdparty.resource.demand.ai.constants.LLMRoleEnum;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Tool;
import cn.com.poc.thirdparty.resource.demand.ai.entity.function.FunctionCallResult;
......@@ -20,7 +23,10 @@ import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author alex.yao
......@@ -122,38 +128,6 @@ public class AgentApplicationTools {
}
}
/**
* 获取Message对话的图片地址
*
* @param messages 对话
* @return 返回图片地址列表,若无则返回null
*/
// public static List<String> getMessageImageUrl(List<Message> messages) {
// List<String> imageUrls = null;
// Message mess = messages.get(messages.size() - 1);
// if (!(mess.getContent() instanceof String) && ((LinkedHashMap) ((ArrayList) mess.getContent()).get(0)).containsKey("image_url")) {
// LinkedHashMap map = ((LinkedHashMap) ((ArrayList) mess.getContent()).get(0));
// MultiContent multiContent = JSONObject.parseObject(JsonUtils.serialize(map), MultiContent.class);
// if (ObjectUtil.isNotNull(multiContent.getImageUrl()) && StringUtils.isNotBlank(multiContent.getImageUrl().getUrl())) {
// imageUrls = new ArrayList<>();
// imageUrls.add(multiContent.getImageUrl().getUrl());
// }
// }
// return imageUrls;
// }
/**
* 构建ImageUrls
*/
// public static List<String> buildImageUrls(String imageUrl) {
// List<String> imageUrls = null;
// if (StringUtils.isNotBlank(imageUrl)) {
// imageUrls = new ArrayList<>();
// imageUrls.add(imageUrl);
// }
// return imageUrls;
// }
/**
* 判断将会调用的插件-用于扣减积分
*/
......@@ -192,4 +166,38 @@ public class AgentApplicationTools {
return checkPluginUseEntity;
}
public static List<Message> buildMessage(String dialogsId, String agentId, Long userId, String input) throws Exception {
BizAgentApplicationDialoguesRecordService bizAgentApplicationDialoguesRecordService = SpringUtils.getBean(BizAgentApplicationDialoguesRecordService.class);
List<Message> messages = new ArrayList<>();
BizAgentApplicationDialoguesRecordEntity recordEntity = new BizAgentApplicationDialoguesRecordEntity();
recordEntity.setDialogsId(dialogsId);
recordEntity.setMemberId(userId);
recordEntity.setAgentId(agentId);
List<BizAgentApplicationDialoguesRecordEntity> recordEntities = bizAgentApplicationDialoguesRecordService.findByExample(recordEntity, null);
if (CollectionUtils.isNotEmpty(recordEntities)) {
for (BizAgentApplicationDialoguesRecordEntity entity : recordEntities) {
Message message = new Message();
message.setContent(entity.getContent());
message.setRole(entity.getRole());
messages.add(message);
}
}
//判断最后是否为User,若是则删除。
if (CollectionUtils.isNotEmpty(messages)) {
if (LLMRoleEnum.USER.getRole().equals(messages.get(messages.size() - 1).getRole())) {
Long recordId = recordEntities.get(recordEntities.size() - 1).getId();
bizAgentApplicationDialoguesRecordService.deletedById(recordId);
messages.remove(messages.size() - 1);
}
}
// 用户输入
Message message = new Message();
message.setContent(input);
message.setRole(LLMRoleEnum.USER.getRole());
messages.add(message);
return messages;
}
}
package cn.com.poc.ai_bi.aggregate;
/**
* 智数:智能问数生成式BI服务
*
* @author alex.yao
* @date 2025/6/20
*/
public interface AiBiService {
/**
* 调用智能问数生成式BI服务
*
* @param dialoguesId 对话id
* @param input 问题
* @param fileUrl 文件地址
* @param knowledgeIds 知识库ids
* @param databaseIds 数据库ids
* @param userId 用户id
*/
void call(String dialoguesId, String input, String fileUrl, Integer[] knowledgeIds, Integer[] databaseIds, Long userId) throws Exception;
}
package cn.com.poc.ai_bi.aggregate.impl;
import cn.com.poc.agent_application.aggregate.AgentApplicationService;
import cn.com.poc.agent_application.constant.AgentApplicationDialoguesRecordConstants;
import cn.com.poc.agent_application.entity.*;
import cn.com.poc.agent_application.service.BizAgentApplicationDialoguesRecordService;
import cn.com.poc.agent_application.service.BizAgentApplicationPublishService;
import cn.com.poc.agent_application.utils.AgentApplicationTools;
import cn.com.poc.ai_bi.aggregate.AiBiService;
import cn.com.poc.ai_dialogues.entity.BizAiDialoguesEntity;
import cn.com.poc.ai_dialogues.service.BizAiDialoguesService;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.utils.StringUtils;
import cn.com.poc.knowledge.aggregate.KnowledgeService;
import cn.com.poc.thirdparty.resource.demand.ai.constants.KnowledgeSearchTypeEnum;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Tool;
import cn.com.poc.thirdparty.resource.demand.ai.entity.function.FunctionCallResult;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.com.yict.framemax.frame.service.FmxParamConfigService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* @author alex.yao
* @date 2025/6/20
*/
@Service
public class AiBiServiceImpl implements AiBiService {
private final Logger logger = LoggerFactory.getLogger(AiBiServiceImpl.class);
private final String FMX_PARAM_AGENT_ID_CODE = "ai_bi.agent_id";
@Resource
private FmxParamConfigService fmxParamConfigService;
@Resource
private BizAiDialoguesService bizAiDialoguesService;
@Resource
private AgentApplicationService agentApplicationService;
@Resource
private KnowledgeService knowledgeService;
@Resource
private BizAgentApplicationPublishService bizAgentApplicationPublishService;
@Resource
private BizAgentApplicationDialoguesRecordService bizAgentApplicationDialoguesRecordService;
@Override
public void call(String dialoguesId, String input, String fileUrl, Integer[] knowledgeIds, Integer[] databaseIds, Long userId) throws Exception {
String agentId = fmxParamConfigService.getParam(FMX_PARAM_AGENT_ID_CODE);
if (StringUtils.isBlank(agentId)) {
logger.error("获取智能问数对话agentId失败");
throw new BusinessException("对话异常");
}
// 获取Agent基本信息
BizAgentApplicationPublishEntity infoEntity = bizAgentApplicationPublishService.getByAgentId(agentId);
if (infoEntity == null) {
logger.error("获取智能问数对话agent信息失败");
throw new BusinessException("对话异常");
}
// 保存对话基础信息
BizAiDialoguesEntity bizAiDialoguesEntity = new BizAiDialoguesEntity();
bizAiDialoguesEntity.setMemberId(userId);
bizAiDialoguesEntity.setDialoguesId(dialoguesId);
bizAiDialoguesEntity.setIsDeleted(CommonConstant.IsDeleted.N);
List<BizAiDialoguesEntity> bizAiDialoguesEntities = bizAiDialoguesService.findByExample(bizAiDialoguesEntity, null);
if (CollectionUtils.isEmpty(bizAiDialoguesEntities)) {
logger.error("dialogues id 不存在,请重新创建");
throw new BusinessException("对话异常");
}
// 保存标题信息
if (StringUtils.isBlank(bizAiDialoguesEntities.get(0).getTitle())) {
BizAiDialoguesEntity portalDialoguesEntity = bizAiDialoguesEntities.get(0);
portalDialoguesEntity.setTitle(input);
bizAiDialoguesService.update(portalDialoguesEntity);
}
// 获取对话配置
String largeModel = infoEntity.getLargeModel();//获取模型
String agentSystem = infoEntity.getAgentSystem();//获取Agent角色词
List<Integer> kdIds = knowledgeService.getKdIdsByKnowledgeInfoIds(knowledgeIds);//获取知识库ids
List<Message> messages = AgentApplicationTools.buildMessage(dialoguesId, agentId, userId, input);//构建消息
List<Tool> tools = AgentApplicationTools.buildFunctionConfig(infoEntity.getVariableStructure(), infoEntity.getIsLongMemory(), dialoguesId, agentId, infoEntity.getUnitIds(), infoEntity.getIsDocumentParsing());//构建函数配置
List<String> fileUrls = new ArrayList<>();//构建文件链接
if (StringUtils.isNotBlank(fileUrl)) {
fileUrls.add(fileUrl);
}
CheckPluginUseEntity checkPluginUseEntity = AgentApplicationTools.checkPluginUse(messages, tools, fileUrls);//检查插件使用
FunctionCallResult functionCallResult = checkPluginUseEntity.getFunctionCallResult();//函数调用结果
boolean stream = true;//是否流式输出
KnowledgeSearchTypeEnum knowledgeSearchTypeEnum = KnowledgeSearchTypeEnum.valueOf(infoEntity.getKnowledgeSearchType());//知识库检索方式
KnowledgeSuperclassProblemConfig knowledgeSuperclassProblemConfig = new KnowledgeSuperclassProblemConfig();//知识库超纲配置
knowledgeSuperclassProblemConfig.setKnowledgeResponseType(infoEntity.getKnowledgeResponseType());//知识库回复类型
knowledgeSuperclassProblemConfig.setKnowledgeCustomResponse(infoEntity.getKnowledgeCustomResponse());//知识库自定义回复
// 记录用户输入时间戳
Long inputTimestamp = System.currentTimeMillis();
// 调用对话Agent
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletResponse response = servletRequestAttributes.getResponse();
AgentResultEntity agentResultEntity = agentApplicationService.callAgentApplication(agentId,
dialoguesId,
largeModel,
agentSystem,
kdIds.toArray(new Integer[0]),
databaseIds,
infoEntity.getCommunicationTurn(),
infoEntity.getTopP(),
infoEntity.getTemperature(),
messages,
tools,
functionCallResult,
stream,
infoEntity.getKnowledgeSimilarity(),
infoEntity.getKnowledgeNResult(),
knowledgeSearchTypeEnum,
knowledgeSuperclassProblemConfig,
response
);
//保存对话记录
//用户输入记录
BizAgentApplicationDialoguesRecordEntity inputRecord = new BizAgentApplicationDialoguesRecordEntity();
inputRecord.setAgentId(agentId);
inputRecord.setMemberId(userId);
inputRecord.setContent(input);
inputRecord.setDialogsId(dialoguesId);
inputRecord.setRole(AgentApplicationDialoguesRecordConstants.ROLE.USER);
inputRecord.setTimestamp(inputTimestamp);
bizAgentApplicationDialoguesRecordService.save(inputRecord);
//AI输出记录
BizAgentApplicationDialoguesRecordEntity outputRecord = new BizAgentApplicationDialoguesRecordEntity();
outputRecord.setRole(AgentApplicationDialoguesRecordConstants.ROLE.ASSISTANT);
outputRecord.setAgentId(infoEntity.getAgentId());
outputRecord.setDialogsId(dialoguesId);
outputRecord.setMemberId(userId);
outputRecord.setTimestamp(System.currentTimeMillis());
outputRecord.setContent(agentResultEntity.getMessage());
outputRecord.setReasoningContent(agentResultEntity.getReasoningContent());
bizAgentApplicationDialoguesRecordService.save(outputRecord);
}
}
package cn.com.poc.ai_bi.dto;
/**
* @author alex.yao
* @date 2025/6/20
*/
public class AiBiDialoguesDto {
/**
* 对话id
*/
private String dialoguesId;
/**
* 问题
*/
private String input;
/**
* 文件地址
*/
private String fileUrl;
/**
* 知识库ids
*/
private Integer[] knowledgeIds;
/**
* 数据库ids
*/
private Integer[] databaseIds;
public String getDialoguesId() {
return dialoguesId;
}
public void setDialoguesId(String dialoguesId) {
this.dialoguesId = dialoguesId;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public String getFileUrl() {
return fileUrl;
}
public void setFileUrl(String fileUrl) {
this.fileUrl = fileUrl;
}
public Integer[] getKnowledgeIds() {
return knowledgeIds;
}
public void setKnowledgeIds(Integer[] knowledgeIds) {
this.knowledgeIds = knowledgeIds;
}
public Integer[] getDatabaseIds() {
return databaseIds;
}
public void setDatabaseIds(Integer[] databaseIds) {
this.databaseIds = databaseIds;
}
}
package cn.com.poc.ai_bi.rest;
import cn.com.poc.ai_bi.dto.AiBiDialoguesDto;
import cn.com.yict.framemax.core.rest.BaseRest;
import cn.com.yict.framemax.web.permission.Access;
import cn.com.yict.framemax.web.permission.Permission;
import org.springframework.web.bind.annotation.RequestBody;
/**
* 智数:智能问数生成式BI服务接口
*
* @author alex.yao
* @date 2025/6/20
*/
@Permission(Access.Safety)
public interface AiBiRest extends BaseRest {
/**
* 调用AI问数
*/
void call(@RequestBody AiBiDialoguesDto dto) throws Exception;
}
package cn.com.poc.ai_bi.rest.impl;
import cn.com.poc.ai_bi.aggregate.AiBiService;
import cn.com.poc.ai_bi.dto.AiBiDialoguesDto;
import cn.com.poc.ai_bi.rest.AiBiRest;
import cn.com.poc.common.utils.Assert;
import cn.com.poc.common.utils.BlContext;
import cn.com.poc.support.security.oauth.entity.UserBaseEntity;
import cn.com.yict.framemax.core.exception.BusinessException;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
/**
* @author alex.yao
* @date 2025/6/20
*/
@Component
public class AiBiRestImpl implements AiBiRest {
@Resource
private AiBiService aiBiService;
@Override
public void call(AiBiDialoguesDto dto) throws Exception {
Assert.notNull(dto);
Assert.notBlank(dto.getDialoguesId(), "对话id不能为空");
Assert.notBlank(dto.getInput(), "输入内容不能为空");
UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
if (ObjectUtils.isEmpty(userBaseEntity)) {
throw new BusinessException("用户未登录");
}
aiBiService.call(dto.getDialoguesId(),
dto.getInput(),
dto.getFileUrl(),
dto.getKnowledgeIds(),
dto.getDatabaseIds(),
userBaseEntity.getUserId());
}
}
......@@ -12,6 +12,8 @@ public enum AiDialoguesTypeEnum {
AI_WRITING("ai_writing", "AI写作"),
AI_BI("ai_bi", "智能问数"),
;
private String type;
......
......@@ -105,7 +105,7 @@ public class PortalServiceImpl implements PortalService {
String largeModel = callEntity.getEnableDeepThinking() ? "DeepSeek" : "DeepSeek-v3";//获取模型
String agentSystem = infoEntity.getAgentSystem();//获取Agent角色词
List<Integer> kdIds = knowledgeService.getKdIdsByKnowledgeInfoIds(callEntity.getKnowledgeIds());//获取知识库ids
List<Message> messages = buildMessages(callEntity.getDialoguesId(), agentId, userId, callEntity.getInput());//构建消息
List<Message> messages = AgentApplicationTools.buildMessage(callEntity.getDialoguesId(), agentId, userId, callEntity.getInput());//构建消息
List<Tool> tools;
if (callEntity.getEnableSearchEngine()) {
tools = AgentApplicationTools.buildFunctionConfig(infoEntity.getVariableStructure(), infoEntity.getIsLongMemory(), callEntity.getDialoguesId(), agentId, infoEntity.getUnitIds(), infoEntity.getIsDocumentParsing());//构建函数配置
......@@ -170,39 +170,4 @@ public class PortalServiceImpl implements PortalService {
outputRecord.setReasoningContent(agentResultEntity.getReasoningContent());
bizAgentApplicationDialoguesRecordService.save(outputRecord);
}
private List<Message> buildMessages(String dialogsId, String agentId, Long userId, String input) throws Exception {
List<Message> messages = new ArrayList<>();
BizAgentApplicationDialoguesRecordEntity recordEntity = new BizAgentApplicationDialoguesRecordEntity();
recordEntity.setDialogsId(dialogsId);
recordEntity.setMemberId(userId);
recordEntity.setAgentId(agentId);
List<BizAgentApplicationDialoguesRecordEntity> recordEntities = bizAgentApplicationDialoguesRecordService.findByExample(recordEntity, null);
if (CollectionUtils.isNotEmpty(recordEntities)) {
for (BizAgentApplicationDialoguesRecordEntity entity : recordEntities) {
Message message = new Message();
message.setContent(entity.getContent());
message.setRole(entity.getRole());
messages.add(message);
}
}
//判断最后是否为User,若是则删除。
if (CollectionUtils.isNotEmpty(messages)) {
if (LLMRoleEnum.USER.getRole().equals(messages.get(messages.size() - 1).getRole())) {
Long recordId = recordEntities.get(recordEntities.size() - 1).getId();
bizAgentApplicationDialoguesRecordService.deletedById(recordId);
messages.remove(messages.size() - 1);
}
}
// 用户输入
Message message = new Message();
message.setContent(input);
message.setRole(LLMRoleEnum.USER.getRole());
messages.add(message);
logger.info("--------- Build Messages dialogsId:{},agentId:{},messages:{}--------------", dialogsId, agentId, messages);
return messages;
}
}
package cn.com.poc.thirdparty.resource.demand.ai.entity.csvchain;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dbchain.DBChainResult;
import cn.com.poc.thirdparty.resource.demand.dgTools.request.AbstractRequest;
import java.io.Serializable;
......
......@@ -40,4 +40,13 @@ public class CSVChainResult extends AbstractResult implements Serializable {
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "{" +
"status='" + status + '\'' +
", result='" + result + '\'' +
", message='" + message + '\'' +
'}';
}
}
......@@ -3,6 +3,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_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;
import cn.com.poc.thirdparty.resource.demand.ai.function.document_understanding.DocumentUnderstandIngFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.extraction.ContractExtractionFunction;
......@@ -52,6 +53,8 @@ public enum LargeModelFunctionEnum {
chart_generate(ChartGenerateFunction.class),
csv_data_analysis(CSVFunction.class),
;
private Class<? extends AbstractLargeModelFunction> function;
......
......@@ -37,7 +37,6 @@ public class ChartGenerateFunction extends AbstractLargeModelFunction {
private final Logger logger = LoggerFactory.getLogger(ChartGenerateFunction.class);
private final String MODEL = "deepseek-v3";
// private final String MODEL = "glm-4-plus";
private final String DESC = "根据用户问题和现有数据生成mermaid图表,如生成饼状图,折线图,散点图,柱状图,流程图等";
......
package cn.com.poc.thirdparty.resource.demand.ai.function.csv_data_analysis;
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.thirdparty.resource.demand.ai.entity.csvchain.CSVChainResponse;
import cn.com.poc.thirdparty.resource.demand.ai.entity.csvchain.CSVChainResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dbchain.DBChainResult;
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.chart_generate.ChartGenerateFunction;
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.ChainService;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* @author alex.yao
* @date 2025/6/20
*/
@Component
public class CSVFunction extends AbstractLargeModelFunction {
private final Logger logger = LoggerFactory.getLogger(ChartGenerateFunction.class);
private final String DESC = "解析用户上传的CSV或Excel文件,并使用Python库pands对其进行分析,根据用户问题返回数据";
private final FunctionLLMConfig functionLLMConfig = new FunctionLLMConfig.FunctionLLMConfigBuilder()
.name("csv_data_analysis")
.description(DESC)
.parameters(new Parameters("object")
.addProperties("question", new Properties("string", "对用户问题优化后的问题"))
.addProperties("file_url", new Properties("string", "文件真实地址"))
)
.build();
@Value(value = "${large-model.apikey}")
private String API_KEY;
@Resource
private ChainService chainService;
@Override
public AbstractFunctionResult<String> doFunction(String content, String identifier, List<DBChainResult> dbChainResults, List<KnowledgeContentResult> knowledgeContentResults) {
AbstractFunctionResult<String> result = new AbstractFunctionResult<>();
JSONObject jsonObject = JSONObject.parseObject(content);
if (!jsonObject.containsKey("file_url") || !jsonObject.containsKey("question")) {
logger.error("缺少必要参数,content:{}", content);
return result;
}
CSVChainResponse csvChainResponse = new CSVChainResponse();
csvChainResponse.setQuestion(jsonObject.getString("question"));
csvChainResponse.setFilePath(jsonObject.getString("file_url"));
csvChainResponse.setApiKey(API_KEY);
CSVChainResult csvChainResult = chainService.csvChain(csvChainResponse);
if (csvChainResult == null || csvChainResult.getResult() == null || "error".equals(csvChainResult.getStatus())) {
logger.error("csvChainResult is null,csvChainResult:{}", csvChainResult);
return result;
}
result.setFunctionResult(csvChainResult.getResult());
result.setPromptContent(csvChainResult.getResult());
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 this.getLLMConfig();
}
}
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