【开源】给ChatGLM写个,Java对接的SDK

news2025/2/28 6:46:38

作者:小傅哥 - 百度搜 小傅哥bugstack
博客:bugstack.cn

沉淀、分享、成长,让自己和他人都能有所收获!😄

大家好,我是技术UP主小傅哥。

清华大学计算机系的超大规模训练模型 ChatGLM-130B 使用效果非常牛,所以我也想把这样的Ai能力接入到自己的应用中或者做一些 IntelliJ IDEA Plugin 使用。但经过了一晚上的折腾,我决定给它写个对接的SDK开源出来!—— 🤔 智谱Ai不是已经有了一个SDK吗?为啥还要写呢?那你写多少了?

在很早之前就关注了智谱Ai(ChatGLM),也看到官网有一个Java对接的SDK方式。但从前几天开始正式对接发现,这SDK是8月份提交的,10个commit,而且已经2个月没有更新了。所以真的是不少Bug呀,呀,呀!如果不去修改它的SDK代码,就没法对接。如;ConfigV3类中,拆分ApiKey的操作;String[] arrStr = apiSecretKey.split("."); 但这里的.是正则的关键字,所以根本没法拆分。一起动就报错 invalid apiSecretKey 这对于初次对接并且没有看源码的伙伴来说,是不小的炸雷。

不过,虽然 SDK 有点赶工,不好用。但不影响智谱Ai(ChatGLM)是个好东西。他的官网中有API HTTP 接口对接描述。所以,小傅哥决定跟着按照它的文档写一个能简单对接,代码有干净整洁的 SDK 让大家使用。

那么,接下来小傅哥就介绍下,如何基于智谱Ai(ChatGLM)的开发者文档,开发一个通用的SDK组件。也让后续有想法PR贡献源码的伙伴,一起参与进来。—— 别看东西不大,写到简历上,也是非常精彩的一笔!

本文不止有智谱Ai-SDK开发,还有如何在项目中运用SDK开发一个自己的OpenAi服务。文末有SDK链接和OpenAi应用工程。

一、对接鉴权

  • 文档:https://open.bigmodel.cn/dev/api
  • ApiKey:https://open.bigmodel.cn/usercenter/apikeys - 申请个人授权,创建ApiKey即可

智谱Ai的Api文档,与ChatGPT对接有一些差

如果大家对接过ChatGPT开发,直接获取一个ApiKey就可以使用了。但在对接智谱Ai的Api时,需要把获取的ApiKey按照.号分割,并需要进行JWT-Token的创建。而这个Token才是实际传给接口的内容。

  • 因为生成Token会比较耗时,所以这里会使用Guava框架进行本地缓存29分钟,有效期30分钟的Token,确保可以有效的刷新。
  • 在工程中提供了 BearerTokenUtils Token 生成工具类,测试的时候可以使用。

二、接口处理

文档:https://open.bigmodel.cn/dev/api#chatglm_lite - 以Api文档的chatglm_lite模型举例对接

传输方式https
请求地址https://open.bigmodel.cn/api/paas/v3/model-api/chatglm_lite/sse-invoke
调用方式SSE
字符编码UTF-8
接口请求头accept: text/event-stream
接口请求格式JSON
响应格式标准 Event Stream
接口请求类型POST
开发语言任意可发起 HTTP 请求的开发语言

在正式开发代码,要把接口的使用先简单测试运行出来。之后再去编写代码。为此这里小傅哥先根据官网的文档和鉴权使用方式,编写了 curl http 请求;

