【Google Cloud イベント体験記】LangChain を用いた対話型生成 AI アプリの作り方

<!-- wp:paragraph -->
<p>2024/09/12(木)に開催された <a href="https://rsvp.withgoogle.com/events/tga_genai_jp_pdt24022">生成 AI Application Development with LLMs on Google Cloud</a> のテクニカルトレーニングに参加しました。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>そこで感じたこと、学んだことを紹介します！</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">なぜトレーニングイベントに参加したのか</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>理由は以下の2つです。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">仕事に関係しない技術の探究</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>1つは、ふだんの仕事では使わない技術に触れるきっかけが欲しかったからです。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>エンジニアとして仕事で使う技術を勉強するのは一般的なことですが、仕事に必要なことばかり学んでいると徐々に視野が狭まる気がします。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>「仕事のため」という意識が続くと、<strong>好奇心に従って新しい知識を探求する</strong>という楽しみも薄れるでしょう。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>技術知識を増やすことは、今後参画するプロジェクトの幅を広げられるはずです。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>長期的にみると、定期的に仕事と関係ない技術を学ぶようにしたいものです。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>私はこれまで生成 AI のアプリ開発をしたことがなかったので、今回のイベントはちょうど良い内容でした。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">社外エンジニアとの交流</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>もう一つの動機は、社外エンジニアとの交流です。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>結果としては、今回のイベントは講義形式だったのでほとんど交流機会はありませんでしたが...。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>日ごろ、社内のエンジニアとは 1on1 などでキャリアや勉強法、セルフマネジメントについて話すことが多いです。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>社外エンジニアと会話することで、</p>
<!-- /wp:paragraph -->

<!-- wp:list {"className":"is-style-index -list-under-dashed"} -->
<ul class="wp-block-list is-style-index -list-under-dashed"><!-- wp:list-item -->
<li>世の中に技術がどのように活用されているのか</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>どのような課題を解決しているのか</li>
<!-- /wp:list-item -->

<!-- wp:list-item -->
<li>世の中の企業は何に困っているのか</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>などを知る機会になれば良いなという思いがありました。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>技術が問題を解決しているリアルな実情を知れたら、勉強のモチベーションも上がるでしょう。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>ビジネス的な視点以外にも、単に社外の人との交流することで気晴らしになるという側面もあると思っています。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>私はまだエンジニア歴1年弱と経験が浅いので、私にとって技術力と経験のあるエンジニアとの交流機会は貴重です。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>意識的に社外エンジニアと交流する機会は作っていきたいものです。</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">トレーニングイベントで学んだこと</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>以降では、イベントで学んだことを書きます。生成 AI アプリ開発に興味がある方はぜひ参考にしてみてください。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>今回のイベントでは、LangChain を使った対話型生成 AI チャットアプリ開発について学びました。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>以下に特に勉強になったトピックを書きます。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">生成 AI の課題</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>昨今の生成 AI は、与えるプロンプトの工夫次第でかなり高精度で人間が求める回答をしてくれるようになりました。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>とは言え、まだまだ品質の制御は難しいようです。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>特に計算問題や、生成 AI のモデルに学習されていない情報について回答させると不正確な答えが返ってきたりします。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>生成 AI を使う側は、<strong>AI が不正確な回答をし得ることをよく理解したうえで利用することが重要</strong>です。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>また、生成 AI が誤った情報をあたかも正しいことのように説明することをハルシネーション（幻覚）と呼びます。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">プロンプトエンジニアリング</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><strong>生成 AI からより正確な回答を得るための指示や命令、設計の技術</strong>をプロンプトエンジニアリングと呼びます。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>以下に代表的なプロンプト技術を紹介します。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Zero-shot prompting</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Zero-shot prompting は、具体例などの詳細説明を与えずに回答させる方法です。</p>
<!-- /wp:paragraph -->

<!-- wp:loos/cap-block {"className":"is-style-inner"} -->
<div class="swell-block-capbox cap_box is-style-inner"><div class="cap_box_ttl"><span><strong><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDUuMiAxMC4xIDQzLjEgOGMtLjQtLjQtMS0uNC0xLjQgMEwxNi4yIDMzLjNsLTkuOS05LjljLS40LS40LTEtLjQtMS40IDBsLTIuMSAyLjFjLS40LjQtLjQgMSAwIDEuNGwxMy40IDEzLjQgMjktMjljLjQtLjIuNC0uOSAwLTEuMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsCheck" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span> プロンプト例</strong></span></div><div class="cap_box_content"><!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box">以下の文章から読み取れる感情は「ポジティブ」「ネガティブ」のどちらですか？<br>文章：今日の天気は晴れです！</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>ChatGPT 4o の回答</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box">この文章から読み取れる感情は「ポジティブ」です。</p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:loos/cap-block -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Few-shot Prompting </h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Few-shot Prompting は、回答パターンや具体例を示したうえで回答させる方法です。</p>
<!-- /wp:paragraph -->

