上記ハンズオン勉強会の資料になります。
ソースコード
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月の回(日程未定)で解説します。