ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

山海万灵 HarmonyOS 文化知识实战(20):AI Gateway 的路由、缓存、限流与审计闭环

山海万灵 HarmonyOS 文化知识实战(20):AI Gateway 的路由、缓存、限流与审计闭环 数字馆长的讲解入口面对的是同一类难题页面只需要稳定的讲解结果、出处和推荐而模型开关、网络超时、缓存命中与限流不能散落在每个页面里。山海万灵把请求集中到ai-service由 Gateway 在进入模型前完成场景收束、上下文装配、缓存判断、限流和审计再把结构化结果返回给应用。图中的本地接口回读展示了两条关键结果受控讲解场景在模型未启用时返回可识别的降级内容OPEN_CHAT在进入模型前被范围守卫拦截。这样临时不可用的模型服务不会把开放式输入带进知识应用的正式内容链路。先把页面动作翻译成受控场景客户端提交节点、节点类型和场景服务端只接受馆长讲解相关的有限枚举。无场景时归一到神兽详情未知值不尝试“猜一个最接近的模型任务”而是直接走范围守卫。private static String normalizeScene(String requestedScene) { if (requestedScene null || requestedScene.isBlank()) { return BEAST_DETAIL; } return switch (requestedScene.trim().toUpperCase(Locale.ROOT)) { case AI_EXPLAIN, AI_EXPLANATION, ARCHIVE, DETAIL, BEAST_DETAIL - BEAST_DETAIL; case BEAST_STORY, STORY - BEAST_STORY; case BEAST_MAP, MAP - BEAST_MAP; case BEAST_HALL, HALL - BEAST_HALL; default - null; }; }场景收束解决了两个工程问题。第一Prompt Builder 能依据确定的场景选择上下文和输出约束第二未知场景无需触碰 Provider 就能返回SCOPE_GUARD响应中的safetyStatusBLOCKED可被界面和审计记录一致识别。页面动作Gateway 场景输入边界返回重点神兽详情讲解BEAST_DETAIL节点 ID、物种类型讲解、出处、关联推荐故事页追问BEAST_STORY已发布故事节点叙事上下文与来源地图导览BEAST_MAP地域与关联节点地域线索与推荐路线开放聊天未纳入任意自由输入范围拦截与安全状态缓存键要能解释“为什么这次可以复用”讲解文本不是只按节点 ID 缓存。场景、Prompt 版本、图谱上下文哈希和模型参数都会改变结果因此它们共同参与请求指纹和缓存键。图谱改边、升级 Prompt 或调节模型参数时旧结果自然不再匹配新键。String contextHash AiGatewayFingerprint.curatorContextHash(context); String modelOptionsHash AiGatewayFingerprint.modelOptionsHash( modelProvider.providerCode(), properties.getOllama()); String cacheKey responseCache.key( scene, nodeId, promptMetadata, contextHash, modelOptionsHash); OptionalCuratorExplanation cached responseCache.find(cacheKey); if (cached.isPresent()) { CuratorExplanation result cached.get().forRequest(requestId, true); audit(requestId, clientKeyHash, scene, nodeId, contextHash, modelOptionsHash, requestHash, result, SUCCESS, null, startedAt); return result; }缓存命中仍会生成新的请求 ID 并写入审计避免把“复用了结果”误解成“没有发生业务请求”。缓存只保存通过结构化输出校验的讲解模型不可用、输出格式异常或场景被拒绝时不把降级文案写进成功缓存。缓存字段作用变更后的行为场景与节点区分讲解意图和对象切换故事或地图会重新计算Prompt 版本锁定提示词语义升级 Prompt 后旧条目失效图谱上下文哈希绑定出处和关系节点、来源或推荐变化后重取模型参数哈希避免混用不同生成设置调整模型或温度后重取限流在调用 Provider 前执行限流器以 Redis 为主计数脚本在窗口内递增并设置过期时间。这样多个服务实例能共享同一窗口Redis 暂时不可用时服务降到进程内计数优先保证接口可以返回受控结果而不是把错误扩散到页面。if (!rateLimiter.tryAcquire(clientKeyHash)) { CuratorExplanation result catalogService.fallback( context, requestId, DEGRADED, false, RATE_LIMIT, promptMetadata); audit(requestId, clientKeyHash, scene, nodeId, contextHash, modelOptionsHash, requestHash, result, FALLBACK, RATE_LIMITED, startedAt); return result; }客户端标识不会以原文写入审计表而是先转为哈希。限流触发后返回的是带来源和安全状态的本地策展内容页面无需根据异常栈拼装兜底 UI也不会把“请求太快”伪装成一段远程生成文本。模型路由与格式化是一条连续链路通过限流后Gateway 才构建 Prompt 并调用已配置的 Provider。模型返回值必须经过 JSON 格式化和内容质量校验任何一步抛出运行时异常都会回落到馆藏策展内容。应用侧始终拿到同一个CuratorExplanation结构展示层不需要认识具体模型。PromptPackage prompt promptBuilder.build(context, scene); ModelCompletion completion modelProvider.generate(prompt); CuratorDraft draft outputFormatter.format(completion.content()); GeneratedAnswer answer contentAssembler.assemble(draft, context, scene); outputQualityValidator.validate(answer, context); CuratorExplanation result new CuratorExplanation( requestId, ABILITY_TYPE, answer.title(), answer.content(), true, AI创作, context.sourceNodes(), context.recommendations(), context.sourceReferences(), context.contextNodes(), context.relations(), PASS, false, false, modelProvider.providerCode(), prompt.metadata()); responseCache.put(cacheKey, result);这里的取舍是把“可生成”与“可展示”分开。Provider 的可用性只决定是否尝试生成正文、出处节点、推荐和AI创作标识仍由服务端的结构化对象统一组装。应用不保存模型密钥也不直接访问模型地址。响应合同让页面只处理业务状态Gateway 返回的不是某个模型厂商的原始报文而是面向数字馆长页面的稳定响应。无论结果来自模型、缓存、范围守卫还是本地策展内容页面都可以读取同一组字段。标题、正文、出处和推荐负责内容呈现provider、fallback、cacheHit与safetyStatus负责呈现来源和状态不需要把网络异常映射成另一套页面模型。public record CuratorExplainResponse( String requestId, String abilityType, String title, String content, boolean aiGenerated, String label, ListString sourceNodes, ListSourceReferenceItem sourceReferences, ListContextNodeItem contextNodes, ListRelationItem relations, ListRecommendationItem recommendations, String safetyStatus, boolean cacheHit, boolean fallback, String provider, String promptId, String promptVersion, String traceId ) { }这种合同把降级做成可见业务状态而不是隐藏的失败分支。模型关闭时fallbacktrue提醒页面继续显示策展内容范围拦截时providerSCOPE_GUARD与safetyStatusBLOCKED让入口保持受控缓存命中时cacheHittrue可以用于性能观察但不会改变读者看到的讲解结构。后续替换模型 Provider 时只要这个合同不变HarmonyOS 页面、CMS 预览和服务端审计都无需跟着迁移模型专属字段。审计只保留排障需要的指纹每次请求都记录请求 ID、场景、节点、Prompt 元数据、上下文哈希、模型参数哈希、缓存命中、处理结果、错误码和耗时。审计不保存原始 Prompt、模型原文、密码或密钥这使问题定位可以聚焦“哪一种受控请求在哪个边界降级”而不会把内容安全风险带进日志。事件结果典型触发条件返回给页面审计用途SUCCESS模型输出校验通过或命中缓存讲解、出处、推荐区分首次生成与缓存命中BLOCKED场景不在白名单安全状态与受控回退识别越界调用FALLBACKProvider 未启用、超时或限流本地策展内容判断降级原因和耗时如何回读这条闭环回归用例覆盖了场景归一化、缓存键变化、Redis 限流、审计持久化、Provider 格式化和 HTTP 控制器。当前本地接口回读中BEAST_DETAIL在 Provider 关闭时得到providerFALLBACK与safetyStatusDEGRADEDOPEN_CHAT得到providerSCOPE_GUARD与safetyStatusBLOCKED。两种结果都保留在同一响应结构中前端可以据此展示明确状态。把一次讲解串成可定位的事件链当用户在图鉴页请求讲解时Gateway 先为请求生成 ID并对客户端标识做哈希。随后场景解析决定请求是否进入允许集合上下文目录提供节点、来源和关系Prompt 元数据、图谱上下文和模型选项共同形成指纹。缓存命中、限流拒绝、模型生成、格式化失败和本地降级最终都会收束为同一种讲解结果。这条事件链的关键不是记录更多文本而是保留能够解释结果的关联信息。例如缓存条目可以由 Prompt 版本和上下文哈希解释同一个节点在不同场景得到不同的请求指纹一次范围拦截没有模型名却有SCOPE_GUARD一次 Provider 关闭导致的降级可以由错误码和耗时定位。审计表只保存这些结构化信息避免把读者输入、原始 Prompt 或模型原文扩散到日志系统。页面侧也因此能保持简单讲解内容总是和出处、推荐一起出现状态字段只决定是否展示 AI 创作标识、降级提示或重试入口。用户从地图、展厅或神兽详情进入时不需要知道 Redis、Ollama 或格式化器的存在这些依赖由 Gateway 隔离业务页面只处理可阅读的知识结果和明确的安全状态。生产部署还需要把共享 Redis、可信身份传递和模型容量作为独立的运行条件Redis 不可用时不能把进程内计数当成多实例限流显存和模型超时必须按实际并发压测设置发布内容的出处约束不能因为模型可用而放宽。关于 HarmonyOS 端的 AI 能力边界可参考 HarmonyOS AI 能力介绍。
返回列表