<!-- wp:loos/cap-block {"className":"is-style-inner"} -->
<div class="swell-block-capbox cap_box is-style-inner"><div class="cap_box_ttl"><span><strong><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDUuMiAxMC4xIDQzLjEgOGMtLjQtLjQtMS0uNC0xLjQgMEwxNi4yIDMzLjNsLTkuOS05LjljLS40LS40LTEtLjQtMS40IDBsLTIuMSAyLjFjLS40LjQtLjQgMSAwIDEuNGwxMy40IDEzLjQgMjktMjljLjQtLjIuNC0uOSAwLTEuMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsCheck" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span> プロンプト例</strong></span></div><div class="cap_box_content"><!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box">りんご：赤<br>ピーマン：緑<br>みかん：橙<br>バナナ：黄<br><br>上記に倣って、ナスについて答えて。<br>ナス：</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>ChatGPT 4o の回答</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box">ナス：紫</p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:loos/cap-block -->

<!-- wp:paragraph -->
<p>上記のように、明示的に色に言及していない質問にも回答できています。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Chain-of-Thought Prompting</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Chain-of-Thought Prompting は、連鎖的にプロンプトを与えることで求める回答に近づけていくプロンプト技術です。</p>
<!-- /wp:paragraph -->

<!-- wp:loos/cap-block {"className":"is-style-inner"} -->
<div class="swell-block-capbox cap_box is-style-inner"><div class="cap_box_ttl"><span><strong><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDUuMiAxMC4xIDQzLjEgOGMtLjQtLjQtMS0uNC0xLjQgMEwxNi4yIDMzLjNsLTkuOS05LjljLS40LS40LTEtLjQtMS40IDBsLTIuMSAyLjFjLS40LjQtLjQgMSAwIDEuNGwxMy40IDEzLjQgMjktMjljLjQtLjIuNC0uOSAwLTEuMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsCheck" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span> プロンプト例</strong></span></div><div class="cap_box_content"><!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box">ナオキさんは、鉛筆を15本持っており、2本を友人のカズヤさんにあげました。<br>翌日、知り合いのミキさんから鉛筆を3本もらった直後に<br>兄弟のタクヤさんと13本の鉛筆を同じ数だけ交換しました。<br>現在、ナオキさんは鉛筆を合計何本もっていますか。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>ChatGPT 4o の回答</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box">ナオキさんが現在持っている鉛筆の本数を順を追って計算します。<br>1. 初めにナオキさんは15本の鉛筆を持っています。<br>2. カズヤさんに2本あげたので、15 - 2 = <strong>13本</strong>になります。<br>3. 翌日、ミキさんから3本もらいましたので、13 + 3 = <strong>16本</strong>になります。<br>4. タクヤさんと13本の鉛筆を同じ数だけ交換したため、鉛筆の本数は変わりません（交換なので増減なし）。<br>したがって、現在ナオキさんは<strong>16本</strong>の鉛筆を持っています。</p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:loos/cap-block -->

<!-- wp:paragraph -->
<p>質問文ごとに対応する計算過程を回答しており、最終的に正しい回答をしています。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">ReAct</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>ReAct は、推論（Reasoning）と行動（Acting)を組み合わせて、言語モデルで推論とタスク遂行を行わせるプロンプト技術です。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Thought（思考）、Action（行動）、Observation（観察）の3つをプロンプトに含めるのが一般的のようです。</p>
<!-- /wp:paragraph -->

