こんにちわん。

久々にBlog等を書いております。私ですw

昨今AIアプリケーションを作る話が増えてきているのでその中で一つ最近盛り上がりつつある(?)DSPyについてちょっと試しているのでそれについてお話していこうかと思います

「AIエージェントキャッチアップ #46 – DSPy v3」を開催しました

こちらのGenerative Agentsさんのブログでも取り上げられておりますが、ジワジワ浸透してきているんですよね。

今日はそんなDSPyについてお話していこうと思います!

プロンプトエンジニアリングってなんか疲れません?

LLMアプリケーションを作るときって結構プロンプトの書き方に悩む事ってあると思います。「あー、このプロンプト、、、期待した結果が返ってこないわ、、、」「Few-shotの例をもっと増やした方がいいのか、、、?」「Chain of Thoughtを使ったほうが、、、?」みたいな試行錯誤をずっと繰り返しているのではないでしょうか?

今の多くのAIアプリケーションはプロンプトを手動で調整していますよね?でも正直、この手動のプロンプティングってすごく非効率だと思いませんか?

その理由はこれが一つあると思っています。

プロンプトって結局文字列なので、バージョン管理もテストも再利用も難しい

じゃあどうすんだい!への一つの答えがDSPyである、と言えます。

DSPyってなんだ?

はい、突然出ましたDSPyです。

スタンフォードNLPグループが開発したDSPyは、「プロンプトではなくプログラミングで基盤モデルを構築する」ためのフレームワークとして登場しました。

もうちょっとわかりやすく言うと、「プロンプトを手動で書く代わりに、プログラムでLLMの動作を定義できるフレームワーク」です!

弊社CTOも関わっておりますが、現在はOSSとして勢いを増しています(GitHubのスター27.9k!!!)

ほら、ちょっと気になってきたのでは?

例えばの例を書きますね、プロンプティングです。従来のアプローチだと、こんな感じですよね

prompt = """
あなたは質問に答える専門家です。
以下の質問に対して、正確で簡潔な回答をしてください。
質問: {question}
回答:
"""

DSPyだと、こうなります。

import dspy
class QA(dspy.Signature):
    question = dspy.InputField()
    answer = dspy.OutputField(desc="正確で簡潔な回答")
qa = dspy.ChainOfThought(QA)

なんだかよくわからないな!ってこともあるかもですが要するに、DSPyは「何をしたいか」を定義するだけで、「どうやってプロンプトを書くか」はフレームワークが自動で最適化してくれる、という訳です!

DSPyの何がいいんだい?

もうちょっと伝わってる気もしますが、じゃあ何が良いのかを書いていきますねw

DSPyのアプローチの面白いところは従来のプロンプティングと根本的に違うアプローチを取っている所です。

1. プロンプトからの解放

今までは「このプロンプトで期待した結果が出るんか?出ないんか?」って悩んでたわけですが、DSPyでは「期待する入力と出力の関係」を定義するだけで、実際のプロンプトはDSPyが自動生成・最適化します

2. 自動最適化がゴイスー

DSPyは与えられたデータセットを使って自動でプロンプトを最適化してくれます。手動で「うーん、この例をFew-shotに追加しよう」とか考える必要がないんですよ、、、すごくないです?

3. プログラマブル

DSPyで書いたコードは普通のPythonコードなんですよ、、、これが何を意味しているのか!?

  • バージョン管理可能
  • ユニットテスト可能
  • モジュール化して再利用可能
  • デバッグ可能

