3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Databricksのカスタマーストーリーを集めてGenieに食べさせたら、提案ネタ探しがかなり楽になった話

3
Posted at

はじめに

営業部でプリセールスエンジニアをやっていると、提案前に毎回そこそこ頑張ることがあります。

それが、「似た導入事例ないかな?」を探す作業です。

自分は営業部所属ですが、もともと十数年開発を担当しSalesforceやServiceNow、AWSやAzureも関わっていたこともあり、こういう面倒ごとはつい仕組みで解決したくなります。最近は Claude Code が全部やってくれることもあり、なおさらその傾向が強くなりました。

そこで今回やったのがDatabricks のカスタマーストーリーを Databricks に取り込んで、Genie で提案で使えるようにする仕組みです。

公開されている導入事例を読む・要約するだけなら、汎用LLMでもかなり近いことはできます。
ただ、提案の現場で欲しいのはそこだけではなくて、

  • 公開されている Web の事例
  • PDF や PowerPoint でもらった個別事例
  • グループ会社や関係者向けに管理されている、一般公開していない導入情報
  • アーキテクチャや規模感から費用感を算出

みたいなものを、まとめて横断的に探せることだったりします。

g2DaqAxI.jpg
提案前の「似た事例ないかな…」を毎回人力でやるの、なかなかしんどい

何がつらかったのか

提案前の情報収集って、やっていること自体はシンプルなんですよね。
Databricks の導入事例ページを見に行って、気になるものをいくつか開いて、PDF があればそっちも見て、英語の事例なら雰囲気で読み、日本語で提案文に直す。
特に「日本企業での事例ってないの?」というオーダーが多いですし、1件2件ならいいのですが、案件が重なると普通にしんどいです。

しかも、提案で使いたいのは単なる「要約」だけではなくて、たとえばこんな観点です。

  • 製造業でのユースケースはあるか
  • データ分析基盤の刷新文脈で話せるか
  • AI/BI 的な見せ方ができるか
  • 導入効果を提案書にそのまま転記しやすいか
  • 似た規模感・似た課題の事例があるか

このへんを毎回ゼロから見にいくのは、さすがに人力だとつらい。

だったら、事例を先に Databricks 側へ寄せておいて、自然言語で聞けるようにしてしまおう、というのが今回の発想です。

本当は、Databricks の Agent Bricks Knowledge Assistant のような仕組みをもっと素直に使えれば話は早いのかもしれません。
ただ、日本リージョンを使っていて2026年2月時点でAgent Bricks Knowledge Assistantはまだ提供されていないことと、ベクトル検索を使うと時間単位で徐々にコストががががが…、気軽に常時回すには少し悩ましい、という非常に現実的な部内事情もあります。

技術的には「それが正攻法では?」と思いつつ、現場ではちゃんと使えることと同じくらいちゃんと払えることも大事です。
なので今回は、なるべく今ある構成で回せるようにして、まずは公開事例を取り込んで Genie で使える形に寄せるところから始めました。

今回やったこと

ざっくり言うと、やったことはシンプルです。

  1. Databricks のカスタマーストーリー一覧を巡回する
  2. 各事例ページの本文や添付 PDF を回収する
  3. テキストとして扱いやすい形にする
  4. チャンク化して Databricks のテーブルに保存する
  5. Genie から質問できるようにする

今回のゴールは「RAG を作ること」そのものではなく、提案業務で使える事例検索の土台を作ることでした。

なので、実装としては派手なことをしているというより、

  • 取得する
  • 整える
  • 検索しやすくする
  • 回答を提案向けに寄せる

という、わりと地味だけど大事な部分をやっています。

ざっくり構成

今回の流れを図にするとこんな感じです。

Databricks カスタマーストーリー一覧
    ↓
各事例ページを取得
    ↓
ページを PDF 化 / 添付 PDF も回収
    ↓
テキスト抽出
    ↓
チャンク化
    ↓
Delta テーブルに保存
    ↓
Genie から自然言語で検索・要約

実装全体はノートブックで組んでいますが、記事ではまず「どこをどう制御しているか」が分かる設定部分だけ載せます。

CATALOG = "your_catalog"
SCHEMA = "sales_demo"
TABLE_NAME = "databricks_customer_stories"

START_PAGE = 1
END_PAGE = 44

CHUNK_CHARS = 2500
CHUNK_OVERLAP = 300

