0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LangChain ToolsとFunction Calling:自然言語による柔軟な制御の仕組み

0
Posted at

LangChain ToolsとFunction Calling:自然言語による柔軟な制御の仕組み

はじめに

LangChainのToolsとFunction Callingは、LLMが外部ツールを呼び出すための強力なメカニズムです。特に、Descriptionに自然言語でプロンプトを記述することで、複雑なルールをコーディングすることなく、LLMにツールの使用方法を理解させることができます。この記事では、この仕組みがなぜ有効で優れているのか、従来のアプローチとの比較を通じて詳しく解説します。

ToolsとFunction Callingの基本概念

Function Callingとは

Function Callingは、LLMが外部の関数(ツール)を呼び出すための仕組みです。LLMは、自然言語で記述された関数の説明を理解し、適切なタイミングで関数を呼び出します。

基本的な構造

import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";

// ツールの定義
const tool = new DynamicStructuredTool({
  name: "get_weather",
  description: "指定された都市の現在の天気情報を取得します。都市名は完全な名前で指定してください。",
  schema: z.object({
    city: z.string().describe("天気を取得する都市名(例: 東京、New York)"),
  }),
  func: async ({ city }) => {
    // 実際の実装
    return `${city}の天気: 晴れ、気温22度`;
  },
});

Descriptionにプロンプトを記述する重要性

従来のアプローチとの比較

従来のアプローチ:複雑なルールをコーディング

// 従来のアプローチ:複雑な条件分岐とルールをコーディング
class WeatherService {
  async getWeather(city) {
    // 都市名の正規化
    const normalizedCity = this.normalizeCityName(city);
    
    // バリデーション
    if (!this.isValidCity(normalizedCity)) {
      throw new Error("無効な都市名です");
    }
    
    // キャッシュチェック
    if (this.cache.has(normalizedCity)) {
      return this.cache.get(normalizedCity);
    }
    
    // API呼び出し
    const weather = await this.apiClient.getWeather(normalizedCity);
    
    // キャッシュに保存
    this.cache.set(normalizedCity, weather);
    
    return weather;
  }
  
  normalizeCityName(city) {
    // 複雑な正規化ロジック
    const cityMap = {
      "tokyo": "Tokyo",
      "toukyou": "Tokyo",
      "東京": "Tokyo",
      // ... 数百のマッピング
    };
    return cityMap[city.toLowerCase()] || city;
  }
  
  isValidCity(city) {
    // 複雑なバリデーションロジック
    const validCities = ["Tokyo", "Osaka", "Kyoto", /* ... */];
    return validCities.includes(city);
  }
}

// LLMに渡す際の複雑なプロンプト
const prompt = `
天気を取得するには、以下のルールに従ってください:
1. 都市名を正規化する必要があります
2. 以下の都市のみサポートされています: ${validCities.join(", ")}
3. キャッシュを確認してからAPIを呼び出してください
4. エラーハンドリングが必要です
...
`;

LangChainのアプローチ:Descriptionに自然言語で記述

import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";

// Descriptionに自然言語でルールを記述
const weatherTool = new DynamicStructuredTool({
  name: "get_weather",
  description: `
天気情報を取得するツールです。

使用方法:
- 都市名は完全な名前で指定してください(例: "Tokyo", "New York")
- 日本語の都市名も使用可能です(例: "東京", "大阪")
- 都市名が不明確な場合は、最も一般的な表記を使用してください
- エラーが発生した場合は、エラーメッセージをそのまま返してください

注意事項:
- このツールは現在の天気情報のみを返します
- 過去や未来の天気情報は取得できません
- キャッシュ機能が自動的に動作します
  `,
  schema: z.object({
    city: z.string().describe("天気を取得する都市名。完全な名前で指定してください。"),
  }),
  func: async ({ city }) => {
    // シンプルな実装(LLMが適切な入力を提供するため、複雑な正規化が不要)
    return await fetchWeather(city);
  },
});

なぜDescriptionが重要なのか

1. LLMが自然言語を理解する

