実践編：GPTとBacklogの連携：プロンプト・チューニングで効果的なプロジェクト管理

前回の記事「<a href="https://azure-recipe.kc-cloud.jp/revolutionize_backlog_gpt/">BacklogとGPT連携でプロジェクト管理を革新！6つの活用法</a>」では、BacklogとGPTを連携させることでの活用方法を６つ紹介しました。

この記事では、プロジェクト管理ツールであるBacklogと、AI技術の一つであるChatGPTを連携させることで、プロジェクト管理の効率化を図る方法を紹介します。具体的には、Backlogの課題のURLをプログラムに渡すことで、自動的に課題の要約、タスク、ネクストアクションを生成するプログラムの実装方法について解説します。

<img src="https://azure-recipe.kc-cloud.jp/wp-content/uploads/2023/03/backlog-issue.png" alt="" width="711" height="294" class="alignnone size-full wp-image-18840" />

記事の内容は、以下の3つのステップに分かれています。
<ol>
 	<li><strong>ChatGPTと一緒にMVPを作る:</strong>
まずは、BacklogとChatGPTを連携させるための最小限の機能を持つプロトタイプ（MVP）を作成します。この段階では、基本的な連携やデータのやり取りができることを確認します。</li>
 	<li><strong>プロンプトエンジニアリングで試行錯誤:</strong>
次に、プロンプトエンジニアリングを活用して、ChatGPTが生成する課題の要約、タスク、ネクストアクションの精度や適切さを向上させるための試行錯誤を行います。</li>
 	<li><strong>完成版:</strong>
最後に、試行錯誤を経て改善されたプログラムの完成版を紹介します。この完成版を使えば、Backlogの課題を効率的に管理し、プロジェクト全体の進行をスムーズにすることができます。</li>
</ol>
この記事を通じて、BacklogとChatGPTの連携によるプロジェクト管理の効率化方法を学び、自身のプロジェクトに活用していただけることを目指しています。
<h2>1. ChatGPTと一緒にMVPを作る</h2>
<span>ChatGPTと連携するJupyter Notebook上で動作するスクリプトを作成し、Backlogから課題を取得し、要約・タスク・ネクストアクションを出力します。</span><span>
</span><span>「Backlogから課題を取得し、ChatGPTを使って要約・タスク・ネクストアクションを生成するJupyter Notebookスクリプト」ぐらいの指示をするだけでスクリプトを作ってくれます。</span>

スクリプト以外に自分で用意するものは以下の４つです。
<ul>
 	<li><strong>OpenAI API Key</strong>　<a href="https://platform.openai.com/account/api-keys">OpenAIのサイト</a>から取得</li>
 	<li><strong>Backlog API Key</strong>　Backlogのサイトから取得、https://[スペース名].backlog.com/EditApiSettings.action のように自分のスペースで取得可能</li>
 	<li><strong>スペース名</strong>　Backlog URLの https://<strong>[スペース名]</strong>.backlog.com/ または https://<strong>[スペース名]</strong>.backlog.jp/ のbacklogの前の部分</li>
 	<li><strong>課題ID</strong>　Backlog課題URLの https://[スペース名].backlog.com/view/<strong>[課題ID] </strong>または https://[スペース名].backlog.jp/view/<strong>[課題ID] </strong>の課題ID、フォーマットは <strong>[プロジェクトID]-[課題番号]（ABC-289など）</strong></li>
</ul>
スクリプトは基本はChatGPTからもらったスクリプトをJupyter notebookが実行できる環境に貼り付けて実行すればOKですが、エラーが出る場合はそのままChatGPTに再度聞くことで解決できます。

<span>以下のコードはほぼChatGPTが生成したものですが、GPT-3を使うスクリプトで提案されたので、30-34行目の部分をmodelをGPT-4に変更し、promptをmessagesに変更しています。gpt-3.5-turboでも同じように動作します。</span>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><code># 必要なライブラリのインストール
!pip install openai requests</code></pre>
</div>

