Review and catalog text messages with Cohere Classify and .NET

Review and catalog text messages with Cohere Classify and .NET
June 13, 2023
Written by
Néstor Campos
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

Classifying information or messages that you receive in your business/project is essential to know how to prioritize or direct such data to another process, so certain actions can be taken based on it. Several companies have a system that classifies the message (like SMS, WhatsApp, or Email) based on the sender, recipient, or subject. Now, thanks to Artificial Intelligence (AI), it can be done based on its content.

In this post, you are going to create a web app that, using the Cohere Classify service, will be able to classify any received text message using Twilio for WhatsApp.

Prerequisites

You will need the following for your development environment:

What is Cohere and Cohere Classify?

Cohere is a platform that offers different Artificial Intelligence services using natural language and LLM (Large Language Model), similar to other platforms such as OpenAI, among others.

Within Cohere's services, there is Classify, which, as its name indicates, from a few examples, you can classify new texts, specifying the text and the label (classification). For example, you can classify messages received from customer service through WhatsApp, SMS, or Email.

Get a Cohere API Key

In order to use Cohere Classify, you will need a Cohere AI account.

After registration, you will see your dashboard, where among various options and examples, you can generate your API key:

Initial dashboard of the Cohere platform with left side menu and usage examples in the center.

Click on "API keys", where you will see the option to create productive API keys (paid with better performance) and trial keys (free). Next, generate a new trial key by clicking on the “New trial key” button, giving a name, and saving it as you will use it later.

Modal window for creating a new trial key, with the name "TextClassifierConsole"

Create your web app

Initialize your project

You will need to create a console project using the .NET CLI. Open a terminal and run the following commands to create a folder that will contain your project:

mkdir TextAIClassifierWeb
cd TextAIClassifierWeb

Next, create the project with the command below:

dotnet new web

Install the Twilio SDK and the Twilio helper library for ASP.NET Core which will help you send and receive WhatsApp messages:

dotnet add package Twilio
dotnet add package Twilio.AspNet.Core

Connect your app to Cohere using the API

To add the Cohere API key to your project, you will use user secrets since it is a good option for local development that is easy to manage, more secure, and for good development practices.

To set user secrets for your project, run the following commands at the command line inside your project's root folder:

dotnet user-secrets init
dotnet user-secrets set "CohereApiKey" "<Cohere API Key>"

Replace <Cohere API Key> with the API Key obtained in the creation of your Cohere account.

Add the objects to send requests and receive responses from the API

With Cohere Classify, the training and inference (classification process with new data) happen in the same call, so you will have to specify some examples to classify along with the new text to classify. In this case, you are going to classify messages that could be sent to different areas of your company (human resources, finance, marketing, etc.).

First, create two files, one that you will use for the API request and one for the response. You will call the first ClassificationRequest.cs, and the second ClassificationResponse.cs, and add the following C# code:

using System.Text.Json.Serialization;

namespace TextAIClassifierWeb;


public class ClassificationRequest
{
    [JsonPropertyName("inputs")]
    public List<string> Inputs { get; set; }
    
    [JsonPropertyName("examples")]
    public List<CategoryRequestExample> Examples { get; set; }
    
    [JsonPropertyName("truncate")]
    public string? Truncate { get; set; }
}

public class CategoryRequestExample
{
    [JsonPropertyName("text")]
    public string Text { get; set; }
    
    [JsonPropertyName("label")]
    public string Label { get; set; }
}

Configure the API call to classify text

Now create the following class in a new ClassifierService.cs file, and add the namespaces and structure of the class:

using System.Text.Json;
using System.Text;

namespace TextAIClassifierWeb;

public class ClassifierService
{
    
}

Next, add a constructor to this class, which will receive the configuration as a parameter, in order to use the previously configured secrets:

private readonly IConfiguration configuration;
private readonly HttpClient httpClient;

public ClassifierService(IConfiguration configuration, HttpClient httpClient)
{
    this.configuration = configuration;
    this.httpClient = httpClient;
}

You will need to create some examples with already classified texts that will be used to train your model. To do this, create a method with the following code:

private static readonly List<CategoryRequestExample> CategoryRequestExamples = new()
{
    new() {Text = "I have a problem with my account", Label = "Customer Service"},
    new() {Text = "I need help with my service", Label = "Customer Service"},
    new() {Text = "I am sending you the sales forecast for the next month", Label = "Finance"},
    new() {Text = "I need help to understand what is the requirements for the next advertising", Label = "Marketing"},
    new() {Text = "Here is the clustering with the customers", Label = "Marketing"},
    new() {Text = "I need to request vacation days", Label = "Human Resources"},
    new() {Text = "You have to prepare the internal training meeting", Label = "Human Resources"},
    new() {Text = "Tomorrow we will go to the company party", Label = "Other (or manual classification)"},
    new() {Text = "There are no pending requests", Label = "Other (or manual classification)"}
};

In a production environment, you would obtain these texts from persistent data systems, such as a database.

Finally, configure the method to prepare and send the request, receiving a text from the user from the console, and using the Cohere API, you will receive the corresponding classification and the confidence level for that classification:

public async Task<List<Classification>> ClassifyText(string message)
{
    var classificationRequest = new ClassificationRequest
    {
        Inputs = new List<string> {message},
        Truncate = "END",
        Examples = CategoryRequestExamples
    };
    var json = JsonSerializer.Serialize(classificationRequest);
    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Post,
        RequestUri = new Uri("https://api.cohere.ai/classify"),
        Headers =
        {
            {"accept", "application/json"},
            {"Cohere-Version", "2022-12-06"},
            {"authorization", "Bearer " + configuration["CohereApiKey"]},
        },
        Content = new StringContent(json, Encoding.UTF8, "application/json")
    };
    using var response = await httpClient.SendAsync(request);
    response.EnsureSuccessStatusCode();
    var body = await response.Content.ReadAsStringAsync();
    var bodyResponse = JsonSerializer.Deserialize<ClassificationResponse>(body);
    return bodyResponse.Classifications;
}

Configure your web app to receive text messages

Now, in Program.cs, add the following code to configure your web app:

using TextAIClassifierWeb;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpClient();
builder.Services.AddControllers();
builder.Services.AddTransient<ClassifierService>();

var app = builder.Build();

app.MapControllers();
app.Run();

Next, create the MessageController.cs file, where you will configure the webhook to receive and reply to WhatsApp messages, with the following code:

using Microsoft.AspNetCore.Mvc;
using Twilio.AspNet.Common;
using Twilio.AspNet.Core;
using Twilio.TwiML;

namespace TextAIClassifierWeb;

[Route("[controller]")]
public class MessageController : TwilioController
{

}

In this new controller, add the constructor to receive the app's configuration (the one that contains the Cohere API Key) and instantiate the ClassifierService:

private readonly ClassifierService classifierService;

public MessageController(ClassifierService classifierService)
{
    this.classifierService = classifierService;
}

It is time to add an action that receives the WhatsApp message, processes it through the Cohere service, and returns the prediction via message to the user. To do this, add this action to the controller:

HttpPost]
public async Task<IActionResult> Index(SmsRequest incomingMessage)
{
    var response = new MessagingResponse();
    var predictionList = await classifierService.ClassifyText(incomingMessage.Body);
    foreach(var prediction in predictionList)
    {
        response.Message($"Prediction: {prediction.Prediction} with confidence {prediction.Confidence:P2}");
    }
    return TwiML(response);
}

And finally, run the web app to get the URL that you will use later. Must be in the format "http://localhost:<port>".

dotnet run

Command line with the result of executing the "dotnet run" command to initialize the web app, obtaining the URL in http and https.

