IBM Developer

Tutorial

Build a web page summarization tool using watsonx.ai flows

Use watsonx.ai flows engine, the IBM Granite chat LLM, and Playright to transform lengthy web content into concise summaries with customizable prompts

There’s is so much information available online that the ability to quickly and accurately summarize web content is becoming a real need. There are browser plugins available to create a summary of a web page, or you can copy-paste a website’s content into a chat assistant and have it summarized. But what if you want to build your own web page summarization tool, that you can use for any website and integrate into your existing applications?

This tutorial will guide you through creating your own web page summarization tool using the CLI and SDK of IBM watsonx.ai flows engine. You'll learn how to set up your environment, construct a flow for summarization, call models from watsonx.ai, and scrape a web page using JavaScript. By the end of this tutorial, you'll have the knowledge and skills to transform any long form content on the internet into a condensed summary.

If you'd like to watch me demo these steps, watch this video:

Prerequisites and setup

Before we dive into building our web page summarization tool, let's ensure we have all the necessary prerequisites in place. You will need a watsonx.ai flows engine account, and familiarity with basic programming in JavaScript. Additionally, make sure you have the following installed on your development environment:

  • Python (3.6 or later)
  • Node.js
  • IBM watsonx.ai flows engine CLI

To get started, log in to the IBM watsonx.ai flows engine dashboard. Follow the instructions to install the CLI on your local machine. Once set up, you can copy-paste the required API key and other details to sign in via the CLI.

Run the following command to log in to watsonx.ai flows engine.

wxflows login

With your development environment ready, we can now proceed to set up the project structure and install the necessary dependencies. Create a new directory for your project and initialize a new watsonx.ai flows engine project:

mkdir webpage-summarization

cd webpage-summarization

wxflows init --endpoint-name wxflows/summarization

This will create a .env.sample and a wxflows.toml file. Copy the .env.sample to a new file called .env:

cp .env.sample .env

And uncomment the following line, by adding shared as its value, so that you can connect to models from watsonx.ai without having to run your own instance:

STEPZEN_WATSONX_HOST=shared

With the setup complete, we're ready to build our summarization flow in the next section.

Creating a summarization flow

Summarization involves using Large Language Models (LLMs) to condense lengthy texts into shorter versions while retaining the main ideas and key points. You don’t need much more than access to a LLM and a prompt to describe what the LLM should do, in this case summarizing the text you provide it with.

In this new summarization flow, we’ll be using the IBM Granite chat model (ibm/granite-13b-chat-v2) that’s available from watsonx.ai and can be using in flows engine. To create a flow, open the wflows.toml file and add the following contents:

[wxflows.deployment]
flows="""
    summarization = templatedPrompt | completion(parameters: summarization.parameters)
"""

The above is a basic flow for setting a prompt template in the step templatedPrompt and then calling a LLM in the subsequent completion step. The step completion needs the parameters argument, so we’re explicitly defining this so it can be set when calling the summarization flow later on. When you call the summarization flow, you can also set arguments like promptTemplate, but we can also define them right here in the wxflows.toml file.

To set a prompt template specifically for summarization, we need to set the promptTemplate argument for the templatedPrompt to be the prompt in the following code block:

[wxflows.deployment]
flows="""
    summarization = templatedPrompt(promptTemplate: "<|system|>You are Granite Chat, an AI language model developed by IBM. You are a cautious assistant. You carefully follow instructions. You are helpful and harmless and you follow ethical guidelines and promote positive behavior.<|user|>Create a concise summary of the document provided below.[Document]{question}[End]<|assistant|>") | completion(parameters: summarization.parameters)
"""

The above prompt sets the groundrules for the LLM and the action “Create a concise summary of the document provided below”. The document is defined as the variable {question} and will be passed when we call the summarization flow. You can also change the prompt to give very detailed summarizations, explain the text to as if you were a five-year old or, as in the above, keep the summary more concise.

To make this summarization flow available via the SDK, we need to deploy it by running the following command:

wxflows deploy

Once deployed, the endpoint will be printed in the terminal and you’re ready continue to the next section of this tutorial. In the next section, we'll create a web scraper script and integrate it with the summarization flow.

Building a webscraper

Now that you have a summarization flow deployed, let’s continue by scraping the content to summarize. For web scraping, we’ll be using Playwright, a Node.js library for automating web browsers, enabling efficient web scraping and testing of modern web applications across various browsers. We will use the SDK for watsonx.ai flows engine to connect to the summarization flow.

First, create a new directory that will contain the web scraper script:

mkdir app
cd app
npm init -y

Next, install the required packages for web scraping and the watsonx.ai flows engine SDK to connect to the flow. To install these packages run the following:

npm install playwright wxflows

Now, we need to run a command to configure Playwright, as it needs to download additional libraries to your local machine:

