ase-sdk-python 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ase_sdk_python-0.1.0/CHANGELOG.md +11 -0
- ase_sdk_python-0.1.0/LICENSE +201 -0
- ase_sdk_python-0.1.0/MANIFEST.in +6 -0
- ase_sdk_python-0.1.0/PKG-INFO +301 -0
- ase_sdk_python-0.1.0/README.md +274 -0
- ase_sdk_python-0.1.0/examples/http_aiaas.py +35 -0
- ase_sdk_python-0.1.0/examples/http_aipaas.py +35 -0
- ase_sdk_python-0.1.0/examples/websocket_stream.py +87 -0
- ase_sdk_python-0.1.0/publish_pypi.sh +79 -0
- ase_sdk_python-0.1.0/pyproject.toml +43 -0
- ase_sdk_python-0.1.0/setup.cfg +4 -0
- ase_sdk_python-0.1.0/src/ase_sdk/__init__.py +20 -0
- ase_sdk_python-0.1.0/src/ase_sdk/auth.py +167 -0
- ase_sdk_python-0.1.0/src/ase_sdk/client.py +346 -0
- ase_sdk_python-0.1.0/src/ase_sdk/exceptions.py +26 -0
- ase_sdk_python-0.1.0/src/ase_sdk/models.py +104 -0
- ase_sdk_python-0.1.0/src/ase_sdk/py.typed +0 -0
- ase_sdk_python-0.1.0/src/ase_sdk_python.egg-info/PKG-INFO +301 -0
- ase_sdk_python-0.1.0/src/ase_sdk_python.egg-info/SOURCES.txt +25 -0
- ase_sdk_python-0.1.0/src/ase_sdk_python.egg-info/dependency_links.txt +1 -0
- ase_sdk_python-0.1.0/src/ase_sdk_python.egg-info/requires.txt +6 -0
- ase_sdk_python-0.1.0/src/ase_sdk_python.egg-info/top_level.txt +1 -0
- ase_sdk_python-0.1.0/tests/test_auth.py +175 -0
- ase_sdk_python-0.1.0/tests/test_auth_isolation.py +47 -0
- ase_sdk_python-0.1.0/tests/test_client.py +198 -0
- ase_sdk_python-0.1.0/tests/test_integration.py +429 -0
- ase_sdk_python-0.1.0/tests/test_websocket_backpressure.py +156 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-09-11
|
|
4
|
+
|
|
5
|
+
- Initial Python SDK based on `iflytek/ase-sdk-go` at commit
|
|
6
|
+
`cf7591bcb340a30c78a0036c30f8a572ee84b9e0`.
|
|
7
|
+
- AIpaas HTTP URL authentication and AIaaS HTTP body digest / header authentication.
|
|
8
|
+
- Synchronous WebSocket connections with signed handshake URLs for both modes.
|
|
9
|
+
- Dictionary requests, reusable request and payload models, JSON and raw responses.
|
|
10
|
+
- Configurable timeouts, TLS, HTTP retry limits, and context-managed cleanup.
|
|
11
|
+
- Source and wheel distributions, examples, and a PyPI publishing script.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright {yyyy} {name of copyright owner}
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ase-sdk-python
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for ASE AIpaas and AIaaS HTTP and WebSocket services
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Keywords: ase,aipaas,aiaas,sdk,websocket
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: requests<3,>=2.32.3
|
|
22
|
+
Requires-Dist: websockets<18,>=15.0.1
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build>=1.2.2; extra == "dev"
|
|
25
|
+
Requires-Dist: twine>=6.1; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# ase-sdk-python
|
|
29
|
+
|
|
30
|
+
ASE 服务的同步 Python SDK,支持 **AIpaas** 和 **AIaaS** 两种请求格式,以及 HTTP 和 WebSocket 调用。
|
|
31
|
+
|
|
32
|
+
实现参考 [iflytek/ase-sdk-go](https://github.com/iflytek/ase-sdk-go/tree/cf7591bcb340a30c78a0036c30f8a572ee84b9e0),固定基线为 `cf7591bcb340a30c78a0036c30f8a572ee84b9e0`。Python 发行包名是 `ase-sdk-python`,导入名是 `ase_sdk`。
|
|
33
|
+
|
|
34
|
+
## 安装
|
|
35
|
+
|
|
36
|
+
需要 Python 3.10 或更新版本:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python -m pip install ase-sdk-python
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
在源码目录中开发:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python3 -m venv .venv
|
|
46
|
+
source .venv/bin/activate
|
|
47
|
+
python -m pip install -e '.[dev]'
|
|
48
|
+
python -m unittest discover -s tests -v
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 凭证与服务地址
|
|
52
|
+
|
|
53
|
+
以下示例从环境变量读取配置:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export ASE_APP_ID='你的 app_id'
|
|
57
|
+
export ASE_API_KEY='你的 api_key'
|
|
58
|
+
export ASE_API_SECRET='你的 api_secret'
|
|
59
|
+
export ASE_HOST='实际服务域名或主机:端口'
|
|
60
|
+
export ASE_URI='/实际服务路径'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`host` 不包含协议或路径,`uri` 以 `/` 开头。默认 `tls=True`,HTTP 使用 HTTPS,WebSocket 使用 WSS;需要访问明确提供明文协议的本地服务时,可显式设置 `tls=False`。
|
|
64
|
+
|
|
65
|
+
地址必须使用 ASCII:国际化域名先转换为 IDNA,非 ASCII 路径先进行百分号编码;`uri` 不包含查询参数或片段。客户端会先规范化地址,再对实际发送的主机名和路径签名。
|
|
66
|
+
|
|
67
|
+
`app_id` 是请求体中的应用标识;`api_key` 用于标识签名凭证;`api_secret` 仅用于本地计算 HMAC,不作为请求字段发送。SDK 会在缺省时填充 `header.app_id`(AIpaas)或 `common.app_id`(AIaaS)。若请求显式提供了与客户端不一致的 `app_id`,会抛出 `ValueError`。
|
|
68
|
+
|
|
69
|
+
## HTTP 单次调用
|
|
70
|
+
|
|
71
|
+
### AIpaas
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import base64
|
|
75
|
+
import os
|
|
76
|
+
|
|
77
|
+
from ase_sdk import Client
|
|
78
|
+
|
|
79
|
+
request = {
|
|
80
|
+
"header": {},
|
|
81
|
+
"parameter": {},
|
|
82
|
+
"payload": {
|
|
83
|
+
"input": { # 按服务协议替换参数名和内容
|
|
84
|
+
"text": base64.b64encode("你好".encode("utf-8")).decode("ascii"),
|
|
85
|
+
"status": 3,
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
with Client(
|
|
91
|
+
app_id=os.environ["ASE_APP_ID"],
|
|
92
|
+
api_key=os.environ["ASE_API_KEY"],
|
|
93
|
+
api_secret=os.environ["ASE_API_SECRET"],
|
|
94
|
+
host=os.environ["ASE_HOST"],
|
|
95
|
+
uri=os.environ["ASE_URI"],
|
|
96
|
+
mode="aipaas", # 默认值
|
|
97
|
+
) as client:
|
|
98
|
+
response = client.once(request)
|
|
99
|
+
print(response)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
AIpaas 单次 HTTP 调用默认补充缺失的 `header.status=3`。显式传入的状态会保留。请求的其他业务参数遵循目标服务的协议。
|
|
103
|
+
|
|
104
|
+
### AIaaS
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
import os
|
|
108
|
+
|
|
109
|
+
from ase_sdk import Client
|
|
110
|
+
|
|
111
|
+
request = {
|
|
112
|
+
"common": {},
|
|
113
|
+
"business": {}, # 按服务协议填写业务参数
|
|
114
|
+
"data": {}, # 按服务协议填写数据和状态
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
with Client(
|
|
118
|
+
app_id=os.environ["ASE_APP_ID"],
|
|
119
|
+
api_key=os.environ["ASE_API_KEY"],
|
|
120
|
+
api_secret=os.environ["ASE_API_SECRET"],
|
|
121
|
+
host=os.environ["ASE_HOST"],
|
|
122
|
+
uri=os.environ["ASE_URI"],
|
|
123
|
+
mode="aiaas",
|
|
124
|
+
) as client:
|
|
125
|
+
response = client.once(request)
|
|
126
|
+
print(response)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`mode="aiaas"` 时,`once()` 使用 AIaaS 请求格式和 HTTP 鉴权。也可以调用 `once_aiaas(request)`,为本次 HTTP 调用显式选用 AIaaS 格式和鉴权。AIaaS 不自动补充状态字段。
|
|
130
|
+
|
|
131
|
+
SDK **不会自动对媒体内容进行 Base64 编码或解码**,也不推断音频格式、采样率、帧大小或业务字段。示例中的编码由调用方完成;如果目标服务接收明文,应直接传明文。
|
|
132
|
+
|
|
133
|
+
## WebSocket 调用
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
import os
|
|
137
|
+
|
|
138
|
+
from ase_sdk import Client
|
|
139
|
+
|
|
140
|
+
with Client(
|
|
141
|
+
app_id=os.environ["ASE_APP_ID"],
|
|
142
|
+
api_key=os.environ["ASE_API_KEY"],
|
|
143
|
+
api_secret=os.environ["ASE_API_SECRET"],
|
|
144
|
+
host=os.environ["ASE_HOST"],
|
|
145
|
+
uri=os.environ["ASE_URI"],
|
|
146
|
+
mode="aipaas",
|
|
147
|
+
) as client:
|
|
148
|
+
client.connect()
|
|
149
|
+
client.send({
|
|
150
|
+
"header": {"status": 2},
|
|
151
|
+
"parameter": {},
|
|
152
|
+
"payload": {}, # 按服务协议填入单帧请求数据
|
|
153
|
+
})
|
|
154
|
+
while True:
|
|
155
|
+
response = client.receive()
|
|
156
|
+
print(response)
|
|
157
|
+
header = response.get("header", {})
|
|
158
|
+
if header.get("code", 0) != 0 or header.get("status") == 2:
|
|
159
|
+
break
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
上述结束条件是常见的 AIpaas 响应约定;请使用实际服务定义的状态和错误字段。AIaaS 通过 `mode="aiaas"` 配合 `send()`,或直接使用 `send_aiaas()`,发送 `common / business / data` 格式。AIaaS 响应通常需要按服务协议检查 `code`、`data.status` 等字段。
|
|
163
|
+
|
|
164
|
+
两种模式的 WebSocket 握手都使用与 Go SDK 一致的 **GET 签名 URL**;AIaaS 的 HTTP Digest 鉴权不用于 WebSocket。
|
|
165
|
+
|
|
166
|
+
`with` 负责退出时清理资源,不主动建立 WebSocket。`connect()` 可显式建立连接;`send()` 和 `receive()` 也会在需要时首次连接。WebSocket 状态由调用方提供,SDK 不自动添加首帧或末帧标志。
|
|
167
|
+
|
|
168
|
+
同一个客户端支持一个发送线程与一个接收线程并发,适合边上传音频边读取结果。不要在同一连接上创建多个接收线程;多个独立会话应使用各自的 `Client`。SDK 不自动重连或重放 WebSocket 帧。
|
|
169
|
+
|
|
170
|
+
源码包的 `examples/` 目录提供 `http_aipaas.py`、`http_aiaas.py` 和 `websocket_stream.py`,支持从 JSON 文件读取目标服务的真实请求;流式示例使用 JSONL 文件逐帧发送,同时接收结果。
|
|
171
|
+
|
|
172
|
+
## API
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
Client(
|
|
176
|
+
app_id, api_key, api_secret, host, uri,
|
|
177
|
+
*, mode="aipaas", tls=True,
|
|
178
|
+
timeout=30, retries=0, retry_backoff=0.5,
|
|
179
|
+
handshake_timeout=10, read_timeout=30, write_timeout=30, close_timeout=5,
|
|
180
|
+
max_size=16 * 1024 * 1024, connect_headers=None,
|
|
181
|
+
)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
| 参数 | 用途 |
|
|
185
|
+
| --- | --- |
|
|
186
|
+
| `mode` | `aipaas` 或 `aiaas`,决定默认请求格式和 HTTP 鉴权 |
|
|
187
|
+
| `tls` | 是否使用 HTTPS / WSS,默认开启并校验证书 |
|
|
188
|
+
| `timeout` | HTTP 请求超时,单位秒 |
|
|
189
|
+
| `retries` | HTTP 请求失败后的最大重试次数,默认 `0` |
|
|
190
|
+
| `retry_backoff` | HTTP 重试的初始退避秒数 |
|
|
191
|
+
| `handshake_timeout` | WebSocket 连接握手超时,单位秒 |
|
|
192
|
+
| `read_timeout` | 等待单条 WebSocket 消息的超时,单位秒 |
|
|
193
|
+
| `write_timeout` | 发送单条 WebSocket 消息的超时,单位秒;超时后中断连接 |
|
|
194
|
+
| `close_timeout` | WebSocket 关闭超时,单位秒;超时后中断底层连接 |
|
|
195
|
+
| `max_size` | WebSocket 接收单条消息的最大字节数,默认 16 MiB |
|
|
196
|
+
| `connect_headers` | WebSocket 握手时附加的请求头,不能覆盖鉴权字段或协议握手字段 |
|
|
197
|
+
|
|
198
|
+
超时参数可设为 `None` 以禁用对应超时,`max_size=None` 可禁用接收大小限制。HTTP 会保留环境代理配置,但不会读取 `.netrc` 中的 Basic 鉴权覆盖 ASE 签名;WebSocket 与 Go SDK 一样直接连接服务。
|
|
199
|
+
|
|
200
|
+
| 方法 | 返回值 / 行为 |
|
|
201
|
+
| --- | --- |
|
|
202
|
+
| `once(request)` | 按客户端模式发送 HTTP POST,返回解析后的 JSON 字典 |
|
|
203
|
+
| `once_raw(request)` | 同上,返回原始响应 `bytes` |
|
|
204
|
+
| `once_aiaas(request)` | 显式使用 AIaaS HTTP POST,返回 JSON 字典 |
|
|
205
|
+
| `once_aiaas_raw(request)` | 显式使用 AIaaS HTTP POST,返回 `bytes` |
|
|
206
|
+
| `connect()` | 建立 WebSocket 连接 |
|
|
207
|
+
| `send(request)` | 按客户端模式发送一条 WebSocket JSON 消息 |
|
|
208
|
+
| `send_aiaas(request)` | 显式发送一条 AIaaS WebSocket JSON 消息 |
|
|
209
|
+
| `receive()` | 读取一条 WebSocket 消息并解析为 JSON 字典 |
|
|
210
|
+
| `receive_raw()` | 读取一条 WebSocket 消息,返回 `bytes` |
|
|
211
|
+
| `close()` / `destroy()` | 关闭连接并释放客户端资源 |
|
|
212
|
+
|
|
213
|
+
字典是最直接的请求表达方式,也可使用导出的 `Request` / `AIPAASRequest`、`AIaaSRequest` / `AIAASRequest`、`RequestHeader`、`TextPayload`、`AudioPayload`、`ImagePayload` 和 `DataStatus` 模型。状态值与 Go SDK 一致:首帧 `0`、中间帧 `1`、末帧 `2`、单次请求 `3`。
|
|
214
|
+
|
|
215
|
+
### 错误与重试
|
|
216
|
+
|
|
217
|
+
- `HTTPError`:HTTP 非成功响应;`status_code` 和 `body` 提供状态码及原始响应正文。
|
|
218
|
+
- `TransportError`:网络、连接或超时等传输错误。
|
|
219
|
+
- `ProtocolError`:响应不是预期的 JSON 对象等协议错误。
|
|
220
|
+
- `ClientClosedError`:客户端已经关闭。
|
|
221
|
+
- 上述 SDK 异常均继承 `ASEError`;无效参数可抛出 `ValueError` 或 `TypeError`。
|
|
222
|
+
|
|
223
|
+
服务业务错误码不为零时,SDK 仍然返回响应,由调用方按实际响应协议判断。原始响应可能包含业务数据,异常的字符串表示不会自动输出签名 URL 或响应正文。
|
|
224
|
+
|
|
225
|
+
默认不重试 HTTP POST。显式增加 `retries` 可能造成服务重复执行或重复计费,只有在调用方能够接受或处理重复执行时才开启。WebSocket 不自动重试。
|
|
226
|
+
|
|
227
|
+
## 鉴权与 Go SDK 的对应关系
|
|
228
|
+
|
|
229
|
+
### AIpaas HTTP,以及两种模式的 WebSocket
|
|
230
|
+
|
|
231
|
+
待签名字符串使用换行符 `\n`,末尾不额外增加换行:
|
|
232
|
+
|
|
233
|
+
```text
|
|
234
|
+
host: {host}
|
|
235
|
+
date: {date}
|
|
236
|
+
{method} {uri} HTTP/1.1
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
HTTP 的 `method` 为 `POST`,WebSocket 为 `GET`。先计算 `Base64(HMAC-SHA256(api_secret, 签名原串))`,再组装:
|
|
240
|
+
|
|
241
|
+
```text
|
|
242
|
+
api_key="{api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature}"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
将整个鉴权描述再次 Base64 编码作为 `authorization`,连同 `date` 和 `host` 一起作为 URL 查询参数进行 URL 编码。
|
|
246
|
+
|
|
247
|
+
### AIaaS HTTP
|
|
248
|
+
|
|
249
|
+
先对实际发送的 JSON 请求体字节计算:
|
|
250
|
+
|
|
251
|
+
```text
|
|
252
|
+
Digest: SHA-256={Base64(SHA256(body_bytes))}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
待签名字符串为:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
host: {host}
|
|
259
|
+
date: {date}
|
|
260
|
+
POST {uri} HTTP/1.1
|
|
261
|
+
digest: SHA-256={body_sha256_base64}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
计算 `Base64(HMAC-SHA256(api_secret, 签名原串))` 后,在请求头中发送:
|
|
265
|
+
|
|
266
|
+
```text
|
|
267
|
+
Authorization: hmac api_key="{api_key}", algorithm="hmac-sha256", headers="host date request-line digest", signature="{signature}"
|
|
268
|
+
Host: {host}
|
|
269
|
+
Date: {date}
|
|
270
|
+
Digest: SHA-256={body_sha256_base64}
|
|
271
|
+
Content-Type: application/json
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
该 Authorization 值包含 `hmac` 前缀,不做第二层 Base64 编码。SDK 对请求体只序列化一次,签名和发送使用相同字节,避免 JSON 空白、字段顺序或字符编码差异引发验签失败。日期采用 UTC 时间;服务端通常要求客户端时钟偏差不超过 300 秒。
|
|
275
|
+
|
|
276
|
+
## 构建和发布
|
|
277
|
+
|
|
278
|
+
发布流程参考同工作区 AIGES 的 `pyaiges`,产出源码包和 wheel,并运行严格元数据检查:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
python -m unittest discover -s tests -v
|
|
282
|
+
PYTHON=.venv/bin/python ./publish_pypi.sh --build-only
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
脚本要求指定解释器中已安装 `build` 和 `twine`,不会自动修改全局 Python 环境。验证通过的产物会复制到 `dist/`。上传仅使用本次构建的两个产物,不会上传 `dist/` 中的历史版本。
|
|
286
|
+
|
|
287
|
+
凭证可配置在 `~/.pypirc`,也可由 `PYPI_TOKEN` 或 `TWINE_USERNAME=__token__` / `TWINE_PASSWORD` 环境变量提供。令牌通过环境变量传给 Twine,不放入命令行参数。配置好凭证后执行:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# 正式 PyPI
|
|
291
|
+
PYTHON=.venv/bin/python ./publish_pypi.sh
|
|
292
|
+
|
|
293
|
+
# TestPyPI 使用独立的 TestPyPI 凭证
|
|
294
|
+
PYTHON=.venv/bin/python ./publish_pypi.sh --test
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
测试覆盖固定 Go 鉴权向量以及本地 HTTP / WebSocket 服务的真实传输;接入实际引擎时还需使用目标服务的业务参数和凭证验证。PyPI 同一版本的发行文件不可覆盖;后续发布需要更新 `pyproject.toml`、SDK 版本和 `CHANGELOG.md`。
|
|
298
|
+
|
|
299
|
+
## 许可证
|
|
300
|
+
|
|
301
|
+
Apache License 2.0,完整许可文本随发行包的 `LICENSE` 文件提供。
|