Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ポスターセッション: 「まっすぐ行って、右!」って言ってラズパイカーを動かしたい 〜生成AI...

Avatar for komo_fr komo_fr
September 25, 2025

ポスターセッション: 「まっすぐ行って、右!」って言ってラズパイカーを動かしたい 〜生成AI × Raspberry Pi Pico × Gradioの試作メモ〜

PyCon JP 2025のポスターセッションの資料です

発表の概要: https://2025.pycon.jp/ja/timetable/talk/9CD3UW

GitHubリポジトリ: https://github.com/komo-fr/llm-pico-car
デモ動画: https://www.youtube.com/watch?v=glEbEZsswRA
発表者X: @komo_fr (https://x.com/komo_fr

Avatar for komo_fr

komo_fr

September 25, 2025
Tweet

More Decks by komo_fr

Other Decks in Programming

Transcript

  1. ൃදऀ͕͍Δ࣌ؒଳ %BZ %BZ ൃදऀ 5PNPLP'VSVLJʢ!LPNP@GSʣ ҎԼͷ࣌ؒଳͰ͸௚઀આ໌͕Ͱ͖Δ༧ఆͰ͢ʂ ͥͻཱ͓ͪدΓ͍ͩ͘͞ େֶͰ͸஌ೳ৘ใϝσΟΞΛઐ߈͠ɺଔۀޙ͸γεςϜ։ൃ΍ɺ 1ZUIPOΛ࢖ͬͨσʔλ׆༻ͷ1P$։ൃɺٕज़ࢧԉͳͲʹैࣄɻ 1Z$PO+1ɺ1Z$PO,ZVTIVJO0LJOBXBɺ4DJ1Z+BQBOͳͲʹొஃɻ

    ࣥචɾ຋༁ ɾʮ1ZUIPOΠϯλϥΫςΟϒɾσʔλϏδϡΞϥΠθʔγϣϯೖ໳ʕ1MPUMZ%BTIʹΑΔσʔλՄࢹԽͱ8FCΞϓϦߏஙʕʯ ʢே૔ॻళɺڞஶʣ ɾʮੈքඪ४.*5ڭՊॻɹ1ZUIPOݴޠʹΑΔϓϩάϥϛϯάΠϯτϩμΫγϣϯୈ൛ʯʢۙ୅Պֶࣾɺڞ༁ʣ ݱࡏɺגࣜձࣾϏʔϓϥ΢υॴଐɻ ᶃ  ᶄ  ᶅ  ᶃ  ᶄ  ड෇ʙ0QFOJOH։࢝લ னͷ௕ΊͷٳΈ࣌ؒ ϙελʔηογϣϯͷ࣌ؒ னͷ௕ΊͷٳΈ࣌ؒ ϙελʔηογϣϯͷ࣌ؒ ϝϯόʔ௨೥ืूதʂ εϙϯαʔϒʔε΋ ΍ͬͯΔΑ 9!LPNP@GS ݄೔ʢ౔ʣͷ 1Z$PONJOJ౦ւͰ΋ -BOH$IBJOͱ-BOH(SBQIʹؔ͢Δ τʔΫΛ͢Δ༧ఆͰ͢ɹͥͻ͖ͯͶ
  2. খܕΧʔΛࣗવݴޠͰ ಈ͔͍ͨ͠ ࣗવݴޠͰখܕΧʔʹࢦ͕ࣔग़ͤͨΒ ͪΐͬͱϖοτΆ͔ͯ͘Θ͍͍ͷͰ͸ʁ Πϝʔδਤ .PUJWBUJPO ΞΠσΞ ੜ੒"*ͰࣗવݴޠˠίϚϯυʹม׵ͨ͠Β ͍͚Δؾ͕͢Δʂ ·͙ͬ͢ߦͬͯ

    ӈʹۂ͕ͬͯʂ ·͙ͬ͢ߦͬͯӈʂ [{ "action": { "type": "forward", "distance_cm": 20,}, { "action": { "type": "turn", "direction": "right", "angle": 90,}, ...] གྷͬͯΈͯʂ ᶃ ࣗવݴޠ ίϚϯυʢࣙॻͷϦετʣ લʹਐΉ ӈʹ౓ճస
  3. શମͷߏ੒ Πϝʔδਤ )PX εϚϗͳͲͷ 8FCϒϥ΢β 1JDP$BSαʔό ʢ3BTQCFSSZ1J1*DPΧʔʣ 8FCΞϓϦ͔Β Ի੠Λೖྗ ίϚϯυΛड৴

     ࣮ߦ ࠓճ࢖ͬͨػମ ,JUSPOJL3BTQCFSSZ1J1JDP༻ ࣗ૸ϩϘοτϓϥοτϑΥʔϜʢόΪʔλΠϓʣ w ిࢠ޻࡞ͷܦݧ͕͋·Γͳ͍ͷͰɺࢢൢͷΩοτΛ࢖͍͍ͨ w Ϧν΢ϜΠΦϯి஑͸؅ཧ͕େมͦ͏ͳͷͰɺסి஑Ͱಈ͔͍ͨ͠ ! 3BTQCFSZ1J1*DP סి஑Ͱಈ͘ຊΩοτʹͨ͠ ᶄ Ի੠Λจࣈى͜͠  ੜ੒"*ͰίϚϯυʹม׵ 1JDP$POUSPMMFSαʔό ʢ.BDʣ Ի੠ ίϚϯυ ˞ੜ੒"*ॲཧ͸0QFO"*ͷ"1*Λར༻ ࠓճͷߏ੒ͷཧ༝ બఆཧ༝ w 1JDPΧʔ୯ମͩͱԻ੠ೝࣝ΍ੜ੒"*Λ࢖͏ͷ͕೉͍͠ʢॲཧ͕ॏ͍ɺ.JDSP1ZUIPOͩͱҰ෦ϥΠϒϥϦΛ࢖͑ͳ͍ʣ ! Ի੠ೝࣝ΍ੜ੒"*Λ࢖͏ॲཧ͸ɺ.BD্Ͱಈ͘8FCαʔόʹ೚ͤͨ 1JDPΧʔͰ͸Ϟʔλ΍-&%ͷ੍ޚ͚ͩΛߦ͏ w ʮ1$ʹ࿩͔͚͠Δʯܗͩͱɺʮ1JDPΧʔʹ࿩͔͚͍ͯ͠Δʯײ͕ബ͘ͳͬͯ͠·͏ ! 8FCϒϥ΢βܦ༝ͷ6*ʹͯ͠ɺεϚϗ͔Β΋ૢ࡞Ͱ͖ΔΑ͏ʹͨ͠ʢτϥϯγʔόʔతͳΠϝʔδͰʣ ंྠ෇͖Ϟʔλʢݸʣ-&%ʢंମͷ۱ʣϒβʔ ࠓճ͸ະ࢖༻͕ͩɺڑ཭ηϯααʔϘϥΠϯτϨʔε༻ηϯα΋༗
  4. (SBEJPͰ࡞ͬͨ 8FCΞϓϦ͔ΒԻ੠ೖྗ ॲཧ଴ͪதͷ޻෉ 4UFQ 6* ᶅ Ի੠ೝࣝ΍ੜ੒"*ॲཧͷ଴͕ͪ࣌ؒ௕͍ͨΊɺ ʮ͢΂ͯͷॲཧ͕׬͔ྃͯ͠Βදࣔ͢ΔʯͷͰ͸ͳ͘ɺ ʮ֤εςοϓͷॲཧ͕׬ྃ͢Δ͝ͱʹ్த݁Ռ͕දࣔ͞ΕΔʯΑ͏ʹͨ͠ (SBEJPͱ͸

    ػցֶशͷσϞΞϓϦͳͲΛ ؆୯ʹ࡞ΕΔ8FCΞϓϦ ϑϨʔϜϫʔΫ બఆཧ༝ w Ի੠ೖྗ΍ը૾ೖྗΛ ؆୯ʹ࡞ΕΔ w ॲཧͷεςοϓ͝ͱʹ ঃʑʹ݁ՌΛฦ͢Α͏ͳ 6*Λ࡞Γ΍͍͢ Ի੠ೖྗ෦෼ ʢHS"VEJPΫϥεʣ ૹ৴ϦηοτϘλϯ ʢHS#VUUPOΫϥεʣ จࣈى͜͠ͷ݁Ռ ʢHS5FYU#PYΫϥεʣ ૹ৴݁ՌʢHS5FYU#PYΫϥεʣ ੜ੒͞ΕͨίϚϯυʢHS+40/Ϋϥεʣ ೖྗྖҬ ग़ྗྖҬ audio_input = gr.Audio(sources=["microphone"], type="filepath", format=“wav") …ུ… audio_input.stop_recording(fn=handler_audio_input, # ࿥Իఀࢭ࣌ʹݺ͹ΕΔؔ਺ inputs=audio_input, # σʔλͷೖྗݩͱͳΔ෦඼ # σʔλͷग़ྗઌͱͳΔ෦඼ outputs=[audio_transcript_output, audio_commands_output, audio_status_output, progress_lamps]) def handler_audio_input(audio_file): success, text = transcribe(audio_file) if success: yield text, None, "จࣈى͜͠׬ྃ", render_lamps(["s", "u", "u"]) commands = text_to_command(text) commands = convert_commands(commands) yield text, commands, "ίϚϯυੜ੒׬ྃ", render_lamps(["s", "s", "u"]) response = send_commands(commands) status = response.get("status") yield text, commands, status, render_lamps(["s"] * 3) else: yield text, None, "จࣈى͜͠ʹࣦഊ͠·ͨ͠ɻऴྃ͠·͢", render_lamps(["e", "u", "u"]) ᶃ(SBEJPͷԻ੠ೖྗͷ෦඼Λ࡞੒ ᶄ࿥Իఀࢭ࣌ʹݺ͹ΕΔؔ਺΍ σʔλͷग़ྗઌΛઃఆ ᶅจࣈى͜͠ͷॲཧΛߦ͏ ᶆจࣈى͜͠ͷ݁ՌΛZJFMEͰฦ͢ ᶈੜ੒"*ͷ݁ՌΛZJFMEͰฦ͢ ᶊQJDPΧʔͷಈ࡞݁ՌΛZJFMEͰฦ͢ ᶇੜ੒"*ͰίϚϯυʹม׵ ᶉQJDPΧʔʹίϚϯυΛૹ৴ ॲཧͷਐḿϥϯϓ ʢHS)5.-Ϋϥεʣ ࿥Իఀࢭϋϯυϥ Ի੠ೖྗͷઃఆ จࣈى͜͠ͷ݁Ռ ม׵ޙͷίϚϯυ ૹ৴݁Ռ ॲཧͷਐḿϥϯϓ QJDP@DPOUSPMMFSBQQQZ
  5. -BOH$IBJO౳Ͱ ࣗવݴޠΛίϚϯυʹม׵ ςΩετˠίϚϯυʢࣙॻͷϦετʣ 4UFQ Ի੠ˠςΩετʢจࣈى͜͠ʣ ᶆ Ի੠ͷ··ੜ੒"*ʹೖྗ͢Δͱ"1*ྉۚͷίετ͕͔͔Γͦ͏ !ϩʔΧϧͰGBTUFSXIJTQFSΛ࢖ͬͯจࣈى͜͠Λ͢Δ from faster_whisper

    import WhisperModel model_size = "tiny" model = WhisperModel(model_size, device="cpu", compute_type="float32") …ུ… segments, _ = model.transcribe(tmp_audio_path, language="ja") text = "".join([segment.text for segment in segments]) -BOH$IBJOܦ༝Ͱ0QFO"*ͷ"1*ʢHQUʣΛ࢖ͬͯίϚϯυΛੜ੒ ᐆດͳݴ༿ΛݴΘΕͨ৔߹͸ɺʮײ৘ʯΛද͢ಈ͖΍৭ʹม׵͢Δ from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate …ུ… prompt = ChatPromptTemplate.from_messages( [ ("system", TEXT_TO_COMMAND_PROMPT), ("human", "ࢦࣔ: {text}"), ] ) llm = ChatOpenAI(model="gpt-4.1", temperature=0) chain = prompt | llm result = chain.invoke({"text": text}) instructions = result.content instructions = _add_led_rgb(instructions) # ੜ੒͞ΕͨίϚϯυ಺ͷLEDͷ৭ʢCSSͷ৭໊ʣΛݩʹRGB৘ใΛ௥Ճ instructions = json.loads(instructions) ༩͑ΒΕͨ೔ຊޠͷࢦࣔจΛɺpicoΧʔ༻ͷJSON ܗࣜͷಈ࡞ίϚϯυ഑ྻʹม׵͍ͯͩ͘͠͞ɻ ࢦࣔͰ͸ͳ͍ݴ༿ΛݴΘΕͨ৔߹ʢʮ͓͸Α͏ʂʯ ʮ͹͔ʂʯͳͲʣ͸ɺݴΘΕͨݴ༿ʹର͢Δײ৘Λ ද͢ಈ࡞ͷίϚϯυ഑ྻʹม׵͍ͯͩ͘͠͞ɻ ίϚϯυ഑ྻ͚ͩΛग़ྗ͠ɺͦΕҎ֎ͷઆ໌จͳͲ ͸ؚΊͳ͍Ͱ͍ͩ͘͞ɻ ֤ίϚϯυ͸ҎԼͷܗࣜΛ࢖༻͍ͯͩ͘͠͞: …ུ… ᶃϞσϧͷಡΈࠐΈ ᶄϞσϧͷ࣮ߦʢจࣈى͜͠ʣ QJDP@DPOUSPMMFSBVEJP@UP@UFYUQZ QJDP@DPOUSPMMFSUFYU@UP@DPNNBOEQZ [ { "action": {"type": "forward", "distance_cm": 20}, "led": {"color": "green", "rgb": (0, 255, 0)}}, { "action": {"type": "turn", "direction": "right", "angle": 90}, "led": {"color": "green", "rgb": (0, 255, 0)}}, …] ੜ੒͞ΕΔίϚϯυͷྫ -BOH$IBJOͱ͸ ೥ʹൃද͞Εͨɺ--.ΞϓϦέʔγϣϯ։ൃͷͨΊͷ1ZUIPOϑϨʔϜϫʔΫ ͭ໨ͷίϚϯυ BDUJPOલਐ͢ΔʢDNʣ MFE྘৭ ͭ໨ͷίϚϯυ BDUJPOӈճసʢ౓ʣ MFE྘৭ ᶃϓϩϯϓτͷߏங ᶄϞσϧͷݺͼग़͠ ᶅϓϩϯϓτͱϞσϧΛܨ͍Ͱ࣮ߦ ᶆग़ྗ݁Ռʹ৘ใ௥Ճ੔ܗͳͲ
  6. 1JDPΧʔ্ͷ αʔόʹίϚϯυΛૹ৴ ίϚϯυΛॱ൪ʹॲཧ 4UFQ ᶇ .JDSPEPUͱ͸ w 'MBTLʹண૝ΛಘͨϛχϚϧͳ8FCϑϨʔϜϫʔΫ w ඪ४ͷ$1ZUIPOʹՃ͑.JDSP1ZUIPOΛαϙʔτ͍ͯ͠ΔͷͰɺ1JDP্Ͱ΋ಈ͔ͤΔ

    w ࠓճͷ༻్ͷ৔߹ɺNJDSPEPUQZʢ໿,#ʣΛ1JDP্ʹஔ͚ͩ͘Ͱ࢖͑Δ from microdot import Microdot from pico_car import Car, RealCar car = Car() if settings.USE_MOCK else RealCar() app = Microdot() …ུ… @app.route("/command", methods=["POST"]) async def handle_command(request): try: car.sound_freq(1000, 0.1) car.sound_freq(1200, 0.1) command_list = request.json car.run_commands(command_list) return {"status": "ok"} except Exception as e: handle_buggy_error() print_exception(e) return {"status": "error", "message": str(e)}, 500 …ུ… app.run(port=5001) ࣗ࡞ͷ1JDPΧʔΫϥεͷ ΠϯελϯεΛੜ੒ .JDSPEPUΞϓϦΛ࡞੒ ίϚϯυΛ࣮ߦ͢Δ"1*ͷఆٛ ᶃड৴ԻΛ໐Β͢ ᶄίϚϯυΛ࣮ߦ QJDP@DBSNBJOQZ Τϥʔൃੜ࣌ͷॲཧΛ࣮ߦʢΤϥʔԻΛ໐Β͢ɺϞʔλఀࢭ౳ʣ αʔόΛىಈ 'MBTLͬΆ͍ॻ͖ํ͕ Ͱ͖Δ ࣮ػͷ1*DPΧʔͰಈ͔͍ͯ͠Δ࣌͸ ݱࡏԿͷॲཧΛ΍͍ͬͯΔͷ͔ϩάͳͲͰ ֬ೝ͠ʹ͍͘ͷͰɺԻͰ௨஌ ୯७ʹGPSจͰίϚϯυΛॱʹ࣮ߦ͍ͯ͘͠ Ϟʔλʔ΍-&%ͷ੍ޚ͸ɺ࣮ػͷΩοτ༻ͷϥΠϒϥϦ  Λ࢖༻ IUUQTHJUIVCDPN,JUSPOJL-UE,JUSPOJL1JDP"VUPOPNPVT3PCPUJDT1MBUGPSN.JDSP1ZUIPO ଎౓ͳͲͷઃఆը໘ ૸ΒͤΔ৔ॴͷঢ়ଶ΍1JDPΧʔͷঢ়ଶʹ ΑΓɺಉ͡ڑ཭ʢDNͳͲʣΛࢦఆ͠ ͯ΋࣮ࡍʹਐΉڑ཭΍ճΔ֯౓͕มΘͬ ͯ͠·͏ ! (SBEJPͰʮϞʔλͷ଎͞ʯ΍ʮඵؒ ͰਐΉڑ཭ɾճస͢Δ֯౓ʯΛௐ੔Ͱ͖ Δઃఆը໘Λ࡞੒ 4UFQඵؒಈ͔ͨ͠ͱ͖ͷ ڑ཭֯౓Λ࣮ଌ 4UFQݱࡏͷઃఆΛऔಘ 4UFQͷ࣮ଌ஋Λݩʹઃఆ ઃఆʹΑͬͯ ϞοΫ࣮ػΛ੾Γସ͑ ʢಈ࡞֬ೝΛεϜʔζʹʣ 1JDP্Ͱ.JDSPEPUαʔόΛಈ͔͢
  7. ࣮ߦ݁Ռɾίʔυ ໘ന͍ͱ͜Ζ 0VUQVU ᶈ σϞಈը (JU)VC ςΩετˠίϚϯυม׵Ͱੜ੒"*Λ࢖͍ͬͯΔͨΊ ᐆດͳݴ༿Ͱ΋ಈ࡞ʹม׵͞ΕΔ གྷͬͯΈͯʂ ͋ͳͨՄѪ͍ΘͶʙ

    ͹͔͹͔ʂ ࠓ೔Φʔλχ͞Μ͕ ϗʔϜϥϯଧͬͨΜͩͬͯ ஥௚Γ͠Α͏ ϐϯΫͰࠨӈʹৼΕͯ ԫ৭Ͱલޙ ੨৭Ͱޙୀ ʢ൵͠Έʁʣ ྘Ͱલਐ ʢߠఆʁʣ ԫ৭Ͱલਐͯ͠ ࠨӈʹৼΕΔʢςϯγϣϯߴʁʣ ϐϯΫͰલਐͯ͠ ࠨӈʹ;Γ;Γ ʢتͼʁʣ IUUQTHJUIVCDPNLPNPGSMMNQJDPDBS IUUQTZPVUVCFHM&C&;TTX3"
  8. վળɾԠ༻ ॲཧ଴ͪ࣌ؒதͷϑΟʔυόοΫ ᶉ ը૾͔Βͷϧʔτೖྗ จࣈى͜͠΍ੜ੒"*ॲཧͷ଴͕ͪ࣌ؒ௕͍ !εςοϓ͝ͱʹ1JDPΧʔʹݱࡏͷεςʔλεΛૹ৴͠ɺԻ΍-&%Ͱ൓Ԡ จࣈى͜͠։࢝ 1JDP$POUSPMMFSαʔό TUBUVTΛߋ৽ ੜ੒"*ʹΑΔ

    ίϚϯυ΁ͷม׵։࢝ "audio_to_text_started" 1JDP$BSαʔό ϒβʔԻ௿Ί -&%఺໓ TUBUVTΛߋ৽ “text_to_command_started" ϒβʔԻߴΊ -&%ॱ൪ʹ఺౮ 1045TUBUVT 1045TUBUVT Ի੠ೖྗ։࢝ TUBUVTΛߋ৽ "recording_started" 1045TUBUVT ϒβʔԻͳ͠ -&%ബ͘఺౮ ίϚϯυੜ੒׬ྃ 1045DPNNBOE ίϚϯυΛॱʹ࣮ߦ Ωϟϯόε্ʹ ϧʔτΛඳ͍ͯೖྗ ʢHS*NBHF&EJUPSʣ 6* (SBEJPͰը૾ೖྗΛ؆୯ʹ࣮ݱ ը૾ˠίϚϯυม׵ -BOH$IBJOͰϓϩϯϓτͱҰॹʹ ը૾Λ0QFO"*ͷ"1*ʹૹ৴ ༩͑ΒΕͨը૾ʹϧʔτ͕ඳ͔Ε͍ͯ·͢ɻ S͕ελʔτ஍఺ͰɺG͕ΰʔϧ஍఺Ͱ͢ɻ ͜ͷϧʔτը૾ΛɺpicoΧʔ༻ͷJSONܗࣜͷಈ࡞ ίϚϯυ഑ྻʹม׵͍ͯͩ͘͠͞ɻ …ུ… ੜ੒͞ΕͨίϚϯυ ʢHS+40/ʣ 1JDPΧʔ͕ಈ͘ʂ σϞಈը গ͠ෳࡶʹͳΔͱؒҧ͏ͷͰ վળͷ༨஍͋Γ
  9. ·ͱΊɾײ૝ ͜ͷϙελʔࢿྉ͸ ͔͜͜Β΋ݟΕ·͢ εϙϯαʔϒʔεͰ͸ ͷϒʔε΋΍ͬͯΔΑ ༡ͼʹ͖ͯͶ (JU)VCσϞಈը΁ͷ ϦϯΫ΋͋Γ·͢ w --.Ͱɺࠓ·Ͱͩͱ೉͔ͬͨ͠ॲཧΛ؆୯ʹ࣮ݱͰ͖ΔΑ͏ʹ

    ͳͬͨ͜ͱΛ࣮ײͨ͠ ࣗવݴޠˠίϚϯυɺը૾ˠίϚϯυͷม׵ w (SBEJPͩͱɺԻ੠΍ը૾ೖྗΛ؆୯ʹѻ͑ͯศར w ੜ੒"*º1JDP͸ɺ·ͩ·ͩԠ༻͢Δͱָͦ͠͏ ྫ1JDPΧʔͷΞΫγϣϯΛ૿΍͢ɻͨͱ͑͹ɺ-&%ͷޫΓํͷύλʔϯΛ૿΍͢ɺ ԻͰײ৘Λද͢ɺαʔϘΛ͚ͭͯ৲ඌͷΑ͏ʹ༳Β͢ͳͲ w ϓϩϯϓτͰ1JDPΧʔͷੑ֨ΛΧελϚΠζ͢Δͱ໘നͦ͏ ྫ͹͔ʂͱݴΘΕͨ࣌ʹ൵͠ΉλΠϓ͔ɺౖΔλΠϓ͔ʢ-&%͕੨PS੺ʣ གྷͬͯΈͯʂͱݴΘΕͨ࣌ͷςϯγϣϯͷߴ͞ʢಈ͖ͷܹ͠͞ʣͷҧ͍ͳͲ w ੜ੒"*ͷར༻ํ๏ʹΑͬͯɺਫ਼౓ɾ଎౓ɾྉۚίετ͕Ͳ͏มΘΔ ͔Λɺ΋͏গ͠ൺֱɾݕ౼͍ͨ͠ ྫɿϞσϧͷҧ͍ɺϩʔΧϧ࣮ߦWT"1*ར༻ɺԻ੠Λͦͷ··౉͔͢ࣄલʹจࣈى ͜͢͠Δ͔ͳͲ w ॲཧ଴ͪ࣌ؒΛͲ͏͢Δ͔͸·ͩ՝୊ʜ ྫॲཧ࣌ؒࣗମΛ୹͘͢Δ͔ɺ଴ͪ࣌ؒͷ޻෉Λ͢Δ͔ w ϓϩάϥϜࣗମ͸͙͢࡞Ε͚ͨͲɺ1JDPͷѻ͍ʹ׳Εͯͳͯ͘खؒ औͬͨ ྫ1JDPͷࠩ͠ࠐΈ͕؁͍ͷ͔Ϟʔλʔ͕ಈ͔ͳ͍ɺंྠ͕͙͢֎ΕΔɺ8J'J͕ͳ͔ ͳ͔ܨ͕Βͳ͍ɺ଎౓ͷௐ੔ͳͲ ᶊ IUUQTTQFBLFSEFDLDPNLPNPGSQZDPOKQQPTUFS