Set up the Twilio Sandbox for WhatsApp

To send WhatsApp messages through your Twilio account, you need to create a WhatsApp Sender, but for testing and developing locally, you can, and in this tutorial, you will use the Twilio Sandbox for WhatsApp.

In order to get to the WhatsApp sandbox, in the left-side menu of the Twilio console click on "Messaging" (if you don't see it, click on "Explore Products", which will display the list with the available products, and there you will see "Messaging"). After that, in the available options open the "Try it out" submenu, and finally, click "Send a WhatsApp message".

Side menu in the Twilio console, highlighting the Messaging > Try it out > "Send a WhatsApp message" menu item.

Next, you have to follow the instruction on the screen, in which you must send a pre-defined message to the indicated number through WhatsApp. This will enable that WhatsApp number to use to send messages to your own WhatsApp number. If you want to send messages to other numbers, the people who own those numbers will have to do this same step.

Twilio Sandbox for WhatsApp console for sending test messages, initializing the process with a test message

After that, you will receive a message in response confirming the Sandbox is configured.

Confirmation message on WhatsApp indicating that the number is available to be used in test mode.

Now you are able to send messages to the Sandbox number and receive messages from the Sandbox number.

Make your webhook public with ngrok for testing

Your web app needs to be publicly accessible for Twilio to send the message webhook requests to your application. That's why you'll use ngrok to create a secure tunnel between your locally running API and ngrok's public forwarding URL.

Leave your .NET application running and open a separate shell. In the new shell, run ngrok with the following command, specifying the HTTP URL that your application is listening to:

ngrok http http://localhost:<port>

Alternatively, if your application also listens to HTTPS, you can create a ngrok tunnel that forwards requests to the HTTPS URL. For this, you'll first need to create a free ngrok account, and then configure the ngrok auth token.

Copy the Forwarding HTTPS address that ngrok created for you, as you will use it in the Twilio Sandbox for the WhatsApp console.

Result of creating an ngrok tunnel in console. The output shows an HTTP and HTTPS Forwarding URL.

In the Twilio portal, go to the Twilio WhatsApp page, in the “Sandbox settings” section, and change the “When a message comes in” endpoint with the generated URL by ngrok, including the /Message path.

The Sandbox settings tab, on the Twilio Sandbox for WhatsApp console. The Sandbox configuration form has two text boxes. A text box "When a message comes in" filled out with the ngrok forwarding URL with the /Message path, and a text box "Status callback URL" which is left empty.


Every time you stop and start a ngrok tunnel, ngrok will generate a new Forwarding URL for you. This means you'll need to update the Sandbox Configuration form with the new Forwarding URL whenever it changes.

Test the project

To test, in the conversations with the Sandbox number, send a text message using WhatsApp.

Sending a message on WhatsApp with the text "I need days off for personal reasons."

In a few seconds, you will see the message with the prediction and confidence percentage.

Received message "Prediction: Human Resources with confidence 0.9244924" for user-submitted text "I need days off for personal reasons."

What's next

This is a great start, and to continue, you can:

  • Send more than 1 message in the same API call (already supported by the class you have built), which will save you time and costs in calls.
  • Optimize the examples, storing them in a database and adding more for each class, which will make the predictions with a higher level of confidence. Note that the minimum number of examples is 2 and the maximum is 2,500, with a maximum of 512 tokens per example.

Additional resources

Cohere Docs - Review all documentation of what you can do with Cohere services.

Twilio WhatsApp – This page contains all the information about the requirements and benefits of using messaging over WhatsApp with Twilio.

Twilio SDK for C# and .NET – You can explain all the options provided by the Twilio C# SDK.

Source Code to this tutorial on GitHub - You can find the source code for this project at this GitHub repository. Use it to compare solutions if you run into any issues.

Néstor Campos is a software engineer, tech founder, and Microsoft Most Value Professional (MVP), working on different types of projects, especially with Web applications.