1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RAGの失敗はベクトルDBだけでは追えない:ClickHouseで100万件のAIログを0.1秒台で監査する

1
Last updated at Posted at 2026-06-05

ClickHouse RAG observability eyecatch

この記事は、Qiita Tech Festa 2026の「AI時代のデータベース、何が変わる?」への参加記事です。

この記事のコード・SQL・1M件ベンチ結果はGistから再現できます。

DDL、データ生成スクリプト、9本の監査SQL、1,000,000行の実測TSV、EXPLAIN indexes = 1の結果をまとめて置いています。

再現用Gist: ClickHouse RAG observability benchmark

AI時代のデータベースで変わるのは、「ベクトル検索ができるか」だけではありません。
実運用で困るのは、次のような問いに答えられないことです。

  • どのプロンプト版から幻覚率が上がったのか
  • 検索スコアが低いとき、回答品質はどれくらい落ちるのか
  • どのナレッジ文書が失敗回答に紐づきやすいのか
  • 新しいエージェント版は本当にリリースしてよいのか
  • コスト・遅延・引用漏れを同じ画面で追えているか

今回は、ローカルDocker上のClickHouseに合成RAGトレース100万件を投入し、RAGの失敗を監査するためのスキーマとSQLを作りました。

先に重要な前提を書きます。
この記事のログは実顧客データではなく、再現可能な合成データです。
モデル名・コスト・失敗率も検証用に作った値であり、特定サービスの実測品質を示すものではありません。

この記事の主眼は、AIアプリの失敗を観測するために、どの列を残し、どのSQLで意思決定するかです。

この記事で持ち帰れるものは3つです。

  • RAG/AIエージェントの監査ログをClickHouseに入れるためのDDL
  • 100万件ログでプロンプト劣化、検索品質、文書汚染、遅延、コストを見るSQL
  • EXPLAIN indexes = 1でPrimaryKeyが効いているか確認するリリース前チェック

結論

観測したいこと ベクトルDBだけで弱い点 ClickHouseに残す列 SQLの出口
プロンプト劣化 検索結果は追えても、プロンプト版別の品質差が見えにくい prompt_version, hallucination_flag, citation_missing リリース判定
検索品質 top-kの中身だけでは失敗率との相関が出ない retrieval_top_score, retrieval_score_gap, feedback_score 検索閾値の見直し
遅延 生成・検索・キャッシュのどこが遅いか分解しにくい latency_ms, retrieval_ms, generation_ms, cache_hit SLO監視
ナレッジ汚染 どの文書が失敗回答に出やすいか集計しにくい retrieved_doc_ids, failure_reason 文書改修の優先順位
コスト 1回答単位では見えても、版別・日別の増加が追いにくい prompt_tokens, completion_tokens, cost_usd 予算ゲート

結論として、AI時代のDBは「検索対象の保存場所」だけでは足りません。モデル・プロンプト・検索・評価・コストを同じ時系列ログとして監査できることが重要になります。

実行環境

今回の検証環境です。

項目
OS macOS + Docker Desktop
Docker 29.5.2
ClickHouse 26.5.1.882
データ件数 1,000,000 rows
データ期間 2026-05-23 00:00:00.555 から 2026-06-05 23:59:58.632
入力形式 JSONEachRow
テーブルエンジン MergeTree
全体実行時間 13.37 sec

ClickHouse公式ドキュメントでは、MergeTree系エンジンは高い取り込みレートと大規模データ向けのテーブルエンジンとして説明されています。今回のような追記中心のAIログには相性が良いです。

参考: MergeTree table engine

作った検証ワークスペース

再現用コードと1M件の実測結果は、以下の公開Gistに置きました。

ClickHouse RAG observability benchmark Gist

Gistには生成済みJSON本体は含めていません。data/rag_traces.jsonlは約816MiBになり、かつスクリプトから再生成できるためです。