```Python
# APIキーの設定
import os
import requests

os.environ['BACKLOG_API_KEY'] = 'your_backlog_api_key'
os.environ['OPENAI_API_KEY'] = 'your_openai_api_key'

your_space = [スペース名]
issue_key = [課題ID]

# OpenAI APIの初期化
import openai
openai.api_key = os.environ['OPENAI_API_KEY']

# Backlog課題の取得
def get_backlog_issue():
    api_endpoint = f'https://{your_space}.backlog.com/api/v2/issues/{issue_key}'
    headers = {'Authorization': f'Bearer {os.environ["BACKLOG_API_KEY"]}'}
    
    response = requests.get(api_endpoint, headers=headers)
    issue = response.json()
    return issue

# ChatGPTへのプロンプト生成と応答取得
def get_chatgpt_response(issue):
    issue = f"課題タイトル: {issue['summary']} \n課題内容: {issue['description']} \n要約・タスク・ネクストアクションを生成してください。"
    
    response = openai.Completion.create(
        model="gpt-4", # "gpt-3.5-turbo"
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": issue},
        ]
    )
    return response.choices[0].text.strip()

# MVPの実行
issue = get_backlog_issue()
response = get_chatgpt_response(issue)

print(response)
```

実行することで、Backlogの課題から要約・タスク・ネクストアクションが出力されます。
<h2>2. プロンプトエンジニアリングで試行錯誤</h2>
このままでも十分有益ですが、プロンプト（messagesの部分）を試行錯誤することで、より望ましい回答を得ることが出来ます。
<span>プロンプトエンジニアリングによって、GPTを活用したプログラムのパフォーマンスを最適化する方法を紹介します。プロンプトエンジニアリングは、AIモデルに与える入力を工夫することで、より良い結果を得るための方法です。</span>
<ol>
 	<li><strong>詳細情報の追加</strong>
入力するデータを増やすことで、AIが求められる情報をより正確に理解できるようになります。</li>
 	<li><strong>プロンプトのスタイルや構造の変更</strong>
GPTに与えるプロンプトを、より具体的かつ詳細な指示に変更してみましょう。プロンプトの構造を変更することで、AIがより理解しやすい形で情報を伝えることができます。例えば、<span>リスト形式や質問形式に変更することで</span>、<span>AIが情報を正確に把握しやすくなるでしょう</span>。</li>
 	<li><strong>AIに例を示す</strong>
プロンプトに、求められる出力の例を与えることで、AIがどのような結果を返すべきかを理解しやすくなります。</li>
</ol>
これらの試行錯誤を繰り返すことで、プロンプトエンジニアリングのスキルを磨き、BacklogとGPTの連携をさらに効果的に活用できるようになります。

<span>具体的な方法をそれぞれ説明します</span>。
<h3>1. 詳細情報の追加</h3>
第１章で紹介したMVPでは、課題の最小限のデータのみを使用していますが、より正確な情報を得るためには、タイトルと説明文以外の情報も取り入れることが重要です。
具体的には、投稿者、投稿日時、期限日、優先度などの情報を追加することで、課題の詳細がより明確になります。これにより、プロジェクト管理を効果的に行うことが可能になります。

さらに、返信（コメント）も取り込むことで、課題の作成後に関する状況や進捗についての情報を追加することができます。これにより、ChatGPTが生成する要約やタスク、ネクストアクションがより現実に即したものとなり、プロジェクト管理に役立つ情報が得られるでしょう。

```python
# Backlog課題の取得
def get_backlog_issue():
    api_endpoint = f'https://{your_space}.backlog.com/api/v2/issues/{issue_key}'
    headers = {'Authorization': f'Bearer {os.environ["BACKLOG_API_KEY"]}'}
    
    response = requests.get(api_endpoint, headers=headers)
    issue = response.json()
    return issue

# Backlog課題のコメント取得
def get_backlog_issue_comments(issue_id):
    api_endpoint = f'https://{your_space}.backlog.com/api/v2/issues/{issue_id}/comments'
    headers = {'Authorization': f'Bearer {os.environ["BACKLOG_API_KEY"]}'}
    
    response = requests.get(api_endpoint, headers=headers)
    comments = response.json()
    return comments

# ChatGPTへのプロンプト生成と応答取得
def get_chatgpt_response(issue, comments):
    prompt = f"課題タイトル: {issue['summary']} \n課題内容: {issue['description']} \n投稿者: {issue['createdUser']['name']} \n投稿日時: {issue['created']} \n期限日: {issue['dueDate']} \n優先度: {issue['priority']['name']} \nコメント: {' '.join([comment['content'] for comment in comments])} \n要約・タスク・ネクストアクションを生成してください。"
    
    response = openai.Completion.create(
        model="gpt-4", # "gpt-3.5-turbo"
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt},
        ]
    )
    return response.choices[0].text.strip()
```

