Hermes

端云协同的AI Agent硬件助手架构方案 #

“在非洲,一个好的助手不是在云端有多聪明,而是在断网时还能帮你拨通电话。”

一、引言 #

传音作为"非洲手机之王",其硬件助手产品(如os语音助手)正面临从指令式语音助手自主AI Agent的范式升级。与硅谷的AI助手不同,传音的AI Agent必须面对三个独特约束:

  1. 网络环境恶劣:非洲部分地区3G仍为主流,断网是常态而非异常
  2. 设备资源受限:中低端机型内存1-2GB、存储16-32GB、无NPU或低端NPU
  3. 多语言碎片化:豪萨语、斯瓦西里语、阿姆哈拉语等小语种离线支持

本文提出端-云-第三方三层架构,核心设计原则是:端侧保可用、云侧提供智能、第三方扩展生态


二、总体架构设计 #

2.1 三层架构总览 #

graph TB
    subgraph "📱 端侧 Edge Layer(设备本体)"
        VAD[VAD唤醒]
        SLM[轻量SLM推理]
        LOCAL_MEM[(本地记忆)]
        LOCAL_TOOL[本地工具执行]
        SYNC[端云同步引擎]
    end
    
    subgraph "☁️ 云侧 Cloud Layer(传音AI平台)"
        AGENT_CORE[Agent核心引擎]
        MEMORY[(云端Memory)]
        RAG[(RAG检索引擎)]
        TOOL_REG[(工具注册中心)]
        DIALOGUE[对话管理DM]
        MONITOR[可观测性]
    end
    
    subgraph "🌐 第三方 Third-Party Layer"
        OAUTH[OAuth鉴权网关]
        MARKETPLACE[技能市场]
        EXT_API[第三方API]
        AUDIT[审计与计量]
    end
    
    SYNC <--> AGENT_CORE
    VAD --> SLM --> LOCAL_TOOL
    SLM -.置信度高.-> LOCAL_TOOL
    SLM -.需云端智能.-> SYNC
    AGENT_CORE --> MEMORY
    AGENT_CORE --> RAG
    AGENT_CORE --> TOOL_REG
    TOOL_REG --> OAUTH
    OAUTH --> MARKETPLACE --> EXT_API
    EXT_API --> AUDIT
    SYNC -.断网降级.-> LOCAL_MEM

2.2 架构原则 #

原则 设计含义 传音场景意义
隐私优先 个人数据默认端侧处理,仅脱敏摘要上云 非洲POPIA/NDPR合规要求
延迟分层 简单操作本地响应<100ms,复杂请求云端处理 弱网环境下用户体验保障
弹性降级 云端不可用时端侧自主运行核心功能 非洲断网场景兜底
开放扩展 第三方API通过标准协议接入,沙箱隔离执行 生态构建与商业化

2.3 端云职责边界 #

┌─────────────────────────────────────────────────────────────────┐
│                        端云职责矩阵                              │
├────────────────┬───────────────────┬────────────────────────────┤
│     能力       │     端侧           │     云端                    │
├────────────────┼───────────────────┼────────────────────────────┤
│ 语音唤醒        │ 关键词唤醒 (Always On)│ 自定义唤醒词训练          │
│ 语音识别        │ 离线ASR (5种核心语言) │ 在线ASR (全量语言+口音)    │
│ 意图理解        │ 规则+轻量SLM (Top 20意图)│ LLM全量意图理解          │
│ 本地控制        │ 直接执行 (拨号/设置/闹钟) │ 无                       │
│ 知识问答        │ 本地知识库 (FAQ)     │ RAG + LLM 全量知识        │
│ 工具调用        │ 本地API (通讯录/相机)   │ 第三方API (天气/外卖/打车) │
│ 多轮对话        │ 上下文窗口<5轮        │ 无限轮次 + Memory检索      │
│ 个性化记忆      │ 最近7天摘要          │ 全量用户画像 + 长期记忆    │
└────────────────┴───────────────────┴────────────────────────────┘

三、端侧(Edge Layer)设计 #

3.1 端侧能力边界与模型选型 #

端侧是"可用性的最后防线",必须在有限资源下保证核心功能。

端侧模型量化对比:

