mirror of
https://github.com/andatoshiki/toshiki-notebook.git
synced 2026-06-06 09:16:45 +00:00
202 lines
113 KiB
HTML
202 lines
113 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-US" dir="ltr">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>Hands-on #3: AWS で自動質問回答ボットを走らせる | Toshiki's Note</title>
|
||
<meta name="description" content="Toshiki's web notebook served via Vitepress!">
|
||
<link rel="preload stylesheet" href="/assets/style.1276ae12.css" as="style">
|
||
<script type="module" src="/assets/app.da2b9cf1.js"></script>
|
||
<link rel="preload" href="/assets/inter-roman-latin.2ed14f66.woff2" as="font" type="font/woff2" crossorigin="">
|
||
<link rel="modulepreload" href="/assets/chunks/framework.ade46834.js">
|
||
<link rel="modulepreload" href="/assets/chunks/theme.2274efad.js">
|
||
<link rel="modulepreload" href="/assets/chunks/ask_many_output.0bb19110.js">
|
||
<link rel="modulepreload" href="/assets/development_aws_handson-qabot.md.15fa9676.lean.js">
|
||
<link rel="stylesheet" href="https://cdnjs.toshiki.dev/ajax/libs/KaTeX/0.16.0/katex.min.css">
|
||
<link rel="stylesheet" href="https://cdnjs.toshiki.dev/ajax/libs/font-awesome/6.3.0/css/all.min.css">
|
||
<link rel="icon" href="/favicon.ico">
|
||
<meta name="author" content="Anda Toshiki">
|
||
<meta name="keywords" content="Toshiki, Anda Toshiki, andatoshiki, GitHub, GitHub action, Vitepress, Vite, Notebook, Knowledge base, Programming, Programming Notes, Academic, Personal, Notebook, Productivity, Journal, Note-taking, Markdown, Notepad, Organization, Tutorial">
|
||
<meta name="google-site-verification" content="lm7PNJiYSPEx1dMast1Xptc0Vk0cU06o-daZSsIgr2I">
|
||
<meta name="HandheldFriendly" content="True">
|
||
<meta name="MobileOptimized" content="320">
|
||
<meta name="theme-color" content="#3c8772">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:locale" content="en-US">
|
||
<meta property="og:title" content="Toshiki's Note">
|
||
<meta property="og:description" content="Toshiki's web notebook served via Vitepress!">
|
||
<meta property="og:site" content="https://note.toshiki.dev">
|
||
<meta property="og:site_name" content="Toshiki's Note">
|
||
<meta property="og:image" content="https://note.toshiki.dev/og-cover.png">
|
||
<script>function siteruntime(){window.setTimeout("siteruntime()",1e3),X=new Date("8/24/2021 10:28:00"),Y=new Date,T=Y.getTime()-X.getTime(),M=24*60*60*1e3,a=T/M,A=Math.floor(a),b=(a-A)*24,B=Math.floor(b),c=(b-B)*60,C=Math.floor((b-B)*60),D=Math.floor((c-C)*60),siteruntime_span.innerHTML="This site has been running for: "+A+" day(s) "+B+" hour(s) "+C+" minute(s) "+D+" second(s)"}siteruntime();</script>
|
||
<script async="true" defer="true" data-website-id="86de8554-d4c9-4f2b-b62a-068b71241048" src="https://umami.toshiki.dev/umami.js"></script>
|
||
<script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
|
||
</head>
|
||
<body>
|
||
<div id="app"><div class="Layout" data-v-83f63849><!--[--><!--]--><!--[--><span tabindex="-1" data-v-0eca8f1e></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-0eca8f1e> Skip to content </a><!--]--><!----><header class="VPNav" data-v-83f63849 data-v-999a1a39><div class="VPNavBar has-sidebar" data-v-999a1a39 data-v-e99cf6bd><div class="container" data-v-e99cf6bd><div class="title" data-v-e99cf6bd><div class="VPNavBarTitle has-sidebar" data-v-e99cf6bd data-v-a8886b70><a class="title" href="/" data-v-a8886b70><!--[--><!--]--><!--[--><img class="VPImage logo" src="/logos/logo.png" alt data-v-164d1caf><!--]--><!--[-->Toshiki's Note<!--]--><!--[--><!--]--></a></div></div><div class="content" data-v-e99cf6bd><div class="curtain" data-v-e99cf6bd></div><div class="content-body" data-v-e99cf6bd><!--[--><!--]--><div class="VPNavBarSearch search" style="--vp-meta-key:'Meta';" data-v-e99cf6bd><!--[--><div id="docsearch"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg class="DocSearch-Search-Icon" width="20" height="20" viewBox="0 0 20 20" aria-label="search icon"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-e99cf6bd data-v-1817056a><span id="main-nav-aria-label" class="visually-hidden" data-v-1817056a>Main Navigation</span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/development/" tabindex="0" data-v-1817056a data-v-f28b94cc data-v-075865b7><!--[-->Development<!--]--><!----></a><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-1817056a data-v-4c03a652><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-4c03a652><span class="text" data-v-4c03a652><!----> Academic <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-4c03a652><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-4c03a652><div class="VPMenu" data-v-4c03a652 data-v-da053c30><div class="items" data-v-da053c30><!--[--><!--[--><div class="VPMenuGroup" data-v-da053c30 data-v-2e982fbb><p class="title" data-v-2e982fbb>K-12</p><!--[--><!--[--><div class="VPMenuLink" data-v-2e982fbb data-v-6f715184><a class="VPLink link" href="/academic/chemistry/index" data-v-6f715184 data-v-075865b7><!--[-->Chemistry<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-2e982fbb data-v-6f715184><a class="VPLink link" href="/discrete-math/index" data-v-6f715184 data-v-075865b7><!--[-->Discrete Math.<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-2e982fbb data-v-6f715184><a class="VPLink link" href="/academic/literature/index" data-v-6f715184 data-v-075865b7><!--[-->Literature<!--]--><!----></a></div><!--]--><!--]--></div><!--]--><!--[--><div class="VPMenuGroup" data-v-da053c30 data-v-2e982fbb><p class="title" data-v-2e982fbb>Tools</p><!--[--><!--[--><div class="VPMenuLink" data-v-2e982fbb data-v-6f715184><a class="VPLink link" href="/academic/physics/ipho-formulas-jpn/1" data-v-6f715184 data-v-075865b7><!--[-->Formulas for IPhO JPN.<!--]--><!----></a></div><!--]--><!--]--></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><span class="VPLink" data-v-6f715184 data-v-075865b7><!--[--><!--]--><!----></span></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><span class="VPLink" data-v-6f715184 data-v-075865b7><!--[--><!--]--><!----></span></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><span class="VPLink" data-v-6f715184 data-v-075865b7><!--[--><!--]--><!----></span></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><span class="VPLink" data-v-6f715184 data-v-075865b7><!--[--><!--]--><!----></span></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><span class="VPLink" data-v-6f715184 data-v-075865b7><!--[--><!--]--><!----></span></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><span class="VPLink" data-v-6f715184 data-v-075865b7><!--[--><!--]--><!----></span></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><span class="VPLink" data-v-6f715184 data-v-075865b7><!--[--><!--]--><!----></span></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-1817056a data-v-4c03a652><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-4c03a652><span class="text" data-v-4c03a652><!----> Application <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-4c03a652><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-4c03a652><div class="VPMenu" data-v-4c03a652 data-v-da053c30><div class="items" data-v-da053c30><!--[--><!--[--><div class="VPMenuGroup" data-v-da053c30 data-v-2e982fbb><p class="title" data-v-2e982fbb>Personal projects</p><!--[--><!--[--><div class="VPMenuLink" data-v-2e982fbb data-v-6f715184><a class="VPLink link" href="/application/markdown-it-katex/how-to-use" data-v-6f715184 data-v-075865b7><!--[-->markdown-it-katex<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-2e982fbb data-v-6f715184><a class="VPLink link" href="/application/vitepress-plugin-shiki-twoslash/index" data-v-6f715184 data-v-075865b7><!--[-->vitepress-plugin-shiki-twoslash<!--]--><!----></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-1817056a data-v-4c03a652><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-4c03a652><span class="text" data-v-4c03a652><!----> Save <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-4c03a652><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-4c03a652><div class="VPMenu" data-v-4c03a652 data-v-da053c30><div class="items" data-v-da053c30><!--[--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><a class="VPLink link" href="/save/reading/index" data-v-6f715184 data-v-075865b7><!--[-->Reading<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-da053c30 data-v-6f715184><a class="VPLink link" href="/academic/vocabulary/index" data-v-6f715184 data-v-075865b7><!--[-->Vocabulary<!--]--><!----></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-e99cf6bd data-v-72c0c02a><label title="toggle dark mode" data-v-72c0c02a data-v-cb74fac6><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-checked="false" data-v-cb74fac6 data-v-9f7dbbcf><span class="check" data-v-9f7dbbcf><span class="icon" data-v-9f7dbbcf><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-cb74fac6><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-cb74fac6><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></label></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-e99cf6bd data-v-268ff66d data-v-65dbf981><!--[--><a class="VPSocialLink" href="https://github.com/andatoshiki" aria-label="github" target="_blank" rel="noopener" data-v-65dbf981 data-v-2d45784b><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink" href="https://twitter.com/andatoshiki" aria-label="twitter" target="_blank" rel="noopener" data-v-65dbf981 data-v-2d45784b><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-e99cf6bd data-v-67546bb2 data-v-4c03a652><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-4c03a652><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-4c03a652><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-4c03a652><div class="VPMenu" data-v-4c03a652 data-v-da053c30><!----><!--[--><!--[--><!----><div class="group" data-v-67546bb2><div class="item appearance" data-v-67546bb2><p class="label" data-v-67546bb2>Appearance</p><div class="appearance-action" data-v-67546bb2><label title="toggle dark mode" data-v-67546bb2 data-v-cb74fac6><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-checked="false" data-v-cb74fac6 data-v-9f7dbbcf><span class="check" data-v-9f7dbbcf><span class="icon" data-v-9f7dbbcf><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-cb74fac6><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-cb74fac6><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></label></div></div></div><div class="group" data-v-67546bb2><div class="item social-links" data-v-67546bb2><div class="VPSocialLinks social-links-list" data-v-67546bb2 data-v-65dbf981><!--[--><a class="VPSocialLink" href="https://github.com/andatoshiki" aria-label="github" target="_blank" rel="noopener" data-v-65dbf981 data-v-2d45784b><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink" href="https://twitter.com/andatoshiki" aria-label="twitter" target="_blank" rel="noopener" data-v-65dbf981 data-v-2d45784b><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-e99cf6bd data-v-2314de5a><span class="container" data-v-2314de5a><span class="top" data-v-2314de5a></span><span class="middle" data-v-2314de5a></span><span class="bottom" data-v-2314de5a></span></span></button></div></div></div></div><!----></header><div class="VPLocalNav" data-v-83f63849 data-v-fa4746c0><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-fa4746c0><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-fa4746c0><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-fa4746c0>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-fa4746c0 data-v-f8dbb575><button data-v-f8dbb575>Return to top</button><!----></div></div><aside class="VPSidebar" data-v-83f63849 data-v-0e47c5d5><div class="curtain" data-v-0e47c5d5></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-0e47c5d5><span class="visually-hidden" id="sidebar-aria-label" data-v-0e47c5d5> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="group" data-v-0e47c5d5><section class="VPSidebarItem level-0 collapsible" data-v-0e47c5d5 data-v-0cc45b6b><div class="item" role="button" tabindex="0" data-v-0cc45b6b><div class="indicator" data-v-0cc45b6b></div><h2 class="text" data-v-0cc45b6b>Wiki Database</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0cc45b6b><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0cc45b6b><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0cc45b6b><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0cc45b6b data-v-0cc45b6b><div class="item" data-v-0cc45b6b><div class="indicator" data-v-0cc45b6b></div><a class="VPLink link link" href="/development/file-naming-convention" data-v-0cc45b6b data-v-075865b7><!--[--><p class="text" data-v-0cc45b6b>File Naming Convention</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-83f63849 data-v-bb292142><div class="VPDoc has-sidebar has-aside" data-v-bb292142 data-v-6c4a7022><!--[--><!--]--><div class="container" data-v-6c4a7022><div class="aside" data-v-6c4a7022><div class="aside-curtain" data-v-6c4a7022></div><div class="aside-container" data-v-6c4a7022><div class="aside-content" data-v-6c4a7022><div class="VPDocAside" data-v-6c4a7022 data-v-f77a9b1a><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-f77a9b1a data-v-ea95c6a2><div class="content" data-v-ea95c6a2><div class="outline-marker" data-v-ea95c6a2></div><div class="outline-title" data-v-ea95c6a2>TOC</div><nav aria-labelledby="doc-outline-aria-label" data-v-ea95c6a2><span class="visually-hidden" id="doc-outline-aria-label" data-v-ea95c6a2> Table of Contents for current page </span><ul class="root" data-v-ea95c6a2 data-v-74f66e6c><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-f77a9b1a></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--[--><!--[--><!--[--><div class="VPDocAsideSponsors"><div class="VPSponsors vp-sponsor aside"><!--[--><section class="vp-sponsor-section"><!----><div class="VPSponsorsGrid vp-sponsor-grid medium"><!--[--><div class="vp-sponsor-grid-item"><a class="vp-sponsor-grid-link" target="_blank" rel="sponsored noopener"><article class="vp-sponsor-grid-box"><h4 class="visually-hidden"></h4><img class="vp-sponsor-grid-image" src="https://jsd.toshiki.dev/gh/andatoshiki/toshiki-notebook@master/assets/logo/sponsor/telegram.png"></article></a></div><!--]--></div></section><!--]--></div></div><!--]--><!--]--><!--]--><!--]--></div></div></div></div><div class="content" data-v-6c4a7022><div class="content-container" data-v-6c4a7022><!--[--><!--]--><!----><main class="main" data-v-6c4a7022><div style="position:relative;" class="vp-doc _development_aws_handson-qabot" data-v-6c4a7022><div><h1 id="hands-on-3-aws-で自動質問回答ボットを走らせる" tabindex="-1">Hands-on #3: AWS で自動質問回答ボットを走らせる <a class="header-anchor" href="#hands-on-3-aws-で自動質問回答ボットを走らせる" aria-label="Permalink to "Hands-on \#3: AWS で自動質問回答ボットを走らせる""></a></h1><p>ハンズオン第三回では, Docker と ECS を駆使した機械学習アプリケーションを実装しよう. 具体的には,深層学習による自然言語処理を行うことで,クライアントから与えられた文章題に対して回答を生成する,自動 Question & Answering ボットを作成しよう. ECS を利用することで,ジョブの数によって動的にインスタンスの数を制御し,並列にタスクを実行するようなシステムを構築しよう.</p><p>通常の機械学習のワークフローでは,モデルの訓練 ⇒ 推論 (データへの適用) が基本的な流れである. しかしながら, GPU 搭載型の EC2 クラスターを使ったモデルの訓練はやや難易度が高いため,次章 (<a href="#sec_aws_batch">???</a>) で取り扱う. 本章は,クラウド上でのクラスターの構築・タスクの管理などの概念に慣れるため,よりシンプルな実装で実現できる Fargate クラスターを用いた推論計算の並列化を紹介する.</p><h2 id="fargate" tabindex="-1">Fargate <a class="header-anchor" href="#fargate" aria-label="Permalink to "Fargate""></a></h2><p>ハンズオンに入っていく前に, <strong>Fargate</strong> という AWS の機能を知っておく必要がある (<a href="#fig:fargate_logo">figure_title</a>).</p><p><img src="/assets/Fargate.9aa64f1c.png" alt="Fargate のアイコン"></p><p>ECS の概要を示した <a href="#ecs_overview">???</a> をもう一度見てみよう. この図で, ECS の管理下にあるクラスターが示されているが,このクラスターの中で計算を行う実体としては二つの選択肢がある. <strong>EC2 あるいは Fargate</strong> のいずれかである. EC2 を用いた場合は,先の章 (<a href="#sec_first_ec2">???</a>, <a href="#sec_jupyter_and_deep_learning">???</a>) で説明したような流れでインスタンスが起動し,計算が実行される. しかし, EC2 を用いた計算機クラスターの作成・管理は技術的な難易度がやや高いので,次章 (<a href="#sec_aws_batch">???</a>) で説明することにする.</p><p>Fargate とは, <strong>ECS での利用に特化</strong>して設計された,<strong>コンテナを使用した計算タスク</strong>を走らせるための仕組みである. 計算を走らせるという点では EC2 と役割は似ているが, Fargate は EC2 インスタンスのような物理的実体はもたない. 物理的実体をもたないというのは,たとえば SSH でログインすることは基本的に想定されていないし,なにかのソフトウェアをインストールしたりなどの概念も存在しない. Fargate ではすべての計算は Docker コンテナを介して行われる. すなわち, Fargate を利用するには,ユーザーは最初に所望の Docker イメージを指定しておき, Fargate は <code>docker run</code> のコマンドを使用することで計算タスクを実行する. Fargate を用いる利点は, Fargate を ECS のクラスターに指定すると,スケーリングなどの操作が簡単な設定・プログラムで構築できる点である.</p><p>Fargate では, EC2 と同様に CPU とメモリーのサイズを必要な分だけ指定できる. 執筆時点では, CPU は 0.25 - 4 コア, RAM は 0.5 - 30 GB の間で選択することができる (詳しくは <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html" target="_blank" rel="noreferrer">公式ドキュメンテーション "Amazon ECS on AWS Fargate"</a> 参照). クラスターのスケーリングが容易な分, Fargate では EC2 ほど大きな CPU コア・ RAM 容量を単一インスタンスに付与することができず,また GPU を利用することもできない.</p><p>以上が Fargate の概要であったが,くどくど言葉で説明してもなかなかピンとこないだろう. ここからは実際に手を動かしながら, ECS と Fargate を使った並列タスクの処理の仕方を学んでいこう.</p><p>厳密には, ECS に付与するクラスターには EC2 と Fargate のハイブリッドを使用することも可能である.</p><h2 id="準備" tabindex="-1">準備 <a class="header-anchor" href="#準備" aria-label="Permalink to "準備""></a></h2><p>ハンズオンのソースコードは GitHub の <a href="https://github.com/tomomano/learn-aws-by-coding/tree/main/handson/qa-bot" target="_blank" rel="noreferrer">handson/qa-bot</a> にある.</p><p>本ハンズオンの実行には,第一回ハンズオンで説明した準備 (<a href="#handson_01_prep">???</a>) が整っていることを前提とする. また, Docker が自身のローカルマシンにインストール済みであることも必要である.</p><p>このハンズオンでは 1CPU/4GB RAM の Fargate インスタンスを使用する. 計算の実行には 0.025 $/hour のコストが発生することに注意.</p><h2 id="transformer-を用いた-question-answering-プログラム" tabindex="-1">Transformer を用いた question-answering プログラム <a class="header-anchor" href="#transformer-を用いた-question-answering-プログラム" aria-label="Permalink to "Transformer を用いた question-answering プログラム""></a></h2><p>このハンズオンで開発する,自動質問回答システムをより具体的に定義しよう. 次のような文脈 (context) と質問 (question) が与えられた状況を想定する.</p><div class="language-txt vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">txt</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.</span></span>
|
||
<span class="line"><span style="color:#839496;"></span></span>
|
||
<span class="line"><span style="color:#839496;">question: In what year did Einstein win the Nobel prize?</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">context: Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed \"the world's most famous equation\". He received the 1921 Nobel Prize in Physics \"for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect\", a pivotal step in the development of quantum theory.</span></span>
|
||
<span class="line"><span style="color:#657B83;"></span></span>
|
||
<span class="line"><span style="color:#657B83;">question: In what year did Einstein win the Nobel prize?</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>今回作成する自動回答システムは,このような問題に対して, context に含まれる文字列から正解となる言葉を見つけ出すものとする. 上の問題では,次のような回答を返すべきである.</p><pre><code>answer: 1921
|
||
</code></pre><p>人間にとっては,このような文章を理解することは容易であるが,コンピュータにそれを解かせるのは難しいことは容易に想像ができるだろう. しかし,近年の深層学習を使った自然言語処理の進歩は著しく,上で示したような例題などは極めて高い正答率で回答できるモデルを作ることができる.</p><p>今回は, <a href="https://github.com/huggingface/transformers" target="_blank" rel="noreferrer">huggingface/transformers</a> で公開されている学習済みの言語モデルを利用することで,上で定義した問題を解く Q&A ボットを作る. この Q&A ボットは <a href="https://en.wikipedia.org/wiki/Transformer_(machine_learning_model)" target="_blank" rel="noreferrer">Transformer</a> とよばれるモデルを使った自然言語処理に支えられえている (<a href="#transformer_architecture">figure_title</a>). このプログラムを, Docker にパッケージしたものが <a href="https://hub.docker.com/repository/docker/tomomano/qabot" target="_blank" rel="noreferrer">著者の Docker Hub リポジトリ</a> に用意してある. クラウドの設計に入る前に,まずはこのプログラムを単体で動かしてみよう.</p><p><img src="/assets/transformer.e184dd01.png" alt="Transformer モデルアーキテクチャ (画像出典: Vaswani+ 2017)"></p><p>なお,今回は学習済みのモデルを用いているので,私達が行うのは与えられた入力をモデルに投入して予測を行う (推論) のみである. 推論の演算は, CPU だけでも十分高速に行うことができるので,コストの削減と,実装をシンプルにする目的で,このハンズオンでは GPU は利用しない. 一般的に, ニューラルネットは学習のほうが圧倒的に計算コストが大きく,そのような場合に GPU はより威力を発揮する.</p><p>次のコマンドで,今回使う Docker image を ローカルにダウンロード (pull) してこよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pull</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/qabot:latest</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pull</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/qabot:latest</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>pull できたら,早速この Docker に質問を投げかけてみよう. まずは context と question をコマンドラインの変数として定義する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">question="In what year did Einstein win the Nobel prize ?"</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">context="Albert Einstein (14 March 1879 – 18 April 1955) was a German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). His work is also known for its influence on the philosophy of science. He is best known to the general public for his mass–energy equivalence formula E = mc2, which has been dubbed the world's most famous equation. He received the 1921 Nobel Prize in Physics for his services to theoretical physics, and especially for his discovery of the law of the photoelectric effect, a pivotal step in the development of quantum theory."</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">question="In what year did Einstein win the Nobel prize ?"</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>そうしたら,次のコマンドによってコンテナを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#839496;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#839496;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#839496;"> </span><span style="color:#2AA198;">foo</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">foo</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>今回用意した Docker image は,第一引数に context となる文字列を,第二引数に question に相当する文字列を受けつける. 第三引数,第四引数については,クラウドに展開するときの実装上の都合なので,いまは気にしなくてよい.</p><p>このコマンドを実行すると,次のような出力が得られるはずである.</p><div class="language-json vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">{ </span><span style="color:#859900;">"score"</span><span style="color:#839496;">: </span><span style="color:#D33682;">0.9881729286683587</span><span style="color:#839496;">, </span><span style="color:#859900;">"start"</span><span style="color:#839496;">: </span><span style="color:#D33682;">437</span><span style="color:#839496;">, </span><span style="color:#859900;">"end"</span><span style="color:#839496;">: </span><span style="color:#D33682;">441</span><span style="color:#839496;">, </span><span style="color:#859900;">"answer"</span><span style="color:#839496;">: </span><span style="color:#2AA198;">"1921"</span><span style="color:#839496;"> }</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">{ </span><span style="color:#859900;">"score"</span><span style="color:#657B83;">: </span><span style="color:#D33682;">0.9881729286683587</span><span style="color:#657B83;">, </span><span style="color:#859900;">"start"</span><span style="color:#657B83;">: </span><span style="color:#D33682;">437</span><span style="color:#657B83;">, </span><span style="color:#859900;">"end"</span><span style="color:#657B83;">: </span><span style="color:#D33682;">441</span><span style="color:#657B83;">, </span><span style="color:#859900;">"answer"</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">"1921"</span><span style="color:#657B83;"> }</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>"score" は正解の自信度を表す数字で, [0,1] の範囲で与えられる. "start", "end" は, context 中の何文字目が正解に相当するかを示しており, "answer" が正解と予測された文字列である. 1921 年という,正しい答えが返ってきていることに注目してほしい.</p><p>もう少し難しい質問を投げかけてみよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">question="Why did Einstein win the Nobel prize ?"</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">docker</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run</span><span style="color:#839496;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#839496;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#839496;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#839496;"> </span><span style="color:#2AA198;">foo</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">question="Why did Einstein win the Nobel prize ?"</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">docker</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">tomomano/qabot</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">context</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">"</span><span style="color:#859900;">${</span><span style="color:#268BD2;">question</span><span style="color:#859900;">}</span><span style="color:#2AA198;">"</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">foo</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">--no_save</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>出力:</p><div class="language-json vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">{ </span><span style="color:#859900;">"score"</span><span style="color:#839496;">: </span><span style="color:#D33682;">0.5235594527494207</span><span style="color:#839496;">, </span><span style="color:#859900;">"start"</span><span style="color:#839496;">: </span><span style="color:#D33682;">470</span><span style="color:#839496;">, </span><span style="color:#859900;">"end"</span><span style="color:#839496;">: </span><span style="color:#D33682;">506</span><span style="color:#839496;">, </span><span style="color:#859900;">"answer"</span><span style="color:#839496;">: </span><span style="color:#2AA198;">"his services to theoretical physics,"</span><span style="color:#839496;"> }</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">{ </span><span style="color:#859900;">"score"</span><span style="color:#657B83;">: </span><span style="color:#D33682;">0.5235594527494207</span><span style="color:#657B83;">, </span><span style="color:#859900;">"start"</span><span style="color:#657B83;">: </span><span style="color:#D33682;">470</span><span style="color:#657B83;">, </span><span style="color:#859900;">"end"</span><span style="color:#657B83;">: </span><span style="color:#D33682;">506</span><span style="color:#657B83;">, </span><span style="color:#859900;">"answer"</span><span style="color:#657B83;">: </span><span style="color:#2AA198;">"his services to theoretical physics,"</span><span style="color:#657B83;"> }</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>今度は, score が 0.52 と,少し自信がないようだが,それでも正しい答えにたどりつけていることがわかる.</p><p>このように, 深層学習に支えられた言語モデルを用いることで,実用にも役に立ちそうな Q&A ボットを実現できていることがわかる. 以降では,このプログラムをクラウドに展開することで,大量の質問に自動で対応できるようなシステムを設計していく.</p><p>今回使用する Question & Answering システムには, DistilBERT という Transformer を基にした言語モデルが用いられている. 興味のある読者は, <a href="https://arxiv.org/abs/1910.01108" target="_blank" rel="noreferrer">原著論文</a> を参照してもらいたい. また, huggingface/transformers による DistilBert の実装のドキュメンテーションは <a href="https://huggingface.co/transformers/model_doc/distilbert.html" target="_blank" rel="noreferrer">公式ドキュメンテーション</a> を参照のこと.</p><p>今回提供する Q-A ボットの Docker のソースコードは <a href="https://github.com/tomomano/learn-aws-by-coding/blob/main/handson/qa-bot/docker/Dockerfile" target="_blank" rel="noreferrer">https://github.com/tomomano/learn-aws-by-coding/blob/main/handson/qa-bot/docker/Dockerfile</a> にある.</p><h2 id="アプリケーションの説明" tabindex="-1">アプリケーションの説明 <a class="header-anchor" href="#アプリケーションの説明" aria-label="Permalink to "アプリケーションの説明""></a></h2><p>このハンズオンで作成するアプリケーションの概要を <a href="#handson_03_architecture">figure_title</a> に示す.</p><p><img src="/assets/handson-03-architecture.f1ebbd6e.png" alt="アプリケーションのアーキテクチャ"></p><p>簡単にまとめると,以下のような設計である.</p><ul><li><p>クライアントは,質問を AWS 上のアプリケーションに送信する.</p></li><li><p>質問のタスクは ECS によって処理される.</p></li><li><p>ECS は, Docker Hub から,イメージをダウンロードする.</p></li><li><p>次に,ECS はクラスター内に新たな Fargate インスタンスを立ち上げ,ダウンロードされた Docker イメージをこの新規インスタンスに配置する.</p><ul><li>このとき,一つの質問に対し一つの Fargate インスタンスを立ち上げることで,複数の質問を並列的に処理できるようにする.</li></ul></li><li><p>ジョブが実行される.</p></li><li><p>ジョブの実行結果 (質問への回答) は, データベース (DynamoDB) に書き込まれる.</p></li><li><p>最後に,クライアントは DynamoDB から質問への回答を読み取る.</p></li></ul><p>それでは,プログラムのソースコードを見てみよう (<a href="https://github.com/tomomano/learn-aws-by-coding/blob/main/handson/qa-bot/app.py" target="_blank" rel="noreferrer">handson/qa-bot/app.py</a>).</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#93A1A1;font-weight:bold;">class</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">EcsClusterQaBot</span><span style="color:#839496;">(</span><span style="color:#6C71C4;">core</span><span style="color:#839496;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#839496;">):</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#93A1A1;font-weight:bold;">def</span><span style="color:#839496;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#839496;">, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs) -> </span><span style="color:#B58900;">None</span><span style="color:#839496;">:</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#859900;">super</span><span style="color:#839496;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#839496;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#839496;">kwargs)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># dynamoDB table to store questions and answers</span></span>
|
||
<span class="line"><span style="color:#839496;"> table </span><span style="color:#859900;">=</span><span style="color:#839496;"> dynamodb.Table(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Table"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> partition_key</span><span style="color:#859900;">=</span><span style="color:#839496;">dynamodb.Attribute(</span></span>
|
||
<span class="line"><span style="color:#839496;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">"item_id"</span><span style="color:#839496;">, type</span><span style="color:#859900;">=</span><span style="color:#839496;">dynamodb.AttributeType.</span><span style="color:#CB4B16;">STRING</span></span>
|
||
<span class="line"><span style="color:#839496;"> ),</span></span>
|
||
<span class="line"><span style="color:#839496;"> billing_mode</span><span style="color:#859900;">=</span><span style="color:#839496;">dynamodb.BillingMode.</span><span style="color:#CB4B16;">PAY_PER_REQUEST</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#839496;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
|
||
<span class="line"><span style="color:#839496;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#839496;"> vpc </span><span style="color:#859900;">=</span><span style="color:#839496;"> ec2.Vpc(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Vpc"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#839496;"> cluster </span><span style="color:#859900;">=</span><span style="color:#839496;"> ecs.Cluster(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Cluster"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
|
||
<span class="line"><span style="color:#839496;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#839496;"> taskdef </span><span style="color:#859900;">=</span><span style="color:#839496;"> ecs.FargateTaskDefinition(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-TaskDef"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#839496;">, </span><span style="color:#586E75;font-style:italic;"># 1 CPU</span></span>
|
||
<span class="line"><span style="color:#839496;"> memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#839496;">, </span><span style="color:#586E75;font-style:italic;"># 4GB RAM</span></span>
|
||
<span class="line"><span style="color:#839496;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;"># grant permissions</span></span>
|
||
<span class="line"><span style="color:#839496;"> table.grant_read_write_data(taskdef.task_role)</span></span>
|
||
<span class="line"><span style="color:#839496;"> taskdef.add_to_task_role_policy(</span></span>
|
||
<span class="line"><span style="color:#839496;"> iam.PolicyStatement(</span></span>
|
||
<span class="line"><span style="color:#839496;"> effect</span><span style="color:#859900;">=</span><span style="color:#839496;">iam.Effect.</span><span style="color:#CB4B16;">ALLOW</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> resources</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span><span style="color:#2AA198;">"*"</span><span style="color:#839496;">],</span></span>
|
||
<span class="line"><span style="color:#839496;"> actions</span><span style="color:#859900;">=</span><span style="color:#839496;">[</span><span style="color:#2AA198;">"ssm:GetParameter"</span><span style="color:#839496;">]</span></span>
|
||
<span class="line"><span style="color:#839496;"> )</span></span>
|
||
<span class="line"><span style="color:#839496;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#586E75;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#839496;"> container </span><span style="color:#859900;">=</span><span style="color:#839496;"> taskdef.add_container(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">"EcsClusterQaBot-Container"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> image</span><span style="color:#859900;">=</span><span style="color:#839496;">ecs.ContainerImage.from_registry(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">"tomomano/qabot:latest"</span></span>
|
||
<span class="line"><span style="color:#839496;"> ),</span></span>
|
||
<span class="line"><span style="color:#839496;"> )</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#586E75;font-weight:bold;">class</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">EcsClusterQaBot</span><span style="color:#657B83;">(</span><span style="color:#6C71C4;">core</span><span style="color:#657B83;">.</span><span style="color:#6C71C4;">Stack</span><span style="color:#657B83;">):</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#586E75;font-weight:bold;">def</span><span style="color:#657B83;"> </span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(self, scope: core.App, name: </span><span style="color:#859900;">str</span><span style="color:#657B83;">, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs) -> </span><span style="color:#B58900;">None</span><span style="color:#657B83;">:</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#859900;">super</span><span style="color:#657B83;">().</span><span style="color:#268BD2;">__init__</span><span style="color:#657B83;">(scope, name, </span><span style="color:#859900;">**</span><span style="color:#657B83;">kwargs)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># dynamoDB table to store questions and answers</span></span>
|
||
<span class="line"><span style="color:#657B83;"> table </span><span style="color:#859900;">=</span><span style="color:#657B83;"> dynamodb.Table(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Table"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> partition_key</span><span style="color:#859900;">=</span><span style="color:#657B83;">dynamodb.Attribute(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> name</span><span style="color:#859900;">=</span><span style="color:#2AA198;">"item_id"</span><span style="color:#657B83;">, type</span><span style="color:#859900;">=</span><span style="color:#657B83;">dynamodb.AttributeType.</span><span style="color:#CB4B16;">STRING</span></span>
|
||
<span class="line"><span style="color:#657B83;"> ),</span></span>
|
||
<span class="line"><span style="color:#657B83;"> billing_mode</span><span style="color:#859900;">=</span><span style="color:#657B83;">dynamodb.BillingMode.</span><span style="color:#CB4B16;">PAY_PER_REQUEST</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> removal_policy</span><span style="color:#859900;">=</span><span style="color:#657B83;">core.RemovalPolicy.</span><span style="color:#CB4B16;">DESTROY</span></span>
|
||
<span class="line"><span style="color:#657B83;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#657B83;"> vpc </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ec2.Vpc(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Vpc"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> max_azs</span><span style="color:#859900;">=</span><span style="color:#D33682;">1</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#657B83;"> cluster </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ecs.Cluster(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Cluster"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#657B83;"> taskdef </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ecs.FargateTaskDefinition(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-TaskDef"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#657B83;">, </span><span style="color:#93A1A1;font-style:italic;"># 1 CPU</span></span>
|
||
<span class="line"><span style="color:#657B83;"> memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#657B83;">, </span><span style="color:#93A1A1;font-style:italic;"># 4GB RAM</span></span>
|
||
<span class="line"><span style="color:#657B83;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;"># grant permissions</span></span>
|
||
<span class="line"><span style="color:#657B83;"> table.grant_read_write_data(taskdef.task_role)</span></span>
|
||
<span class="line"><span style="color:#657B83;"> taskdef.add_to_task_role_policy(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> iam.PolicyStatement(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> effect</span><span style="color:#859900;">=</span><span style="color:#657B83;">iam.Effect.</span><span style="color:#CB4B16;">ALLOW</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> resources</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span><span style="color:#2AA198;">"*"</span><span style="color:#657B83;">],</span></span>
|
||
<span class="line"><span style="color:#657B83;"> actions</span><span style="color:#859900;">=</span><span style="color:#657B83;">[</span><span style="color:#2AA198;">"ssm:GetParameter"</span><span style="color:#657B83;">]</span></span>
|
||
<span class="line"><span style="color:#657B83;"> )</span></span>
|
||
<span class="line"><span style="color:#657B83;"> )</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#93A1A1;font-style:italic;">#</span></span>
|
||
<span class="line"><span style="color:#657B83;"> container </span><span style="color:#859900;">=</span><span style="color:#657B83;"> taskdef.add_container(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">"EcsClusterQaBot-Container"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ecs.ContainerImage.from_registry(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">"tomomano/qabot:latest"</span></span>
|
||
<span class="line"><span style="color:#657B83;"> ),</span></span>
|
||
<span class="line"><span style="color:#657B83;"> )</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br></div></div><ul><li><p>ここでは,回答の結果を書き込むためのデータベースを用意している. DynamoDB については,サーバーレスアーキテクチャの章で扱うので,今は気にしなくてよい.</p></li><li><p>ここでは,ハンズオン #1, #2 で行ったのと同様に, VPC を定義している.</p></li><li><p>ここで, ECS のクラスター (cluster) を定義している. クラスターとは,仮想サーバーのプールのことであり,クラスターの中に複数の仮想インスタンスを配置する.</p></li><li><p>ここで,実行するタスクを定義している (task definition).</p></li><li><p>ここで, タスクの実行で使用する Docker イメージを定義している.</p></li></ul><h3 id="ecs-と-fargate" tabindex="-1">ECS と Fargate <a class="header-anchor" href="#ecs-と-fargate" aria-label="Permalink to "ECS と Fargate""></a></h3><p>ECS と Fargate の部分について,コードをくわしく見てみよう.</p><div class="language-python vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">python</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#839496;">cluster </span><span style="color:#859900;">=</span><span style="color:#839496;"> ecs.Cluster(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Cluster"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> vpc</span><span style="color:#859900;">=</span><span style="color:#839496;">vpc,</span></span>
|
||
<span class="line"><span style="color:#839496;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;">taskdef </span><span style="color:#859900;">=</span><span style="color:#839496;"> ecs.FargateTaskDefinition(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#268BD2;">self</span><span style="color:#839496;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-TaskDef"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#839496;">, </span><span style="color:#586E75;font-style:italic;"># 1 CPU</span></span>
|
||
<span class="line"><span style="color:#839496;"> memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#839496;">, </span><span style="color:#586E75;font-style:italic;"># 4GB RAM</span></span>
|
||
<span class="line"><span style="color:#839496;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#839496;">container </span><span style="color:#859900;">=</span><span style="color:#839496;"> taskdef.add_container(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">"EcsClusterQaBot-Container"</span><span style="color:#839496;">,</span></span>
|
||
<span class="line"><span style="color:#839496;"> image</span><span style="color:#859900;">=</span><span style="color:#839496;">ecs.ContainerImage.from_registry(</span></span>
|
||
<span class="line"><span style="color:#839496;"> </span><span style="color:#2AA198;">"tomomano/qabot:latest"</span></span>
|
||
<span class="line"><span style="color:#839496;"> ),</span></span>
|
||
<span class="line"><span style="color:#839496;">)</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#657B83;">cluster </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ecs.Cluster(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-Cluster"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> vpc</span><span style="color:#859900;">=</span><span style="color:#657B83;">vpc,</span></span>
|
||
<span class="line"><span style="color:#657B83;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;">taskdef </span><span style="color:#859900;">=</span><span style="color:#657B83;"> ecs.FargateTaskDefinition(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#268BD2;">self</span><span style="color:#657B83;">, </span><span style="color:#2AA198;">"EcsClusterQaBot-TaskDef"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> cpu</span><span style="color:#859900;">=</span><span style="color:#D33682;">1024</span><span style="color:#657B83;">, </span><span style="color:#93A1A1;font-style:italic;"># 1 CPU</span></span>
|
||
<span class="line"><span style="color:#657B83;"> memory_limit_mib</span><span style="color:#859900;">=</span><span style="color:#D33682;">4096</span><span style="color:#657B83;">, </span><span style="color:#93A1A1;font-style:italic;"># 4GB RAM</span></span>
|
||
<span class="line"><span style="color:#657B83;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#657B83;">container </span><span style="color:#859900;">=</span><span style="color:#657B83;"> taskdef.add_container(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">"EcsClusterQaBot-Container"</span><span style="color:#657B83;">,</span></span>
|
||
<span class="line"><span style="color:#657B83;"> image</span><span style="color:#859900;">=</span><span style="color:#657B83;">ecs.ContainerImage.from_registry(</span></span>
|
||
<span class="line"><span style="color:#657B83;"> </span><span style="color:#2AA198;">"tomomano/qabot:latest"</span></span>
|
||
<span class="line"><span style="color:#657B83;"> ),</span></span>
|
||
<span class="line"><span style="color:#657B83;">)</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p><code>cluster =</code> の箇所で,空の ECS クラスターを定義している.</p><p>次に, <code>taskdef=ecs.FargateTaskDefinition</code> の箇所で, Fargate インスタンスを使ったタスクを定義しており,とくにここでは 1 CPU, 4GB RAM というマシンスペックを指定している. また,このようにして定義されたタスクは,デフォルトで 1 タスクにつき 1 インスタンスが使用される.</p><p>最後に, <code>container =</code> の箇所で,タスクの実行で使用する Docker image を定義している. ここでは, Docker Hub に置いてある image をダウンロードしてくるよう指定している.</p><p>このようにわずか数行のコードであるが,これだけで前述したような,タスクのスケジューリングなどが自動で実行される.</p><p>このコードで <code>cpu=1024</code> と指定されているのに注目してほしい. これは CPU ユニットと呼ばれる数で, 以下の換算表に従って仮想 CPU (virtual CPU; vCPU) が割り当てられる. 1024 が 1 CPU に相当する. 0.25 や 0.5 vCPU などの数字は,それぞれ実効的に 1/4, 1/2 の CPU 時間が割り当てられることを意味する. また, CPU ユニットによって使用できるメモリー量も変わってくる. たとえば, 1024 CPU ユニットを選択した場合は, 2 から 8 GB の範囲でのみメモリー量を指定することができる. 最新の情報は <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html" target="_blank" rel="noreferrer">公式ドキュメンテーション "Amazon ECS on AWS Fargate"</a> を参照のこと.</p><table><caption>CPU ユニットと 指定可能なメモリー量の換算表</caption><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><tbody><tr class="odd"><td><p>CPU ユニット</p></td><td><p>メモリーの値</p></td></tr><tr class="even"><td><p>256 (.25 vCPU)</p></td><td><p>0.5 GB, 1 GB, 2 GB</p></td></tr><tr class="odd"><td><p>512 (.5 vCPU)</p></td><td><p>1 GB, 2 GB, 3 GB, 4 GB</p></td></tr><tr class="even"><td><p>1024 (1 vCPU)</p></td><td><p>2 GB, 3 GB, 4 GB, 5 GB, 6 GB, 7 GB, 8 GB</p></td></tr><tr class="odd"><td><p>2048 (2 vCPU)</p></td><td><p>Between 4 GB and 16 GB in 1-GB increments</p></td></tr><tr class="even"><td><p>4096 (4 vCPU)</p></td><td><p>Between 8 GB and 30 GB in 1-GB increments</p></td></tr></tbody></table><h2 id="スタックのデプロイ" tabindex="-1">スタックのデプロイ <a class="header-anchor" href="#スタックのデプロイ" aria-label="Permalink to "スタックのデプロイ""></a></h2><p>スタックの中身が理解できたところで,早速スタックをデプロイしてみよう.</p><p>デプロイの手順は,これまでのハンズオンとほとんど共通である. SSH によるログインの必要がないので,むしろ単純なくらいである. ここでは,コマンドのみ列挙する (<code>#</code> で始まる行はコメントである). それぞれの意味を忘れてしまった場合は,ハンズオン 1, 2 に戻って復習していただきたい. シークレットキーの設定も忘れずに (<a href="#aws_cli_install">???</a>).</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#586E75;font-style:italic;"># プロジェクトのディレクトリに移動</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cd</span><span style="color:#839496;"> </span><span style="color:#2AA198;">handson/qa-bot</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#586E75;font-style:italic;"># venv を作成し,依存ライブラリのインストールを行う</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python3</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#839496;"> </span><span style="color:#2AA198;">venv</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">source</span><span style="color:#839496;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">pip</span><span style="color:#839496;"> </span><span style="color:#2AA198;">install</span><span style="color:#839496;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#839496;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#586E75;font-style:italic;"># デプロイを実行</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#93A1A1;font-style:italic;"># プロジェクトのディレクトリに移動</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cd</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">handson/qa-bot</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#93A1A1;font-style:italic;"># venv を作成し,依存ライブラリのインストールを行う</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python3</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-m</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">venv</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">source</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">.env/bin/activate</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">pip</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">install</span><span style="color:#657B83;"> </span><span style="color:#CB4B16;">-r</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">requirements.txt</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#93A1A1;font-style:italic;"># デプロイを実行</span></span>
|
||
<span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">deploy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>デプロイのコマンドが無事に実行されれば, <a href="#handson_03_cdk_output">figure_title</a> のような出力が得られるはずである.</p><p><img src="/assets/cdk_output.9daf7c9d.png" alt="CDKデプロイ実行後の出力"></p><p>AWS コンソールにログインして,デプロイされたスタックの中身を確認してみよう. コンソールから,ECS のページに行くと <a href="#handson_03_ecs_console">figure_title</a> のような画面が表示されるはずである. <code>EcsClusterQaBot-XXXX</code> という名前ついたクラスターを見つけよう.</p><p>Cluster というのが,先ほど説明したとおり,複数の仮想インスタンスを束ねる一つの単位である. <a href="#handson_03_ecs_console">figure_title</a> で, FARGATE という文字の下に <code>0 Running tasks</code>, <code>0 Pending tasks</code> と表示されていることを確認しよう. この時点では一つもタスクが走っていないので,数字はすべて 0 になっている.</p><p><img src="/assets/ecs_console.b76b2a4f.png" alt="ECS コンソール画面"></p><p>続いて,この画面の左のメニューバーから <code>Task Definitions</code> という項目を見つけ,クリックしよう. 移動した先のページで <code>EcsClusterQaBotEcsClusterQaBotTaskDefXXXX</code> という項目が見つかるので,開く. 開いた先のページをスクロールすると <a href="#handson_03_ecs_task_definition">figure_title</a> に示したような情報が見つかるだろう. 使用する CPU ・メモリーの量や, Docker container の実行に関する設定などが,この Task Definition の画面から確認することができる.</p><p><img src="/assets/ecs_task_definition.4f9a65fb.png" alt="Task definition の確認"></p><h2 id="タスクの実行" tabindex="-1">タスクの実行 <a class="header-anchor" href="#タスクの実行" aria-label="Permalink to "タスクの実行""></a></h2><p>それでは,質問をデプロイしたクラウドに提出してみよう.</p><p>ECS にタスクを投入するのはやや複雑なので,タスクの投入を簡単にするプログラム (<code>run_task.py</code>) を用意した (<a href="https://github.com/tomomano/learn-aws-by-coding/blob/main/handson/qa-bot/run_task.py" target="_blank" rel="noreferrer">handson/qa-bot/run_task.py</a>).</p><p>次のようなコマンドで,ECS クラスターに新しい質問を投入することができる.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ask</span><span style="color:#839496;"> </span><span style="color:#2AA198;">"A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro."</span><span style="color:#839496;"> </span><span style="color:#2AA198;">"What is the name of the baby?"</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ask</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">"A giant peach was flowing in the river. She picked it up and brought it home. Later, a healthy baby was born from the peach. She named the baby Momotaro."</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">"What is the name of the baby?"</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p><code>run_task.py</code> を実行するには, コマンドラインで AWS の認証情報が設定されていることが前提である.</p><p>"ask" の引数に続き,文脈 (context) と質問 (question) を引数として渡している.</p><p>このコマンドを実行すると, "Waiting for the task to finish…" と出力が表示され,回答を得るまでしばらく待たされる. この間, AWS では ECS がタスクを受理し,新しい Fargate のインスタンスを起動し, Docker イメージをそのインスタンスに配置する,という一連の処理がなされている. AWS コンソールから,この一連の様子をモニタリングしてみよう.</p><p>先ほどの ECS コンソール画面にもどり,クラスターの名前をクリックすることで,クラスターの詳細画面を開く. 次に, "Tasks" という名前のタブがあるので,それを開く (<a href="#ecs_task_monitoring">figure_title</a>). すると,実行中のタスクの一覧が表示されるだろう.</p><p><img src="/assets/ecs_task_monitoring.11682009.png" alt="ECS のタスクの実行状況をモニタリング"></p><p><a href="#ecs_task_monitoring">figure_title</a> で見て取れるように, "Last status = Pending" となっていることから,この時点では,タスクを実行する準備をしている段階である,ということがわかる. Fargate のインスタンスを起動し, Docker image を配置するまでおよそ 1-2 分の時間がかかる.</p><p>しばらく待つうちに, Status が "RUNNING" に遷移し,計算が始まる. 計算が終わると, Status は "STOPPED" に遷移し, ECS によって Fargate インスタンスは自動的にシャットダウンされる.</p><p><a href="#ecs_task_monitoring">figure_title</a> の画面から, "Task" の列にあるタスク ID クリックすることで,タスクの詳細画面を開いてみよう (<a href="#ecs_task_detail">figure_title</a>). "Last status", "Platform version" など,タスクの情報が表示されている. また, "Logs" のタブを開くことで,コンテナの吐き出した実行ログを閲覧することができる.</p><p><img src="/assets/ecs_task_detail.ec5c1d9f.png" alt="質問タスクの実行結果"></p><p>さて, <code>run_task.py</code> を実行したコマンドラインに戻ってきてみると, <a href="#ask_question_output">figure_title</a> のような出力が得られているはずである. "Momotaro" という正しい回答が返ってきている!</p><p><img src="/assets/ask_question_output.7fe69f85.png" alt="質問タスクの実行結果"></p><h2 id="タスクの同時実行" tabindex="-1">タスクの同時実行 <a class="header-anchor" href="#タスクの同時実行" aria-label="Permalink to "タスクの同時実行""></a></h2><p>さて,先ほどはたった一つの質問を投入したわけだが,今回設計したアプリケーションは, ECS と Fargate を使うことで同時にたくさんの質問を処理することができる. 実際に,たくさんの質問を一度に投入してみよう. <code>run_task.py</code> に <code>ask_many</code> というオプションを付けることで,複数の質問を一度に送信できる. 質問の内容は <a href="https://github.com/tomomano/learn-aws-by-coding/blob/main/handson/qa-bot/problems.json" target="_blank" rel="noreferrer">handson/qa-bot/problems.json</a> に定義されている.</p><p>次のようなコマンドを実行しよう.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">ask_many</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">ask_many</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>このコマンドを実行した後で,先ほどの ECS コンソールに行き,タスクの一覧を見てみよう (<a href="#ecs_many_tasks">figure_title</a>). 複数の Fargate インスタンスが起動され,タスクが並列に実行されているのがわかる.</p><p><img src="/assets/ecs_many_tasks.ad809e16.png" alt="複数の質問タスクを同時に投入する"></p><p>すべてのタスクのステータスが "STOPPED" になったことを確認した上で,質問への回答を取得しよう. それには,次のコマンドを実行する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">list_answers</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">list_answers</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>結果として, <a href="#ask_many_output">figure_title</a> のような出力が得られるだろう. 複雑な文章問題に対し,高い正答率で回答できていることがわかるだろう.</p><p><img src="/assets/ask_many_output.ee31d9f8.png" alt=" の実行結果"></p><p>おめでとう! ここまでついてこれた読者はとても初歩的ながらも,深層学習による言語モデルを使って自動で質問への回答を生成するシステムを創り上げることができた! それも,数百の質問にも同時に対応できるような,とても高いスケーラビリティーをもったシステムである! 今回は GUI (Graphical User Interface) を用意することはしなかったが,このシステムに簡単な GUI を追加すればなかなか立派なウェブサービスとして運用できるだろう.</p><p><code>run_task.py</code> で質問を投入し続けると,回答を記録しているデータベースにどんどんエントリーが溜まっていく. これらのエントリーをすべて消去するには,次のコマンドを使う.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">python</span><span style="color:#839496;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#839496;"> </span><span style="color:#2AA198;">clear</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">python</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">run_task.py</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">clear</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div><h2 id="スタックの削除" tabindex="-1">スタックの削除 <a class="header-anchor" href="#スタックの削除" aria-label="Permalink to "スタックの削除""></a></h2><p>これにて,今回のハンズオンは終了である. 最後にスタックを削除しよう.</p><p>スタックを削除するには,前回までと同様に, AWS コンソールにログインし CloudFormation の画面から DELETE ボタンをクリックするか,コマンドラインからコマンドを実行する. コマンドラインから行う場合は,次のコマンドを使用する.</p><div class="language-shell vp-adaptive-theme line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">shell</span><pre class="shiki solarized-dark vp-code-dark"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#839496;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#839496;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><pre class="shiki solarized-light vp-code-light"><code><span class="line"><span style="color:#268BD2;">$</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">cdk</span><span style="color:#657B83;"> </span><span style="color:#2AA198;">destroy</span></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br></div></div></div></div></main><footer class="VPDocFooter" data-v-6c4a7022 data-v-b5edbda4><!--[--><!--[--><!--[--><!--[--><!----><!--]--><!--]--><!--]--><!--]--><div class="edit-info" data-v-b5edbda4><div class="edit-link" data-v-b5edbda4><a class="VPLink link edit-link-button" href="https://github.com/andatoshiki/toshiki-notebook/edit/master/docs/development/aws/handson-qabot.md" target="_blank" rel="noreferrer" data-v-b5edbda4 data-v-075865b7><!--[--><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="edit-link-icon" aria-label="edit icon" data-v-b5edbda4><path d="M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"></path><path d="M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"></path></svg> Edit this page on GitHub<!--]--><!----></a></div><div class="last-updated" data-v-b5edbda4><p class="VPLastUpdated" data-v-b5edbda4 data-v-00fbdbd8>Last updated: <time datetime="2023-06-11T16:43:20.000Z" data-v-00fbdbd8></time></p></div></div><div class="prev-next" data-v-b5edbda4><div class="pager" data-v-b5edbda4><!----></div><div class="pager" data-v-b5edbda4><a class="pager-link next" href="/development/file-naming-convention" data-v-b5edbda4><span class="desc" data-v-b5edbda4>Next page</span><span class="title" data-v-b5edbda4>File Naming Convention</span></a></div></div></footer><!--[--><!--[--><!--[--><div id="comment-container"></div><!--]--><!--]--><!--]--></div></div></div><!--[--><!--]--></div></div><footer class="VPFooter has-sidebar" data-v-83f63849 data-v-02da8605><div class="container" data-v-02da8605><p class="message" data-v-02da8605>Wrote with <i class="heart fa fa-heart fa-xs fa-beat"></i> and <i class="coffee fa fa-coffee fa-xs" aria-hidden="true"></i> by <a href="https://toshiki.dev">Anda Toshiki</a> at <code>root@andatoshiki:/~</code></p><p class="copyright" data-v-02da8605>Copyright © 2023-2023 <a href="https://github.com/andatoshiki">Anda Toshiki</a>, <a href="https://github.com/lolilab">LoliLab</a> and <a href="https://github.com/toshikidev">Toshiki Dev</a> present <br /><span id="siteruntime_span"></span></p></div></footer><!--[--><!--]--></div></div>
|
||
<script>__VP_HASH_MAP__ = JSON.parse("{\"academic_chemistry_index.md\":\"5ed3141e\",\"academic_physics_ipho-formulas-jpn_6.md\":\"e1d4cfda\",\"academic_physics_ipho-formulas-jpn_12.md\":\"686a3074\",\"academic_chemistry_problems_03-02-1.md\":\"e994fec9\",\"academic_chemistry_notes_12-5.md\":\"dd8cec68\",\"academic_physics_ipho-formulas-jpn_3.md\":\"124f4341\",\"academic_physics_ipho-formulas-jpn_4.md\":\"42568d7b\",\"academic_physics_ipho-formulas-jpn_2.md\":\"59a1b4a2\",\"academic_physics_index.md\":\"9e10ccb4\",\"academic_physics_ipho-formulas-jpn_1.md\":\"5add3cd7\",\"academic_physics_ipho-formulas-jpn_10.md\":\"67d19ce2\",\"academic_chemistry_problems_02-20.md\":\"c99e2760\",\"academic_physics_ipho-formulas-jpn_11.md\":\"3c575396\",\"academic_chemistry_problems_03-02-2.md\":\"7bce6660\",\"academic_chemistry_problems_03-02-3.md\":\"e985beae\",\"academic_literature_writing_methods-of-development.md\":\"a7324a3e\",\"application_vitepress-plugin-shiki-twoslash_guide_markdown-extensions.md\":\"22f61405\",\"academic_physics_ipho-formulas-jpn_5.md\":\"a205da50\",\"academic_literature_index.md\":\"66df3ccf\",\"academic_physics_ipho-formulas-jpn_7.md\":\"046ce05c\",\"academic_physics_ipho-formulas-jpn_8.md\":\"8d6b7048\",\"academic_physics_ipho-formulas-jpn_9.md\":\"8cf0e277\",\"academic_vocabulary_2023_02_2023-02-27.md\":\"8fa7aaf7\",\"academic_vocabulary_index.md\":\"5594c9e7\",\"application_markdown-it-katex_how-to-use.md\":\"be7c4663\",\"application_markdown-it-katex_tips.md\":\"01705826\",\"application_vitepress-plugin-shiki-twoslash_api_annotations.md\":\"eb1d59ad\",\"application_vitepress-plugin-shiki-twoslash_api_cutting.md\":\"2cf8de19\",\"application_vitepress-plugin-shiki-twoslash_api_emit.md\":\"e018e0e6\",\"application_vitepress-plugin-shiki-twoslash_api_errors.md\":\"790d21a9\",\"application_vitepress-plugin-shiki-twoslash_api_includes.md\":\"0483ab7b\",\"application_vitepress-plugin-shiki-twoslash_api_logging.md\":\"6243397b\",\"application_vitepress-plugin-shiki-twoslash_api_multi-file.md\":\"26339718\",\"application_vitepress-plugin-shiki-twoslash_api_queries.md\":\"993bf41c\",\"application_vitepress-plugin-shiki-twoslash_config_reference.md\":\"b102d8ba\",\"application_vitepress-plugin-shiki-twoslash_guide_custom-theme.md\":\"99c5bb86\",\"development_aws_readme.md\":\"0bb29e47\",\"development_aws_acknowledgement.md\":\"e21b036e\",\"development_aws_appendix.md\":\"b532216a\",\"development_aws_assignments.md\":\"07481fa9\",\"development_aws_author.md\":\"27df09d2\",\"development_aws_aws-batch.md\":\"5992a8bb\",\"application_vitepress-plugin-shiki-twoslash_config_flags.md\":\"0f646d11\",\"development_aws_aws-get-started.md\":\"a6e57773\",\"development_aws_closing.md\":\"06e3954d\",\"development_aws_cloud.md\":\"9e7cb764\",\"development_aws_docker-system.md\":\"0f876020\",\"development_aws_handson-bashoutter.md\":\"f12b58fb\",\"development_aws_handson-ec2.md\":\"783a74b3\",\"development_aws_handson-jupyter.md\":\"d1d9d86c\",\"development_aws_handson-qabot.md\":\"15fa9676\",\"application_vitepress-plugin-shiki-twoslash_index.md\":\"ecbbab92\",\"development_aws_handson-serverless.md\":\"e1f40ed8\",\"application_vitepress-plugin-shiki-twoslash_api_types.md\":\"552c12a7\",\"development_aws_introduction.md\":\"3cb21933\",\"development_aws_license.md\":\"88d4814c\",\"academic_physics_ipho-formulas-jpn_13.md\":\"48dc3ca2\",\"development_aws_main.md\":\"5403d752\",\"development_aws_scientific-computing.md\":\"05ccc477\",\"development_aws_serverless.md\":\"08551339\",\"development_aws_webserver.md\":\"d695735a\",\"development_file-naming-convention.md\":\"4fe6f86b\",\"development_rclone-for-r2.md\":\"e801d99f\",\"getting-started.md\":\"69d6ca98\",\"index.md\":\"194ed2db\",\"javascript_notes_1_1-1.md\":\"8a59d267\",\"javascript_notes_1_1-2.md\":\"c90f4e53\",\"jp_index.md\":\"500bc708\",\"roadmap.md\":\"4e123da7\",\"save_reading_index.md\":\"8e93cacc\",\"save_reading_outliers_1.md\":\"1a73c2c0\",\"save_reading_outliers_2.md\":\"d1388e1f\",\"save_reading_outliers_3.md\":\"20c0e9e6\",\"save_reading_outliers_4.md\":\"fb372c7f\",\"application_markdown-it-katex_support-function.md\":\"3562e862\",\"application_markdown-it-katex_support-table.md\":\"36357a78\"}")
|
||
__VP_SITE_DATA__ = JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Toshiki's Note\",\"description\":\"Toshiki's web notebook served via Vitepress!\",\"base\":\"/\",\"head\":[],\"appearance\":true,\"themeConfig\":{\"nav\":[{\"text\":\"Development\",\"link\":\"/development/\"},{\"text\":\"Academic\",\"items\":[{\"text\":\"K-12\",\"items\":[{\"text\":\"Chemistry\",\"link\":\"/academic/chemistry/index\",\"activeMatch\":\"/academic/chemistry/\"},{\"text\":\"Discrete Math.\",\"link\":\"/discrete-math/index\",\"activeMatch\":\"/categories/fragments/\"},{\"text\":\"Literature\",\"link\":\"/academic/literature/index\",\"activeMatch\":\"/academic/literature/\"}]},{\"text\":\"Tools\",\"items\":[{\"text\":\"Formulas for IPhO JPN.\",\"link\":\"/academic/physics/ipho-formulas-jpn/1\",\"activeMatch\":\"/academic/physics/ipho-formulas-jpn/\"}]},{\"text\":\"\",\"link\":\"\",\"activeMatch\":\"\"},{\"text\":\"\",\"link\":\"\",\"activeMatch\":\"\"},{\"text\":\"\",\"link\":\"\",\"activeMatch\":\"\"},{\"text\":\"\",\"link\":\"\",\"activeMatch\":\"\"},{\"text\":\"\",\"link\":\"\",\"activeMatch\":\"\"},{\"text\":\"\",\"link\":\"\",\"activeMatch\":\"\"},{\"text\":\"\",\"link\":\"\",\"activeMatch\":\"\"}],\"activeMatch\":\"/academic/\"},{\"text\":\"Application\",\"items\":[{\"text\":\"Personal projects\",\"items\":[{\"text\":\"markdown-it-katex\",\"link\":\"/application/markdown-it-katex/how-to-use\",\"activeMatch\":\"/application/markdown-it-katex/\"},{\"text\":\"vitepress-plugin-shiki-twoslash\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/index\",\"activeMatch\":\"/application/vitepress-plugin-shiki-twoslash/index\"}]}],\"activeMatch\":\"/save/\"},{\"text\":\"Save\",\"items\":[{\"text\":\"Reading\",\"link\":\"/save/reading/index\",\"activeMatch\":\"/save/reading/\"},{\"text\":\"Vocabulary\",\"link\":\"/academic/vocabulary/index\",\"activeMatch\":\"/academic/vocabulary/\"}],\"activeMatch\":\"/save/\"}],\"sidebar\":{\"/development/\":[{\"text\":\"Wiki Database\",\"collapsed\":false,\"items\":[{\"text\":\"File Naming Convention\",\"link\":\"/development/file-naming-convention\"}]}],\"/academic/chemistry/\":[{\"text\":\"Textbook\",\"collapsed\":true,\"items\":[{\"text\":\"12-5: Reaction Mechanism\",\"link\":\"/academic/chemistry/notes/12-5\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"}]},{\"text\":\"Kinetics\",\"collapsed\":false,\"items\":[{\"text\":\"Rate determining steps\",\"link\":\"/academic/chemistry/notes/kinetics/rate-determining-step\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"}]},{\"text\":\"Problems & Solutions\",\"collapsed\":true,\"items\":[{\"text\":\"Problem: 02-20\",\"link\":\"/academic/chemistry/problems/02-20\"},{\"text\":\"Problem: 03-02-1\",\"link\":\"/academic/chemistry/problems/03-02-1\"},{\"text\":\"Problem: 03-02-2\",\"link\":\"/academic/chemistry/problems/03-02-2\"},{\"text\":\"Problem: 03-02-3\",\"link\":\"/academic/chemistry/problems/03-02-3\"}]}],\"/academic/physics\":[{\"text\":\"IPhO Formulas: JP Ver.\",\"collapsed\":false,\"items\":[{\"text\":\"1: 数学\",\"link\":\"/academic/physics/ipho-formulas-jpn/1\"},{\"text\":\"2: 一般的な推奨事\",\"link\":\"/academic/physics/ipho-formulas-jpn/2\"},{\"text\":\"3: 運動学\",\"link\":\"/academic/physics/ipho-formulas-jpn/3\"},{\"text\":\"4: 力学\",\"link\":\"/academic/physics/ipho-formulas-jpn/4\"},{\"text\":\"5: 振動と波\",\"link\":\"/academic/physics/ipho-formulas-jpn/5\"},{\"text\":\"6: 幾何光学,測光\",\"link\":\"/academic/physics/ipho-formulas-jpn/6\"},{\"text\":\"7: 波動光学\",\"link\":\"/academic/physics/ipho-formulas-jpn/7\"},{\"text\":\"8: 電気回路\",\"link\":\"/academic/physics/ipho-formulas-jpn/8\"},{\"text\":\"9: 電磁気学\",\"link\":\"/academic/physics/ipho-formulas-jpn/9\"},{\"text\":\"10: 熱力\",\"link\":\"/academic/physics/ipho-formulas-jpn/10\"},{\"text\":\"11: 量子力学\",\"link\":\"/academic/physics/ipho-formulas-jpn/11\"},{\"text\":\"12: Keplerの法則\",\"link\":\"/academic/physics/ipho-formulas-jpn/12\"},{\"text\":\"13: 相対性理論\",\"link\":\"/academic/physics/ipho-formulas-jpn/13\"}]}],\"/academic/vocabulary/\":[{\"text\":\"Vocabulary\",\"collapsed\":true,\"items\":[{\"text\":\"2023-02-27\",\"link\":\"/academic/vocabulary/2023/02/2023-02-27\"}]}],\"/academic/literature/\":[{\"text\":\"Writing Resources\",\"collapsed\":true,\"items\":[{\"text\":\"Patterns of Organization and Methods of Development\",\"link\":\"/academic/literature/writing/methods-of-development\"}]}],\"/javascript/\":[{\"text\":\"1: Basic JavaScript-Value, Variables, and Control Flow\",\"collapsed\":true,\"items\":[{\"text\":\"1-1: Numbers\",\"link\":\"/javascript/notes/1/1-1\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"},{\"text\":\"\",\"link\":\"\"}]}],\"/save/reading/\":[{\"text\":\"Outliers\",\"collapsed\":true,\"items\":[{\"text\":\"Introduction & Chapter 1: The Roseto Mystery\",\"link\":\"/save/reading/outliers/1\"},{\"text\":\"Chapter 2: The 10,000-Hour Rule\",\"link\":\"/save/reading/outliers/2\"},{\"text\":\"Chapter 3: The Trouble with Geniuses, Part 1\",\"link\":\"/save/reading/outliers/3\"},{\"text\":\"Chapter 4: The Trouble with Geniuses, Part 2\",\"link\":\"/save/reading/outliers/4\"}]}],\"/application/markdown-it-katex/\":[{\"text\":\"markdown-it-katex\",\"collapsed\":false,\"items\":[{\"text\":\"1: How to use?\",\"link\":\"/application/markdown-it-katex/how-to-use\"},{\"text\":\"2: KaTeX supported functions\",\"link\":\"/application/markdown-it-katex/support-function\"},{\"text\":\"3: KaTeX support tables\",\"link\":\"/application/markdown-it-katex/support-table\"},{\"text\":\"4: Tips\",\"link\":\"/application/markdown-it-katex/tips\"}]}],\"/application/vitepress-plugin-shiki-twoslash/\":[{\"text\":\"Guide\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/\"},{\"text\":\"Markdown Extensions\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/guide/markdown-extensions\"},{\"text\":\"Using a Custom Theme\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/guide/custom-theme\"}]},{\"text\":\"Features\",\"collapsed\":false,\"items\":[{\"text\":\"Queries\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/queries\"},{\"text\":\"Errors\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/errors\"},{\"text\":\"Emit\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/emit\"},{\"text\":\"Cutting\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/cutting\"},{\"text\":\"Multi-file\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/multi-file\"},{\"text\":\"@types\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/types\"},{\"text\":\"Meta Annotations\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/annotations\"},{\"text\":\"Logging\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/logging\"},{\"text\":\"Includes\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/api/includes\"}]},{\"text\":\"Config\",\"collapsed\":false,\"items\":[{\"text\":\"Reference\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/config/reference\"},{\"text\":\"Compiler Flags\",\"link\":\"/application/vitepress-plugin-shiki-twoslash/config/flags\"}]}]},\"footer\":{\"copyright\":\"Copyright © 2023-2023 <a href=\\\"https://github.com/andatoshiki\\\">Anda Toshiki</a>, <a href=\\\"https://github.com/lolilab\\\">LoliLab</a> and <a href=\\\"https://github.com/toshikidev\\\">Toshiki Dev</a> present <br /><span id=\\\"siteruntime_span\\\"></span>\",\"message\":\"Wrote with <i class=\\\"heart fa fa-heart fa-xs fa-beat\\\"></i> and <i class=\\\"coffee fa fa-coffee fa-xs\\\" aria-hidden=\\\"true\\\"></i> by <a href=\\\"https://toshiki.dev\\\">Anda Toshiki</a> at <code>root@andatoshiki:/~</code>\"},\"logo\":\"/logos/logo.png\",\"outline\":\"deep\",\"outlineTitle\":\"TOC\",\"outlineBadges\":false,\"lastUpdatedText\":\"Last updated\",\"algolia\":{\"appId\":\"G9IUR45K98\",\"apiKey\":\"8528cc91281d8112b28f508317a96dd3\",\"indexName\":\"toshiki-notebook\"},\"editLink\":{\"pattern\":\"https://github.com/andatoshiki/toshiki-notebook/edit/master/docs/:path\",\"text\":\"Edit this page on GitHub\"},\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/andatoshiki\"},{\"icon\":\"twitter\",\"link\":\"https://twitter.com/andatoshiki\"}]},\"locales\":{\"/\":{\"label\":\"English\",\"lang\":\"en-US\"},\"/jp/\":{\"label\":\"Japanese\",\"title\":\"Vue Test Utils\",\"lang\":\"jp-JP\",\"description\":\"La documentation officielle de Vue Test Utils\"}},\"scrollOffset\":90,\"cleanUrls\":true}")</script>
|
||
|
||
</body>
|
||
</html> |