Swift集成大语言模型:LLM.swift SDK让AI开发更简单

news2026/5/3 22:34:33
1. 项目概述当 Swift 遇见大语言模型如果你是一名 iOS 或 macOS 开发者最近肯定被各种 AI 应用刷屏了。从能帮你写代码的 Copilot到能和你聊天的智能助手背后都离不开大语言模型LLM。但每次想在自己的 Swift 项目里集成这些酷炫的 AI 能力你是不是总觉得有点“水土不服”要么得折腾复杂的网络请求和 JSON 解析要么得面对五花八门的 API 文档调试起来更是让人头大。eastriverlee/LLM.swift这个项目就是来帮你解决这些痛点的。它不是一个模型本身而是一个纯 Swift 编写的、轻量级且类型安全的 SDK目标是把调用 OpenAI、AnthropicClaude这些主流大模型 API 的过程变得像调用本地函数一样简单直观。想象一下你不再需要手动拼接 HTTP 请求体、处理流式响应Streaming的琐碎细节或者为每个 API 的参数名和类型而查阅文档。LLM.swift 通过 Swift 强大的类型系统和优雅的 API 设计将这些复杂性全部封装起来。你只需要关注你的业务逻辑比如“让 AI 总结这段文本”或者“根据用户描述生成一张图片的提示词”。这个项目特别适合正在开发下一代智能应用的 Apple 平台开发者无论是想给 App 增加一个智能聊天机器人、一个文档摘要功能还是一个创意写作助手LLM.swift 都能显著降低你的集成门槛让你能把精力集中在创造更好的用户体验上而不是和 API 细节搏斗。2. 核心设计理念与架构解析2.1 为什么需要另一个 LLM SDK市面上已经存在一些用于调用 AI 服务的 Swift 包那为什么还要有 LLM.swift它的核心设计理念可以概括为三点极简的开发者体验DX、彻底的类型安全、以及模块化的可扩展性。很多现有的解决方案要么是某个更大框架的一部分显得过于臃肿要么提供的 API 比较底层仍然需要开发者处理很多样板代码。LLM.swift 的初衷是做一个“专注且优雅”的胶水层。首先它追求极简的 API。例如完成一个基础的聊天对话你只需要几行代码let openAIClient OpenAIService(apiKey: “your-api-key”) let response try await openAIClient.chat( model: .gpt4, messages: [.init(role: .user, content: “Hello, world!”)] ) print(response.choices.first?.message.content)这种设计让代码的意图非常清晰几乎不需要注释。其次类型安全是贯穿始终的原则。所有 API 的请求参数和响应模型都通过 Swift 的struct和enum来定义。这意味着你在编码时就能获得编译器的自动补全和类型检查传递一个错误的模型名称或无效的参数类型在编译阶段就会被捕获而不是在运行时收到一个晦涩的 API 错误。这大大提高了开发效率和代码的健壮性。最后是模块化。项目采用了清晰的关注点分离Separation of Concerns设计。网络层、模型定义层、具体服务实现层如 OpenAI、Anthropic都是解耦的。这种设计不仅让代码库更易于维护也为未来支持更多的 AI 服务提供商如 Google Gemini、本地部署的模型 API铺平了道路。你甚至可以基于其协议Protocol轻松地为内部或小众的模型服务实现自己的适配器。2.2 核心模块与工作流程LLM.swift 的架构可以划分为几个核心模块理解它们有助于你更高效地使用和必要时进行扩展。核心协议与类型Core Protocols Types这是项目的基石。它定义了一系列协议如LLMServiceProtocol规定了任何大模型服务都应具备的基本能力如发送聊天补全请求。同时它定义了通用的数据模型例如ChatMessage包含角色role和内容content这些模型在不同服务商之间是通用的确保了上层接口的一致性。服务提供商实现Service Implementations这是针对每个具体 AI 服务商的适配层。例如OpenAIService和AnthropicService。每个服务类都遵循核心协议但内部负责处理该服务商特有的 API 端点、请求/响应格式、身份验证方式如 API Key 的携带方式可能不同以及错误映射。当你调用openAIClient.chat(...)时OpenAIService会将通用的ChatMessage数组转换成 OpenAI API 要求的特定 JSON 结构并处理其特有的参数如temperature,top_p。网络与工具层Network Utilities一个轻量且强大的网络层负责实际的 HTTP 通信通常基于 Swift 的URLSession进行封装支持异步async/await调用。工具层则包含了一些辅助功能比如计算 Token 数量的近似工具这对于控制成本和满足模型上下文长度限制很重要以及处理流式响应Streaming的便捷方法。流式响应是 LLM 应用中的常见需求它允许模型生成的内容像打字一样逐字返回能极大提升用户体验。LLM.swift 通过AsyncThrowingStream等现代 Swift 并发特性让处理流式响应变得异常简单。整个工作流程是这样的开发者使用类型安全的构建器或直接传递参数创建一个请求 - 请求被传递给具体的服务类如OpenAIService- 服务类将通用请求转换为供应商特定的格式并调用网络层 - 网络层发送 HTTP 请求并接收响应 - 响应被解析回类型安全的模型对象 - 最终结果返回给开发者。这个过程中开发者始终在与高级的、语义化的 Swift 对象打交道。3. 快速上手指南与基础用法3.1 环境准备与安装开始使用 LLM.swift 的第一步是将其添加到你的项目中。由于它是一个 Swift Package集成过程非常标准化。假设你正在使用 Xcode 进行开发打开你的 Xcode 项目在项目导航器中点击你的项目文件。选择你的 App Target然后切换到“Package Dependencies”选项卡。点击“”按钮在搜索框中输入该仓库的 Git URLhttps://github.com/eastriverlee/LLM.swift.git。Xcode 会自动获取包信息。在“Dependency Rule”部分通常可以选择“Up to Next Major Version”以便自动获取兼容的更新然后点击“Add Package”。在接下来的对话框中确保将LLM产品添加到你的 Target 中。完成这些步骤后你就可以在项目的任意 Swift 文件中通过import LLM来引入这个模块了。除了 Xcode 的图形化界面你也可以直接在Package.swift文件中添加依赖声明这对于纯 Swift Package Manager 的项目或者需要精确版本控制的场景更合适。注意由于项目需要访问网络别忘了在 iOS/macOS 等平台的 App 中配置相应的网络权限。对于 iOS需要在Info.plist中添加NSAppTransportSecurity相关配置或者直接允许任意加载仅限调试。对于使用 SwiftUI 生命周期的 App你可能需要在项目配置中启用 “Outgoing Connections (Client)” 能力。3.2 发起你的第一个 AI 请求安装完成后让我们从一个最简单的例子开始让 GPT-3.5 打个招呼。首先你需要一个 OpenAI 的 API Key。如果你还没有可以去 OpenAI 的官网注册并获取。请务必妥善保管你的 API Key不要将它硬编码在客户端代码中提交到公开的版本控制系统如 GitHub。在实际项目中更安全的做法是通过后端服务中转请求或者至少将 Key 存储在环境变量或安全的配置文件中。假设我们已经将 API Key 安全地存放在了环境变量OPENAI_API_KEY中。以下是如何在 Swift 中发起请求import LLM // 1. 创建服务实例 let openAI OpenAIService(apiKey: ProcessInfo.processInfo.environment[“OPENAI_API_KEY”] ?? “”) // 2. 定义对话消息 let messages: [ChatMessage] [ .init(role: .system, content: “你是一个乐于助人的助手。”), .init(role: .user, content: “用一句简短的话介绍你自己。”) ] // 3. 发起异步请求 Task { do { let response try await openAI.chat( model: .gpt3_5Turbo, messages: messages, temperature: 0.7 // 控制创造性的参数0-2之间越高越随机 ) // 4. 处理响应 if let firstChoice response.choices.first { print(“AI 回复\(firstChoice.message.content)”) } } catch { print(“请求失败\(error)”) } }这段代码清晰地展示了使用 LLM.swift 的四个步骤初始化、构输入、调用、处理结果。ChatMessage的role属性非常重要system角色用于设定 AI 的行为和身份user角色代表用户的输入。temperature参数是控制生成文本“创造性”的关键设置为 0 时输出最确定、可重复设置为较高的值如 0.8 或 1.2时输出会更随机、更有创意。3.3 核心参数详解与调优仅仅能调用 API 还不够要想让 AI 按照你的预期工作理解并调优核心参数是关键。LLM.swift 将这些参数都封装成了类型安全的属性方便你探索。模型选择 (model)这是最重要的选择。OpenAIService提供了像.gpt4,.gpt4Turbo,.gpt3_5Turbo这样的枚举值。选择模型时需要考虑平衡GPT-4 系列通常更强大、更“聪明”但价格更贵、速度可能稍慢GPT-3.5-Turbo 性价比高、速度快适合大多数常规对话任务。你需要根据任务复杂度、成本预算和响应速度要求来权衡。温度与核采样 (temperature,top_p)这两个参数都用于控制生成的随机性但方式不同。temperature直接调整采样概率分布的“平滑度”。值越高所有可能的下一个词的概率分布越平缓低概率的词被选中的机会增加输出更不可预测、更有创意。值越低概率分布越尖锐模型会更倾向于选择最高概率的词输出更稳定、更可预测。对于需要事实准确性的问答建议用低温0-0.3对于创意写作、头脑风暴可以用高温0.7-1.0。top_p核采样这是一种动态选择词汇范围的方法。设置top_p0.9意味着模型只从累积概率达到 90% 的最高概率词汇中进行采样。它通常能产生比固定温度更自然、更多样的输出。注意通常不建议同时调整temperature和top_p建议只使用其中一个。最大生成长度 (maxTokens)这个参数限制 AI 单次响应能生成的最大 Token 数可以粗略理解为词或字片段的数量。它有两个作用一是控制成本生成的 Token 越多费用越高二是防止 AI 陷入无意义的冗长输出。你需要根据上下文长度和预期回答的篇幅来设置。例如对于一个简短的总结设置maxTokens: 150可能就够了。停止序列 (stop)这是一个字符串数组用于告诉模型在生成到特定序列时停止。例如如果你在构建一个 QA 系统可以设置stop: [“\n\n”, “Q:”]这样当模型生成出两个换行可能表示回答结束或新的“Q:”开头时可能表示它开始自己提问了就会自动停止。这是一个非常实用且常被忽略的控制生成质量的功能。在实际项目中我通常的做法是为不同类型的任务如“创意写作”、“代码生成”、“精确摘要”创建不同的参数配置预设struct然后在调用时根据场景选用对应的预设。这样既能保证行为一致也便于集中调整优化。4. 高级功能与实战技巧4.1 流式响应Streaming的实现与优化流式响应是提升 AI 应用用户体验的“杀手锏”。想象一下 ChatGPT 那种逐字输出的效果而不是等待好几秒后一次性显示一大段文字。LLM.swift 对 Streaming 的支持做得非常优雅。使用流式响应你不再直接获得一个完整的ChatResponse对象而是获得一个AsyncThrowingStreamChatStreamChunk, Error。你可以遍历这个流实时处理每一个到达的“数据块”。下面是一个结合 SwiftUI 的典型示例展示如何在界面上实现打字机效果import SwiftUI import LLM struct ChatView: View { StateObject private var viewModel ChatViewModel() State private var inputText “” var body: some View { VStack { ScrollView { ForEach(viewModel.messages) { message in MessageBubble(message: message) } } HStack { TextField(“输入消息...”, text: $inputText) Button(“发送”) { Task { await viewModel.sendMessage(inputText) } inputText “” } } } } } MainActor class ChatViewModel: ObservableObject { Published var messages: [DisplayMessage] [] private let openAIService OpenAIService(apiKey: “your-key”) func sendMessage(_ text: String) async { // 1. 先将用户消息添加到界面 let userMessage DisplayMessage(id: UUID(), role: .user, content: text, isComplete: true) messages.append(userMessage) // 2. 创建一个“正在输入”的 AI 消息占位符 let aiMessageId UUID() let loadingMessage DisplayMessage(id: aiMessageId, role: .assistant, content: “”, isComplete: false) messages.append(loadingMessage) // 3. 准备对话历史通常只发送最近几轮以节省 Token let chatHistory: [ChatMessage] prepareHistory(for: text) do { // 4. 发起流式请求 let stream try await openAIService.chatStream( model: .gpt4, messages: chatHistory ) // 5. 实时处理流 for try await chunk in stream { if let deltaContent chunk.choices.first?.delta.content { // 找到界面上那个“正在输入”的消息并追加内容 if let index messages.firstIndex(where: { $0.id aiMessageId }) { messages[index].content.append(deltaContent) } } // 检查是否结束 if chunk.choices.first?.finishReason ! nil { if let index messages.firstIndex(where: { $0.id aiMessageId }) { messages[index].isComplete true // 标记为完成 } break } } } catch { // 错误处理更新占位符消息为错误信息 if let index messages.firstIndex(where: { $0.id aiMessageId }) { messages[index].content “请求失败\(error.localizedDescription)” messages[index].isComplete true } } } }实操心得处理流式响应时网络稳定性很重要。在实际应用中我建议增加重试逻辑特别是对于非用户主动取消的错误和超时控制。另外频繁更新 UI每收到一个 chunk 就更新在低端设备上可能导致性能问题可以考虑一个小优化累积一小段时间如 50-100 毫秒或一定数量的字符后再更新一次 UI而不是每个字符都更新这能在流畅度和实时性之间取得很好的平衡。4.2 函数调用Function Calling的集成函数调用是让大模型从“聊天机器人”升级为“智能体”的关键能力。它允许模型根据对话内容主动请求调用你预先定义好的工具函数并将结果返回给模型从而完成更复杂的任务。LLM.swift 也支持这一强大功能。其核心流程是你定义一组工具函数包括函数名、描述、参数 JSON Schema - 在聊天请求中传入这些工具定义 - 模型在认为需要时会在响应中返回一个“函数调用请求” - 你在本地执行对应的函数 - 将函数执行结果作为新的消息发送给模型 - 模型根据结果生成最终的回答给用户。假设我们正在开发一个智能旅行助手它需要能查询天气。我们首先需要定义一个符合Tool协议的结构体来描述这个函数import LLM // 1. 定义函数的参数结构 struct WeatherQueryParams: Codable { let location: String let date: String? // 可选参数 } // 2. 定义工具 let weatherTool Tool( function: .init( name: “get_current_weather”, description: “获取指定城市的当前天气信息”, parameters: WeatherQueryParams.schema // 这里需要实现一个从 Codable 类型生成 JSON Schema 的扩展 ) ) // 在实际的聊天请求中将工具传入 let response try await openAIClient.chat( model: .gpt4, messages: messages, tools: [weatherTool] // 传入工具定义 ) // 3. 检查响应中是否包含工具调用 if let toolCall response.choices.first?.message.toolCalls?.first { switch toolCall.function.name { case “get_current_weather”: // 解析参数 let params try JSONDecoder().decode(WeatherQueryParams.self, from: toolCall.function.arguments.data(using: .utf8)!) // 执行实际函数这里模拟 let weatherResult fetchWeatherFromAPI(location: params.location) // 将结果作为新的“tool”角色消息发送回给模型 let resultMessage ChatMessage( role: .tool, content: weatherResult, toolCallId: toolCall.id // 必须关联对应的调用 ID ) // 将这条消息加入历史并再次调用 chat API让模型生成面向用户的回答 let finalResponse try await openAIClient.chat( model: .gpt4, messages: messages [resultMessage] ) // 处理 finalResponse... default: break } }注意事项函数调用的成功与否极大程度上依赖于你对函数描述的清晰度。description字段要准确说明函数做什么、参数的意义。参数 Schema 要尽可能详细比如location需要是城市名还是经纬度。模型是根据这些描述来决定是否以及如何调用函数的。一个常见的坑是如果函数描述不清模型可能会错误地调用函数或者以错误的格式提供参数导致 JSON 解析失败。务必为你的工具函数编写完善的错误处理并在模型调用出错时将友好的错误信息返回给模型让它有机会纠正或向用户解释。4.3 上下文管理与 Token 节省策略大语言模型有上下文窗口限制例如GPT-4 Turbo 是 128K tokens。虽然 LLM.swift 本身不管理历史但如何高效地管理对话历史是你构建应用时必须考虑的问题。无脑地将整个对话历史每次都发送给 API不仅浪费 Token增加成本也可能在长对话后超出限制。一个高效的上下文管理策略通常包括摘要压缩当对话轮数很多时可以将早期的重要对话内容进行摘要然后用一段简短的摘要文本来替代原始的多轮对话从而节省大量 Token。你可以让 AI 自己来生成摘要。例如在对话达到一定轮数后插入一个系统消息“请将上述对话的核心事实和用户需求总结成一段不超过100字的摘要。”滑动窗口这是最简单常用的策略。只保留最近 N 轮对话例如最近10轮。这适用于话题集中、短期记忆为主的场景。关键信息提取从历史对话中提取出关键实体如人名、地点、项目名、用户明确表达的偏好和设定将这些信息作为系统提示词的一部分而不是完整的对话记录。函数调用记忆如果使用了函数调用函数执行的结果尤其是结构化数据可以以精简的形式保存而不是保存整个冗长的自然语言结果。LLM.swift 虽然没有内置这些高级管理功能但其清晰的[ChatMessage]数组接口让你可以非常灵活地实现自己的管理策略。你可以维护一个完整的本地对话历史而在每次调用 API 前通过上述策略生成一个精简版的messages数组发送出去。Token 计算小技巧精确计算 Token 数比较复杂不同模型的分词器不同。OpenAI 提供了tiktoken库但在 Swift 中直接使用不便。一个实用的近似方法是对于英文1个 Token 约等于 0.75 个单词或 4 个字符对于中文1个 Token 约等于 1.5 到 2 个汉字。LLM.swift 未来可能会集成或提供 Token 计数工具但目前你可以用这个经验值进行粗略的成本估算和上下文长度控制。在关键场景更推荐通过调用 OpenAI 的专用 Token 计数端点来获取准确数字。5. 错误处理、调试与性能优化5.1 全面的错误处理策略在使用任何网络服务时健壮的错误处理都是必不可少的。LLM.swift 抛出的错误通常是LLMError枚举类型它涵盖了从网络问题到 API 业务逻辑错误的多种情况。do { let response try await openAIClient.chat(...) } catch let error as LLMError { switch error { case .networkError(let underlyingError): // 处理网络连接失败、超时等 print(“网络错误: \(underlyingError.localizedDescription)”) // 可以在这里触发重试逻辑 case .apiError(let statusCode, let message): // 处理 API 返回的错误如 401无效API Key429速率限制503服务繁忙 print(“API 错误 (状态码 \(statusCode)): \(message)”) if statusCode 429 { // 速率限制建议指数退避重试 await exponentialBackoffRetry() } case .decodingError: // 响应数据解析失败可能是 API 格式变更或库的 Bug print(“数据解析失败”) case .invalidResponse: // 响应格式不符合预期 print(“无效的响应格式”) } } catch { // 捕获其他未知错误 print(“未知错误: \(error)”) }重要建议速率限制429错误这是最常见的错误之一。所有 AI 服务商都有严格的速率限制。务必实现指数退避重试机制。不要立即重试而是等待一段时间如 1秒、2秒、4秒、8秒...这能有效避免因短时间内重复请求而持续被限。令牌超限context_length_exceeded当你的消息总 Token 数超过模型上下文窗口时会发生。你的错误处理逻辑应该能捕获这个特定错误并触发你的上下文管理策略如自动摘要或清除最早的历史。API Key 失效或余额不足这通常表现为 401 或 403 错误。在面向用户的产品中你需要有优雅的降级方案比如提示用户“服务暂时不可用”并记录日志通知管理员。5.2 调试与日志记录在开发阶段查看实际发送的请求和接收的响应对于调试问题至关重要。LLM.swift 的网络层通常可以注入自定义的 URLSession 配置这为我们添加调试日志提供了入口。一个有效的方法是为你的URLSession配置一个自定义的URLSessionConfiguration并设置其httpAdditionalHeaders或使用网络调试代理工具如 Proxyman, Charles。更直接的方式是如果你需要深度定制可以 fork LLM.swift 项目在它的网络请求发送前和收到响应后添加打印语句。// 示例创建一个打印详细日志的 URLSession let configuration URLSessionConfiguration.default // 可以在这里注入自定义的 HTTP 头等 let session URLSession(configuration: configuration) // 假设 LLM.swift 支持注入自定义 session具体看其初始化方法 let openAIClient OpenAIService(apiKey: apiKey, session: session) // 另外在 Swift 中你可以使用 OSLog 或第三方库如 SwiftyBeaver来结构化地记录日志。 import OSLog let logger Logger(subsystem: “com.yourapp.llm”, category: “api”) // 在关键位置记录 logger.debug(“Sending chat request with \(messages.count) messages”)对于生产环境建议记录请求的元数据如模型、Token 使用量、耗时和错误信息但切勿记录完整的请求和响应内容因为它们可能包含用户隐私数据。这些日志对于监控成本、分析性能和排查问题非常有价值。5.3 性能优化与最佳实践连接复用与超时设置确保你复用了OpenAIService或AnthropicService实例而不是每次请求都创建新的。单例模式或依赖注入是好的选择。同时根据你的应用场景合理设置超时。对于流式响应你可能需要更长的超时时间如 60 秒以上因为连接会保持打开状态直到生成完成。异步与并发充分利用 Swift 的async/await并发模型。你可以并发地发起多个独立的 AI 请求以提升效率。例如同时为一篇文章生成摘要、提取关键词和检测情感。async let summary generateSummary(text: article) async let keywords extractKeywords(text: article) async let sentiment analyzeSentiment(text: article) let (finalSummary, finalKeywords, finalSentiment) await (summary, keywords, sentiment)缓存策略对于某些确定性较高的请求例如将固定提示词模板与用户输入结合如果结果在短时间内不会变化可以考虑在客户端或服务器端实施缓存。这能减少 API 调用次数节省成本和延迟。但要注意缓存不适合创造性任务或实时信息查询。成本监控每个 API 响应中都包含了使用的 Token 数量usage字段。强烈建议你记录这些数据并建立简单的成本监控。可以设置每日预算告警或者在客户端实现“Token 预算”功能防止意外的高消耗。降级与熔断在面向用户的生产环境中不能假设 AI 服务 100% 可用。设计降级策略例如当主要模型如 GPT-4不可用或超时时自动切换到更便宜、更快的模型如 GPT-3.5-Turbo或者直接返回一个友好的离线提示。在连续失败多次后可以考虑实现熔断机制暂时停止向故障服务发送请求。6. 项目扩展与生态结合LLM.swift 本身是一个优秀的客户端 SDK但要构建一个完整的 AI 应用你通常需要将其置于更大的技术栈中。6.1 与 SwiftUI/UIKit 的深度集成如前文流式响应示例所示与 SwiftUI 的集成非常自然。核心模式是使用Observable或StateObject来管理视图模型ViewModel在视图模型中持有 LLM 服务实例并处理异步逻辑。对于 UIKit你可以遵循类似的 MVC 或 MVVM 模式在 Controller 或 ViewModel 中调用 LLM.swift。一个更高级的模式是创建一个通用的AIService抽象层背后可以灵活切换不同的提供商OpenAI, Anthropic甚至未来本地模型。这样你的业务逻辑代码将与具体的 SDK 解耦。protocol AIServiceProtocol { func chat(messages: [ChatMessage]) async throws - String } class MyAppAIService: AIServiceProtocol { private let openAIClient: OpenAIService private let anthropicClient: AnthropicService? private let currentProvider: Provider .openAI // 可从配置读取 func chat(messages: [ChatMessage]) async throws - String { switch currentProvider { case .openAI: let response try await openAIClient.chat(model: .gpt4, messages: messages) return response.choices.first?.message.content ?? “” case .anthropic: // 调用 Anthropic 的实现... return “” } } }6.2 后端集成与安全考量绝对不要将你的 API Key 硬编码在移动端 App 中并分发出去。这会导致密钥泄露他人可以盗用你的额度甚至以你的名义进行滥用。正确的架构是客户端你的 iOS/macOS App 使用 LLM.swift 向后端服务器你控制的发送请求。请求中只包含用户输入和必要的会话标识不包含 AI 服务商的 API Key。后端服务器使用你喜欢的后端语言如 Swift Vapor, Node.js, Python FastAPI构建一个简单的代理服务。这个服务接收来自客户端的请求附加上你的 API Key然后转发给 OpenAI 等供应商最后将结果返回给客户端。这样做的好处除了安全还包括可以在后端统一实施速率限制、缓存、日志记录、成本分摊、提示词工程优化等。LLM.swift 虽然主要面向客户端但其清晰的接口使得在后端 Swift 项目如 Vapor中使用也同样方便。6.3 探索本地模型与未来方向虽然当前 LLM.swift 主要面向云端 API但其设计是开放的。社区已经开始探索将其与本地运行的模型如通过 Ollama、llama.cpp 提供的本地 API进行集成。由于它定义了清晰的协议为这些本地服务编写一个适配器是完全可行的。未来随着 Apple 平台自身 AI 能力的增强如 Core ML 对更大模型的支持LLM.swift 也可能演变为一个统一的抽象层让开发者可以无缝地在“云端强大模型”和“端侧隐私模型”之间进行切换根据任务需求、网络状况和隐私要求选择最合适的执行方式。这将是移动端 AI 应用的一个强大范式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2579674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…