<!-- wp:loos/cap-block {"className":"is-style-inner"} -->
<div class="swell-block-capbox cap_box is-style-inner"><div class="cap_box_ttl"><span><strong><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDUuMiAxMC4xIDQzLjEgOGMtLjQtLjQtMS0uNC0xLjQgMEwxNi4yIDMzLjNsLTkuOS05LjljLS40LS40LTEtLjQtMS40IDBsLTIuMSAyLjFjLS40LjQtLjQgMSAwIDEuNGwxMy40IDEzLjQgMjktMjljLjQtLjIuNC0uOSAwLTEuMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsCheck" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span> プロンプト例</strong></span></div><div class="cap_box_content"><!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box">エンジニアの効率的な勉強方法を教えてください。<br>Thought：<br>Action：<br>Observation：</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>ChatGPT 4o の回答</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph {"className":"is-style-dent_box"} -->
<p class="is-style-dent_box"><strong>Thought:</strong><br>エンジニアの効率的な勉強方法を模索する際、効果的なアプローチとして具体的な行動計画を立てることが重要です。<br><strong>Action:</strong><br>目標設定 - 学習する分野やスキルを明確にします。<br>教材選び - 信頼できる教材やオンラインコースを活用。<br>実践 - コーディングやプロジェクトベースの学習で知識を応用。<br>コミュニティ参加 - オンラインフォーラムやオープンソースプロジェクトに参加。<br>レビューとフィードバック - 定期的に進捗を確認し、改善点を見つける。<br><strong>Observation:</strong><br>自分の理解度を高めるためには、実践的な経験とフィードバックが重要です。</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol class="wp-block-list"><!-- wp:list-item -->
<li></li>
<!-- /wp:list-item --></ol>
<!-- /wp:list --></div></div>
<!-- /wp:loos/cap-block -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Google Cloud のデータガバナンス</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>まず、データガバナンスという用語について、以下に Google Cloud が定義する内容を示します。</p>
<!-- /wp:paragraph -->

<!-- wp:loos/cap-block {"className":"is-style-onborder_ttl"} -->
<div class="swell-block-capbox cap_box is-style-onborder_ttl"><div class="cap_box_ttl"><span><strong><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ0OCA1MTIiPjxwYXRoIGQ9Ik00NDggODB2NDhjMCA0NC4yLTEwMC4zIDgwLTIyNCA4MFMwIDE3Mi4yIDAgMTI4VjgwQzAgMzUuOCAxMDAuMyAwIDIyNCAwUzQ0OCAzNS44IDQ0OCA4MHpNMzkzLjIgMjE0LjdjMjAuOC03LjQgMzkuOS0xNi45IDU0LjgtMjguNlYyODhjMCA0NC4yLTEwMC4zIDgwLTIyNCA4MFMwIDMzMi4yIDAgMjg4VjE4Ni4xYzE0LjkgMTEuOCAzNCAyMS4yIDU0LjggMjguNkM5OS43IDIzMC43IDE1OS41IDI0MCAyMjQgMjQwczEyNC4zLTkuMyAxNjkuMi0yNS4zek0wIDM0Ni4xYzE0LjkgMTEuOCAzNCAyMS4yIDU0LjggMjguNkM5OS43IDM5MC43IDE1OS41IDQwMCAyMjQgNDAwczEyNC4zLTkuMyAxNjkuMi0yNS4zYzIwLjgtNy40IDM5LjktMTYuOSA1NC44LTI4LjZWNDMyYzAgNDQuMi0xMDAuMyA4MC0yMjQgODBTMCA0NzYuMiAwIDQzMlYzNDYuMXoiPjwvcGF0aD48L3N2Zz4=)" data-icon="FasDatabase" data-id="0" aria-hidden="true" class="swl-inline-icon"> </span>データガバナンスとは</strong></span></div><div class="cap_box_content"><!-- wp:paragraph -->
<p>データ ガバナンスは、データの取得から、使用および廃棄に至るまでのライフサイクル全体にわたってデータを管理するための原則に則ったアプローチです。</p>
<!-- /wp:paragraph -->

<!-- wp:loos/post-link {"style":"slim","isNewTab":true,"rel":"noopener noreferrer","linkData":{"url":"https://cloud.google.com/learn/what-is-data-governance?hl=ja#data-governance-in-the-cloud"},"icon":"externalLink"} /--></div></div>
<!-- /wp:loos/cap-block -->