// LLMは自然言語の説明を理解し、適切にツールを呼び出す
const tool = new DynamicStructuredTool({
  name: "calculate_discount",
  description: `
割引を計算するツールです。

ルール:
- 通常価格と割引率(パーセント)を受け取ります
- 割引率は0から100の間の数値である必要があります
- 割引後の価格を計算して返します
- 割引率が100を超える場合は、エラーを返します
- 割引率が負の数の場合も、エラーを返します

計算式: 割引後価格 = 通常価格 × (1 - 割引率 / 100)

例:
- 通常価格: 1000円、割引率: 10% → 割引後価格: 900円
- 通常価格: 5000円、割引率: 20% → 割引後価格: 4000円
  `,
  schema: z.object({
    originalPrice: z.number().describe("通常価格(円)"),
    discountRate: z.number().describe("割引率(0-100のパーセント)"),
  }),
  func: async ({ originalPrice, discountRate }) => {
    // LLMが適切な入力を提供するため、バリデーションが簡素化
    if (discountRate < 0 || discountRate > 100) {
      return `エラー: 割引率は0から100の間である必要があります`;
    }
    const discountedPrice = originalPrice * (1 - discountRate / 100);
    return `割引後価格: ${discountedPrice}円(割引額: ${originalPrice - discountedPrice}円)`;
  },
});

2. 柔軟性と拡張性

// Descriptionを更新するだけで、動作を変更できる
const searchTool = new DynamicStructuredTool({
  name: "search_products",
  description: `
商品を検索するツールです。

検索方法:
- キーワード検索: 商品名、説明、カテゴリから検索
- 価格範囲検索: minPriceとmaxPriceを指定
- カテゴリ検索: 特定のカテゴリのみを検索
- 複合検索: 上記の条件を組み合わせて検索

検索の優先順位:
1. 商品名の完全一致
2. 商品名の部分一致
3. 説明文の一致
4. カテゴリの一致

注意事項:
- 検索結果は最大50件まで返します
- 結果は関連性の高い順にソートされます
- 価格範囲を指定する場合、両方の値を指定してください
  `,
  schema: z.object({
    keyword: z.string().optional().describe("検索キーワード"),
    category: z.string().optional().describe("カテゴリ名"),
    minPrice: z.number().optional().describe("最小価格"),
    maxPrice: z.number().optional().describe("最大価格"),
  }),
  func: async ({ keyword, category, minPrice, maxPrice }) => {
    // Descriptionに記述されたルールに基づいて、LLMが適切なパラメータを提供
    return await searchProducts({ keyword, category, minPrice, maxPrice });
  },
});

なぜこのアプローチが優れているのか

1. コードの簡素化

従来のアプローチ

// 複雑なルールをコーディングする必要がある
class ProductSearch {
  async search(params) {
    // バリデーション
    if (params.minPrice && params.maxPrice && params.minPrice > params.maxPrice) {
      throw new Error("最小価格は最大価格以下である必要があります");
    }
    
    // キーワードの正規化
    const normalizedKeyword = this.normalizeKeyword(params.keyword);
    
    // 検索ロジック
    let results = [];
    if (normalizedKeyword) {
      results = await this.searchByKeyword(normalizedKeyword);
    }
    
    // カテゴリフィルタ
    if (params.category) {
      results = this.filterByCategory(results, params.category);
    }
    
    // 価格フィルタ
    if (params.minPrice || params.maxPrice) {
      results = this.filterByPrice(results, params.minPrice, params.maxPrice);
    }
    
    // ソート
    results = this.sortByRelevance(results);
    
    // 結果の制限
    return results.slice(0, 50);
  }
  
  normalizeKeyword(keyword) {
    // 複雑な正規化ロジック
    return keyword.trim().toLowerCase();
  }
  
  // ... 多くのヘルパーメソッド
}

LangChainのアプローチ

// Descriptionにルールを記述するだけで、LLMが適切に処理
const searchTool = new DynamicStructuredTool({
  name: "search_products",
  description: `
商品を検索します。

検索条件:
- keyword: 検索キーワード(オプション)
- category: カテゴリ名(オプション)
- minPrice: 最小価格(オプション、maxPriceと一緒に使用)
- maxPrice: 最大価格(オプション、minPriceと一緒に使用)

ルール:
- minPriceを指定する場合、maxPriceも指定してください
- minPriceはmaxPrice以下である必要があります
- キーワードは自動的に正規化されます
- 結果は関連性の高い順にソートされ、最大50件返されます
  `,
  schema: z.object({
    keyword: z.string().optional().describe("検索キーワード"),
    category: z.string().optional().describe("カテゴリ名"),
    minPrice: z.number().optional().describe("最小価格(maxPriceと一緒に使用)"),
    maxPrice: z.number().optional().describe("最大価格(minPriceと一緒に使用)"),
  }),
  func: async (params) => {
    // LLMが適切なパラメータを提供するため、バリデーションが簡素化
    return await searchProducts(params);
  },
});

