OpenAIとLangChainを活用したジェンダーバイアス解消ツール「バイアスチェッカー」を作った話

# はじめに
こんにちは！
Webエンジニアをしている、かなです。

Qiitaの投稿がだいぶ久しぶりになっちゃいました。

現在、bgrass株式会社で女性ITエンジニア向けハイスキル転職サービス「[WAKE Career](https://wake-career.jp/)」の開発に携わっています。

この度、WAKE Careerの新機能として、企業向けのバイアスチェッカーをリリースしました！！

この機能の開発には、初めてOpenAIとLangChainを活用しました。どのようなプロセスを経て、この機能を実装したのかをご紹介したいと思います。

OpenAIやLangChainを用いて何か作りたいと考えている方の参考になると嬉しいです！

# バイアスチェッカーとは？
バイアスチェッカー？なにそれ？となってると思うので、この機能について先に説明します。

バイアスチェッカーは、求人票や求職者とのメッセージのやり取りの中で、ジェンダーバイアスを含む言葉遣いや、女性求職者が応募をためらうような表現がなされていないかをチェックし、より適切な表現を提案する機能になります。

![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255876/1592d813-14ec-e0ba-92cf-5c3022dcaaab.png)

私たち人間は、誰もが何らかのバイアスを持っています。バイアスを持つこと自体が問題なのではなく、問題はそのバイアスを認識し、それを取り除く取り組みをするかどうかにあります。
バイアスチェッカーは、このような取り組みをサポートするツールとして開発をしました。自身が無意識のうちに持っているかもしれないジェンダーバイアスに気付き、考えるきっかけを提供し、求職者への適切なアプローチができることを目指しています。

次に、どのようなステップでバイアスチェッカーを開発したかを書いていこうと思います。


# Step1. プロンプトエンジニアリングの基礎を学ぶ
開発を進めていくにも、私自身OpenAIを用いた開発をするのが初めて&日常でChatGPTをちゃんと使いこなせてたわけではなかったので、これを機に「プロンプトエンジニアリングとは？」の基礎からざっくりインプットしました。
学ぶにあたって参考になった文献はこちらになります↓

- プロンプトエンジニアリングの基礎
    - [Prompt Engineering Guide](https://www.promptingguide.ai/jp)

- ながらインプットでおすすめの動画

   -  [【総集編】プロンプトエンジニアリングの基礎を初心者さん向けに解説！](https://youtu.be/VC0WRDQ5mkU?si=6ZB8Zph_XQPG-5z4)

   -  [最新研究まとめ！26個のプロンプト原則をまとめて解説してみた](https://youtu.be/VTyy1xAzKQg?si=EV4hYm2Opua6J423)

# Step2. プロンプト設計
基礎知識をざっくり身につけた後、バイアスチェッカーのプロンプト設計に取り掛かりました。

「**プロンプトを制する者はAIを制する**」というお教えのもと、まずはどのようなプロンプトにするのかを検討しました。

冒頭でも書いたように、バイアスチェッカーで達成したいことは以下になります。
`
ユーザーが入力した内容に対して、ジェンダーバイアスを含む言葉遣いや、女性求職者が応募をためらうような表現がなされていないかをチェックし、より適切な表現を提案すること。
`

この目的を達成するために、まずは評価基準を検討しました。

評価基準については、ChatGPT先生に壁打ち相手になっていただき、５つの評価基準でチェックを行うことにしました。

- ジェンダー表現の多様性: 性別や性の多様性に基づく差別表現が含まれているか
- アクセシビリティ: すべてのユーザーにとって理解しやすくアクセスしやすいか
- 差別的な表現: 人種、性別、宗教などの特徴に基づいた差別表現が含まれているか
- 排他的な表現: 特定の性別や年齢、立場の人々を意図的にまたは無意識に排除している表現が含まれているか
- その他: 上記のカテゴリに当てはまらない場合の評価

また、プロンプトの内容はプロンプトの原則を駆使して組み立てていきました。

- 役割を与える（あなたは〇〇〇です。）
- プロンプトのフォーマット化
- 従うべき要件を提示する
- ステップバイステップで考えてもらう
など

# Step3. Colabを使って動かしてみる
ちゃんと実装する前に、まずはGoogle Colabを使用してStep2で考えてプロンプトを検証してみました。
Google Colabは、Googleアカウントがあれば誰でも簡単にPythonコードの実行環境を構築できます。環境構築の手間が省け、すぐに検証を行うことができ便利です。

さらに、社内のメンバーにもColabで動かしてもらい、出力結果の内容のフィードバックをいただきながら、プロンプトの改善と試行錯誤を重ねました。


## コードの解説
### 出力結果をJSON形式にする
出力結果をJSON形式で取得したかったので、LangChainの`PydanticOutputParser`を活用してJSON出力を実現しました。
```python
import os
from pydantic import BaseModel, Field
from typing import List, Dict
from langchain_openai import AzureChatOpenAI
from langchain_core.prompts import (
    PromptTemplate,
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate
)
from fastapi import HTTPException, status
from langchain.chains import LLMChain
from langchain.output_parsers import PydanticOutputParser

class Bias(BaseModel):
    category: str = Field(...,description="カテゴリ")
    description: str = Field(...,description="バイアスの内容の説明")
    target_keyword: str = Field(...,description="バイアスの対象となるキーワード")
    suggestion: str = Field(...,description="バイアスのある文への改善案")

class BiasList(BaseModel):
    biases: list[Bias] = Field(...,description="バイアス結果のリスト")

parser = PydanticOutputParser(pydantic_object=BiasList)
```

### プロンプトのテンプレート化
LangChainの`PromptTemplate`を用いて、プロンプトのテンプレート化を行いました。
これにより、ユーザーからの入力値をqueryとして受け取り、それをプロンプトのテンプレートに組み込んで実行することができるようになります。

```python
# プロンプトのテンプレート
system_template = '''
あなたはジェンダーダイバーシティとキャリアに関する専門知識を持つ採用担当者として、入力された文章を分析し評価する任務を担っている。

~~~ 省略 ~~~

{format_instructions}
'''


system_prompt = PromptTemplate(
    template=system_template,
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

system_message_prompt = SystemMessagePromptTemplate(prompt=system_prompt)
human_message_prompt = HumanMessagePromptTemplate.from_template('{query}')
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
```

# Step4. API＆UI実装
プロンプトの出力結果がいい感じになったのでバイアスチェッカーのAPI実装に取り掛かりました。

APIを実装するにあたって採用した技術スタックは次のとおりです。
- FastAPI
- Supabase
- Vercel

WAKE Career自体は、Next.jsとSupabaseを用いて実装され、Vercelでデプロイをしています。API側も、これまでの技術スタックをそのまま活かせるようにFastAPIを選択しました。その結果、スムーズに開発を進めることができました。


```python
@app.post("/api/bias-check")
async def bias_check(input_data: Request, user: dict = Depends(authenticate_user)):
    if check_bias_permission(user):
        return check_bias(input_data)

    raise HTTPException(
        status_code=status.HTTP_403_FORBIDDEN,
        detail="Not authorized to perform bias check."
    )
```

```python
def check_bias(input_data: Dict[str, str]) -> Dict[str, List[Dict]]:
    MAX_TEXT_LENGTH = 1000
    if len(input_data.input) > MAX_TEXT_LENGTH:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Please limit input to 1000 characters")

    llm = AzureChatOpenAI(
        temperature=0.6,
        deployment_name=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
        azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
        openai_api_key=os.environ["AZURE_OPENAI_API_KEY"],
        api_version=os.environ["AZURE_OPENAI_API_VERSION"],
        streaming=True
    )
    chain = LLMChain(llm=llm, prompt=chat_prompt)
    chain_output = chain.invoke({"query": input_data.input})
    result_data = parser.parse(chain_output['text'])

    transformed_biases = []
    for bias in [bias.dict() for bias in result_data.biases]:
        targets = bias["target_keyword"].split('、')
        for target in targets:
            new_bias = bias.copy()
            new_bias["target_keyword"] = target
            transformed_biases.append(new_bias)

    return {"biases": transformed_biases}
```

# OpenAIからAzure OpenAIへ移行
当初OpenAIを利用して開発していましたが、Microsoftのスタートアップ支援プログラムを活用できるとのことでAzure OpneAIに移行しました。（Azureクレジットの無料枠を一定期間利用できるというありがたい特典）

https://learn.microsoft.com/ja-jp/azure/ai-services/openai/


# デプロイ
FastAPIをVercelへデプロイする方法に関しては[こちら](https://github.com/hebertcisco/deploy-python-fastapi-in-vercel)のソースを参考に実装しました。
この方のおかげで割と簡単にできました。

# 今後の展望と改善点
バイアスチェッカーの精度をより上げていくために、現在使用しているAzure OpenAIのモデル`gpt-3.5-turbo`から`gpt-4`へのバージョンアップを検討しています。このアップグレードに加え、プロンプトの見直しも行うことで、出力結果の精度をさらに高めていきます。

また、WAKE Careerが定義する求人のガイドラインをモデルに読み込ませ、ガイドラインの内容も考慮したチェックを行えるようにしていきたいです。

バイアスチェッカーを現在独立した画面で実装されています。求人作成や求職者とのメッセージのやり取りの中で、バイアスチェックと添削がもっとスムーズに行えるようUX改善も行っていきたいです。

# まとめ
バイアスチェッカーの開発を通じて、初めて触れる技術の壁に直面しながらも、無事リリースすることができ、私自身さらに成長＆自信につながりました。
この経験で、プロンプトエンジニアリングの理解を深められ、生成AIの可能性と魅力を実感する貴重な機会になりました。

今後もバイアスチェッカーをブラッシュアップし、ユーザーへの価値提供とジェンダーギャップの解消に取り組んでいけたらと思っています。

# エンジニア絶賛募集中！
現在、私1人でWAKE Careerの開発を行っています。このプロダクトの成長をより加速させていくためにも、性別を問わず一緒に開発を進めてくれるエンジニアを募集しています。

現在、bgrassで働くメンバーは女性のみになってしまってます。
女性ばかりってちょっと怖いな、入りにくいな…と思う方もいるでしょう。
正直なところ以前までは私もそう思っていました。
人間関係が複雑そうとか、キラキラした雰囲気に圧倒されるんじゃないかなとか。そういうイメージを持っていました。
しかし、実際に働いてみると、そういったことはなく、小さい組織ながらも、一人ひとりが自分の役割を全うし、互いに認め合い、尊重し合う環境で、楽しく働けています。
身だしなみに気を使うこともありません。（完全リモート勤務です。寝巻きのまま働くの最高ww）

バイアスは誰にでもあるもの。だた、少し視点を変えてみたり、行動してみるだけで新しい発見や興味の幅が広がるかもしれません。

ジェンダーバイアスという社会課題の解消やDEI推進をテクノロジーを通じて実現しようとする私たちのチャレンジに、少しでも興味を持っていただけた方は、ぜひカジュアル面談しましょう！
もしくは、私に直接DMを送ってください。お待ちしています！

https://www.wantedly.com/projects/1629905