作者来自 Elastic Ashish Tiwari一个可运行的演示将 Sarvam AI 语音与 Elastic Agent Builder 相结合身份验证、针对每位客户的 ES|QL 查询以及在通话过程中无需多语言索引即可在 22 种印度语言之间切换。Agent Builder 现已正式发布。立即开始使用Elastic Cloud Trial并查看 Agent Builder 的文档。Mitr 是一个银行语音 agent能够理解印地语、马拉地语、英语以及另外 19 种印度语言并且无需事先告知就能够在一句话中途、一次通话中途自动切换语言。在一次语音交互背后 Sarvam AI 负责转录并翻译来电者的问题ElasticAgent Builder负责验证其身份并查询其私有交易账本随后 Sarvam 使用来电者自己的语言播报答案。整个过程只需五个 HTTP 调用。无需自定义RAG框架。无需多语言索引。该 agent 运行在基于semantic_text与参数化ES|QL的hybrid search之上而这一切都构建于 Elastic Agent Builder。问题以多语言语音方式访问私有银行数据对于许多用户来说访问个人财务信息例如交易记录、工资入账或待退款项一直受到语言障碍的困扰。虽然用户更倾向于使用自己的母语进行交互但大多数银行和金融系统仅支持英语。这就造成了一个明显的鸿沟用户需要查询特定的、私有的财务数据却无法用自己最熟悉的语言自然地完成这一过程。一个真正有效的解决方案必须弥合这一鸿沟使用户无论选择哪种语言都能够通过自然对话安全、实时地访问私有交易数据。再进一步考虑印度所具有的独特情况来电者最熟悉的语言可能是印地语、马拉地语、泰米尔语或者二十多种语言中的任意一种并且可能会在一句话中途切换语言。而能够回答他们问题的数据却存储在使用英语和结构化查询的系统中。此外在你播报哪怕一卢比的余额之前都必须先验证来电者的身份并且绝不能跨越客户边界访问数据。因此一个真正有用的语音 agent 必须同时完成三项困难的任务理解并使用来电者的语言进行回复并且能够跟上他们在通话过程中切换语言。访问每位客户私有且敏感的交易数据即真实的交易账本而不仅仅是常见问题文章。保证安全性在披露任何信息之前验证身份并且将每一次query的范围严格限定为单一客户。我将这一切构建成了一个开源演示“Mitr”在印地语中意为“朋友”面向一家虚构的“Pratham Bank”。其核心场景是日常资金相关问题以及UPI欺诈举报。这是一个绝佳的压力测试因为它迫使上述三项要求同时得到满足并且对于全国各地的用户来说都极具现实意义。什么是 Sarvam AI以及为什么要用于印度语音 agentSarvam AI 是一家印度 AI 公司提供语音转文本speech-to-text、翻译translation以及文本转语音text-to-speechAPI这些能力专门为 22 种印度语言构建。如果你在为印度用户开发产品Sarvam AI 是一个非常值得了解的方案。该公司成立于 2023 年总部位于班加罗尔由 Vivek Raghavan 和 Pratyush Kumar 创立两人都曾参与AI4Bharat。Sarvam 已成为印度 “主权 AI” 推动中的重要公司之一并在 IndiaAI Mission 下被选中为国家构建基础模型。Sarvam 之所以适合这个场景并不只是因为模型本身而是它专门为印度语言打造的语音与语言技术栈并以干净的 REST API 形式提供。我们在这里使用了其中三个能力Saarassaaras:v3覆盖 22 种印度语言加英语的语音转文本并具备自动语言检测能力。这种检测能力是 “随时切换语言” 体验中的关键隐藏能力用户不需要声明语言模型会在每一次语音输入中自动识别。Mayuramayura:v1针对印度语言以及混合语言code-mixed language即人们日常说话中夹杂英语的方式优化的翻译模型。Bulbulbulbul:v3文本转语音系统提供 30 多种自然的印度口音与声音。这三项能力都非常简单只需通过 HTTP 调用即可完成例如 POST /speech-to-text、POST /translate、POST /text-to-speech对接地址为 https://api.sarvam.ai并通过 api-subscription-key 头进行认证。Sarvam 还提供多种集成方式包括 HTTP、WebSocket 和 Batch 处理可以根据不同的技术需求选择最合适的方式。西方的 STT/TTS 技术栈往往把印度语言当作 “附加支持”而 Sarvam 是把它们当作核心场景来设计的。对于面向未来五亿用户的银行语音客服来说这种差异是决定性的。多语言语音 agent 架构如何工作多语言语音 agent 架构如何工作整个系统依赖一个核心设计决策这个决策让其余所有复杂性都得以保持简单来电者始终用自己的语言被听见并被回应而 ElasticSearch 始终使用英语进行查询以通过 agent 获取正确上下文。Sarvam 负责两端的翻译因此数据层和推理层保持语言无关你不需要让索引、工具或 agent prompt 变成多语言版本。不过我们在语义搜索中使用的是 Jina 模型 v5用于 semantic search它支持多语言搜索。下面是一次完整语音交互的端到端流程由一个轻量 FastAPI 后端编排本质上只是按顺序执行五个 HTTP 调用以下是单次语音交互的逐步流程音频输入Audio Input过程从麦克风捕获用户语音开始。语音转文本STT与语言检测音频被发送到 Sarvam AI 的Saarasv3模型。该步骤负责转录语音并自动识别来电者使用的语言。翻译为英语转写结果被传递给 Sarvam 的Mayurav1翻译模型将用户语音转换为英语。这确保推理层保持语言无关。推理与工具执行英文文本被发送到 Elastic Agent Builder 的POST /api/agent_builder/converseendpoint。该 agent 会验证用户身份并通过工具检索信息例如查询交易数据或知识库然后生成回复。翻译回母语与语音合成TTS生成的英文回复会通过 SarvamMayura模型翻译回来电者的原始语言。最后翻译后的文本会发送到 SarvamBulbulv3模型生成自然语音WAV文件并播放给用户。后端Python 应用本身不包含任何业务逻辑。它不会决定调用哪个工具、如何组织回答或者是否验证通过这些全部都在 Elastic Agent Builder 的 agent 内部完成。这种分层是刻意设计的编排层保持极简、无状态每次请求而 “智能大脑” 则在 Elastic 中以声明式方式配置。如何为语音 agent 设计 Elasticsearch 索引结构我们使用三个索引并按照 数据是什么what the data is以及如何查询how its queried进行拆分 —— 而这个拆分方式直接决定了整个 agent 的设计方式。索引数据类型查询方式使用场景bank-support-kb通用知识混合 BM25 语义检索“如何举报欺诈”bank-transactions私有结构化数据参数化 ESQLbank-customers私有结构化数据参数化 ESQL索引 1通用知识语义检索— bank-support-kb贷款利率、费用说明、欺诈处理流程、退款规则以及养老金到账时间等内容 —— 这些都是用户以模糊、多种表达方式提问的知识。我们将其存储为semantic_text因此可以在零embedding代码的情况下实现混合关键词 语义检索。关键技巧是copy_to一个普通文本字段会被镜像到一个semantic_text字段中并绑定到一个inferenceendpoint这样你就可以在同一份内容上同时获得BM25和向量检索能力。{ mappings: { properties: { title: { type: text }, category: { type: keyword }, content: { type: text, copy_to: content_semantic }, content_semantic: { type: semantic_text, inference_id: .jina-embeddings-v5-text-small } } } }Embeddings 在 ingest数据写入阶段由所引用的 inference endpoint 生成例如jina-embeddings-v5-text-small。整个过程中没有 embedding pipeline 需要运行也不需要维护 vector store更不需要处理chunking这种复杂的拼接逻辑。你只需要写入文档然后用自然语言查询Elasticsearch 会自动处理 BM25 向量融合。索引 2 和 3私有数据精确结构化bank-transactions是一个按客户划分的账本工资、EMI、UPI、ATM、退款、养老金等每一条记录都包含金额、渠道、交易对手、状态以及实时余额。bank-customers则保存每个客户的一条档案记录其中包含用于验证的 dob 等信息。这些都是结构化数据必须保证精确性因此使用ES|QL查询并且始终限定在单个customer_id范围内。你不希望用模糊语义去判断一笔 ₹14,999 的扣款是否发生你需要的是确定性、可重复的精确查询。如何为私有数据配置 Elastic Agent Builder 工具Elastic Agent Builder 允许你在不使用独立vector database、不搭建 RAG 框架、也不写复杂编排代码的情况下让 agent 直接基于数据工作。不过在这个场景中我们仍然会显式给 agent 提供工具以确保执行精度。因此你只需要添加工具和一段指令 promptElastic 会负责推理循环、工具调用并流式返回答案。我们的 agent 只有三个工具而它们的划分方式与数据模型完全一致bank_kb_search用于知识库的 index_search 工具针对 “如何举报欺诈” 这类问题的 hybrid retrieval在知识库上执行 BM25 semantic search 的混合检索。customer_profile参数化 ES|QL 工具用于验证 DOB 并检查账户状态。下面是 ES|QL 查询的写法{ id: customer_profile, type: esql, description: ( Fetch ONE customers profile by customer_id, …. ), configuration: { query: ( fFROM {CUST_INDEX} | WHERE customer_id ?customer_id | KEEP customer_id, name, dob, dob_display, mobile_last4, account_last4, city, products, kyc_status, upi_status, account_status | LIMIT 1 ), params: { customer_id: {type: string, description: Authenticated customer id, e.g. CUST1002} }, }, },customer_transactions一个参数化 ES|QL 工具用于资金类问题“我的工资到账了吗”“那笔扣款是什么”。示例交易工具{ id: customer_profile, type: esql, description: ( Fetch ONE customers profile by customer_id, …. ), configuration: { query: ( fFROM {CUST_INDEX} | WHERE customer_id ?customer_id | KEEP customer_id, name, dob, dob_display, mobile_last4, account_last4, city, products, kyc_status, upi_status, account_status | LIMIT 1 ), params: { customer_id: {type: string, description: Authenticated customer id, e.g. CUST1002} }, }, },这些 ES|QL 工具是在设计层面就被“护栏化guardrailed by construction”的LLM 只能控制一个带类型的参数而不能控制查询结构本身。它无法扩大 WHERE 子句无法移除customer_id过滤条件因为它更像一个primary_key也无法访问其他客户的数据行。agent 本身是通过POST /api/agent_builder/agents创建的其中包含定义行为的指令向来电者问候、在披露任何信息之前验证出生日期date of birth、将每次查询都限制在已认证的customer_id范围内并根据意图选择合适工具查询交易用 transactions回答 “如何举报欺诈” 用 KB。因为这些逻辑都存在于 Kibana 中而不是后端服务里所以要修改 agent 的人格或规则只需要编辑这些 instructions 并重新运行创建脚本即可。运行中的服务器本身不会改变改变的是 agent 的定义。你也可以在 Kibana - Agents 中直接修改这些指令。如何调用 Elastic Agent Builder 的 converse API在运行时后端不会直接与 LLM 或索引交互。它只会将一个英文问题发送到 Agent Builder 的流式 converse endpoint然后由 Elastic 负责编排工具调用与模型推理POST {KIBANA_URL}/api/agent_builder/converse/async Authorization: ApiKey key kbn-xsrf: true { agent_id: pratham-bank-support-agent, input: [AUTHENTICATED CALLER customer_idCUST1002, namePriya ...] Customer says: why was money debited?, conversation_id: persisted per call, inference_id: groq-1 }开发者需要重点注意的三点可信上下文而不是 LLM 可以伪造的工具。已认证的customer_id由后端作为可信上下文注入到 agent 输入中。模型只是使用它来填充 ES|QL 参数但它从不 “选择” 这个值因此用户无法通过对话诱导系统访问其他账户。跨轮次的身份保持。后端为每个来电者维护一个conversation_id。一旦 agent 在第一轮验证了来电者的 DOB这个验证状态会在整个通话过程中持续生效无需重复询问。出于演示目的我们这里只加入了 DOB 验证但可以扩展为更多验证参数。可插拔的推理 LLM。converse 请求体中的inference_id字段由AGENT_INFERENCE_ID环境变量设置用于选择 agent 推理所使用的 chat-completion endpoint如果留空则使用 Agent Builder 默认模型。关键点是这与semantic_text字段上的 embeddinginference_id是完全不同的概念。一个用于生成文档 embedding一个用于进行推理。响应采用 Server-Sent EventsSSE流式返回最终答案出现在message_complete事件的message_content字段中。也建议显式处理 error 事件否则工具调用失败时可能会静默退化为空回答。实际运行效果展示https://www.bilibili.com/video/BV1fgTa63Es4/在这个 demo 中用户一开始用英语发起对话随后用印地语提供出生日期date of birth再用印地语询问 “home loan EMI debited?”房贷 EMI 是否被扣款之后又切换到马拉地语继续整个对话。在这一次交互背后agent 验证了他的 DOB并通过 ES|QL 工具确认了他的房贷状态以及 Flipkart 退款情况。还有另一个 demo 场景“未经授权扣款Money debited without consent”在这个场景中agent 会建议用户拨打印度 1930 网络犯罪热线并通过语义知识库semantic knowledge base进行 UPI ID 冻结与处理建议。两个工具、三种语言、一次对话。在同一个 agent 中看到它在通话中平滑切换语言是 Sarvam Elastic 组合真正“成立”的时刻。将多语言语音 agent 推向生产环境这是一个 demo。所有数据都是合成的“Pratham Bank” 是虚构的。但走向生产环境的路径主要是 “加固hardening”而不是重新设计。在真实部署中你需要做的是使用Elasticsearch document-level security / RBAC基于已认证用户进行每个用户的访问控制而不是信任传入的customer_id在浏览器麦克风之前增加真实的身份认证与电话系统或 WebRTC 层将密钥存储在托管的 secrets 管理系统中而不是.env文件。但核心不会改变semantic_text 参数化 ES|QL 的分层设计、先验证再查询的身份流程以及严格的查询契约。自行运行整个系统是一个 Docker 工作流清理、初始化索引与数据导入、构建 agent、启动服务通过.env文件注入 Elastic 和 Sarvam 的凭证即可运行。准备一个启用 Agent Builder的 Elastic 部署并配置一个text-embedding inference endpoint再添加 Sarvam API key几分钟内就可以和 Mitr 对话。完整代码、配置和 demo 在这个 repo 中。关键总结让每个平台发挥各自优势。Sarvam 负责语音与印度语言Elastic Agent Builder 负责数据推理两者之间只用一个轻量编排层连接。“用用户语言回答”是一条单行契约它让多语言系统保持可维护性索引、工具和 prompt 都不需要多语言化。semantic_text 参数化 ES|QL 工具覆盖了智能体的两大核心能力语义理解 精确私有数据无需额外基础设施。先验证身份始终做作用域隔离。身份验证和 per-customer 限制必须在工具层实现而不是依赖模型判断这是 demo 和生产系统的关键分界线。Demo 中所有数据均为合成“Pratham Bank”为虚构。基于 Elastic Agent Builder Sarvam AI 构建。原文Mitr: multilingual banking voice agent with Sarvam AI - Elasticsearch Labs