やりたいこと
Contentful で記事を書く際に文章を考えるのが面倒なので、重要なポイントだけ箇条書きにして、あとは自動で文章を生成してほしいと思っています。
実現方法
Contentful の UI Extension を使って実現します。
UI Extensions では Contentful の画面をカスタムできるもので、サイドバーの機能やフィールドの機能を JavaScript ベースのコーディングで拡張できます。
今回は、以下のような仕様で UI Extensions を作ってみます。
- ChatGPT への命令内容を入力するフィールド (Field名: input)
- ChatGPT が生成した文章の内容を出力するフィールド (Field名: output)
- input に入力した後にボタンを押下し、API 経由で ChatGPT に文章を作成してもらう
- UI Extensions のタイプはフィールド機能を拡張する「Field extensions」を利用します
この記事ではこれから実装手順が長く続きます。実際に作ってみて有用だと感じたユースケースについては「最後に」の章に記載しているので、実装に興味がない方はそちらをご覧ください。
実装
では早速取り掛かっていきます。
1. UI Extensions の作成
まず UI Extensions を作成していきます。
1.1 プロジェクトの作成
Contentful の公式サイトにある手順でプロジェクトを作成します。
Createコマンドを叩き、今回は「Template」を元に作成しました。
% npx create-contentful-app contentful-with-chatgpt
Creating a Contentful app in ~/Developer/contentful-with-chatgpt.
? Do you want to start with a blank template or use one of our examples? (Use arrow keys)
❯ Template
Example
次に開発するフレームワークを選択します。
TypeScript と JavaScript 含め、一番下の Vue 以外はすべて React ベースです。Contentful は基本的に React ベースで作られているようなので、特段の理由がない限りは Vue 以外を選んだ方が良いと思います。今回は Contentful 公式の情報源が多そうな TypeScript のテンプレートを選択しました。
% npx create-contentful-app contentful-with-chatgpt
Creating a Contentful app in ~/Developer/contentful-with-chatgpt.
? Do you want to start with a blank template or use one of our examples? Template
? Pick a template
❯ TypeScript
JavaScript
Next.js
React + Vite
Vue
ここまで終えるとプロジェクトが作成され、 npm start
を実行するようにサジェストされます。もちろんまだ何も実装していないので実行して何か起こるわけではありませんが、とりあえず実行してみます。
% cd contentful-with-chatgpt
% npm start
問題なくローカルサーバ起動すればOKです。
1.2 OpenAI パッケージインストール
続いて、ChatGPT の API を呼び出すため、OpenAI のパッケージをインストールします。
手順は以下の公式ドキュメントにある通りです。
% npm install openai
added 2 packages, and audited 1568 packages in 2s
246 packages are looking for funding
run `npm fund` for details
6 high severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
特にエラーが発生しなければ OK です。
先に、この後 OpenAI の API 呼び出しで使うクライアントを作成する処理を実装しておきます。
import { Configuration, OpenAIApi } from "openai";
export const createClient = (param: {
organization: string;
apiKey: string;
}) => {
const configuration = new Configuration({
organization: param.organization,
apiKey: param.apiKey,
});
return new OpenAIApi(configuration);
};
1.3 UI Extension 本体の実装
冒頭にも書きましたが今回はフィールド機能を拡張する「Field extensions」というタイプの UI Extensions を利用するため、 src/locations/Field.tsx
にコードを書いていきます。
特筆すべき点を列挙しておきます。
- ボタン押下で
generateComment
メソッドが呼び出され、API 経由で ChatGPT にリクエストを送り、レスポンスの中から回答を output フィールドに出力させます。 - 以下の3点については parameters という仕組みで外部から値を挿入できるようにします。
- outputフィールドのID (parameters.instance.outputFiledId)
- OpenAIのOrganization (parameters.instance.openaiOrganization)
- OpenAIのAPI Key (parameters.instance.openaiApiKey)
- parameters には「installation parameters」と「instance parameters」の2種類がありますが、今回は実装が簡単な「instance parameters」を使います。
- スタイルの実装は Contentful 公式のコンポーネントライブラリ Forma 36 を利用します。
- Textarea コンポーネントは長文用のテキストボックスで、ユーザが高さを変えることができます。それに応じてフィールドを囲むエリアの大きさも自動調整して欲しいので AutoResizer を有効化しておきます。
今回のコードは以下のようになります。
import React, { useState } from "react";
import { Box, Text, Button, Textarea } from "@contentful/f36-components";
import { FieldExtensionSDK } from "@contentful/app-sdk";
import {
useAutoResizer,
useSDK,
useFieldValue,
} from "@contentful/react-apps-toolkit";
import { createClient } from "../lib/openai";
const Field = () => {
useAutoResizer();
const sdk = useSDK<FieldExtensionSDK>();
const OUTPUT_FILED_ID = sdk.parameters.instance.outputFiledId;
const openai = createClient({
organization: sdk.parameters.instance.openaiOrganization,
apiKey: sdk.parameters.instance.openaiApiKey,
});
const [inputText, setInputText] = useFieldValue<string>();
const [, setOutputText] = useFieldValue<string>(OUTPUT_FILED_ID);
const [isLoading, setIsLoading] = useState(false);
const generateComment = async () => {
if (!inputText) return;
setIsLoading(true);
try {
const response = await openai.createChatCompletion({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: inputText }],
});
setOutputText(response.data.choices[0].message?.content ?? "");
} catch (error) {
console.log(error);
}
setIsLoading(false);
};
return (
<>
<Textarea
defaultValue={inputText}
onChange={(e) => setInputText(e.target.value)}
/>
<Box marginBottom="spacingXs">
<Text fontColor={"gray600"} fontWeight={"fontWeightMedium"}>
{`ChatGPTへのインプットを入力してボタンを押下してください`}
</Text>
</Box>
<Box>
<Button
variant="secondary"
isLoading={isLoading}
isDisabled={!inputText || !!isLoading}
onClick={generateComment}
>
Generate
</Button>
</Box>
</>
);
};
export default Field;
2. ローカル環境 UI Extensions のインストールと設定
ここまでで UI Extensions の実装は完了したので、実際に Contentful にインストールして、起動したローカルサーバと接続してテストできる状態にします。
2.1 Create app
Contentful にログインし、 Organization Settings > Apps > Create app
と進みます。
まず、Name と Frontend を設定します。まだローカルサーバと接続してテストする段階なので Frontend には localhost
を入力します。ポート番号は .env
で設定した内容と合わせてください。デフォルトは3000のはずです。
次に、Locations を設定します。今回は Field Extensions を作成しているので、「Entry Field」を選びます。また、箇条書きで文を入力する想定なので「Long text」を選択します。
続いて「instance parameters」を設定します。デフォルト値には適切な値を設定してください。
2.2 Install app
ここまで終わえると、Organization Settings ではなく Space の画面に遷移し Apps を開き、先ほど作成した UI Extensions をこの Space へインストールします。
2.3 Content Model の設定
続いて、Content Model から該当のモデルを開き、「Add field」ボタンを押下して、output フィールドと input フィールドを追加します。
両方とも Text タイプを選択します。
両方とも Long text タイプを選択します。
output フィールドの Appearance は Multiple line で問題ありませんが、 input フィールドの Appearance は、作成した UI Extensions を指定します。Instalation parametes の値がデフォルト値のままだとまずい場合はここで変更します。
以下のようになりました。Save を押下して実際に試してみます。
3. テスト
Content を開き、「Add Entry」を押下します。
開いた画面で input フィールドに ChatGPT への依頼事項を記載し、「Generate」を押下すると...、数秒経ってから output フィールドに ChatGPT からの返答が表示されます!!
4. 本番インストール
全て問題なさそうであれば、公式サイト手順で deploy & hosting します。
最後に
今回は Contentful の UI Extension に ChatGPT を組み込み、記事を作成させてみました。
この記事ではお試しで作成したので、単純に ChatGPT への input と output を項目として用意するだけになりましたが、実際にコンテンツ運用されている方は、他に記事のタイトルやタグなど設定が必須な項目がたくさんあると思うので、それらを元に ChatGPT への入力文字列を組み立てるようなプログラムを構築すれば、よりコンテンツ作成者の最小限の労力で同様の結果を得られるようになると思います。
ただ、ブログ記事全体を出力するのは「入力を書くぐらいなら自分で書いた方が早い!」という意見もあると思うので、以下のようなユースケースが適していると思います。
- ブログではないコンテンツの中でちょこっと文章が必要な部分(ECサイトの商品紹介や、商品紹介サイトのコメントなど?)
- ネイティブ言語でない言語でコンテンツ作成が必要な場合
特に、後者に関しては、英語の文章が必要な際に「○○の文章を英語で書いて」と ChatGPT にお願いすると、翻訳ツールを使うよりもナチュラルな英語を作ってくれます。こちらは日本語で要点を書いているだけなでナチュラルな英語が出力されるので、ものすごい省力化につながります。
今回作成した UI Extensions の実際のコードは、GitHubで公開しています。
興味がある方はぜひ利用してみてください。