Closed1

LangChain.jsのPromptTemplateの中で{}を変数以外で使いたい時は{{}}にすればいい

serinuntiusserinuntius

タイトル通りなのですが、PromptTemplateは {variable} を変数として解釈してしまいます。

適当なソースコードを食わせるとSingle '}' in template."というエラーが出て困りました。

ソースコードをPromptTemplateに渡したいときは、変数として解釈されると困ります。
どうすればいいのか特にドキュメントには書いてないので、実装をみてみたら、どうやらPythonの f"" のフォーマットを参考に作られた実装であることがわかりました。ということはもしかすると {{}} を使えば変数として扱われないかもしれません。

ソースコードを読み込んで、どのように処理されているか確認してみましょう。

parseFStringを解説する

export const parseFString = (template: string): ParsedFStringNode[] => {
  // https://github.com/python/cpython/blob/135ec7cefbaffd516b77362ad2b2ad1025af462e/Objects/stringlib/unicode_format.h#L700-L706
  
  const chars = template.split("");
  const nodes: ParsedFStringNode[] = [];

  // 次の開始/終了ブラケットを見つけるためのヘルパー関数です。
  const nextBracket = (bracket: "}" | "{" | "{}", start: number) => {
    for (let i = start; i < chars.length; i += 1) {
      if (bracket.includes(chars[i])) {
        return i;
      }
    }
    return -1;
  };

  let i = 0;
  // 文字列全体をループします。
  while (i < chars.length) {
    // 二つの"{"の場合、"{"をテキストとしてノードに追加します。ここ大事👍
    if (chars[i] === "{" && i + 1 < chars.length && chars[i + 1] === "{") {
      nodes.push({ type: "literal", text: "{" });
      i += 2;
    } 
    // 二つの"}"の場合、"}"をテキストとしてノードに追加します。ここ大事👍
    else if (
      chars[i] === "}" &&
      i + 1 < chars.length &&
      chars[i + 1] === "}"
    ) {
      nodes.push({ type: "literal", text: "}" });
      i += 2;
    } 
    // "{"が単独で現れた場合、次の"}"までを変数としてノードに追加します。
    else if (chars[i] === "{") {
      const j = nextBracket("}", i);
      if (j < 0) {
        throw new Error("Unclosed '{' in template.");
      }

      nodes.push({
        type: "variable",
        name: chars.slice(i + 1, j).join(""),
      });
      i = j + 1;
    } 
    // 単独の"}"が現れた場合、エラーをスローします。
    else if (chars[i] === "}") {
      throw new Error("Single '}' in template.");
    } 
    // 上記のどれでもない場合、次の"{"または"}"までをテキストとしてノードに追加します。
    else {
      const next = nextBracket("{}", i);
      const text = (next < 0 ? chars.slice(i) : chars.slice(i, next)).join("");
      nodes.push({ type: "literal", text });
      i = next < 0 ? chars.length : next;
    }
  }
  // 解析したノードの配列を返します。
  return nodes;
};

ここ大事👍 のところを見ていただけるとわかりますが、{{ が連続した場合literalとして扱われ、変数として扱われないことがわかりました。

まとめ

LangChain.jsのPromptTemplateに変数以外で{} を使いたい場合は {{}} を代わりに使いましょう。

参考文献 https://github.com/hwchase17/langchainjs/blob/a7007bf6a1ae8051f45e8444f44eaaa346009d1e/langchain/src/prompts/template.ts#L9

このスクラップは2023/07/01にクローズされました