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. アジェンダ
 •

    概要
 • ChatGPTでのコード変換について
 • denoでの実装の単純な例
 • denoでChatGPT使ってコード変換する
 2
  2. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. 自己紹介
 3

    • 名前
 ◦ 藤原佳顕
 • 仕事
 ◦ FantiaとかCreatiaとか社内アプリとか
 • 好み
 ◦ Clojure、Rust
 • 趣味
 ◦ 格闘ゲーム
 ▪ Melty Blood、SF6
 ◦ STG(ダライアスとか)も好き

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

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

  5. 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"], } }, ] };
  6. 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); }
  7. 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) }
  8. 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 } }
  9. 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のみ考える 

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

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


    12 • Chat Completions APIアクセス→ほぼ変わらないが一旦json返すだけ(function_callは別でやる)
 async function call(req: ChatGPTInput): Promise<ChatGPTOutput> { 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; }
  12. 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"] } } ]};
  13. 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; }
  14. 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, }
  15. Copyright (C) 2021 Toranoana Inc. All Rights Reserved. denoでChatGPT使ってコード変換する
 


    16 • 出来上がったもの
 • ファイルが大きいので実際のものを見せる 

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

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