模型 参数量 量化后大小 首Token延迟 适用场景
Qwen2.5-0.5B 0.5B 350MB (INT4) ~200ms 意图分类、简单问答
Gemma-2-2B 2B 1.2GB (INT4) ~800ms 复杂理解、多轮对话
Whisper-Tiny 39M 75MB (FP16) ~50ms 离线语音识别
自研SLM-300M 300M 180MB (INT4) ~120ms 本地意图路由

推荐方案:采用自研300M SLM作为端侧路由核心,配合Whisper-Tiny做离线ASR,整体端侧模型包控制在500MB以内,适配低端机型。

3.2 端侧推理管线 #

graph LR
    MIC[麦克风输入] --> VAD[VAD检测]
    VAD -->|语音片段| ASR[离线ASR]
    ASR -->|文本| ROUTER[意图路由器 SLM]
    
    ROUTER -->|置信度>0.8| LOCAL[本地执行]
    ROUTER -->|置信度<0.8| CLOUD[上传云端]
    ROUTER -->|网络不可用| FALLBACK[本地兜底]
    
    LOCAL --> RESP[端侧响应]
    CLOUD --> SYNC[端云同步]
    FALLBACK --> RESP
    
    SYNC -->|云端响应| RESP
    RESP --> TTS[本地/云端TTS]
    TTS --> SPK[扬声器输出]

端侧意图路由器实现:

// IntentRouter - 端侧轻量意图分类与路由决策
type IntentRouter struct {
    model    *SLM           // 端侧小模型
    rules    *RuleEngine    // 规则引擎兜底
    config   *RouterConfig  // 路由阈值配置
}

func (r *IntentRouter) Route(text string) *RouteDecision {
    // 1. 规则优先(高确定性意图直接匹配,零推理成本)
    if ruleMatch := r.rules.Match(text); ruleMatch != nil {
        if ruleMatch.Confidence > 0.95 {
            return &RouteDecision{
                Target:  ExecutionTargetLocal,
                Action:  ruleMatch.Action,
                Reason:  "rule_match",
            }
        }
    }
    
    // 2. SLM推理(0.3B参数,INT4量化,内存占用~180MB)
    result := r.model.Predict(text)
    
    // 3. 路由决策
    if result.Confidence >= r.config.LocalThreshold {
        // 高置信度:本地执行
        return &RouteDecision{
            Target:  ExecutionTargetLocal,
            Action:  result.Action,
            Reason:  "slm_high_confidence",
        }
    } else if result.Confidence >= r.config.CloudThreshold {
        // 中等置信度:需要云端增强
        return &RouteDecision{
            Target:  ExecutionTargetCloud,
            Action:  result.Action,
            Reason:  "slm_medium_confidence",
        }
    } else if r.isNetworkAvailable() {
        // 低置信度:云端LLM处理
        return &RouteDecision{
            Target:  ExecutionTargetCloud,
            Action:  "general_query",
            Reason:  "slm_low_confidence",
        }
    } else {
        // 网络不可用:端侧兜底
        return &RouteDecision{
            Target:  ExecutionTargetFallback,
            Action:  "fallback_response",
            Reason:  "no_network",
        }
    }
}

3.3 端云协同策略 #

何时本地?何时上云?

class EdgeCloudPolicy:
    """端云协同策略引擎"""
    
    def decide(self, intent: Intent, context: Context) -> ExecutionTarget:
        # 规则1:隐私敏感操作优先本地
        if intent.category in [PRIVACY_LOCAL_EXECUTION]:
            return LOCAL
        
        # 规则2:网络状态评估
        network_quality = self.measure_network()
        if network_quality < THRESHOLD_POOR:
            return LOCAL_FALLBACK  # 弱网强制本地
        
        # 规则3:延迟预算评估
        estimated_cloud_latency = (
            self.rtt_to_cloud() + 
            self.estimate_cloud_processing(intent)
        )
        if estimated_cloud_latency > intent.max_acceptable_latency:
            return LOCAL  # 云端太慢,降级本地
        
        # 规则4:能力匹配
        if not self.local_model.can_handle(intent):
            return CLOUD  # 端侧模型不支持
        
        # 规则5:成本权衡(云侧LLM调用成本 vs 本地推理电量消耗)
        if self.should_save_cloud_quota(intent):
            return LOCAL  # 节省云端配额
        
        return CLOUD  # 默认走云端

