☰
ChatGLM SDK(chatglm-sdk-java)实战:智谱 AI 鉴权、SSE 流式对接与会话工厂设计
2026/9/25 8:07:53 网站建设 项目流程
  • 文档
  • 教程
  • 后端

【免费下载链接】CodeGuide

:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、点赞、分享)!

项目地址:https://gitcode.com/gh_mirrors/code/CodeGuide
点击查看免费下载

本文以《ChatGPT 微服务应用体系构建》项目中的chatglm-sdk-java组件为主线,完整讲解如何基于智谱 AI(ChatGLM)开发者文档自研一个干净、易用的 Java SDK:从 ApiKey 到 JWT Token 的鉴权链路、chatglm_lite模型 SSE 流式接口对接、会话模型 + 工厂模式的核心设计,以及最终在 SpringBoot 工程中的配置化接入。读完本文,你将掌握一套可复用的"HTTP 服务封装成通用 SDK"的方法论,并能在自己的 OpenAi 应用服务中直接对接 ChatGLM 大模型。

一、为什么选择自研 ChatGLM SDK

ChatGLM 是清华大学计算机系发布的超大规模训练模型(GLM-130B / ChatGLM-6B),使用效果出色。在实际应用中,我们希望把这样的 AI 能力接入到自己的业务系统(例如 IntelliJ IDEA Plugin、自动回帖服务等)中,而对接的第一步就是找到好用的 Java SDK。

彼时智谱 AI 官网虽然提供了一个 Java 对接 SDK,但该 SDK 存在明显的"赶工"痕迹:提交时间较早、仅有少量 commit、且已连续两个月未更新,实际对接时 Bug 较多。其中一个非常典型的坑就在ConfigV3类拆分 ApiKey 的代码上:

String[] arrStr = apiSecretKey.split(".");

这里的"."是正则表达式中的关键字(匹配任意字符),因此这段代码根本无法按点号正确拆分 ApiKey,一启动就会报错invalid apiSecretKey。对于初次对接且没有看源码的伙伴来说,这无疑是一颗不小的"炸雷"。

不过,虽然官方 SDK 体验不佳,但智谱 AI(ChatGLM)本身是个好东西,其官网提供了完整的 API HTTP 接口对接描述。因此小傅哥决定按官方文档编写一个"能简单对接、代码干净整洁"的 SDK 开源出来,本文所讲的正是这套 SDK 的完整设计实现(对应仓库文档:chatglm-sdk-java.md)。

说明:本文主题相关的模型背景可参考仓库文档 2023-05-21-chatglm-6b.md;SDK 后续演进(3.0/4.0/cogview 兼容)可参考 chatglm-sdk-java-v2.md。

二、对接鉴权:从 ApiKey 到 JWT Token

智谱 AI 的 Api 文档与 ChatGPT 对接存在明显差异:如果大家对接过 ChatGPT 开发,直接获取一个 ApiKey 就可以使用;但在对接智谱 AI 的 Api 时,需要把获取的 ApiKey 按照.号分割,并创建 JWT-Token,而这个 Token 才是实际传给接口的内容。

1. ApiKey 的获取与形态

  • 在智谱 AI 开放平台申请个人授权、创建 ApiKey 即可获得,形态类似4e087e4135306ef4a676f0cce3cee560.sgP2DUs*****,即"ID + 点号 + Secret"的组合。
  • 调用接口时,Authorization: Bearer后面传的是JWT Token,而不是直接从官网复制的 ApiKey。

2. JWT Token 的创建原理

从文档示例中的 Token 串可以观察其标准三段式结构(header.payload.signature)。对前两段做 Base64 解码即可看到约定:

  • Header(请求头):包含typ: JWT、alg: HS256、sign_type: SIGN;
  • Payload(载荷):包含api_key(即 ApiKey 点号前的 ID 部分)、exp(过期时间戳)、timestamp(生成时间戳)。

也就是说,SDK 需要基于 ApiKey 中分割出的 ID 与 Secret,用HS256 算法签名生成一个有时效的 JWT Token,再携带该 Token 去访问模型接口。

3. Token 刷新策略:Guava 本地缓存

因为生成 Token 相对耗时,SDK 中引入 Guava 框架进行本地缓存,设计为:

  • 缓存时长 29 分钟,Token 有效期 30 分钟;
  • 在 Token 过期前主动刷新,确保每次请求都能拿到有效 Token,同时避免频繁重复签名计算。

