qq群聊机器人接入ChatGPT-简介和源码-创新互联

qq群聊机器人接入ChatGPT

2022-12-23 更新,因为最近Chatgpt升级了安全策略,此方法已经不能使用。有新的解决方案出来会及时更新

最近 ChatGPT 很火,也注册了账号玩了玩,确实灰常强大。但是也有的小伙伴可能没办法注册账号,我就想着把qq群机器人接入ChatGPT。 过程还是比较简单顺利的。下面简单介绍一下

创新互联公司是一家专注于成都做网站、成都网站制作与策划设计,西乡塘网站建设哪家好?创新互联公司做网站,专注于网站建设10多年,网设计领域的专业建站公司;建站业务涵盖:西乡塘等地区。西乡塘做网站价格咨询:13518219792

直接跳过介绍,查项目代码

1. ChatGPT 网页的几个接口介绍。 1.1 第一个接口https://chat.openai.com/backend-api/moderations

控制台上看到每次都有调用这个接口,但是阻塞这个接口,也可以正常运行。所有可以忽略这个接口。

1.2 第二个接口https://chat.openai.com/backend-api/conversation

这个接口就是发送请求,获取响应的接口。控制台上看是fetch请求,但把请求直接copy出来,发现请求总是403。

1.3 第三个接口https://chat.openai.com/api/auth/session

最后看到这个接口,大概就是刷新token的,第二个接口之前没有调用这个接口,所以请求可能鉴权失败。

1.4 总结: 经过我的捣鼓,再加上 github 看了下别人写的插件,可以像下面这样正确的发送请求已经接受响应。 2. ChatGPT 具体请求示例 1. 复制cookie

从浏览器控制台请求的请求头,或者 application ->cookie 复制出 __Secure-next-auth.session-token 的key和value。

示例:

"__Secure-next-auth.session-token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..R3Kc7SzojKpBGjqD.A8_9DrrtRoHFzEiJXrfWzePQg后面省略..."

ps: (__Secure-next-auth.callback-url 和 __Host-next-auth.csrf-token 可要可不要)

2. 发起session请求,这里用java okhttp实现,没有多余封装,直接硬码

把结果 nextAuthSessionToken 和 authorization 保留下来。nextAuthSessionToken 作为下一次请求 sessionReq
方法的参数(就不用每次都复制了),nextAuthSessionToken 和 authorization 都传递到下一个接口作为参数

public static String[] sessionReq(String copyCookie) throws IOException {//copyCookie就是从浏览器请求的请求头,或者 application ->cookie 复制出 __Secure-next-auth.session-token 的key和value。   
        //ps: (__Secure-next-auth.callback-url 和 __Host-next-auth.csrf-token 可要可不要)
        //示例: "__Secure-next-auth.session-token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0....后面省略"

        HashMapheaderMap = Maps.newHashMap();
        headerMap.put("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36");
        headerMap.put("cookie", copyCookie);
        headerMap.put("accept-encoding", "gzip, deflate, br");
        //session接口
        Request getRequest = new Request.Builder()
                .url("https://chat.openai.com/api/auth/session")
                .get()
                .headers(Headers.of(headerMap))
                .build();

        Response responseSession = client.newCall(getRequest).execute();
        String result = CharStreams.toString(new InputStreamReader(responseSession.body().byteStream(), StandardCharsets.UTF_8));
        logger.info("session response: {}", result);
        Map map = objectMapper.readValue(result, Map.class);
        String setCookie = responseSession.headers().get("set-cookie");
        Mapcollect = Splitter.on(";").splitToList(setCookie)
                .stream().filter(it ->it.contains("=")).map(it ->it.split("="))
                .collect(Collectors.toMap(it ->it[0], it ->it[1]));
        String nextAuthSessionToken = collect.get("__Secure-next-auth.session-token");
        String authorization = (String) map.get("accessToken");
        logger.info("nextAuthSessionToken: {}", nextAuthSessionToken);
        ChatGPTHandle.sessionToken = nextAuthSessionToken;
        logger.info("authorization: {}", authorization);
        return new String[]{nextAuthSessionToken, authorization};
    }
