Published on

Spring AI (قسمت ششم): استفاده از Function Calling برای تقویت برنامه‌های هوش مصنوعی

نویسندگان

Spring AI (قسمت ششم): استفاده از Function Calling برای تقویت برنامه‌های هوش مصنوعی

مقدمه

یکی از قابلیت‌های کلیدی در Spring AI، پشتیبانی از فراخوانی توابع (Function Calling) است. این ویژگی به مدل هوش مصنوعی اجازه می‌دهد تا درخواست اجرای توابع سمت کلاینت را صادر کرده و بدین ترتیب به اطلاعات مورد نیاز دسترسی پیدا کند یا وظایف خاصی را به صورت پویا اجرا کند.

این قابلیت کاربردهای مختلفی دارد، از جمله:

ارائه اطلاعات لحظه‌ای: مانند اطلاعات آب و هوا یا نرخ ارز که نیاز به داده‌های به‌روز دارند.

تعامل با سیستم‌های داخلی: اجرای توابعی برای دسترسی به داده‌های پایگاه داده یا سیستم‌های مدیریت محتوا.

اتصال به سرویس‌های خارجی: برای انجام وظایفی مانند رزرو بلیط، ارسال پیامک، یا فراخوانی APIهای شخص ثالث.

Spring AI از فراخوانی توابع برای مدل‌های مختلف هوش مصنوعی پشتیبانی می‌کند:

  • Anthropic Claude
  • Azure OpenAI
  • Google VertexAI Gemini
  • Groq
  • Mistral AI
  • Ollama
  • OpenAI

نحوه کارکرد Function Calling

Spring AI این امکان را فراهم می‌کند تا توابع سفارشی جاوا را با استفاده از ChatClient ثبت کنید. این بدان معناست که شما می‌توانید توابعی تعریف کنید که توسط مدل هوش مصنوعی قابل فراخوانی باشند. مدل هوش مصنوعی به صورت هوشمند JSONی تولید می‌کند که حاوی پارامترهای لازم برای فراخوانی یکی از این توابع است. این فرآیند به توسعه‌دهندگان این امکان را می‌دهد که از قابلیت‌های LLM برای اتصال به ابزارها و APIهای خارجی استفاده کنند.

برای مثال، فرض کنید یک تابع Java داریم که وظیفه دارد دمای کنونی یک مکان خاص را از یک سرویس آب و هوایی دریافت کند. زمانی که کاربر از مدل هوش مصنوعی سوالی مانند "دمای کنونی در تهران چقدر است؟" می‌پرسد، مدل به صورت خودکار تشخیص می‌دهد که برای پاسخ به این سوال نیاز به فراخوانی تابعی خاص دارد که دما را دریافت می‌کند. مدل یک JSON تولید می‌کند که شامل پارامترهای لازم برای فراخوانی این تابع است (مثلاً نام مکان). سپس، این JSON در برنامه شما استفاده می‌شود تا تابع مربوطه فراخوانی شود و نتیجه به مدل برگردد.

این JSON توسط API مستقیماً فراخوانی نمی‌شود، بلکه شما می‌توانید از آن در کد خود استفاده کرده و نتیجه را به مدل برگردانید تا مکالمه تکمیل شود. این فرآیند به توسعه‌دهندگان این امکان را می‌دهد که از قابلیت‌های LLM برای اتصال به ابزارها و APIهای خارجی استفاده کنند.

مدل‌های هوش مصنوعی به گونه‌ای آموزش داده شده‌اند که زمان مورد نیاز برای فراخوانی یک تابع را تشخیص دهند و JSONی تولید کنند که با امضای تابع تطابق داشته باشد. این JSON توسط API مستقیماً فراخوانی نمی‌شود، بلکه شما می‌توانید از آن در کد خود استفاده کرده و نتیجه را به مدل برگردانید تا مکالمه تکمیل شود.

فرآیند فراخوانی توابع در Spring AI

تصویر زیر فرآیند فراخوانی توابع در Spring AI را نشان می‌دهد:

Di
  1. تعریف توابع در چت پرامپت: توابع با نام، توضیحات و امضای ورودی تعریف می‌شوند.
  2. درخواست فراخوانی از مدل هوش مصنوعی: مدل هوش مصنوعی درخواست فراخوانی تابع را ارسال می‌کند.
  3. فراخوانی تابع سمت کلاینت: تابع از طریق Spring AI و Function Registry فراخوانی می‌شود.
  4. برگرداندن نتیجه به مدل هوش مصنوعی: نتیجه اجرای تابع به مدل برمی‌گردد.
  5. پاسخ نهایی به کاربر: پاسخ نهایی که شامل نتیجه اجرای تابع است به کاربر ارائه می‌شود.

پیاده‌سازی نمونه

