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

06-01 1628阅读

文档列表

官方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

    0.3.0


        
            
                com.coze
                coze-api
                ${coze.version}
            
        
                子pom.xml

    
       com.coze
       coze-api
    

参数配置

clientId、publicKeyId、privateKey请参考教程OAuth应用的创建与授权

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

                    application.yml
coze:
  clientId: 123456789
  publicKeyId: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  privateKeyFilePath: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  #privateKey: test
  wwwBase: https://www.coze.cn
  apiBase: https://api.coze.cn
  botId: 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应用ID
    private String clientId;
    //公钥
    private String publicKeyId;
    //私钥
    private String privateKey;
    //私钥证书路径
    private String privateKeyFilePath;
    //coze官网
    private String wwwBase;
    //cozeApi请求地址
    private String apiBase;
    //智能体botId
    private 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);
    //配置类
    @Autowired
    private CozeConfig cozeConfig;
    
    //OAuth授权工具
    private JWTOAuthClient oauth;
    //get
    public CozeConfig getCozeConfig() {
        return cozeConfig;
    }
    //get
    public JWTOAuthClient getJWTOAuthClient() {
        return oauth;
    }
    
    //单例
    @PostConstruct
    public void init() {
        this.oauth = createJWTOAuthClient();
    }
    /**
     * 初始化CozeJWTOAuth
     *
     * @return
     */
    public JWTOAuthClient createJWTOAuthClient() {
        try {
            //读取coze_private_key_pem
            String 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工具类
    @Autowired
    private CozeJWTOAuthUtil cozeJWTOAuthUtil;
    @Autowired
    private 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;
}

结果

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

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) {
        //获取用户jwtToken
        OAuthToken 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()中也可以直接传文字而不封装Message
        CreateChatReq 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有提供获取这些会话内消息列表的接口/工具类
}

结语

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

高阶版实现方式

流式传输接口 打字机效果的完整实现https://blog.csdn.net/weixin_44548582/article/details/148171608

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码