4. BearerTokenUtils 工具类

工程中提供了BearerTokenUtilsToken 生成工具类,测试阶段可以直接使用它来快速创建 JWT Token,例如在 curl 脚本或单元测试中替换Authorization请求头,无需先跑通整个 SDK。

对比可见官方 SDK 的split(".")缺陷:正则中.匹配任意字符,正确写法应是split("\\.")。这也是自研 SDK 时首先修正的底层细节之一。

三、接口处理:chatglm_lite 模型 SSE 对接

以 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 直接验证:

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

执行后即可获得流式应答效果(也可以把这段脚本导入到 ApiPost 等工具中运行)。其中关键参数说明:

  • Authorization: Bearer后面传的是JWT Token(可用工程中的BearerTokenUtils创建),不是 ApiKey 原文;
  • request_id:请求唯一标识,用于链路追踪与幂等;
  • incremental:true表示增量返回(每次都只返回新增片段),配合 SSE 实现打字机效果;
  • sseFormat:SSE 返回数据格式,示例为data;
  • prompt:旧版模型的对话消息数组,元素含role(如user)与content(提问内容)。

四、组件开发:会话模型 + 工厂模式

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

1. 工程结构与会话流程

工程非常注重会话的设计和使用,因为框架的根基搭建好以后,扩展各项功能就会有迹可循(大部分代码之所以最后被填充得很乱,正是因为早期没有考虑好框架)。会话流程以工厂创建 Session为入口点,其他操作都在组件内部自行处理完毕,调用方无需感知内部细节。

2. 核心代码:DefaultOpenAiSessionFactory.openSession()

@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创建工厂、开启会话的服务对象,核心脉络可以拆解为三层:

  1. 日志拦截器:通过HttpLoggingInterceptor按configuration.getLevel()输出请求/响应日志,便于联调排查;
  2. HTTP 客户端:基于 OkHttp3 构建,注入日志拦截器与自定义的OpenAiHTTPInterceptor(负责拼装Authorization等鉴权头),并分别配置连接、写入、读取三个方向的超时时间;
  3. API 服务:基于 Retrofit 将 HTTP API 声明为 Java 接口IOpenAiApi,使用RxJava2CallAdapterFactory支持响应式调用、JacksonConverterFactory完成 JSON 序列化/反序列化,最终返回DefaultOpenAiSession会话对象。

使用方只需要在自己的工程中创建一个工厂对象,即可对接使用(下文有完整示例)。这套"OkHttp3 + Retrofit2 封装 HTTP 服务"的技术组合,也是面试中被高频考察的技能点(详见仓库面试汇总文档 notes.md 中的技能描述)。

3. 设计演进:执行器解耦(v2 补充)

SDK 在后续版本(GLM-3.0、GLM-4.0、cogview 发布后)做了兼容性重构,核心思路是在会话请求与模型调用之间引入**执行器(Executor)**进行解耦:不同模型(chatglm_std、chatglm_pro、glm-4……)路由到不同的执行器上,旧版模型走GLMOldExecutor(v3 接口、模型放在 URL 中),新版模型走GLMExecutor(v4 统一接口、模型作为入参),并通过ChatCompletionRequest.toString()对prompt/messages等字段做差异化装配。详细实现可参考 chatglm-sdk-java-v2.md。

五、组件使用:引入依赖与单元测试

1. 组件配置

  • 申请 ApiKey:智谱 AI 开放平台用户中心创建即可;
  • 运行环境:JDK 1.8+;
  • Maven 坐标(v1 测试阶段未推送 Maven 中央仓库,需要下载代码本地install后使用;v2 起已发布到 Maven 仓库,版本号2.0):
<dependency> <groupId>cn.bugstack</groupId> <artifactId>chatglm-sdk-java</artifactId> <version>1.0-SNAPSHOT</version> </dependency>

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(); } }

测试中的关键点:

  • 会话初始化:Configuration配置apiHost与apiSecretKey,交给DefaultOpenAiSessionFactory创建工厂并openSession()开启会话;
  • 模型选择:通过Model枚举指定,支持chatGLM_6b_SSE、chatglm_lite、chatglm_lite_32k、chatglm_std、chatglm_pro等旧版模型;
  • 流式回调:EventSourceListener.onEvent中按type区分消息类型——add增量、finish结束、error错误、interrupted中断;结束时通过response.getMeta()解析 Tokens 消耗统计;
  • 阻塞等待:CountDownLatch(1).await()让测试线程等待流式应答完成后再退出。

