当前位置: 首页 > news >正文

java springBoot 整合 扣子cozeAI 智能体 对话

文档列表

官方API在线调试,帮助理解https://www.coze.cn/open/playground/list_conversations官方API文档,帮助理解https://www.coze.cn/open/docs/developer_guides/create_conversationCoze_JavaSDK 文档https://www.coze.cn/open/docs/developer_guides/java_overviewcoze_java_sdk_demo 示例https://github.com/coze-dev/coze-java

demo中各工具类的Example有助于理解后按自己的需求编码,建议pull下来看一遍

引入依赖

                    父pom.xml
<properties><coze.version>0.3.0</coze.version>
</properties><dependencyManagement><dependencies><dependency><groupId>com.coze</groupId><artifactId>coze-api</artifactId><version>${coze.version}</version></dependency></dependencies>
</dependencyManagement>
                子pom.xml
<dependencies><dependency><groupId>com.coze</groupId><artifactId>coze-api</artifactId></dependency>
</dependencies>

参数配置

clientIdpublicKeyIdprivateKey请参考教程OAuth应用的创建与授权

我的配置方式只是演示,并非最优唯一解,官方文档中都是建议把这些参数写入系统环境变量中

                    application.yml
coze:clientId: 123456789publicKeyId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxprivateKeyFilePath: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#privateKey: testwwwBase: https://www.coze.cnapiBase: https://api.coze.cnbotId: 987654321

 新建配置类

package com.coze.config;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** @Author: Tenk* 扣子参数配置类*/
@Component
@ConfigurationProperties(prefix = "coze")
public class CozeConfig {//OAuth应用IDprivate String clientId;//公钥private String publicKeyId;//私钥private String privateKey;//私钥证书路径private String privateKeyFilePath;//coze官网private String wwwBase;//cozeApi请求地址private String apiBase;//智能体botIdprivate String botId;

编写工具类

package com.coze.util;import com.coze.openapi.service.auth.JWTOAuthClient;
import com.coze.openapi.service.auth.TokenAuth;
import com.coze.openapi.service.service.CozeAPI;
import com.coze.config.CozeConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;/*** 初始化CozeJWTOAuth授权工具** @url https://github.com/coze-dev/coze-java/blob/main/example/src/main/java/example/auth/JWTOAuthExample.java* @Author: Tenk*/
@Component
public class CozeJWTOAuthUtil {private static final Logger log = LoggerFactory.getLogger(CozeJWTOAuthUtil.class);//配置类@Autowiredprivate CozeConfig cozeConfig;//OAuth授权工具private JWTOAuthClient oauth;//getpublic CozeConfig getCozeConfig() {return cozeConfig;}//getpublic JWTOAuthClient getJWTOAuthClient() {return oauth;}//单例@PostConstructpublic void init() {this.oauth = createJWTOAuthClient();}/*** 初始化CozeJWTOAuth** @return*/public JWTOAuthClient createJWTOAuthClient() {try {//读取coze_private_key_pemString jwtOAuthPrivateKey = new String(Files.readAllBytes(Paths.get(cozeConfig.getPrivateKeyFilePath())), StandardCharsets.UTF_8);oauth = new JWTOAuthClient.JWTOAuthBuilder().clientID(cozeConfig.getClientId()).privateKey(jwtOAuthPrivateKey).publicKey(cozeConfig.getPublicKeyId()).baseURL(cozeConfig.getApiBase()).build();} catch (Exception e) {log.error("初始化CozeJWTOAuth失败", e);return null;}return oauth;}
}

service方法

/*** 常量** @Author: Tenk*/
public class CozeConstants {public static final String JWT_TOKEN = "coze:jwt_token:";public static final String CONVERSATION = "coze:conversation:";
}

 1.OAuth JWT 授权

为什么需要会话隔离https://www.coze.cn/open/docs/developer_guides/session_isolation

