研究開発部の堤と申します。今年9月にニューヨークで開催されたtry! Swift NYCというカンファレンスに参加してきました。
try! Swiftは2016年から東京・インド・ニューヨーク等で開催されている、Swiftのデベロッパーカンファレンスです。東京での開催時は毎回参加していますが 1、スピーカー・参加者ともに国際色豊か 2 なのが特徴です。
ニューヨーク版への参加は今回が初 3 でした。会期自体は9/5〜7の3日間あったのですが、9/3に iOSDCの登壇 があり、どうしても初日からの参加が難しかったため、2日目・3日目のワークショップからの参加となりました。
午前・午後それぞれ3時間、2日間で計4つのワークショップ枠があり、各時間枠の中で参加者が希望のものを選ぶ、という形式でした。
私が選んだのは以下の4つ。
- Bringing Existing Apps to visionOS: Adopting Accessible Features for Spatial Computing
- Talking to your data with Swift
- Working with language (models) on iOS
- The Next Dimension: Constructing the Apple Watch Store on visionOS
このうち、2つのワークショップの内容について紹介します。
Talking to your data with Swift
概要
try! Swift NYCのサイトにある概要を引用すると、こういう内容です。
In this workshop, you'll learn how to connect LLMs to an external data source to power your very own chatbot.
We'll cover:
- The fundamentals of retrieval augmented generation with the LLM APIs available today — the main architecture for the chatbot.
- A conceptual understanding of text embeddings and vector databases — that (alongisde LLMs) serve as the key infrastructure for the chatbot.
- An understanding of the limitations and safety of these techniques, and how to think about integrating them into your own iOS apps
実際のワークショップの内容は、 検索対象のテキストデータをOpenAIのEmbeddings APIでベクトル化しておき、クエリをベクトル化したものとのコサイン類似度を計算して関連するデータを抽出する(というのをSwiftで実装する)、というものでした 4。
要は独自データについてGPTに質問できるアプリをSwiftで書く、ということです。
学び
このワークショップが行われた9/5以降にChatGPTのWebブラウジング機能が復活し(9/27)、この記事を書いている前日(11/7)に発表されたGPT-4ターボでは大幅に長い入力を扱えるようになった今、このベクトル検索の実装が必要になる機会はもうあまりないかもしれませんが、当時は私も非常に興味のあるトピックでした。
AccelerateフレームワークのvDSPを利用したコサイン類似度の計算等、参考になる実装がいろいろとありました。
extension vDSP { @inlinable public static func cosineSimilarity<U: AccelerateBuffer>( lhs: U, rhs: U ) -> Double where U.Element == Double { let dotProduct = vDSP.dot(lhs, rhs) let lhsMagnitude = vDSP.sumOfSquares(lhs).squareRoot() let rhsMagnitude = vDSP.sumOfSquares(rhs).squareRoot() return dotProduct / (lhsMagnitude * rhsMagnitude) } @inlinable public static func cosineSimilarity<U: AccelerateBuffer>( lhs: U, rhs: U ) -> Float where U.Element == Float { let dotProduct = vDSP.dot(lhs, rhs) let lhsMagnitude = vDSP.sumOfSquares(lhs).squareRoot() let rhsMagnitude = vDSP.sumOfSquares(rhs).squareRoot() return dotProduct / (lhsMagnitude * rhsMagnitude) } }
Working with language (models) on iOS
try! Swift NYCのサイトにある概要を引用すると、こういう内容です。
ChatGPT, GPT-4, and LLMs are the talk of the town. But aside from racist chatbots, obviously incorrect quotes, and psychedelic images how can we really leverage these language models to improve our apps? Let’s discover APIs that offer services that we can really use in day-to-day development and go down the rabbit hole up until the point of using custom CoreML models and even training them. We’ll start with what Apple has given us with the Natural Language framework and slowly build our way up to the complex large language models (LLMs), such as ChatGPT and Whisper, that we can use for incredibly powerful applications.
There are many different layers to AI and machine learning on mobile and we can leverage the powers of the built-in processors to do powerful on-device machine learning tasks but sometimes it is just necessary to do compute-heavy tasks somewhere else. We'll explore all the possibilities that we have for this!
iOSにおけるさまざまな自然言語処理の実装について学ぶワークショップでした。
具体的には、以下のような内容を学びました。Core MLのGPTモデル以外はいずれの手法も試したことはあったのですが、良い復習になったので受講して良かったです。
Natural Languageフレームワークを用いた自然言語処理
NLLanguageRecognizer
を用いて言語の判定を行う。
private let recognizer = NLLanguageRecognizer()
func identifyLanguage(snippet: String) -> NLLanguage? { recognizer.processString(snippet) return recognizer.dominantLanguage }
NLTagger
を用いて単語の種別(名前、場所、組織名)を特定する
let tagger = NLTagger(tagSchemes: [.nameType]) tagger.string = sentence let tags = tagger.tags(in: sentence.startIndex..<sentence.endIndex, unit: .word, scheme: .nameType, options: options) ...
NLTagger
を用いて文章を品詞分解する
let tagger = NLTagger(tagSchemes: [.lexicalClass]) tagger.string = sampleSentence let tags = tagger.tags(in: sampleSentence.startIndex..<sampleSentence.endIndex, unit: .word, scheme: .lexicalClass, options: options) ...
OpenAI APIを用いた自然言語処理
- テキストを生成する
- 間違ったコードを修正してもらう
(いずれもChat APIにそういうクエリを投げるだけ)
let chat = Chat(role: .user, content: prompt) let query = ChatQuery(model: .gpt3_5Turbo, messages: [chat]) let result = try await openAI.chats(query: query) print("result: \(result)")
Core MLを用いた自然言語処理
Bert.mlmodel
を利用して質問に答えてもらう
let prediction = model.predict(question: question, context: context) print("Prediction: \(prediction)")
GPT2.mlmodel
を利用して、テキストを補完してもらう
let generatedTextAndTime = model.generate(text: text, nTokens: 10, callback: { (generatedText, timeTaken) in DispatchQueue.main.async { self.generatedText = generatedText self.generationSpeed = "\(timeTaken) sec/token" } })
↑のコードはものすごくシンプルですが、ワークショップ内では触れられなかったそれぞれのCore MLモデルを直接たたくラッパークラス群の実装を見るとかなり複雑怪奇で、アカデミックなレイヤーまで理解し、モデル内部に精通してないととても書けなそうです。
あとから講師に「このCore MLモデルとラッパー実装はどこから来たのか?Appleが配布してるものとはまた別物のようだが?」と聞いたところ、HuggingFaceの下記リポジトリから来ているとのこと。
思い出
英語の話
色々と書いてますが、実は私は英語はそれほどできません。ワークショップもほぼ聞き取れないので、説明を理解することは諦め、ほとんどの時間はコードとにらめっこし、Slackから質問していました。
ただ講師の方々は非常に親切で、とあるワークショップの講師の方などは私向けにスクリーンにリアルタイムに書き起こし字幕を表示してくれたりもしました。
日々の発信活動の成果
久々の海外カンファレンス参加で心細くもあったのですが、とある講師の方が私の顔を見て、「君ってもしかして(スマホを見せながら)このARKit-Samplerの人?」と気付いて声をかけてくれたときはとても嬉しかったです。OSS活動をしていてよかったなと 5。
しかもなんと、その方はベルリン出身で、私が2016年にベルリンのカンファレンスで登壇したときにその場にいらっしゃって、トークの中で話したCore Bluetoothの本のことも覚えててくれたのでした。
パーティー
マンハッタンのとあるビルのルーフトップでパーティーが行われました。
ぼっちになる覚悟で参加したのですが、ひとりになってる人に話しかけたり、ワークショップの講師の方に話しかけたり、主催のナターシャさんに話しかけたりしてなんだかんだ非常に楽しく過ごせました。
おわりに
try! Swift NYCで参加した2つのワークショップについて紹介しました。講師の方々にもたくさん質問でき、非常に学びが多く大満足の2日間でした。来年春に開催されるtry! Swift Tokyoももちろんチケットは購入済みです。参加されるみなさま、現地でお会いしましょう!