npx playwright install

Now we're ready to build the web scraper. In a new file called index.js, copy-paste the following code that will import Playwright (and the flows engine SDK) and navigate to a given web page:

const playwright = require('playwright');
const wxflows = require('wxflows');

async function getWebsiteContents(url, locator) {
    const browser = await playwright['chromium'].launch();
    const context = await browser.newContext();

    const page = await context.newPage(); // navigate to a given URL

    await page.goto(url);

    // get the text inside the locator
    const text = await page.locator(locator).innerText();

    await browser.close();

    return text
};

The function getWebsiteContents will navigate to a given URL and look for text in the locator that you pass. The locator could, for example, be an HTML element or a CSS classname. Also, we’re setting the browser type to chromium. Playwright will spin up a virtual browser where it will mimic how a person would visit a web page.

To use the webscraper, you can add the following block of code below the getWebsiteContents function:

(async () => {
    const content = await getWebsiteContents("https://developer.ibm.com/tutorials/awb-build-rag-application-watsonx-ai-flows-engine/", '.content-data');

    console.log(content);
})();

By running the command node index.js the webscraper will go to the URL above and fetch the contents inside the element with the CSS classname article. The given URL is a blog post about building a RAG application with watsonx.ai flows engine, and the result will be printed in your terminal as text.

You can substitute the URL with any other web page, to find the locator of your text you should open the web page in a browser and use the developer tools to find the locator. Right click your mouse somewhere on the page, and then select “Inspect” (for Chrome), and hover over the content you want to scrape:

Finding locator of a website

For more information on supported locators, have a look at the Playwright documention.

Finally, we can now connect the webscraper to the watsonx.ai flows engine SDK and summarize the content that we scrape from a web page.

Summarize the content using the wxflows SDK

In the previous section, you’ve already import the SDK into the index.js file, so the only thing that’s left is connecting the SDK to the webscraper. The watsonx.ai flows engine SDK requires the connection details, such as the endpoint and your watsonx.ai flows engine API Key. When running wxflows deploy, the endpoint that you’ve deployed the flows to will be printed in the terminal, you can retrieve the API Key with the command wxflows whoami --apikey.

After retrieving these details, add the following code to index.js:

(async () => {
    const model = new wxflows({
        endpoint: 'YOUR_ENDPOINT',
        apikey: 'YOUR_APIKEY'
    })

    const content = await getWebsiteContents("https://developer.ibm.com/tutorials/awb-build-rag-application-watsonx-ai-flows-engine/", '.content-data')

    const schema = await model.generate();

    const result = await model.flow({
        flowName: 'summarization',
        schema,
        variables: {
            aiEngine: 'WATSONX',
            model: 'ibm/granite-13b-chat-v2',
            question: content, // The content to summarize
            parameters: {
                min_new_tokens: 100,
                max_new_tokens: 1000,
                stop_sequences: []
            }
        }
    })

    console.log('Summary: ', result?.data?.summarization?.out?.results[0]?.generated_text)
})();

In the function model.flow, you’re passing the name of the flow, the schema of your flows engine endpoint, and a range of arguments needed to generate the response. For example, the argument question will be used to inject the content that needs to be summarized into the prompt template you added to the summarization flow. Other arguments such as min_new_token, max_new_tokens, and stop_sequences are set to improve the LLM response.

To run the above, you can copy the following command into your terminal:

node index.js

This command should print a summary similar to this one:

Summary:
The document provides a tutorial on how to build a question-answer application using JavaScript and IBM's watsonx.ai flows engine. The application uses Retrieval-Augmented Generation (RAG) to answer questions about a set of documents stored in a vector database. The tutorial is designed for developers who want to use AI in their applications without diving too deep into the complexities of machine learning models. The watsonx.ai flows engine is an end-to-end developer toolkit for building AI applications that simplifies the integration with Large Language Models (LLMs) and connects them to enterprise data. The tutorial covers the steps to set up a new project, upload data to the vector database, explore a flow, deploy flows, and set up a new application. The document also provides an example application that can be used to try out the flow.

To continue, I’d recommend playing with the arguments and the prompt template to tweak the summary. As suggested earlier, you could have the LLM explain the content to you as if you were a five-year old or to make the summary more detailed.

You can find the source code of this tutorial in our GitHub repository.

Summary and next steps

By completing this tutorial, you’ve learned how to build a web page summarization tool using IBM's watsonx.ai flows engine and Playwright. You’ve set up your development environment, created a summarization flow, built a web scraper, and integrated it with the watsonx.ai flows engine SDK. This new tool can now help you to transform lengthy web content into concise summaries. Experiment with different prompt templates and parameters to customize the summaries to your needs.

We're curious to find out what you're building. Join our Discord community and let us know!