    引入上面编写的工具类和redis工具类@Autowiredprivate CozeJWTOAuthUtil cozeJWTOAuthUtil;@Autowiredprivate RedisService redisService;
//根据系统用户id,生成access_token,以达到会话隔离的效果
public OAuthToken getAccessToken(String userId) {OAuthToken accessToken;if (redisService.hasKey(CozeConstants.JWT_TOKEN + userId)) {accessToken = JSONObject.parseObject(redisService.getCacheObject(CozeConstants.JWT_TOKEN + userId).toString(), OAuthToken.class);} else {//token默认15分钟有效期,redis存14分钟accessToken = cozeJWTOAuthUtil.getJWTOAuthClient().getAccessToken(userId);redisService.setCacheObject(CozeConstants.JWT_TOKEN + userId, accessToken, 14L, TimeUnit.MINUTES);}return accessToken;
}

结果

2.向智能体发送消息

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Null;/*** @Author: Tenk* AI聊天业务对象*/
public class ChatBo {@NotBlank(message = "请输入内容")private String content;private String userId;
}
public String createChatMessage(ChatBo bo) {//获取用户jwtTokenOAuthToken accessToken = getAccessToken(bo.getUserId());//获取扣子Api工具CozeAPI cozeAPI = cozeJWTOAuthUtil.createCozeAPIByUser(accessToken.getAccessToken());//获取会话id,演示所设计的是每人是唯一的会话,可以单独new个表做管理String conversationId = null;if (redisService.hasKey(CozeConstants.CONVERSATION + bo.getUserId())) {conversationId = redisService.getCacheObject(CozeConstants.CONVERSATION + bo.getUserId()).toString();} else {//反之创建新会话CreateConversationResp resp = cozeAPI.conversations().create(new CreateConversationReq(null, null, cozeJWTOAuthUtil.getCozeConfig().getTripBotId()));conversationId = resp.getConversation().getId();redisService.setCacheObject(CozeConstants.CONVERSATION + bo.getUserId(), conversationId);}//先手动创建message,否则拿不到messageId等信息以存入数据库CreateMessageReq.CreateMessageReqBuilder<?, ?> msgReq = CreateMessageReq.builder().conversationID(conversationId).role(MessageRole.USER).content(bo.getContent()).contentType(MessageContentType.TEXT);CreateMessageResp msgResp = cozeAPI.conversations().messages().create(msgReq.build());//通过响应拿到user question的message信息Message userMsg = msgResp.getMessage();//创建对话请求,再将创建的message附加到对话中//.messages()中也可以直接传文字而不封装MessageCreateChatReq chatReq = CreateChatReq.builder().stream(false).autoSaveHistory(true).botID(cozeJWTOAuthUtil.getCozeConfig().getTripBotId()).conversationID(conversationId).userID(bo.getUserId()).messages(Collections.singletonList(userMsg))//.messages(Collections.singletonList(Message.buildUserQuestionText(bo.getContent())).build();ChatPoll chatPoll = null;try {//发送对话请求并自动轮询chatPoll = cozeAPI.chat().createAndPoll(chatReq);} catch (Exception e) {log.error("发送对话失败:{}", e.getMessage());return null;}//解析AI消息String content = null;for (Message message : chatPoll.getMessages()) {if (message.getType().getValue().equals(MessageType.ANSWER.getValue())) {// AI完成后的完整答复content = message.getContent();}}return content;//Tips//封装的userMessage和遍历chatPoll得到的botMessage可以自己整理写入数据库以记录。//无特殊需求,其实不用,因为coze有提供获取这些会话内消息列表的接口/工具类
}

结语

前期会花一些时间在官方文档里,吸收概念,理解透彻了才好动手,大家有不理解的,其它想法或经验欢迎留言提出、分享,后续研究更多使用方法会逐一分享出来 。

http://www.xdnf.cn/news/106543.html

相关文章:

  • AI 人工智能模型:从理论到实践的深度解析⚡YQW · Studio ⚡【Deepseek】【Chat GPT】
  • python函数与模块
  • PyCharm 链接 Podman Desktop 的 podman-machine-default Linux 虚拟环境
  • YOLO学习笔记 | 从YOLOv5到YOLOv11:技术演进与核心改进
  • JVM学习笔记
  • Spark论述及其作用
  • 五、实现隐藏(Hiding the Implementation)
  • 记录一次OGG进程abended,报错OGG-01431、OGG-01003、OGG-01151、OGG-01296问题的处理
  • Windows 同步技术-一次性初始化
  • Discuz!与DeepSeek的AI融合:打造智能网址导航新体验——以“虎跃办公”为例
  • 15.FineReport动态展示需要的列
  • 运维案例:让服务器稳定运行,守护业务不掉线!
  • 块压缩与图片压缩优缺点对比
  • 高可靠性厚铜PCB生产的五大关键设备
  • leetcode刷题——判断对称二叉树(C语言版)
  • 知识链(Chain-of-Knowledge):通过对异构来源的动态知识适配实现大语言模型的知识落地
  • 数据通信学习笔记之OSPF的基础术语-距离矢量路由协议
  • 概率dp总结
  • 精准识别违规登录:Windows事件ID 4624全维度分析手册
  • 解决AWS中ELB的目标群组中出现不正常数
  • JAVA工程师面试题(一)
  • 在串的简单模式匹配中,当模式串位j与目标串位i比较时,两字符不相等,则i的位移方式是?
  • 快速生成安卓证书并打包生成安卓apk(保姆教程)
  • HCIP-OSPF综合实验
  • Linux网络编程 从集线器到交换机的网络通信全流程——基于Packet Tracer的深度实验
  • 第十篇:系统分析师第三遍——7、8章
  • Kubernetes服务自动注册Consul全攻略 - 基于consul-register的实践指南
  • vue3:十一、主页面布局(修改顶部导航栏样式-左侧,页面名称设置)
  • Vue3:大纲思路
  • 深入解析C++ STL Stack:后进先出的数据结构