🦒

[promptfoo] プロンプトを TS で管理して評価しよう

に公開

こんにちは。PeopleXエンジニアの竹内です。

弊社では promptfoo を用いたプロンプトの評価基盤も試験的に導入していました。最近では Langfuse を試したりと、引き続き LLM Ops に関してはあれこれ波乱万丈ですが、その中でも promptfoo を色々触っていた時期の供養(?)としてアドベントカレンダーにて知見を残していこうと思います。

promptfoo 自体はシンプルでサクッと使えますが、ドキュメントに載ってないユースケースを考えた時にどうしようかな?となるシーンもあるため、なるべく記事に残しておきたいなと思ったのがきっかけです

promptfoo のプロンプト管理方法について

promptfoo にはプロンプトの管理方法として以下があります。

  • 設定ファイル(.yaml)直記入
  • 別ファイル .txt .md .j2 .json ファイルに別だし
  • 動的プロンプトとして管理
    • JS
    • Python
  • .sh のような実行可能スクリプトで管理

プロダクトにプロンプトを埋め込む際、テンプレート管理したり状況によって差し込む文章を変えたりと、大枠は決まっていても、いくつか中身が異なる動的プロンプトとして管理することも多いかと思います。

その場合、ドキュメントに記載の JS での書き方に補足する形で TypeScript の場合の書き方を紹介します。

config ファイル

promptfoo の設定ファイルは下記の通りです。
プロンプトを .ts ファイルで外部指定します。プロバイダの設定は見ての通りですが、引数で使いたいデータは test-cases.yaml に定義します。

# yaml-language-server: $schema=https://promptfoo.dev/config-schema.json

# Learn more about building a configuration: https://promptfoo.dev/docs/configuration/guide

description: "daily recipie evaluations"

prompts:
  - file://prompts/recipie.ts

providers:
  - openai:gpt-4.1-mini
  - openai:gpt-4.1

tests:
  - file://test-cases.yaml

プロンプト

string を返す関数を定義し、プロンプトのテンプレートとして提供しつつつ、 promptfoo から実行する際は デフォルトエクスポートしている 関数から呼び出せます。

import { ApiProvider } from "promptfoo";

export const recipiePrompt = (
  assistant_role: string,
  items: string[],
) => `
あなたは${assistant_role}です。

以下の素材を使って、今日の晩御飯の献立を考えてください
`${items.join(",")}`
`;

type PromptVars = {
  assistant_role: string;
  items: string[]
}

export default function({ vars, _provider_ }: { vars: PromptVars, _provider: ApiProvider }) {
  return recipiePrompt (
    vars.assistant_role || "中華料理に強い料理人",
    vars.items || ["玉ねぎ", "長ネギ", "にら", "ひき肉" ],
  );
};

テストケース

テストケースごとに使う引数を変えられます。

- description: 中華料理人として中華料理のレシピを考えてくれる
  vars:
    assistant_role: 中華料理に強い料理人
    items: ["玉ねぎ", "長ネギ", "にら", "ひき肉"]
  assert:
    - type: llm-rubric
      value: 関係ないジャンルではなく中華料理のレシピを考えてくれる
    - type: llm-rubric
      value: 指定した素材以外を使うレシピでないこと
      
- description: イタリア料理人としてイタリア料理のレシピを考えてくれる
  vars:
    assistant_role: イタリア料理に強い料理人
    items: ["トマト", "バジル", "モッツァレラチーズ", "オリーブオイル"]
  assert:
    - type: llm-rubric
      value: 関係ないジャンルではなくイタリア料理のレシピを考えてくれる
    - type: llm-rubric
      value: 指定した素材以外を使うレシピでないこと

まとめ

上記のようにすることで、プロダクトからもプロンプトを読み込みつつ、promptfoo からもプロンプトの評価ができるようになります。

個人的には promptfoo の使い勝手は好きなので、個人開発で Langfuse を使うほどでもないけど、プロンプトの評価はしていきたいな、というときにガシガシ使っていきたいです。

/以上

GitHubで編集を提案
PeopleXテックブログ

Discussion