@anam-ai/js-sdk

中文文档
4.29.1发布于 2026/10/19MITTypeScriptESM + CJS近 30 天下载 30.8万

Anam AI 客户端 JavaScript SDK

中文使用文档
文档目录14 节
  1. 导言
  2. 文档
  3. 实例
  4. 先决条件
  5. Anam AI 账户
  6. Anam API 密钥
  7. 折旧通知
  8. 地方发展
  9. 生产用途
  10. 聊天流
  11. 交付失败
  12. 跨工具呼叫的演讲
  13. 司长说明(第4节)
  14. 发送主任 Note 提示会中段

Anam AI JavaScript SDK 软件

这是JavaScript SDK的官方版本,用于将Anam AI实时数字人物集成到你的产品中. 它提供了一个简单而直观的API,与Anam AI的服务交互.

导言

Anam AI JavaScript SDK旨在帮助开发者将Anam AI的数字人格集成到他们的JavaScript应用中. SDK提供一套API和公用设施,以方便在实时环境中创建,管理和与数字人物互动.

文档

完整的文件可在 翻译:。 。 。 .

实例

看看我们 实例项目 用于执行样本.

先决条件

Anam AI 账户

创建自由账户头到 阿南实验室 并注册.

Anam API 密钥

要使用 SDK 您首先需要 API 密钥 。 遵守指示 这里 来创造一个.

开始

首先,在您的工程中安装 SDK

npm install @anam-ai/js-sdk

折旧通知

重要编号: brainType 输入 PersonaConfig 已贬值,并将在未来版本被删除。 请使用 llmId 换句话说 如果您正在使用 brainType在控制台上你会看到堕落警告 在过渡时期,这两个领域都得到了支持.

地方发展

最快速的开始测试 SDK 是直接使用您的 API 密钥与我们的 SDK 和下面显示的示例人物配置 . 要使用 SDK 您首先需要创建实例 AnamClient为本地开发,您可以使用 unsafe_createClientWithApiKey 方法.

import { unsafe_createClientWithApiKey } from '@anam-ai/js-sdk';

const anamClient = unsafe_createClientWithApiKey('your-api-key', {
  personaId: '<PERSONA ID HERE>',
  name: 'Cara',
  avatarId: '30fa96d0-26c4-4e55-94a0-517025942e18',
  voiceId: '6bfbe25a-979d-40f3-a92b-5394170af54b',
  brainType: 'ANAM_GPT_4O_MINI_V1',
  systemPrompt:
    "[STYLE] Reply in natural speech without formatting. Add pauses using '...' and very occasionally a disfluency. [PERSONALITY] You are Cara, a helpful assistant.",
});

页:1: 方法 unsafe_createClientWithApiKey 对生产使用来说是不安全的,因为它需要将您的 api 密钥暴露给客户端。 部署到生产时见 生产用途 先说.

一旦您有 Anam 客户端实例 已关闭, 您可以通过流到 DOM 中的音频和视频元素开始会话 .

await anamClient.streamToVideoElement('video-element-id');

这将使用预配置的人物a id开始一个新的会话,并在 DOM 中以匹配的元素 id 开始流视频元素.

要停止会话使用 stopStreaming 方法.

anamClient.stopStreaming();

生产用途

当部署到生产时,重要的是不要公开曝光您的API密钥. 为避免这个问题, 您应该先将您的 API 密钥交换为服务器侧的短长会话符 。 然后会话符号可以传递给客户端, 并用于 Evolution Anam SDK .

从服务器