四、云侧(Cloud Layer)设计 #

4.1 云端Agent核心引擎 #

云端是智能的"大脑",负责复杂推理、Memory管理、Tool编排。

graph TB
    subgraph "Agent核心"
        PLANNER[任务规划器]
        MEMORY_MGR[Memory管理器]
        TOOL_ORCH[工具编排器]
        RESPONSE_GEN[响应生成器]
    end
    
    subgraph "支撑服务"
        LLM[LLM推理服务]
        VECTOR_DB[(向量数据库)]
        TOOL_REG[(工具注册中心)]
        DIALOGUE_STATE[(对话状态存储)]
    end
    
    USER_REQUEST --> PLANNER
    PLANNER --> MEMORY_MGR
    MEMORY_MGR --> VECTOR_DB
    PLANNER --> TOOL_ORCH
    TOOL_ORCH --> TOOL_REG
    TOOL_REG --> LLM
    PLANNER --> RESPONSE_GEN
    RESPONSE_GEN --> LLM
    LLM --> RESPONSE_GEN
    RESPONSE_GEN --> USER_RESPONSE
    PLANNER -.写入.-> DIALOGUE_STATE

Agent执行流程(ReAct模式):

class CloudAgent:
    """云端AI Agent核心"""
    
    async def execute(self, request: AgentRequest) -> AgentResponse:
        # 1. 加载对话上下文
        context = await self.memory.load_context(request.session_id)
        
        # 2. 检索相关记忆
        memories = await self.memory.retrieve(request.query, top_k=5)
        
        # 3. 任务规划(LLM生成行动计划)
        plan = await self.planner.generate(
            query=request.query,
            context=context,
            memories=memories
        )
        
        # 4. 工具编排执行
        results = []
        for step in plan.steps:
            if step.requires_tool:
                tool_result = await self.tool_orchestrator.execute(step)
                results.append(tool_result)
        
        # 5. 响应生成
        response = await self.response_generator.generate(
            plan=plan,
            results=results,
            context=context
        )
        
        # 6. 更新Memory
        await self.memory.store(
            session_id=request.session_id,
            interaction=request.query,
            response=response.text,
            metadata={"tools_used": [t.name for t in results]}
        )
        
        return response

4.2 多设备协同与记忆同步 #

传音用户通常拥有多台设备(手机+手表+电视),Agent需要跨设备协同。

┌─────────────────────────────────────────────────────────────┐
│                   跨设备记忆同步架构                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Phone ────┐                                               │
│             │  端侧摘要 ──► 云端Memory ──► 广播增量更新       │
│   Watch ────┤                    │                          │
│             │                    ▼                          │
│   TV    ────┘              ┌──────────────┐                 │
│                            │ Conflict     │                 │
│                            │ Resolver     │                 │
│                            └──────────────┘                 │
│                                   │                         │
│                                   ▼                         │
│                          ┌──────────────┐                   │
│                          │ 统一用户画像  │                   │
│                          └──────────────┘                   │
└─────────────────────────────────────────────────────────────┘

冲突解决策略:

// MemorySyncResolver - 处理多设备记忆冲突
type MemorySyncResolver struct {
    store *MemoryStore
}

func (r *MemorySyncResolver) Resolve(conflicts []MemoryEntry) MemoryEntry {
    // 策略1:时间戳优先(最新覆盖)
    latest := conflicts[0]
    for _, entry := range conflicts[1:] {
        if entry.UpdatedAt.After(latest.UpdatedAt) {
            latest = entry
        }
    }
    
    // 策略2:设备权重(手机 > 手表 > TV)
    // 同时间戳时,高优先级设备的数据更可信
    if r.hasTie(conflicts) {
        return r.resolveByDevicePriority(conflicts)
    }
    
    return latest
}

4.3 智能体技能市场(插件体系) #

# 技能注册表(云端维护)
skills:
  - skill_id: "weather_query"
    name: "天气查询"
    provider: "third_party:openweathermap"
    endpoint: "https://api.openweathermap.org/data/2.5/weather"
    auth_type: "api_key"
    description: "查询全球城市实时天气"
    capabilities: ["current", "forecast"]
    languages: ["en", "fr", "ha", "sw", "am"]
    rate_limit: 100/minute
    latency_p99: "500ms"
    
  - skill_id: "local_taxi"
    name: "本地打车"
    provider: "third_party:bolt_africa"
    endpoint: "https://api.bolt.eu/v1/ride"
    auth_type: "oauth2"
    description: "非洲本地打车服务"
    capabilities: ["estimate", "book", "track"]
    regions: ["ng", "ke", "za", "eg"]
    rate_limit: 50/minute

