Compare commits
5 Commits
1dd00d329c
...
60477f99f5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60477f99f5 | ||
|
|
565c530dd5 | ||
|
|
5130885033 | ||
|
|
8e6463845b | ||
|
|
e89bffe289 |
@@ -2,7 +2,7 @@ CREATE TABLE `service_ai_feedback`
|
|||||||
(
|
(
|
||||||
`id` bigint NOT NULL,
|
`id` bigint NOT NULL,
|
||||||
`source` longtext NOT NULL,
|
`source` longtext NOT NULL,
|
||||||
`analysis_short` longtext,
|
`conclusion` longtext,
|
||||||
`analysis` longtext,
|
`analysis` longtext,
|
||||||
`pictures` longtext,
|
`pictures` longtext,
|
||||||
`status` varchar(50) NOT NULL DEFAULT 'ANALYSIS_PROCESSING',
|
`status` varchar(50) NOT NULL DEFAULT 'ANALYSIS_PROCESSING',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ CREATE TABLE `service_ai_knowledge`
|
|||||||
`id` bigint NOT NULL,
|
`id` bigint NOT NULL,
|
||||||
`vector_source_id` varchar(100) NOT NULL,
|
`vector_source_id` varchar(100) NOT NULL,
|
||||||
`name` varchar(100) NOT NULL,
|
`name` varchar(100) NOT NULL,
|
||||||
|
`description` longtext NOT NULL,
|
||||||
`strategy` varchar(10) NOT NULL,
|
`strategy` varchar(10) NOT NULL,
|
||||||
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`modified_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`modified_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.web.controller.caht;
|
package com.lanyuanxiaoyao.service.ai.web.controller.chat;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.configuration.Prompts;
|
import com.lanyuanxiaoyao.service.ai.web.configuration.Prompts;
|
||||||
@@ -45,12 +45,28 @@ public class FeedbackController {
|
|||||||
feedbackService.remove(id);
|
feedbackService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("reanalysis")
|
||||||
|
public void reanalysis(@RequestParam("id") Long id) {
|
||||||
|
feedbackService.reanalysis(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("conclude")
|
||||||
|
public void conclude(@RequestBody ConcludeItem item) {
|
||||||
|
feedbackService.updateConclusion(item.getId(), item.getConclusion());
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static final class CreateItem {
|
public static final class CreateItem {
|
||||||
private String source;
|
private String source;
|
||||||
private ImmutableList<Long> pictures;
|
private ImmutableList<Long> pictures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static final class ConcludeItem {
|
||||||
|
private Long id;
|
||||||
|
private String conclusion;
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static final class ListItem {
|
public static final class ListItem {
|
||||||
private Long id;
|
private Long id;
|
||||||
@@ -58,7 +74,7 @@ public class FeedbackController {
|
|||||||
private ImmutableList<String> pictures;
|
private ImmutableList<String> pictures;
|
||||||
private Feedback.Status status;
|
private Feedback.Status status;
|
||||||
private String analysis;
|
private String analysis;
|
||||||
private String analysisShort;
|
private String conclusion;
|
||||||
|
|
||||||
public ListItem(FileStoreProperties fileStoreProperties, Feedback feedback) {
|
public ListItem(FileStoreProperties fileStoreProperties, Feedback feedback) {
|
||||||
this.id = feedback.getId();
|
this.id = feedback.getId();
|
||||||
@@ -67,7 +83,7 @@ public class FeedbackController {
|
|||||||
.collect(id -> StrUtil.format("{}/upload/download/{}", fileStoreProperties.getDownloadPrefix(), id));
|
.collect(id -> StrUtil.format("{}/upload/download/{}", fileStoreProperties.getDownloadPrefix(), id));
|
||||||
this.status = feedback.getStatus();
|
this.status = feedback.getStatus();
|
||||||
this.analysis = feedback.getAnalysis();
|
this.analysis = feedback.getAnalysis();
|
||||||
this.analysisShort = feedback.getAnalysisShort();
|
this.conclusion = feedback.getConclusion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,18 @@ public class KnowledgeBaseController {
|
|||||||
@PostMapping("add")
|
@PostMapping("add")
|
||||||
public void add(
|
public void add(
|
||||||
@RequestParam("name") String name,
|
@RequestParam("name") String name,
|
||||||
|
@RequestParam("description") String description,
|
||||||
@RequestParam("strategy") String strategy
|
@RequestParam("strategy") String strategy
|
||||||
) throws ExecutionException, InterruptedException {
|
) throws ExecutionException, InterruptedException {
|
||||||
knowledgeBaseService.add(name, strategy);
|
knowledgeBaseService.add(name, description, strategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("update_description")
|
||||||
|
public void updateDescription(
|
||||||
|
@RequestParam("id") Long id,
|
||||||
|
@RequestParam("description") String description
|
||||||
|
) {
|
||||||
|
knowledgeBaseService.updateDescription(id, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("name")
|
@GetMapping("name")
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import org.eclipse.collections.api.list.ImmutableList;
|
|||||||
public class Feedback {
|
public class Feedback {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String source;
|
private String source;
|
||||||
private String analysisShort;
|
|
||||||
private String analysis;
|
|
||||||
private ImmutableList<Long> pictureIds;
|
private ImmutableList<Long> pictureIds;
|
||||||
|
private String analysis;
|
||||||
|
private String conclusion;
|
||||||
private Status status;
|
private Status status;
|
||||||
private Long createdTime;
|
private Long createdTime;
|
||||||
private Long modifiedTime;
|
private Long modifiedTime;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class Knowledge {
|
|||||||
private Long id;
|
private Long id;
|
||||||
private Long vectorSourceId;
|
private Long vectorSourceId;
|
||||||
private String name;
|
private String name;
|
||||||
|
private String description;
|
||||||
private String strategy;
|
private String strategy;
|
||||||
private Long createdTime;
|
private Long createdTime;
|
||||||
private Long modifiedTime;
|
private Long modifiedTime;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class KnowledgeVO {
|
|||||||
private Long id;
|
private Long id;
|
||||||
private Long vectorSourceId;
|
private Long vectorSourceId;
|
||||||
private String name;
|
private String name;
|
||||||
|
private String description;
|
||||||
private String strategy;
|
private String strategy;
|
||||||
private Long size;
|
private Long size;
|
||||||
private Long points;
|
private Long points;
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Service
|
@Service
|
||||||
public class FeedbackService {
|
public class FeedbackService {
|
||||||
public static final String FEEDBACK_TABLE_NAME = Constants.DATABASE_NAME + ".service_ai_feedback";
|
public static final String FEEDBACK_TABLE_NAME = Constants.DATABASE_NAME + ".service_ai_feedback";
|
||||||
public static final String[] FEEDBACK_COLUMNS = new String[]{"id", "source", "analysis_short", "analysis", "pictures", "status", "created_time", "modified_time"};
|
public static final String[] FEEDBACK_COLUMNS = new String[]{"id", "source", "conclusion", "analysis", "pictures", "status", "created_time", "modified_time"};
|
||||||
private static final RowMapper<Feedback> feedbackMapper = (rs, row) -> {
|
private static final RowMapper<Feedback> feedbackMapper = (rs, row) -> {
|
||||||
Feedback feedback = new Feedback();
|
Feedback feedback = new Feedback();
|
||||||
feedback.setId(rs.getLong(1));
|
feedback.setId(rs.getLong(1));
|
||||||
feedback.setSource(rs.getString(2));
|
feedback.setSource(rs.getString(2));
|
||||||
feedback.setAnalysisShort(rs.getString(3));
|
feedback.setConclusion(rs.getString(3));
|
||||||
feedback.setAnalysis(rs.getString(4));
|
feedback.setAnalysis(rs.getString(4));
|
||||||
feedback.setPictureIds(
|
feedback.setPictureIds(
|
||||||
StrUtil.isBlank(rs.getString(5))
|
StrUtil.isBlank(rs.getString(5))
|
||||||
@@ -92,20 +92,32 @@ public class FeedbackService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateAnalysis(Long id, String analysis, String analysisShort) {
|
public void updateAnalysis(Long id, String analysis) {
|
||||||
Assert.notNull(id, "ID cannot be null");
|
Assert.notNull(id, "ID cannot be null");
|
||||||
template.update(
|
template.update(
|
||||||
SqlBuilder.update(FEEDBACK_TABLE_NAME)
|
SqlBuilder.update(FEEDBACK_TABLE_NAME)
|
||||||
.set("analysis", "?")
|
.set("analysis", "?")
|
||||||
.addSet("analysis_short", "?")
|
|
||||||
.whereEq("id", "?")
|
.whereEq("id", "?")
|
||||||
.precompileSql(),
|
.precompileSql(),
|
||||||
analysis,
|
analysis,
|
||||||
analysisShort,
|
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void updateConclusion(Long id, String conclusion) {
|
||||||
|
Assert.notNull(id, "ID cannot be null");
|
||||||
|
template.update(
|
||||||
|
SqlBuilder.update(FEEDBACK_TABLE_NAME)
|
||||||
|
.set("conclusion", "?")
|
||||||
|
.whereEq("id", "?")
|
||||||
|
.precompileSql(),
|
||||||
|
conclusion,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
updateStatus(id, Feedback.Status.FINISHED);
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateStatus(Long id, Feedback.Status status) {
|
public void updateStatus(Long id, Feedback.Status status) {
|
||||||
Assert.notNull(id, "ID cannot be null");
|
Assert.notNull(id, "ID cannot be null");
|
||||||
@@ -140,4 +152,9 @@ public class FeedbackService {
|
|||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void reanalysis(Long id) {
|
||||||
|
updateStatus(id, Feedback.Status.ANALYSIS_PROCESSING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import com.lanyuanxiaoyao.service.ai.web.entity.vo.KnowledgeVO;
|
|||||||
import com.lanyuanxiaoyao.service.common.Constants;
|
import com.lanyuanxiaoyao.service.common.Constants;
|
||||||
import io.qdrant.client.QdrantClient;
|
import io.qdrant.client.QdrantClient;
|
||||||
import io.qdrant.client.grpc.Collections;
|
import io.qdrant.client.grpc.Collections;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -32,14 +31,16 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Service
|
@Service
|
||||||
public class KnowledgeBaseService {
|
public class KnowledgeBaseService {
|
||||||
public static final String KNOWLEDGE_TABLE_NAME = Constants.DATABASE_NAME + ".service_ai_knowledge";
|
public static final String KNOWLEDGE_TABLE_NAME = Constants.DATABASE_NAME + ".service_ai_knowledge";
|
||||||
|
public static final String[] KNOWLEDGE_COLUMNS = new String[]{"id", "vector_source_id", "name", "description", "strategy", "created_time", "modified_time"};
|
||||||
private static final RowMapper<Knowledge> knowledgeMapper = (rs, row) -> {
|
private static final RowMapper<Knowledge> knowledgeMapper = (rs, row) -> {
|
||||||
Knowledge knowledge = new Knowledge();
|
Knowledge knowledge = new Knowledge();
|
||||||
knowledge.setId(rs.getLong(1));
|
knowledge.setId(rs.getLong(1));
|
||||||
knowledge.setVectorSourceId(rs.getLong(2));
|
knowledge.setVectorSourceId(rs.getLong(2));
|
||||||
knowledge.setName(rs.getString(3));
|
knowledge.setName(rs.getString(3));
|
||||||
knowledge.setStrategy(rs.getString(4));
|
knowledge.setDescription(rs.getString(4));
|
||||||
knowledge.setCreatedTime(rs.getTimestamp(5).getTime());
|
knowledge.setStrategy(rs.getString(5));
|
||||||
knowledge.setModifiedTime(rs.getTimestamp(6).getTime());
|
knowledge.setCreatedTime(rs.getTimestamp(6).getTime());
|
||||||
|
knowledge.setModifiedTime(rs.getTimestamp(7).getTime());
|
||||||
return knowledge;
|
return knowledge;
|
||||||
};
|
};
|
||||||
private final JdbcTemplate template;
|
private final JdbcTemplate template;
|
||||||
@@ -56,7 +57,7 @@ public class KnowledgeBaseService {
|
|||||||
|
|
||||||
public Knowledge get(Long id) {
|
public Knowledge get(Long id) {
|
||||||
return template.queryForObject(
|
return template.queryForObject(
|
||||||
SqlBuilder.select("id", "vector_source_id", "name", "strategy", "created_time", "modified_time")
|
SqlBuilder.select(KNOWLEDGE_COLUMNS)
|
||||||
.from(KNOWLEDGE_TABLE_NAME)
|
.from(KNOWLEDGE_TABLE_NAME)
|
||||||
.whereEq("id", "?")
|
.whereEq("id", "?")
|
||||||
.precompileSql(),
|
.precompileSql(),
|
||||||
@@ -66,7 +67,7 @@ public class KnowledgeBaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void add(String name, String strategy) throws ExecutionException, InterruptedException {
|
public void add(String name, String description, String strategy) throws ExecutionException, InterruptedException {
|
||||||
Integer count = template.queryForObject(
|
Integer count = template.queryForObject(
|
||||||
SqlBuilder.select("count(*)")
|
SqlBuilder.select("count(*)")
|
||||||
.from(KNOWLEDGE_TABLE_NAME)
|
.from(KNOWLEDGE_TABLE_NAME)
|
||||||
@@ -82,13 +83,14 @@ public class KnowledgeBaseService {
|
|||||||
long id = SnowflakeId.next();
|
long id = SnowflakeId.next();
|
||||||
long vectorSourceId = SnowflakeId.next();
|
long vectorSourceId = SnowflakeId.next();
|
||||||
template.update(
|
template.update(
|
||||||
SqlBuilder.insertInto(KNOWLEDGE_TABLE_NAME, "id", "vector_source_id", "name", "strategy")
|
SqlBuilder.insertInto(KNOWLEDGE_TABLE_NAME, "id", "vector_source_id", "name", "description", "strategy")
|
||||||
.values()
|
.values()
|
||||||
.addValue("?", "?", "?", "?")
|
.addValue("?", "?", "?", "?", "?")
|
||||||
.precompileSql(),
|
.precompileSql(),
|
||||||
id,
|
id,
|
||||||
vectorSourceId,
|
vectorSourceId,
|
||||||
name,
|
name,
|
||||||
|
description,
|
||||||
strategy
|
strategy
|
||||||
);
|
);
|
||||||
client.createCollectionAsync(
|
client.createCollectionAsync(
|
||||||
@@ -100,6 +102,18 @@ public class KnowledgeBaseService {
|
|||||||
).get();
|
).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void updateDescription(Long id, String description) {
|
||||||
|
template.update(
|
||||||
|
SqlBuilder.update(KNOWLEDGE_TABLE_NAME)
|
||||||
|
.set("description", "?")
|
||||||
|
.whereEq("id", "?")
|
||||||
|
.precompileSql(),
|
||||||
|
description,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public String getName(Long id) {
|
public String getName(Long id) {
|
||||||
return template.queryForObject(
|
return template.queryForObject(
|
||||||
SqlBuilder.select("name")
|
SqlBuilder.select("name")
|
||||||
@@ -113,7 +127,7 @@ public class KnowledgeBaseService {
|
|||||||
|
|
||||||
public ImmutableList<KnowledgeVO> list() {
|
public ImmutableList<KnowledgeVO> list() {
|
||||||
return template.query(
|
return template.query(
|
||||||
SqlBuilder.select("id", "vector_source_id", "name", "strategy", "created_time", "modified_time")
|
SqlBuilder.select(KNOWLEDGE_COLUMNS)
|
||||||
.from(KNOWLEDGE_TABLE_NAME)
|
.from(KNOWLEDGE_TABLE_NAME)
|
||||||
.orderByDesc("created_time")
|
.orderByDesc("created_time")
|
||||||
.build(),
|
.build(),
|
||||||
@@ -127,6 +141,7 @@ public class KnowledgeBaseService {
|
|||||||
vo.setId(knowledge.getId());
|
vo.setId(knowledge.getId());
|
||||||
vo.setVectorSourceId(knowledge.getVectorSourceId());
|
vo.setVectorSourceId(knowledge.getVectorSourceId());
|
||||||
vo.setName(knowledge.getName());
|
vo.setName(knowledge.getName());
|
||||||
|
vo.setDescription(knowledge.getDescription());
|
||||||
vo.setPoints(info.getPointsCount());
|
vo.setPoints(info.getPointsCount());
|
||||||
vo.setSegments(info.getSegmentsCount());
|
vo.setSegments(info.getSegmentsCount());
|
||||||
vo.setStatus(info.getStatus().name());
|
vo.setStatus(info.getStatus().name());
|
||||||
@@ -165,7 +180,7 @@ public class KnowledgeBaseService {
|
|||||||
String text,
|
String text,
|
||||||
Integer limit,
|
Integer limit,
|
||||||
Double threshold
|
Double threshold
|
||||||
) throws ExecutionException, InterruptedException, IOException {
|
) throws ExecutionException, InterruptedException {
|
||||||
Knowledge knowledge = get(id);
|
Knowledge knowledge = get(id);
|
||||||
Boolean exists = client.collectionExistsAsync(String.valueOf(knowledge.getVectorSourceId())).get();
|
Boolean exists = client.collectionExistsAsync(String.valueOf(knowledge.getVectorSourceId())).get();
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
@@ -182,13 +197,6 @@ public class KnowledgeBaseService {
|
|||||||
.similarityThreshold(threshold)
|
.similarityThreshold(threshold)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
// 如果只是一个知识库的话,似乎没有什么rerank的必要...
|
|
||||||
/* List<org.noear.solon.ai.rag.Document> rerankDocuments = rerankingModel.rerank(
|
|
||||||
text,
|
|
||||||
documents.stream()
|
|
||||||
.map(doc -> new org.noear.solon.ai.rag.Document(doc.getId(), doc.getText(), doc.getMetadata(), doc.getScore()))
|
|
||||||
.toList()
|
|
||||||
); */
|
|
||||||
return Lists.immutable.ofAll(documents)
|
return Lists.immutable.ofAll(documents)
|
||||||
.collect(Document::getText);
|
.collect(Document::getText);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ public class FeedbackNodes {
|
|||||||
if (StrUtil.isBlank(optimizedSource)) {
|
if (StrUtil.isBlank(optimizedSource)) {
|
||||||
log.warn("Optimized source is blank");
|
log.warn("Optimized source is blank");
|
||||||
}
|
}
|
||||||
context.setOptimizedSource(optimizedSource);
|
context.setOptimizedSource(StrUtil.trim(optimizedSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "feedback_suggest", nodeName = "大模型建议", nodeType = NodeTypeEnum.COMMON)
|
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "feedback_suggest", nodeName = "大模型建议", nodeType = NodeTypeEnum.COMMON)
|
||||||
@@ -165,29 +165,39 @@ public class FeedbackNodes {
|
|||||||
Feedback feedback = context.getFeedback();
|
Feedback feedback = context.getFeedback();
|
||||||
ChatClient client = chatClientBuilder.build();
|
ChatClient client = chatClientBuilder.build();
|
||||||
String analysis = client.prompt()
|
String analysis = client.prompt()
|
||||||
|
// language=TEXT
|
||||||
.system("""
|
.system("""
|
||||||
你是一名专业的IT系统运维工程师,对于用户输入的报障信息,你会给出专业的意见
|
你是一名专业的IT系统运维工程师。针对用户输入的报障信息,严格遵循以下步骤:
|
||||||
|
1. 提取关键要素: 精准识别报障信息中的关键要素(如系统/设备名称、故障现象、错误信息、时间地点、影响范围、用户操作步骤等)。
|
||||||
|
2. 分析诊断: 基于提取的要素,运用运维专业知识,分析潜在原因,并提出优先级高、可操作性强的排障建议或初步诊断方向。
|
||||||
|
3. 输出专业意见:
|
||||||
|
内容要求: 意见必须包含明确的行动步骤(如检查XX日志、验证XX配置、重启XX服务、联系XX团队)、潜在风险提示及预期效果。
|
||||||
|
表达要求: 使用清晰、简洁、专业的技术术语,避免使用推测性语言或不确定词汇(如“可能”、“大概”、“也许”)。
|
||||||
|
格式要求: 直接输出意见内容,避免添加引导语(如“我的建议是”、“根据报障信息”等)。
|
||||||
""")
|
""")
|
||||||
.user(context.getOptimizedSource())
|
.user(context.getOptimizedSource())
|
||||||
.call()
|
.call()
|
||||||
.content();
|
.content();
|
||||||
feedback.setAnalysis(analysis);
|
feedback.setAnalysis(StrUtil.trim(analysis));
|
||||||
Assert.notBlank(analysis, "Analysis cannot be blank");
|
Assert.notBlank(analysis, "Analysis cannot be blank");
|
||||||
String analysisShort = client.prompt()
|
String conclusion = client.prompt()
|
||||||
|
// language=TEXT
|
||||||
.system("""
|
.system("""
|
||||||
你是一名专业的文字编辑,对用户输入的内容,用一段话总结内容
|
你是一名专业的文字编辑。严格按以下要求处理用户输入:
|
||||||
""")
|
核心逻辑: 用一段话精准总结输入内容的核心信息,确保涵盖所有关键点。禁止虚构、扩展或添加原文不存在的信息。
|
||||||
|
输出规范: 仅输出一段总结文本。禁止分点、分段、使用Markdown格式(如着重、- 或 1. 等列表符号)或添加任何无关引导语(如“总结如下”、“该总结指出”、“本文总结”等)。直接给出总结文本。""")
|
||||||
.user(analysis)
|
.user(analysis)
|
||||||
.call()
|
.call()
|
||||||
.content();
|
.content();
|
||||||
feedback.setAnalysisShort(analysisShort);
|
feedback.setConclusion(StrUtil.trim(conclusion));
|
||||||
}
|
}
|
||||||
|
|
||||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "feedback_save", nodeName = "保存分析内容", nodeType = NodeTypeEnum.COMMON)
|
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "feedback_save", nodeName = "保存分析内容", nodeType = NodeTypeEnum.COMMON)
|
||||||
public void saveFeedback(NodeComponent node) {
|
public void saveFeedback(NodeComponent node) {
|
||||||
FeedbackContext context = node.getContextBean(FeedbackContext.class);
|
FeedbackContext context = node.getContextBean(FeedbackContext.class);
|
||||||
Feedback feedback = context.getFeedback();
|
Feedback feedback = context.getFeedback();
|
||||||
feedbackService.updateAnalysis(feedback.getId(), feedback.getAnalysis(), feedback.getAnalysisShort());
|
feedbackService.updateAnalysis(feedback.getId(), feedback.getAnalysis());
|
||||||
|
feedbackService.updateConclusion(feedback.getId(), feedback.getConclusion());
|
||||||
feedbackService.updateStatus(feedback.getId(), Feedback.Status.ANALYSIS_SUCCESS);
|
feedbackService.updateStatus(feedback.getId(), Feedback.Status.ANALYSIS_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
server:
|
||||||
|
compression:
|
||||||
|
enabled: true
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: service-ai-web
|
name: service-ai-web
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import {amisRender, commonInfo, crudCommonOptions, mappingField, mappingItem} fr
|
|||||||
|
|
||||||
const FeedbackDiv = styled.div`
|
const FeedbackDiv = styled.div`
|
||||||
.feedback-list-images {
|
.feedback-list-images {
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
.antd-Img-container {
|
.antd-Img-container {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -84,17 +86,24 @@ const Feedback: React.FC = () => {
|
|||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'source',
|
|
||||||
label: '故障描述',
|
label: '故障描述',
|
||||||
|
type: 'flex',
|
||||||
|
direction: 'column',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'tpl',
|
||||||
|
className: 'white-space-pre',
|
||||||
|
tpl: '${source}',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'pictures',
|
|
||||||
label: '相关截图',
|
|
||||||
width: 200,
|
|
||||||
className: 'feedback-list-images',
|
className: 'feedback-list-images',
|
||||||
type: 'images',
|
type: 'images',
|
||||||
enlargeAble: true,
|
enlargeAble: true,
|
||||||
enlargeWithGallary: true,
|
enlargeWithGallary: true,
|
||||||
|
source: '${pictures}',
|
||||||
|
showToolbar: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: '状态',
|
||||||
@@ -105,9 +114,107 @@ const Feedback: React.FC = () => {
|
|||||||
{
|
{
|
||||||
type: 'operation',
|
type: 'operation',
|
||||||
label: '操作',
|
label: '操作',
|
||||||
width: 150,
|
width: 200,
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
|
visibleOn: '${status === \'ANALYSIS_SUCCESS\'}',
|
||||||
|
type: 'action',
|
||||||
|
label: '重新分析',
|
||||||
|
level: 'link',
|
||||||
|
size: 'sm',
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: {
|
||||||
|
method: 'get',
|
||||||
|
url: `${commonInfo.baseAiUrl}/feedback/reanalysis`,
|
||||||
|
data: {
|
||||||
|
id: '${id}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
confirmText: '确认执行重新分析?',
|
||||||
|
confirmTitle: '重新分析',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
disabledOn: '${status === \'ANALYSIS_PROCESSING\'}',
|
||||||
|
type: 'action',
|
||||||
|
label: '详情',
|
||||||
|
level: 'link',
|
||||||
|
size: 'sm',
|
||||||
|
actionType: 'dialog',
|
||||||
|
dialog: {
|
||||||
|
title: '报障详情',
|
||||||
|
size: 'lg',
|
||||||
|
closeOnOutside: true,
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
visibleOn: '${status !== \'FINISHED\'}',
|
||||||
|
type: 'action',
|
||||||
|
actionType: 'close',
|
||||||
|
label: '取消',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visibleOn: '${status !== \'FINISHED\'}',
|
||||||
|
type: 'submit',
|
||||||
|
label: '确认',
|
||||||
|
level: 'primary',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
body: {
|
||||||
|
debug: commonInfo.debug,
|
||||||
|
type: 'form',
|
||||||
|
mode: 'normal',
|
||||||
|
api: {
|
||||||
|
method: 'post',
|
||||||
|
url: `${commonInfo.baseAiUrl}/feedback/conclude`,
|
||||||
|
data: {
|
||||||
|
id: '${id}',
|
||||||
|
conclusion: '${conclusion|default:undefined}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'textarea',
|
||||||
|
name: 'source',
|
||||||
|
label: '报障描述',
|
||||||
|
static: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'control',
|
||||||
|
name: 'pictures',
|
||||||
|
label: '相关截图',
|
||||||
|
body: {
|
||||||
|
type: 'images',
|
||||||
|
enlargeAble: true,
|
||||||
|
enlargeWithGallary: true,
|
||||||
|
showToolbar: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'control',
|
||||||
|
name: 'analysis',
|
||||||
|
label: 'AI辅助分析',
|
||||||
|
body: {
|
||||||
|
type: 'markdown',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visibleOn: '${status !== \'FINISHED\'}',
|
||||||
|
type: 'textarea',
|
||||||
|
name: 'conclusion',
|
||||||
|
label: '结论',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
visibleOn: '${status === \'FINISHED\'}',
|
||||||
|
type: 'textarea',
|
||||||
|
name: 'conclusion',
|
||||||
|
label: '结论',
|
||||||
|
static: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
disabledOn: '${status === \'ANALYSIS_PROCESSING\'}',
|
||||||
type: 'action',
|
type: 'action',
|
||||||
label: '删除',
|
label: '删除',
|
||||||
className: 'text-danger hover:text-red-600',
|
className: 'text-danger hover:text-red-600',
|
||||||
@@ -121,8 +228,8 @@ const Feedback: React.FC = () => {
|
|||||||
id: '${id}',
|
id: '${id}',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
confirmText: '确认删除',
|
|
||||||
confirmTitle: '删除',
|
confirmTitle: '删除',
|
||||||
|
confirmText: '删除后将无法恢复,确认删除?',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,12 +50,20 @@ const Knowledge: React.FC = () => {
|
|||||||
type: 'input-text',
|
type: 'input-text',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: '名称',
|
label: '名称',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'textarea',
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: 'strategy',
|
name: 'strategy',
|
||||||
label: '类型',
|
label: '类型',
|
||||||
value: 'Cosine',
|
value: 'Cosine',
|
||||||
|
required: true,
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '文本',
|
label: '文本',
|
||||||
@@ -77,6 +85,11 @@ const Knowledge: React.FC = () => {
|
|||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: '名称',
|
label: '名称',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '类型',
|
label: '类型',
|
||||||
@@ -99,8 +112,41 @@ const Knowledge: React.FC = () => {
|
|||||||
{
|
{
|
||||||
type: 'operation',
|
type: 'operation',
|
||||||
label: '操作',
|
label: '操作',
|
||||||
width: 150,
|
width: 200,
|
||||||
buttons: [
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
label: '更新',
|
||||||
|
level: 'link',
|
||||||
|
size: 'sm',
|
||||||
|
actionType: 'dialog',
|
||||||
|
dialog: {
|
||||||
|
title: '更新描述',
|
||||||
|
body: {
|
||||||
|
debug: commonInfo.debug,
|
||||||
|
type: 'form',
|
||||||
|
api: {
|
||||||
|
method: 'post',
|
||||||
|
url: `${commonInfo.baseAiUrl}/knowledge/update_description`,
|
||||||
|
dataType: 'form',
|
||||||
|
},
|
||||||
|
mode: 'normal',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'hidden',
|
||||||
|
name: "id",
|
||||||
|
// value: '${id}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'textarea',
|
||||||
|
name: 'description',
|
||||||
|
label: '描述',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'action',
|
type: 'action',
|
||||||
label: '详情',
|
label: '详情',
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ import {
|
|||||||
TableOutlined,
|
TableOutlined,
|
||||||
ToolOutlined,
|
ToolOutlined,
|
||||||
} from '@ant-design/icons'
|
} from '@ant-design/icons'
|
||||||
|
import {values} from 'licia'
|
||||||
import {Navigate, type RouteObject} from 'react-router'
|
import {Navigate, type RouteObject} from 'react-router'
|
||||||
import Conversation from './pages/ai/Conversation.tsx'
|
import Conversation from './pages/ai/Conversation.tsx'
|
||||||
|
import Feedback from './pages/ai/feedback/Feedback.tsx'
|
||||||
import DataDetail from './pages/ai/knowledge/DataDetail.tsx'
|
import DataDetail from './pages/ai/knowledge/DataDetail.tsx'
|
||||||
import DataImport from './pages/ai/knowledge/DataImport.tsx'
|
import DataImport from './pages/ai/knowledge/DataImport.tsx'
|
||||||
import DataSegment from './pages/ai/knowledge/DataSegment.tsx'
|
import DataSegment from './pages/ai/knowledge/DataSegment.tsx'
|
||||||
@@ -28,10 +30,8 @@ import Tool from './pages/overview/Tool.tsx'
|
|||||||
import Version from './pages/overview/Version.tsx'
|
import Version from './pages/overview/Version.tsx'
|
||||||
import Yarn from './pages/overview/Yarn.tsx'
|
import Yarn from './pages/overview/Yarn.tsx'
|
||||||
import YarnCluster from './pages/overview/YarnCluster.tsx'
|
import YarnCluster from './pages/overview/YarnCluster.tsx'
|
||||||
import {commonInfo} from './util/amis.tsx'
|
|
||||||
import Test from './pages/Test.tsx'
|
import Test from './pages/Test.tsx'
|
||||||
import Feedback from './pages/ai/feedback/Feedback.tsx'
|
import {commonInfo} from './util/amis.tsx'
|
||||||
import {values} from 'licia'
|
|
||||||
|
|
||||||
export const routes: RouteObject[] = [
|
export const routes: RouteObject[] = [
|
||||||
{
|
{
|
||||||
@@ -203,7 +203,7 @@ export const menus = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/ai/feedback',
|
path: '/ai/feedback',
|
||||||
name: '智慧报账',
|
name: '智慧报障',
|
||||||
icon: <CheckSquareOutlined/>,
|
icon: <CheckSquareOutlined/>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ export function crudCommonOptions() {
|
|||||||
resizable: false,
|
resizable: false,
|
||||||
syncLocation: false,
|
syncLocation: false,
|
||||||
silentPolling: true,
|
silentPolling: true,
|
||||||
|
columnsTogglable: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
server:
|
server:
|
||||||
port: 0
|
port: 0
|
||||||
|
compression:
|
||||||
|
enabled: true
|
||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: service-web
|
name: service-web
|
||||||
|
|||||||
Reference in New Issue
Block a user