スタンバイ2+1年の軌跡

# はじめに
この記事は スタンバイ [Advent Calendar 2022](https://qiita.com/advent-calendar/2022/stanby) の25日目の記事です。
早いもので株式会社スタンバイにJoinして2年が終わろうとしています。この機会に、この2+1年間の軌跡をスタンバイが外に発信している記事の一部を紹介しながら背景やエピソードを添えて、まとめてみようと思います。

・[Stanby Tech Blog](https://techblog.stanby.co.jp/)
・Advent Calendar([Advent Calendar 2022](https://qiita.com/advent-calendar/2022/stanby), [Advent Calendar 2021](https://qiita.com/advent-calendar/2021/stanby))

とその前になぜ、2+1年なのかは、インタビュー記事([事業成功にフォーカスした、エンジニアのプロ集団を作っていきたい](https://recruit.stanby.co.jp/interview/008/))を参照するのが良いのですが、読むのが面倒な方のために簡単に説明すると、スタンバイへJoinする1年前の2019年12月末に代表の南と邂逅し、[ヤフー](https://www.yahoo.co.jp/)の明石としてスタンバイの検索精度向上の取り組みを始めたのが2020年1月、スタンバイにJoinしたのが、2021年1月ですので、2+1年の軌跡になります。

# 技術負債との闘い
スタンバイでのエンジニアリングの取り組みを例えると``技術負債との闘い``のひとことで締めくくれるかと思います。[株式会社スタンバイ](https://stanby.co.jp/)は、2019年12月に[Zホールディングス株式会社](https://www.z-holdings.co.jp/)と[ビジョナル株式会社](https://www.visional.inc/ja/index.html)のJoint Ventureとして設立された企業ですが、いわゆるスタンバイサービスは、ビズリーチの一事業を継承したものであるため既に4-5年の歳月を積み重ねてきたいわゆる年代物のサービスです。

4-5年間サービスを継続し続けるというのは、それはそれで一つの尊敬できるものであり、スタートアップの中でも数少ない生き残りともいえ、その実績と成果があってのJoint Ventureであるのも頷けるのですが、4-5年の歴史というのは、それなりにしょっぱい技術負債を樽の中に詰め込んで居るものなのです。

# 検索エンジン
最初に手をつけたのが、このサービスの心臓であり、最大の差別化ポイントの検索エンジンでした。ちなみにスタンバイの検索エンジンには、Organic(無料掲載求人)とAd(有料掲載求人)の2種類の検索エンジンがあり、GoogleやヤフーなどのWeb検索と同様に有料掲載求人については、Organicの結果の上位、中位、下位の固定枠に表示されます。
インタビュー記事([事業成功にフォーカスした、エンジニアのプロ集団を作っていきたい](https://recruit.stanby.co.jp/interview/008/))で語ったように、ヤフーvsスタンバイでOrganic検索のABテストコンペを実施し、その結果、ヤフーの方式が採用されることになりました。いまだから話せますが、当時のスタンバイの技術レベルでは、この結果はわかっていたことでしたが、``あなたたちは検索エンジンのことを理解していない``と外の人間がいきなり、やってきて話してもだれも納得しないのでこのイベントを実施し、ヤフーとの協業という形をスムーズに進めることができたかと思います。

結果として、
- Organic検索エンジンにはYahoo!ABYSSという検索プラットフォーム
- Ad検索エンジンにはElasticsearch

を採用。これは、Yahoo!ABYSSを利用し、ヤフーエンジニアとの協業を進めることにより、ヤフーの持つ検索Knowledgeをスタンバイに吸収し、スタンバイの検索技術の底上げを図ることを目的とし、その一方で、Yahoo!ABYSSで培った知識を自社検索エンジンに取り込むことにより、スタンバイ内での検索エンジンの知識や運用経験を養うためにこの２エンジン体制をとることにしました。
ヤフーの検索エンジンをお借りすることは非常にメリットの多いことなのですが、これは、諸刃の剣であり、ヤフー内の政策でこのエンジンの提供をいつ止められてもスタンバイが死なないようにこの体制にしました。これは、ヤフーを非難する訳ではなく、ソフトウェアにはライフサイクルもあり、ヤフーだけでなく、AWSなどクラウドそして、僕自身ヤフーのCTOなどを経験して、実際にこのような外部提供機能を様々な事情により断念した記憶があるからです。``あと、そのほうがエンジニアのモチベーションも維持できますからね笑``

## Organic検索

Oeganic検索エンジンの一番の負債は、スタンバイサービス開発初期に作られた学習モデルが更新されずに改善されていなかったことですが、この取り組みによって大きく前進、さらに定期的な新モデルでのテストも実施されるようになり、改善サイクルがまわるようになりました。

Stanby Tech Blog[スタンバイの検索の仕組み](https://techblog.stanby.co.jp/entry/stanby_search)にてご確認ください。

## Ad検索

一方、Ad検索エンジンについては、エンジンの切り替えをしなかったのと、多くの``意味不明``なアルゴリズムが随所に蓄積されていたためこんなに簡単ではありませんでした。

最初の取り組みとして、以下を実施しました。
1. 新モデル適応と[GSP](https://en.wikipedia.org/wiki/Generalized_second-price_auction)導入
1. Second Phase Ranking の導入
1. アルゴリズムとモデルの統一

Stanby Tech Blog[スタンバイの広告表示におけるロジックについて](https://techblog.stanby.co.jp/entry/ad_search_article)あたりを参考にされると良いかと思います。

### 1. 新モデル適応と[GSP](https://en.wikipedia.org/wiki/Generalized_second-price_auction)導入

GSPっぽいものが入っていたが、GSPは、Auction理論を応用して、``価格を上限適正値``に引き上げていくものなのですが、GSPっぽいものは、``価格を中央適正値``に寄せるようなもので、これだと価格適正化が行われそうもありませんでした。モデルは、Organicと同様で、サービス開発初期に作成されたものでした笑

### 2. Second Phase Ranking の導入

Adにおける、Second Pahse Rankingの重要性については、期待収益額順にRe-Rankingして掲載順を決定するのですが
```
　　例：　　期待収益額 = 入札額 × 予測CTR
```
このときに予測CTRがものすごく低く、入札額が高い不適切な広告が上位に来てしまうことが発生します。これを避けるために、First Phaseで適合性の高い広告順(上述では、予測CTR順)でRankingした上で、上位n本をSecond Phaseに渡し、期待収益順にRe-Rankingすることにより、適切な広告間でのAuctionを実現する必要があります。ElasticsearchのRe-Rank Plug-inである、[Learning to Rank](https://elasticsearch-learning-to-rank.readthedocs.io/en/latest/)がそれにあたるのですが、パフォーマンスが出ない、Yahoo!ABYSSのKnowledgeを取り入れるためには、拡張性に欠けるということで独自開発する必要がありました。
同じグループであるZOZOさんも相当苦労されていた([Elasticsearch Learning to Rankプラグインの使い方とポイント](https://techblog.zozo.com/entry/elasticsearch-learning-to-rank-plugin))と風の噂に聞いていました。

### 3. アルゴリズムとモデルの統一
なんとなくそれぞれの背景は想像ついたのですが、検索条件とか出面によってアルゴリズムが異なったる。ここでは、詳細には触れたくないほどの負債でした。

### 取り組んだ結果
4-5年の歴史と[運用型広告](https://ja.wikipedia.org/wiki/%E9%81%8B%E7%94%A8%E5%9E%8B%E5%BA%83%E5%91%8A)とはすごいもので、新モデル適応と[GSP]の取り組みだけでは、旧アルゴリズムには勝てませんでした。Second Phase Ranking の導入を並行して進めたことと、社内のMLチームの努力もあって、今年の4月に文句ない状態で1〜3を達成することができました。
結果として、4月〜12月までで求人企業様のROIを向上しつつ、広告収益性は2倍近く向上できるような体制になってきました。
先述のインタビュー記事では、ここまでを1〜3までを1年でと考えていたので結果2年掛かってしまいました。

# 求人データ取り組み
皆さんご承知かと思いますが、スタンバイは、求人検索エンジンです。求人検索エンジンで重要なものをふたつあげてと言われれば、先ほど、紹介した、検索エンジンとその検索エンジンのコンテンツである求人票です。
スタンバイの求人票は、３つの方法で取り込まれています。
1. データフィード
1. クロール
1. CMSからの入稿

このうち、1.と2.については、ジョブデータコアグループの開発する仕組みで実現されていますが、この仕組みでは、求人票の収集、分析、蓄積、管理、(分類)などが責務があり、なによりフレッシュネスをいかに担保するかが大きな課題です。Daily約2000万前後の求人の取り込みと、規約確認、同一求人などの分析や判別、そして、管理、求人票判定器によって判定された結果の反映などが実施され、結果としてスタンバイに掲載される求人票は約1200万(まとめ求人を考慮すると約800万)程度を処理する仕組みとなっています。

この求人取り組みも大きな課題を抱えており、2021年11月頃から大幅なリプレースを実施しました。

- Stanby Tech Blog [スタンバイの求人情報取込の仕組みを作り直した話　〜序章〜](https://techblog.stanby.co.jp/entry/jobstore_PJT_0/)
- Stanby Tech Blog [求人取り込み周りのリプレイスについて](https://techblog.stanby.co.jp/entry/jobstore_PJT_1/)
- Advent Calender 2022 [クローラー（求人取り込みシステム）のリアーキ対応について](https://qiita.com/naoki_0409/items/d2e84dd88cc96a1e3a1f)

この件については、Tech Blogにしっかり記述されているので特筆しなくても良さそうですね。
結果として、法律対応や求人票拡充のためのカラムの追加など柔軟に対応でき始めています。

最近の取り組みとしては、クロールデータのフレッシュネスを担保するための終了求人チェックを如何に効率よく行うかと言う課題に取り組んでいるところです。

# Stanby-API

Stanby Tech Blog '[プロダクト開発体制のこれまでとこれから](https://techblog.stanby.co.jp/entry/organization)'に紹介されているとおり、2021年4月の組織変更で、技術ドメインに基づいたチーム体制に変更しているのですが、その弊害として、複数チームがメンテナーとなっているのが、このStanby-APIといサービスです。
スタンバイは、[マイクロサービスアーキテクチャ](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9)を採用しているのですが、マイクロサービスって進めていくと、マイクロサービス群をいい感じにマッシュアップしてくれたり、ドメインの責務から外れるようなアルゴリズムなどもすべて集約されるいわゆる``かゆいところに手が届く``的なサービスができあがるのですが、いわゆるこれがそれにあたります笑
結果として、何か機能改修が必要な際には必ずメンテナンスを余儀なくされ、ほとんどのチームがメンテナーとなっているので、開発効率を著しく下げています。
詳細については、このプロジェクトが終わった頃、担当エンジニアが書くかもしれないので割愛しますが、モジュラモノリス化により、この課題に取り組んでいます。

# Geo-API

求人サービスとして、Geographic情報の把握と理解というのは、重要な課題の一つなのですが、全スタンバイエンジニアがヤバいなーと思いながら見て見ぬふりをし続けたのがこのGeo-API。
Geo-APIにはいくつかの機能があり、

- 基本機能
    - 住所のNormalization (住所文字列の正規化)
    - Geo-Coder (住所から緯度経度情報への変換）
    - Reverse Geo-Coder (緯度経度情報から住所への変換）
- その他
    - 駅などの地点情報の判定
    - 地点情報の住所の特定

みんなが言うには、
- 誰も仕様を理解していない
- どの機能がどこで使われているのかも分からない
- コードめちゃくちゃなので触りたくない

と、カオスですね笑
このパンドラの箱をとうとうこじ開けました。Phase-1は、春には目にすることができそうです。

# QAC (Query-Auto-Completion)

Advent Calender 2022 [日本語クエリオートコンプリーションの実現](https://qiita.com/kinshotomoya/items/0764a7ba78d2b97e3004)

でも紹介された、いわゆる検索サジェスト機能です。
これも、開発当初から一切メンテされていない、効果測定もしたことないからよくわからない、という誰も触れなくなったモジュール。
Lightな機能だからこそElasticsearchやSolrの機能を使わずに、Luceneで開発して、検索技術の理解を深めようというのが今のスタンバイのエンジニアらしい取り組みですね。
時がたち社内のエンジニアのレベルが維持できなかったり、環境が変わったときに負債化するので、もっと、汎用的な仕組みにすべきでは？という意見が聞こえてきそうですが、今は検索技術の理解のほうが重要だと思ってます。

これは、そろそろ、第一弾のABテストが始まるのかな。

# さいごに

他にもご紹介したことはたくさんありますが、今回はこのあたりにしたいと思います。
この記事を書きながらも、新規リリース目白押しで、来年も楽しみな年になりそうです。

今年もエンジニア達の自発的な呼びかけのもとアドベントカレンダーが実現され、トリを務めさせてもらいました。スタンバイは、まだまだ、これからです！

それでは、Happy Merry Christmas & Happy New Year!!
みなさんもよいお年をお迎えください！！

#### 追記
文字だらけの記事で申し訳ありませんでした。この記事を書こうと思っていた時期に、家族全員がコロナに罹患してしまいました。妻、私、子供2人と順に発症して、自宅療養だけではなく、さすがに検査しなきゃと考え検査したところ、抗原検査で私だけ陰性？？？病院で検査したところ、なぜか一人だけインフルエンザといういわゆる従来型コロナに発症のまっただ中でこの記事を書いていますのでこれ以上の編集はご勘弁を・・・笑

この記事を公開する頃には、体調も万全になり家族で元気にクリスマスを祝っていると思います！