ローカルでは次の構成にしました。

tmp/clickhouse-rag-observability/
├── Makefile
├── docker-compose.yml
├── scripts/
│   ├── generate-rag-traces.mjs
│   └── run-benchmark.sh
├── sql/
│   ├── 00_schema.sql
│   └── queries/
│       ├── 01_prompt_regression.sql
│       ├── 02_retrieval_score_failure.sql
│       ├── 03_latency_outliers.sql
│       ├── 04_hallucination_sources.sql
│       ├── 05_daily_quality_cost.sql
│       ├── 06_release_gate.sql
│       ├── 07_filtered_tenant_prompt_slice.sql
│       ├── 08_storage_parts.sql
│       └── 09_explain_primary_key.sql
├── data/
└── results/

実行コマンドはこれだけです。

curl -L -o clickhouse-rag-observability-source.tgz \
  https://gist.github.com/YushiYamamoto/0fcd4fc2cba5f44998bd39d420fd41a8/raw/clickhouse-rag-observability-source.tgz

tar -xzf clickhouse-rag-observability-source.tgz
cd clickhouse-rag-observability
make all ROWS=1000000

やっていることは単純です。

  1. clickhouse/clickhouse-server:latest をDockerで起動する
  2. Node.jsで合成RAGトレースをJSONEachRow形式で生成する
  3. ClickHouseに投入する
  4. 9本の監査SQLを実行してTSVと実行時間を保存する

ClickHouseのJSONEachRowは、1行1JSONのNDJSON/JSONLines形式として扱えるため、アプリケーションログの投入に向いています。

参考: JSONEachRow

RAGトレースのスキーマ

テーブルは次のようにしました。

CREATE DATABASE IF NOT EXISTS rag_observability;

CREATE TABLE rag_observability.rag_traces
(
    event_time DateTime64(3),
    event_date Date MATERIALIZED toDate(event_time),
    trace_id String,
    session_id String,
    tenant_id LowCardinality(String),
    app LowCardinality(String),
    prompt_version LowCardinality(String),
    model LowCardinality(String),
    embedding_model LowCardinality(String),
    query_intent LowCardinality(String),
    query String,
    retrieved_doc_ids Array(String),
    retrieval_top_score Float32,
    retrieval_score_gap Float32,
    retrieval_doc_count UInt8,
    answer_chars UInt16,
    latency_ms UInt32,
    retrieval_ms UInt32,
    generation_ms UInt32,
    cost_usd Float64,
    hallucination_flag UInt8,
    citation_missing UInt8,
    feedback_score Int8,
    failure_reason LowCardinality(String),
    prompt_tokens UInt32,
    completion_tokens UInt32,
    safety_redacted UInt8,
    cache_hit UInt8,
    INDEX idx_hallucination hallucination_flag TYPE set(2) GRANULARITY 4,
    INDEX idx_prompt_version prompt_version TYPE set(0) GRANULARITY 4,
    INDEX idx_retrieval_score retrieval_top_score TYPE minmax GRANULARITY 4
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_date)
ORDER BY (tenant_id, app, prompt_version, event_time, trace_id)
SETTINGS index_granularity = 8192;

ポイントは、queryanswerの全文を中心にしないことです。全文は別ストレージに逃がしてもよく、ClickHouse側には監査に必要な列を残します。

  • prompt_version: プロンプト変更の影響を見る
  • retrieval_top_score: 検索品質と失敗率の相関を見る
  • retrieved_doc_ids: 失敗に絡む文書を特定する
  • hallucination_flag: 評価結果を集計可能にする
  • citation_missing: 引用漏れを別指標として扱う
  • latency_ms, cost_usd: 品質だけでなく運用面の劣化を見る

実測1: プロンプト版ごとの劣化を探す

まず、プロンプト版ごとに幻覚率、引用漏れ率、遅延、コストを見るSQLです。