curl -X POST \
        -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsInNpZ25fdHlwZSI6IlNJR04ifQ.eyJhcGlfa2V5IjoiNGUwODdlNDEzNTMwNmVmNGE2NzZmMGNjZTNjZWU1NjAiLCJleHAiOjE2OTY5OTM5ODIzMTQsInRpbWVzdGFtcCI6MTY5Njk5MjE4MjMxNH0.9nxhRXTJcP4Q_YTQ8w5y0CZOBOu0epP1J56oDaYewQ8" \
        -H "Content-Type: application/json" \
        -H "User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)" \
        -H "Accept: text/event-stream" \
        -d '{
        "top_p": 0.7,
        "sseFormat": "data",
        "temperature": 0.9,
        "incremental": true,
        "request_id": "xfg-1696992276607",
        "prompt": [
        {
        "role": "user",
        "content": "写个java冒泡排序"
        }
        ]
        }' \
  http://open.bigmodel.cn/api/paas/v3/model-api/chatglm_lite/sse-invoke
  • 注意:Authorization: Bearer 后面传的是 JWT Token 不是一个直接从官网复制的 ApiKey - 你可以使用工程中 BearerTokenUtils 创建
  • 之后可以直接运行这段脚本(也可以导入到ApiPost工具中),执行后就能获得到运行效果了。—— 速度非常快!

三、组件开发

在🤔考虑到抽象和设计原则下,小傅哥这里采用了会话模型结构进行工程框架设计。把程序的调用抽象为一次会话,而会话的创建则交给工厂🏭。通过工厂屏蔽使用细节,在使用上简化调用,尽可能让外部最少知道原则。这样的设计实现方式,既可以满足调用方开心的使用,也可以让SDK贡献者见代码如见文档,容易理解和上手。

1. 工程结构

  • 工程非常注重会话的设计和使用,因为框架的根基搭建好以后,扩展各项功能就会有迹可循。大部分代码就是因为早期没有考虑好框架,最后功能来了被填充的很乱。

2. 会话流程

  • 会话流程以工厂创建 Session 为入口点进行使用,其他的操作都在组件内自己处理好。

3. 代码举例

@Override
public OpenAiSession openSession() {
    // 1. 日志配置
    HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
    httpLoggingInterceptor.setLevel(configuration.getLevel());
    
    // 2. 开启 Http 客户端
    OkHttpClient okHttpClient = new OkHttpClient
            .Builder()
            .addInterceptor(httpLoggingInterceptor)
            .addInterceptor(new OpenAiHTTPInterceptor(configuration))
            .connectTimeout(configuration.getConnectTimeout(), TimeUnit.SECONDS)
            .writeTimeout(configuration.getWriteTimeout(), TimeUnit.SECONDS)
            .readTimeout(configuration.getReadTimeout(), TimeUnit.SECONDS)
            .build();
    configuration.setOkHttpClient(okHttpClient);
    
    // 3. 创建 API 服务
    IOpenAiApi openAiApi = new Retrofit.Builder()
            .baseUrl(configuration.getApiHost())
            .client(okHttpClient)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(JacksonConverterFactory.create())
            .build().create(IOpenAiApi.class);
    configuration.setOpenAiApi(openAiApi);
    return new DefaultOpenAiSession(configuration);
}
  • 这是一段 DefaultOpenAiSessionFactory 创建工厂开启会话的服务对象。使用方只需要在自己的工程中,创建出一个工厂对象就可以对接使用了。下文有代码示例
  • 其他更多的代码,直接看小傅哥开发好的 chatglm-sdk-java

四、组件使用

1. 组件配置

  • 申请ApiKey:https://open.bigmodel.cn/usercenter/apikeys - 注册申请开通,即可获得 ApiKey
  • 运行环境:JDK 1.8+
  • maven pom - 暂时测试阶段,未推送到Maven中央仓库,需要下载代码本地 install 后使用
<dependency>
    <groupId>cn.bugstack</groupId>
    <artifactId>chatglm-sdk-java</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
  • 源码(Github):https://github.com/fuzhengwei/chatglm-sdk-java
  • 源码(Gitee):https://gitee.com/fustack/chatglm-sdk-java
  • 源码(Gitcode):https://gitcode.net/KnowledgePlanet/road-map/chatglm-sdk-java

2. 单元测试

@Slf4j
public class ApiTest {

    private OpenAiSession openAiSession;

    @Before
    public void test_OpenAiSessionFactory() {
        // 1. 配置文件
        Configuration configuration = new Configuration();
        configuration.setApiHost("https://open.bigmodel.cn/");
        configuration.setApiSecretKey("4e087e4135306ef4a676f0cce3cee560.sgP2*****");
        // 2. 会话工厂
        OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration);
        // 3. 开启会话
        this.openAiSession = factory.openSession();
    }

    /**
     * 流式对话
     */
    @Test
    public void test_completions() throws JsonProcessingException, InterruptedException {
        // 入参;模型、请求信息
        ChatCompletionRequest request = new ChatCompletionRequest();
        request.setModel(Model.CHATGLM_LITE); // chatGLM_6b_SSE、chatglm_lite、chatglm_lite_32k、chatglm_std、chatglm_pro
        request.setPrompt(new ArrayList<ChatCompletionRequest.Prompt>() {
            private static final long serialVersionUID = -7988151926241837899L;

            {
                add(ChatCompletionRequest.Prompt.builder()
                        .role(Role.user.getCode())
                        .content("写个java冒泡排序")
                        .build());
            }
        });

        // 请求
        openAiSession.completions(request, new EventSourceListener() {
            @Override
            public void onEvent(EventSource eventSource, @Nullable String id, @Nullable String type, String data) {
                ChatCompletionResponse response = JSON.parseObject(data, ChatCompletionResponse.class);
                log.info("测试结果 onEvent:{}", response.getData());
                // type 消息类型,add 增量,finish 结束,error 错误,interrupted 中断
                if (EventType.finish.getCode().equals(type)) {
                    ChatCompletionResponse.Meta meta = JSON.parseObject(response.getMeta(), ChatCompletionResponse.Meta.class);
                    log.info("[输出结束] Tokens {}", JSON.toJSONString(meta));
                }
            }

            @Override
            public void onClosed(EventSource eventSource) {
                log.info("对话完成");
            }
        });

        // 等待
        new CountDownLatch(1).await();
    }

}
  • 这是一个单元测试类,也是最常使用的流式对话模式。

五、应用接入

1. SpringBoot 配置类

@Configuration
@EnableConfigurationProperties(ChatGLMSDKConfigProperties.class)
public class ChatGLMSDKConfig {

    @Bean
    @ConditionalOnProperty(value = "wxpay.config.enabled", havingValue = "true", matchIfMissing = false)
    public OpenAiSession openAiSession(ChatGLMSDKConfigProperties properties) {
        // 1. 配置文件
        cn.bugstack.chatglm.session.Configuration configuration = new cn.bugstack.chatglm.session.Configuration();
        configuration.setApiHost(properties.getApiHost());
        configuration.setApiSecretKey(properties.getApiSecretKey());

        // 2. 会话工厂
        OpenAiSessionFactory factory = new DefaultOpenAiSessionFactory(configuration);

        // 3. 开启会话
        return factory.openSession();
    }

}

@Data
@ConfigurationProperties(prefix = "chatglm.sdk.config", ignoreInvalidFields = true)
public class ChatGLMSDKConfigProperties {

    /** 状态;open = 开启、close 关闭 */
    private boolean enable;
    /** 转发地址 */
    private String apiHost;
    /** 可以申请 sk-*** */
    private String apiSecretKey;

}
@Autowired(required = false)
private OpenAiSession openAiSession;
  • 注意:如果你在服务中配置了关闭启动 ChatGLM SDK 那么注入 openAiSession 为 null

2. yml 配置

# ChatGLM SDK Config
chatglm:
  sdk:
    config:
      # 状态;true = 开启、false 关闭
      enabled: false
      # 官网地址 
      api-host: https://open.bigmodel.cn/
      # 官网申请 https://open.bigmodel.cn/usercenter/apikeys
      api-key: 4e087e4135306ef4a676f0cce3cee560.sgP2DUs*****
  • 你可以在配置文件中,通过 enabled 参数,启动和关闭 ChatGLM SDK

六、应用开发

