🐙

GitHub Copilotを独自に拡張し翻訳ツールにした

2024/10/06に公開

VSCode拡張機能「Translate Agent」をリリース

  • どういったもの? ... @translator を呼び出すことでCopilot Chat上で翻訳を簡単に行える
  • 何をしている? ... システムプロンプトを変更しているだけです。
  • インストール手順 ... VSCode Marketplaceからダウンロードします。

https://marketplace.visualstudio.com/items?itemName=HikaruEgashira.vscode-translate-agent

https://github.com/HikaruEgashira/translator-extension

<img src="https://github.com/HikaruEgashira/translator-extension/raw/HEAD/screenshot.png" alt="screenshot" width="300" />

Translate Agentを支える技術

Language Model API

この拡張機能は VSCode v1.91 より安定版となったLanguage Model APIを利用しています。これによりGitHub Copilotやその他Copilot Modelに拡張機能からアクセスできるようになります。

https://code.visualstudio.com/api/extension-guides/language-model

@vscode/prompt-tsx

拡張機能を作成するにあたって @vscode/prompt-tsx というライブラリを利用しました。これにより比較的直感的にプロンプトを構築できます。

https://www.npmjs.com/package/@vscode/prompt-tsx
https://code.visualstudio.com/api/extension-guides/language-model

未リリースですが、wikipedia apiの検索結果を利用するwiki-participantという拡張機能をフォークをベースに改良してみる過程でこのライブラリを理解しました。今回の拡張機能と以下のリポジトリを参考に皆さんもお好きなCopilot拡張機能を作成してみてください。

https://github.com/HikaruEgashira/wikipedia-participant

どんな感じで書くのか概要

prompt.tsxの中身です。もしも検索結果などのコンテキストを追加する場合はPromptPropsに追加しプロンプトを構築します。

import {
  ...
} from "@vscode/prompt-tsx";

export interface PromptProps extends BasePromptElementProps {
  userQuery: string;
}

export class TranslatePrompt extends PromptElement<PromptProps, void> {
  render(_state: undefined, _sizing: PromptSizing) {
    return (
      <>
        <AssistantMessage>
          You are a translator.
          If given English text, translate in Japanese.
          Else if given text in any other language, translate in English.
          Output only the result.
        </AssistantMessage>
        <UserMessage>{this.props.userQuery}</UserMessage>
      </>
    );
  }
}

実際に利用するchathandler.tsの部分です。
selectChatModelsで好きなモデル(phi-3など)を利用できるほか、ローディング中やエラーのメッセージなどのUIはここで制御します。

...
const MODEL_SELECTOR: vscode.LanguageModelChatSelector = {
  vendor: "copilot",
  family: "gpt-4o",
};

export const chatHandler: vscode.ChatRequestHandler = async (request, _context, stream, token) => {
  try {
    const [model] = await vscode.lm.selectChatModels(MODEL_SELECTOR);
    if (model) {
      // このあたりでコンテキストを追加したりする拡張が考えられる(wikipedia-participant参考)

      const { messages } = await renderPrompt(
        TranslatePrompt,
        { userQuery: request.prompt },
        { modelMaxPromptTokens: model.maxInputTokens },
        model,
      );

      const chatResponse = await model.sendRequest(messages, {}, token);

      for await (const fragment of chatResponse.text) {
        stream.markdown(fragment);  // Chat UIに表示する部分
      }
    }
  } catch (err) {
    handleChatError(err, stream);
  }

  return { metadata: { command: "" } };
};

参考資料

まずはここ
https://code.visualstudio.com/api/extension-guides/chat

テンプレートなど
https://github.com/copilot-extensions

Discussion