<h3>2. プロンプトのスタイルや構造の変更</h3>
プロンプトのスタイルや構造を変更することで、ChatGPTからの応答の質が大幅に向上する場合があります。以下に、プロンプトのスタイルや構造を変更する方法のいくつかを示します。
<ol>
 	<li><strong>明確な指示の追加</strong>プロンプトに明確な指示を追加することで、ChatGPTに期待する応答形式を理解させることができます。例えば、「要約・タスク・ネクストアクションを生成してください」という指示を追加することで、ChatGPTに具体的な出力形式を伝えることができます。</li>
 	<li><strong>質問形式への変更</strong>プロンプトを質問形式に変更することで、ChatGPTがより自然な形で回答を提供するようになることがあります。例えば、「この課題の要約は何ですか？」「タスクは何ですか？」「次のアクションは何ですか？」といった質問形式に変更することができます。</li>
 	<li><strong>情報の再構成</strong>プロンプト内の情報の構成を変更することで、ChatGPTの理解度を向上させることができます。例えば、課題の情報を「課題タイトル」「課題内容」などのカテゴリに分けて、情報を整理しやすくすることができます。</li>
 	<li><strong>詳細度の調整</strong>プロンプトに与える情報の詳細度を調整することで、ChatGPTの応答の質を向上させることができます。例えば、必要以上の情報を削除したり、重要な情報を強調したりすることで、ChatGPTに重要なポイントに焦点を当てさせることができます。</li>
</ol>
これらの方法を用いてプロンプトを最適化することで、ChatGPTからの応答の質を向上させることができます。試行錯誤を繰り返すことで、最適なプロンプト構造を見つけることができます。

ChatGPTに生成してもらうと以下のようになりましたが、細かく分けるよりまとめて入れたほうがちゃんとした結果になりやすいです。次の「AIに例を示す」の章で具体的な変更を行います。
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><code>messages=[
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": f"課題タイトル: {issue['summary']}"},
    {"role": "user", "content": f"課題内容: {issue['description']}"},
    {"role": "user", "content": "この課題の要約は何ですか？"},
    {"role": "assistant", "content": "{要約}"},
    {"role": "user", "content": "タスクは何ですか？"},
    {"role": "assistant", "content": "{タスク}"},
    {"role": "user", "content": "次のアクションは何ですか？"},
]</code></pre>
</div>
<h3>3. AIに例を示す</h3>
<span>AIに具体的な例を示して、期待するフォーマットで出力させる方法を紹介します。
</span><span>例示することで、AIはより正確な情報を提供しやすくなるでしょう。具体的な例を提示することで、AIがより正確な情報を提供することが期待できます。プロンプトエンジニアリングを用いて、ChatGPTに対して効果的に指示を出すことができます。</span>

前項で触れた細かく分けるよりまとめて入れるについても反映したものが以下です。
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-python" data-lang="Python"><code>messages=[
    {"role": "system", "content": "あなたは役に立つアシスタントです。プロジェクトの課題から以下のフォーマットで要約、タスク、ネクストアクションを生成してください。\n\n【プロジェクト概要】\n\n【タスク】\n\n【ネクストアクション】\n\n例：\n課題タイトル: 新しいウェブサイトのデザイン\n課題内容: モバイルフレンドリーなウェブサイトのデザイン案を作成する。\n\n【プロジェクト概要】モバイルフレンドリーなウェブサイトのデザイン案作成\n【タスク】1. 競合他社のウェブサイト分析 2. デザインコンセプトの提案 3. モックアップの作成\n【ネクストアクション】競合他社のウェブサイト分析を開始する"},
    {"role": "user", "content": f"課題タイトル: {issue['summary']} \n課題内容: {issue['description']} \n投稿者: {issue['createdUser']['name']} \n投稿日時: {issue['created']} \n期限日: {issue['dueDate']} \n優先度: {issue['priority']['name']} \nコメント: {' '.join([comment['content'] for comment in comments])} "},
]</code></pre>
</div>
<span>systemメッセージで</span>役割ややってほしいことを明確にして、<span>userメッセージに出来るだけ詳細な内容を渡すことで、より正確な情報が返ってくるでしょう</span>。
<h2>完成版</h2>
今までの内容をまとめたコードは以下になります。

