Friend 后端子服务内部机制深度解析:Pusher、LLM Gateway、Diarizer、NLLB 翻译与 Serverless GPU 的进程内职责拆解

Friend 后端子服务内部机制深度解析:Pusher、LLM Gateway、Diarizer、NLLB 翻译与 Serverless GPU 的进程内职责拆解 Friend 后端子服务内部机制深度解析Pusher、LLM Gateway、Diarizer、NLLB 翻译与 Serverless GPU 的进程内职责拆解【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/FriendFriendOpenGlass 开源 AI 眼镜配套后端将实时音频流转发、LLM 自动通道、说话人分离、多语言翻译与无服务器 GPU 任务拆分为独立的 Docker 子服务。本文以仓库中的 backend/docs/subservice-internals.md 为主体逐个子服务梳理其进程内的核心职责、关键配置参数、HTTP 端点与可靠性设计并结合作业源码印证底层实现帮助你在部署、排障或二次开发时快速定位这个子服务在自己的进程里到底做了什么。为什么需要子服务内部细节文档Friend 的 Python 后端是一个多进程分布式系统服务间调用关系Service Map与部署/运行时契约统一维护在 backend/AGENTS.md 中而每个子服务在自己的进程内部做什么则收敛到本文对应的 backend/docs/subservice-internals.md两者通过大小限制脚本.github/scripts/check_agents_md_lean.py保持backend/AGENTS.md的瘦身避免单份文档膨胀。从 backend/AGENTS.md 的 Service Map 可以看出完整的调用拓扑backend (main.py) ├── ws ──► pusher (pusher/) ├── ──────► diarizer (diarizer/) ├── ──────► vad (modal/) ├── ──────► parakeet (parakeet/) ├── ──────► modulate (managed API) ├── ──────► deepgram-self-hosted (显式流式策略) ├── ──────► nllb-translation (nllb_translation/) └── ──────► llm-gateway (llm_gateway/main.py) pusher ├── ──────► diarizer (diarizer/) └── ──────► parakeet / modulate (STT)即backend主进程通过二进制 WebSocket 把音频推给pusherpusher负责实时数据分发、转录路由、LLM 对话分析、音频上传与说话人采样提取llm_gateway是 Omi 自管的 LLM 自动通道网关diarizer与nllb_translation分别是 GPU 上的说话人分析与 NLLB 翻译服务modal承载 VAD 等无服务器 GPU 函数及若干 Cloud Run Job。下面逐一展开。Pusher实时数据分发中枢进程内职责清单按 backend/docs/subservice-internals.mdpusher 是一个独立的 Docker 服务单独部署在自己的进程内承担六类任务接收音频与转录文本通过二进制 WebSocket 协议接收来自 backend-listen 的音频与转录结果转发转录到集成/Webhook按 1 秒批次路由转录文本给集成与 Webhook流式转发音频以 4 秒累积窗口把音频流式转发给 ML 服务与开发者 WebhookLLM 对话分析运行由 LLM 驱动的对话分析记忆提取、行动项、洞察音频批量上传以 60 秒批次、最多 3 次重试把音频上传到私有云存储说话人采样排队按 120 秒最小年龄阈值排队说话人样本提取并发上限每个 WebSocket 连接最多 5 个并发后台任务。此外从源码看 pusher 还负责调用 diarizer 与配置的 Parakeet/Modulate STT 服务完成说话人样本提取utils/speaker_identification.py→utils/speaker_sample.py对应 backend/AGENTS.md 中的描述。入口与生命周期pusher/main.pypusher/main.py 是 pusher 的 FastAPI 入口其工程细节值得关注日志分级路由configure_split_stream_logging将 INFO/DEBUG 输出到 stdout、WARNING 输出到 stderr避免 GKE Cloud Logging 把例行请求日志误判为 ERROR 级别对应 issues #9136、#9138、#9135。Firebase 初始化仅在SERVICE_ACCOUNT_JSON存在时用证书初始化否则走默认 ADC。静态能力准入_validate_static_capabilities启动时校验内存写入/读取模式环境变量MemoryRolloutMode.write/read不满足则直接抛错拒绝该 revision 上线——因为conversation.finalize.persisted依赖memory.canonical.mutate能力同时校验流式 STT 环境validate_streaming_stt_env。优雅停机shutdown 时先ReadinessGate.begin_drain()即使 chart 的 preStop 钩子未执行也能先摘除新流量再drain_background_tasks(timeout10.0)排空会话最后close_all_clients()。健康、就绪与内部排空端点GET /healthliveness只要进程存活就返回 200GET /readyreadinessReadinessGate.is_serving()为真返回 200排空中返回 503POST /__internal/drain只接受 loopback 对端request.client.host必须是127.0.0.1/::1依赖 uvicorn 未启用--proxy-headers防止 X-Forwarded-For 伪造供 pod 内 preStop 钩子调用幂等设计与 lifespan shutdown 路径可安全重复触发。启动时还会创建_temp、_samples、_segments、_speech_profiles等目录分别用于临时文件、说话人样本、音频片段与语音画像。LLM GatewayOmi 自管的 LLM 自动通道网关llm_gateway/是内部 FastAPI 服务入口 llm_gateway/main.py为omi:auto:*系列的 chat-completions 通道提供自动选择模型车道能力调用方式由 backend 使用服务级认证调用不直接暴露给客户端公开共享会话聊天只允许使用专用通道omi:auto:public-shared-conversation-chat任何网关故障都直接返回 unavailable其他职责拥有/v1/embeddings接口面以及公司付费的桌面端 Vertex 通道。路由面与中间件从入口源码可见其路由注册llm_gateway/main.pyhealth健康检查openai_compatibleOpenAI 兼容的 chat-completions 通道embeddings向量嵌入接口anthropic_messagesAnthropic Messages 兼容面桌面端聊天使用metricsPrometheus 指标。全局request_correlation中间件为每个请求生成/透传request_idREQUEST_ID_HEADER未处理的异常处理器会把request_id写入响应头保证错误可追踪但不泄露敏感信息。lifespan 关闭阶段会并发执行四类清理accounting 持久化任务排空、图像生成客户端、Anthropic Messages 客户端与 provider registry。配置目录llm_gateway/config/承载网关的车道体系各配置见 backend/llm_gateway/configlanes.yaml车道定义哪些omi:auto:*通道走哪个模型/供应商feature_bundles.yaml功能包组合route_artifacts.yaml路由产物定义cost_rate_cards.yaml成本费率表配合gateway/accounting.py记账generated_route_overrides.yaml生成的路由覆盖项。底层实现上gateway/目录提供配置加载config_loader.py、供应商注册providers.py、请求解析resolver.py、SSE 流式sse.py、Vertex PT 策略vertex_pt_policy.py与 JIT 预算jit_budget.py等模块配合 backend/AGENTS.md 中提到的OMI_LLM_GATEWAY_CONNECT_TIMEOUT_SECONDS默认 3、OMI_LLM_GATEWAY_FIRST_BYTE_TIMEOUT_SECONDS默认 15、OMI_LLM_GATEWAY_CIRCUIT_FAILURE_THRESHOLD默认 2、OMI_LLM_GATEWAY_CIRCUIT_COOLDOWN_SECONDS默认 30等超时/熔断参数完成可选的网关一跳。DiarizerGPU 上的说话人音频分析diarizer/是独立的 GPU/CUDA Docker 服务入口 diarizer/main.py提供三个端点端点用途底层模型POST /v1/diarization说话人边界检测pyannote/speaker-diarizationPOST /v1/embedding说话人向量提取pyannote/embeddingPOST /v2/embedding备选说话人向量wespeaker-voxceleb-resnet34-LM另有GET /health用于存活探测。三个端点均接收UploadFile音频文件并返回 JSONList[Dict]或List[float]实现分布在 backend/diarizer/diarization.py 与 backend/diarizer/embedding.py。调用方包括backend与pusher通过HOSTED_SPEAKER_EMBEDDING_API_URL环境变量定位说话人匹配策略实现在utils/stt/speaker_match.py。v1与v2两代 embedding 接口的存在意味着系统可以在 pyannote 与 Wespeaker 两种说话人向量模型之间切换或并存后者通常作为前者的替代/补充。NLLB Translation自托管多语言翻译nllb_translation/是独立 GPU/CUDA Docker 服务基于NLLB-200distilled 600M CTranslate2做批量句子翻译核心入口 nllb_translation/main.py。端点点位POST /v1/translate批量句子翻译GET /metricsPrometheus 指标GET /health存活返回模型加载状态、模型目录、beam size、compute type、线程数等诊断信息GET /ready就绪模型未加载或 in-flight 已达上限时返回 503摘除出 EndpointsGET /live活跃持续饱和超过NLLB_SATURATED_LIVE_SECONDS时返回 503触发 kube 重启。请求/响应模型// POST /v1/translate { contents: [Hello world, Good morning], target_language_code: zh-CN, source_language_code: en, // 可选缺省时自动检测 request_id: optional-correlation-id } // 响应 { translations: [ { translated_text: 你好世界, detected_language_code: en }, { translated_text: 早上好, detected_language_code: en } ], model: facebook/nllb-200-distilled-600M, latency_ms: 12.3 }contents数组长度受NLLB_MAX_BATCH_SIZE默认 64约束PydanticField(max_length...)。关键配置参数全部来自源码环境变量读取环境变量默认值说明NLLB_MODEL_DIR/models/nllb-200-distilled-600M-ct2-int8CTranslate2 模型目录CT2_DEVICEcuda推理设备CT2_COMPUTE_TYPEint8_float16计算精度CT2_INTER_THREADS1CTranslate2 进程间线程数CT2_INTRA_THREADS4CTranslate2 进程内线程数NLLB_MAX_INPUT_LENGTH512最大输入 token 长度NLLB_MAX_BATCH_SIZE64单请求最大句子数NLLB_BEAM_SIZE1束搜索宽度1 贪心解码追求低延迟NLLB_INFERENCE_WORKERS2推理线程池大小NLLB_MAX_IN_FLIGHTworkers × 2最大并发在飞请求数低于 worker 数会被钳制NLLB_SATURATED_LIVE_SECONDS180持续饱和触发 liveness 失败的时间窗PORT8080服务端口语言代码映射与自动检测服务内置BCP47 → NLLB映射表nllb_translation/main.py覆盖 en、es、zh/zh-CN/zh-Hans→zho_Hans、zh-TW/zh-Hant→zho_Hant、hi、pt、ru、ja、de、ar、fr、it、ko、nl、th、tr、uk、ur、vi 等语种_resolve_nllb_code支持大小写归一化、-拆基如zh-CN→zh、以及反向的 NLLB→BCP47 查询。翻译时若不提供source_language_code则直接以目标语言前缀驱动解码并在结果中回填检测到的源语言。可靠性设计准入控制与饱和处理源码注释揭示了一个真实事故驱动的设计2026-09-03无界队列曾积压到 38k 在飞请求而 pod 仍显示 Ready因为 liveness 只做 TCP 探测。为此实现了三层防护信号量准入asyncio.Semaphore(MAX_IN_FLIGHT)超过上限立即返回 503admission_full而不是排入执行器队列backend 的 listen 侧把 HTTP 500 映射为provider_5xx并回退到 Gemini对应文档所述Fallback to Gemini 2.5 Flash-Lite when NLLB is unavailable饱和就绪摘除/ready在 in-flight 达上限时返回 503让负载均衡不再调度新流量卡死活跃失败/live在持续饱和超过SATURATED_LIVE_SECONDS时返回 503交给 kube 重启。指标观测Prometheus 指标/metrics包括nllb_requests_total按目标语言/状态计数、nllb_translation_latency_seconds、nllb_inference_latency_seconds纯 CTranslate2 推理延迟剔除分词、nllb_tokenization_latency_seconds、nllb_request_queue_duration_seconds、nllb_active_requests、nllb_model_loaded、nllb_batch_size、nllb_model_load_duration_seconds等可用于观测分词 vs 推理 vs 排队三段耗时占比。Modal无服务器 GPU 服务与 Cloud Run Jobsmodal/目录混合承载两类负载Modal 上部署的无服务器 GPU 函数VAD语音活动检测POST /v1/vad基于 pyannote/voice-activity-detection仅由 backend 调用utils/stt/vad.pyCloud Run Jobs定时任务notifications-jobmodal/job.py每小时推送通知 X 平台同步memory-maintenance-jobmodal/memory_maintenance_job.py短时记忆ST→ 长期记忆LT的规范性维护TTL 审计 → 终结性整合/晋升knowledge-ledger-drain-jobmodal/knowledge_ledger_drain_job.py受限的 writer 模式迁移。对应镜像各有独立 DockerfileDockerfile、Dockerfile.daily_memory_sweep_job、Dockerfile.day3_reengagement_email_job、Dockerfile.frame_request_retention_job、Dockerfile.knowledge_ledger_drain_job、Dockerfile.memory_maintenance_job、Dockerfile.notifications_job。记忆维护任务的关键开关是MEMORY_ENABLEDon|off代码默认 off而维护任务本身由独立开关MEMORY_CANONICAL_MAINTENANCE_ENABLED控制环境契约由backend/scripts/validate-backend-runtime-env.py校验调度节奏由 Cloud Scheduler 负责。子服务间的协作要点排障速查音频链路backendutils/pusher.py通过 WebSocket 推音频给 pusher → pusher 按 4s 窗口流式转发给 ML 服务与开发者 webhook、按 60s 批次上传私有云存储3 次重试→ 说话人采样在音频年龄 ≥120s 后排队经 diarizer 提取向量并与语音画像匹配。转录链路pusher 按 1s 批次把转录文本路由到集成/WebhookSTT 由 Parakeet/Modulate 承担HOSTED_PARAKEET_API_URL/MODULATE_API_KEY。翻译链路backend 在HOSTED_TRANSLATION_API_URL设置且选中 NLLB 时调用nllb_translationutils/translation.pyNLLB 不可用时回退 Gemini 2.5 Flash-Lite。LLM 链路backend 以omi:auto:*通道经 llm_gateway 调用 LLM网关故障可按熔断参数回退直连公开共享会话聊天则严格锁定专用通道。并发纪律pusher 每个 WebSocket 连接最多 5 个并发后台任务并使用utils/async_tasks.py的supervise_tasks/drain_tasks/gather_safe管理长连接任务详见 backend/AGENTS.md 的 WebSocket 并发章节。总结Friend 后端把实时分发pusher、LLM 自动通道llm_gateway、说话人分析diarizer、多语言翻译nllb_translation与无服务器 GPU 任务modal拆成职责清晰的独立进程配合 backend/docs/subservice-internals.md 这份进程内职责清单与 backend/AGENTS.md 的 Service Map可以在不改动代码的前提下快速理解每个容器的内部行为、参数语义与故障边界。对希望深入源码的读者建议从 backend/pusher/main.py、backend/llm_gateway/main.py、backend/diarizer/main.py、backend/nllb_translation/main.py 与 backend/modal/main.py 五个入口开始对照本文逐项验证。【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考