This is an automated email from the ASF dual-hosted git repository.
gaoxihui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozhera.git
The following commit(s) were added to refs/heads/master by this push:
new b7b2bd35 feat: add the function of ai log analysis (#593)
b7b2bd35 is described below
commit b7b2bd3557f899b796284429375b2ea8c61e9129
Author: Xue <[email protected]>
AuthorDate: Mon Jun 30 11:24:14 2025 +0800
feat: add the function of ai log analysis (#593)
* feat: added ai intelligent log analysis function, Solution 1
- added ai intelligent log analysis function, Solution 1
* feat: ai intelligent log analysis
-ai intelligent log analysis 02
* feat: Final version with added artificial intelligence log analysis
function
-Final version with added artificial intelligence log analysis function
---------
Co-authored-by: wtt <[email protected]>
---
ozhera-log/log-manager/pom.xml | 5 +
.../log/manager/controller/MilogAiController.java | 70 ++++
.../manager/mapper/MilogAiConversationMapper.java | 31 ++
.../ozhera/log/manager/model/bo/BotQAParam.java | 36 ++
.../manager/model/dto/AiAnalysisHistoryDTO.java | 28 ++
.../log/manager/model/dto/LogAiAnalysisDTO.java | 14 +
.../manager/model/pojo/MilogAiConversationDO.java | 52 +++
.../manager/model/vo/LogAiAnalysisResponse.java | 9 +
.../manager/service/MilogAiAnalysisService.java | 45 +++
.../manager/service/bot/ContentSimplifyBot.java | 88 +++++
.../log/manager/service/bot/LogAnalysisBot.java | 94 +++++
.../service/impl/MilogAiAnalysisServiceImpl.java | 416 +++++++++++++++++++++
.../src/main/resources/config.properties | 2 +-
ozhera-log/log-manager/src/main/resources/log.sql | 18 +
.../resources/mapper/MilogAiConversationMapper.xml | 34 ++
ozhera-log/pom.xml | 15 +
16 files changed, 956 insertions(+), 1 deletion(-)
diff --git a/ozhera-log/log-manager/pom.xml b/ozhera-log/log-manager/pom.xml
index 2ae23f7b..8be0cf3e 100644
--- a/ozhera-log/log-manager/pom.xml
+++ b/ozhera-log/log-manager/pom.xml
@@ -291,6 +291,11 @@ http://www.apache.org/licenses/LICENSE-2.0
</exclusions>
</dependency>
+ <dependency>
+ <groupId>run.mone</groupId>
+ <artifactId>hive</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/controller/MilogAiController.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/controller/MilogAiController.java
new file mode 100644
index 00000000..aa27bb43
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/controller/MilogAiController.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.controller;
+
+import com.xiaomi.youpin.docean.anno.Controller;
+import com.xiaomi.youpin.docean.anno.RequestMapping;
+import com.xiaomi.youpin.docean.anno.RequestParam;
+import org.apache.ozhera.log.manager.model.bo.BotQAParam;
+import org.apache.ozhera.log.manager.model.dto.AiAnalysisHistoryDTO;
+import org.apache.ozhera.log.manager.model.dto.LogAiAnalysisDTO;
+import org.apache.ozhera.log.manager.model.vo.LogAiAnalysisResponse;
+import org.apache.ozhera.log.common.Result;
+import org.apache.ozhera.log.manager.service.MilogAiAnalysisService;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Controller
+public class MilogAiController {
+
+ @Resource
+ private MilogAiAnalysisService milogAiAnalysisService;
+
+ @RequestMapping(path = "/milog/tail/aiAnalysis", method = "post")
+ public Result<LogAiAnalysisResponse> aiAnalysis(LogAiAnalysisDTO
tailLogAiAnalysisDTO) {
+ return milogAiAnalysisService.tailLogAiAnalysis(tailLogAiAnalysisDTO);
+ }
+
+ @RequestMapping(path = "/milog/tail/aiHistoryList", method = "post")
+ public Result<List<AiAnalysisHistoryDTO>>
getAiHistoryList(@RequestParam(value = "storeId") Long storeId){
+ return milogAiAnalysisService.getAiHistoryList(storeId);
+ }
+
+ @RequestMapping(path = "/milog/tail/aiConversation", method = "post")
+ public Result<List<BotQAParam.QAParam>>
getAiConversation(@RequestParam(value = "id") Long id){
+ return milogAiAnalysisService.getAiConversation(id);
+ }
+
+ @RequestMapping(path = "/milog/tail/deleteAiConversation", method = "post")
+ public Result<Boolean> deleteAiConversation(@RequestParam(value = "id")
Long id){
+ return milogAiAnalysisService.deleteAiConversation(id);
+ }
+
+ @RequestMapping(path = "/milog/tail/updateAiName", method = "post")
+ public Result<Boolean> updateAiName(@RequestParam(value = "id") Long id,
@RequestParam(value = "name") String name){
+ return milogAiAnalysisService.updateAiName(id, name);
+ }
+
+ @RequestMapping(path = "/milog/tail/closeAiAnalysis", method = "post")
+ public Result<Boolean> closeAiAnalysis(@RequestParam(value = "id") Long
id){
+ return milogAiAnalysisService.closeAiAnalysis(id);
+ }
+
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/mapper/MilogAiConversationMapper.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/mapper/MilogAiConversationMapper.java
new file mode 100644
index 00000000..f6d6f157
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/mapper/MilogAiConversationMapper.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ozhera.log.manager.model.pojo.MilogAiConversationDO;
+
+import java.util.List;
+
+@Mapper
+public interface MilogAiConversationMapper extends
BaseMapper<MilogAiConversationDO> {
+ List<MilogAiConversationDO> getListByUserAndStore(@Param(value =
"storeId") Long storeId, @Param(value = "creator") String creator);
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/bo/BotQAParam.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/bo/BotQAParam.java
new file mode 100644
index 00000000..d0dbd524
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/bo/BotQAParam.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.model.bo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class BotQAParam {
+ private List<QAParam> historyConversation;
+ private String LatestQuestion;
+
+ @Data
+ public static class QAParam {
+ private String time;
+ private String user;
+ private String bot;
+ }
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/dto/AiAnalysisHistoryDTO.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/dto/AiAnalysisHistoryDTO.java
new file mode 100644
index 00000000..88da678d
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/dto/AiAnalysisHistoryDTO.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.model.dto;
+
+import lombok.Data;
+
+@Data
+public class AiAnalysisHistoryDTO {
+ private Long id;
+ private String name;
+ private String createTime;
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/dto/LogAiAnalysisDTO.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/dto/LogAiAnalysisDTO.java
new file mode 100644
index 00000000..f6312b81
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/dto/LogAiAnalysisDTO.java
@@ -0,0 +1,14 @@
+package org.apache.ozhera.log.manager.model.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class LogAiAnalysisDTO {
+ private List<String> logs;
+
+ private Long storeId;
+
+ private Long conversationId;
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/pojo/MilogAiConversationDO.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/pojo/MilogAiConversationDO.java
new file mode 100644
index 00000000..3d7f2b92
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/pojo/MilogAiConversationDO.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.model.pojo;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("milog_ai_conversation")
+public class MilogAiConversationDO implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ private Long storeId;
+
+ private String conversationName;
+
+ private String conversationContext;
+
+ private String originalConversation;
+
+ private String creator;
+
+ private Long createTime;
+
+ private Long updateTime;
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/vo/LogAiAnalysisResponse.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/vo/LogAiAnalysisResponse.java
new file mode 100644
index 00000000..62bfef76
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/model/vo/LogAiAnalysisResponse.java
@@ -0,0 +1,9 @@
+package org.apache.ozhera.log.manager.model.vo;
+
+import lombok.Data;
+
+@Data
+public class LogAiAnalysisResponse {
+ private Long conversationId;
+ private String content;
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/MilogAiAnalysisService.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/MilogAiAnalysisService.java
new file mode 100644
index 00000000..783040b1
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/MilogAiAnalysisService.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.service;
+
+import org.apache.ozhera.log.common.Result;
+import org.apache.ozhera.log.manager.model.bo.BotQAParam;
+import org.apache.ozhera.log.manager.model.dto.AiAnalysisHistoryDTO;
+import org.apache.ozhera.log.manager.model.dto.LogAiAnalysisDTO;
+import org.apache.ozhera.log.manager.model.vo.LogAiAnalysisResponse;
+
+import java.util.List;
+
+public interface MilogAiAnalysisService {
+
+ Result<LogAiAnalysisResponse> tailLogAiAnalysis(LogAiAnalysisDTO
tailLogAiAnalysisDTO);
+
+ void shutdown();
+
+ Result<List<AiAnalysisHistoryDTO>> getAiHistoryList(Long storeId);
+
+ Result<List<BotQAParam.QAParam>> getAiConversation(Long id);
+
+ Result<Boolean> deleteAiConversation(Long id);
+
+ Result<Boolean> updateAiName(Long id, String name);
+
+ Result<Boolean> closeAiAnalysis(Long id);
+
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/bot/ContentSimplifyBot.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/bot/ContentSimplifyBot.java
new file mode 100644
index 00000000..fb802e0c
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/bot/ContentSimplifyBot.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.service.bot;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.xiaomi.youpin.docean.anno.Service;
+import run.mone.hive.Environment;
+import run.mone.hive.llm.LLM;
+import run.mone.hive.llm.LLMProvider;
+import run.mone.hive.roles.Role;
+import run.mone.hive.schema.AiMessage;
+import run.mone.hive.schema.Message;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+@Service
+public class ContentSimplifyBot extends Role {
+ private String baseText = """
+ 你是一个对话摘要压缩助手,接下来我会提供一段对话历史,格式是一个 JSON 列表,列表中的每一项是一个对象,包含三个字段:
+
+ - "time":会话开始的时间
+ - "user":表示用户的提问或陈述
+ - "bot":表示机器人的回答
+
+ 你的任务是对整段对话进行语义压缩,保留关键信息,删除冗余、重复、细节性描述,使对话更加简洁、精炼。但请务必:
+
+ 1. **保持输出数据结构与输入一致**:输出仍然是一个 JSON 列表,每一项仍然包含 "time" 、"user" 和
"bot" 三个字段。
+ 2. **尽可能减少轮数**:若多轮对话围绕同一问题展开,可以合并为一轮,但必须保留语义完整,并且时间选择为多轮中最后一轮的时间。
+ 3.
**对于一些无关的信息,或者没有什么用的信息直接去除,一定在保留核心关键信息的情况下尽可能的压缩,至少保证压缩后的字符为压缩前的30%往下
+ 4. **如果每轮的数据中存在原始的日志信息,那么对于日志信息不要进行压缩,需要保持原样
+ 5. **不得添加任何非对话内容**,例如“压缩后的内容如下”、“总结如下”等。
+ 6. **输出必须是一个合法的 JSON 列表,结构和字段不变**。
+
+ 下面是原始对话历史,请进行压缩(注意格式):
+ {{original_text}}
+ """;
+
+ public ContentSimplifyBot() {
+ super("ContentSimplifyBot", "压缩历史对话");
+ setEnvironment(new Environment());
+ }
+
+ @Override
+ public CompletableFuture<Message> run() {
+ Message msg = this.rc.getNews().poll();
+ String content = msg.getContent();
+ String text = baseText.replace("{{original_text}}", content);
+ JsonObject req = getReq(llm, text);
+ List<AiMessage> messages = new ArrayList<>();
+ messages.add(AiMessage.builder().jsonContent(req).build());
+ String result = llm.syncChat(this, messages);
+
+ return
CompletableFuture.completedFuture(Message.builder().content(result).build());
+ }
+
+ private JsonObject getReq(LLM llm, String text) {
+ JsonObject req = new JsonObject();
+ if (llm.getConfig().getLlmProvider() == LLMProvider.CLAUDE_COMPANY) {
+ req.addProperty("role", "user");
+ JsonArray contentJsons = new JsonArray();
+ JsonObject obj1 = new JsonObject();
+ obj1.addProperty("type", "text");
+ obj1.addProperty("text", text);
+ contentJsons.add(obj1);
+ req.add("content", contentJsons);
+ }
+ return req;
+ }
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/bot/LogAnalysisBot.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/bot/LogAnalysisBot.java
new file mode 100644
index 00000000..b578ade3
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/bot/LogAnalysisBot.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.service.bot;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.xiaomi.youpin.docean.anno.Service;
+import run.mone.hive.Environment;
+import run.mone.hive.llm.LLM;
+import run.mone.hive.llm.LLMProvider;
+import run.mone.hive.roles.Role;
+import run.mone.hive.schema.AiMessage;
+import run.mone.hive.schema.Message;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+@Service
+public class LogAnalysisBot extends Role {
+ private static String baseText = """
+ ## 角色
+ 你是一个AI日志解释助手,负责分析、解释日志数据,为用户提供清晰的概要和易懂的解释。
+
+ ### 技能
+ - 多格式日志分析:能够解析和理解不同来源和格式的日志文件。
+ - 关键信息提取:能够从繁杂的日志数据中提取重要信息和发现模式。
+ - 异常检测与诊断:根据日志内容快速识别系统的潜在问题或异常行为。
+ - 翻译技术语言:将复杂的技术日志信息转换为用户易于理解的解释。
+ - 实时数据处理:具备实时监控和分析日志数据流的能力。
+ - 自我学习与优化:通过机器学习不断提升分析和解释的准确性及效率。
+ - 多轮问答处理:能够理解并利用历史问答数据,准确回答用户当前的问题。
+
+ ### 约束
+ - 严格保密:在分析和解释日志时,严格保护用户数据的隐私和安全。
+ - 高度准确:确保提供的解释和概要准确反映日志数据的实际内容。
+ - 快速响应:在用户提出需求时能够迅速提供所需的日志解释和支持。
+ - 广泛兼容:能够兼容并支持分析多种来源和格式的日志文件。
+ - 用户友好性:确保解释结果简洁明了,即使非技术用户也能轻松理解。
+ - 可扩展性强:随着日志数据量和复杂性的增长,能够持续适应并提供有效分析。
+
+ 下面是你需要分析的日志内容或用户问题:
+ {{log_text}}
+ """;
+
+ public LogAnalysisBot() {
+ super("LogAnalysisBot", "分析用户日志");
+ setEnvironment(new Environment());
+ }
+
+ @Override
+ public CompletableFuture<Message> run() {
+ Message msg = this.rc.getNews().poll();
+ String content = msg.getContent();
+ String text = baseText.replace("{{log_text}}", content);
+ JsonObject req = getReq(llm, text);
+ List<AiMessage> messages = new ArrayList<>();
+ messages.add(AiMessage.builder().jsonContent(req).build());
+ String result = llm.syncChat(this, messages);
+
+ return
CompletableFuture.completedFuture(Message.builder().content(result).build());
+ }
+
+ private JsonObject getReq(LLM llm, String text) {
+ JsonObject req = new JsonObject();
+ if (llm.getConfig().getLlmProvider() == LLMProvider.CLAUDE_COMPANY) {
+ req.addProperty("role", "user");
+ JsonArray contentJsons = new JsonArray();
+ JsonObject obj1 = new JsonObject();
+ obj1.addProperty("type", "text");
+ obj1.addProperty("text", text);
+ contentJsons.add(obj1);
+ req.add("content", contentJsons);
+ }
+ return req;
+ }
+
+}
diff --git
a/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/impl/MilogAiAnalysisServiceImpl.java
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/impl/MilogAiAnalysisServiceImpl.java
new file mode 100644
index 00000000..6e1eab8c
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/java/org/apache/ozhera/log/manager/service/impl/MilogAiAnalysisServiceImpl.java
@@ -0,0 +1,416 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.log.manager.service.impl;
+
+import cn.hutool.core.thread.ThreadUtil;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.xiaomi.data.push.common.SafeRun;
+import com.xiaomi.youpin.docean.anno.Service;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ozhera.log.common.Result;
+import org.apache.ozhera.log.exception.CommonError;
+import org.apache.ozhera.log.manager.common.context.MoneUserContext;
+import org.apache.ozhera.log.manager.mapper.MilogAiConversationMapper;
+import org.apache.ozhera.log.manager.model.bo.BotQAParam;
+import org.apache.ozhera.log.manager.model.dto.AiAnalysisHistoryDTO;
+import org.apache.ozhera.log.manager.model.dto.LogAiAnalysisDTO;
+import org.apache.ozhera.log.manager.model.pojo.MilogAiConversationDO;
+import org.apache.ozhera.log.manager.model.vo.LogAiAnalysisResponse;
+import org.apache.ozhera.log.manager.service.MilogAiAnalysisService;
+import org.apache.ozhera.log.manager.service.bot.ContentSimplifyBot;
+import org.apache.ozhera.log.manager.service.bot.LogAnalysisBot;
+import org.apache.ozhera.log.manager.user.MoneUser;
+import run.mone.hive.configs.LLMConfig;
+import run.mone.hive.llm.LLM;
+import run.mone.hive.llm.LLMProvider;
+import run.mone.hive.schema.Message;
+
+
+import javax.annotation.Resource;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import static run.mone.hive.llm.ClaudeProxy.*;
+
+@Slf4j
+@Service
+public class MilogAiAnalysisServiceImpl implements MilogAiAnalysisService {
+
+ @Resource
+ private LogAnalysisBot analysisBot;
+
+ @Resource
+ private ContentSimplifyBot contentSimplifyBot;
+
+ @Resource
+ private MilogAiConversationMapper milogAiConversationMapper;
+
+ private static final ConcurrentHashMap<Long, Map<String,
List<BotQAParam.QAParam>>> QA_CACHE = new ConcurrentHashMap<>();
+
+ private static final ConcurrentHashMap<Long, Object> LOCK = new
ConcurrentHashMap<>();
+
+ private static final String MODEL_KEY = "model";
+ private static final String ORIGINAL_KEY = "original";
+
+ private static final ConcurrentHashMap<Long, Long> CONVERSATION_TIME = new
ConcurrentHashMap<>();
+ private static final long CONVERSATION_TIMEOUT = 10 * 60 * 1000;
+
+ private static final Gson gson = new Gson();
+
+ private ScheduledExecutorService scheduledExecutor;
+
+ public void init() {
+ LLMConfig config = LLMConfig.builder()
+ .llmProvider(LLMProvider.CLAUDE_COMPANY)
+ .url(getClaudeUrl())
+ .version(getClaudeVersion())
+ .maxTokens(getClaudeMaxToekns())
+ .build();
+ LLM llm = new LLM(config);
+ analysisBot.setLlm(llm);
+ contentSimplifyBot.setLlm(llm);
+ scheduledExecutor = Executors.newScheduledThreadPool(2,
ThreadUtil.newNamedThreadFactory("manager-ai-conversation", false));
+ scheduledExecutor.scheduleAtFixedRate(() ->
SafeRun.run(this::processTask), 0, 2, TimeUnit.MINUTES);
+ scheduledExecutor.scheduleAtFixedRate(() ->
SafeRun.run(this::checkTokenLength), 0, 1, TimeUnit.MINUTES);
+ }
+
+
+ @Override
+ public Result<LogAiAnalysisResponse> tailLogAiAnalysis(LogAiAnalysisDTO
tailLogAiAnalysisDTO) {
+
+ if (tailLogAiAnalysisDTO.getStoreId() == null) {
+ return Result.failParam("Store id is null");
+ }
+
+ if (requestExceedLimit(tailLogAiAnalysisDTO.getLogs())) {
+ return Result.failParam("The length of the input information
reaches the maximum limit");
+ }
+
+ MoneUser user = MoneUserContext.getCurrentUser();
+ LogAiAnalysisResponse response = new LogAiAnalysisResponse();
+ Long conversationId;
+ if (tailLogAiAnalysisDTO.getConversationId() == null) {
+ String answer = "";
+ try {
+ BotQAParam param = new BotQAParam();
+
param.setLatestQuestion(gson.toJson(tailLogAiAnalysisDTO.getLogs()));
+ String text = formatString(param);
+
analysisBot.getRc().news.put(Message.builder().content(text).build());
+ Message result = analysisBot.run().join();
+ answer = result.getContent();
+ } catch (Exception e) {
+ log.error("An error occurred in the request for the large
model, err: {}", e.getMessage());
+ return Result.fail(CommonError.SERVER_ERROR.getCode(), "An
error occurred in the request for the large model");
+ }
+
+ BotQAParam.QAParam conversation = new BotQAParam.QAParam();
+ long timestamp = System.currentTimeMillis();
+ String nowTimeStr =
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+ conversation.setTime(nowTimeStr);
+ conversation.setUser(gson.toJson(tailLogAiAnalysisDTO.getLogs()));
+ conversation.setBot(answer);
+
+ List<BotQAParam.QAParam> ModelHistory = new ArrayList<>();
+ List<BotQAParam.QAParam> OriginalHistory = new ArrayList<>();
+ ModelHistory.add(conversation);
+ OriginalHistory.add(conversation);
+ //The first request will be created
+ MilogAiConversationDO conversationDO = new MilogAiConversationDO();
+ conversationDO.setStoreId(tailLogAiAnalysisDTO.getStoreId());
+ conversationDO.setCreator(user.getUser());
+ conversationDO.setConversationContext(gson.toJson(ModelHistory));
+
conversationDO.setOriginalConversation(gson.toJson(OriginalHistory));
+
+ conversationDO.setCreateTime(timestamp);
+ conversationDO.setUpdateTime(timestamp);
+ conversationDO.setConversationName("新对话 " + nowTimeStr);
+ milogAiConversationMapper.insert(conversationDO);
+ conversationId = conversationDO.getId();
+ Map<String, List<BotQAParam.QAParam>> cache = new HashMap<>();
+ cache.put(MODEL_KEY, ModelHistory);
+ cache.put(ORIGINAL_KEY, OriginalHistory);
+ QA_CACHE.put(conversationId, cache);
+ response.setConversationId(conversationId);
+ response.setContent(answer);
+ CONVERSATION_TIME.put(conversationId, timestamp);
+ return Result.success(response);
+ } else {
+ String answer = "";
+ conversationId = tailLogAiAnalysisDTO.getConversationId();
+ //This is not first request, need lock
+ Object lock = LOCK.computeIfAbsent(conversationId, k -> new
Object());
+ synchronized (lock) {
+ Map<String, List<BotQAParam.QAParam>> cache =
QA_CACHE.get(conversationId);
+ if (cache == null || cache.isEmpty()) {
+ cache = getHistoryFromDb(conversationId);
+ }
+ List<BotQAParam.QAParam> modelHistory = cache.get(MODEL_KEY);
+ List<BotQAParam.QAParam> originalHistory =
cache.get(ORIGINAL_KEY);
+ try {
+ BotQAParam param = new BotQAParam();
+ param.setHistoryConversation(modelHistory);
+
param.setLatestQuestion(gson.toJson(tailLogAiAnalysisDTO.getLogs()));
+ String text = formatString(param);
+
analysisBot.getRc().news.put(Message.builder().content(gson.toJson(text)).build());
+ Message result = analysisBot.run().join();
+ answer = result.getContent();
+
+ } catch (InterruptedException e) {
+ log.error("An error occurred in the request for the large
model, err: {}", e.getMessage());
+ return Result.fail(CommonError.SERVER_ERROR.getCode(), "An
error occurred in the request for the large model");
+ }
+ BotQAParam.QAParam conversation = new BotQAParam.QAParam();
+
conversation.setTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd
HH:mm:ss")));
+
conversation.setUser(gson.toJson(tailLogAiAnalysisDTO.getLogs()));
+ conversation.setBot(answer);
+ modelHistory.add(conversation);
+ originalHistory.add(conversation);
+ cache.put(MODEL_KEY, modelHistory);
+ cache.put(ORIGINAL_KEY, originalHistory);
+ QA_CACHE.put(conversationId, cache);
+ CONVERSATION_TIME.put(conversationId,
System.currentTimeMillis());
+ }
+ LOCK.remove(conversationId);
+ response.setConversationId(conversationId);
+ response.setContent(answer);
+ return Result.success(response);
+ }
+
+ }
+
+
+ private Map<String, List<BotQAParam.QAParam>> getHistoryFromDb(Long
conversationId) {
+ MilogAiConversationDO milogAiConversationDO =
milogAiConversationMapper.selectById(conversationId);
+ String conversationContext =
milogAiConversationDO.getConversationContext();
+
+ if (conversationContext == null || conversationContext.isBlank()) {
+ return Collections.emptyMap();
+ }
+
+ List<BotQAParam.QAParam> modelConversation =
gson.fromJson(conversationContext, new TypeToken<List<BotQAParam.QAParam>>() {
+ }.getType());
+ List<BotQAParam.QAParam> originalConversation =
gson.fromJson(milogAiConversationDO.getOriginalConversation(), new
TypeToken<List<BotQAParam.QAParam>>() {
+ }.getType());
+
+ Map<String, List<BotQAParam.QAParam>> res = new HashMap<>();
+ res.put(MODEL_KEY, modelConversation);
+ res.put(ORIGINAL_KEY, originalConversation);
+ return res;
+ }
+
+
+ private void processTask() {
+ for (Map.Entry<Long, Long> entry : CONVERSATION_TIME.entrySet()) {
+ Long conversationId = entry.getKey();
+ Object lock = LOCK.computeIfAbsent(conversationId, k -> new
Object());
+ synchronized (lock) {
+ saveHistory(conversationId);
+ //It has not been operated for a long time
+ if (System.currentTimeMillis() - entry.getValue() >
CONVERSATION_TIMEOUT) {
+ CONVERSATION_TIME.remove(entry.getKey());
+ log.info("clean timeout conversation: {}", entry.getKey());
+ }
+ }
+ LOCK.remove(conversationId);
+ }
+ }
+
+ private void saveHistory(Long conversationId) {
+ log.info("开始存入数据库, id : {}", conversationId);
+ MilogAiConversationDO milogAiConversationDO =
milogAiConversationMapper.selectById(conversationId);
+ Map<String, List<BotQAParam.QAParam>> map =
QA_CACHE.get(conversationId);
+ List<BotQAParam.QAParam> modelHistory = map.get(MODEL_KEY);
+ List<BotQAParam.QAParam> originalHistory = map.get(ORIGINAL_KEY);
+ milogAiConversationDO.setUpdateTime(System.currentTimeMillis());
+
milogAiConversationDO.setConversationContext(gson.toJson(modelHistory));
+
milogAiConversationDO.setOriginalConversation(gson.toJson(originalHistory));
+ milogAiConversationMapper.updateById(milogAiConversationDO);
+ }
+
+
+ private void checkTokenLength() {
+ for (Map.Entry<Long, Map<String, List<BotQAParam.QAParam>>> entry :
QA_CACHE.entrySet()) {
+ Long conversationId = entry.getKey();
+ Object lock = LOCK.computeIfAbsent(conversationId, k -> new
Object());
+ synchronized (lock) {
+ List<BotQAParam.QAParam> originalHistory =
entry.getValue().get(ORIGINAL_KEY);
+ Integer index = compressIndex(entry.getValue());
+ if (index > 0) {
+ List<BotQAParam.QAParam> needCompress =
originalHistory.subList(0, index);
+ List<BotQAParam.QAParam> unchangeList =
originalHistory.subList(index, originalHistory.size());
+ String res = "";
+ try {
+
contentSimplifyBot.getRc().news.put(Message.builder().content(gson.toJson(needCompress)).build());
+ Message result = contentSimplifyBot.run().join();
+ res = result.getContent();
+ } catch (Exception e) {
+ log.error("An error occurred when requesting the large
model to compress data");
+ }
+ if (!res.isBlank()) {
+ List<BotQAParam.QAParam> compressedList =
gson.fromJson(res, new TypeToken<List<BotQAParam.QAParam>>() {
+ }.getType());
+ compressedList.addAll(unchangeList);
+ entry.getValue().put(MODEL_KEY, compressedList);
+ QA_CACHE.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ LOCK.remove(conversationId);
+ }
+ }
+
+ private static String formatString(BotQAParam param) {
+ StringBuilder sb = new StringBuilder();
+ List<BotQAParam.QAParam> historyConversation =
param.getHistoryConversation();
+ if (historyConversation != null && !historyConversation.isEmpty()) {
+ sb.append("历史对话:\n");
+ historyConversation.forEach(h -> {
+ sb.append(String.format("[%s] ###用户: %s ###助手: %s\n",
h.getTime(), h.getUser(), h.getBot()));
+ });
+ }
+ sb.append("最新问题: \n ###用户: ").append(param.getLatestQuestion());
+ return sb.toString()
+ .replaceAll("[\u0000-\u001F]", "")
+ .replaceAll("[\\\\\"]", "");
+
+ }
+
+
+ private static Boolean requestExceedLimit(List<String> logs) {
+ String request = gson.toJson(logs);
+ if (request.length() >= 20000) {
+ return true;
+ }
+ return false;
+ }
+
+ private static Integer compressIndex(Map<String, List<BotQAParam.QAParam>>
map) {
+ List<BotQAParam.QAParam> paramList = map.get(MODEL_KEY);
+ if (gson.toJson(paramList).length() <= 40000) {
+ return 0;
+ }
+ int limit = 20000;
+ List<BotQAParam.QAParam> originalList = map.get(ORIGINAL_KEY);
+ int sum = 0;
+ int index = originalList.size();
+ for (int i = originalList.size() - 1; i >= 0; i--) {
+ BotQAParam.QAParam param = originalList.get(i);
+ String str = gson.toJson(param);
+ sum += str.length();
+ index = i;
+ if (sum >= limit) {
+ break;
+ }
+ }
+ int maxCompress = originalList.size() - 20;
+ return Math.max(index, maxCompress);
+ }
+
+
+ @Override
+ public void shutdown() {
+ if (!QA_CACHE.isEmpty()){
+ log.info("The project is closed and the cache is flushed to the
disk");
+ for (Map.Entry<Long, Map<String, List<BotQAParam.QAParam>>> entry
: QA_CACHE.entrySet()) {
+ MilogAiConversationDO milogAiConversationDO =
milogAiConversationMapper.selectById(entry.getKey());
+ List<BotQAParam.QAParam> modelHistory =
entry.getValue().get(MODEL_KEY);
+ List<BotQAParam.QAParam> originalHistory =
entry.getValue().get(ORIGINAL_KEY);
+
milogAiConversationDO.setUpdateTime(System.currentTimeMillis());
+
milogAiConversationDO.setConversationContext(gson.toJson(modelHistory));
+
milogAiConversationDO.setOriginalConversation(gson.toJson(originalHistory));
+ milogAiConversationMapper.updateById(milogAiConversationDO);
+ }
+ }
+ }
+
+ @Override
+ public Result<List<AiAnalysisHistoryDTO>> getAiHistoryList(Long storeId) {
+ MoneUser user = MoneUserContext.getCurrentUser();
+ List<MilogAiConversationDO> historyList =
milogAiConversationMapper.getListByUserAndStore(storeId, user.getUser());
+ List<AiAnalysisHistoryDTO> result = new ArrayList<>();
+ if(!historyList.isEmpty()){
+ result = historyList.stream().map(h -> {
+ AiAnalysisHistoryDTO dto = new AiAnalysisHistoryDTO();
+ dto.setId(h.getId());
+ dto.setName(h.getConversationName());
+ dto.setCreateTime(timestampToStr(h.getCreateTime()));
+ return dto;
+ }).toList();
+ }
+ return Result.success(result);
+ }
+
+ @Override
+ public Result<List<BotQAParam.QAParam>> getAiConversation(Long id) {
+ Map<String, List<BotQAParam.QAParam>> stringListMap = QA_CACHE.get(id);
+ if (stringListMap != null && !stringListMap.isEmpty()) {
+ List<BotQAParam.QAParam> paramList =
stringListMap.get(ORIGINAL_KEY);
+ return Result.success(paramList);
+ }
+ MilogAiConversationDO conversationDO =
milogAiConversationMapper.selectById(id);
+ String originalConversationStr =
conversationDO.getOriginalConversation();
+ List<BotQAParam.QAParam> res = gson.fromJson(originalConversationStr,
new TypeToken<List<BotQAParam.QAParam>>() {}.getType());
+ return Result.success(res);
+ }
+
+ @Override
+ public Result<Boolean> deleteAiConversation(Long id) {
+ milogAiConversationMapper.deleteById(id);
+ QA_CACHE.remove(id);
+ return Result.success(true);
+ }
+
+ @Override
+ public Result<Boolean> updateAiName(Long id, String name) {
+ MilogAiConversationDO conversationDO =
milogAiConversationMapper.selectById(id);
+ conversationDO.setConversationName(name);
+ conversationDO.setUpdateTime(System.currentTimeMillis());
+ milogAiConversationMapper.updateById(conversationDO);
+ return Result.success(true);
+ }
+
+ @Override
+ public Result<Boolean> closeAiAnalysis(Long id) {
+ Map<String, List<BotQAParam.QAParam>> stringListMap = QA_CACHE.get(id);
+ if (stringListMap != null && !stringListMap.isEmpty()) {
+ MilogAiConversationDO conversationDO =
milogAiConversationMapper.selectById(id);
+ conversationDO.setUpdateTime(System.currentTimeMillis());
+
conversationDO.setConversationContext(gson.toJson(stringListMap.get(MODEL_KEY)));
+
conversationDO.setOriginalConversation(gson.toJson(stringListMap.get(ORIGINAL_KEY)));
+ milogAiConversationMapper.updateById(conversationDO);
+ QA_CACHE.remove(id);
+ }
+ return Result.success(true);
+ }
+
+ private static String timestampToStr(long timestamp) {
+ Instant instant = Instant.ofEpochMilli(timestamp);
+ LocalDateTime dateTime = LocalDateTime.ofInstant(instant,
ZoneId.systemDefault());
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd
HH:mm:ss.SSS");
+ return dateTime.format(formatter);
+ }
+}
diff --git a/ozhera-log/log-manager/src/main/resources/config.properties
b/ozhera-log/log-manager/src/main/resources/config.properties
index f5559794..a1dafe8a 100644
--- a/ozhera-log/log-manager/src/main/resources/config.properties
+++ b/ozhera-log/log-manager/src/main/resources/config.properties
@@ -54,7 +54,7 @@ db_open_transactional=true
db_print_sql=false
milogpattern=timestamp,level,traceId,threadName,className,line,message
-mybatis_mapper_location=mapper/MilogEsClusterMapper.xml,mapper/MilogEsIndexMapper.xml,mapper/MilogLogProcessMapper.xml,mapper/MilogLogTemplateDetailMapper.xml,mapper/MilogLogTemplateMapper.xml,mapper/MilogLogCountMapper.xml,mapper/MilogLogstailMapper.xml,mapper/MilogLogSearchSaveMapper.xml,mapper/MilogEsClusterMapper.xml,mapper/MilogLogNumAlertMapper.xml,mapper/MilogAnalyseDashboardMapper.xml,mapper/MilogAnalyseGraphMapper.xml,mapper/MilogAnalyseDashboardGraphRefMapper.xml,mapper/MilogAn
[...]
+mybatis_mapper_location=mapper/MilogEsClusterMapper.xml,mapper/MilogEsIndexMapper.xml,mapper/MilogLogProcessMapper.xml,mapper/MilogLogTemplateDetailMapper.xml,mapper/MilogLogTemplateMapper.xml,mapper/MilogLogCountMapper.xml,mapper/MilogLogstailMapper.xml,mapper/MilogLogSearchSaveMapper.xml,mapper/MilogEsClusterMapper.xml,mapper/MilogLogNumAlertMapper.xml,mapper/MilogAnalyseDashboardMapper.xml,mapper/MilogAnalyseGraphMapper.xml,mapper/MilogAnalyseDashboardGraphRefMapper.xml,mapper/MilogAn
[...]
#\u53EA\u53D1\u9001mq\uFF0C\u4E0D\u6D88\u8D39\u7684\u65E5\u5FD7\u7C7B\u578B
log_type_mq_not_consume=${log_type_mq_not_consume}
diff --git a/ozhera-log/log-manager/src/main/resources/log.sql
b/ozhera-log/log-manager/src/main/resources/log.sql
index fd69ebaf..95ddfb05 100644
--- a/ozhera-log/log-manager/src/main/resources/log.sql
+++ b/ozhera-log/log-manager/src/main/resources/log.sql
@@ -568,4 +568,22 @@ CREATE TABLE `project` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_bin ROW_FORMAT = Dynamic;
+-- ----------------------------
+-- Table structure for milog_ai_conversation
+-- ----------------------------
+DROP TABLE IF EXISTS `milog_ai_conversation`;
+CREATE TABLE `milog_ai_conversation` (
+ `id` bigint(0) NOT NULL AUTO_INCREMENT,
+ `store_id` bigint(0) NULL DEFAULT NULL COMMENT
'store id',
+ `conversation_name` varchar(100) CHARACTER SET
utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'conversation name',
+ `conversation_context` text CHARACTER SET utf8mb4
COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'The conversation context used by
llm',
+ `original_conversation` text CHARACTER SET utf8mb4
COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT 'The original context with llm',
+ `creator` varchar(100) CHARACTER SET utf8mb4
COLLATE utf8mb4_bin NOT NULL COMMENT 'creator',
+ `update_time` bigint(0) NULL DEFAULT NULL,
+ `create_time` bigint(0) NULL DEFAULT NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_store_id`(`store_id`),
+ INDEX `idx_creator`(`creator`)
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE =
utf8mb4_bin ROW_FORMAT = Dynamic;
+
SET FOREIGN_KEY_CHECKS = 1;
diff --git
a/ozhera-log/log-manager/src/main/resources/mapper/MilogAiConversationMapper.xml
b/ozhera-log/log-manager/src/main/resources/mapper/MilogAiConversationMapper.xml
new file mode 100644
index 00000000..3f78fc4e
--- /dev/null
+++
b/ozhera-log/log-manager/src/main/resources/mapper/MilogAiConversationMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper
namespace="org.apache.ozhera.log.manager.mapper.MilogAiConversationMapper">
+
+ <select id="getListByUserAndStore"
+
resultType="org.apache.ozhera.log.manager.model.pojo.MilogAiConversationDO">
+ SELECT *
+ FROM milog_ai_conversation
+ WHERE store_id = #{storeId}
+ AND creator = #{creator}
+ ORDER BY update_time DESC
+ </select>
+
+</mapper>
\ No newline at end of file
diff --git a/ozhera-log/pom.xml b/ozhera-log/pom.xml
index 06560dbc..9600e9a5 100644
--- a/ozhera-log/pom.xml
+++ b/ozhera-log/pom.xml
@@ -82,6 +82,21 @@ http://www.apache.org/licenses/LICENSE-2.0
<artifactId>log4j-web</artifactId>
<version>2.24.3</version>
</dependency>
+ <dependency>
+ <groupId>run.mone</groupId>
+ <artifactId>hive</artifactId>
+ <version>1.6.2-jdk21-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>logback-classic</artifactId>
+ <groupId>ch.qos.logback</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>logback-core</artifactId>
+ <groupId>ch.qos.logback</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
<dependency>
<groupId>cn.hutool</groupId>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]