```Python
# APIキーの設定
import os
import requests

os.environ['BACKLOG_API_KEY'] = 'your_backlog_api_key'
os.environ['OPENAI_API_KEY'] = 'your_openai_api_key'

your_space = [スペース名]
issue_key = [課題ID]

# OpenAI APIの初期化
import openai
openai.api_key = os.environ['OPENAI_API_KEY']

# Backlog課題の取得
def get_backlog_issue():
    api_endpoint = f'https://{your_space}.backlog.com/api/v2/issues/{issue_key}'
    headers = {'Authorization': f'Bearer {os.environ["BACKLOG_API_KEY"]}'}
    
    response = requests.get(api_endpoint, headers=headers)
    issue = response.json()
    return issue

# Backlog課題のコメント取得
def get_backlog_issue_comments(issue_id):
    api_endpoint = f'https://{your_space}.backlog.com/api/v2/issues/{issue_id}/comments'
    headers = {'Authorization': f'Bearer {os.environ["BACKLOG_API_KEY"]}'}
    
    response = requests.get(api_endpoint, headers=headers)
    comments = response.json()
    return comments

# ChatGPTへのプロンプト生成と応答取得
def get_chatgpt_response(issue, comments):
    prompt = f"課題タイトル: {issue['summary']} \n課題内容: {issue['description']} \n投稿者: {issue['createdUser']['name']} \n投稿日時: {issue['created']} \n期限日: {issue['dueDate']} \n優先度: {issue['priority']['name']} \nコメント: {' '.join([comment['content'] for comment in comments])} \n要約・タスク・ネクストアクションを生成してください。"
    
    response = openai.Completion.create(
        model="gpt-4", # "gpt-3.5-turbo"
        messages=[
            {"role": "system", "content": "あなたは役に立つアシスタントです。プロジェクトの課題から以下のフォーマットで要約、タスク、ネクストアクションを生成してください。\n\n【プロジェクト概要】\n\n【タスク】\n\n【ネクストアクション】\n\n例：\n課題タイトル: 新しいウェブサイトのデザイン\n課題内容: モバイルフレンドリーなウェブサイトのデザイン案を作成する。\n\n【プロジェクト概要】モバイルフレンドリーなウェブサイトのデザイン案作成\n【タスク】1. 競合他社のウェブサイト分析 2. デザインコンセプトの提案 3. モックアップの作成\n【ネクストアクション】競合他社のウェブサイト分析を開始する"},
            {"role": "user", "content": prompt},
        ]
    )
    return response.choices[0].text.strip()

# プログラムの実行
issue = get_backlog_issue()
response = get_chatgpt_response(issue)

print(response)
```

ChatGPTを使ってBacklogの課題を効果的に管理する方法について学びました。プロンプトエンジニアリングを活用し、AIを使ってプロジェクト管理を革新しましょう。
<h2>まとめ</h2>
この記事では、BacklogとGPT-4を連携させる方法とプロンプトエンジニアリングを活用して、より効果的なプロジェクト管理を実現する方法を紹介しました。具体的な手順や試行錯誤を通じて、プロンプトエンジニアリングのスキルを磨くことで、BacklogとGPT-4の連携がさらに効果的に活用できるようになります。
<ol>
 	<li>BacklogとGPT-4の連携を通じて、課題の要約、タスク、ネクストアクションを自動生成できます。</li>
 	<li>プロンプトエンジニアリングを用いて、AIがより正確で役立つ情報を提供できるようになります。</li>
</ol>
プロンプトエンジニアリングの実践を通じて、プロジェクト管理の効率化や効果的なデータ活用を図ることができます。これにより、チーム全体の生産性向上やコミュニケーションの最適化が期待できます。