はじめに
安野たかひろ氏の都知事選マニフェストリポジトリで使用されているGitHub Actionsワークフローは、オープンソースプロジェクトの効率的な管理を実現する優れた例です。このワークフローは、新しいイシューが開かれた際に自動的に実行され、コンテンツの適切性チェック、重複イシューの検出、そしてラベル付けを行います。
この記事では、issue-review.yml
ファイルの内容を詳細に解説し、初心者の方でも理解できるように丁寧に説明していきます。
自分のリポジトリに組み込んだ例がこちら
ワークフローの概要
このGitHub Actionsワークフローは以下の主要な機能を持っています:
- 新しいイシューが開かれたときに自動的に起動
- イシューの内容を分析し、不適切なコンテンツをチェック
- 既存のイシューとの重複を検出
- 必要に応じてラベルを付与
ワークフローの詳細解説
トリガーとパーミッション設定
name: Issue Review
on:
issues:
types: [opened]
permissions:
issues: write
contents: read
このセクションでは、ワークフローの名前を定義し、トリガー条件とパーミッションを設定しています。
on.issues.types: [opened]
: 新しいイシューが開かれたときにワークフローが起動します。permissions
: ワークフローがイシューの読み書きと、リポジトリコンテンツの読み取りを行うための権限を設定しています。
ジョブの定義
jobs:
review_issue:
runs-on: ubuntu-latest
review_issue
という名前のジョブを定義し、最新のUbuntuランナーで実行するように指定しています。
ステップの設定
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install openai
pip install PyGithub
pip install qdrant-client
pip install regex
これらのステップでは、以下の準備を行っています:
- リポジトリのチェックアウト
- Pythonの設定
- 必要なPythonパッケージのインストール
メインの処理ステップ
- name: Review Issue with LLM
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
QD_API_KEY: ${{ secrets.QD_API_KEY }}
QD_URL: ${{ secrets.QD_URL }}
run: |
python <<EOF
# ... (Pythonスクリプト)
EOF
このステップでは、環境変数を設定し、Pythonスクリプトを実行してイシューのレビューを行います。
Pythonスクリプトの詳細解説
以下、Pythonスクリプトの主要な部分を解説します。
必要なライブラリのインポートと初期設定
# 必要なライブラリをインポート
import github
from github import Github
import os
import openai
import regex as re
from qdrant_client import QdrantClient
from qdrant_client.models import PointStruct
# 環境変数から各種APIキーとURLを取得
token = os.getenv("GITHUB_TOKEN")
qd_api = os.getenv("QD_API_KEY")
qd_url = os.getenv("QD_URL")
# GitHubクライアントの初期化
g = Github(token)
repo = g.get_repo("${{ github.repository }}")
issue = repo.get_issue(${{ github.event.issue.number }})
issue_content = f"{issue.title}\n{issue.body}"
# ラベルの作成(既に存在する場合はエラーをキャッチして無視)
try:
repo.create_label(name="toxic", color="ff0000")
repo.create_label(name="duplicated", color="708090")
except:
pass
# Qdrantクライアントの初期化
qdrant_client = QdrantClient(
url=qd_url,
api_key=qd_api,
)
# OpenAIクライアントの初期化
openai_client = openai.Client()
embedding_model = "text-embedding-3-small"
collection_name = "issue_collection"
この部分では、必要なライブラリをインポートし、各種APIクライアントを初期化しています。また、GitHubリポジトリからイシューの情報を取得し、必要なラベルを作成しています。
画像の不適切性チェック関数
def validate_image(text):
# GPT-4-visionを使用して画像の不適切性をチェック
model_name = "gpt-4o"
prompt = "この画像が暴力的、もしくは性的な画像の場合trueと返してください。"
# テキストから画像URLを抽出
image_url = re.search(r"!\[[^\s]+\]\((https://[^\s]+)\)", text)
if image_url and len(image_url) > 1:
image_url = image_url[1]
else:
return False
try:
# OpenAI APIを使用して画像の内容をチェック
response = openai_client.chat.completions.create(
model=model_name,
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{
"type": "image_url",
"image_url": {
"url": image_url
},
},
],
}
],
max_tokens=1200,
)
except:
# エラーが発生した場合は、安全のためTrueを返す
return True
# レスポンスに"true"が含まれていれば不適切と判断
v = response.choices[0].message.content.lower()
return "true" in v
この関数は、イシューに含まれる画像URLを抽出し、GPT-4-visionを使用して画像の不適切性をチェックします。
コンテンツの不適切性チェック関数
def judge_violation(text):
# OpenAIのモデレーションAPIを使用してテキストの不適切性をチェック
response = openai_client.moderations.create(input=text)
flag = response.results[0].flagged
# 画像の不適切性もチェック
video_flag = validate_image(text)
if flag or video_flag:
print(response)
issue.add_to_labels("toxic")
if video_flag:
warn = "不適切な画像です。アカウントBANの危険性があります。"
else:
warn = "不適切な投稿です。アカウントBANの危険性があります。"
issue.create_comment(warn)
issue.edit(state="closed")
return True
return flag
この関数は、テキストの不適切性をOpenAIのモデレーションAPIでチェックし、画像の不適切性もvalidate_image
関数を使用してチェックします。不適切なコンテンツが検出された場合、イシューにラベルを付け、警告コメントを追加してイシューをクローズします。
イシューの追加と重複チェック関数
def add_issue(text:str, iss_num:int):
# テキストの埋め込みベクトルを作成し、Qdrantに保存
texts = [text]
ids = [iss_num]
result = openai_client.embeddings.create(input=texts, model=embedding_model)
points = [
PointStruct(
id=idx,
vector=data.embedding,
payload={"text": t},
)
for idx, data, t in zip(ids, result.data, texts)
]
qdrant_client.upsert(collection_name, points)
return text
def merge_issue(iss:int):
# 重複イシューにラベルを付け、コメントを追加
issue.add_to_labels("duplicated")
print(f"merge to {iss}")
issue.create_comment(f"#{iss} と重複しているかもしれません")
return iss
def qd_search(text:str):
# Qdrantで類似イシューを検索
results = qdrant_client.search(
collection_name=collection_name,
query_vector=openai_client.embeddings.create(
input=[text],
model=embedding_model,
)
.data[0]
.embedding,
)
return results
def qd_add(text:str, iss_num:int):
# 新しいイシューをQdrantに追加
texts = [text]
ids = [iss_num]
result = openai_client.embeddings.create(input=texts, model=embedding_model)
points = [
PointStruct(
id=idx,
vector=data.embedding,
payload={"text": text},
)
for idx, data, text in zip(ids, result.data, texts)
]
qdrant_client.upsert(collection_name, points)
これらの関数は、イシューの追加、重複チェック、そして類似イシューの検索を行います。Qdrantベクトルデータベースを使用して、効率的な類似性検索を実現しています。
メイン処理
# イシューの不適切性をチェック
if judge_violation(issue_content):
quit()
# 類似イシューを検索
results = qd_search(issue_content)
if len(results) > 2:
results = results[:3]
else:
results = results
print(results)
# 検索結果を整形
res = ""
for i in results:
res+=f'id:{i.id}\n内容:{i.payload["text"]}\n'
res = res.strip()
# GPT-4を使用して重複イシューの判断
prompt = f"""
以下は市民から寄せられた政策提案です。
{issue_content}
この投稿を読み、以下の過去提案の中に重複する提案があるかを判断してください。
{res}
重複する提案があればそのidを出力してください。
もし存在しない場合は0と出力してください。
[出力形式]
id:0
"""
print(prompt)
completion = openai_client.chat.completions.create(
model="gpt-4o",
max_tokens= 1024,
messages=[
{"role": "system", "content": prompt},
]
)
review = completion.choices[0].message.content
if ":" in review:
review = review.split(":")[-1]
if review.isdecimal():
if review == "0":
add_issue(issue_content, issue.number)
else:
merge_issue(int(review))
print(review)
メイン処理部分では、以下の手順でイシューの処理を行います:
- イシューの不適切性をチェック
- 類似イシューを検索
- GPT-4を使用して重複イシューの判断
- 結果に基づいてイシューを追加または重複としてマーク
まとめ
このGitHub Actionsワークフローは、高度な自然言語処理技術と機械学習を活用して、イシュー管理を自動化しています。主な特徴は以下の通りです:
- OpenAIのAPIを使用した不適切コンテンツの検出
- Qdrantベクトルデータベースを使用した効率的な類似イシュー検索
- GPT-4を活用した重複イシューの判断
このような自動化により、大規模なオープンソースプロジェクトでのイシュー管理が効率化され、コミュニティの健全性維持と建設的な議論の促進が可能になります。
開発者の方々は、このワークフローを参考にして、自身のプロジェクトに合わせたカスタマイズを行うことで、より効率的なプロジェクト管理を実現できるでしょう。
コメント