Skip to main content

Project 02: LLM using Hugging Face for Beginners

LLM and Hugging Face: Sentiment Analysis

Sentiment Analysis is a popular Natural Language Processing (NLP) task that falls under text classification.

It involves assigning labels to a given text input along with a probability score, determining whether the sentiment expressed is positive, negative, or neutral.

In this guide, we will build a full-stack sentiment analysis application using Hugging Face's Inference API, Node.js for the backend, and React for the frontend.

Setup Backend code [Node.js and Express.js]

In server.js backend file, route your Hugging Face Inference API as below

// sentiment analysis or text classification
app.post('/api/sentiment-analysis', async(req, res) => {
    const { input } = req.body
    console.log(input)
    try {
        const response = await hf.textClassification({
            model: 'Liusuthu/my_text_classification_model_based_on_distilbert',
            inputs: input
        })
        res.status(200).send(response)
    } catch(err) {
        res.status(500).json({
            message: `Error in classifying text at backednd: ${err}`
        })
    }
})

You can try other models, like distilbert-base-uncased-finetuned-sst-2-english, from Hugging Face and output format for this type of model generates below:

 output: 
[
    { "label": "POSITIVE", "score": 0.93 },
    { "label": "NEGATIVE", "score": 0.245 }
]

Setup Frontend UI [ REACT ]

Create SentimentAnalysis.js component

import React, { useEffect, useState } from 'react'
import axios from 'axios'

const SentimentAnalysis = () => {
  const [input, setInput] = useState('')
  const [result, setResult] = useState('')
  const [analysis, setAnalysis] = useState(null)
  const [progressbar, setProgressbar] = useState({
    positive: 0,
    negative: 0
  })

  const handleAnalyze = async (e) => {
    e.preventDefault()
    try {
      const response = await axios.post('http://localhost:5000/api/sentiment-analysis', { input })
      setResult(response.data)
      console.log(response.data)
    } catch (err) {
      setResult({ message: 'Error occured in calling API' })
    }
  }

  useEffect(() => {
    if (result) {
      const sentiment = result.filter(t => t.score > 0.5)
      setAnalysis(sentiment)

      // handle progress bar for positives
      const posLabel = result.find(t => t.label === 'POSITIVE')
      const negLabel = result.find(t => t.label === 'NEGATIVE')

      const posScore = posLabel ? (posLabel.score * 100).toFixed(2) : 0;
      const negScore = negLabel ? (negLabel.score * 100).toFixed(2) : 0;
      setProgressbar({
        positive: `${posScore}%`,
        negative: `${negScore}%`
      })

      function updatedProgressbar(elementId, score) {
        let progressWidth = 0;
        const element = document.getElementById(elementId)
        const id = setInterval(() => {
          if (progressWidth >= score) clearInterval(id)
          else {
            progressWidth++
            element.style.width = `${progressWidth}%`
            element.style.backgroundColor = score > 50 ? "#4caf50" : "#f44336"
          }
        }, 10)
      }
      updatedProgressbar('positive-progress', posScore)
      updatedProgressbar('negative-progress', negScore)
    }
  }, [result])

  return (
    <>
      <form onSubmit={handleAnalyze}>
        <h2>Sentiment Analysis</h2>
        <textarea
          rows='10'
          cols='50'
          value={input}
          onChange={(e) => setInput(e.target.value)}
        >
        </textarea>
        <button>Analyze</button>
      </form>

      <div className='result'>
        <h3>Analysis</h3>
        <p className='warning'>{result.message && result.message}</p>
        {analysis && analysis.length > 0 && (
          analysis[0].label === 'POSITIVE' ? <p id='pos'>{analysis[0].label} &#128525;</p>
            : analysis[0].label === 'NEGATIVE' ? <p id='neg'>{analysis[0].label} &#128530;</p>
              : null
        )}

        <h3>Analyzer</h3>
        <div className='pg-container'>
          <h4>Positive</h4>
          <div id='progressbar-container'>
            <div id='positive-progress' className='progressbar'></div>
          </div>
          <p>{progressbar && progressbar.positive}</p>
        </div>
        
        <div className='pg-container'>
          <h4>Negative </h4>
          <div id='progressbar-container'>
            <div id='negative-progress' className='progressbar'></div>
          </div>
          <p>{progressbar && progressbar.negative}</p>
        </div>
                
      </div>
    </>
  )
}

export default SentimentAnalysis

Style the above code as per your requirements. After entering text and analyzing it, the frontend displays the sentiment along with progress bars representing the positive and negative sentiment scores.

Run the application

  • Backend
// if nodemon is installed
// in package.json
{
....,
  "scripts": {
    "start": "nodemon server.js",
      ....
    }
.....
}

// command prompt
npm start 

//
// if nodemon not installed
node server.js
Figure - Sentiment Analysis using LLM Hugging Face

By leveraging AI-powered models, we can quickly analyze textual sentiment and display insightful visualizations. You can extend this by:

  • Using a different pre-trained model
  • Adding more detailed analysis (e.g., neutral sentiment, word-level breakdown)
  • Deploying the app using cloud platforms like Vercel and Heroku.