SELECT
    prompt_version,
    count() AS traces,
    round(avg(hallucination_flag) * 100, 2) AS hallucination_rate_pct,
    round(avg(citation_missing) * 100, 2) AS citation_missing_rate_pct,
    round(avg(latency_ms), 1) AS avg_latency_ms,
    round(quantile(0.95)(latency_ms), 1) AS p95_latency_ms,
    round(sum(cost_usd), 4) AS total_cost_usd,
    round(avg(feedback_score), 2) AS avg_feedback,
    topKIf(3)(failure_reason, failure_reason != 'none') AS top_failure_reasons
FROM rag_traces
GROUP BY prompt_version
ORDER BY hallucination_rate_pct DESC;

結果です。

prompt_version traces hallucination_rate_pct citation_missing_rate_pct avg_latency_ms p95_latency_ms total_cost_usd avg_feedback top_failure_reasons
v1_baseline 239,518 18.94 14.68 1208.1 2022.4 128.8580 3.39 missing_citation, stale_doc, tool_boundary
v3_agentic 240,554 16.16 13.11 1448.4 2274.4 187.1723 3.77 missing_citation, stale_doc, ambiguous_owner
v4_cost_guard 199,885 15.30 12.65 1174.1 1990.0 87.9558 3.86 missing_citation, stale_doc, ambiguous_owner
v2_grounded 320,043 14.38 12.20 1291.7 2084.0 192.8952 3.97 missing_citation, stale_doc, tool_boundary

ここで重要なのは、平均フィードバックだけならv3_agenticは悪く見えないことです。しかし、v2_groundedと比べると幻覚率・引用漏れ率・遅延が同時に悪化しています。AI機能のリリース判定では、単一指標ではなく複数指標の差分を見る必要があります。

実測2: 検索スコアと失敗率の相関を見る

次に、検索スコアをバケット化して失敗率を見ます。

WITH
    multiIf(
        retrieval_top_score < 0.55, 'low(<0.55)',
        retrieval_top_score < 0.70, 'mid(0.55-0.70)',
        retrieval_top_score < 0.85, 'high(0.70-0.85)',
        'very_high(>=0.85)'
    ) AS score_bucket
SELECT
    score_bucket,
    count() AS traces,
    round(avg(hallucination_flag) * 100, 2) AS hallucination_rate_pct,
    round(avg(citation_missing) * 100, 2) AS citation_missing_rate_pct,
    round(avg(feedback_score), 2) AS avg_feedback,
    round(avg(latency_ms), 1) AS avg_latency_ms
FROM rag_traces
GROUP BY score_bucket
ORDER BY min(retrieval_top_score);

結果です。

score_bucket traces hallucination_rate_pct citation_missing_rate_pct avg_feedback avg_latency_ms
low(<0.55) 52,291 36.40 24.03 3.26 1290.6
mid(0.55-0.70) 274,467 21.56 16.05 3.63 1285.6
high(0.70-0.85) 446,038 12.54 11.21 3.85 1286.6
very_high(>=0.85) 227,204 11.75 10.75 3.87 1283.6

retrieval_top_score < 0.55のバケットでは幻覚率が36.40%まで上がりました。この結果から、例えば次のようなガードを設計できます。

  • top scoreが0.55未満なら回答を生成せず、追加質問に切り替える
  • 0.55から0.70は「根拠が弱い」ラベルを出す
  • セキュリティや契約系のintentでは閾値を上げる
  • 検索スコアと引用漏れを別々のメトリクスとして監視する

ベクトルDBは検索候補を返します。しかし、検索候補が最終回答の失敗にどう効いたかを長期的に見るには、検索ログと評価ログを同じ分析基盤に残す必要があります。

実測3: 遅延の外れ値を見る

AIエージェントは便利でも、遅くなりすぎるとプロダクトに載りません。モデルとプロンプト版ごとにp95/p99を見ます。