2. 保守性の向上

// ルールを変更する場合、Descriptionを更新するだけ
const orderTool = new DynamicStructuredTool({
  name: "create_order",
  description: `
注文を作成します。

注文ルール(2024年12月更新):
- 最小注文金額: 1,000円
- 最大注文金額: 100,000円
- 配送料: 購入金額が5,000円以上の場合無料、それ以外は500円
- 支払い方法: クレジットカード、銀行振込、コンビニ決済
- 在庫確認: 注文前に在庫を自動確認します
- キャンセル: 注文後24時間以内はキャンセル可能

注意事項:
- 在庫がない場合は、代替商品を提案します
- 配送先が離島の場合は、追加料金が発生する場合があります
  `,
  schema: z.object({
    items: z.array(z.object({
      productId: z.string(),
      quantity: z.number(),
    })).describe("注文する商品のリスト"),
    paymentMethod: z.enum(["credit_card", "bank_transfer", "convenience_store"]).describe("支払い方法"),
    shippingAddress: z.string().describe("配送先住所"),
  }),
  func: async (params) => {
    // Descriptionに記述されたルールに基づいて、LLMが適切な入力を提供
    return await createOrder(params);
  },
});

// ルールが変更された場合、Descriptionを更新するだけで対応可能
// コードの変更が最小限で済む

3. エラーハンドリングの簡素化

// Descriptionにエラーハンドリングのルールを記述
const dataProcessingTool = new DynamicStructuredTool({
  name: "process_data",
  description: `
データを処理します。

処理ルール:
- 入力データはJSON形式である必要があります
- データが無効な場合、エラーメッセージを返します
- データが大きすぎる場合(10MB以上)、エラーを返します
- 処理に時間がかかる場合(30秒以上)、タイムアウトエラーを返します

エラーハンドリング:
- エラーが発生した場合、エラーの種類と原因を明確に返します
- リトライ可能なエラーの場合、自動的にリトライします
- リトライ不可能なエラーの場合、エラーメッセージを返します
  `,
  schema: z.object({
    data: z.string().describe("処理するデータ(JSON形式)"),
    operation: z.enum(["filter", "sort", "aggregate", "transform"]).describe("実行する操作"),
  }),
  func: async ({ data, operation }) => {
    // LLMが適切な入力を提供し、エラーハンドリングが簡素化
    try {
      const parsedData = JSON.parse(data);
      return await processData(parsedData, operation);
    } catch (error) {
      return `エラー: 無効なJSON形式です。${error.message}`;
    }
  },
});

4. 動的な動作の実現

// Descriptionに動的なルールを記述することで、柔軟な動作を実現
const recommendationTool = new DynamicStructuredTool({
  name: "get_recommendations",
  description: `
商品のレコメンデーションを取得します。

レコメンデーションアルゴリズム:
- ユーザーの過去の購入履歴を分析
- 類似ユーザーの購入履歴を参照
- 商品の評価とレビューを考慮
- 季節やトレンドを反映

パラメータ:
- userId: ユーザーID(必須)
- category: カテゴリ(オプション、指定するとそのカテゴリのみ)
- limit: 返す件数(デフォルト: 10、最大: 50)

注意事項:
- ユーザーの好みに基づいてパーソナライズされます
- 新規ユーザーの場合、人気商品を推薦します
- 在庫がない商品は除外されます
  `,
  schema: z.object({
    userId: z.string().describe("ユーザーID"),
    category: z.string().optional().describe("カテゴリ名(オプション)"),
    limit: z.number().optional().describe("返す件数(デフォルト: 10、最大: 50)"),
  }),
  func: async ({ userId, category, limit = 10 }) => {
    // Descriptionに記述されたルールに基づいて、LLMが適切なパラメータを提供
    return await getRecommendations({ userId, category, limit });
  },
});

実践的な例

例1:複雑なビジネスルールの実装

