Category Archives: 技術

created’自己複製プログラム × 腕立て伏せ回数計測’

本記事は以下 Advent Calendarの12日目の記事です。
🎄GMOペパボエンジニア Advent Calendar 2023
#意識低いトレーニング部 Advent Calendar
※GMOペパボの社内Slackには #意識低いトレーニング部 というチャンネルがあります。


技術寄りの話・筋トレの話を混ぜて何か書きたいなと思い、無理やりテーマを設定しました。

自己複製プログラム × 腕立て伏せ回数計測

経緯
上の画像は今年5月時点と10月時点の体成分分析です。

今年からジムに通い始めて約半年が経過しました。しかし、画像からわかる通り、誤差範囲でしか変化していません。
多い時には週に1回ジムに行くという圧倒的意識(の低さ)なのですが、ここまで変化がないと悲しくなります。
In hindsight (振り返ってみると), 日々のモチベーション・数値目標がない状態だったのがまずかったのかもしれません。#意識低いトレーニング部 Advent Calendarでも数値目標が大切だと言ってました。
しかし、いつも使っている筋トレアプリには、過去最高記録を確認する機能がなく少し不便。そこで、過去の最高記録を追跡できるシステムを作ってみることにしました。

作ったもの


説明
この謎ファイルは、実行するたびに自分自身をコピーして、新しい目標の腕立て伏せ回数が書かれたファイルを生成します。ファイル名には腕立て伏せの回数が記載されており、作成日時を見ることで、いつ記録を更新したかが分かるようになっています。

使用方法
ファイルをダブルクリックすると、次の目標が書かれたファイルが生成されます。
目標をクリアしたらもう一度ボタンを押下しましょう。

実装の詳細
自宅のPC(windows)で簡単に実行できるようにbatファイルで作成しました。
コメントを見ていただければ何をしているかが分かると思います。

@echo off
setlocal EnableDelayedExpansion
:: ファイル名を取得
set "original_file_name=%~n0"
:: ファイル名を「:」で分割
set "prefix="
set "count=0"
for /f "tokens=1* delims=:" %%a in ("!original_file_name!") do (
    set "prefix=%%a"
    set /a "count=%%b"
)
:: 回数を増やす
set /a "new_count=count + 5"
:: 新しいファイル名を生成(元のテキスト部分を保持)
set "new_file_name=!prefix!:%new_count%"
:: ファイルをコピーして新しいファイルを作成
copy "%~f0" "!new_file_name!.bat"
endlocal

まとめ
このファイルを活用して、2024年は60kg&体脂肪率13%を目標に増量していく所存です。
おいしいご飯情報in福岡 をお待ちしております。


おまけ
このプログラムは、自身を出力するプログラム「Quine」と似たコンセプトを持っています。Quineの紹介およびRubyでの実装例もついでに紹介します。

Quineとは、以下の条件を満たすプログラムを指します。
要は、コードと出力が同じになるようにコーディングをするパズルです。

  • 文字列を出力するプログラムである
  • 出力される文字列がそのプログラム自身を表す文字列と同一である

Rubyでの実装例

eval s="puts'eval s='+s.inspect"

解説

  1. s="puts'eval s='+s.inspect"
    変数sに文字列が代入される
  2. eval s
    変数sの中身をRubyのコードとして評価(実行)します
    sに代入された文字列がプログラムとして機能します

read’世界一流エンジニア思考法’

メモを書き起こします

効率よく成果を出すには
・時間・行うタスクを絞ることで最大のパフォーマンスを出すように。
 やらないことを見つけることで、より価値の高い行動に集中することができる。(= lazy)
・1日4時間は自分用の時間として予定をブロックしておく。
 「(会議等で)集中してプログラミングできない」ということを避けるため。
・自分にその分野のメンタルモデルやコンテキストがなければ、すぐに詳しい人に聞いた方が良い場合が多い
・回答者に大きな工数がかかるような質問であれば、自分で調べた方が良いが、そうでない場合、聞いた方が効率が良い。どんな質問であれば早急に回答ができるかを事前に聞いてみるのも手。
・自分が知らない時ほどリプロする(リプロってなに)

記憶術
コーネルメソッドを活用する
・会議に対する記憶媒体を”頭の中だけ”にするには、「後で人に説明する前提で理解する」
 理解するために、ビジュアルのイメージやメンタルモデルを(頭で)作りながら聞く


よいコンディションで働く
・テストステロンが高まると、抑うつ・イライラ・不眠のような更年期特有の症状から解放されやすい。筋トレをする・肉や玉ねぎを食べるといった改善や、テストステロンブースターのようなサプリを摂るのも良い。

created’eval_generate_and_run’

はじめに

最近Rubyを入門しています。
Rubyの特徴として挙げられる”メタプログラミング”を活かしたアプリを作成しました。