model prompt_version traces avg_latency_ms p95_latency_ms p99_latency_ms max_latency_ms
reasoning-large v3_agentic 43,099 2044.2 2472.0 2585.1 2805
reasoning-large v2_grounded 57,822 1885.4 2296.0 2410.1 2691
reasoning-large v1_baseline 43,254 1800.9 2217.0 2336.3 2587
reasoning-large v4_cost_guard 35,861 1764.4 2167.0 2284.2 2556
balanced-pro v3_agentic 81,874 1464.3 1855.0 1964.0 2253
local-edge v3_agentic 43,531 1325.1 1706.4 1820.0 2059

ここではreasoning-large + v3_agenticが最も重く、p95が2472msでした。リリース判定では「精度が少し良い」だけでなく、p95遅延の増分を予算化する必要があります。

実測4: 失敗に絡む文書をランキングする

RAGの運用で見落としやすいのが、文書単位の品質です。
回答が壊れたとき、プロンプトだけを直しても、古い文書や曖昧なrunbookが混ざっていると再発します。

ClickHouseのarrayJoinを使うと、retrieved_doc_idsの配列を文書単位の行に展開できます。
公式ドキュメントでも、arrayJoinは1行を配列要素の数だけ複数行へ展開する関数として説明されています。

参考: arrayJoin function

SELECT
    doc_id,
    count() AS retrieved_count,
    sum(hallucination_flag) AS hallucination_count,
    round(avg(hallucination_flag) * 100, 2) AS hallucination_rate_pct,
    round(avg(retrieval_top_score), 3) AS avg_top_score,
    topK(4)(query_intent) AS frequent_intents,
    topKIf(3)(failure_reason, failure_reason != 'none') AS top_failure_reasons
FROM
(
    SELECT
        arrayJoin(retrieved_doc_ids) AS doc_id,
        hallucination_flag,
        retrieval_top_score,
        query_intent,
        failure_reason
    FROM rag_traces
)
GROUP BY doc_id
HAVING retrieved_count >= 20
ORDER BY hallucination_count DESC
LIMIT 15;

結果の一部です。

doc_id retrieved_count hallucination_count hallucination_rate_pct avg_top_score frequent_intents top_failure_reasons
kb_current_migration_002 2,862 544 19.01 0.757 migration missing_citation, stale_doc, ambiguous_owner
kb_current_migration_064 2,884 540 18.72 0.758 migration missing_citation, stale_doc, ambiguous_owner
kb_current_migration_008 2,790 532 19.07 0.751 migration missing_citation, stale_doc, ambiguous_owner
kb_current_migration_067 2,779 522 18.78 0.755 migration missing_citation, stale_doc, tool_boundary

このランキングがあると、「プロンプトを直す」だけでなく「どの文書を直すか」まで落とせます。
特にsecuritymigrationのような高リスクintentでは、文書レビューの優先順位をデータで決められます。

実測5: リリースゲートをSQLにする

最後に、プロンプト版のリリース判定をSQLにします。ここではv3_agenticv2_groundedと比較しました。

SELECT
    'v3_agentic_vs_v2_grounded' AS comparison,
    round((avgIf(hallucination_flag, prompt_version = 'v3_agentic') - avgIf(hallucination_flag, prompt_version = 'v2_grounded')) * 100, 2) AS hallucination_delta_pct,
    round((avgIf(citation_missing, prompt_version = 'v3_agentic') - avgIf(citation_missing, prompt_version = 'v2_grounded')) * 100, 2) AS citation_missing_delta_pct,
    round(quantileIf(0.95)(latency_ms, prompt_version = 'v3_agentic') - quantileIf(0.95)(latency_ms, prompt_version = 'v2_grounded'), 1) AS p95_latency_delta_ms,
    round((sumIf(cost_usd, prompt_version = 'v3_agentic') / countIf(prompt_version = 'v3_agentic') * 1000) - (sumIf(cost_usd, prompt_version = 'v2_grounded') / countIf(prompt_version = 'v2_grounded') * 1000), 6) AS cost_delta_per_1000_traces,
    if(
        hallucination_delta_pct <= 1.0
        AND citation_missing_delta_pct <= 1.0
        AND p95_latency_delta_ms <= 250,
        'ship',
        'hold'
    ) AS release_decision
FROM rag_traces;

結果です。

comparison hallucination_delta_pct citation_missing_delta_pct p95_latency_delta_ms cost_delta_per_1000_traces release_decision
v3_agentic_vs_v2_grounded 1.78 0.91 190.4 0.175372 hold

この例ではholdです。
理由は、p95遅延は許容内でも、幻覚率と引用漏れ率の増分がしきい値を超えているからです。

この形にしておくと、AI機能のレビューが「なんとなく良さそう」から「このSQLを通ったらship」に変わります。

実測6: ClickHouseのPrimaryKeyが効いているか見る

ここまでの集計は「SQLでRAGログを分析した」だけにも見えます。
ClickHouseを使う理由を出すには、ORDER BYとPrimaryKeyが実際に読み取り範囲を絞っているかを確認する必要があります。

今回のテーブルでは、次の順に並べています。

ORDER BY (tenant_id, app, prompt_version, event_time, trace_id)

これは、AIログでよくある調査単位に合わせています。

  • どのテナントか
  • どのAIアプリか
  • どのプロンプト版か
  • いつの期間か
  • どのtraceか

例えば、jp-smbテナントのsupport-ragアプリで、v3_agenticの2026-06-01以降だけを見るSQLを用意しました。

SELECT
    tenant_id,
    app,
    prompt_version,
    count() AS traces,
    round(avg(hallucination_flag) * 100, 2) AS hallucination_rate_pct,
    round(quantile(0.95)(latency_ms), 1) AS p95_latency_ms,
    round(sum(cost_usd), 5) AS total_cost_usd,
    topKIf(3)(failure_reason, failure_reason != 'none') AS top_failure_reasons
FROM rag_traces
WHERE
    tenant_id = 'jp-smb'
    AND app = 'support-rag'
    AND prompt_version = 'v3_agentic'
    AND event_time >= toDateTime64('2026-06-01 00:00:00', 3)
GROUP BY
    tenant_id,
    app,
    prompt_version;

結果です。

tenant_id app prompt_version traces hallucination_rate_pct p95_latency_ms total_cost_usd top_failure_reasons
jp-smb support-rag v3_agentic 5,507 16.67 2258.7 4.2556 missing_citation, stale_doc, tool_boundary

このクエリは100万件のテーブルに対して0.004 secでした。さらにEXPLAIN indexes = 1を見ると、PrimaryKeyで読み取りgranuleが絞られています。

PrimaryKey
  Keys:
    tenant_id
    app
    prompt_version
    event_time
  Parts: 4/4
  Granules: 7/124
  Search Algorithm: binary search

ここがClickHouseらしいポイントです。
RAGログは「あとで全部読むログ」ではなく、障害対応やリリース判定で特定のテナント、アプリ、プロンプト版、期間を高速に切るデータです。
ORDER BYを調査軸に合わせると、同じテーブルから全体傾向と個別調査の両方を引けます。

実測7: 100万件ログの保存サイズを見る

保存サイズも確認しました。

SELECT
    sum(rows) AS rows,
    formatReadableSize(sum(bytes_on_disk)) AS bytes_on_disk,
    formatReadableSize(sum(data_compressed_bytes)) AS compressed_data,
    formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed_data,
    round(sum(data_uncompressed_bytes) / nullIf(sum(data_compressed_bytes), 0), 2) AS compression_ratio,
    count() AS active_parts
FROM system.parts
WHERE
    database = 'rag_observability'
    AND table = 'rag_traces'
    AND active;

結果です。