// 複雑なビジネスルールをDescriptionに記述
const bookingTool = new DynamicStructuredTool({
  name: "book_appointment",
  description: `
予約を作成します。

予約ルール:
1. 営業時間: 平日 9:00-18:00、土曜 9:00-13:00、日曜・祝日は休業
2. 予約可能時間: 30分単位(例: 9:00, 9:30, 10:00)
3. 予約のキャンセル: 24時間前まで可能
4. 予約の変更: 48時間前まで可能
5. 最大予約数: 1人あたり1日3件まで
6. 予約の重複: 同じ時間帯に複数の予約は不可

特別ルール:
- 新規顧客の場合、初回予約は10%割引
- リピーター(3回以上)の場合、5%割引
- キャンセル料: 24時間以内のキャンセルは50%のキャンセル料

エラーハンドリング:
- 営業時間外の予約: エラーメッセージを返す
- 予約可能時間外: 最も近い予約可能時間を提案
- 予約の重複: 代替時間を提案
  `,
  schema: z.object({
    customerId: z.string().describe("顧客ID"),
    serviceId: z.string().describe("サービスID"),
    dateTime: z.string().describe("予約希望日時(YYYY-MM-DD HH:mm形式)"),
  }),
  func: async ({ customerId, serviceId, dateTime }) => {
    // Descriptionに記述されたルールに基づいて、LLMが適切な入力を提供
    // 複雑なバリデーションロジックが不要
    return await bookAppointment({ customerId, serviceId, dateTime });
  },
});

例2:データ変換ツール

// データ変換のルールをDescriptionに記述
const dataTransformTool = new DynamicStructuredTool({
  name: "transform_data",
  description: `
データを変換します。

変換ルール:
- 日付形式: YYYY-MM-DD形式に統一
- 数値形式: カンマ区切りを削除し、数値に変換
- 文字列: 前後の空白を削除、大文字小文字を統一
- null値: 空文字列に変換
- 配列: 重複を削除、ソート

変換タイプ:
- normalize: データの正規化(デフォルト)
- format: フォーマットの統一
- validate: バリデーションとエラー検出
- clean: 不要なデータの削除

注意事項:
- 変換前のデータ形式を自動検出
- 変換できないデータはエラーとして返す
- 変換ログを保持
  `,
  schema: z.object({
    data: z.string().describe("変換するデータ(JSON形式)"),
    transformType: z.enum(["normalize", "format", "validate", "clean"]).describe("変換タイプ"),
  }),
  func: async ({ data, transformType }) => {
    // Descriptionに記述されたルールに基づいて、LLMが適切な入力を提供
    return await transformData(data, transformType);
  },
});

例3:複数のツールを組み合わせた例

// 各ツールのDescriptionに詳細なルールを記述
const tools = [
  new DynamicStructuredTool({
    name: "search_products",
    description: `
商品を検索します。

検索方法:
- キーワード検索: 商品名、説明、カテゴリから検索
- 価格範囲: minPriceとmaxPriceを指定(両方必要)
- カテゴリ: 特定のカテゴリのみ検索
- 在庫: 在庫がある商品のみ検索

検索の優先順位:
1. 商品名の完全一致
2. 商品名の部分一致
3. 説明文の一致

注意事項:
- 検索結果は最大50件
- 結果は関連性順にソート
- 価格範囲を指定する場合、両方の値を指定
    `,
    schema: z.object({
      keyword: z.string().optional().describe("検索キーワード"),
      category: z.string().optional().describe("カテゴリ名"),
      minPrice: z.number().optional().describe("最小価格"),
      maxPrice: z.number().optional().describe("最大価格"),
      inStock: z.boolean().optional().describe("在庫がある商品のみ"),
    }),
    func: async (params) => await searchProducts(params),
  }),
  
  new DynamicStructuredTool({
    name: "get_product_details",
    description: `
商品の詳細情報を取得します。

取得する情報:
- 商品名、説明、価格
- 在庫状況
- 評価とレビュー
- 関連商品
- 配送情報

注意事項:
- 商品IDは必須
- 存在しない商品IDの場合、エラーを返す
- 在庫がない場合、入荷予定日を表示
    `,
    schema: z.object({
      productId: z.string().describe("商品ID"),
    }),
    func: async ({ productId }) => await getProductDetails(productId),
  }),
  
  new DynamicStructuredTool({
    name: "add_to_cart",
    description: `
カートに商品を追加します。

追加ルール:
- 商品IDと数量を指定
- 在庫がない場合はエラー
- 数量は1以上、在庫数以下
- 既にカートにある場合、数量を更新

注意事項:
- カートの最大商品数: 50件
- カートの最大合計金額: 100,000円
- これらの制限を超える場合、エラーを返す
    `,
    schema: z.object({
      productId: z.string().describe("商品ID"),
      quantity: z.number().describe("数量(1以上)"),
    }),
    func: async ({ productId, quantity }) => await addToCart(productId, quantity),
  }),
];