ONLY_NEW = "true"
BASE_LIST_URL = "https://www.databricks.com/jp/customers?page={page}"

このあたりの設定で、

  • Databricks 側の保存先
  • どの一覧ページを巡回するか
  • 1チャンクをどのくらいのサイズで切るか
  • 差分取り込みにするか

を決めています。

「Genie に食べさせる」と一言で書くと軽そうですが、実際にはGenie の前段で、検索しやすい形に整えるところがいちばん大事でした。

N7qKomoN.jpg
公開情報も手元の資料も、最終的には“聞ける状態”に寄せたい

取り込み部分はどう作ったか

今回は一覧ページの巡回や事例ページの取得に Playwright を使っています。

理由はシンプルで、普通の HTTP 取得だけだとちょっと取りづらい場面があるからです。
素直に開いて、そのままページを PDF にしたほうが後工程も楽でした。

まずは一覧ページをレンダリングして、事例URLを拾います。

async def extract_story_urls_from_list_page(page_num: int):
    url = BASE_LIST_URL.format(page=page_num)
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(
            user_agent="Mozilla/5.0 ...",
            locale="ja-JP",
            timezone_id="Asia/Tokyo"
        )
        page = await context.new_page()
        await page.goto(url, wait_until="domcontentloaded", timeout=180_000)
        await page.wait_for_timeout(3000)

        hrefs = await page.eval_on_selector_all(
            "a[href]", "els => els.map(e => e.getAttribute('href'))"
        )

