Slide 1

Slide 1 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. denoとChatGPTでコード変換器を作る
 
 虎の穴ラボ 藤原 佳顕
 1

Slide 2

Slide 2 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. アジェンダ
 ● 概要
 ● ChatGPTでのコード変換について
 ● denoでの実装の単純な例
 ● denoでChatGPT使ってコード変換する
 2

Slide 3

Slide 3 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 自己紹介
 3 ● 名前
 ○ 藤原佳顕
 ● 仕事
 ○ FantiaとかCreatiaとか社内アプリとか
 ● 好み
 ○ Clojure、Rust
 ● 趣味
 ○ 格闘ゲーム
 ■ Melty Blood、SF6
 ○ STG(ダライアスとか)も好き


Slide 4

Slide 4 text

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使えば生成部分は簡単にできそう
 ■ 手直し等はまた別途必要


Slide 5

Slide 5 text

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


Slide 6

Slide 6 text

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"], } }, ] };

Slide 7

Slide 7 text

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); }

Slide 8

Slide 8 text

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) }

Slide 9

Slide 9 text

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 } }

Slide 10

Slide 10 text

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のみ考える 


Slide 11

Slide 11 text

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は実ファイルに対する処理


Slide 12

Slide 12 text

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; }

Slide 13

Slide 13 text

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"] } } ]};

Slide 14

Slide 14 text

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; }

Slide 15

Slide 15 text

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, }

Slide 16

Slide 16 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. denoでChatGPT使ってコード変換する
 
 16 ● 出来上がったもの
 ● ファイルが大きいので実際のものを見せる 


Slide 17

Slide 17 text

Copyright (C) 2021 Toranoana Inc. All Rights Reserved. まとめ
 ● 生成後のコードがちょっとバグってる時がある点は注意 
 ○ 結局手で直せる分の知識が必要 
 ● denoだとTypeScriptやJavaScriptのAPIがそのまま動くのでJSONレスポンス扱うのにかな り便利な印象
 ● パーミッションもしっかりしていできるので変なファイルを送ってしまったり、変なフォルダに 書き出してしまったりなどを制御できそう 
 ● 最終的にワンバイナリにできるようにすれば通常のリプレイス案件などにも活用できそう 
 17