CrestApps Banner

Extending AI Models with Custom Functions in Orchard Core

Blog Post default image

Extending AI Models with Custom Functions in Orchard Core

Artificial Intelligence (AI) is revolutionizing web applications by providing dynamic, intelligent interactions. In Orchard Core, AI capabilities can be extended beyond basic interactions by implementing custom functions that provide tailored responses and actions. This guide will walk you through extending AI models with functions using the CrestApps.OrchardCore.AI package.


Why Extend AI Models with Custom Functions?

AI models provide a strong foundation for chatbot interactions, but often, applications require specialized logic to fetch external data, perform calculations, or integrate with third-party services. By creating custom functions, developers can extend the AI's capabilities while keeping control over its behavior.

Some use cases for extending AI models with functions include:

  • Retrieving real-time data (e.g., weather, stock prices, news updates).
  • Integrating with APIs (e.g., CRM, inventory systems, support tickets).
  • Performing complex computations (e.g., financial calculations, analytics processing).

Creating a Custom AI Function

The CrestApps.OrchardCore.AI package allows you to register custom functions that AI profiles can call when interacting with users. Here’s how you can create a simple function to fetch weather information based on a user’s location.

Step 1: Define the Function

To create a custom AI function, inherit from AIFunction and override its behavior:

public sealed class GetWeatherFunction : AIFunction
{
    private const string _locationProperty = "Location";
    public const string TheName = "get_weather";

    public GetWeatherFunction()
    {
        Name = TheName;
        Description = "Retrieves weather information for a specified location.";

        var metadata = new JsonObject()
        {
            {"type", "object"},
            {"properties", new JsonObject()
                {
                    { _locationProperty, new JsonObject()
                        {
                            {"type", "string" },
                            {"description", "The geographic location for which the weather information is requested." },
                        }
                    }
                }
            },
            {"required", new JsonArray(_locationProperty)},
            {"return_type", new JsonObject()
                {
                    {"type", "string"},
                    {"description", "The weather condition at the specified location."},
                }
            },
        };

        JsonSchema = JsonSerializer.Deserialize<JsonElement>(metadata);
    }

    public override string Name { get; }

    public override string Description { get; }

    public override JsonElement JsonSchema { get; }

    protected override Task<object> InvokeCoreAsync(IEnumerable<KeyValuePair<string, object>> arguments, CancellationToken cancellationToken)
    {
        var prompt = arguments.First(x => x.Key == _locationProperty).Value;

        string location = null;

        if (prompt is JsonElement jsonElement)
        {
            location = jsonElement.GetString();
        }
        else if (prompt is JsonNode jsonNode)
        {
            location = jsonNode.ToJsonString();
        }
        else if (prompt is string str)
        {
            location = str;
        }
        else
        {
            location = prompt?.ToString();
        }

        var weather = Random.Shared.NextDouble() > 0.5 ? $"It's sunny in {location}." : $"It's raining in {location}.";

        return Task.FromResult<object>(weather);
    }
}

Step 2: Register the Function

To make the function available in your AI setup, register it as a service in your Startup class:

services.AddAITool<GetWeatherFunction>(GetWeatherFunction.Name, options =>
{
    options.Title = "Weather Getter";
    options.Description = "Retrieves weather information for a specified location.";
});

This ensures that the AI service can access and use your custom function when processing user requests.


Using Custom Functions in AI Profiles

Once a function is registered, it can be used in AI profiles to extend chatbot capabilities.

  1. Navigate to the AI Profiles Section in the Orchard Core dashboard.
  2. Create or edit an existing AI profile.
  3. Enable the custom function in the function list.
  4. Test the function to ensure it responds correctly.

This allows AI-powered chatbots and automation workflows to utilize external data and provide smarter responses.


Example Use Case: AI-Driven Customer Support

Consider a scenario where a chatbot needs to provide real-time shipping status updates. By creating a custom function that fetches shipment details from an API, the AI can offer instant support to customers.

Example function:

public sealed class GetShippingStatusFunction : AIFunction
{
    private const string _trackingNumberProperty = "TrackingNumber";
    public const string TheName = "get_shipping_status";

    public GetShippingStatusFunction()
    {
        Name = TheName;
        Description = "Retrieves the current status of a shipment.";

        var metadata = new JsonObject()
        {
            {"type", "object"},
            {"properties", new JsonObject()
                {
                    { _trackingNumberProperty, new JsonObject()
                        {
                            {"type", "string" },
                            {"description", "The tracking number of the shipment." },
                        }
                    }
                }
            },
            {"required", new JsonArray(_trackingNumberProperty)},
            {"return_type", new JsonObject()
                {
                    {"type", "string"},
                    {"description", "The current shipment status."},
                }
            },
        };

        JsonSchema = JsonSerializer.Deserialize<JsonElement>(metadata);
    }

    public override string Name { get; }

    public override string Description { get; }

    public override JsonElement JsonSchema { get; }

    protected override async Task<object> InvokeCoreAsync(IEnumerable<KeyValuePair<string, object>> arguments, CancellationToken cancellationToken)
    {
        var prompt = arguments.First(x => x.Key == _trackingNumberProperty).Value;

        string trackingNumber = prompt?.ToString();
        string status = await FetchShippingStatusFromAPI(trackingNumber);

        return status;
    }

    private async Task<string> FetchShippingStatusFromAPI(string trackingNumber)
    {
        await Task.Delay(500);
        return $"Shipment {trackingNumber} is in transit.";
    }
}

Register the function as before and integrate it into your AI profile. Now, the chatbot can provide instant tracking updates!


Conclusion

Extending AI models with custom functions in Orchard Core enables developers to create more intelligent, data-driven chatbots and applications. By implementing and registering functions tailored to your needs, you can:

  • Integrate AI with external APIs and data sources.
  • Customize responses for specific business needs.
  • Enhance chatbot functionalities with real-time insights.

Start extending your AI models today and unlock the full potential of AI-driven interactions in Orchard Core!


Additional Resources