View in English

  • Apple 开发者
    • 入门汇总

    探索“入门汇总”

    • 概览
    • 学习
    • Apple Developer Program

    及时了解最新动态

    • 最新动态
    • 开发者你好
    • 平台

    探索“平台”

    • Apple 平台
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    • App Store

    精选

    • 设计
    • 分发
    • 游戏
    • 配件
    • 网页
    • Home
    • CarPlay 车载
    • 技术

    探索“技术”

    • 概览
    • Xcode
    • Swift
    • SwiftUI

    精选

    • 辅助功能
    • App Intents
    • Apple 智能
    • 游戏
    • 机器学习与 AI
    • 安全性
    • Xcode Cloud
    • 社区

    探索“社区”

    • 概览
    • “与 Apple 会面交流”活动
    • 社区主导的活动
    • 开发者论坛
    • 开源

    精选

    • WWDC
    • Swift Student Challenge
    • 开发者故事
    • App Store 大奖
    • Apple 设计大奖
    • Apple Developer Centers
    • 文档

    探索“文档”

    • 文档库
    • 技术概述
    • 示例代码
    • 《人机界面指南》
    • 视频

    发布说明

    • 精选更新
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • Apple tvOS
    • Xcode
    • 下载

    探索“下载”

    • 所有下载
    • 操作系统
    • 应用程序
    • 设计资源

    精选

    • Xcode
    • TestFlight
    • 字体
    • SF Symbols
    • Icon Composer
    • 支持

    探索“支持”

    • 概览
    • 帮助指南
    • 开发者论坛
    • “反馈助理”
    • 联系我们

    精选

    • 《开发者账户帮助》
    • 《App 审核指南》
    • 《App Store Connect 帮助》
    • 即将实行的要求
    • 协议和准则
    • 系统状态
  • 快速链接

    • 活动
    • 新闻
    • 论坛
    • 示例代码
    • 视频
 

视频

打开菜单 关闭菜单
  • 专题
  • 所有视频
  • 关于

