上記ハンズオン勉強会の資料になります。
ソースコード
FastAPIの準備
python -m venv fastapi-env
source fastapi-env/bin/activate
fastapi-env/Scripts/activate
pip install fastapi uvicorn
touch main.py
from fastapi import FastAPI app = FastAPI() @app.get('/') def index(): return 'hello'
- 実行
uvicorn main:app --reload
- 別ターミナルにて
curl -s http://localhost:8000/
- POSTも追加
from pydantic import BaseModel
class User(BaseModel): name: str @app.post('/api/hello') def hello_service(user: User): resp = { 'message': 'Hello, {}!'.format(user.name) } return resp
USER='{"name":"平賀源内"}' curl -X POST -H "Content-Type: application/json" -d "$USER" -s http://localhost:8000/api/hello | jq .
Google Cloudでサービスアカウントの準備
Geminiマルチモーダルプログラミングハンズオン - Toilを無くして徒然なるままに日暮し硯に向かひたいの記事を参考に、ロールへ
Vertex AI ユーザー
ディスカバリー エンジン ユーザー
を追加し、環境変数の設定
Geminiを呼び出すコードを記載
- main.pyの上に以下を追加
import vertexai from vertexai.generative_models import GenerativeModel
- main.pyの下に以下を追加
class Question(BaseModel): query: str @app.post('/api/llm') def llm_service(question: Question): prompt = question.query vertexai.init(location="us-west1") # vertexaiの初期化で、ロケーションを設定 model = GenerativeModel("gemini-2.0-flash-001") # モデルを設定 response = model.generate_content( # プロンプトをモデルに入れて出力(レスポンスを得る) prompt ) print(response.text) # コンソールログにresponseのテキストを表示 resp = { 'answer': response.text } # responseを形作る return resp
ライブラリのインストール
requirements.txt
に以下を記載
google-cloud-aiplatform==1.83.0 vertexai==1.43.0 langchain_core==0.3.33 langchain_google_vertexai==2.0.12 google===3.0.0 google-cloud-discoveryengine==0.13.6
pip install -r requirements.txt
--break-system-packages
をつけよ、とエラーが出たら以下
pip install --user -r requirements.txt --break-system-packages
実行方法
uvicorn main:app --reload
- 別ターミナルにて
QUESTION='{"query":"プロンプトエンジニアリングとは何ですか?"}'
curl -X POST -H "Content-Type: application/json" -d "$QUESTION" -s http://localhost:8000/api/llm | jq .
LangChainを用いる
import vertexai # 削除 from vertexai.generative_models import GenerativeModel # 削除 from langchain_google_vertexai import VertexAI # 追記 from langchain_core.prompts import PromptTemplate # 追記
@app.post('/api/llm') def llm_service(question: Question): human_question = question.query model = VertexAI(model_name="gemini-2.0-flash-001", location="us-west1") template = """質問: {question} ステップバイステップで考えてください。""" prompt_template = PromptTemplate.from_template(template) chain = prompt_template | model # prompt_templateをmodelに引き渡す処理を"|"を用いて簡単に実現 response = chain.invoke({"question": human_question}) # invokeは全ての処理が終わってから値を返す。他にはstreamなど print(response) resp = { 'answer': response } return resp
RAG構築
Google Cloud Vertex AI Agent Builderの使い方 - Toilを無くして徒然なるままに日暮し硯に向かひたいの記事を参考に、Google Cloud Storageにドキュメントを格納し、Agent Builderで検索アプリを作ります。
- main.pyの上に追記
from google.api_core.client_options import ClientOptions from google.cloud import discoveryengine_v1 as discoveryengine import os import google.auth credentials, project_id = google.auth.default()
main.pyの下に追記
'DISCOVERY_ENGINE_ID'を書き換えます
@app.post('/api/retriever') def retriever_service(question: Question): search_query = question.query project_id location: str = "global" engine_id: str = 'DISCOVERY_ENGINE_ID' # AI Applicationsで作成したアプリケーションのIDに変更する def search( project_id: str, location: str, engine_id: str, search_query: str, ) -> discoveryengine.services.search_service.pagers.SearchPager: client_options = ( ClientOptions(api_endpoint=f"{location}-discoveryengine.googleapis.com") if location != "global" else None ) client = discoveryengine.SearchServiceClient(client_options=client_options) serving_config = f"projects/{project_id}/locations/{location}/collections/default_collection/engines/{engine_id}/servingConfigs/default_config" content_search_spec = discoveryengine.SearchRequest.ContentSearchSpec( snippet_spec=discoveryengine.SearchRequest.ContentSearchSpec.SnippetSpec( return_snippet=True ), summary_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec( summary_result_count=3, include_citations=True, ignore_adversarial_query=True, ignore_non_summary_seeking_query=True, model_prompt_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec.ModelPromptSpec( preamble="文献の検索結果を要約してください" ), model_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec( version="stable", ), ), ) request = discoveryengine.SearchRequest( serving_config=serving_config, query=search_query, page_size=3, content_search_spec=content_search_spec, query_expansion_spec=discoveryengine.SearchRequest.QueryExpansionSpec( condition=discoveryengine.SearchRequest.QueryExpansionSpec.Condition.AUTO, ), spell_correction_spec=discoveryengine.SearchRequest.SpellCorrectionSpec( mode=discoveryengine.SearchRequest.SpellCorrectionSpec.Mode.AUTO ), ) page_result = client.search(request) return page_result response = search(project_id, location, engine_id, search_query) resp = { 'search_result': response.summary.summary_text } print(resp) return resp
QUESTION='{"query":"情報セキュリティにおいて気をつけるべきことを教えてください"}'
curl -X POST -H "Content-Type: application/json" -d "$QUESTION" -s http://localhost:8000/api/retriever | jq .
課題
retriever_service
を定義しましたが、検索結果をcontextとして、LLMへの問い合わせを行なってください。
次回、5月の回(日程未定)で解説します。