DuckDBではじめるRAGの構築からベクトル分析まで
千株式会社 / よねすけ
メンバー / 機械学習エンジニア / 従業員規模: 301名〜500名 / エンジニア組織: 51名〜100名
ツールの利用規模 | ツールの利用開始時期 | 事業形態 |
---|---|---|
10名以下 | 2025年2月 | B to B B to C |
ツールの利用規模 | 10名以下 |
---|---|
ツールの利用開始時期 | 2025年2月 |
事業形態 | B to B B to C |
アーキテクチャ
アーキテクチャの意図・工夫
工夫のポイントは、RAGのベクトルストアとしてDuckDBを採用した点です。
これによりベクトル検索機能だけでなく、蓄積したベクトルデータの分析を行うことが可能になるため、外部ツールを導入することなくRAGの品質管理システムが構築できるようになります。
その他技術の選定のポイント
RAGパイプラインを効率的に構築するため、データ取り込みからインデックス作成、クエリ実行までを包括的にサポートするフレームワークであるLlamaIndexを採用しました。
社内情報などセキュアな情報を取り扱うため、ローカル環境でLLMを実行できるOllamaを採用しました。Ollamaで提供されているモデルの多くは量子化によって軽量化されており、特別なGPU環境がなくとも高速な推論が可能です。これにより、セキュリティを確保しつつ、ローカルでの性能検証を容易に行えました。
導入の背景・解決したかった問題
導入背景
以前より機械学習やデータサイエンスの分析用データベースとしてDuckDBを採用していました。
PandasやPolarsといったデータフレームライブラリとの相性が良く、処理が高速な点が魅力です。
今回、このDuckDBをLLMアプリケーション開発にも導入し、RAGの品質を向上させるための分析基盤として活用することにしました。
本記事では、その背景にある課題と目的を説明します。
RAGの品質における課題
LLMアプリケーション開発において、独自情報に基づいた回答を生成する技術に RAG (Retrieval-Augmented Generation) があります。 RAGは社内ドキュメントなどを収集し、検索対象となるベクトルデータベースを構築します。
しかし、このデータベースの元となるドキュメントの質が低い、あるいは内容に偏りがあると、RAGの性能を最大限に引き出せず、LLMの回答が期待する品質に達しないという課題がありました。
ドキュメントの質の低下
ドキュメントの質の低下とは、回答に不要な情報、誤った情報、ノイズ(HTMLやMarkdownの書式データなど)の混入や、不十分なテキスト抽出といった問題が挙げられます。
いわゆる「Garbage In, Garbage Out(ゴミを入れれば、ゴミしか出てこない)」という言葉でよく表現される問題です。
ドキュメントの偏り
ドキュメントの偏りとは、収集された情報が特定の視点、トピック、スタイルに著しく偏っている状態を指します。
これにより、LLMが生成する回答も中立性や網羅性を欠いたものになります。
具体的な対策
この課題に対処するには、一般的に以下のようなアプローチが考えられます。
- 情報源の改善: より質の高い情報ソースを選定する。
- データクレンジング: 収集したデータからノイズや不要な情報を除去する。
- 前処理の最適化: ドキュメントの解析(パース)やテキスト分割を適切に行う。
実際にこれらの対策を講じたところ、回答の品質向上が見られました。
では、構築したRAGシステムを継続的に改善していくためには、どのような仕組みが必要でしょうか?
どのような状態を目指していたか
RAGに用いるドキュメントは、Embeddingモデルによってベクトル化され、ベクトルデータベースに蓄積されます。
この蓄積されたデータがどのような状態にあるのかを継続的に分析・可視化できる仕組みが必要だと考えました。
なぜなら、分析を通じて「特定のトピックにデータが偏っていないか」「ノイズを多く含む不適切なドキュメント群はどれか」といった質と偏りの問題を定量的に発見できるようになるからです。
このように、データに基づいた改善サイクルを回せる状態を目指していました。
比較検討したサービス
- SQLite
- Chroma
比較した軸
選定軸
今回の分析基盤の選定にあたり、重視した軸は以下の2点です。
- 分析と可視化の容易さ: Pythonのデータサイエンスライブラリ(Pandas, Polarsなど)とシームレスに連携し、手軽にデータを分析・可視化できること。
- トータルコストの低さ: 「開発者の学習コスト」「コードの簡潔さ」「ライセンス料金」といった、導入から運用までにかかる総合的なコストが低いこと。
この選定軸に基づき、代替候補となる以下のツールと比較検討を行いました。
SQLite
まず候補に挙がったのが、同じくアプリケーションに組み込んで使えるデータベースであるSQLiteです。 Pythonに標準でバンドルされており、軽量で導入が容易なため広く使われています。
SQLiteとDuckDBの決定的な違いは何でしょうか。
それは設計思想の違いにあります。
DuckDBはオンライン分析処理(OLAP)向けに設計されており、大規模データに対する集計や分析を得意とします。
一方、SQLiteはオンライントランザクション処理(OLTP)向けに設計されており、個別のレコードを高速に読み書きする汎用的な処理を得意とします。
今回の目的は、ベクトルデータベースに蓄積した大規模なデータ群の傾向を分析することでした。
この分析特化の目的には、OLAPを得意とするDuckDBがより適していると判断しました。
Chroma
次に、RAGで標準的に用いられるベクトルデータベースのChromaを検討しました。
無料で使えるオープンソースのベクトルデータベースであり、RAGにおけるSQLiteのような立ち位置のツールです。
RAGパイプライン全体を見据えると、Chromaの活用は自然な選択肢でした。
しかし、Chromaの主目的はあくまでベクトル検索であり、柔軟なデータ分析機能は備わっていません。
一方で、面白いことに、分析ツールであるはずのDuckDBにもベクトル検索機能が搭載されており、LangChainやLlamaIndexといった主要なLLMフレームワークと連携することも可能です。
つまり、Chromaは分析ができず、DuckDBは高品質な分析とRAG実装の両方を1つでこなせる可能性を秘めていました。
ベクトル検索用のデータベースと、その利用状況を分析するためのデータベースを別々に構築・運用する必要がなく、技術スタックをシンプルに保てることも大きな魅力でした。
この汎用性の高さが、DuckDBを選ぶ強力な後押しとなりました。
選定理由
以上の比較検討を経て、選定軸を最も満たすツールとしてDuckDBの採用を決定しました。改めて、決定理由は以下の通りです。
圧倒的な処理速度による分析効率の向上: 大容量データに対する分析クエリを極めて高速に実行できます。
これにより、思考を止めずにデータと向き合うことができ、「分析と可視化の容易さ」という要件を高いレベルで満たします。
エコシステムとの親和性と低コスト: わずか数行でPandasと連携できる手軽さは、開発者の学習コストやコードの複雑さを大幅に下げます。
オープンソースである点も踏まえ、「トータルコストの低さ」という要件にも完全に合致しました。
DuckDBの高速性やPandasとの親和性については、私の過去の登壇資料もご参考ください。
導入の成果
改善したかった課題はどれくらい解決されたか
今回の導入により、Embedding後のベクトルデータを2次元平面にプロットし、ドキュメント同士の意味的な距離感を直感的に把握できるようになりました。
これにより、例えば以下のような課題発見が可能です。
品質の低いデータの特定: ノイズの多いドキュメントや、意図から外れた内容のドキュメントが、主要なデータ群から孤立したクラスターとして可視化される。
データの偏りの発見: 特定のトピックに関するデータばかりが密集しており、他のトピックが不足している領域を視覚的に特定できる。
さらに、可視化されたデータポイントを選択して、その場で元データの確認や不要なデータの削除を行える仕組みも構築しました。これにより、「Garbage In, Garbage Out」の問題に対し、データに基づいた具体的な改善サイクルを回せる状態となり、当初目指していた姿を実現できました。
導入時の苦労・悩み
LangChainやLlamaIndexといったLLMフレームワークとDuckDBを連携させたベクトル更新・削除処理の実装には試行錯誤が伴いました。
特にこれらのフレームワークは、まだ発展途上であり、ベクトルストアごとの細かい操作(特定のメタデータを持つベクトルだけを更新するなど)に対応しきれていない部分があります。 そのため、フレームワークの抽象化されたメソッドだけでは実現できず、DuckDBのSQL操作を組み合わせる必要があるため、コードが煩雑になりがちという課題が残っています。 シンプルでメンテナンス性の高いコードを維持していくことが、今後の課題です。
導入に向けた社内への説明
上長・チームへの説明
DuckDBがいかに分析用データベースとして機械学習やデータサイエンスと親和性が高いかを上記の選定軸で説明しました。
その上で、単なる分析ツールとしてだけでなく、「LLMのベクトルストアとしても活用できる」という新たな可能性を示し、「技術スタックを複雑化させることなく、LLM開発の品質向上に取り組める」というメリットを伝えました。
今後はRAGの品質改善に限らず、LLM開発におけるデータ分析基盤として、DuckDBの活用を推進していく方針となりました。
活用方法
よく使う機能
DuckDBをDataframeとして読み込む機能はよく使います。
conn = duckdb.connect("duckdbのパス")
duck_df = conn.table("テーブル名").df()
これであとはPandasとしてテーブルデータを加工したり可視化に繋げることができます。
加工したデータフレームをDuckDBで保存するためには以下のようにSQL文を使います。
with duckdb.connect(db_path) as conn:
# DataFrameをDuckDBに登録
conn.register("temp_df", duckdb_df)
# テーブルを上書き作成
conn.execute(f"CREATE OR REPLACE TABLE {table_name} AS SELECT * FROM temp_df")
# 一時テーブルを削除
conn.execute("DROP VIEW temp_df")
このように、Pandasとデータベースどちらを操作するかによって書き方は変わりますが、比較的短いコードで操作が可能です。
ツールの良い点
- ワークフローへの柔軟性: Pythonのデータフレーム操作とシームレスに連携でき、既存の機械学習・データサイエンスのワークフローにスムーズに組み込めます。
- 高いコストパフォーマンス: インストールするだけで使える手軽さと、インメモリでの高速処理能力を両立しています。
- オープンソース: ライセンス費用を気にすることなく、スモールスタートから大規模な活用まで検討できます。
ツールの課題点
- 実際の活用事例が少ない:最近は海外の記事などでDuckDBを使う事例が増えているように見受けられますので、国内以外の記事にも目を向けると参考になるかもしれません。
- PythonでもSQL文でも書けてしまうため、コードの可読性が低下する可能性がある:チームで開発する際には、どちらのスタイルを主として使うか、あらかじめコーディング規約を決めておくことが、中長期的なメンテナンス性を保つ上で重要になるでしょう。
ツールを検討されている方へ
PythonやPandasなど、機械学習やデータサイエンスの文脈でデータベースをお探しの方にはおすすめです。
特にスプレッドシートやCSVファイルなどでデータを管理していたり、SQliteから分析しているようなケースでは高速で快適な分析ツールを作ることが可能です。
PythonやPandasに慣れている必要がありますが、それほどSQLの知識がなくてもデータベースを操作できるので、学習コストも低く導入はしやすいと思います。
今後、LLMによる分析の自動化がさらに進んでも、その結果が本当に正しいのか、データに偏りがないかを最終的に検証するのは人間の役割です。
そのような「人間がデータと向き合い、深く洞察を得る」場面において、手元で高速にデータを探索できるDuckDBは、強力な武器になります。
今後の展望
DuckDBがLLMアプリケーション開発で分析用データベースとしてだけでなく、ベクトルデータベースとしても機能することを確認できました。
今後は更にRAGだけでなく、エージェント機能を含めた自社サービスへの開発に応用/拡大していく予定です。
千株式会社 / よねすけ
メンバー / 機械学習エンジニア / 従業員規模: 301名〜500名 / エンジニア組織: 51名〜100名
よく見られているレビュー
千株式会社 / よねすけ
メンバー / 機械学習エンジニア / 従業員規模: 301名〜500名 / エンジニア組織: 51名〜100名
レビューしているツール
目次
- アーキテクチャ
- 導入の背景・解決したかった問題
- 活用方法