ここでは、ページ描画後の a[href] を見て /jp/customers/* に該当するものを拾っています。
つまり「HTMLをベタ読みして終わり」ではなく、実際にブラウザで開いて拾う方針です。

次に、個別の事例ページを PDF 化します。

async def render_story_page_to_pdf(story_url: str, out_pdf_path: str):
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(
            user_agent="Mozilla/5.0 ...",
            locale="ja-JP",
            timezone_id="Asia/Tokyo"
        )
        page = await context.new_page()

        await page.goto(story_url, wait_until="domcontentloaded", timeout=180_000)
        await page.wait_for_timeout(1500)

        pdf_bytes = await page.pdf(
            format="A4",
            print_background=True,
            margin={"top": "12mm", "bottom": "12mm", "left": "10mm", "right": "10mm"},
        )

導入事例って、ページだけで完結しているものもあれば、PDF が添付されているものもあります。
なので今回は、ページそのものも PDF 化してしまって、添付PDFと同じ文書パイプラインに寄せることにしました。

このあたりは実務寄りの作りですが、あとで扱いやすくするにはかなり効きます。

PDF 化とチャンク化を入れた理由

今回、自分の中で割と大事だったのが、ページ本文だけでなく PDF も含めて同じ土俵で扱えるようにしたことです。

導入事例って、ページだけで完結しているものもあれば、PDF で詳しい資料がぶら下がっているものもあります。
さらに現場では、個別にもらう提案補助資料や PowerPoint が混ざることもあるので、最終的には「文書であること」を起点に揃えたほうが扱いやすいです。

なので今回は、

  • Web ページは PDF 化して保存
  • 添付 PDF も回収
  • テキスト抽出後にチャンク化
  • 文書種別を持ったまま保存

という流れにしました。テキストサイズがあまりにも大きすぎると Genie が途中で諦めちゃうことが多いので回答にブレがでちゃったんですよね

wI9dhs9g.jpg

まずはチャンクサイズの設定です。ここは最適解というより、まず試しやすい値から始めています。

CHUNK_CHARS = 2500
CHUNK_OVERLAP = 300

次に、PDF を構造化してテキスト抽出します。

SELECT
  RIGHT(path, len(path)-5) AS doc_uri,
  ai_parse_document(
    content,
    map(
      'version','2.0',
      'descriptionElementTypes','*'
    )
  ) AS parsed
FROM READ_FILES('/Volumes/.../*.pdf', format => 'binaryFile')

最後に、全文をそのまま持たせるのではなく、固定長 + オーバーラップで結構ざっくり目にチャンク化します。

@F.udf(returnType=ArrayType(chunk_struct))
def chunk_udf(text: str):
    chunks = chunk_text_fixed(text or "", CHUNK_CHARS, CHUNK_OVERLAP)
    out = []
    for idx, c in chunks:
        out.append({
            "chunk_index": idx,
            "chunk_text": c,
            "chunk_char_len": len(c),
            "chunk_hash": sha256_hex(c),
        })
    return out

Delta テーブルに載せると何がうれしいのか

文書を回収して終わりだと、結局また探しにくいです。

なので、最終的には Genie から使いやすいように、チャンク単位でテーブルに持たせています。
保持しているのは以下のような情報です。

  • 事例元(Databricks社の情報?社内の情報?グループの情報?)
  • 種類(ページ or PDF)
  • 取得元 URL
  • 取得日
  • タイトル
  • 文書 ID
  • チャンク番号
  • チャンク本文
  • ハッシュ
  • 更新日時

こうしておくと、

  • 再取り込み時に差分を見やすい
  • URL 単位で元ネタに戻りやすい
  • Genie 側で根拠付きにしやすい
  • 後から別用途にも流用しやすい

というメリットがあります。

AI というと派手な印象はありますが、お客様への提案でもめちゃくちゃ大事なのがこの地味なメタデータ設計ですよと伝えています。

Genie にはどう食べさせたか

後は、テーブルを Genie Space で指定するだけですが、Genie 側では一般的な指示に設定を行っています。

やりたかったのは雑な要約ではなくて、提案書に転記しやすい形の返答です。
なので、たとえばこんな方針を入れています。

  • 日本語ドキュメントを優先する
  • 日本語が少なければ英語を翻訳して回答する
  • 根拠を本文中で引用する
  • 取得元 URL を明示する
  • 見つからない場合は「該当情報がありません」と言う
  • 推測は注記扱いにする
  • 提案書に書きやすい体裁で返す
  • アーキテクチャや規模から社内の事例を参考値として費用感を返す

実際の設定全文はここでは出しませんが、ポイントは**「何を答えるか」より「どう答えるか」をかなり明示したこと**です。

LLM は賢いですが、業務文脈では「いい感じにやって」だとちょっと危ない。
逆に、回答ルールを先に固めると、提案の下書きとしてかなり使いやすくなります。

実際にどう使うのか

使い方としては本当にシンプルで、Genie に自然言語で聞くだけです。

たとえばこんな感じです。

  • 製造業で Databricks を使った導入事例を提案向けにまとめて
  • データ基盤刷新の文脈で使えそうな事例を3件教えて
  • 日本語の事例を優先して、導入背景・効果・提案での言い回しを整理して
  • 類似する事例がなければ英語も含めて要約して

すると、URL 付き・引用付きで、提案のたたき台としてそのまま使いやすい返答が返ってきます。

もちろん最終的な表現は人間が整えます。
でも、ゼロから調べて書くのに比べるとかなり楽です。

この「ゼロイチを AI に任せて、最後の整形だけ人がやる」感じは、プリセールスとの相性がかなりいいと思っています。

あと、今回よかったのは、Genie の一般的な指示をあらかじめ定義しておくことで、こちらの質問が多少ラフでも、提案向けに要点を整理して返してくれるようになったことです。
提案経験の浅いメンバーでも提案の要点を理解し提案書骨子の構成が一定になることです。

たとえば、単に「製造業の事例ある?」くらいの聞き方でも、

  • 日本語のドキュメントを優先する
  • 必要なら英語を日本語にして返す
  • 根拠になった箇所を引用する
  • 提案書に書きやすい形でまとめる
  • 元の URL も示す

といったルールを先に持たせておくことで、毎回こちらが細かく指示しなくても、それなりに“仕事で使える返し方”をしてくれます。

このへんは地味ですがかなり効いていて、毎回プロンプトを頑張るというより、Genie 側に回答の作法を覚えてもらうイメージに近いです。
簡素な質問でも要点を押さえてくれるので、提案前の下調べの初速が上がりました。

hlsxvp5Z.jpg
ラフな質問でも、回答の作法を先に定義しておくとかなり使いやすい

ここで、実際に効いていた一般的な指示の考え方はこんな感じです。

あなたはDatabricksの導入事例に関するアシスタントです。
ユーザーの質問や事例要求に対して、Databricks社のWebサイトや自社事例、グループ会社が公開したドキュメントから日本語で回答してください。

【回答ルール】
1. 日本語のドキュメントを最優先で回答する
2. 根拠として使用した箇所は「」形式で引用する
3. 提案書に書きやすい体裁で回答する
4. 取得元URLをハイパーリンクとして表示する
5. 見つからない場合は「提供された事例には該当情報がありません」とちゃんと答える

実際に使ってみたかったのは公開されているカスタマーストーリーだけではありません。

  • 自社で蓄積してきた事例
  • グループ会社で共有可能な事例
  • 関係者向けに管理されている事例
  • 一般公開はしていないが、社内で提案用途に参照される導入情報

このあたりこそ、提案時にいちばん効くことがあります。

もちろん、こうした情報は取り扱いルールや権限制御を前提に扱う必要がありますが、その前提のうえで、まずは許可された範囲の PDF を手動でアップロードして試しました。

やり方としては手堅い運用ですが、公開 Web の事例と手元の PDF を同じ検索体験に寄せられるだけでも、かなり価値があります。

公開情報だけを要約するなら、汎用LLMでもかなり頑張れます。
ただ、提案の現場で効くのは、公開情報に加えて自分たちの文脈の情報までまとめて扱えることでした。

ここがよかった

やってみて素直によかったのは、公開事例を“読む”から“聞く”に変えられたことです。

ただページを貯めるだけだと、結局あとで人間がまた読む必要があります。
でも Genie で聞けるようにすると、

  • 条件をつけて探せる
  • 似た観点で横並び比較できる
  • 提案向けの文章に寄せられる
  • 根拠 URL に戻れる

という形に変わります。

特によかったのは、公開情報と手動で追加した PDF ベースの事例を、同じ問いかけ方で扱えるようになったことです。
「Web に載っている話」と「社内でしか見られない話」が別々の場所にある状態だと、結局は人間が頭の中でつなぐしかありません。そこを少しでもまとめて扱えるようになると、提案前の下調べがだいぶ楽になります。

あと、今回いちばん大きかったのは、今後の拡張イメージがかなり明確になったことです。

公開されている Databricks のカスタマーストーリーだけなら、正直汎用LLMでもかなり戦えます。
でも、そこに

  • グループ会社の導入事例
  • 非公開の社内ナレッジ
  • 提案メモ
  • PDF や PowerPoint の補助資料
  • 構築プロジェクトの議事録

みたいなものを混ぜられるようになると、一気に価値が変わり自分たちのデータ側に寄せた基盤の強みだなと思いました。

逆に泥臭かったところ

もちろん、きれいごとだけでは終わりません。

公開 Web の情報はある程度自動で取り込めても、現場で本当に欲しい PDF や PowerPoint は、もらいものだったり、関係者限りだったり、保存場所がバラバラだったりします。

なので今のところは、個別の事例は手動でアップロードして登録する運用も併用しています。

ここはちょっと泥臭いですが、逆に言うと、業務で使う仕組みってだいたいこんなものだよなとも思っています。
全部を最初から完全自動化しようとすると、たぶん進みません。

あとは週1でWait置きながら取りに行ってはいるものの、「いつブロックされるかな?」とドキドキしていますし、サイトの構造変更などもありますしね
このへんはわりと素直に、運用で殴る世界です。

まとめ

やっていることだけ見るとそこまで派手ではないのですが、実務ではかなり効きました。

今回のポイントをまとめるとこんな感じです。

  • 公開事例を自然言語で引けるようにした
  • 提案向けの回答ルールを Genie に持たせた
  • 根拠 URL や引用を返せる形にした
  • 将来的に非公開資料も含めた横断検索へ広げやすくなった
  • 一方で、クロール運用や手動登録はそれなりに泥臭い
  • Claude Code でほとんどコード書かずにできたこと(一番大事)

たぶんこの手の仕組みって、Genie がすごいというより、Genie の前にどれだけ情報を揃えて整えられるかが本質なんだと思います。

次は、公開されているカスタマーストーリーだけでなく、手元の PDF や PowerPoint、関係者向けの情報ももう少し自然に混ぜられるようにしたいところです。

そして定期クロールは、今日も無事に動いてくれることを祈ります。

公開情報を要約するだけなら、汎用LLMでもかなりできます。
それでも今回あえて Databricks 側に寄せたのは、最終的に欲しかったのが“自分たちの文脈の情報まで含めて検索できること”だったからです。

たぶんこの差が、便利なおもちゃで終わるか、仕事で使う道具になるかの分かれ目なんだと思っています。

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?