
第3回 金融データ活用チャレンジ RAGシステムを作らずに質問に回答しよう!
昨年に引き続き、「金融データ活用チャレンジ」に参加しました。今回は、一般社団法人 金融データ活用推進協会(FDUA)と金融庁が共催するイベントです。テーマは
「生成AIを活用して企業のESGレポートや統合報告書に関連する質問に回答しよう!」
実務にも応用できる設定であり、質問への回答精度を競います。一般的には、RAGシステムを構築してデータを参照しながら回答するのが定石ですが、今回はあえてRAGシステムを用いずに回答するシステムを構築しました。その手法を共有します。
(金融庁共催)第3回金融データ活用チャレンジ | SIGNATE - Data Science Competition
1. 課題
本コンペティションでは、J-LAKE(*パートナー企業であるDATAZORAのKIJIサービス提供データを含む)の情報を用いてRAGシステムを構築していただきます。提供されたデータを元に、質問(query.csv)に対する回答を生成し、その回答の精度を競います。 生成した回答は、指定のフォーマットに従い、投稿してください。
課題をよく見ると、「RAGシステムを構築していただきます」と明記されていますね。しかし、いきなりRAGシステムを構築するのは大変です。そこで、まずはRAGを用いないシンプルな回答システムを作成し、その後RAGシステムへと発展させていくことにします。
2. Search-Augumented Generation (SAG)
RAGは、事前に準備したデータをデータベース化し、そのデータを参照して回答する手法です。しかし、データベースの構築や埋め込み処理は、初学者にとってハードルが高い部分もあります。そこで、代替手法としてインターネット検索を活用する Search-Augmented Generation (SAG) を用いた回答システムを構築しました。
Tavilyというサービスを使用しました。Pythonのプログラム上でインターネット検索を実行し、検索結果を取得できるため、外部データを動的に活用できます。以下に実際のコードを示します。
retriever = TavilySearchAPIRetriever(k=2)
prompt = ChatPromptTemplate.from_template('''\
以下の文脈だけを踏まえて質問に回答してください。文脈だけで質問へ回答することが難しい場合は「わかりません」と回答してください。50文字以内で回答してください。
文脈: """
{context}
"""
質問: {question}
''')
model = ChatOpenAI(model="gpt-4o-mini", max_tokens=54, temperature=0)
RAGシステムでは、コード内で "retriever" を構築する部分が難所となりますが、Tavilyを用いたSAGでは、シンプルな実装で同様の機能を実現できます。
Tavilyは、毎月1,000回のAPIコールまで無料で利用できます。詳しくは、npakaさんのブログ記事が参考になります。
LangChain の Tavily Serch API を試す|npaka
3. サンプルコード
Google Colaboratoryで動作するサンプルコードを作成しました。実行するには、先ほどのTavilyのAPIキーとOpenAIのAPIキーを準備してください。
なお、Google Colaboratoryのシークレット機能を利用すると、APIキーを安全に管理できます。詳しくは、npakaさんのブログ記事が参考になります。
Google Colab のシークレット機能の使い方|npaka
インターネット検索をもとに回答する場合、回答の正確性が課題となります。そこで、生成AIを活用して回答の品質をチェックし、誤っている可能性が高い場合は「わかりません。」と返すようにしました。
この仕組みでは、質問・文脈(インターネット検索の結果)・回答 をもとに、LLMに回答の品質を評価させる形を取っています。
# ジャッジメントノード用クラス
class Judgement(BaseModel):
judge: bool = Field(default=False, description="判定結果")
reason: str = Field(default="", description="判定理由")
# 実際のジャッジメント処理を行う関数
def perform_check(query: str, context: str, answer: str) -> dict[str, Any]:
# ジャッジメント用プロンプト
prompt = ChatPromptTemplate.from_template(
"""以下の質問、文脈、回答を基に回答の品質を評価してください。
回答は50文字以内という条件を満たしていること。
文脈の情報をもとに質問に対して正確に回答していて、虚偽の内容が含まれない場合は'True'を、そうでない場合は'False'を回答してください。
文脈だけで質問へ回答することが難しい場合がありますが、その場合は「わかりません」と回答していれば'True'を回答して下さい。
さらにその判断理由も説明してください。
質問: {query}
文脈: {context}
回答: {answer}
""".strip()
)
# モデルとチェインの設定
judgement_model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
chain = prompt | judgement_model | StrOutputParser()
# チェインの実行
result_json = chain.invoke({"query": query, "context": context, "answer": answer})
try:
lines = result_json.strip().split("判断理由:")
judge = lines[0].strip().lower() == 'true'
reason = lines[1].strip() if len(lines) > 1 else "理由が提供されていません。"
result = Judgement(judge=judge, reason=reason)
except ValueError as e:
raise ValueError(f"Failed to parse response: {result_json}") from e
return {
"current_judge": result.judge,
"judgement_reason": result.reason
}
ちなみに、回答の品質をLLMに評価させるコードは、こちらの書籍を参考にしました。というより、書籍の内容をほぼそのまま活用させていただきました。
LangChainとLangGraphによるRAG・AIエージェント[実践]入門:書籍案内|技術評論社
この書籍は、RAGシステムやAIエージェントの実践的な構築方法を詳しく解説しており、実装レベルで役立つコードも豊富に掲載されています。具体的なコード付きで学べるため、RAG・AIエージェントシステムの開発を進める上で非常に参考になります。
Google Colaboratoryで動作するノートブックはこちらです。提出したところ、暫定評価は 0.10 でした。まずまずの結果です。
https://colab.research.google.com/drive/1Loxb_39ONIphlBGh2Nydv7JtcHzXsRQs?usp=sharing
最後に
第3回 金融データ活用チャレンジ の締め切りまで、ついに 残り3日! 🔥
ここからが本当の勝負どころです。最終調整、新たなアプローチの試行——最後のひと踏ん張りが結果を左右します!
参加者の皆さん、一緒に ラストスパート を駆け抜けましょう!🚀 健闘を祈ります! 💪✨