rows bytes_on_disk compressed_data uncompressed_data compression_ratio active_parts
1,000,000 96.37 MiB 96.34 MiB 343.51 MiB 3.57 4

生成元のJSONEachRowファイルは約816MiBでしたが、ClickHouse上では約96MiBでした。
実データでは列の種類や文字列長で変わりますが、AIログのように列が多く、低カーディナリティな分類列が多いデータでは、列指向DBの圧縮と集計の恩恵を受けやすいです。

クエリ実行時間

100万件の手元Docker環境でも、監査クエリはすべて短時間で終わりました。

Query Elapsed seconds
prompt regression 0.016
retrieval score failure 0.011
latency outliers 0.017
hallucination sources 0.125
daily quality cost 0.012
release gate 0.007
filtered tenant prompt slice 0.004
storage parts 0.004
explain primary key 0.002

もちろん、本番では件数、パーティション、ORDER BY、圧縮、マテリアライズドビュー、分散構成で数字は変わります。それでも、RAGログのような追記型・時系列・集計中心のデータでは、ClickHouseを「AIの観測DB」として使う価値があります。

SQLite/PostgreSQLだけだと何が厳しいか

誤解を避けるために書くと、SQLiteやPostgreSQLでもAIログの保存や分析はできます。
小規模なPoC、管理画面の絞り込み、業務レコードとのJOINが主目的なら、むしろ既存のPostgreSQLに寄せた方が運用は簡単です。

ただし、今回のようなRAG監査ワークロードでは、見る軸が増えます。

  • 追記中心の大量イベント
  • tenant_id, app, prompt_version, model, query_intentの多軸集計
  • p95/p99の遅延監視
  • 文書ID配列を展開した失敗ランキング
  • 日別・版別のコスト集計
  • リリース前後の差分判定

この条件では、SQLite/PostgreSQLだけで押し切ると次の設計が重くなります。

観点 SQLiteで厳しい点 PostgreSQLで厳しい点 ClickHouseで楽になる点
追記型ログ 単一ファイルDBとしてローカル検証には強いが、継続的な高頻度ログ集計には向きにくい OLTP本体と分析クエリが同居すると負荷分離が必要 追記・集計中心の列指向テーブルとして分けやすい
多軸集計 100万件以上でp95やgroup byを何度も切る用途は重くなりやすい index、partition、materialized viewをかなり設計する必要がある LowCardinality, MergeTree, ORDER BYで集計軸を設計しやすい
配列展開 retrieved_doc_idsのような配列ログを高速に分析する設計が難しい JSONB/配列/正規化の選択で設計が割れやすい Array(String) + arrayJoinで文書別ランキングを作りやすい
p95/p99 percentile系を繰り返す分析は用途外になりがち 可能だが、運用DBで重い分析を回すと影響範囲が広い quantile系の集計を監査SQLに組み込みやすい
圧縮と保管 ログ保管がファイル肥大化しやすい 圧縮や古いpartition管理を別途考える 今回はJSONEachRow約816MiB相当をテーブル上約96MiBで保持できた

つまり、SQLite/PostgreSQLが悪いという話ではありません。役割を分けるのが現実的です。

役割 向いているDB
ユーザー、権限、業務レコード PostgreSQL
ローカルPoC、軽量な再現テスト SQLite
RAG/AIエージェントの大量監査ログ ClickHouse
ベクトル検索そのもの vector DB / PostgreSQL pgvector / 専用検索基盤

AI時代のデータベース設計では、「全部を1つのDBに入れる」よりも、業務状態はOLTP、検索は検索基盤、監査ログはClickHouseのように役割を分けた方が、リリース判定と障害調査がやりやすくなります。

実務に入れるときのチェックリスト

