Created
February 9, 2022 09:07
-
-
Save SETIADEEPANSHU/7c2ececa58ffd2fff2d87585de5ec911 to your computer and use it in GitHub Desktop.
Tutorial1_Basic_QA_Pipeline.ipynb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "view-in-github", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"<a href=\"https://colab.research.google.com/gist/SETIADEEPANSHU/7c2ececa58ffd2fff2d87585de5ec911/tutorial1_basic_qa_pipeline.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "QSzZawlKt5BO" | |
}, | |
"source": [ | |
"# Build Your First QA System\n", | |
"\n", | |
"<img style=\"float: right;\" src=\"https://upload.wikimedia.org/wikipedia/en/d/d8/Game_of_Thrones_title_card.jpg\">\n", | |
"\n", | |
"[](https://colab.research.google.com/github/deepset-ai/haystack/blob/master/tutorials/Tutorial1_Basic_QA_Pipeline.ipynb)\n", | |
"\n", | |
"Question Answering can be used in a variety of use cases. A very common one: Using it to navigate through complex knowledge bases or long documents (\"search setting\").\n", | |
"\n", | |
"A \"knowledge base\" could for example be your website, an internal wiki or a collection of financial reports. \n", | |
"In this tutorial we will work on a slightly different domain: \"Game of Thrones\". \n", | |
"\n", | |
"Let's see how we can use a bunch of Wikipedia articles to answer a variety of questions about the \n", | |
"marvellous seven kingdoms.\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": false, | |
"id": "4k1bQAdpt5BU" | |
}, | |
"source": [ | |
"### Prepare environment\n", | |
"\n", | |
"#### Colab: Enable the GPU runtime\n", | |
"Make sure you enable the GPU runtime to experience decent speed in this tutorial.\n", | |
"**Runtime -> Change Runtime type -> Hardware accelerator -> GPU**\n", | |
"\n", | |
"<img src=\"https://raw.githubusercontent.com/deepset-ai/haystack/master/docs/_src/img/colab_gpu_runtime.jpg\">" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"name": "#%%\n" | |
}, | |
"id": "_mHD-dfJt5BV" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Make sure you have a GPU running\n", | |
"!nvidia-smi" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "UkHd8HwIt5BX" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Install the latest release of Haystack in your own environment\n", | |
"#! pip install farm-haystack\n", | |
"\n", | |
"# Install the latest master of Haystack\n", | |
"!pip install --upgrade pip\n", | |
"!pip install git+https://github.com/deepset-ai/haystack.git#egg=farm-haystack[colab]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "PTSAVujet5BY" | |
}, | |
"outputs": [], | |
"source": [ | |
"from haystack.utils import clean_wiki_text, convert_files_to_dicts, fetch_archive_from_http, print_answers\n", | |
"from haystack.nodes import FARMReader, TransformersReader" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "Em2A64fct5BZ" | |
}, | |
"source": [ | |
"## Document Store\n", | |
"\n", | |
"Haystack finds answers to queries within the documents stored in a `DocumentStore`. The current implementations of `DocumentStore` include `ElasticsearchDocumentStore`, `FAISSDocumentStore`, `SQLDocumentStore`, and `InMemoryDocumentStore`.\n", | |
"\n", | |
"**Here:** We recommended Elasticsearch as it comes preloaded with features like [full-text queries](https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html), [BM25 retrieval](https://www.elastic.co/elasticon/conf/2016/sf/improved-text-scoring-with-bm25), and [vector storage for text embeddings](https://www.elastic.co/guide/en/elasticsearch/reference/7.6/dense-vector.html).\n", | |
"\n", | |
"**Alternatives:** If you are unable to setup an Elasticsearch instance, then follow the [Tutorial 3](https://github.com/deepset-ai/haystack/blob/master/tutorials/Tutorial3_Basic_QA_Pipeline_without_Elasticsearch.ipynb) for using SQL/InMemory document stores.\n", | |
"\n", | |
"**Hint**: This tutorial creates a new document store instance with Wikipedia articles on Game of Thrones. However, you can configure Haystack to work with your existing document stores.\n", | |
"\n", | |
"### Start an Elasticsearch server\n", | |
"You can start Elasticsearch on your local machine instance using Docker. If Docker is not readily available in your environment (e.g. in Colab notebooks), then you can manually download and execute Elasticsearch from source." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "RO-I7pB0t5Ba" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Recommended: Start Elasticsearch using Docker via the Haystack utility function\n", | |
"from haystack.utils import launch_es\n", | |
"\n", | |
"launch_es()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "vy-cn7Hxt5Bb" | |
}, | |
"outputs": [], | |
"source": [ | |
"# In Colab / No Docker environments: Start Elasticsearch from source\n", | |
"! wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.2-linux-x86_64.tar.gz -q\n", | |
"! tar -xzf elasticsearch-7.9.2-linux-x86_64.tar.gz\n", | |
"! chown -R daemon:daemon elasticsearch-7.9.2\n", | |
"\n", | |
"import os\n", | |
"from subprocess import Popen, PIPE, STDOUT\n", | |
"\n", | |
"es_server = Popen(\n", | |
" [\"elasticsearch-7.9.2/bin/elasticsearch\"], stdout=PIPE, stderr=STDOUT, preexec_fn=lambda: os.setuid(1) # as daemon\n", | |
")\n", | |
"# wait until ES has started\n", | |
"! sleep 30" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"name": "#%%\n" | |
}, | |
"id": "GxiKKXtGt5Bc" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Connect to Elasticsearch\n", | |
"\n", | |
"from haystack.document_stores import ElasticsearchDocumentStore\n", | |
"\n", | |
"document_store = ElasticsearchDocumentStore(host=\"localhost\", username=\"\", password=\"\", index=\"document\")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"pycharm": { | |
"name": "#%% md\n" | |
}, | |
"id": "XhPHTo9It5Bd" | |
}, | |
"source": [ | |
"## Preprocessing of documents\n", | |
"\n", | |
"Haystack provides a customizable pipeline for:\n", | |
" - converting files into texts\n", | |
" - cleaning texts\n", | |
" - splitting texts\n", | |
" - writing them to a Document Store\n", | |
"\n", | |
"In this tutorial, we download Wikipedia articles about Game of Thrones, apply a basic cleaning function, and index them in Elasticsearch." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"name": "#%%\n" | |
}, | |
"id": "3h0ohI6qt5Be" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Let's first fetch some documents that we want to query\n", | |
"# Here: 517 Wikipedia articles for Game of Thrones\n", | |
"doc_dir = \"data/article_txt_got\"\n", | |
"s3_url = \"https://s3.eu-central-1.amazonaws.com/deepset.ai-farm-qa/datasets/documents/wiki_gameofthrones_txt.zip\"\n", | |
"fetch_archive_from_http(url=s3_url, output_dir=doc_dir)\n", | |
"\n", | |
"# Convert files to dicts\n", | |
"# You can optionally supply a cleaning function that is applied to each doc (e.g. to remove footers)\n", | |
"# It must take a str as input, and return a str.\n", | |
"dicts = convert_files_to_dicts(dir_path=doc_dir, clean_func=clean_wiki_text, split_paragraphs=True)\n", | |
"\n", | |
"# We now have a list of dictionaries that we can write to our document store.\n", | |
"# If your texts come from a different source (e.g. a DB), you can of course skip convert_files_to_dicts() and create the dictionaries yourself.\n", | |
"# The default format here is:\n", | |
"# {\n", | |
"# 'text': \"<DOCUMENT_TEXT_HERE>\",\n", | |
"# 'meta': {'name': \"<DOCUMENT_NAME_HERE>\", ...}\n", | |
"# }\n", | |
"# (Optionally: you can also add more key-value-pairs here, that will be indexed as fields in Elasticsearch and\n", | |
"# can be accessed later for filtering or shown in the responses of the Pipeline)\n", | |
"\n", | |
"# Let's have a look at the first 3 entries:\n", | |
"print(dicts[:3])\n", | |
"\n", | |
"# Now, let's write the dicts containing documents to our DB.\n", | |
"document_store.write_documents(dicts)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "hvIMsj5Zt5Bf" | |
}, | |
"source": [ | |
"## Initalize Retriever, Reader, & Pipeline\n", | |
"\n", | |
"### Retriever\n", | |
"\n", | |
"Retrievers help narrowing down the scope for the Reader to smaller units of text where a given question could be answered.\n", | |
"They use some simple but fast algorithm.\n", | |
"\n", | |
"**Here:** We use Elasticsearch's default BM25 algorithm\n", | |
"\n", | |
"**Alternatives:**\n", | |
"\n", | |
"- Customize the `ElasticsearchRetriever`with custom queries (e.g. boosting) and filters\n", | |
"- Use `TfidfRetriever` in combination with a SQL or InMemory Document store for simple prototyping and debugging\n", | |
"- Use `EmbeddingRetriever` to find candidate documents based on the similarity of embeddings (e.g. created via Sentence-BERT)\n", | |
"- Use `DensePassageRetriever` to use different embedding models for passage and query (see Tutorial 6)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "TlDmyjYRt5Bf" | |
}, | |
"outputs": [], | |
"source": [ | |
"from haystack.nodes import ElasticsearchRetriever\n", | |
"\n", | |
"retriever = ElasticsearchRetriever(document_store=document_store)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"is_executing": false, | |
"name": "#%%\n" | |
}, | |
"id": "7DZxeNOQt5Bg" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Alternative: An in-memory TfidfRetriever based on Pandas dataframes for building quick-prototypes with SQLite document store.\n", | |
"\n", | |
"# from haystack.nodes import TfidfRetriever\n", | |
"# retriever = TfidfRetriever(document_store=document_store)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "Bv91FkkGt5Bg" | |
}, | |
"source": [ | |
"### Reader\n", | |
"\n", | |
"A Reader scans the texts returned by retrievers in detail and extracts the k best answers. They are based\n", | |
"on powerful, but slower deep learning models.\n", | |
"\n", | |
"Haystack currently supports Readers based on the frameworks FARM and Transformers.\n", | |
"With both you can either load a local model or one from Hugging Face's model hub (https://huggingface.co/models).\n", | |
"\n", | |
"**Here:** a medium sized RoBERTa QA model using a Reader based on FARM (https://huggingface.co/deepset/roberta-base-squad2)\n", | |
"\n", | |
"**Alternatives (Reader):** TransformersReader (leveraging the `pipeline` of the Transformers package)\n", | |
"\n", | |
"**Alternatives (Models):** e.g. \"distilbert-base-uncased-distilled-squad\" (fast) or \"deepset/bert-large-uncased-whole-word-masking-squad2\" (good accuracy)\n", | |
"\n", | |
"**Hint:** You can adjust the model to return \"no answer possible\" with the no_ans_boost. Higher values mean the model prefers \"no answer possible\"\n", | |
"\n", | |
"#### FARMReader" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"is_executing": false | |
}, | |
"id": "6xiIMlmPt5Bg" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Load a local model or any of the QA models on\n", | |
"# Hugging Face's model hub (https://huggingface.co/models)\n", | |
"\n", | |
"reader = FARMReader(model_name_or_path=\"deepset/roberta-base-squad2\", use_gpu=True)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "gSmtLhEwt5Bh" | |
}, | |
"source": [ | |
"#### TransformersReader" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "8RKrvCkHt5Bh" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Alternative:\n", | |
"# reader = TransformersReader(model_name_or_path=\"distilbert-base-uncased-distilled-squad\", tokenizer=\"distilbert-base-uncased\", use_gpu=-1)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "rClshvpRt5Bh" | |
}, | |
"source": [ | |
"### Pipeline\n", | |
"\n", | |
"With a Haystack `Pipeline` you can stick together your building blocks to a search pipeline.\n", | |
"Under the hood, `Pipelines` are Directed Acyclic Graphs (DAGs) that you can easily customize for your own use cases.\n", | |
"To speed things up, Haystack also comes with a few predefined Pipelines. One of them is the `ExtractiveQAPipeline` that combines a retriever and a reader to answer our questions.\n", | |
"You can learn more about `Pipelines` in the [docs](https://haystack.deepset.ai/docs/latest/pipelinesmd)." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"is_executing": false | |
}, | |
"id": "xV-jmWUst5Bi" | |
}, | |
"outputs": [], | |
"source": [ | |
"from haystack.pipelines import ExtractiveQAPipeline\n", | |
"\n", | |
"pipe = ExtractiveQAPipeline(reader, retriever)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "miwGDJqPt5Bi" | |
}, | |
"source": [ | |
"## Voilà! Ask a question!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"is_executing": false | |
}, | |
"id": "Ac0VMKhyt5Bi" | |
}, | |
"outputs": [], | |
"source": [ | |
"# You can configure how many candidates the reader and retriever shall return\n", | |
"# The higher top_k_retriever, the better (but also the slower) your answers.\n", | |
"prediction = pipe.run(\n", | |
" query=\"Who is the father of Arya Stark?\", params={\"Retriever\": {\"top_k\": 10}, \"Reader\": {\"top_k\": 5}}\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "3Dol2Yrot5Bj" | |
}, | |
"outputs": [], | |
"source": [ | |
"# prediction = pipe.run(query=\"Who created the Dothraki vocabulary?\", params={\"Reader\": {\"top_k\": 5}})\n", | |
"# prediction = pipe.run(query=\"Who is the sister of Sansa?\", params={\"Reader\": {\"top_k\": 5}})" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "X9w7jp61t5Bj" | |
}, | |
"outputs": [], | |
"source": [ | |
"# Now you can either print the object directly...\n", | |
"from pprint import pprint\n", | |
"\n", | |
"pprint(prediction)\n", | |
"\n", | |
"# Sample output:\n", | |
"# {\n", | |
"# 'answers': [ <Answer: answer='Eddard', type='extractive', score=0.9919578731060028, offsets_in_document=[{'start': 608, 'end': 615}], offsets_in_context=[{'start': 72, 'end': 79}], document_id='cc75f739897ecbf8c14657b13dda890e', meta={'name': '454_Music_of_Game_of_Thrones.txt'}}, context='...' >,\n", | |
"# <Answer: answer='Ned', type='extractive', score=0.9767240881919861, offsets_in_document=[{'start': 3687, 'end': 3801}], offsets_in_context=[{'start': 18, 'end': 132}], document_id='9acf17ec9083c4022f69eb4a37187080', meta={'name': '454_Music_of_Game_of_Thrones.txt'}}, context='...' >,\n", | |
"# ...\n", | |
"# ]\n", | |
"# 'documents': [ <Document: content_type='text', score=0.8034909798951382, meta={'name': '332_Sansa_Stark.txt'}, embedding=None, id=d1f36ec7170e4c46cde65787fe125dfe', content='\\n===\\'\\'A Game of Thrones\\'\\'===\\nSansa Stark begins the novel by being betrothed to Crown ...'>,\n", | |
"# <Document: content_type='text', score=0.8002150354529785, meta={'name': '191_Gendry.txt'}, embedding=None, id='dd4e070a22896afa81748d6510006d2', 'content='\\n===Season 2===\\nGendry travels North with Yoren and other Night's Watch recruits, including Arya ...'>,\n", | |
"# ...\n", | |
"# ],\n", | |
"# 'no_ans_gap': 11.688868522644043,\n", | |
"# 'node_id': 'Reader',\n", | |
"# 'params': {'Reader': {'top_k': 5}, 'Retriever': {'top_k': 5}},\n", | |
"# 'query': 'Who is the father of Arya Stark?',\n", | |
"# 'root_node': 'Query'\n", | |
"# }" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"pycharm": { | |
"is_executing": false, | |
"name": "#%%\n" | |
}, | |
"id": "aJGq1iL1t5Bk" | |
}, | |
"outputs": [], | |
"source": [ | |
"# ...or use a util to simplify the output\n", | |
"# Change `minimum` to `medium` or `all` to raise the level of detail\n", | |
"print_answers(prediction, details=\"minimum\")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": false, | |
"pycharm": { | |
"name": "#%% md\n" | |
}, | |
"id": "y-0CpVjGt5Bk" | |
}, | |
"source": [ | |
"## About us\n", | |
"\n", | |
"This [Haystack](https://github.com/deepset-ai/haystack/) notebook was made with love by [deepset](https://deepset.ai/) in Berlin, Germany\n", | |
"\n", | |
"We bring NLP to the industry via open source! \n", | |
"Our focus: Industry specific language models & large scale QA systems. \n", | |
" \n", | |
"Some of our other work: \n", | |
"- [German BERT](https://deepset.ai/german-bert)\n", | |
"- [GermanQuAD and GermanDPR](https://deepset.ai/germanquad)\n", | |
"- [FARM](https://github.com/deepset-ai/FARM)\n", | |
"\n", | |
"Get in touch:\n", | |
"[Twitter](https://twitter.com/deepset_ai) | [LinkedIn](https://www.linkedin.com/company/deepset-ai/) | [Slack](https://haystack.deepset.ai/community/join) | [GitHub Discussions](https://github.com/deepset-ai/haystack/discussions) | [Website](https://deepset.ai)\n", | |
"\n", | |
"By the way: [we're hiring!](https://www.deepset.ai/jobs)\n" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.9.7" | |
}, | |
"colab": { | |
"name": "Tutorial1_Basic_QA_Pipeline.ipynb", | |
"provenance": [], | |
"include_colab_link": true | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment