【开源】给ChatGLM写个,Java对接的SDK
作者:小傅哥 - 百度搜 小傅哥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
【开源】给ChatGLM写个,Java对接的SDK的更多相关文章
- 恕我直言,在座的各位根本写不好Java!
其实,本不想把标题写的那么恐怖,只是发现很多人干了几年 Java 以后,都自认为是一个不错的 Java 程序员了,可以拿着上万的工资都处宣扬自己了,写这篇文章的目的并不是嘲讽和我一样做 Java 的同 ...
- 自己写一个java.lang.reflect.Proxy代理的实现
前言 Java设计模式9:代理模式一文中,讲到了动态代理,动态代理里面用到了一个类就是java.lang.reflect.Proxy,这个类是根据代理内容为传入的接口生成代理用的.本文就自己写一个Pr ...
- 开源工作流 Bonita BPM (JAVA)
Bonita BPM 开源工作流 Bonita BPM (JAVA) http://www.bonitasoft.com/
- 阿里开源自用 OpenJDK 版本,Java 社区迎来中国力量
阿里开源自用 OpenJDK 版本,Java 社区迎来中国力量 3 月 21 日,阿里巴巴将宣布开源 Alibaba Dragonwell.届时,开发者可通过阿里云开发者中心及 Github 社区下载 ...
- 手写一个Java程序输出HelloWorld
` 创建一个Hello.java文件使用记事本打开 public class Hello{ public static void main(String [] args){ System.out.pr ...
- Java对接拼多多开放平台API(加密上云等全流程)
前言 本文为[小小赫下士 blog]原创,搬运请保留本段,或请在醒目位置设置原文地址和原作者. 作者:小小赫下士 原文地址:Java对接拼多多开放平台API(加密上云等全流程) 本文章为企业ERP(I ...
- 分享 Java微信开发SDK
分享 Java微信开发SDK •发布于 4周前 •作者 朋也 •432 次浏览 •最后一次编辑是 2周前 •来自 分享 给大家分享两个java开发微信公众号的sdk jfinal-weixin ...
- 【转】独立游戏如何对接STEAM SDK
独立开发者在对接STEAM SDK之前 首先得先登上青睐之光,也就是我们俗称的"绿光" 一般要先对接G胖家的SDK,然后提交版本,最后等待审核... 我本身是unity 开发,对C ...
- 微信公众平台Java版极速SDK
JEEWX-API 是第一个微信公众平台Java版极速SDK,基于 jeewx-api 开发可以立即拥有简单易用的API,让开发更加轻松自如,节省更多时间 http://www.jeewx.com/
- eclipse导入java和android sdk源码,帮助文档
eclipse导入java和android sdk源码,帮助文档 http://blog.csdn.net/ashelyhss/article/details/37993261 JavaDoc集成到E ...
随机推荐
- macOS 系统 Kafka 快速入门
Kafka 的核心功能是高性能的消息发送与高性能的消息消费.以下是 Kafka 的快速入门教程. 下载并解压缩 Kafka 二进制代码压缩文件 打开 Kafka 官网的下载地址,可以看到不同版本的 K ...
- Typora markdown 满屏显示,去除两边的留白
Typora 宽度在CSS样式文件中有个 max-width 值,现在的显示器分辨率比较高,会导致编辑器两边留白比较多 导致文档编辑时,高分辨率的显示器,得不到充分利用 解决方案 修改源码编辑器样式 ...
- 说说 Go 语言的坑(二)
上一篇文章 说说 Go 语言 for-range 的坑 说的是 for-range 的,工作中,其实还是遇到蛮多奇奇怪怪的问题,这里也顺便整理了一下,就当作是续集:) 先继续看 for-range 的 ...
- 解决phpMyAdmin点击"结构"列页面失去响应的问题
最后更新时间 2017-12-05. 我的环境: phpMyAdmin:4.0.4.1 PHP:5.6.11 第一步 关闭自动更新 打开 ./libraries 目录下的 vendor_config. ...
- Unity UGUI的CanvasScaler(画布缩放器)组件的介绍及使用
Unity UGUI的CanvasScaler(画布缩放器)组件的介绍及使用 1. 什么是CanvasScaler组件? CanvasScaler是Unity中UGUI系统中的一个组件,用于控制画布的 ...
- Debian12配置NTP时间同步
环境 查看系统版本:lsb_release -a 配置NTP时间同步 下面的配置需要用到管理员权限,可以使用su切换到管理员权限. 查看/修正 时区 查看系统时区:timedatectl 如果时区不是 ...
- SQL Server 配置允许远程连接
前言 需要别人远程你的数据库,首先需要的是在一个局域网内,或者连接的是同一个路由器,接下来就是具体步骤: 1.首先是要检查SQLServer数据库服务器中是否允许远程链接.其具体操作为: 1. 打开数 ...
- Django message组件
使用message组件要在seetings中配置 ①INSTALLED_APPS (项目需要什么功能都放在这 既可以有数据库,又可以写代码,html文件,和自己写的APP一个道理) ②MIDDLE ...
- ip2location.py
import re import geoip2.database from tabulate import tabulate from matplotlib import pyplot as plt ...
- SPI总线学习笔记
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空 ...