package com.ard.agent.service;
|
|
import com.alibaba.cloud.ai.graph.RunnableConfig;
|
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
|
import com.alibaba.cloud.ai.graph.checkpoint.savers.MemorySaver;
|
import com.alibaba.cloud.ai.graph.exception.GraphRunnerException;
|
import com.ard.agent.tool.KnowledgeTools;
|
import com.ard.agent.tool.MonitorTools;
|
import com.ard.agent.tool.SystemTools;
|
import com.ard.common.security.utils.SecurityUtils;
|
import jakarta.annotation.Resource;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.ai.chat.client.ChatClient;
|
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
|
import org.springframework.ai.chat.messages.AssistantMessage;
|
import org.springframework.ai.chat.messages.UserMessage;
|
import org.springframework.ai.chat.model.ChatModel;
|
import org.springframework.ai.chat.model.ChatResponse;
|
import org.springframework.ai.chat.prompt.Prompt;
|
import org.springframework.ai.content.Content;
|
import org.springframework.ai.support.ToolCallbacks;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.stereotype.Service;
|
import reactor.core.publisher.Flux;
|
|
@Slf4j
|
@Service
|
public class AIChatService {
|
|
@Resource
|
private ChatClient chatClient;
|
@Resource
|
@Qualifier("ollamaChatModel")
|
private ChatModel chatModel;
|
@Resource
|
private SystemTools systemTools; // 注入工具类
|
@Resource
|
private MonitorTools monitorTools; // 注入工具类
|
@Resource
|
private KnowledgeTools knowledgeTools;
|
@Resource
|
private ReactAgent cameraAgent; // 注入配置好的 Agent
|
private static final String SYSTEM_PROMPT = """
|
你是摄像头管理助手。请严格遵守以下规则:
|
|
1. **工具优先原则**:当用户问题涉及摄像机的实时状态、修改操作、查询具体设备信息时,
|
必须调用对应的工具(getCameraDetail/searchCameras/updateCameraInfo),
|
绝对不要使用自己的记忆或上下文中的静态文本来回答。
|
|
2. **知识库使用场景**:只有当用户询问操作指南、故障排查手册、产品说明等静态知识时,
|
才使用知识库中的内容。
|
|
3. **冲突处理**:如果知识库中提到了某类操作,但用户要求执行具体操作,
|
必须以工具调用的结果为准。
|
|
========== 输出格式 ==========
|
使用 Markdown 格式输出:
|
- ## 标题
|
- - 列表项
|
- **加粗** 强调
|
- 表格用于数据展示
|
""";
|
/**
|
* 流式对话
|
*/
|
public Flux<String> streamChat(String userMessage) {
|
Long userId = SecurityUtils.getUserId();
|
return chatClient.prompt()
|
.system(SYSTEM_PROMPT)
|
.user(userMessage)
|
.advisors(advisor -> advisor.param("chat_memory_conversation_id", userId))
|
.tools(systemTools,monitorTools, knowledgeTools)
|
.stream()
|
.content();
|
}
|
|
/**
|
* 对话服务入口
|
*/
|
public String chat(String userMessage) throws GraphRunnerException {
|
Long userId = SecurityUtils.getUserId();
|
// 1. 为每个用户创建唯一的 threadId
|
RunnableConfig config = RunnableConfig.builder()
|
.threadId(userId.toString()) // 比如从 SecurityUtils.getUserId() 获取
|
.build();
|
// 3. 调用 Agent 的 call 方法并执行
|
AssistantMessage response = cameraAgent.call(userMessage,config);
|
// 4. 从响应中提取文本内容
|
return response.getText();
|
}
|
|
private static final String SYSTEM_PROMPT1 = """
|
你是智能管理助手,拥有以下能力:
|
|
## 可用工具
|
### 摄像头管理
|
- getCameraDetail: 查询摄像机详情
|
- searchCameras: 搜索摄像机
|
- updateCameraInfo: 修改摄像机信息
|
|
### 系统管理
|
- searchUsers: 搜索用户
|
- searchDepts: 搜索部门
|
- searchRoles: 搜索角色
|
- getUserRoles: 查询用户角色
|
|
### 知识库
|
- searchKnowledgeBase: 查询知识文档
|
|
## 原则
|
1. 根据问题自动选择工具
|
2. 数据必须来自工具调用
|
3. 用 Markdown 格式回复
|
""";
|
|
/**
|
* 流式聊天
|
*/
|
public Flux<String> streamChat1(String userMessage) {
|
Long userId = SecurityUtils.getUserId();
|
RunnableConfig config = RunnableConfig.builder()
|
.threadId(userId.toString())
|
.build();
|
ReactAgent agent = ReactAgent.builder()
|
.name("UnifiedAgent")
|
.model(chatModel)
|
.instruction(SYSTEM_PROMPT1)
|
.tools(ToolCallbacks.from(monitorTools, systemTools, knowledgeTools))
|
.saver(new MemorySaver())
|
.build();
|
|
try {
|
return agent.streamMessages(userMessage, config)
|
.filter(msg -> msg instanceof AssistantMessage)
|
.map(Content::getText)
|
.doOnError(error -> log.error("Agent执行出错: {}", error.getMessage()));
|
} catch (GraphRunnerException e) {
|
throw new RuntimeException(e);
|
}
|
}
|
}
|