OpenAI APIとWordPressを連携させた自動投稿プロジェクト: 実践ガイドとコード解説


OpenAIのAPIを使ってAI生成のHTMLをWordPressに自動投稿する趣味プロジェクトを始めました。
様々な方法があるかと思いますので大きな枠組みやキーとなったプロンプトなど重要な部分を絞っての紹介となりますが、何か参考になれば幸いです。

成果物 : <a href="https://ai.next-text.info" target="blank">ai.next-text.info</a>

<hr />

## プロジェクトの特徴
- パーソナリティが異なる複数のWP投稿者を用意
- 投稿者毎に担当するカテゴリーを予め用意
- node-cronを使って自動生成した記事を自動投稿

### node-cronでの自動化
```typescript
import authors from "./authors/authors"
import * as cron from 'node-cron'

let authorIndex = 0
cron.schedule('* */5 * * *', async () => {
    const author = authors[authorIndex]
    
    //authorをローテーション
    authorIndex = (authorIndex + 1) % authors.length 
    try{
        await autoPost(author)
    } catch(err : any){
        console.log(err)
    }
})
```

### 参考の投稿者 (ikuraとtarao)
```typescript
const ikura = {
      username: "ikura",
      email: "ikura@namino",
      password: "asdfa"
      personality: "フロントエンドデベロッパーのZ世代女子",
      categories: ["UXデザイン", "モバイルマーケティング"]
}
const tarao = {
    username: "tarao",
    email: "tarao@isono",
    password: "fasdfas"
    personality: "日本語勉強中の挙動不審なZ世代のマーケティングスペシャリスト",
    categories: ["SNSマーケティング", "バイラルマーケティング"]
}
```
※ username, email, passwordはは投稿の際に必要なプロパティです

<hr />

## 自動投稿の流れ(autoPost)
概要としては、自動投稿プログラムからOpen AIのAPIに必要なコンテンツをひとつずつ生成してもらい最終的にWordPressのREST APIを使って投稿するといった流れになっています。
```mermaid
sequenceDiagram
participant server as 自動投稿プログラム
participant gpt as GPT (OpenAI API)
participant dalle as 画像生成(OpenAI API)
participant wp as WordPress

server->>gpt: 1. HTML生成のプロンプトをPOST
gpt->>server: HTML
server->>gpt: 2. 返ってきたHTMLからタイトルと抜粋の生成、カテゴリー選択をするプロンプトをPOST
gpt->>server: タイトル、抜粋、カテゴリー
server->>gpt: 3. 抜粋を元にした画像生成テキスト生成のプロンプトをPOST
gpt->>server: 画像生成テキスト
server->>dalle: 4. 画像生成テキストをポスト
dalle->>server: 画像
server->>wp: 5.HTML、タイトル、抜粋、カテゴリー、画像を使って記事を投稿
```

<hr />

## キーとなるプロンプト
プロンプトエンジニアリングのテクニックを活用しています。
参考までに、以下のプロンプトで使っている手法は<a href="https://bux-web.com/posts/315" target="blank">こちらの記事</a>で紹介しています。

### 1. html生成のプロンプト

投稿者特有のパーソナリティとカテゴリーを使ったプロンプトを<a href="https://platform.openai.com/docs/guides/gpt/chat-completions-api" target="blank">Chat Completion API</a>に渡しています。<br />※成果物の投稿を見ていただくと一部HTMLの出力に失敗している事が確認出来るため改善が必要です

```typescript
makeMessagesForHtmlPrompt(author){
    const category = pickCategory(author.categories)
    return [
        {
            "role":"system",
            "content": `あなたの名前は${author.username}です。${author.personality}としてWordPressの記事を生成します。`
        },
        {
            "role":"user",
            "content":`カテゴリー:${category}に関する投稿を${author.personality}らしい口調で書いてください。次のHTMLタグのみを利用してください。[h2,h3,h4,ul,ol,li,table,thead,tbody,th,td,blockquote,p,hr] html, body, headなどは必要ありません。`
        }
    ]
}

```

    
### 2. excerpt生成のプロンプト
Few Shotラーニングを活用しています。<br />はじめに例題を使って返して欲しい形式を学習させています。<br />また「###」はセクションを明確にするために使用しており、${generatedHTML}は1のプロンプトの成果物を使っています。
```typescript
makeMessagesForWpPostPrompt(generatedHtml: string): ChatMessages{
    return [
        {
            "role":"system",
            "content":"You are JSON generator that returns JSON by reading HTML article and make JSON with user's instruction."
        },
        {
            "role":"user",
            "content":`以下の記事を読んでください。  
            ###<h1>SEOって何？Z世代が教える"検索エンジン最適化"の裏技</h1><p>Hey fam! 今日は、みんな大好き（？）SEO、つまり検索エンジン最適化についておしゃべりしようと思います。</p><h2>SEOって何よ？</h2><p>簡単に言うと、SEOはGoogle先生に好かれるテクニックです。これでみんなのサイトやブログが検索結果で上位に表示されるわけ。</p>###
            title、excerpt、categoryをJSON形式で出力してください。categoryは[SEO, Marketing]のどれかを選んでください。JSONのみを返してください。`
        },
        {
            "role":"assistant",
            "content":`
            {
                “title”:”SEOって何なん？”,
                “excerpt”:”SEOはGoogle先生に好かれるテクニックです。キーワード選び、質の高いコンテンツ、バックリンクの重要性を抑えましょう。”,
                “category”:”SEO”
            }
            `
        },
        {
            "role":"user",
            "content":`以下の記事を読んでください。###${generatedHtml}###
            title、excerpt、categoryをJSON形式で出力してください。categoryは[${this.props.categories.join(", ")}]のどれかを選んでください。JSONのみを返してください。`
        },
    ]
}
```

### 3. イメージ生成用のテキスト作成のためのプロンプト
画像生成のAPIは英語の方が精度が良いため以下のようなプロンプトとなっています。「---」はセクションを明確にするために使用しています。
<br />このプロンプトの成果物の最後に" cubism painting."のようなスタイルを指定する事で生成される画像に統一感を持たせる事が出来ます。

こちらもまだ改善が必要ですが、現状の一例として「web analytics understanding visitor behavior for website improvement cubism　painting」といったテキストが生成出来ています。

```typescript
const makeThumbnailPromptFromText = async (text:string): Promise<string> => {
return [
        {
            "role":"system",
            "content":"You are a machine that generate image generation idea from a given text."
        },
        {
            "role":"user",
            "content":"read a article excerpt and make suitable thumbnail image description for the excerpt in English. ---Kanazawa, often overshadowed by Tokyo and Kyoto, is a city in Japan's Ishikawa Prefecture that offers a rich blend of history, culture, and natural beauty. Known as Little Kyoto, it's a must-visit for anyone interested in traditional Japanese arts and crafts.---"
        },
        {
            "role":"assistant",
            "content":"Japanese historic arts and crafts"
        },
        {
            "role":"user",
            "content": `read a article excerpt and make suitable thumbnail image description for the excerpt in English. ---${text}---`
        }
    ]
}
```

<hr />

以上となります。最後までお読み頂きありがとうございました。<br />

OpenAIのドキュメント:　https://platform.openai.com/docs/introduction<br />このプロジェクトでは、GPTとImage generationを使用しました。