Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when wiring LLM features into the Apple client (macOS / iOS) — streaming chat via the FastAPI multi-LLM gateway, or on-device inference (Apple Foundation Models / Core ML). Provides the route decision (gateway vs on-device), streaming transport pattern, env/config contract, offline & cost guardrails, and minimum verifications before declaring the integration done.
.claude/skills/pcliangx-agf-wiring-apple-llm/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 20% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -2% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 12% | 0% |
| case-14 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 27% | 0% |
Use this skill when:
apple/ app 加对话 / 生成 / 总结类 LLM 功能默认走后端网关:FastAPI 后端已按 skill agf-wiring-multi-llm-sdk 封装 DeepSeek / Doubao / Qwen / MiniMax(provider 切换、fallback、cost telemetry 全在服务端)。客户端只对一个自有 API 说话,不直连任何 LLM 厂商。
| 场景 | 路由 | 理由 | |---|---|---| | 对话 / 生成 / RAG(默认) | 后端网关 | key 不进客户端、provider 可热切、成本计量集中、合规审计单点 | | 离线可用 / 隐私敏感(文本不出设备)/ 低延迟小任务(分类、摘要短文本) | on-device(Apple Foundation Models framework,iOS 26+ / macOS 26+;或 Core ML 自带模型) | 零 token 成本、断网可用;但模型能力 / 上下文受限 | | 多模态生成(文生图 / 视频) | 后端网关(ml-engineer 维护的推理服务) | 客户端不嵌大模型 |
> 铁律:LLM 厂商 API key 永不进客户端。客户端二进制可被逆向,任何打进 app 的 key 等于公开。只有自有后端的会话凭证可进客户端。
on-device 路径若成为产品主路径(非补充),属技术选型变更 → tech-lead 新开 ADR。
后端以 SSE(text/event-stream)暴露流式 chat 端点。注意:OpenAPI 对 SSE 描述能力有限——流式端点允许在生成 client 之外手写一个最小 SSE transport(这是 ADR-008「禁手写」的唯一豁免点,豁免范围仅限流式通道本身;请求/响应模型仍用生成类型):
swift// AppCore/Sources/AppCore/LLM/StreamingClient.swift —— 唯一允许的手写网络层(SSE 豁免) let (bytes, response) = try await URLSession.shared.bytes(for: request) for try await line in bytes.lines { guard line.hasPrefix("data: ") else { continue } let payload = line.dropFirst(6) if payload == "[DONE]" { break } // decode 用生成的 Components.Schemas.ChatChunk 类型,不手写 DTO }
Task.cancel() 必须真正断开 SSE 连接(防后台烧 token)@MainActor 的 AsyncSequence 消费,禁在主线程做 JSON 解析客户端无 .env;配置走 build configuration / Info.plist 注入:
| 项 | 载体 | 说明 | |---|---|---| | 网关 base URL | xcconfig per-configuration(Debug → localhost / UAT 栈,Release → 生产) | 禁硬编码在 Swift 源码 | | 会话凭证 | Keychain | 禁 UserDefaults / 文件 | | on-device 模型开关 | feature flag(后端下发或本地配置) | 降级链路可远程关 |
@available + 能力探测 gating,回落网关或隐藏入口apple-native.md §7):AI 生成内容须有举报 / 过滤入口;用户输入发往后端在隐私政策声明;隐私清单如实标注localhost:1),确认降级行为符合上表strings 扫 release 二进制无任何厂商 key / 网关密钥(strings App | grep -iE 'sk-|api[_-]?key')agf-wiring-multi-llm-sdk(服务端 SSOT,本 skill 不重复)| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 24,620 | 19,532 | -21% | 1 | 1 | 0% | 4,445 | 5,344 | +20% | 0 | 0 | — |
case-02 | fail→fail | 30,713 | 28,881 | -6% | 1 | 1 | 0% | 5,209 | 6,947 | +33% | 0 | 0 | — |
case-03 | fail→pass | 26,594 | 17,429 | -34% | 1 | 1 | 0% | 4,584 | 4,509 | -2% | 0 | 0 | — |
case-04 | pass→pass | 16,099 | 11,835 | -26% | 1 | 1 | 0% | 2,662 | 3,379 | +27% | 0 | 0 | — |
case-13 | pass→pass | 16,620 | 12,082 | -27% | 1 | 1 | 0% | 2,645 | 3,302 | +25% | 0 | 0 | — |
case-05 | pass→pass | 16,178 | 11,041 | -32% | 1 | 1 | 0% | 2,374 | 3,310 | +39% | 0 | 0 | — |
case-06 | pass→pass | 13,571 | 8,162 | -40% | 1 | 1 | 0% | 2,231 | 2,872 | +29% | 0 | 0 | — |
case-07 | pass→pass | 11,561 | 4,174 | -64% | 1 | 1 | 0% | 1,898 | 2,097 | +10% | 0 | 0 | — |
case-08 | fail→pass | 11,805 | 5,218 | -56% | 1 | 1 | 0% | 2,107 | 2,357 | +12% | 0 | 0 | — |
case-09 | pass→pass | 13,588 | 8,209 | -40% | 1 | 1 | 0% | 1,990 | 2,795 | +40% | 0 | 0 | — |
case-10 | pass→pass | 9,143 | 1,912 | -79% | 1 | 1 | 0% | 1,418 | 1,683 | +19% | 0 | 0 | — |
case-11 | pass→pass | 9,194 | 3,246 | -65% | 1 | 1 | 0% | 1,441 | 1,968 | +37% | 0 | 0 | — |
case-12 | pass→pass | 13,584 | 9,759 | -28% | 1 | 1 | 0% | 2,066 | 2,996 | +45% | 0 | 0 | — |
case-14 | fail→pass | 17,438 | 5,997 | -66% | 1 | 1 | 0% | 2,469 | 2,259 | -9% | 0 | 0 | — |
case-15 | pass→pass | 17,804 | 14,092 | -21% | 1 | 1 | 0% | 2,978 | 3,763 | +26% | 0 | 0 | — |
case-16 | pass→pass | 15,253 | 8,574 | -44% | 1 | 1 | 0% | 2,328 | 2,720 | +17% | 0 | 0 | — |
case-17 | pass→pass | 19,780 | 7,175 | -64% | 1 | 1 | 0% | 2,951 | 2,552 | -14% | 0 | 0 | — |
case-18 | pass→pass | 14,576 | 8,138 | -44% | 1 | 1 | 0% | 2,255 | 2,627 | +16% | 0 | 0 | — |
case-19 | pass→pass | 10,519 | 5,945 | -43% | 1 | 1 | 0% | 1,699 | 2,331 | +37% | 0 | 0 | — |
case-20 | pass→pass | 22,994 | 17,318 | -25% | 1 | 1 | 0% | 4,358 | 4,686 | +8% | 0 | 0 | — |
case-21 | pass→pass | 14,302 | 12,263 | -14% | 1 | 1 | 0% | 2,654 | 3,759 | +42% | 0 | 0 | — |
case-22 | pass→pass | 12,143 | 9,166 | -25% | 1 | 1 | 0% | 2,096 | 2,884 | +38% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.