// LLMは各ツールのDescriptionを理解し、適切にツールを選択・使用
const agent = await createOpenAIFunctionsAgent({
  llm,
  tools,
  prompt,
});

なぜこのアプローチが機能するのか

1. LLMの自然言語理解能力

// LLMは自然言語の説明を理解し、適切にツールを呼び出す
const tool = new DynamicStructuredTool({
  name: "calculate_tax",
  description: `
税金を計算します。

計算ルール:
- 消費税率: 10%(2024年現在)
- 軽減税率: 8%(食品、新聞など)
- 計算式: 税込価格 = 税抜価格 × (1 + 税率 / 100)
- 端数処理: 切り捨て

例:
- 税抜価格: 1000円、税率: 10% → 税込価格: 1100円
- 税抜価格: 500円、税率: 8% → 税込価格: 540円

注意事項:
- 税率は0から100の間である必要があります
- 負の税率は使用できません
  `,
  schema: z.object({
    price: z.number().describe("税抜価格"),
    taxRate: z.number().describe("税率(0-100のパーセント)"),
  }),
  func: async ({ price, taxRate }) => {
    // LLMがDescriptionを理解し、適切な入力を提供
    // 複雑なバリデーションロジックが不要
    if (taxRate < 0 || taxRate > 100) {
      return "エラー: 税率は0から100の間である必要があります";
    }
    const totalPrice = Math.floor(price * (1 + taxRate / 100));
    return `税込価格: ${totalPrice}円(税額: ${totalPrice - price}円)`;
  },
});

2. プロンプトエンジニアリングの効果

// 効果的なDescriptionの書き方
const effectiveTool = new DynamicStructuredTool({
  name: "process_order",
  description: `
注文を処理します。

【重要】処理の流れ:
1. 在庫確認 → 在庫がない場合はエラー
2. 価格計算 → 割引適用、送料計算
3. 支払い処理 → 支払い方法に応じた処理
4. 注文確定 → 在庫を減らし、注文を確定

【ルール】
- 最小注文金額: 1,000円
- 最大注文金額: 100,000円
- 送料: 5,000円以上で無料、それ以外は500円
- 支払い方法: クレジットカード、銀行振込、コンビニ決済

【エラーハンドリング】
- 在庫不足: 在庫数を表示し、代替商品を提案
- 金額制限超過: エラーメッセージと制限内容を表示
- 支払いエラー: 支払い方法の変更を提案

【例】
入力: { items: [{id: "P001", qty: 2}], payment: "credit_card" }
出力: 注文確定、合計金額: 2,000円、送料: 500円、総額: 2,500円
  `,
  schema: z.object({
    items: z.array(z.object({
      productId: z.string(),
      quantity: z.number(),
    })),
    paymentMethod: z.enum(["credit_card", "bank_transfer", "convenience_store"]),
  }),
  func: async (params) => await processOrder(params),
});

3. スキーマとDescriptionの連携

// Schemaの説明とDescriptionを連携させる
const tool = new DynamicStructuredTool({
  name: "analyze_sentiment",
  description: `
テキストの感情分析を行います。

分析内容:
- 感情の種類: ポジティブ、ネガティブ、ニュートラル
- 感情の強度: 0.0から1.0のスコア
- キーワード: 感情に影響を与えるキーワードを抽出

分析ルール:
- 日本語と英語の両方に対応
- スラングや略語も認識
- 文脈を考慮した分析

出力形式:
- sentiment: 感情の種類
- score: 感情の強度(0.0-1.0)
- keywords: 影響を与えるキーワードのリスト
  `,
  schema: z.object({
    text: z.string().describe("分析するテキスト(日本語または英語)"),
    language: z.enum(["auto", "ja", "en"]).describe("言語(auto: 自動検出、ja: 日本語、en: 英語)"),
  }),
  func: async ({ text, language }) => {
    // DescriptionとSchemaの説明が連携し、LLMが適切な入力を提供
    return await analyzeSentiment(text, language);
  },
});