五、第三方API(Third-Party Layer)设计 #

5.1 开放平台接入架构 #

第三方API是Agent能力扩展的关键,必须通过标准化协议接入。

graph LR
    AGENT[Agent引擎] --> GATEWAY[API网关]
    GATEWAY --> AUTH[OAuth鉴权]
    AUTH --> RATE[限流熔断]
    RATE --> SANDBOX[执行沙箱]
    SANDBOX --> EXT[第三方API]
    EXT --> MONITOR[调用审计]
    MONITOR --> BILL[计量计费]
    
    SANDBOX -.超时.-> FALLBACK[降级响应]
    SANDBOX -.异常.-> CIRCUIT[熔断器]

5.2 第三方服务治理 #

class ThirdPartyGateway:
    """第三方API网关 - 安全、可控、可观测"""
    
    def __init__(self, config: GatewayConfig):
        self.circuit_breaker = CircuitBreaker(
            failure_threshold=5,
            recovery_timeout=60  # 60秒后尝试恢复
        )
        self.timeout = config.timeout  # 默认3秒超时
        self.retry_policy = RetryPolicy(max_retries=1)
    
    async def call(self, skill_id: str, params: dict) -> ToolResult:
        # 1. 查找技能配置
        skill = self.skill_registry.get(skill_id)
        
        # 2. 鉴权注入
        auth_header = await self.auth_manager.get_token(skill)
        
        # 3. 熔断器检查
        if self.circuit_breaker.is_open(skill_id):
            return self.fallback_response(skill_id)
        
        try:
            # 4. 带超时的HTTP调用
            response = await self.http_client.post(
                url=skill.endpoint,
                json=params,
                headers={"Authorization": auth_header},
                timeout=self.timeout
            )
            
            # 5. 结果校验
            if response.status_code != 200:
                raise APIError(f"HTTP {response.status_code}")
            
            # 6. 审计记录
            await self.audit.record(skill_id, response)
            
            return ToolResult(data=response.json(), success=True)
            
        except TimeoutError:
            self.circuit_breaker.record_failure(skill_id)
            return self.fallback_response(skill_id)
        except APIError as e:
            self.circuit_breaker.record_failure(skill_id)
            return ToolResult(error=str(e), success=False)

5.3 安全沙箱与数据脱敏 #

第三方API调用必须经过严格的安全审查:

// DataSanitizer -  outgoing数据脱敏
func SanitizeForThirdParty(data map[string]interface{}, policy *PrivacyPolicy) map[string]interface {
    sanitized := make(map[string]interface{})
    
    for key, value := range data {
        if policy.IsSensitive(key) {
            // 脱敏处理
            switch policy.GetMaskType(key) {
            case MASK_HASH:
                sanitized[key] = sha256Hash(value)
            case MASK_REDACT:
                sanitized[key] = "[REDACTED]"
            case MASK_PARTIAL:
                sanitized[key] = partialMask(value)
            }
        } else {
            sanitized[key] = value
        }
    }
    
    return sanitized
}

六、云端/第三方API不可用应对方案 #

“在非洲,API的不可用不是异常,而是常态。好的架构不是假设一切正常,而是假设一切都会失败。”

在端云协同架构中,云端API和第三方服务的不可用是最关键的系统性风险。本节从检测、隔离、降级、恢复四个维度构建完整的容错体系。

6.1 故障场景分类与影响矩阵 #

故障场景 典型表现 影响范围 用户感知 应对级别
云端LLM服务宕机 502/503、超时 复杂推理、知识问答 回答变简单或拒绝 🔴 P0
云端Memory服务不可用 向量库连接失败 个性化、多轮对话 遗忘用户偏好 🟡 P1
第三方API限流/超时 429、5xx、高延迟 天气/打车/外卖等技能 部分功能不可用 🟡 P1
第三方OAuth失效 401 Unauthorized 需要授权的技能 提示重新登录 🟢 P2
区域网络中断 DNS失败、连接超时 所有云端能力 整体降级到端侧 🔴 P0
CDN/边缘节点故障 模型包下载失败 OTA更新、语言包 无法获取新能力 🟢 P2

