はじめに
今の時代AI使えばなんでも作れるやろ!と思い失敗した失敗談です。
もっとAIをうまく使えれば精度上げられたのかなとも思うので、こうした方がいいんじゃない?などあればコメント頂けますと幸いです。
背景:Slackの会話が見つからない問題
Slackを使っていると、「あの話、どこでしたっけ?」という場面によく遭遇します(自分だけ?)
SlackAIで検索機能はあるもののplanの値段が倍くらい違うのと検索した結果を元に色々したいと考えていたので自分でアプリケーション作成してみようと思い立ちました。
そこで、まずはMVPとして「自然言語で検索できるSlack検索アプリ」を作ることにしました
(ベクトル検索やEmbeddingについての知識はなし)
開発プロセス
技術調査と仕様書作成
最初のステップとして、以下を実施しました:
-
技術調査
- どんな技術スタックが必要か
- Slack APIの使い方
- ベクトル検索について
-
仕様書の作成
- 機能要件の整理
- システム構成の決定
- 開発ステップの洗い出し
正直、この段階ではベクトル検索などの技術的な理解は全くと言っていいほどないです
Claude Codeで仕様書に沿って実装
作成した仕様書をもとに、Claude Codeで実装を進めました。
採用した技術スタック:
- フロントエンド: Streamlit(Pythonだけで簡単にUIが作れる)
- Slackデータ取得: slack-sdk
- Embedding: Sentence Transformers(無料のローカルモデル)
- ベクトルDB: ChromaDB
- 言語: Python 3.12
実装自体は比較的スムーズで、Claude Codeが仕様書に沿って各機能を実装してくれました。
以下作成した仕様書になります。
# Slack自然言語検索アプリ 開発仕様書 (MVP案)
## 1. プロジェクト概要
### 1.1. プロジェクト名
Slack会話履歴 セマンティック検索ツール (仮称)
### 1.2. 背景と目的
Slackでは重要な会話が日々流れてしまい、後から「あの会話はどこでしたか?」と探すのが困難になっている。
この問題を解決するため、Slackの会話履歴を自然言語(キーワードや曖昧な記憶に基づく文章)で検索し、該当する会話の場所(チャンネル、発言日時)を特定できる最小限のアプリケーションを開発する。
### 1.3. MVP (最小機能) の定義
* **IN (対象内)**:
* 管理者が指定した**特定のパブリックチャンネル**の履歴を検索対象とする。
* 過去の会話履歴をバッチ処理で取得し、検索用データベースに登録する。
* シンプルなWeb UIを提供し、ユーザーが検索クエリ(自然言語)を入力できる。
* 検索クエリと意味的に近い会話(メッセージ)を検索結果として表示する。
* 検索結果には、「チャンネル名」「発言日時」「メッセージの抜粋」「Slackメッセージへのパーマリンク(URL)」を表示する。
* **OUT (対象外)**:
* プライベートチャンネル、ダイレクトメッセージ(DM)の検索。
* リアルタイムでの会話の同期(検索対象への反映はバッチ処理)。
* Slackアプリ内での対話型UI(例: スラッシュコマンド、Slackボット)。
* AIによる高度な要約の生成(RAG)。
* 複雑なユーザー認証機能(MVPでは社内限定利用などを想定)。
---
## 2. 機能要件
### 2.1. データ取得機能 (バッチ処理)
* **機能**: Slack APIを使用し、指定されたパブリックチャンネルのメッセージ履歴を定期的に(例: 1日1回)取得する。
* **使用API**:
* `conversations.list`: 対象チャンネルIDのリストを取得するため。
* `conversations.history`: 各チャンネルのメッセージ履歴(テキスト、発言者ID、タイムスタンプ)を取得する。
* `chat.getPermalink`: 検索結果表示用のパーマリンクを取得するため。
### 2.2. データ処理・インデックス機能
* **機能**: 取得したSlackメッセージのテキストを、自然言語処理(NLP)モデルを用いて「ベクトル」に変換する。
* **処理**:
1. メッセージテキストをEmbeddingモデル(埋め込みモデル)に入力し、数値のベクトルデータを生成する。
2. 生成したベクトルデータを、元のメッセージ情報(チャンネルID、タイムスタンプ、パーマリンク)と紐付けて「ベクトルデータベース」に保存(インデックス化)する。
### 2.3. 検索インターフェース機能 (Web UI)
* **機能**: ユーザーが検索クエリを入力し、結果を閲覧するためのシンプルなWebページを提供する。
* **UI要素**:
* 検索ボックス(1行)
* 検索実行ボタン
* 検索結果表示エリア
### 2.4. 検索実行機能
* **機能**: ユーザーが入力した検索クエリ(自然言語)を、データ処理時と同じEmbeddingモデルでベクトル化する。
* **処理**:
1. クエリのベクトルを生成する。
2. ベクトルデータベースに対し、そのクエリベクトルと「意味的に最も近い」メッセージのベクトルを検索する(セマンティック検索)。
### 2.5. 結果表示機能
* **機能**: 検索実行機能で見つかったメッセージの情報を、関連度順にWeb UIに表示する。
* **表示項目 (各結果)**:
* 関連度スコア (参考)
* チャンネル名
* 発言日時
* メッセージの抜粋 (スニペット)
* 該当メッセージへのSlackパーマリンク (クリックするとSlackアプリでその場所に飛べる)
---
## 3. 非機能要件
* **セキュリティ**: Slack APIトークンは環境変数などを用い、コード内にハードコードせず安全に管理する。
* **対象データ**: テキストメッセージのみを対象とし、画像やファイル内のテキストは(MVPでは)検索対象外とする。
* **パフォーマンス**: 検索クエリ入力後、5秒以内に結果を表示することを目指す。
---
## 4. システム構成・開発環境 (推奨案)
迅速な開発と低コスト運用を最優先した、最小構成の提案です。
| カテゴリ | 推奨技術 | 選択理由 |
| :----------------------- | :------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- |
| **プログラミング言語** | **Python 3.10+** | AI/NLPライブラリ、Webフレームワーク、データ処理の全てが揃っており、迅速な開発(プロトタイピング)に最適。 |
| **バックエンド (API)** | **FastAPI** または **Flask** | 軽量で高速なAPIサーバーをPythonで簡単に構築できる。 |
| **フロントエンド (UI)** | **Streamlit** | **(MVP最推奨)** PythonのみでインタラクティブなWeb UIを即座に構築可能。バックエンドと一体化できるため開発速度が最速。 |
| **データ取得** | **Slack SDK (Python)** | Slack APIをPythonから簡単に利用できる公式ライブラリ。 |
| **NLP (Embedding)** | **OpenAI API** <br> (例: `text-embedding-3-small`) | **(推奨)** APIを呼び出すだけで高性能なベクトル化が可能。自前でモデルを管理する必要がない。従量課金だがMVPのデータ量なら安価。 |
| (代替案: ローカル) | Sentence Transformers | オープンソース。GPU環境があれば無料で実行可能だが、環境構築とモデル選定の手間がかかる。 |
| **ベクトルデータベース** | **ChromaDB** | **(推奨)** オープンソースで導入が非常に簡単。Pythonとの親和性が高く、ローカルファイルやインメモリで動作するためMVPに最適。 |
| **実行環境** | **ローカルPC** または **Render (Free Tier)** | まずはローカルPCで開発。外部に公開・共有する場合は、Renderなどの無料枠があるPaaSがデプロイしやすい。 |
---
## 5. 開発ステップ (推奨)
1. **Slack App作成**: Slack側でAppを作成し、必要なスコープ(`channels:history`, `channels:read`等)を設定し、APIトークンを取得する。
2. **データ取得・処理 (Jupyter Notebook / Pythonスクリプト)**:
* まずは単体のスクリプトで、Slack APIからデータを取得できるか確認する。
* 取得したテキストをOpenAI APIでベクトル化し、ChromaDBに保存する処理を実装する。
3. **UIと検索機能の実装 (Streamlit)**:
* Streamlitで検索ボックスと検索ボタンを設置する。
* 入力されたクエリをベクトル化し、ChromaDBを検索するロジックを実装する。
* 検索結果をStreamlit上で表示する。
4. **デプロイ (任意)**:
* 作成したアプリをRender等にデプロイし、チームメンバーが利用できるようにする。
結果:アプリケーション自体は完成
1時間程度で基本機能は完成しました:
- Slackチャンネルからメッセージを取得
- メッセージをベクトル化してChromaDBに保存
- 検索クエリをベクトル化して類似検索
- StreamlitでシンプルなUI提供
実際に使ってみた結果(失敗談)
検索精度が想定より大幅に低かった
実際に使ってみると、期待していた結果とはかけ離れていました。
AIに関しての会話を検索したのに全く関係ないものが出力されています。(塗りつぶされているところにはチャンネル名が入ってます。)
検索結果の上位10件を見ても、ほぼ関係ないものばかり表示され、全く使い物になりません...
うまくいかなかった原因分析
実装後に調べてみて、自分の理解不足が浮き彫りになりました。
ドメイン知識なしでは改善の手が打てない
一番の問題は、精度が低い理由が分からないことでした。
- ベクトル化のプロセスで何が起きているのか分からない
- 検索結果のスコアが何を意味するのか分からない
- どのパラメータをどう調整すれば良くなるのか分からない
「動くものは作れたが、良くすることができない」という状態に陥りました。
学んだこと・反省点
AIツールで「作る」ことはできても「良くする」には理解が必要
Claude CodeやGemini AIのおかげで、コードを書くこと自体は簡単でした。しかし、それは「動くもの」を作れるというだけ。
「使えるもの」に仕上げるには、やはり自分自身の技術理解が不可欠だと痛感しました。
MVP思考は正しかったが、基礎知識の重要性を痛感
「まず作ってみる」というアプローチ自体は間違っていなかったと思います。実際に動かしてみることで、何が分かっていないかが明確になりました。
ただし、ある程度の基礎知識は事前に学んでおくべきだったと反省しています。
まとめ
失敗から得た教訓
よかった点:
- MVPを迅速に作成できた
- 実際に動かすことで課題が明確になった
- 何を学ぶべきかが分かった
悪かった点:
- 基礎知識なしでは改善できない
- 精度の低さを解決する手段が分からない
作ってみて感じたこと
- MVP思考は大事:まず動くものを作ってみる価値はある
- でも基礎は学ぼう:ある程度の基礎知識は事前に身につけておく
- 失敗を恐れない:失敗から学べることは多い
- 学び直しを躊躇しない:分からないことが分かったら、素直に学び直す
今回は失敗してしまいましたが、学びなおしてリトライしたいと思います!