Kernel#evalとは

Rubyのevalメソッドは、文字列として与えられたRubyコードを実行するために使用されます。これは、PythonのexecやJavaScriptのevalなど、他の言語における同様の機能に類似しています。

基本的な使い方

code = "1 + 2"
result = eval(code)
puts result # 出力: 3

上記の例では、code変数に格納された文字列がRubyの式として評価され、その結果がresult変数に代入されます。

つくったもの

Github

無題の動画 ‐ Clipchampで作成

解説

GPTへのリクエスト内容

  • 使用する候補のAPI等
    • 使い方(リクエスト・レスポンスパラメータ一覧)
  • 解決してほしい課題(ユーザー入力内容)
  • evalコードに関する指定
    • 出力形式の指定(e.g. “標準出力で会話形式”)

GPTからのレスポンス内容

  • Kernel#evalメソッドに引数として渡せる状態のRubyコード
  • evalの実行に足りない情報(未実装)

その後

GPTからのレスポンスであるRubyコードをeval(response_content["eval_code"])とすれば完成。

今後の展望

アップデートごとにGPTの扱えるトークン数が増えています。候補のAPIを数多く渡すことで、より多様なリクエストに対応できるようになります。
例えばLineAPIを渡してみたり、slackのAPIを渡してみたり。。。

created’ShelfSheriff’

こちらの記事を参考に、OpenAIのVisonを使用して、画像データの解析結果をJSON形式で返却してもらいました。

実際に作ったもの

https://shelf-sheriff.vercel.app

Github

本棚の内容から、いくつかの診断+オススメのジャンルを提案してくれるWebアプリです。
アドベンチャーゲーム風に進行します。

概要(API周りに着目)

クライアント側React画像データを読み取り&Base64エンコード
サーバー側PythonデータURLの形式でOpenAIのAPIにBase64画像データを渡す

実装時に気をつけた点

  • Base64エンコード
    公式マニュアルにも書かれていますが、ローカルデータをVisonのモデルに渡すにはBase64でエンコードを行います。インターネットに転がっている画像を参照したい場合以外は、この方法になるということです。
  • MAXトークン数
    無尽蔵にトークンを使用されると、金銭面で嬉しくないのでトークン数を絞ります。
    しかし、JSONの特性上、途中でデータが切れてしまうとデコードできないので、プロンプトで”○文字以内”と調整すると良いです。
  • 画像形式
    .png, .jpeg, .jpg, .webp, .gifがサポート対象です。(公式)
  • 画像サイズ
    1画像あたり20MBまでの制限があります。(公式)

あとは、実際にAPIを叩くと親切なエラー文が返ってくるので、適宜対応できるかと思います。

クライアント側のコード一部

  //ファイルアップロード処理
  const handleFileUpload = async (event) => {
    const file = event.target.files[0];
    if (file) {
      setIsUploading(true);
      try {
        const base64 = await toBase64(file);
        const apiEndpoint = process.env.REACT_APP_API_ENDPOINT;

        const response = await axios.post(apiEndpoint, { image: base64 });
        onComplete(response.data);
      } catch (error) {
        console.error("File upload failed:", error);
      } finally {
        setIsUploading(false);
      }
    }
  };

  // エンコード処理:画像ファイル->Base64データ
  const toBase64 = (file) => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result.split(',')[1]);
    reader.onerror = error => reject(error);
  });
サーバー側のコード全文
from decimal import Decimal
import json, os, openai
  
def decimal_to_int(obj):
    if isinstance(obj, Decimal):
        return int(obj)
  
def lambda_handler(event, context):
    openai.api_key = os.environ['API_Key']
    base64_string = event["image"]
  
    print(base64_string)
    response = openai.ChatCompletion.create(
        model="gpt-4-vision-preview",
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": "あなたはユーモアのあるプロファイリングを行うプロです。口調は口数の少ないミステリアスな探偵。この本棚の持ち主に対して以下内容を推測してください。-character:性格(ユーモアのある表現と根拠)(hint...少ない本こそ関心が深い可能性もあります) - interesting:興味のある分野と根拠 -recommend:これから興味を持つことをお勧めする意外な分野と根拠。character,interesting,recommendという3つのkeyに対してそれぞれ70字以上100字以下のvalueを紐づけたJSONデータを返却してください。jsonファイル出力結果はstart,endで終わるようにしてください。"},
                    {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_string}",}},
                ],
            }
        ],
        max_tokens=500,
    )
    response_content = response["choices"][0]["message"]["content"]
    response_content = response_content[5:-3] #文頭にあるstart,文末にあるendの文字を削除
    response_content = json.loads(response_content)
    print("Received response:" + json.dumps(response, default=decimal_to_int, ensure_ascii=False))
    return response_content

Amazon CodeWhispererを使ってみました

