EVA Client SDK for Python | EVA Python SDK
EVA Client SDK for Python
autoark-eva-client-sdk is the EVA multi-turn voice dialogue SDK from
AutoArk AI. It orchestrates VAD, media, and conversation state locally
while using ASR, LLM, and TTS through the fixed EVA Gateway. Import it as eva_client_sdk.
Installation
To run the complete voice and native AEC example below:
uv add "autoark-eva-client-sdk[pyaudio]"
If you do not use the SDK's built-in PyAudio helper, install only the core distribution:
uv add autoark-eva-client-sdk
Pin the complete version your production application has actually accepted. The SDK requires
CPython >=3.11; see the platform matrix below.
The pyaudio extra also requires a working system PortAudio installation. Each wheel already
carries the native AEC ABI v2 library for its platform; AEC needs no separate download or build.
Complete voice dialogue example
This program uses the system-default microphone and speaker with VAD, ASR, LLM, TTS, and native
AEC. Inject the AK safely through the host environment as EVA_GATEWAY_API_KEY; never put it in
source, command arguments, logs, or reports.
import asyncio
import os
from eva_client_sdk import (
AgentEvent,
AsrConfig,
EmotionConfig,
EvaVoiceDialogueAgentConfig,
LlmConfig,
TtsConfig,
VadConfig,
create_eva_voice_dialogue_agent,
)
from eva_client_sdk.media import NativeAecProcessor, create_pyaudio_media_transports
CAPTURE_SAMPLE_RATE = 48_000
def show_event(event: AgentEvent) -> None:
if event.type == "reply.partial":
print(event.text, end="", flush=True)
elif event.type == "reply.final":
print()
elif event.type == "emotion.detected":
confidence = "n/a" if event.confidence is None else f"{event.confidence:.2f}"
print(
f"\nEmotion: {event.emotion_code} "
f"(confidence={confidence}, latency={event.latency_ms} ms, "
f"source={event.source}, text={event.text_preview!r})"
)
elif event.type == "error":
print(f"\nEVA error: {event.error.message}")
async def main() -> None:
aec = NativeAecProcessor(
sample_rate=CAPTURE_SAMPLE_RATE,
stream_delay_ms=60,
)
transports = create_pyaudio_media_transports(
input_sample_rate=CAPTURE_SAMPLE_RATE,
aec=aec,
)
agent = create_eva_voice_dialogue_agent(
EvaVoiceDialogueAgentConfig(
api_key=os.environ["EVA_GATEWAY_API_KEY"],
asr=AsrConfig(model="ark-asr-plus", sample_rate=16_000),
llm=LlmConfig(
model="volcengine-doubao-seed-2.0-lite",
extra_parameters={"thinking": {"type": "disabled"}},
),
tts=TtsConfig(
model="ark-tts-flash",
voice="zh_en_male_evan",
sample_rate=44_100,
),
vad=VadConfig(sensitivity=0.7, silence_threshold_ms=400),
emotion=EmotionConfig(enabled=True),
transports=transports,
)
)
unsubscribe = agent.on_event(show_event)
try:
await agent.start()
await agent.set_audio_input_enabled(True)
await asyncio.to_thread(
input,
"Start speaking; press Enter when you are ready to exit.\n",
)
finally:
try:
await agent.stop()
finally:
unsubscribe()
if __name__ == "__main__":
asyncio.run(main())
Microphone input creates speech turns and TTS plays through the speaker. Enter only controls process
exit; the program does not guess reply completion with a fixed sleep. The Gateway endpoint is
fixed by the SDK; public configuration exposes no base URL, headers, HTTP transport, or
stage-provider injection.
What you can leave out
| Item | Required? | Behaviour when omitted |
|---|---|---|
api_key, asr, llm, tts |
Required to construct the Agent | They cannot be omitted. Model, voice, and authorization availability come from EVA Models and the tenant. |
transports + vad |
Required for continuous voice | Omitting both opens no device; the application can initiate only text turns through submit_text(). |
[pyaudio] extra / PortAudio |
Required only for the built-in PyAudio helper | Omit it when providing custom AudioInputSource / AudioOutputSink implementations. |
NativeAecProcessor |
API-optional; recommended for an open speaker + microphone route | Omitting aec makes the helper use passthrough, so no software echo cancellation occurs. Headphones, hardware AEC, or an already-clean custom input may not need it. |
| Input/output device index | Optional | PortAudio uses the system-default input and output devices. |
camera + [camera] extra |
Optional | No camera session is held; voice and text dialogue continue normally. |
greeting, history, emotion, barge_in |
Optional | Defaults to no greeting, no extra history, no emotion sidecar, and no initial-playback guard. |
commands, metadata, system_prompt |
Optional | Registers no tools, attaches no business metadata, and uses an empty system instruction. |
set_audio_input_enabled(), set_camera_enabled(), and set_tts_enabled() are runtime switches,
not a second configuration system. A configured capability can still be disabled for later capture
or playback while the Agent is running.
Emotion recognition
The complete example enables emotion recognition with EmotionConfig(enabled=True). It handles
both microphone transcripts and user text passed to submit_text(), then emits an
emotion.detected event with:
emotion_code: one ofneutral,happy,sad,angry,anxious,confused,excited,frustrated, orunknownby default. Customlabelsreplace this default set; the SDK still retainsunknown.confidence: optional model-reported confidence, not a statistically calibrated probability.source,text_preview, andlatency_ms: whether the input came from speech or text, a preview of at most 100 characters of the classified content, and the time spent on this emotion classification.text_previewcontains user content, so apply your application's privacy rules before logging it.
Emotion recognition runs concurrently with the normal reply and never rewrites the reply,
conversation history, or TTS. Do not rely on its ordering relative to reply.final. Uncertain
content becomes unknown; a request failure emits a non-fatal error without interrupting the
normal reply. instructions only adds business context and can be omitted when the default
classification needs no customization.
Native AEC
Keep the complete example's NativeAecProcessor when TTS plays through an open speaker while the
microphone is listening. You can omit it with headphones, device-provided hardware AEC, or a custom
microphone source that already supplies echo-clean audio. AEC addresses speaker feedback only; it
does not replace environmental noise suppression, VAD, or microphone-array processing.
The built-in PyAudio helper supplies the far-end reference at the real playback boundary, so the
application does not push playback data or calculate buffer sizes. Set
NativeAecProcessor.sample_rate and
create_pyaudio_media_transports(input_sample_rate=...) to the same sample rate. The built-in
capture path uses mono pcm_s16le.
stream_delay_ms defaults to 60 ms as a practical starting point. If audible echo remains on the
target device, tune it within 0–500 ms for the actual microphone/playback route, then accept the
result at real volume in the real room. Omitting aec selects passthrough, which performs no
software echo cancellation. Explicit native AEC fails with structured not_configured when the
current wheel does not support it; it never degrades silently.
Optional: add a camera
Camera is an optional media role and is never enabled automatically:
uv add "autoark-eva-client-sdk[camera]"
# With both built-in audio and camera helpers:
uv add "autoark-eva-client-sdk[pyaudio,camera]"
from dataclasses import replace
from eva_client_sdk import CameraConfig
from eva_client_sdk.media import OpenCvCameraSource
transports = replace(transports, camera=OpenCvCameraSource())
# Add to EvaVoiceDialogueAgentConfig(...):
camera = CameraConfig(capture_timeout_ms=1500)
Call await agent.set_camera_enabled(True) after creation to hold a camera session. While enabled,
at most one image participates in each speech turn. A local capture failure or timeout surfaces as
a structured media error and the turn continues as text-only.
Agent Facade
create_eva_voice_dialogue_agent(config) returns a VoiceDialogueAgent with eight stable methods:
| Method | Purpose |
|---|---|
start() |
Starts the Agent and configured resources; concurrent calls share the result. |
submit_text() |
Submits one text turn. |
set_audio_input_enabled() |
Enables or disables later microphone input. |
set_camera_enabled() |
Enables or disables the persistent camera session. |
set_tts_enabled() |
Enables or disables later speech synthesis and playback. |
get_messages() |
Reads an immutable snapshot of final user/assistant messages. |
on_event() |
Subscribes to the single public event stream and returns an unsubscribe function. |
stop() |
Enters the terminal state and releases resources; an instance cannot restart. |
Configuration
The README describes top-level configuration and purpose only. For required/optional status,
defaults, ranges, units, direction, trade-offs, and validation, read each dataclass field's #:
comment or callable Args: docstring.
This README and its Chinese counterpart are the authoring sources for the package description.
The release build embeds both complete documents in the distribution metadata Description,
rendered by package indexes as the Project Description; the wheel does not install a separate
project README file.
| Top-level configuration / entrypoint | What it controls |
|---|---|
EvaVoiceDialogueAgentConfig.api_key |
The Gateway credential used by ASR, LLM, and TTS. |
EvaVoiceDialogueAgentConfig.asr |
Speech-recognition model and target PCM sample rate. |
EvaVoiceDialogueAgentConfig.llm |
Reply model, generation parameters, and extra provider-compatible options. |
EvaVoiceDialogueAgentConfig.tts |
Speech-synthesis model, voice selection, speed, volume, and output audio format. |
EvaVoiceDialogueAgentConfig.vad |
Local speech start/end detection; required with transports. |
EvaVoiceDialogueAgentConfig.system_prompt |
System instruction used for every LLM reply. |
EvaVoiceDialogueAgentConfig.greeting |
Whether and how the Agent greets on startup. |
EvaVoiceDialogueAgentConfig.history |
How much completed dialogue is sent as LLM context. |
EvaVoiceDialogueAgentConfig.camera |
How long a speech turn waits for a camera snapshot. |
EvaVoiceDialogueAgentConfig.emotion |
Emotion sidecar, labels, instructions, and input limit. |
EvaVoiceDialogueAgentConfig.barge_in |
When speech is admitted for interruption during playback. |
EvaVoiceDialogueAgentConfig.commands |
Available commands and the per-turn call budget. |
EvaVoiceDialogueAgentConfig.metadata |
Stable business metadata attached to events and context. |
EvaVoiceDialogueAgentConfig.transports |
Audio, AEC, and optional camera roles; omission is text-only. |
AsrConfig / LlmConfig / TtsConfig |
Model selection and tuning for managed ASR, LLM, and TTS. |
VadConfig |
Local VAD speech threshold and end-of-speech silence. |
StaticGreeting / DynamicGreeting |
Fixed-text and LLM-generated startup greeting strategies with optional speech synthesis. |
HistoryConfig |
Maximum completed history turns carried by each LLM request. |
CameraConfig |
Image wait limit for one speech turn. |
EmotionConfig |
Emotion catalog, business context, and input limit. |
BargeInConfig |
Initial-playback speech-admission guard window. |
SubmitTextOptions |
Identity and metadata for one manual text turn. |
CommandParameter / CommandDefinition / CommandRegistration / CommandsConfig |
Command schemas, handler binding, and per-turn budget. |
MediaTransports |
Complete input, output, AEC, and optional camera roles. |
create_eva_voice_dialogue_agent |
Validates configuration and creates an Agent without starting resources or network work. |
PyAudioInputSource / PyAudioOutputSink / create_pyaudio_media_transports |
PyAudio devices, buffers, queues, and AEC assembly. |
NativeAecProcessor |
Native AEC library, audio format, route delay, and high-pass processing. |
OpenCvCameraSource |
OpenCV camera device, JPEG quality, and resize limit. |
LlmConfig.extra_parameters adds model-specific parameters to the LLM request-body top level. It
cannot override SDK-managed model, stream, messages, temperature, max_tokens, tools, or
tool_choice; see the external configuration references below for model-specific parameters.
External configuration references
- Create
EvaVoiceDialogueAgentConfig.api_keyin the EVA Console; its format is similar toak-xxxxxxxx.... Alternatively, use EVA Skill, or refer to the EVA CLI guide to obtain an API Key. The application owns secure storage and rotation; the SDK does not store the AK.
See EVA Models for the ASR, LLM, and TTS models, TTS voices, and the
model-selection information used by AsrConfig, LlmConfig, and TtsConfig, including
supported ranges, exact values, and defaults of sample rates and model parameters. When selecting a
model, use compatible sample rates, voices, generation settings, and model-specific parameters.
Optional tuning parameters such as temperature and token limits may be omitted to use Gateway or
model defaults; fields with SDK defaults still follow their field documentation. The SDK validates
field shapes and basic numeric constraints but does not maintain a dynamic model compatibility
matrix.
The SDK's managed ASR and TTS paths currently support PCM (pcm_s16le) only: the ASR model must
accept PCM input, and the TTS model must produce PCM output. Models without PCM support cannot be
used with the current SDK.
Example model and voice strings demonstrate wiring; they are not a stable catalog for every tenant or environment.
Commands
Register each command as a definition/handler pair when constructing the Agent:
from datetime import UTC, datetime
from eva_client_sdk import (
CommandDefinition,
CommandRegistration,
CommandResult,
CommandsConfig,
)
def get_current_time(_call, context) -> CommandResult:
if context.signal.cancelled:
return CommandResult(ok=False, message="Command cancelled")
return CommandResult(
ok=True,
data={"iso_time": datetime.now(UTC).isoformat()},
)
commands = CommandsConfig(
registrations=(
CommandRegistration(
definition=CommandDefinition(
name="get_current_time",
description="Return the current UTC time.",
),
handler=get_current_time,
),
)
)
Pass commands as EvaVoiceDialogueAgentConfig.commands. Handlers run in the application process
and should observe cancellation; the application owns idempotency and compensation for external
side effects.
Events and errors
Dialogue progress surfaces through the single discriminated event stream from on_event().
Common events cover transcripts, replies, playback, interruption, latency, emotion, command
lifecycle, image capture, and error. All listeners are synchronous observers; one listener's
exception is isolated from the rest.
Synchronous configuration/lifecycle errors raise EvaSdkError; runtime failures surface as
structured error events. The SDK also writes listener failures and redacted views of surfaced
errors to the stdlib named logger eva_client_sdk, but it never installs a handler, calls
basicConfig, or chooses a destination:
import logging
logging.getLogger("eva_client_sdk").addHandler(logging.StreamHandler())
That logger carries error-level information only—never AKs, raw Gateway responses, conversation text, or ordinary progress events.
Media SPI and defaults
Applications can use the defaults or replace AudioInputSource, AudioOutputSink, AecProcessor,
and CameraSnapshotSource. Once the Agent owns an assembled object, the application should not
drive its lifecycle concurrently.
| Role | Default implementation | Default behaviour |
|---|---|---|
| input | PyAudioInputSource |
Continuously captures PCM from a PortAudio device. |
| output | PyAudioOutputSink |
Plays TTS PCM in order with flush/drain/stop. |
| AEC | PassthroughAecProcessor / NativeAecProcessor |
Selects no processing or bundled native AEC. |
| camera | OpenCvCameraSource |
Holds one session and captures JPEG for speech turns. |
Finding device indices
PyAudio / PortAudio device indices are host-specific. Omit input_device_index or
output_device_index to use the system defaults; otherwise enumerate devices with PyAudio itself:
import pyaudio
audio = pyaudio.PyAudio()
try:
for index in range(audio.get_device_count()):
info = audio.get_device_info_by_index(index)
print(
index,
info["name"],
f"input={info['maxInputChannels']}",
f"output={info['maxOutputChannels']}",
)
finally:
audio.terminate()
Choose an index with maxInputChannels > 0 for input and one with maxOutputChannels > 0 for
output. OpenCV has no portable camera-enumeration API. To select OpenCvCameraSource.device_index,
probe a bounded range such as 0..9 with cv2.VideoCapture(index), check isOpened(), and call
release() immediately.
With fully custom input/output/AEC, interface compatibility does not establish device-level playback-clock alignment. Integrations needing stronger AEC should coordinate reference at their actual playback boundary and validate on the target device.
Platforms and verified matrix
The release carries one abi3 wheel per platform:
| Wheel | Platform baseline | Bundled native AEC |
|---|---|---|
cp311-abi3-macosx_11_0_arm64 |
macOS 11.0 / Apple Silicon | libeva_aec.2.dylib |
cp311-abi3-manylinux_2_28_x86_64 |
glibc >= 2.28 / x86_64 |
libeva_aec.so.2 |
cp311-abi3-manylinux_2_28_aarch64 |
glibc >= 2.28 / aarch64 |
libeva_aec.so.2 |
Only combinations exercised by an isolated install appear below. Requires-Python >=3.11 defines
installation range; it does not promote absent versions to verified support:
| CPython | Platform | Status |
|---|---|---|
| 3.11 | macOS arm64 | verified |
| 3.12 | macOS arm64 | verified |
| 3.13 | macOS arm64 | verified |
| 3.13 | Linux x86_64 | verified |
| 3.13 | Linux aarch64 | verified |
Combinations absent from the table are unverified. The manylinux wheels target glibc-based Linux, not Alpine/musl.
Boundaries
-
Native AEC passes ABI, exported-symbol, and platform-baseline checks; those do not accept echo-cancellation route, latency, or quality on a target device.
-
The macOS wheel contains an ad-hoc signed, non-notarized
eva_client_sdk/_native/libeva_aec.2.dylib. A signed/notarized application must cover that file in its own signing pipeline:codesign --force --options runtime --timestamp \ --sign "Developer ID Application: <your team>" \ "$(python -c 'import eva_client_sdk, pathlib; print(pathlib.Path(eva_client_sdk.__file__).parent / "_native" / "libeva_aec.2.dylib")')"
-
Windows is not a target platform.
License and Gateway service
This SDK is proprietary software available for public download, not open-source software. The
AutoArk AI Proprietary SDK License Agreement is in LICENSE; EVA Gateway is a separate hosted
service governed by GATEWAY_TERMS.md; third-party software and model assets are listed in
THIRD_PARTY_NOTICES.md. All three ship in the wheel under dist-info/licenses/.
EVA Python SDK
autoark-eva-client-sdk 是 AutoArk AI 提供的 EVA 多轮语音对话 SDK。
它在本地编排 VAD、媒体与会话状态,通过固定 EVA Gateway 使用 ASR、LLM 和 TTS;Python import
名为 eva_client_sdk。
安装
运行下面的完整语音与 native AEC 示例:
uv add "autoark-eva-client-sdk[pyaudio]"
如果不用 SDK 内置 PyAudio helper,只安装 core distribution 即可:
uv add autoark-eva-client-sdk
生产应用应固定自己实际验收过的完整版本。SDK 要求 CPython >=3.11;支持的平台见后文矩阵。
pyaudio extra 还要求系统可用的 PortAudio。wheel 已携带当前平台匹配的 native AEC ABI v2 库,
不需要另行下载或编译 AEC。
完整语音对话示例
这个程序使用系统默认麦克风和扬声器,启用 VAD、ASR、LLM、TTS 与 native AEC。把 AK 通过宿主
环境安全注入为 EVA_GATEWAY_API_KEY,不要写进源码、命令参数、日志或报告。
import asyncio
import os
from eva_client_sdk import (
AgentEvent,
AsrConfig,
EmotionConfig,
EvaVoiceDialogueAgentConfig,
LlmConfig,
TtsConfig,
VadConfig,
create_eva_voice_dialogue_agent,
)
from eva_client_sdk.media import NativeAecProcessor, create_pyaudio_media_transports
CAPTURE_SAMPLE_RATE = 48_000
def show_event(event: AgentEvent) -> None:
if event.type == "reply.partial":
print(event.text, end="", flush=True)
elif event.type == "reply.final":
print()
elif event.type == "emotion.detected":
confidence = "n/a" if event.confidence is None else f"{event.confidence:.2f}"
print(
f"\n情绪: {event.emotion_code} "
f"(confidence={confidence}, latency={event.latency_ms} ms, "
f"source={event.source}, text={event.text_preview!r})"
)
elif event.type == "error":
print(f"\nEVA error: {event.error.message}")
async def main() -> None:
aec = NativeAecProcessor(
sample_rate=CAPTURE_SAMPLE_RATE,
stream_delay_ms=60,
)
transports = create_pyaudio_media_transports(
input_sample_rate=CAPTURE_SAMPLE_RATE,
aec=aec,
)
agent = create_eva_voice_dialogue_agent(
EvaVoiceDialogueAgentConfig(
api_key=os.environ["EVA_GATEWAY_API_KEY"],
asr=AsrConfig(model="ark-asr-plus", sample_rate=16_000),
llm=LlmConfig(
model="volcengine-doubao-seed-2.0-lite",
extra_parameters={"thinking": {"type": "disabled"}},
),
tts=TtsConfig(
model="ark-tts-flash",
voice="zh_en_male_evan",
sample_rate=44_100,
),
vad=VadConfig(sensitivity=0.7, silence_threshold_ms=400),
emotion=EmotionConfig(enabled=True),
transports=transports,
)
)
unsubscribe = agent.on_event(show_event)
try:
await agent.start()
await agent.set_audio_input_enabled(True)
await asyncio.to_thread(
input,
"可以开始说话;完成对话后按回车退出。\n",
)
finally:
try:
await agent.stop()
finally:
unsubscribe()
if __name__ == "__main__":
asyncio.run(main())
程序在麦克风输入上形成语音 turn,扬声器播放 TTS;按回车只负责结束进程,不用固定 sleep 猜测
回复时间。Gateway endpoint 由 SDK 固定,公共配置不提供 base URL、headers、HTTP transport 或
stage provider 注入。
哪些可以不选
| 项 | 是否必需 | 省略后的行为 |
|---|---|---|
api_key、asr、llm、tts |
Agent 构造必需 | 不能省略。model、voice 与授权以 EVA Models 和租户为准。 |
transports + vad |
连续语音必需 | 两者都省略时不打开设备,只能由应用调用 submit_text() 发起文本 turn。 |
[pyaudio] extra / PortAudio |
仅内置 PyAudio helper 必需 | 自定义 AudioInputSource / AudioOutputSink 时可以不装。 |
NativeAecProcessor |
API 层可选;外放扬声器 + 麦克风场景建议启用 | 不传 aec 时 helper 使用 passthrough,音频不会经过软件消回声。耳机、设备已有硬件 AEC 或自定义 clean input 可选择省略。 |
| input/output device index | 可选 | 省略时使用 PortAudio 的系统默认输入/输出设备。 |
camera + [camera] extra |
可选 | 不持有摄像头 session,语音和文本对话不受影响。 |
greeting、history、emotion、barge_in |
可选 | 分别保持无问候、无额外历史、无情绪旁路、无首次播放保护的默认行为。 |
commands、metadata、system_prompt |
可选 | 不注册工具、不附加业务 metadata、使用空 system instruction。 |
set_audio_input_enabled()、set_camera_enabled() 和 set_tts_enabled() 是运行时开关,不是另一套
配置。即使对应能力已配置,也可以在运行中关闭后续采集或播放。
情绪识别
完整示例已用 EmotionConfig(enabled=True) 开启情绪识别。它同时处理麦克风转写和
submit_text() 提交的用户文本,并通过 emotion.detected 事件返回:
emotion_code:默认为neutral、happy、sad、angry、anxious、confused、excited、frustrated或unknown。自定义labels会替换这组 默认值,SDK 仍会保留unknown。confidence:模型自报的可选信心度,不是经过统计校准的概率。source、text_preview和latency_ms:分别说明输入来自语音还是文本、被分类内容的 最多 100 字符预览,以及本次情绪分类耗时。text_preview包含用户内容,写日志时 应按业务的隐私规则处理。
情绪识别与正常回复并发,不改写回复、对话历史或 TTS;不要假定它与
reply.final 的先后顺序。无法判定的内容返回 unknown;分类请求失败会产生非致命
error,但不会中断正常回复。instructions 只用于补充业务语境;不需要自定义分类时可以
省略。
Native AEC
开放扬声器播放 TTS,同时用麦克风收音时,建议保留完整示例中的
NativeAecProcessor。耳机、设备已有硬件 AEC,或应用能提供已消回声的麦克风输入时,可以
省略它。AEC 只处理扬声器回灌,不替代环境降噪、VAD 或麦克风阵列处理。
内置 PyAudio helper 会在真实 playback boundary 自动提供 far-end reference,调用方不需要
推送播放数据或计算 buffer 大小。只需让 NativeAecProcessor.sample_rate 与
create_pyaudio_media_transports(input_sample_rate=...) 使用同一个采样率;内置采集路径使用
mono pcm_s16le。
stream_delay_ms 默认 60 ms,适合作为首次调试的起点。如果目标设备仍有明显回声,再根据
实际麦克风与播放 route 延迟在 0–500 ms 内调整,并在实际音量、房间和设备上验收。
不传 aec 时 helper 使用 passthrough,即不做软件消回声;显式启用 native AEC 但当前
wheel 不支持时,会以结构化 not_configured 失败,不会静默降级。
可选:增加摄像头
摄像头是可选 media role,不会由 Agent 自动开启:
uv add "autoark-eva-client-sdk[camera]"
# 同时使用内置音频与摄像头 helper:
uv add "autoark-eva-client-sdk[pyaudio,camera]"
from dataclasses import replace
from eva_client_sdk import CameraConfig
from eva_client_sdk.media import OpenCvCameraSource
transports = replace(transports, camera=OpenCvCameraSource())
# 在 EvaVoiceDialogueAgentConfig(...) 中加入:
camera = CameraConfig(capture_timeout_ms=1500)
创建 Agent 后调用 await agent.set_camera_enabled(True) 才持有 camera session。启用期间,每个
speech turn 至多使用一张图片;本地抓图失败或超时会通过结构化 media error 浮现,并以纯文本继续。
Agent Facade
create_eva_voice_dialogue_agent(config) 返回的 VoiceDialogueAgent 提供八个稳定方法:
| 方法 | 用途 |
|---|---|
start() |
启动 Agent 与已配置资源;重复并发调用共享结果。 |
submit_text() |
提交一轮文本输入。 |
set_audio_input_enabled() |
开关后续麦克风输入。 |
set_camera_enabled() |
开关持续 camera session。 |
set_tts_enabled() |
开关后续语音合成与播放。 |
get_messages() |
读取最终用户/assistant 消息的不可变快照。 |
on_event() |
订阅唯一公共事件流并取得退订函数。 |
stop() |
进入终态并释放设备与 Gateway 连接;同一实例不可重启。 |
配置
README 只介绍顶层配置及其用途。字段级必填性、默认值、范围、单位、调节方向、代价和校验规则,
请查看 dataclass 字段旁的 #: 注释或 callable 的 Args: docstring。
本 README 与英文 README 是软件包项目说明的维护来源。构建发布包时,两份完整正文会写入
distribution metadata 的 Description,并在 package index 显示为 Project Description;wheel
不会另行安装独立的项目 README 文件。
| 顶层配置 / 入口 | 控制什么 |
|---|---|
EvaVoiceDialogueAgentConfig.api_key |
Agent 访问 Gateway ASR、LLM 和 TTS 使用的凭证。 |
EvaVoiceDialogueAgentConfig.asr |
语音转写 model 和目标 PCM 采样率。 |
EvaVoiceDialogueAgentConfig.llm |
回复 model 与生成参数。 |
EvaVoiceDialogueAgentConfig.tts |
合成 model、voice 与音频参数。 |
EvaVoiceDialogueAgentConfig.vad |
本地语音起止检测;提供 transports 时必需。 |
EvaVoiceDialogueAgentConfig.system_prompt |
每次 LLM 回复使用的 system instruction。 |
EvaVoiceDialogueAgentConfig.greeting |
Agent 启动时是否问候以及如何生成。 |
EvaVoiceDialogueAgentConfig.history |
后续 LLM 请求携带多少轮历史问答。 |
EvaVoiceDialogueAgentConfig.camera |
speech turn 等待 camera snapshot 的时限。 |
EvaVoiceDialogueAgentConfig.emotion |
情绪旁路、labels、补充 instructions 与输入上限。 |
EvaVoiceDialogueAgentConfig.barge_in |
首次播放期间何时允许新语音进入打断判定。 |
EvaVoiceDialogueAgentConfig.commands |
可调用 command 和每个 turn 的调用预算。 |
EvaVoiceDialogueAgentConfig.metadata |
附加到相关事件和上下文的稳定业务 metadata。 |
EvaVoiceDialogueAgentConfig.transports |
audio、AEC 和可选 camera media roles;省略即 text-only。 |
AsrConfig / LlmConfig / TtsConfig |
托管 ASR、LLM、TTS 的 model 选择与调音参数。 |
VadConfig |
本地 VAD 的语音阈值和收尾静音。 |
StaticGreeting / DynamicGreeting |
固定问候和由 LLM 生成的动态问候。 |
HistoryConfig |
每次 LLM 请求最多携带的已完成历史轮数。 |
CameraConfig |
单个 speech turn 等待图片的时限。 |
EmotionConfig |
情绪分类目录、业务补充和输入限制。 |
BargeInConfig |
首次播放的 speech-admission 保护窗口。 |
SubmitTextOptions |
一次手动文本 turn 的 identity 和 metadata。 |
CommandParameter / CommandDefinition / CommandRegistration / CommandsConfig |
command schema、handler 绑定与每 turn 预算。 |
MediaTransports |
完整 input、output、AEC 与可选 camera 角色。 |
create_eva_voice_dialogue_agent |
从完整配置创建 Agent,不会自动 start。 |
PyAudioInputSource / PyAudioOutputSink / create_pyaudio_media_transports |
默认 PyAudio 设备、buffer、队列和 AEC 装配。 |
NativeAecProcessor |
native AEC 库、音频格式、route 延迟和高通处理。 |
OpenCvCameraSource |
默认 OpenCV camera 设备、JPEG 质量和缩放上限。 |
LlmConfig.extra_parameters 把 SDK 尚未预定义的模型参数添加到 LLM request body 顶层,不能覆盖
SDK 管理的 model、stream、messages、temperature、max_tokens、tools 或
tool_choice;具体 model 参数见下方外部配置参考。
外部配置参考
- 用户可在 控制台 创建并获取
EvaVoiceDialogueAgentConfig.api_key,格式如ak-xxxxxxxx...;也可使用 EVA Skill,或按 EVA CLI 文档获取 API Key。接入应用负责 安全存储和轮换;SDK 不存储 AK。
AsrConfig、LlmConfig 和 TtsConfig 对应的 ASR、LLM、TTS model、TTS voice,以及采样率和模型参数的支持范围、准确值与默认值见
EVA Models。选择 model 时,相关采样率、voice、生成参数与
model-specific 参数必须配套使用。temperature、token 上限等可选调音参数可以省略,由 Gateway
或 model 使用默认行为;带 SDK 默认值的字段仍以对应字段注释为准。SDK 只校验字段形状和基础
数值,不维护动态 model 兼容矩阵。
当前 SDK 的托管 ASR 和 TTS 链路只支持 PCM(pcm_s16le):ASR model 必须支持 PCM 输入,
TTS model 必须支持 PCM 输出。不支持 PCM 的 model 无法用于当前 SDK。
示例中的 model 和 voice 只是接线示例,不构成所有租户或环境都可用的稳定目录。
Command
Command 在 Agent 构造时成对注册 definition 与 handler:
from datetime import UTC, datetime
from eva_client_sdk import (
CommandDefinition,
CommandRegistration,
CommandResult,
CommandsConfig,
)
def get_current_time(_call, context) -> CommandResult:
if context.signal.cancelled:
return CommandResult(ok=False, message="Command cancelled")
return CommandResult(
ok=True,
data={"iso_time": datetime.now(UTC).isoformat()},
)
commands = CommandsConfig(
registrations=(
CommandRegistration(
definition=CommandDefinition(
name="get_current_time",
description="获取当前 UTC 时间。",
),
handler=get_current_time,
),
)
)
把 commands 传给 EvaVoiceDialogueAgentConfig.commands。handler 在应用进程内执行,应观察
取消信号;外部副作用的幂等与补偿仍由应用负责。
事件与错误
对话进展只经 on_event() 的一条判别事件流浮现。常用事件包括 transcript、reply、playback、
interruption、latency、emotion、command lifecycle、image capture 和 error;所有 listener 都是
同步观察者,单个 listener 抛错会被隔离。
配置/lifecycle 的同步错误抛 EvaSdkError;运行错误以结构化 error 事件浮现。SDK 还把 listener
异常和已浮现错误的脱敏视图写到 stdlib 具名 logger eva_client_sdk,但不会自行添加 handler、调用
basicConfig 或决定日志去向:
import logging
logging.getLogger("eva_client_sdk").addHandler(logging.StreamHandler())
该 logger 只承载 error 级信息,不包含 AK、Gateway 原始响应、对话文本或普通进度事件。
Media SPI 与默认实现
应用可以直接使用默认 helper,也可以替换 AudioInputSource、AudioOutputSink、AecProcessor 和
CameraSnapshotSource。Agent 一旦接管已装配对象,应用不应再并发驱动其 lifecycle。
| 角色 | 默认实现 | 默认行为 |
|---|---|---|
| input | PyAudioInputSource |
从 PortAudio 设备持续采集 PCM。 |
| output | PyAudioOutputSink |
顺序播放 TTS PCM,支持 flush/drain/stop。 |
| AEC | PassthroughAecProcessor / NativeAecProcessor |
选择不处理或随包 native AEC。 |
| camera | OpenCvCameraSource |
持有单个 session 并按 speech turn 抓取 JPEG。 |
查询设备索引
PyAudio / PortAudio 设备索引由当前主机决定。省略 input_device_index 或
output_device_index 时使用系统默认设备;需要指定时,可用 PyAudio 自己的查询接口列出设备:
import pyaudio
audio = pyaudio.PyAudio()
try:
for index in range(audio.get_device_count()):
info = audio.get_device_info_by_index(index)
print(
index,
info["name"],
f"input={info['maxInputChannels']}",
f"output={info['maxOutputChannels']}",
)
finally:
audio.terminate()
输入设备选择 maxInputChannels > 0 的索引,输出设备选择 maxOutputChannels > 0 的索引。
OpenCV 没有跨平台的摄像头枚举 API;需要指定 OpenCvCameraSource.device_index 时,可在一个有限范围
(例如 0..9)内逐个打开 cv2.VideoCapture(index),用 isOpened() 判断并立即 release()。
完全自定义 input/output/AEC 时,公共接口兼容不自动保证设备 playback-clock alignment;需要更强 AEC 效果的 integration 应按实际播放边界协调 reference,并在目标设备验收。
平台与验证矩阵
每个平台发布一只 abi3 wheel:
| Wheel | 平台基线 | 随包 native AEC |
|---|---|---|
cp311-abi3-macosx_11_0_arm64 |
macOS 11.0 / Apple Silicon | libeva_aec.2.dylib |
cp311-abi3-manylinux_2_28_x86_64 |
glibc >= 2.28 / x86_64 |
libeva_aec.so.2 |
cp311-abi3-manylinux_2_28_aarch64 |
glibc >= 2.28 / aarch64 |
libeva_aec.so.2 |
下表只列实际执行过隔离安装的组合;Requires-Python >=3.11 只表示安装范围,不把未列版本提升为
已验证支持:
| CPython | 平台 | 状态 |
|---|---|---|
| 3.11 | macOS arm64 | 已验证 |
| 3.12 | macOS arm64 | 已验证 |
| 3.13 | macOS arm64 | 已验证 |
| 3.13 | Linux x86_64 | 已验证 |
| 3.13 | Linux aarch64 | 已验证 |
不在表中的组合未经验证。manylinux wheel 面向使用 glibc 的 Linux,不适用于 Alpine/musl。
边界
-
native AEC 通过 ABI、导出符号与平台基线检查,不代表目标设备的 route、延迟或消回声效果已验收。
-
macOS wheel 内的
eva_client_sdk/_native/libeva_aec.2.dylib是 ad-hoc 签名,未经 Apple notarization。签名公证分发的应用应让自己的签名流程覆盖该文件:codesign --force --options runtime --timestamp \ --sign "Developer ID Application: <你的团队>" \ "$(python -c 'import eva_client_sdk, pathlib; print(pathlib.Path(eva_client_sdk.__file__).parent / "_native" / "libeva_aec.2.dylib")')"
-
Windows 不是当前目标平台。
许可与 Gateway 服务
本 SDK 是公开下载的专有软件,并非开源软件。SDK 适用 LICENSE 中的 AutoArk AI Proprietary SDK
License Agreement;EVA Gateway 是独立托管服务,适用 GATEWAY_TERMS.md;第三方软件和模型资产见
THIRD_PARTY_NOTICES.md。三份文本随 wheel 交付在 dist-info/licenses/ 下。
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file autoark_eva_client_sdk-1.0.0-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: autoark_eva_client_sdk-1.0.0-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 14.4 MB
- Tags: CPython 3.11+, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f5016c8976c0523a07314ccfa4ec640a7c4641f8e1e28169ad1d8fb29c6436e
|
|
| MD5 |
367321cc2d097fc018c75a42130e975b
|
|
| BLAKE2b-256 |
b3843fedabf22f7be4a952dd6c3a6c8be48e47a6cdca92acb8fd71ba04185adb
|
File details
Details for the file autoark_eva_client_sdk-1.0.0-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: autoark_eva_client_sdk-1.0.0-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 14.3 MB
- Tags: CPython 3.11+, manylinux: glibc 2.27+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11f35939f63cf3d11380b92ca9979c3d140e537f0fdb2bf2b04ce52aefca40ab
|
|
| MD5 |
1c947a565adacc72e92e15c23551104f
|
|
| BLAKE2b-256 |
91a1682cc8bb9ca42bb26c890d2061a51a2f7b44578c65db99f2f63a7a163872
|
File details
Details for the file autoark_eva_client_sdk-1.0.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: autoark_eva_client_sdk-1.0.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 4.5 MB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2577e70425194642ae2c64ccba3696181259da67994d91e49f661bacc9938ee9
|
|
| MD5 |
41b55fc9824bba097da6deaab6b86b97
|
|
| BLAKE2b-256 |
5d6fcbd0e4110473e0a43d0cd138aac21644498863594f9ae4ae6f00464450f1
|