更多视频

  • 简介
  • 概要
  • 转写文稿
  • 代码
  • 使用 Core Spotlight 进行 LLM 搜索

    使用 SpotlightSearchTool 和 LanguageModelSession,将基础搜索升级为检索增强系统。探索 Core Spotlight 集成功能、委托式数据填充模式,以及元数据质量对搜索结果的影响。了解如何使用自定 PipelineStages 执行情感分析等任务。探索相关最佳做法,以便在你的 App 中建立索引,并构建灵活又贴合情境的搜索体验。

    章节

    • 0:00 - Introduction
    • 1:41 - Grounding answers with Spotlight tool-calling
    • 4:00 - Configure and add SpotlightSearchTool
    • 6:44 - Displaying results and partial replies
    • 6:46 - Provide full items with an index delegate
    • 8:12 - Customizing with guidance profiles
    • 11:02 - Reference resolution with a contact resolver
    • 11:24 - Custom pipeline stages
    • 12:47 - Evaluating response quality
    • 15:53 - Next steps

    资源

    • Spotlight search tool
    • Making your indexed content available to Foundation Models
      • 高清视频
      • 标清视频
  • 搜索此视频…

    大家好,我是 Jennifer, 来自 Spotlight 工程团队。 今年,我们将 搜索功能提升到全新水平, 借助 Foundation Models 和 Core Spotlight。 您可以在应用中 构建丰富的对话体验, 只需让您的 应用内容 供大型语言模型 进行推理和响应生成即可。 我来自加利福尼亚州,这里 有许多美丽的徒步路线。 我一直在慢慢探索 其中一些最美的小径, 于是我想开发 一款应用来辅助记录。 在我的徒步路线应用中,我已经 可以浏览州立公园和各种小径。 完成一段路线后, 我喜欢记下 徒步中最享受的部分。 但如果能向语言模型 询问 我已经完成的所有徒步路线, 甚至询问我应该尝试的新路线,那就太棒了。 Foundation Models 框架让这一切变得轻松。 通过在应用中引入 语言模型会话, 我可以提出各种问题, 模型仅凭自身的世界知识 便能作出解答。 但我真正想要的, 是关于应用中已知路线的答案。 这正是 Spotlight 能发挥作用的地方。 徒步路线应用 已将所有精彩路线建立索引, 存储在 Core Spotlight 搜索索引中。 为了帮助模型回答 关于特定路线的问题, 我们可以使用应用的 Core Spotlight 搜索索引, 通过 Foundation Models 框架 的工具调用来实现。 Foundation Models 中的 Tool 协议是一个强大的概念, 可用于 扩展模型的能力, 既可以为请求执行操作, 也可以查找模型生成响应 所需的上下文。

    工具通过声明 其参数和输出来运作, 同时附有描述 工具功能的说明。 当模型决定 需要使用某个工具时, 它会直接生成 调用该工具的参数, 并利用该输出 进行响应生成。 如果您还没有了解过, 有一些精彩的讲座值得关注, 例如《深入探讨 Foundation Models 框架》, 可以帮助您深入了解 工具调用的工作原理。 那么,如果我们有一个工具, 让模型生成搜索请求, 在应用的 Core Spotlight 索引上进行搜索,会怎样? 今天,我们将推出 SpotlightSearchTool。 这是一个采用工具协议的工具, 让语言模型能够直接搜索 Core Spotlight 中的应用内容, 以生成基于上下文的响应。 SpotlightSearchTool 可在 iOS、iPadOS、macOS 和 visionOS 上使用。

    在开始之前, 您需要确保应用已通过 Core Spotlight 捐献了可搜索内容。 请查看我们之前的讲座 《通过 Core Spotlight 支持语义搜索》, 其中介绍了如何向 Spotlight 捐献可搜索内容, 如何通过委托和重新索引扩展 管理捐献, 以及如何对项目属性 执行结构化搜索, 以及如何针对语义索引进行搜索。

    一旦您的应用向 Core Spotlight 捐献了可搜索项目, 或为 Apple Intelligence 建立了实体索引, 我们就可以开始了。 本视频内容丰富! 我们将展示如何提供 新的 SpotlightSearchTool 给您的语言模型会话。 然后,我们将探讨如何通过指导 自定义 SpotlightSearchTool, 知识提供程序, 以及专业功能。 最后,我们将探讨 评估模型响应的方法, 使用评估框架。 好,让我们开始吧。 首先,让我们来看看 SpotlightSearchTool 如何用于 基于上下文的响应生成。 在我们的徒步路线应用中, 我们已捐献了可搜索项目, 到代表徒步路线的 Spotlight 索引中。 每条路线都有元数据, 如路线名称和位置。 在某些徒步路线上, 还有一些个人详情, 例如完成徒步的日期, 以及我写的关于 那些徒步经历的笔记。 如果我想问:我去过哪些徒步路线? 模型需要按属性搜索项目, 如完成日期 和位置, 才能给出答案。 那么,让我们将 这个功能集成到应用中。 采用 SpotlightSearchTool 时, 我们需要关注三件事。

    我们需要配置工具, 以便执行我们希望 模型进行的搜索。 然后,我们需要为模型 添加额外的上下文, 在搜索进行时, 以获得最佳响应。 最后, 我们将探索在应用用户界面中 显示结果的不同方式。

    配置工具与直接执行 Spotlight 查询差别不大。 我们首先导入 CoreSpotlight 和 FoundationModels。 然后,只需一行代码,工具即可 搜索您应用的 Core Spotlight 索引。 您也可以为 SpotlightSearchTool 提供自定义配置。 在这里,我们指定了一个 FileSource, 以对应用沙盒中的 文件路径执行搜索。 接下来,您需要为应用 选择合适的模型, 无论是 SystemLanguageModel 还是您选择的其他模型, 都可以通过新的 Model Provider API 来实现。 选定模型后, 将新的 SpotlightSearchTool 实例 添加到 LanguageModelSession, 即可开始获取响应。 这感觉就像魔法, 但响应遵循 工具调用和生成的路径。 对于"我去过哪些徒步路线?" 这样的问题, 模型可能首先决定 需要使用 SpotlightSearchTool, 模型将使用 生成的查询调用工具, Spotlight 将执行该查询, 并返回 结果集的描述, 模型将对该输出进行推理, 并生成最终响应。

    现在,当我问: 我去过哪些徒步路线?时, 模型可以生成基于 应用内容的答案。

    您可能会注意到,在某些响应中, 模型无法看到 所有的元数据, 这些元数据是为项目捐献的。 这是因为 Spotlight 索引中 的某些元数据, 如文本内容和 HTML, 以高度压缩的格式存储, 可供搜索, 但无法以 语言模型可读的方式恢复。 在这种情况下,您需要考虑 为项目提供额外的元数据, 在 SpotlightSearchTool 执行搜索时。 如果您的应用向 Core Spotlight 捐献了可搜索内容, 您应该已经熟悉 索引委托协议。 您的应用需要在 CSSearchableIndex 上设置索引委托, 以处理重新索引请求, 例如 Spotlight 需要 执行迁移或恢复时。 对于 SpotlightSearchTool, 我们向委托添加了一个方法, 以恢复完整的 CSSearchableItem, 通过其唯一标识符。 这允许模型 有效管理数百万个 结果的响应。 在您的索引委托上, 只需采用新的 searchableItems(forIdentifiers:), 返回完整的 CSSearchableItem。

    如果您的应用有 不适合捐献用于搜索的元数据, 但可能对 模型推理有用, 此时可以在项目上 设置额外的属性, 供模型查看。

    现在我们已经配置好 工具以执行搜索, 我们需要考虑 如何显示结果 以及在用户界面中展示响应。 会话响应是对 结果集的简洁描述。 在助手风格的界面中, 这通常是应用 希望显示的内容。 但搜索结果也可以直接从 SpotlightSearchTool 本身获取。 对于列表式显示,这是 访问可搜索项目的最佳方式, 尤其是当结果集较大时。 搜索回复在搜索过程中 分批返回结果, 因此可以使用查询标记 管理对话流, 确保用户界面 与模型保持同步。 要从 SpotlightSearchTool 访问结果, 您的应用可以 等待搜索回复, 并检查回复内容中的 CSSearchableItem。 搜索回复以 异步事件序列的形式到达, 每个回复可能包含一批结果, 直到工具调用完成。 请注意,对于任何给定的响应, 模型可能会多次 调用 SpotlightSearchTool, 然后才生成最终响应。 因此,请对每个回复 使用 queryToken, 以确定用户界面 何时应刷新。

    SpotlightSearchTool 提供了丰富的搜索能力, 从文本语义搜索, 到元数据结构化搜索, 如日期、人员、位置等。 但根据您选择的 语言模型, 您可能需要 自定义 SpotlightSearchTool, 既针对模型, 也针对您的应用内容。 有几种方法可以 自定义 SpotlightSearchTool。 指导配置文件可用于 限定工具的搜索能力范围。

    为工具提供世界知识 有助于参考解析。 而实现自定义管道阶段, 可以改善模型对 应用内容的推理。 SpotlightSearchTool 向模型 提供其全部搜索能力, 用于引导生成。 但指导配置文件可以将该指导 范围缩小到应用所需的内容。 徒步路线应用 不捐献人员关系, 因此,关于如何搜索 作者和收件人的指导, 对于有限上下文模型 可以跳过。 若要有选择性地启用 人员和日期等搜索能力的指导, 请使用 GuidanceProfile。 您甚至可以指定 确切的元数据属性列表, 供模型在搜索时参考。 然后使用配置文件 设置动态指导级别, 在创建 SpotlightSearchTool 时。 设备端模型的 上下文大小更受限, 因此最好使用针对性指导 以实现更简单的搜索能力。 参考解析是 您的应用的另一种方式, 以提供搜索索引中 不直接可用的上下文。 举个例子,如果徒步路线应用 确实捐献了人员关系, 使用该应用的人可能会 询问路线上的其他参与者。 在这种情况下,模型需要知道 提示中"该人"指的是谁。 如果应用已知道 该人是谁, 使用联系人解析器帮助工具 筛选到正确的结果集。 contactResolver 应返回 与用户身份相关的 任何联系人信息, 可与搜索索引中的 元数据进行匹配。

    最后,您的应用可以利用 自定义管道阶段, 进一步推进文档推理。 对于非常复杂的请求, 语言模型可能会 放弃简单的搜索查询, 而选择管道搜索。 管道搜索将 对索引的查询汇聚在一起, 加上对结果集的计算, 以实现最高效率。 我可以询问: 今年我走过了多少条路线, 每个月 平均走了多少英里? 现在,模型可以 执行简单搜索, 并在内存中保持计数 来回答问题。 或者,如果结果集 可能很大, SpotlightSearchTool 允许模型请求 Spotlight 运行一系列 搜索和计算阶段的管道。 通过管道搜索, 模型可以将这个复杂查询 分解为一系列步骤。 模型可能会生成一个 搜索已完成徒步的请求, 以及一个按月 构建表格的计数阶段, 然后是一个计算 所有计数平均值的阶段。 管道阶段允许工具执行 高效的计算或转换, 代表模型对 搜索结果集进行处理。 您的应用可以通过注册 自己的自定义阶段来参与其中。 管道阶段遵循 Generable 协议, 因此模型将根据用户的提示 按需生成阶段。 每当生成一个阶段时, 在适当时候,模型可以选择 将数据返回给应用。

    Foundation Models 深入探讨讲座 有一个关于引导生成的精彩部分, 以及 Generable 类型, 我强烈推荐。 让我们再来看看 徒步路线应用。 某些路线包含关于 每次徒步经历的个人笔记, 所以我可能会想问: 我记得在某些徒步中感到非常快乐。 是哪些路线呢? 模型本身可以对我的快乐程度 做出最佳猜测, 只需阅读我的笔记。

    或者,应用可以注册 一个自定义阶段, 计算每个项目的 快乐分数, 让模型生成响应, 仅基于计算出的 最高分结果。 要构建一个计算 快乐分数的自定义阶段, 我们需要以 CSSearchableItem 为输入, 并返回评分版本作为输出。 分数可以通过运行 情感分析模型来计算, 针对项目的笔记属性, 或通过某些其他自定义逻辑, 或许将被评为 5 星的 徒步纳入考量。 由于这是一个 Generable 类型, 我们可以使用 Guides 添加属性, 告知模型应优先 选择哪些结果。 然后,只需将阶段添加到 工具的配置中即可注册该阶段。 还有一件事: 还记得 SpotlightSearchTool 如何返回 包含搜索结果的回复用于显示吗? 模型可能会决定发送回 包含管道阶段 输出数据的搜索回复, 作为另一种部分结果。 从汇总计数和表格, 到自由文本 或计算的数值, 您的应用可以显示 部分或全部这些数据类型。 每个回复都附带一个便捷的 LLM 生成标签, 描述内容, 为您的应用用户界面 提供最大灵活性。 有如此多的自定义选项, 从我们选择的模型, 到我们应用 捐献的可搜索内容, 到指导级别和自定义推理, 我们如何从整体上验证, 模型在我们应用中的 响应效果?

    评估框架可以在 几个重要方面帮助我们。 我们不仅可以快速构建评估, 查看模型调用 工具的效果, 以及响应的质量; 我们还可以快速迭代 应用的可搜索内容, 与 SpotlightSearchTool 本身的 不同指导配置文件配合使用。 评估框架提供了 一些出色的 API, 用于构建端到端 评估套件, 从大规模数据集生成, 到使用自定义指标 运行评估和报告。 有一些精彩的讲座深入介绍了 样本数据生成 API, 以及关于为智能体应用 创建稳健评估的视频, 是入门的绝佳资源, 用于评估使用工具调用 的模型响应。 就我们的目的而言, 我们将专注于结果覆盖率, 作为评估徒步路线 对话体验的方式。 我们想知道,给定一个在 Core Spotlight 中建立索引的数据集, 模型基于我们期望找到的项目 生成响应的效果如何。 我们首先定义一个采用 ModelSampleProtocol 的数据集。 我们的 TrailRequest 已包含 自然语言输入, 这是人们可能在我们应用中 询问路线的方式, 输出是语言模型响应, 以及对 请求轨迹的预期。 我们还将添加一组 可搜索项目的唯一标识符, 我们期望工具为该提示 返回这些标识符。

    如果我们有真实数据可以测试, 那非常好; 但如果没有,我们可以使用 样本生成 API, 根据提示生成数据。 让我们在 Xcode 中看看这个。 对于我们的评估, 我们可以定义一组徒步路线, 以及我们应用预计向 Core Spotlight 捐献的元数据。 然后,我们将构建一组 种子样本,用于我们的评估。 样本可以以任何 Codable 格式序列化, JSON 非常适合这个用途。 我们的样本包括查询 和项目标识符集合, 我们期望这些标识符 在搜索中被返回。 我们还可以提供一个 样本响应,稍后使用, 与模型的实际响应 进行质量比较。 在命令行工具中使用 样本生成 API, 我可以将这个种子集 扩展为更多变体, 以广泛覆盖人们可能 询问路线的方式。

    下一步是定义包含 指标和轨迹的评估。 对于我们的样本, 我们期望响应的轨迹 包含对 SpotlightSearchTool 的调用以执行查询, 以下是我们可能 定义该预期的方式。 以下是评估流程的概述, 考虑最终响应中包含了 多少预期项目。 在我们的测试目标中, 我们的评估将从生成的数据集中 加载路线项目和样本。 然后,我们将路线项目 捐献给 Core Spotlight, 并为此评估配置 SpotlightSearchTool。 评估运行完成后, 我们可以为包含的 任何指标设置预期, 例如结果覆盖率。

    这只是构建 全面评估的开始, 将帮助您为应用 打造最佳体验。

    对于 Foundation Models 来说,这是重要的一年, 我们希望您能充分利用它。 下载我们的示例代码, 查看徒步路线应用的实际效果。 尝试向应用添加您自己的 自定义功能,真正了解可能性。 您可能还需要添加 自己的评估套件, 从评估智能体深入探讨中 获取一些灵感。 请记住,我们不再 编写搜索查询了。 我们提供内容, 让智能来完成其余的工作。

    • 0:59 - Ask the model with a Foundation Models session

      let response = try await session.respond(to: "What are some nice hikes near water?")
    • 4:20 - Set up SpotlightSearchTool

      // Set up SpotlightSearchTool
        import CoreSpotlight
        import FoundationModels
      
        // In one line, the tool is ready to search your app's Core Spotlight index
        let tool = SpotlightSearchTool()
      
        // Or provide a custom configuration — e.g. search file paths in your app's sandbox
        let fileTool = SpotlightSearchTool(
            configuration: .init(
                sources: [
                    .files
                ]
            )
        )
    • 4:50 - Add SpotlightSearchTool to a session

      // Add SpotlightSearchTool to a session
        import CoreSpotlight
        import FoundationModels
        
        let tool = SpotlightSearchTool()
      
        let session = LanguageModelSession(model: model, tools: [tool], instructions: instructions)
      
        let response = try await session.respond(to: "What hikes have I gone on?")
    • 6:24 - Implement an index delegate

      // Implement an index delegate
        import CoreSpotlight
      
        class IndexDelegate: NSObject, CSSearchableIndexDelegate {
      
            // Called when the index requests searchable items for the provided identifiers
            func searchableItems(forIdentifiers identifiers: [String]) async -> [CSSearchableItem] {
                let entries = await mystore.fetchEntries(ids: identifiers)
                return entries.map { makeSearchableItem(from: $0) }
            }
        }
    • 7:37 - Track the query token for refresh

      // Track the query token for refresh
        import CoreSpotlight
        import FoundationModels
      
        let tool = SpotlightSearchTool()
      
        for await reply in tool.searchResults {
        
            if reply.queryToken != currentToken {
                // New query — start a new display section
                currentToken = reply.queryToken
            }
      
            switch reply.content {
            case .items(let searchItems):
            }
        }
    • 8:42 - Set a dynamic guidance profile

      // Set a dynamic guidance profile
        import CoreSpotlight
        import FoundationModels
      
        let profile = SpotlightSearchTool.GuidanceProfile(
            textMatch: true,
            dates: true,
            people: false,
            attributes: [.title, .altitude, .completionDate]
        )
      
        let tool = SpotlightSearchTool(
            configuration: .init(
                guide: .init(level: .dynamic(profile))
            )
        )
      
        // On-device models have smaller context — prefer focused guidance
        let focusedTool = SpotlightSearchTool(
            configuration: .init(
                guide: .init(level: .focused(.items))
            )
        )
    • 9:32 - Implement a ContactResolver

      // Implement a ContactResolver
        import CoreSpotlight
        import FoundationModels
      
        struct MyContactResolver: ContactResolver {
        
            func userIdentity() -> ResolvedContact {
                // Pull from whatever identity source your app has —
                // account profile, Contacts framework, sign-in session, etc.
                var contact = ResolvedContact(displayName: "Jane Doe")
                contact.emailAddresses = ["jane@example.com", "jdoe@work.com"]
                contact.names = ["Jane", "JD"]
                return contact
            }
        }
        
        tool.contactResolver = MyContactResolver()
    • 11:34 - Define a custom stage

      // Define a custom stage
        import CoreSpotlight
        import FoundationModels
      
        @Generable
        struct HappinessStage: CustomStage {
            static var name = "happiness"
            static var description = "Scores hike by how happy the author was"
            static var inputTypes: [SearchPipelineDataType] = [.items]
            static var outputTypes: [SearchPipelineDataType] = [.scoredItems]
      
            @Guide(description: "Minimum happiness score (0.0-1.0) to include in results")
            var threshold: Double?
      
            func execute(on input: SearchPipelineData) async throws -> SearchPipelineData {
                return SearchPipelineData(payload: .scoredItems(sorted))
            }
        }
      
        // Register the stage by adding it to the tool's configuration
        let tool = SpotlightSearchTool(configuration: .init(
            customStages: [.happinessBoost(threshold: 0.5)])
        )
    • 12:10 - Handle a reply data types

      // Handle a reply data types
        import CoreSpotlight
        import FoundationModels
      
        for await reply in tool.searchResults {
      
            let label = reply.label
            case .items(let searchItems):
            case .scoredItems(let scored):
            case .groupedItems(let groups):
            case .count(let count):
            case .table(let table):
            case .statistic(let statistic):
            case .text(let text):
                continue
            }   
        }
    • 13:47 - Define an evaluation dataset with ModelSampleProtocol

      // Evaluations
        import Evaluations
        
        struct TrailRequest: ModelSampleProtocol {
        
            typealias ExpectedValue = String                    // sample response
            typealias Expectation   = TrajectoryExpectation     
            
            var input:  ModelSampleInput
            var output: ModelSampleOutput<String, TrajectoryExpectation>
            
            var expectedIdentifiers: [String]
        }
    • 15:06 - Define the trajectory expectation

      // Evaluations
        import Evaluations
        
        TrajectoryExpectation(
            unordered: [
                ToolExpectation("searchSpotlight", arguments: [.keyOnly(argumentName: "query")])
            ]   
        )
    • 15:17 - Run the evaluation test —

      @Test("Trail search evaluation meets quality thresholds")
        func trailSearchEval() async throws {
        
            let items = try Self.loadItems()
            let samples = try Self.loadSamples()
            
            try await Self.indexDelegate.indexSearchableItems(items)
            let tool = Self.makeSearchTool()
            
            let evaluation = TrailSearchEvaluation(
                tool: tool,
                dataset: ArrayLoader(samples: samples)
            )   
            
            let result = try await evaluation.run()
            let coverageMean = result.aggregateValue(.mean(of: Metric("ResultCoverage")))
            #expect(coverageMean >= 0.5, "Result coverage should be at least 50% across queries")
        }
    • 0:00 - Introduction
    • Build conversational search by making app content available to a language model. Sets up the running example: a hiking trails app that browses state parks and trails and stores personal notes on completed hikes.

    • 1:41 - Grounding answers with Spotlight tool-calling
    • A LanguageModelSession answers broad questions from world knowledge, but to answer only about the app's hikes you ground it in the Core Spotlight index via the Foundation Models Tool protocol. Introduces SpotlightSearchTool (iOS, iPadOS, macOS, visionOS) and the prerequisite of donating searchable content.

    • 4:00 - Configure and add SpotlightSearchTool
    • Import CoreSpotlight and FoundationModels, create the tool (optionally with a custom configuration like a FileSource), choose a model (SystemLanguageModel or a Model Provider), and add the tool to a session. Walks the tool-call trajectory from query to grounded response.

    • 6:44 - Displaying results and partial replies
    • The session response suits an assistant-style UI, while the tool's searchable items suit a list UI. Search replies arrive as an async sequence of batched results; use the query token to know when to refresh, since the model may call the tool multiple times per response.

    • 6:46 - Provide full items with an index delegate
    • Some donated metadata is stored compactly and isn't readable by the model. Implement searchableItemsForIdentifiers on the CSSearchableIndexDelegate to recover the full CSSearchableItem on demand and attach extra attributes for the model to reason over.

    • 8:12 - Customizing with guidance profiles
    • SpotlightSearchTool exposes its full search capabilities for guided generation; a GuidanceProfile scopes that guidance to only what the app needs (such as specific attributes or a dynamic guide level), which matters for the smaller context of on-device models.

    • 11:02 - Reference resolution with a contact resolver
    • When a query references a person ("Who did I go hiking with?"), supply a ContactResolver that returns contact information matching the user's identity, so the tool can disambiguate and filter to the right results.

    • 11:24 - Custom pipeline stages
    • For complex requests the model can run a pipeline of search plus computation stages instead of a simple query. Register your own @Generable stages (such as a happiness-score stage over notes); the model generates stages on demand and may return computed data back to the app for display.

    • 12:47 - Evaluating response quality
    • Use the Evaluations framework to measure tool-calling and response quality. Define a dataset via ModelSampleProtocol with expected item identifiers and trajectory, expand seed samples with the Sample Generation APIs, and assert metrics like result coverage in a test.

    • 15:53 - Next steps
    • Download the hiking trails sample, add your own custom functionality and evaluation suite, and lean into the deep-dive sessions. The takeaway: stop writing search queries, provide the content and let intelligence do the rest.

Developer Footer

  • 视频
  • WWDC26
  • 使用 Core Spotlight 进行 LLM 搜索
  • 打开菜单 关闭菜单
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    打开菜单 关闭菜单
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    打开菜单 关闭菜单
    • 辅助功能
    • 配件
    • Apple 智能
    • App 扩展
    • App Store
    • 音频与视频 (英文)
    • 增强现实
    • 设计
    • 分发
    • 教育
    • 字体 (英文)
    • 游戏
    • 健康与健身
    • App 内购买项目
    • 本地化
    • 地图与位置
    • 机器学习与 AI
    • 开源资源 (英文)
    • 安全性
    • Safari 浏览器与网页 (英文)
    打开菜单 关闭菜单
    • 完整文档 (英文)
    • 部分主题文档 (简体中文)
    • 教程
    • 下载
    • 论坛 (英文)
    • 视频
    打开菜单 关闭菜单
    • 支持文档
    • 联系我们
    • 错误报告
    • 系统状态 (英文)
    打开菜单 关闭菜单
    • Apple 开发者
    • App Store Connect
    • 证书、标识符和描述文件 (英文)
    • 反馈助理
    打开菜单 关闭菜单
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program (英文)
    • Mini Apps Partner Program
    • News Partner Program (英文)
    • Video Partner Program (英文)
    • 安全赏金计划 (英文)
    • Security Research Device Program (英文)
    打开菜单 关闭菜单
    • 与 Apple 会面交流
    • Apple Developer Center
    • App Store 大奖 (英文)
    • Apple 设计大奖
    • Apple Developer Academies (英文)
    • WWDC
    阅读最近新闻。
    获取 Apple Developer App。
    版权所有 © 2026 Apple Inc. 保留所有权利。
    使用条款 隐私政策 协议和准则