به عنوان مثال، فرض کنید نیاز داریم تا مدل هوش مصنوعی بتواند اطلاعاتی درباره دمای کنونی یک مکان خاص ارائه دهد. ابتدا یک تابع ساده ایجاد می‌کنیم که از یک سرویس آب و هوا استفاده می‌کند و نتیجه را به مدل برمی‌گرداند:

public class MockWeatherService implements Function<Request, Response> {

    public enum Unit { C, F }
    public record Request(String location, Unit unit) {}
    public record Response(double temp, Unit unit) {}

    public Response apply(Request request) {
        return new Response(30.0, Unit.C);
    }
}



ثبت توابع به عنوان Beanها

Spring AI چندین روش برای ثبت توابع سفارشی به عنوان Bean در زمینه Spring فراهم می‌کند.

توابع ساده جاوا

در این روش، شما یک @Bean در زمینه برنامه خود تعریف می‌کنید، همانطور که هر شیء دیگر در Spring مدیریت می‌شود.

به صورت داخلی، Spring AI ChatModel یک نمونه از FunctionCallbackWrapper ایجاد می‌کند که منطق مورد نیاز برای فراخوانی آن از طریق مدل هوش مصنوعی را اضافه می‌کند. نام @Bean به عنوان نام تابع استفاده می‌شود.

@Configuration
static class Config {

    @Bean
    @Description("Get the weather in location") // توضیحات تابع
    public Function<MockWeatherService.Request, MockWeatherService.Response> currentWeather() {
        return new MockWeatherService();
    }
}

حاشیه‌نویسی @Description اختیاری است و توضیحات تابعی را فراهم می‌کند که به مدل کمک می‌کند زمان فراخوانی تابع را تشخیص دهد. این ویژگی برای کمک به مدل هوش مصنوعی جهت تعیین اینکه چه تابعی را فراخوانی کند، اهمیت دارد.

روش دیگری برای ارائه توضیحات تابع استفاده از حاشیه‌نویسی @JsonClassDescription بر روی MockWeatherService.Request است:

@Configuration
static class Config {
    @Bean
    public Function<Request, Response> currentWeather() { // نام Bean به عنوان نام تابع
        return new MockWeatherService();
    }
}

@JsonClassDescription("Get the weather in location") // توضیحات تابع
public record Request(String location, Unit unit) {}

بهتر است که شیء درخواست را با اطلاعاتی حاشیه‌نویسی کنید به طوری که طرح JSON تولید شده برای آن تابع تا حد امکان توضیحی باشد تا مدل هوش مصنوعی بتواند تابع صحیح را فراخوانی کند.

استفاده از FunctionCallbackWrapper

راه دیگر برای ثبت یک تابع، ایجاد یک FunctionCallbackWrapper به این صورت است:

@Configuration
static class Config {

    @Bean
    public FunctionCallback weatherFunctionInfo() {
        return FunctionCallbackWrapper.builder(new MockWeatherService())
            .withName("CurrentWeather") // (1) نام تابع
            .withDescription("Get the weather in location") // (2) توضیحات تابع
            .build();
    }
}

این روش تابع MockWeatherService را به عنوان تابع CurrentWeather با ChatClient ثبت می‌کند. همچنین توضیحات و یک مبدل پاسخ اختیاری برای تبدیل پاسخ به متن به صورتی که مدل انتظار دارد، فراهم می‌کند.

به صورت پیش‌فرض، مبدل پاسخ عملیات سریال‌سازی JSON را بر روی شیء پاسخ انجام می‌دهد. FunctionCallbackWrapper به صورت داخلی امضای فراخوانی تابع را بر اساس کلاس MockWeatherService.Request تعیین می‌کند.

فعال‌سازی توابع با نام Bean

برای اینکه مدل هوش مصنوعی بتواند تابع CurrentWeather شما را فراخوانی کند، باید آن را در درخواست‌های چت فعال کنید:

ChatClient chatClient = ...

ChatResponse response = chatClient.prompt("What's the weather like in San Francisco, Tokyo, and Paris?")
    .functions("CurrentWeather") // فعال‌سازی تابع
    .call()
    .chatResponse();

logger.info("Response: {}", response);

سوال کاربر بالا باعث می‌شود که سه بار تابع CurrentWeather فراخوانی شود (یک بار برای هر شهر) و پاسخ نهایی به صورت زیر خواهد بود:

  • سان‌فرانسیسکو، CA: 30.0°C
  • توکیو، ژاپن: 10.0°C
  • پاریس، فرانسه: 15.0°C

نتیجه‌گیری

قابلیت Function Calling یکی از ویژگی‌های قدرتمند Spring AI است که امکان تعامل مستقیم مدل هوش مصنوعی با سیستم‌ها و سرویس‌های خارجی را فراهم می‌کند. این ویژگی توسعه‌دهندگان را قادر می‌سازد که وظایف پیچیده‌تر و پاسخ‌های دقیق‌تر را به کاربران ارائه دهند.