const response = await fetch(`https://api.anam.ai/v1/auth/session-token`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${apiKey}`,
  },
  body: JSON.stringify({
    personaConfig: {
      name: 'Cara',
      avatarId: '30fa96d0-26c4-4e55-94a0-517025942e18',
      voiceId: '6bfbe25a-979d-40f3-a92b-5394170af54b',
      llmId: '<LLM ID HERE>',
      systemPrompt:
        "[STYLE] Reply in natural speech without formatting. Add pauses using '...' and very occasionally a disfluency. [PERSONALITY] You are Cara, a helpful assistant.",
    },
  }),
});
const data = await response.json();
const sessionToken = data.sessionToken;

一旦您有会话符号,您就可以使用 createClient 将 Anam SDK 程序用于初始化 Anam 客户端实例.

import { createClient } from '@anam-ai/js-sdk';

const anamClient = createClient('your-session-token');

不论您是否使用 API 密钥或会话符号将客户端曝光同一套可用的流化方法 .

看这里 例如,在生产环境中开始会话的序列图.

聊天流

createTalkMessageStream 直接发送文字给 TTS 供人发言,一次一个块。 溪流中的所有块都有一个相通的ID,这是中断相关联的.

const stream = anamClient.createTalkMessageStream();
for (const chunk of llmChunks) {
  await stream.streamMessageChunk(chunk.text, chunk.isLast);
}

你可以马上开始谈话 streamToVideoElement() 决定。 在信号连接首次打开前发送的块被排出队列,并在完成时发送.

交付失败

对话流块通过会话的信号连接。 在回答心跳的引擎上(见 旧引擎 在下面,SDK检查与心跳的关联, 以及一个块确认块到达后发出的心跳的答案。 SDK 不重新发送块 。 如果一个块不能被发送,因为连接已经下降或停止回答,或者它在大约3秒内没有得到确认,流停止接受块, stream.getState() 返回时 TalkMessageStreamState.DELIVERY_FAILED,客户端会发出 MESSAGE_DELIVERY_FAILED 与流的关联 ID。 SDK自己重新连接;决定如何处理答案由你决定. 一个选择是回到 talk() 全文为:

import { AnamEvent } from '@anam-ai/js-sdk';

interface Answer {
  correlationId: string;
  text: string;
  complete: boolean;
  failed: boolean;
}

// Only the latest answer falls back: once a new one starts, the old one is stale.
let latest: Answer | null = null;

// Register once per client, not once per stream.
anamClient.addListener(AnamEvent.MESSAGE_DELIVERY_FAILED, (failure) => {
  const answer = latest;
  if (!answer || failure.correlationId !== answer.correlationId) return;
  answer.failed = true;
  // If the failure arrives after the answer is complete, speak it now.
  if (answer.complete) anamClient.talk(answer.text).catch(console.error);
});

async function speak(llmChunks: AsyncIterable<{ text: string; isLast: boolean }>) {
  const stream = anamClient.createTalkMessageStream();
  const answer: Answer = {
    correlationId: stream.getCorrelationId(),
    text: '',
    complete: false,
    failed: false,
  };
  latest = answer;
  for await (const chunk of llmChunks) {
    answer.text += chunk.text;
    // A failed or interrupted stream rejects further chunks, so keep collecting the
    // answer instead. This also covers a stale answer, whose failure the listener ignores.
    if (stream.isActive()) await stream.streamMessageChunk(chunk.text, chunk.isLast);
  }
  answer.complete = true;
  if (answer.failed && latest === answer) await anamClient.talk(answer.text);
}

故障意味着发动机没有确认块,而不是它从来没有收到过块. 有些答案可能已经说过了 talk() 复说. 一旦客户收到 TALK_STREAM_INTERRUPTED 对于一溪,它不会发射 MESSAGE_DELIVERY_FAILED 对于它。 连接被关闭时发送的中断可以被错过,不过,因此倒计时仍然可以重复用户中断的答案. 反向也可能发生:引擎可以在客户端重新连接后交付中断,所以 TALK_STREAM_INTERRUPTED 可以在你开始倒计时后到达已经失败的溪流.

结束会话不是执行失败。 之后 stopStreaming(),或者当客户端发出 CONNECTION_CLOSED 因为服务器结束会话或媒体连接失败, 未确认块会丢失 MESSAGE_DELIVERY_FAILED,之后发送的块被丢弃。 处理 CONNECTION_CLOSED 作为每个开口的溪流的尽头。 唯一的例外是信号连接本身就永远关闭:未经证实的块在之前失败了 CONNECTION_CLOSED。 。 。 .

只确认谈话流 。 音频发送通过 createAgentAudioInputStream() 而不是,所以一个停止工作而不关闭的连接 可能会失去它不发生任何事件.

旧引擎

确认块需要一个能回答心跳的引擎. 当会话准备就绪时会这样说的引擎 sendsHeartbeatAcks: true 输入 sessionready 留言。 在更古老的引擎上,SDK在会话准备好后会停止跟踪块并像以前一样发送,在连接重新连接时排队. 还发作 MESSAGE_DELIVERY_FAILED 在三种情况下:

  • 连接关闭后发送块 .
  • 一个块在连接首次打开前被排入队列,它永远不会打开.
  • 在会话准备好之前发送一个块,会话需要3秒多的时间才能准备好. 在此之前,SDK无法从已经停止响应的引擎中分辨出一个更老的引擎,因此它会使流失效并重新连接. 等待时间 AnamEvent.SESSION_READY 在第一个块避免这一点之前.

跨工具呼叫的演讲

当您的应用程序运行工具时, 谈话流可以保持开放 。 在工具之前和之后给出演讲,呼叫单独的发音ids,第二个等待第一个完成播放.

[注] Utterance ids需要一个Cara 4相机. Cara 3相机运行一个更古老的引擎, 静悄悄地丢出字段: 文字仍然被说出 utteranceId。没有错误或警告,所以请检查身份证明是否回来了而不是等待失败.

[大 utteranceId 表示语音的开始,而不是单个文本块。 把它放在第一个块上,然后从该词中的剩余块中省去。 仅在下一个语句开始时设置新的 id .

const stream = anamClient.createTalkMessageStream();

// Utterance A can begin playing while the tool runs.
await stream.streamMessageChunk('Let me check ', false, crypto.randomUUID());
await stream.streamMessageChunk('that for you.', false); // Continues utterance A.

const toolResultText = await runToolCall();

// Utterance B waits for A to finish, then continues with the result.
await stream.streamMessageChunk(toolResultText, true, crypto.randomUUID());

工具必须迅速完成. 服务器关闭一个15秒的谈话流, 却没有收到一个带文字的块, 结束转弯, 并拒绝随后发送到这个关联ID上的任何信息 。 空块不重设计时器 。 对于一个可能跑得更长的工具,让第一句话结束流出,并在结果到来时开始一个新的流出.

同样的命令适用于立即准备好的两种言论。 寄出不同的代号,第二个则等待第一个完成游戏:

const stream = anamClient.createTalkMessageStream();
await stream.streamMessageChunk('First utterance.', false, crypto.randomUUID());
await stream.streamMessageChunk('Second utterance.', true, crypto.randomUUID());

Ids必须是小写 Canonical UUID v4 字符串,这就是什么 crypto.randomUUID() 返回; 其它任何投掷。 他们回来的人 一个消息事件作为 utteranceId,所以你可以匹配自己的身份 与人说话.

司长说明(第4节)

在Cara 4相机上您可以添加 司长 指导阿凡达的表演. 提供内置 presetStyle 或者说 自由形式 customStylePrompt ——两者是相互排斥的(由《联合国宪章》和《联合国宪章》所强化) DirectorNotes ——加可选 expressivity 值,从 0 改为 1,控制样式的表达性(较低值比较稳定;较高值增加样式并一起进行语音驱动运动;省略后使用引擎默认值)。 Director Notes没有被转发到会话脚本创建中,并且只被应用到Cara 4 avatars上;对于更古老的模型,服务器忽略它们,会话在没有它们的情况下进行.

import { unsafe_createClientWithApiKey } from '@anam-ai/js-sdk';

const anamClient = unsafe_createClientWithApiKey('your-api-key', {
  personaId: '<PERSONA ID HERE>',
  name: 'Cara',
  // Use a Cara 4 avatar — Director Notes are ignored on older models.
  avatarId: '30fa96d0-26c4-4e55-94a0-517025942e18',
  voiceId: '6bfbe25a-979d-40f3-a92b-5394170af54b',
  llmId: '<LLM ID HERE>',
  systemPrompt:
    '[STYLE] Reply in natural speech without formatting. [PERSONALITY] You are Cara, a helpful assistant.',
  directorNotes: {
    presetStyle: 'warm',
    expressivity: 0.5,
  },
});

要使用自由形式样式而不是预设,请提供 customStylePrompt数字 :

directorNotes: {
  customStylePrompt:
    'Warm smile, composed, slightly amused, looking directly at camera',
  expressivity: 0.5,
}

您也可以设置 expressivity 曲调如何表达阿凡达的默认风格:

directorNotes: {
  expressivity: 0.2,
}

发送主任 Note 提示会中段

在卡拉4号,你可以使用 sendDirectorNoteCue 以在对话中改变表演。 Cues使用引擎的专用提示路径,因此不会清洗缓冲音频或视频. 数据通道提示主要用于音频通过会话;对于Twitchey会话,偏好在人物语音文本中内置提示标记.

import { AnamEvent, type DirectorNoteCueTag } from '@anam-ai/js-sdk';

let cueChannelOpen = false;
anamClient.addListener(AnamEvent.DATA_CHANNEL_OPEN, () => {
  cueChannelOpen = true;
});
anamClient.addListener(AnamEvent.CONNECTION_CLOSED, () => {
  cueChannelOpen = false;
});

// Call this later from your TTS timing callback for an active persona turn.
function onTtsCue(tag: DirectorNoteCueTag, atSeconds: number) {
  if (!cueChannelOpen) {
    throw new Error('Director Note cue channel is not open');
  }

  anamClient.sendDirectorNoteCue(tag, { atSeconds });
}

// Wire onTtsCue to your TTS provider's cue/word-timing callback. For example,
// report `warm` at 0 seconds and `surprised` at 1.25 seconds for that turn.

在启动流前注册听众, 使其不能错过事件 。 发送前 DATA_CHANNEL_OPEN 而不是悄悄地放弃提示。 发信号时间立即应用提示. inSeconds 是一个从现在开始的延迟,在积极反应,同时 atSeconds 是一个绝对的相抵,从个人的语音开始,在对齐给生成的音频提示时首选;最多提供一个。 运行时提示标记还包括只显示提示的样式,例如 laughter, (中文(简体) ), curious, (中文(简体) ), concerned,以及 surprised 无法作为会话启动的 presetStyle 数值.

版本与发布记录

@anam-ai/js-sdk 共发布 216 个版本,首次发布于 2024/06/12;过去 12 个月发布了 74 个版本。

版本发布日期距今
4.29.1latest2026/10/1919 天前
4.29.02026/10/1424 天前
4.28.02026/10/0930 天前
4.27.12026/09/241 个月前
4.27.02026/09/022 个月前
4.26.02026/08/252 个月前

其他发布通道:rc → 1.7.0-rc.1,alpha → 4.21.0-alpha.0。

关于 @anam-ai/js-sdk 的常见问题

@anam-ai/js-sdk 是什么?

Anam AI 客户端 JavaScript SDK

如何安装 @anam-ai/js-sdk?

在项目目录运行 npm install @anam-ai/js-sdk,或使用 pnpm add / yarn add / bun add。

@anam-ai/js-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@anam-ai/js-sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@anam-ai/js-sdk 可以商用吗?

@anam-ai/js-sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@anam-ai/js-sdk 的下载量有多少?

根据 npm 官方下载统计,@anam-ai/js-sdk 在 2026/10/06 – 2026/11/04 这 30 天内被下载 307,615 次,日均约 10,254 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@anam-ai/js-sdk 还在维护吗?

最新版本 4.29.1 发布于 2026/10/19(19 天前);至今共发布 216 个版本,其中过去 12 个月发布了 74 个;首次发布于 2024/06/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。