6.2 云端API不可用应对策略 #

6.2.1 多层健康检测 #

graph LR
    A[主动探测] -->|每30s心跳| B[健康状态]
    C[被动监控] -->|请求失败率| B
    D[端侧探针] -->|多端RTT统计| B
    B -->|状态变化| E[降级管理器]
    E -->|触发| F[切换降级层级]

多维度健康判定:

class CloudHealthMonitor:
    """云端服务健康度评估"""
    
    def __init__(self):
        self.active_probe_interval = 30  # 主动探测间隔(秒)
        self.failure_window = 10         # 滑动窗口大小
        self.failure_threshold = 0.4     # 失败率阈值
        
    async def evaluate(self, session_id: str) -> ServiceHealth:
        # 1. 主动探测(轻量心跳请求)
        active = await self.probe_health_check()
        
        # 2. 被动监控(近期请求失败率)
        recent_failures = self.get_failure_rate(window=self.failure_window)
        
        # 3. 端侧探针(多设备RTT统计)
        edge_rtt = await self.aggregate_edge_probes()
        
        # 4. 综合判定
        if active.status != 200 or recent_failures > self.failure_threshold:
            return ServiceHealth(
                status=UNHEALTHY,
                reason=f"active={active.status}, failure_rate={recent_failures:.2f}",
                suggested_level=self.compute_degradation_level()
            )
        
        return ServiceHealth(status=HEALTHY, rtt=edge_rtt.median)

6.2.2 云端API降级路径 #

云端LLM不可用时的降级路径:
┌─────────────────────────────────────────────────────────────────┐
│ L0: 云端完整LLM (GPT-4级别)                                      │
│    ↓ 不可用                                                      │
│ L1: 云端备用模型 (同一平台的不同模型/不同区域)                      │
│    ↓ 不可用                                                      │
│ L2: 云端轻量模型 (同一平台的小模型,成本更低但更稳定)               │
│    ↓ 不可用                                                      │
│ L3: 端侧SLM (300M INT4量化)                                      │
│    ↓ 不可用/置信度低                                              │
│ L4: 端侧规则引擎 (预置意图模板 + 关键词匹配)                       │
│    ↓ 不可用                                                      │
│ L5: 预置回复库 (常见问题的标准话术)                                │
└─────────────────────────────────────────────────────────────────┘

云端多活与备用路由:

class CloudRouter:
    """云端服务路由与故障切换"""
    
    def __init__(self):
        self.providers = [
            Provider(name="primary",   endpoint="api.transsion.com/v1",  priority=1),
            Provider(name="fallback-1", endpoint="api-backup.transsion.com/v1", priority=2),
            Provider(name="fallback-2", endpoint="api-edge.transsion.com/v1", priority=3),
        ]
        self.circuit_breakers = {p.name: CircuitBreaker() for p in self.providers}
    
    async def route(self, request: AgentRequest) -> AgentResponse:
        # 按优先级尝试可用provider
        for provider in sorted(self.providers, key=lambda p: p.priority):
            cb = self.circuit_breakers[provider.name]
            
            if cb.state == OPEN:
                continue  # 熔断中,跳过
            
            try:
                response = await self.call_provider(provider, request)
                cb.record_success()
                return response
            except Exception as e:
                cb.record_failure()
                logger.warning(f"Provider {provider.name} failed: {e}")
                continue
        
        # 所有云端provider均不可用 → 降级到端侧
        return self.trigger_edge_fallback(request)

6.3 第三方API不可用应对策略 #

6.3.1 多供应商冗余 #

对于关键第三方服务(天气、地图、翻译等),应接入多个供应商,自动切换:

# 第三方服务多供应商配置
services:
  weather:
    primary:
      provider: "openweathermap"
      endpoint: "https://api.openweathermap.org/data/2.5/weather"
      rate_limit: 100/min
      cost_tier: "free"
    backup:
      - provider: "weatherapi"
        endpoint: "https://api.weatherapi.com/v1/current.json"
        rate_limit: 1000000/month
        cost_tier: "paid"
      - provider: "accuweather"
        endpoint: "https://dataservice.accuweather.com/currentconditions"
        cost_tier: "paid"
      
  translation:
    primary:
      provider: "google_translate"
    backup:
      - provider: "deepl"
      - provider: "local_model"  # 端侧轻量翻译模型
      
  maps:
    primary:
      provider: "google_maps"
    backup:
      - provider: "mapbox"
      - provider: "osm_local"  # 离线OpenStreetMap数据

