Langchain-Chatchat 讯飞星火(Spark)接入指南:SparkApi 鉴权签名与 WebSocket 请求链路解析
【免费下载链接】Langchain-ChatchatLangchain-Chatchat(原Langchain-ChatGLM)基于 Langchain 与 ChatGLM, Qwen 与 Llama 等语言模型的 RAG 与 Agent 应用 | Langchain-Chatchat (formerly langchain-ChatGLM), local knowledge based LLM (like ChatGLM, Qwen and Llama) RAG and Agent app with langchain项目地址: https://gitcode.com/GitHub_Trending/la/Langchain-Chatchat
本篇指南以 SparkApi.md 为主体,系统讲解 Langchain-Chatchat 为接入讯飞星火大模型(Spark API)而封装的 SparkApi 工具模块:
Ws_Param类如何生成携带鉴权信息的 WebSocket 连接 URL,gen_params如何构造符合 API 规范的请求体,以及它们与模型工作器XingHuoWorker的组合调用链路。读完本文,你将掌握 Langchain-Chatchat 集成星火在线模型的完整底层原理,并能依据鉴权算法与请求结构完成二次开发或排障。
一、SparkApi 在 Langchain-Chatchat 中的定位
Langchain-Chatchat 支持通过各类"在线模型工作器(model worker)"接入云端大模型服务。讯飞星火(Spark / iFLYTEK Spark)属于典型的在线 API 服务:它与本地模型不同,不需要下载权重,而是通过WebSocket长连接与讯飞云端交互,且连接建立前必须完成一套基于HMAC-SHA256的签名鉴权。
SparkApi模块正是这套通信机制中"最底层、与业务无关"的工具层。从其被引用的关系看,模块核心由两部分构成:
| 组成部分 | 职责 | 文档出处 |
|---|---|---|
Ws_Param类 | 保存 APPID / APIKey / APISecret 等凭证并生成带鉴权参数的连接 URL | SparkApi.md |
gen_params()函数 | 将提问文本与采样参数组装为符合星火 API 规范的 JSON 请求体 | SparkApi.md |
两者的"消费者"是上层的工作器实现。根据仓库中的配套文档 xinghuo.md,SparkApi.Ws_Param与SparkApi.gen_params均由xinghuo.py中的request函数调用:先通过Ws_Param.create_url()拿到鉴权 URL,再以gen_params()生成请求数据,随后用websockets.connect建立连接并异步接收流式文本。也就是说,SparkApi 是星火接入的"地基",而XingHuoWorker是搭建在其上的"业务层"。
说明:本仓库当前快照中,
model_workers目录下的原始 Python 实现文件未包含在内,但 xinghuo.md、base.md 等 API 文档完整记录了上述类的接口契约与调用关系,本文据此展开。
二、Ws_Param类:凭证模型与 URL 解析
Ws_Param是一个"凭证 + URL 构造器"双重职责的类。它的全部实例属性如下:
| 属性 | 类型含义 | 说明 |
|---|---|---|
APPID | 应用 ID | 在讯飞开放平台创建应用后获得 |
APIKey | API 密钥 | 用于访问 Spark 服务 |
APISecret | 密钥的 Secret | 参与签名计算的核心机密 |
host | 网络地址 | 由Spark_url解析出的netloc(主机名 + 端口) |
path | URL 路径 | 由Spark_url解析出的path |
Spark_url | 服务完整 URL | 形如wss://.../v1.1/chat的连接地址 |
2.1__init__:构造与 URL 拆解
构造函数接收APPID、APIKey、APISecret、Spark_url四个参数,完成两件事:
- 将四个入参原样保存在实例上,供后续方法使用;
- 使用 Python 标准库
urllib.parse.urlparse解析Spark_url,把解析结果的netloc与path分别赋给self.host与self.path。
这种"先拆解、后签名、再拼接"的设计,是为了在create_url中把host、path作为独立片段参与签名原文构造(详见下文)。它同时意味着Spark_url的格式是否规范会直接影响签名能否通过,因此文档特别提示:
- 使用前须确保
Spark_url可被正确解析出网络位置与路径; - 本构造函数不做参数合法性校验,
APPID/APIKey/APISecret的准确性与安全性需要调用方负责; - 三个凭证应统一从讯飞开放平台的应用管理后台获取。
三、create_url:基于 HMAC-SHA256 的鉴权 URL 生成
create_url是Ws_Param中技术含量最高的方法,其核心任务是把"明文凭证"加工成"可被服务端验证的签名",并拼接到原始 URL 上。官方 WebSocket 鉴权流程通常包含五个环节,本方法一一对应:
① 生成 RFC1123 时间戳 date ② 拼接签名原文:host + "\n" + date + "\n" + "GET " + path + " HTTP/1.1" ③ 以 APISecret 为密钥,对签名原文做 HMAC-SHA256 加密 ④ 将密文做 Base64 编码得到 signature_sha ⑤ 构造 Authorization = "APIKey 变量" + ":" + signature_sha,连同 date、host 一起 URL 编码后附加到 Spark_url 末尾这里补充几个值得注意的工程细节:
- RFC1123 时间戳即
GMT格式的 HTTP 标准日期(如Mon, 20 Sep 2023 12:00:00 GMT)。该时间同时用于签名原文与最终 URL 的date参数,服务端据此校验请求新鲜度,因此文档强调"生成的 URL 应立即使用,避免因时间差导致鉴权失败"。 - 签名原文采用三行结构(
host、date、请求行),这是讯飞 WebSocket 鉴权协议约定的拼接方式;请求行使用大写GET与HTTP/1.1版本号,与常规 HTTP 签名规范一致。 - 密钥分工:
APIKey以明文身份标识出现在Authorization前缀中,APISecret则只作为 HMAC 密钥参与运算,绝不直接传输。
最终生成的 URL 结构可概括为:
Spark_url + "?" + "authorization=" + Base64(Authorization头) + "&date=" + URL编码(RFC1123时间) + "&host=" + host文档给出的示意如下:
https://spark.example.com/api?authorization=Base64EncodedString&date=RFC1123Date&host=spark.example.com其中authorization的值是对APIKey:Base64(HMAC-SHA256签名)再一次编码后的字符串。务必注意:此 URL 已内含APIKey与APISecret的派生物,属敏感信息,文档明确警告:打印日志或调试输出时应谨慎,防止凭证泄露。
四、gen_params:星火对话请求体的组装
拿到鉴权 URL 后,下一步是构造真正要发送的对话请求。gen_params(appid, domain, question, temperature, max_token)负责完成这一任务,其返回结构为星火 API 标准的三段式 JSON:
{ "header": { "app_id": "your_appid", "uid": "1234" }, "parameter": { "chat": { "domain": "your_domain", "random_threshold": 0.5, "max_tokens": 100, "auditing": "default", "temperature": 0.7 } }, "payload": { "message": { "text": "你的问题" } } }各字段职责如下:
| 字段 | 所属层级 | 作用与建议 |
|---|---|---|
app_id | header | 应用标识,须与Ws_Param.APPID一致 |
uid | header | 会话内用户标识,便于服务端区分请求来源 |
domain | parameter.chat | 请求所属领域/模型版本标识(如general、generalv2等,具体以接入版本为准) |
random_threshold | parameter.chat | 随机采样阈值,控制回答多样性 |
max_tokens | parameter.chat | 生成最大 token 数,须依据实际版本上限调整 |
auditing | parameter.chat | 内容审核级别 |
temperature | parameter.chat | 创造性控制参数:值越高回答越多样,值越低越确定 |
text | payload.message | 用户的提问文本(question) |
该函数把appid、domain、question以及生成控制参数统一收敛进一个自洽的数据结构中,使上层代码无需关心星火 API 的层级嵌套细节,是"业务与协议解耦"的关键一环。
五、完整调用链路:从request到XingHuoWorker
5.1request:WebSocket 连接与流式接收
根据 xinghuo.md,xinghuo.py中的request(appid, api_key, api_secret, Spark_url, domain, question, temperature, max_token)把上文两个工具串成一条完整链路:
创建 Ws_Param 对象 → 调用 create_url() 得到鉴权 URL → 调用 gen_params() 生成请求 JSON → websockets.connect(url) 建立连接 → json.dumps 后发送请求体 → 异步循环逐帧接收服务端响应 ├─ 响应 header.status == 2 → 处理完成,结束循环 └─ 响应 payload 含文本 → 逐块 yield 给调用方其中request是异步生成器:既通过await等待网络事件,又用yield把分片文本逐段吐出。文档提示调用方需在异步环境下使用,并通过异步迭代消费结果。响应头status == 2是星火协议中"本轮生成完毕"的信号,是该循环的终止条件。
5.2XingHuoWorker:工作器封装与版本管理
XingHuoWorker继承自ApiModelWorker(见 base.md),是模型工作器层级对星火 API 的落地实现。它的核心设计点包括:
- 默认属性:
model_names默认为["xinghuo-api"],context_len默认 8000(通过kwargs.setdefault("context_len", 8000)设置,可被外部配置覆盖); - 版本映射:
do_chat内部维护version_mapping(含各版本的 domain、URL 与 max_tokens 上限),由内嵌函数get_version_details(version_key)按params.version取用;未命中时返回{"domain": None, "url": None}完成优雅降级,避免异常中断; - token 上限收敛:
params.max_tokens = min(details["max_tokens"], params.max_tokens),确保请求不超过服务端允许的上限; - 异步同步化:通过
iter_over_async(同步迭代异步生成器的工具,详见 utils.md)把request产生的异步流逐步拉取,并累加到text后以{"error_code": 0, "text": "..."}的形式逐块 yield 给上层; - 未实现的方法:
get_embeddings目前仅打印参数,暗示星火 worker 暂未落地 embedding 能力,需要 embedding 场景时应改用其他嵌入模型; - 对话模板:
make_conv_template生成name=model_names[0]、系统提示为"你是一个聪明的助手,请根据用户的提示来完成任务"、roles=["user", "assistant"]、sep="\n### "、stop_str="###"的会话结构。
5.3 配置字段的注入方式
在 base.md 中可以看到,在线 API 配置基类ApiConfigParams显式声明了星火相关字段APPID、APISecret(以及worker_name等),并允许extra = "allow"兼容额外字段。其load_config(worker_name)与validate_config机制会调用get_model_worker_config(配置合并逻辑见 utils.md),把"默认配置 + 在线模型配置 + 特定模型配置"逐层合并后回填到参数对象。因此在 Langchain-Chatchat 中接入星火时,只需在模型配置中声明 provider 与上述凭证字段,XingHuoWorker.do_chat内的params.load_config(...)便会自动完成配置装载,而无需手工逐项传参。
六、接入注意事项与排障要点
结合原文档的"注意"条目与整体调用链,实际接入时建议重点检查以下几点:
- 凭证三件套齐全:
APPID、APIKey、APISecret缺一不可,任一错误都会导致鉴权失败或连接被拒;务必从讯飞开放平台后台获取,勿硬编码进版本库。 Spark_url与version匹配:Spark_url决定host/path拆分结果,version决定domain与url的选取;两者不匹配会直接表现为握手失败或返回未知 domain。- URL 即时使用:签名内的时间戳基于当前时间,URL 生成到发起连接之间不应有显著延迟,否则会因时间窗过期鉴权失败。
- 不要在日志中打印鉴权 URL:URL 携带可推导凭证的信息,调试时建议打码或仅打印 host 部分。
- 异步环境约束:
request、do_chat均为异步生成器,须在异步环境中await/ 异步迭代;事件循环获取失败时需自行创建,避免循环冲突(do_chat与iter_over_async都体现了这一处理)。 - 参数边界:
temperature与max_tokens直接决定输出质量与长度,须结合所选模型版本的实际取值范围设定,服务端 max_tokens 上限由get_version_details统一收敛。
七、小结
从模块职责看,Langchain-Chatchat 将"鉴权与协议细节"下沉到SparkApi,将"版本策略与业务封装"上移到XingHuoWorker,中间以request的 WebSocket 异步流作为桥梁,形成了一条清晰的三层调用链:SparkApi.Ws_Param.create_url()(签名 URL)→SparkApi.gen_params()(协议请求体)→request()(连接与流式收发)。理解这条链路的读者,既能独立排查星火接入中的签名、参数与异步问题,也能以此为模板,为 Langchain-Chatchat 扩展其他 WebSocket 型在线模型工作器提供参考。
进一步阅读:
- SparkApi.md:本篇主题文档,含
Ws_Param与gen_params的完整契约说明 - xinghuo.md:
request与XingHuoWorker的实现细节、版本映射与输出示例 - base.md:
ApiConfigParams/ApiModelWorker基类设计,说明 APPID、APISecret 等字段如何随配置注入 - utils.md:
get_model_worker_config、iter_over_async等支撑工具
【免费下载链接】Langchain-ChatchatLangchain-Chatchat(原Langchain-ChatGLM)基于 Langchain 与 ChatGLM, Qwen 与 Llama 等语言模型的 RAG 与 Agent 应用 | Langchain-Chatchat (formerly langchain-ChatGLM), local knowledge based LLM (like ChatGLM, Qwen and Llama) RAG and Agent app with langchain项目地址: https://gitcode.com/GitHub_Trending/la/Langchain-Chatchat
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考