六、应用接入:SpringBoot 集成 ChatGLM SDK

SDK 设计好之后,如何在自己的 OpenAi 应用服务中配置化接入?这里提供一个标准的 SpringBoot 集成方案。

1. SpringBoot 配置类

@Configuration @EnableConfigurationProperties(ChatGLMSDKConfigProperties.class) public class ChatGLMSDKConfig { @Bean @ConditionalOnProperty(value = "chatglm.sdk.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; }

要点说明:

  • @EnableConfigurationProperties激活配置属性绑定;@ConfigurationProperties(prefix = "chatglm.sdk.config")将 yml 中对应前缀的配置映射到属性类;
  • @ConditionalOnProperty(value = "chatglm.sdk.config.enabled", havingValue = "true", matchIfMissing = false)实现开关式注入:只有配置了enabled: true时才创建OpenAiSessionBean,默认关闭;
  • 通过DefaultOpenAiSessionFactory+Configuration完成会话工厂的创建,对外暴露OpenAiSession。

业务代码中按需注入(注意关闭状态下为 null):

@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 能力。这套配置类 + 条件装配的接入方式,在仓库的实战工程中也有完整落地:例如 http.md 中的"ChatGLM 自动回帖"场景,就是通过ChatGLMSDKConfig将OpenAiSession装配进 Spring 容器,再在定时任务ZSXQJob中调用 SDK 完成对帖子的智能回复(未开启时注入为 null,任务会走降级提示逻辑)。

七、在 OpenAi 应用中的落地:多渠道策略模式

SDK 的价值最终体现在业务应用上。在《ChatGPT 微服务应用体系构建》的 API 工程中(见 第9节:OpenAi多渠道策略模式.md),对接 ChatGLM 前即可先阅读本 SDK 文档完成组件开发。应用层通过策略模式扩展 OpenAi 多渠道对接:定义一个通信渠道策略接口、返回统一格式的数据,ChatGPT 与 ChatGLM 分别实现自己的渠道处理类,再以枚举为 Key 注入到 Map 中。前端选择不同模型问答时,根据模型枚举从 Map 中取出对应策略执行。这样即使后续再拓展其他大模型服务,也只需要新增一个策略实现,具备极佳的扩展性。

八、总结

围绕chatglm-sdk-java,本文完整还原了从零开发一个"智谱 AI SDK"并接入应用的全过程,核心要点可归纳为:

  1. 鉴权链路特殊:智谱 AI 不是直接使用 ApiKey,而是先按.分割 ApiKey、基于 HS256 生成 JWT Token,并借助 Guava 缓存(29 分钟缓存 / 30 分钟有效期)实现高效刷新;
  2. SSE 流式对接:chatglm_lite等旧版模型走/api/paas/v3/model-api/{model}/sse-invoke接口,入参为prompt数组,通过incremental实现增量返回,用 curl 先行验证再落代码;
  3. 会话模型 + 工厂模式:以"会话抽象 + 工厂创建 + 拦截器鉴权 + Retrofit 接口化"为核心设计,屏蔽底层细节,让 SDK 易用、易扩展、易贡献;
  4. SpringBoot 配置化接入:通过@ConditionalOnProperty开关式装配OpenAiSessionBean,配合chatglm.sdk.config前缀的 yml 配置,一条命令即可开启/关闭模型能力;
  5. 演进兼容:后续 GLM-3.0/4.0/cogview 等新模型通过"执行器解耦 + 参数兼容装配"平滑升级(详见 chatglm-sdk-java-v2.md)。

这套 SDK 的"HTTP 服务封装成通用组件"方法论,同样适用于对接微信公众号、微信支付、任意第三方 REST 服务等场景,是值得沉淀并写进简历的实战能力。

  • 文档
  • 教程
  • 后端

【免费下载链接】CodeGuide

:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、点赞、分享)!

项目地址:https://gitcode.com/gh_mirrors/code/CodeGuide
点击查看免费下载

相关推荐

上一篇:Aya未来展望:路线图解读与eBPF技术发展趋势
下一篇:如何快速下载Twitter Spaces音频:完整新手教程与终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询