ベストプラクティス

1. Descriptionの書き方

// ✅ 良い例:明確で詳細な説明
const goodTool = new DynamicStructuredTool({
  name: "calculate_shipping",
  description: `
配送料を計算します。

計算ルール:
- 地域別の基本料金を適用
- 重量に応じた追加料金を計算
- サイズが大きい場合は追加料金

地域区分:
- 本州: 基本料金 500円
- 北海道・沖縄: 基本料金 1,000円
- 離島: 基本料金 1,500円

重量料金:
- 1kg以下: 無料
- 1-5kg: +200円
- 5-10kg: +500円
- 10kg以上: +1,000円

注意事項:
- 重量とサイズの両方を考慮
- 複数の商品がある場合、合計重量で計算
  `,
  // ...
});

// ❌ 悪い例:曖昧で不十分な説明
const badTool = new DynamicStructuredTool({
  name: "calculate_shipping",
  description: "配送料を計算します", // 情報が不足
  // ...
});

2. エラーメッセージの記述

// Descriptionにエラーハンドリングのルールを記述
const tool = new DynamicStructuredTool({
  name: "validate_email",
  description: `
メールアドレスを検証します。

検証ルール:
- メールアドレスの形式をチェック
- ドメインの存在を確認
- 無効なメールアドレスの場合、エラーメッセージを返す

エラーメッセージ:
- 形式エラー: "メールアドレスの形式が正しくありません"
- ドメインエラー: "ドメインが存在しません"
- その他: "メールアドレスが無効です"

有効な例:
- user@example.com
- test.user@example.co.jp

無効な例:
- user@ (ドメインがない)
- @example.com (ユーザー名がない)
- user example.com (@がない)
  `,
  schema: z.object({
    email: z.string().describe("検証するメールアドレス"),
  }),
  func: async ({ email }) => {
    // Descriptionに記述されたルールに基づいて、LLMが適切に処理
    return await validateEmail(email);
  },
});

3. 例の提供

// Descriptionに具体例を含める
const tool = new DynamicStructuredTool({
  name: "format_date",
  description: `
日付をフォーマットします。

フォーマット形式:
- YYYY-MM-DD: 2024-12-09
- DD/MM/YYYY: 09/12/2024
- YYYY年MM月DD日: 2024年12月09日
- 相対日付: 今日、明日、昨日

使用例:
- 入力: "2024-12-09", 形式: "YYYY-MM-DD" → 出力: "2024-12-09"
- 入力: "2024-12-09", 形式: "DD/MM/YYYY" → 出力: "09/12/2024"
- 入力: "today", 形式: "YYYY-MM-DD" → 出力: 今日の日付

注意事項:
- 無効な日付形式の場合、エラーを返す
- 相対日付は現在の日付を基準に計算
  `,
  schema: z.object({
    date: z.string().describe("フォーマットする日付"),
    format: z.enum(["YYYY-MM-DD", "DD/MM/YYYY", "YYYY年MM月DD日"]).describe("フォーマット形式"),
  }),
  func: async ({ date, format }) => await formatDate(date, format),
});

まとめ

LangChainのToolsとFunction Callingは、Descriptionに自然言語でプロンプトを記述することで、複雑なルールをコーディングすることなく、LLMにツールの使用方法を理解させることができます。

主要な利点

  1. コードの簡素化: 複雑なバリデーションやルールをコーディングする必要がない
  2. 保守性の向上: Descriptionを更新するだけで動作を変更できる
  3. 柔軟性: 自然言語でルールを記述できるため、柔軟な動作が可能
  4. エラーハンドリングの簡素化: Descriptionにエラーハンドリングのルールを記述できる
  5. LLMの理解: LLMが自然言語を理解し、適切にツールを呼び出す

なぜこのアプローチが優れているのか

  1. 自然言語の力: LLMは自然言語を理解するため、複雑なルールを自然言語で記述できる
  2. プロンプトエンジニアリング: 効果的なDescriptionにより、LLMの動作を制御できる
  3. スキーマとの連携: Schemaの説明とDescriptionを連携させることで、より正確な入力を得られる
  4. 拡張性: 新しいルールを追加する場合、Descriptionを更新するだけで対応可能

このアプローチにより、従来の複雑なコーディングを避けながら、柔軟で保守性の高いAIエージェントアプリケーションを構築できます。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?