<!-- wp:paragraph -->
<p>データ管理において、特にセキュリティ面の不安から、重要なデータをクラウド環境に保管することに抵抗のある企業・個人は少なくないのではないでしょうか。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Google Cloud では、豊富なセキュリティサービス・監視サービスを提供してくれています。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>生成 AI を使用する場合に関しても基盤モデルに送信される顧客データはすべて暗号化され、顧客からの明示的な同意がなければ学習に使用されることもありません。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>最低限のセキュリティ知識は必要ですが、正しく運用すればセキュリティリスクを抑えられるはずです。</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2 class="wp-block-heading">LangChain を使った対話型 AI チャットアプリ開発</h2>
<!-- /wp:heading -->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">LangChain とは</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>LangChain は、<strong>大規模言語モデル（LLM）に基づいてアプリケーション開発を構築するための OSS フレームワーク</strong>です。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Python や TypeScript などの言語をサポートしています。以下では、Python での実装例を書いています。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">LangChain を用いた対話型アプリの実装例</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>以下に LangChain を用いた対話型アプリの実装例を示します。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>実行環境は Google Cloud の Vertex AI ワークベンチの Jupyter Notebook を想定しています。</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">ライブラリのインストール</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>以下のコマンドで必要なライブラリをインストールしましょう</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>明示的にバージョン指定していないライブラリは最新バージョンをインストールするよう <code>--upgrade</code> オプションをつけています。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>また、<code>--user</code> オプションで、Notebook にログインしているユーザーにのみインストールするようにしています。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"bash","langName":"Bash"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-bash" data-lang="Bash"><code>! pip install google-cloud-aiplatform \
    langchain==0.0.323 \
    chromadb==0.3.26 \
    pydantic==1.10.8 \
    typing-inspect==0.8.0 \
    typing_extensions==4.5.0 \
    pandas \
    datasets \
    google-api-python-client \
    pypdf \
    faiss-cpu \
    transformers \
    config \
    --upgrade --user</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">カーネルインスタンスの再起動</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>ライブラリをインストールできたら、Kernel を再起動して環境が新しいパッケージにアクセスできるようにします。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>以下のコードを Notebook セルで実行しても良いですし、Notebook の UI から手動で Kernel を Restart しても良いです。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"python","langName":"Python"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-python" data-lang="Python"><code>import IPython

app = IPython.Application.instance()
app.kernel.do_shutdown(True)</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">ライブラリのインポート</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>以下の Notebook セルを実行して使用するライブラリをインポートしましょう。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>LangChain と Vertex AI SDK のバージョンを出力します。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"python","langName":"Python"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-python" data-lang="Python"><code>import time

import langchain
from google.cloud import aiplatform
from langchain.chat_models import ChatVertexAI
from langchain.embeddings import VertexAIEmbeddings
from langchain.llms import VertexAI
from langchain.schema import HumanMessage, SystemMessage
from pydantic import BaseModel
from langchain.prompts import PromptTemplate

print(f&quot;LangChain version: {langchain.__version__}&quot;)
print(f&quot;Vertex AI SDK version: {aiplatform.__version__}&quot;)</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:paragraph {"className":"is-style-balloon_box2"} -->
<p class="is-style-balloon_box2">Output</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"bash","langName":"Bash"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-bash" data-lang="Bash"><code>LangChain version: 0.0.323
Vertex AI SDK version: 1.67.1</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">Vertex AI Embeddings API 呼び出し制限をかける関数を定義</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Vertex AI Enbeddings API には時間あたりの API 呼び出し回数に制約があるため、Python 側で制限するよう関数を定義しておきます。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block {"langType":"python","langName":"Python"} -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-python" data-lang="Python"><code># Embeddings APIのレート制限のためのユーティリティ関数
def rate_limit(max_per_minute: int) -&gt; None:
    period = 60 / max_per_minute
    print(&quot;Waiting&quot;)
    while True:
        before = time.time()
        yield
        after = time.time()
        elapsed = after - before
        sleep_time = max(0, period - elapsed)
        if sleep_time &gt; 0:
            print(&quot;.&quot;, end=&quot;&quot;)
            time.sleep(sleep_time)


class CustomVertexAIEmbeddings(VertexAIEmbeddings, BaseModel):
    requests_per_minute: int
    num_instances_per_batch: int

    # embed_documents メソッドのオーバーライド
    def embed_documents(self, texts: list) -&gt; list:
        limiter = rate_limit(self.requests_per_minute)
        results = []
        docs = list(texts)

        while docs:
            head, docs = (
                docs[: self.num_instances_per_batch],
                docs[self.num_instances_per_batch :],
            )
            chunk = self.client.get_embeddings(head)
            results.extend(chunk)
            next(limiter)

        return [r.to_numpy() for r in results]</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:heading {"level":4} -->
<h4 class="wp-block-heading">モデル定義</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>今回は、text-bison という生成 AI モデルを使用します。</p>
<!-- /wp:paragraph -->

<!-- wp:loos/cap-block {"className":"is-style-onborder_ttl"} -->
<div class="swell-block-capbox cap_box is-style-onborder_ttl"><div class="cap_box_ttl"><span><strong><span data-icon="PhCpu" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxyZWN0IHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2IiBmaWxsPSJub25lIj48L3JlY3Q+PHJlY3QgeD0iMTAwIiB5PSIxMDAiIHdpZHRoPSI1NiIgaGVpZ2h0PSI1NiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiI+PC9yZWN0PjxyZWN0IHg9IjQ4IiB5PSI0OCIgd2lkdGg9IjE2MCIgaGVpZ2h0PSIxNjAiIHJ4PSI4IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ij48L3JlY3Q+PGxpbmUgeDE9IjIwOCIgeTE9IjEwNCIgeDI9IjIzMiIgeTI9IjEwNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiI+PC9saW5lPjxsaW5lIHgxPSIyMDgiIHkxPSIxNTIiIHgyPSIyMzIiIHkyPSIxNTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiPjwvbGluZT48bGluZSB4MT0iMjQiIHkxPSIxMDQiIHgyPSI0OCIgeTI9IjEwNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiI+PC9saW5lPjxsaW5lIHgxPSIyNCIgeTE9IjE1MiIgeDI9IjQ4IiB5Mj0iMTUyIiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ij48L2xpbmU+PGxpbmUgeDE9IjE1MiIgeTE9IjIwOCIgeDI9IjE1MiIgeTI9IjIzMiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiI+PC9saW5lPjxsaW5lIHgxPSIxMDQiIHkxPSIyMDgiIHgyPSIxMDQiIHkyPSIyMzIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMTYiPjwvbGluZT48bGluZSB4MT0iMTUyIiB5MT0iMjQiIHgyPSIxNTIiIHkyPSI0OCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxNiI+PC9saW5lPjxsaW5lIHgxPSIxMDQiIHkxPSIyNCIgeDI9IjEwNCIgeTI9IjQ4IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjE2Ij48L2xpbmU+PC9zdmc+)" aria-hidden="true" class="swl-inline-icon"> </span> text-bison モデルとは</strong></span></div><div class="cap_box_content"><!-- wp:paragraph -->
<p>text-bison モデルは、Vertex AI が提供する学習済み生成 AI モデルの一つで、Google が開発した PaLM 2 の Bison モデルを言語タスク向けに最適化されたモデルです。</p>
<!-- /wp:paragraph --></div></div>
<!-- /wp:loos/cap-block -->

<!-- wp:paragraph -->
<p>Embedding 手法を使います。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Embedding とは 自然言語（単語、文章）をベクトル空間に変換してコンピュータが自然言語を理解できるようにする手法です。</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-plain"><code>llm = VertexAI(
    model_name=&quot;text-bison&quot;,
    max_output_tokens=256,
    temperature=0.1,
    top_p=0.8,
    top_k=40,
    verbose=True,
)

EMBEDDING_QPM = 100
EMBEDDING_NUM_BATCH = 5

embeddings = CustomVertexAIEmbeddings(
    requests_per_minute=EMBEDDING_QPM,
    num_instances_per_batch=EMBEDDING_NUM_BATCH,
)

example_prompt = PromptTemplate(
    input_variables=[&quot;input&quot;, &quot;output&quot;],
    template=&quot;Example Input: {input}\nExample Output: {output}&quot;,
)

examples = [
    {&quot;input&quot;: &quot;pirate&quot;, &quot;output&quot;: &quot;ship&quot;},
    {&quot;input&quot;: &quot;pilot&quot;, &quot;output&quot;: &quot;plane&quot;},
    {&quot;input&quot;: &quot;driver&quot;, &quot;output&quot;: &quot;car&quot;},
    {&quot;input&quot;: &quot;tree&quot;, &quot;output&quot;: &quot;ground&quot;},
    {&quot;input&quot;: &quot;bird&quot;, &quot;output&quot;: &quot;nest&quot;},
]

example_selector = SemanticSimilarityExampleSelector.from_examples(
    examples,
    embeddings,
    FAISS,
    k=2,
)
similar_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix=&quot;指定したものが通常置かれている場所を示す&quot;,
    suffix=&quot;Input: {noun}\nOutput:&quot;,
    input_variables=[&quot;noun&quot;],
)
my_noun = &quot;student&quot;

print(similar_prompt.format(noun=my_noun))
print(llm(similar_prompt.format(noun=my_noun)))
</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:paragraph -->
<p>Output</p>
<!-- /wp:paragraph -->

<!-- wp:loos-hcb/code-block -->
<div class="hcb_wrap"><pre class="prism undefined-numbers lang-plain"><code>Waiting
指定したものが通常置かれている場所を示す

Example Input: driver
Example Output: car

Example Input: pilot
Example Output: plane

Input: student
Output:
 school</code></pre></div>
<!-- /wp:loos-hcb/code-block -->

<!-- wp:paragraph -->
<p>ここでは、Few-shot Prompting でプロンプトを与えて、<code>example</code> 変数に具体例を提示しながら質問しています。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>各種モデルで調整するパラメータについて理解できていないところもありますが、概ね LangChain を使って生成 AI アプリケーションを作る流れはイメージできました。</p>
<!-- /wp:paragraph -->