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

【20220803_toranoana.deno#13】denoとChatGPTでコード変換機を作る

 【20220803_toranoana.deno#13】denoとChatGPTでコード変換機を作る

toranoana.deno#13での発表資料です。
https://yumenosora.connpass.com/event/289328/

虎の穴ラボ株式会社

August 03, 2023
Tweet

More Decks by 虎の穴ラボ株式会社

Other Decks in Technology

Transcript

  1. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoとChatGPTでコード変換器を作る


    虎の穴ラボ 藤原 佳顕

    1

    View full-size slide

  2. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    アジェンダ

    ● 概要

    ● ChatGPTでのコード変換について

    ● denoでの実装の単純な例

    ● denoでChatGPT使ってコード変換する

    2

    View full-size slide

  3. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    自己紹介

    3
    ● 名前

    ○ 藤原佳顕

    ● 仕事

    ○ FantiaとかCreatiaとか社内アプリとか

    ● 好み

    ○ Clojure、Rust

    ● 趣味

    ○ 格闘ゲーム

    ■ Melty Blood、SF6

    ○ STG(ダライアスとか)も好き


    View full-size slide

  4. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    ChatGPTでのコード変換について

    4
    ● ChatGPTにおまかせするとかなりの精度でライブラリ等を変換できる

    ○ 実践例

    ■ https://toranoana-lab.hatenablog.com/entry/2023/07/14/100000

    ● 通常のUIでやるには以下のような問題がある

    ○ 大量のファイルがある場合一個一個質問投げてコピペしないといけない

    ○ 上記の様にCSSを外出しする場合労力も二倍になる

    ○ ChatGPTのAPI使えば生成部分は簡単にできそう

    ■ 手直し等はまた別途必要


    View full-size slide

  5. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    ChatGPTでのコード変換について

    5
    ● ChatGPTのAPI

    ○ https://platform.openai.com/docs/guides/gpt/chat-completions-api

    ○ Chat Completions APIと呼ばれるもの

    ○ プラスで、Function callingを利用

    ■ 問い合わせ時にコールバックする予定の関数と引数を与えることで、レス
    ポンスとしてその関数に入れられる値を返してくれる


    View full-size slide

  6. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでの実装の単純な例


    6
    ● まずは単純な問い合わせ 

    const prompt = {
    "model": "gpt-3.5-turbo-16k",
    "messages": [{"role": "user", "content": "What's the weather like in Boston?"}],
    "functions": [
    {
    "name": "get_current_weather",
    "description": "Get the current weather in a given location",
    "parameters": {
    "type": "object",
    "properties": {
    "location": {"type": "string", "description": "The city and state, e.g. San Francisco, CA",},
    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
    },
    "required": ["location"],
    }
    },
    ]
    };

    View full-size slide

  7. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでの実装の単純な例


    7
    ● コールバックのget_current_weather関数を用意 

    ● 引数等は問い合わせ時のfunctionsにあわせる形で 

    interface OutputParams {
    location: string;
    unit?: "celsius" | "fahrenheit";
    }
    function get_current_weather(params: OutputParams){
    console.log(params);
    }

    View full-size slide

  8. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでの実装の単純な例


    8
    ● 実際の呼び出し

    ● 細かいチェックは無し。Chat Completions API呼び出し→コールバック呼び出し 

    async function call() {
    const res = await fetch(ENDPOINT_URL, {
    method: "POST",
    headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${OPENAI_API_KEY}`,
    "OpenAI-Organization": OPENAI_ORGANIZATION
    },
    body: JSON.stringify(prompt)
    });
    const json = await res.json()
    get_current_weather(json.choices[0].message.function_call.arguments)
    }

    View full-size slide

  9. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでの実装の単純な例


    9
    ● 左:結果、右:APIからのレスポンス

    {
    "location": "Boston, MA"
    }
    {
    id: "*******",
    object: "chat.completion",
    created: 1690528622,
    model: "gpt-3.5-turbo-16k-0613",
    choices: [
    {
    index: 0,
    message: {
    role: "assistant",
    content: null,
    function_call: {
    name: "get_current_weather",
    arguments: '{\n "location": "Boston, MA"\n}'
    }
    },
    finish_reason: "function_call"
    }
    ],
    usage: { prompt_tokens: 82, completion_tokens: 18, total_tokens: 100 }
    }

    View full-size slide

  10. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでChatGPT使ってコード変換する


    10
    ● 処理の流れ

    ○ 対象ディレクトリを再帰的にチェック

    ○ .vueファイルの場合中身をテキストで読み取り

    ○ Chat Completions APIアクセス

    ○ 関数呼び出ししてt(j)sxとcssをファイル保存(function_call)

    ● パーミッションはread,write,netが必要になる想定

    ● 今回は一旦は汎用性などは考えずVue→Reactのみ考える

    View full-size slide

  11. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでChatGPT使ってコード変換する


    11
    ● 対象ディレクトリチェックとファイル読み取り

    async function readFile(path: string) {
    const text = await Deno.readTextFile(path);
    return text;
    }
    async function exec(baseDir: string, targetExt: string) {
    const pattern = new RegExp(`.${targetExt}$`);
    for await (const dirEntry of Deno.readDir(baseDir)) {
    if (dirEntry.isDirectory) {
    await exec(`${baseDir}/${dirEntry.name}`, targetExt);
    } else if (dirEntry.isFile) {
    const filePath = `${baseDir}/${dirEntry.name}`;
    if (!pattern.test(filePath)) {
    continue;
    }
    const text = await readFile(filePath);
    await transform(filePath, text);
    }
    }
    }
    ifが再帰部分、else ifは実ファイルに対する処理


    View full-size slide

  12. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでChatGPT使ってコード変換する


    12
    ● Chat Completions APIアクセス→ほぼ変わらないが一旦json返すだけ(function_callは別でやる)

    async function call(req: ChatGPTInput): Promise {
    const res = await fetch(ENDPOINT_URL, {
    method: "POST",
    headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${OPENAI_API_KEY}`,
    "OpenAI-Organization": OPENAI_ORGANIZATION
    },
    body: JSON.stringify(req)
    });
    const json = await res.json() as ChatGPTOutput;
    // TODO: トークンが最大になると
    finish_reasonがlengthで返ってくるので再帰するなどしたいが、
    function_callの場合一旦保留
    // const isContinue = json.choices[0].finish_reason === 'length'
    return json;
    }

    View full-size slide

  13. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでChatGPT使ってコード変換する


    13
    ● Chat Completions APIアクセス時のオブジェクト

    {
    "max_tokens": 10000,
    "model": "gpt-3.5-turbo-16k",
    "messages": [
    {"role": "user", "content": buildVue2ReactPrompt(filename, code)}
    ],
    "functions": [
    {
    "name": "outputReact",
    "description": "Reactのソースをファイルに書き出す関数 ",
    "parameters": {
    "type": "object",
    "properties": {
    "codeFilename": {
    "type": "string",
    "description": "保存先ファイル名。元のファイル名と同じにすること "
    },
    "code": {
    "type": "string",
    "description": "Reactソースコード文字列 "
    },
    "styleFilename": {
    "type": "string",
    "description": "CSS(SCSS)シートの保存先ファイル名。元のファイル名と同じにするこ
    と"
    },
    "style": {
    "type": "string",
    "description": "CSS(SCSS)のソースコードの文字列 "
    }
    },
    "required": ["codeFilename", "code", "styleFilename", "style"]
    }
    }
    ]};

    View full-size slide

  14. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでChatGPT使ってコード変換する


    14
    ● プロンプト(基本ブログの内容と同様)

    function buildVue2ReactPrompt(filename: string, code: string): string {
    const prompt = `
    以下Vue3で書かれたプログラムです。React HooksとTypeScriptを利用してReactに書き換えてください。条件は以下です。
    ・ファイル名は${filename}.tsx
    ・コンポーネント名は${filename}とすること
    ・scoped cssは${filename}.module.scssとして別ファイルにし、それを${filename}.tsxに適用すること
    ${code}
    `;
    return prompt;
    }

    View full-size slide

  15. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでChatGPT使ってコード変換する


    15
    ● 保存関数とまとめたもの

    async function outputReact(info: OutputReact) {
     await Deno.writeFile(info.codeFilename, new TextEncoder().encode(info.code));
     await Deno.writeFile(info.styleFilename, new TextEncoder().encode(info.style));
    }
    async function transform(filename: string, target: string) {
    const req = buildVue2ReactFunctionCallRequest(filename, target);
    const res = await call(req);
    const func = res.choices[0].message.function_call;
    const realFunc = outputFunctions[func.name];
    realFunc(JSON.parse(func.arguments.replace(/\n/g, "")));
    }
    interface OutputReact {
    codeFilename: string;
    code: string;
    styleFilename: string;
    style: string;
    }
    const outputFunctions: {[key: string]: (args: any) => void} = {
    outputReact,
    }

    View full-size slide

  16. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    denoでChatGPT使ってコード変換する


    16
    ● 出来上がったもの

    ● ファイルが大きいので実際のものを見せる

    View full-size slide

  17. Copyright (C) 2021 Toranoana Inc. All Rights Reserved.
    まとめ

    ● 生成後のコードがちょっとバグってる時がある点は注意

    ○ 結局手で直せる分の知識が必要

    ● denoだとTypeScriptやJavaScriptのAPIがそのまま動くのでJSONレスポンス扱うのにかな
    り便利な印象

    ● パーミッションもしっかりしていできるので変なファイルを送ってしまったり、変なフォルダに
    書き出してしまったりなどを制御できそう

    ● 最終的にワンバイナリにできるようにすれば通常のリプレイス案件などにも活用できそう

    17

    View full-size slide