Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
78 changes: 44 additions & 34 deletions lab-extractive-question-answering.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
},
"outputs": [],
"source": [
"!pip install -qU datasets pinecone-client sentence-transformers torch"
"# !pip install -qU datasets pinecone-client sentence-transformers torch"
]
},
{
Expand Down Expand Up @@ -242,7 +242,8 @@
"from datasets import load_dataset\n",
"\n",
"# load the squad dataset into a pandas dataframe\n",
"df = load_dataset(\"squad\", split=\"train\").to_pandas()"
"df = load_dataset(\"squad\", split=\"train\").to_pandas()\n",
"df.head()"
]
},
{
Expand All @@ -260,9 +261,9 @@
"outputs": [],
"source": [
"# select only title and context column\n",
"df = None\n",
"df = df[[\"title\", \"context\"]]\n",
"# drop rows containing duplicate context passages\n",
"df = None\n",
"df = df.drop_duplicates(subset=[\"context\"])\n",
"df"
]
},
Expand Down Expand Up @@ -293,7 +294,7 @@
"metadata": {},
"outputs": [],
"source": [
"!pip install -qU langchain-pinecone pinecone-notebooks"
"# !pip install -qU langchain-pinecone pinecone-notebooks"
]
},
{
Expand All @@ -310,11 +311,9 @@
"spec = ServerlessSpec(\n",
" cloud=\"aws\", region=\"us-east-1\"\n",
")\n",
"\n",
"# connect to pinecone environment\n",
"pc = Pinecone(\n",
" api_key = PINECONE_API_KEY,\n",
" environment='us-east-1' # find next to API key in console\n",
" api_key = PINECONE_API_KEY\n",
")"
]
},
Expand All @@ -337,14 +336,18 @@
},
"outputs": [],
"source": [
"index_name = None\n",
"index_name = \"question-answering\"\n",
"\n",
"# check if the extractive-question-answering index exists\n",
"if index_name not in pinecone.list_indexes().names():\n",
" # create the index if it does not exist\n",
" None\n",
"if not pc.has_index(index_name):\n",
" pc.create_index(\n",
" name=index_name,\n",
" dimension=384,\n",
" metric=\"cosine\",\n",
" spec=spec\n",
" )\n",
"# connect to extractive-question-answering index we created\n",
"index = pinecone.Index(index_name)"
"index = pc.Index(index_name)"
]
},
{
Expand Down Expand Up @@ -550,7 +553,7 @@
"# set device to GPU if available\n",
"device = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
"# load the retriever model from huggingface model hub\n",
"retriever = None #use the 'multi-qa-MiniLM-L6-cos-v1' model from HuggingFace to build the retriever\n",
"retriever = SentenceTransformer('sentence-transformers/multi-qa-MiniLM-L6-cos-v1')\n",
"retriever"
]
},
Expand Down Expand Up @@ -609,17 +612,17 @@
"\n",
"for i in tqdm(range(0, len(df), batch_size)):\n",
" # find end of batch\n",
" None\n",
" i_end = min(i + batch_size, len(df))\n",
" # extract batch\n",
" None\n",
" batch = df.iloc[i:i_end]\n",
" # generate embeddings for batch\n",
" emb = None\n",
" emb = retriever.encode(batch[\"context\"].tolist()).tolist()\n",
" # get metadata\n",
" meta = None\n",
" meta = batch.to_dict(orient=\"records\")\n",
" # create unique IDs\n",
" ids = None\n",
" ids = [str(idx) for idx in batch.index]\n",
" # add all to upsert list\n",
" to_upsert = None\n",
" to_upsert = list(zip(ids, emb, meta))\n",
" # upsert/insert these records to pinecone\n",
" _ = index.upsert(vectors=to_upsert)\n",
"\n",
Expand Down Expand Up @@ -718,12 +721,24 @@
},
"outputs": [],
"source": [
"from transformers import pipeline\n",
"from transformers import AutoTokenizer, AutoModelForQuestionAnswering\n",
"\n",
"model_name = 'deepset/electra-base-squad2'\n",
"# load the reader model into a question-answering pipeline\n",
"reader = pipeline(tokenizer=model_name, model=model_name, task='question-answering', device=device)\n",
"reader"
"\n",
"tokenizer = AutoTokenizer.from_pretrained(model_name)\n",
"model = AutoModelForQuestionAnswering.from_pretrained(model_name).to(device)\n",
"def reader(question, context):\n",
" inputs = tokenizer(question, context, return_tensors='pt', truncation=True, max_length=512).to(device)\n",
" with torch.no_grad():\n",
" outputs = model(**inputs)\n",
" \n",
" start = outputs.start_logits.argmax()\n",
" end = outputs.end_logits.argmax() + 1\n",
" \n",
" answer = tokenizer.convert_tokens_to_string(\n",
" tokenizer.convert_ids_to_tokens(inputs['input_ids'][0][start:end])\n",
" )\n",
" return {\"answer\": answer, \"score\": outputs.start_logits.max().item()}"
]
},
{
Expand All @@ -748,11 +763,11 @@
"# gets context passages from the pinecone index\n",
"def get_context(question, top_k):\n",
" # generate embeddings for the question\n",
" xq = None\n",
" xq = retriever.encode(question)\n",
" # search pinecone index for context passage with the answer\n",
" xc = None\n",
" xc = index.query(vector=xq.tolist(), top_k=5, include_metadata=True)\n",
" # extract the context passage from pinecone search result\n",
" c = None\n",
" c = [x['metadata']['context'] for x in xc['matches']]\n",
" return c"
]
},
Expand Down Expand Up @@ -942,7 +957,7 @@
},
"gpuClass": "standard",
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": ".venv (3.14.0)",
"language": "python",
"name": "python3"
},
Expand All @@ -956,7 +971,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
"version": "3.14.0"
},
"papermill": {
"default_parameters": {},
Expand All @@ -970,11 +985,6 @@
"start_time": "2021-04-15T21:06:38.122812",
"version": "2.3.3"
},
"vscode": {
"interpreter": {
"hash": "5fe10bf018ef3e697f9035d60bf60847932a12bface18908407fd371fe880db9"
}
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"00b344135da443ac90e6e6a0f53cfe0f": {
Expand Down