3. 发起 conversation 请求,同样用java okhttp实现,没有多余封装,直接硬码

requestBody 只用替换 query就行,conCookieMap 就是之前复制的cookie里的内容,这里我把三组都写上了,
__Host-next-auth.csrf-token 和 __Secure-next-auth.callback-url 都是固定值

public static String conversation(String[] auths, String requestBody) throws IOException {//这个 requestBody 可以作为模板写死,不同的请求只需要修改里面的query 
//        String requestBody = "{\"parent_message_id\":\"" + UUID.randomUUID()
//                + "\",\"action\":\"next\",\"messages\":[{\"role\":\"user\",\"id\":\""
//                + UUID.randomUUID() + "\",\"content\":{\"content_type\":\"text\",\"parts\":[\"" + "query" + "\"]}}]," +
//                "\"model\":\"text-davinci-002-render\"}";

        String nextAuthSessionToken = auths[0];
        String authorization = auths[1];
        //替换那个 cookie
        MapconCookieMap = new HashMap<>(4, 1);
        //这个就是上面复制的cookie里的内容
        conCookieMap.put("__Secure-next-auth.session-token", nextAuthSessionToken);
        StringBuilder sb = new StringBuilder();
        conCookieMap.forEach((k, v) ->sb.append(k).append("=").append(v).append("; "));
        sb.deleteCharAt(sb.length() - 2);


        HashMaphashMap = Maps.newHashMap();
        hashMap.put("accept-encoding", "gzip, deflate, br");
        hashMap.put("accept-language", "zh-CN,zh;q=0.9");
        hashMap.put("authorization", "Bearer " + authorization);
        hashMap.put("content-type", "application/json");
        hashMap.put("cookie", sb.toString().trim());
        hashMap.put("origin", "https: //chat.openai.com");
        hashMap.put("referer", "https: //chat.openai.com/chat");
        hashMap.put("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36");
        Request post = new Request.Builder()
                .headers(Headers.of(hashMap))
                .url("https://chat.openai.com/backend-api/conversation")
                .post(RequestBody.create(MediaType.parse("application/json"), requestBody)).build();
        
        Call call = client.newCall(post);
        Response response = call.execute();
        if (response.isSuccessful()) {//处理response的响应消息
            String res = CharStreams.toString(new InputStreamReader(response.body().byteStream(), StandardCharsets.UTF_8));
            //这里是连续多行
            //a
            //a b
            //a b c
            //这直接取倒数第二行
            String[] split = res.split("\n");
            Listcollect1 = Arrays.stream(split).filter(Strings::isNotBlank)
                    .collect(Collectors.toList());
            String fullLine = collect1.get(collect1.size() - 2);
            Map map1 = objectMapper.readValue(fullLine.substring(5), Map.class);
            ArrayList list = (ArrayList) ((Map) ((Map) map1.get("message")).get("content")).get("parts");
            return (String) list.get(0);
        } else {logger.info(response.code() + "  " + response.toString());
        }
        return "服务出错了, g了";
    }
这样基本就能返回成功了,需要的依赖是 okhttp3 和 jackson 和 guava。普通java web项目里应该都有 3. 接入qq机器人,我用的是 github 开源 mirai 3.1 基于 mirai 开发一个简单的 qq机器人,支持艾特回复。 想了一下,还是直接上代码吧,介绍累死我了。(以后有空再加) 项目地址

这里跟一下趋势,用的springboot3.0 java17开发

mirai-qq-bot 最后效果演示

在这里插入图片描述

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前名称:qq群聊机器人接入ChatGPT-简介和源码-创新互联
文章源于:http://pwwzsj.com/article/dhgphc.html