RAG/AIエージェントのログをClickHouseに入れるなら、最初に次を決めておくと後で効きます。

  • trace_idを全サービスで共通にする
  • prompt_versionmodelを必ず残す
  • 検索結果は本文ではなくdoc_idとscoreを残す
  • hallucination_flagは人手評価、LLM評価、自動テストのどれかを明記する
  • citation_missingを幻覚とは別指標にする
  • latency_msを検索・生成・ツール実行に分ける
  • cost_usdまたは推定token数を残す
  • リリース前後を比較できるように、実験群と対照群を同じテーブルに入れる
  • 個人情報や機密文はClickHouseに直接入れず、マスキング後のメタデータを入れる
  • 失敗文書ランキングを週次のナレッジ改善タスクに接続する

本番導入テンプレ

本番に入れるなら、最初から巨大な基盤を作るより、次の4層で始めるのが現実的です。

役割 最初に作るもの
収集 アプリからAI実行ログを送る trace_id, tenant_id, prompt_version, model, latency_ms
評価 回答品質を後付けで更新する hallucination_flag, citation_missing, feedback_score
監査 リリース可否を見る prompt版比較SQL、p95遅延SQL、コストSQL
改善 改修タスクへつなぐ 文書別失敗ランキング、低score回答リスト

最初の運用ルールはこのくらいで十分です。

release gate:
  hallucination_delta_pct <= 1.0
  citation_missing_delta_pct <= 1.0
  p95_latency_delta_ms <= 250

retrieval guard:
  retrieval_top_score < 0.55 -> do not answer, ask a clarification
  0.55 <= retrieval_top_score < 0.70 -> answer with weak-evidence warning

weekly knowledge review:
  sort documents by hallucination_count desc
  review top 20 documents
  fix stale_doc and missing_citation first

このテンプレの狙いは、AIを「チャット機能」として見るのをやめ、リリース判定・障害調査・ナレッジ改善が回るプロダクト機能として扱うことです。

失敗パターン

今回の検証から、RAG運用で起きがちな失敗を5つに整理できます。

失敗パターン 症状 対策
検索スコアだけを見る top-kは返るが回答品質が改善しない retrieval_top_scorehallucination_flagを同じテーブルで見る
プロンプトだけを直す 失敗文書が残り続ける arrayJoin(retrieved_doc_ids)で文書別に失敗率を見る
平均遅延だけを見る p95/p99でUXが壊れる quantile(0.95), quantile(0.99)をリリースゲートに入れる
引用漏れを幻覚に混ぜる どの品質問題なのか判断できない hallucination_flagcitation_missingを分ける
コストを後で見る 品質改善と同時に運用費が跳ねる cost_usdを版別・日別に集計する

まとめ

AI時代のデータベースは、単に「ベクトルを保存できるDB」ではありません。
RAGやAIエージェントを本番運用するなら、検索、生成、評価、遅延、コスト、文書品質を横断して見る必要があります。

今回の100万件ベンチマークでは、ClickHouseで次の判断ができました。

  • プロンプト版ごとの幻覚率・引用漏れ率・遅延を比較する
  • 検索スコアが低いバケットの失敗率を確認する
  • 失敗に絡む文書をランキングする
  • PrimaryKeyで特定テナント・アプリ・プロンプト版・期間を高速に切る
  • 100万件ログの保存サイズと圧縮比を確認する
  • p95遅延と品質差分でリリース可否を決める
  • AIログを「後から読むログ」ではなく「ship/holdを決めるデータ」に変える

RAGの精度改善は、モデル選定やプロンプト改善だけでは足りません。

AIの失敗をSQLで監査できる状態にすることが、AI時代のデータベースに求められる役割だと考えます。

参考リンク

この記事を書いた人✏️@YushiYamamoto
ITPRODX.com代表 / AIアーキテクト
Next.js / TypeScript / n8nを活用した自律型アーキテクチャ設計を専門としています。
日々の自動化の検証結果や、ビジネス側の視点(ROI等)に関するより深い考察は、以下の公式サイトおよびnoteで発信しています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?