资讯详情

资讯详情

Vision Agents 实战:用 Python 构建静默监听式 AI 会议教练(Sales Assistant 示例全解析)

Vision Agents 实战用 Python 构建静默监听式 AI 会议教练Sales Assistant 示例全解析【免费下载链接】Vision-AgentsOpen Vision Agents by Stream. Build voice and vision agents quickly with any model or video provider. Uses Streams edge network for ultra-low latency.项目地址: https://gitcode.com/GitHub_Trending/vi/Vision-Agents本篇技术指南以仓库中 examples/09_sales_assistant_example 的完整示例为主体讲解如何基于 Vision Agents 构建一个AI Meeting Copilot它能在会议、面试和销售通话中静默监听麦克风与系统音频通过 AssemblyAI 完成带说话人分离的实时转写再由 Gemini 生成接下来该说什么的教练建议并同步到 Stream Chat 显示在半透明 macOS 覆盖层上。读完本文你将掌握一个非实时 STT LLM 推理链路的完整搭建方法、Agent HTTP 服务器与会话接口的设计方式以及如何通过系统提示词instructions.md约束 AI 教练的输出风格。示例是什么AI 会议教练Sales Assistant09_sales_assistant_example是一个实时 AI 副驾real-time AI copilot示例在会议、面试、销售通话进行期间它静默监听你的麦克风和系统音频对其他参会者不可见把对话转写成文本并做说话人分离speaker diarization随后分析对话内容在一个半透明 macOS 覆盖层overlay上实时给出教练建议——例如现在该说什么如何过渡到下一个话题。该 agent 可以被扩展以接入 RAG 与自定义知识库从而让建议贴合你自己的产品、公司打法手册playbook或具体交易上下文。也就是说它从一个通用教练变成了懂你业务的专属顾问。说明本示例只涉及Python Agent这一侧即本目录配套的 macOS 覆盖层应用位于独立的 companion 演示仓库中README 中给出了其地址本文按当前仓库约束只展开 Python Agent 侧的实现。系统架构Python Agent macOS 覆盖层项目由两个组件组成分工明确组件位置职责Python Agent本目录examples/09_sales_assistant_exampleVision Agents 后端加入 Stream Video 通话用 AssemblyAI 转写音频带 diarization用 Gemini 分析转录文本并把教练建议文本发回macOS App独立 companion 仓库vision-agents-sales-assistant-demo半透明 macOS 覆盖层通过一个 Stream Video 通话捕获麦克风 系统音频并显示 agent 给出的建议整体运行流程5 步用户打开 macOS 覆盖层点击Start应用创建一个带屏幕共享包含系统音频捕获的 Stream Video 通话应用告知 Python Agent 服务器加入该通话Agent 转写音频AssemblyAI STT diarization并生成教练建议Gemini LLM教练建议以文本形式通过Stream Chat显示在半透明覆盖层上。这种端侧捕获音频 云端 Agent 分析的拆分使得 AI 的加入对通话中的其他参与者完全不可见——他们看不到覆盖层也听不到任何 TTS 声音只会感觉到你突然说得很到位。核心 AI 流水线非实时 STT LLM该示例的关键设计在于使用了一条非实时non-realtimeSTT LLM 流水线与实时语音对话流水线相比更加轻量AssemblyAI STT把会议音频转写为文本并启用说话人分离speaker_labelsTrue。在 AssemblyAI 插件文档 中可以看到启用后每个转录事件会为不同说话人携带独立的participant原始标签存放在response.other[speaker_label]中Gemini LLM分析转录文本生成 1–3 句的简短教练建议示例使用gemini-flash-lite-latest模型见 main.pyStream Chat 同步LLM 响应由 Vision Agents SDK 自动同步到messaging:{callId}频道见 stream_edge_transport.py 中self.client.chat.channel(messaging, call.id)的实现macOS 覆盖层监听该频道并渲染文本无需 TTS因为建议以文本显示而非语音播放整个流水线不需要文本转语音也让 WebRTC 配置保持简单——Agent 只需一个订阅subscriber连接无需发布publisher音频轨道。提示来自官方 README如果希望增加屏幕分析能力可以把gemini.LLM换成gemini.Realtime(fps3)。需要注意Realtime 模式会额外输出音频Agent 除了把建议写入聊天外还会把建议朗读出来。环境与前置条件运行本示例需要满足以下条件macOS 13.0 或更高版本因为覆盖层应用是 macOS 原生应用Python 3.12推荐使用 uvuv 是 Astral 出品的包管理器本示例的pyproject.toml中requires-python 3.12或 pip三组 API KeyStreamVideo API key secret用于通话与 Chat 同步Google AI StudioGemini API key用于 LLM 分析AssemblyAISTT API key用于转写。环境变量清单从 main.py 与插件源码可以确认以下环境变量按需填入.env文件环境变量用途读取位置依据STREAM_API_KEYStream 应用 Key用于创建通话与生成客户端 tokenmain.pySTREAM_API_SECRETStream 应用 SecretSDK 鉴权getstream 插件读取ASSEMBLYAI_API_KEYAssemblyAI STT 鉴权stt.pyGOOGLE_API_KEYGemini LLM 鉴权gemini_llm.py事实提示README 中列出项目结构包含.env.example模板但当前仓库该目录实际只包含README.md、instructions.md、main.py、pyproject.toml四个文件并未随附.env.example。如需模板可参考仓库内其他示例如 examples/04_football_commentator_example/env.example 和 examples/11_moderation_example/env.example或直接按上表变量名自行创建.env文件。快速开始从零启动 coaching server1. Python Agent本仓库# 复制并填写 API Key如仓库无该模板文件请按上文环境变量表手动创建 cp .env.example .env # 用编辑器编辑 .env填入 Stream / Gemini / AssemblyAI 的 key # 安装依赖使用 uv uv sync # 启动 Agent HTTP 服务器 uv run main.py serve服务器默认监听http://localhost:8000。macOS 应用会调用POST /sessions来启动教练会话README 中的简化表述当前 SDK 的完整路由为POST /calls/{call_id}/sessions详见下文HTTP 接口一节。依赖清单定义在 pyproject.toml 中vision-agents核心库 vision-agents-plugins-assemblyai、vision-agents-plugins-getstream、vision-agents-plugins-gemini三个插件以及python-dotenv加载.env和getstreamSDK 客户端。值得注意的是[tool.uv.sources]中将三个依赖都指向了仓库内的../../agents-core与../../plugins/*并以editable true方式安装即直接使用本仓库的源码运行。2. macOS 覆盖层应用配套的 macOS 应用位于独立的 companion 演示仓库中需要按该仓库 README 中的构建与运行说明来执行。该应用预期 Agent 服务器运行在http://localhost:8000所以请先启动 Python Agent。serve 命令的可用参数serve子命令由 Runner CLI 提供见 runner.py支持以下选项参数默认值说明--host127.0.0.1服务器监听地址--port8000服务器端口--agents-log-levelINFOAgent 侧日志级别DEBUG/INFO/WARNING/ERROR/CRITICAL--http-log-levelINFOFastAPI 与 uvicorn 的日志级别--debug关闭开启 asyncio 调试模式--no-splash关闭关闭启动时的 splash 界面使用指南一次完整的教练会话启动 Python Agent 服务器终端 1uv run main.py serve运行 macOS 覆盖层——参见 companion 应用仓库的说明其 README 中描述了构建与运行步骤屏幕右上角出现半透明覆盖层窗口点击Start开始一次教练会话应用将自动共享你的屏幕包含系统音频连接 AI Agent实时显示陆续到达的教练建议点击Stop结束会话。HTTP 接口会话生命周期当uv run main.py serve启动后Agent 通过 Runner 的 HTTP 服务暴露会话接口。当前 SDK 的核心路由定义在 api.pyPOST /calls/{call_id}/sessions启动新 Agent 并让其加入指定通话对应 README 中POST /sessions的完整形态成功返回201与session_id、call_id、session_started_at超出并发或单通话会话上限时返回429DELETE /calls/{call_id}/sessions/{session_id}以及同路径的 POST.../close兼容浏览器 sendBeacon 场景请求关闭会话返回202GET /calls/{call_id}/sessions/{session_id}查询运行中会话的信息GET /calls/{call_id}/sessions/{session_id}/metrics从注册表registry读取会话指标GET /health/GET /ready存活与就绪探针/ready在 launcher 尚未就绪时返回503。这些接口的鉴权行为由ServeOptions控制options.py包括can_start_session、can_close_session、can_view_session、can_view_metrics四个可调用对象默认放行以及 CORS 配置默认允许所有来源与方法。此外本示例还通过runner.fast_api挂载了两个自定义端点见下文源码剖析用于注入会议上下文与签发客户端 token。源码剖析main.py 逐段解读main.py 是示例的全部后端代码只有约 110 行结构非常清晰。1. Agent 定义create_agentasync def create_agent(**kwargs) - Agent: agent Agent( edgegetstream_edge.Edge(), agent_userUser(nameSales Assistant, idsales-assistant-agent), instructionsRead instructions.md, llmgemini.LLM(gemini-flash-lite-latest), sttassemblyai.STT(speaker_labelsTrue), ) return agentedge使用 getstream 插件的Edge()传输层负责 Stream 边缘网络上的音视频连通agent_user定义了 Agent 在 Stream 中的身份instructionsRead instructions.md使用指令语法引用 Markdown 文件作为系统提示词。SDK 的 instructions.py 中用正则([^\s])解析所有提及的.md文件并把文件内容合并进完整提示词忽略以.开头的文件、非 md 文件以及 base 目录外的文件llm使用 Gemini 的 flash-lite 轻量模型sttassemblyai.STT(speaker_labelsTrue)开启说话人分离。AssemblyAI 插件还支持max_speakers1–10 的说话人数量提示需同时开启speaker_labels、speech_model默认u3-rt-pro、sample_rate默认 16000 Hz等参数插件测试 test_assemblyai_stt.py 验证了 speaker labels 的默认关闭与开启行为。注释中特别说明不需要 TTS——Agent 把建议写入 Stream Chat 而非发声这也让 WebRTC 配置保持简单只有 subscriber 连接没有 publisher 音频轨道。2. 加入通话join_callasync def join_call(agent, call_type, call_id, **kwargs) - None: call await agent.create_call(call_type, call_id) async with agent.join(call): prompt ( Listen to the conversation. Provide real-time coaching suggestions — tell the user what to say next. Keep every suggestion to 1-3 sentences. ) if _meeting_context: prompt fMeeting context: {_meeting_context}\n\n{prompt} await agent.simple_response(prompt) await agent.finish()agent.create_call(call_type, call_id)创建通话对象agent.join(call)以上下文管理器方式加入通话进入后即开始教练先拼接一段启动指令倾听对话、给出实时教练建议、告诉用户接下来说什么、每条建议保持 1–3 句如果 macOS 应用预先设置了会议上下文_meeting_context则作为前缀注入 prompt让建议贴合当前会议背景agent.simple_response(prompt)把注入指令交给 LLM。SDK 中 Agent.simple_response 会把请求路由到推理流inference flow与语音驱动的回合共享同一套 LLM/TTS/音频管线participant缺省时归属 Agent 自己interruptTrue时会抢占进行中的 LLM 回合。LLM 的响应会自动同步到messaging:{call_id}频道agent.finish()保持 Agent 存活等待通话结束agents.py此后 STT 轮次检测turn detection会自动触发额外的simple_response调用实现持续的实时建议。3. Runner 与自定义端点runner Runner(AgentLauncher(create_agentcreate_agent, join_calljoin_call))Runnerrunner.py负责以 HTTP 服务器模式运行 AgentAgentLauncheragent_launcher.py负责预热与生命周期管理——确保 LLM、TTS、STT、轮次检测等组件在接收会话前完成初始化这也是/ready探针返回 503 与否的依据。示例额外暴露了两个端点供 macOS 应用使用runner.fast_api.put(/context) async def set_context(request: dict) - JSONResponse: global _meeting_context _meeting_context request.get(context, ) return JSONResponse({ok: True}) runner.fast_api.get(/auth/token) async def create_token(user_id: str Query(...)) - JSONResponse: token _stream_client.create_token(user_id) return JSONResponse({token: token, apiKey: _api_key})PUT /context在会话开始前设置会议上下文如客户公司、谈判要点、本次面试职位上下文会注入到join_call的启动 prompt 中GET /auth/token?user_id...为 Flutter 客户端生成 Stream 用户 token并返回apiKey使客户端能使用与 Agent 相同的 Stream 应用获取凭证。最后runner.cli()把 CLI 入口serve等子命令绑定到脚本使得uv run main.py serve可直接启动服务器。提示词设计instructions.md 系统提示instructions.md 是整个教练人设的灵魂也是被Read instructions.md注入的完整系统提示词角色定义你是 Sales Assistant——一个实时会议与面试教练。你监听用户在实时会议、面试或通话中的麦克风任务是在对话进行中给出简短、可执行的教练建议——告诉用户接下来该说什么。六条行为规则保持简洁每条建议必须 1–3 句话。用户是在对话进行中实时阅读你的建议读不了段落聚焦说什么不要描述你听到了什么也不要复述会议内容——直接给用户能说出口的话主动出击发现有人提问就建议答案察觉犹豫就建议自信的回应冷场时就建议一个过渡话题利用转录音频转录告诉你已说过的话用它保持上下文、避免重复已谈过的要点保持隐身永远不要提到你自己、覆盖层或教练系统把建议写成用户自己的内心声音适应场景无论是求职面试、销售电话、团队站立会还是一对一沟通都要调整教练风格以匹配情境。四条示例建议展示期望的输出形态Say: Thats a great point — we saw a 20% improvement after implementing that change.直接给出可说的话术Mention your experience with distributed systems here.提示应提及的经历Ask them: What does success look like for this role in the first 90 days?建议向对方提出的问题Wrap up this point and transition to the pricing discussion.引导话题过渡这套提示词的设计要点在于输出必须是可直接朗读的短句且绝不能让对方察觉 AI 的存在——这与半透明覆盖层 无 TTS的产品形态是自洽的。扩展方向RAG 与自定义知识库官方 README 明确指出 agent 可以扩展 RAG 与自定义知识库让建议贴合你的产品、公司打法手册或具体交易上下文。仓库内提供了多种 RAG 插件如 qdrant、turbopuffer可参考屏幕分析把gemini.LLM换成gemini.Realtime(fps3)即可让 agent 看到共享屏幕画面例如演示中的演示文稿实现基于画面的实时建议注意 Realtime 模式会同时输出音频agent 会把建议朗读出来替换模型与 STT 提供商Vision Agents 提供了丰富的插件生态openai、anthropic、deepgram、elevenlabs 等 30 插件均在 plugins 目录下可以按预算、时延和语言需求自由组合 LLM 与 STT。项目结构速览examples/09_sales_assistant_example/ ├── main.py # Agent 定义 HTTP 服务器create_agent / join_call / Runner ├── instructions.md # 教练 Agent 的系统提示词 指令引用的 Markdown ├── pyproject.toml # 依赖清单uv 管理指向仓库内源码 └── README.md # 本示例的完整使用文档README 中列出的.env.example模板在当前仓库未随附请按上文环境变量清单自行创建或参考 examples/04_football_commentator_example/env.example 的格式。小结09_sales_assistant_example展示了 Vision Agents 在语音转写 分析 文本回传这一非实时推理链路上的典型用法AssemblyAI 负责带说话人分离的转写Gemini 负责基于转录的实时教练建议Stream 边缘网络负责通话与 Chat 同步main.py以约百行代码将其串成完整的 HTTP 服务。配合精心设计的系统提示词一个对其他参会者完全不可见的 AI 会议教练就此诞生——这也是将 Vision Agents 用于会议副驾、面试陪练、销售陪练等场景的绝佳起点。【免费下载链接】Vision-AgentsOpen Vision Agents by Stream. Build voice and vision agents quickly with any model or video provider. Uses Streams edge network for ultra-low latency.项目地址: https://gitcode.com/GitHub_Trending/vi/Vision-Agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →