1. Обзор
В этой лабораторной работе вы узнаете, как добавить мощные функции поиска в своё приложение, используя поиск по векторному сходству в Firestore . Вы реализуете функцию семантического поиска для приложения для создания заметок, написанного на Swift и SwiftUI.
Чему вы научитесь
- Как установить расширение Vector Search с Firestore для вычисления векторных вложений.
- Как вызвать функции Firebase Cloud из приложения Swift.
- Как предварительно фильтровать данные на основе вошедшего в систему пользователя.
Что вам понадобится
- Xcode 15.3
- Пример кода для практического занятия. Вы скачаете его на следующем этапе практического занятия.
2. Создайте и настройте проект Firebase.
Для использования расширения Firebase Vector Search вам потребуется проект Firebase. В этой части практикума вы создадите новый проект Firebase и активируете необходимые сервисы, такие как Cloud Firestore и Firebase Authentication.
Создать проект Firebase
- Войдите в консоль Firebase, используя свою учетную запись Google.
- Нажмите кнопку, чтобы создать новый проект, а затем введите имя проекта (например,
Firestore Vector Search Codelab
). - Нажмите «Продолжить» .
- При появлении соответствующего запроса ознакомьтесь с условиями Firebase и примите их, а затем нажмите кнопку «Продолжить» .
- (Необязательно) Включите помощь ИИ в консоли Firebase (так называемая «Gemini в Firebase»).
- Для этой лабораторной работы вам не понадобится Google Analytics, поэтому отключите опцию Google Analytics.
- Нажмите «Создать проект» , дождитесь завершения подготовки проекта, а затем нажмите «Продолжить» .
Дополнительную информацию о проектах Firebase см. в разделе Понимание проектов Firebase .
Обновите свой тарифный план Firebase
Чтобы использовать Firebase Extensions и их базовые облачные сервисы, ваш проект Firebase должен быть включен в тарифный план с оплатой по мере использования (Blaze) , что означает, что он должен быть связан с учетной записью Cloud Billing .
- Для учетной записи Cloud Billing требуется способ оплаты, например кредитная карта.
- Если вы новичок в Firebase и Google Cloud, проверьте, имеете ли вы право на кредит в размере 300 долларов США и бесплатную пробную учетную запись Cloud Billing .
- Если вы выполняете эту практическую работу в рамках мероприятия, узнайте у организатора, доступны ли какие-либо облачные кредиты.
Чтобы обновить свой проект до плана Blaze, выполните следующие действия:
- В консоли Firebase выберите обновление вашего плана .
- Выберите тарифный план Blaze. Следуйте инструкциям на экране, чтобы подключить аккаунт Cloud Billing к своему проекту.
Если вам потребовалось создать учетную запись Cloud Billing в рамках этого обновления, вам может потребоваться вернуться к процессу обновления в консоли Firebase, чтобы завершить обновление.
Включите и настройте продукты Firebase в консоли
Приложение, которое вы создаете, использует несколько продуктов Firebase, доступных для приложений Apple:
- Аутентификация Firebase , позволяющая пользователям легко входить в ваше приложение.
- Cloud Firestore для сохранения структурированных данных в облаке и мгновенного получения уведомлений об изменении данных.
- Правила безопасности Firebase для защиты вашей базы данных.
Некоторые из этих продуктов требуют специальной настройки или должны быть включены с помощью консоли Firebase.
Включить анонимную аутентификацию для аутентификации Firebase
Это приложение использует анонимную аутентификацию , позволяя пользователям начать работу с приложением без необходимости создания учётной записи. Это обеспечивает простой и быстрый процесс регистрации. Подробнее об анонимной аутентификации (и о том, как перейти на именной аккаунт) см. в разделе «Рекомендации по анонимной аутентификации» .
- На левой панели консоли Firebase нажмите «Сборка» > «Аутентификация» . Затем нажмите « Начать» .
- Теперь вы находитесь на панели аутентификации, где можете видеть зарегистрированных пользователей, настраивать поставщиков входа и управлять настройками.
- Выберите вкладку «Способ входа» (или нажмите здесь, чтобы перейти непосредственно на вкладку).
- В параметрах поставщика выберите «Анонимный» , переведите переключатель в положение «Включить» , а затем нажмите «Сохранить» .
Настройка Cloud Firestore
Это приложение Swift использует Cloud Firestore для сохранения заметок.
Вот как настроить Cloud Firestore в вашем проекте Firebase:
- На левой панели консоли Firebase разверните пункт «Сборка» , а затем выберите «База данных Firestore» .
- Нажмите Создать базу данных .
- Оставьте идентификатор базы данных равным
(default)
. - Выберите местоположение вашей базы данных, затем нажмите «Далее» .
Для настоящего приложения вам нужно выбрать местоположение, близкое к вашим пользователям. - Нажмите «Начать в тестовом режиме» . Ознакомьтесь с отказом от ответственности о правилах безопасности.
Далее в этой лабораторной работе вы добавите правила безопасности для защиты своих данных. Не распространяйте и не публикуйте приложение, не добавив правила безопасности для своей базы данных. - Нажмите «Создать» .
Настройка облачного хранилища для Firebase
Веб-приложение использует облачное хранилище для Firebase для хранения, загрузки и обмена изображениями.
Вот как настроить облачное хранилище для Firebase в вашем проекте Firebase:
- На левой панели консоли Firebase разверните Сборка , а затем выберите Хранилище .
- Нажмите « Начать» .
- Выберите местоположение для контейнера хранения по умолчанию.
Бакеты вUS-WEST1
,US-CENTRAL1
иUS-EAST1
могут воспользоваться тарифом «Всегда бесплатно» для Google Cloud Storage. Бакеты во всех остальных регионах следуют тарифам и условиям использования Google Cloud Storage . - Нажмите «Начать в тестовом режиме» . Ознакомьтесь с отказом от ответственности о правилах безопасности.
Далее в этой лабораторной работе вы добавите правила безопасности для защиты своих данных. Не распространяйте и не публикуйте приложение, не добавив правила безопасности для вашего контейнера хранилища . - Нажмите «Создать» .
3. Подключите мобильное приложение.
В этом разделе практикума вы загрузите исходный код простого приложения для создания заметок и подключите его к только что созданному вами проекту Firebase.
Загрузите пример приложения
- Перейдите по адресу https://github.com/FirebaseExtended/codelab-firestore-vectorsearch-ios и клонируйте репозиторий на свой локальный компьютер.
- Откройте проект Notes.xcodeproj в Xcode.
Подключите приложение к вашему проекту Firebase
Чтобы ваше приложение могло получить доступ к сервисам Firebase, необходимо настроить его в консоли Firebase. Вы можете подключить несколько клиентских приложений к одному проекту Firebase. Например, если вы создаёте приложение для Android или веб-приложение, их следует подключить к одному проекту Firebase.
Дополнительную информацию о проектах Firebase см. в разделе Понимание проектов Firebase .
- В консоли Firebase перейдите на страницу обзора вашего проекта Firebase.
- Нажмите на значок iOS+, чтобы добавить свое приложение iOS.
- На экране добавления Firebase в приложение Apple вставьте идентификатор пакета из проекта Xcode ( com.google.firebase.codelab.Notes ).
- При желании вы можете ввести псевдоним приложения ( Notes для iOS ).
- Нажмите «Зарегистрировать приложение», чтобы перейти к следующему шагу.
- Загрузите файл GoogleServices-Info.plist .
- Перетащите файл GoogleServices-Info.plist в папку Notes вашего проекта Xcode. Удобнее всего поместить его под файл Assets.xcassets .
- При необходимости выберите Копировать элементы , убедитесь, что в поле Добавить к объектам выбран целевой объект Примечания , и нажмите Готово .
- В консоли Firebase теперь можно выполнить оставшуюся часть процесса настройки: в примере, который вы скачали в начале этого раздела, уже установлен Firebase Apple SDK и настроена инициализация. Завершить процесс можно, нажав «Продолжить в консоли» .
Запустите приложение
Пришло время опробовать приложение!
- Вернувшись в Xcode, запустите приложение в симуляторе iOS. В раскрывающемся списке «Назначения запуска» сначала выберите один из симуляторов iOS.
- Затем нажмите кнопку «Выполнить» или сочетание клавиш ⌘ + R.
- После успешного запуска приложения на симуляторе добавьте несколько заметок.
- В консоли Firebase перейдите в браузер данных Firestore, чтобы увидеть новые документы, создаваемые по мере добавления новых заметок в приложение.
4. Установите расширение Vector Search with Firestore.
В этой части лабораторной работы вы установите расширение Vector Search с Firestore и настроите его в соответствии с требованиями приложения для создания заметок, над которым вы работаете.
Начать установку расширения
- Оставаясь в разделе Firestore, нажмите на вкладку Расширения .
- Нажмите «Explore Extensions Hub».
- Введите «вектор».
- Нажмите «Поиск векторов с расширением Firestore».
Вы перейдете на страницу сведений о расширении, где сможете подробнее прочитать о нем, о том, как оно работает, какие службы Firebase ему требуются и как его настроить.
- Нажмите «Установить» в консоли Firebase .
- Вам будет представлен список всех ваших проектов.
- Выберите проект, который вы создали на первом этапе этой лабораторной работы.
Настройте расширение
- Проверьте включенные API и созданные ресурсы.
- Включите необходимые службы.
- После включения всех служб нажмите кнопку Далее .
- Проверьте доступ, предоставленный этому расширению.
- Настройте расширение:
- Выберите Vertex AI в качестве LLM
- Путь сбора : заметки
- Лимит запросов по умолчанию : 3
- Имя поля ввода : текст
- Имя выходного поля: встраивание
- Имя поля статуса: * *статус*
- Встроить существующие документы : Да
- Обновить существующие документы : Да
- Расположение облачной функции : us-central1
- Нажмите «Установить расширение» , чтобы завершить установку.
Это может занять пару минут. Пока вы ждёте завершения установки, можете перейти к следующему разделу руководства и ознакомиться с дополнительной информацией о векторных вложениях.
5. Предыстория
Пока вы ждете окончания установки, вот некоторая справочная информация о том, как работает расширение Vector Search with Firestore.
Что такое векторы, вложения и векторные базы данных?
- Векторы — это математические объекты, представляющие величину и направление величины. Их можно использовать для представления данных, упрощающего сравнение и поиск.
- Эмбеддинги — это векторы, представляющие значение слова или фразы. Они создаются путём обучения нейронной сети на большом корпусе текстов и изучения взаимосвязей между словами.
- Векторные базы данных оптимизированы для хранения и поиска векторных данных. Они обеспечивают эффективный поиск ближайших соседей — процесс нахождения векторов, наиболее похожих на вектор запроса.
Как работает поиск векторов?
Поиск по вектору основан на сравнении вектора запроса со всеми векторами в базе данных. Векторы, наиболее похожие на вектор запроса, возвращаются в качестве результатов поиска.
Сходство между двумя векторами можно измерить с помощью различных метрик расстояния. Наиболее распространённой метрикой расстояния является косинусное сходство, которое измеряет угол между двумя векторами.
6. Попробуйте расширение поиска векторов Firestore.
Прежде чем использовать расширение Vector Search с Firestore в приложении iOS, которое вы загрузили ранее в этой практической работе, вы можете опробовать расширение в консоли Firebase.
Прочитать документацию
Расширения Firebase включают документацию по принципу работы.
- После завершения установки расширения нажмите кнопку « Начать» .
- Ознакомьтесь со вкладкой «Как работает это расширение» — там объясняется:
- как вычислить вложения для документов, добавляя их в коллекцию
notes
, - как сделать запрос к индексу, вызвав вызываемую функцию
ext-firestore-vector-search-queryCallable
, - или как выполнить запрос к индексу, добавив документ запроса в коллекцию
_firestore-vector-search/index/queries
. - Здесь также объясняется, как настроить пользовательскую функцию встраивания — это полезно, если ни одна из LLM, поддерживаемых расширением, не соответствует вашим требованиям, и вы хотели бы использовать другую LLM для вычисления встраиваний.
- как вычислить вложения для документов, добавляя их в коллекцию
- Нажмите ссылку на панель управления Cloud Firestore , чтобы перейти к вашему экземпляру Firestore.
- Перейдите к документу
_firestore-vector-search/index
. Он должен показать, что расширение завершило вычисление векторных представлений для всех документов заметок, созданных вами на предыдущем этапе этой практической работы. - Чтобы убедиться в этом, откройте один из документов заметок, и вы увидите дополнительное поле с именем
embedding
типаvector<768>
, а также полеstatus
.
Создать образец документа
Вы можете создать новый документ в консоли Firebase, чтобы увидеть расширение в действии.
- Оставаясь в браузере данных Firestore, перейдите к коллекции
notes
и нажмите + Добавить документ в средней колонке. - Нажмите кнопку «Автоидентификация» , чтобы сгенерировать новый уникальный идентификатор документа.
- Добавьте поле
text
типа «Строка» и вставьте текст в поле «Значение» . Важно, чтобы это был не lorem ipsum или какой-либо другой случайный текст. Например, выберите новостную статью. - Нажмите «Сохранить» .
- Обратите внимание, как расширение добавляет поле статуса, указывающее на то, что оно обрабатывает данные.
- Через некоторое время вы должны увидеть новое
embedding
поля со значениемvector<768>
.
Выполнить запрос
Расширение Vector Search with Firestore имеет удобную функцию, которая позволяет вам делать запросы к индексу документа без необходимости подключения приложения.
- В разделе Firestore консоли Firebase перейдите к документу
_firestore-vector-search/index
- Нажмите + Начать сбор
- Создайте новую подколлекцию с именем
queries
- Создайте новый документ и укажите в поле
query
текст, встречающийся в одном из ваших документов. Этот вариант лучше всего подходит для семантических запросов, например, «Как сопоставить документы Firestore с помощью Swift» (при условии, что хотя бы одна из добавленных вами заметок содержит текст, обсуждающий эту тему). - Вы можете увидеть ошибку в статусе
- Это связано с отсутствием индекса. Чтобы настроить конфигурацию отсутствующего индекса, перейдите в консоль Google Cloud для вашего проекта, перейдя по этой ссылке , и выберите свой проект из списка.
- В Cloud Log Explorer теперь должно появиться сообщение об ошибке «FAILED_PRECONDITION: Отсутствует конфигурация векторного индекса. Создайте требуемый индекс с помощью следующей команды gcloud: ...»
- Сообщение об ошибке также содержит команду
gcloud
, которую необходимо выполнить для настройки отсутствующего индекса. - Выполните следующую команду в командной строке. Если на вашем компьютере не установлен интерфейс командной строки
gcloud
, следуйте инструкциям по его установке. Создание индекса занимает несколько минут. Ход процесса можно отслеживать на вкладке «Индексы» в разделе Firestore консоли Firebase.gcloud alpha firestore indexes composite create --project=INSERT-YOUR=PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding
- После настройки индекса вы можете создать новый документ запроса.
- Теперь в поле результатов вы должны увидеть список соответствующих идентификаторов документов.
- Скопируйте один из этих идентификаторов и вернитесь к коллекции
notes
. - Используйте сочетание клавиш ⌘+F для поиска скопированного вами идентификатора документа — этот документ лучше всего соответствует вашему запросу.
7. Реализуйте семантический поиск
Наконец, пришло время подключить ваше мобильное приложение к расширению Vector Search с Firestore и реализовать функцию семантического поиска, которая позволит вашим пользователям выполнять поиск в своих заметках с помощью запросов на естественном языке.
Подключите вызываемую функцию для выполнения запросов
Расширение Vector Search with Firestore включает облачную функцию, которую можно вызывать из мобильного приложения для запроса индекса, созданного ранее в этой практической работе. На этом этапе вы установите соединение между мобильным приложением и этой вызываемой функцией. Swift SDK Firebase включает API, упрощающие вызов удалённых функций.
- Вернитесь в Xcode и убедитесь, что вы находитесь в проекте, который вы клонировали на предыдущем этапе этой лабораторной работы.
- Откройте файл
NotesRepository.swift
. - Найдите строку, содержащую
private lazy var vectorSearchQueryCallable: Callable
= functions.httpsCallable("")
Чтобы вызвать вызываемую облачную функцию, вам необходимо указать имя функции, которую вы хотите вызвать.
- Перейдите в консоль Firebase для вашего проекта и откройте пункт меню «Функции» в разделе «Сборка» .
- Вы увидите список функций, установленных расширением.
- Найдите файл с именем
ext-firestore-vector-search-queryCallable
и скопируйте его имя. - Вставьте имя в код. Теперь оно должно выглядеть так:
private lazy var vectorSearchQueryCallable: Callable<String, String> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
Вызов функции запроса
- Найдите метод
performQuery
- Вызовите вызываемую функцию, вызвав
let result = try await vectorSearchQueryCallable(searchTerm)
Поскольку это удаленный вызов, он может завершиться неудачей.
- Добавьте базовую обработку ошибок, чтобы отлавливать все ошибки и регистрировать их в консоли Xcode.
private func performQuery(searchTerm: String) async -> [String] { do { let result = try await vectorSearchQueryCallable(searchTerm) return [result] } catch { print(error.localizedDescription) return [] } }
Подключите пользовательский интерфейс
Чтобы пользователи могли искать свои заметки, вы добавите строку поиска на экран списка заметок. Когда пользователь вводит поисковый запрос, вам нужно вызвать метод performQuery
реализованный на предыдущем шаге. Благодаря модификаторам searchable
и представления task
в SwiftUI, это займёт всего пару строк кода.
- Сначала откройте
NotesListScreen.swift
- Чтобы добавить поле поиска в список, добавьте модификатор вида
.searchable(text: $searchTerm, prompt: "Search")
непосредственно над строкой.navigationTitle("Notes")
- Затем вызовите функцию поиска, добавив следующий код чуть ниже:
.task(id: searchTerm, debounce: .milliseconds(800)) {
await notesRepository.semanticSearch(searchTerm: searchTerm)
}
Этот фрагмент кода вызывает ваш метод semanticSearch
асинхронно. Устанавливая тайм-аут в 800 миллисекунд, вы указываете модификатору задачи отложить ввод пользователя на 0,8 секунды. Это означает, что semanticSearch
будет вызван только после того, как пользователь прервёт ввод более чем на 0,8 секунды.
Теперь ваш код должен выглядеть так:
...
List(repository.notes) { note in
NavigationLink(value: note) {
NoteRowView(note: note)
}
.swipeActions {
Button(role: .destructive, action: { deleteNote(note: note) }) {
Label("Delete", systemImage: "trash")
}
}
}
.searchable(text: $searchTerm, prompt: "Search")
.task(id: searchTerm, debounce: .milliseconds(800)) {
await notesRepository.semanticSearch(searchTerm: searchTerm)
}
.navigationTitle("Notes")
...
Запустите приложение
- Нажмите ⌘ + R (или кнопку «Запустить»), чтобы запустить приложение в iOS Simulator.
- Вы должны увидеть те же заметки, которые вы добавили в приложение ранее в этой кодовой лаборатории, а также любые заметки, которые вы добавили через консоль Firebase.
- Вы должны увидеть поле поиска в верхней части списка заметок .
- Введите термин, встречающийся в одном из добавленных вами документов. Этот вариант, опять же, лучше всего подходит для семантических запросов, например «Как вызвать асинхронные API Firebase из Swift» (при условии, что хотя бы одна из добавленных вами заметок содержит текст, посвященный этой теме).
- Вероятно, вы ожидаете увидеть результат поиска, но вместо этого список пуст, а консоль Xcode отображает сообщение об ошибке: «Функция была вызвана с недопустимым аргументом».
Это означает, что вы отправили данные в неправильном формате.
Проанализируйте сообщение об ошибке
- Чтобы узнать, в чем проблема, перейдите в консоль Firebase.
- Перейти в раздел «Функции»
- Найдите функцию
ext-firestore-vector-search-queryCallable
, откройте дополнительное меню, нажав на три вертикальные точки. - Выберите «Просмотреть журналы» , чтобы перейти к проводнику журналов.
- Вы должны увидеть ошибку.
Unhandled error ZodError: [
{
"code": "invalid_type",
"expected": "object",
"received": "string",
"path": [],
"message": "Expected object, received string"
}
]
Это означает, что вы отправили данные в неправильном формате.
Используйте правильные типы данных
Чтобы узнать, в каком формате расширение ожидает параметры, ознакомьтесь с документацией к расширению.
- Перейдите в раздел «Расширения» на консоли Firebase.
- Нажмите «Управление» ->
- В разделе «Как работает это расширение» вы найдете спецификацию входных и выходных параметров.
- Вернитесь в Xcode и перейдите к
NotesRepository.swift
- Добавьте следующий код в начало файла:
private struct QueryRequest: Codable { var query: String var limit: Int? var prefilters: [QueryFilter]? } private struct QueryFilter: Codable { var field: String var `operator`: String var value: String } private struct QueryResponse: Codable { var ids: [String] }
QueryRequest
соответствует структуре входного параметра, ожидаемого расширением, согласно документации к расширению. Он также содержит вложенный атрибутprefilter
, который понадобится вам позже.QueryResponse
соответствует структуре ответа расширения. - Найдите спецификацию вызываемой функции и обновите типы входных и выходных данных.
private lazy var vectorSearchQueryCallable: Callable<QueryRequest, QueryResponse> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
- Обновить вызов вызываемой функции в
performQuery
private func performQuery(searchTerm: String) async -> [String] { do { let queryRequest = QueryRequest(query: searchTerm, limit: 2) let result = try await vectorSearchQueryCallable(queryRequest) print(result.ids) return result.ids } catch { print(error.localizedDescription) return [] } }
Запустите приложение еще раз.
- Запустите приложение еще раз.
- Введите поисковый запрос, содержащий термины, включенные в одну из ваших заметок.
- Теперь вы должны увидеть отфильтрованный список заметок.
Предварительная фильтрация пользовательских данных
Прежде чем пуститься в пляс в знак празднования , хочу сказать, что в текущей версии приложения есть проблема: набор результатов содержит данные по всем пользователям.
Вы можете убедиться в этом, запустив приложение в другом симуляторе и добавив новые документы. Новые документы будут отображаться только в этом симуляторе. Если вы снова запустите приложение в другом симуляторе, вы увидите только документы, созданные в первый раз.
Если вы выполните поиск, вы заметите, что вызов vectorSearchQueryCallable
возвращает идентификаторы документов, которые могут принадлежать другому пользователю. Чтобы предотвратить это, необходимо использовать предварительный фильтр .
В performQuery
обновите код следующим образом:
let prefilters: [QueryFilter] = if let uid = user?.uid {
[QueryFilter(field: "userId", operator: "==", value: uid)]
}
else {
[]
}
let queryRequest = QueryRequest(query: searchTerm,
limit: 2,
prefilters: prefilters)
Это позволит предварительно отфильтровать данные на основе идентификатора вошедшего в систему пользователя. Как и следовало ожидать, для этого требуется обновить индекс Firestore.
Выполните следующую команду из командной строки, чтобы определить новый индекс Firestore, включающий как userId
, так и векторные внедрения в поле embedding
.
gcloud alpha firestore indexes composite create --project=INSERT-YOUR-PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=order=ASCENDING,field-path=userId --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding
После завершения построения индекса запустите приложение еще раз, чтобы убедиться, что оно работает так, как и ожидалось.
8. Поздравления
Поздравляем с успешным завершением этой лабораторной работы!
В этой лабораторной работе вы узнали, как:
- Настройте базу данных Cloud Firestore с включенным семантическим поиском.
- Создайте простое приложение SwiftUI для взаимодействия с базой данных.
- Реализуйте панель поиска, используя модификатор представления с возможностью поиска и модификатор задач SwiftUI.
- Вызовите облачную функцию для выполнения семантического поиска в базе данных, используя интерфейс Callable Firestore SDK.
Благодаря знаниям, полученным в ходе этой лабораторной работы, вы теперь сможете создавать мощные приложения, использующие возможности семантического поиска Cloud Firestore для предоставления пользователям более интуитивно понятного и эффективного опыта поиска.
Чтобы узнать больше о новом векторном поле Firestore и о том, как вычислять векторные вложения, ознакомьтесь с документацией .