aha-python
Audio Harness Python SDK,发行包名为 aha-python,导入名为 aha。
使用 Python 3.10–3.12,通过 Poetry 开发:
poetry env use python3.10
poetry install
poetry run aha version
poetry run pytest
poetry build
首版对接现有 /v1/realtime WebSocket 和 x_aha=v1。一条连接只有一路输入。
不提供文件上传、文件转写、Jobs、Artifacts、gRPC 客户端或多 Stream。
安装与分层
发布前使用构建出的 wheel:
poetry run python -m pip install /workspace/libs/aha-python/dist/aha_python-0.1.0-py3-none-any.whl
aha.contracts 提供共享的模型、验证器和编解码;导入它不会加载 aha.client。
为了保持现有服务端的类型继承和协议一致性,基础依赖保留 OpenAI 2.50 系列、Pydantic v2,
客户端使用 websockets 15。SDK 不依赖服务端源码、NumPy、音频设备、Torch 或模型运行时。
导入不会建立连接或启动线程。同步和异步客户端分别使用原生同步和异步 WebSocket。
实时转写
import asyncio
from aha import AsyncAudioHarness, AudioFormat
async def run(pcm_chunks):
async with AsyncAudioHarness(base_url="http://localhost:8000") as client:
async with client.transcriptions.connect(
model="meeting-transcribe", # 服务端已发布的工作流名称
audio=AudioFormat.pcm16(sample_rate=16000),
session={"audio": {"input": {"turn_detection": None}}},
) as session:
async def feed():
await session.send_audio(pcm_chunks)
await session.input_audio_buffer.commit()
sender = asyncio.create_task(feed())
try:
async for event in session.events():
if event.type == "conversation.item.input_audio_transcription.completed":
print(event.transcript)
elif event.type == "error":
print(event.error.code)
# 由应用的停止条件结束消费;主转写完成不等于说话人结果已齐。
finally:
sender.cancel()
await asyncio.gather(sender, return_exceptions=True)
异步 send_audio 接受 bytes、同步或异步 bytes 迭代来源;同步版本接受 bytes 或同步来源。
来源必须为 PCM S16LE 单声道,支持 16/24 kHz,默认 24 kHz。SDK 合并碎块并按默认 20 ms 分块,
不做解码、重采样、静音填充或实时速度节流。来源取得数据的速度由应用控制。
来源跨块的半个样本会合并,最终仍有半个样本时报错,已发送音频不会自动撤销。
一次只运行一个 send_audio;不要同时调用低层 append 或在生产者尚未结束时 commit/clear。
connect() 等待 session.created、发送初始配置并等待 session.updated 后返回。
这两个事件仍然交付给用户。session.update() 等后续方法只发送命令,返回生成的客户端 event_id,
不表示服务端接受或执行完成;通过事件观察结果及关联错误。
同步用法相同,将 AsyncAudioHarness 换成 AudioHarness,使用 with、普通 for,不加 await。
连续发送和消费必须并行(同步使用调用方线程),避免输出积压。
语音智能体与控制
client.realtime.connect(model="voice-agent") 连接已发布智能体。两类会话均提供以下方法,
实际适用范围沿用服务端,纯转写不支持的 Agent 操作仍返回业务错误:
| 方法 | 作用 |
|---|---|
session.session.update(config) |
更新现有协议支持的 Session 字段 |
session.input_audio_buffer.append/commit/clear |
输入 bytes、提交、清空 |
session.response.create/cancel |
创建或取消回复 |
session.conversation.item.create/retrieve/delete/truncate |
会话条目操作及已播放位置截断 |
session.tools.submit_output(call_id, output) |
提交客户端工具结果 |
session.tools.respond_approval(approval_request_id, approved) |
显式回答 MCP 审批 |
session.agent_backend.respond_approval/respond_question/cancel |
后台 Agent 审批、问答与取消 |
session.send(event) |
发送现有契约支持的模型或字典,音频字段使用 bytes |
服务端保留工具执行和审批决策权。SDK 不自动批准、重做工具或把取消当成副作用回滚。
TTS response.output_audio.delta 的 delta 是解码后的 PCM bytes;输出格式沿用服务端(24 kHz mono)。
应用负责播放器缓冲、清空和实际播放水位。取消使用 response.cancel(),同步已听内容使用
conversation.item.truncate();现有 WS 不支持服务端播放缓冲 clear,SDK 不模拟该确认。
参考 文本与 TTS 示例 和 内存 PCM 示例:
AHA_BASE_URL=http://localhost:8000 AHA_MODEL=voice-agent poetry run python examples/voice.py
交互式客户端体验测试见 SDK 客户端工作台。
这是独立的 Poetry + React demo,浏览器采集麦克风,Python 桥接服务使用已安装的 aha wheel;
支持实时转写、文本对话、TTS 播放、审批和事件检查,不增加 SDK 主包的 Web 依赖。
审批回复示例(只在业务已作出明确决定后发送):
await session.agent_backend.respond_approval(
request_id=event.request_id,
approval_id=event.approval_id,
approved=False,
)
结束、错误和资源边界
send_audio来源耗尽只表示字节已发送,不自动 commit/close。自动 VAD 和手动 commit 完全沿用服务端。close()/上下文退出释放连接、读取任务或线程,不保证待处理结果交付,不提供finish/drained。 当前 WS 没有全分支排空屏障,静默超时也不能证明处理完成。主转写之后仍可能有说话人结果。- 一个会话只允许一个活动事件迭代器;事件不按文本内容去重,也不自动合并或改写 revision。
已知事件的新增可选字段可从
model_extra读取(严格 AHA 类型的model_dump()不包含它们),未知类型以UnknownEvent交付并保留.raw。 - 服务端
error是可恢复业务事件,消费者可继续读取。无效事件抛ProtocolError,断线抛ConnectionLost(含last_event_id和outcome_unknown=True)。不自动重连、重试或重放。 - 来源迭代和用户消费任务由调用方拥有,必须在自己的
finally中取消/回收;SDK 拥有连接读取任务。
Limits 可配置连接、发送、关闭、消费者等待和队列预算:默认分别为 10、30、10、30 秒,
事件队列最多 256 条且原始事件累计不超过 8 MiB,单条网络消息最多 1 MiB,PCM 分块 20 ms。
WebSocket 内部缓冲另有 16 帧上限;事件反序列化对象也占内存,字节预算不是进程 RSS 上限。
消费者超时抛 ConsumerBackpressure 并中止连接,已入队事件交付后暴露错误;不默默丢弃它们。
这些是 SDK 本地预算,现有服务端没有输入确认/额度协商,不能据此声称服务端已接收或完成推理。
from aha import AsyncAudioHarness, Limits
client = AsyncAudioHarness(
base_url="https://audio.example/v1",
api_key="由应用安全取得的凭证",
limits=Limits(event_queue_count=128, consumer_timeout=5),
)
base_url 接受 HTTP(S)/WS(S)、根路径、/v1 或完整 /v1/realtime。
api_key 作为 Bearer header 发送,不能与自定义 Authorization 同时指定;应用当前由部署网关鉴权。
可传入 headers、ssl_context 和 proxy(默认尊重环境代理,None 禁用);TLS 默认验证证书。
同一异步客户端及其会话只在创建和使用它们的事件循环内操作。
契约与验证
poetry run aha schema --direction client
poetry run aha schema --direction server
poetry run pytest
poetry build
Schema 是现有线协议(JSON 中音频为 Base64);Python send() 和事件视图使用 bytes。
服务端应使用 aha.contracts 的原有严格适配器,客户端宽容解析不会改变服务端验证规则。
测试使用本地 WebSocket 服务,不依赖模型或外部服务。
Metadata
Release files for aha-python 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| aha_python-0.1.0.tar.gz | 21.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aha_python-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 46.6 kB
Release files / aha_python-0.1.0.tar.gz
| Download URL | aha_python-0.1.0.tar.gz |
|---|---|
| Size | 21.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d83d79f603593ebbb57a6a339d891ebf59bdc7dc6d40e3e41f8b16634a29c514
|
|
BLAKE2b-256 checksum How to use checksums |
708d4dbbb81b48ce305accd8bbd3b99c0e2a045b5ae74ece5d562b9f99e5ba82
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.13.5 Linux/6.8.0-138-generic
|
Release files / aha_python-0.1.0-py3-none-any.whl
| Download URL | aha_python-0.1.0-py3-none-any.whl |
|---|---|
| Size | 24.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d965a6a208065c4c19fe5767268da18c49b98dc4a026ed17c611c947aeaa5066
|
|
BLAKE2b-256 checksum How to use checksums |
de8459126e908feee060d085b00ddc6b673612b8a30be64acb9fc48da560802b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.13.5 Linux/6.8.0-138-generic
|
Security for aha-python 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.