GitHub Copilotはお金がかかるので、個人利用無料&VSCode対応のAmazon CodeWhispererを使ってみました。

慣れると、コーディング速度や集中力を削減できるらしいが、初めて使った感覚としては、コーディング中に突然複数行の処理が姿を現すので驚いて集中が切れます。調理中のまな板に突然合わせ調味料を置かれた感覚です。(え? あぁこれ次のやつ?ありがとう…)

過集中にならないのは、冷静にコーディング出来るし良い面なのだろう…

Google Cloud Skills Boostの生成系AIを試した

Google Cloud Skills BoostGenerative AI learning pathが出たと聞いたので、やってみました。動画・ドキュメント・テストの構成で生成系AIについて学べます。

コースごとに以下のようなバッヂがもらえます。生成系AIは現時点で11コースあるみたいです。

他のコース(抜粋)

  • Encoder-Decoder Architecture
  • Attention Mechanism
  • Transformer Models and BERT Model

使い方だけでなく仕組みの部分も解説されているので、全部通して学習すれば大半の人間より生成系AIわかるマンになりそう。私はGoogle Cloud Skills Boostの存在自体初めて知ったので、今後英語, 技術の勉強に活用したいな

rinnaの対話GPT言語モデルをGoogle Colabで触ってみた

Google Colab(PRO)でrinna/Japanese GPT-NeoX  (Hugging face)を使ってみました。

推論 on Google Colab

Python3にて以下を順次実行します。

#機械学習ライブラリ
!pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

#Hugging Faceのモデルをしようするため
!pip install transformers sentencepiece
import time
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

# トークナイザーとモデルを取得
tokenizer = AutoTokenizer.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft", use_fast=False)
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-neox-3.6b-instruction-sft").to("cpu")
--colabでは ここで分割--
# 質問
question = "初夏の季語を5つ教えて"

prompt = f"ユーザー: {question}<NL>システム: "

token_ids = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt")

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        do_sample=True,
        max_new_tokens=128,
        temperature=0.7,
        repetition_penalty=1.1,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id
    )
output = tokenizer.decode(output_ids.tolist()[0][token_ids.size(1):])
output = output.replace("<NL>", "\n")

print(output)

output:

初夏とは、6月から7月初めまでの数ヶ月間です。この時期に俳句や歌、詩などの詩的な作品でよく使われる季語には、「梅雨」、「立葵」、「紫陽花」、「夏至」、「半夏生」があります。

質問を投げてから回答までに20~30秒程度かかります。

パラメータ比較

rinnaのパラメータはGPT2の2倍強

モデルパラメータ数 [個]
rinna/Japanese GPT-NeoX 36憶
GPT215億
GPT31750億
GPT4非公開

vsGPT3

GPT3とrinnaではどちらが日本語に優れているのでしょうか。

Language Models are Few-Shot Learnersでは、Common Crawl(大規模Webクロールテキスト)の重みが60%です。また、論文のsubmit時点である2020年のインターネット上での日本語の割合は2.2%(参考)です。

上記論文(Language Models are Few-Shot Learners)より.Datasets used to train GPT-3

これらを単純に乗算すると「410B(billion) * 0.6 * 0.022 = 5.412B」となり、rinnaの3.6Bよりも大きいです。したがって、GPT3の方が優れていると言えるのではないでしょうか。GPT3時点でこの差が付いているので、GPT4ではもっと大きな差が付いているんじゃないかなあと思います。

おわり

比較しておいてアレですが、rinnaはトークンが少ないので少々良いPCであればローカル環境で実行できる点がすごいです。(小並感)

Open AIのAPIとは異なり、プロンプトを外部へ渡しているわけではないので、このモデルを独自にファインチューニングすれば、機密情報もある程度学習させれて便利になるのかなあ…

watched ‘WWDC 2023 keynote’

初めて開発者会議をリアルタイムで見ました。

今までのWWDCやGoogleIO2023, Microsoft Build2023は、後日まとめ記事で見たり、podcast(rebuild.fm)で聞いたりするくらいでした。今回は、昨今のLLMブームに関してAppleが何か発表するかな~という気持ちと、AppleのAR/VRヘッドギアに関する発表をいち早く聞きたかったという思いがあり、リアルタイムで見ました。

LLMに関連するのはキーボードのautocorrect,音声入力でGPTとおなじtransformerモデルを使用しているくらいかな。というところ。AR/VRについては約50万円($3,499)のヘッドギアが発売されたこと。いろいろ技術を盛り込んでいるからか、高すぎて私には買えない;;

Apple Vision “Pro”という名前だし、廉価verが発売されるような気がします。家にVR機器がないので、少し無理してでも体験してみたい。。。。

また、WWDCの前にExtended TokyoというWWDCをもっと楽しむためのイベントにClusterで参加していました。次回のWWDCはオフラインでワイワイ見たい。。