{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "#Use GLiNER - a multilingual BERT-based NER Tool\n",
        "\n",
        "Zaratiana, Urchade, Nadi Tomeh, Pierre Holat, and Thierry Charnois. 2024. “GLiNER: Generalist Model for Named Entity Recognition Using Bidirectional Transformer.” In Proceedings of the 2024 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies (Volume 1: Long Papers), edited by Kevin Duh, Helena Gomez, and Steven Bethard, 5364–5376. Mexico City, Mexico: Association for Computational Linguistics. https://doi.org/10.18653/v1/2024.naacl-long.300."
      ],
      "metadata": {
        "id": "ZbISiQBRy7EH"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tGlW3wI3wRXl"
      },
      "outputs": [],
      "source": [
        "# STEP 1: Install dependencies\n",
        "\n",
        "!pip install gliner nltk\n"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# STEP 2: Try the demo from the GitHub Repository\n",
        "\n",
        "\n",
        "from gliner import GLiNER\n",
        "\n",
        "# Initialize GLiNER with the base model\n",
        "model = GLiNER.from_pretrained(\"urchade/gliner_medium-v2.1\")\n",
        "\n",
        "# Sample text for entity prediction\n",
        "text = \"\"\"\n",
        "Cristiano Ronaldo dos Santos Aveiro (Portuguese pronunciation: [kɾiʃˈtjɐnu ʁɔˈnaldu]; born 5 February 1985) is a Portuguese professional footballer who plays as a forward for and captains both Saudi Pro League club Al Nassr and the Portugal national team. Widely regarded as one of the greatest players of all time, Ronaldo has won five Ballon d'Or awards,[note 3] a record three UEFA Men's Player of the Year Awards, and four European Golden Shoes, the most by a European player. He has won 33 trophies in his career, including seven league titles, five UEFA Champions Leagues, the UEFA European Championship and the UEFA Nations League. Ronaldo holds the records for most appearances (183), goals (140) and assists (42) in the Champions League, goals in the European Championship (14), international goals (128) and international appearances (205). He is one of the few players to have made over 1,200 professional career appearances, the most by an outfield player, and has scored over 850 official senior career goals for club and country, making him the top goalscorer of all time.\n",
        "\"\"\"\n",
        "\n",
        "# Labels for entity prediction\n",
        "# Most GLiNER models should work best when entity types are in lower case or title case\n",
        "labels = [\"Person\", \"Award\", \"Date\", \"Competitions\", \"Teams\"]\n",
        "\n",
        "# Perform entity prediction\n",
        "entities = model.predict_entities(text, labels, threshold=0.5)\n",
        "\n",
        "# Display predicted entities and their labels\n",
        "for entity in entities:\n",
        "    print(entity[\"text\"], \"=>\", entity[\"label\"])"
      ],
      "metadata": {
        "id": "CviaODYLwW4Q"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Load a new text from GitHub\n",
        "!wget https://github.com/dbamman/anlp25/raw/refs/heads/main/data/twain_innocents_abroad.txt\n",
        "\n"
      ],
      "metadata": {
        "id": "SrSlhqsB5rEV"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# STEP 3: Use GLiNER for your own data\n",
        "\n",
        "from gliner import GLiNER\n",
        "import nltk\n",
        "import csv\n",
        "import os  # <--- import os for file checks\n",
        "\n",
        "# Download NLTK tokenizers\n",
        "nltk.download('punkt')\n",
        "nltk.download('punkt_tab')\n",
        "\n",
        "from nltk.tokenize import word_tokenize\n",
        "\n",
        "\n",
        "# STEP 4: Read text from input file\n",
        "\n",
        "with open(\"twain_innocents_abroad.txt\", \"r\", encoding=\"utf-8\") as f:\n",
        "    text = f.read()\n",
        "\n",
        "text = \"\\n\".join(text.split(\"\\n\\n\")[:5])\n",
        "\n",
        "# Normalize tabs to spaces\n",
        "text = text.replace('\\t', ' ')\n",
        "\n",
        "\n",
        "# STEP 5: Load GLiNER model\n",
        "\n",
        "model = GLiNER.from_pretrained(\"urchade/gliner_large-v2.1\")\n",
        "\n",
        "\n",
        "# Define entity labels (you can adjust these)\n",
        "labels = [\"Person\", \"Date\", \"Location\", \"GPE\"]\n",
        "\n",
        "#What could be further labels of interest?\n",
        "\n",
        "from nltk.tokenize import TreebankWordTokenizer\n",
        "\n",
        "tokenizer = TreebankWordTokenizer()\n",
        "\n",
        "\n",
        "# STEP 6: Run entity recognition\n",
        "\n",
        "token_entities = []\n",
        "\n",
        "for line in text.split(\"\\n\"):\n",
        "    entities = model.predict_entities(line, labels, threshold=0.5)\n",
        "    spans = tokenizer.span_tokenize(line)\n",
        "\n",
        "    print(entities)\n",
        "    for (start, end) in spans:\n",
        "        # print(token)\n",
        "        label = \"\"\n",
        "        for ent in entities:\n",
        "            if ent[\"start\"] < end and ent[\"end\"] > start:\n",
        "            # if token in ent[\"text\"]:  # rough match\n",
        "                label = ent[\"label\"]\n",
        "                break\n",
        "        token = line[start:end]\n",
        "        token_entities.append((token, label))\n",
        "        print(token, \"\\t\", label)\n",
        "\n",
        "\n"
      ],
      "metadata": {
        "id": "7fYat6orxWNq"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "Given the limited list of labels. What would be further labels needed to annotate the Named Entities in the sample text? You can also try the model with a text in another language than English.\n",
        "GLiNER, however, has a default input **length limit of 384 tokens**. This constraint is due to the underlying transformer architecture, which typically has a maximum sequence length of 512 tokens."
      ],
      "metadata": {
        "id": "ie3g2XdQVACk"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "#Try GLiNER on another text of your choice, such as one taken from Gutenberg.org\n",
        "#Use wget to refer to a weblink and download the content for use in this notebook.\n",
        "!wget --no-check-certificate https://www.gutenberg.org/cache/epub/11/pg11.txt #Alice in Wonderland\n",
        "\n",
        "\n",
        "#Which named entity types are you interested in recognizing?"
      ],
      "metadata": {
        "id": "jfztI6luz321"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# STEP 4: Read text from input file\n",
        "\n",
        "with open(\"pg11.txt\", \"r\", encoding=\"utf-8\") as f:\n",
        "    text = f.read()\n",
        "\n",
        "text = \"\\n\".join(text.split(\"\\n\\n\")[:5])\n",
        "\n",
        "# Normalize tabs to spaces\n",
        "text = text.replace('\\t', ' ')\n",
        "\n",
        "\n",
        "# STEP 5: Load GLiNER model\n",
        "\n",
        "model = GLiNER.from_pretrained(\"urchade/gliner_large-v2.1\")\n",
        "\n",
        "\n",
        "# Define entity labels (you can adjust these)\n",
        "labels = [\"Person\", \"Date\", \"Location\", \"GPE\"]\n",
        "\n",
        "#What could be further labels of interest?\n",
        "\n",
        "from nltk.tokenize import TreebankWordTokenizer\n",
        "\n",
        "tokenizer = TreebankWordTokenizer()\n",
        "\n",
        "\n",
        "# STEP 6: Run entity recognition\n",
        "\n",
        "token_entities = []\n",
        "\n",
        "for line in text.split(\"\\n\"):\n",
        "    entities = model.predict_entities(line, labels, threshold=0.5)\n",
        "    spans = tokenizer.span_tokenize(line)\n",
        "\n",
        "    print(entities)\n",
        "    for (start, end) in spans:\n",
        "        # print(token)\n",
        "        label = \"\"\n",
        "        for ent in entities:\n",
        "            if ent[\"start\"] < end and ent[\"end\"] > start:\n",
        "            # if token in ent[\"text\"]:  # rough match\n",
        "                label = ent[\"label\"]\n",
        "                break\n",
        "        token = line[start:end]\n",
        "        token_entities.append((token, label))\n",
        "        print(token, \"\\t\", label)"
      ],
      "metadata": {
        "id": "e4TbPkfHUevX"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "6NU6KxkdVMqC"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}