基于本文开发的 ChatGLM SDK 就可以对接到 OpenAi 开发一个自己的应用了。https://bugstack.cn/md/project/chatgpt/chatgpt.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1087234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Qt之QTableWidget和QTreeWidget】树悬停、选择样式及表格表头和首行间隔线

QTableWidget设置表头与首行间隔线 win10 实例化QTableWidget后&#xff0c;表格表头和首行中间无间隔线&#xff0c;以下是通过样式表进行设置&#xff1a; // 设置横向表格头的间隔线&#xff0c;可设置四个方向的间隔线,不需要间隔线的可以设置为0px// border-left:0px sol…

同城本地顺风车微信小程序源码系统,前端+后端完整搭建教程

大家好&#xff0c;今天要给大家分享一款同城本地顺风车微信小程序源码系统&#xff0c;同城本地顺风车微信小程序源码系统是一种基于互联网和移动社交平台的顺风车服务系统&#xff0c;搭建起来也十分简单。 系统特色功能一览&#xff1a; 地图定位&#xff1a;用户可以通过地…

C#中的Dispatcher:Invoke与BeginInvoke的使用

Dispatcher是.NET框架中的一个重要概念&#xff0c;用于处理异步消息传递。在C#中&#xff0c;Dispatcher提供了两种方法&#xff1a;Invoke和BeginInvoke&#xff0c;用于控制线程上消息的顺序和执行方式。 目录 一、Dispatcher.Invoke二、Dispatcher.BeginInvoke三、使用场景…

极简c++(4)类的静态成员

静态数据成员 ::是作用域操作符&#xff01; #include<iostream> using namespace std;class Point{private:int x,y;public:point(int x 0,int y 0):x(x),y(y){}~point();int getX(){return x;}int getY(){return x;} }假设需要统计点的个数&#xff0c;考虑添加一个…

Krypton控件组使用之KryptonRibbon

1.去掉File按钮 2.去掉 Cutomize 菜单

安规电容总结

安规电容 顾名思义&#xff1a;电容即使失效后&#xff0c;也不会漏电或者放电伤人&#xff0c;要符合安全规定 多数高压认证产品都需要。 上图&#xff1a; X电容&#xff1a; Y电容&#xff1a; 区别&#xff1a; 电路示意&#xff1a;

安卓配置图标——Qt For Android

前言 相对于给PC端配置图标&#xff0c;给移动端配置有点复杂。 在做跨平台方面&#xff0c;我遵循的原则是能用Qt解决的&#xff0c;就使用Qt的方法&#xff0c;毕竟我对Qt还是很熟悉的。在配置图标方面&#xff0c;界面中所有风格样式都是可以通过qss配置的&#xff1b;平台…

使用 Apache Camel 和 Quarkus 的微服务(五)

【squids.cn】 全网zui低价RDS&#xff0c;免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 在本系列的第三部分中&#xff0c;我们了解了如何在 Minikube 中部署基于 Quarkus/Camel 的微服务&#xff0c;这是最常用的 Kubernetes 本地实现之一。虽然这样的本地…

198、RabbitMQ 的核心概念 及 工作机制概述; Exchange 类型 及 该类型对应的路由规则;了解什么是JMS。

目录 JMS 讲解★ RabbitMQ的核心概念★ RabbitMQ工作机制★ Connection&#xff08;连接&#xff09; 与 Channel&#xff08;通信信道&#xff09;★ Exchange★ Exchange与Queue★ Exchange的类型&#xff08;4种&#xff09;及 该类型对应的路由规则 看RabbitMQ 之前&#x…

适合学生写作业的台灯有哪些?双十一学生台灯推荐清单

现在很多家长为了娃的学习需求&#xff0c;基本都会备上一盏台灯&#xff0c;但桌面台灯有其无法避免的局限性&#xff0c;比如&#xff1a;光照范围不够大、光线过度集中、光线均匀度不足、产生眩光等问题&#xff0c;可能会对孩子的视力健康带来不利影响。 因此建议大家选择…

兴趣社如何搭建一个兴趣社区?

