feat:增加可观测性的相关监听器 & 修复前端问答报错outputkey问题

This commit is contained in:
evo
2026-04-01 22:32:01 +08:00
parent 3071bfd0f9
commit ef99c540bb
31 changed files with 1034 additions and 23 deletions

View File

@@ -22,6 +22,8 @@ import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.agent.ChartGenerationAgent;
import org.ruoyi.agent.SqlAgent;
import org.ruoyi.observability.MyAgentListener;
import org.ruoyi.observability.MyMcpClientListener;
import org.ruoyi.agent.WebSearchAgent;
import org.ruoyi.agent.tool.ExecuteSqlQueryTool;
import org.ruoyi.agent.tool.QueryAllTablesTool;
@@ -213,6 +215,7 @@ public class ChatServiceFacade implements IChatService {
McpClient mcpClient = new DefaultMcpClient.Builder()
.transport(transport)
.listener(new MyMcpClientListener())
.build();
ToolProvider toolProvider = McpToolProvider.builder()
@@ -227,6 +230,7 @@ public class ChatServiceFacade implements IChatService {
McpClient mcpClient1 = new DefaultMcpClient.Builder()
.transport(transport1)
.listener(new MyMcpClientListener())
.build();
ToolProvider toolProvider1 = McpToolProvider.builder()
@@ -261,6 +265,7 @@ public class ChatServiceFacade implements IChatService {
.chatModel(plannerModel)
.subAgents(sqlAgent, chartGenerationAgent)
.responseStrategy(SupervisorResponseStrategy.LAST)
.listener(new MyAgentListener())
.build();
String invoke = supervisor.invoke(chatRequest.getContent());

View File

@@ -1,24 +1,31 @@
package org.ruoyi.service.chat.impl.provider;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.enums.ChatModeType;
import org.ruoyi.observability.ChatModelListenerProvider;
import org.ruoyi.service.chat.AbstractChatService;
import org.springframework.stereotype.Service;
/**
* @Author: xiaoen
* @Description: deepseek 服务调用
* @Date: Created in 19:12 2026/3/17
* Deepseek服务调用
*
* @author xiaoen
* @date 2026/3/17
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class DeepseekServiceImpl implements AbstractChatService {
private final ChatModelListenerProvider listenerProvider;
@Override
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo, ChatRequest chatRequest) {
return OpenAiStreamingChatModel.builder()
@@ -26,6 +33,7 @@ public class DeepseekServiceImpl implements AbstractChatService {
.apiKey(chatModelVo.getApiKey())
.modelName(chatModelVo.getModelName())
.returnThinking(chatRequest.getEnableThinking())
.listeners(listenerProvider.getChatModelListeners())
.build();
}

View File

@@ -1,13 +1,16 @@
package org.ruoyi.service.chat.impl.provider;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.ollama.OllamaStreamingChatModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.enums.ChatModeType;
import org.ruoyi.service.chat.AbstractChatService;
import org.springframework.stereotype.Service;
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.observability.ChatModelListenerProvider;
/**
* OllamaAI服务调用
@@ -17,13 +20,17 @@ import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class OllamaServiceImpl implements AbstractChatService {
private final ChatModelListenerProvider listenerProvider;
@Override
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo, ChatRequest chatRequest) {
return OllamaStreamingChatModel.builder()
.baseUrl(chatModelVo.getApiHost())
.modelName(chatModelVo.getModelName())
.listeners(listenerProvider.getChatModelListeners())
.build();
}

View File

@@ -3,10 +3,12 @@ package org.ruoyi.service.chat.impl.provider;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.enums.ChatModeType;
import org.ruoyi.observability.ChatModelListenerProvider;
import org.ruoyi.service.chat.AbstractChatService;
import org.springframework.stereotype.Service;
@@ -19,15 +21,19 @@ import org.springframework.stereotype.Service;
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class OpenAIServiceImpl implements AbstractChatService {
private final ChatModelListenerProvider listenerProvider;
@Override
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo, ChatRequest chatRequest) {
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo,ChatRequest chatRequest) {
return OpenAiStreamingChatModel.builder()
.baseUrl(chatModelVo.getApiHost())
.apiKey(chatModelVo.getApiKey())
.modelName(chatModelVo.getModelName())
.returnThinking(chatRequest.getEnableThinking())
.listeners(listenerProvider.getChatModelListeners())
.build();
}

View File

@@ -1,24 +1,30 @@
package org.ruoyi.service.chat.impl.provider;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.enums.ChatModeType;
import org.ruoyi.observability.ChatModelListenerProvider;
import org.ruoyi.service.chat.AbstractChatService;
import org.springframework.stereotype.Service;
/**
* OPENAI服务调用
* PPIO服务调用
*
* @author ageerle@163.com
* @date 2025/12/13
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class PPIOServiceImpl implements AbstractChatService {
private final ChatModelListenerProvider listenerProvider;
@Override
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo, ChatRequest chatRequest) {
return OpenAiStreamingChatModel.builder()
@@ -26,6 +32,7 @@ public class PPIOServiceImpl implements AbstractChatService {
.apiKey(chatModelVo.getApiKey())
.modelName(chatModelVo.getModelName())
.returnThinking(chatRequest.getEnableThinking())
.listeners(listenerProvider.getChatModelListeners())
.build();
}

View File

@@ -1,11 +1,14 @@
package org.ruoyi.service.chat.impl.provider;
import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.enums.ChatModeType;
import org.ruoyi.observability.ChatModelListenerProvider;
import org.ruoyi.service.chat.AbstractChatService;
import org.springframework.stereotype.Service;
@@ -18,14 +21,17 @@ import org.springframework.stereotype.Service;
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class QianWenChatServiceImpl implements AbstractChatService {
// 添加文档解析的前缀字段
private final ChatModelListenerProvider listenerProvider;
@Override
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo,ChatRequest chatRequest) {
return QwenStreamingChatModel.builder()
.apiKey(chatModelVo.getApiKey())
.modelName(chatModelVo.getModelName())
.listeners(listenerProvider.getChatModelListeners())
.build();
}

View File

@@ -1,11 +1,14 @@
package org.ruoyi.service.chat.impl.provider;
import dev.langchain4j.community.model.zhipu.ZhipuAiStreamingChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.enums.ChatModeType;
import org.ruoyi.observability.ChatModelListenerProvider;
import org.ruoyi.service.chat.AbstractChatService;
import org.springframework.stereotype.Service;
@@ -18,13 +21,17 @@ import org.springframework.stereotype.Service;
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class ZhiPuChatServiceImpl implements AbstractChatService {
private final ChatModelListenerProvider listenerProvider;
@Override
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo, ChatRequest chatRequest) {
return ZhipuAiStreamingChatModel.builder()
.apiKey(chatModelVo.getApiKey())
.model(chatModelVo.getModelName())
.listeners(listenerProvider.getChatModelListeners())
.build();
}

View File

@@ -4,8 +4,12 @@ package org.ruoyi.service.embed.impl;
import dev.langchain4j.community.model.dashscope.QwenEmbeddingModel;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.listener.EmbeddingModelListener;
import dev.langchain4j.model.output.Response;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.observability.EmbeddingModelListenerProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.ruoyi.enums.ModalityType;
@@ -20,9 +24,11 @@ import java.util.Set;
@Component("alibailian")
public class AliBaiLianBaseEmbedProvider extends OpenAiEmbeddingProvider {
private ChatModelVo chatModelVo;
@Autowired
private EmbeddingModelListenerProvider embeddingModelListenerProvider;
@Override
public void configure(ChatModelVo config) {
this.chatModelVo = config;
@@ -35,12 +41,18 @@ public class AliBaiLianBaseEmbedProvider extends OpenAiEmbeddingProvider {
@Override
public Response<List<Embedding>> embedAll(List<TextSegment> textSegments) {
return QwenEmbeddingModel.builder()
List<EmbeddingModelListener> listeners = embeddingModelListenerProvider.getEmbeddingModelListeners();
EmbeddingModel model = QwenEmbeddingModel.builder()
.apiKey(chatModelVo.getApiKey())
.modelName(chatModelVo.getModelName())
.dimension(chatModelVo.getModelDimension())
.build()
.embedAll(textSegments);
.build();
if (!listeners.isEmpty()) {
model = model.addListeners(listeners);
}
return model.embedAll(textSegments);
}
}

View File

@@ -2,11 +2,16 @@ package org.ruoyi.service.embed.impl;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.listener.EmbeddingModelListener;
import dev.langchain4j.model.ollama.OllamaEmbeddingModel;
import dev.langchain4j.model.output.Response;
import jakarta.annotation.Resource;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.enums.ModalityType;
import org.ruoyi.observability.EmbeddingModelListenerProvider;
import org.ruoyi.service.embed.BaseEmbedModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@@ -21,6 +26,9 @@ import java.util.Set;
public class OllamaEmbeddingProvider implements BaseEmbedModelService {
private ChatModelVo chatModelVo;
@Resource
private EmbeddingModelListenerProvider embeddingModelListenerProvider;
@Override
public void configure(ChatModelVo config) {
this.chatModelVo = config;
@@ -34,10 +42,16 @@ public class OllamaEmbeddingProvider implements BaseEmbedModelService {
// ollama不能设置embedding维度使用milvus时请注意创建向量表时需要先设定维度大小
@Override
public Response<List<Embedding>> embedAll(List<TextSegment> textSegments) {
return OllamaEmbeddingModel.builder()
List<EmbeddingModelListener> listeners = embeddingModelListenerProvider.getEmbeddingModelListeners();
EmbeddingModel model = OllamaEmbeddingModel.builder()
.baseUrl(chatModelVo.getApiHost())
.modelName(chatModelVo.getModelName())
.build()
.embedAll(textSegments);
.build();
if (!listeners.isEmpty()) {
model = model.addListeners(listeners);
}
return model.embedAll(textSegments);
}
}

View File

@@ -2,11 +2,15 @@ package org.ruoyi.service.embed.impl;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.listener.EmbeddingModelListener;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.model.output.Response;
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
import org.ruoyi.enums.ModalityType;
import org.ruoyi.observability.EmbeddingModelListenerProvider;
import org.ruoyi.service.embed.BaseEmbedModelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@@ -21,6 +25,9 @@ import java.util.Set;
public class OpenAiEmbeddingProvider implements BaseEmbedModelService {
protected ChatModelVo chatModelVo;
@Autowired
private EmbeddingModelListenerProvider embeddingModelListenerProvider;
@Override
public void configure(ChatModelVo config) {
this.chatModelVo = config;
@@ -33,12 +40,18 @@ public class OpenAiEmbeddingProvider implements BaseEmbedModelService {
@Override
public Response<List<Embedding>> embedAll(List<TextSegment> textSegments) {
return OpenAiEmbeddingModel.builder()
List<EmbeddingModelListener> listeners = embeddingModelListenerProvider.getEmbeddingModelListeners();
EmbeddingModel model = OpenAiEmbeddingModel.builder()
.baseUrl(chatModelVo.getApiHost())
.apiKey(chatModelVo.getApiKey())
.modelName(chatModelVo.getModelName())
.dimensions(chatModelVo.getModelDimension())
.build()
.embedAll(textSegments);
.build();
if (!listeners.isEmpty()) {
model = model.addListeners(listeners);
}
return model.embedAll(textSegments);
}
}