可能可能うるせえ!(失礼しました

要するに、「LLMアプリケーションを普通のソフトウェアのように開発できる」!です!

実際どうやるの?

はい!気になってきましたよね?それでは実際の使い方を軽く見ていきましょう!

まずはシンプルなコードから

import dspy
# 0. MLflowのセットアップ(ロギング)
import mlflow
mlflow.dspy.autolog()
# 1. LLMを設定
lm = dspy.LM('databricks/databricks-claude-sonnet-4')
dspy.configure(lm=lm)
# 2. 入出力の形式を定義(Signature)
class QA(dspy.Signature):
    """質問に対して正確な回答を生成する"""
    question = dspy.InputField()
    answer = dspy.OutputField(desc="質問に対する正確で簡潔な回答")
# 3. モジュールを定義
class QAModule(dspy.Module):
    def __init__(self):
        super().__init__()
        self.generate_answer = dspy.ChainOfThought(QA)
    
    def forward(self, question):
        return self.generate_answer(question=question)
# 4. 使用
qa_system = QAModule()
result = qa_system(question="SQLとNoSQLデータベースの違いを教えてください")

はい、できました。

プロンプト書いてませんよ、僕。

これを改善してみる

# まず曖昧な質問で試してみる
question_ambiguous = "SQLとNoSQLデータベースの違いを教えてください"
result_ambiguous = qa_system(question=question_ambiguous)

print("【曖昧な質問】", question_ambiguous)
print("【曖昧な回答】", result_ambiguous.answer)

# プロンプト改善提案用Signature
class PromptImprovement(dspy.Signature):
    original_prompt: str = dspy.InputField()
    original_answer: str = dspy.InputField()
    improvement_points: str = dspy.OutputField()
    improved_prompt: str = dspy.OutputField()

# Predictモジュールを作成
improve_prompt = dspy.Predict(PromptImprovement)

# 曖昧な質問・回答を入力
improvement_result = improve_prompt(
    original_prompt=question_ambiguous,
    original_answer=result_ambiguous.answer
)

print("【改善ポイント】\n", improvement_result.improvement_points)
print("【より良いPrompt例】\n", improvement_result.improved_prompt)

こうすると、プロンプトエンジニアリング自体をAIに任せられるわけです。

# DSPyが自動生成した改善Promptで再質問
question_improved = improvement_result.improved_prompt
result_improved = qa_system(question=question_improved)
print("改善した質問:", question_improved)
print("改善した回答:", result_improved.answer)

できた改善前後の結果を比べてみましょう

改善前後の比較: 改善前

プロンプト

SQLとNoSQLデータベースの違いを教えてください

回答

SQLとNoSQLデータベースの主な違いは以下の通りです:

SQLデータベース(関係データベース)

  • データ構造: テーブル形式で行と列に構造化されたデータ
  • スキーマ: 固定スキーマが必要(事前にテーブル構造を定義)
  • クエリ言語: SQL(Structured Query Language)を使用
  • ACID特性: 強力なACID特性(原子性、一貫性、独立性、永続性)
  • スケーラビリティ: 垂直スケーリング(サーバーの性能向上)が主
  • : MySQL、PostgreSQL、Oracle、SQL Server

NoSQLデータベース

  • データ構造: 柔軟な形式(ドキュメント、キー・バリュー、グラフ、列指向など)
  • スキーマ: スキーマレスまたは動的スキーマ
  • クエリ言語: データベースごとに異なるAPI
  • ACID特性: 結果整合性を重視(BASE特性)
  • スケーラビリティ: 水平スケーリング(サーバー台数増加)が得意
  • : MongoDB、Redis、Cassandra、Neo4j

使い分け

  • SQL: 複雑な関係性、トランザクション処理、データ整合性が重要な場合
  • NoSQL: 大量データ、高速処理、柔軟なデータ構造が必要な場合 【改善ポイント】 元のプロンプトは基本的な質問として適切ですが、以下の点で改善できます:
  1. 具体的な使用場面や業界での実例を求める要素が不足

  2. パフォーマンスや運用面での比較観点が明示されていない

  3. 学習者のレベル(初心者/中級者/上級者)が不明確

  4. 実際の選択基準や判断材料についての言及がない

  5. 現代的な技術トレンドやハイブリッド型データベースへの言及が促されていない 【より良いPrompt例】 SQLとNoSQLデータベースの違いについて、以下の観点から詳しく説明してください:

  6. 基本的な特徴の比較(データ構造、スキーマ、クエリ言語、ACID特性)

  7. パフォーマンスとスケーラビリティの違い

  8. 具体的な使用場面と業界での実例

  9. 選択する際の判断基準(どのような要件の時にどちらを選ぶべきか)

  10. 代表的な製品例とそれぞれの特徴

  11. 運用・保守面での違い(コスト、人材要件など)

  12. 現代的なトレンド(NewSQLやマルチモデルデータベースなど)

初心者にも理解しやすいよう、具体例を交えて説明し、実際のシステム設計で参考になる実践的な情報も含めてください。

改善前後の比較: 改善後

プロンプト

SQLとNoSQLデータベースの違いについて、以下の観点から詳しく説明してください:

  1. 基本的な特徴の比較(データ構造、スキーマ、クエリ言語、ACID特性)
  2. パフォーマンスとスケーラビリティの違い
  3. 具体的な使用場面と業界での実例
  4. 選択する際の判断基準(どのような要件の時にどちらを選ぶべきか)
  5. 代表的な製品例とそれぞれの特徴
  6. 運用・保守面での違い(コスト、人材要件など)
  7. 現代的なトレンド(NewSQLやマルチモデルデータベースなど)

初心者にも理解しやすいよう、具体例を交えて説明し、実際のシステム設計で参考になる実践的な情報も含めてください。

回答

SQLとNoSQLデータベースの包括的比較

1. 基本的な特徴の比較

データ構造

  • SQL(リレーショナル):テーブル形式で行と列によるデータ格納
    • 例:顧客テーブル(ID、名前、メール、住所)
  • NoSQL:多様な形式
    • ドキュメント型:JSON形式(MongoDB)
    • キー・バリュー型:単純なペア(Redis)
    • カラム型:列指向(Cassandra)
    • グラフ型:ノードと関係(Neo4j)

スキーマ

  • SQL:固定スキーマ(事前定義必須)
    CREATE TABLE users (
      id INT PRIMARY KEY,
      name VARCHAR(100) NOT NULL,
      email VARCHAR(255) UNIQUE
    );
    
  • NoSQL:柔軟なスキーマ(スキーマレス)
    // 異なる構造のドキュメントが同じコレクションに共存可能
    {"name": "田中", "email": "tanaka@example.com"}
    {"name": "佐藤", "phone": "090-1234-5678", "age": 30}
    

クエリ言語

  • SQL:標準化されたSQL言語
  • NoSQL:製品固有のAPI(統一性なし)

ACID特性

  • SQL:完全なACID保証
  • NoSQL:BASE原則(結果整合性)、一部製品でACID対応

2. パフォーマンスとスケーラビリティ

パフォーマンス

  • SQL

    • 複雑なクエリに強い
    • JOINが多い場合は性能低下
    • インデックス最適化が重要
  • NoSQL

    • 単純な読み書きが高速
    • 大量データの並列処理に優れる
    • 複雑な集計は苦手

スケーラビリティ

  • SQL:垂直スケーリング(スケールアップ)が主流

    • サーバーのCPU・メモリ増強
    • 水平分散は複雑
  • NoSQL:水平スケーリング(スケールアウト)が得意

    • サーバー台数を増やして分散処理
    • 自動シャーディング機能

3. 具体的な使用場面と実例

SQL適用例

  • 金融システム:銀行の勘定系(三菱UFJ銀行)
  • ECサイト:在庫・注文管理(楽天市場)
  • ERP:企業資源管理(SAP)
  • 会計システム:複雑な帳簿処理

NoSQL適用例

  • SNS:Facebook(ユーザープロフィール)
  • 動画配信:Netflix(視聴履歴・推薦)
  • IoT:Tesla(車両データ収集)
  • ゲーム:ポケモンGO(位置情報・プレイヤーデータ)

4. 選択する際の判断基準

SQLを選ぶべき場合

  • データの整合性が最重要
  • 複雑なクエリが頻繁
  • トランザクション処理が必要
  • 既存システムとの連携重視
  • 例:会計システム、在庫管理

NoSQLを選ぶべき場合

  • 大量データの高速処理
  • スキーマ変更が頻繁
  • 水平スケーリングが必要
  • 開発速度重視
  • 例:ログ解析、リアルタイム分析

5. 代表的な製品例

SQL系

  • MySQL:Web系で人気、オープンソース
  • PostgreSQL:高機能、JSON対応
  • Oracle:エンタープライズ向け、高性能
  • SQL Server:Microsoft製品との親和性

NoSQL系

  • MongoDB:ドキュメント型、開発しやすい
  • Redis:インメモリ、キャッシュ用途
  • Cassandra:大規模分散、高可用性
  • DynamoDB:AWS管理型、サーバーレス

6. 運用・保守面での違い

コスト面

  • SQL

    • ライセンス費用(Oracle等)
    • 専門人材の確保が比較的容易
    • 運用ツールが豊富
  • NoSQL

    • オープンソース中心で低コスト
    • クラウド管理型サービス活用
    • 専門知識を持つ人材が少ない

人材要件

  • SQL:多くのエンジニアが習得済み
  • NoSQL:製品固有の知識が必要

7. 現代的なトレンド

NewSQL

  • 特徴:SQLの使いやすさ + NoSQLのスケーラビリティ
  • 製品例
    • Google Spanner:グローバル分散ACID
    • CockroachDB:PostgreSQL互換
    • TiDB:MySQL互換

マルチモデルデータベース

  • Azure Cosmos DB:複数のAPIに対応
  • Amazon DocumentDB:MongoDB互換
  • ArangoDB:ドキュメント・グラフ・キーバリュー対応

クラウドネイティブ

  • サーバーレス化の進展
  • 自動スケーリング機能
  • 管理負荷の軽減

実践的な選択指針

段階的アプローチ

  1. 要件分析:整合性 vs 性能・スケーラビリティ
  2. プロトタイプ:小規模で両方試す
  3. ハイブリッド構成:用途別に使い分け

現実的な判断

  • 既存チームのスキル
  • 運用体制の整備状況
  • 将来の拡張性要件
  • 予算制約

多くの現代的なシステムでは、SQLとNoSQLを適材適所で組み合わせる「ポリグロット永続化」が主流となっています。

どうでしょう?

全然違いましたよね!

更には、他にも以下のような事、

  • 最適なFew-shot例を選択
  • プロンプトの構造を調整
  • Chain of Thoughtの使い方を最適化

などもしてくれるわけです。これまで手動で試行錯誤していたことが、ある程度コードに任せられるわけですね!嬉しいね!

どんなユースケースに向いてる?

ではどんなユースケースで使えそうかですが、個人的には以下のようなケースでDSPyが威力を発揮すると思います

スモールスタートから本格運用まで(なんでもやん)
最初は簡単なSignatureから始めて、データが集まってきたら自動最適化で改善していく、みたいな使い方ができる

複雑なパイプライン
複数のLLM呼び出しを組み合わせる場合、従来だと各段階でプロンプトを手動調整する必要がありました
DSPyなら全体を通して自動最適化可能です

チーム開発
プロンプトが文字列じゃなくてコードになるので、レビューもしやすく、変更履歴も追いやすいメリットがあります

今日から使えるDSPyです!

DSPyどうでしたでしょう?

そんなこんなでDSPyの最初の一歩的な記事を書いてみましたが、どうでしたでしょう?

私が思うところは端的に言えばこれです。

「プロンプトエンジニアリングからプログラマブルなLLMアプリケーション開発へ」

DSPy!是非触れてみてください!

コメントを残す

Trending