社交产品的本质是帮助用户提升社交的质量与效率&#xff0c;而兴趣则是找到本质的捷径。用户对兴趣社区的使用主要是围绕兴趣爱好&#xff0c;社交属性以及粉丝活动三个方向。对感兴趣的话题&#xff0c;用户天然有更强的分享讨论欲&#xff0c;更期待与人社交互动。“越垂直的…

通过Moonbeam路由流动性,如何转移token至Hydra?

在Moonbeam路由流动性&#xff08;Moonbeam Routed Liquidity&#xff09;功能下&#xff0c;用户在简洁的界面即可从如以太坊、Solona、Polygon、Avalanche等生态将流动性转移至波卡平行链。 开始操作前&#xff0c;请先准备以下条件&#xff1a; 原始链上的资产 原始链上的g…

[elasticsearch]使用postman来查询数据

最近需要debug程序&#xff0c;debug的时候需要查找elasticsearch里面的数据是否正确。 第一步建立一个post请求&#xff0c;并按照图下的方式填上ur和参数&#xff1a; 发送post请求&#xff0c;url为&#xff1a; http://ip:port/index_name/_search我这里查询的是title字…

spring cloud config pattern 用法

看了官网,对pattern用法的讲解,感觉讲的不是很清楚,只是讲了 config server端的配置,没有讲清楚如果从 client 端连接 config server 端的话,需要怎么配置,其中最重要的就是怎么对pattern进行识别,摸锁了一段时间,搞清楚了pattern的用法 springboot version:3.0.4 s…

中科院提出“思维传播”,极大增强ChatGPT等模型复杂推理能力

中国科学院自动化研究所与耶鲁大学计算机系研究人员联合发布了&#xff0c;一份名为《思维传播:用大型语言模型进行基于类比的复杂推理》的论文。 ChatGPT等大型语言模型展示出了超强的创造能力&#xff0c;只需简单的文本提示就能生成小说、营销创意、简历等各种文本内容。但…

同城生活广告投放小程序源码系统 带完整搭建教程

今天给大家分享一个同城生活广告投放小程序源码系统&#xff0c;可以通过这个小程序投放广告来获取盈利&#xff0c;操作简单&#xff0c;后台功能强大&#xff0c;新手或小白不用担心。以下是部分核心代码&#xff1a; 系统特色功能如下&#xff1a; 多城市选择&#xff1a;该…

机器视觉公司还是招人?

文章目录 他们是真的在招人吗&#xff1f;裁那么多人&#xff0c;却还要招那么多人&#xff0c;图什么&#xff1f;为什么&#xff1f;闹着玩&#xff1f;我们常见的裁员原因有以下几种&#xff1a;几个小建议&#xff1a; 最近机器视觉搞外包&#xff0c;搞AI外观检测&#xf…

Spring Boot中的JdbcTemplate是什么,如何使用

Spring Boot中的JdbcTemplate是什么&#xff0c;如何使用 Spring Boot是一个流行的Java应用程序开发框架&#xff0c;它简化了Java应用程序的开发过程&#xff0c;并提供了丰富的功能和工具。在Spring Boot中&#xff0c;JdbcTemplate是一个强大的数据库访问工具&#xff0c;它…

如何使用 arrayList.removeAll(Collection<?> c)?

引言 对于 Collection 集合及其实现类都有 removeAll(Collection<?> c)。 对于ArrayList 的实例对象&#xff0c;在数据比较多的情况下&#xff0c;方法 removeAll() 的传参 c 的类型是 HashSet会比是 ArrayList 的情况快的多。 原因 我们来细看一下ArrayList类的re…

redis简介和配置教程

redis简洁版教程 一、概述1、简介2、特点3、优势 二、配置 一、概述 1、简介 Redis是一个高性能的 key-value 数据库。 2、特点 Redis支持数据的持久化&#xff0c;可以将内存中的数据保存在磁盘中&#xff0c;重启的时候可以再次加载进行使用。Redis不仅仅支持简单的key-v…