供应商自动切换逻辑:

class ThirdPartyMultiProvider:
    """第三方服务多供应商路由"""
    
    async def call(self, service: str, **params) -> ServiceResult:
        config = self.service_config[service]
        providers = [config.primary] + config.backup
        
        for provider in providers:
            health = self.health_checker.check(provider)
            if health != HEALTHY:
                continue
                
            try:
                result = await self.invoke(provider, params)
                # 记录成功,更新provider优先级(成功的排前面)
                self.promote_provider(service, provider)
                return result
            except (TimeoutError, APIError) as e:
                self.demote_provider(service, provider)
                logger.warning(f"Provider {provider.name} failed: {e}")
                continue
        
        # 所有供应商均不可用 → 使用缓存或兜底回复
        return self.fallback_for_service(service, params)

6.3.2 智能缓存与预取 #

缓存策略矩阵:
┌──────────────┬──────────┬───────────┬────────────────────────────┐
│ 数据类型      │ TTL       │ 过期策略   │ 非洲场景优化               │
├──────────────┼──────────┼───────────┼────────────────────────────┤
│ 天气数据      │ 30分钟   │ Stale-while-revalidate │ 提前缓存当日预报    │
│ 翻译结果      │ 永久     │ 内容哈希不变即有效      │ 常用短语预缓存      │
│ 地图路线      │ 10分钟   │ 距离过期              │ 离线地图包常驻      │
│ 新闻/资讯     │ 1小时    │ LRU淘汰               │ WiFi时预下载        │
│ 用户偏好      │ 永久     │ 增量更新               │ 端侧持久化          │
│ 商品/价格     │ 5分钟    │ 严格一致              │ 不可缓存,需实时     │
└──────────────┴──────────┴───────────┴────────────────────────────┘
class SmartCache:
    """智能缓存 - 支持预取、过期降级、staleness容忍"""
    
    async def get(self, key: str, service: str) -> CacheResult:
        cached = self.store.get(key)
        
        if cached and not cached.expired:
            return CacheResult(data=cached.value, source="cache_fresh")
        
        if cached and cached.stale_while_revalidate:
            # 返回过期数据,后台异步刷新
            asyncio.create_task(self.refresh(key, service))
            return CacheResult(data=cached.value, source="cache_stale")
        
        # 缓存未命中,尝试同步获取
        try:
            fresh = await self.fetch_and_cache(key, service)
            return CacheResult(data=fresh, source="live")
        except Exception:
            # 即使过期缓存也优于无响应
            if cached:
                return CacheResult(data=cached.value, source="cache_expired_fallback")
            raise ServiceUnavailable(f"No cached data for {key}")
    
    async def prefetch(self, predictions: List[PrefetchHint]):
        """WiFi连接时预取可能需要的数据"""
        if self.is_wifi_connected() and self.is_charging():
            for hint in predictions:
                await self.fetch_and_cache(hint.key, hint.service)

6.3.3 降级回复生成 #

当第三方API完全不可用且无缓存时,生成体面的降级回复:

class GracefulFallback:
    """优雅降级回复生成"""
    
    FALLBACK_TEMPLATES = {
        "weather": {
            "offline": "目前无法获取实时天气数据。建议您查看手机天气组件,或稍后网络恢复时再问我。",
            "partial": "我能查到{city}的历史平均气温约{temp}°C,但实时数据暂不可用。",
        },
        "taxi": {
            "offline": "打车服务暂时不可用。您可以直接打开Bolt/Uber应用叫车。",
        },
        "translation": {
            "offline": "离线翻译引擎已启动(准确率约85%)。如需更精准的翻译,请连接网络。",
        },
        "general": {
            "offline": "这个功能需要联网才能使用。我现在可以帮您做这些本地操作:{local_capabilities}",
        },
    }
    
    def generate(self, service: str, context: dict, network_state: str) -> str:
        templates = self.FALLBACK_TEMPLATES.get(service, self.FALLBACK_TEMPLATES["general"])
        template = templates.get(network_state, templates.get("offline"))
        
        # 填充模板变量
        return template.format(**context)

6.4 端侧兜底能力清单 #

当所有云端和第三方API都不可用时,端侧必须能独立完成的核心功能:

端侧兜底能力清单(断网可用):
├── 📞 通信类
│   ├── 拨打电话 / 发送短信 / 查询通话记录
│   ├── 读取/编辑通讯录
│   └── 读取未读消息
├── 📱 设备控制类
│   ├── 调节音量/亮度/WiFi/蓝牙
│   ├── 打开/关闭应用
│   ├── 设置闹钟/定时器/提醒
│   └── 音乐播放控制(本地媒体)
├── 📝 个人助理类
│   ├── 创建/查询/编辑备忘录
│   ├── 本地日历查询
│   └── 计算器/单位换算
├── 🌍 离线知识类
│   ├── 预置FAQ问答(500+条目)
│   ├── 离线翻译(核心语言对,准确率~85%)
│   └── 离线地图导航(已下载区域)
└── 💬 对话兜底类
    ├── "我不知道,但网络恢复后我会记住这个问题"
    ├── "这个问题需要联网,目前可以做的是:..."
    └── 记录用户问题,网络恢复后异步查询并推送

6.5 故障恢复与自愈 #

graph TB
    DETECT[故障检测] --> ISOLATE[隔离故障服务]
    ISOLATE --> DEGRADE[激活降级方案]
    DEGRADE --> MONITOR[持续健康探测]
    MONITOR -->|3次连续成功| RECOVER{服务恢复?}
    RECOVER -->|是| GRADUAL[渐进式恢复]
    RECOVER -->|否| MONITOR
    GRADUAL --> VERIFY[验证数据一致性]
    VERIFY --> NORMAL[恢复正常服务]
    
    DEGRADED -.断网期间.-> QUEUE[(请求队列)]
    QUEUE -.网络恢复.-> REPLAY[重放未处理请求]
    REPLAY --> NORMAL

渐进式恢复策略:

class GradualRecovery:
    """服务恢复不是瞬间完成的,需要渐进式验证"""
    
    async def on_service_restored(self, service: str):
        # Phase 1: 小流量验证(1%请求走新恢复的服务)
        await self.canary_test(service, traffic_pct=0.01)
        
        # Phase 2: 逐步放量(10% → 50% → 100%)
        for pct in [0.1, 0.5, 1.0]:
            success_rate = await self.ramp_traffic(service, pct)
            if success_rate < 0.95:
                # 恢复不稳定,回退
                self.rollback(service)
                return
        
        # Phase 3: 重放断网期间的积压请求
        pending = self.dequeue_pending_requests(service)
        for req in pending:
            await self.replay_request(req)
            
        # Phase 4: 通知端侧恢复全功能
        await self.broadcast_service_restored(service)

七、关键技术实现 #

7.1 端云通信协议 #

协议 适用场景 优势 劣势
gRPC 结构化数据传输(记忆同步、状态更新) 高性能、强类型、双向流 需要代理、防火墙穿透复杂
WebSocket 实时音频流、流式对话 全双工、低延迟 连接管理开销大
SSE 云端向端侧推送(通知、增量更新) 简单、HTTP兼容 单向、连接数限制
HTTP/2 批量请求、非实时数据 多路复用、头部压缩 不适合流式音频

推荐方案:音频流用WebSocket,状态同步用gRPC,推送通知用SSE。

7.2 端侧摘要 → 云端增量更新 #

为节省带宽,端侧不上传原始对话,而是上传结构化摘要:

class EdgeSummary:
    """端侧对话摘要 - 最小化云端同步数据量"""
    
    def summarize(self, conversation: List[Turn]) -> SyncPayload:
        return SyncPayload(
            session_id=self.session_id,
            device_id=self.device_id,
            timestamp=time.now(),
            # 不上传原始对话,只上传结构化摘要
            intents=[turn.intent for turn in conversation],
            entities_extracted=self.extract_entities(conversation),
            user_preferences=self.detect_preferences(conversation),
            # 关键记忆点(而非完整对话)
            key_memories=[
                MemoryPoint(
                    type="preference",
                    content=f"用户喜欢{topic}",
                    confidence=0.85
                )
                for topic in self.detect_topics(conversation)
            ],
            # 统计信息
            turn_count=len(conversation),
            total_duration=conversation[-1].timestamp - conversation[0].timestamp,
        )
    
    def payload_size(self) -> int:
        """摘要大小通常 < 2KB,原始对话可能 > 50KB"""
        return len(json.dumps(self.summarize([])))

7.3 弹性降级策略 #

┌─────────────────────────────────────────────────────────────┐
│                    弹性降级层级                               │
├────────┬────────────────────────────────────────────────────┤
│ L0 全功能│ 云端LLM + 全量Memory + 第三方工具                  │
│ L1 精简云│ 云端轻量模型 + 短期Memory + 核心工具                │
│ L2 端侧智能│ 端侧SLM + 本地记忆 + 本地工具                      │
│ L3 端侧规则│ 规则引擎 + 预置回复 + 基础控制                     │
│ L4 基础控制│ 仅设备控制(拨号、设置、播放)                      │
└────────┴────────────────────────────────────────────────────┘

降级触发条件:

class DegradationManager:
    def evaluate(self, metrics: SystemMetrics) -> DegradationLevel:
        if metrics.cloud_available and metrics.network_quality > 0.7:
            return L0_FULL
        elif metrics.cloud_available and metrics.network_quality > 0.3:
            return L1_LITE
        elif not metrics.cloud_available and metrics.slm_available:
            return L2_EDGE
        elif not metrics.slm_available and metrics.rules_available:
            return L3_RULES
        else:
            return L4_BASIC

八、非洲本地化适配 #

8.1 弱网环境优化 #

优化策略 技术方案 效果
离线能力包 端侧预置5种核心语言的ASR+SLM模型 断网可用核心功能
断点续传 请求失败自动缓存,网络恢复后重试 弱网请求不丢失
边缘节点 在拉各斯、内罗毕、约翰内斯堡部署边缘推理 延迟从800ms降至150ms
数据压缩 Opus音频编码(12kbps)+ Protobuf序列化 带宽占用降低80%

8.2 低端设备适配 #

约束条件 适配方案 资源占用
内存1GB 模型按需加载(非全量常驻) 运行时内存<300MB
存储16GB 模型包压缩+增量更新 模型包<500MB
无NPU CPU推理+INT4量化 延迟增加但可用
电池小 推理时CPU频率限制+VAD唤醒 功耗<5%日常使用

8.3 多语言端侧支持 #

端侧预置语言包策略:
├── 核心语言(预装,始终可用)
│   ├── 英语(非洲口音)
│   ├── 法语(非洲口音)
│   └── 斯瓦西里语
├── 扩展语言(按需下载,WiFi推荐)
│   ├── 豪萨语
│   ├── 约鲁巴语
│   ├── 阿姆哈拉语
│   └── 祖鲁语
└── 云端语言(仅在线可用)
    ├── 所有非洲语言(50+)
    └── 多语言混合输入

九、总结 #

核心架构要点 #

设计维度 方案选择 理由
端侧模型 300M SLM INT4量化 低端设备可运行、延迟<200ms
通信协议 WebSocket音频 + gRPC状态 兼顾实时性和结构化传输
降级策略 5层弹性降级 从全功能到基础控制的平滑过渡
第三方接入 沙箱隔离 + 熔断保护 安全可控的生态扩展
记忆同步 端侧摘要 → 云端增量 带宽优化80%+
API容错 多供应商 + 智能缓存 + 渐进恢复 云端/第三方不可用时自动切换

面试金句 #

“端云协同不是把云端的能力搬一部分到端侧,而是让端侧和云端各司其职——端侧保可用,云端供智能。”

“在非洲,一个不能在断网时拨电话的助手,再聪明也是摆设。”

“第三方API的接入不是越多越好,而是越可控越好——沙箱、熔断、脱敏,缺一不可。”

“端侧摘要同步的设计精髓:不传原始对话,只传结构化记忆——既省带宽,又保隐私。”

“好的API容错不是祈祷服务永远可用,而是假设一切都会失败——多供应商冗余、智能缓存、渐进恢复,缺一不可。”


本文档为面试技术方案,实际落地需结合传音硬件平台(芯片、NPU、OS)做进一步适配。